import { parseDocument } from "@lib/documents.ts"; import { parse } from "yaml"; import { createCrud } from "@lib/crud.ts"; import { stringify } from "$std/yaml/stringify.ts"; import { extractHashTags, formatDate } from "@lib/string.ts"; import { fixRenderedMarkdown } from "@lib/helpers.ts"; export type Article = { id: string; type: "article"; content: string; name: string; tags: string[]; meta: { status: "finished" | "not-finished"; date: Date; link: string; image?: string; author?: string; rating?: number; }; }; const crud = createCrud
({ prefix: "Media/articles/", parse: parseArticle, }); function renderArticle(article: Article) { const meta = article.meta; if ("date" in meta) { meta.date = formatDate(meta.date); } return fixRenderedMarkdown(`${ meta ? `--- ${stringify(meta)} ---` : `--- ---` } # ${article.name} ${article.tags.map((t) => `#${t}`).join(" ")} ${article.content} `); } function parseArticle(original: string, id: string): Article { const doc = parseDocument(original); let meta = {} as Article["meta"]; let name = ""; const range = [Infinity, -Infinity]; for (const child of doc.children) { if (child.type === "yaml") { meta = parse(child.value) as Article["meta"]; if (meta["rating"] && typeof meta["rating"] === "string") { meta.rating = [...meta.rating?.matchAll("⭐")].length; } continue; } if ( child.type === "heading" && child.depth === 1 && !name && child.children.length === 1 && child.children[0].type === "text" ) { name = child.children[0].value; continue; } if (name) { const start = child.position?.start.offset || Infinity; const end = child.position?.end.offset || -Infinity; if (start < range[0]) range[0] = start; if (end > range[1]) range[1] = end; } } let content = original.slice(range[0], range[1]); const tags = extractHashTags(content); for (const tag of tags) { content = content.replace("#" + tag, ""); } return { type: "article", id, name, tags, content, meta, }; } export const getAllArticles = crud.readAll; export const getArticle = crud.read; export const createArticle = (article: Article) => { const content = renderArticle(article); return crud.create(article.id, content); };