From 3fbe7031934430ebbea8bca30266e0a262c0525d Mon Sep 17 00:00:00 2001 From: Cobblestone Date: Fri, 11 Aug 2023 17:57:29 -0400 Subject: [PATCH] fix: Make `mentionRegex` stricter (#1) * use stricter regex * remove leading whitespace from regex --- README.md | 11 ++++++++--- lib/index.js | 32 +++++++++++++++++++++++++------- package-lock.json | 4 ++-- test/index.js | 3 +++ 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 35d150b..986be1e 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,9 @@ [![Build][build-badge]][build] [![Coverage][coverage-badge]][coverage] - ## What is this? -This package is a [unified][] ([remark][]) plugin to convert @ mentions to links: `@wooorm` -> `[**@wooorm**](https://github.com/wooorm)`. +This package is a [unified][unified-link] ([remark][remark-link]) plugin to convert @ mentions to links: `@wooorm` -> `[**@wooorm**](https://github.com/wooorm)`. **unified** is a project that transforms content with abstract syntax trees (ASTs). @@ -19,7 +18,9 @@ This is a remark plugin that transforms mdast. ```sh npm install remark-mentions ``` + ## Usage + ```js import {remark} from 'remark' import remarkMentions from 'remark-mentions' @@ -43,4 +44,8 @@ console.log(String(file)) [coverage-badge]: https://img.shields.io/codecov/c/github/finnrg/remark-mentions.svg -[coverage]: https://codecov.io/github/finnrg/remark-mentions \ No newline at end of file +[coverage]: https://codecov.io/github/finnrg/remark-mentions + +[unified-link]: https://github.com/unifiedjs/unified + +[remark-link]: https://github.com/remarkjs/remark diff --git a/lib/index.js b/lib/index.js index a5a0168..67c9e94 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,5 +1,7 @@ /** * @typedef {import('mdast').Root} Root + * + * @typedef {import('mdast').PhrasingContent} PhrasingContent * * @typedef {import('mdast-util-find-and-replace').ReplaceFunction} ReplaceFunction * @@ -10,9 +12,9 @@ import { findAndReplace } from "mdast-util-find-and-replace"; -const userGroup = "[\\da-z][-\\da-z]{0,38}"; +const userGroup = "[\\da-z][-\\da-z_]{0,38}"; const mentionRegex = new RegExp( - "@(" + userGroup + "(?:\\/" + userGroup + ")?)", + "(?:^|\\s)@(" + userGroup + ")", "gi" ); @@ -34,10 +36,26 @@ export default function remarkMentions( * @param {string} username */ function replaceMention(value, username) { - return { - type: "link", - url: opts.usernameLink(username), - children: [{ type: "strong", children: [{ type: "text", value }] }], - }; + /** @type {PhrasingContent[]} */ + let whitespace = []; + + // Separate leading white space + if (value.indexOf("@") > 0) { + whitespace.push({ + type: "text", + value: value.substring(0, value.indexOf("@")), + }); + } + + return [ + ...whitespace, + { + type: "link", + url: opts.usernameLink(username), + children: [ + { type: "strong", children: [{ type: "text", value: value.trim() }] }, // Trim the username here + ], + }, + ]; } } diff --git a/package-lock.json b/package-lock.json index 8fb0370..d017ae3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "remark-mentions", - "version": "1.0.0", + "version": "1.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "remark-mentions", - "version": "1.0.0", + "version": "1.0.2", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", diff --git a/test/index.js b/test/index.js index 67e528b..c254ca8 100644 --- a/test/index.js +++ b/test/index.js @@ -8,6 +8,7 @@ import { remark } from "remark"; import { VFile } from "vfile"; test("remark-mentions", (t) => { + t.equal(typeof remarkMentions, "function", "should be a function"); t.doesNotThrow(() => { @@ -17,6 +18,8 @@ test("remark-mentions", (t) => { t.equal(process("@test"), "[**@test**](/test)\n"); t.equal(process("This is @test"), "This is [**@test**](/test)\n"); + + t.equal(process("https://example.com/@test"), "https://example.com/@test\n"); t.equal( process("@test", { usernameLink: (username) => `/Profile/${username}` }),