README
React Mark JS
π¬ A React wrapper around the popular mark.js library.
Contents
Single Page Doc
β‘οΈ Installation
The best way to install react-mark.js
is via the
npm
package which you can install with npm
(or yarn
if you prefer)
π¦ NPM
npm install -S mark.js react-mark.js
π¦ Yarn
yarn add mark.js react-mark.js
NOTE:
mark-js
is a peer dependency
βοΈ Importing Components
You can choose to import single components like react-mark.js/Marker
rather
than the entire component library.
import Marker from "react-mark.js/Marker";
// or; if you prefer
import { Marker } from "react-marker.js";
π Basic Example
import Marker from "react-mark.js/Marker";
// or; if you prefer
import { Marker } from "react-mark.js";
export default () => (
<Marker mark="reprehenderit">
Cillum proident eu eiusmod incididunt pariatur.
Ullamco qui deserunt ut reprehenderit cupidatat cupidatat
nisi non occaecat non commodo. Magna
incididunt eu laboris laboris labore. Sit duis
ullamco qui nostrud aliqua do
consectetur do incididunt eiusmod nulla consectetur.
Sint reprehenderit culpa consectetur irure commodo magna.
Officia Lorem veniam est cillum.
</Marker>
);
πββοΈ Styling
When you wrap a component with <Marker />
; the text-content
that you are trying to highlight will automatically be wrapped
with <mark /> HTML Element
.
Mark Elements usually comes with default styles and that may be enough for some use cases.
Custom configuration for this inline <mark />
element depends on
the style-framework that is integrated in your application.
(demo β)
CSS - Single ElementIf you have your styles in a CSS file; you can simply add styles for
the mark element
in your CSS stylesheet:
mark {
background-color: deeppink;
}
If you multiple markers on your page and want to style each one differently that too is possible.
(demo β)
CSS - Multiple ElementsIf you want to mark each element differently you need
to pass a className
in the options object to
<Marker />
element and then add the styles for
each class.
<Marker
options={{className: 'custom-marker-1'}}
mark="hello"
>
Hello World
</Marker>
<Marker
options={{className: 'custom-marker-2'}}
mark="hello"
>
Hello World
</Marker>
Now, add the CSS styles for each class
mark.custom-marker-1 {
background-color: orange;
padding: 2px;
}
mark.custom-marker-2 {
background-color: lightgreen;
padding: 2px;
}
(demo β)
Styled ComponentsYou can simply pass the Marker
to the styled component
and style it. For ex:
import styled from "styled-components";
export const OrangeMarker = styled(Marker)`
mark {
background-color: orange !important;
}
`;
export const LightGreenMarker = styled(Marker)`
mark {
background-color: lightgreen;
}
`;
π Components
<Marker />
Stack Blitz Demo β
β‘οΈ A wrapper component to higlight text-content matching strings.
import React from "react";
import Marker from "react-mark.js/Marker"; // or, import {Marker} from 'react-mark.js'
const MarkerExamples = () => {
return (
<div>
<h2>Single String</h2>
<Marker mark="Ullamco qui deserunt ut reprehenderit">
Cillum proident eu eiusmod incididunt pariatur.
Ullamco qui deserunt ut
reprehenderit cupidatat cupidatat nisi non
occaecat non commodo. Magna
incididunt eu laboris laboris labore.
</Marker>
<h2>Multiple Strings</h2>
<Marker mark={["eiusmod incididunt", "commodo. Magna"]}>
Cillum proident eu eiusmod incididunt pariatur.
Ullamco qui deserunt ut
reprehenderit cupidatat cupidatat nisi non occaecat
non commodo. Magna
incididunt eu laboris laboris labore.
</Marker>
<h2>Configure Wrapper Element</h2>
<Marker
as="section"
mark="Ullamco qui deserunt ut reprehenderit"
>
Cillum proident eu eiusmod incididunt pariatur.
Ullamco qui deserunt ut reprehenderit cupidatat
cupidatat nisi non occaecat non commodo.
Magna incididunt eu laboris laboris labore.
</Marker>
<h2>With Options</h2>
<Marker
as="section"
mark="nisi non occaecat"
options={{
className: "custom-marker-1"
}}
>
Cillum proident eu eiusmod incididunt pariatur.
Ullamco qui deserunt ut reprehenderit cupidatat
cupidatat nisi non occaecat non commodo. Magna
incididunt eu laboris laboris labore.
</Marker>
</div>
);
};
export default MarkerExamples;
<RegExpMarker />
Stack Blitz Demo β
β‘οΈ A wrapper component to higlight strings matching a regular expression.
import React from "react";
import { RegExpMarker } from "react-mark.js";
const RegExpMarkerExamples = () => (
<div>
<h2>Marking with RegExp</h2>
<RegExpMarker mark={/qui/}>
Cillum proident eu eiusmod incididunt pariatur. Ullamco qui deserunt ut
reprehenderit cupidatat cupidatat nisi non occaecat non commodo. Magna
incididunt eu laboris laboris labore.{" "}
</RegExpMarker>
</div>
);
export default RegExpMarkerExamples;
<RangesMarker />
Stack Blitz Demo β
β‘οΈ Sometimes you may want to mark text-content based on the position in the text content instead of a string. For ex. you would like to mark 5 letters from the 3rd position of text.
import React from "react";
import RangesMarker from "react-mark.js/RangesMarker";
// or import {RangesMarker} from 'react-mark.js'
const blue = { color: "blue" };
export const RangesExample = () => {
return (
<div>
<h2>Single Range</h2>
<RangesMarker
style={blue}
mark={[
{
length: 5,
start: 3
}
]}
>
<h3>0123456789</h3>
</RangesMarker>
<h2>Multiple Ranges</h2>
<RangesMarker
style={blue}
mark={[
{
length: 5,
start: 3
},
{
length: 15,
start: 11
}
]}
>
<h3>0123456789 123456789 123456789 123456789</h3>
</RangesMarker>
<h2>With Options</h2>
<RangesMarker
mark={[
{
length: 5,
start: 3
},
{
length: 15,
start: 11
}
]}
options={{
className: "custom-marker-1"
}}
>
<h3 style={blue}>0123456789 123456789 123456789 123456789</h3>
</RangesMarker>
</div>
);
};
export default RangesExample;
πͺ Hooks
useMarkerStack Blitz Demo βοΈ
This recipe is for more custom configuration as you can
access the markerRef
and marker
(which is a MarkJS instance).
markerRef
- you would pass this to the component wrapping your element.marker
- a MarkJS instance which has an API for marking and un-marking.
Lets dive into an example which will make things more clearer.
import React from "react";
import { useMarker } from "react-mark.js";
const MyContent = () => {
const { markerRef, marker } = useMarker();
React.useEffect(() => {
if (marker) {
marker.mark("orl");
}
}, [marker]);
const mark = React.useCallback(() => {
marker.mark("Hello"); // https://markjs.io#mark
}, [marker]);
const unmark = React.useCallback(() => {
marker.unmark(); // https://markjs.io#unmark
}, [marker]);
return (
<div ref={markerRef}>
Hello World
<button onClick={mark}>Mark</button>
<button onClick={unmark}>Unmark</button>
</div>
);
};
export default MyContent;
Options
options
(optional prop)
β‘οΈ You can pass any of these options to the options props (source - mark.js):
Option | Type | Default | Description |
---|---|---|---|
element | string | "mark" | HTML element to wrap matches, e.g. span |
className | string | "" | A class name that will be appended to element |
exclude | array | [ ] | An array with exclusion selectors. Matches inside these elements will be ignored. Example: "filter": ["h1", ".ignore"] |
separateWordSearch | boolean | true | Whether to search for each word separated by a blank instead of the complete term |
accuracy | string or object | "partially" | Either one of the following string values:
|
diacritics | boolean | true | If diacritic characters should be matched. For example "piΔkny" would also match "piekny" and "doner" would also match "dΓΆner" |
synonyms | object | {} | An object with synonyms. The key will be a synonym for the value and the value for the key. Example: synonyms: {"one": "1"} will add the synonym "1" for "one" and vice versa |
iframes | boolean | false | Whether to search also inside iframes. If you don't have permissions to some iframes (e.g. because they have a different origin) they will be silently skipped. If you don't want to search inside specific iframes (e.g. facebook share), you can pass an exclude selector that matches these iframes |
iframesTimeout | number | 5000 | The maximum ms to wait for a load event before skipping an iframe. Especially important when there's no internet connection or a browser "offline" mode is enabled and an iframe has an online src β then the load event is never fired |
acrossElements | boolean | false | Whether to search for matches across elements |
caseSensitive | boolean | false | Whether to search case sensitive |
ignoreJoiners | boolean | false | Whether to also find matches that contain soft hyphen, zero width space, zero width non-joiner and zero width joiner. They're used to indicate a point for a line break where there isn't enough space to show the full word |
ignorePunctuation | array | [ ] | An array of punctuation mark strings. These punctuation marks can be between any characters, e.g. setting this option to ["'"] would match "Worlds", "World's" and "Wo'rlds". One or more apostrophes between the letters would still produce a match (e.g. "W'o''r'l'd's"). A typical setting for this option could be as follows: ":;.,-βββ_(){}[]!'\"+=".split("") |
wildcards | string | "disabled" | Set to any of the following string values:
|
each | function | A callback for each marked element. Receives the marked DOM element as a parameter | |
filter | function | A callback to filter or limit matches. It will be called for each match and receives the following parameters:
| |
noMatch | function | A callback function that will be called when there are no matches. Receives the not found term as a parameter | |
done | function | A callback function after all marks are done. Receives the total number of marks as a parameter | |
debug | boolean | false | Set this option to true if you want to log messages |
log | object | console | Log messages to a specific object (only if debug is true) |
unmarkOptions
(optional prop)
β‘οΈ Any of the following options can be passed
to the unmarkOptions prop
in the available components
or hook (source - mark.js):.
Option | Type | Default | Description |
---|---|---|---|
element | string | "" | Will remove only marked elements with this specific element |
className | string | "" | Will remove only marked elements with this specific class name |
exclude | array | [ ] |
An array with exclusion selectors. These elements will be ignored.
Example: "filter": ["h1", ".ignore"]
|
iframes | boolean | false |
Whether to search also inside iframes. If you don't have permissions to
some iframes (e.g. because they have a{" "}
different origin
) they will be silently skipped. If you don't want to search inside specific
iframes (e.g. facebook share), you can pass an exclude selector
that matches these iframes
|
iframesTimeout | number | 5000 |
The maximum ms to wait for a load event before skipping an
iframe. Especially important when there's no internet connection or a
browser "offline" mode is enabled and an iframe has an online{" "}
src β then the load event is never fired
|
done | function | A callback function after all marked elements were removed | |
debug | boolean | false |
Set this option to true if you want to log messages
|
log | object | console |
Log messages to a specific object (only if debug is true)
|