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]*?(?:(?=[\\