@glyphjs/compiler 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,809 @@
1
+ 'use strict';
2
+
3
+ var parser = require('@glyphjs/parser');
4
+ var ir = require('@glyphjs/ir');
5
+ var yaml = require('yaml');
6
+ var schemas = require('@glyphjs/schemas');
7
+
8
+ // src/compile.ts
9
+
10
+ // src/inline.ts
11
+ function convertPhrasingContent(nodes) {
12
+ const result = [];
13
+ for (const node of nodes) {
14
+ const converted = convertSingleNode(node);
15
+ if (converted) {
16
+ result.push(converted);
17
+ }
18
+ }
19
+ return result;
20
+ }
21
+ function convertSingleNode(node) {
22
+ switch (node.type) {
23
+ case "text":
24
+ return { type: "text", value: node.value };
25
+ case "strong":
26
+ return {
27
+ type: "strong",
28
+ children: convertPhrasingContent(node.children)
29
+ };
30
+ case "emphasis":
31
+ return {
32
+ type: "emphasis",
33
+ children: convertPhrasingContent(node.children)
34
+ };
35
+ case "delete":
36
+ return {
37
+ type: "delete",
38
+ children: convertPhrasingContent(node.children)
39
+ };
40
+ case "inlineCode":
41
+ return { type: "inlineCode", value: node.value };
42
+ case "link": {
43
+ const linkNode = {
44
+ type: "link",
45
+ url: node.url,
46
+ children: convertPhrasingContent(node.children)
47
+ };
48
+ if (node.title != null) {
49
+ linkNode.title = node.title;
50
+ }
51
+ return linkNode;
52
+ }
53
+ case "image": {
54
+ const imgNode = {
55
+ type: "image",
56
+ src: node.url
57
+ };
58
+ if (node.alt != null) {
59
+ imgNode.alt = node.alt;
60
+ }
61
+ if (node.title != null) {
62
+ imgNode.title = node.title;
63
+ }
64
+ return imgNode;
65
+ }
66
+ case "break":
67
+ return { type: "break" };
68
+ default: {
69
+ const unknown = node;
70
+ if (typeof unknown["value"] === "string") {
71
+ return { type: "text", value: unknown["value"] };
72
+ }
73
+ return null;
74
+ }
75
+ }
76
+ }
77
+
78
+ // src/diagnostics.ts
79
+ function createDiagnostic(source, severity, code, message, position, details) {
80
+ const diag = { severity, code, message, source };
81
+ if (position) {
82
+ diag.position = position;
83
+ }
84
+ if (details !== void 0) {
85
+ diag.details = details;
86
+ }
87
+ return diag;
88
+ }
89
+ function createSchemaError(componentType, message, position, details) {
90
+ return createDiagnostic(
91
+ "schema",
92
+ "error",
93
+ "SCHEMA_VALIDATION_FAILED",
94
+ `Schema validation failed for ui:${componentType}: ${message}`,
95
+ position,
96
+ details
97
+ );
98
+ }
99
+ function createUnknownComponentInfo(componentType, position) {
100
+ return createDiagnostic(
101
+ "compiler",
102
+ "info",
103
+ "UNKNOWN_COMPONENT_TYPE",
104
+ `Unknown component type "ui:${componentType}". Block preserved as-is.`,
105
+ position
106
+ );
107
+ }
108
+ function createYamlError(componentType, yamlError, position) {
109
+ return createDiagnostic(
110
+ "parser",
111
+ "error",
112
+ "YAML_PARSE_ERROR",
113
+ `YAML parse error in ui:${componentType}: ${yamlError}`,
114
+ position
115
+ );
116
+ }
117
+
118
+ // src/ast-to-ir.ts
119
+ var DEFAULT_POSITION = {
120
+ start: { line: 0, column: 0 },
121
+ end: { line: 0, column: 0 }
122
+ };
123
+ function isGlyphUIBlock(node) {
124
+ return node.type === "glyphUIBlock";
125
+ }
126
+ function translateNode(node, ctx) {
127
+ if (isGlyphUIBlock(node)) {
128
+ return translateGlyphUIBlock(node, ctx);
129
+ }
130
+ return translateMdastNode(node, ctx);
131
+ }
132
+ function translateGlyphUIBlock(node, ctx) {
133
+ const componentType = node.componentType;
134
+ const blockType = `ui:${componentType}`;
135
+ const position = node.position ?? DEFAULT_POSITION;
136
+ const blockDiagnostics = [];
137
+ const blockId = node.glyphId ? node.glyphId : ir.generateBlockId(ctx.documentId, blockType, node.rawYaml);
138
+ if (node.glyphId) {
139
+ ctx.blockIdMap.set(node.glyphId, blockId);
140
+ }
141
+ if (node.yamlError) {
142
+ const diag = createYamlError(componentType, node.yamlError, position);
143
+ blockDiagnostics.push(diag);
144
+ ctx.diagnostics.push(diag);
145
+ }
146
+ let data = node.parsedData ?? {};
147
+ if (node.parsedData) {
148
+ const schema = schemas.componentSchemas.get(componentType);
149
+ if (schema) {
150
+ const result = schema.safeParse(node.parsedData);
151
+ if (!result.success) {
152
+ const zodErrors = result.error.issues.map(
153
+ (issue) => `${issue.path.join(".")}: ${issue.message}`
154
+ ).join("; ");
155
+ const diag = createSchemaError(componentType, zodErrors, position, result.error.issues);
156
+ blockDiagnostics.push(diag);
157
+ ctx.diagnostics.push(diag);
158
+ data = node.parsedData;
159
+ } else {
160
+ data = result.data;
161
+ }
162
+ } else {
163
+ const diag = createUnknownComponentInfo(componentType, position);
164
+ blockDiagnostics.push(diag);
165
+ ctx.diagnostics.push(diag);
166
+ }
167
+ }
168
+ if (node.refs && node.refs.length > 0) {
169
+ processRefs(node.refs, blockId, ctx);
170
+ }
171
+ const block = {
172
+ id: blockId,
173
+ type: blockType,
174
+ data,
175
+ position
176
+ };
177
+ if (blockDiagnostics.length > 0) {
178
+ block.diagnostics = blockDiagnostics;
179
+ }
180
+ return block;
181
+ }
182
+ function processRefs(refs, sourceBlockId, ctx) {
183
+ for (const ref of refs) {
184
+ const reference = {
185
+ id: ir.generateBlockId(ctx.documentId, "ref", `${sourceBlockId}->${ref.target}`),
186
+ type: ref.type ?? "navigates-to",
187
+ sourceBlockId,
188
+ targetBlockId: ref.target
189
+ };
190
+ if (ref.label) {
191
+ reference.label = ref.label;
192
+ }
193
+ if (ref.sourceAnchor) {
194
+ reference.sourceAnchor = ref.sourceAnchor;
195
+ }
196
+ if (ref.targetAnchor) {
197
+ reference.targetAnchor = ref.targetAnchor;
198
+ }
199
+ if (ref.bidirectional) {
200
+ reference.bidirectional = ref.bidirectional;
201
+ }
202
+ reference.unresolved = true;
203
+ ctx.references.push(reference);
204
+ }
205
+ }
206
+ function translateMdastNode(node, ctx) {
207
+ const position = node.position ?? DEFAULT_POSITION;
208
+ switch (node.type) {
209
+ case "heading":
210
+ return translateHeading(node, position, ctx);
211
+ case "paragraph":
212
+ return translateParagraph(node, position, ctx);
213
+ case "list":
214
+ return translateList(node, position, ctx);
215
+ case "code":
216
+ return translateCode(node, position, ctx);
217
+ case "blockquote":
218
+ return translateBlockquote(node, position, ctx);
219
+ case "image":
220
+ return translateImage(node, position, ctx);
221
+ case "thematicBreak":
222
+ return translateThematicBreak(position, ctx);
223
+ case "html":
224
+ return translateHtml(node, position, ctx);
225
+ case "yaml":
226
+ return null;
227
+ default:
228
+ return null;
229
+ }
230
+ }
231
+ function translateHeading(node, position, ctx) {
232
+ const depth = node["depth"] ?? 1;
233
+ const children = convertPhrasingContent(node.children ?? []);
234
+ const content = inlineNodesToText(children);
235
+ return {
236
+ id: ir.generateBlockId(ctx.documentId, "heading", content),
237
+ type: "heading",
238
+ data: { depth, children },
239
+ position
240
+ };
241
+ }
242
+ function translateParagraph(node, position, ctx) {
243
+ const children = convertPhrasingContent(node.children ?? []);
244
+ const content = inlineNodesToText(children);
245
+ return {
246
+ id: ir.generateBlockId(ctx.documentId, "paragraph", content),
247
+ type: "paragraph",
248
+ data: { children },
249
+ position
250
+ };
251
+ }
252
+ function translateList(node, position, ctx) {
253
+ const ordered = node["ordered"] ?? false;
254
+ const start = ordered ? node["start"] ?? 1 : void 0;
255
+ const items = translateListItems(node.children ?? []);
256
+ const content = listDataToText({ items });
257
+ const data = { ordered, items };
258
+ if (start !== void 0) {
259
+ data.start = start;
260
+ }
261
+ return {
262
+ id: ir.generateBlockId(ctx.documentId, "list", content),
263
+ type: "list",
264
+ data,
265
+ position
266
+ };
267
+ }
268
+ function translateListItems(listItemNodes) {
269
+ const items = [];
270
+ for (const itemNode of listItemNodes) {
271
+ if (itemNode.type !== "listItem") continue;
272
+ const itemChildren = itemNode.children ?? [];
273
+ let inlineChildren = [];
274
+ let subList;
275
+ for (const child of itemChildren) {
276
+ if (child.type === "paragraph") {
277
+ inlineChildren = convertPhrasingContent(child.children ?? []);
278
+ } else if (child.type === "list") {
279
+ const subOrdered = child["ordered"] ?? false;
280
+ const subStart = subOrdered ? child["start"] ?? 1 : void 0;
281
+ const subItems = translateListItems(child.children ?? []);
282
+ subList = { ordered: subOrdered, items: subItems };
283
+ if (subStart !== void 0) {
284
+ subList.start = subStart;
285
+ }
286
+ }
287
+ }
288
+ const item = { children: inlineChildren };
289
+ if (subList) {
290
+ item.subList = subList;
291
+ }
292
+ items.push(item);
293
+ }
294
+ return items;
295
+ }
296
+ function translateCode(node, position, ctx) {
297
+ const value = node.value ?? "";
298
+ const language = node["lang"] ?? void 0;
299
+ const meta = node["meta"] ?? void 0;
300
+ const data = { value };
301
+ if (language) {
302
+ data["language"] = language;
303
+ }
304
+ if (meta) {
305
+ data["meta"] = meta;
306
+ }
307
+ return {
308
+ id: ir.generateBlockId(ctx.documentId, "code", value),
309
+ type: "code",
310
+ data,
311
+ position
312
+ };
313
+ }
314
+ function translateBlockquote(node, position, ctx) {
315
+ const allInlineNodes = [];
316
+ for (const child of node.children ?? []) {
317
+ if (child.type === "paragraph") {
318
+ const inlines = convertPhrasingContent(child.children ?? []);
319
+ allInlineNodes.push(...inlines);
320
+ }
321
+ }
322
+ const content = inlineNodesToText(allInlineNodes);
323
+ return {
324
+ id: ir.generateBlockId(ctx.documentId, "blockquote", content),
325
+ type: "blockquote",
326
+ data: { children: allInlineNodes },
327
+ position
328
+ };
329
+ }
330
+ function translateImage(node, position, ctx) {
331
+ const src = node["url"] ?? "";
332
+ const alt = node["alt"] ?? void 0;
333
+ const title = node["title"] ?? void 0;
334
+ const data = { src };
335
+ if (alt) {
336
+ data["alt"] = alt;
337
+ }
338
+ if (title) {
339
+ data["title"] = title;
340
+ }
341
+ return {
342
+ id: ir.generateBlockId(ctx.documentId, "image", src),
343
+ type: "image",
344
+ data,
345
+ position
346
+ };
347
+ }
348
+ function translateThematicBreak(position, ctx) {
349
+ return {
350
+ id: ir.generateBlockId(ctx.documentId, "thematic-break", "---"),
351
+ type: "thematic-break",
352
+ data: {},
353
+ position
354
+ };
355
+ }
356
+ function translateHtml(node, position, ctx) {
357
+ const value = node.value ?? "";
358
+ return {
359
+ id: ir.generateBlockId(ctx.documentId, "html", value),
360
+ type: "html",
361
+ data: { value },
362
+ position
363
+ };
364
+ }
365
+ function inlineNodesToText(nodes) {
366
+ return nodes.map((node) => {
367
+ switch (node.type) {
368
+ case "text":
369
+ return node.value;
370
+ case "inlineCode":
371
+ return node.value;
372
+ case "strong":
373
+ case "emphasis":
374
+ case "delete":
375
+ return inlineNodesToText(node.children);
376
+ case "link":
377
+ return inlineNodesToText(node.children);
378
+ case "image":
379
+ return node.alt ?? "";
380
+ case "break":
381
+ return "\n";
382
+ default:
383
+ return "";
384
+ }
385
+ }).join("");
386
+ }
387
+ function listDataToText(data) {
388
+ return data.items.map((item) => {
389
+ let text = inlineNodesToText(item.children);
390
+ if (item.subList) {
391
+ text += "\n" + listDataToText(item.subList);
392
+ }
393
+ return text;
394
+ }).join("\n");
395
+ }
396
+ var GLYPH_LINK_PREFIX = "#glyph:";
397
+ function extractInlineReferences(block, documentId) {
398
+ const references = [];
399
+ const inlineNodes = extractInlineNodes(block);
400
+ for (const node of inlineNodes) {
401
+ if (node.type === "link" && node.url.startsWith(GLYPH_LINK_PREFIX)) {
402
+ const targetBlockId = node.url.slice(GLYPH_LINK_PREFIX.length);
403
+ if (!targetBlockId) continue;
404
+ const label = inlineNodesToPlainText(node.children);
405
+ const reference = {
406
+ id: ir.generateBlockId(documentId, "ref", `${block.id}->${targetBlockId}`),
407
+ type: "navigates-to",
408
+ sourceBlockId: block.id,
409
+ targetBlockId,
410
+ unresolved: true
411
+ };
412
+ if (label) {
413
+ reference.label = label;
414
+ }
415
+ references.push(reference);
416
+ }
417
+ }
418
+ return references;
419
+ }
420
+ function extractAllInlineReferences(blocks, documentId) {
421
+ const references = [];
422
+ for (const block of blocks) {
423
+ const blockRefs = extractInlineReferences(block, documentId);
424
+ references.push(...blockRefs);
425
+ if (block.children) {
426
+ const childRefs = extractAllInlineReferences(block.children, documentId);
427
+ references.push(...childRefs);
428
+ }
429
+ }
430
+ return references;
431
+ }
432
+ function resolveReferences(references, blocks, diagnostics) {
433
+ const blockIdSet = collectAllBlockIds(blocks);
434
+ for (const ref of references) {
435
+ if (blockIdSet.has(ref.targetBlockId)) {
436
+ ref.unresolved = false;
437
+ } else {
438
+ ref.unresolved = true;
439
+ diagnostics.push(
440
+ createDiagnostic(
441
+ "compiler",
442
+ "warning",
443
+ "UNRESOLVED_REFERENCE",
444
+ `Reference target "${ref.targetBlockId}" was not found in the document.`
445
+ )
446
+ );
447
+ }
448
+ }
449
+ }
450
+ function collectAllBlockIds(blocks) {
451
+ const ids = /* @__PURE__ */ new Set();
452
+ for (const block of blocks) {
453
+ ids.add(block.id);
454
+ if (block.children) {
455
+ for (const id of collectAllBlockIds(block.children)) {
456
+ ids.add(id);
457
+ }
458
+ }
459
+ }
460
+ return ids;
461
+ }
462
+ function validateGlyphIdUniqueness(blockIdMap, blocks, diagnostics) {
463
+ const glyphIdOccurrences = /* @__PURE__ */ new Map();
464
+ for (const glyphId of blockIdMap.keys()) {
465
+ const count = countBlocksWithGlyphId(blocks, glyphId);
466
+ glyphIdOccurrences.set(glyphId, count);
467
+ }
468
+ for (const [glyphId, count] of glyphIdOccurrences) {
469
+ if (count > 1) {
470
+ diagnostics.push(
471
+ createDiagnostic(
472
+ "compiler",
473
+ "error",
474
+ "DUPLICATE_GLYPH_ID",
475
+ `Duplicate glyph-id "${glyphId}" found on ${String(count)} blocks. Block IDs must be unique within a document.`
476
+ )
477
+ );
478
+ }
479
+ }
480
+ }
481
+ function countBlocksWithGlyphId(blocks, glyphId) {
482
+ let count = 0;
483
+ for (const block of blocks) {
484
+ if (block.id === glyphId) {
485
+ count++;
486
+ }
487
+ }
488
+ return count;
489
+ }
490
+ function extractInlineNodes(block) {
491
+ const data = block.data;
492
+ const nodes = [];
493
+ if (Array.isArray(data["children"])) {
494
+ nodes.push(...data["children"]);
495
+ }
496
+ if (Array.isArray(data["items"])) {
497
+ for (const item of data["items"]) {
498
+ if (Array.isArray(item.children)) {
499
+ nodes.push(...item.children);
500
+ }
501
+ }
502
+ }
503
+ return nodes;
504
+ }
505
+ function inlineNodesToPlainText(nodes) {
506
+ return nodes.map((node) => {
507
+ switch (node.type) {
508
+ case "text":
509
+ return node.value;
510
+ case "inlineCode":
511
+ return node.value;
512
+ case "strong":
513
+ case "emphasis":
514
+ case "delete":
515
+ return inlineNodesToPlainText(node.children);
516
+ case "link":
517
+ return inlineNodesToPlainText(node.children);
518
+ case "image":
519
+ return node.alt ?? "";
520
+ case "break":
521
+ return "\n";
522
+ default:
523
+ return "";
524
+ }
525
+ }).join("");
526
+ }
527
+ function compileContainerBlocks(blocks, ctx) {
528
+ for (const block of blocks) {
529
+ if (block.type === "ui:tabs") {
530
+ compileTabsBlock(block, ctx);
531
+ } else if (block.type === "ui:steps") {
532
+ compileStepsBlock(block, ctx);
533
+ }
534
+ }
535
+ }
536
+ function compileTabsBlock(block, ctx) {
537
+ const data = block.data;
538
+ const tabs = data["tabs"];
539
+ if (!Array.isArray(tabs)) return;
540
+ const allChildren = [];
541
+ for (const tab of tabs) {
542
+ if (typeof tab.content !== "string") continue;
543
+ const childBlocks = parseContentToBlocks(tab.content, block, ctx);
544
+ allChildren.push(...childBlocks);
545
+ }
546
+ if (allChildren.length > 0) {
547
+ block.children = allChildren;
548
+ }
549
+ }
550
+ function compileStepsBlock(block, ctx) {
551
+ const data = block.data;
552
+ const steps = data["steps"];
553
+ if (!Array.isArray(steps)) return;
554
+ const allChildren = [];
555
+ for (const step of steps) {
556
+ if (typeof step.content !== "string") continue;
557
+ const childBlocks = parseContentToBlocks(step.content, block, ctx);
558
+ allChildren.push(...childBlocks);
559
+ }
560
+ if (allChildren.length > 0) {
561
+ block.children = allChildren;
562
+ }
563
+ }
564
+ function parseContentToBlocks(content, parentBlock, ctx) {
565
+ const ast = parser.parseGlyphMarkdown(content);
566
+ const blocks = [];
567
+ for (const child of ast.children) {
568
+ if (child.type === "glyphUIBlock") {
569
+ ctx.diagnostics.push(
570
+ createDiagnostic(
571
+ "compiler",
572
+ "warning",
573
+ "NESTED_UI_COMPONENT",
574
+ `Nested ui: component found inside container block "${parentBlock.id}". Nested ui: components inside tabs/steps are not supported in v1 and will be ignored.`,
575
+ child.position
576
+ )
577
+ );
578
+ continue;
579
+ }
580
+ const block = translateNode(child, ctx);
581
+ if (block) {
582
+ blocks.push(block);
583
+ }
584
+ }
585
+ return blocks;
586
+ }
587
+ function hasNestedUiBlocks(content) {
588
+ return /```ui:/m.test(content);
589
+ }
590
+ function validateContainerBlocks(blocks, diagnostics) {
591
+ for (const block of blocks) {
592
+ if (block.type === "ui:tabs") {
593
+ validateTabsData(block, diagnostics);
594
+ } else if (block.type === "ui:steps") {
595
+ validateStepsData(block, diagnostics);
596
+ }
597
+ }
598
+ }
599
+ function validateTabsData(block, _diagnostics) {
600
+ const data = block.data;
601
+ const tabs = data["tabs"];
602
+ if (!Array.isArray(tabs) || tabs.length === 0) {
603
+ return;
604
+ }
605
+ for (const tab of tabs) {
606
+ if (!tab.label) {
607
+ _diagnostics.push(
608
+ createDiagnostic(
609
+ "compiler",
610
+ "warning",
611
+ "MISSING_TAB_LABEL",
612
+ `A tab in block "${block.id}" is missing a label.`,
613
+ block.position
614
+ )
615
+ );
616
+ }
617
+ }
618
+ }
619
+ function validateStepsData(block, _diagnostics) {
620
+ const data = block.data;
621
+ const steps = data["steps"];
622
+ if (!Array.isArray(steps) || steps.length === 0) {
623
+ return;
624
+ }
625
+ for (const step of steps) {
626
+ if (!step.title) {
627
+ _diagnostics.push(
628
+ createDiagnostic(
629
+ "compiler",
630
+ "warning",
631
+ "MISSING_STEP_TITLE",
632
+ `A step in block "${block.id}" is missing a title.`,
633
+ block.position
634
+ )
635
+ );
636
+ }
637
+ }
638
+ }
639
+
640
+ // src/compile.ts
641
+ function compile(markdown, options) {
642
+ const diagnostics = [];
643
+ const ast = parser.parseGlyphMarkdown(markdown);
644
+ const { metadata, layout, frontmatterGlyphId } = extractFrontmatter(ast.children, diagnostics);
645
+ const documentId = options?.documentId ?? ir.generateDocumentId({
646
+ glyphId: frontmatterGlyphId,
647
+ filePath: options?.filePath,
648
+ content: markdown
649
+ });
650
+ if (options?.filePath && !metadata.sourceFile) {
651
+ metadata.sourceFile = options.filePath;
652
+ }
653
+ const references = [];
654
+ const ctx = {
655
+ documentId,
656
+ diagnostics,
657
+ references,
658
+ blockIdMap: /* @__PURE__ */ new Map()
659
+ };
660
+ const blocks = [];
661
+ for (const child of ast.children) {
662
+ const block = translateNode(child, ctx);
663
+ if (block) {
664
+ blocks.push(block);
665
+ }
666
+ }
667
+ compileContainerBlocks(blocks, ctx);
668
+ validateContainerBlocks(blocks, diagnostics);
669
+ inferMetadata(metadata, blocks);
670
+ const blockIds = blocks.map((b) => b.id);
671
+ const resolvedIds = ir.resolveBlockIdCollisions(blockIds);
672
+ for (let i = 0; i < blocks.length; i++) {
673
+ const block = blocks[i];
674
+ const resolvedId = resolvedIds[i];
675
+ if (block && resolvedId) {
676
+ block.id = resolvedId;
677
+ }
678
+ }
679
+ validateGlyphIdUniqueness(ctx.blockIdMap, blocks, diagnostics);
680
+ const inlineRefs = extractAllInlineReferences(blocks, documentId);
681
+ references.push(...inlineRefs);
682
+ resolveReferences(references, blocks, diagnostics);
683
+ const ir$1 = {
684
+ version: "1.0.0",
685
+ id: documentId,
686
+ metadata,
687
+ blocks,
688
+ references,
689
+ layout
690
+ };
691
+ const hasErrors = diagnostics.some((d) => d.severity === "error");
692
+ return { ir: ir$1, diagnostics, hasErrors };
693
+ }
694
+ function extractFrontmatter(children, diagnostics) {
695
+ const metadata = {};
696
+ let layout = { mode: "document", spacing: "normal" };
697
+ let frontmatterGlyphId;
698
+ const firstChild = children[0];
699
+ if (firstChild && firstChild.type === "yaml" && typeof firstChild.value === "string") {
700
+ try {
701
+ const parsed = yaml.parse(firstChild.value);
702
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
703
+ const fm = parsed;
704
+ if (typeof fm["glyph-id"] === "string") {
705
+ frontmatterGlyphId = fm["glyph-id"];
706
+ }
707
+ if (typeof fm["title"] === "string") {
708
+ metadata.title = fm["title"];
709
+ }
710
+ if (typeof fm["description"] === "string") {
711
+ metadata.description = fm["description"];
712
+ }
713
+ if (Array.isArray(fm["authors"])) {
714
+ metadata.authors = fm["authors"].filter(
715
+ (a) => typeof a === "string"
716
+ );
717
+ }
718
+ if (typeof fm["createdAt"] === "string") {
719
+ metadata.createdAt = fm["createdAt"];
720
+ }
721
+ if (Array.isArray(fm["tags"])) {
722
+ metadata.tags = fm["tags"].filter(
723
+ (t) => typeof t === "string"
724
+ );
725
+ }
726
+ if (fm["layout"] && typeof fm["layout"] === "object" && !Array.isArray(fm["layout"])) {
727
+ const rawLayout = fm["layout"];
728
+ layout = {
729
+ mode: isLayoutMode(rawLayout["mode"]) ? rawLayout["mode"] : "document",
730
+ spacing: isLayoutSpacing(rawLayout["spacing"]) ? rawLayout["spacing"] : "normal"
731
+ };
732
+ if (typeof rawLayout["columns"] === "number") {
733
+ layout.columns = rawLayout["columns"];
734
+ }
735
+ if (typeof rawLayout["maxWidth"] === "string") {
736
+ layout.maxWidth = rawLayout["maxWidth"];
737
+ }
738
+ }
739
+ }
740
+ } catch (err) {
741
+ const message = err instanceof Error ? err.message : String(err);
742
+ diagnostics.push(
743
+ createDiagnostic(
744
+ "parser",
745
+ "error",
746
+ "FRONTMATTER_PARSE_ERROR",
747
+ `Failed to parse frontmatter YAML: ${message}`,
748
+ firstChild.position
749
+ )
750
+ );
751
+ }
752
+ }
753
+ return { metadata, layout, frontmatterGlyphId };
754
+ }
755
+ function isLayoutMode(value) {
756
+ return value === "document" || value === "dashboard" || value === "presentation";
757
+ }
758
+ function isLayoutSpacing(value) {
759
+ return value === "compact" || value === "normal" || value === "relaxed";
760
+ }
761
+ function inferMetadata(metadata, blocks) {
762
+ if (!metadata.title) {
763
+ const firstHeading = blocks.find(
764
+ (b) => b.type === "heading" && b.data["depth"] === 1
765
+ );
766
+ if (firstHeading) {
767
+ const data = firstHeading.data;
768
+ if (data.children) {
769
+ metadata.title = data.children.map((node) => {
770
+ if ("value" in node && typeof node.value === "string") {
771
+ return node.value;
772
+ }
773
+ return "";
774
+ }).join("");
775
+ }
776
+ }
777
+ }
778
+ if (!metadata.description) {
779
+ const firstParagraph = blocks.find((b) => b.type === "paragraph");
780
+ if (firstParagraph) {
781
+ const data = firstParagraph.data;
782
+ if (data.children) {
783
+ metadata.description = data.children.map((node) => {
784
+ if ("value" in node && typeof node.value === "string") {
785
+ return node.value;
786
+ }
787
+ return "";
788
+ }).join("");
789
+ }
790
+ }
791
+ }
792
+ }
793
+
794
+ exports.compile = compile;
795
+ exports.compileContainerBlocks = compileContainerBlocks;
796
+ exports.convertPhrasingContent = convertPhrasingContent;
797
+ exports.createDiagnostic = createDiagnostic;
798
+ exports.createSchemaError = createSchemaError;
799
+ exports.createUnknownComponentInfo = createUnknownComponentInfo;
800
+ exports.createYamlError = createYamlError;
801
+ exports.extractAllInlineReferences = extractAllInlineReferences;
802
+ exports.extractInlineReferences = extractInlineReferences;
803
+ exports.hasNestedUiBlocks = hasNestedUiBlocks;
804
+ exports.resolveReferences = resolveReferences;
805
+ exports.translateNode = translateNode;
806
+ exports.validateContainerBlocks = validateContainerBlocks;
807
+ exports.validateGlyphIdUniqueness = validateGlyphIdUniqueness;
808
+ //# sourceMappingURL=index.cjs.map
809
+ //# sourceMappingURL=index.cjs.map