Skip to content

Commit

Permalink
fix: replace lookbehind in math regex
Browse files Browse the repository at this point in the history
  • Loading branch information
jiawei686 authored and humyfred committed Mar 17, 2022
1 parent 9cfeb41 commit 4dc2a7e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 14 deletions.
22 changes: 16 additions & 6 deletions src/core/hooks/InlineMath.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import ParagraphBase from '@/core/ParagraphBase';
import { escapeFormulaPunctuations, LoadMathModule } from '@/utils/mathjax';
import { getHTML } from '@/utils/dom';
import { isBrowser } from '@/utils/env';
import { isLookbehindSupported } from '@/utils/regexp';
import { replaceLookbehind } from '@/utils/lookbehind-replace';

/**
* 行内公式的语法
* 虽然叫做行内公式,Cherry依然将其视为“段落级语法”,因为其具备排他性并且需要优先渲染
Expand All @@ -34,7 +37,7 @@ export default class InlineMath extends ParagraphBase {
this.engine = isBrowser() ? config.engine ?? 'MathJax' : 'node';
}

toHtml(wholeMatch, m1) {
toHtml(wholeMatch, leadingChar, m1) {
if (!m1) {
return wholeMatch;
}
Expand All @@ -47,18 +50,18 @@ export default class InlineMath extends ParagraphBase {
const html = this.katex.renderToString(m1, {
throwOnError: false,
});
const result = `<span class="Cherry-InlineMath" data-type="mathBlock" data-lines="${lines}">${html}</span>`;
const result = `${leadingChar}<span class="Cherry-InlineMath" data-type="mathBlock" data-lines="${lines}">${html}</span>`;
return this.pushCache(result, ParagraphBase.IN_PARAGRAPH_CACHE_KEY_PREFIX + sign);
}

if (this.MathJax?.tex2svg) {
// MathJax渲染
const svg = getHTML(this.MathJax.tex2svg(m1, { em: 12, ex: 6, display: false }), true);
const result = `<span class="Cherry-InlineMath" data-type="mathBlock" data-lines="${lines}">${svg}</span>`;
const result = `${leadingChar}<span class="Cherry-InlineMath" data-type="mathBlock" data-lines="${lines}">${svg}</span>`;
return this.pushCache(result, ParagraphBase.IN_PARAGRAPH_CACHE_KEY_PREFIX + sign);
}
// 既无MathJax又无katex时,原样输出
const result = `<span class="Cherry-InlineMath" data-type="mathBlock"
const result = `${leadingChar}<span class="Cherry-InlineMath" data-type="mathBlock"
data-lines="${lines}">$${escapeFormulaPunctuations(m1)}$</span>`;
return this.pushCache(result, ParagraphBase.IN_PARAGRAPH_CACHE_KEY_PREFIX + sign);
}
Expand All @@ -67,15 +70,22 @@ export default class InlineMath extends ParagraphBase {
if (!this.test(str)) {
return str;
}
return str.replace(this.RULE.reg, this.toHtml.bind(this));
if (isLookbehindSupported()) {
return str.replace(this.RULE.reg, this.toHtml.bind(this));
}
return replaceLookbehind(str, this.RULE.reg, this.toHtml.bind(this), true, 1);
}

makeHtml(str) {
return str;
}

rule() {
const ret = { begin: '(?<!\\\\)~D\\n?', end: '(?<!\\\\)~D', content: '(.*?)\\n?' };
const ret = {
begin: isLookbehindSupported() ? '((?<!\\\\))~D\\n?' : '(^|[^\\\\])~D\\n?',
content: '(.*?)\\n?',
end: '~D',
};
ret.reg = new RegExp(ret.begin + ret.content + ret.end, 'g');
return ret;
}
Expand Down
23 changes: 15 additions & 8 deletions src/core/hooks/MathBlock.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import ParagraphBase from '@/core/ParagraphBase';
import { escapeFormulaPunctuations, LoadMathModule } from '@/utils/mathjax';
import { getHTML } from '@/utils/dom';
import { isBrowser } from '@/utils/env';
import { isLookbehindSupported } from '@/utils/regexp';
import { replaceLookbehind } from '@/utils/lookbehind-replace';

export default class MathBlock extends ParagraphBase {
static HOOK_NAME = 'mathBlock';
Expand All @@ -35,7 +37,7 @@ export default class MathBlock extends ParagraphBase {
this.engine = isBrowser() ? config.engine ?? 'MathJax' : 'node';
}

toHtml(wholeMatch, lineSpace, content) {
toHtml(wholeMatch, lineSpace, leadingChar, content) {
LoadMathModule.bind(this)('engine');
// 去掉开头的空字符,去掉结尾的换行符
const wholeMatchWithoutSpace = wholeMatch.replace(/^[ \f\r\t\v]*/, '').replace(/\s*$/, '');
Expand All @@ -62,34 +64,39 @@ export default class MathBlock extends ParagraphBase {
});
const result = `<div data-sign="${sign}" class="Cherry-Math" data-type="mathBlock"
data-lines="${lines}">${html}</div>`;
return this.getCacheWithSpace(this.pushCache(result, sign, lines), wholeMatch);
return leadingChar + this.getCacheWithSpace(this.pushCache(result, sign, lines), wholeMatch);
}
if (this.MathJax?.tex2svg) {
// MathJax渲染
const svg = getHTML(this.MathJax.tex2svg(content), true);
const result = `<div data-sign="${sign}" class="Cherry-Math" data-type="mathBlock"
data-lines="${lines}">${svg}</div>`;
return this.getCacheWithSpace(this.pushCache(result, sign, lines), wholeMatch);
return leadingChar + this.getCacheWithSpace(this.pushCache(result, sign, lines), wholeMatch);
}

// 既无MathJax又无katex时,原样输出
const result = `<div data-sign="${sign}" class="Cherry-Math" data-type="mathBlock"
data-lines="${lines}">$$${escapeFormulaPunctuations(content)}$$</div>`;
return this.getCacheWithSpace(this.pushCache(result, sign, lines), wholeMatch);
return leadingChar + this.getCacheWithSpace(this.pushCache(result, sign, lines), wholeMatch);
}

beforeMakeHtml(str) {
let $str = str;
$str = $str.replace(this.RULE.reg, this.toHtml.bind(this));
return $str;
if (isLookbehindSupported()) {
return str.replace(this.RULE.reg, this.toHtml.bind(this));
}
return replaceLookbehind(str, this.RULE.reg, this.toHtml.bind(this), true, 1);
}

makeHtml(str) {
return str;
}

rule() {
const ret = { begin: '(\\s*)(?<!\\\\)~D~D\\s*', end: '\\s*(?<!\\\\)~D~D(?:\\s{0,1})', content: '([\\w\\W]*?)' };
const ret = {
begin: isLookbehindSupported() ? '(\\s*)((?<!\\\\))~D~D\\s*' : '(\\s*)(^|[^\\\\])~D~D\\s*',
content: '([\\w\\W]*?)',
end: '(\\s*)~D~D(?:\\s{0,1})',
};
ret.reg = new RegExp(ret.begin + ret.content + ret.end, 'g');
return ret;
}
Expand Down

0 comments on commit 4dc2a7e

Please sign in to comment.