From 1d691ccac7166291c78be4f430f6fa33ecab5c10 Mon Sep 17 00:00:00 2001 From: yutent Date: Fri, 21 Apr 2023 19:15:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96markd=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/markd/core.js | 107 ++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 57 deletions(-) diff --git a/src/markd/core.js b/src/markd/core.js index d2cf047..add3ef0 100644 --- a/src/markd/core.js +++ b/src/markd/core.js @@ -15,6 +15,8 @@ const CODEBLOCK_RE = /```(.*?)([\w\W]*?)```/g const BLOCK_RE = /<([\w\-]+)([^>]*?)>([\w\W]*?)<\/\1>/g const IS_DOM_RE = /^<([\w\-]+)[^>]*?>.*?<\/\1>$/ const STYLE_RE = /]*?>([\w\W]*?)<\/style>/g +const SINGLE_LINE_HTML_RE = /^\s*?<([\w\-]+)[^>]*?>.*?<\/\1>\s*?$/ +const MULTI_LINE_HTML_RE = /^\s*?<\/?[^>]*?>/ const INLINE = { code: /`([^`]*?[^`\\\s])`/g, @@ -27,11 +29,6 @@ const INLINE = { qlist: /((
)*?)([\+\-\*]|\d+\.) (.*)/ // 引用中的列表 } -const ATTR_BR_SYMBOL = '⨨☇' -const NODE_BR_SYMBOL = '⨨⤶' -const ATTR_BR_EXP = new RegExp(ATTR_BR_SYMBOL, 'g') -const NODE_BR_EXP = new RegExp(NODE_BR_SYMBOL, 'g') - const Helper = { // 是否分割线 isHr(str) { @@ -127,7 +124,7 @@ const Decoder = { }, // 分割线 hr(name = '') { - return `
` + return `\n\n
\n\n` }, // 标题 head(str) { @@ -140,16 +137,13 @@ const Decoder = { if (level === 1) { return `

${m2}

` } else { - return `${m2}` + return `\n\n${m2}\n` } }) } return false }, - // 引用模块 - blockquote(str) { - // - }, + // 任务 task(str) { var todoChecked = Helper.isTodo(str) @@ -158,7 +152,7 @@ const Decoder = { var stat = todoChecked === 1 ? 'checked' : '' var txt = todoChecked === 1 ? `${word}` : word - return `
${txt}
` + return `\n
${txt}
\n` } return false } @@ -171,23 +165,10 @@ function fixed(str) { .replace(/\t/g, ' ') .replace(/\u00a0/g, ' ') .replace(/\u2424/g, '\n') - .replace(TAG_RE, (m, name, attr) => { - // 标签内的换行, 转为一组特殊字符, 方便后面还原 - return `<${name + attr.replace(/\n/g, ATTR_BR_SYMBOL)}>` - }) - .replace(BLOCK_RE, (m, tag, attr, txt) => { - return `<${tag + attr}>${txt.replace(/\n/g, NODE_BR_SYMBOL)}` - }) - .replace(CODEBLOCK_RE, (m, lang, txt) => { - // 还原换行 - let rollback = txt.replace(NODE_BR_EXP, '\n').replace(ATTR_BR_EXP, '\n') - return '```' + lang + rollback + '```' - }) - .replace(BLOCK_RE, (m, tag, attr, txt) => { - return `<${tag + attr.replace(ATTR_BR_EXP, ' ')}>${txt - .replace(NODE_BR_EXP, '\n') - .replace(ATTR_BR_EXP, ' ')}` - }) +} + +function trimBr(str) { + return str.endsWith('
') ? str.slice(0, -4) : str } class Tool { @@ -213,10 +194,10 @@ class Tool { emptyLineLength = 0 if (tmp.startsWith('```')) { if (isCodeBlock) { - list.push('') + list.push('\n\n\n') } else { list.push( - tmp.replace(/^```([\w\#\-]*?)$/, ``) + tmp.replace(/^```([\w\#\-]*?)$/, `\n<wc-code lang="$1"><xmp>`) ) } isCodeBlock = !isCodeBlock @@ -233,9 +214,9 @@ class Tool { thead.shift() thead.pop() list.push( - `<table><thead><tr>${thead + `\n<table>\n<thead><tr>${thead .map(_ => `<th>${_}</th>`) - .join('')}</tr></thead><tbody>` + .join('')}</tr></thead>\n<tbody>` ) isTable = true continue @@ -270,7 +251,7 @@ class Tool { } else { if (isTable) { isTable = false - list.push('</tbody></table>') + list.push('</tbody>\n</table>\n') continue } if (list.length === 0 || (!isCodeBlock && emptyLineLength > 1)) { @@ -299,6 +280,7 @@ class Tool { var isQuoteList = false // 引用中的列表, 只支持一层级 var quoteListStyle = 0 // 1有序, 2 无序 + var isHtmlBlock = false // 是否原生html代码块 // for (let it of this.list) { @@ -343,10 +325,11 @@ class Tool { // wc-code标签直接拼接, 判断时多拼一个 < 和 >, // 是为了避免在 wc-markd嵌入代码块示例时, 将其内容编译为html - if (~it.indexOf('<wc-code') || ~it.indexOf('wc-code>')) { + if (it.includes('<wc-code') || it.includes('wc-code>')) { + // 如果之前未闭合的段落, 先闭合 if (isParagraph) { isParagraph = false - html += '</p>' + html += '</p>\n' } html += it isCodeBlock = !isCodeBlock @@ -374,9 +357,13 @@ class Tool { let head = Decoder.head(it) if (head) { - isParagraph = false + html = trimBr(html) + if (isParagraph) { + isParagraph = false + html += '</p>' + } + html += head - // console.log(html) continue } @@ -408,7 +395,7 @@ class Tool { if (innerQuote) { // 之前有引用的列表时, 直接结束列表 if (isQuoteList) { - html += `</${quoteListStyle === 1 ? 'ul' : 'ul'}>` + html += `</${quoteListStyle === 1 ? 'ul' : 'ol'}>\n` isQuoteList = false } } @@ -423,9 +410,8 @@ class Tool { var qlist = '' // 已有列表 - if (isQuoteList) { - // 因为只支持一层级的列表, 所以同一级别不区分有序无序, 强制统一 - } else { + // 因为只支持一层级的列表, 所以同一级别不区分有序无序, 强制统一 + if (isQuoteList === false) { isQuoteList = true if (currListStyle === 1) { qlist += '<ol>' @@ -515,11 +501,18 @@ class Tool { } if (isParagraph) { - html += `${it}<br>` + html += `${it}\n` } else { - html += `<p>${it}<br>` + if (isHtmlBlock || SINGLE_LINE_HTML_RE.test(it)) { + html += `${it}\n` + } else if (MULTI_LINE_HTML_RE.test(it)) { + isHtmlBlock = !isHtmlBlock + html += `${it}\n` + } else { + html += `\n<p>\n${it}` + isParagraph = true + } } - isParagraph = true } else { // 如果是在代码中, 直接拼接, 并加上换行 if (isCodeBlock) { @@ -534,7 +527,7 @@ class Tool { emptyLineLength = 0 while (blockquoteLevel > 0) { blockquoteLevel-- - html += '</blockquote>' + html += '</blockquote>\n' } } continue @@ -544,10 +537,10 @@ class Tool { if (emptyLineLength > 1) { while (orderListLevel > -1 || unorderListLevel > -1) { if (orderListLevel > unorderListLevel) { - html += '</ol>' + html += '</ol>\n' orderListLevel-- } else { - html += '</ul>' + html += '</ul>\n' unorderListLevel-- } } @@ -560,24 +553,24 @@ class Tool { // if (isParagraph) { if (emptyLineLength > 1) { + emptyLineLength = 0 isParagraph = false - html += '</p>' + html = trimBr(html) + html += '\n</p>\n' + } else { + html += '<br>' } } } } } - // 修正内嵌样式 - html = html.replace(STYLE_RE, (m, code) => { - return `<style>${code - .replace(/<br>/g, '') - .replace(/<p>/g, '') - .replace(/<\/p>/g, '')}</style>` - }) + if (isParagraph) { + html += '</p>' + } delete this.list delete this.__LINKS__ - return html + return html.trim() } }