Skip to content

Commit

Permalink
Merge pull request #4423 from traPtitech/fix/mention-embed-in-url
Browse files Browse the repository at this point in the history
URL内のメンションは埋め込まれないように
  • Loading branch information
nokhnaton authored Dec 30, 2024
2 parents 3a43eae + 61afa32 commit a4134d1
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 9 deletions.
18 changes: 13 additions & 5 deletions src/lib/markdown/internalLinkEmbedder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@
* https://github.com/traPtitech/traQ/blob/master/utils/message/replacer.goと同様
*/

const mentionRegex = /:?[@@]([^\s@@]{0,31}[^\s@@:])/g
// URLの一部になっているときは置換しない (URLの正規表現は完全ではない)
const urlRegexStr = '(?:https?://)?(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]+(?:/[^/]+)*/?'
const mentionRegex = new RegExp(
`(?<!${urlRegexStr}):?[@@]([^\\s@@.]{0,31}[^\\s@@:.])\\.?`,
'g'
)
const userStartsRegex = /^[@@]([a-zA-Z0-9_-]{1,32})/g
const channelRegex = /[##]([a-zA-Z0-9_/-]+)/g
const channelRegex = new RegExp(
`(?<!${urlRegexStr})[##]([a-zA-Z0-9_/-]+)`,
'g'
)

const backQuote = '`'
const dollar = '$'
Expand Down Expand Up @@ -115,9 +123,9 @@ const replaceAll = (m: string, getters: Readonly<ReplaceGetters>) => {
const replaceMention = (m: string, getters: Readonly<UserAndGroupGetters>) => {
return m.replace(mentionRegex, s => {
// 始まりが:なものを除外
if (s.startsWith(':')) {
return s
}
if (s.startsWith(':')) return s
// 終わりが.のものを除外
if (s.endsWith('.')) return s

// .slice(1)は先頭の@を消すため
// 小文字化はgetter内で行う
Expand Down
24 changes: 20 additions & 4 deletions tests/unit/lib/markdown/internalLinkEmbedder.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type {
ReplaceGetters,
Entity
Entity,
ReplaceGetters
} from '/@/lib/markdown/internalLinkEmbedder'
import { replace } from '/@/lib/markdown/internalLinkEmbedder'

Expand All @@ -20,6 +20,10 @@ const users = {
'dfdff0c9-5de0-46ee-9721-2525e8bb3d47': {
name: 'very_long_long_long_long_lo_name',
id: 'dfdff0c9-5de0-46ee-9721-2525e8bb3d47'
},
'dfdff0c9-5de0-46ee-9721-2525e8bb3d48': {
name: 'trap',
id: 'dfdff0c9-5de0-46ee-9721-2525e8bb3d48'
}
}
const groups = {
Expand Down Expand Up @@ -60,6 +64,7 @@ const testStore: ReplaceGetters = {
type Spec = [string, string]

const specs: Spec[] = [
// must embed cases
[
'aaaa#aeee `#a` @takashi_trapa @takashi_trap @#a\n```\n#a @takashi_trap\n```\n@okあok',
'aaaa#aeee `#a` @takashi_trapa !{"type":"user","raw":"@takashi_trap","id":"dfdff0c9-5de0-46ee-9721-2525e8bb3d45"} @!{"type":"channel","raw":"#a","id":"ea452867-553b-4808-a14f-a47ee0009ee6"}\n```\n#a @takashi_trap\n```\n!{"type":"group","raw":"@okあok","id":"dfabf0c9-5de0-46ee-9721-2525e8bb3d45"}'
Expand Down Expand Up @@ -112,12 +117,23 @@ const specs: Spec[] = [
[
'@a',
'!{"type":"user","raw":"@a","id":"dfdff0c9-5de0-46ee-9721-2525e8bb3d44"}'
]
],
// must not embed cases
['https://example.com#a', 'https://example.com#a'],
['example.com/#a', 'example.com/#a'],
['example.com/hello#a', 'example.com/hello#a'],
['https://example.com/@takashi_trap', 'https://example.com/@takashi_trap'],
[
'example.com/users/@takashi_trap/hello',
'example.com/users/@takashi_trap/hello'
],
['[email protected]', '[email protected]'],
['@ab', '@ab']
]

describe('internalLinkEmbedder', () => {
specs.forEach(([before, after], i) => {
it(`can embed internal links ${i}`, () => {
it(`must or must not embed internal links ${i}`, () => {
expect(replace(before, testStore)).toEqual(after)
})
})
Expand Down

0 comments on commit a4134d1

Please sign in to comment.