par(md): add closing sequence

refac: rename heading to atx heading
This commit is contained in:
Dmitriy Pleshevskiy 2022-06-11 22:41:15 +03:00
parent ef1baea81b
commit 5bd148bf17
Signed by: pleshevskiy
GPG Key ID: 1B59187B161C0215
2 changed files with 40 additions and 24 deletions

View File

@ -5,7 +5,7 @@ import { MarkdownParser } from "./md.ts";
const ren = new HtmlStrRenderer();
Deno.test({
name: "should parse header",
name: "should parse empty ATX header",
fn: () => {
const par = new MarkdownParser();
const res = par.parse("#");
@ -14,16 +14,16 @@ Deno.test({
});
Deno.test({
name: "should parse header with text",
name: "should parse ATX header with text",
fn: () => {
const par = new MarkdownParser();
const res = par.parse("# hello");
assertEquals(ren.render(res), "<h1>hello</h1>");
assertEquals(ren.render(par.parse("# hello")), "<h1>hello</h1>");
assertEquals(ren.render(par.parse("# hello#")), "<h1>hello#</h1>");
},
});
Deno.test({
name: "should parse header with specific level",
name: "should parse ATX header with specific level",
fn: () => {
const par = new MarkdownParser();
assertEquals(ren.render(par.parse("# hello")), "<h1>hello</h1>");
@ -36,7 +36,7 @@ Deno.test({
});
Deno.test({
name: "should parse header if line contains additional spaces",
name: "should parse ATX header if line contains additional spaces",
fn: () => {
const par = new MarkdownParser();
assertEquals(ren.render(par.parse(" # hello")), "<h1>hello</h1>");
@ -44,3 +44,15 @@ Deno.test({
assertEquals(ren.render(par.parse(" # hello")), "<h1>hello</h1>");
},
});
Deno.test({
name: "should parse ATX header with closing sequence",
fn: () => {
const par = new MarkdownParser();
assertEquals(ren.render(par.parse("# #")), "<h1></h1>");
assertEquals(ren.render(par.parse("# hello #")), "<h1>hello</h1>");
assertEquals(ren.render(par.parse("# hello #########")), "<h1>hello</h1>");
assertEquals(ren.render(par.parse("# hello # ")), "<h1>hello</h1>");
assertEquals(ren.render(par.parse("###### hello #")), "<h6>hello</h6>");
},
});

View File

@ -2,7 +2,8 @@ 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|$)/;
const RE_OPEN_ATX_HEADING = /^\s{0,3}(#{1,6})(\s|$)/;
const RE_CLOSE_ATX_HEADING = /(^|\s+)#*\s*$/;
export class MarkdownParser implements Parser {
parse(input: string): AnyNode {
@ -10,29 +11,32 @@ export class MarkdownParser implements Parser {
let readStr = input;
const match = RE_OPEN_HEADING.exec(readStr);
const match = RE_OPEN_ATX_HEADING.exec(readStr);
if (!isNil(match)) {
readStr = readStr.slice(match[0].length);
console.log({ match });
const heading: AstHeading = {
kind: AstKind.Heading,
const atxHeading: AstAtxHeading = {
kind: AstKind.AtxHeading,
level: match[1].length as HeadingLevel,
content: [],
};
ast.content.push(heading);
ast.content.push(atxHeading);
if (match[2].length > 0) {
const textContent = readStr.split("\n", 1)[0];
readStr = readStr.slice(textContent.length);
const endMatch = RE_CLOSE_ATX_HEADING.exec(readStr);
const text: AstText = {
kind: AstKind.Text,
content: textContent,
};
const headingContent = isNil(endMatch)
? readStr.split("\n", 1)[0]
: readStr.slice(0, endMatch.index);
readStr = readStr.slice(headingContent.length);
heading.content.push(text);
if (headingContent.trim().length) {
const text: AstText = {
kind: AstKind.Text,
content: headingContent.trim(),
};
atxHeading.content.push(text);
}
}
}
@ -40,7 +44,7 @@ export class MarkdownParser implements Parser {
}
}
function Heading(ast: AstHeading): Elem {
function Heading(ast: AstAtxHeading): Elem {
return new Elem(`h${ast.level}`, {}, ast.content.map(Text));
}
@ -51,9 +55,9 @@ function Text(ast: AstText): TextNode {
// AST
type AstDocument = BaseAstItem<AstKind.Document, AstDocumentChild[]>;
type AstDocumentChild = AstHeading;
type AstDocumentChild = AstAtxHeading;
interface AstHeading extends BaseAstItem<AstKind.Heading, AstText[]> {
interface AstAtxHeading extends BaseAstItem<AstKind.AtxHeading, AstText[]> {
level: HeadingLevel;
}
@ -68,6 +72,6 @@ interface BaseAstItem<K extends AstKind, Cont> {
enum AstKind {
Document,
Heading,
AtxHeading,
Text,
}