Marked.js自定义列表扩展误识别行内内容为列表的问题求助
Marked.js自定义列表扩展误识别行内内容为列表的问题求助
大家好,我最近在给Marked.js做一个自定义列表扩展,想让它支持字母、罗马数字这些不同样式的有序列表,就像HTML里的<ol type>那样。目前大部分情况都正常,但遇到一个奇怪的问题,想请教一下大家。
我用Marked.js解析Markdown,原生Markdown不支持字母、罗马数字这类有序列表样式,所以我写了下面这个自定义扩展代码:
const customList = { name: "customList", level: "block", start(src) { return src.match(/(?:^|\n)(\s*)(-|\+|\*|\d+\.|[A-Za-z]+\.|[iIvVxX]+\.)(\s+)/)?.index; }, tokenizer(src, tokens) { const rule = /^([^\S\r\n]*)(-|\+|\*|\d+\.|[A-Za-z]+\.|[iIvVxX]+\.)(\s+)(.*)/; const textRule = /^([^\S\r\n]*)(.*)/; const match = rule.exec(src); let style; if (match) { if (/-/.test(match[2])) style = "-"; else if (/\+/.test(match[2])) style = "+"; else if (/\*/.test(match[2])) style = "*"; else if (/\d+\./.test(match[2])) style = "1"; else if (/[IVX]+\./.test(match[2])) style = "I"; else if (/[ivx]+\./.test(match[2])) style = "i"; else if (/[A-Z]+\./.test(match[2])) style = "A"; else if (/[a-z]+\./.test(match[2])) style = "a"; const items = []; let remainingSrc = src; let prevIndent = match[1].length; let itemText = "", raw = ""; while (remainingSrc) { const itemMatch = rule.exec(remainingSrc); const textMatch = textRule.exec(remainingSrc); if (itemMatch && itemMatch[1].length === prevIndent) { let itemStyle; if (/-/.test(itemMatch[2])) itemStyle = "-"; else if (/\+/.test(itemMatch[2])) itemStyle = "+"; else if (/\*/.test(itemMatch[2])) itemStyle = "*"; else if (/\d+\./.test(itemMatch[2])) itemStyle = "1"; else if (/[IVX]+\./.test(itemMatch[2])) itemStyle = "I"; else if (/[ivx]+\./.test(itemMatch[2])) itemStyle = "i"; else if (/[A-Z]+\./.test(itemMatch[2])) itemStyle = "A"; else if (/[a-z]+\./.test(itemMatch[2])) itemStyle = "a"; else break; if (itemStyle !== style) break; if (itemText) { const itemTokens = []; this.lexer.inlineTokens(itemText, itemTokens); items.push({ type: "customListItem", raw: raw, tokens: itemTokens }); } itemText = itemMatch[4].trim(); raw = itemMatch[0]; remainingSrc = remainingSrc.slice(itemMatch[0].length + 1); } else if (textMatch && textMatch[1].length === prevIndent) { itemText += "\n" + textMatch[2]; raw += "\n" + textMatch[0]; remainingSrc = remainingSrc.slice(textMatch[0].length + 1); } else break; } if (itemText) { const itemTokens = []; this.lexer.inlineTokens(itemText, itemTokens); items.push({ type: "customListItem", raw: raw, tokens: itemTokens }); } const token = { type: "customList", raw: src.slice(0, src.length - remainingSrc.length), style: style, items: items }; return token; } }, renderer(token) { const listItems = token.items.map(item => `<li>${this.parser.parseInline(item.tokens)}</li>` ).join('\n'); if (token.style === "-" || token.style === "+" || token.style === "*") return `<ul>\n${listItems}\n</ul>\n`; else if (token.style === "1" || token.style === "I" || token.style === "i" || token.style === "A" || token.style === "a") return `<ol type="${token.style}">\n${listItems}\n</ol>\n`; }, childTokens: ["items"] }; marked.use({ extensions: [customList] });
目前大部分场景下它都能正常工作,比如:
- 例子1:执行
marked.parse("1. first\n2. second\n3. third"),输出正确的有序列表:
- first
- second
- third
- 例子2:执行
marked.parse("A. first\nB. second\n* first\n* second"),能正确区分字母有序列表和无序列表:
- first
- second
- first
- second
但是当我执行marked.parse("1 + 1")的时候,输出却变成了:
1
- 1
这明显不符合预期,我本来希望只有出现在行首(周围是空白字符)的列表标记才会被识别成列表,而不是行中间的+符号。
我试着在tokenizer函数里加了console.log(src)来排查,发现处理1 + 1的时候,居然输出了两次内容:1 + 1和+ 1,这让我完全摸不着头脑,不知道为什么会出现这种情况。
我是JavaScript新手,代码可能写得有点粗糙,有没有大佬能帮我看看问题出在哪?如果需要更多信息的话,我随时补充,谢谢大家!
内容来源于stack exchange
相关产品推荐
相关产品推荐

