improve djot plugin
This commit is contained in:
12
_config.ts
12
_config.ts
@@ -2,13 +2,19 @@ import lume from "lume/mod.ts";
|
|||||||
import nav from "lume/plugins/nav.ts";
|
import nav from "lume/plugins/nav.ts";
|
||||||
import codeHighlight from "lume/plugins/code_highlight.ts";
|
import codeHighlight from "lume/plugins/code_highlight.ts";
|
||||||
import googleFonts from "lume/plugins/google_fonts.ts";
|
import googleFonts from "lume/plugins/google_fonts.ts";
|
||||||
import { djotLoader, djotRender } from "./_djot.ts";
|
import djotPlugin from "./_djot.ts";
|
||||||
|
import djot from "@djot/djot";
|
||||||
|
|
||||||
const site = lume();
|
const site = lume();
|
||||||
|
|
||||||
site.use(nav());
|
site.use(nav());
|
||||||
site.use(codeHighlight());
|
site.use(codeHighlight());
|
||||||
|
|
||||||
|
site.use(djotPlugin({
|
||||||
|
renderOptions: {
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
site.use(googleFonts({
|
site.use(googleFonts({
|
||||||
cssFile: "/styles/main.css",
|
cssFile: "/styles/main.css",
|
||||||
placeholder: "/* import fonts */",
|
placeholder: "/* import fonts */",
|
||||||
@@ -21,8 +27,4 @@ site.use(googleFonts({
|
|||||||
site.copy("/styles");
|
site.copy("/styles");
|
||||||
site.copy("favicon.svg");
|
site.copy("favicon.svg");
|
||||||
|
|
||||||
site.data("djot", djotRender);
|
|
||||||
site.filter("djot", djotRender);
|
|
||||||
site.loadPages([".dj"], djotLoader);
|
|
||||||
|
|
||||||
export default site;
|
export default site;
|
||||||
|
|||||||
94
_djot.ts
94
_djot.ts
@@ -1,4 +1,25 @@
|
|||||||
import djot from "@djot/djot";
|
import djot from "@djot/djot";
|
||||||
|
import Site from "lume/core/site.ts";
|
||||||
|
import { merge } from "lume/core/utils/object.ts";
|
||||||
|
|
||||||
|
// Djot does not export these types
|
||||||
|
type Filter = object;
|
||||||
|
type HTMLRenderOptions = object;
|
||||||
|
|
||||||
|
export interface Options {
|
||||||
|
/** The list of file extensions this plugin applies to */
|
||||||
|
extensions?: string[];
|
||||||
|
|
||||||
|
filters?: Filter[];
|
||||||
|
|
||||||
|
/** Options passed to djot library */
|
||||||
|
renderOptions?: HTMLRenderOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default options
|
||||||
|
export const defaults: Options = {
|
||||||
|
extensions: [".dj", ".djot"],
|
||||||
|
};
|
||||||
|
|
||||||
function extractTitle(ast: djot.Doc): string {
|
function extractTitle(ast: djot.Doc): string {
|
||||||
const firstSection = ast.children.find((c) => c.tag == "section");
|
const firstSection = ast.children.find((c) => c.tag == "section");
|
||||||
@@ -10,35 +31,80 @@ function extractTitle(ast: djot.Doc): string {
|
|||||||
return title ?? "No title";
|
return title ?? "No title";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function djotRender(content: string): string {
|
|
||||||
return djot.renderHTML(djot.parse(content));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function djotLoader(path: string | URL) {
|
export async function djotLoader(path: string | URL) {
|
||||||
const content = await Deno.readTextFile(path);
|
const content = await Deno.readTextFile(path);
|
||||||
|
|
||||||
const ast = djot.parse(content);
|
const ast = djot.parse(content);
|
||||||
|
const title = extractTitle(ast);
|
||||||
|
|
||||||
djot.applyFilter(ast, () => {
|
|
||||||
return {
|
return {
|
||||||
link: (el) => {
|
title,
|
||||||
|
content,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const stripMarkupSourceLinks: Filter = () => {
|
||||||
|
return {
|
||||||
|
link: (el: djot.Link) => {
|
||||||
if (el.destination) {
|
if (el.destination) {
|
||||||
el.destination = el.destination.replace(
|
el.destination = el.destination.replace(
|
||||||
/(\.dj)(#[^.\s]+)?$/,
|
/(.(?:dj|md))(#[^.\s]+)?$/,
|
||||||
(_match: string, _ext: string, section: string) => {
|
(_match: string, _ext: string, section: string) => {
|
||||||
return section ? section : "";
|
return section ?? "";
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultFilters = [
|
||||||
|
stripMarkupSourceLinks,
|
||||||
|
];
|
||||||
|
|
||||||
|
export class DjotEngine implements Lume.Engine {
|
||||||
|
filters: Filter[];
|
||||||
|
renderOptions?: HTMLRenderOptions;
|
||||||
|
|
||||||
|
constructor(filters: Filter[] = [], renderOptions?: HTMLRenderOptions) {
|
||||||
|
this.filters = [...defaultFilters, ...filters];
|
||||||
|
this.renderOptions = renderOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
render(
|
||||||
|
content: string | djot.Doc,
|
||||||
|
_data?: Record<string, unknown>,
|
||||||
|
_filename?: string,
|
||||||
|
): string {
|
||||||
|
if (typeof content === "string") {
|
||||||
|
content = djot.parse(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.filters.forEach((filter, _index, _array) => {
|
||||||
|
djot.applyFilter(content, filter);
|
||||||
});
|
});
|
||||||
|
|
||||||
const title = extractTitle(ast);
|
return djot.renderHTML(
|
||||||
const html = djot.renderHTML(ast);
|
content,
|
||||||
|
this.renderOptions,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
addHelper() {}
|
||||||
title,
|
|
||||||
content: html,
|
deleteCache() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function (userOptions?: Options) {
|
||||||
|
const options = merge(defaults, userOptions);
|
||||||
|
|
||||||
|
return function (site: Site) {
|
||||||
|
const engine = new DjotEngine(options.filters, options.renderOptions);
|
||||||
|
|
||||||
|
site.loadPages(options.extensions, {
|
||||||
|
loader: djotLoader,
|
||||||
|
engine,
|
||||||
|
});
|
||||||
|
|
||||||
|
site.filter("djot", (content) => engine.render(content as string));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user