@refrakt-md/runes 0.17.0 → 0.18.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/config.d.ts.map +1 -1
- package/dist/config.js +36 -342
- package/dist/config.js.map +1 -1
- package/dist/drawer-pipeline.d.ts.map +1 -1
- package/dist/drawer-pipeline.js +7 -22
- package/dist/drawer-pipeline.js.map +1 -1
- package/dist/lib/component.d.ts.map +1 -1
- package/dist/lib/component.js +50 -3
- package/dist/lib/component.js.map +1 -1
- package/dist/tags/budget.d.ts.map +1 -1
- package/dist/tags/budget.js +99 -9
- package/dist/tags/budget.js.map +1 -1
- package/dist/tags/chart.d.ts.map +1 -1
- package/dist/tags/chart.js +31 -64
- package/dist/tags/chart.js.map +1 -1
- package/dist/tags/diagram.d.ts.map +1 -1
- package/dist/tags/diagram.js +33 -7
- package/dist/tags/diagram.js.map +1 -1
- package/dist/tags/embed.d.ts.map +1 -1
- package/dist/tags/embed.js +28 -10
- package/dist/tags/embed.js.map +1 -1
- package/dist/tags/sandbox.d.ts.map +1 -1
- package/dist/tags/sandbox.js +32 -50
- package/dist/tags/sandbox.js.map +1 -1
- package/package.json +3 -3
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA+B,MAAM,uBAAuB,CAAC;AAEtF,OAAO,KAAK,EAAE,mBAAmB,EAAmB,cAAc,EAAkB,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAS/H,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA+B,MAAM,uBAAuB,CAAC;AAEtF,OAAO,KAAK,EAAE,mBAAmB,EAAmB,cAAc,EAAkB,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAS/H,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AA8B9D;gFACgF;AAChF,eAAO,MAAM,UAAU,EAAE,WAsfxB,CAAC;AAEF,sGAAsG;AACtG,eAAO,MAAM,UAAU,aAAa,CAAC;AAIrC,gEAAgE;AAChE,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,EAAE,CAAC;CACzB;AA0vCD,UAAU,YAAY;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAsKD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CACnC,UAAU,EAAE,OAAO,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE;IACT,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChI,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IACnC;;;uBAGmB;IACnB,YAAY,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACrC,EACD,GAAG,EAAE,eAAe;AACpB;;yEAEyE;AACzE,cAAc,CAAC,EAAE,OAAO,EAAE,GACxB,OAAO,CAqBT;AAED,2DAA2D;AAC3D,MAAM,WAAW,wBAAwB;IACxC;;8DAE0D;IAC1D,YAAY,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACrC;;kFAE8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;6CACyC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;2EAIuE;IACvE,WAAW,CAAC,EAAE;QACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC/B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC;;;yEAGiE;QACjE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,WAAW,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACF;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,GAAE,wBAA6B,GAAG,mBAAmB,CA0ShG;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,EAAE,mBAA+C,CAAC"}
|
package/dist/config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isTag,
|
|
1
|
+
import { isTag, readField, resolveGap, ratioToFr, resolveOffset, resolveValign, parsePlacement } from '@refrakt-md/transform';
|
|
2
2
|
import Markdoc from '@markdoc/markdoc';
|
|
3
3
|
const { Tag } = Markdoc;
|
|
4
4
|
import { createComponentRenderable } from './lib/index.js';
|
|
@@ -15,58 +15,6 @@ import { resolveExpands } from './expand-pipeline.js';
|
|
|
15
15
|
import { resolveCollections } from './collection-resolve.js';
|
|
16
16
|
import { resolveRelationships } from './relationships-resolve.js';
|
|
17
17
|
import { resolveAggregates } from './aggregate-resolve.js';
|
|
18
|
-
// ─── Budget postTransform helpers ───
|
|
19
|
-
const BUDGET_CURRENCY_SYMBOLS = {
|
|
20
|
-
USD: '$', EUR: '€', GBP: '£', JPY: '¥', CNY: '¥',
|
|
21
|
-
AUD: 'A$', CAD: 'C$', CHF: 'CHF ', SEK: 'kr', NOK: 'kr', DKK: 'kr',
|
|
22
|
-
INR: '₹', KRW: '₩', BRL: 'R$', MXN: 'MX$', ZAR: 'R',
|
|
23
|
-
};
|
|
24
|
-
function formatBudgetAmount(amount, symbol) {
|
|
25
|
-
const parts = (amount % 1 === 0 ? String(amount) : amount.toFixed(2)).split('.');
|
|
26
|
-
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
27
|
-
return symbol + parts.join('.');
|
|
28
|
-
}
|
|
29
|
-
function parseBudgetDays(duration) {
|
|
30
|
-
let days = 0;
|
|
31
|
-
const dayMatch = duration.match(/(\d+)\s*day/i);
|
|
32
|
-
const weekMatch = duration.match(/(\d+)\s*week/i);
|
|
33
|
-
const monthMatch = duration.match(/(\d+)\s*month/i);
|
|
34
|
-
if (dayMatch)
|
|
35
|
-
days += parseInt(dayMatch[1]);
|
|
36
|
-
if (weekMatch)
|
|
37
|
-
days += parseInt(weekMatch[1]) * 7;
|
|
38
|
-
if (monthMatch)
|
|
39
|
-
days += parseInt(monthMatch[1]) * 30;
|
|
40
|
-
if (days === 0) {
|
|
41
|
-
const num = parseInt(duration);
|
|
42
|
-
if (!isNaN(num))
|
|
43
|
-
days = num;
|
|
44
|
-
}
|
|
45
|
-
return days;
|
|
46
|
-
}
|
|
47
|
-
function parseBudgetAmount(str) {
|
|
48
|
-
const cleaned = str.replace(/[€$£¥₹₩\s]/g, '').replace(/,/g, '');
|
|
49
|
-
const range = cleaned.match(/^([\d.]+)\s*[-–]\s*([\d.]+)/);
|
|
50
|
-
if (range)
|
|
51
|
-
return (parseFloat(range[1]) + parseFloat(range[2])) / 2;
|
|
52
|
-
const num = parseFloat(cleaned);
|
|
53
|
-
return isNaN(num) ? 0 : num;
|
|
54
|
-
}
|
|
55
|
-
/** Recursively find all nodes with a specific data-rune attribute */
|
|
56
|
-
function collectByRune(children, typeName) {
|
|
57
|
-
const results = [];
|
|
58
|
-
for (const c of children) {
|
|
59
|
-
if (isTag(c)) {
|
|
60
|
-
if (c.attributes?.['data-rune'] === typeName) {
|
|
61
|
-
results.push(c);
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
results.push(...collectByRune(c.children, typeName));
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return results;
|
|
69
|
-
}
|
|
70
18
|
/** Read text content from a property span child */
|
|
71
19
|
function readPropText(node, prop) {
|
|
72
20
|
for (const c of node.children) {
|
|
@@ -135,12 +83,13 @@ export const coreConfig = {
|
|
|
135
83
|
},
|
|
136
84
|
layout: { root: ['topbar'] },
|
|
137
85
|
sections: { topbar: 'header' },
|
|
86
|
+
// Opt in to the highlight transform's `theme.code.colorScheme` cascade
|
|
87
|
+
// (topbar + tab chrome flip with the inner code). Static flag → declared
|
|
88
|
+
// via rootAttributes rather than a postTransform. The `data-code-host`
|
|
89
|
+
// consumer reads it truthily, so `"true"` is equivalent to the old
|
|
90
|
+
// valueless boolean.
|
|
91
|
+
rootAttributes: { 'data-code-host': 'true' },
|
|
138
92
|
editHints: { panel: 'code' },
|
|
139
|
-
postTransform(node) {
|
|
140
|
-
// Opt in to the highlight transform's `theme.code.colorScheme`
|
|
141
|
-
// cascade so the topbar + tab chrome flip with the inner code.
|
|
142
|
-
return { ...node, attributes: { ...node.attributes, 'data-code-host': true } };
|
|
143
|
-
},
|
|
144
93
|
},
|
|
145
94
|
PageSection: { block: 'page-section' },
|
|
146
95
|
TableOfContents: { block: 'toc' },
|
|
@@ -202,45 +151,13 @@ export const coreConfig = {
|
|
|
202
151
|
Embed: {
|
|
203
152
|
block: 'embed',
|
|
204
153
|
defaultDensity: 'compact',
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const aspect = readMeta(node, 'aspect') || '16:9';
|
|
211
|
-
const provider = readMeta(node, 'provider') || '';
|
|
212
|
-
const [w, h] = aspect.split(':').map(Number);
|
|
213
|
-
const paddingPercent = h && w ? (h / w) * 100 : 56.25;
|
|
214
|
-
// Filter out consumed meta tags
|
|
215
|
-
const contentChildren = node.children.filter(child => {
|
|
216
|
-
if (!isTag(child) || child.name !== 'meta')
|
|
217
|
-
return true;
|
|
218
|
-
const prop = child.attributes['data-field'];
|
|
219
|
-
return !['embedUrl', 'url', 'title', 'aspect', 'provider', 'type'].includes(prop);
|
|
220
|
-
});
|
|
221
|
-
const children = [];
|
|
222
|
-
if (embedUrl) {
|
|
223
|
-
children.push(makeTag('div', { class: `${block}__wrapper`, style: `padding-bottom: ${paddingPercent}%` }, [
|
|
224
|
-
makeTag('iframe', {
|
|
225
|
-
src: embedUrl,
|
|
226
|
-
title,
|
|
227
|
-
frameborder: '0',
|
|
228
|
-
allow: 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture',
|
|
229
|
-
allowfullscreen: '',
|
|
230
|
-
loading: 'lazy',
|
|
231
|
-
}, []),
|
|
232
|
-
]));
|
|
233
|
-
}
|
|
234
|
-
children.push(makeTag('div', { class: `${block}__fallback` }, contentChildren));
|
|
235
|
-
return {
|
|
236
|
-
...node,
|
|
237
|
-
attributes: {
|
|
238
|
-
...node.attributes,
|
|
239
|
-
...(provider ? { 'data-provider': provider } : {}),
|
|
240
|
-
},
|
|
241
|
-
children,
|
|
242
|
-
};
|
|
154
|
+
// SPEC-081: the rune transform builds the wrapper/iframe/fallback
|
|
155
|
+
// structure directly; `provider` is a bag-only modifier that surfaces
|
|
156
|
+
// as `data-provider`. No postTransform.
|
|
157
|
+
modifiers: {
|
|
158
|
+
provider: { source: 'meta', default: 'generic', noBemClass: true },
|
|
243
159
|
},
|
|
160
|
+
editHints: { fallback: 'none' },
|
|
244
161
|
},
|
|
245
162
|
Breadcrumb: {
|
|
246
163
|
block: 'breadcrumb',
|
|
@@ -290,53 +207,12 @@ export const coreConfig = {
|
|
|
290
207
|
blocks: {
|
|
291
208
|
meta: { fields: ['duration', { field: 'currency', align: 'end' }], layout: 'bar' },
|
|
292
209
|
},
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
const duration = node.attributes['data-duration'] || '';
|
|
300
|
-
const showPerDay = node.attributes['data-show-per-day'] !== 'false';
|
|
301
|
-
const symbol = BUDGET_CURRENCY_SYMBOLS[currency.toUpperCase()] || currency + ' ';
|
|
302
|
-
// Find all BudgetCategory children and compute totals
|
|
303
|
-
const categories = collectByRune(node.children, 'budget-category');
|
|
304
|
-
let grandTotal = 0;
|
|
305
|
-
for (const cat of categories) {
|
|
306
|
-
// Read from data attributes set by engine from label/subtotal modifiers
|
|
307
|
-
const label = cat.attributes['data-label'] || '';
|
|
308
|
-
const subtotalStr = cat.attributes['data-subtotal'] || '0';
|
|
309
|
-
const subtotal = parseFloat(subtotalStr) || 0;
|
|
310
|
-
grandTotal += subtotal;
|
|
311
|
-
// Inject category header with label and formatted subtotal
|
|
312
|
-
const catHeader = makeTag('div', { class: `${catBlock}__header` }, [
|
|
313
|
-
makeTag('span', { class: `${catBlock}__label` }, [label]),
|
|
314
|
-
makeTag('span', { class: `${catBlock}__subtotal` }, [formatBudgetAmount(subtotal, symbol)]),
|
|
315
|
-
]);
|
|
316
|
-
cat.children.unshift(catHeader);
|
|
317
|
-
}
|
|
318
|
-
// Build footer with totals
|
|
319
|
-
const footerChildren = [
|
|
320
|
-
makeTag('div', { class: `${block}__total` }, [
|
|
321
|
-
makeTag('span', { class: `${block}__total-label` }, ['Total']),
|
|
322
|
-
makeTag('span', { class: `${block}__total-amount` }, [formatBudgetAmount(grandTotal, symbol)]),
|
|
323
|
-
]),
|
|
324
|
-
];
|
|
325
|
-
if (duration && showPerDay) {
|
|
326
|
-
const days = parseBudgetDays(duration);
|
|
327
|
-
if (days > 0) {
|
|
328
|
-
const perDay = grandTotal / days;
|
|
329
|
-
footerChildren.push(makeTag('div', { class: `${block}__per-day` }, [
|
|
330
|
-
makeTag('span', { class: `${block}__per-day-label` }, ['Per day']),
|
|
331
|
-
makeTag('span', { class: `${block}__per-day-amount` }, [formatBudgetAmount(perDay, symbol)]),
|
|
332
|
-
]));
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
const footer = makeTag('div', { class: `${block}__footer` }, footerChildren);
|
|
336
|
-
return {
|
|
337
|
-
...node,
|
|
338
|
-
children: [...node.children, footer],
|
|
339
|
-
};
|
|
210
|
+
// SPEC-081: the transform emits flat header slots and derives the
|
|
211
|
+
// totals (footer + category headers built there); `layout` builds the
|
|
212
|
+
// preamble <header>, and the categories / footer append after it.
|
|
213
|
+
layout: {
|
|
214
|
+
root: ['meta', 'preamble'],
|
|
215
|
+
preamble: { tag: 'header', children: ['headline', 'blurb', 'image'] },
|
|
340
216
|
},
|
|
341
217
|
},
|
|
342
218
|
BudgetCategory: {
|
|
@@ -493,115 +369,14 @@ export const coreConfig = {
|
|
|
493
369
|
Chart: {
|
|
494
370
|
block: 'chart',
|
|
495
371
|
defaultDensity: 'compact',
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
let chartData = { headers: [], rows: [] };
|
|
503
|
-
try {
|
|
504
|
-
chartData = JSON.parse(dataJson);
|
|
505
|
-
}
|
|
506
|
-
catch { /* fallback */ }
|
|
507
|
-
const colors = [
|
|
508
|
-
'var(--rf-color-info)', 'var(--rf-color-success)',
|
|
509
|
-
'var(--rf-color-warning)', 'var(--rf-color-danger)',
|
|
510
|
-
'#7c3aed', '#0891b2',
|
|
511
|
-
];
|
|
512
|
-
const svgW = 600, svgH = 300;
|
|
513
|
-
const pad = { top: 30, right: 20, bottom: 40, left: 50 };
|
|
514
|
-
const cw = svgW - pad.left - pad.right;
|
|
515
|
-
const ch = svgH - pad.top - pad.bottom;
|
|
516
|
-
const labels = chartData.rows.map(r => r[0] || '');
|
|
517
|
-
const series = chartData.headers.slice(1);
|
|
518
|
-
const values = chartData.rows.map(r => r.slice(1).map(v => parseFloat(v) || 0));
|
|
519
|
-
const maxVal = Math.max(...values.flat(), 1);
|
|
520
|
-
const bgw = cw / Math.max(labels.length, 1);
|
|
521
|
-
const bw = bgw / Math.max(series.length + 1, 2);
|
|
522
|
-
// Build SVG children
|
|
523
|
-
const svgChildren = [];
|
|
524
|
-
// Axes
|
|
525
|
-
svgChildren.push(makeTag('line', {
|
|
526
|
-
x1: String(pad.left), y1: String(pad.top),
|
|
527
|
-
x2: String(pad.left), y2: String(svgH - pad.bottom),
|
|
528
|
-
stroke: 'var(--rf-color-border)', 'stroke-width': '1',
|
|
529
|
-
}, []));
|
|
530
|
-
svgChildren.push(makeTag('line', {
|
|
531
|
-
x1: String(pad.left), y1: String(svgH - pad.bottom),
|
|
532
|
-
x2: String(svgW - pad.right), y2: String(svgH - pad.bottom),
|
|
533
|
-
stroke: 'var(--rf-color-border)', 'stroke-width': '1',
|
|
534
|
-
}, []));
|
|
535
|
-
if (chartType === 'bar') {
|
|
536
|
-
for (let i = 0; i < labels.length; i++) {
|
|
537
|
-
for (let si = 0; si < series.length; si++) {
|
|
538
|
-
const h = (values[i][si] / maxVal) * ch;
|
|
539
|
-
svgChildren.push(makeTag('rect', {
|
|
540
|
-
x: String(pad.left + i * bgw + si * bw + bw * 0.25),
|
|
541
|
-
y: String(pad.top + ch - h),
|
|
542
|
-
width: String(bw * 0.75),
|
|
543
|
-
height: String(h),
|
|
544
|
-
style: `fill: ${colors[si % colors.length]}`,
|
|
545
|
-
rx: '2',
|
|
546
|
-
}, []));
|
|
547
|
-
}
|
|
548
|
-
svgChildren.push(makeTag('text', {
|
|
549
|
-
x: String(pad.left + i * bgw + bgw / 2),
|
|
550
|
-
y: String(svgH - pad.bottom + 20),
|
|
551
|
-
'text-anchor': 'middle', 'font-size': '12',
|
|
552
|
-
fill: 'var(--rf-color-muted)',
|
|
553
|
-
}, [labels[i]]));
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
else if (chartType === 'line') {
|
|
557
|
-
for (let si = 0; si < series.length; si++) {
|
|
558
|
-
const pts = labels.map((_, i) => `${pad.left + i * bgw + bgw / 2},${pad.top + ch - (values[i][si] / maxVal) * ch}`).join(' ');
|
|
559
|
-
svgChildren.push(makeTag('polyline', {
|
|
560
|
-
points: pts, fill: 'none',
|
|
561
|
-
style: `stroke: ${colors[si % colors.length]}`,
|
|
562
|
-
'stroke-width': '2',
|
|
563
|
-
}, []));
|
|
564
|
-
for (let i = 0; i < labels.length; i++) {
|
|
565
|
-
svgChildren.push(makeTag('circle', {
|
|
566
|
-
cx: String(pad.left + i * bgw + bgw / 2),
|
|
567
|
-
cy: String(pad.top + ch - (values[i][si] / maxVal) * ch),
|
|
568
|
-
r: '4',
|
|
569
|
-
style: `fill: ${colors[si % colors.length]}`,
|
|
570
|
-
}, []));
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
for (let i = 0; i < labels.length; i++) {
|
|
574
|
-
svgChildren.push(makeTag('text', {
|
|
575
|
-
x: String(pad.left + i * bgw + bgw / 2),
|
|
576
|
-
y: String(svgH - pad.bottom + 20),
|
|
577
|
-
'text-anchor': 'middle', 'font-size': '12',
|
|
578
|
-
fill: 'var(--rf-color-muted)',
|
|
579
|
-
}, [labels[i]]));
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
const children = [];
|
|
583
|
-
if (title) {
|
|
584
|
-
children.push(makeTag('figcaption', { class: `${block}__title` }, [title]));
|
|
585
|
-
}
|
|
586
|
-
children.push(makeTag('div', { class: `${block}__container` }, [
|
|
587
|
-
makeTag('svg', {
|
|
588
|
-
viewBox: `0 0 ${svgW} ${svgH}`,
|
|
589
|
-
class: `${block}__svg`,
|
|
590
|
-
}, svgChildren),
|
|
591
|
-
]));
|
|
592
|
-
// Legend
|
|
593
|
-
if (series.length > 1) {
|
|
594
|
-
const legendItems = series.map((name, i) => makeTag('span', { class: `${block}__legend-item` }, [
|
|
595
|
-
makeTag('span', {
|
|
596
|
-
class: `${block}__legend-color`,
|
|
597
|
-
style: `background: ${colors[i % colors.length]};`,
|
|
598
|
-
}, []),
|
|
599
|
-
name,
|
|
600
|
-
]));
|
|
601
|
-
children.push(makeTag('div', { class: `${block}__legend` }, legendItems));
|
|
602
|
-
}
|
|
603
|
-
return { ...node, children };
|
|
372
|
+
// SPEC-083: the transform emits the rf-chart element wrapping the data
|
|
373
|
+
// `<table>`; `type` / `stacked` are bag-only modifiers (→ data-type /
|
|
374
|
+
// data-stacked) the web component reads. No postTransform.
|
|
375
|
+
modifiers: {
|
|
376
|
+
type: { source: 'meta', default: 'bar', noBemClass: true },
|
|
377
|
+
stacked: { source: 'meta', noBemClass: true },
|
|
604
378
|
},
|
|
379
|
+
editHints: { data: 'none' },
|
|
605
380
|
},
|
|
606
381
|
// ─── Text formatting & layout runes ───
|
|
607
382
|
PullQuote: {
|
|
@@ -735,31 +510,10 @@ export const coreConfig = {
|
|
|
735
510
|
block: 'diagram',
|
|
736
511
|
defaultDensity: 'compact',
|
|
737
512
|
editHints: { source: 'code' },
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
const sourceMeta = findByDataName(node, 'source');
|
|
743
|
-
const source = sourceMeta?.attributes?.content || '';
|
|
744
|
-
// Build fallback HTML (visible in SSR, replaced by web component)
|
|
745
|
-
const children = [];
|
|
746
|
-
if (title) {
|
|
747
|
-
children.push(makeTag('figcaption', { class: `${block}__title` }, [title]));
|
|
748
|
-
}
|
|
749
|
-
const containerChildren = source
|
|
750
|
-
? [makeTag('pre', { class: `${block}__source` }, [makeTag('code', {}, [source])])]
|
|
751
|
-
: [];
|
|
752
|
-
children.push(makeTag('div', { class: `${block}__container` }, containerChildren));
|
|
753
|
-
// Hidden source for web component to read
|
|
754
|
-
if (source) {
|
|
755
|
-
children.push(makeTag('div', { 'data-content': 'source', style: 'display:none' }, [source]));
|
|
756
|
-
}
|
|
757
|
-
return {
|
|
758
|
-
...node,
|
|
759
|
-
name: 'rf-diagram',
|
|
760
|
-
attributes: { ...node.attributes, 'data-language': language },
|
|
761
|
-
children,
|
|
762
|
-
};
|
|
513
|
+
// SPEC-081: the rune transform emits the `rf-diagram` element + SSR
|
|
514
|
+
// fallback; `language` is a bag-only modifier (→ data-language).
|
|
515
|
+
modifiers: {
|
|
516
|
+
language: { source: 'meta', default: 'mermaid', noBemClass: true },
|
|
763
517
|
},
|
|
764
518
|
},
|
|
765
519
|
Tint: { block: 'tint', parent: '*' },
|
|
@@ -769,64 +523,6 @@ export const coreConfig = {
|
|
|
769
523
|
block: 'sandbox',
|
|
770
524
|
defaultDensity: 'compact',
|
|
771
525
|
editHints: { source: 'code' },
|
|
772
|
-
postTransform(node) {
|
|
773
|
-
// Read meta values
|
|
774
|
-
const content = readMeta(node, 'content') || '';
|
|
775
|
-
const framework = readMeta(node, 'framework') || '';
|
|
776
|
-
const dependencies = readMeta(node, 'dependencies') || '';
|
|
777
|
-
const label = readMeta(node, 'label') || '';
|
|
778
|
-
const height = readMeta(node, 'height') || 'auto';
|
|
779
|
-
const designTokens = readMeta(node, 'design-tokens') || '';
|
|
780
|
-
const securityMode = readMeta(node, 'security-mode') || 'trusted';
|
|
781
|
-
const allowJs = readMeta(node, 'allow-js') || 'true';
|
|
782
|
-
const sandboxOrigin = readMeta(node, 'sandbox-origin') || '';
|
|
783
|
-
// Keep non-meta children (fallback pre) and extract source panels
|
|
784
|
-
const fallbackChildren = [];
|
|
785
|
-
const sourcePanelOrigins = [];
|
|
786
|
-
for (const child of node.children) {
|
|
787
|
-
if (!isTag(child)) {
|
|
788
|
-
fallbackChildren.push(child);
|
|
789
|
-
continue;
|
|
790
|
-
}
|
|
791
|
-
if (child.name === 'meta') {
|
|
792
|
-
// Collect origin data from source panels
|
|
793
|
-
if (child.attributes?.['data-field'] === 'source-panel' && child.attributes?.['data-origin']) {
|
|
794
|
-
sourcePanelOrigins.push(`${child.attributes['data-label'] || ''}\t${child.attributes['data-origin']}`);
|
|
795
|
-
}
|
|
796
|
-
continue;
|
|
797
|
-
}
|
|
798
|
-
fallbackChildren.push(child);
|
|
799
|
-
}
|
|
800
|
-
// Wrap fallback and source in <template> tags (inert/invisible).
|
|
801
|
-
// Using <template> instead of <div> avoids HTML parser issues:
|
|
802
|
-
// when <rf-sandbox> is inside <p>, block elements like <pre> or
|
|
803
|
-
// <div> cause <p> to auto-close, pushing children out of the
|
|
804
|
-
// custom element. <template> is parsed but never rendered.
|
|
805
|
-
const children = [
|
|
806
|
-
...(fallbackChildren.length > 0
|
|
807
|
-
? [makeTag('template', { 'data-content': 'fallback' }, fallbackChildren)]
|
|
808
|
-
: []),
|
|
809
|
-
makeTag('template', { 'data-content': 'source' }, [content]),
|
|
810
|
-
];
|
|
811
|
-
return {
|
|
812
|
-
...node,
|
|
813
|
-
name: 'rf-sandbox',
|
|
814
|
-
attributes: {
|
|
815
|
-
...node.attributes,
|
|
816
|
-
'data-source-content': content,
|
|
817
|
-
...(framework ? { 'data-framework': framework } : {}),
|
|
818
|
-
...(dependencies ? { 'data-dependencies': dependencies } : {}),
|
|
819
|
-
...(label ? { 'data-label': label } : {}),
|
|
820
|
-
'data-height': height,
|
|
821
|
-
...(designTokens ? { 'data-design-tokens': designTokens } : {}),
|
|
822
|
-
...(sourcePanelOrigins.length > 0 ? { 'data-source-origins': sourcePanelOrigins.join('\n') } : {}),
|
|
823
|
-
'data-security-mode': securityMode,
|
|
824
|
-
'data-allow-js': allowJs,
|
|
825
|
-
...(sandboxOrigin ? { 'data-sandbox-origin': sandboxOrigin } : {}),
|
|
826
|
-
},
|
|
827
|
-
children,
|
|
828
|
-
};
|
|
829
|
-
},
|
|
830
526
|
},
|
|
831
527
|
},
|
|
832
528
|
};
|
|
@@ -2007,14 +1703,12 @@ function resolveBlogPosts(renderable, allPosts, ctx, pageUrl) {
|
|
|
2007
1703
|
const result = mapBlogTags(renderable, (tag) => {
|
|
2008
1704
|
if (tag.attributes['data-rune'] !== 'blog')
|
|
2009
1705
|
return tag;
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
const
|
|
2013
|
-
const
|
|
2014
|
-
const
|
|
2015
|
-
const
|
|
2016
|
-
const filterStr = Tag.isTag(filterMeta) ? filterMeta.attributes.content : '';
|
|
2017
|
-
const limitStr = Tag.isTag(limitMeta) ? limitMeta.attributes.content : '';
|
|
1706
|
+
// SPEC-082: read field values from the bag (bag-first, meta-fallback).
|
|
1707
|
+
// The cross-page tree still carries the `data-rune-fields` attribute.
|
|
1708
|
+
const folder = readField(tag, 'folder') ?? '';
|
|
1709
|
+
const sort = readField(tag, 'sort') || 'date-desc';
|
|
1710
|
+
const filterStr = readField(tag, 'filter') ?? '';
|
|
1711
|
+
const limitStr = readField(tag, 'limit') ?? '';
|
|
2018
1712
|
const limit = limitStr ? parseInt(limitStr, 10) : undefined;
|
|
2019
1713
|
if (!folder) {
|
|
2020
1714
|
ctx.warn('Blog rune missing folder attribute', pageUrl);
|