Files
WRNexusJS/packages/content/src/advanced.ts
T
Clintchiz 586a6db8ff
Quality / quality (ubuntu-latest) (push) Failing after 21s
Quality / quality (windows-latest) (push) Canceled after 0s
release: WRNexusJS 0.8.0
2026-08-02 23:18:51 +05:30

153 lines
5.4 KiB
TypeScript

export type MdxComponent = (props: Record<string, string>, children: string) => string;
const escapeHtml = (value: string) =>
value.replace(
/[&<>"']/g,
(character) =>
({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[character]!,
);
/** Execute explicitly registered MDX components without evaluating arbitrary JavaScript. */
export function renderMdxComponents(
source: string,
components: Record<string, MdxComponent>,
): string {
let output = source;
const parseProps = (raw: string) =>
Object.fromEntries(
[...raw.matchAll(/([A-Za-z_$][\w$-]*)\s*=\s*["']([^"']*)["']/g)].map((match) => [
match[1]!,
match[2]!,
]),
);
for (let pass = 0; pass < 20; pass++) {
let changed = false;
output = output.replace(
/<([A-Z][A-Za-z0-9_$]*)\b([^>]*)>([\s\S]*?)<\/\1>|<([A-Z][A-Za-z0-9_$]*)\b([^>]*)\/>/g,
(whole, pairedName, pairedProps, children, singleName, singleProps) => {
const name = pairedName ?? singleName;
const component = components[name];
if (!component) throw new Error(`WRN-CONTENT-MDX-COMPONENT: '${name}' is not registered.`);
changed = true;
return component(parseProps(pairedProps ?? singleProps ?? ""), children ?? "");
},
);
if (!changed) break;
}
if (/<[A-Z][A-Za-z0-9_$]*\b/.test(output))
throw new Error("WRN-CONTENT-MDX-DEPTH: component expansion exceeded its bound.");
return output;
}
export interface SyntaxLanguageBundle {
highlight(source: string): string;
}
export function createIncrementalHighlighter(
loaders: Record<string, () => SyntaxLanguageBundle | Promise<SyntaxLanguageBundle>>,
) {
const loaded = new Map<string, Promise<SyntaxLanguageBundle>>();
return {
languages: () => [...loaded.keys()],
async highlight(language: string, source: string) {
const load = loaders[language];
if (!load) return escapeHtml(source);
let bundle = loaded.get(language);
if (!bundle) {
bundle = Promise.resolve(load());
loaded.set(language, bundle);
}
return (await bundle).highlight(source);
},
async render(html: string) {
const matches = [
...html.matchAll(/<pre><code class="language-([\w-]+)">([\s\S]*?)<\/code><\/pre>/g),
];
let output = html;
for (const match of matches)
output = output.replace(
match[0],
`<pre><code class="language-${match[1]}">${await this.highlight(match[1]!, match[2]!)}</code></pre>`,
);
return output;
},
};
}
export interface VendorAdapterOptions {
fetch?: (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
token?: string;
map?: (entry: any) => { id: string; content: string; source?: string };
}
const requestJson = async (
url: string,
options: VendorAdapterOptions,
headers: HeadersInit = {},
) => {
const response = await (options.fetch ?? globalThis.fetch)(url, { headers });
if (!response.ok) throw new Error(`WRN-CONTENT-CMS: ${response.status}`);
return response.json();
};
const normalize = (entry: any, source: string, map?: VendorAdapterOptions["map"]) =>
map?.(entry) ?? {
id: String(entry.id ?? entry.sys?.id ?? entry._id),
content: String(entry.content ?? entry.body ?? entry.fields?.body ?? ""),
source,
};
export function contentfulAdapter(
space: string,
environment = "master",
options: VendorAdapterOptions = {},
) {
return {
async list(collection: string) {
const url = `https://cdn.contentful.com/spaces/${encodeURIComponent(space)}/environments/${encodeURIComponent(environment)}/entries?content_type=${encodeURIComponent(collection)}`;
const value = await requestJson(
url,
options,
options.token ? { authorization: `Bearer ${options.token}` } : {},
);
return (value.items ?? []).map((entry: any) =>
normalize(entry, `contentful:${space}:${entry.sys?.id}`, options.map),
);
},
};
}
export function sanityAdapter(
project: string,
dataset: string,
options: VendorAdapterOptions & { apiVersion?: string } = {},
) {
return {
async list(collection: string) {
const query = encodeURIComponent(`*[_type == $type]`);
const url = `https://${encodeURIComponent(project)}.api.sanity.io/v${options.apiVersion ?? "2024-01-01"}/data/query/${encodeURIComponent(dataset)}?query=${query}&$type=${encodeURIComponent(JSON.stringify(collection))}`;
const value = await requestJson(
url,
options,
options.token ? { authorization: `Bearer ${options.token}` } : {},
);
return (value.result ?? []).map((entry: any) =>
normalize(entry, `sanity:${project}:${entry._id}`, options.map),
);
},
};
}
export function strapiAdapter(baseUrl: string, options: VendorAdapterOptions = {}) {
const base = new URL(baseUrl);
if (!/^https?:$/.test(base.protocol)) throw new Error("Strapi URL must use HTTP(S)");
return {
async list(collection: string) {
if (!/^[A-Za-z0-9_-]+$/.test(collection)) throw new Error("Invalid Strapi collection");
const value = await requestJson(
new URL(`/api/${collection}`, base).href,
options,
options.token ? { authorization: `Bearer ${options.token}` } : {},
);
return (value.data ?? []).map((entry: any) =>
normalize(entry, `strapi:${base.host}:${entry.id}`, options.map),
);
},
};
}