@pagesmith/core 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/REFERENCE.md +281 -0
- package/assets/favicon.svg +4 -0
- package/dist/ai/index.d.mts +3 -2
- package/dist/ai/index.d.mts.map +1 -1
- package/dist/ai/index.mjs +454 -79
- package/dist/ai/index.mjs.map +1 -1
- package/dist/assets/index.mjs +1 -1
- package/dist/{assets-bX08zEJm.mjs → assets-DXiWF_KI.mjs} +1 -1
- package/dist/{assets-bX08zEJm.mjs.map → assets-DXiWF_KI.mjs.map} +1 -1
- package/dist/{content-config-fHPaFZ7i.d.mts → content-config-Bfe4W9us.d.mts} +4 -6
- package/dist/{content-config-fHPaFZ7i.d.mts.map → content-config-Bfe4W9us.d.mts.map} +1 -1
- package/dist/{content-layer-B7fQ3im4.mjs → content-layer-DPK1EmfY.mjs} +100 -52
- package/dist/content-layer-DPK1EmfY.mjs.map +1 -0
- package/dist/css/index.d.mts +1 -1
- package/dist/css/index.mjs +1 -1
- package/dist/{css-ekIt2Fdb.mjs → css-BneO430t.mjs} +5 -4
- package/dist/css-BneO430t.mjs.map +1 -0
- package/dist/{heading-Dhvzlay-.d.mts → heading-BpDXnl-7.d.mts} +1 -1
- package/dist/{heading-Dhvzlay-.d.mts.map → heading-BpDXnl-7.d.mts.map} +1 -1
- package/dist/{index-BQ6B1-qG.d.mts → index-BBYkDxwI.d.mts} +7 -7
- package/dist/{index-BQ6B1-qG.d.mts.map → index-BBYkDxwI.d.mts.map} +1 -1
- package/dist/index-Bg9srb5U.d.mts +13 -0
- package/dist/index-Bg9srb5U.d.mts.map +1 -0
- package/dist/{index-DpRBzO8Q.d.mts → index-CbOKbkjJ.d.mts} +3 -3
- package/dist/index-CbOKbkjJ.d.mts.map +1 -0
- package/dist/{index-sFCx17CD.d.mts → index-YXQxMV6J.d.mts} +10 -8
- package/dist/index-YXQxMV6J.d.mts.map +1 -0
- package/dist/index.d.mts +19 -13
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +30 -7
- package/dist/index.mjs.map +1 -1
- package/dist/loaders/index.d.mts +3 -3
- package/dist/loaders/index.mjs +2 -2
- package/dist/{loaders-DyABmDrE.mjs → loaders-Cf-BXf2L.mjs} +32 -18
- package/dist/loaders-Cf-BXf2L.mjs.map +1 -0
- package/dist/markdown/index.d.mts +2 -2
- package/dist/markdown/index.mjs +1 -1
- package/dist/{markdown-Cj5X26FL.mjs → markdown-CyrHoDhP.mjs} +37 -9
- package/dist/markdown-CyrHoDhP.mjs.map +1 -0
- package/dist/schemas/index.d.mts +3 -3
- package/dist/schemas/index.mjs +1 -1
- package/dist/{schemas-DJS7wOzd.mjs → schemas-UL4ynWsA.mjs} +3 -3
- package/dist/schemas-UL4ynWsA.mjs.map +1 -0
- package/dist/{types-DUsjRE7Y.d.mts → types-Cn52sdoq.d.mts} +2 -2
- package/dist/{types-DUsjRE7Y.d.mts.map → types-Cn52sdoq.d.mts.map} +1 -1
- package/dist/vite/index.d.mts +2 -2
- package/dist/vite/index.d.mts.map +1 -1
- package/dist/vite/index.mjs +33 -17
- package/dist/vite/index.mjs.map +1 -1
- package/package.json +3 -7
- package/dist/content-layer-B7fQ3im4.mjs.map +0 -1
- package/dist/convert-DnuB6SVV.mjs +0 -52
- package/dist/convert-DnuB6SVV.mjs.map +0 -1
- package/dist/css-ekIt2Fdb.mjs.map +0 -1
- package/dist/index-CeNDTM-y.d.mts +0 -7
- package/dist/index-CeNDTM-y.d.mts.map +0 -1
- package/dist/index-DpRBzO8Q.d.mts.map +0 -1
- package/dist/index-sFCx17CD.d.mts.map +0 -1
- package/dist/loaders-DyABmDrE.mjs.map +0 -1
- package/dist/markdown-Cj5X26FL.mjs.map +0 -1
- package/dist/schemas-DJS7wOzd.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loaders-Cf-BXf2L.mjs","names":["parseYaml","parse"],"sources":["../src/loaders/errors.ts","../src/loaders/json.ts","../src/loaders/jsonc.ts","../src/loaders/markdown.ts","../src/loaders/toml.ts","../src/loaders/yaml.ts","../src/loaders/index.ts"],"sourcesContent":["export class LoaderError extends Error {\n readonly filePath: string\n readonly format: string\n readonly line?: number\n readonly column?: number\n\n constructor(message: string, filePath: string, format: string, line?: number, column?: number) {\n super(`${format} parse error in ${filePath}${line ? `:${line}` : ''}: ${message}`)\n this.name = 'LoaderError'\n this.filePath = filePath\n this.format = format\n this.line = line\n this.column = column\n }\n}\n","/**\n * JSON / JSON5 / JSONC loader.\n *\n * Detects format from file extension and parses accordingly.\n */\n\nimport { readFile } from 'fs/promises'\nimport JSON5 from 'json5'\nimport { LoaderError } from './errors'\nimport type { Loader, LoaderResult } from './types'\n\nexport class JsonLoader implements Loader {\n name = 'json'\n kind = 'data' as const\n extensions = ['.json', '.json5']\n\n async load(filePath: string): Promise<LoaderResult> {\n const raw = await readFile(filePath, 'utf-8')\n const isJson = filePath.endsWith('.json')\n\n try {\n const data = isJson ? JSON.parse(raw) : JSON5.parse(raw)\n return { data }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new LoaderError(message, filePath, isJson ? 'JSON' : 'JSON5')\n }\n }\n}\n","/**\n * JSONC loader — JSON with Comments.\n *\n * Strips single-line (//) and multi-line comments before parsing.\n * Delegates to JSON.parse after stripping (no JSON5 superset features).\n */\n\nimport { readFile } from 'fs/promises'\nimport { LoaderError } from './errors'\nimport type { Loader, LoaderResult } from './types'\n\n/** Strip // and block comments, preserving strings. */\nfunction stripComments(raw: string): string {\n let result = ''\n let i = 0\n const len = raw.length\n\n while (i < len) {\n // String literal — copy verbatim to preserve contents\n if (raw[i] === '\"') {\n let end = i + 1\n while (end < len && raw[end] !== '\"') {\n if (raw[end] === '\\\\') end++ // skip escaped char\n end++\n }\n result += raw.slice(i, end + 1)\n i = end + 1\n continue\n }\n\n // Single-line comment\n if (raw[i] === '/' && raw[i + 1] === '/') {\n i += 2\n while (i < len && raw[i] !== '\\n') i++\n continue\n }\n\n // Block comment\n if (raw[i] === '/' && raw[i + 1] === '*') {\n i += 2\n while (i < len && !(raw[i] === '*' && raw[i + 1] === '/')) i++\n i += 2 // skip closing */\n continue\n }\n\n result += raw[i]\n i++\n }\n\n return result\n}\n\nexport class JsoncLoader implements Loader {\n name = 'jsonc'\n kind = 'data' as const\n extensions = ['.jsonc']\n\n async load(filePath: string): Promise<LoaderResult> {\n const raw = await readFile(filePath, 'utf-8')\n try {\n const stripped = stripComments(raw)\n const data = JSON.parse(stripped)\n return { data }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new LoaderError(message, filePath, 'JSONC')\n }\n }\n}\n","/**\n * Markdown loader.\n *\n * Uses gray-matter to extract YAML frontmatter and body content.\n * Rendering is NOT done here — it's deferred to ContentEntry.render().\n */\n\nimport { readFile } from 'fs/promises'\nimport matter from 'gray-matter'\nimport { parse as parseYaml } from 'yaml'\nimport { LoaderError } from './errors'\nimport type { Loader, LoaderResult } from './types'\n\nexport class MarkdownLoader implements Loader {\n name = 'markdown'\n kind = 'markdown' as const\n extensions = ['.md']\n\n async load(filePath: string): Promise<LoaderResult> {\n const raw = await readFile(filePath, 'utf-8')\n try {\n const { data, content } = matter(raw, { engines: { yaml: parseYaml } })\n return { data, content }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new LoaderError(message, filePath, 'Markdown')\n }\n }\n}\n","/**\n * TOML loader.\n */\n\nimport { readFile } from 'fs/promises'\nimport { parse } from 'smol-toml'\nimport { LoaderError } from './errors'\nimport type { Loader, LoaderResult } from './types'\n\nexport class TomlLoader implements Loader {\n name = 'toml'\n kind = 'data' as const\n extensions = ['.toml']\n\n async load(filePath: string): Promise<LoaderResult> {\n const raw = await readFile(filePath, 'utf-8')\n try {\n const data = parse(raw)\n return { data }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new LoaderError(message, filePath, 'TOML')\n }\n }\n}\n","/**\n * YAML loader.\n */\n\nimport { readFile } from 'fs/promises'\nimport { parse } from 'yaml'\nimport { LoaderError } from './errors'\nimport type { Loader, LoaderResult } from './types'\n\nexport class YamlLoader implements Loader {\n name = 'yaml'\n kind = 'data' as const\n extensions = ['.yaml', '.yml']\n\n async load(filePath: string): Promise<LoaderResult> {\n const raw = await readFile(filePath, 'utf-8')\n try {\n const data = parse(raw) ?? {}\n return { data }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n const line =\n err != null && typeof err === 'object' && 'linePos' in err\n ? (err as any).linePos?.[0]?.line\n : undefined\n throw new LoaderError(message, filePath, 'YAML', line)\n }\n }\n}\n","/**\n * Loader registry — resolves loader type strings to Loader instances.\n */\n\nexport { JsonLoader } from './json'\nexport { JsoncLoader } from './jsonc'\nexport { LoaderError } from './errors'\nexport { MarkdownLoader } from './markdown'\nexport { TomlLoader } from './toml'\nexport type { Loader, LoaderResult, LoaderType } from './types'\nexport { YamlLoader } from './yaml'\n\nimport { JsonLoader } from './json'\nimport { JsoncLoader } from './jsonc'\nimport { MarkdownLoader } from './markdown'\nimport { TomlLoader } from './toml'\nimport type { Loader, LoaderType } from './types'\nimport { YamlLoader } from './yaml'\n\n/** Singleton loader instances (loaders are stateless). */\nconst markdownLoader = new MarkdownLoader()\nconst jsonLoader = new JsonLoader()\nconst jsoncLoader = new JsoncLoader()\nconst yamlLoader = new YamlLoader()\nconst tomlLoader = new TomlLoader()\n\n/** Custom loader registry for user-registered loaders. */\nconst customLoaders = new Map<string, Loader>()\n\n/** Register a custom loader by name. */\nexport function registerLoader(name: string, loader: Loader): void {\n customLoaders.set(name, loader)\n}\n\n/** Resolve a loader type string or custom Loader instance. */\nexport function resolveLoader(loaderOrType: LoaderType | Loader): Loader {\n if (typeof loaderOrType === 'object') return loaderOrType\n\n const custom = customLoaders.get(loaderOrType)\n if (custom) return custom\n\n switch (loaderOrType) {\n case 'markdown':\n return markdownLoader\n case 'json':\n case 'json5':\n return jsonLoader\n case 'jsonc':\n return jsoncLoader\n case 'yaml':\n return yamlLoader\n case 'toml':\n return tomlLoader\n default:\n throw new Error(`Unknown loader type: ${loaderOrType as string}`)\n }\n}\n\n/** Get default include glob patterns for a loader. */\nexport function defaultIncludePatterns(loader: Loader): string[] {\n return loader.extensions.map((ext) => `**/*${ext}`)\n}\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { r as MarkdownConfig } from "../heading-
|
|
2
|
-
import { n as processMarkdown, t as MarkdownResult } from "../index-
|
|
1
|
+
import { r as MarkdownConfig } from "../heading-BpDXnl-7.mjs";
|
|
2
|
+
import { n as processMarkdown, t as MarkdownResult } from "../index-CbOKbkjJ.mjs";
|
|
3
3
|
export { MarkdownConfig, MarkdownResult, processMarkdown };
|
package/dist/markdown/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as processMarkdown } from "../markdown-
|
|
1
|
+
import { t as processMarkdown } from "../markdown-CyrHoDhP.mjs";
|
|
2
2
|
export { processMarkdown };
|
|
@@ -17,6 +17,17 @@ import remarkSmartypants from "remark-smartypants";
|
|
|
17
17
|
import { unified } from "unified";
|
|
18
18
|
//#region src/markdown/pipeline.ts
|
|
19
19
|
const DEFAULT_MARKDOWN_CONFIG = {};
|
|
20
|
+
/** Default language aliases for fenced code blocks that Shiki doesn't recognize natively. */
|
|
21
|
+
const DEFAULT_LANG_ALIASES = {
|
|
22
|
+
dot: "text",
|
|
23
|
+
mermaid: "text",
|
|
24
|
+
plantuml: "text",
|
|
25
|
+
excalidraw: "json",
|
|
26
|
+
drawio: "xml",
|
|
27
|
+
proto: "protobuf",
|
|
28
|
+
ejs: "html",
|
|
29
|
+
hbs: "handlebars"
|
|
30
|
+
};
|
|
20
31
|
function getTextContent(node) {
|
|
21
32
|
if (node.type === "text") return node.value || "";
|
|
22
33
|
if (node.children) return node.children.map(getTextContent).join("");
|
|
@@ -34,7 +45,19 @@ function createProcessor(config) {
|
|
|
34
45
|
const processor = unified().use(remarkParse).use(remarkGfm).use(remarkMath).use(remarkFrontmatter, ["yaml"]).use(remarkGithubAlerts).use(remarkSmartypants);
|
|
35
46
|
if (config.remarkPlugins) for (const plugin of config.remarkPlugins) if (Array.isArray(plugin)) processor.use(plugin[0], plugin[1]);
|
|
36
47
|
else processor.use(plugin);
|
|
48
|
+
const langAlias = {
|
|
49
|
+
...DEFAULT_LANG_ALIASES,
|
|
50
|
+
...config.shiki?.langAlias
|
|
51
|
+
};
|
|
52
|
+
processor.use(() => (tree) => {
|
|
53
|
+
const visit = (node) => {
|
|
54
|
+
if (node?.type === "code" && typeof node.lang === "string" && langAlias[node.lang]) node.lang = langAlias[node.lang];
|
|
55
|
+
if (Array.isArray(node?.children)) for (const child of node.children) visit(child);
|
|
56
|
+
};
|
|
57
|
+
visit(tree);
|
|
58
|
+
});
|
|
37
59
|
processor.use(remarkRehype, { allowDangerousHtml: true });
|
|
60
|
+
processor.use(rehypeMathjax);
|
|
38
61
|
const lightTheme = config.shiki?.themes?.light || "github-light";
|
|
39
62
|
const darkTheme = config.shiki?.themes?.dark || "github-dark";
|
|
40
63
|
processor.use(rehypeExpressiveCode, {
|
|
@@ -49,7 +72,7 @@ function createProcessor(config) {
|
|
|
49
72
|
borderColor: "var(--ps-color-border-subtle, var(--color-border-subtle, #e5e7eb))"
|
|
50
73
|
}
|
|
51
74
|
});
|
|
52
|
-
processor.use(
|
|
75
|
+
processor.use(rehypeSlug).use(rehypeAutolinkHeadings, { behavior: "wrap" }).use(rehypeExternalLinks, {
|
|
53
76
|
target: "_blank",
|
|
54
77
|
rel: ["noopener", "noreferrer"]
|
|
55
78
|
}).use(rehypeAccessibleEmojis);
|
|
@@ -76,20 +99,25 @@ async function processMarkdown(raw, config, preExtracted) {
|
|
|
76
99
|
content = parsed.content;
|
|
77
100
|
}
|
|
78
101
|
const resolvedConfig = config && Object.keys(config).length > 0 ? config : DEFAULT_MARKDOWN_CONFIG;
|
|
102
|
+
if (Object.isFrozen(resolvedConfig) === false) Object.freeze(resolvedConfig);
|
|
79
103
|
let processor = processorCache.get(resolvedConfig);
|
|
80
104
|
if (!processor) {
|
|
81
105
|
processor = createProcessor(resolvedConfig);
|
|
82
106
|
processorCache.set(resolvedConfig, processor);
|
|
83
107
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
108
|
+
try {
|
|
109
|
+
const result = await processor.process(content);
|
|
110
|
+
const headings = Array.isArray(result.data.headings) ? result.data.headings : [];
|
|
111
|
+
return {
|
|
112
|
+
html: String(result),
|
|
113
|
+
headings,
|
|
114
|
+
frontmatter
|
|
115
|
+
};
|
|
116
|
+
} catch (err) {
|
|
117
|
+
throw new Error(`Markdown processing failed: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
118
|
+
}
|
|
91
119
|
}
|
|
92
120
|
//#endregion
|
|
93
121
|
export { processMarkdown as t };
|
|
94
122
|
|
|
95
|
-
//# sourceMappingURL=markdown-
|
|
123
|
+
//# sourceMappingURL=markdown-CyrHoDhP.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-CyrHoDhP.mjs","names":["parseYaml"],"sources":["../src/markdown/pipeline.ts"],"sourcesContent":["import matter from 'gray-matter'\nimport { parse as parseYaml } from 'yaml'\nimport { rehypeAccessibleEmojis } from 'rehype-accessible-emojis'\nimport rehypeAutolinkHeadings from 'rehype-autolink-headings'\nimport rehypeExpressiveCode, {\n type BundledShikiTheme,\n type RehypeExpressiveCodeOptions,\n} from 'rehype-expressive-code'\nimport rehypeExternalLinks from 'rehype-external-links'\nimport rehypeMathjax from 'rehype-mathjax/svg'\nimport rehypeSlug from 'rehype-slug'\nimport rehypeStringify from 'rehype-stringify'\nimport remarkFrontmatter from 'remark-frontmatter'\nimport remarkGfm from 'remark-gfm'\nimport remarkGithubAlerts from 'remark-github-alerts'\nimport remarkMath from 'remark-math'\nimport remarkParse from 'remark-parse'\nimport remarkRehype from 'remark-rehype'\nimport remarkSmartypants from 'remark-smartypants'\nimport { unified } from 'unified'\nimport type { Heading } from '../schemas/heading'\nimport type { MarkdownConfig } from '../schemas/markdown-config'\n\nexport type MarkdownResult = {\n html: string\n headings: Heading[]\n frontmatter: Record<string, unknown>\n}\n\nexport type { MarkdownConfig }\n\nconst DEFAULT_MARKDOWN_CONFIG: MarkdownConfig = {}\n\n/** Default language aliases for fenced code blocks that Shiki doesn't recognize natively. */\nconst DEFAULT_LANG_ALIASES: Record<string, string> = {\n dot: 'text',\n mermaid: 'text',\n plantuml: 'text',\n excalidraw: 'json',\n drawio: 'xml',\n proto: 'protobuf',\n ejs: 'html',\n hbs: 'handlebars',\n}\n\nfunction getTextContent(node: any): string {\n if (node.type === 'text') return node.value || ''\n if (node.children) return node.children.map(getTextContent).join('')\n return ''\n}\n\nfunction extractHeadings(tree: any, headings: Heading[]): void {\n if (tree.type === 'element' && /^h[1-6]$/.test(tree.tagName)) {\n headings.push({\n depth: parseInt(tree.tagName[1]),\n text: getTextContent(tree),\n slug: tree.properties?.id || '',\n })\n }\n if (tree.children) {\n for (const child of tree.children) {\n extractHeadings(child, headings)\n }\n }\n}\n\nfunction createProcessor(config: MarkdownConfig) {\n const processor = unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkMath)\n .use(remarkFrontmatter, ['yaml'])\n // GitHub-flavored alerts: > [!NOTE], > [!TIP], > [!IMPORTANT], > [!WARNING], > [!CAUTION]\n .use(remarkGithubAlerts)\n // Smart typography: \"smart quotes\", em—dashes, el…lipses\n .use(remarkSmartypants)\n\n if (config.remarkPlugins) {\n for (const plugin of config.remarkPlugins) {\n if (Array.isArray(plugin)) processor.use(plugin[0], plugin[1])\n else processor.use(plugin)\n }\n }\n\n // Apply language aliases to fenced code blocks before Expressive Code processes them.\n // Merge defaults with user-provided aliases (user overrides take precedence).\n const langAlias = { ...DEFAULT_LANG_ALIASES, ...config.shiki?.langAlias }\n processor.use(() => (tree: any) => {\n const visit = (node: any): void => {\n if (node?.type === 'code' && typeof node.lang === 'string' && langAlias[node.lang]) {\n node.lang = langAlias[node.lang]\n }\n if (Array.isArray(node?.children)) {\n for (const child of node.children) visit(child)\n }\n }\n visit(tree)\n })\n\n processor.use(remarkRehype, { allowDangerousHtml: true })\n\n // MathJax must run before Expressive Code so that math elements (from remark-math)\n // are rendered to SVG before Expressive Code tries to highlight them as code blocks.\n processor.use(rehypeMathjax)\n\n // Expressive Code — syntax highlighting, code frames, tabs, copy button\n const lightTheme = (config.shiki?.themes?.light || 'github-light') as BundledShikiTheme\n const darkTheme = (config.shiki?.themes?.dark || 'github-dark') as BundledShikiTheme\n\n processor.use(rehypeExpressiveCode, {\n themes: [darkTheme, lightTheme],\n useDarkModeMediaQuery: true,\n styleOverrides: {\n uiFontFamily: 'var(--ps-font-sans, var(--font-family, system-ui, sans-serif))',\n codeFontFamily: 'var(--ps-font-mono, var(--font-mono, ui-monospace, monospace))',\n codeFontSize: 'var(--ps-font-size-sm, 0.875rem)',\n codeLineHeight: '1.7',\n borderRadius: 'var(--ps-radius-lg, 0.5rem)',\n borderColor: 'var(--ps-color-border-subtle, var(--color-border-subtle, #e5e7eb))',\n },\n } satisfies RehypeExpressiveCodeOptions)\n\n processor\n .use(rehypeSlug)\n .use(rehypeAutolinkHeadings, { behavior: 'wrap' })\n // External links: add target=\"_blank\" rel=\"noopener noreferrer\" to absolute URLs\n .use(rehypeExternalLinks, {\n target: '_blank',\n rel: ['noopener', 'noreferrer'],\n })\n // Accessible emojis: wrap emoji characters in <span role=\"img\" aria-label=\"...\">\n .use(rehypeAccessibleEmojis)\n\n processor.use(() => (tree: any, file: any) => {\n const headings: Heading[] = []\n extractHeadings(tree, headings)\n file.data.headings = headings\n })\n\n if (config.rehypePlugins) {\n for (const plugin of config.rehypePlugins) {\n if (Array.isArray(plugin)) processor.use(plugin[0], plugin[1])\n else processor.use(plugin)\n }\n }\n\n processor.use(rehypeStringify, { allowDangerousHtml: true })\n return processor\n}\n\nconst processorCache = new WeakMap<MarkdownConfig, ReturnType<typeof createProcessor>>()\n\nexport async function processMarkdown(\n raw: string,\n config?: MarkdownConfig,\n preExtracted?: { content: string; frontmatter: Record<string, unknown> },\n): Promise<MarkdownResult> {\n let frontmatter: Record<string, unknown>\n let content: string\n if (preExtracted) {\n frontmatter = preExtracted.frontmatter\n content = preExtracted.content\n } else {\n const parsed = matter(raw, { engines: { yaml: parseYaml } })\n frontmatter = parsed.data\n content = parsed.content\n }\n const resolvedConfig = config && Object.keys(config).length > 0 ? config : DEFAULT_MARKDOWN_CONFIG\n // Freeze to prevent mutation — the processor is cached by object reference.\n if (Object.isFrozen(resolvedConfig) === false) Object.freeze(resolvedConfig)\n let processor = processorCache.get(resolvedConfig)\n if (!processor) {\n processor = createProcessor(resolvedConfig)\n processorCache.set(resolvedConfig, processor)\n }\n try {\n const result = await processor.process(content)\n const headings = Array.isArray(result.data.headings) ? (result.data.headings as Heading[]) : []\n return { html: String(result), headings, frontmatter }\n } catch (err) {\n throw new Error(\n `Markdown processing failed: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n )\n }\n}\n"],"mappings":"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"}
|
package/dist/schemas/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as RawEntry, i as CollectionDef, n as ContentPlugin, t as ContentLayerConfig } from "../content-config-
|
|
2
|
-
import { i as MarkdownConfigSchema, n as HeadingSchema, r as MarkdownConfig, t as Heading } from "../heading-
|
|
3
|
-
import { a as ProjectFrontmatter, i as BlogFrontmatterSchema, n as BaseFrontmatterSchema, o as ProjectFrontmatterSchema, r as BlogFrontmatter, t as BaseFrontmatter } from "../index-
|
|
1
|
+
import { c as RawEntry, i as CollectionDef, n as ContentPlugin, t as ContentLayerConfig } from "../content-config-Bfe4W9us.mjs";
|
|
2
|
+
import { i as MarkdownConfigSchema, n as HeadingSchema, r as MarkdownConfig, t as Heading } from "../heading-BpDXnl-7.mjs";
|
|
3
|
+
import { a as ProjectFrontmatter, i as BlogFrontmatterSchema, n as BaseFrontmatterSchema, o as ProjectFrontmatterSchema, r as BlogFrontmatter, t as BaseFrontmatter } from "../index-BBYkDxwI.mjs";
|
|
4
4
|
export { BaseFrontmatter, BaseFrontmatterSchema, BlogFrontmatter, BlogFrontmatterSchema, CollectionDef, ContentLayerConfig, ContentPlugin, Heading, HeadingSchema, MarkdownConfig, MarkdownConfigSchema, ProjectFrontmatter, ProjectFrontmatterSchema, RawEntry };
|
package/dist/schemas/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as ProjectFrontmatterSchema, i as BlogFrontmatterSchema, n as HeadingSchema, r as BaseFrontmatterSchema, t as MarkdownConfigSchema } from "../schemas-
|
|
1
|
+
import { a as ProjectFrontmatterSchema, i as BlogFrontmatterSchema, n as HeadingSchema, r as BaseFrontmatterSchema, t as MarkdownConfigSchema } from "../schemas-UL4ynWsA.mjs";
|
|
2
2
|
export { BaseFrontmatterSchema, BlogFrontmatterSchema, HeadingSchema, MarkdownConfigSchema, ProjectFrontmatterSchema };
|
|
@@ -4,8 +4,8 @@ const BaseFrontmatterSchema = z.object({
|
|
|
4
4
|
title: z.string(),
|
|
5
5
|
description: z.string(),
|
|
6
6
|
publishedDate: z.coerce.date(),
|
|
7
|
-
lastUpdatedOn: z.coerce.date(),
|
|
8
|
-
tags: z.array(z.string()).
|
|
7
|
+
lastUpdatedOn: z.coerce.date().optional(),
|
|
8
|
+
tags: z.array(z.string()).default([]),
|
|
9
9
|
draft: z.boolean().optional().default(false)
|
|
10
10
|
}).passthrough();
|
|
11
11
|
const ProjectFrontmatterSchema = BaseFrontmatterSchema.extend({
|
|
@@ -44,4 +44,4 @@ const MarkdownConfigSchema = z.object({
|
|
|
44
44
|
//#endregion
|
|
45
45
|
export { ProjectFrontmatterSchema as a, BlogFrontmatterSchema as i, HeadingSchema as n, BaseFrontmatterSchema as r, MarkdownConfigSchema as t };
|
|
46
46
|
|
|
47
|
-
//# sourceMappingURL=schemas-
|
|
47
|
+
//# sourceMappingURL=schemas-UL4ynWsA.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas-UL4ynWsA.mjs","names":[],"sources":["../src/schemas/frontmatter.ts","../src/schemas/heading.ts","../src/schemas/markdown-config.ts"],"sourcesContent":["import { z } from 'zod'\n\n// ── Base frontmatter (required for all content items) ──\n\nexport const BaseFrontmatterSchema = z\n .object({\n title: z.string(),\n description: z.string(),\n publishedDate: z.coerce.date(),\n lastUpdatedOn: z.coerce.date().optional(),\n tags: z.array(z.string()).default([]),\n draft: z.boolean().optional().default(false),\n })\n .passthrough()\n\nexport type BaseFrontmatter = z.infer<typeof BaseFrontmatterSchema>\n\n// ── Project frontmatter (extends base with project-specific fields) ──\n\nexport const ProjectFrontmatterSchema = BaseFrontmatterSchema.extend({\n gitRepo: z.string().url().optional(),\n links: z\n .array(\n z.object({\n url: z.string().url(),\n text: z.string(),\n }),\n )\n .optional(),\n})\n\nexport type ProjectFrontmatter = z.infer<typeof ProjectFrontmatterSchema>\n\n// ── Blog frontmatter (extends base with blog-specific fields) ──\n\nexport const BlogFrontmatterSchema = BaseFrontmatterSchema.extend({\n category: z.string().optional(),\n featured: z.boolean().optional(),\n coverImage: z.string().optional(),\n})\n\nexport type BlogFrontmatter = z.infer<typeof BlogFrontmatterSchema>\n","import { z } from 'zod'\n\n// ── Heading (extracted from markdown) ──\n\nexport const HeadingSchema = z.object({\n depth: z.number(),\n text: z.string(),\n slug: z.string(),\n})\n\nexport type Heading = z.infer<typeof HeadingSchema>\n","import { z } from 'zod'\n\n// ── Markdown config ──\n\nexport const MarkdownConfigSchema = z.object({\n remarkPlugins: z.array(z.any()).optional(),\n rehypePlugins: z.array(z.any()).optional(),\n shiki: z\n .object({\n themes: z.object({\n light: z.string(),\n dark: z.string(),\n }),\n langAlias: z.record(z.string(), z.string()).optional(),\n defaultShowLineNumbers: z.boolean().optional(),\n })\n .optional(),\n})\n\nexport type MarkdownConfig = z.infer<typeof MarkdownConfigSchema>\n"],"mappings":";;AAIA,MAAa,wBAAwB,EAClC,OAAO;CACN,OAAO,EAAE,QAAQ;CACjB,aAAa,EAAE,QAAQ;CACvB,eAAe,EAAE,OAAO,MAAM;CAC9B,eAAe,EAAE,OAAO,MAAM,CAAC,UAAU;CACzC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC;CACrC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC,QAAQ,MAAM;CAC7C,CAAC,CACD,aAAa;AAMhB,MAAa,2BAA2B,sBAAsB,OAAO;CACnE,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,UAAU;CACpC,OAAO,EACJ,MACC,EAAE,OAAO;EACP,KAAK,EAAE,QAAQ,CAAC,KAAK;EACrB,MAAM,EAAE,QAAQ;EACjB,CAAC,CACH,CACA,UAAU;CACd,CAAC;AAMF,MAAa,wBAAwB,sBAAsB,OAAO;CAChE,UAAU,EAAE,QAAQ,CAAC,UAAU;CAC/B,UAAU,EAAE,SAAS,CAAC,UAAU;CAChC,YAAY,EAAE,QAAQ,CAAC,UAAU;CAClC,CAAC;;;ACnCF,MAAa,gBAAgB,EAAE,OAAO;CACpC,OAAO,EAAE,QAAQ;CACjB,MAAM,EAAE,QAAQ;CAChB,MAAM,EAAE,QAAQ;CACjB,CAAC;;;ACJF,MAAa,uBAAuB,EAAE,OAAO;CAC3C,eAAe,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,UAAU;CAC1C,eAAe,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,UAAU;CAC1C,OAAO,EACJ,OAAO;EACN,QAAQ,EAAE,OAAO;GACf,OAAO,EAAE,QAAQ;GACjB,MAAM,EAAE,QAAQ;GACjB,CAAC;EACF,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAAC,UAAU;EACtD,wBAAwB,EAAE,SAAS,CAAC,UAAU;EAC/C,CAAC,CACD,UAAU;CACd,CAAC"}
|
|
@@ -21,8 +21,8 @@ interface Loader {
|
|
|
21
21
|
/** File extensions this loader handles */
|
|
22
22
|
extensions: string[];
|
|
23
23
|
/** Parse raw file content into data + optional body */
|
|
24
|
-
load(filePath: string):
|
|
24
|
+
load(filePath: string): Promise<LoaderResult>;
|
|
25
25
|
}
|
|
26
26
|
//#endregion
|
|
27
27
|
export { LoaderResult as n, LoaderType as r, Loader as t };
|
|
28
|
-
//# sourceMappingURL=types-
|
|
28
|
+
//# sourceMappingURL=types-Cn52sdoq.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types-
|
|
1
|
+
{"version":3,"file":"types-Cn52sdoq.d.mts","names":[],"sources":["../src/loaders/types.ts"],"mappings":";;AAOA;;;;;KAAY,UAAA;AAAA,KACA,UAAA;AAAA,UAEK,YAAA;EAFK;EAIpB,IAAA,EAAM,MAAA;EAFS;EAIf,OAAA;AAAA;AAAA,UAGe,MAAA;EALf;EAOA,IAAA;EALA;EAOA,IAAA,EAAM,UAAA;EAPC;EASP,UAAA;EANqB;EAQrB,IAAA,CAAK,QAAA,WAAmB,OAAA,CAAQ,YAAA;AAAA"}
|
package/dist/vite/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { a as CollectionMap, i as CollectionDef, o as InferCollectionData, t as ContentLayerConfig } from "../content-config-
|
|
3
|
-
import { t as Heading } from "../heading-
|
|
2
|
+
import { a as CollectionMap, i as CollectionDef, o as InferCollectionData, t as ContentLayerConfig } from "../content-config-Bfe4W9us.mjs";
|
|
3
|
+
import { t as Heading } from "../heading-BpDXnl-7.mjs";
|
|
4
4
|
import * as http from "node:http";
|
|
5
5
|
import { Agent, ClientRequest, ClientRequestArgs, OutgoingHttpHeaders } from "node:http";
|
|
6
6
|
import { Http2SecureServer } from "node:http2";
|