Skip to content

Commit

Permalink
fix: allow strikethrough inside strong and em to follow gfm (#3569)
Browse files Browse the repository at this point in the history
  • Loading branch information
UziTech authored Jan 2, 2025
1 parent 33eb5c6 commit 8a01658
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 3 deletions.
19 changes: 16 additions & 3 deletions src/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,27 +249,40 @@ const _notPunctuationOrSpace = /[^\s\p{P}\p{S}]/u;
const punctuation = edit(/^((?![*_])punctSpace)/, 'u')
.replace(/punctSpace/g, _punctuationOrSpace).getRegex();

// GFM allows ~ inside strong and em for strikethrough
const _punctuationGfmStrongEm = /(?!~)[\p{P}\p{S}]/u;
const _punctuationOrSpaceGfmStrongEm = /(?!~)[\s\p{P}\p{S}]/u;
const _notPunctuationOrSpaceGfmStrongEm = /(?:[^\s\p{P}\p{S}]|~)/u;

// sequences em should skip over [title](link), `code`, <html>
const blockSkip = /\[[^[\]]*?\]\((?:\\.|[^\\\(\)]|\((?:\\.|[^\\\(\)])*\))*\)|`[^`]*?`|<[^<>]*?>/g;

const emStrongLDelim = edit(/^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/, 'u')
.replace(/punct/g, _punctuation)
.getRegex();

const emStrongRDelimAst = edit(
const emStrongRDelimAstCore =
'^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)' // Skip orphan inside strong
+ '|[^*]+(?=[^*])' // Consume to delim
+ '|(?!\\*)punct(\\*+)(?=[\\s]|$)' // (1) #*** can only be a Right Delimiter
+ '|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)' // (2) a***#, a*** can only be a Right Delimiter
+ '|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)' // (3) #***a, ***a can only be Left Delimiter
+ '|[\\s](\\*+)(?!\\*)(?=punct)' // (4) ***# can only be Left Delimiter
+ '|(?!\\*)punct(\\*+)(?!\\*)(?=punct)' // (5) #***# can be either Left or Right Delimiter
+ '|notPunctSpace(\\*+)(?=notPunctSpace)', 'gu') // (6) a***a can be either Left or Right Delimiter
+ '|notPunctSpace(\\*+)(?=notPunctSpace)'; // (6) a***a can be either Left or Right Delimiter

const emStrongRDelimAst = edit(emStrongRDelimAstCore, 'gu')
.replace(/notPunctSpace/g, _notPunctuationOrSpace)
.replace(/punctSpace/g, _punctuationOrSpace)
.replace(/punct/g, _punctuation)
.getRegex();

const emStrongRDelimAstGfm = edit(emStrongRDelimAstCore, 'gu')
.replace(/notPunctSpace/g, _notPunctuationOrSpaceGfmStrongEm)
.replace(/punctSpace/g, _punctuationOrSpaceGfmStrongEm)
.replace(/punct/g, _punctuationGfmStrongEm)
.getRegex();

// (6) Not allowed for _
const emStrongRDelimUnd = edit(
'^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)' // Skip orphan inside strong
Expand Down Expand Up @@ -375,7 +388,7 @@ const inlinePedantic: Record<InlineKeys, RegExp> = {

const inlineGfm: Record<InlineKeys, RegExp> = {
...inlineNormal,
escape: edit(escape).replace('])', '~|])').getRegex(),
emStrongRDelimAst: emStrongRDelimAstGfm,
url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, 'i')
.replace('email', /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/)
.getRegex(),
Expand Down
15 changes: 15 additions & 0 deletions test/specs/new/strikethrough_in_em_strong.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<p><em><del>a</del></em>b</p>

<p><em><del>a</del></em>b</p>

<p><strong><del>a</del></strong>b</p>

<p><strong><del>a</del></strong>b</p>

<p>_<del>a</del>_b</p>

<p>_<del>a</del>_b</p>

<p>__<del>a</del>__b</p>

<p>__<del>a</del>__b</p>
15 changes: 15 additions & 0 deletions test/specs/new/strikethrough_in_em_strong.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
*~a~*b

*~~a~~*b

**~a~**b

**~~a~~**b

_~a~_b

_~~a~~_b

__~a~__b

__~~a~~__b

0 comments on commit 8a01658

Please sign in to comment.