/** * Copyright (c) Microsoft Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // @ts-check /** @typedef {{ * type: 'text' | 'li' | 'code' | 'gen' | 'h0' | 'h1' | 'h2' | 'h3' | 'h4', * text?: string, * codeLang?: string, * lines?: string[], * liType?: 'default' | 'bullet' | 'ordinal', * children?: MarkdownNode[] * }} MarkdownNode */ function normalizeLines(content) { const inLines = content.replace(/\r\n/g, '\n').split('\n'); let inCodeBlock = false; const outLines = []; let outLineTokens = []; for (const line of inLines) { let singleLineExpression = line.startsWith('#'); let flushParagraph = !line.trim() || line.trim().startsWith('1.') || line.trim().startsWith('<') || line.trim().startsWith('>') || line.trim().startsWith('-') || line.trim().startsWith('*') || singleLineExpression; if (line.startsWith('```')) { inCodeBlock = !inCodeBlock; flushParagraph = true; } if (flushParagraph && outLineTokens.length) { outLines.push(outLineTokens.join(' ')); outLineTokens = []; } const trimmedLine = line.trim(); if (inCodeBlock || singleLineExpression) outLines.push(line); else if (trimmedLine) outLineTokens.push(trimmedLine.startsWith('-') ? line : trimmedLine); } if (outLineTokens.length) outLines.push(outLineTokens.join(' ')); return outLines; } /** * @param {string[]} lines */ function buildTree(lines) { /** @type {MarkdownNode} */ const root = { type: 'h0', text: '', children: [] }; /** @type {MarkdownNode[]} */ const stack = [root]; /** @type {MarkdownNode[]} */ let liStack = null; for (let i = 0; i < lines.length; ++i) { let line = lines[i]; if (line.startsWith('```')) { /** @type {MarkdownNode} */ const node = { type: 'code', lines: [], codeLang: line.substring(3) }; stack[0].children.push(node); line = lines[++i]; while (!line.startsWith('```')) { node.lines.push(line); line = lines[++i]; } continue; } if (line.startsWith('