Created
May 3, 2023 12:19
-
-
Save RickCarlino/18a25052b9720dea4b9ca62682125e0a to your computer and use it in GitHub Desktop.
Really simple Gemtext parser in Typescript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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