From 0e97260b32d995682112bf5f6339be1dd621fe59 Mon Sep 17 00:00:00 2001 From: 3y3k0 <3y3k0@yandex-team.ru> Date: Wed, 1 Feb 2023 05:15:11 +0300 Subject: [PATCH] fix(liquid): Process large fence blocks --- src/transform/liquid/index.ts | 68 ++++++++++++++++++++++---------- src/transform/plugins/typings.ts | 5 ++- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/src/transform/liquid/index.ts b/src/transform/liquid/index.ts index 87a2b23a..aec1bb22 100644 --- a/src/transform/liquid/index.ts +++ b/src/transform/liquid/index.ts @@ -8,7 +8,38 @@ import ArgvService, {ArgvSettings} from './services/argv'; import {Dictionary} from 'lodash'; const codes: string[] = []; -const regexp = /`{3}(((?!`{3})[^])+)`{3}/g; + +const fence = '```'; + +const find = (open: string, close: string, string: string, index: number) => { + const start = string.indexOf(open, index); + const end = start > -1 ? string.indexOf(close, start + open.length) : -1; + + return [start, end]; +}; + +const replace = ( + open: string, + close: string, + value: (string: string) => string, + string: string, +) => { + let result = ''; + let carriage = 0; + let [start, end] = find(open, close, string, carriage); + + while (start > -1 && end > -1) { + const fragment = string.slice(start + open.length, end); + + result += string.slice(carriage, start) + open + value(fragment) + close; + carriage = end + close.length; + [start, end] = find(open, close, string, carriage); + } + + result += string.slice(carriage); + + return result; +}; function saveCode( str: string, @@ -16,28 +47,25 @@ function saveCode( path?: string, substitutions?: boolean, ) { - let i = 0; - - return str.replace(regexp, (_, code: string) => { - i++; - - const codeWithVars = substitutions ? applySubstitutions(code, vars, path) : code; - - codes.push(codeWithVars); - - /* Keep the same count of lines to avoid transformation of the source map */ - const codeLines = codeWithVars.split('\n'); - const emptyLines = codeLines.length > 1 ? codeLines.reduce((acc) => acc + '\n', '') : ''; - - return '```' + i + emptyLines + '```'; - }); + return replace( + fence, + fence, + (code) => { + const codeWithVars = substitutions ? applySubstitutions(code, vars, path) : code; + const index = codes.push(codeWithVars) - 1; + + /* Keep the same count of lines to avoid transformation of the source map */ + const codeLines = codeWithVars.split('\n'); + const emptyLines = codeLines.length > 1 ? '\n'.repeat(codeLines.length) : ''; + + return `${index}${emptyLines}`; + }, + str, + ); } function repairCode(str: string) { - return str.replace(regexp, (_, code) => { - const number = code.trimRight(); - return '```' + codes[number - 1] + '```'; - }); + return replace(fence, fence, (code) => codes[Number(code)], str); } function liquid< diff --git a/src/transform/plugins/typings.ts b/src/transform/plugins/typings.ts index 7b3675d5..a0c0546c 100644 --- a/src/transform/plugins/typings.ts +++ b/src/transform/plugins/typings.ts @@ -9,4 +9,7 @@ export interface MarkdownItPluginOpts { isLintRun: boolean; } -export type MarkdownItPluginCb = (md: MarkdownIt, opts: T & MarkdownItPluginOpts) => void; +export type MarkdownItPluginCb = ( + md: MarkdownIt, + opts: T & MarkdownItPluginOpts, +) => void;