62 lines
1.7 KiB
TypeScript
62 lines
1.7 KiB
TypeScript
import YAML from "yaml";
|
|
const FRONTMATTER_REGEX = /^---[\s\S]*?---/gm;
|
|
|
|
/**
|
|
* Parse a markdown document with optional YAML frontmatter into an object
|
|
* with the markdown content and any frontmatter as keys.
|
|
* @param content The raw markdown content
|
|
* @param markdownKey The key to use for the markdown content
|
|
* @returns The parsed markdown content and frontmatter
|
|
*/
|
|
function parse(
|
|
content: string,
|
|
markdownKey = "content",
|
|
): Record<string, unknown> {
|
|
const markdown = content.trim().replace(FRONTMATTER_REGEX, "").trim();
|
|
let frontmatter: Record<string, unknown> = {};
|
|
|
|
if (FRONTMATTER_REGEX.test(content)) {
|
|
const frontmatterString = content.match(FRONTMATTER_REGEX)?.[0] ?? "";
|
|
const cleanFrontmatter = frontmatterString.replaceAll("---", "").trim();
|
|
frontmatter = YAML.parse(cleanFrontmatter);
|
|
}
|
|
|
|
return {
|
|
[markdownKey]: markdown,
|
|
...frontmatter,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Serialize an object with markdown content and optional frontmatter into a
|
|
* Markdown document. Uses the `content` key for the markdown content by default.
|
|
* @param data The object to serialize
|
|
* @param markdownKey The key to use for the markdown content
|
|
* @returns The parsed markdown content and frontmatter
|
|
*/
|
|
function stringify(
|
|
data: Record<string, unknown>,
|
|
markdownKey = "content",
|
|
): string {
|
|
const markdown = String(data[markdownKey] ?? "");
|
|
const frontmatter = { ...data };
|
|
delete frontmatter[markdownKey];
|
|
|
|
const remainingKeys = Object.keys(frontmatter).length;
|
|
|
|
if (remainingKeys === 0) {
|
|
return markdown;
|
|
}
|
|
|
|
const stringifiedFrontmatter = YAML.stringify(frontmatter).trim();
|
|
|
|
return `---\n${stringifiedFrontmatter}\n---\n${markdown}`;
|
|
}
|
|
|
|
const EMDY = {
|
|
parse,
|
|
stringify,
|
|
} as const;
|
|
|
|
export default EMDY;
|