@refrakt-md/runes 0.14.4 → 0.16.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 (119) hide show
  1. package/dist/aggregate-resolve.d.ts +4 -0
  2. package/dist/aggregate-resolve.d.ts.map +1 -0
  3. package/dist/aggregate-resolve.js +209 -0
  4. package/dist/aggregate-resolve.js.map +1 -0
  5. package/dist/collection-helpers.d.ts +101 -0
  6. package/dist/collection-helpers.d.ts.map +1 -0
  7. package/dist/collection-helpers.js +206 -0
  8. package/dist/collection-helpers.js.map +1 -0
  9. package/dist/collection-resolve.d.ts +5 -0
  10. package/dist/collection-resolve.d.ts.map +1 -0
  11. package/dist/collection-resolve.js +209 -0
  12. package/dist/collection-resolve.js.map +1 -0
  13. package/dist/config.d.ts +46 -4
  14. package/dist/config.d.ts.map +1 -1
  15. package/dist/config.js +208 -88
  16. package/dist/config.js.map +1 -1
  17. package/dist/deferred-body.d.ts +19 -0
  18. package/dist/deferred-body.d.ts.map +1 -0
  19. package/dist/deferred-body.js +70 -0
  20. package/dist/deferred-body.js.map +1 -0
  21. package/dist/drawer-pipeline.d.ts +33 -0
  22. package/dist/drawer-pipeline.d.ts.map +1 -0
  23. package/dist/drawer-pipeline.js +206 -0
  24. package/dist/drawer-pipeline.js.map +1 -0
  25. package/dist/expand-pipeline.d.ts +51 -0
  26. package/dist/expand-pipeline.d.ts.map +1 -0
  27. package/dist/expand-pipeline.js +314 -0
  28. package/dist/expand-pipeline.js.map +1 -0
  29. package/dist/field-match.d.ts +43 -0
  30. package/dist/field-match.d.ts.map +1 -0
  31. package/dist/field-match.js +121 -0
  32. package/dist/field-match.js.map +1 -0
  33. package/dist/functions.d.ts +36 -0
  34. package/dist/functions.d.ts.map +1 -0
  35. package/dist/functions.js +74 -0
  36. package/dist/functions.js.map +1 -0
  37. package/dist/index.d.ts +34 -4
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +95 -4
  40. package/dist/index.js.map +1 -1
  41. package/dist/lang-map.d.ts +32 -0
  42. package/dist/lang-map.d.ts.map +1 -0
  43. package/dist/lang-map.js +76 -0
  44. package/dist/lang-map.js.map +1 -0
  45. package/dist/lib/index.d.ts +6 -0
  46. package/dist/lib/index.d.ts.map +1 -1
  47. package/dist/lib/index.js +9 -0
  48. package/dist/lib/index.js.map +1 -1
  49. package/dist/lib/read-file.d.ts +78 -0
  50. package/dist/lib/read-file.d.ts.map +1 -0
  51. package/dist/lib/read-file.js +166 -0
  52. package/dist/lib/read-file.js.map +1 -0
  53. package/dist/nodes.d.ts.map +1 -1
  54. package/dist/nodes.js +18 -2
  55. package/dist/nodes.js.map +1 -1
  56. package/dist/outline-scope.d.ts +46 -0
  57. package/dist/outline-scope.d.ts.map +1 -0
  58. package/dist/outline-scope.js +208 -0
  59. package/dist/outline-scope.js.map +1 -0
  60. package/dist/plugins.d.ts +13 -0
  61. package/dist/plugins.d.ts.map +1 -1
  62. package/dist/plugins.js +65 -1
  63. package/dist/plugins.js.map +1 -1
  64. package/dist/relationships-resolve.d.ts +4 -0
  65. package/dist/relationships-resolve.d.ts.map +1 -0
  66. package/dist/relationships-resolve.js +180 -0
  67. package/dist/relationships-resolve.js.map +1 -0
  68. package/dist/snippet-pipeline.d.ts +42 -0
  69. package/dist/snippet-pipeline.d.ts.map +1 -0
  70. package/dist/snippet-pipeline.js +219 -0
  71. package/dist/snippet-pipeline.js.map +1 -0
  72. package/dist/tags/aggregate.d.ts +19 -0
  73. package/dist/tags/aggregate.d.ts.map +1 -0
  74. package/dist/tags/aggregate.js +59 -0
  75. package/dist/tags/aggregate.js.map +1 -0
  76. package/dist/tags/card.d.ts +25 -0
  77. package/dist/tags/card.d.ts.map +1 -0
  78. package/dist/tags/card.js +138 -0
  79. package/dist/tags/card.js.map +1 -0
  80. package/dist/tags/collection.d.ts +10 -0
  81. package/dist/tags/collection.d.ts.map +1 -0
  82. package/dist/tags/collection.js +54 -0
  83. package/dist/tags/collection.js.map +1 -0
  84. package/dist/tags/conversation.d.ts.map +1 -1
  85. package/dist/tags/conversation.js +26 -6
  86. package/dist/tags/conversation.js.map +1 -1
  87. package/dist/tags/drawer.d.ts +26 -0
  88. package/dist/tags/drawer.d.ts.map +1 -0
  89. package/dist/tags/drawer.js +134 -0
  90. package/dist/tags/drawer.js.map +1 -0
  91. package/dist/tags/expand.d.ts +22 -0
  92. package/dist/tags/expand.d.ts.map +1 -0
  93. package/dist/tags/expand.js +76 -0
  94. package/dist/tags/expand.js.map +1 -0
  95. package/dist/tags/progress.d.ts +9 -0
  96. package/dist/tags/progress.d.ts.map +1 -0
  97. package/dist/tags/progress.js +96 -0
  98. package/dist/tags/progress.js.map +1 -0
  99. package/dist/tags/relationships.d.ts +12 -0
  100. package/dist/tags/relationships.d.ts.map +1 -0
  101. package/dist/tags/relationships.js +62 -0
  102. package/dist/tags/relationships.js.map +1 -0
  103. package/dist/tags/snippet.d.ts +19 -0
  104. package/dist/tags/snippet.d.ts.map +1 -0
  105. package/dist/tags/snippet.js +49 -0
  106. package/dist/tags/snippet.js.map +1 -0
  107. package/dist/util.d.ts +11 -0
  108. package/dist/util.d.ts.map +1 -1
  109. package/dist/util.js +35 -0
  110. package/dist/util.js.map +1 -1
  111. package/dist/xref-patterns.d.ts +57 -0
  112. package/dist/xref-patterns.d.ts.map +1 -0
  113. package/dist/xref-patterns.js +140 -0
  114. package/dist/xref-patterns.js.map +1 -0
  115. package/dist/xref-resolve.d.ts +22 -5
  116. package/dist/xref-resolve.d.ts.map +1 -1
  117. package/dist/xref-resolve.js +203 -79
  118. package/dist/xref-resolve.js.map +1 -1
  119. package/package.json +3 -3
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Snippet pipeline hooks (SPEC-062).
3
+ *
4
+ * - **Preprocess** walks the parsed Markdoc AST, finds every `{% snippet %}`
5
+ * tag, resolves + slices its source file, and replaces the tag with a
6
+ * Markdoc `fence` node. The fence carries `content` and `language` (so
7
+ * the existing code-block transform syntax-highlights it identically to
8
+ * a triple-backtick fence) plus `data-snippet-source` / `data-snippet-lines`
9
+ * attributes for downstream tooling and the wrap step.
10
+ *
11
+ * - **PostProcess** walks the rendered renderable tree, finds every `<pre>`
12
+ * element carrying `data-snippet-source`, and — when not nested under a
13
+ * fence-consuming container (`data-rune="code-group"`, `data-rune="diff"`)
14
+ * — wraps it in `<figure class="rf-snippet">` so themes can style snippet
15
+ * blocks distinctly from regular code blocks (and tooling can find
16
+ * `data-source-path` on the figure).
17
+ *
18
+ * This separation is the SPEC-062 composition story: container runes see
19
+ * snippet output as a regular fence (because preprocess made it one) and
20
+ * consume it transparently; standalone snippets get the figure chrome via
21
+ * the wrap step. Captions / titles are intentionally not provided — wrap
22
+ * a snippet in `{% codegroup title="..." %}` if you want a labelled chrome.
23
+ */
24
+ import type { Node } from '@markdoc/markdoc';
25
+ import type { PreprocessContext, PreprocessPage, PipelineContext, TransformedPage, AggregatedData } from '@refrakt-md/types';
26
+ /**
27
+ * Preprocess: replace every `{% snippet %}` tag in the AST with a `fence`
28
+ * node carrying the resolved file content. After this runs, no snippet
29
+ * tags remain in the AST — only fences (some "snippet-derived" identified
30
+ * by their `data-snippet-source` attribute).
31
+ */
32
+ export declare function preprocessSnippets(ast: Node, page: PreprocessPage, ctx: PreprocessContext): Node | void;
33
+ /**
34
+ * PostProcess: wrap standalone snippet-derived `<pre>` elements in the
35
+ * snippet figure chrome. Run as part of `corePipelineHooks.postProcess`.
36
+ *
37
+ * Container-nested snippets (inside `<div data-rune="code-group">` or
38
+ * `<div data-rune="diff">` outputs) are left alone — the container's chrome
39
+ * is already there and the figure would be duplicate.
40
+ */
41
+ export declare function wrapStandaloneSnippets(page: TransformedPage, _aggregated: AggregatedData, _ctx: PipelineContext): TransformedPage;
42
+ //# sourceMappingURL=snippet-pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snippet-pipeline.d.ts","sourceRoot":"","sources":["../src/snippet-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAiC7H;;;;;GAKG;AACH,wBAAgB,kBAAkB,CACjC,GAAG,EAAE,IAAI,EACT,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,iBAAiB,GACpB,IAAI,GAAG,IAAI,CAYb;AAsGD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACrC,IAAI,EAAE,eAAe,EACrB,WAAW,EAAE,cAAc,EAC3B,IAAI,EAAE,eAAe,GACnB,eAAe,CAIjB"}
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Snippet pipeline hooks (SPEC-062).
3
+ *
4
+ * - **Preprocess** walks the parsed Markdoc AST, finds every `{% snippet %}`
5
+ * tag, resolves + slices its source file, and replaces the tag with a
6
+ * Markdoc `fence` node. The fence carries `content` and `language` (so
7
+ * the existing code-block transform syntax-highlights it identically to
8
+ * a triple-backtick fence) plus `data-snippet-source` / `data-snippet-lines`
9
+ * attributes for downstream tooling and the wrap step.
10
+ *
11
+ * - **PostProcess** walks the rendered renderable tree, finds every `<pre>`
12
+ * element carrying `data-snippet-source`, and — when not nested under a
13
+ * fence-consuming container (`data-rune="code-group"`, `data-rune="diff"`)
14
+ * — wraps it in `<figure class="rf-snippet">` so themes can style snippet
15
+ * blocks distinctly from regular code blocks (and tooling can find
16
+ * `data-source-path` on the figure).
17
+ *
18
+ * This separation is the SPEC-062 composition story: container runes see
19
+ * snippet output as a regular fence (because preprocess made it one) and
20
+ * consume it transparently; standalone snippets get the figure chrome via
21
+ * the wrap step. Captions / titles are intentionally not provided — wrap
22
+ * a snippet in `{% codegroup title="..." %}` if you want a labelled chrome.
23
+ */
24
+ import Markdoc from '@markdoc/markdoc';
25
+ import { readSnippetFile, SnippetSandboxError } from './lib/read-file.js';
26
+ import { inferLanguage } from './lang-map.js';
27
+ const { Ast, Tag } = Markdoc;
28
+ /** Resolve a Markdoc attribute value to a string. Handles literal strings
29
+ * and Markdoc `Variable` AST nodes (e.g. `path=$file.path` parses as a
30
+ * Variable, not a string). Unresolvable references (variable missing from
31
+ * the context, or attribute is some other AST shape) return an empty
32
+ * string — matching transform-time variable-evaluation behaviour. */
33
+ function resolveAttributeValue(value, variables) {
34
+ if (value === undefined || value === null)
35
+ return '';
36
+ if (typeof value === 'string')
37
+ return value;
38
+ if (typeof value === 'number' || typeof value === 'boolean')
39
+ return String(value);
40
+ if (typeof value === 'object' && '$$mdtype' in value) {
41
+ const node = value;
42
+ if (node.$$mdtype === 'Variable' && Array.isArray(node.path)) {
43
+ let current = variables;
44
+ for (const segment of node.path) {
45
+ if (current === null || current === undefined)
46
+ return '';
47
+ current = current[segment];
48
+ }
49
+ return current === null || current === undefined ? '' : String(current);
50
+ }
51
+ }
52
+ return '';
53
+ }
54
+ /** Containers whose output consumes their fence children — wrapping a
55
+ * snippet-derived `<pre>` inside them would be duplicate chrome. */
56
+ const FENCE_CONSUMING_CONTAINERS = new Set(['code-group', 'diff']);
57
+ /**
58
+ * Preprocess: replace every `{% snippet %}` tag in the AST with a `fence`
59
+ * node carrying the resolved file content. After this runs, no snippet
60
+ * tags remain in the AST — only fences (some "snippet-derived" identified
61
+ * by their `data-snippet-source` attribute).
62
+ */
63
+ export function preprocessSnippets(ast, page, ctx) {
64
+ if (!ctx.projectRoot) {
65
+ // No project root configured — silently no-op. Snippet refs will fall
66
+ // through to the schema's transform, which throws a clear error.
67
+ return;
68
+ }
69
+ let mutated = false;
70
+ walkAndReplaceSnippets(ast, page, ctx, ctx.projectRoot, (didReplace) => {
71
+ if (didReplace)
72
+ mutated = true;
73
+ });
74
+ return mutated ? ast : undefined;
75
+ }
76
+ function walkAndReplaceSnippets(node, page, ctx, projectRoot, onReplaced) {
77
+ if (!node.children)
78
+ return;
79
+ for (let i = 0; i < node.children.length; i++) {
80
+ const child = node.children[i];
81
+ if (child.type === 'tag' && child.tag === 'snippet') {
82
+ // Always produce a fence — successful resolution returns the
83
+ // real fence; sandbox / missing-file / variable-resolution errors
84
+ // produce an error fence so the snippet tag never reaches the
85
+ // schema's transform (which throws). The build keeps going and
86
+ // the failure is visible on the rendered page.
87
+ node.children[i] = resolveSnippetToFence(child, page, ctx, projectRoot);
88
+ onReplaced(true);
89
+ // Don't recurse — replaced.
90
+ continue;
91
+ }
92
+ walkAndReplaceSnippets(child, page, ctx, projectRoot, onReplaced);
93
+ }
94
+ }
95
+ /** Build a `fence` AST node that renders a clear error message in place of
96
+ * the snippet. Used when resolution fails (sandbox, missing file, malformed
97
+ * lines, unresolvable variable reference). The fence carries the original
98
+ * attempted path in `data-snippet-source` so tooling can still detect
99
+ * snippet provenance. */
100
+ function makeErrorFence(pathAttr, message) {
101
+ return new Ast.Node('fence', {
102
+ content: `snippet error: ${message}\n`,
103
+ language: 'text',
104
+ 'data-snippet-source': pathAttr || '(unresolved)',
105
+ 'data-snippet-error': message,
106
+ });
107
+ }
108
+ function resolveSnippetToFence(tag, page, ctx, projectRoot) {
109
+ const pathAttr = resolveAttributeValue(tag.attributes.path, ctx.variables);
110
+ const lines = tag.attributes.lines !== undefined
111
+ ? resolveAttributeValue(tag.attributes.lines, ctx.variables)
112
+ : undefined;
113
+ const langAttr = tag.attributes.lang !== undefined
114
+ ? resolveAttributeValue(tag.attributes.lang, ctx.variables)
115
+ : undefined;
116
+ if (!pathAttr) {
117
+ const msg = 'snippet `path` attribute is required (and an unresolvable variable reference resolves to empty)';
118
+ ctx.error(msg, page.url);
119
+ return makeErrorFence('', msg);
120
+ }
121
+ let result;
122
+ try {
123
+ result = readSnippetFile({
124
+ pathAttr,
125
+ projectRoot,
126
+ lines: lines || undefined,
127
+ referencingPage: page.relativePath,
128
+ });
129
+ }
130
+ catch (err) {
131
+ if (err instanceof SnippetSandboxError) {
132
+ ctx.error(err.message, page.url);
133
+ return makeErrorFence(pathAttr, err.message);
134
+ }
135
+ // Unexpected error type — still produce an error fence so the build
136
+ // doesn't crash on a single page.
137
+ const msg = err.message ?? String(err);
138
+ ctx.error(`snippet "${pathAttr}" failed unexpectedly: ${msg}`, page.url);
139
+ return makeErrorFence(pathAttr, msg);
140
+ }
141
+ for (const warning of result.warnings) {
142
+ ctx.warn(warning, page.url);
143
+ }
144
+ const language = (langAttr && langAttr.length > 0) ? langAttr : inferLanguage(result.relativePath);
145
+ const fenceAttrs = {
146
+ content: result.content,
147
+ language,
148
+ 'data-snippet-source': result.relativePath,
149
+ };
150
+ if (lines)
151
+ fenceAttrs['data-snippet-lines'] = lines;
152
+ // Construct a fence Ast.Node. Markdoc parses ``` blocks as
153
+ // new Ast.Node('fence', { content, language }) — same shape here.
154
+ return new Ast.Node('fence', fenceAttrs);
155
+ }
156
+ /**
157
+ * PostProcess: wrap standalone snippet-derived `<pre>` elements in the
158
+ * snippet figure chrome. Run as part of `corePipelineHooks.postProcess`.
159
+ *
160
+ * Container-nested snippets (inside `<div data-rune="code-group">` or
161
+ * `<div data-rune="diff">` outputs) are left alone — the container's chrome
162
+ * is already there and the figure would be duplicate.
163
+ */
164
+ export function wrapStandaloneSnippets(page, _aggregated, _ctx) {
165
+ const wrapped = walkAndWrap(page.renderable, /* containerAncestors */ false);
166
+ if (wrapped === page.renderable)
167
+ return page;
168
+ return { ...page, renderable: wrapped };
169
+ }
170
+ function walkAndWrap(node, insideFenceContainer) {
171
+ if (Array.isArray(node)) {
172
+ let mutated = false;
173
+ const next = node.map((c) => {
174
+ const w = walkAndWrap(c, insideFenceContainer);
175
+ if (w !== c)
176
+ mutated = true;
177
+ return w;
178
+ });
179
+ return mutated ? next : node;
180
+ }
181
+ if (!Tag.isTag(node))
182
+ return node;
183
+ const tag = node;
184
+ const dataRune = tag.attributes?.['data-rune'];
185
+ const enteredFenceContainer = typeof dataRune === 'string' && FENCE_CONSUMING_CONTAINERS.has(dataRune);
186
+ const childAncestor = insideFenceContainer || enteredFenceContainer;
187
+ // Wrap matching <pre> elements that aren't inside a fence-consuming container.
188
+ if (tag.name === 'pre' &&
189
+ tag.attributes?.['data-snippet-source'] !== undefined &&
190
+ !insideFenceContainer) {
191
+ return wrapPreInFigure(tag);
192
+ }
193
+ if (!tag.children || tag.children.length === 0)
194
+ return tag;
195
+ let mutated = false;
196
+ const newChildren = tag.children.map((c) => {
197
+ const w = walkAndWrap(c, childAncestor);
198
+ if (w !== c)
199
+ mutated = true;
200
+ return w;
201
+ });
202
+ if (!mutated)
203
+ return tag;
204
+ return new Tag(tag.name, tag.attributes, newChildren);
205
+ }
206
+ function wrapPreInFigure(preTag) {
207
+ const attrs = preTag.attributes;
208
+ const source = String(attrs['data-snippet-source'] ?? '');
209
+ const linesAttr = attrs['data-snippet-lines'] !== undefined ? String(attrs['data-snippet-lines']) : undefined;
210
+ const figureAttrs = {
211
+ class: 'rf-snippet',
212
+ 'data-rune': 'snippet',
213
+ 'data-source-path': source,
214
+ };
215
+ if (linesAttr)
216
+ figureAttrs['data-lines'] = linesAttr;
217
+ return new Tag('figure', figureAttrs, [preTag]);
218
+ }
219
+ //# sourceMappingURL=snippet-pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snippet-pipeline.js","sourceRoot":"","sources":["../src/snippet-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAGvC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;AAE7B;;;;sEAIsE;AACtE,SAAS,qBAAqB,CAAC,KAAc,EAAE,SAA8C;IAC5F,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IAClF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,UAAU,IAAK,KAAiC,EAAE,CAAC;QACnF,MAAM,IAAI,GAAG,KAA6C,CAAC;QAC3D,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9D,IAAI,OAAO,GAAY,SAAS,CAAC;YACjC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,IAAgB,EAAE,CAAC;gBAC7C,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS;oBAAE,OAAO,EAAE,CAAC;gBACzD,OAAO,GAAI,OAAmC,CAAC,OAAO,CAAC,CAAC;YACzD,CAAC;YACD,OAAO,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACzE,CAAC;IACF,CAAC;IACD,OAAO,EAAE,CAAC;AACX,CAAC;AAED;qEACqE;AACrE,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;AAEnE;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CACjC,GAAS,EACT,IAAoB,EACpB,GAAsB;IAEtB,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QACtB,sEAAsE;QACtE,iEAAiE;QACjE,OAAO;IACR,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,sBAAsB,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC,UAAU,EAAE,EAAE;QACtE,IAAI,UAAU;YAAE,OAAO,GAAG,IAAI,CAAC;IAChC,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AAClC,CAAC;AAED,SAAS,sBAAsB,CAC9B,IAAU,EACV,IAAoB,EACpB,GAAsB,EACtB,WAAmB,EACnB,UAAuC;IAEvC,IAAI,CAAC,IAAI,CAAC,QAAQ;QAAE,OAAO;IAE3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAE/B,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;YACrD,6DAA6D;YAC7D,kEAAkE;YAClE,8DAA8D;YAC9D,+DAA+D;YAC/D,+CAA+C;YAC/C,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,qBAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;YACxE,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,4BAA4B;YAC5B,SAAS;QACV,CAAC;QAED,sBAAsB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;IACnE,CAAC;AACF,CAAC;AAED;;;;0BAI0B;AAC1B,SAAS,cAAc,CAAC,QAAgB,EAAE,OAAe;IACxD,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE;QAC5B,OAAO,EAAE,kBAAkB,OAAO,IAAI;QACtC,QAAQ,EAAE,MAAM;QAChB,qBAAqB,EAAE,QAAQ,IAAI,cAAc;QACjD,oBAAoB,EAAE,OAAO;KAC7B,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAC7B,GAAS,EACT,IAAoB,EACpB,GAAsB,EACtB,WAAmB;IAEnB,MAAM,QAAQ,GAAG,qBAAqB,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IAC3E,MAAM,KAAK,GAAG,GAAG,CAAC,UAAU,CAAC,KAAK,KAAK,SAAS;QAC/C,CAAC,CAAC,qBAAqB,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,GAAG,CAAC,SAAS,CAAC;QAC5D,CAAC,CAAC,SAAS,CAAC;IACb,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,KAAK,SAAS;QACjD,CAAC,CAAC,qBAAqB,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,SAAS,CAAC;QAC3D,CAAC,CAAC,SAAS,CAAC;IAEb,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,iGAAiG,CAAC;QAC9G,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACzB,OAAO,cAAc,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACJ,MAAM,GAAG,eAAe,CAAC;YACxB,QAAQ;YACR,WAAW;YACX,KAAK,EAAE,KAAK,IAAI,SAAS;YACzB,eAAe,EAAE,IAAI,CAAC,YAAY;SAClC,CAAC,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;YACxC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YACjC,OAAO,cAAc,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAC9C,CAAC;QACD,oEAAoE;QACpE,kCAAkC;QAClC,MAAM,GAAG,GAAI,GAAa,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;QAClD,GAAG,CAAC,KAAK,CAAC,YAAY,QAAQ,0BAA0B,GAAG,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACzE,OAAO,cAAc,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACvC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAEnG,MAAM,UAAU,GAA4B;QAC3C,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,QAAQ;QACR,qBAAqB,EAAE,MAAM,CAAC,YAAY;KAC1C,CAAC;IACF,IAAI,KAAK;QAAE,UAAU,CAAC,oBAAoB,CAAC,GAAG,KAAK,CAAC;IAEpD,2DAA2D;IAC3D,kEAAkE;IAClE,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC1C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACrC,IAAqB,EACrB,WAA2B,EAC3B,IAAqB;IAErB,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,wBAAwB,CAAC,KAAK,CAAC,CAAC;IAC7E,IAAI,OAAO,KAAK,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;AACzC,CAAC;AAED,SAAS,WAAW,CAAC,IAAa,EAAE,oBAA6B;IAChE,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAC3B,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAC;YAC/C,IAAI,CAAC,KAAK,CAAC;gBAAE,OAAO,GAAG,IAAI,CAAC;YAC5B,OAAO,CAAC,CAAC;QACV,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9B,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAa,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,MAAM,GAAG,GAAG,IAAgC,CAAC;IAE7C,MAAM,QAAQ,GAAI,GAAG,CAAC,UAAkD,EAAE,CAAC,WAAW,CAAC,CAAC;IACxF,MAAM,qBAAqB,GAAG,OAAO,QAAQ,KAAK,QAAQ,IAAI,0BAA0B,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvG,MAAM,aAAa,GAAG,oBAAoB,IAAI,qBAAqB,CAAC;IAEpE,+EAA+E;IAC/E,IACC,GAAG,CAAC,IAAI,KAAK,KAAK;QACjB,GAAG,CAAC,UAAkD,EAAE,CAAC,qBAAqB,CAAC,KAAK,SAAS;QAC9F,CAAC,oBAAoB,EACpB,CAAC;QACF,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAE3D,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC1C,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,GAAG,IAAI,CAAC;QAC5B,OAAO,CAAC,CAAC;IACV,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,OAAO;QAAE,OAAO,GAAG,CAAC;IAEzB,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,UAAU,EAAE,WAAoB,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,eAAe,CAAC,MAAgC;IACxD,MAAM,KAAK,GAAG,MAAM,CAAC,UAAqC,CAAC;IAC3D,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1D,MAAM,SAAS,GAAG,KAAK,CAAC,oBAAoB,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE9G,MAAM,WAAW,GAA4B;QAC5C,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,SAAS;QACtB,kBAAkB,EAAE,MAAM;KAC1B,CAAC;IACF,IAAI,SAAS;QAAE,WAAW,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IAErD,OAAO,IAAI,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC,MAAM,CAAU,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,19 @@
1
+ import Markdoc from '@markdoc/markdoc';
2
+ export declare const AGGREGATE_SENTINEL = "__aggregate-sentinel";
3
+ /**
4
+ * `aggregate` (SPEC-076) — the third post-process-resolved query rune, beside
5
+ * `collection` and `relationships`. Where they project entities and edges, this
6
+ * one projects **numbers** — counts over the same field-match query, optionally
7
+ * broken down by group. Two modes from the same rune:
8
+ *
9
+ * - **No-body**: emits a single inline integer (the count). Replaces the
10
+ * standalone `count` rune proposal.
11
+ * - **Body-zoned**: source splits on top-level `hr` into preamble / template /
12
+ * fallback. `$item` is bound differently per zone — preamble gets totals,
13
+ * template gets the per-group projection, fallback gets zeros.
14
+ *
15
+ * The body is captured via `deferBody` and reparsed per group in the resolver
16
+ * (the same path collection's per-item template uses).
17
+ */
18
+ export declare const aggregate: Markdoc.Schema;
19
+ //# sourceMappingURL=aggregate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../src/tags/aggregate.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAKvC,eAAO,MAAM,kBAAkB,yBAAyB,CAAC;AAEzD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS,gBAsCpB,CAAC"}
@@ -0,0 +1,59 @@
1
+ import Markdoc from '@markdoc/markdoc';
2
+ const { Tag } = Markdoc;
3
+ import { createContentModelSchema, createComponentRenderable } from '../lib/index.js';
4
+ import { readDeferredBody } from '../deferred-body.js';
5
+ export const AGGREGATE_SENTINEL = '__aggregate-sentinel';
6
+ /**
7
+ * `aggregate` (SPEC-076) — the third post-process-resolved query rune, beside
8
+ * `collection` and `relationships`. Where they project entities and edges, this
9
+ * one projects **numbers** — counts over the same field-match query, optionally
10
+ * broken down by group. Two modes from the same rune:
11
+ *
12
+ * - **No-body**: emits a single inline integer (the count). Replaces the
13
+ * standalone `count` rune proposal.
14
+ * - **Body-zoned**: source splits on top-level `hr` into preamble / template /
15
+ * fallback. `$item` is bound differently per zone — preamble gets totals,
16
+ * template gets the per-group projection, fallback gets zeros.
17
+ *
18
+ * The body is captured via `deferBody` and reparsed per group in the resolver
19
+ * (the same path collection's per-item template uses).
20
+ */
21
+ export const aggregate = createContentModelSchema({
22
+ attributes: {
23
+ type: { type: String, required: false, default: '', description: 'Entity type(s), comma-separated.' },
24
+ filter: { type: String, required: false, default: '', description: 'field:value clauses defining the primary set being measured (SPEC-070 grammar).' },
25
+ value: { type: String, required: false, default: '', description: 'Optional secondary field:value clause defining the achieved subset within `filter` (e.g. value="status:done"). When set, $item.value is the count matching both; $item.percent is the ratio. Without it, the rune is a pure count + breakdown — no progress-bar semantics.' },
26
+ group: { type: String, required: false, default: '', description: 'Group-by field; omit to render the body once with totals.' },
27
+ sort: { type: String, required: false, default: '', description: 'Sort groups by `key`, `count`, `value`, or `percent` (prefix `-` for descending). Honors SPEC-072 domain-aware ordering when the group field has one.' },
28
+ limit: { type: String, required: false, default: '', description: 'Cap the number of groups (after sort).' },
29
+ empty: { type: String, required: false, default: '', description: 'Fallback text shown when the query matches no entities (self-closing form; body form uses a fallback zone). Absent → render nothing.' },
30
+ },
31
+ deferBody: true,
32
+ contentModel: { type: 'sequence', fields: [] },
33
+ transform(_resolved, attrs) {
34
+ const meta = (field, content) => new Tag('meta', { 'data-field': field, content });
35
+ const bodySource = readDeferredBody(attrs) ?? '';
36
+ const hasBody = bodySource.length > 0;
37
+ const metas = [
38
+ meta('aggregate-type', String(attrs.type ?? '')),
39
+ meta('aggregate-filter', String(attrs.filter ?? '')),
40
+ meta('aggregate-value', String(attrs.value ?? '')),
41
+ meta('aggregate-group', String(attrs.group ?? '')),
42
+ meta('aggregate-sort', String(attrs.sort ?? '')),
43
+ meta('aggregate-limit', String(attrs.limit ?? '')),
44
+ meta('aggregate-empty', String(attrs.empty ?? '')),
45
+ meta(AGGREGATE_SENTINEL, 'true'),
46
+ ];
47
+ if (bodySource)
48
+ metas.push(meta('aggregate-body', bodySource));
49
+ // Self-closing form must be inline-safe (no <section> mid-prose), so the
50
+ // outer tag is a span when there's no body. Body form is a <section>.
51
+ return createComponentRenderable({
52
+ rune: 'aggregate',
53
+ tag: hasBody ? 'section' : 'span',
54
+ properties: {},
55
+ children: metas,
56
+ });
57
+ },
58
+ });
59
+ //# sourceMappingURL=aggregate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregate.js","sourceRoot":"","sources":["../../src/tags/aggregate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import Markdoc from '@markdoc/markdoc';
2
+ /**
3
+ * `card` (SPEC-070) — a generic, self-contained content card.
4
+ *
5
+ * The body is divided by `---` (hr) into up to three zones:
6
+ *
7
+ * [media] --- body [--- footer]
8
+ *
9
+ * - **media** (optional leading zone): any content — an image, a `{% codegroup %}`,
10
+ * a `{% sandbox %}`, etc. Reuses the shared split layout (`SplitLayoutModel`):
11
+ * side-by-side with the body on wide screens, a full-bleed header on mobile
12
+ * (`data-media-position="top"`).
13
+ * - **body**: the main content.
14
+ * - **footer** (optional trailing zone): a muted meta row (date · tags · …).
15
+ *
16
+ * Zone roles are positional by count: 1 → body; 2 → media + body; 3 → media +
17
+ * body + footer. A leading empty zone (`--- body --- footer`) means "no media".
18
+ *
19
+ * `href` makes the whole card a link (a stretched link overlay, so real links
20
+ * inside body/footer stay clickable). The card carries no `$item`/registry
21
+ * knowledge — it's plain and composable, standalone or fed by a collection
22
+ * body template.
23
+ */
24
+ export declare const card: Markdoc.Schema;
25
+ //# sourceMappingURL=card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../src/tags/card.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAOvC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,IAAI,gBAwHf,CAAC"}
@@ -0,0 +1,138 @@
1
+ import Markdoc from '@markdoc/markdoc';
2
+ const { Tag } = Markdoc;
3
+ import { createContentModelSchema, createComponentRenderable, asNodes } from '../lib/index.js';
4
+ import { RenderableNodeCursor } from '../lib/renderable.js';
5
+ import { SplitLayoutModel, buildLayoutMetas, extractMediaImage } from './common.js';
6
+ /**
7
+ * `card` (SPEC-070) — a generic, self-contained content card.
8
+ *
9
+ * The body is divided by `---` (hr) into up to three zones:
10
+ *
11
+ * [media] --- body [--- footer]
12
+ *
13
+ * - **media** (optional leading zone): any content — an image, a `{% codegroup %}`,
14
+ * a `{% sandbox %}`, etc. Reuses the shared split layout (`SplitLayoutModel`):
15
+ * side-by-side with the body on wide screens, a full-bleed header on mobile
16
+ * (`data-media-position="top"`).
17
+ * - **body**: the main content.
18
+ * - **footer** (optional trailing zone): a muted meta row (date · tags · …).
19
+ *
20
+ * Zone roles are positional by count: 1 → body; 2 → media + body; 3 → media +
21
+ * body + footer. A leading empty zone (`--- body --- footer`) means "no media".
22
+ *
23
+ * `href` makes the whole card a link (a stretched link overlay, so real links
24
+ * inside body/footer stay clickable). The card carries no `$item`/registry
25
+ * knowledge — it's plain and composable, standalone or fed by a collection
26
+ * body template.
27
+ */
28
+ export const card = createContentModelSchema({
29
+ base: SplitLayoutModel,
30
+ attributes: {
31
+ href: { type: String, required: false, default: '', description: 'Optional link target; makes the whole card clickable.' },
32
+ },
33
+ contentModel: {
34
+ type: 'sequence',
35
+ fields: [{ name: 'body', match: 'any', optional: true, greedy: true }],
36
+ },
37
+ transform(resolved, attrs, config) {
38
+ // Split the body nodes on `hr` (`---`) into zones.
39
+ const nodes = asNodes(resolved.body);
40
+ const zones = [[]];
41
+ for (const n of nodes) {
42
+ if (n.type === 'hr')
43
+ zones.push([]);
44
+ else
45
+ zones[zones.length - 1].push(n);
46
+ }
47
+ let mediaNodes = [];
48
+ let bodyNodes = [];
49
+ let footerNodes = [];
50
+ if (zones.length === 1) {
51
+ bodyNodes = zones[0];
52
+ }
53
+ else if (zones.length === 2) {
54
+ mediaNodes = zones[0];
55
+ bodyNodes = zones[1];
56
+ }
57
+ else {
58
+ mediaNodes = zones[0];
59
+ footerNodes = zones[zones.length - 1];
60
+ bodyNodes = zones.slice(1, -1).flat();
61
+ }
62
+ const { metas: layoutMetas, children: layoutChildren } = buildLayoutMetas(attrs);
63
+ const children = [...layoutChildren];
64
+ // Media zone — unwrap a bare image; otherwise render arbitrary content.
65
+ if (mediaNodes.length > 0) {
66
+ const mediaCursor = new RenderableNodeCursor(Markdoc.transform(mediaNodes, config));
67
+ const img = extractMediaImage(mediaCursor);
68
+ const inner = img ? [img] : mediaCursor.toArray();
69
+ children.push(new Tag('div', { 'data-section': 'media', 'data-name': 'media' }, inner));
70
+ }
71
+ // Eyebrow: a leading paragraph immediately followed by a heading becomes a
72
+ // kicker (the page-section / recipe pattern). The rest stays freeform body.
73
+ let eyebrowNode;
74
+ let mainBodyNodes = bodyNodes;
75
+ if (bodyNodes.length >= 2 &&
76
+ bodyNodes[0].type === 'paragraph' &&
77
+ bodyNodes[1].type === 'heading') {
78
+ eyebrowNode = bodyNodes[0];
79
+ mainBodyNodes = bodyNodes.slice(1);
80
+ }
81
+ // Content zone (body + optional footer) — one grid child so the split
82
+ // layout puts media | content; footer sits at the bottom of content.
83
+ const bodyInner = [];
84
+ let eyebrowTag;
85
+ if (eyebrowNode) {
86
+ const eyebrowCursor = new RenderableNodeCursor(Markdoc.transform([eyebrowNode], config));
87
+ const first = eyebrowCursor.toArray()[0];
88
+ if (Markdoc.Tag.isTag(first)) {
89
+ eyebrowTag = first;
90
+ bodyInner.push(eyebrowTag);
91
+ }
92
+ }
93
+ const bodyCursor = new RenderableNodeCursor(Markdoc.transform(mainBodyNodes, config));
94
+ const bodyRendered = bodyCursor.toArray();
95
+ // The body's leading heading is the card title — give it a hook so it can
96
+ // sit tight under an eyebrow instead of carrying default prose top margin.
97
+ let titleTag;
98
+ const firstBody = bodyRendered[0];
99
+ if (Markdoc.Tag.isTag(firstBody) && /^h[1-6]$/.test(firstBody.name)) {
100
+ titleTag = firstBody;
101
+ }
102
+ bodyInner.push(...bodyRendered);
103
+ const bodyDiv = new Tag('div', { 'data-name': 'body' }, bodyInner);
104
+ const contentChildren = [bodyDiv];
105
+ let footerTag;
106
+ if (footerNodes.length > 0) {
107
+ const footerCursor = new RenderableNodeCursor(Markdoc.transform(footerNodes, config));
108
+ footerTag = new Tag('footer', { 'data-name': 'footer' }, footerCursor.toArray());
109
+ contentChildren.push(footerTag);
110
+ }
111
+ const contentDiv = new Tag('div', { 'data-name': 'content' }, contentChildren);
112
+ children.push(contentDiv);
113
+ // Whole-card link as a stretched overlay (keeps nested links valid).
114
+ let linkTag;
115
+ const href = String(attrs.href ?? '');
116
+ if (href) {
117
+ linkTag = new Tag('a', { 'data-name': 'link', href, 'aria-hidden': 'true', tabindex: '-1' }, []);
118
+ children.push(linkTag);
119
+ }
120
+ const refs = { content: contentDiv, body: bodyDiv };
121
+ if (titleTag)
122
+ refs.title = titleTag;
123
+ if (eyebrowTag)
124
+ refs.eyebrow = eyebrowTag;
125
+ if (footerTag)
126
+ refs.footer = footerTag;
127
+ if (linkTag)
128
+ refs.link = linkTag;
129
+ return createComponentRenderable({
130
+ rune: 'card',
131
+ tag: 'div',
132
+ properties: { layout: layoutMetas.layout },
133
+ refs,
134
+ children,
135
+ });
136
+ },
137
+ });
138
+ //# sourceMappingURL=card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card.js","sourceRoot":"","sources":["../../src/tags/card.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAEvC,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;AACxB,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/F,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEpF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,wBAAwB,CAAC;IAC5C,IAAI,EAAE,gBAAgB;IACtB,UAAU,EAAE;QACX,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,uDAAuD,EAAE;KAC1H;IACD,YAAY,EAAE;QACb,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;KACtE;IACD,SAAS,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM;QAChC,mDAAmD;QACnD,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,KAAK,GAAa,CAAC,EAAE,CAAC,CAAC;QAC7B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;;gBAC/B,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC;QAED,IAAI,UAAU,GAAW,EAAE,CAAC;QAC5B,IAAI,SAAS,GAAW,EAAE,CAAC;QAC3B,IAAI,WAAW,GAAW,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACP,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACtC,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACvC,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAEjF,MAAM,QAAQ,GAAyB,CAAC,GAAG,cAAc,CAAC,CAAC;QAE3D,wEAAwE;QACxE,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,WAAW,GAAG,IAAI,oBAAoB,CAC3C,OAAO,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,CAAyB,CAC7D,CAAC;YACF,MAAM,GAAG,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;YAC3C,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YAClD,QAAQ,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,KAA6B,CAAC,CAAC,CAAC;QACjH,CAAC;QAED,2EAA2E;QAC3E,4EAA4E;QAC5E,IAAI,WAA6B,CAAC;QAClC,IAAI,aAAa,GAAG,SAAS,CAAC;QAC9B,IACC,SAAS,CAAC,MAAM,IAAI,CAAC;YACrB,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW;YACjC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,EAC9B,CAAC;YACF,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;YAC3B,aAAa,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACpC,CAAC;QAED,sEAAsE;QACtE,qEAAqE;QACrE,MAAM,SAAS,GAAyB,EAAE,CAAC;QAC3C,IAAI,UAAgD,CAAC;QACrD,IAAI,WAAW,EAAE,CAAC;YACjB,MAAM,aAAa,GAAG,IAAI,oBAAoB,CAC7C,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,EAAE,MAAM,CAAyB,CAChE,CAAC;YACF,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YACzC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9B,UAAU,GAAG,KAAK,CAAC;gBACnB,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC5B,CAAC;QACF,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,oBAAoB,CAC1C,OAAO,CAAC,SAAS,CAAC,aAAa,EAAE,MAAM,CAAyB,CAChE,CAAC;QACF,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,EAA0B,CAAC;QAClE,0EAA0E;QAC1E,2EAA2E;QAC3E,IAAI,QAA8C,CAAC;QACnD,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YACrE,QAAQ,GAAG,SAAS,CAAC;QACtB,CAAC;QACD,SAAS,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,CAAC;QACnE,MAAM,eAAe,GAAyB,CAAC,OAAO,CAAC,CAAC;QACxD,IAAI,SAA+C,CAAC;QACpD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,YAAY,GAAG,IAAI,oBAAoB,CAC5C,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE,MAAM,CAAyB,CAC9D,CAAC;YACF,SAAS,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,YAAY,CAAC,OAAO,EAA0B,CAAC,CAAC;YACzG,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACjC,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,eAAe,CAAC,CAAC;QAC/E,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAE1B,qEAAqE;QACrE,IAAI,OAA6C,CAAC;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QACtC,IAAI,IAAI,EAAE,CAAC;YACV,OAAO,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;YACjG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;QAED,MAAM,IAAI,GAA6C,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC9F,IAAI,QAAQ;YAAE,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC;QACpC,IAAI,UAAU;YAAE,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC;QAC1C,IAAI,SAAS;YAAE,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACvC,IAAI,OAAO;YAAE,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC;QAEjC,OAAO,yBAAyB,CAAC;YAChC,IAAI,EAAE,MAAM;YACZ,GAAG,EAAE,KAAK;YACV,UAAU,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE;YAC1C,IAAI;YACJ,QAAQ;SACR,CAAC,CAAC;IACJ,CAAC;CACD,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import Markdoc from '@markdoc/markdoc';
2
+ export declare const COLLECTION_SENTINEL = "__collection-sentinel";
3
+ /**
4
+ * `collection` (SPEC-070) — queries the entity registry for many entities and
5
+ * projects them into a layout. Emits a sentinel that the postProcess resolver
6
+ * (`resolveCollections`) fills with real entity data. The body, when present,
7
+ * is a per-entity template captured via the deferBody mechanism (WORK-262).
8
+ */
9
+ export declare const collection: Markdoc.Schema;
10
+ //# sourceMappingURL=collection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../../src/tags/collection.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAKvC,eAAO,MAAM,mBAAmB,0BAA0B,CAAC;AAE3D;;;;;GAKG;AACH,eAAO,MAAM,UAAU,gBA2CrB,CAAC"}
@@ -0,0 +1,54 @@
1
+ import Markdoc from '@markdoc/markdoc';
2
+ const { Tag } = Markdoc;
3
+ import { createContentModelSchema, createComponentRenderable } from '../lib/index.js';
4
+ import { readDeferredBody } from '../deferred-body.js';
5
+ export const COLLECTION_SENTINEL = '__collection-sentinel';
6
+ /**
7
+ * `collection` (SPEC-070) — queries the entity registry for many entities and
8
+ * projects them into a layout. Emits a sentinel that the postProcess resolver
9
+ * (`resolveCollections`) fills with real entity data. The body, when present,
10
+ * is a per-entity template captured via the deferBody mechanism (WORK-262).
11
+ */
12
+ export const collection = createContentModelSchema({
13
+ attributes: {
14
+ type: { type: String, required: false, default: '', description: 'Entity type(s), comma-separated.' },
15
+ filter: { type: String, required: false, default: '', description: 'field:value clauses (SPEC-070 grammar).' },
16
+ sort: { type: String, required: false, default: '', description: 'Sort field (prefix - for descending).' },
17
+ group: { type: String, required: false, default: '', description: 'Group-by field.' },
18
+ limit: { type: String, required: false, default: '', description: 'Max items.' },
19
+ show: { type: String, required: false, default: '', description: 'Alias for type (entity types to include).' },
20
+ fields: { type: String, required: false, default: '', description: 'Comma-separated data fields to project.' },
21
+ layout: { type: String, required: false, default: 'list', description: 'Arrangement: list (stacked) | grid (multi-column) | table (aligned columns). Item chrome comes from the item — the no-body built-in, or a rune like {% card %} in the body template.' },
22
+ 'group-display': { type: String, required: false, default: 'headings', matches: ['headings', 'accordion'], description: 'How groups are presented when `group` is set: headings (default) or accordion (collapsible native <details> panels, styled like the accordion rune, with a per-group count).' },
23
+ empty: { type: String, required: false, default: '', description: 'Fallback text shown when the query yields nothing (no-body form; body-template form uses a fallback zone). Absent → render nothing.' },
24
+ },
25
+ deferBody: true,
26
+ contentModel: { type: 'sequence', fields: [] },
27
+ transform(_resolved, attrs) {
28
+ const meta = (field, content) => new Tag('meta', { 'data-field': field, content });
29
+ const bodySource = readDeferredBody(attrs) ?? '';
30
+ const metas = [
31
+ meta('collection-type', String(attrs.type ?? attrs.show ?? '')),
32
+ meta('collection-filter', String(attrs.filter ?? '')),
33
+ meta('collection-sort', String(attrs.sort ?? '')),
34
+ meta('collection-group', String(attrs.group ?? '')),
35
+ meta('collection-limit', String(attrs.limit ?? '')),
36
+ meta('collection-fields', String(attrs.fields ?? '')),
37
+ meta('collection-layout', String(attrs.layout ?? 'list')),
38
+ meta('collection-group-display', String(attrs['group-display'] ?? 'headings')),
39
+ meta('collection-empty', String(attrs.empty ?? '')),
40
+ meta(COLLECTION_SENTINEL, 'true'),
41
+ ];
42
+ if (bodySource)
43
+ metas.push(meta('collection-body', bodySource));
44
+ const placeholder = new Tag('div', { 'data-name': 'items' }, []);
45
+ return createComponentRenderable({
46
+ rune: 'collection',
47
+ tag: 'section',
48
+ properties: {},
49
+ refs: { items: placeholder },
50
+ children: [...metas, placeholder],
51
+ });
52
+ },
53
+ });
54
+ //# sourceMappingURL=collection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection.js","sourceRoot":"","sources":["../../src/tags/collection.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../src/tags/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAMvC,eAAO,MAAM,mBAAmB,gBA8B9B,CAAC;AAkDH,eAAO,MAAM,YAAY,gBA2BvB,CAAC"}
1
+ {"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../src/tags/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,kBAAkB,CAAC;AAMvC,eAAO,MAAM,mBAAmB,gBA8B9B,CAAC;AAwEH,eAAO,MAAM,YAAY,gBA2BvB,CAAC"}