@pagesmith/core 0.3.0 → 0.4.1
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/README.md +28 -4
- package/REFERENCE.md +163 -94
- package/dist/ai/index.d.mts +5 -3
- package/dist/ai/index.d.mts.map +1 -1
- package/dist/ai/index.mjs +300 -206
- package/dist/ai/index.mjs.map +1 -1
- package/dist/assets/index.d.mts +10 -1
- package/dist/assets/index.d.mts.map +1 -1
- package/dist/assets/index.mjs +2 -2
- package/dist/{assets-DXiWF_KI.mjs → assets-CAPOqQ_P.mjs} +42 -5
- package/dist/assets-CAPOqQ_P.mjs.map +1 -0
- package/dist/{content-config-Bfe4W9us.d.mts → content-config-Bu2HH0Yx.d.mts} +49 -17
- package/dist/{content-config-Bfe4W9us.d.mts.map → content-config-Bu2HH0Yx.d.mts.map} +1 -1
- package/dist/{content-layer-DPK1EmfY.mjs → content-layer-CJRrNpZ_.mjs} +192 -36
- package/dist/content-layer-CJRrNpZ_.mjs.map +1 -0
- package/dist/content-layer-Ckt08g2i.d.mts +122 -0
- package/dist/content-layer-Ckt08g2i.d.mts.map +1 -0
- package/dist/create/index.d.mts.map +1 -1
- package/dist/create/index.mjs +31 -30
- package/dist/create/index.mjs.map +1 -1
- package/dist/css/index.d.mts +1 -1
- package/dist/css/index.mjs +1 -1
- package/dist/css-CO3CBqxx.mjs +24 -0
- package/dist/css-CO3CBqxx.mjs.map +1 -0
- package/dist/heading-D4X2L4vd.d.mts +12 -0
- package/dist/heading-D4X2L4vd.d.mts.map +1 -0
- package/dist/{index-BBYkDxwI.d.mts → index-B4YZRIzb.d.mts} +1 -1
- package/dist/{index-BBYkDxwI.d.mts.map → index-B4YZRIzb.d.mts.map} +1 -1
- package/dist/{index-Bg9srb5U.d.mts → index-B7NRZAxd.d.mts} +1 -1
- package/dist/{index-Bg9srb5U.d.mts.map → index-B7NRZAxd.d.mts.map} +1 -1
- package/dist/{index-YXQxMV6J.d.mts → index-CryArLlX.d.mts} +2 -2
- package/dist/{index-YXQxMV6J.d.mts.map → index-CryArLlX.d.mts.map} +1 -1
- package/dist/{index-CbOKbkjJ.d.mts → index-D44syBt-.d.mts} +3 -2
- package/dist/index-D44syBt-.d.mts.map +1 -0
- package/dist/index.d.mts +16 -99
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +15 -11
- package/dist/index.mjs.map +1 -1
- package/dist/loaders/index.d.mts +2 -2
- package/dist/loaders/index.mjs +1 -1
- package/dist/{loaders-Cf-BXf2L.mjs → loaders-DnyWfANR.mjs} +3 -3
- package/dist/loaders-DnyWfANR.mjs.map +1 -0
- package/dist/markdown/index.d.mts +2 -2
- package/dist/markdown/index.mjs +1 -1
- package/dist/{markdown-CyrHoDhP.mjs → markdown-DMHd400a.mjs} +29 -2
- package/dist/markdown-DMHd400a.mjs.map +1 -0
- package/dist/{heading-BpDXnl-7.d.mts → markdown-config-CDvh5aJ-.d.mts} +2 -10
- package/dist/markdown-config-CDvh5aJ-.d.mts.map +1 -0
- package/dist/mcp/index.d.mts +23 -0
- package/dist/mcp/index.d.mts.map +1 -0
- package/dist/mcp/index.mjs +2 -0
- package/dist/mcp/server.d.mts +13 -0
- package/dist/mcp/server.d.mts.map +1 -0
- package/dist/mcp/server.mjs +2 -0
- package/dist/runtime/index.d.mts.map +1 -1
- package/dist/runtime/index.mjs +4 -9
- package/dist/runtime/index.mjs.map +1 -1
- package/dist/schemas/index.d.mts +4 -3
- package/dist/server-BZA_iSen.mjs +203 -0
- package/dist/server-BZA_iSen.mjs.map +1 -0
- package/dist/ssg-utils/index.d.mts +51 -0
- package/dist/ssg-utils/index.d.mts.map +1 -0
- package/dist/ssg-utils/index.mjs +119 -0
- package/dist/ssg-utils/index.mjs.map +1 -0
- package/dist/{types-Cn52sdoq.d.mts → types-B-V5qemH.d.mts} +1 -1
- package/dist/{types-Cn52sdoq.d.mts.map → types-B-V5qemH.d.mts.map} +1 -1
- package/dist/vite/index.d.mts +69 -34
- package/dist/vite/index.d.mts.map +1 -1
- package/dist/vite/index.mjs +296 -228
- package/dist/vite/index.mjs.map +1 -1
- package/docs/agents/AGENTS.md.template +29 -0
- package/docs/agents/changelog-notes.md +15 -0
- package/docs/agents/errors.md +150 -0
- package/docs/agents/migration.md +25 -0
- package/docs/agents/recipes.md +50 -0
- package/docs/agents/usage.md +119 -0
- package/docs/llms-full.txt +111 -0
- package/docs/llms.txt +68 -0
- package/package.json +57 -4
- package/dist/assets-DXiWF_KI.mjs.map +0 -1
- package/dist/content-layer-DPK1EmfY.mjs.map +0 -1
- package/dist/css-BneO430t.mjs +0 -20
- package/dist/css-BneO430t.mjs.map +0 -1
- package/dist/heading-BpDXnl-7.d.mts.map +0 -1
- package/dist/index-CbOKbkjJ.d.mts.map +0 -1
- package/dist/loaders-Cf-BXf2L.mjs.map +0 -1
- package/dist/markdown-CyrHoDhP.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { t as processMarkdown } from "./markdown-
|
|
2
|
-
import { a as linkValidator,
|
|
3
|
-
import { a as TomlLoader, c as JsonLoader, i as YamlLoader, n as registerLoader, o as MarkdownLoader, s as JsoncLoader } from "./loaders-
|
|
1
|
+
import { t as processMarkdown } from "./markdown-DMHd400a.mjs";
|
|
2
|
+
import { a as linkValidator, c as validateSchema, d as convert, i as createLinkValidator, n as builtinMarkdownValidators, o as headingValidator, r as runValidators, s as codeBlockValidator, t as createContentLayer, u as ContentEntry } from "./content-layer-CJRrNpZ_.mjs";
|
|
3
|
+
import { a as TomlLoader, c as JsonLoader, i as YamlLoader, n as registerLoader, o as MarkdownLoader, s as JsoncLoader } from "./loaders-DnyWfANR.mjs";
|
|
4
4
|
import { Fragment, HtmlString, h } from "./jsx-runtime/index.mjs";
|
|
5
|
-
import { t as buildCss } from "./css-
|
|
5
|
+
import { t as buildCss } from "./css-CO3CBqxx.mjs";
|
|
6
6
|
import { a as ProjectFrontmatterSchema, i as BlogFrontmatterSchema, n as HeadingSchema, r as BaseFrontmatterSchema, t as MarkdownConfigSchema } from "./schemas-UL4ynWsA.mjs";
|
|
7
|
-
import { getAiArtifactContent, getAiArtifacts, installAiArtifacts } from "./ai/index.mjs";
|
|
8
7
|
import matter from "gray-matter";
|
|
9
8
|
import { parse } from "yaml";
|
|
10
9
|
import { z } from "zod";
|
|
@@ -37,16 +36,21 @@ function extractFrontmatter(raw) {
|
|
|
37
36
|
content
|
|
38
37
|
};
|
|
39
38
|
}
|
|
40
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* Validate frontmatter against a Zod schema. Returns parsed data or errors.
|
|
41
|
+
*
|
|
42
|
+
* @deprecated Use `validateSchema()` from `@pagesmith/core` for richer
|
|
43
|
+
* validation results including field paths and severity levels.
|
|
44
|
+
*/
|
|
41
45
|
function validateFrontmatter(frontmatter, schema) {
|
|
42
|
-
const
|
|
43
|
-
if (
|
|
46
|
+
const { issues, validatedData } = validateSchema(frontmatter, schema);
|
|
47
|
+
if (issues.length === 0) return {
|
|
44
48
|
success: true,
|
|
45
|
-
data:
|
|
49
|
+
data: validatedData
|
|
46
50
|
};
|
|
47
51
|
return {
|
|
48
52
|
success: false,
|
|
49
|
-
errors:
|
|
53
|
+
errors: issues.map((issue) => issue.field ? `${issue.field}: ${issue.message}` : issue.message)
|
|
50
54
|
};
|
|
51
55
|
}
|
|
52
56
|
//#endregion
|
|
@@ -74,6 +78,6 @@ function extractToc(html) {
|
|
|
74
78
|
return headings;
|
|
75
79
|
}
|
|
76
80
|
//#endregion
|
|
77
|
-
export { BaseFrontmatterSchema, BlogFrontmatterSchema, ContentEntry, Fragment, HeadingSchema, HtmlString, JsonLoader, JsoncLoader, MarkdownConfigSchema, MarkdownLoader, ProjectFrontmatterSchema, TomlLoader, YamlLoader, buildCss, builtinMarkdownValidators, codeBlockValidator, convert, createContentLayer, createLinkValidator, defineCollection, defineCollections, defineConfig, extractFrontmatter, extractToc,
|
|
81
|
+
export { BaseFrontmatterSchema, BlogFrontmatterSchema, ContentEntry, Fragment, HeadingSchema, HtmlString, JsonLoader, JsoncLoader, MarkdownConfigSchema, MarkdownLoader, ProjectFrontmatterSchema, TomlLoader, YamlLoader, buildCss, builtinMarkdownValidators, codeBlockValidator, convert, createContentLayer, createLinkValidator, defineCollection, defineCollections, defineConfig, extractFrontmatter, extractToc, h, headingValidator, linkValidator, processMarkdown, registerLoader, runValidators, validateFrontmatter, z };
|
|
78
82
|
|
|
79
83
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["parseYaml"],"sources":["../src/config.ts","../src/frontmatter.ts","../src/toc.ts"],"sourcesContent":["/**\n * Configuration helpers.\n *\n * defineConfig() and defineCollection() are type-safe identity functions\n * that provide TypeScript inference for collection schemas.\n */\n\nimport type { z } from 'zod'\nimport type { CollectionComputed, CollectionDef, CollectionMap } from './schemas/collection'\nimport type { Loader, LoaderType } from './loaders/types'\nimport type { ContentLayerConfig } from './schemas/content-config'\n\n/** Define a content layer configuration with type inference. */\nexport function defineConfig(config: ContentLayerConfig): ContentLayerConfig {\n return config\n}\n\n/** Define a collection with Zod schema type inference. */\nexport function defineCollection<\n const S extends z.ZodType,\n const TComputed extends CollectionComputed = {},\n const TLoader extends LoaderType | Loader = LoaderType | Loader,\n>(\n def: Omit<CollectionDef<S, TComputed, TLoader>, 'computed'> & {\n computed?: TComputed & CollectionComputed\n },\n): CollectionDef<S, TComputed, TLoader> {\n return def\n}\n\n/** Define a named collection map with strong literal inference. */\nexport function defineCollections<const TCollections extends CollectionMap>(\n collections: TCollections,\n): TCollections {\n return collections\n}\n","/**\n * Frontmatter extraction and validation.\n *\n * Uses gray-matter to parse YAML frontmatter from markdown,\n * and optionally validates against a Zod schema.\n */\n\nimport matter from 'gray-matter'\nimport { parse as parseYaml } from 'yaml'\nimport type { ZodSchema } from 'zod'\n\nexport type FrontmatterResult = {\n frontmatter: Record<string, any>\n content: string\n}\n\n/** Extract frontmatter from raw markdown using gray-matter. */\nexport function extractFrontmatter(raw: string): FrontmatterResult {\n const { data, content } = matter(raw, { engines: { yaml: parseYaml } })\n return { frontmatter: data, content }\n}\n\n
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["parseYaml"],"sources":["../src/config.ts","../src/frontmatter.ts","../src/toc.ts"],"sourcesContent":["/**\n * Configuration helpers.\n *\n * defineConfig() and defineCollection() are type-safe identity functions\n * that provide TypeScript inference for collection schemas.\n */\n\nimport type { z } from 'zod'\nimport type { CollectionComputed, CollectionDef, CollectionMap } from './schemas/collection'\nimport type { Loader, LoaderType } from './loaders/types'\nimport type { ContentLayerConfig } from './schemas/content-config'\n\n/** Define a content layer configuration with type inference. */\nexport function defineConfig(config: ContentLayerConfig): ContentLayerConfig {\n return config\n}\n\n/** Define a collection with Zod schema type inference. */\nexport function defineCollection<\n const S extends z.ZodType,\n const TComputed extends CollectionComputed = {},\n const TLoader extends LoaderType | Loader = LoaderType | Loader,\n>(\n def: Omit<CollectionDef<S, TComputed, TLoader>, 'computed'> & {\n computed?: TComputed & CollectionComputed\n },\n): CollectionDef<S, TComputed, TLoader> {\n return def\n}\n\n/** Define a named collection map with strong literal inference. */\nexport function defineCollections<const TCollections extends CollectionMap>(\n collections: TCollections,\n): TCollections {\n return collections\n}\n","/**\n * Frontmatter extraction and validation.\n *\n * Uses gray-matter to parse YAML frontmatter from markdown,\n * and optionally validates against a Zod schema.\n */\n\nimport matter from 'gray-matter'\nimport { parse as parseYaml } from 'yaml'\nimport type { ZodSchema } from 'zod'\nimport { validateSchema } from './validation/schema-validator'\n\nexport type FrontmatterResult = {\n frontmatter: Record<string, any>\n content: string\n}\n\n/** Extract frontmatter from raw markdown using gray-matter. */\nexport function extractFrontmatter(raw: string): FrontmatterResult {\n const { data, content } = matter(raw, { engines: { yaml: parseYaml } })\n return { frontmatter: data, content }\n}\n\n/**\n * Validate frontmatter against a Zod schema. Returns parsed data or errors.\n *\n * @deprecated Use `validateSchema()` from `@pagesmith/core` for richer\n * validation results including field paths and severity levels.\n */\nexport function validateFrontmatter<T>(\n frontmatter: Record<string, any>,\n schema: ZodSchema<T>,\n): { success: true; data: T } | { success: false; errors: string[] } {\n const { issues, validatedData } = validateSchema(frontmatter, schema)\n\n if (issues.length === 0) {\n return { success: true, data: validatedData as T }\n }\n\n const errors = issues.map((issue) =>\n issue.field ? `${issue.field}: ${issue.message}` : issue.message,\n )\n return { success: false, errors }\n}\n","import type { Heading } from './schemas/heading'\n\n/**\n * Extract table of contents headings from an HTML string.\n *\n * Regex-based: finds <h[1-6] id=\"...\">text</h[1-6]>, strips inner HTML tags.\n * No dependency on unified — works on any HTML string.\n */\nexport function extractToc(html: string): Heading[] {\n const headings: Heading[] = []\n const re = /<h([1-6])\\s+id=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/h\\1>/gi\n let match: RegExpExecArray | null\n\n while ((match = re.exec(html)) !== null) {\n const depth = parseInt(match[1], 10)\n const slug = match[2]\n // Strip inner HTML tags to get plain text\n const text = match[3].replace(/<[^>]+>/g, '').trim()\n headings.push({ depth, text, slug })\n }\n\n return headings\n}\n"],"mappings":";;;;;;;;;;;AAaA,SAAgB,aAAa,QAAgD;AAC3E,QAAO;;;AAIT,SAAgB,iBAKd,KAGsC;AACtC,QAAO;;;AAIT,SAAgB,kBACd,aACc;AACd,QAAO;;;;;;;;;;;AChBT,SAAgB,mBAAmB,KAAgC;CACjE,MAAM,EAAE,MAAM,YAAY,OAAO,KAAK,EAAE,SAAS,EAAE,MAAMA,OAAW,EAAE,CAAC;AACvE,QAAO;EAAE,aAAa;EAAM;EAAS;;;;;;;;AASvC,SAAgB,oBACd,aACA,QACmE;CACnE,MAAM,EAAE,QAAQ,kBAAkB,eAAe,aAAa,OAAO;AAErE,KAAI,OAAO,WAAW,EACpB,QAAO;EAAE,SAAS;EAAM,MAAM;EAAoB;AAMpD,QAAO;EAAE,SAAS;EAAO,QAHV,OAAO,KAAK,UACzB,MAAM,QAAQ,GAAG,MAAM,MAAM,IAAI,MAAM,YAAY,MAAM,QAC1D;EACgC;;;;;;;;;;AClCnC,SAAgB,WAAW,MAAyB;CAClD,MAAM,WAAsB,EAAE;CAC9B,MAAM,KAAK;CACX,IAAI;AAEJ,SAAQ,QAAQ,GAAG,KAAK,KAAK,MAAM,MAAM;EACvC,MAAM,QAAQ,SAAS,MAAM,IAAI,GAAG;EACpC,MAAM,OAAO,MAAM;EAEnB,MAAM,OAAO,MAAM,GAAG,QAAQ,YAAY,GAAG,CAAC,MAAM;AACpD,WAAS,KAAK;GAAE;GAAO;GAAM;GAAM,CAAC;;AAGtC,QAAO"}
|
package/dist/loaders/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as LoaderResult, r as LoaderType, t as Loader } from "../types-
|
|
2
|
-
import { a as TomlLoader, c as JsoncLoader, i as YamlLoader, l as JsonLoader, n as registerLoader, o as MarkdownLoader, r as resolveLoader, s as LoaderError, t as defaultIncludePatterns } from "../index-
|
|
1
|
+
import { n as LoaderResult, r as LoaderType, t as Loader } from "../types-B-V5qemH.mjs";
|
|
2
|
+
import { a as TomlLoader, c as JsoncLoader, i as YamlLoader, l as JsonLoader, n as registerLoader, o as MarkdownLoader, r as resolveLoader, s as LoaderError, t as defaultIncludePatterns } from "../index-CryArLlX.mjs";
|
|
3
3
|
export { JsonLoader, JsoncLoader, Loader, LoaderError, LoaderResult, LoaderType, MarkdownLoader, TomlLoader, YamlLoader, defaultIncludePatterns, registerLoader, resolveLoader };
|
package/dist/loaders/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as TomlLoader, c as JsonLoader, i as YamlLoader, l as LoaderError, n as registerLoader, o as MarkdownLoader, r as resolveLoader, s as JsoncLoader, t as defaultIncludePatterns } from "../loaders-
|
|
1
|
+
import { a as TomlLoader, c as JsonLoader, i as YamlLoader, l as LoaderError, n as registerLoader, o as MarkdownLoader, r as resolveLoader, s as JsoncLoader, t as defaultIncludePatterns } from "../loaders-DnyWfANR.mjs";
|
|
2
2
|
export { JsonLoader, JsoncLoader, LoaderError, MarkdownLoader, TomlLoader, YamlLoader, defaultIncludePatterns, registerLoader, resolveLoader };
|
|
@@ -86,8 +86,8 @@ var JsoncLoader = class {
|
|
|
86
86
|
async load(filePath) {
|
|
87
87
|
const raw = await readFile(filePath, "utf-8");
|
|
88
88
|
try {
|
|
89
|
-
const
|
|
90
|
-
return { data: JSON.parse(
|
|
89
|
+
const withoutTrailingCommas = stripComments(raw).replace(/,\s*([}\]])/g, "$1");
|
|
90
|
+
return { data: JSON.parse(withoutTrailingCommas) };
|
|
91
91
|
} catch (err) {
|
|
92
92
|
throw new LoaderError(err instanceof Error ? err.message : String(err), filePath, "JSONC");
|
|
93
93
|
}
|
|
@@ -190,4 +190,4 @@ function defaultIncludePatterns(loader) {
|
|
|
190
190
|
//#endregion
|
|
191
191
|
export { TomlLoader as a, JsonLoader as c, YamlLoader as i, LoaderError as l, registerLoader as n, MarkdownLoader as o, resolveLoader as r, JsoncLoader as s, defaultIncludePatterns as t };
|
|
192
192
|
|
|
193
|
-
//# sourceMappingURL=loaders-
|
|
193
|
+
//# sourceMappingURL=loaders-DnyWfANR.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loaders-DnyWfANR.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 withoutTrailingCommas = stripped.replace(/,\\s*([}\\]])/g, '$1')\n const data = JSON.parse(withoutTrailingCommas)\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":";;;;;;AAAA,IAAa,cAAb,cAAiC,MAAM;CACrC;CACA;CACA;CACA;CAEA,YAAY,SAAiB,UAAkB,QAAgB,MAAe,QAAiB;AAC7F,QAAM,GAAG,OAAO,kBAAkB,WAAW,OAAO,IAAI,SAAS,GAAG,IAAI,UAAU;AAClF,OAAK,OAAO;AACZ,OAAK,WAAW;AAChB,OAAK,SAAS;AACd,OAAK,OAAO;AACZ,OAAK,SAAS;;;;;;;;;;ACDlB,IAAa,aAAb,MAA0C;CACxC,OAAO;CACP,OAAO;CACP,aAAa,CAAC,SAAS,SAAS;CAEhC,MAAM,KAAK,UAAyC;EAClD,MAAM,MAAM,MAAM,SAAS,UAAU,QAAQ;EAC7C,MAAM,SAAS,SAAS,SAAS,QAAQ;AAEzC,MAAI;AAEF,UAAO,EAAE,MADI,SAAS,KAAK,MAAM,IAAI,GAAG,MAAM,MAAM,IAAI,EACzC;WACR,KAAK;AAEZ,SAAM,IAAI,YADM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,EACjC,UAAU,SAAS,SAAS,QAAQ;;;;;;;;;;;;;ACbzE,SAAS,cAAc,KAAqB;CAC1C,IAAI,SAAS;CACb,IAAI,IAAI;CACR,MAAM,MAAM,IAAI;AAEhB,QAAO,IAAI,KAAK;AAEd,MAAI,IAAI,OAAO,MAAK;GAClB,IAAI,MAAM,IAAI;AACd,UAAO,MAAM,OAAO,IAAI,SAAS,MAAK;AACpC,QAAI,IAAI,SAAS,KAAM;AACvB;;AAEF,aAAU,IAAI,MAAM,GAAG,MAAM,EAAE;AAC/B,OAAI,MAAM;AACV;;AAIF,MAAI,IAAI,OAAO,OAAO,IAAI,IAAI,OAAO,KAAK;AACxC,QAAK;AACL,UAAO,IAAI,OAAO,IAAI,OAAO,KAAM;AACnC;;AAIF,MAAI,IAAI,OAAO,OAAO,IAAI,IAAI,OAAO,KAAK;AACxC,QAAK;AACL,UAAO,IAAI,OAAO,EAAE,IAAI,OAAO,OAAO,IAAI,IAAI,OAAO,KAAM;AAC3D,QAAK;AACL;;AAGF,YAAU,IAAI;AACd;;AAGF,QAAO;;AAGT,IAAa,cAAb,MAA2C;CACzC,OAAO;CACP,OAAO;CACP,aAAa,CAAC,SAAS;CAEvB,MAAM,KAAK,UAAyC;EAClD,MAAM,MAAM,MAAM,SAAS,UAAU,QAAQ;AAC7C,MAAI;GAEF,MAAM,wBADW,cAAc,IAAI,CACI,QAAQ,gBAAgB,KAAK;AAEpE,UAAO,EAAE,MADI,KAAK,MAAM,sBAAsB,EAC/B;WACR,KAAK;AAEZ,SAAM,IAAI,YADM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,EACjC,UAAU,QAAQ;;;;;;;;;;;;ACrDvD,IAAa,iBAAb,MAA8C;CAC5C,OAAO;CACP,OAAO;CACP,aAAa,CAAC,MAAM;CAEpB,MAAM,KAAK,UAAyC;EAClD,MAAM,MAAM,MAAM,SAAS,UAAU,QAAQ;AAC7C,MAAI;GACF,MAAM,EAAE,MAAM,YAAY,OAAO,KAAK,EAAE,SAAS,EAAE,MAAMA,OAAW,EAAE,CAAC;AACvE,UAAO;IAAE;IAAM;IAAS;WACjB,KAAK;AAEZ,SAAM,IAAI,YADM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,EACjC,UAAU,WAAW;;;;;;;;;AChB1D,IAAa,aAAb,MAA0C;CACxC,OAAO;CACP,OAAO;CACP,aAAa,CAAC,QAAQ;CAEtB,MAAM,KAAK,UAAyC;EAClD,MAAM,MAAM,MAAM,SAAS,UAAU,QAAQ;AAC7C,MAAI;AAEF,UAAO,EAAE,MADIC,QAAM,IAAI,EACR;WACR,KAAK;AAEZ,SAAM,IAAI,YADM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,EACjC,UAAU,OAAO;;;;;;;;;ACZtD,IAAa,aAAb,MAA0C;CACxC,OAAO;CACP,OAAO;CACP,aAAa,CAAC,SAAS,OAAO;CAE9B,MAAM,KAAK,UAAyC;EAClD,MAAM,MAAM,MAAM,SAAS,UAAU,QAAQ;AAC7C,MAAI;AAEF,UAAO,EAAE,MADI,MAAM,IAAI,IAAI,EAAE,EACd;WACR,KAAK;AAMZ,SAAM,IAAI,YALM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,EAKjC,UAAU,QAHvC,OAAO,QAAQ,OAAO,QAAQ,YAAY,aAAa,MAClD,IAAY,UAAU,IAAI,OAC3B,KAAA,EACgD;;;;;;;ACL5D,MAAM,iBAAiB,IAAI,gBAAgB;AAC3C,MAAM,aAAa,IAAI,YAAY;AACnC,MAAM,cAAc,IAAI,aAAa;AACrC,MAAM,aAAa,IAAI,YAAY;AACnC,MAAM,aAAa,IAAI,YAAY;;AAGnC,MAAM,gCAAgB,IAAI,KAAqB;;AAG/C,SAAgB,eAAe,MAAc,QAAsB;AACjE,eAAc,IAAI,MAAM,OAAO;;;AAIjC,SAAgB,cAAc,cAA2C;AACvE,KAAI,OAAO,iBAAiB,SAAU,QAAO;CAE7C,MAAM,SAAS,cAAc,IAAI,aAAa;AAC9C,KAAI,OAAQ,QAAO;AAEnB,SAAQ,cAAR;EACE,KAAK,WACH,QAAO;EACT,KAAK;EACL,KAAK,QACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,QACE,OAAM,IAAI,MAAM,wBAAwB,eAAyB;;;;AAKvE,SAAgB,uBAAuB,QAA0B;AAC/D,QAAO,OAAO,WAAW,KAAK,QAAQ,OAAO,MAAM"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as processMarkdown, t as MarkdownResult } from "../index-
|
|
1
|
+
import { t as MarkdownConfig } from "../markdown-config-CDvh5aJ-.mjs";
|
|
2
|
+
import { n as processMarkdown, t as MarkdownResult } from "../index-D44syBt-.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-DMHd400a.mjs";
|
|
2
2
|
export { processMarkdown };
|
|
@@ -86,6 +86,33 @@ function createProcessor(config) {
|
|
|
86
86
|
processor.use(rehypeStringify, { allowDangerousHtml: true });
|
|
87
87
|
return processor;
|
|
88
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Processor cache keyed by MarkdownConfig object reference.
|
|
91
|
+
*
|
|
92
|
+
* **Why a WeakMap keyed by object reference?**
|
|
93
|
+
* Building a unified processor chain is expensive — it loads Shiki grammars,
|
|
94
|
+
* theme JSON, and instantiates every remark/rehype plugin. Caching the
|
|
95
|
+
* processor by config reference lets callers that reuse the same config object
|
|
96
|
+
* (the common case) skip all of that setup on subsequent calls. The WeakMap
|
|
97
|
+
* also ensures that if a config object is garbage-collected, its processor is
|
|
98
|
+
* too, so long-running processes don't leak memory.
|
|
99
|
+
*
|
|
100
|
+
* **Why is the config frozen?**
|
|
101
|
+
* The cache assumes the config does not change after the processor is built.
|
|
102
|
+
* If a caller mutated a config object after the processor was created, later
|
|
103
|
+
* calls would still receive the stale processor (keyed by the same reference),
|
|
104
|
+
* producing silently wrong output. Freezing the config at first use turns that
|
|
105
|
+
* silent bug into a loud TypeError on any attempted mutation.
|
|
106
|
+
*
|
|
107
|
+
* **What if a consumer needs different settings?**
|
|
108
|
+
* Pass a new config object — a fresh reference gets its own cache entry.
|
|
109
|
+
* For example: `processMarkdown(md, { ...existingConfig, remarkPlugins: [...] })`.
|
|
110
|
+
*/
|
|
111
|
+
function deepFreeze(obj) {
|
|
112
|
+
Object.freeze(obj);
|
|
113
|
+
for (const value of Object.values(obj)) if (value && typeof value === "object" && !Object.isFrozen(value)) deepFreeze(value);
|
|
114
|
+
return obj;
|
|
115
|
+
}
|
|
89
116
|
const processorCache = /* @__PURE__ */ new WeakMap();
|
|
90
117
|
async function processMarkdown(raw, config, preExtracted) {
|
|
91
118
|
let frontmatter;
|
|
@@ -99,7 +126,7 @@ async function processMarkdown(raw, config, preExtracted) {
|
|
|
99
126
|
content = parsed.content;
|
|
100
127
|
}
|
|
101
128
|
const resolvedConfig = config && Object.keys(config).length > 0 ? config : DEFAULT_MARKDOWN_CONFIG;
|
|
102
|
-
if (Object.isFrozen(resolvedConfig) === false)
|
|
129
|
+
if (Object.isFrozen(resolvedConfig) === false) deepFreeze(resolvedConfig);
|
|
103
130
|
let processor = processorCache.get(resolvedConfig);
|
|
104
131
|
if (!processor) {
|
|
105
132
|
processor = createProcessor(resolvedConfig);
|
|
@@ -120,4 +147,4 @@ async function processMarkdown(raw, config, preExtracted) {
|
|
|
120
147
|
//#endregion
|
|
121
148
|
export { processMarkdown as t };
|
|
122
149
|
|
|
123
|
-
//# sourceMappingURL=markdown-
|
|
150
|
+
//# sourceMappingURL=markdown-DMHd400a.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-DMHd400a.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\n/**\n * Processor cache keyed by MarkdownConfig object reference.\n *\n * **Why a WeakMap keyed by object reference?**\n * Building a unified processor chain is expensive — it loads Shiki grammars,\n * theme JSON, and instantiates every remark/rehype plugin. Caching the\n * processor by config reference lets callers that reuse the same config object\n * (the common case) skip all of that setup on subsequent calls. The WeakMap\n * also ensures that if a config object is garbage-collected, its processor is\n * too, so long-running processes don't leak memory.\n *\n * **Why is the config frozen?**\n * The cache assumes the config does not change after the processor is built.\n * If a caller mutated a config object after the processor was created, later\n * calls would still receive the stale processor (keyed by the same reference),\n * producing silently wrong output. Freezing the config at first use turns that\n * silent bug into a loud TypeError on any attempted mutation.\n *\n * **What if a consumer needs different settings?**\n * Pass a new config object — a fresh reference gets its own cache entry.\n * For example: `processMarkdown(md, { ...existingConfig, remarkPlugins: [...] })`.\n */\nfunction deepFreeze<T extends object>(obj: T): T {\n Object.freeze(obj)\n for (const value of Object.values(obj)) {\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n deepFreeze(value)\n }\n }\n return obj\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 after caching — see processorCache JSDoc above.\n if (Object.isFrozen(resolvedConfig) === false) deepFreeze(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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"}
|
|
@@ -15,13 +15,5 @@ declare const MarkdownConfigSchema: z.ZodObject<{
|
|
|
15
15
|
}, z.core.$strip>;
|
|
16
16
|
type MarkdownConfig = z.infer<typeof MarkdownConfigSchema>;
|
|
17
17
|
//#endregion
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
depth: z.ZodNumber;
|
|
21
|
-
text: z.ZodString;
|
|
22
|
-
slug: z.ZodString;
|
|
23
|
-
}, z.core.$strip>;
|
|
24
|
-
type Heading = z.infer<typeof HeadingSchema>;
|
|
25
|
-
//#endregion
|
|
26
|
-
export { MarkdownConfigSchema as i, HeadingSchema as n, MarkdownConfig as r, Heading as t };
|
|
27
|
-
//# sourceMappingURL=heading-BpDXnl-7.d.mts.map
|
|
18
|
+
export { MarkdownConfigSchema as n, MarkdownConfig as t };
|
|
19
|
+
//# sourceMappingURL=markdown-config-CDvh5aJ-.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-config-CDvh5aJ-.d.mts","names":[],"sources":["../src/schemas/markdown-config.ts"],"mappings":";;;cAIa,oBAAA,EAAoB,CAAA,CAAA,SAAA;;;;;;;;;;;;KAerB,cAAA,GAAiB,CAAA,CAAE,KAAA,QAAa,oBAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CoreMcpServerOptions, createCoreMcpServer, startCoreMcpServer } from "./server.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/mcp/shared.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Shared MCP server utilities.
|
|
6
|
+
*
|
|
7
|
+
* Common helpers used by both @pagesmith/core and @pagesmith/docs MCP servers.
|
|
8
|
+
*/
|
|
9
|
+
/** Read the package version from a package.json relative to the calling module. */
|
|
10
|
+
declare function getPackageVersion(moduleDir: string): string;
|
|
11
|
+
/** Resolve a doc file path relative to the package root. */
|
|
12
|
+
declare function resolvePackageDocPath(moduleDir: string, relativePath: string): string;
|
|
13
|
+
/** Load a file as an MCP text resource response. Throws if the file doesn't exist. */
|
|
14
|
+
declare function asTextResource(uri: string, path: string): {
|
|
15
|
+
contents: {
|
|
16
|
+
uri: string;
|
|
17
|
+
mimeType: string;
|
|
18
|
+
text: string;
|
|
19
|
+
}[];
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { type CoreMcpServerOptions, asTextResource, createCoreMcpServer, getPackageVersion, resolvePackageDocPath, startCoreMcpServer };
|
|
23
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/mcp/shared.ts"],"mappings":";;;;;;;;;iBAUgB,iBAAA,CAAkB,SAAA;AAAlC;AAAA,iBAOgB,qBAAA,CAAsB,SAAA,UAAmB,YAAA;;iBAKzC,cAAA,CAAe,GAAA,UAAa,IAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { t as ContentLayer } from "../content-layer-Ckt08g2i.mjs";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
|
|
4
|
+
//#region src/mcp/server.d.ts
|
|
5
|
+
type CoreMcpServerOptions = {
|
|
6
|
+
layer: ContentLayer;
|
|
7
|
+
rootDir?: string;
|
|
8
|
+
};
|
|
9
|
+
declare function createCoreMcpServer(options: CoreMcpServerOptions): McpServer;
|
|
10
|
+
declare function startCoreMcpServer(options: CoreMcpServerOptions): Promise<void>;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { CoreMcpServerOptions, createCoreMcpServer, startCoreMcpServer };
|
|
13
|
+
//# sourceMappingURL=server.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.mts","names":[],"sources":["../../src/mcp/server.ts"],"mappings":";;;;KAQY,oBAAA;EACV,KAAA,EAAO,YAAA;EACP,OAAA;AAAA;AAAA,iBAqBc,mBAAA,CAAoB,OAAA,EAAS,oBAAA,GAAuB,SAAA;AAAA,iBA8S9C,kBAAA,CAAmB,OAAA,EAAS,oBAAA,GAAuB,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/runtime/index.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/runtime/index.ts"],"mappings":";;AAgEA;;;;;AAGA;;;;;AAGA;;;iBANgB,aAAA,CAAA;AAAA,iBAGA,YAAA,CAAA;AAAA,iBAGA,iBAAA,CAAA;AAAA,iBAGA,gBAAA,CAAA;AAAA,iBAKA,aAAA,CAAA;AAAA,iBAGA,YAAA,CAAA;AAAA,iBAGA,iBAAA,CAAA;AAAA,iBAGA,gBAAA,CAAA;AAAA,iBAKA,cAAA,CAAA;AAAA,iBAGA,kBAAA,CAAA"}
|
package/dist/runtime/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "fs";
|
|
1
2
|
import { dirname, join } from "path";
|
|
2
|
-
import { readFileSync } from "fs";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
4
|
//#region src/runtime/index.ts
|
|
5
5
|
/**
|
|
@@ -33,6 +33,7 @@ function readAsset(relPath) {
|
|
|
33
33
|
for (const dir of ["dist", "src"]) try {
|
|
34
34
|
return readFileSync(join(pkgDir, dir, relPath), "utf-8");
|
|
35
35
|
} catch {}
|
|
36
|
+
console.warn(`[pagesmith] Asset not found: ${relPath}`);
|
|
36
37
|
return "";
|
|
37
38
|
}
|
|
38
39
|
function resolveAssetPath(relPath) {
|
|
@@ -40,17 +41,11 @@ function resolveAssetPath(relPath) {
|
|
|
40
41
|
const mapped = ASSET_PATHS[relPath];
|
|
41
42
|
if (mapped) {
|
|
42
43
|
const path = join(pkgDir, "src", mapped);
|
|
43
|
-
|
|
44
|
-
readFileSync(path);
|
|
45
|
-
return path;
|
|
46
|
-
} catch {}
|
|
44
|
+
if (existsSync(path)) return path;
|
|
47
45
|
}
|
|
48
46
|
for (const dir of ["dist", "src"]) {
|
|
49
47
|
const path = join(pkgDir, dir, relPath);
|
|
50
|
-
|
|
51
|
-
readFileSync(path);
|
|
52
|
-
return path;
|
|
53
|
-
} catch {}
|
|
48
|
+
if (existsSync(path)) return path;
|
|
54
49
|
}
|
|
55
50
|
return join(pkgDir, "dist", relPath);
|
|
56
51
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/runtime/index.ts"],"sourcesContent":["/**\n * Runtime CSS/JS exports.\n *\n * Provides pre-built CSS and JS paths for consumers who want\n * ready-to-use styling and interactivity for rendered content.\n *\n * Two tiers:\n * - \"Runtime\" (standalone): full site — reset, prose, layout, TOC\n * - \"Content\": just markdown rendering — reset, prose, viewport\n *\n * Code block styling is handled by Expressive Code (injected inline\n * during markdown processing). The CSS bundles here cover prose,\n * inline code, and layout only.\n */\n\nimport { readFileSync } from 'fs'\nimport { dirname, join } from 'path'\nimport { fileURLToPath } from 'url'\n\nconst ASSET_PATHS: Record<string, string> = {\n 'standalone.css': 'styles/standalone.css',\n 'content.css': 'styles/content.css',\n 'styles/viewport.css': 'styles/viewport.css',\n}\n\nfunction getPackageDir(): string {\n const thisDir = dirname(fileURLToPath(import.meta.url))\n // From src/runtime/ → src/ → package root\n // From dist/runtime/ → dist/ → package root\n return join(thisDir, '..', '..')\n}\n\nfunction readAsset(relPath: string): string {\n const pkgDir = getPackageDir()\n const mapped = ASSET_PATHS[relPath]\n if (mapped) {\n try {\n return readFileSync(join(pkgDir, 'src', mapped), 'utf-8')\n } catch {}\n }\n for (const dir of ['dist', 'src']) {\n try {\n return readFileSync(join(pkgDir, dir, relPath), 'utf-8')\n } catch {}\n }\n return ''\n}\n\nfunction resolveAssetPath(relPath: string): string {\n const pkgDir = getPackageDir()\n const mapped = ASSET_PATHS[relPath]\n if (mapped) {\n const path = join(pkgDir, 'src', mapped)\n
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/runtime/index.ts"],"sourcesContent":["/**\n * Runtime CSS/JS exports.\n *\n * Provides pre-built CSS and JS paths for consumers who want\n * ready-to-use styling and interactivity for rendered content.\n *\n * Two tiers:\n * - \"Runtime\" (standalone): full site — reset, prose, layout, TOC\n * - \"Content\": just markdown rendering — reset, prose, viewport\n *\n * Code block styling is handled by Expressive Code (injected inline\n * during markdown processing). The CSS bundles here cover prose,\n * inline code, and layout only.\n */\n\nimport { existsSync, readFileSync } from 'fs'\nimport { dirname, join } from 'path'\nimport { fileURLToPath } from 'url'\n\nconst ASSET_PATHS: Record<string, string> = {\n 'standalone.css': 'styles/standalone.css',\n 'content.css': 'styles/content.css',\n 'styles/viewport.css': 'styles/viewport.css',\n}\n\nfunction getPackageDir(): string {\n const thisDir = dirname(fileURLToPath(import.meta.url))\n // From src/runtime/ → src/ → package root\n // From dist/runtime/ → dist/ → package root\n return join(thisDir, '..', '..')\n}\n\nfunction readAsset(relPath: string): string {\n const pkgDir = getPackageDir()\n const mapped = ASSET_PATHS[relPath]\n if (mapped) {\n try {\n return readFileSync(join(pkgDir, 'src', mapped), 'utf-8')\n } catch {}\n }\n for (const dir of ['dist', 'src']) {\n try {\n return readFileSync(join(pkgDir, dir, relPath), 'utf-8')\n } catch {}\n }\n console.warn(`[pagesmith] Asset not found: ${relPath}`)\n return ''\n}\n\nfunction resolveAssetPath(relPath: string): string {\n const pkgDir = getPackageDir()\n const mapped = ASSET_PATHS[relPath]\n if (mapped) {\n const path = join(pkgDir, 'src', mapped)\n if (existsSync(path)) return path\n }\n for (const dir of ['dist', 'src']) {\n const path = join(pkgDir, dir, relPath)\n if (existsSync(path)) return path\n }\n return join(pkgDir, 'dist', relPath)\n}\n\n// Standalone (full site)\nexport function getRuntimeCSS(): string {\n return readAsset('standalone.css')\n}\nexport function getRuntimeJS(): string {\n return readAsset('standalone.js')\n}\nexport function getRuntimeCSSPath(): string {\n return resolveAssetPath('standalone.css')\n}\nexport function getRuntimeJSPath(): string {\n return resolveAssetPath('standalone.js')\n}\n\n// Content (markdown rendering only)\nexport function getContentCSS(): string {\n return readAsset('content.css')\n}\nexport function getContentJS(): string {\n return readAsset('content.js')\n}\nexport function getContentCSSPath(): string {\n return resolveAssetPath('content.css')\n}\nexport function getContentJSPath(): string {\n return resolveAssetPath('content.js')\n}\n\n// Individual CSS files\nexport function getViewportCSS(): string {\n return readAsset('styles/viewport.css')\n}\nexport function getViewportCSSPath(): string {\n return resolveAssetPath('styles/viewport.css')\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAmBA,MAAM,cAAsC;CAC1C,kBAAkB;CAClB,eAAe;CACf,uBAAuB;CACxB;AAED,SAAS,gBAAwB;AAI/B,QAAO,KAHS,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC,EAGlC,MAAM,KAAK;;AAGlC,SAAS,UAAU,SAAyB;CAC1C,MAAM,SAAS,eAAe;CAC9B,MAAM,SAAS,YAAY;AAC3B,KAAI,OACF,KAAI;AACF,SAAO,aAAa,KAAK,QAAQ,OAAO,OAAO,EAAE,QAAQ;SACnD;AAEV,MAAK,MAAM,OAAO,CAAC,QAAQ,MAAM,CAC/B,KAAI;AACF,SAAO,aAAa,KAAK,QAAQ,KAAK,QAAQ,EAAE,QAAQ;SAClD;AAEV,SAAQ,KAAK,gCAAgC,UAAU;AACvD,QAAO;;AAGT,SAAS,iBAAiB,SAAyB;CACjD,MAAM,SAAS,eAAe;CAC9B,MAAM,SAAS,YAAY;AAC3B,KAAI,QAAQ;EACV,MAAM,OAAO,KAAK,QAAQ,OAAO,OAAO;AACxC,MAAI,WAAW,KAAK,CAAE,QAAO;;AAE/B,MAAK,MAAM,OAAO,CAAC,QAAQ,MAAM,EAAE;EACjC,MAAM,OAAO,KAAK,QAAQ,KAAK,QAAQ;AACvC,MAAI,WAAW,KAAK,CAAE,QAAO;;AAE/B,QAAO,KAAK,QAAQ,QAAQ,QAAQ;;AAItC,SAAgB,gBAAwB;AACtC,QAAO,UAAU,iBAAiB;;AAEpC,SAAgB,eAAuB;AACrC,QAAO,UAAU,gBAAgB;;AAEnC,SAAgB,oBAA4B;AAC1C,QAAO,iBAAiB,iBAAiB;;AAE3C,SAAgB,mBAA2B;AACzC,QAAO,iBAAiB,gBAAgB;;AAI1C,SAAgB,gBAAwB;AACtC,QAAO,UAAU,cAAc;;AAEjC,SAAgB,eAAuB;AACrC,QAAO,UAAU,aAAa;;AAEhC,SAAgB,oBAA4B;AAC1C,QAAO,iBAAiB,cAAc;;AAExC,SAAgB,mBAA2B;AACzC,QAAO,iBAAiB,aAAa;;AAIvC,SAAgB,iBAAyB;AACvC,QAAO,UAAU,sBAAsB;;AAEzC,SAAgB,qBAA6B;AAC3C,QAAO,iBAAiB,sBAAsB"}
|
package/dist/schemas/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { c as RawEntry, i as CollectionDef, n as ContentPlugin, t as ContentLayerConfig } from "../content-config-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { c as RawEntry, i as CollectionDef, n as ContentPlugin, t as ContentLayerConfig } from "../content-config-Bu2HH0Yx.mjs";
|
|
2
|
+
import { n as MarkdownConfigSchema, t as MarkdownConfig } from "../markdown-config-CDvh5aJ-.mjs";
|
|
3
|
+
import { n as HeadingSchema, t as Heading } from "../heading-D4X2L4vd.mjs";
|
|
4
|
+
import { a as ProjectFrontmatter, i as BlogFrontmatterSchema, n as BaseFrontmatterSchema, o as ProjectFrontmatterSchema, r as BlogFrontmatter, t as BaseFrontmatter } from "../index-B4YZRIzb.mjs";
|
|
4
5
|
export { BaseFrontmatter, BaseFrontmatterSchema, BlogFrontmatter, BlogFrontmatterSchema, CollectionDef, ContentLayerConfig, ContentPlugin, Heading, HeadingSchema, MarkdownConfig, MarkdownConfigSchema, ProjectFrontmatter, ProjectFrontmatterSchema, RawEntry };
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "fs";
|
|
2
|
+
import { basename, resolve } from "path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
+
//#region src/mcp/shared.ts
|
|
7
|
+
/**
|
|
8
|
+
* Shared MCP server utilities.
|
|
9
|
+
*
|
|
10
|
+
* Common helpers used by both @pagesmith/core and @pagesmith/docs MCP servers.
|
|
11
|
+
*/
|
|
12
|
+
/** Read the package version from a package.json relative to the calling module. */
|
|
13
|
+
function getPackageVersion(moduleDir) {
|
|
14
|
+
const pkgPath = resolve(moduleDir, "..", "..", "package.json");
|
|
15
|
+
return JSON.parse(readFileSync(pkgPath, "utf-8")).version ?? "0.0.0";
|
|
16
|
+
}
|
|
17
|
+
/** Resolve a doc file path relative to the package root. */
|
|
18
|
+
function resolvePackageDocPath(moduleDir, relativePath) {
|
|
19
|
+
return resolve(moduleDir, "..", "..", relativePath);
|
|
20
|
+
}
|
|
21
|
+
/** Load a file as an MCP text resource response. Throws if the file doesn't exist. */
|
|
22
|
+
function asTextResource(uri, path) {
|
|
23
|
+
if (!existsSync(path)) throw new Error(`Resource file not found: ${path}`);
|
|
24
|
+
return { contents: [{
|
|
25
|
+
uri,
|
|
26
|
+
mimeType: "text/markdown",
|
|
27
|
+
text: readFileSync(path, "utf-8")
|
|
28
|
+
}] };
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/mcp/server.ts
|
|
32
|
+
function getLoaderType(loader) {
|
|
33
|
+
if (typeof loader === "string") return loader;
|
|
34
|
+
return loader.name ?? "custom";
|
|
35
|
+
}
|
|
36
|
+
function getSchemaFieldNames(schema) {
|
|
37
|
+
if (schema instanceof z.ZodObject) return Object.keys(schema.shape);
|
|
38
|
+
if (schema instanceof z.ZodOptional || schema instanceof z.ZodNullable) return getSchemaFieldNames(schema.unwrap());
|
|
39
|
+
if (schema instanceof z.ZodDefault) return getSchemaFieldNames(schema._def.innerType);
|
|
40
|
+
}
|
|
41
|
+
function createCoreMcpServer(options) {
|
|
42
|
+
const { layer } = options;
|
|
43
|
+
const baseRoot = resolve(options.rootDir ?? process.cwd());
|
|
44
|
+
const server = new McpServer({
|
|
45
|
+
name: "@pagesmith/core-mcp",
|
|
46
|
+
version: getPackageVersion(import.meta.dirname)
|
|
47
|
+
}, { instructions: ["Use core_* tools to inspect @pagesmith/core content layers.", `Root directory: ${baseRoot}`].join("\n") });
|
|
48
|
+
server.registerTool("core_list_collections", {
|
|
49
|
+
description: "List all configured collections with their loader type, directory, and schema field names.",
|
|
50
|
+
inputSchema: {}
|
|
51
|
+
}, async () => {
|
|
52
|
+
const collections = layer.getCollectionNames().map((name) => {
|
|
53
|
+
const def = layer.getCollectionDef(name);
|
|
54
|
+
return {
|
|
55
|
+
name,
|
|
56
|
+
loader: def ? getLoaderType(def.loader) : "unknown",
|
|
57
|
+
directory: def?.directory,
|
|
58
|
+
schemaFields: def ? getSchemaFieldNames(def.schema) : void 0
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
return { content: [{
|
|
62
|
+
type: "text",
|
|
63
|
+
text: JSON.stringify(collections, null, 2)
|
|
64
|
+
}] };
|
|
65
|
+
});
|
|
66
|
+
server.registerTool("core_list_entries", {
|
|
67
|
+
description: "List entries in a collection with slug, title, description, and file path. Does not render content. Supports pagination via limit/offset.",
|
|
68
|
+
inputSchema: {
|
|
69
|
+
collection: z.string().describe("Collection name"),
|
|
70
|
+
limit: z.number().int().min(1).max(200).default(50).describe("Maximum number of entries to return (default 50)"),
|
|
71
|
+
offset: z.number().int().min(0).default(0).describe("Number of entries to skip (default 0)")
|
|
72
|
+
}
|
|
73
|
+
}, async ({ collection, limit, offset }) => {
|
|
74
|
+
const entries = await layer.getCollection(collection);
|
|
75
|
+
const total = entries.length;
|
|
76
|
+
const items = entries.slice(offset, offset + limit).map((entry) => {
|
|
77
|
+
const data = entry.data ?? {};
|
|
78
|
+
return {
|
|
79
|
+
slug: entry.slug,
|
|
80
|
+
title: typeof data.title === "string" ? data.title : void 0,
|
|
81
|
+
description: typeof data.description === "string" ? data.description : void 0,
|
|
82
|
+
filePath: entry.filePath
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
return { content: [{
|
|
86
|
+
type: "text",
|
|
87
|
+
text: JSON.stringify({
|
|
88
|
+
collection,
|
|
89
|
+
total,
|
|
90
|
+
offset,
|
|
91
|
+
limit,
|
|
92
|
+
count: items.length,
|
|
93
|
+
entries: items
|
|
94
|
+
}, null, 2)
|
|
95
|
+
}] };
|
|
96
|
+
});
|
|
97
|
+
server.registerTool("core_get_entry", {
|
|
98
|
+
description: "Load a single content entry by collection name and slug. Returns slug, validated data, rendered HTML, headings, and read time.",
|
|
99
|
+
inputSchema: {
|
|
100
|
+
collection: z.string().describe("Collection name"),
|
|
101
|
+
slug: z.string().describe("Entry slug")
|
|
102
|
+
}
|
|
103
|
+
}, async ({ collection, slug }) => {
|
|
104
|
+
const entry = await layer.getEntry(collection, slug);
|
|
105
|
+
if (!entry) throw new Error(`Entry not found: ${collection}/${slug}`);
|
|
106
|
+
const rendered = await entry.render();
|
|
107
|
+
return { content: [{
|
|
108
|
+
type: "text",
|
|
109
|
+
text: JSON.stringify({
|
|
110
|
+
slug: entry.slug,
|
|
111
|
+
collection: entry.collection,
|
|
112
|
+
filePath: entry.filePath,
|
|
113
|
+
data: entry.data,
|
|
114
|
+
html: rendered.html,
|
|
115
|
+
headings: rendered.headings,
|
|
116
|
+
readTime: rendered.readTime
|
|
117
|
+
}, null, 2)
|
|
118
|
+
}] };
|
|
119
|
+
});
|
|
120
|
+
server.registerTool("core_validate", {
|
|
121
|
+
description: "Run validation on a specific collection or all collections. Returns structured validation results with error and warning counts.",
|
|
122
|
+
inputSchema: { collection: z.string().optional().describe("Collection name (omit to validate all)") }
|
|
123
|
+
}, async ({ collection }) => {
|
|
124
|
+
const results = await layer.validate(collection);
|
|
125
|
+
return { content: [{
|
|
126
|
+
type: "text",
|
|
127
|
+
text: JSON.stringify(results, null, 2)
|
|
128
|
+
}] };
|
|
129
|
+
});
|
|
130
|
+
server.registerTool("core_search_entries", {
|
|
131
|
+
description: "Search entries across collections by matching a query string against titles, descriptions, tags, and slugs. Case-insensitive. Returns up to 20 matches.",
|
|
132
|
+
inputSchema: {
|
|
133
|
+
query: z.string().describe("Search query string"),
|
|
134
|
+
collection: z.string().optional().describe("Limit search to a specific collection")
|
|
135
|
+
}
|
|
136
|
+
}, async ({ query, collection }) => {
|
|
137
|
+
if (!query.trim()) return { content: [{
|
|
138
|
+
type: "text",
|
|
139
|
+
text: JSON.stringify({
|
|
140
|
+
query,
|
|
141
|
+
matches: [],
|
|
142
|
+
count: 0
|
|
143
|
+
}, null, 2)
|
|
144
|
+
}] };
|
|
145
|
+
const queryLower = query.toLowerCase();
|
|
146
|
+
const maxResults = 20;
|
|
147
|
+
const collectionNames = collection ? [collection] : layer.getCollectionNames();
|
|
148
|
+
const matches = [];
|
|
149
|
+
for (const name of collectionNames) {
|
|
150
|
+
if (matches.length >= maxResults) break;
|
|
151
|
+
const entries = await layer.getCollection(name);
|
|
152
|
+
for (const entry of entries) {
|
|
153
|
+
if (matches.length >= maxResults) break;
|
|
154
|
+
const data = entry.data ?? {};
|
|
155
|
+
const title = typeof data.title === "string" ? data.title : "";
|
|
156
|
+
const description = typeof data.description === "string" ? data.description : "";
|
|
157
|
+
const tags = Array.isArray(data.tags) ? data.tags.join(" ") : "";
|
|
158
|
+
if (`${entry.slug} ${title} ${description} ${tags}`.toLowerCase().includes(queryLower)) matches.push({
|
|
159
|
+
collection: name,
|
|
160
|
+
slug: entry.slug,
|
|
161
|
+
title: title || void 0,
|
|
162
|
+
description: description || void 0,
|
|
163
|
+
filePath: entry.filePath
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return { content: [{
|
|
168
|
+
type: "text",
|
|
169
|
+
text: JSON.stringify({
|
|
170
|
+
query,
|
|
171
|
+
collection: collection ?? null,
|
|
172
|
+
count: matches.length,
|
|
173
|
+
matches
|
|
174
|
+
}, null, 2)
|
|
175
|
+
}] };
|
|
176
|
+
});
|
|
177
|
+
server.registerResource("core-agent-usage", "pagesmith://core/agents/usage", {
|
|
178
|
+
title: "@pagesmith/core agent usage",
|
|
179
|
+
description: "Version-matched AI usage guide for @pagesmith/core.",
|
|
180
|
+
mimeType: "text/markdown"
|
|
181
|
+
}, async () => asTextResource("pagesmith://core/agents/usage", resolvePackageDocPath(import.meta.dirname, "docs/agents/usage.md")));
|
|
182
|
+
server.registerResource("core-llms-full", "pagesmith://core/llms-full", {
|
|
183
|
+
title: "@pagesmith/core llms-full",
|
|
184
|
+
description: "Version-matched full AI reference for @pagesmith/core.",
|
|
185
|
+
mimeType: "text/markdown"
|
|
186
|
+
}, async () => asTextResource("pagesmith://core/llms-full", resolvePackageDocPath(import.meta.dirname, "docs/llms-full.txt")));
|
|
187
|
+
server.registerResource("core-reference", "pagesmith://core/reference", {
|
|
188
|
+
title: "@pagesmith/core reference",
|
|
189
|
+
description: "Core package reference for content layer, schemas, loaders, and markdown pipeline.",
|
|
190
|
+
mimeType: "text/markdown"
|
|
191
|
+
}, async () => asTextResource("pagesmith://core/reference", resolvePackageDocPath(import.meta.dirname, "REFERENCE.md")));
|
|
192
|
+
return server;
|
|
193
|
+
}
|
|
194
|
+
async function startCoreMcpServer(options) {
|
|
195
|
+
const server = createCoreMcpServer(options);
|
|
196
|
+
const transport = new StdioServerTransport();
|
|
197
|
+
await server.connect(transport);
|
|
198
|
+
console.error(`[pagesmith:mcp] @pagesmith/core MCP server started (root=${basename(resolve(options.rootDir ?? process.cwd()))})`);
|
|
199
|
+
}
|
|
200
|
+
//#endregion
|
|
201
|
+
export { resolvePackageDocPath as a, getPackageVersion as i, startCoreMcpServer as n, asTextResource as r, createCoreMcpServer as t };
|
|
202
|
+
|
|
203
|
+
//# sourceMappingURL=server-BZA_iSen.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-BZA_iSen.mjs","names":[],"sources":["../src/mcp/shared.ts","../src/mcp/server.ts"],"sourcesContent":["/**\n * Shared MCP server utilities.\n *\n * Common helpers used by both @pagesmith/core and @pagesmith/docs MCP servers.\n */\n\nimport { existsSync, readFileSync } from 'fs'\nimport { resolve } from 'path'\n\n/** Read the package version from a package.json relative to the calling module. */\nexport function getPackageVersion(moduleDir: string): string {\n const pkgPath = resolve(moduleDir, '..', '..', 'package.json')\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as { version?: string }\n return pkg.version ?? '0.0.0'\n}\n\n/** Resolve a doc file path relative to the package root. */\nexport function resolvePackageDocPath(moduleDir: string, relativePath: string): string {\n return resolve(moduleDir, '..', '..', relativePath)\n}\n\n/** Load a file as an MCP text resource response. Throws if the file doesn't exist. */\nexport function asTextResource(uri: string, path: string) {\n if (!existsSync(path)) {\n throw new Error(`Resource file not found: ${path}`)\n }\n\n return {\n contents: [\n {\n uri,\n mimeType: 'text/markdown',\n text: readFileSync(path, 'utf-8'),\n },\n ],\n }\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { basename, resolve } from 'path'\nimport { z } from 'zod'\nimport type { ContentLayer } from '../content-layer.js'\nimport type { Loader } from '../loaders/types.js'\nimport { asTextResource, getPackageVersion, resolvePackageDocPath } from './shared.js'\n\nexport type CoreMcpServerOptions = {\n layer: ContentLayer\n rootDir?: string\n}\n\nfunction getLoaderType(loader: string | Loader): string {\n if (typeof loader === 'string') return loader\n return loader.name ?? 'custom'\n}\n\nfunction getSchemaFieldNames(schema: z.ZodType): string[] | undefined {\n if (schema instanceof z.ZodObject) {\n return Object.keys(schema.shape)\n }\n if (schema instanceof z.ZodOptional || schema instanceof z.ZodNullable) {\n return getSchemaFieldNames(schema.unwrap() as z.ZodType)\n }\n if (schema instanceof z.ZodDefault) {\n return getSchemaFieldNames(schema._def.innerType as z.ZodType)\n }\n return undefined\n}\n\nexport function createCoreMcpServer(options: CoreMcpServerOptions): McpServer {\n const { layer } = options\n const baseRoot = resolve(options.rootDir ?? process.cwd())\n\n const server = new McpServer(\n {\n name: '@pagesmith/core-mcp',\n version: getPackageVersion(import.meta.dirname),\n },\n {\n instructions: [\n 'Use core_* tools to inspect @pagesmith/core content layers.',\n `Root directory: ${baseRoot}`,\n ].join('\\n'),\n },\n )\n\n // ── Tools ──\n\n server.registerTool(\n 'core_list_collections',\n {\n description:\n 'List all configured collections with their loader type, directory, and schema field names.',\n inputSchema: {},\n },\n async () => {\n const names = layer.getCollectionNames()\n const collections = names.map((name) => {\n const def = layer.getCollectionDef(name)\n return {\n name,\n loader: def ? getLoaderType(def.loader) : 'unknown',\n directory: def?.directory,\n schemaFields: def ? getSchemaFieldNames(def.schema) : undefined,\n }\n })\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(collections, null, 2),\n },\n ],\n }\n },\n )\n\n server.registerTool(\n 'core_list_entries',\n {\n description:\n 'List entries in a collection with slug, title, description, and file path. Does not render content. Supports pagination via limit/offset.',\n inputSchema: {\n collection: z.string().describe('Collection name'),\n limit: z\n .number()\n .int()\n .min(1)\n .max(200)\n .default(50)\n .describe('Maximum number of entries to return (default 50)'),\n offset: z\n .number()\n .int()\n .min(0)\n .default(0)\n .describe('Number of entries to skip (default 0)'),\n },\n },\n async ({\n collection,\n limit,\n offset,\n }: {\n collection: string\n limit: number\n offset: number\n }) => {\n const entries = await layer.getCollection(collection)\n const total = entries.length\n const page = entries.slice(offset, offset + limit)\n\n const items = page.map((entry) => {\n const data = (entry.data ?? {}) as Record<string, unknown>\n return {\n slug: entry.slug,\n title: typeof data.title === 'string' ? data.title : undefined,\n description: typeof data.description === 'string' ? data.description : undefined,\n filePath: entry.filePath,\n }\n })\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n collection,\n total,\n offset,\n limit,\n count: items.length,\n entries: items,\n },\n null,\n 2,\n ),\n },\n ],\n }\n },\n )\n\n server.registerTool(\n 'core_get_entry',\n {\n description:\n 'Load a single content entry by collection name and slug. Returns slug, validated data, rendered HTML, headings, and read time.',\n inputSchema: {\n collection: z.string().describe('Collection name'),\n slug: z.string().describe('Entry slug'),\n },\n },\n async ({ collection, slug }: { collection: string; slug: string }) => {\n const entry = await layer.getEntry(collection, slug)\n if (!entry) {\n throw new Error(`Entry not found: ${collection}/${slug}`)\n }\n\n const rendered = await entry.render()\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n slug: entry.slug,\n collection: entry.collection,\n filePath: entry.filePath,\n data: entry.data,\n html: rendered.html,\n headings: rendered.headings,\n readTime: rendered.readTime,\n },\n null,\n 2,\n ),\n },\n ],\n }\n },\n )\n\n server.registerTool(\n 'core_validate',\n {\n description:\n 'Run validation on a specific collection or all collections. Returns structured validation results with error and warning counts.',\n inputSchema: {\n collection: z.string().optional().describe('Collection name (omit to validate all)'),\n },\n },\n async ({ collection }: { collection?: string }) => {\n const results = await layer.validate(collection)\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(results, null, 2),\n },\n ],\n }\n },\n )\n\n server.registerTool(\n 'core_search_entries',\n {\n description:\n 'Search entries across collections by matching a query string against titles, descriptions, tags, and slugs. Case-insensitive. Returns up to 20 matches.',\n inputSchema: {\n query: z.string().describe('Search query string'),\n collection: z.string().optional().describe('Limit search to a specific collection'),\n },\n },\n async ({ query, collection }: { query: string; collection?: string }) => {\n if (!query.trim()) {\n return {\n content: [\n { type: 'text', text: JSON.stringify({ query, matches: [], count: 0 }, null, 2) },\n ],\n }\n }\n\n const queryLower = query.toLowerCase()\n const maxResults = 20\n const collectionNames = collection ? [collection] : layer.getCollectionNames()\n\n type SearchMatch = {\n collection: string\n slug: string\n title?: string\n description?: string\n filePath: string\n }\n\n const matches: SearchMatch[] = []\n\n for (const name of collectionNames) {\n if (matches.length >= maxResults) break\n const entries = await layer.getCollection(name)\n for (const entry of entries) {\n if (matches.length >= maxResults) break\n const data = (entry.data ?? {}) as Record<string, unknown>\n const title = typeof data.title === 'string' ? data.title : ''\n const description = typeof data.description === 'string' ? data.description : ''\n const tags = Array.isArray(data.tags) ? data.tags.join(' ') : ''\n const searchText = `${entry.slug} ${title} ${description} ${tags}`.toLowerCase()\n\n if (searchText.includes(queryLower)) {\n matches.push({\n collection: name,\n slug: entry.slug,\n title: title || undefined,\n description: description || undefined,\n filePath: entry.filePath,\n })\n }\n }\n }\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { query, collection: collection ?? null, count: matches.length, matches },\n null,\n 2,\n ),\n },\n ],\n }\n },\n )\n\n // ── Resources ──\n\n server.registerResource(\n 'core-agent-usage',\n 'pagesmith://core/agents/usage',\n {\n title: '@pagesmith/core agent usage',\n description: 'Version-matched AI usage guide for @pagesmith/core.',\n mimeType: 'text/markdown',\n },\n async () =>\n asTextResource(\n 'pagesmith://core/agents/usage',\n resolvePackageDocPath(import.meta.dirname, 'docs/agents/usage.md'),\n ),\n )\n\n server.registerResource(\n 'core-llms-full',\n 'pagesmith://core/llms-full',\n {\n title: '@pagesmith/core llms-full',\n description: 'Version-matched full AI reference for @pagesmith/core.',\n mimeType: 'text/markdown',\n },\n async () =>\n asTextResource(\n 'pagesmith://core/llms-full',\n resolvePackageDocPath(import.meta.dirname, 'docs/llms-full.txt'),\n ),\n )\n\n server.registerResource(\n 'core-reference',\n 'pagesmith://core/reference',\n {\n title: '@pagesmith/core reference',\n description:\n 'Core package reference for content layer, schemas, loaders, and markdown pipeline.',\n mimeType: 'text/markdown',\n },\n async () =>\n asTextResource(\n 'pagesmith://core/reference',\n resolvePackageDocPath(import.meta.dirname, 'REFERENCE.md'),\n ),\n )\n\n return server\n}\n\nexport async function startCoreMcpServer(options: CoreMcpServerOptions): Promise<void> {\n const server = createCoreMcpServer(options)\n const transport = new StdioServerTransport()\n await server.connect(transport)\n // Keep logs on stderr; stdout is reserved for MCP protocol messages.\n console.error(\n `[pagesmith:mcp] @pagesmith/core MCP server started (root=${basename(resolve(options.rootDir ?? process.cwd()))})`,\n )\n}\n"],"mappings":"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"}
|