remove cruft: just a content entry type now!
This commit is contained in:
+1
-1
@@ -42,7 +42,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.13.10",
|
"@types/node": "^22.13.10",
|
||||||
"astro": "^5.4.2",
|
"astro": "^6.0.8",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.8.2",
|
||||||
"vite": "^6.2.1"
|
"vite": "^6.2.1"
|
||||||
|
|||||||
+5
-24
@@ -1,19 +1,8 @@
|
|||||||
import type {AstroIntegration, ContentEntryType, HookParameters} from "astro"
|
import type {AstroIntegration, ContentEntryType, HookParameters} from "astro"
|
||||||
import {fileURLToPath} from "url"
|
import {fileURLToPath} from "url"
|
||||||
import gemtextVitePlugin from "./vitePlugin.js"
|
|
||||||
import {parse as parseYaml} from "yaml"
|
import {parse as parseYaml} from "yaml"
|
||||||
|
|
||||||
/** Gemtext configuration options */
|
export interface GemtextConfig {}
|
||||||
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"> & {
|
type SetupHookParams = HookParameters<"astro:config:setup"> & {
|
||||||
// `addPageExtension` and `contentEntryType` are not a public APIs
|
// `addPageExtension` and `contentEntryType` are not a public APIs
|
||||||
@@ -23,9 +12,6 @@ type SetupHookParams = HookParameters<"astro:config:setup"> & {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function gemtext(config: GemtextConfig = {}): AstroIntegration {
|
export default function gemtext(config: GemtextConfig = {}): AstroIntegration {
|
||||||
if (!config.titleFormat) {
|
|
||||||
config.titleFormat = "first-heading"
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
name: "astro-gemtext",
|
name: "astro-gemtext",
|
||||||
hooks: {
|
hooks: {
|
||||||
@@ -35,10 +21,10 @@ export default function gemtext(config: GemtextConfig = {}): AstroIntegration {
|
|||||||
params.addContentEntryType({
|
params.addContentEntryType({
|
||||||
extensions: [".gmi"],
|
extensions: [".gmi"],
|
||||||
getRenderFunction: async (config) => {
|
getRenderFunction: async (config) => {
|
||||||
return async (entry) => ({
|
return async (entry) => ({
|
||||||
html: entry.body ?? '',
|
html: entry.body ?? "",
|
||||||
frontmatter: entry.data,
|
frontmatter: entry.data,
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
getEntryInfo: async ({fileUrl, contents}) => {
|
getEntryInfo: async ({fileUrl, contents}) => {
|
||||||
const lines = contents.split("\n")
|
const lines = contents.split("\n")
|
||||||
@@ -81,11 +67,6 @@ export default function gemtext(config: GemtextConfig = {}): AstroIntegration {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
params.updateConfig({
|
|
||||||
vite: {
|
|
||||||
plugins: [gemtextVitePlugin(config)],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
import type {NamedSSRLoadedRendererValue} from "astro"
|
|
||||||
import {AstroError} from "astro/errors"
|
|
||||||
import {AstroJSX, jsx} from "astro/jsx-runtime"
|
|
||||||
import {renderJSX} from "astro/runtime/server/index.js"
|
|
||||||
|
|
||||||
const slotName = (str: string) =>
|
|
||||||
str.trim().replace(/[-_]([a-z])/g, (_, w) => w.toUpperCase())
|
|
||||||
|
|
||||||
// NOTE: In practice, MDX components are always tagged with `__astro_tag_component__`, so the right renderer
|
|
||||||
// is used directly, and this check is not often used to return true.
|
|
||||||
export async function check(
|
|
||||||
Component: any,
|
|
||||||
props: any,
|
|
||||||
{default: children = null, ...slotted} = {},
|
|
||||||
) {
|
|
||||||
if (typeof Component !== "function") return false
|
|
||||||
const slots: Record<string, any> = {}
|
|
||||||
for (const [key, value] of Object.entries(slotted)) {
|
|
||||||
const name = slotName(key)
|
|
||||||
slots[name] = value
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const result = await Component({...props, ...slots, children})
|
|
||||||
return result[AstroJSX]
|
|
||||||
} catch (e) {
|
|
||||||
throwEnhancedErrorIfMdxComponent(e as Error, Component)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function renderToStaticMarkup(
|
|
||||||
this: any,
|
|
||||||
Component: any,
|
|
||||||
props = {},
|
|
||||||
{default: children = null, ...slotted} = {},
|
|
||||||
) {
|
|
||||||
const slots: Record<string, any> = {}
|
|
||||||
for (const [key, value] of Object.entries(slotted)) {
|
|
||||||
const name = slotName(key)
|
|
||||||
slots[name] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
const {result} = this
|
|
||||||
try {
|
|
||||||
const html = await renderJSX(
|
|
||||||
result,
|
|
||||||
jsx(Component, {...props, ...slots, children}),
|
|
||||||
)
|
|
||||||
return {html}
|
|
||||||
} catch (e) {
|
|
||||||
throwEnhancedErrorIfMdxComponent(e as Error, Component)
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function throwEnhancedErrorIfMdxComponent(error: Error, Component: any) {
|
|
||||||
// if the exception is from an mdx component
|
|
||||||
// throw an error
|
|
||||||
if (Component[Symbol.for("mdx-component")]) {
|
|
||||||
// if it's an existing AstroError, we don't need to re-throw, keep the original hint
|
|
||||||
if (AstroError.is(error))
|
|
||||||
return // Mimic the fields of the internal `AstroError` class (not from `astro/errors`) to
|
|
||||||
// provide better title and hint for the error overlay
|
|
||||||
;(error as any).title = error.name
|
|
||||||
;(error as any).hint =
|
|
||||||
`This issue often occurs when your MDX component encounters runtime errors.`
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderer: NamedSSRLoadedRendererValue = {
|
|
||||||
name: "astro:gmi",
|
|
||||||
check,
|
|
||||||
renderToStaticMarkup,
|
|
||||||
}
|
|
||||||
|
|
||||||
export default renderer
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
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,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user