feat: initial refactor to use marka as backend
This commit is contained in:
161
lib/documents.ts
161
lib/documents.ts
@@ -1,19 +1,7 @@
|
||||
import { unified } from "https://esm.sh/unified@10.1.2";
|
||||
import { render } from "gfm";
|
||||
import "https://esm.sh/prismjs@1.29.0/components/prism-typescript?no-check";
|
||||
import "https://esm.sh/prismjs@1.29.0/components/prism-bash?no-check";
|
||||
import "https://esm.sh/prismjs@1.29.0/components/prism-rust?no-check";
|
||||
import remarkParse from "https://esm.sh/remark-parse@10.0.2";
|
||||
import remarkStringify from "https://esm.sh/remark-stringify@10.0.3";
|
||||
import remarkFrontmatter, {
|
||||
Root,
|
||||
} from "https://esm.sh/remark-frontmatter@4.0.1";
|
||||
import { SILVERBULLET_SERVER } from "@lib/env.ts";
|
||||
import { fixRenderedMarkdown } from "@lib/helpers.ts";
|
||||
import { createLogger } from "@lib/log/index.ts";
|
||||
import { db } from "@lib/db/sqlite.ts";
|
||||
import { documentTable } from "@lib/db/schema.ts";
|
||||
import { eq } from "drizzle-orm/sql";
|
||||
|
||||
export type Document = {
|
||||
name: string;
|
||||
@@ -24,114 +12,6 @@ export type Document = {
|
||||
perm: string;
|
||||
};
|
||||
|
||||
const log = createLogger("documents");
|
||||
|
||||
export async function getDocuments(): Promise<Document[]> {
|
||||
let documents = await db.select().from(documentTable).all();
|
||||
if (documents.length) return documents;
|
||||
|
||||
const headers = new Headers();
|
||||
headers.append("Accept", "application/json");
|
||||
headers.append("X-Sync-Mode", "true");
|
||||
log.debug("fetching all documents");
|
||||
const response = await fetch(`${SILVERBULLET_SERVER}/index.json`, {
|
||||
headers: headers,
|
||||
});
|
||||
|
||||
documents = await response.json();
|
||||
await db.delete(documentTable);
|
||||
await db.insert(documentTable).values(documents);
|
||||
|
||||
return documents;
|
||||
}
|
||||
|
||||
export function createDocument(
|
||||
name: string,
|
||||
content: string | ArrayBuffer,
|
||||
mediaType?: string,
|
||||
) {
|
||||
const headers = new Headers();
|
||||
|
||||
if (mediaType) {
|
||||
headers.append("Content-Type", mediaType);
|
||||
}
|
||||
|
||||
log.info("creating document", { name });
|
||||
|
||||
if (typeof content === "string") {
|
||||
updateDocument(name, content).catch(log.error);
|
||||
}
|
||||
|
||||
return fetch(SILVERBULLET_SERVER + "/" + name, {
|
||||
body: content,
|
||||
method: "PUT",
|
||||
headers,
|
||||
});
|
||||
}
|
||||
|
||||
async function fetchDocument(name: string) {
|
||||
log.debug("fetching document", { name });
|
||||
const headers = new Headers();
|
||||
headers.append("X-Sync-Mode", "true");
|
||||
const response = await fetch(SILVERBULLET_SERVER + "/" + name, { headers });
|
||||
if (response.status === 404) {
|
||||
return;
|
||||
}
|
||||
return response.text();
|
||||
}
|
||||
|
||||
export async function getDocument(name: string): Promise<string | undefined> {
|
||||
const documents = await db.select().from(documentTable).where(
|
||||
eq(documentTable.name, name),
|
||||
).limit(1);
|
||||
// This updates the document in the background
|
||||
fetchDocument(name).then((content) => {
|
||||
if (content) {
|
||||
updateDocument(name, content);
|
||||
} else {
|
||||
db.delete(documentTable).where(eq(documentTable.name, name));
|
||||
}
|
||||
}).catch(
|
||||
log.error,
|
||||
);
|
||||
if (documents[0]?.content) return documents[0].content;
|
||||
|
||||
const text = await fetchDocument(name);
|
||||
if (!text) {
|
||||
db.delete(documentTable).where(eq(documentTable.name, name));
|
||||
return;
|
||||
}
|
||||
await updateDocument(name, text);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
export function updateDocument(name: string, content: string) {
|
||||
return db.update(documentTable).set({
|
||||
content,
|
||||
}).where(eq(documentTable.name, name)).run();
|
||||
}
|
||||
|
||||
export function transformDocument(input: string, cb: (r: Root) => Root) {
|
||||
const out = unified()
|
||||
.use(remarkParse)
|
||||
.use(remarkFrontmatter, ["yaml"])
|
||||
.use(() => (tree) => {
|
||||
return cb(tree);
|
||||
})
|
||||
.use(remarkStringify)
|
||||
.processSync(input);
|
||||
|
||||
return fixRenderedMarkdown(String(out));
|
||||
}
|
||||
|
||||
export function parseDocument(doc: string) {
|
||||
return unified()
|
||||
.use(remarkParse)
|
||||
.use(remarkFrontmatter, ["yaml", "toml"])
|
||||
.parse(doc);
|
||||
}
|
||||
|
||||
function removeFrontmatter(doc: string) {
|
||||
if (doc.trim().startsWith("---")) {
|
||||
return doc.trim().split("---").filter((s) => s.length).slice(1).join("---");
|
||||
@@ -160,42 +40,15 @@ export function removeImage(doc: string, imageUrl?: string) {
|
||||
|
||||
export function renderMarkdown(doc: string) {
|
||||
return render(removeFrontmatter(doc), {
|
||||
baseUrl: SILVERBULLET_SERVER,
|
||||
baseUrl: "https://max-richter.dev",
|
||||
allowMath: true,
|
||||
});
|
||||
}
|
||||
|
||||
export type ParsedDocument = ReturnType<typeof parseDocument>;
|
||||
export type DocumentChild = ParsedDocument["children"][number];
|
||||
|
||||
export function findRangeOfChildren(children: DocumentChild[]) {
|
||||
const firstChild = children[0];
|
||||
const lastChild = children.length > 1
|
||||
? children[children.length - 1]
|
||||
: firstChild;
|
||||
|
||||
const start = firstChild.position?.start.offset;
|
||||
const end = lastChild.position?.end.offset;
|
||||
|
||||
if (typeof start !== "number" || typeof end !== "number") return;
|
||||
|
||||
return [start, end];
|
||||
}
|
||||
|
||||
export function getTextOfRange(children: DocumentChild[], text: string) {
|
||||
if (!children || children.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const range = findRangeOfChildren(children);
|
||||
if (!range) return;
|
||||
return text.substring(range[0], range[1]);
|
||||
}
|
||||
|
||||
export function getTextOfChild(child: DocumentChild): string | undefined {
|
||||
if ("value" in child) return child.value;
|
||||
if ("children" in child) {
|
||||
return getTextOfChild(child.children[0]);
|
||||
}
|
||||
return;
|
||||
export function createDocument(
|
||||
path: string,
|
||||
entry: string,
|
||||
mimetype = "image/jpeg",
|
||||
) {
|
||||
console.log("creating", { path, entry, mimetype });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user