This repository has been archived on 2023-08-30. You can view files and clone it, but cannot push or open issues/pull-requests.
bytedo
/
wcui
Archived
1
0
Fork 0

优化代码着色;优化markd解析,更好的支持html+md混编;优化pager样式

old
宇天 2021-04-28 18:46:09 +08:00
parent 9565a65686
commit c8d6dc664b
4 changed files with 75 additions and 32 deletions

View File

@ -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) => { .replace(TAG_END_EXP, (m, tag) => {
return `[tag]</${tag}>[/tag]` return `[tag]</${tag}>[/tag]`
}) })
.replace(TAG_CM_EXP, '[cm]<!--$1-->[cm]') .replace(TAG_CM_EXP, '[cm]<!--$1-->[cm]')
return rebuild(code) return rebuild(code)
} }

View File

@ -197,4 +197,4 @@ const SVG_PATH = {
export default SVG_PATH export default SVG_PATH
// console.log(Object.keys(SVG_PATH).length) // console.log(Object.keys(SVG_PATH).length)
// console.log(Object.keys(SVG_PATH)) // console.log(Object.keys(SVG_PATH).join(','))

View File

@ -5,12 +5,16 @@
*/ */
const HR_LIST = ['=', '-', '_', '*'] const HR_LIST = ['=', '-', '_', '*']
const LIST_REG = /^(([\+\-\*])|(\d+\.))\s/ const LIST_RE = /^(([\+\-\*])|(\d+\.))\s/
const TODO_REG = /^\-\s\[(x|\s)\]\s/ const TODO_RE = /^\-\s\[(x|\s)\]\s/
const ESCAPE_REG = /\\([-+*_`])/g const ESCAPE_RE = /\\([-+*_`])/g
const QLINK_REG = /^\[(\d+)\]: ([\S]+)\s*?((['"])[\s\S]*?\4)?\s*?$/ const QLINK_RE = /^\[(\d+)\]: ([\S]+)\s*?((['"])[\s\S]*?\4)?\s*?$/
const TAG_REG = /<([\w\-]+)([\w\W]*?)>/g const TAG_RE = /<([\w\-]+)([\w\W]*?)>/g
const ATTR_REG = /^[\s\S]*?(style="[^"]*?")[\s\S]*?$/ 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 = /<style[^>]*?>([\w\W]*?)<\/style>/g
const INLINE = { const INLINE = {
code: /`([^`]*?[^`\\\s])`/g, code: /`([^`]*?[^`\\\s])`/g,
@ -36,7 +40,7 @@ const Helper = {
// 是否列表, -1不是, 1为有序列表, 0为无序列表 // 是否列表, -1不是, 1为有序列表, 0为无序列表
isList(str) { isList(str) {
var v = str.trim() var v = str.trim()
if (LIST_REG.test(v)) { if (LIST_RE.test(v)) {
var n = +v[0] var n = +v[0]
if (n === n) { if (n === n) {
return 1 return 1
@ -49,7 +53,7 @@ const Helper = {
// 是否任务列表 // 是否任务列表
isTodo(str) { isTodo(str) {
var v = str.trim() var v = str.trim()
if (TODO_REG.test(v)) { if (TODO_RE.test(v)) {
return v[3] === 'x' ? 1 : 0 return v[3] === 'x' ? 1 : 0
} }
return -1 return -1
@ -61,13 +65,17 @@ const Helper = {
return str.replace(/^\s+/, '') return str.replace(/^\s+/, '')
}, },
isQLink(str) { isQLink(str) {
if (QLINK_REG.test(str)) { if (QLINK_RE.test(str)) {
return { [RegExp.$1]: { l: RegExp.$2, t: RegExp.$3 } } return { [RegExp.$1]: { l: RegExp.$2, t: RegExp.$3 } }
} }
return false return false
}, },
isTable(str) { isTable(str) {
return /^\|.+?\|$/.test(str) return /^\|.+?\|$/.test(str)
},
// 是否原生dom节点
isNativeDom(str) {
return IS_DOM_RE.test(str)
} }
} }
@ -107,7 +115,7 @@ const Decoder = {
return m return m
} }
}) })
.replace(ESCAPE_REG, '$1') // 处理转义字符 .replace(ESCAPE_RE, '$1') // 处理转义字符
}, },
// 分割线 // 分割线
hr() { hr() {
@ -138,7 +146,7 @@ const Decoder = {
task(str) { task(str) {
var todoChecked = Helper.isTodo(str) var todoChecked = Helper.isTodo(str)
if (~todoChecked) { if (~todoChecked) {
var word = str.replace(TODO_REG, '').trim() var word = str.replace(TODO_RE, '').trim()
var stat = todoChecked === 1 ? 'checked' : '' var stat = todoChecked === 1 ? 'checked' : ''
var txt = todoChecked === 1 ? `<del>${word}</del>` : word var txt = todoChecked === 1 ? `<del>${word}</del>` : word
@ -155,12 +163,22 @@ function fixed(str) {
.replace(/\t/g, ' ') .replace(/\t/g, ' ')
.replace(/\u00a0/g, ' ') .replace(/\u00a0/g, ' ')
.replace(/\u2424/g, '\n') .replace(/\u2424/g, '\n')
.replace(TAG_REG, (m, name, attr) => { .replace(TAG_RE, (m, name, attr) => {
let tmp = attr.replace(/\n/g, '⨨☇') // 标签内的换行, 转为一组特殊字符, 方便后面还原 // 标签内的换行, 转为一组特殊字符, 方便后面还原
if (tmp !== attr) { return `<${name + attr.replace(/\n/g, '⨨☇')}>`
tmp = ' ' + tmp })
} .replace(BLOCK_RE, (m, tag, attr, txt) => {
return `<${name + tmp}>` return `<${tag + attr}>${txt.replace(/\n/g, '⨨⤶')}</${tag}>`
})
.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, ' ')}</${tag}>`
}) })
} }
@ -179,6 +197,8 @@ class Tool {
var isTable = false // 是否表格 var isTable = false // 是否表格
var emptyLineLength = 0 //连续空行的数量 var emptyLineLength = 0 //连续空行的数量
// console.log(lines)
for (let it of lines) { for (let it of lines) {
let tmp = it.trim() let tmp = it.trim()
@ -206,20 +226,21 @@ class Tool {
} else { } else {
var qlink var qlink
if (isCodeBlock) { if (isCodeBlock) {
it = it it = it.replace(/</g, '&lt;').replace(/>/g, '&gt;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/⨨☇/g, '\n') // 代码块要还原回换行
} else { } else {
it = it it = it
.replace(/(⨨☇)+/g, ' ') // 非代码块直接转为空格, 并进行xss过滤 // 非代码块进行xss过滤
.replace(INLINE.code, (m, txt) => { .replace(INLINE.code, (m, txt) => {
return `\`${txt.replace(/</g, '&lt;').replace(/>/g, '&gt;')}\`` return `\`${txt.replace(/</g, '&lt;').replace(/>/g, '&gt;')}\``
}) })
.replace(/<(\/?)script[^>]*?>/g, '&lt;$1script&gt;') .replace(/<(\/?)script[^>]*?>/g, '&lt;$1script&gt;')
.replace(TAG_REG, (m, name, attr) => { .replace(TAG_RE, (m, name, attr = '') => {
attr = attr.replace(ATTR_REG, '$1').trim() // 过滤所有onXX=""事件属性
return `<${name} ${attr}>` attr = attr.replace(ATTR_RE, ' ').trim()
if (attr) {
attr = ' ' + attr
}
return `<${name}${attr}>`
}) })
} }
qlink = Helper.isQLink(it) qlink = Helper.isQLink(it)
@ -412,7 +433,7 @@ class Tool {
// 左侧空格长度 // 左侧空格长度
let tmp = Helper.ltrim(it) let tmp = Helper.ltrim(it)
let ltrim = it.length - tmp.length 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 level = Math.floor(ltrim / 2)
let tag = listChecked > 0 ? 'ol' : 'ul' let tag = listChecked > 0 ? 'ol' : 'ul'
@ -458,6 +479,11 @@ class Tool {
continue continue
} }
if (Helper.isNativeDom(it)) {
html += it
continue
}
if (isParagraph) { if (isParagraph) {
html += `${it}<br>` html += `${it}<br>`
} else { } else {
@ -506,7 +532,14 @@ class Tool {
} }
} }
} }
// console.log(html)
// 修正内嵌样式
html = html.replace(STYLE_RE, (m, code) => {
return `<style>${code
.replace(/<br>/g, '')
.replace(/<p>/g, '')
.replace(/<\/p>/g, '')}</style>`
})
delete this.list delete this.list
delete this.__LINKS__ delete this.__LINKS__
return html return html

View File

@ -34,16 +34,25 @@
background: var(--color-teal-1); background: var(--color-teal-1);
color: #fff; color: #fff;
} }
&.jump {
display: flex;
}
} }
input { input {
width: 48px; width: 48px;
height: 36px; height: 36px;
padding: 0 4px; padding: 0 4px;
border: 2px solid var(--color-plain-2); border: 1px solid var(--color-grey-2);
border-radius: 4px; border-radius: 3px;
text-align: center; text-align: center;
outline: none; 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 => `<span class="curr item">${n}</span>`, curr: n => `<span class="curr item">${n}</span>`,
info: (t, p) => `<span class="item">共 ${t}条, ${p}页</span>`, info: (t, p) => `<span class="item">共 ${t}条, ${p}页</span>`,
jump: n => jump: n =>
`<section class="item"><input maxlength="6" value="${n}"><wc-button data-act="go" class="item">Go</wc-button></section>` `<section class="item jump"><input maxlength="6" value="${n}"><wc-button data-act="go" class="item">Go</wc-button></section>`
} }
// //