kitfly 0.2.0 → 0.2.3

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 (126) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +25 -10
  3. package/VERSION +1 -1
  4. package/dist/_raw/content/guide/branding.md +146 -0
  5. package/dist/_raw/content/guide/data-driven-content.md +204 -0
  6. package/dist/_raw/content/reference/configuration.md +145 -7
  7. package/dist/_raw/content/reference/environment-variables.md +26 -1
  8. package/dist/_raw/content/reference/glossary.md +25 -1
  9. package/dist/_raw/content/reference/key-concepts.md +30 -2
  10. package/dist/_raw/content/reference/plugins.md +14 -0
  11. package/dist/_raw/content/reference/slides-authoring-guidelines.md +129 -0
  12. package/dist/_raw/content/reference.md +1 -0
  13. package/dist/_raw/docs/decisions/ADR-0006-data-driven-content.md +350 -0
  14. package/dist/content/deployment/preflight.html +10 -6
  15. package/dist/content/deployment/recipes/aws-s3.html +10 -6
  16. package/dist/content/deployment/recipes/cloudflare-pages.html +10 -6
  17. package/dist/content/deployment/recipes/cloudflare-r2.html +10 -6
  18. package/dist/content/deployment/recipes/fly-io.html +10 -6
  19. package/dist/content/deployment/recipes/github-pages.html +10 -6
  20. package/dist/content/deployment/recipes/netlify.html +10 -6
  21. package/dist/content/deployment/recipes/vercel.html +10 -6
  22. package/dist/content/deployment/secrets-and-env-vars.html +10 -6
  23. package/dist/content/deployment.html +10 -6
  24. package/dist/content/guide/approaches.html +10 -6
  25. package/dist/content/guide/branding.html +510 -0
  26. package/dist/content/guide/data-driven-content.html +543 -0
  27. package/dist/content/guide/features.html +10 -6
  28. package/dist/content/guide/getting-started.html +10 -6
  29. package/dist/content/guide/kitfly-overview.html +10 -6
  30. package/dist/content/reference/configuration.html +135 -9
  31. package/dist/content/reference/design-catalog.html +10 -6
  32. package/dist/content/reference/environment-variables.html +50 -8
  33. package/dist/content/reference/glossary.html +24 -8
  34. package/dist/content/reference/key-concepts.html +33 -9
  35. package/dist/content/reference/plugins.html +22 -7
  36. package/dist/content/reference/slides-authoring-guidelines.html +422 -0
  37. package/dist/content/reference/structure.html +10 -6
  38. package/dist/content/reference.html +11 -6
  39. package/dist/content/templates/crucible.html +10 -6
  40. package/dist/content/templates/handbook.html +10 -6
  41. package/dist/content/templates/minimal.html +10 -6
  42. package/dist/content/templates/overview.html +10 -6
  43. package/dist/content/templates/pipeline.html +10 -6
  44. package/dist/content/templates/productbook.html +10 -6
  45. package/dist/content/templates/runbook.html +10 -6
  46. package/dist/content/templates/servicebook.html +10 -6
  47. package/dist/content-index.json +38 -2
  48. package/dist/docs/decisions/ADR-0001-minimalist-site-code.html +10 -6
  49. package/dist/docs/decisions/ADR-0002-ai-accessibility.html +10 -6
  50. package/dist/docs/decisions/ADR-0003-single-file-bundle.html +10 -6
  51. package/dist/docs/decisions/ADR-0004-bun-runtime.html +10 -6
  52. package/dist/docs/decisions/ADR-0005-plugin-contract-and-distribution.html +10 -6
  53. package/dist/docs/decisions/ADR-0006-data-driven-content.html +752 -0
  54. package/dist/docs/decisions/DDR-0001-viewport-locked-layout.html +10 -6
  55. package/dist/docs/decisions/DDR-0002-theme-system.html +10 -6
  56. package/dist/docs/decisions/DDR-0003-bounded-logo-slot.html +10 -6
  57. package/dist/docs/decisions/DDR-0004-slides-rendering-model.html +10 -6
  58. package/dist/docs/decisions/DDR-0005-deterministic-layout-boundary.html +10 -6
  59. package/dist/docs/userguide/cli/build.html +10 -6
  60. package/dist/docs/userguide/cli/bundle.html +10 -6
  61. package/dist/docs/userguide/cli/dev.html +10 -6
  62. package/dist/docs/userguide/cli/init.html +10 -6
  63. package/dist/docs/userguide/cli/servers.html +10 -6
  64. package/dist/docs/userguide/cli/stop.html +10 -6
  65. package/dist/docs/userguide/cli/update.html +10 -6
  66. package/dist/docs/userguide/cli/version.html +10 -6
  67. package/dist/docs/userguide/cli.html +10 -6
  68. package/dist/docs/userguide/sharing.html +10 -6
  69. package/dist/index.html +10 -6
  70. package/dist/llms.txt +3 -3
  71. package/dist/provenance.json +4 -4
  72. package/dist/schemas/plugin-registry.schema.html +10 -6
  73. package/dist/schemas/plugin-schemas-notes.html +10 -6
  74. package/dist/schemas/plugin.schema.html +10 -6
  75. package/dist/schemas/plugins.schema.html +10 -6
  76. package/dist/schemas/v0/common.schema.html +14 -10
  77. package/dist/schemas/v0/plugin-registry.schema.html +13 -9
  78. package/dist/schemas/v0/plugin.schema.html +13 -9
  79. package/dist/schemas/v0/plugins.schema.html +13 -9
  80. package/dist/schemas/v0/site.schema.html +67 -7
  81. package/dist/schemas/v0/theme.schema.html +21 -17
  82. package/dist/schemas.html +10 -6
  83. package/dist/styles.css +39 -4
  84. package/package.json +1 -1
  85. package/plugins-dist/latex-runtime.js +140 -0
  86. package/plugins-dist/latex.js +178 -0
  87. package/plugins-dist/slides-charts-lite-runtime.js +179 -0
  88. package/plugins-dist/slides-charts-lite.js +198 -0
  89. package/plugins-dist/slides-visuals.css +166 -0
  90. package/plugins-dist/slides-visuals.js +124 -33
  91. package/registry/plugins.yaml +30 -5
  92. package/schemas/v0/site.schema.json +56 -0
  93. package/scripts/build.ts +195 -70
  94. package/scripts/bundle.ts +122 -11
  95. package/scripts/dev.ts +345 -178
  96. package/src/__tests__/brief.test.ts +151 -0
  97. package/src/__tests__/build.test.ts +234 -4
  98. package/src/__tests__/bundle.test.ts +134 -0
  99. package/src/__tests__/dev-plugin-errors.test.ts +20 -0
  100. package/src/__tests__/fixtures/fences/slides-visuals/invalid/flow-branching-no-source.md +5 -0
  101. package/src/__tests__/fixtures/fences/slides-visuals/invalid/flow-converging-no-target.md +6 -0
  102. package/src/__tests__/fixtures/fences/slides-visuals/invalid/staircase-empty-steps.md +3 -0
  103. package/src/__tests__/fixtures/fences/slides-visuals/invalid/timeline-horizontal-no-events.md +2 -0
  104. package/src/__tests__/fixtures/fences/slides-visuals/valid/flow-branching-no-split.md +7 -0
  105. package/src/__tests__/fixtures/fences/slides-visuals/valid/flow-branching.md +8 -0
  106. package/src/__tests__/fixtures/fences/slides-visuals/valid/flow-converging-no-merge.md +7 -0
  107. package/src/__tests__/fixtures/fences/slides-visuals/valid/flow-converging.md +8 -0
  108. package/src/__tests__/fixtures/fences/slides-visuals/valid/staircase-down.md +7 -0
  109. package/src/__tests__/fixtures/fences/slides-visuals/valid/staircase.md +8 -0
  110. package/src/__tests__/fixtures/fences/slides-visuals/valid/timeline-horizontal.md +9 -0
  111. package/src/__tests__/fixtures/fences/slides-visuals/valid/timeline-vertical.md +10 -0
  112. package/src/__tests__/init.test.ts +51 -2
  113. package/src/__tests__/latex-runtime.bun.test.ts +35 -0
  114. package/src/__tests__/shared.test.ts +621 -1
  115. package/src/__tests__/slides-charts-lite-runtime.bun.test.ts +45 -0
  116. package/src/__tests__/slides-visuals-runtime-regressions.bun.test.ts +33 -0
  117. package/src/cli.ts +11 -4
  118. package/src/commands/init.ts +1 -1
  119. package/src/shared.ts +761 -18
  120. package/src/site/styles.css +39 -4
  121. package/src/site/template.html +5 -2
  122. package/src/templates/brief.ts +486 -0
  123. package/src/templates/deck.ts +59 -0
  124. package/src/templates/driver.ts +46 -13
  125. package/src/templates/handbook.ts +32 -0
  126. package/src/templates/runbook.ts +32 -0
@@ -222,3 +222,169 @@
222
222
  margin-inline: auto;
223
223
  background: color-mix(in srgb, var(--kitfly-visual-accent) 10%, var(--kitfly-visual-bg));
224
224
  }
225
+
226
+ .kitfly-visual .block {
227
+ border: 1px solid var(--kitfly-visual-border);
228
+ border-radius: 10px;
229
+ padding: 0.6rem 0.75rem;
230
+ background: color-mix(in srgb, var(--kitfly-visual-bg) 75%, var(--color-bg));
231
+ }
232
+ .kitfly-visual .accent {
233
+ background: color-mix(in srgb, var(--kitfly-visual-accent) 12%, var(--kitfly-visual-bg));
234
+ color: color-mix(in srgb, var(--kitfly-visual-accent) 70%, var(--color-text));
235
+ font-weight: 800;
236
+ }
237
+
238
+ /* Timeline horizontal */
239
+ .kitfly-timeline-h { overflow-x: auto; }
240
+ .kitfly-timeline-h-track {
241
+ position: relative;
242
+ display: flex;
243
+ justify-content: space-between;
244
+ gap: 0.75rem;
245
+ padding: 0.2rem 0;
246
+ }
247
+ .kitfly-timeline-h-track::before {
248
+ content: "";
249
+ position: absolute;
250
+ left: 0.5rem;
251
+ right: 0.5rem;
252
+ top: 50%;
253
+ border-top: 2px solid var(--kitfly-visual-border);
254
+ }
255
+ .kitfly-timeline-h-event {
256
+ position: relative;
257
+ display: grid;
258
+ justify-items: center;
259
+ gap: 0.3rem;
260
+ min-width: 7rem;
261
+ }
262
+ .kitfly-timeline-h-marker {
263
+ width: 0.7rem;
264
+ height: 0.7rem;
265
+ border-radius: 999px;
266
+ border: 2px solid color-mix(in srgb, var(--kitfly-visual-accent) 60%, var(--kitfly-visual-border));
267
+ background: var(--color-bg);
268
+ z-index: 1;
269
+ }
270
+ .kitfly-timeline-h-label { font-weight: 700; text-align: center; }
271
+ .kitfly-timeline-h-date { color: var(--kitfly-visual-muted); font-size: 0.88rem; text-align: center; }
272
+
273
+ /* Timeline vertical */
274
+ .kitfly-timeline-v-track {
275
+ position: relative;
276
+ display: grid;
277
+ gap: 0.75rem;
278
+ }
279
+ .kitfly-timeline-v-track::before {
280
+ content: "";
281
+ position: absolute;
282
+ left: 0.35rem;
283
+ top: 0.2rem;
284
+ bottom: 0.2rem;
285
+ border-left: 2px solid var(--kitfly-visual-border);
286
+ }
287
+ .kitfly-timeline-v-event {
288
+ position: relative;
289
+ display: grid;
290
+ grid-template-columns: 1rem 1fr;
291
+ gap: 0.65rem;
292
+ align-items: start;
293
+ }
294
+ .kitfly-timeline-v-marker {
295
+ width: 0.7rem;
296
+ height: 0.7rem;
297
+ margin-top: 0.28rem;
298
+ border-radius: 999px;
299
+ border: 2px solid color-mix(in srgb, var(--kitfly-visual-accent) 60%, var(--kitfly-visual-border));
300
+ background: var(--color-bg);
301
+ z-index: 1;
302
+ }
303
+ .kitfly-timeline-v-label { font-weight: 700; }
304
+ .kitfly-timeline-v-date { color: var(--kitfly-visual-muted); font-size: 0.88rem; margin-top: 0.2rem; }
305
+
306
+ /* Flow branching */
307
+ .kitfly-flow-branch { display: grid; gap: 0.5rem; justify-items: center; }
308
+ .kitfly-flow-branch-source,
309
+ .kitfly-flow-branch-split { width: min(28rem, 100%); text-align: center; }
310
+ .kitfly-flow-branch-arrow { color: var(--kitfly-visual-muted); line-height: 1; }
311
+ .kitfly-flow-branch-arms,
312
+ .kitfly-flow-branch-targets {
313
+ width: 100%;
314
+ display: grid;
315
+ gap: 0.55rem;
316
+ grid-template-columns: repeat(var(--kitfly-branch-count, 1), minmax(0, 1fr));
317
+ }
318
+ .kitfly-flow-branch-arm { text-align: center; color: var(--kitfly-visual-muted); }
319
+ .kitfly-flow-branch-target { text-align: center; min-width: 0; overflow-wrap: anywhere; }
320
+
321
+ /* Flow converging */
322
+ .kitfly-flow-converge { display: grid; gap: 0.5rem; justify-items: center; }
323
+ .kitfly-flow-converge-sources,
324
+ .kitfly-flow-converge-arms {
325
+ width: 100%;
326
+ display: grid;
327
+ gap: 0.55rem;
328
+ grid-template-columns: repeat(var(--kitfly-source-count, 1), minmax(0, 1fr));
329
+ }
330
+ .kitfly-flow-converge-source,
331
+ .kitfly-flow-converge-target,
332
+ .kitfly-flow-converge-merge { text-align: center; min-width: 0; overflow-wrap: anywhere; }
333
+ .kitfly-flow-converge-arm,
334
+ .kitfly-flow-converge-arrow { text-align: center; color: var(--kitfly-visual-muted); }
335
+ .kitfly-flow-converge-target,
336
+ .kitfly-flow-converge-merge { width: min(28rem, 100%); }
337
+
338
+ /* Staircase */
339
+ .kitfly-staircase { display: grid; gap: 0.45rem; }
340
+ .kitfly-staircase-step {
341
+ border: 1px solid var(--kitfly-visual-border);
342
+ border-radius: 10px;
343
+ padding: 0.6rem 0.75rem;
344
+ width: calc(100% - (var(--kitfly-step-level, 0) * 28%));
345
+ margin-left: calc(var(--kitfly-step-level, 0) * 28%);
346
+ font-weight: 700;
347
+ background: color-mix(in srgb, var(--kitfly-visual-accent) calc(6% + (var(--kitfly-step-level, 0) * 12%)), var(--kitfly-visual-bg));
348
+ }
349
+ .kitfly-staircase.is-down .kitfly-staircase-step {
350
+ width: calc(100% - ((1 - var(--kitfly-step-level, 0)) * 28%));
351
+ margin-left: calc((1 - var(--kitfly-step-level, 0)) * 28%);
352
+ }
353
+
354
+ @media (max-width: 640px) {
355
+ .kitfly-timeline-h-track {
356
+ display: grid;
357
+ justify-content: stretch;
358
+ gap: 0.75rem;
359
+ padding-left: 1rem;
360
+ }
361
+ .kitfly-timeline-h-track::before {
362
+ left: 0.35rem;
363
+ right: auto;
364
+ top: 0.2rem;
365
+ bottom: 0.2rem;
366
+ border-top: 0;
367
+ border-left: 2px solid var(--kitfly-visual-border);
368
+ }
369
+ .kitfly-timeline-h-event {
370
+ grid-template-columns: 1rem 1fr;
371
+ grid-template-rows: auto auto;
372
+ align-items: start;
373
+ min-width: 0;
374
+ }
375
+ .kitfly-timeline-h-marker {
376
+ grid-column: 1;
377
+ grid-row: 1 / span 2;
378
+ margin-top: 0.25rem;
379
+ }
380
+ .kitfly-timeline-h-label { grid-column: 2; grid-row: 1; }
381
+ .kitfly-timeline-h-date { grid-column: 2; grid-row: 2; }
382
+ .kitfly-timeline-h-label,
383
+ .kitfly-timeline-h-date { text-align: left; }
384
+ .kitfly-flow-branch-arms,
385
+ .kitfly-flow-branch-targets,
386
+ .kitfly-flow-converge-sources,
387
+ .kitfly-flow-converge-arms {
388
+ grid-template-columns: 1fr;
389
+ }
390
+ }
@@ -89,6 +89,12 @@
89
89
  return ["left", "right"];
90
90
  case "comparison-table":
91
91
  return ["headers", "rows"];
92
+ case "flow-branching":
93
+ return ["branches"];
94
+ case "flow-converging":
95
+ return ["sources"];
96
+ case "staircase":
97
+ return ["steps"];
92
98
  default:
93
99
  return [];
94
100
  }
@@ -98,6 +104,12 @@
98
104
  switch (type) {
99
105
  case "compare":
100
106
  return ["left-title", "right-title"];
107
+ case "flow-branching":
108
+ return ["source", "split"];
109
+ case "flow-converging":
110
+ return ["target", "merge"];
111
+ case "staircase":
112
+ return ["direction"];
101
113
  default:
102
114
  return [];
103
115
  }
@@ -120,38 +132,6 @@
120
132
  return { key, value: parseScalar(m[2]) };
121
133
  }
122
134
 
123
- function asTextItem(value) {
124
- if (typeof value === "string") return value;
125
- if (!value || typeof value !== "object") return String(value ?? "");
126
- if (typeof value.text === "string") return value.text;
127
- if (typeof value.label === "string" && typeof value.value === "string") return `${value.label}: ${value.value}`;
128
- const parts = [];
129
- for (const [k, v] of Object.entries(value)) {
130
- if (typeof v === "string" && v.trim()) parts.push(`${k}: ${v}`);
131
- }
132
- return parts.length ? parts.join(" · ") : "";
133
- }
134
-
135
- function listKeysForType(type) {
136
- switch (type) {
137
- case "compare":
138
- return ["left", "right"];
139
- case "comparison-table":
140
- return ["headers", "rows"];
141
- default:
142
- return [];
143
- }
144
- }
145
-
146
- function isListKeyMarker(li, allowedKeys) {
147
- if (!allowedKeys || allowedKeys.length === 0) return null;
148
- const raw = (li.textContent || "").trim();
149
- const m = raw.match(/^([a-z0-9_-]+)\s*:\s*$/i);
150
- if (!m) return null;
151
- const key = m[1].toLowerCase();
152
- return allowedKeys.includes(key) ? key : null;
153
- }
154
-
155
135
  function parseBodyNodes(nodes) {
156
136
  const out = {};
157
137
  let pendingKey = null;
@@ -366,6 +346,104 @@
366
346
  return root;
367
347
  }
368
348
 
349
+ function renderTimelineHorizontal(data) {
350
+ const events = Array.isArray(data.events) ? data.events : [];
351
+ const root = el("div", "kitfly-visual kitfly-timeline-h");
352
+ const track = el("div", "kitfly-timeline-h-track");
353
+ for (const event of events) {
354
+ const item = typeof event === "object" && event ? event : { label: String(event ?? "") };
355
+ const node = el("div", "kitfly-timeline-h-event");
356
+ node.appendChild(el("div", "kitfly-timeline-h-label", item.label || ""));
357
+ node.appendChild(el("div", "kitfly-timeline-h-marker"));
358
+ if (item.date) node.appendChild(el("div", "kitfly-timeline-h-date", item.date));
359
+ track.appendChild(node);
360
+ }
361
+ root.appendChild(track);
362
+ return root;
363
+ }
364
+
365
+ function renderTimelineVertical(data) {
366
+ const events = Array.isArray(data.events) ? data.events : [];
367
+ const root = el("div", "kitfly-visual kitfly-timeline-v");
368
+ const track = el("div", "kitfly-timeline-v-track");
369
+ for (const event of events) {
370
+ const item = typeof event === "object" && event ? event : { label: String(event ?? "") };
371
+ const row = el("div", "kitfly-timeline-v-event");
372
+ row.appendChild(el("div", "kitfly-timeline-v-marker"));
373
+ const content = el("div", "kitfly-timeline-v-content");
374
+ content.appendChild(el("div", "kitfly-timeline-v-label", item.label || ""));
375
+ if (item.date) content.appendChild(el("div", "kitfly-timeline-v-date", item.date));
376
+ row.appendChild(content);
377
+ track.appendChild(row);
378
+ }
379
+ root.appendChild(track);
380
+ return root;
381
+ }
382
+
383
+ function renderFlowBranching(data) {
384
+ const source = String(data.source || "").trim();
385
+ const split = String(data.split || "").trim();
386
+ const branches = Array.isArray(data.branches) ? data.branches : [];
387
+ const branchCount = Math.max(branches.length, 1);
388
+ const root = el("div", "kitfly-visual kitfly-flow-branch");
389
+ root.style.setProperty("--kitfly-branch-count", String(branchCount));
390
+ root.appendChild(el("div", "kitfly-flow-branch-source block", source));
391
+ root.appendChild(el("div", "kitfly-flow-branch-arrow", "↓"));
392
+ if (split) {
393
+ root.appendChild(el("div", "kitfly-flow-branch-split block accent", split));
394
+ root.appendChild(el("div", "kitfly-flow-branch-arrow", "↓"));
395
+ }
396
+ const arms = el("div", "kitfly-flow-branch-arms");
397
+ const targets = el("div", "kitfly-flow-branch-targets");
398
+ for (const branch of branches) {
399
+ arms.appendChild(el("div", "kitfly-flow-branch-arm", "↓"));
400
+ targets.appendChild(el("div", "kitfly-flow-branch-target block", asTextItem(branch)));
401
+ }
402
+ root.appendChild(arms);
403
+ root.appendChild(targets);
404
+ return root;
405
+ }
406
+
407
+ function renderFlowConverging(data) {
408
+ const sources = Array.isArray(data.sources) ? data.sources : [];
409
+ const merge = String(data.merge || "").trim();
410
+ const target = String(data.target || "").trim();
411
+ const sourceCount = Math.max(sources.length, 1);
412
+ const root = el("div", "kitfly-visual kitfly-flow-converge");
413
+ root.style.setProperty("--kitfly-source-count", String(sourceCount));
414
+ const sourceRow = el("div", "kitfly-flow-converge-sources");
415
+ const armRow = el("div", "kitfly-flow-converge-arms");
416
+ for (const source of sources) {
417
+ sourceRow.appendChild(el("div", "kitfly-flow-converge-source block", asTextItem(source)));
418
+ armRow.appendChild(el("div", "kitfly-flow-converge-arm", "↓"));
419
+ }
420
+ root.appendChild(sourceRow);
421
+ root.appendChild(armRow);
422
+ if (merge) {
423
+ root.appendChild(el("div", "kitfly-flow-converge-merge block accent", merge));
424
+ root.appendChild(el("div", "kitfly-flow-converge-arrow", "↓"));
425
+ }
426
+ root.appendChild(el("div", "kitfly-flow-converge-target block", target));
427
+ return root;
428
+ }
429
+
430
+ function renderStaircase(data) {
431
+ const steps = Array.isArray(data.steps) ? data.steps : [];
432
+ const direction = String(data.direction || "up").trim().toLowerCase();
433
+ const reverse = direction === "down";
434
+ const total = Math.max(steps.length - 1, 1);
435
+ const root = el("div", "kitfly-visual kitfly-staircase");
436
+ if (reverse) root.classList.add("is-down");
437
+ steps.forEach((step, idx) => {
438
+ const row = el("div", "kitfly-staircase-step", asTextItem(step));
439
+ const normalized = reverse ? (steps.length - 1 - idx) / total : idx / total;
440
+ row.style.setProperty("--kitfly-step-idx", String(idx));
441
+ row.style.setProperty("--kitfly-step-level", String(normalized));
442
+ root.appendChild(row);
443
+ });
444
+ return root;
445
+ }
446
+
369
447
  function renderBlock(type, data) {
370
448
  switch (type) {
371
449
  case "kpi":
@@ -386,6 +464,16 @@
386
464
  return renderPyramid(data);
387
465
  case "funnel":
388
466
  return renderFunnel(data);
467
+ case "timeline-horizontal":
468
+ return renderTimelineHorizontal(data);
469
+ case "timeline-vertical":
470
+ return renderTimelineVertical(data);
471
+ case "flow-branching":
472
+ return renderFlowBranching(data);
473
+ case "flow-converging":
474
+ return renderFlowConverging(data);
475
+ case "staircase":
476
+ return renderStaircase(data);
389
477
  default:
390
478
  return null;
391
479
  }
@@ -481,7 +569,10 @@
481
569
  buckets[currentKey] = [];
482
570
 
483
571
  for (const li of node.querySelectorAll(":scope > li")) {
484
- if ((type === "stat-grid" || type === "scorecard") && currentKey === "metrics") {
572
+ if (
573
+ ((type === "stat-grid" || type === "scorecard") && currentKey === "metrics") ||
574
+ ((type === "timeline-horizontal" || type === "timeline-vertical") && currentKey === "events")
575
+ ) {
485
576
  buckets[currentKey].push(parseListItemToValue(li));
486
577
  continue;
487
578
  }
@@ -1,8 +1,8 @@
1
1
  # yaml-language-server: $schema=../schemas/v0/plugin-registry.schema.json
2
2
  version: 1
3
- updated: "2026-02-13"
3
+ updated: "2026-02-15"
4
4
  baseUrl: "https://github.com/3leaps/kitfly/releases/download"
5
- # Canonical plugin registry (v0.2.0-alpha)
5
+ # Canonical plugin registry (v0.2.1)
6
6
  plugins:
7
7
  callouts:
8
8
  name: "Callout Boxes"
@@ -21,7 +21,7 @@ plugins:
21
21
  slides-visuals:
22
22
  name: "Slides Visuals"
23
23
  description: "Widgets and composed figures for Kitfly slides (::: blocks)"
24
- version: "0.2.0"
24
+ version: "0.2.1"
25
25
  contract: "1"
26
26
  kitfly: ">=0.2.0 <1.0.0"
27
27
  license: MIT
@@ -31,5 +31,30 @@ plugins:
31
31
  js: "plugins-dist/slides-visuals.js"
32
32
  css: "plugins-dist/slides-visuals.css"
33
33
  assetSha256:
34
- js: "sha256:d122e0a23d0a5edda4521e210b9d7ff98021c9690b9545635b1167f8a3db2f6a"
35
- css: "sha256:99f020d59c0c006c4941566d351067189eb69c53fe4ffa422fe7d62fc30d62d2"
34
+ js: "sha256:716059fbb0045af5305e552557368fe812569121986e0ce533f96753197c6ee1"
35
+ css: "sha256:dae86214e5f3f628deb6fec3f7bd871fa419f0310993cde9e845392ac16d9ec1"
36
+ latex:
37
+ name: "LaTeX/KaTeX Math Rendering"
38
+ description: "LaTeX math rendering via KaTeX ($...$ inline, $$...$$ display, fenced math)"
39
+ version: "0.2.2"
40
+ contract: "1"
41
+ kitfly: ">=0.2.0 <1.0.0"
42
+ license: MIT
43
+ verified: true
44
+ assets:
45
+ js: "plugins-dist/latex.js"
46
+ assetSha256:
47
+ js: "sha256:5475e344dc424e3015c3a8b2fd8152101354fe2622d322a0fa4f73d1335b4232"
48
+ slides-charts-lite:
49
+ name: "Slides Charts Lite"
50
+ description: "Simple charts for Kitfly slides (bar, line, pie)"
51
+ version: "0.2.2"
52
+ contract: "1"
53
+ kitfly: ">=0.2.0 <1.0.0"
54
+ license: MIT
55
+ verified: true
56
+ modes: ["slides"]
57
+ assets:
58
+ js: "plugins-dist/slides-charts-lite.js"
59
+ assetSha256:
60
+ js: "sha256:ea1afbe48bc94c617af1ee2d53febcaa8d48e83253094a1cbef598f77ec15013"
@@ -22,6 +22,11 @@
22
22
  "description": "Root directory for content (relative to repo root)",
23
23
  "default": "."
24
24
  },
25
+ "dataroot": {
26
+ "type": "string",
27
+ "description": "Root directory for data binding files (relative to repo root)",
28
+ "default": "data"
29
+ },
25
30
  "title": {
26
31
  "type": "string",
27
32
  "description": "Site title shown in browser tab and header",
@@ -90,6 +95,10 @@
90
95
  "description": "Path to logo image (relative to site root)",
91
96
  "default": "assets/brand/logo.png"
92
97
  },
98
+ "logoDark": {
99
+ "type": "string",
100
+ "description": "Path to dark mode logo image (relative to site root). Shown when dark theme is active."
101
+ },
93
102
  "favicon": {
94
103
  "type": "string",
95
104
  "description": "Path to favicon image (relative to site root)",
@@ -191,6 +200,29 @@
191
200
  "type": "boolean",
192
201
  "description": "Show Built with Kitfly attribution",
193
202
  "default": true
203
+ },
204
+ "logo": {
205
+ "type": "string",
206
+ "description": "Path to footer logo image (relative to site root)"
207
+ },
208
+ "logoDark": {
209
+ "type": "string",
210
+ "description": "Path to dark mode footer logo image (relative to site root)"
211
+ },
212
+ "logoUrl": {
213
+ "type": "string",
214
+ "description": "Make footer logo a clickable link to this URL"
215
+ },
216
+ "logoAlt": {
217
+ "type": "string",
218
+ "description": "Alt text for footer logo (defaults to copyright text if set, brand name otherwise)"
219
+ },
220
+ "logoHeight": {
221
+ "type": "integer",
222
+ "description": "Max height of footer logo in pixels",
223
+ "minimum": 10,
224
+ "maximum": 40,
225
+ "default": 20
194
226
  }
195
227
  },
196
228
  "additionalProperties": false
@@ -213,6 +245,30 @@
213
245
  }
214
246
  },
215
247
  "additionalProperties": false
248
+ },
249
+ "prebuild": {
250
+ "type": "array",
251
+ "description": "Commands to run before dev/build/bundle",
252
+ "items": {
253
+ "type": "object",
254
+ "required": [
255
+ "command"
256
+ ],
257
+ "properties": {
258
+ "command": {
259
+ "type": "string",
260
+ "description": "Shell command to execute"
261
+ },
262
+ "watch": {
263
+ "type": "array",
264
+ "description": "File patterns that re-run this hook in dev mode",
265
+ "items": {
266
+ "type": "string"
267
+ }
268
+ }
269
+ },
270
+ "additionalProperties": false
271
+ }
216
272
  }
217
273
  },
218
274
  "additionalProperties": false