Fixes #27605: inline math blocks can't be preceeded/followed by alphanumerical characters (#30175) (#30250)

Backport #30175 by @jmlt2002

- Inline math blocks couldn't be preceeded or succeeded by
alphanumerical characters due to changes introduced in PR #21171.
Removed the condition that caused this (precedingCharacter condition)
and added a new exit condition of the for-loop that checks if a specific
'$' was escaped using '\' so that the math expression can be rendered as
intended.
- Additionally this PR fixes another bug where math blocks of the type
'$xyz$abc$' where the dollar sign was not escaped by the user, generated
an error (shown in the screenshots below)
- Altered the tests to accomodate for the changes

Former behaviour (from try.gitea.io):

![image](https://github.com/go-gitea/gitea/assets/114936010/8f0cbb21-321d-451c-b871-c67a8e1e9235)

Fixed behaviour (from my local build):

![image](https://github.com/go-gitea/gitea/assets/114936010/5c22687c-6f11-4407-b5e7-c14b838bc20d)

(Edit) Source code for the README.md file:
```
$x$ -$x$ $x$-

a$xa$ $xa$a 1$xb$ $xb$1

$a a$b b$

a$b $a a$b b$

$a a\$b b$
```

Signed-off-by: João Tiago <joao.leal.tintas@tecnico.ulisboa.pt>
Co-authored-by: João Tiago <114936010+jmlt2002@users.noreply.github.com>
(cherry picked from commit 5123ed31914f704348c0660468a3707011f5a160)
This commit is contained in:
Giteabot 2024-04-03 14:06:39 +08:00 committed by Earl Warren
parent 4ed431531b
commit 0d3f446460
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
2 changed files with 31 additions and 7 deletions

View file

@ -509,9 +509,17 @@ func TestMathBlock(t *testing.T) {
`\(a\) \(b\)`, `\(a\) \(b\)`,
`<p><code class="language-math is-loading">a</code> <code class="language-math is-loading">b</code></p>` + nl, `<p><code class="language-math is-loading">a</code> <code class="language-math is-loading">b</code></p>` + nl,
}, },
{
`$a$.`,
`<p><code class="language-math is-loading">a</code>.</p>` + nl,
},
{
`.$a$`,
`<p>.$a$</p>` + nl,
},
{ {
`$a a$b b$`, `$a a$b b$`,
`<p><code class="language-math is-loading">a a$b b</code></p>` + nl, `<p>$a a$b b$</p>` + nl,
}, },
{ {
`a a$b b`, `a a$b b`,
@ -519,7 +527,15 @@ func TestMathBlock(t *testing.T) {
}, },
{ {
`a$b $a a$b b$`, `a$b $a a$b b$`,
`<p>a$b <code class="language-math is-loading">a a$b b</code></p>` + nl, `<p>a$b $a a$b b$</p>` + nl,
},
{
"a$x$",
`<p>a$x$</p>` + nl,
},
{
"$x$a",
`<p>$x$a</p>` + nl,
}, },
{ {
"$$a$$", "$$a$$",

View file

@ -41,9 +41,12 @@ func (parser *inlineParser) Trigger() []byte {
return parser.start[0:1] return parser.start[0:1]
} }
func isPunctuation(b byte) bool {
return b == '.' || b == '!' || b == '?' || b == ',' || b == ';' || b == ':'
}
func isAlphanumeric(b byte) bool { func isAlphanumeric(b byte) bool {
// Github only cares about 0-9A-Za-z return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9')
return (b >= '0' && b <= '9') || (b >= 'A' && b <= 'Z') || (b >= 'a' && b <= 'z')
} }
// Parse parses the current line and returns a result of parsing. // Parse parses the current line and returns a result of parsing.
@ -56,7 +59,7 @@ func (parser *inlineParser) Parse(parent ast.Node, block text.Reader, pc parser.
} }
precedingCharacter := block.PrecendingCharacter() precedingCharacter := block.PrecendingCharacter()
if precedingCharacter < 256 && isAlphanumeric(byte(precedingCharacter)) { if precedingCharacter < 256 && (isAlphanumeric(byte(precedingCharacter)) || isPunctuation(byte(precedingCharacter))) {
// need to exclude things like `a$` from being considered a start // need to exclude things like `a$` from being considered a start
return nil return nil
} }
@ -75,14 +78,19 @@ func (parser *inlineParser) Parse(parent ast.Node, block text.Reader, pc parser.
ender += pos ender += pos
// Now we want to check the character at the end of our parser section // Now we want to check the character at the end of our parser section
// that is ender + len(parser.end) // that is ender + len(parser.end) and check if char before ender is '\'
pos = ender + len(parser.end) pos = ender + len(parser.end)
if len(line) <= pos { if len(line) <= pos {
break break
} }
if !isAlphanumeric(line[pos]) { suceedingCharacter := line[pos]
if !isPunctuation(suceedingCharacter) && !(suceedingCharacter == ' ') {
return nil
}
if line[ender-1] != '\\' {
break break
} }
// move the pointer onwards // move the pointer onwards
ender += len(parser.end) ender += len(parser.end)
} }