From 5234226fb3f9e08f5a3c965b2e1c5ba4b1d527f3 Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Wed, 8 Jul 2026 11:34:24 +1000 Subject: [PATCH 1/3] fix: preserve code spans adjacent to tildes --- src/rules.ts | 2 +- test/specs/new/codespan_adjacent_tilde.html | 5 +++++ test/specs/new/codespan_adjacent_tilde.md | 9 +++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 test/specs/new/codespan_adjacent_tilde.html create mode 100644 test/specs/new/codespan_adjacent_tilde.md diff --git a/src/rules.ts b/src/rules.ts index c9bc07c5d6..1321134a20 100644 --- a/src/rules.ts +++ b/src/rules.ts @@ -475,7 +475,7 @@ const inlineGfm: Record = { .getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, - text: edit(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\~code

+

before~after

+

`strike

+

~code ` tick

+

deleted code

diff --git a/test/specs/new/codespan_adjacent_tilde.md b/test/specs/new/codespan_adjacent_tilde.md new file mode 100644 index 0000000000..c7506a61f1 --- /dev/null +++ b/test/specs/new/codespan_adjacent_tilde.md @@ -0,0 +1,9 @@ +~`code` + +`before`~`after` + +`~strike~ + +~``code ` tick`` + +~~`deleted code`~~ From ee8110f048434c5232dcc42a17c9d66c2d166e76 Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Wed, 8 Jul 2026 11:47:23 +1000 Subject: [PATCH 2/3] perf: isolate mixed delimiter boundaries --- src/Tokenizer.ts | 4 +++- src/rules.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Tokenizer.ts b/src/Tokenizer.ts index e6f900d457..ef44e1eae2 100644 --- a/src/Tokenizer.ts +++ b/src/Tokenizer.ts @@ -948,7 +948,9 @@ export class _Tokenizer { } inlineText(src: string): Tokens.Text | undefined { - const cap = this.rules.inline.text.exec(src); + const cap = this.options.gfm && !this.options.pedantic + ? /^(`+(?=~)|~+(?=`))/.exec(src) ?? this.rules.inline.text.exec(src) + : this.rules.inline.text.exec(src); if (cap) { const escaped = this.lexer.state.inRawBlock; return { diff --git a/src/rules.ts b/src/rules.ts index 1321134a20..c9bc07c5d6 100644 --- a/src/rules.ts +++ b/src/rules.ts @@ -475,7 +475,7 @@ const inlineGfm: Record = { .getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, - text: edit(/^(`+|~+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\ Date: Wed, 8 Jul 2026 12:04:31 +1000 Subject: [PATCH 3/3] refactor: keep delimiter boundaries in grammar --- src/Tokenizer.ts | 4 +--- src/rules.ts | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Tokenizer.ts b/src/Tokenizer.ts index ef44e1eae2..e6f900d457 100644 --- a/src/Tokenizer.ts +++ b/src/Tokenizer.ts @@ -948,9 +948,7 @@ export class _Tokenizer { } inlineText(src: string): Tokens.Text | undefined { - const cap = this.options.gfm && !this.options.pedantic - ? /^(`+(?=~)|~+(?=`))/.exec(src) ?? this.rules.inline.text.exec(src) - : this.rules.inline.text.exec(src); + const cap = this.rules.inline.text.exec(src); if (cap) { const escaped = this.lexer.state.inRawBlock; return { diff --git a/src/rules.ts b/src/rules.ts index c9bc07c5d6..b93e0c52cf 100644 --- a/src/rules.ts +++ b/src/rules.ts @@ -475,7 +475,7 @@ const inlineGfm: Record = { .getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, - text: edit(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\