summaryrefslogtreecommitdiff
path: root/src/vitePlugin.ts
blob: 7b5ef44677ddcc14ae6bd04aa69b02445867e328 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import {HTMLRenderer, parse} from "gemtext"
import path from "path"
import {pathToFileURL} from "url"
import type {Plugin} from "vite"
import {type GemtextConfig} from "./index.js"

function transform(code: string, id: string, config: GemtextConfig) {
    const result = parse(code)
    let title

    if (config.titleFormat === "first-heading") {
        for (const node of result.data) {
            if (node._ === 4) {
                title = node.text
                break
            }
        }
    } else if (config.titleFormat === "filename") {
        title = path.basename(id)
    }
    const html = result.generate(HTMLRenderer)
    return `
import {
    createComponent,
    render,
    renderComponent,
    unescapeHTML,
} from "astro/runtime/server/index.js";
import { Fragment, jsx as h } from "astro/jsx-runtime";
${config.layout ? `import Layout from ${JSON.stringify(config.layout)};` : ""}
export const name = "TypstComponent";
export const html = ${JSON.stringify(html)};
export const frontmatter = undefined;
export const file = ${JSON.stringify(id)};
export const url = ${JSON.stringify(pathToFileURL(id))};
export function compiledContent() {
    return html;
}
export function getHeadings() {
    return undefined;
}
export async function Content() {
    const content = h(Fragment, {"set:html": html});
    ${config.layout ? `return h(Layout, {title: ${JSON.stringify(title)}, children: content});` : ""}
    ${!config.layout ? `return content;` : ""}
}
export default Content;
`
}

export default function gemtextVitePlugin(config: GemtextConfig): Plugin {
    // let server: ViteDevServer
    return {
        name: "astro-gemtext",
        enforce: "pre",
        transform(code, id) {
            if (!id.endsWith('.gmi')) return
            return {
                code: transform(code, id, config),
                map: null,
            }
        },
    }
}