UNPKG

7.57 kBSource Map (JSON)View Raw
1{"version":3,"file":"ParagraphSplitter.js","sourceRoot":"","sources":["../../src/parser/ParagraphSplitter.ts"],"names":[],"mappings":"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","sourcesContent":["import { DocSection, DocNode, DocNodeKind, DocParagraph, DocPlainText } from '../nodes';\r\n\r\n/**\r\n * The ParagraphSplitter is a secondary stage that runs after the NodeParser has constructed\r\n * the DocComment. It splits DocParagraph nodes into multiple paragraphs by looking for\r\n * paragraph delimiters. Following CommonMark conventions, paragraphs are delimited by\r\n * one or more blank lines. (These lines end with SoftBreak nodes.) The blank lines are\r\n * not discarded. Instead, they are attached to the preceding paragraph. If the DocParagraph\r\n * starts with blank lines, they are preserved to avoid creating a paragraph containing only\r\n * whitespace.\r\n */\r\nexport class ParagraphSplitter {\r\n private static readonly _whitespaceRegExp: RegExp = /^\\s*$/;\r\n\r\n /**\r\n * Split all paragraphs belonging to the provided subtree.\r\n */\r\n public static splitParagraphs(node: DocNode): void {\r\n if (node instanceof DocSection) {\r\n ParagraphSplitter.splitParagraphsForSection(node);\r\n\r\n // (We don't recurse here, since sections cannot contain subsections)\r\n } else {\r\n for (const childNode of node.getChildNodes()) {\r\n ParagraphSplitter.splitParagraphs(childNode);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Split all paragraphs belonging to the provided DocSection.\r\n */\r\n public static splitParagraphsForSection(docSection: DocSection): void {\r\n const inputNodes: ReadonlyArray<DocNode> = docSection.nodes;\r\n const outputNodes: DocNode[] = [];\r\n\r\n for (const oldNode of inputNodes) {\r\n if (oldNode.kind === DocNodeKind.Paragraph) {\r\n ParagraphSplitter._splitParagraph(oldNode as DocParagraph, outputNodes);\r\n } else {\r\n outputNodes.push(oldNode);\r\n }\r\n }\r\n\r\n // Replace the inputNodes with the outputNodes\r\n docSection.clearNodes();\r\n docSection.appendNodes(outputNodes);\r\n }\r\n\r\n private static _splitParagraph(oldParagraph: DocParagraph, outputNodes: DocNode[]): void {\r\n const inputParagraphNodes: ReadonlyArray<DocNode> = oldParagraph.nodes;\r\n\r\n let currentParagraph: DocParagraph = new DocParagraph({ configuration: oldParagraph.configuration });\r\n outputNodes.push(currentParagraph);\r\n\r\n const enum SplitterState {\r\n Start,\r\n AwaitingTrailer,\r\n ReadingTrailer\r\n }\r\n let state: SplitterState = SplitterState.Start;\r\n\r\n let currentIndex: number = 0;\r\n while (currentIndex < inputParagraphNodes.length) {\r\n // Scan forwards to the end of the line\r\n let isBlankLine: boolean = true;\r\n let lineEndIndex: number = currentIndex; // non-inclusive\r\n do {\r\n const node: DocNode = inputParagraphNodes[lineEndIndex++];\r\n if (node.kind === DocNodeKind.SoftBreak) {\r\n break;\r\n }\r\n if (isBlankLine) {\r\n if (!this._isWhitespace(node)) {\r\n isBlankLine = false;\r\n }\r\n }\r\n } while (lineEndIndex < inputParagraphNodes.length);\r\n\r\n // At this point, the line and SoftBreak will be in inputParagraphNodes.slice(currentIndex, lineEndIndex)\r\n\r\n switch (state) {\r\n case SplitterState.Start:\r\n // We're skipping any blank lines that start the first paragraph\r\n if (!isBlankLine) {\r\n state = SplitterState.AwaitingTrailer;\r\n }\r\n break;\r\n case SplitterState.AwaitingTrailer:\r\n // We already saw some content, so now we're looking for a blank line that starts the trailer\r\n // at the end of this paragraph\r\n if (isBlankLine) {\r\n state = SplitterState.ReadingTrailer;\r\n }\r\n break;\r\n case SplitterState.ReadingTrailer:\r\n // We already found the trailer, so now we're looking for a non-blank line that will\r\n // begin a new paragraph\r\n if (!isBlankLine) {\r\n // Start a new paragraph\r\n currentParagraph = new DocParagraph({ configuration: oldParagraph.configuration });\r\n outputNodes.push(currentParagraph);\r\n\r\n state = SplitterState.AwaitingTrailer;\r\n }\r\n break;\r\n }\r\n\r\n // Append the line onto the current paragraph\r\n for (let i: number = currentIndex; i < lineEndIndex; ++i) {\r\n currentParagraph.appendNode(inputParagraphNodes[i]);\r\n }\r\n\r\n currentIndex = lineEndIndex;\r\n }\r\n }\r\n\r\n private static _isWhitespace(node: DocNode): boolean {\r\n switch (node.kind) {\r\n case DocNodeKind.PlainText:\r\n const docPlainText: DocPlainText = node as DocPlainText;\r\n return ParagraphSplitter._whitespaceRegExp.test(docPlainText.text);\r\n default:\r\n return false;\r\n }\r\n }\r\n}\r\n"]}
\No newline at end of file