From 42b5239d55475ae289c5095e327b454c6716e42b Mon Sep 17 00:00:00 2001 From: dousha Date: Tue, 7 Nov 2023 23:34:09 +0800 Subject: [PATCH 1/3] add math block for markdown import --- src/services/import/markdown.js | 2 + src/services/import/tex.js | 95 +++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 src/services/import/tex.js diff --git a/src/services/import/markdown.js b/src/services/import/markdown.js index e350cd065..f9cac8eab 100644 --- a/src/services/import/markdown.js +++ b/src/services/import/markdown.js @@ -1,10 +1,12 @@ "use strict"; const marked = require("marked"); +const texPlugin = require("./tex").texPlugin; const htmlSanitizer = require("../html_sanitizer"); const importUtils = require("./utils"); function renderToHtml(content, title) { + marked.use(texPlugin()); const html = marked.parse(content, { mangle: false, headerIds: false diff --git a/src/services/import/tex.js b/src/services/import/tex.js new file mode 100644 index 000000000..d763b2106 --- /dev/null +++ b/src/services/import/tex.js @@ -0,0 +1,95 @@ +const inlineRule = /^(\${1,2})(?!\$)((?:\\.|[^\\\n])*?(?:\\.|[^\\\n$]))\1(?=[\s?!.,:?!。,:]|$)/; +const blockRule = /^(\${1,2})\n((?:\\[^]|[^\\])+?)\n\1(?:\n|$)/; + +function texPlugin(options = {}) { + return { + extensions: [ + inlineKatex(options, createRenderer(options, false)), + blockKatex(options, createRenderer(options, true)) + ] + }; +} + +function createRenderer(options, newlineAfter) { + return (token) => { + let result = token.text; + if (token.displayMode) { + // full block mode + result = `\\[ ${result} \\]`; + } else { + // inline block mode + result = `\\( ${result} \\)`; + } + + if (newlineAfter) { + result += '\n'; + } + + return result; + }; +} + +function inlineKatex(options, renderer) { + return { + name: 'inlineKatex', + level: 'inline', + start(src) { + let index; + let indexSrc = src; + + while (indexSrc) { + index = indexSrc.indexOf('$'); + if (index === -1) { + return; + } + + if (index === 0 || indexSrc.charAt(index - 1) === ' ') { + const possibleKatex = indexSrc.substring(index); + + if (possibleKatex.match(inlineRule)) { + return index; + } + } + + indexSrc = indexSrc.substring(index + 1).replace(/^\$+/, ''); + } + }, + tokenizer(src, tokens) { + const match = src.match(inlineRule); + if (match) { + return { + type: 'inlineKatex', + raw: match[0], + text: match[2].trim(), + displayMode: match[1].length === 2 + }; + } + }, + renderer + }; +} + +function blockKatex(options, renderer) { + return { + name: 'blockKatex', + level: 'block', + tokenizer(src, tokens) { + const match = src.match(blockRule); + if (match) { + return { + type: 'blockKatex', + raw: match[0], + text: match[2].trim(), + displayMode: match[1].length === 2 + }; + } + }, + renderer + }; +} + + +module.exports = { + texPlugin +}; + From 07537a14ae4be0ac229579f9a4a4ae5e1339e345 Mon Sep 17 00:00:00 2001 From: dousha Date: Tue, 7 Nov 2023 23:34:39 +0800 Subject: [PATCH 2/3] remove unused parameters --- src/services/import/tex.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/import/tex.js b/src/services/import/tex.js index d763b2106..913bda276 100644 --- a/src/services/import/tex.js +++ b/src/services/import/tex.js @@ -54,7 +54,7 @@ function inlineKatex(options, renderer) { indexSrc = indexSrc.substring(index + 1).replace(/^\$+/, ''); } }, - tokenizer(src, tokens) { + tokenizer(src) { const match = src.match(inlineRule); if (match) { return { @@ -73,7 +73,7 @@ function blockKatex(options, renderer) { return { name: 'blockKatex', level: 'block', - tokenizer(src, tokens) { + tokenizer(src) { const match = src.match(blockRule); if (match) { return { From fc47e22af7e7b623975f73207af861f0f16917b4 Mon Sep 17 00:00:00 2001 From: dousha Date: Wed, 8 Nov 2023 00:02:45 +0800 Subject: [PATCH 3/3] add support for \(\) and \[\] syntax --- src/services/import/tex.js | 67 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/src/services/import/tex.js b/src/services/import/tex.js index 913bda276..0e1bc7e7a 100644 --- a/src/services/import/tex.js +++ b/src/services/import/tex.js @@ -1,11 +1,15 @@ const inlineRule = /^(\${1,2})(?!\$)((?:\\.|[^\\\n])*?(?:\\.|[^\\\n$]))\1(?=[\s?!.,:?!。,:]|$)/; -const blockRule = /^(\${1,2})\n((?:\\[^]|[^\\])+?)\n\1(?:\n|$)/; +const alternativeInlineRule = /^\\\((?!\$)((?:\\.|[^\\\n])*?(?:\\.|[^\\\n$]))\\\)(?=[\s?!.,:?!。,:]|$)/; +const blockRule = /^(\${1,2})[\s\n]((?:\\[^]|[^\\])+?)[\s\n]\1(?:\n|$)/; +const alternativeBlockRule = /^\\\[(\s*)((?:\\[^]|[^\\])+?)(\s*)\\](?:\n|$)/; function texPlugin(options = {}) { return { extensions: [ inlineKatex(options, createRenderer(options, false)), - blockKatex(options, createRenderer(options, true)) + altInlineKatex(options, createRenderer(options, false)), + blockKatex(options, createRenderer(options, true)), + altBlockKatex(options, createRenderer(options, true)) ] }; } @@ -69,6 +73,46 @@ function inlineKatex(options, renderer) { }; } +function altInlineKatex(options, renderer) { + return { + name: 'altInlineKatex', + level: 'inline', + start(src) { + let index; + let indexSrc = src; + + while (indexSrc) { + index = indexSrc.indexOf('\\('); + if (index === -1) { + return; + } + + if (index === 0 || indexSrc.charAt(index - 1) === ' ') { + const possibleKatex = indexSrc.substring(index + 1); + + if (possibleKatex.match(alternativeInlineRule)) { + return index; + } + } + + indexSrc = indexSrc.substring(index + 2).replace(/^\\[()]/, ''); + } + }, + tokenizer(src) { + const match = src.match(alternativeInlineRule); + if (match) { + return { + type: 'inlineKatex', + raw: match[0], + text: match[1].trim(), + displayMode: false + }; + } + }, + renderer + }; +} + function blockKatex(options, renderer) { return { name: 'blockKatex', @@ -88,8 +132,25 @@ function blockKatex(options, renderer) { }; } +function altBlockKatex(options, renderer) { + return { + name: 'altBlockKatex', + level: 'block', + tokenizer(src) { + const match = src.match(alternativeBlockRule); + if (match) { + return { + type: 'blockKatex', + raw: match[0], + text: match[2].trim(), + displayMode: true + }; + } + }, + renderer + }; +} module.exports = { texPlugin }; -