diff --git a/package.json b/package.json index a0b75ff5..2e6a47f7 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@types/flat": "^5.0.1", "@types/gravatar": "^1.8.0", "@types/js-yaml": "^4.0.0", + "@types/linkify-it": "^3.0.2", "@types/lodash.clonedeep": "^4.5.6", "@types/lodash.isequal": "^4.5.5", "@types/lodash.merge": "^4.6.6", @@ -76,7 +77,6 @@ "lodash.merge": "^4.6.2", "markdown-it": "^12.0.4", "markdown-it-math-loose": "^4.1.1", - "markdown-it-mentions": "^1.0.0", "markdown-it-merge-cells": "^1.0.1", "mathjax-full": "^3.1.2", "mobx": "^4.15.4", @@ -116,6 +116,7 @@ "svgo": "^1.3.2", "svgo-loader": "^2.2.1", "timeago.js": "^4.0.2", + "tlds": "^1.227.0", "twemoji": "^13.0.1", "typeface-lato": "^1.1.13", "typeface-saira": "^1.1.13", diff --git a/patches/markdown-it-mentions+1.0.0.patch b/patches/markdown-it-mentions+1.0.0.patch deleted file mode 100644 index 30914642..00000000 --- a/patches/markdown-it-mentions+1.0.0.patch +++ /dev/null @@ -1,10 +0,0 @@ -diff --git a/node_modules/markdown-it-mentions/index.js b/node_modules/markdown-it-mentions/index.js -index a89b364..5dbdf41 100644 ---- a/node_modules/markdown-it-mentions/index.js -+++ b/node_modules/markdown-it-mentions/index.js -@@ -22,4 +22,4 @@ function parser(match, utils) { - ].join(''); - } - --module.exports = regexp(/@(\w+)/, parser); -+module.exports = regexp(/@([a-zA-Z0-9\-_.#$]{3,24})/, parser); diff --git a/src/markdown/markdown.ts b/src/markdown/markdown.ts index a8067f4d..27c501dd 100644 --- a/src/markdown/markdown.ts +++ b/src/markdown/markdown.ts @@ -3,8 +3,10 @@ import { v4 as uuid } from "uuid"; import MarkdownItMath from "markdown-it-math-loose"; import MarkdownItMergeCells from "markdown-it-merge-cells/src"; -import MarkdownItMentions from "markdown-it-mentions"; import MarkdownItTaskLists from "@hackmd/markdown-it-task-lists"; +import LinkifyIt from "linkify-it"; + +import tlds from "tlds"; export interface MarkdownHighlightPlaceholder { id: string; @@ -84,13 +86,30 @@ export function renderMarkdown( blockRenderer: (code: string) => addMathPlaceholder(code, true) }); renderer.use(MarkdownItMergeCells); - renderer.use(MarkdownItMentions, { - parseURL: (username: string) => `/u/${username}` - }); renderer.use(MarkdownItTaskLists, { enabled: true }); + renderer.linkify.add("@", { + validate: (text: string, pos: number, self: LinkifyIt.LinkifyIt): number | boolean => { + var tail: string = text.slice(pos); + const re: RegExp = /^[a-zA-Z0-9\-_.#$]{3,24}$/; + + if (re.test(tail)) { + if (pos >= 2 && tail[pos - 2] === "@") { + return false; + } + return tail.match(re)[0].length; + } + return 0; + }, + normalize: (match: LinkifyIt.Match): void => { + match.url = "/u/" + encodeURIComponent(match.url.replace(/^@/, "")); + } + }); + + renderer.linkify.tlds(tlds); + if (onPatchRenderer) onPatchRenderer(renderer); return [renderer.render(text), highlightPlaceholders, mathPlaceholders, findPlaceholderElement]; diff --git a/src/utils/validators.ts b/src/utils/validators.ts index d6818039..4f42e936 100644 --- a/src/utils/validators.ts +++ b/src/utils/validators.ts @@ -1,6 +1,5 @@ import validator from "validator"; -// Change `/patches/markdown-it-mentions+1.0.0.patch` together if you change this regex export function isValidUsername(username: string): boolean { return /^[a-zA-Z0-9\-_.#$]{3,24}$/.test(username); } diff --git a/yarn.lock b/yarn.lock index 04c69d03..b3b098f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1862,6 +1862,11 @@ resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-2.1.0.tgz#ea3dd64c4805597311790b61e872cbd1ed2cd806" integrity sha512-Q7DYAOi9O/+cLLhdaSvKdaumWyHbm7HAk/bFwwyTuU0arR5yyCeW5GOoqt4tJTpDRxhpx9Q8kQL6vMpuw9hDSw== +"@types/linkify-it@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.2.tgz#fd2cd2edbaa7eaac7e7f3c1748b52a19143846c9" + integrity sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA== + "@types/lodash.clonedeep@^4.5.6": version "4.5.6" resolved "https://registry.yarnpkg.com/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.6.tgz#3b6c40a0affe0799a2ce823b440a6cf33571d32b" @@ -8794,13 +8799,6 @@ markdown-it-math-loose@^4.1.1: optionalDependencies: ascii2mathml "^0.6.2" -markdown-it-mentions@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/markdown-it-mentions/-/markdown-it-mentions-1.0.0.tgz#2dc6a06d0604bfbf57ac22efb3558f338098990a" - integrity sha512-zZnkEWHfnIXCwzgv9WJh0Wo6iuwLJaApfOMQfKEqjYM5A98XXEChPRqI7jvZAdzPGfCfaBFv0GUQqUYw4DeSjg== - dependencies: - markdown-it-regexp "^0.4.0" - markdown-it-merge-cells@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/markdown-it-merge-cells/-/markdown-it-merge-cells-1.0.1.tgz#ad375a09fa709213c19a354e537e560789ae2be8" @@ -8808,11 +8806,6 @@ markdown-it-merge-cells@^1.0.1: dependencies: babel-runtime "^6.26.0" -markdown-it-regexp@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/markdown-it-regexp/-/markdown-it-regexp-0.4.0.tgz#d64d713eecec55ce4cfdeb321750ecc099e2c2dc" - integrity sha1-1k1xPuzsVc5M/esyF1DswJniwtw= - markdown-it@^12.0.4: version "12.0.4" resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.0.4.tgz#eec8247d296327eac3ba9746bdeec9cfcc751e33" @@ -12953,6 +12946,11 @@ tiny-warning@^1.0.0: resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== +tlds@^1.227.0: + version "1.227.0" + resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.227.0.tgz#6352577d74c4b7f6f80ebdeebafdf28c10aee8c0" + integrity sha512-H6KXre7PSkfZyPiGzHvdG/p42LCfPmmyH3MhmZnULiVGEGXKBe8vzyLrw6q0UAtXOL0eNScA9vC4DcfhrcaPlg== + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"