From c8d6dc664b93f72c7b23e4336902c9bb718d2a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E5=A4=A9?= Date: Wed, 28 Apr 2021 18:46:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=E7=9D=80?= =?UTF-8?q?=E8=89=B2;=E4=BC=98=E5=8C=96markd=E8=A7=A3=E6=9E=90,=E6=9B=B4?= =?UTF-8?q?=E5=A5=BD=E7=9A=84=E6=94=AF=E6=8C=81html+md=E6=B7=B7=E7=BC=96;?= =?UTF-8?q?=E4=BC=98=E5=8C=96pager=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/code/colorful.js | 3 +- src/icon/svg.js | 2 +- src/markd/core.js | 87 ++++++++++++++++++++++++++++++-------------- src/pager/index.wc | 15 ++++++-- 4 files changed, 75 insertions(+), 32 deletions(-) diff --git a/src/code/colorful.js b/src/code/colorful.js index ca4c771..438a8cc 100644 --- a/src/code/colorful.js +++ b/src/code/colorful.js @@ -62,12 +62,13 @@ export function colorHtml(code) { } }) } - return `[tag]<${tag + attr}>[/tag]` + return `[tag]<${tag}[/tag]${attr}[tag]>[/tag]` }) .replace(TAG_END_EXP, (m, tag) => { return `[tag]</${tag}>[/tag]` }) .replace(TAG_CM_EXP, '[cm]<!--$1-->[cm]') + return rebuild(code) } diff --git a/src/icon/svg.js b/src/icon/svg.js index 9ed1703..e1819c6 100644 --- a/src/icon/svg.js +++ b/src/icon/svg.js @@ -197,4 +197,4 @@ const SVG_PATH = { export default SVG_PATH // console.log(Object.keys(SVG_PATH).length) -// console.log(Object.keys(SVG_PATH)) +// console.log(Object.keys(SVG_PATH).join(',')) diff --git a/src/markd/core.js b/src/markd/core.js index 7c6657d..f0fdf70 100644 --- a/src/markd/core.js +++ b/src/markd/core.js @@ -5,12 +5,16 @@ */ const HR_LIST = ['=', '-', '_', '*'] -const LIST_REG = /^(([\+\-\*])|(\d+\.))\s/ -const TODO_REG = /^\-\s\[(x|\s)\]\s/ -const ESCAPE_REG = /\\([-+*_`])/g -const QLINK_REG = /^\[(\d+)\]: ([\S]+)\s*?((['"])[\s\S]*?\4)?\s*?$/ -const TAG_REG = /<([\w\-]+)([\w\W]*?)>/g -const ATTR_REG = /^[\s\S]*?(style="[^"]*?")[\s\S]*?$/ +const LIST_RE = /^(([\+\-\*])|(\d+\.))\s/ +const TODO_RE = /^\-\s\[(x|\s)\]\s/ +const ESCAPE_RE = /\\([-+*_`])/g +const QLINK_RE = /^\[(\d+)\]: ([\S]+)\s*?((['"])[\s\S]*?\4)?\s*?$/ +const TAG_RE = /<([\w\-]+)([\w\W]*?)>/g +const ATTR_RE = /\s*?on[a-zA-Z]+="[^"]*?"\s*?/g +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 INLINE = { code: /`([^`]*?[^`\\\s])`/g, @@ -36,7 +40,7 @@ const Helper = { // 是否列表, -1不是, 1为有序列表, 0为无序列表 isList(str) { var v = str.trim() - if (LIST_REG.test(v)) { + if (LIST_RE.test(v)) { var n = +v[0] if (n === n) { return 1 @@ -49,7 +53,7 @@ const Helper = { // 是否任务列表 isTodo(str) { var v = str.trim() - if (TODO_REG.test(v)) { + if (TODO_RE.test(v)) { return v[3] === 'x' ? 1 : 0 } return -1 @@ -61,13 +65,17 @@ const Helper = { return str.replace(/^\s+/, '') }, isQLink(str) { - if (QLINK_REG.test(str)) { + if (QLINK_RE.test(str)) { return { [RegExp.$1]: { l: RegExp.$2, t: RegExp.$3 } } } return false }, isTable(str) { return /^\|.+?\|$/.test(str) + }, + // 是否原生dom节点 + isNativeDom(str) { + return IS_DOM_RE.test(str) } } @@ -107,7 +115,7 @@ const Decoder = { return m } }) - .replace(ESCAPE_REG, '$1') // 处理转义字符 + .replace(ESCAPE_RE, '$1') // 处理转义字符 }, // 分割线 hr() { @@ -138,7 +146,7 @@ const Decoder = { task(str) { var todoChecked = Helper.isTodo(str) if (~todoChecked) { - var word = str.replace(TODO_REG, '').trim() + var word = str.replace(TODO_RE, '').trim() var stat = todoChecked === 1 ? 'checked' : '' var txt = todoChecked === 1 ? `${word}` : word @@ -155,12 +163,22 @@ function fixed(str) { .replace(/\t/g, ' ') .replace(/\u00a0/g, ' ') .replace(/\u2424/g, '\n') - .replace(TAG_REG, (m, name, attr) => { - let tmp = attr.replace(/\n/g, '⨨☇') // 标签内的换行, 转为一组特殊字符, 方便后面还原 - if (tmp !== attr) { - tmp = ' ' + tmp - } - return `<${name + tmp}>` + .replace(TAG_RE, (m, name, attr) => { + // 标签内的换行, 转为一组特殊字符, 方便后面还原 + return `<${name + attr.replace(/\n/g, '⨨☇')}>` + }) + .replace(BLOCK_RE, (m, tag, attr, txt) => { + return `<${tag + attr}>${txt.replace(/\n/g, '⨨⤶')}` + }) + .replace(CODEBLOCK_RE, (m, lang, txt) => { + // 还原换行 + let rollback = txt.replace(/⨨⤶/g, '\n').replace(/⨨☇/g, '\n') + return '```' + lang + rollback + '```' + }) + .replace(BLOCK_RE, (m, tag, attr, txt) => { + return `<${tag + attr.replace(/(⨨☇)+/g, ' ')}>${txt + .replace(/⨨⤶/g, ' ') + .replace(/(⨨☇)+/g, ' ')}` }) } @@ -179,6 +197,8 @@ class Tool { var isTable = false // 是否表格 var emptyLineLength = 0 //连续空行的数量 + // console.log(lines) + for (let it of lines) { let tmp = it.trim() @@ -206,20 +226,21 @@ class Tool { } else { var qlink if (isCodeBlock) { - it = it - .replace(//g, '>') - .replace(/⨨☇/g, '\n') // 代码块要还原回换行 + it = it.replace(//g, '>') } else { it = it - .replace(/(⨨☇)+/g, ' ') // 非代码块直接转为空格, 并进行xss过滤 + // 非代码块进行xss过滤 .replace(INLINE.code, (m, txt) => { return `\`${txt.replace(//g, '>')}\`` }) .replace(/<(\/?)script[^>]*?>/g, '<$1script>') - .replace(TAG_REG, (m, name, attr) => { - attr = attr.replace(ATTR_REG, '$1').trim() - return `<${name} ${attr}>` + .replace(TAG_RE, (m, name, attr = '') => { + // 过滤所有onXX=""事件属性 + attr = attr.replace(ATTR_RE, ' ').trim() + if (attr) { + attr = ' ' + attr + } + return `<${name}${attr}>` }) } qlink = Helper.isQLink(it) @@ -412,7 +433,7 @@ class Tool { // 左侧空格长度 let tmp = Helper.ltrim(it) let ltrim = it.length - tmp.length - let word = tmp.replace(LIST_REG, '').trim() + let word = tmp.replace(LIST_RE, '').trim() let level = Math.floor(ltrim / 2) let tag = listChecked > 0 ? 'ol' : 'ul' @@ -458,6 +479,11 @@ class Tool { continue } + if (Helper.isNativeDom(it)) { + html += it + continue + } + if (isParagraph) { html += `${it}
` } else { @@ -506,7 +532,14 @@ class Tool { } } } - // console.log(html) + + // 修正内嵌样式 + html = html.replace(STYLE_RE, (m, code) => { + return `` + }) delete this.list delete this.__LINKS__ return html diff --git a/src/pager/index.wc b/src/pager/index.wc index a79f799..f9baa54 100644 --- a/src/pager/index.wc +++ b/src/pager/index.wc @@ -34,16 +34,25 @@ background: var(--color-teal-1); color: #fff; } + + &.jump { + display: flex; + } } input { width: 48px; height: 36px; padding: 0 4px; - border: 2px solid var(--color-plain-2); - border-radius: 4px; + border: 1px solid var(--color-grey-2); + border-radius: 3px; text-align: center; outline: none; + transition: box-shadow 0.15s linear; + + &:focus { + box-shadow: 0 0 0 2px var(--color-plain-a); + } } } @@ -140,7 +149,7 @@ const LAYOUT_DICT = { curr: n => `${n}`, info: (t, p) => `共 ${t}条, ${p}页`, jump: n => - `
Go
` + `
Go
` } //