Implement simple regexp based highlighter

This commit is contained in:
Chi Vinh Le
2017-09-12 20:47:05 +07:00
parent f2804f2394
commit d18a9a057b
7 changed files with 57 additions and 56 deletions
@@ -1,25 +1,56 @@
import React from 'react';
import Highlighter from 'react-highlight-words';
import Linkify from 'react-linkify';
const linkify = new Linkify();
import {linkRegexp} from '../utils/regexp';
const wordSeperator = /([.\s'"?!])/;
function markWords(body, words, index) {
const tokens = body.split(wordSeperator);
const content = [];
let tmp = [];
tokens.forEach((token, i) => {
if (words.indexOf(token.toLowerCase()) >= 0) {
content.push(...tmp);
tmp = [];
content.push(<mark key={`${index}_${i}`}>{token}</mark>);
return;
}
tmp.push(token);
});
content.push(...tmp);
return content;
}
function markLinks(body) {
const tokens = body.split(linkRegexp);
const content = [];
let tmp = [];
tokens
.filter((token) => token)
.forEach((token, i) => {
if (token.match(linkRegexp)) {
content.push(...tmp);
tmp = [];
content.push(<mark key={i}>{token}</mark>);
return;
}
tmp.push(token);
});
content.push(...tmp);
return content;
}
export default ({suspectWords, bannedWords, body, ...rest}) => {
const links = linkify.getMatches(body);
const linkText = links ? links.map((link) => link.raw) : [];
const searchWords = [
...suspectWords,
...bannedWords,
...linkText
];
const words = [...suspectWords, ...bannedWords].map((word) => word.toLowerCase());
const content = markLinks(body)
.map((element, index) => {
if (typeof element !== 'string') {
return element;
}
return markWords(element, words, index);
});
return (
<Highlighter
{...rest}
autoEscape={true}
searchWords={searchWords}
textToHighlight={body}
/>
<div {...rest}>
{content}
</div>
);
};
@@ -1,9 +1,8 @@
import React from 'react';
import Linkify from 'react-linkify';
const linkify = new Linkify();
import {linkRegexp} from '../utils/regexp';
export default ({text, children}) => {
const hasLinks = !!linkify.getMatches(text);
const hasLinks = text.match(linkRegexp);
if (!hasLinks) {
return null;
@@ -127,7 +127,7 @@ class Comment extends React.Component {
</div>
<CommentAnimatedEdit body={comment.body}>
<div className={styles.itemBody}>
<p className={styles.body}>
<div className={styles.body}>
<CommentBodyHighlighter
suspectWords={suspectWords}
bannedWords={bannedWords}
@@ -141,7 +141,7 @@ class Comment extends React.Component {
>
<Icon name="open_in_new" /> {t('comment.view_context')}
</a>
</p>
</div>
<Slot
fill="adminCommentContent"
data={data}
+1
View File
@@ -2,3 +2,4 @@ export const isPremod = (mod) => mod === 'PRE';
export const getModPath = (type = 'all', assetId) =>
assetId ? `/admin/moderate/${type}/${assetId}` : `/admin/moderate/${type}`;
+1
View File
@@ -0,0 +1 @@
export const linkRegexp = /([-a-zA-Z0-9@:%_+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_+.~#?&//=]*)?)/;
-2
View File
@@ -154,9 +154,7 @@
"react": "^15.4.2",
"react-apollo": "^1.4.12",
"react-dom": "^15.4.2",
"react-highlight-words": "^0.6.0",
"react-input-autosize": "^1.1.4",
"react-linkify": "^0.1.3",
"react-mdl": "^1.7.2",
"react-mdl-selectfield": "^0.2.0",
"react-recaptcha": "^2.2.6",
+1 -30
View File
@@ -922,7 +922,7 @@ babel-register@^6.26.0:
mkdirp "^0.5.1"
source-map-support "^0.4.15"
babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0, babel-runtime@^6.6.1:
babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0, babel-runtime@^6.6.1:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
dependencies:
@@ -3396,12 +3396,6 @@ hide-powered-by@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/hide-powered-by/-/hide-powered-by-1.0.0.tgz#4a85ad65881f62857fc70af7174a1184dccce32b"
highlight-words-core@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/highlight-words-core/-/highlight-words-core-1.0.3.tgz#0886d0e757c8ca3928cbc873042bd544f8f6b2e5"
dependencies:
babel-runtime "^6.11.6"
history@^3.0.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/history/-/history-3.3.0.tgz#fcedcce8f12975371545d735461033579a6dae9c"
@@ -4395,12 +4389,6 @@ license-webpack-plugin@^1.0.0:
dependencies:
ejs "^2.5.7"
linkify-it@^1.2.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-1.2.4.tgz#0773526c317c8fd13bd534ee1d180ff88abf881a"
dependencies:
uc.micro "^1.0.1"
linkify-it@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.0.3.tgz#d94a4648f9b1c179d64fa97291268bdb6ce9434f"
@@ -6379,12 +6367,6 @@ react-dom@^15.3.1, react-dom@^15.4.2:
object-assign "^4.1.0"
prop-types "~15.5.7"
react-highlight-words@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/react-highlight-words/-/react-highlight-words-0.6.0.tgz#e12e9fedda4333e410ea408cdedffc77122020aa"
dependencies:
highlight-words-core "^1.0.2"
react-input-autosize@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-1.1.4.tgz#cbc45072d4084ddc57806db8e3b34e644b8366ac"
@@ -6392,13 +6374,6 @@ react-input-autosize@^1.1.4:
create-react-class "^15.5.2"
prop-types "^15.5.8"
react-linkify@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/react-linkify/-/react-linkify-0.1.3.tgz#6e886180bda6c8fdc5f9f8a7ebe82fc0f48db7ad"
dependencies:
linkify-it "^1.2.0"
tlds "^1.57.0"
react-mdl-selectfield@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/react-mdl-selectfield/-/react-mdl-selectfield-0.2.0.tgz#36e1a97233036c057ab2bdb31ec09ad8d9988411"
@@ -7456,10 +7431,6 @@ title-case-minors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/title-case-minors/-/title-case-minors-1.0.0.tgz#51f17037c294747a1d1cda424b5004c86d8eb115"
tlds@^1.57.0:
version "1.185.0"
resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.185.0.tgz#9d5ddaae379778a98e3edc3a131d46a40cbc3ba4"
tmp@^0.0.31:
version "0.0.31"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7"