Improve/fix latex math extension. To mitigate false positives: * We accept $ and $$ as a potential opener only if it's not preceded with alnum char. * Similarly closer cannot be followed with alnum char. * We now also match closer with last preceding pontential opener, not the first one. (And to avoid nesting, any previous openers are ignored.) * Also revert an unintended change in 3fc207affaba313cc1f4ef3b4e9e57df89b0e028 which allowed keeping nested resolved marks in it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
diff --git a/src/md4c.c b/src/md4c.c
index ca57f2d..b77df6c 100644
--- a/src/md4c.c
+++ b/src/md4c.c
@@ -3344,8 +3344,17 @@ md_collect_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int table_mode)
while(tmp < line_end && CH(tmp) == _T('$'))
tmp++;
- if (tmp - off <= 2)
- PUSH_MARK(ch, off, tmp, MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER);
+ if(tmp - off <= 2) {
+ unsigned flags = MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER;
+
+ if(off > line_beg && !ISUNICODEWHITESPACEBEFORE(off) && !ISUNICODEPUNCTBEFORE(off))
+ flags &= ~MD_MARK_POTENTIAL_OPENER;
+ if(tmp < line_end && !ISUNICODEWHITESPACE(tmp) && !ISUNICODEPUNCT(tmp))
+ flags &= ~MD_MARK_POTENTIAL_CLOSER;
+ if(flags != 0)
+ PUSH_MARK(ch, off, tmp, flags);
+ }
+
off = tmp;
continue;
}
@@ -3854,21 +3863,30 @@ md_analyze_tilde(MD_CTX* ctx, int mark_index)
static void
md_analyze_dollar(MD_CTX* ctx, int mark_index)
{
- if(DOLLAR_OPENERS.head >= 0) {
+ MD_MARK* mark = &ctx->marks[mark_index];
+
+ if((mark->flags & MD_MARK_POTENTIAL_CLOSER) && DOLLAR_OPENERS.tail >= 0) {
/* If the potential closer has a non-matching number of $, discard */
- MD_MARK* open = &ctx->marks[DOLLAR_OPENERS.tail];
- MD_MARK* close = &ctx->marks[mark_index];
+ MD_MARK* opener = &ctx->marks[DOLLAR_OPENERS.tail];
int opener_index = DOLLAR_OPENERS.tail;
+ MD_MARK* closer = mark;
+ int closer_index = mark_index;
- if (open->end - open->beg == close->end - close->beg) {
+ if(opener->end - opener->beg == closer->end - closer->beg) {
/* We are the matching closer */
- md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_CROSSING);
- md_resolve_range(ctx, &DOLLAR_OPENERS, opener_index, mark_index);
+ md_rollback(ctx, opener_index, closer_index, MD_ROLLBACK_ALL);
+ md_resolve_range(ctx, &DOLLAR_OPENERS, opener_index, closer_index);
+
+ /* Discard all pending openers: Latex math span do not allow
+ * nesting. */
+ DOLLAR_OPENERS.head = -1;
+ DOLLAR_OPENERS.tail = -1;
return;
}
}
- md_mark_chain_append(ctx, &DOLLAR_OPENERS, mark_index);
+ if(mark->flags & MD_MARK_POTENTIAL_OPENER)
+ md_mark_chain_append(ctx, &DOLLAR_OPENERS, mark_index);
}
static MD_MARK*
diff --git a/test/spec-latex-math.txt b/test/spec-latex-math.txt
index 1f44fea..d939bf9 100644
--- a/test/spec-latex-math.txt
+++ b/test/spec-latex-math.txt
@@ -15,6 +15,36 @@ $a+b=c$ Hello, world!
--flatex-math
````````````````````````````````
+However the LaTeX math spans cannot be nested:
+
+```````````````````````````````` example
+$$foo $bar$ baz$$
+.
+<p>$$foo <x-equation>bar</x-equation> baz$$</p>
+.
+--flatex-math
+````````````````````````````````
+
+The opening delimiter cannot be preceded with an alphanumerical character:
+
+```````````````````````````````` example
+x$a+b=c$
+.
+<p>x$a+b=c$</p>
+.
+--flatex-math
+````````````````````````````````
+
+Similarly the closing delimiter cannot be followed with an alphanumerical character:
+
+```````````````````````````````` example
+$a+b=c$x
+.
+<p>$a+b=c$x</p>
+.
+--flatex-math
+````````````````````````````````
+
If the double dollar sign is used, the math span is a display math span.
```````````````````````````````` example