From fd464f82dae0b427d80517ce7aa96dccb72b2f47 Mon Sep 17 00:00:00 2001 From: Christopher Breeden Date: Sun, 15 May 2016 13:57:01 -0500 Subject: [PATCH] Added proper math-mode escaping --- index.js | 45 ++++++++++++++++++++++----------------- test/fixtures/default.txt | 14 ++++++++++++ 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/index.js b/index.js index 64e6723..57e8eea 100644 --- a/index.js +++ b/index.js @@ -40,20 +40,33 @@ function isValidDelim(state, pos) { } function math_inline(state, silent) { - var start, match, token, res, - pos = state.pos; + var start, match, token, res, pos, esc_count; if (state.src[state.pos] !== "$") { return false; } - res = isValidDelim(state, pos); + res = isValidDelim(state, state.pos); if (!res.can_open) { if (!silent) { state.pending += "$"; } state.pos += 1; return true; } + // First check for and bypass all properly escaped delimieters + // This loop will assume that the first leading backtick can not + // be the first character in state.src, which is known since + // we have found an opening delimieter already. start = state.pos + 1; - match = state.src.indexOf("$", start); + match = start; + while ( (match = state.src.indexOf("$", match)) !== -1) { + // Found potential $, look for escapes, pos will point to + // first non escape when complete + pos = match - 1; + while (state.src[pos] === "\\") { pos -= 1; } + + // Even number of escapes, potential closing delimiter found + if ( ((match - pos) % 2) == 1 ) { break; } + match += 1; + } // No closing delimter found. Consume $ and continue. if (match === -1) { @@ -62,22 +75,6 @@ function math_inline(state, silent) { return true; } - res = isValidDelim(state, match); - - // We only will look at the very next delimeter while searching - // for closing delimeters. As a consequnce, we will never send - // KaTeX a $ inside of math mode, even if escaped. The other alternative - // would otherwise require escaping commonly used things such as - // \int, \sum, etc... Perhaps there is a way to find a better solution. - // Such as counting the number of \\\\\\\$ and if odd escape $ and remove - // and leading \ or otherwise leave as is. - - if (!res.can_close) { - if (!silent) { state.pending += "$"; } - state.pos = start; - return true; - } - // Check if we have empty content, ie: $$. Do not parse. if (match - start === 0) { if (!silent) { state.pending += "$$"; } @@ -85,6 +82,14 @@ function math_inline(state, silent) { return true; } + // Check for valid closing delimiter + res = isValidDelim(state, match); + if (!res.can_close) { + if (!silent) { state.pending += "$"; } + state.pos = start; + return true; + } + if (!silent) { token = state.push('math_inline', 'math', 0); token.markup = "$"; diff --git a/test/fixtures/default.txt b/test/fixtures/default.txt index 3d6acc3..bf9dc4e 100644 --- a/test/fixtures/default.txt +++ b/test/fixtures/default.txt @@ -207,3 +207,17 @@ It's well know that $$1 + 1 = 3$$ for sufficiently large 1. .

It's well know that $$1 + 1 = 3$$ for sufficiently large 1.

. + +Escaped delimiters in math mode +. +Money adds: $\$X + \$Y = \$Z$. +. +

Money adds: $X+$Y=$Z\$X + \$Y = \$Z.

+. + +Multiple escaped delimiters in math module +. +Weird-o: $\displaystyle{\begin{pmatrix} \$ & 1\\\$ \end{pmatrix}}$. +. +

Weird-o: ($1$)\displaystyle{\begin{pmatrix} \$ & 1\\\$ \end{pmatrix}}.

+.