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>tags/v1.21.11
@@ -503,9 +503,17 @@ func TestMathBlock(t *testing.T) { | |||
`\(a\) \(b\)`, | |||
`<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$`, | |||
`<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`, | |||
@@ -513,7 +521,15 @@ func TestMathBlock(t *testing.T) { | |||
}, | |||
{ | |||
`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$$", |
@@ -41,9 +41,12 @@ func (parser *inlineParser) Trigger() []byte { | |||
return parser.start[0:1] | |||
} | |||
func isPunctuation(b byte) bool { | |||
return b == '.' || b == '!' || b == '?' || b == ',' || b == ';' || b == ':' | |||
} | |||
func isAlphanumeric(b byte) bool { | |||
// Github only cares about 0-9A-Za-z | |||
return (b >= '0' && b <= '9') || (b >= 'A' && b <= 'Z') || (b >= 'a' && b <= 'z') | |||
return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9') | |||
} | |||
// 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() | |||
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 | |||
return nil | |||
} | |||
@@ -75,14 +78,19 @@ func (parser *inlineParser) Parse(parent ast.Node, block text.Reader, pc parser. | |||
ender += pos | |||
// 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) | |||
if len(line) <= pos { | |||
break | |||
} | |||
if !isAlphanumeric(line[pos]) { | |||
suceedingCharacter := line[pos] | |||
if !isPunctuation(suceedingCharacter) && !(suceedingCharacter == ' ') { | |||
return nil | |||
} | |||
if line[ender-1] != '\\' { | |||
break | |||
} | |||
// move the pointer onwards | |||
ender += len(parser.end) | |||
} |