import { AnyNode, Elem, Fragment, TextNode } from "../core/node.ts"; import { isNil } from "../core/utils.ts"; import { Parser } from "./types.ts"; const RE_OPEN_HEADING = /^\s{0,3}(#{1,6})(\s|$)/; export class MarkdownParser implements Parser { parse(input: string): AnyNode { const ast: AstDocument = { kind: AstKind.Document, content: [] }; let readStr = input; const match = RE_OPEN_HEADING.exec(readStr); if (!isNil(match)) { readStr = readStr.slice(match[0].length); console.log({ match }); const heading: AstHeading = { kind: AstKind.Heading, level: match[1].length as HeadingLevel, content: [], }; ast.content.push(heading); if (match[2].length > 0) { const textContent = readStr.split("\n", 1)[0]; readStr = readStr.slice(textContent.length); const text: AstText = { kind: AstKind.Text, content: textContent, }; heading.content.push(text); } } return new Fragment(ast.content.map(Heading)); } } function Heading(ast: AstHeading): Elem { return new Elem(`h${ast.level}`, {}, ast.content.map(Text)); } function Text(ast: AstText): TextNode { return new TextNode(ast.content); } // AST type AstDocument = BaseAstItem; type AstDocumentChild = AstHeading; interface AstHeading extends BaseAstItem { level: HeadingLevel; } type AstText = BaseAstItem; type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6; interface BaseAstItem { kind: K; content: Cont; } enum AstKind { Document, Heading, Text, }