diff --git a/src/core/hooks/Paragraph.js b/src/core/hooks/Paragraph.js index a7937478..7b835b0c 100644 --- a/src/core/hooks/Paragraph.js +++ b/src/core/hooks/Paragraph.js @@ -38,6 +38,7 @@ export default class Paragraph extends ParagraphBase { this.classicBr = options.globalConfig.classicBr; this.removeBrAfterBlock = null; this.removeBrBeforeBlock = null; + this.removeNewlinesBetweenTags = null; } /** @@ -47,24 +48,67 @@ export default class Paragraph extends ParagraphBase { */ $cleanParagraph(str) { const { classicBr } = this.$engine.$cherry.options.engine.global; + // remove leading and trailing newlines + const trimedPar = str.replace(/^\n+/, '').replace(/\n+$/, ''); if (classicBr) { - return str.replace(/^\n+/, '').replace(/\n+$/, ''); + return trimedPar; } + const minifiedPar = this.joinRawHtml(trimedPar); + return minifiedPar.replace(/\n/g, '
').replace(/\r/g, '\n'); // recover \n from \r + } + /** + * remove all newlines in html text + * + * @param {string} textContainsHtml + */ + joinRawHtml(textContainsHtml) { if (!this.removeBrAfterBlock) { - const allBlockNames = this.$engine.htmlWhiteListAppend - ? `${this.$engine.htmlWhiteListAppend}|${blockNames}`.replace(/\|\|+/g, '|') - : blockNames; + // preprocess custom white list + const customTagWhiteList = this.$engine.htmlWhiteListAppend?.split('|') ?? []; + customTagWhiteList + .map((tag) => { + if (/[a-z-]+/gi.test(tag)) { + return tag; + } + return null; + }) + .filter((tag) => tag !== null); + // concat all white list + const allBlockNames = customTagWhiteList.concat(blockNames).join('|'); // 段落标签自然换行,所以去掉段落标签两边的换行符 - this.removeBrAfterBlock = new RegExp(`<(${allBlockNames})(>| [^>]*>)\\s*\\n\\s*`, 'ig'); - this.removeBrBeforeBlock = new RegExp(`\\n\\s*<\\/(${allBlockNames})>\\s*\\n`, 'ig'); + /** + * remove newlines after start tag, and remove whitespaces before newline + * e.g. + *

\n text

=>

text

+ * ^^ + * $1$2 + */ + this.removeBrAfterBlock = new RegExp(`<(${allBlockNames})((?: [^>]*?)>)[^\\S\\n]*?\\n`, 'ig'); + /** + * remove newlines before end tag, and whitespaces before end tag will be preserved + * e.g. + *

text\n

=>

text

+ * ^ + * $1 + */ + this.removeBrBeforeBlock = new RegExp(`\\n[^\\S\\n]*?<\\/(${allBlockNames})>[^\\S\\n]*?\\n`, 'ig'); + /** + * remove newlines between end tag & start tag + * e.g. + *

\n

=>

\r

+ * ^ ^^ ^ ^^^^^^^^^^^^ + * $1 $2 $3 $4 + */ + this.removeNewlinesBetweenTags = new RegExp( + `<\\/(${allBlockNames})>[^\\S\\n]*?\\n([^\\S\\n]*?)<(${allBlockNames})((?: [^>]*?)>)`, + 'ig', + ); } - return str - .replace(/^\n+/, '') - .replace(/\n+$/, '') + return textContainsHtml .replace(this.removeBrAfterBlock, '<$1$2') .replace(this.removeBrBeforeBlock, '') - .replace(/\n/g, '
'); + .replace(this.removeNewlinesBetweenTags, '\r$2<$3$4'); // replace \n to \r } /** diff --git a/src/sass/markdown.scss b/src/sass/markdown.scss index 995bcb0b..98545812 100644 --- a/src/sass/markdown.scss +++ b/src/sass/markdown.scss @@ -150,6 +150,15 @@ table { border-collapse: collapse; + th, + td { + border: 1px solid $borderColor; + padding: 0.2em 0.4em; + min-width: 100px; + } + th { + background-color: #eee; + } } a { @@ -323,14 +332,10 @@ td { border: 1px solid $borderColor; padding: 0.2em 0.4em; + min-width: 100px; } th { - min-width: 100px; white-space: nowrap; - background-color: #eee; - } - td { - min-width: 100px; } } } diff --git a/src/utils/tableContentHander.js b/src/utils/tableContentHander.js index 33b3e2bd..1aa2d948 100644 --- a/src/utils/tableContentHander.js +++ b/src/utils/tableContentHander.js @@ -115,7 +115,7 @@ const tableContentHander = { * 获取预览区域被点击的table对象,并记录table的顺位 */ $collectTableDom() { - const list = Array.from(this.previewerDom.querySelectorAll('table')); + const list = Array.from(this.previewerDom.querySelectorAll('table.cherry-table')); const tableNode = this.$getClosestNode(this.td, 'TABLE'); if (tableNode === false) { return false;