fix: only convert leading tabs to spaces (#1559) (#2434)

* fix: non leading-tabs in markdown content (#1559)

Only replaces tabs at the beginning of a block construct. Tabs in the
middle of the item are unaffected.

All tests passing. Tabs in both GFM and CommonMark at 100%

fixes #1559

* update new/html_comments.html to preserve tab

* combine redundant if condition

* add test for tab immediately after blockquote character
This commit is contained in:
rossipedia 2022-04-10 18:37:04 -06:00 committed by GitHub
parent 3dc35bb7b8
commit 7d19665167
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 14 additions and 8 deletions

View File

@ -115,8 +115,7 @@ export class Lexer {
*/ */
lex(src) { lex(src) {
src = src src = src
.replace(/\r\n|\r/g, '\n') .replace(/\r\n|\r/g, '\n');
.replace(/\t/g, ' ');
this.blockTokens(src, this.tokens); this.blockTokens(src, this.tokens);
@ -133,8 +132,13 @@ export class Lexer {
*/ */
blockTokens(src, tokens = []) { blockTokens(src, tokens = []) {
if (this.options.pedantic) { if (this.options.pedantic) {
src = src.replace(/^ +$/gm, ''); src = src.replace(/\t/g, ' ').replace(/^ +$/gm, '');
} else {
src = src.replace(/^( *)(\t+)/gm, (_, leading, tabs) => {
return leading + ' '.repeat(tabs.length);
});
} }
let token, lastToken, cutSrc, lastParagraphClipped; let token, lastToken, cutSrc, lastParagraphClipped;
while (src) { while (src) {

View File

@ -151,7 +151,7 @@ export class Tokenizer {
blockquote(src) { blockquote(src) {
const cap = this.rules.block.blockquote.exec(src); const cap = this.rules.block.blockquote.exec(src);
if (cap) { if (cap) {
const text = cap[0].replace(/^ *> ?/gm, ''); const text = cap[0].replace(/^ *>[ \t]?/gm, '');
return { return {
type: 'blockquote', type: 'blockquote',
@ -187,7 +187,7 @@ export class Tokenizer {
} }
// Get next list item // Get next list item
const itemRegex = new RegExp(`^( {0,3}${bull})((?: [^\\n]*)?(?:\\n|$))`); const itemRegex = new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`);
// Check if current bullet point can start a new List Item // Check if current bullet point can start a new List Item
while (src) { while (src) {

View File

@ -11,10 +11,10 @@ export const block = {
newline: /^(?: *(?:\n|$))+/, newline: /^(?: *(?:\n|$))+/,
code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/, code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,
fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?=\n|$)|$)/, fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?=\n|$)|$)/,
hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/, hr: /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,
heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/, heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,
blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/, blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
list: /^( {0,3}bull)( [^\n]+?)?(?:\n|$)/, list: /^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/,
html: '^ {0,3}(?:' // optional indentation html: '^ {0,3}(?:' // optional indentation
+ '<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1) + '<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
+ '|comment[^\\n]*(\\n+|$)' // (2) + '|comment[^\\n]*(\\n+|$)' // (2)

View File

@ -37,7 +37,7 @@
<h3 id="example-10">Example 10</h3> <h3 id="example-10">Example 10</h3>
<!-- multi <!-- multi
line line
comment comment
--> -->

View File

@ -0,0 +1 @@
<blockquote><p>test</p></blockquote>

View File

@ -0,0 +1 @@
> test