TextHighlighter
TextHighlighter allows you to highlight text on web pages. Just select it!
Getting started
Using the library as an npm package
Install the library by running:
$ npm install @perlego/text-highlighter
Then you can use it like so:
import TextHighlighter from '@perlego/text-highlighter';
const highlighter = new TextHighlighter(sandboxRef.current);
const highlighter = new TextHighlighter(document.getElementById("sandbox"));
CommonJS with Node environments
const TextHighlighter = require('@perlego/text-highlighter/cjs');
const highlighter = new TextHighlighter(sandboxRef.current);
const highlighter = new TextHighlighter(document.getElementById("sandbox"));
Supporting IE11
One thing to note when using this library as a package, you are responsible for providing the polyfills
for the core JavaScript features outlined in the latest ECMAScript specifications.
Within this library we use features such as Array.prototype.includes and Array.prototype.find
which aren't support by IE11 without polyfills.
You will need to install core-js and regenerator-runtime.
npm install --save core-js regenerator-runtime
You can add the following two lines at the BEGINNING of your application's entrypoint file (index.js or main.js):
import "core-js/stable";
import "regenerator-runtime/runtime";
Using the library as a script file
Clone down this repository, checkout to the release tag representing the version you would like to use.
(2.x.x + only, this won't work for 1.x.x, please refer to the documentation provided with 1.x.x releases)
Ensure grunt is installed globally:
npm install -g grunt
Build the minified version of the library using the following command:
npm run build
Copy the script file from build/prod/TextHighlighter.min.js
to the head section of your web page:
<script type="text/javascript" src="TextHighlighter.min.js"></script>
And use it!
var hltr = new TextHighlighter(document.body);
Features
- Highlighting of selected text.
- Highlighting all occurrences of given text (find & highlight).
- Removing highlights.
- Selecting highlight color.
- Serialization & deserialization.
- Focusing & deselecting overlapping highlights.
- Works well in iframes.
- Keeps DOM clean.
- No dependencies (apart from core-js and regenerator-runtime for IE11). No jQuery or other libraries needed.
Using the library
You can find the API reference here
which details the interface for the highlighter and the utility functionality that you could also make use
of in your project.
Simple example
import TextHighlighter from '@perlego/text-highlighter';
import { isDuplicate } from './utils';
import highlightsApi from './services/highlights-api';
class ArticleView {
constructor(data) {
this.data = data;
const pageElement = document.getElementById("article");
this.highlighter = new TextHighlighter(
pageElement,
{
version: "independencia",
onBeforeHighlight: this.onBeforeHighlight,
onAfterHighlight: this.onAfterHighlight,
preprocessDescriptors: this.preprocessDescriptors,
onRemoveHighlight: this.onRemoveHighlight
});
}
onBeforeHighlight = (range) => {
return !isDuplicate(range)
}
onRemoveHighlight = (highlightElement) => {
const proceed = window.confirm("Are you sure you want to remove this highlight?");
return proceed;
}
preprocessDescriptors = (range, descriptors, timestamp) => {
const uniqueId = `hlt-${Math.random()
.toString(36)
.substring(2, 15) +
Math.random()
.toString(36)
.substring(2, 15)}`;
const descriptorsWithIds = descriptors.map(descriptor => {
const [wrapper, ...rest] = descriptor;
return [
wrapper.replace(
'class="highlighted"',
`class="highlighted ${uniqueId}"`
),
...rest
];
});
return { descriptors: descriptorsWithIds, meta: { id: uniqueId } };
}
onAfterHighlight = (range, descriptors, timestamp, meta) => {
highlightsApi.saveBatch(meta.id, descriptorsWithIds)
.then((result) => {
})
.catch((err) => console.error(err));
}
render = () => {
}
}
Example disabling default event binding
For the case where you want to trigger the process of creating highlights from a custom event fired in your application you can
do something like the following:
import TextHighlighter from '@perlego/text-highlighter';
import { isDuplicate } from './utils';
import highlightsApi from './services/highlights-api';
class ArticleView {
constructor(data) {
this.data = data;
const pageElement = document.getElementById("article");
this.createButton = document.getElementById("create-highlight");
this.highlighter = new TextHighlighter(
pageElement,
{
version: "independencia",
useDefaultEvents: false,
onBeforeHighlight: this.onBeforeHighlight,
onAfterHighlight: this.onAfterHighlight,
preprocessDescriptors: this.preprocessDescriptors,
onRemoveHighlight: this.onRemoveHighlight
});
this.highlightHandler = highlighter.highlightHandler.bind(highlighter);
createButton.addEventListener("click", this.highlightHandler);
}
destroy() {
createButton.removeEventListener("click", this.highlightHanlder);
}
onBeforeHighlight = (range) => {
return !isDuplicate(range)
}
onRemoveHighlight = (highlightElement) => {
const proceed = window.confirm("Are you sure you want to remove this highlight?");
return proceed;
}
preprocessDescriptors = (range, descriptors, timestamp) => {
const uniqueId = `hlt-${Math.random()
.toString(36)
.substring(2, 15) +
Math.random()
.toString(36)
.substring(2, 15)}`;
const descriptorsWithIds = descriptors.map(descriptor => {
const [wrapper, ...rest] = descriptor;
return [
wrapper.replace(
'class="highlighted"',
`class="highlighted ${uniqueId}"`
),
...rest
];
});
return { descriptors: descriptorsWithIds, meta: { id: uniqueId } };
}
onAfterHighlight = (range, descriptors, timestamp, meta) => {
highlightsApi.saveBatch(meta.id, descriptorsWithIds)
.then((result) => {
})
.catch((err) => console.error(err));
}
render = () => {
}
}
Options
See the TextHighlighter API Reference for the list of all the options,
their default values and detailed descriptions.
Compatibility
Should work in all decent browsers and IE 11.
Running the tests
First run npm install
from the root directory of the repo to install all the test runner dependencies.
To run both integration and unit tests at once use the following:
npm run test:all
Integration tests
The integration tests covers the integration of the larger components that make up the highlighting
functionality such as serialisation + deserialisation, focusing, deselecting, normalisation and interaction with callbacks.
To run the integration tests use the following command:
npm run test:integration
Unit tests
The unit tests cover functions that make up the smaller components that query, manipulate the DOM
along with pure utility pieces.
To run the unit tests use the following command:
npm run test:unit
Running the Primitivo tests (The first version of the highlighter)
The first version of the highlighter contains tests in a standalone jasmine runner that runs in the browser.
To run those tests, first set up the server:
node webserver.js
Then go to http://localhost:5002/test/test.html
and the tests will run on page load.
Building the library for NodeJS (CommonJS modules)
There is a cjs version of the library that gets tracked in version control that is built whenever changes are made.
This is done automatically through a commit hook whenever you make a commit to the repo.
If you need to build this version of the library manually, you can use the following:
npm run build:cjs
And then commit the changes in the cjs folder to version control.
Building the API reference documentation
Ensure all dev dependencies are installed using:
npm install
Ensure grunt is installed globally:
npm install -g grunt
To build the documentation, run the following command:
grunt jsdoc
Ensure the test server is running:
node webserver.js
Then go to http://localhost:5002/doc
to see the API reference for the library.
Demos
Documentation
You may check API reference or
Wiki pages on GitHub.