Do not highlight usernames inside links (#366)

sweet!

* Do not highlight usernames  inside words

Fixes #156

* Do not search on separate words

* Add accuracy options to markjs
This commit is contained in:
Matt Steele 2020-11-17 19:29:03 -06:00 committed by GitHub
parent f8d94c2dc2
commit aeb221b32f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 29714 additions and 19 deletions

2
build/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules
web_modules

View File

@ -1467,6 +1467,11 @@
"global": "^4.3.2" "global": "^4.3.2"
} }
}, },
"mark.js": {
"version": "8.11.1",
"resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz",
"integrity": "sha1-GA8fnr74sOY45BZq1S24eb6y/8U="
},
"mdn-data": { "mdn-data": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",

View File

@ -6,12 +6,13 @@
"dependencies": { "dependencies": {
"@joeattardi/emoji-button": "^4.5.0", "@joeattardi/emoji-button": "^4.5.0",
"@justinribeiro/lite-youtube": "^0.9.1", "@justinribeiro/lite-youtube": "^0.9.1",
"@videojs/http-streaming": "2.3.0",
"@videojs/themes": "^1.0.1", "@videojs/themes": "^1.0.1",
"htm": "^3.0.4", "htm": "^3.0.4",
"mark.js": "^8.11.1",
"preact": "^10.5.7", "preact": "^10.5.7",
"tailwindcss": "^1.9.6", "tailwindcss": "^1.9.6",
"video.js": "7.10.2", "video.js": "7.10.2"
"@videojs/http-streaming": "2.3.0"
}, },
"devDependencies": { "devDependencies": {
"cssnano": "^4.1.10", "cssnano": "^4.1.10",
@ -27,6 +28,7 @@
"@justinribeiro/lite-youtube", "@justinribeiro/lite-youtube",
"htm", "htm",
"preact", "preact",
"mark.js/dist/mark.es6.min.js",
"tailwindcss/dist/tailwind.min.css" "tailwindcss/dist/tailwind.min.css"
], ],
"alias": { "alias": {

View File

@ -1,5 +1,6 @@
import { h, Component } from '/js/web_modules/preact.js'; import { h, Component } from '/js/web_modules/preact.js';
import htm from '/js/web_modules/htm.js'; import htm from '/js/web_modules/htm.js';
import Mark from '/js/web_modules/markjs/dist/mark.es6.min.js';
const html = htm.bind(h); const html = htm.bind(h);
import { import {
@ -10,11 +11,27 @@ import { convertToText } from '../../utils/chat.js';
import { SOCKET_MESSAGE_TYPES } from '../../utils/websocket.js'; import { SOCKET_MESSAGE_TYPES } from '../../utils/websocket.js';
export default class ChatMessageView extends Component { export default class ChatMessageView extends Component {
render() { async componentDidUpdate(prevProps) {
const { message, username } = this.props; const { message, username } = this.props;
const { author, body, timestamp } = message; if (prevProps.message === message && this.state.formattedMessage) {
return;
}
const { body } = message;
const formattedMessage = formatMessageText(body, username); const formattedMessage = await formatMessageText(body, username);
this.setState({
formattedMessage
});
}
render() {
const { message } = this.props;
const { author, timestamp } = message;
const { formattedMessage } = this.state;
if (!formattedMessage) {
return;
}
const formattedTimestamp = formatTimestamp(timestamp); const formattedTimestamp = formatTimestamp(timestamp);
const isSystemMessage = message.type === SOCKET_MESSAGE_TYPES.SYSTEM; const isSystemMessage = message.type === SOCKET_MESSAGE_TYPES.SYSTEM;
@ -60,21 +77,30 @@ function getChatMessageClassString() {
return 'message flex flex-row items-start p-3 m-3 rounded-lg shadow-s text-sm'; return 'message flex flex-row items-start p-3 m-3 rounded-lg shadow-s text-sm';
} }
export function formatMessageText(message, username) { export async function formatMessageText(message, username) {
let formattedText = highlightUsername(message, username); let formattedText = getMessageWithEmbeds(message);
formattedText = getMessageWithEmbeds(formattedText); formattedText = convertToMarkup(formattedText);
return convertToMarkup(formattedText); return await highlightUsername(formattedText, username);
} }
function highlightUsername(message, username) { function highlightUsername(message, username) {
const pattern = new RegExp( // https://github.com/julmot/mark.js/issues/115
'@?' + username.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), const node = document.createElement('span');
'gi' node.innerHTML = message;
); return new Promise(res => {
return message.replace( new Mark(node).mark(username, {
pattern, element: 'span',
'<span class="highlighted px-1 rounded font-bold bg-orange-500">$&</span>' className: 'highlighted px-1 rounded font-bold bg-orange-500',
); separateWordSearch: false,
accuracy: {
value: 'exactly',
limiters: [",", ".", "'", '?', '@'],
},
done() {
res(node.innerHTML);
}
});
});
} }
function getMessageWithEmbeds(message) { function getMessageWithEmbeds(message) {

View File

@ -1,4 +1,5 @@
import { c as createCommonjsModule, g as getDefaultExportFromCjs, d as document_1, w as window_1, a as core, b as commonjsGlobal } from '../../../common/core-b8f2ee39.js'; import { c as createCommonjsModule, g as getDefaultExportFromCjs, a as commonjsGlobal } from '../../../common/_commonjsHelpers-37fa8da4.js';
import { d as document_1, w as window_1, c as core } from '../../../common/core-440932cf.js';
//[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF] //[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
//[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] //[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]

View File

@ -0,0 +1,25 @@
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
function createCommonjsModule(fn, basedir, module) {
return module = {
path: basedir,
exports: {},
require: function (path, base) {
return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
}
}, fn(module, module.exports), module.exports;
}
function getDefaultExportFromNamespaceIfNotNamed (n) {
return n && Object.prototype.hasOwnProperty.call(n, 'default') && Object.keys(n).length === 1 ? n['default'] : n;
}
function commonjsRequire () {
throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
}
export { commonjsGlobal as a, getDefaultExportFromNamespaceIfNotNamed as b, createCommonjsModule as c, getDefaultExportFromCjs as g };

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@
"@videojs/http-streaming/dist/videojs-http-streaming.min.js": "./@videojs/http-streaming/dist/videojs-http-streaming.min.js", "@videojs/http-streaming/dist/videojs-http-streaming.min.js": "./@videojs/http-streaming/dist/videojs-http-streaming.min.js",
"@videojs/themes/fantasy/index.css": "./@videojs/themes/fantasy/index.css", "@videojs/themes/fantasy/index.css": "./@videojs/themes/fantasy/index.css",
"htm": "./htm.js", "htm": "./htm.js",
"mark.js/dist/mark.es6.min.js": "./markjs/dist/mark.es6.min.js",
"preact": "./preact.js", "preact": "./preact.js",
"tailwindcss/dist/tailwind.min.css": "./tailwindcss/dist/tailwind.min.css", "tailwindcss/dist/tailwind.min.css": "./tailwindcss/dist/tailwind.min.css",
"video.js": "./video.js/core.js", "video.js": "./video.js/core.js",

File diff suppressed because one or more lines are too long

View File

@ -1 +1,2 @@
export { a as default } from '../common/core-b8f2ee39.js'; import '../common/_commonjsHelpers-37fa8da4.js';
export { c as default } from '../common/core-440932cf.js';