forked from Gitlink/forgeplus-react
md files and xss
This commit is contained in:
parent
7b430d8257
commit
82b979894b
|
@ -97,6 +97,9 @@ body {
|
|||
.editormd-image-click-expand .editormd-image-dialog .image-link {
|
||||
display: none;
|
||||
}
|
||||
.editormd-fullscreen{
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
/* 解决鼠标框选时,左边第一列没高亮的问题 */
|
||||
.CodeMirror .CodeMirror-lines pre.CodeMirror-line,
|
||||
|
|
|
@ -23,6 +23,7 @@ function indentCodeCompensation(raw, text) {
|
|||
.join('\n');
|
||||
}
|
||||
|
||||
|
||||
//兼容之前的 ##标题式写法
|
||||
let toc = []
|
||||
let ctx = ["<ul>"]
|
||||
|
@ -48,15 +49,15 @@ function buildToc(coll, k, level, ctx) {
|
|||
});
|
||||
ctx.push("</ul>")
|
||||
}
|
||||
ctx.push("</li>")
|
||||
ctx.push("</li>");
|
||||
k = buildToc(coll, k, level, ctx)
|
||||
return k
|
||||
}
|
||||
|
||||
export function getTocContent() {
|
||||
buildToc(toc, 0, 0, ctx)
|
||||
ctx.push("</ul>")
|
||||
return ctx.join("")
|
||||
buildToc(toc, 0, 0, ctx);
|
||||
ctx.push("</ul>");
|
||||
return ctx.join("");
|
||||
}
|
||||
|
||||
const tokenizer = {
|
||||
|
@ -117,6 +118,7 @@ function replace_math_with_ids(text) {
|
|||
return rs
|
||||
}
|
||||
|
||||
|
||||
const original_listitem = renderer.listitem
|
||||
renderer.listitem = function (text, task, checked) {
|
||||
return original_listitem(replace_math_with_ids(text), task, checked)
|
||||
|
@ -155,9 +157,9 @@ renderer.heading = function (text, level, raw) {
|
|||
level: level,
|
||||
text: text
|
||||
})
|
||||
return '<h' + level + ' id="' + anchor + '">' + text + '</h' + level + '>'
|
||||
let id = anchor.replace(/[.,/#!$%^&*;:{}=\-_`~():,。¥;「」|?》《~·【】‘、!]/g,"");
|
||||
return '<h' + level + ' id="' + id + '" class="markdown_anchors"><a name="#'+id+'" class="anchors"><i class="iconfont icon-lianjieicon font-14"></i></a>' + text + '</h' + level + '>'
|
||||
}
|
||||
|
||||
marked.setOptions({
|
||||
silent: true,
|
||||
smartypants: true,
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
import marked from 'marked'
|
||||
import { escape } from 'marked/src/helpers'
|
||||
|
||||
function indentCodeCompensation(raw, text) {
|
||||
const matchIndentToCode = raw.match(/^(\s+)(?:```)/);
|
||||
if (matchIndentToCode === null) {
|
||||
return text;
|
||||
}
|
||||
const indentToCode = matchIndentToCode[1];
|
||||
return text
|
||||
.split('\n')
|
||||
.map(node => {
|
||||
const matchIndentInNode = node.match(/^\s+/);
|
||||
if (matchIndentInNode === null) {
|
||||
return node;
|
||||
}
|
||||
const [indentInNode] = matchIndentInNode;
|
||||
if (indentInNode.length >= indentToCode.length) {
|
||||
return node.slice(indentToCode.length);
|
||||
}
|
||||
return node;
|
||||
})
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
//兼容之前的 ##标题式写法
|
||||
let toc = []
|
||||
let ctx = ["<ul>"]
|
||||
const renderer = new marked.Renderer()
|
||||
const headingRegex = /^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/
|
||||
|
||||
export function cleanToc() {
|
||||
toc = []
|
||||
ctx = ["<ul>"]
|
||||
}
|
||||
|
||||
function buildToc(coll, k, level, ctx) {
|
||||
if (k >= coll.length || coll[k].level <= level) { return k }
|
||||
var node = coll[k]
|
||||
ctx.push("<li><a href='#" + node.anchor + "'>" + node.text + "</a>")
|
||||
k++
|
||||
var childCtx = []
|
||||
k = buildToc(coll, k, node.level, childCtx)
|
||||
if (childCtx.length > 0) {
|
||||
ctx.push("<ul>")
|
||||
childCtx.forEach(function (idm) {
|
||||
ctx.push(idm)
|
||||
});
|
||||
ctx.push("</ul>")
|
||||
}
|
||||
ctx.push("</li>")
|
||||
k = buildToc(coll, k, level, ctx)
|
||||
return k
|
||||
}
|
||||
|
||||
export function getTocContent() {
|
||||
buildToc(toc, 0, 0, ctx)
|
||||
ctx.push("</ul>")
|
||||
return ctx.join("")
|
||||
}
|
||||
|
||||
const tokenizer = {
|
||||
heading(src) {
|
||||
const cap = headingRegex.exec(src)
|
||||
if (cap) {
|
||||
return {
|
||||
type: 'heading',
|
||||
raw: cap[0],
|
||||
depth: cap[1].length,
|
||||
text: cap[2]
|
||||
}
|
||||
}
|
||||
},
|
||||
fences(src) {
|
||||
const cap = this.rules.block.fences.exec(src)
|
||||
if (cap) {
|
||||
const raw = cap[0]
|
||||
let text = indentCodeCompensation(raw, cap[3] || '')
|
||||
const lang = cap[2] ? cap[2].trim() : cap[2]
|
||||
if (['latex', 'katex', 'math'].indexOf(lang) >= 0) {
|
||||
const id = next_id()
|
||||
const expression = text
|
||||
text = id
|
||||
math_expressions[id] = { type: 'block', expression }
|
||||
}
|
||||
return {
|
||||
type: 'code',
|
||||
raw,
|
||||
lang,
|
||||
text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const latexRegex = /(?:\${2})([^\n`]+?)(?:\${2})/gi
|
||||
let katex_count = 0
|
||||
const next_id = () => `__special_katext_id_${katex_count++}__`
|
||||
let math_expressions = {}
|
||||
|
||||
export function getMathExpressions() {
|
||||
return math_expressions
|
||||
}
|
||||
|
||||
export function resetMathExpressions() {
|
||||
katex_count = 0
|
||||
math_expressions = {}
|
||||
}
|
||||
|
||||
function replace_math_with_ids(text) {
|
||||
let rs = text.replace(latexRegex, (_match, expression) => {
|
||||
const id = next_id()
|
||||
math_expressions[id] = { type: 'inline', expression }
|
||||
return id
|
||||
})
|
||||
|
||||
return rs
|
||||
}
|
||||
|
||||
const original_listitem = renderer.listitem
|
||||
renderer.listitem = function (text, task, checked) {
|
||||
return original_listitem(replace_math_with_ids(text), task, checked)
|
||||
}
|
||||
|
||||
const original_paragraph = renderer.paragraph
|
||||
renderer.paragraph = function (text) {
|
||||
return original_paragraph(replace_math_with_ids(text))
|
||||
}
|
||||
|
||||
const original_tablecell = renderer.tablecell
|
||||
renderer.tablecell = function (content, flags) {
|
||||
return original_tablecell(replace_math_with_ids(content), flags)
|
||||
}
|
||||
|
||||
renderer.code = function (code, infostring, escaped) {
|
||||
const lang = (infostring || '').match(/\S*/)[0];
|
||||
if (!lang) {
|
||||
return '<pre class="prettyprint linenums"><code>'
|
||||
+ (escaped ? code : escape(code, true))
|
||||
+ '</code></pre>';
|
||||
}
|
||||
|
||||
if (['latex', 'katex', 'math'].indexOf(lang) >= 0) {
|
||||
return `<p class='editormd-tex'>${code}</p>`
|
||||
} else {
|
||||
return `<pre class="prettyprint linenums"><code class="language-${infostring}">${escaped ? code : escape(code, true)}</code></pre>\n`
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
renderer.heading = function (text, level, raw) {
|
||||
let anchor = this.options.headerPrefix + raw.toLowerCase().replace(/[^\w\\u4e00-\\u9fa5]]+/g, '-');
|
||||
toc.push({
|
||||
anchor: anchor,
|
||||
level: level,
|
||||
text: text
|
||||
})
|
||||
return '<h' + level + ' id="' + anchor + '">' + text + '</h' + level + '>'
|
||||
}
|
||||
|
||||
marked.setOptions({
|
||||
silent: true,
|
||||
smartypants: true,
|
||||
gfm: true,
|
||||
pedantic: false
|
||||
})
|
||||
|
||||
marked.use({ tokenizer, renderer });
|
||||
|
||||
export default marked
|
Loading…
Reference in New Issue