mirror of
https://github.com/purocean/yn.git
synced 2026-09-24 15:46:02 +08:00
feat: 升级 Katex 公示支持中文
This commit is contained in:
+1
-1
@@ -75,10 +75,10 @@
|
||||
"eslint-plugin-vue": "^7.11.1",
|
||||
"github-markdown-css": "^4.0.0",
|
||||
"highlight.js": "^11.0.1",
|
||||
"katex": "^0.13.11",
|
||||
"lodash-es": "^4.17.21",
|
||||
"markdown-it": "^12.0.6",
|
||||
"markdown-it-attrs": "^4.0.0",
|
||||
"markdown-it-katex": "^2.0.3",
|
||||
"markdown-it-multimd-table": "^4.1.0",
|
||||
"mermaid": "^8.10.2",
|
||||
"monaco-editor": "^0.25.2",
|
||||
|
||||
@@ -44,7 +44,6 @@ import { debounce } from 'lodash-es'
|
||||
import { useStore } from 'vuex'
|
||||
import { computed, defineComponent, nextTick, onBeforeUnmount, onMounted, ref, toRefs, watch } from 'vue'
|
||||
import Markdown from 'markdown-it'
|
||||
import katex from 'markdown-it-katex'
|
||||
import MarkdownItAttrs from 'markdown-it-attrs'
|
||||
import MultimdTable from 'markdown-it-multimd-table'
|
||||
|
||||
@@ -59,7 +58,6 @@ import 'highlight.js/styles/atom-one-dark.css'
|
||||
import 'katex/dist/katex.min.css'
|
||||
|
||||
const markdown = Markdown({ linkify: true, breaks: true, html: true, })
|
||||
.use(katex)
|
||||
.use(MarkdownItAttrs)
|
||||
.use(MultimdTable, { multiline: true })
|
||||
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
/* eslint-disable prefer-const */
|
||||
// https://raw.githubusercontent.com/waylonflinn/markdown-it-katex/master/index.js
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
/* Process inline math */
|
||||
/*
|
||||
Like markdown-it-simplemath, this is a stripped down, simplified version of:
|
||||
https://github.com/runarberg/markdown-it-math
|
||||
|
||||
It differs in that it takes (a subset of) LaTeX as input and relies on KaTeX
|
||||
for rendering output.
|
||||
*/
|
||||
|
||||
import katex from 'katex'
|
||||
import { Plugin } from '@fe/useful/plugin'
|
||||
|
||||
// Test if potential opening or closing delimieter
|
||||
// Assumes that there is a "$" at state.src[pos]
|
||||
function isValidDelim (state: any, pos: number) {
|
||||
let prevChar; let nextChar
|
||||
const max = state.posMax
|
||||
let can_open = true
|
||||
let can_close = true
|
||||
|
||||
prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1
|
||||
nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1
|
||||
|
||||
// Check non-whitespace conditions for opening and closing, and
|
||||
// check that closing delimeter isn't followed by a number
|
||||
if (prevChar === 0x20/* " " */ || prevChar === 0x09/* \t */ ||
|
||||
(nextChar >= 0x30/* "0" */ && nextChar <= 0x39/* "9" */)) {
|
||||
can_close = false
|
||||
}
|
||||
if (nextChar === 0x20/* " " */ || nextChar === 0x09/* \t */) {
|
||||
can_open = false
|
||||
}
|
||||
|
||||
return {
|
||||
can_open: can_open,
|
||||
can_close: can_close
|
||||
}
|
||||
}
|
||||
|
||||
function math_inline (state: any, silent: boolean) {
|
||||
let start, match, token, res, pos, esc_count
|
||||
|
||||
if (state.src[state.pos] !== '$') { return false }
|
||||
|
||||
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 = 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) {
|
||||
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 += '$$' }
|
||||
state.pos = start + 1
|
||||
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 = '$'
|
||||
token.content = state.src.slice(start, match)
|
||||
}
|
||||
|
||||
state.pos = match + 1
|
||||
return true
|
||||
}
|
||||
|
||||
function math_block (state: any, start: number, end: number, silent: boolean) {
|
||||
let firstLine; let lastLine; let next; let lastPos; let found = false; let token
|
||||
let pos = state.bMarks[start] + state.tShift[start]
|
||||
let max = state.eMarks[start]
|
||||
|
||||
if (pos + 2 > max) { return false }
|
||||
if (state.src.slice(pos, pos + 2) !== '$$') { return false }
|
||||
|
||||
pos += 2
|
||||
firstLine = state.src.slice(pos, max)
|
||||
|
||||
if (silent) { return true }
|
||||
if (firstLine.trim().slice(-2) === '$$') {
|
||||
// Single line expression
|
||||
firstLine = firstLine.trim().slice(0, -2)
|
||||
found = true
|
||||
}
|
||||
|
||||
for (next = start; !found;) {
|
||||
next++
|
||||
|
||||
if (next >= end) { break }
|
||||
|
||||
pos = state.bMarks[next] + state.tShift[next]
|
||||
max = state.eMarks[next]
|
||||
|
||||
if (pos < max && state.tShift[next] < state.blkIndent) {
|
||||
// non-empty line with negative indent should stop the list:
|
||||
break
|
||||
}
|
||||
|
||||
if (state.src.slice(pos, max).trim().slice(-2) === '$$') {
|
||||
lastPos = state.src.slice(0, max).lastIndexOf('$$')
|
||||
lastLine = state.src.slice(pos, lastPos)
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
state.line = next + 1
|
||||
|
||||
token = state.push('math_block', 'math', 0)
|
||||
token.block = true
|
||||
token.content = (firstLine && firstLine.trim() ? firstLine + '\n' : '') +
|
||||
state.getLines(start + 1, next, state.tShift[start], true) +
|
||||
(lastLine && lastLine.trim() ? lastLine : '')
|
||||
token.map = [start, state.line]
|
||||
token.markup = '$$'
|
||||
return true
|
||||
}
|
||||
|
||||
function math_plugin (md: any, options: any) {
|
||||
// Default options
|
||||
|
||||
options = options || {}
|
||||
|
||||
// set KaTeX as the renderer for markdown-it-simplemath
|
||||
const katexInline = function (latex: any) {
|
||||
options.displayMode = false
|
||||
try {
|
||||
return katex.renderToString(latex, options)
|
||||
} catch (error) {
|
||||
if (options.throwOnError) { console.log(error) }
|
||||
return latex
|
||||
}
|
||||
}
|
||||
|
||||
const inlineRenderer = function (tokens: any, idx: any) {
|
||||
return katexInline(tokens[idx].content)
|
||||
}
|
||||
|
||||
const katexBlock = function (latex: any) {
|
||||
options.displayMode = true
|
||||
try {
|
||||
return '<p>' + katex.renderToString(latex, options) + '</p>'
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
if (options.throwOnError) { console.log(error) }
|
||||
return latex
|
||||
}
|
||||
}
|
||||
|
||||
const blockRenderer = function (tokens: any, idx: any) {
|
||||
return katexBlock(tokens[idx].content) + '\n'
|
||||
}
|
||||
|
||||
md.inline.ruler.after('escape', 'math_inline', math_inline)
|
||||
md.block.ruler.after('blockquote', 'math_block', math_block, {
|
||||
alt: ['paragraph', 'reference', 'blockquote', 'list']
|
||||
})
|
||||
md.renderer.rules.math_inline = inlineRenderer
|
||||
md.renderer.rules.math_block = blockRenderer
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'markdown-toc',
|
||||
register: ctx => {
|
||||
ctx.markdown.registerPlugin(math_plugin)
|
||||
}
|
||||
} as Plugin
|
||||
Vendored
+1
@@ -10,3 +10,4 @@ declare module 'markdown-it-multimd-table'
|
||||
declare module 'markdown-it-katex'
|
||||
declare module '@json-editor/json-editor'
|
||||
declare module 'mermaid/dist/mermaid.js'
|
||||
declare module 'katex'
|
||||
|
||||
@@ -13,6 +13,7 @@ import markdownLink from '@fe/plugins/markdown-link'
|
||||
import markdownTaskList from '@fe/plugins/markdown-task-list'
|
||||
import markdownFootnote from '@/renderer/plugins/markdown-footnote'
|
||||
import transformImgOutLink from '@fe/plugins/transform-img-out-link'
|
||||
import markdownItKatex from '@/renderer/plugins/markdown-it-katex'
|
||||
import copyText from '@fe/plugins/copy-text'
|
||||
import tableCellEdit from '@fe/plugins/table-cell-edit'
|
||||
import switchTodo from '@fe/plugins/switch-todo'
|
||||
@@ -39,6 +40,7 @@ export default [
|
||||
markdownLink,
|
||||
markdownTaskList,
|
||||
markdownFootnote,
|
||||
markdownItKatex,
|
||||
transformImgOutLink,
|
||||
copyText,
|
||||
tableCellEdit,
|
||||
|
||||
@@ -1456,6 +1456,11 @@ commander@^5.0.0:
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
|
||||
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
|
||||
|
||||
commander@^6.0.0:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
|
||||
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
|
||||
|
||||
component-bind@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
|
||||
@@ -3731,12 +3736,12 @@ jsprim@^1.2.2:
|
||||
json-schema "0.2.3"
|
||||
verror "1.10.0"
|
||||
|
||||
katex@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/katex/-/katex-0.6.0.tgz#12418e09121c05c92041b6b3b9fb6bab213cb6f3"
|
||||
integrity sha1-EkGOCRIcBckgQbazuftrqyE8tvM=
|
||||
katex@^0.13.11:
|
||||
version "0.13.11"
|
||||
resolved "https://registry.yarnpkg.com/katex/-/katex-0.13.11.tgz#66138ebf173f25ef130cd3a3ea3ea1d12a3f1362"
|
||||
integrity sha512-yJBHVIgwlAaapzlbvTpVF/ZOs8UkTj/sd46Fl8+qAf2/UiituPYVeapVD8ADZtqyRg/qNWUKt7gJoyYVWLrcXw==
|
||||
dependencies:
|
||||
match-at "^0.1.0"
|
||||
commander "^6.0.0"
|
||||
|
||||
keygrip@~1.1.0:
|
||||
version "1.1.0"
|
||||
@@ -3967,13 +3972,6 @@ markdown-it-attrs@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/markdown-it-attrs/-/markdown-it-attrs-4.0.0.tgz#eadae3ea0c7d17c5e83b98a4ec95a47f4e4960f5"
|
||||
integrity sha512-uLjtdCmhhmL3BuZsReYkFxk74qKjj5ahe34teBpOCJ4hYZZl7/ftLyXWLowngC2moRkbLEvKwN/7TMwbhbHE/A==
|
||||
|
||||
markdown-it-katex@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it-katex/-/markdown-it-katex-2.0.3.tgz#d7b86a1aea0b9d6496fab4e7919a18fdef589c39"
|
||||
integrity sha1-17hqGuoLnWSW+rTnkZoY/e9YnDk=
|
||||
dependencies:
|
||||
katex "^0.6.0"
|
||||
|
||||
markdown-it-multimd-table@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it-multimd-table/-/markdown-it-multimd-table-4.1.0.tgz#5c23eba9ceda580dc5c7301927a01610e0ee37b9"
|
||||
@@ -4003,11 +4001,6 @@ markdown-it@^12.0.6:
|
||||
mdurl "^1.0.1"
|
||||
uc.micro "^1.0.5"
|
||||
|
||||
match-at@^0.1.0:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/match-at/-/match-at-0.1.1.tgz#25d040d291777704d5e6556bbb79230ec2de0540"
|
||||
integrity sha512-h4Yd392z9mST+dzc+yjuybOGFNOZjmXIPKWjxBd1Bb23r4SmDOsk2NYCU2BMUBGbSpZqwVsZYNq26QS3xfaT3Q==
|
||||
|
||||
matcher@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca"
|
||||
|
||||
Reference in New Issue
Block a user