Add option to compile markdown

This commit is contained in:
Endeavorance 2025-03-21 14:58:26 -04:00
parent e7218143ec
commit c1f3c6cade
7 changed files with 62 additions and 237 deletions

View file

@ -1,6 +1,12 @@
import { watch } from "node:fs/promises";
import chalk from "chalk";
import { CLIError, MuseError, loadFromBinding, resolveBindingPath } from "#lib";
import {
CLIError,
MuseError,
compileMarkdownInPlaybill,
loadFromBinding,
resolveBindingPath,
} from "#lib";
import { renderPlaybillToHTML } from "#render/html";
import {
type CLIArguments,
@ -30,6 +36,9 @@ async function processBinding({ inputFilePath, options }: CLIArguments) {
switch (options.renderer) {
case "json":
if (options.markdown) {
await compileMarkdownInPlaybill(binding);
}
serializedPlaybill = binding.playbill.serialize();
break;
case "html":

View file

@ -6,9 +6,9 @@ import type { BoundPlaybill } from "./binding";
import remarkWikiLink from "remark-wiki-link";
import { toSlug } from "./slug";
import rehypeRaw from "rehype-raw";
import rehypeSanitize from "rehype-sanitize";
import remarkGfm from "remark-gfm";
import rehypeShiftHeading from "rehype-shift-heading";
import type { TaggedComponent } from "@proscenium/playbill";
export type MarkdownParserFunction = (input: string) => Promise<string>;
@ -37,11 +37,43 @@ export function createMarkdownRenderer(
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeRaw)
.use(rehypeShiftHeading, { shift: 1 })
.use(rehypeSanitize)
.use(rehypeStringify);
// TODO: Add sanitization
return async (input: string): Promise<string> => {
const parsed = await parser.process(input);
return String(parsed);
};
}
export async function compileMarkdownInPlaybill(
boundPlaybill: BoundPlaybill,
): Promise<BoundPlaybill> {
const renderMarkdown = createMarkdownRenderer(boundPlaybill);
const playbill = boundPlaybill.playbill;
// Define a processor function to iterate over all components and process their markdown
const processMarkdownInComponent = async (entry: TaggedComponent) => {
entry.component.description = await renderMarkdown(
entry.component.description,
);
if (entry.type === "resource" && entry.component.type === "table") {
const newData: string[][] = [];
for (const row of entry.component.data) {
const newRow: string[] = [];
for (const cell of row) {
newRow.push(await renderMarkdown(cell));
}
newData.push(newRow);
}
entry.component.data = newData;
}
};
// Process all components
await playbill.processComponents(processMarkdownInComponent);
return boundPlaybill;
}

View file

@ -1,6 +1,6 @@
import { Playbill, type TaggedComponent } from "@proscenium/playbill";
import { Playbill } from "@proscenium/playbill";
import sortBy from "lodash-es/sortBy";
import { createMarkdownRenderer, type BoundPlaybill } from "#lib";
import { compileMarkdownInPlaybill, type BoundPlaybill } from "#lib";
import { GlossaryTable } from "./component/glossary";
import { PageHeader } from "./component/header";
import { ItemCard } from "./component/item";
@ -17,31 +17,7 @@ export async function renderPlaybillToHTML(
// Make a copy of the playbill to avoid modifying the original
// and compile all description markdown
const playbill = Playbill.fromSerialized(boundPlaybill.playbill.serialize());
// Prepare a rendering function for markdown that is aware of the playbill binding
const renderMarkdown = createMarkdownRenderer(boundPlaybill);
// Define a processor function to iterate over all components and process their markdown
const processMarkdownInComponent = async (entry: TaggedComponent) => {
entry.component.description = await renderMarkdown(
entry.component.description,
);
if (entry.type === "resource" && entry.component.type === "table") {
const newData: string[][] = [];
for (const row of entry.component.data) {
const newRow: string[] = [];
for (const cell of row) {
newRow.push(await renderMarkdown(cell));
}
newData.push(newRow);
}
entry.component.data = newData;
}
};
// Process all components
await playbill.processComponents(processMarkdownInComponent);
await compileMarkdownInPlaybill(boundPlaybill);
// Soprt rules by their order prop
const rulesByOrder = sortBy(Object.values(playbill.rules), "order");

View file

@ -16,6 +16,7 @@ Options:
--outfile, -o Specify the output file path. If not specified, output to stdout
--watch, -w Watch the directory for changes and recompile
--renderer, -r Specify the output renderer. Options: json, html
--markdown Compile markdown in descriptions when rendering to JSON
--help, -h Show this help message
`.trim();
@ -35,6 +36,7 @@ export interface CLIArguments {
help: boolean;
renderer: Renderer;
watch: boolean;
markdown: boolean;
};
}
@ -74,6 +76,10 @@ export function parseCLIArguments(argv: string[]): CLIArguments {
default: false,
type: "boolean",
},
markdown: {
default: false,
type: "boolean",
},
},
strict: true,
allowPositionals: true,
@ -99,6 +105,7 @@ export function parseCLIArguments(argv: string[]): CLIArguments {
help: options.help,
renderer: parsedRenderer.data,
watch: options.watch,
markdown: options.markdown,
},
};
}