68 lines
2.7 KiB
TypeScript
68 lines
2.7 KiB
TypeScript
import type {AstroIntegration, ContentEntryType, HookParameters} from "astro"
|
|
import {fileURLToPath} from "url"
|
|
import gemtextVitePlugin from "./vitePlugin.js"
|
|
import { parse as parseYaml } from "yaml";
|
|
|
|
/** Gemtext configuration options */
|
|
export interface GemtextConfig {
|
|
/** Absolute import path to the layout to use for all gemtext pages.
|
|
* If not provided, HMR and the Astro toolbar will not work. (default: none) */
|
|
layout?: string
|
|
/** The format to use for the page title. Can be one of:
|
|
* - `first-heading`: The first heading in the document will be used as the title. (default)
|
|
* - `filename`: The filename of the document will be used as the title.
|
|
*/
|
|
titleFormat?: "first-heading" | "filename"
|
|
}
|
|
|
|
type SetupHookParams = HookParameters<"astro:config:setup"> & {
|
|
// `addPageExtension` and `contentEntryType` are not a public APIs
|
|
// Add type defs here
|
|
addPageExtension: (extension: string) => void
|
|
addContentEntryType: (contentEntryType: ContentEntryType) => void
|
|
}
|
|
|
|
export default function gemtext(config: GemtextConfig = {}): AstroIntegration {
|
|
if (!config.titleFormat) {
|
|
config.titleFormat = "first-heading"
|
|
}
|
|
return {
|
|
name: "astro-gemtext",
|
|
hooks: {
|
|
"astro:config:setup": async (_params) => {
|
|
const params = _params as SetupHookParams
|
|
params.addPageExtension('.gmi')
|
|
params.addContentEntryType({
|
|
extensions: ['.gmi'],
|
|
getEntryInfo: async ({ fileUrl, contents }) => {
|
|
const lines = contents.split('\n');
|
|
let data: Record<string, unknown> = {};
|
|
let frontmatter = '';
|
|
let bodyStartLineIndex = 0;
|
|
|
|
if (lines.at(0) === '---' && lines.lastIndexOf('---') > 0) {
|
|
bodyStartLineIndex = lines.indexOf('---', 1) + 1;
|
|
frontmatter = lines.slice(1, bodyStartLineIndex).join('\n');
|
|
try {
|
|
data = { ...data, ...parseYaml(frontmatter, { schema: 'yaml-1.1' }) };
|
|
} catch { }
|
|
}
|
|
|
|
return {
|
|
data,
|
|
rawData: frontmatter,
|
|
body: lines.slice(bodyStartLineIndex).join('\n'),
|
|
slug: typeof data['slug'] === 'string' ? data['slug'] : fileUrl.pathname,
|
|
};
|
|
},
|
|
})
|
|
params.updateConfig({
|
|
vite: {
|
|
plugins: [gemtextVitePlugin(config)],
|
|
},
|
|
})
|
|
},
|
|
},
|
|
}
|
|
}
|