Skip to content

Instantly share code, notes, and snippets.

@RickCarlino
Created May 3, 2023 12:19
Show Gist options
  • Save RickCarlino/18a25052b9720dea4b9ca62682125e0a to your computer and use it in GitHub Desktop.
Save RickCarlino/18a25052b9720dea4b9ca62682125e0a to your computer and use it in GitHub Desktop.
Really simple Gemtext parser in Typescript
// Gemtext.ts
type TextNode = {
type: "text";
content: string;
};
type LinkNode = {
type: "link";
url: string;
title: string;
};
type HeadingNode = {
type: "heading";
level: number;
content: string;
};
type ListItemNode = {
type: "listItem";
content: string;
};
type BlockquoteNode = {
type: "blockquote";
content: string;
};
type PreformattedNode = {
type: "preformatted";
content: string;
};
type GemtextNode =
| TextNode
| LinkNode
| HeadingNode
| ListItemNode
| BlockquoteNode
| PreformattedNode;
function parseGemtext(gemtext: string): GemtextNode[] {
const lines = gemtext.split("\n");
const ast: GemtextNode[] = [];
let preformatted = false;
for (const line of lines) {
if (preformatted) {
if (line === "```") {
preformatted = false;
continue;
}
ast.push({
type: "preformatted",
content: line,
});
} else {
const linkRegex = /^=>\s*(\S+)\s*(.*)$/;
const headingRegex = /^(#{1,6})\s+(.*)$/;
const listItemRegex = /^\*\s+(.*)$/;
const blockquoteRegex = /^>\s+(.*)$/;
const preformattedRegex = /^```$/;
if (linkRegex.test(line)) {
const [, url, title] = line.match(linkRegex) || [];
ast.push({ type: "link", url, title });
} else if (headingRegex.test(line)) {
const [, level, content] = line.match(headingRegex) || [];
ast.push({ type: "heading", level: level.length, content });
} else if (listItemRegex.test(line)) {
const [, content] = line.match(listItemRegex) || [];
ast.push({ type: "listItem", content });
} else if (blockquoteRegex.test(line)) {
const [, content] = line.match(blockquoteRegex) || [];
ast.push({ type: "blockquote", content });
} else if (preformattedRegex.test(line)) {
preformatted = true;
} else {
ast.push({ type: "text", content: line });
}
}
}
return ast;
}
export default parseGemtext;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment