@refrakt-md/runes 0.15.0 → 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 (73) 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 +6 -0
  14. package/dist/config.d.ts.map +1 -1
  15. package/dist/config.js +55 -1
  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/expand-pipeline.js +25 -16
  22. package/dist/expand-pipeline.js.map +1 -1
  23. package/dist/field-match.d.ts +43 -0
  24. package/dist/field-match.d.ts.map +1 -0
  25. package/dist/field-match.js +121 -0
  26. package/dist/field-match.js.map +1 -0
  27. package/dist/functions.d.ts +36 -0
  28. package/dist/functions.d.ts.map +1 -0
  29. package/dist/functions.js +74 -0
  30. package/dist/functions.js.map +1 -0
  31. package/dist/index.d.ts +25 -1
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +63 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/lib/index.d.ts +6 -0
  36. package/dist/lib/index.d.ts.map +1 -1
  37. package/dist/lib/index.js +9 -0
  38. package/dist/lib/index.js.map +1 -1
  39. package/dist/nodes.d.ts.map +1 -1
  40. package/dist/nodes.js +6 -1
  41. package/dist/nodes.js.map +1 -1
  42. package/dist/outline-scope.d.ts +17 -0
  43. package/dist/outline-scope.d.ts.map +1 -1
  44. package/dist/outline-scope.js +59 -0
  45. package/dist/outline-scope.js.map +1 -1
  46. package/dist/relationships-resolve.d.ts +4 -0
  47. package/dist/relationships-resolve.d.ts.map +1 -0
  48. package/dist/relationships-resolve.js +180 -0
  49. package/dist/relationships-resolve.js.map +1 -0
  50. package/dist/tags/aggregate.d.ts +19 -0
  51. package/dist/tags/aggregate.d.ts.map +1 -0
  52. package/dist/tags/aggregate.js +59 -0
  53. package/dist/tags/aggregate.js.map +1 -0
  54. package/dist/tags/card.d.ts +25 -0
  55. package/dist/tags/card.d.ts.map +1 -0
  56. package/dist/tags/card.js +138 -0
  57. package/dist/tags/card.js.map +1 -0
  58. package/dist/tags/collection.d.ts +10 -0
  59. package/dist/tags/collection.d.ts.map +1 -0
  60. package/dist/tags/collection.js +54 -0
  61. package/dist/tags/collection.js.map +1 -0
  62. package/dist/tags/conversation.d.ts.map +1 -1
  63. package/dist/tags/conversation.js +26 -6
  64. package/dist/tags/conversation.js.map +1 -1
  65. package/dist/tags/progress.d.ts +9 -0
  66. package/dist/tags/progress.d.ts.map +1 -0
  67. package/dist/tags/progress.js +96 -0
  68. package/dist/tags/progress.js.map +1 -0
  69. package/dist/tags/relationships.d.ts +12 -0
  70. package/dist/tags/relationships.d.ts.map +1 -0
  71. package/dist/tags/relationships.js +62 -0
  72. package/dist/tags/relationships.js.map +1 -0
  73. package/package.json +3 -3
@@ -0,0 +1,4 @@
1
+ import type { EntityRegistry, PipelineContext } from '@refrakt-md/types';
2
+ import { type CollectionEmbedConfig } from './collection-helpers.js';
3
+ export declare function resolveAggregates(renderable: unknown, pageUrl: string, registry: Readonly<EntityRegistry>, embedConfig: CollectionEmbedConfig | undefined, ctx: PipelineContext): unknown;
4
+ //# sourceMappingURL=aggregate-resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregate-resolve.d.ts","sourceRoot":"","sources":["../src/aggregate-resolve.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAsB,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE7F,OAAO,EACN,KAAK,qBAAqB,EAE1B,MAAM,yBAAyB,CAAC;AAiNjC,wBAAgB,iBAAiB,CAChC,UAAU,EAAE,OAAO,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,EAClC,WAAW,EAAE,qBAAqB,GAAG,SAAS,EAC9C,GAAG,EAAE,eAAe,GAClB,OAAO,CAaT"}
@@ -0,0 +1,209 @@
1
+ /**
2
+ * aggregate postProcess resolver (SPEC-076).
3
+ *
4
+ * Walks the serialized renderable, finds `aggregate` sentinels, queries the
5
+ * registry, and emits either a single integer (no-body inline form) or a
6
+ * body-zoned breakdown (preamble totals / per-group template / fallback). Per
7
+ * group the captured body source is reparsed with `$item` bound to the group
8
+ * projection — same machinery `collection`'s per-item template uses, just at
9
+ * group granularity (no nested item-list splice).
10
+ */
11
+ import Markdoc from '@markdoc/markdoc';
12
+ import { parseFieldMatch, matchesFieldMatch } from './field-match.js';
13
+ import { buildOrdering, splitBodyZones, renderItemTemplate, groupEntities, } from './collection-helpers.js';
14
+ import { AGGREGATE_SENTINEL } from './tags/aggregate.js';
15
+ const { Tag } = Markdoc;
16
+ function isTag(node) {
17
+ return Tag.isTag(node);
18
+ }
19
+ function metaContent(tag, field) {
20
+ for (const child of tag.children ?? []) {
21
+ if (isTag(child) && child.name === 'meta' && child.attributes['data-field'] === field) {
22
+ return String(child.attributes.content ?? '');
23
+ }
24
+ }
25
+ return '';
26
+ }
27
+ function hasSentinel(tag) {
28
+ return (tag.children ?? []).some((c) => isTag(c) && c.name === 'meta' && c.attributes['data-field'] === AGGREGATE_SENTINEL);
29
+ }
30
+ function readQuery(tag) {
31
+ const limitRaw = metaContent(tag, 'aggregate-limit');
32
+ const limitNum = Number(limitRaw);
33
+ return {
34
+ types: metaContent(tag, 'aggregate-type').split(',').map((s) => s.trim()).filter(Boolean),
35
+ filter: metaContent(tag, 'aggregate-filter'),
36
+ value: metaContent(tag, 'aggregate-value'),
37
+ group: metaContent(tag, 'aggregate-group'),
38
+ sort: metaContent(tag, 'aggregate-sort'),
39
+ limit: limitRaw && Number.isFinite(limitNum) && limitNum > 0 ? Math.floor(limitNum) : undefined,
40
+ bodySource: metaContent(tag, 'aggregate-body'),
41
+ empty: metaContent(tag, 'aggregate-empty'),
42
+ };
43
+ }
44
+ function percentOf(value, count) {
45
+ if (count <= 0)
46
+ return 0;
47
+ return Math.round((value / count) * 100);
48
+ }
49
+ function countValue(entities, valueParsed) {
50
+ if (!valueParsed)
51
+ return entities.length;
52
+ return entities.filter((e) => matchesFieldMatch(e, valueParsed)).length;
53
+ }
54
+ /** Sort groups by a projection field (`key` | `count` | `value` | `percent`),
55
+ * honoring domain-aware ordering on the group field when sorting by `key`. */
56
+ function sortGroups(groups, sortExpr, groupField, ordering, valueParsed) {
57
+ if (!sortExpr)
58
+ return groups;
59
+ let field = sortExpr.trim();
60
+ let dir = 1;
61
+ if (field.startsWith('-')) {
62
+ dir = -1;
63
+ field = field.slice(1);
64
+ }
65
+ else if (field.endsWith('-desc')) {
66
+ dir = -1;
67
+ field = field.slice(0, -5);
68
+ }
69
+ else if (field.endsWith('-asc')) {
70
+ field = field.slice(0, -4);
71
+ }
72
+ if (field === 'count') {
73
+ return [...groups].sort(([, a], [, b]) => (a.length - b.length) * dir);
74
+ }
75
+ if (field === 'value') {
76
+ return [...groups].sort(([, a], [, b]) => (countValue(a, valueParsed) - countValue(b, valueParsed)) * dir);
77
+ }
78
+ if (field === 'percent') {
79
+ return [...groups].sort(([, a], [, b]) => {
80
+ const pa = percentOf(countValue(a, valueParsed), a.length);
81
+ const pb = percentOf(countValue(b, valueParsed), b.length);
82
+ return (pa - pb) * dir;
83
+ });
84
+ }
85
+ // 'key' (default explicit case) — domain ordering when groupField has one.
86
+ return [...groups].sort(([ka, ma], [kb, mb]) => {
87
+ const ta = ma[0]?.type ?? '';
88
+ const tb = mb[0]?.type ?? '';
89
+ const ra = ordering.rank(ta, groupField, ka);
90
+ const rb = ordering.rank(tb, groupField, kb);
91
+ const aR = ra >= 0, bR = rb >= 0;
92
+ if (aR && bR) {
93
+ if (ra !== rb)
94
+ return (ra - rb) * dir;
95
+ }
96
+ else if (aR !== bR)
97
+ return aR ? -1 : 1;
98
+ return ka.localeCompare(kb) * dir;
99
+ });
100
+ }
101
+ function resolveOne(tag, registry, embedConfig, ordering, ctx, pageUrl) {
102
+ const q = readQuery(tag);
103
+ // Primary set: union of registry.getAll(type) per type, then filter.
104
+ let entities = [];
105
+ for (const type of q.types)
106
+ entities.push(...registry.getAll(type));
107
+ if (q.filter) {
108
+ const parsed = parseFieldMatch(q.filter);
109
+ for (const w of parsed.warnings)
110
+ ctx.warn(`aggregate filter: ${w}`, pageUrl);
111
+ entities = entities.filter((e) => matchesFieldMatch(e, parsed));
112
+ }
113
+ const valueParsed = q.value ? parseFieldMatch(q.value) : null;
114
+ if (valueParsed) {
115
+ for (const w of valueParsed.warnings)
116
+ ctx.warn(`aggregate value: ${w}`, pageUrl);
117
+ }
118
+ const countTotal = entities.length;
119
+ const valueTotal = countValue(entities, valueParsed);
120
+ // Without a `value` attribute, the in-context "achievement" is the count
121
+ // itself — so percent reads as 100 (a full bar, semantically vacuous).
122
+ const percentTotal = q.value ? percentOf(valueTotal, countTotal) : 100;
123
+ // No-body form → inline integer. The engine has already added
124
+ // `class="rf-aggregate"` to the wrapper span; we just stamp the count and
125
+ // swap children for the digit.
126
+ if (!q.bodySource) {
127
+ return new Tag(tag.name, {
128
+ ...tag.attributes,
129
+ 'data-aggregate': 'count',
130
+ 'data-count': String(countTotal),
131
+ }, [String(countTotal)]);
132
+ }
133
+ const zones = splitBodyZones(q.bodySource);
134
+ const tmpl = zones.template;
135
+ const attrs = { ...tag.attributes, 'data-aggregate': 'breakdown' };
136
+ // Empty state: fallback zone, else `empty` attribute, else nothing.
137
+ if (countTotal === 0) {
138
+ const out = [];
139
+ if (zones.fallback && embedConfig) {
140
+ const vars = { item: { key: '', count: 0, value: 0, percent: 0, total: 0, shown: 0 } };
141
+ out.push(new Tag('div', { 'data-name': 'empty', class: 'rf-aggregate__empty' }, renderItemTemplate(zones.fallback, embedConfig, vars)));
142
+ }
143
+ else if (q.empty) {
144
+ out.push(new Tag('div', { 'data-name': 'empty', class: 'rf-aggregate__empty' }, [q.empty]));
145
+ }
146
+ return new Tag(tag.name, attrs, out);
147
+ }
148
+ // Preamble (once, when non-empty) — totals projection on $item.
149
+ const head = [];
150
+ if (zones.preamble && embedConfig) {
151
+ const vars = { item: { count: countTotal, value: valueTotal, percent: percentTotal, total: countTotal } };
152
+ head.push(new Tag('div', { 'data-name': 'preamble', class: 'rf-aggregate__preamble' }, renderItemTemplate(zones.preamble, embedConfig, vars)));
153
+ }
154
+ // Ungrouped: render the template once with the totals projection on $item.
155
+ if (!q.group) {
156
+ const out = [...head];
157
+ if (tmpl && embedConfig) {
158
+ const vars = { item: { key: '', count: countTotal, value: valueTotal, percent: percentTotal, total: countTotal, shown: 1 } };
159
+ out.push(new Tag('div', { 'data-name': 'items', class: 'rf-aggregate__items' }, renderItemTemplate(tmpl, embedConfig, vars)));
160
+ }
161
+ return new Tag(tag.name, attrs, out);
162
+ }
163
+ // Grouped: groupEntities (domain order by default) → sort → limit.
164
+ let groups = [...groupEntities(entities, q.group, ordering).entries()];
165
+ groups = sortGroups(groups, q.sort, q.group, ordering, valueParsed);
166
+ if (q.limit !== undefined && groups.length > q.limit)
167
+ groups = groups.slice(0, q.limit);
168
+ const shown = groups.length;
169
+ const groupNodes = [];
170
+ if (tmpl && embedConfig) {
171
+ for (const [key, members] of groups) {
172
+ const groupCount = members.length;
173
+ const groupValue = countValue(members, valueParsed);
174
+ const groupPercent = q.value ? percentOf(groupValue, groupCount) : 100;
175
+ const vars = {
176
+ item: {
177
+ key,
178
+ count: groupCount,
179
+ value: groupValue,
180
+ percent: groupPercent,
181
+ total: countTotal,
182
+ shown,
183
+ },
184
+ };
185
+ const kids = renderItemTemplate(tmpl, embedConfig, vars);
186
+ groupNodes.push(new Tag('div', { class: 'rf-aggregate__group', 'data-group': key, 'data-block': '' }, kids));
187
+ }
188
+ }
189
+ const itemsDiv = new Tag('div', { 'data-name': 'items', class: 'rf-aggregate__items' }, groupNodes);
190
+ return new Tag(tag.name, attrs, [...head, itemsDiv]);
191
+ }
192
+ export function resolveAggregates(renderable, pageUrl, registry, embedConfig, ctx) {
193
+ const ordering = buildOrdering(embedConfig);
194
+ const walk = (node) => {
195
+ if (Array.isArray(node))
196
+ return node.map(walk);
197
+ if (!isTag(node))
198
+ return node;
199
+ const tag = node;
200
+ if (tag.attributes?.['data-rune'] === 'aggregate' && hasSentinel(tag)) {
201
+ return resolveOne(tag, registry, embedConfig, ordering, ctx, pageUrl);
202
+ }
203
+ if (!tag.children || tag.children.length === 0)
204
+ return tag;
205
+ return new Tag(tag.name, tag.attributes, tag.children.map(walk));
206
+ };
207
+ return walk(renderable);
208
+ }
209
+ //# sourceMappingURL=aggregate-resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregate-resolve.js","sourceRoot":"","sources":["../src/aggregate-resolve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Shared helpers for entity-listing runes (SPEC-070 / SPEC-072).
3
+ *
4
+ * Extracted from `collection-resolve.ts` so both `collection` and
5
+ * `relationships` render from one implementation: entity field access, the
6
+ * title link, sorting, grouping, and the per-item deferred-body reparse. The
7
+ * pieces are source-agnostic — the caller supplies the item set and the
8
+ * per-item template variables (so `relationships` can bind `$kind` alongside
9
+ * `$item`).
10
+ */
11
+ import Markdoc from '@markdoc/markdoc';
12
+ import type { RenderableTreeNode } from '@markdoc/markdoc';
13
+ import type { EntityRegistration } from '@refrakt-md/types';
14
+ declare const Tag: typeof Markdoc.Tag;
15
+ type TagNode = InstanceType<typeof Tag>;
16
+ /** The three optional body zones (SPEC-072 Cap 5), split on top-level `hr`. */
17
+ export interface BodyZones {
18
+ preamble?: string;
19
+ template: string;
20
+ fallback?: string;
21
+ }
22
+ /**
23
+ * Split a captured body source on **top-level** `hr` (`---`) into zones,
24
+ * card-style: 1 → template; 2 → preamble + template; 3 → preamble + template +
25
+ * fallback. A leading empty zone skips the preamble. A `---` inside a nested
26
+ * tag (e.g. `{% card %}`) is a child of that tag, not a top-level sibling, so
27
+ * it is never a delimiter.
28
+ */
29
+ export declare function splitBodyZones(bodySource: string): BodyZones;
30
+ /** Embed config threaded through the pipeline so deferred per-item templates
31
+ * can be re-transformed with the entity bound. */
32
+ export interface CollectionEmbedConfig {
33
+ tags: Record<string, unknown>;
34
+ nodes: Record<string, unknown>;
35
+ projectRoot?: string;
36
+ /** Explicit `(type → field → ordered values)` overrides (SPEC-072 / WORK-276),
37
+ * used when presentation order differs from a rune's declaration order.
38
+ * Defaults are otherwise derived from each rune's attribute `matches`. */
39
+ orderings?: Record<string, Record<string, string[]>>;
40
+ }
41
+ /** Resolves a domain-aware order for an enum field, keyed by `(type, field)`
42
+ * (SPEC-072). Defaults come from each rune's attribute `matches`; explicit
43
+ * overrides win. Unknown `(type, field)` → no ordering (lexical fallback). */
44
+ export declare class Ordering {
45
+ private readonly matches;
46
+ private readonly overrides;
47
+ constructor(matches: Record<string, Record<string, string[]>>, overrides?: Record<string, Record<string, string[]>>);
48
+ order(type: string, field: string): string[] | undefined;
49
+ /** Index of `value` within the `(type, field)` ordering, or -1 when there is
50
+ * no ordering or the value isn't in it. */
51
+ rank(type: string, field: string, value: string): number;
52
+ }
53
+ /** Build an {@link Ordering} from an embed config: derive defaults from each
54
+ * tag schema's attribute `matches`, then layer the explicit `orderings`. */
55
+ export declare function buildOrdering(embedConfig: CollectionEmbedConfig | undefined): Ordering;
56
+ export declare function entityUrl(e: EntityRegistration): string;
57
+ export declare function entityTitle(e: EntityRegistration): string;
58
+ export declare function fieldValue(e: EntityRegistration, field: string): string;
59
+ /** A title link to an entity, or a plain span when it has no URL. The BEM
60
+ * block is the caller's (collection / relationships). */
61
+ export declare function titleLink(e: EntityRegistration, block: string): TagNode;
62
+ /** The `$item` projection bound inside a per-item template. */
63
+ export declare function projectItem(e: EntityRegistration): {
64
+ id: string;
65
+ type: string;
66
+ url: string;
67
+ data: Record<string, unknown>;
68
+ };
69
+ /** Sort entities by a `sort` expression (`field`, `-field`, `field-desc`).
70
+ * With an {@link Ordering}, enum fields sort by domain rank (each entity ranked
71
+ * within its *own* `(type, field)` order — so mixed-type sets compose); ranked
72
+ * items come before unranked, which then fall back to numeric/lexical. */
73
+ export declare function sortEntities(entities: EntityRegistration[], sortExpr: string, ordering?: Ordering): EntityRegistration[];
74
+ /** Group items into an insertion-ordered map keyed by a derived string. */
75
+ export declare function groupBy<T>(items: T[], keyOf: (item: T) => string): Map<string, T[]>;
76
+ /** Group entities by one of their fields (empty → `(none)`). With an
77
+ * {@link Ordering}, groups are emitted in domain order — each group's
78
+ * representative (minimum) rank across its members, ranked groups first. */
79
+ export declare function groupEntities(entities: EntityRegistration[], field: string, ordering?: Ordering): Map<string, EntityRegistration[]>;
80
+ /** One collapsible group in a `group-display="accordion"` rendering. */
81
+ export interface AccordionPanel {
82
+ /** Raw group key, surfaced as `data-group`. */
83
+ key: string;
84
+ /** Display label shown in the summary. */
85
+ label: string;
86
+ /** Member count, shown beside the label. */
87
+ count: number;
88
+ /** Already-rendered group contents. */
89
+ nodes: RenderableTreeNode[];
90
+ }
91
+ /** Render grouped items as an accordion of native `<details>` panels, styled to
92
+ * match the accordion rune (`.rf-accordion` / `.rf-accordion-item`). Collapsed
93
+ * by default and independent (multiple open) — the collapse is what makes the
94
+ * per-group count worth showing. The classes are emitted directly because
95
+ * collection/relationships resolve in postProcess, after the engine. */
96
+ export declare function renderGroupAccordion(panels: AccordionPanel[]): RenderableTreeNode[];
97
+ /** Re-transform a captured per-item template with the given variables bound
98
+ * (e.g. `{ item }` for collection, `{ item, kind }` for relationships). */
99
+ export declare function renderItemTemplate(bodySource: string, embedConfig: CollectionEmbedConfig, variables: Record<string, unknown>): RenderableTreeNode[];
100
+ export {};
101
+ //# sourceMappingURL=collection-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection-helpers.d.ts","sourceRoot":"","sources":["../src/collection-helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Shared helpers for entity-listing runes (SPEC-070 / SPEC-072).
3
+ *
4
+ * Extracted from `collection-resolve.ts` so both `collection` and
5
+ * `relationships` render from one implementation: entity field access, the
6
+ * title link, sorting, grouping, and the per-item deferred-body reparse. The
7
+ * pieces are source-agnostic — the caller supplies the item set and the
8
+ * per-item template variables (so `relationships` can bind `$kind` alongside
9
+ * `$item`).
10
+ */
11
+ import Markdoc from '@markdoc/markdoc';
12
+ import { resolveEntityField } from './field-match.js';
13
+ import { transformDeferredTemplate } from './deferred-body.js';
14
+ const { Tag, Ast } = Markdoc;
15
+ /**
16
+ * Split a captured body source on **top-level** `hr` (`---`) into zones,
17
+ * card-style: 1 → template; 2 → preamble + template; 3 → preamble + template +
18
+ * fallback. A leading empty zone skips the preamble. A `---` inside a nested
19
+ * tag (e.g. `{% card %}`) is a child of that tag, not a top-level sibling, so
20
+ * it is never a delimiter.
21
+ */
22
+ export function splitBodyZones(bodySource) {
23
+ if (!bodySource)
24
+ return { template: '' };
25
+ // Prepend a newline so a leading `---` (the empty-preamble form,
26
+ // `--- template --- fallback`) isn't parsed as YAML frontmatter — which
27
+ // would swallow the first zone and its delimiter, collapsing everything to
28
+ // a single zone and dropping the fallback. Zone content is re-formatted
29
+ // from the segment nodes below, so the extra newline never leaks in.
30
+ const ast = Markdoc.parse('\n' + bodySource);
31
+ const segments = [[]];
32
+ for (const node of ast.children) {
33
+ if (node.type === 'hr')
34
+ segments.push([]);
35
+ else
36
+ segments[segments.length - 1].push(node);
37
+ }
38
+ if (segments.length === 1)
39
+ return { template: bodySource };
40
+ const src = (nodes) => (nodes.length ? Markdoc.format(new Ast.Node('document', {}, nodes)) : '');
41
+ const s = segments.map(src);
42
+ if (s.length === 2)
43
+ return { preamble: s[0] || undefined, template: s[1] };
44
+ return { preamble: s[0] || undefined, template: s[1], fallback: s[2] || undefined };
45
+ }
46
+ /** Resolves a domain-aware order for an enum field, keyed by `(type, field)`
47
+ * (SPEC-072). Defaults come from each rune's attribute `matches`; explicit
48
+ * overrides win. Unknown `(type, field)` → no ordering (lexical fallback). */
49
+ export class Ordering {
50
+ constructor(matches, overrides = {}) {
51
+ this.matches = matches;
52
+ this.overrides = overrides;
53
+ }
54
+ order(type, field) {
55
+ return this.overrides[type]?.[field] ?? this.matches[type]?.[field];
56
+ }
57
+ /** Index of `value` within the `(type, field)` ordering, or -1 when there is
58
+ * no ordering or the value isn't in it. */
59
+ rank(type, field, value) {
60
+ const ord = this.order(type, field);
61
+ if (!ord)
62
+ return -1;
63
+ return ord.indexOf(value);
64
+ }
65
+ }
66
+ /** Build an {@link Ordering} from an embed config: derive defaults from each
67
+ * tag schema's attribute `matches`, then layer the explicit `orderings`. */
68
+ export function buildOrdering(embedConfig) {
69
+ const matches = {};
70
+ const tags = embedConfig?.tags ?? {};
71
+ for (const [type, schema] of Object.entries(tags)) {
72
+ const attrs = schema?.attributes;
73
+ if (!attrs)
74
+ continue;
75
+ for (const [field, def] of Object.entries(attrs)) {
76
+ const m = def?.matches;
77
+ if (Array.isArray(m) && m.every((x) => typeof x === 'string')) {
78
+ (matches[type] ??= {})[field] = m;
79
+ }
80
+ }
81
+ }
82
+ return new Ordering(matches, embedConfig?.orderings ?? {});
83
+ }
84
+ export function entityUrl(e) {
85
+ return e.sourceUrl || String(e.data.url ?? '');
86
+ }
87
+ export function entityTitle(e) {
88
+ const d = e.data;
89
+ return String(d.title ?? d.name ?? e.id);
90
+ }
91
+ export function fieldValue(e, field) {
92
+ const v = resolveEntityField(e, field);
93
+ if (Array.isArray(v))
94
+ return v.join(', ');
95
+ return String(v ?? '');
96
+ }
97
+ /** A title link to an entity, or a plain span when it has no URL. The BEM
98
+ * block is the caller's (collection / relationships). */
99
+ export function titleLink(e, block) {
100
+ const url = entityUrl(e);
101
+ const label = entityTitle(e);
102
+ const cls = `${block}__title`;
103
+ return url
104
+ ? new Tag('a', { class: cls, href: url }, [label])
105
+ : new Tag('span', { class: cls }, [label]);
106
+ }
107
+ /** The `$item` projection bound inside a per-item template. */
108
+ export function projectItem(e) {
109
+ return { id: e.id, type: e.type, url: entityUrl(e), data: e.data };
110
+ }
111
+ /** Sort entities by a `sort` expression (`field`, `-field`, `field-desc`).
112
+ * With an {@link Ordering}, enum fields sort by domain rank (each entity ranked
113
+ * within its *own* `(type, field)` order — so mixed-type sets compose); ranked
114
+ * items come before unranked, which then fall back to numeric/lexical. */
115
+ export function sortEntities(entities, sortExpr, ordering) {
116
+ if (!sortExpr)
117
+ return entities;
118
+ let field = sortExpr.trim();
119
+ let dir = 1;
120
+ if (field.startsWith('-')) {
121
+ dir = -1;
122
+ field = field.slice(1);
123
+ }
124
+ else if (field.endsWith('-desc')) {
125
+ dir = -1;
126
+ field = field.slice(0, -5);
127
+ }
128
+ else if (field.endsWith('-asc')) {
129
+ field = field.slice(0, -4);
130
+ }
131
+ const ranked = ordering && entities.some((e) => ordering.order(e.type, field));
132
+ return [...entities].sort((a, b) => {
133
+ if (ranked) {
134
+ const ra = ordering.rank(a.type, field, fieldValue(a, field));
135
+ const rb = ordering.rank(b.type, field, fieldValue(b, field));
136
+ const aR = ra >= 0, bR = rb >= 0;
137
+ if (aR && bR) {
138
+ if (ra !== rb)
139
+ return (ra - rb) * dir;
140
+ }
141
+ else if (aR !== bR)
142
+ return aR ? -1 : 1; // ranked before unranked, dir-independent
143
+ }
144
+ const av = fieldValue(a, field);
145
+ const bv = fieldValue(b, field);
146
+ const an = Number(av);
147
+ const bn = Number(bv);
148
+ if (av !== '' && bv !== '' && Number.isFinite(an) && Number.isFinite(bn))
149
+ return (an - bn) * dir;
150
+ return av.localeCompare(bv) * dir;
151
+ });
152
+ }
153
+ /** Group items into an insertion-ordered map keyed by a derived string. */
154
+ export function groupBy(items, keyOf) {
155
+ const groups = new Map();
156
+ for (const item of items) {
157
+ const key = keyOf(item);
158
+ const arr = groups.get(key);
159
+ if (arr)
160
+ arr.push(item);
161
+ else
162
+ groups.set(key, [item]);
163
+ }
164
+ return groups;
165
+ }
166
+ /** Group entities by one of their fields (empty → `(none)`). With an
167
+ * {@link Ordering}, groups are emitted in domain order — each group's
168
+ * representative (minimum) rank across its members, ranked groups first. */
169
+ export function groupEntities(entities, field, ordering) {
170
+ const groups = groupBy(entities, (e) => fieldValue(e, field) || '(none)');
171
+ if (!ordering || ![...entities].some((e) => ordering.order(e.type, field)))
172
+ return groups;
173
+ const repRank = (members) => {
174
+ let min = Infinity;
175
+ for (const m of members) {
176
+ const r = ordering.rank(m.type, field, fieldValue(m, field));
177
+ if (r >= 0 && r < min)
178
+ min = r;
179
+ }
180
+ return min;
181
+ };
182
+ const sorted = [...groups.entries()].sort((a, b) => repRank(a[1]) - repRank(b[1]));
183
+ return new Map(sorted);
184
+ }
185
+ /** Render grouped items as an accordion of native `<details>` panels, styled to
186
+ * match the accordion rune (`.rf-accordion` / `.rf-accordion-item`). Collapsed
187
+ * by default and independent (multiple open) — the collapse is what makes the
188
+ * per-group count worth showing. The classes are emitted directly because
189
+ * collection/relationships resolve in postProcess, after the engine. */
190
+ export function renderGroupAccordion(panels) {
191
+ const items = panels.map((p) => new Tag('details', { class: 'rf-accordion-item', 'data-group': p.key }, [
192
+ new Tag('summary', { class: 'rf-accordion-item__header' }, [
193
+ new Tag('span', { class: 'rf-accordion-item__title' }, [p.label]),
194
+ new Tag('span', { class: 'rf-accordion-item__count' }, [String(p.count)]),
195
+ ]),
196
+ new Tag('div', { class: 'rf-accordion-item__body' }, p.nodes),
197
+ ]));
198
+ return [new Tag('div', { class: 'rf-accordion' }, items)];
199
+ }
200
+ /** Re-transform a captured per-item template with the given variables bound
201
+ * (e.g. `{ item }` for collection, `{ item, kind }` for relationships). */
202
+ export function renderItemTemplate(bodySource, embedConfig, variables) {
203
+ const out = transformDeferredTemplate(bodySource, embedConfig, variables);
204
+ return (Array.isArray(out) ? out : [out]);
205
+ }
206
+ //# sourceMappingURL=collection-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection-helpers.js","sourceRoot":"","sources":["../src/collection-helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { EntityRegistry, PipelineContext } from '@refrakt-md/types';
2
+ import { type CollectionEmbedConfig } from './collection-helpers.js';
3
+ export type { CollectionEmbedConfig };
4
+ export declare function resolveCollections(renderable: unknown, pageUrl: string, registry: Readonly<EntityRegistry>, embedConfig: CollectionEmbedConfig | undefined, ctx: PipelineContext): unknown;
5
+ //# sourceMappingURL=collection-resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection-resolve.d.ts","sourceRoot":"","sources":["../src/collection-resolve.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAsB,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAI7F,OAAO,EACN,KAAK,qBAAqB,EAI1B,MAAM,yBAAyB,CAAC;AAMjC,YAAY,EAAE,qBAAqB,EAAE,CAAC;AAuOtC,wBAAgB,kBAAkB,CACjC,UAAU,EAAE,OAAO,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,EAClC,WAAW,EAAE,qBAAqB,GAAG,SAAS,EAC9C,GAAG,EAAE,eAAe,GAClB,OAAO,CAaT"}