@hale-bopp/valentino-engine 2.0.0 → 2.2.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +2 -2
  3. package/dist/bin/commands/llms.d.ts +2 -0
  4. package/dist/bin/commands/llms.d.ts.map +1 -0
  5. package/dist/bin/commands/llms.js +84 -0
  6. package/dist/bin/commands/llms.js.map +1 -0
  7. package/dist/bin/valentino.js +6 -1
  8. package/dist/bin/valentino.js.map +1 -1
  9. package/dist/core/animation.d.ts +18 -0
  10. package/dist/core/animation.d.ts.map +1 -0
  11. package/dist/core/animation.js +91 -0
  12. package/dist/core/animation.js.map +1 -0
  13. package/dist/core/editor.d.ts +80 -0
  14. package/dist/core/editor.d.ts.map +1 -0
  15. package/dist/core/editor.js +421 -0
  16. package/dist/core/editor.js.map +1 -0
  17. package/dist/core/encoding.d.ts +32 -0
  18. package/dist/core/encoding.d.ts.map +1 -0
  19. package/dist/core/encoding.js +112 -0
  20. package/dist/core/encoding.js.map +1 -0
  21. package/dist/core/gallery.d.ts +53 -0
  22. package/dist/core/gallery.d.ts.map +1 -0
  23. package/dist/core/gallery.js +123 -0
  24. package/dist/core/gallery.js.map +1 -0
  25. package/dist/core/gallery.test.d.ts +2 -0
  26. package/dist/core/gallery.test.d.ts.map +1 -0
  27. package/dist/core/gallery.test.js +127 -0
  28. package/dist/core/gallery.test.js.map +1 -0
  29. package/dist/core/guardrails-cms.d.ts +31 -1
  30. package/dist/core/guardrails-cms.d.ts.map +1 -1
  31. package/dist/core/guardrails-cms.js +160 -0
  32. package/dist/core/guardrails-cms.js.map +1 -1
  33. package/dist/core/llms-generator.d.ts +36 -0
  34. package/dist/core/llms-generator.d.ts.map +1 -0
  35. package/dist/core/llms-generator.js +95 -0
  36. package/dist/core/llms-generator.js.map +1 -0
  37. package/dist/core/page-generator.d.ts +85 -0
  38. package/dist/core/page-generator.d.ts.map +1 -0
  39. package/dist/core/page-generator.js +353 -0
  40. package/dist/core/page-generator.js.map +1 -0
  41. package/dist/core/page-generator.test.d.ts +2 -0
  42. package/dist/core/page-generator.test.d.ts.map +1 -0
  43. package/dist/core/page-generator.test.js +138 -0
  44. package/dist/core/page-generator.test.js.map +1 -0
  45. package/dist/core/types.d.ts +11 -0
  46. package/dist/core/types.d.ts.map +1 -1
  47. package/dist/index.d.ts +14 -1
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +14 -2
  50. package/dist/index.js.map +1 -1
  51. package/package.json +2 -2
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Template Gallery — Pure helpers for enumerating catalog entries.
3
+ * PBI #610 — Provides gallery-ready metadata from ValentinoCatalogV1.
4
+ *
5
+ * No DOM, no fetch — pure functions only.
6
+ * The consumer (portal) renders the gallery UI.
7
+ */
8
+ import type { ValentinoCatalogV1, PageSpecV1, PagesManifestV1 } from './types.js';
9
+ export type GalleryEntryKind = 'blueprint' | 'template' | 'page';
10
+ export type GalleryEntry = {
11
+ /** Unique key (blueprint ID, template ID, or page ID) */
12
+ id: string;
13
+ kind: GalleryEntryKind;
14
+ /** Display name (derived from ID) */
15
+ name: string;
16
+ /** Description for the gallery card */
17
+ description: string;
18
+ /** Page profile (if available) */
19
+ profile?: string;
20
+ /** Theme ID (if available) */
21
+ themeId?: string;
22
+ /** Number of sections in the blueprint/page */
23
+ sectionCount: number;
24
+ /** Section types present (for preview/filtering) */
25
+ sectionTypes: string[];
26
+ /** Governance tier (if available) */
27
+ governanceTier?: string;
28
+ };
29
+ export type GalleryFilter = {
30
+ kind?: GalleryEntryKind | GalleryEntryKind[];
31
+ profile?: string;
32
+ sectionType?: string;
33
+ search?: string;
34
+ };
35
+ /**
36
+ * List all gallery entries from a catalog.
37
+ * Returns blueprints first, then templates.
38
+ */
39
+ export declare function listCatalogEntries(catalog: ValentinoCatalogV1): GalleryEntry[];
40
+ /**
41
+ * List gallery entries from a pages manifest (existing pages as starting points).
42
+ * Optionally provide a specs map (pageId -> PageSpecV1) for richer metadata.
43
+ */
44
+ export declare function listPageEntries(manifest: PagesManifestV1, specs?: Map<string, PageSpecV1>): GalleryEntry[];
45
+ /**
46
+ * List all gallery entries: catalog + manifest pages.
47
+ */
48
+ export declare function listAllGalleryEntries(catalog: ValentinoCatalogV1, manifest?: PagesManifestV1, specs?: Map<string, PageSpecV1>): GalleryEntry[];
49
+ /**
50
+ * Filter gallery entries by criteria.
51
+ */
52
+ export declare function filterGalleryEntries(entries: GalleryEntry[], filter: GalleryFilter): GalleryEntry[];
53
+ //# sourceMappingURL=gallery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gallery.d.ts","sourceRoot":"","sources":["../../src/core/gallery.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACR,kBAAkB,EAGlB,UAAU,EACV,eAAe,EAGlB,MAAM,YAAY,CAAC;AAMpB,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAEjE,MAAM,MAAM,YAAY,GAAG;IACvB,yDAAyD;IACzD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,gBAAgB,CAAC;IACvB,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,YAAY,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IACxB,IAAI,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAqEF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,YAAY,EAAE,CAY9E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC3B,QAAQ,EAAE,eAAe,EACzB,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAChC,YAAY,EAAE,CAIhB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACjC,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,CAAC,EAAE,eAAe,EAC1B,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAChC,YAAY,EAAE,CAMhB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAChC,OAAO,EAAE,YAAY,EAAE,EACvB,MAAM,EAAE,aAAa,GACtB,YAAY,EAAE,CAgBhB"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Template Gallery — Pure helpers for enumerating catalog entries.
3
+ * PBI #610 — Provides gallery-ready metadata from ValentinoCatalogV1.
4
+ *
5
+ * No DOM, no fetch — pure functions only.
6
+ * The consumer (portal) renders the gallery UI.
7
+ */
8
+ // ---------------------------------------------------------------------------
9
+ // Helpers
10
+ // ---------------------------------------------------------------------------
11
+ /** Convert a kebab-case or camelCase ID to a human-readable name */
12
+ function humanize(id) {
13
+ return id
14
+ .replace(/[-_]/g, ' ')
15
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
16
+ .replace(/\b\w/g, c => c.toUpperCase())
17
+ .trim();
18
+ }
19
+ function uniqueSectionTypes(sections) {
20
+ return [...new Set(sections.map(s => s.type))];
21
+ }
22
+ // ---------------------------------------------------------------------------
23
+ // Entry builders
24
+ // ---------------------------------------------------------------------------
25
+ function blueprintToEntry(id, entry) {
26
+ const spec = entry.spec;
27
+ return {
28
+ id,
29
+ kind: 'blueprint',
30
+ name: humanize(id),
31
+ description: `Blueprint: ${spec.sections.length} sections, profile ${spec.profile || 'generic'}`,
32
+ profile: spec.profile,
33
+ themeId: spec.themeId,
34
+ sectionCount: spec.sections.length,
35
+ sectionTypes: uniqueSectionTypes(spec.sections),
36
+ governanceTier: entry.governance?.tier,
37
+ };
38
+ }
39
+ function templateToEntry(id, entry) {
40
+ return {
41
+ id,
42
+ kind: 'template',
43
+ name: humanize(id),
44
+ description: `Template: profile ${entry.page?.profile || 'generic'}`,
45
+ profile: entry.page?.profile,
46
+ themeId: entry.page?.themeId,
47
+ sectionCount: 0,
48
+ sectionTypes: [],
49
+ };
50
+ }
51
+ function manifestPageToEntry(page, pageSpec) {
52
+ const sections = pageSpec?.sections || [];
53
+ return {
54
+ id: page.id,
55
+ kind: 'page',
56
+ name: humanize(page.id),
57
+ description: `Page: ${page.route}`,
58
+ profile: pageSpec?.profile,
59
+ themeId: pageSpec?.themeId,
60
+ sectionCount: sections.length,
61
+ sectionTypes: uniqueSectionTypes(sections),
62
+ };
63
+ }
64
+ // ---------------------------------------------------------------------------
65
+ // Public API
66
+ // ---------------------------------------------------------------------------
67
+ /**
68
+ * List all gallery entries from a catalog.
69
+ * Returns blueprints first, then templates.
70
+ */
71
+ export function listCatalogEntries(catalog) {
72
+ const entries = [];
73
+ for (const [id, entry] of Object.entries(catalog.pageBlueprints)) {
74
+ entries.push(blueprintToEntry(id, entry));
75
+ }
76
+ for (const [id, entry] of Object.entries(catalog.templates)) {
77
+ entries.push(templateToEntry(id, entry));
78
+ }
79
+ return entries;
80
+ }
81
+ /**
82
+ * List gallery entries from a pages manifest (existing pages as starting points).
83
+ * Optionally provide a specs map (pageId -> PageSpecV1) for richer metadata.
84
+ */
85
+ export function listPageEntries(manifest, specs) {
86
+ return manifest.pages
87
+ .filter(p => p.status === 'published')
88
+ .map(p => manifestPageToEntry(p, specs?.get(p.id)));
89
+ }
90
+ /**
91
+ * List all gallery entries: catalog + manifest pages.
92
+ */
93
+ export function listAllGalleryEntries(catalog, manifest, specs) {
94
+ const entries = listCatalogEntries(catalog);
95
+ if (manifest) {
96
+ entries.push(...listPageEntries(manifest, specs));
97
+ }
98
+ return entries;
99
+ }
100
+ /**
101
+ * Filter gallery entries by criteria.
102
+ */
103
+ export function filterGalleryEntries(entries, filter) {
104
+ return entries.filter(entry => {
105
+ if (filter.kind) {
106
+ const kinds = Array.isArray(filter.kind) ? filter.kind : [filter.kind];
107
+ if (!kinds.includes(entry.kind))
108
+ return false;
109
+ }
110
+ if (filter.profile && entry.profile !== filter.profile)
111
+ return false;
112
+ if (filter.sectionType && !entry.sectionTypes.includes(filter.sectionType))
113
+ return false;
114
+ if (filter.search) {
115
+ const q = filter.search.toLowerCase();
116
+ if (!entry.name.toLowerCase().includes(q) && !entry.description.toLowerCase().includes(q)) {
117
+ return false;
118
+ }
119
+ }
120
+ return true;
121
+ });
122
+ }
123
+ //# sourceMappingURL=gallery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gallery.js","sourceRoot":"","sources":["../../src/core/gallery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=gallery.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gallery.test.d.ts","sourceRoot":"","sources":["../../src/core/gallery.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,127 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { listCatalogEntries, listPageEntries, listAllGalleryEntries, filterGalleryEntries } from './gallery.js';
3
+ const catalog = {
4
+ version: '1',
5
+ templates: {
6
+ 'product-tpl': { page: { profile: 'product-surface', themeId: 'dark' } },
7
+ },
8
+ sectionPresets: {},
9
+ transitionProfiles: {},
10
+ pageBlueprints: {
11
+ 'landing-bp': {
12
+ spec: {
13
+ version: '1',
14
+ id: 'landing-bp',
15
+ profile: 'home-signature',
16
+ sections: [
17
+ { type: 'hero', titleKey: 'bp.hero.title' },
18
+ { type: 'cards', variant: 'catalog', items: [{ titleKey: 'bp.card1' }] },
19
+ { type: 'cta', titleKey: 'bp.cta.title' },
20
+ ],
21
+ },
22
+ },
23
+ 'about-bp': {
24
+ spec: {
25
+ version: '1',
26
+ id: 'about-bp',
27
+ profile: 'reading-manifesto',
28
+ sections: [
29
+ { type: 'hero', titleKey: 'about.hero.title' },
30
+ { type: 'manifesto', contentPrefix: 'about.manifesto' },
31
+ ],
32
+ },
33
+ governance: { tier: 'standard' },
34
+ },
35
+ },
36
+ };
37
+ const manifest = {
38
+ version: '1',
39
+ pages: [
40
+ { id: 'home', route: '/', spec: 'home.json', status: 'published' },
41
+ { id: 'draft-page', route: '/draft', spec: 'draft.json', status: 'draft' },
42
+ { id: 'about', route: '/about', spec: 'about.json', status: 'published' },
43
+ ],
44
+ };
45
+ describe('listCatalogEntries', () => {
46
+ it('returns blueprints and templates', () => {
47
+ const entries = listCatalogEntries(catalog);
48
+ expect(entries).toHaveLength(3); // 2 blueprints + 1 template
49
+ });
50
+ it('blueprints have section metadata', () => {
51
+ const entries = listCatalogEntries(catalog);
52
+ const landing = entries.find(e => e.id === 'landing-bp');
53
+ expect(landing).toBeDefined();
54
+ expect(landing.kind).toBe('blueprint');
55
+ expect(landing.sectionCount).toBe(3);
56
+ expect(landing.sectionTypes).toContain('hero');
57
+ expect(landing.sectionTypes).toContain('cards');
58
+ expect(landing.sectionTypes).toContain('cta');
59
+ });
60
+ it('templates have kind template', () => {
61
+ const entries = listCatalogEntries(catalog);
62
+ const tpl = entries.find(e => e.id === 'product-tpl');
63
+ expect(tpl).toBeDefined();
64
+ expect(tpl.kind).toBe('template');
65
+ expect(tpl.profile).toBe('product-surface');
66
+ });
67
+ it('includes governance tier', () => {
68
+ const entries = listCatalogEntries(catalog);
69
+ const about = entries.find(e => e.id === 'about-bp');
70
+ expect(about.governanceTier).toBe('standard');
71
+ });
72
+ });
73
+ describe('listPageEntries', () => {
74
+ it('returns only published pages', () => {
75
+ const entries = listPageEntries(manifest);
76
+ expect(entries).toHaveLength(2);
77
+ expect(entries.map(e => e.id)).toContain('home');
78
+ expect(entries.map(e => e.id)).toContain('about');
79
+ expect(entries.map(e => e.id)).not.toContain('draft-page');
80
+ });
81
+ it('entries have kind page', () => {
82
+ const entries = listPageEntries(manifest);
83
+ expect(entries.every(e => e.kind === 'page')).toBe(true);
84
+ });
85
+ });
86
+ describe('listAllGalleryEntries', () => {
87
+ it('combines catalog and manifest', () => {
88
+ const entries = listAllGalleryEntries(catalog, manifest);
89
+ expect(entries.length).toBe(5); // 2 bp + 1 tpl + 2 published pages
90
+ });
91
+ it('works with catalog only', () => {
92
+ const entries = listAllGalleryEntries(catalog);
93
+ expect(entries).toHaveLength(3);
94
+ });
95
+ });
96
+ describe('filterGalleryEntries', () => {
97
+ const all = listAllGalleryEntries(catalog, manifest);
98
+ it('filters by kind', () => {
99
+ const blueprints = filterGalleryEntries(all, { kind: 'blueprint' });
100
+ expect(blueprints).toHaveLength(2);
101
+ expect(blueprints.every(e => e.kind === 'blueprint')).toBe(true);
102
+ });
103
+ it('filters by multiple kinds', () => {
104
+ const result = filterGalleryEntries(all, { kind: ['blueprint', 'template'] });
105
+ expect(result).toHaveLength(3);
106
+ });
107
+ it('filters by profile', () => {
108
+ const result = filterGalleryEntries(all, { profile: 'home-signature' });
109
+ expect(result.length).toBeGreaterThanOrEqual(1);
110
+ expect(result.every(e => e.profile === 'home-signature')).toBe(true);
111
+ });
112
+ it('filters by section type', () => {
113
+ const result = filterGalleryEntries(all, { sectionType: 'manifesto' });
114
+ expect(result.length).toBeGreaterThanOrEqual(1);
115
+ expect(result.every(e => e.sectionTypes.includes('manifesto'))).toBe(true);
116
+ });
117
+ it('filters by search text', () => {
118
+ const result = filterGalleryEntries(all, { search: 'landing' });
119
+ expect(result.length).toBeGreaterThanOrEqual(1);
120
+ });
121
+ it('combines filters', () => {
122
+ const result = filterGalleryEntries(all, { kind: 'blueprint', profile: 'home-signature' });
123
+ expect(result).toHaveLength(1);
124
+ expect(result[0].id).toBe('landing-bp');
125
+ });
126
+ });
127
+ //# sourceMappingURL=gallery.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gallery.test.js","sourceRoot":"","sources":["../../src/core/gallery.test.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * CMS Guardrails — Pure validation rules for CMS capabilities.
3
3
  * Migrated from easyway-portal scripts/guardrails-cms.mjs (PBI #606).
4
+ * Extended with media, language, breadcrumb, and route checks (PBI #605).
4
5
  * No I/O (no fs, no fetch) — works on pre-loaded data only.
5
- * I/O-dependent checks (media orphans, SEO from disk, encoding) stay in the consumer.
6
6
  */
7
7
  import type { PagesManifestV1 } from './types.js';
8
8
  import type { RedirectRule } from './redirects.js';
9
9
  import type { SeoSpec } from './seo.js';
10
+ import type { MediaManifest } from './media.js';
10
11
  export type CmsWarning = {
11
12
  type: string;
12
13
  severity: 'warning' | 'error';
@@ -30,11 +31,40 @@ export declare function checkRedirects(manifest: PagesManifestV1, rules: Redirec
30
31
  export declare function checkSeoCompleteness(manifest: PagesManifestV1, specsById: Map<string, {
31
32
  seo?: SeoSpec;
32
33
  }>): CmsWarning[];
34
+ /**
35
+ * Check that ogImage in page specs references an existing media key.
36
+ * Requires pre-loaded specs and media manifest.
37
+ */
38
+ export declare function checkOgImageExists(specsById: Map<string, {
39
+ seo?: SeoSpec;
40
+ }>, mediaManifest: MediaManifest): CmsWarning[];
41
+ /**
42
+ * Find media assets not referenced by any page spec.
43
+ * Scans all spec sections for media keys in known fields.
44
+ */
45
+ export declare function checkMediaOrphans(specsById: Map<string, {
46
+ seo?: SeoSpec;
47
+ sections?: Array<Record<string, any>>;
48
+ }>, mediaManifest: MediaManifest): CmsWarning[];
49
+ /** Warn about media assets without alt text (accessibility). */
50
+ export declare function checkMediaMissingAlt(mediaManifest: MediaManifest): CmsWarning[];
51
+ /** Warn about pages with deep routes (3+ segments) that may need intermediate breadcrumb pages. */
52
+ export declare function checkBreadcrumbDepth(manifest: PagesManifestV1): CmsWarning[];
53
+ /**
54
+ * Check language coverage: keys in one language map missing from another.
55
+ * Accepts flattened key sets (consumer handles the JSON loading/flattening).
56
+ */
57
+ export declare function checkLanguageCoverage(contentByLang: Map<string, Set<string>>): CmsWarning[];
58
+ /** Error if manifest has duplicate routes. */
59
+ export declare function checkDuplicateRoutes(manifest: PagesManifestV1): CmsWarning[];
33
60
  /** Run all pure CMS guardrails. Returns combined warnings. */
34
61
  export declare function collectPureCmsWarnings(manifest: PagesManifestV1, options?: {
35
62
  redirectRules?: RedirectRule[];
36
63
  specsById?: Map<string, {
37
64
  seo?: SeoSpec;
65
+ sections?: Array<Record<string, any>>;
38
66
  }>;
67
+ mediaManifest?: MediaManifest;
68
+ contentByLang?: Map<string, Set<string>>;
39
69
  }): CmsWarning[];
40
70
  //# sourceMappingURL=guardrails-cms.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"guardrails-cms.d.ts","sourceRoot":"","sources":["../../src/core/guardrails-cms.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAkB,eAAe,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,MAAM,UAAU,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,iEAAiE;AACjE,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,GAAG,UAAU,EAAE,CAazE;AAED,kEAAkE;AAClE,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,eAAe,GAAG,UAAU,EAAE,CAyB/E;AAED,yCAAyC;AACzC,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,eAAe,GAAG,UAAU,EAAE,CAUhF;AAED,uDAAuD;AACvD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,GAAG,UAAU,EAAE,CAWtE;AAED,yDAAyD;AACzD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,UAAU,EAAE,CAyB7F;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAC1C,UAAU,EAAE,CAsBd;AAED,8DAA8D;AAC9D,wBAAgB,sBAAsB,CAClC,QAAQ,EAAE,eAAe,EACzB,OAAO,CAAC,EAAE;IACN,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,GAAG,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC9C,GACF,UAAU,EAAE,CASd"}
1
+ {"version":3,"file":"guardrails-cms.d.ts","sourceRoot":"","sources":["../../src/core/guardrails-cms.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAkB,eAAe,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,KAAK,EAAc,aAAa,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,MAAM,UAAU,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,iEAAiE;AACjE,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,GAAG,UAAU,EAAE,CAazE;AAED,kEAAkE;AAClE,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,eAAe,GAAG,UAAU,EAAE,CAyB/E;AAED,yCAAyC;AACzC,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,eAAe,GAAG,UAAU,EAAE,CAUhF;AAED,uDAAuD;AACvD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,GAAG,UAAU,EAAE,CAWtE;AAED,yDAAyD;AACzD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,UAAU,EAAE,CAyB7F;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAC1C,UAAU,EAAE,CAsBd;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAC9B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,EACzC,aAAa,EAAE,aAAa,GAC7B,UAAU,EAAE,CAmBd;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC7B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;CAAE,CAAC,EAChF,aAAa,EAAE,aAAa,GAC7B,UAAU,EAAE,CAiCd;AAED,gEAAgE;AAChE,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,aAAa,GAAG,UAAU,EAAE,CAa/E;AAED,mGAAmG;AACnG,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,eAAe,GAAG,UAAU,EAAE,CAmB5E;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACjC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,GACxC,UAAU,EAAE,CAkCd;AAED,8CAA8C;AAC9C,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,eAAe,GAAG,UAAU,EAAE,CAkB5E;AAED,8DAA8D;AAC9D,wBAAgB,sBAAsB,CAClC,QAAQ,EAAE,eAAe,EACzB,OAAO,CAAC,EAAE;IACN,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,GAAG,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;KAAE,CAAC,CAAC;IAClF,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;CAC5C,GACF,UAAU,EAAE,CAed"}
@@ -125,6 +125,160 @@ export function checkSeoCompleteness(manifest, specsById) {
125
125
  }
126
126
  return warnings;
127
127
  }
128
+ /**
129
+ * Check that ogImage in page specs references an existing media key.
130
+ * Requires pre-loaded specs and media manifest.
131
+ */
132
+ export function checkOgImageExists(specsById, mediaManifest) {
133
+ const warnings = [];
134
+ const mediaKeys = new Set(mediaManifest.assets.map((a) => a.key));
135
+ for (const [pageId, spec] of specsById) {
136
+ const ogImage = spec.seo?.ogImage;
137
+ if (!ogImage)
138
+ continue;
139
+ // Skip if it looks like a path/URL (only validate media key references)
140
+ if (ogImage.includes('/') || ogImage.includes('.'))
141
+ continue;
142
+ if (!mediaKeys.has(ogImage)) {
143
+ warnings.push({
144
+ type: 'cms-og-image-missing',
145
+ severity: 'warning',
146
+ file: `/pages/${pageId}.json`,
147
+ message: `Page "${pageId}" has seo.ogImage="${ogImage}" but no matching media asset found`,
148
+ });
149
+ }
150
+ }
151
+ return warnings;
152
+ }
153
+ /**
154
+ * Find media assets not referenced by any page spec.
155
+ * Scans all spec sections for media keys in known fields.
156
+ */
157
+ export function checkMediaOrphans(specsById, mediaManifest) {
158
+ const warnings = [];
159
+ if (!mediaManifest.assets.length)
160
+ return warnings;
161
+ // Collect all referenced media keys from specs
162
+ const referencedKeys = new Set();
163
+ for (const [, spec] of specsById) {
164
+ // OG image
165
+ if (spec.seo?.ogImage)
166
+ referencedKeys.add(spec.seo.ogImage);
167
+ // Scan sections for common media fields
168
+ for (const section of spec.sections ?? []) {
169
+ const json = JSON.stringify(section);
170
+ for (const asset of mediaManifest.assets) {
171
+ if (json.includes(asset.key) || json.includes(asset.file)) {
172
+ referencedKeys.add(asset.key);
173
+ }
174
+ }
175
+ }
176
+ }
177
+ for (const asset of mediaManifest.assets) {
178
+ if (!referencedKeys.has(asset.key)) {
179
+ warnings.push({
180
+ type: 'cms-media-orphan',
181
+ severity: 'warning',
182
+ file: 'media.manifest.json',
183
+ message: `Media asset "${asset.key}" (${asset.file}) is not referenced by any page spec`,
184
+ });
185
+ }
186
+ }
187
+ return warnings;
188
+ }
189
+ /** Warn about media assets without alt text (accessibility). */
190
+ export function checkMediaMissingAlt(mediaManifest) {
191
+ const warnings = [];
192
+ for (const asset of mediaManifest.assets) {
193
+ if (!asset.alt || !asset.alt.trim()) {
194
+ warnings.push({
195
+ type: 'cms-media-missing-alt',
196
+ severity: 'warning',
197
+ file: 'media.manifest.json',
198
+ message: `Media asset "${asset.key}" has no alt text — accessibility issue`,
199
+ });
200
+ }
201
+ }
202
+ return warnings;
203
+ }
204
+ /** Warn about pages with deep routes (3+ segments) that may need intermediate breadcrumb pages. */
205
+ export function checkBreadcrumbDepth(manifest) {
206
+ const warnings = [];
207
+ const routes = new Set(manifest.pages.map((p) => p.route));
208
+ for (const page of manifest.pages) {
209
+ const segments = page.route.split('/').filter(Boolean);
210
+ if (segments.length < 3)
211
+ continue;
212
+ // Check if parent route exists
213
+ const parentRoute = '/' + segments.slice(0, -1).join('/');
214
+ if (!routes.has(parentRoute)) {
215
+ warnings.push({
216
+ type: 'cms-breadcrumb-depth',
217
+ severity: 'warning',
218
+ file: 'pages.manifest.json',
219
+ message: `Page "${page.id}" has deep route "${page.route}" but parent "${parentRoute}" doesn't exist — breadcrumb will have gaps`,
220
+ });
221
+ }
222
+ }
223
+ return warnings;
224
+ }
225
+ /**
226
+ * Check language coverage: keys in one language map missing from another.
227
+ * Accepts flattened key sets (consumer handles the JSON loading/flattening).
228
+ */
229
+ export function checkLanguageCoverage(contentByLang) {
230
+ const warnings = [];
231
+ const langs = [...contentByLang.keys()];
232
+ for (let i = 0; i < langs.length; i++) {
233
+ for (let j = i + 1; j < langs.length; j++) {
234
+ const langA = langs[i];
235
+ const langB = langs[j];
236
+ const keysA = contentByLang.get(langA);
237
+ const keysB = contentByLang.get(langB);
238
+ for (const key of keysA) {
239
+ if (!keysB.has(key)) {
240
+ warnings.push({
241
+ type: 'cms-language-coverage',
242
+ severity: 'warning',
243
+ file: `content/${langA}.json`,
244
+ message: `Key "${key}" exists in ${langA.toUpperCase()} but not in ${langB.toUpperCase()}`,
245
+ });
246
+ }
247
+ }
248
+ for (const key of keysB) {
249
+ if (!keysA.has(key)) {
250
+ warnings.push({
251
+ type: 'cms-language-coverage',
252
+ severity: 'warning',
253
+ file: `content/${langB}.json`,
254
+ message: `Key "${key}" exists in ${langB.toUpperCase()} but not in ${langA.toUpperCase()}`,
255
+ });
256
+ }
257
+ }
258
+ }
259
+ }
260
+ return warnings;
261
+ }
262
+ /** Error if manifest has duplicate routes. */
263
+ export function checkDuplicateRoutes(manifest) {
264
+ const warnings = [];
265
+ const seen = new Map();
266
+ for (const page of manifest.pages) {
267
+ const existing = seen.get(page.route);
268
+ if (existing) {
269
+ warnings.push({
270
+ type: 'cms-duplicate-route',
271
+ severity: 'error',
272
+ file: 'pages.manifest.json',
273
+ message: `Route "${page.route}" is claimed by both "${existing}" and "${page.id}"`,
274
+ });
275
+ }
276
+ else {
277
+ seen.set(page.route, page.id);
278
+ }
279
+ }
280
+ return warnings;
281
+ }
128
282
  /** Run all pure CMS guardrails. Returns combined warnings. */
129
283
  export function collectPureCmsWarnings(manifest, options) {
130
284
  return [
@@ -132,8 +286,14 @@ export function collectPureCmsWarnings(manifest, options) {
132
286
  ...checkPublishAtCoherence(manifest),
133
287
  ...checkMaintenanceModeLeak(manifest),
134
288
  ...check404Exists(manifest),
289
+ ...checkDuplicateRoutes(manifest),
290
+ ...checkBreadcrumbDepth(manifest),
135
291
  ...checkRedirects(manifest, options?.redirectRules ?? []),
136
292
  ...(options?.specsById ? checkSeoCompleteness(manifest, options.specsById) : []),
293
+ ...(options?.specsById && options?.mediaManifest ? checkOgImageExists(options.specsById, options.mediaManifest) : []),
294
+ ...(options?.specsById && options?.mediaManifest ? checkMediaOrphans(options.specsById, options.mediaManifest) : []),
295
+ ...(options?.mediaManifest ? checkMediaMissingAlt(options.mediaManifest) : []),
296
+ ...(options?.contentByLang ? checkLanguageCoverage(options.contentByLang) : []),
137
297
  ];
138
298
  }
139
299
  //# sourceMappingURL=guardrails-cms.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"guardrails-cms.js","sourceRoot":"","sources":["../../src/core/guardrails-cms.ts"],"names":[],"mappings":"AAiBA,iEAAiE;AACjE,MAAM,UAAU,iBAAiB,CAAC,QAAyB;IACvD,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO;YAAE,SAAS;QACtC,IAAI,IAAI,CAAC,SAAS;YAAE,SAAS;QAC7B,QAAQ,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,kBAAkB;YACxB,QAAQ,EAAE,SAAS;YACnB,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,SAAS,IAAI,CAAC,EAAE,+EAA+E;SAC3G,CAAC,CAAC;IACP,CAAC;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,uBAAuB,CAAC,QAAyB;IAC7D,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,SAAS;QAC9B,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnC,IAAI,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;YACrB,QAAQ,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,uBAAuB;gBAC7B,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE,qBAAqB;gBAC3B,OAAO,EAAE,SAAS,IAAI,CAAC,EAAE,6BAA6B,IAAI,CAAC,SAAS,GAAG;aAC1E,CAAC,CAAC;YACH,SAAS;QACb,CAAC;QACD,IAAI,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACtE,QAAQ,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,oBAAoB;gBAC1B,QAAQ,EAAE,SAAS;gBACnB,IAAI,EAAE,qBAAqB;gBAC3B,OAAO,EAAE,SAAS,IAAI,CAAC,EAAE,gCAAgC,IAAI,CAAC,SAAS,oBAAoB,IAAI,CAAC,MAAM,4BAA4B;aACrI,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,wBAAwB,CAAC,QAAyB;IAC9D,IAAI,QAAQ,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;QACpC,OAAO,CAAC;gBACJ,IAAI,EAAE,6BAA6B;gBACnC,QAAQ,EAAE,SAAS;gBACnB,IAAI,EAAE,qBAAqB;gBAC3B,OAAO,EAAE,8FAA8F;aAC1G,CAAC,CAAC;IACP,CAAC;IACD,OAAO,EAAE,CAAC;AACd,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,cAAc,CAAC,QAAyB;IACpD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC;IAChE,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,OAAO,CAAC;gBACJ,IAAI,EAAE,iBAAiB;gBACvB,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE,qBAAqB;gBAC3B,OAAO,EAAE,kFAAkF;aAC9F,CAAC,CAAC;IACP,CAAC;IACD,OAAO,EAAE,CAAC;AACd,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,cAAc,CAAC,QAAyB,EAAE,KAAqB;IAC3E,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAClC,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IACnC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAEhE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAC5B,QAAQ,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,6BAA6B;gBACnC,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE,gBAAgB;gBACtB,OAAO,EAAE,aAAa,IAAI,CAAC,IAAI,QAAQ,IAAI,CAAC,EAAE,gCAAgC;aACjF,CAAC,CAAC;QACP,CAAC;QACD,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1D,IAAI,WAAW,EAAE,CAAC;YACd,QAAQ,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,oBAAoB;gBAC1B,QAAQ,EAAE,SAAS;gBACnB,IAAI,EAAE,gBAAgB;gBACtB,OAAO,EAAE,oBAAoB,IAAI,CAAC,IAAI,QAAQ,IAAI,CAAC,EAAE,QAAQ,WAAW,CAAC,EAAE,GAAG;aACjF,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAChC,QAAyB,EACzB,SAAyC;IAEzC,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC;IAE7E,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE,SAAS;QACxB,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO;YAAE,SAAS;QACtC,IAAI,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC;YAAE,SAAS;QAC9C,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,SAAS;QAEnC,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;YAClE,QAAQ,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,iBAAiB;gBACvB,QAAQ,EAAE,SAAS;gBACnB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,SAAS,IAAI,CAAC,EAAE,+EAA+E;aAC3G,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,sBAAsB,CAClC,QAAyB,EACzB,OAGC;IAED,OAAO;QACH,GAAG,iBAAiB,CAAC,QAAQ,CAAC;QAC9B,GAAG,uBAAuB,CAAC,QAAQ,CAAC;QACpC,GAAG,wBAAwB,CAAC,QAAQ,CAAC;QACrC,GAAG,cAAc,CAAC,QAAQ,CAAC;QAC3B,GAAG,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,aAAa,IAAI,EAAE,CAAC;QACzD,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,QAAQ,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KACnF,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"guardrails-cms.js","sourceRoot":"","sources":["../../src/core/guardrails-cms.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * LLMs.txt Generator — Pure functions to produce llms.txt and llms-full.txt
3
+ * from a PagesManifest and optional content/spec data.
4
+ * No I/O — the consumer provides the loaded data.
5
+ *
6
+ * llms.txt = L0 Matrioska (max ~50 lines, site index for LLM agents)
7
+ * llms-full.txt = L1 Matrioska (detailed per-page breakdown)
8
+ *
9
+ * Follows the emerging llms.txt standard (like robots.txt for AI crawlers).
10
+ */
11
+ import type { PagesManifestV1, PageSpecV1 } from './types.js';
12
+ export type LlmsGeneratorOptions = {
13
+ /** Site name displayed in the header */
14
+ siteName: string;
15
+ /** One-line tagline / description */
16
+ tagline?: string;
17
+ /** Base URL (e.g. https://example.com) — used in llms-full.txt links */
18
+ baseUrl?: string;
19
+ /** Capabilities bullet points */
20
+ capabilities?: string[];
21
+ /** Content resolver: given a content key, returns the string value (or undefined) */
22
+ resolveContent?: (key: string) => string | undefined;
23
+ /** Pre-loaded page specs by page id (for llms-full.txt section details) */
24
+ specsById?: Map<string, PageSpecV1>;
25
+ };
26
+ /**
27
+ * Generate llms.txt — compact site index (L0 Matrioska).
28
+ * Max ~50 lines: header, pages list, capabilities.
29
+ */
30
+ export declare function generateLlmsTxt(manifest: PagesManifestV1, options: LlmsGeneratorOptions): string;
31
+ /**
32
+ * Generate llms-full.txt — detailed per-page breakdown (L1 Matrioska).
33
+ * Includes section types, SEO metadata, and page purpose.
34
+ */
35
+ export declare function generateLlmsFullTxt(manifest: PagesManifestV1, options: LlmsGeneratorOptions): string;
36
+ //# sourceMappingURL=llms-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llms-generator.d.ts","sourceRoot":"","sources":["../../src/core/llms-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG9D,MAAM,MAAM,oBAAoB,GAAG;IAC/B,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,qFAAqF;IACrF,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACrD,2EAA2E;IAC3E,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACvC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,eAAe,CAC3B,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,oBAAoB,GAC9B,MAAM,CAwCR;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAC/B,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,oBAAoB,GAC9B,MAAM,CAuDR"}