From 6b17ad76bae35673cf65ebd59cac6f02270096d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E5=A4=A9?= Date: Mon, 10 Feb 2020 03:11:19 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84markdown=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/index.wc | 52 ++++++++----- src/markd/parser.js | 181 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 213 insertions(+), 20 deletions(-) create mode 100644 src/markd/parser.js diff --git a/src/markd/index.wc b/src/markd/index.wc index 626053a..ffa58e3 100644 --- a/src/markd/index.wc +++ b/src/markd/index.wc @@ -11,6 +11,8 @@ } .markd { padding: 10px; + // white-space: pre-wrap; + // word-wrap: break-word; } a { text-decoration: underline; @@ -27,6 +29,12 @@ em { strong { color: nth($cd, 3); } +a { + strong, + em { + color: inherit; + } +} em, strong, del { @@ -39,17 +47,15 @@ img { max-width: 100%; } -blockquote { - &.md-quote { - margin: 10px 0; - padding: 5px 10px; - border-left: 5px solid nth($ct, 1); - background: #f2faf7; - color: nth($cgr, 1); - - p { - margin: 0; - } +blockquote.md-quote { + margin: 10px 0; + padding: 5px 10px; + line-height: 1.5; + border-left: 5px solid nth($ct, 1); + background: #f2faf7; + color: nth($cgr, 1); + p { + margin: 0; } } @@ -171,14 +177,13 @@ h6 { padding: 0 5px; } a { - visibility: hidden; - position: absolute; - left: -25px; - width: 25px; - padding: 0 3px; - font-weight: bold; text-decoration: none; - text-align: center; + color: #333; + + &::before { + content: '# '; + color: nth($ct, 1); + } } &:hover a { visibility: visible; @@ -225,7 +230,12 @@ table { } code.inline { + display: inline-block; + margin: 0 2px; + padding: 0 3px; color: nth($co, 3); + background: nth($cp, 1); + border-radius: 2px; } @@ -233,7 +243,8 @@ code.inline { import $ from '../utils' import '../code/index' -import parser from './core' +// import parser from './core' +import parser from './parser' export default class Markd { props = {} @@ -246,7 +257,8 @@ export default class Markd { } mounted() { - this.__BOX__.innerHTML = parser.safe(this.textContent) + // this.__BOX__.innerHTML = parser.safe(this.textContent) + this.__BOX__.innerHTML = parser(this.textContent) this.textContent = '' } } diff --git a/src/markd/parser.js b/src/markd/parser.js new file mode 100644 index 0000000..f026972 --- /dev/null +++ b/src/markd/parser.js @@ -0,0 +1,181 @@ +/** + * markdown解析器 + * @author yutent + * @date 2020/02/07 17:14:19 + */ + +'use strict' +const HR_LIST = ['=', '-', '_', '*'] +const log = console.log + +const Helper = { + // 是否分割线 + isHr(str) { + var s = str[0] + if (HR_LIST.includes(s)) { + return str.startsWith(s.repeat(3)) + } + return false + } +} + +const Tool = { + // 初始化字符串, 处理多余换行等 + init(str) { + // 去掉\r, 将\t转为空格(2个) + str = str.replace(/\r/g, '').replace(/\t/g, ' ') + var list = [] + var lines = str.split('\n') + var isCodeBlock = false // 是否代码块 + var emptyLineLength = 0 //连续空行的数量 + + for (let it of lines) { + let tmp = it.trim() + // 空行 + if (!tmp) { + if (list.length === 0 || (!isCodeBlock && emptyLineLength > 0)) { + continue + } + emptyLineLength++ + list.push(tmp) + } else { + emptyLineLength = 0 + if (tmp.startsWith('```')) { + if (isCodeBlock) { + list.push('') + } else { + list.push(tmp.replace(/^```([\w\#\-]*?)$/, '')) + } + isCodeBlock = !isCodeBlock + } else { + list.push(it) + } + } + } + log(list) + this.list = list + return this + }, + + parse() { + var html = '' + var isCodeBlock = false // 是否代码块 + var emptyLineLength = 0 //连续空行的数量 + var isBlockquote = false + var blockquoteLevel = 0 + var isParagraph = false + + // + for (let it of this.list) { + // 空行 + if (!it) { + // 如果是在代码中, 直接拼接, 并加上换行 + if (isCodeBlock) { + html += it + '\n' + } else { + emptyLineLength++ + + // 引用结束 + if (isBlockquote) { + isBlockquote = false + html += '' + if (emptyLineLength > 0) { + while (blockquoteLevel > 0) { + emptyLineLength = 0 + blockquoteLevel-- + html += '' + } + } + continue + } + + // + if (isParagraph) { + isParagraph = false + html += '

' + } /* else { + html += '
' + } */ + } + } else { + // wc-code标签直接拼接 + if (~it.indexOf('wc-code')) { + html += it + isCodeBlock = !isCodeBlock + } else { + // 同上代码块的处理 + if (isCodeBlock) { + html += it + '\n' + continue + } + + it = it + .replace(/`(.*?)`/g, '$1') + .replace(/(\-\-|\*\*)(.*?)\1/g, '$2') + .replace(/(\-|\*)(.*?)\1/g, '$2') + .replace(/\!\[([^]*?)\]\(([^)]*?)\)/g, '$1') + .replace(/\[([^]*?)\]\(([^)]*?)\)/g, '$1') + + // + if (it.startsWith('>')) { + html += it.replace(/^(>+) /, m => { + let len = m.trim().length + let tmp = '' + if (isBlockquote) { + // 若之前已经有一个未闭合的引用, 需要减去已有缩进级别, 避免产生新的引用标签 + len = len - blockquoteLevel + } else { + blockquoteLevel = len + } + log('bq: ', blockquoteLevel, it) + while (len > 0) { + len-- + tmp += '
' + } + return tmp + }) + + if (isBlockquote) { + html += '
' + } + isParagraph = false + isBlockquote = true + continue + } + + if (isBlockquote) { + html += it + continue + } + + // + if (it.startsWith('#')) { + isParagraph = false + let end = '' + html += it.replace(/^#{1,6} /, m => { + let level = m.trim().length + end = `` + return `` + }) + html += end + + continue + } + + // log('it => ', isParagraph, it) + if (isParagraph) { + html += `${it}
` + } else { + html += `

${it}
` + } + isParagraph = true + } + } + } + return html + } +} + +export default function(str) { + return Tool.init(str).parse() +}