yumiamd 0.1.15 → 0.1.16

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/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runCli
4
- } from "./chunk-7A5BHABM.js";
4
+ } from "./chunk-UPUEFJLX.js";
5
5
 
6
6
  // src/bin.ts
7
7
  var result = await runCli(process.argv);
@@ -81,6 +81,45 @@ function createTable(rows, headers) {
81
81
  ...headers ? { headers } : {}
82
82
  };
83
83
  }
84
+ function createChart(chartType, labels, series, title) {
85
+ return {
86
+ type: "chart",
87
+ chartType,
88
+ labels,
89
+ series,
90
+ ...title ? { title } : {}
91
+ };
92
+ }
93
+ function createMermaid(code, chartType) {
94
+ return {
95
+ type: "mermaid",
96
+ code,
97
+ ...chartType ? { chartType } : {}
98
+ };
99
+ }
100
+ function createTimeline(items, layout = "horizontal") {
101
+ return {
102
+ type: "timeline",
103
+ items,
104
+ layout
105
+ };
106
+ }
107
+ function createCompare(left, right, leftTitle, rightTitle) {
108
+ return {
109
+ type: "compare",
110
+ left,
111
+ right,
112
+ ...leftTitle ? { leftTitle } : {},
113
+ ...rightTitle ? { rightTitle } : {}
114
+ };
115
+ }
116
+ function createBadge(text, variant) {
117
+ return {
118
+ type: "badge",
119
+ text,
120
+ ...variant ? { variant } : {}
121
+ };
122
+ }
84
123
  function createGroup(elements, direction = "row", gap) {
85
124
  return {
86
125
  type: "group",
@@ -402,6 +441,32 @@ var DefaultYumiaParser = class {
402
441
  i++;
403
442
  continue;
404
443
  }
444
+ if (directiveHeader.startsWith("badge")) {
445
+ const badgeArg = directiveHeader.slice(5).trim();
446
+ const variantMatch = badgeArg.match(/variant=['"](.*?)['"]/);
447
+ const textMatch = badgeArg.match(/text=['"](.*?)['"]/);
448
+ const variant = variantMatch ? variantMatch[1] : void 0;
449
+ let text = textMatch ? textMatch[1] : badgeArg.replace(/variant=['"].*?['"]/, "").trim();
450
+ text = text.replace(/^['"](.*)['"]$/, "$1");
451
+ const el = createBadge(text, variant);
452
+ el.loc = {
453
+ start: { line: currentLineNum, column: 1 },
454
+ end: { line: currentLineNum, column: rawLine.length + 1 }
455
+ };
456
+ elements.push(el);
457
+ i++;
458
+ continue;
459
+ }
460
+ if (directiveHeader.startsWith("chart") && (directiveHeader.includes("data=") || directiveHeader.includes("labels="))) {
461
+ const el = this.parseChartDirective(directiveHeader, []);
462
+ el.loc = {
463
+ start: { line: currentLineNum, column: 1 },
464
+ end: { line: currentLineNum, column: rawLine.length + 1 }
465
+ };
466
+ elements.push(el);
467
+ i++;
468
+ continue;
469
+ }
405
470
  const [directiveName, ...args] = directiveHeader.split(" ");
406
471
  const directiveArg = args.join(" ").trim();
407
472
  const blockLines = [];
@@ -410,7 +475,7 @@ var DefaultYumiaParser = class {
410
475
  let closed = false;
411
476
  while (i < lines.length) {
412
477
  const innerLine = lines[i]?.trim() ?? "";
413
- const isSingleLine = innerLine.startsWith(":::metric") || innerLine.startsWith(":::layout");
478
+ const isSingleLine = innerLine.startsWith(":::metric") || innerLine.startsWith(":::layout") || innerLine.startsWith(":::badge") && (innerLine.includes("text=") || innerLine.includes("variant=")) || innerLine.startsWith(":::chart") && innerLine.includes("data=");
414
479
  if (innerLine.startsWith(":::") && innerLine.length > 3 && !isSingleLine) {
415
480
  nestedCount++;
416
481
  } else if (innerLine === ":::") {
@@ -473,6 +538,41 @@ var DefaultYumiaParser = class {
473
538
  end: { line: baseLine + i - 1, column: 1 }
474
539
  };
475
540
  elements.push(el);
541
+ } else if (directiveName === "mermaid") {
542
+ const code = blockLines.join("\n").trim();
543
+ const el = createMermaid(code);
544
+ el.loc = {
545
+ start: { line: directiveStartLine, column: 1 },
546
+ end: { line: baseLine + i - 1, column: 1 }
547
+ };
548
+ elements.push(el);
549
+ } else if (directiveName === "chart") {
550
+ const el = this.parseChartDirective(directiveArg, blockLines);
551
+ el.loc = {
552
+ start: { line: directiveStartLine, column: 1 },
553
+ end: { line: baseLine + i - 1, column: 1 }
554
+ };
555
+ elements.push(el);
556
+ } else if (directiveName === "timeline") {
557
+ const el = this.parseTimelineBlock(directiveArg, blockLines);
558
+ el.loc = {
559
+ start: { line: directiveStartLine, column: 1 },
560
+ end: { line: baseLine + i - 1, column: 1 }
561
+ };
562
+ elements.push(el);
563
+ } else if (directiveName === "compare") {
564
+ const el = this.parseCompareBlock(directiveArg, blockLines, blockBaseLine);
565
+ el.loc = {
566
+ start: { line: directiveStartLine, column: 1 },
567
+ end: { line: baseLine + i - 1, column: 1 }
568
+ };
569
+ elements.push(el);
570
+ } else if (directiveName === "step") {
571
+ const { elements: stepElements } = this.parseLines(blockLines, blockBaseLine);
572
+ for (const sEl of stepElements) {
573
+ sEl.step = 1;
574
+ elements.push(sEl);
575
+ }
476
576
  }
477
577
  continue;
478
578
  }
@@ -621,6 +721,140 @@ var DefaultYumiaParser = class {
621
721
  }
622
722
  return columns;
623
723
  }
724
+ parseChartDirective(headerArg, blockLines) {
725
+ const typeMatch = headerArg.match(/type=['"](.*?)['"]/);
726
+ const titleMatch = headerArg.match(/title=['"](.*?)['"]/);
727
+ const labelsMatch = headerArg.match(/labels=['"](.*?)['"]/);
728
+ const dataMatch = headerArg.match(/data=['"](.*?)['"]/);
729
+ const chartType = typeMatch ? typeMatch[1] : "bar";
730
+ const title = titleMatch ? titleMatch[1] : void 0;
731
+ let labels = [];
732
+ const series = [];
733
+ if (labelsMatch && labelsMatch[1]) {
734
+ labels = labelsMatch[1].split(",").map((s) => s.trim()).filter(Boolean);
735
+ }
736
+ if (dataMatch && dataMatch[1]) {
737
+ const rawData = dataMatch[1].trim();
738
+ if (rawData.includes(":")) {
739
+ const parts = rawData.split(",").map((p) => p.trim());
740
+ const values = [];
741
+ const extractedLabels = [];
742
+ for (const part of parts) {
743
+ const [k, v] = part.split(":").map((s) => s.trim());
744
+ if (k && v !== void 0) {
745
+ extractedLabels.push(k);
746
+ values.push(parseFloat(v) || 0);
747
+ }
748
+ }
749
+ if (labels.length === 0)
750
+ labels = extractedLabels;
751
+ series.push({ name: title || "Data", values });
752
+ } else {
753
+ const values = rawData.split(",").map((v) => parseFloat(v.trim()) || 0);
754
+ series.push({ name: title || "Data", values });
755
+ }
756
+ }
757
+ for (const line of blockLines) {
758
+ const trimmed = line.trim();
759
+ if (!trimmed || trimmed.startsWith("#"))
760
+ continue;
761
+ if (trimmed.toLowerCase().startsWith("labels:")) {
762
+ labels = trimmed.slice(7).split(",").map((s) => s.trim()).filter(Boolean);
763
+ } else if (trimmed.toLowerCase().startsWith("series:")) {
764
+ const seriesContent = trimmed.slice(7).trim();
765
+ const sMatch = seriesContent.match(/^(.*?)\s*\[(.*?)\]$/);
766
+ if (sMatch && sMatch[1] && sMatch[2]) {
767
+ const sName = sMatch[1].trim();
768
+ const sValues = sMatch[2].split(",").map((v) => parseFloat(v.trim()) || 0);
769
+ series.push({ name: sName, values: sValues });
770
+ }
771
+ } else if (trimmed.includes("|")) {
772
+ const parts = trimmed.split("|").map((s) => s.trim());
773
+ if (parts.length >= 2) {
774
+ const [l, valStr] = parts;
775
+ if (l && valStr) {
776
+ labels.push(l);
777
+ const val = parseFloat(valStr) || 0;
778
+ if (series.length === 0)
779
+ series.push({ name: "Data", values: [] });
780
+ series[0]?.values.push(val);
781
+ }
782
+ }
783
+ }
784
+ }
785
+ if (labels.length === 0) {
786
+ const maxLen = Math.max(0, ...series.map((s) => s.values.length));
787
+ labels = Array.from({ length: maxLen }, (_, i) => `Item ${i + 1}`);
788
+ }
789
+ return createChart(chartType, labels, series, title);
790
+ }
791
+ parseTimelineBlock(headerArg, blockLines) {
792
+ const layoutMatch = headerArg.match(/layout=['"](.*?)['"]/);
793
+ const layout = layoutMatch && layoutMatch[1] === "vertical" ? "vertical" : "horizontal";
794
+ const items = [];
795
+ for (const line of blockLines) {
796
+ const trimmed = line.trim();
797
+ if (!trimmed)
798
+ continue;
799
+ const bracketMatch = trimmed.match(/^[-*]?\s*\[(.*?)\]\s*(.*?)(?::\s*(.*))?$/);
800
+ if (bracketMatch && bracketMatch[1] && bracketMatch[2]) {
801
+ items.push({
802
+ date: bracketMatch[1].trim(),
803
+ title: bracketMatch[2].trim(),
804
+ description: bracketMatch[3] ? bracketMatch[3].trim() : void 0
805
+ });
806
+ continue;
807
+ }
808
+ if (trimmed.includes("|")) {
809
+ const parts = trimmed.split("|").map((s) => s.trim());
810
+ if (parts.length >= 2) {
811
+ items.push({
812
+ date: parts[0],
813
+ title: parts[1] || "",
814
+ description: parts[2] || void 0
815
+ });
816
+ continue;
817
+ }
818
+ }
819
+ items.push({
820
+ title: trimmed.replace(/^[-*]\s*/, "")
821
+ });
822
+ }
823
+ return createTimeline(items, layout);
824
+ }
825
+ parseCompareBlock(headerArg, blockLines, baseLine) {
826
+ const leftMatch = headerArg.match(/left=['"](.*?)['"]/);
827
+ const rightMatch = headerArg.match(/right=['"](.*?)['"]/);
828
+ const leftTitle = leftMatch ? leftMatch[1] : void 0;
829
+ const rightTitle = rightMatch ? rightMatch[1] : void 0;
830
+ let leftLines = [];
831
+ let rightLines = [];
832
+ let currentSide = "left";
833
+ for (const line of blockLines) {
834
+ const trimmed = line.trim();
835
+ if (trimmed === ":::vs" || trimmed === ":::right" || trimmed === "---") {
836
+ currentSide = "right";
837
+ continue;
838
+ }
839
+ if (trimmed === ":::left") {
840
+ currentSide = "left";
841
+ continue;
842
+ }
843
+ if (currentSide === "left") {
844
+ leftLines.push(line);
845
+ } else {
846
+ rightLines.push(line);
847
+ }
848
+ }
849
+ if (rightLines.length === 0 && leftLines.length > 1) {
850
+ const half = Math.ceil(leftLines.length / 2);
851
+ rightLines = leftLines.slice(half);
852
+ leftLines = leftLines.slice(0, half);
853
+ }
854
+ const { elements: leftElements } = this.parseLines(leftLines, baseLine);
855
+ const { elements: rightElements } = this.parseLines(rightLines, baseLine + leftLines.length);
856
+ return createCompare(leftElements, rightElements, leftTitle, rightTitle);
857
+ }
624
858
  };
625
859
  function parseYumia(source, options) {
626
860
  const parser = new DefaultYumiaParser();
@@ -2050,6 +2284,21 @@ var PptxRenderer = class {
2050
2284
  case "columns":
2051
2285
  this.renderColumns(pptxSlide, pptx, node, scaleX, scaleY, theme);
2052
2286
  break;
2287
+ case "badge":
2288
+ this.renderBadge(pptxSlide, pptx, element, rect, theme);
2289
+ break;
2290
+ case "chart":
2291
+ this.renderChart(pptxSlide, pptx, element, rect, theme);
2292
+ break;
2293
+ case "timeline":
2294
+ this.renderTimeline(pptxSlide, pptx, element, rect, theme);
2295
+ break;
2296
+ case "compare":
2297
+ this.renderCompare(pptxSlide, pptx, node, scaleX, scaleY, theme);
2298
+ break;
2299
+ case "mermaid":
2300
+ this.renderMermaid(pptxSlide, pptx, element, rect, theme);
2301
+ break;
2053
2302
  default:
2054
2303
  break;
2055
2304
  }
@@ -2358,6 +2607,216 @@ var PptxRenderer = class {
2358
2607
  valign: "middle"
2359
2608
  });
2360
2609
  }
2610
+ renderBadge(pptxSlide, pptx, badge, rect, theme) {
2611
+ const colorKey = badge.variant || "primary";
2612
+ const badgeColor = this.cleanHexColor(theme.colors[colorKey] || theme.colors.primary);
2613
+ const badgeW = Math.min(2.5, Math.max(1, badge.text.length * 0.12 + 0.4));
2614
+ const badgeH = Math.min(0.38, rect.h);
2615
+ pptxSlide.addShape(pptx.ShapeType.roundRect, {
2616
+ x: rect.x,
2617
+ y: rect.y,
2618
+ w: badgeW,
2619
+ h: badgeH,
2620
+ fill: { color: this.cleanHexColor(theme.colors.surface) },
2621
+ line: { color: badgeColor, width: 1.5 },
2622
+ rectRadius: 0.15
2623
+ });
2624
+ pptxSlide.addText(badge.text.toUpperCase(), {
2625
+ x: rect.x,
2626
+ y: rect.y,
2627
+ w: badgeW,
2628
+ h: badgeH,
2629
+ fontSize: 10,
2630
+ bold: true,
2631
+ color: badgeColor,
2632
+ fontFace: cleanFontFace(theme.typography.headingFont),
2633
+ align: "center",
2634
+ valign: "middle"
2635
+ });
2636
+ }
2637
+ renderChart(pptxSlide, pptx, chart, rect, theme) {
2638
+ const series = chart.series || [];
2639
+ const labels = chart.labels || [];
2640
+ const chartData = series.map((s) => ({
2641
+ name: s.name || "Data",
2642
+ labels,
2643
+ values: s.values
2644
+ }));
2645
+ let pptxChartType = pptx.ChartType.bar;
2646
+ if (chart.chartType === "line")
2647
+ pptxChartType = pptx.ChartType.line;
2648
+ if (chart.chartType === "pie")
2649
+ pptxChartType = pptx.ChartType.pie;
2650
+ if (chart.chartType === "doughnut")
2651
+ pptxChartType = pptx.ChartType.doughnut;
2652
+ const chartColors = [
2653
+ this.cleanHexColor(theme.colors.primary),
2654
+ this.cleanHexColor(theme.colors.accent),
2655
+ this.cleanHexColor(theme.colors.secondary),
2656
+ this.cleanHexColor(theme.colors.success),
2657
+ this.cleanHexColor(theme.colors.warning)
2658
+ ];
2659
+ try {
2660
+ pptxSlide.addChart(pptxChartType, chartData, {
2661
+ x: rect.x,
2662
+ y: rect.y,
2663
+ w: rect.w,
2664
+ h: rect.h,
2665
+ showTitle: Boolean(chart.title),
2666
+ title: chart.title || "",
2667
+ titleColor: this.cleanHexColor(theme.colors.text),
2668
+ titleFontFace: cleanFontFace(theme.typography.headingFont),
2669
+ showLegend: true,
2670
+ legendPos: "b",
2671
+ legendColor: this.cleanHexColor(theme.colors.muted || theme.colors.text),
2672
+ chartColors
2673
+ });
2674
+ } catch {
2675
+ pptxSlide.addShape(pptx.ShapeType.roundRect, {
2676
+ x: rect.x,
2677
+ y: rect.y,
2678
+ w: rect.w,
2679
+ h: rect.h,
2680
+ fill: { color: this.cleanHexColor(theme.colors.surface) },
2681
+ line: { color: this.cleanHexColor(theme.colors.border), width: 1 }
2682
+ });
2683
+ pptxSlide.addText(`[Chart: ${chart.title || chart.chartType}]`, {
2684
+ x: rect.x,
2685
+ y: rect.y,
2686
+ w: rect.w,
2687
+ h: rect.h,
2688
+ color: this.cleanHexColor(theme.colors.primary),
2689
+ align: "center",
2690
+ valign: "middle"
2691
+ });
2692
+ }
2693
+ }
2694
+ renderTimeline(pptxSlide, pptx, timeline, rect, theme) {
2695
+ const items = timeline.items || [];
2696
+ if (items.length === 0)
2697
+ return;
2698
+ const itemW = rect.w / items.length;
2699
+ const lineY = rect.y + 0.25;
2700
+ pptxSlide.addShape(pptx.ShapeType.rect, {
2701
+ x: rect.x + 0.2,
2702
+ y: lineY,
2703
+ w: rect.w - 0.4,
2704
+ h: 0.03,
2705
+ fill: { color: this.cleanHexColor(theme.colors.border) }
2706
+ });
2707
+ items.forEach((item, idx) => {
2708
+ const itemX = rect.x + idx * itemW;
2709
+ const dotX = itemX + itemW / 2 - 0.1;
2710
+ pptxSlide.addShape(pptx.ShapeType.roundRect, {
2711
+ x: dotX,
2712
+ y: lineY - 0.08,
2713
+ w: 0.2,
2714
+ h: 0.2,
2715
+ fill: { color: this.cleanHexColor(theme.colors.primary) },
2716
+ line: { color: this.cleanHexColor(theme.colors.background), width: 2 },
2717
+ rectRadius: 0.1
2718
+ });
2719
+ if (item.date) {
2720
+ pptxSlide.addText(item.date, {
2721
+ x: itemX,
2722
+ y: lineY + 0.18,
2723
+ w: itemW,
2724
+ h: 0.25,
2725
+ fontSize: 11,
2726
+ bold: true,
2727
+ color: this.cleanHexColor(theme.colors.accent || theme.colors.primary),
2728
+ fontFace: cleanFontFace(theme.typography.codeFont),
2729
+ align: "center"
2730
+ });
2731
+ }
2732
+ const descText = item.description ? `
2733
+ ${item.description}` : "";
2734
+ pptxSlide.addText(`${item.title}${descText}`, {
2735
+ x: itemX + 0.05,
2736
+ y: lineY + 0.45,
2737
+ w: itemW - 0.1,
2738
+ h: rect.h - 0.55,
2739
+ fontSize: 12,
2740
+ color: this.cleanHexColor(theme.colors.text),
2741
+ fontFace: cleanFontFace(theme.typography.bodyFont),
2742
+ align: "center",
2743
+ valign: "top"
2744
+ });
2745
+ });
2746
+ }
2747
+ renderCompare(pptxSlide, pptx, node, scaleX, scaleY, theme) {
2748
+ const { element, bounds } = node;
2749
+ const compare = element;
2750
+ const rect = this.toInches(bounds, scaleX, scaleY);
2751
+ const colW = (rect.w - 0.4) / 2;
2752
+ pptxSlide.addShape(pptx.ShapeType.roundRect, {
2753
+ x: rect.x,
2754
+ y: rect.y,
2755
+ w: colW,
2756
+ h: rect.h,
2757
+ fill: { color: this.cleanHexColor(theme.colors.surface) },
2758
+ line: { color: this.cleanHexColor(theme.colors.border), width: 1 },
2759
+ rectRadius: 0.1
2760
+ });
2761
+ if (compare.leftTitle) {
2762
+ pptxSlide.addText(compare.leftTitle, {
2763
+ x: rect.x + 0.15,
2764
+ y: rect.y + 0.15,
2765
+ w: colW - 0.3,
2766
+ h: 0.4,
2767
+ fontSize: 14,
2768
+ bold: true,
2769
+ color: this.cleanHexColor(theme.colors.primary),
2770
+ fontFace: cleanFontFace(theme.typography.headingFont)
2771
+ });
2772
+ }
2773
+ const rightX = rect.x + colW + 0.4;
2774
+ pptxSlide.addShape(pptx.ShapeType.roundRect, {
2775
+ x: rightX,
2776
+ y: rect.y,
2777
+ w: colW,
2778
+ h: rect.h,
2779
+ fill: { color: this.cleanHexColor(theme.colors.surface) },
2780
+ line: { color: this.cleanHexColor(theme.colors.border), width: 1 },
2781
+ rectRadius: 0.1
2782
+ });
2783
+ if (compare.rightTitle) {
2784
+ pptxSlide.addText(compare.rightTitle, {
2785
+ x: rightX + 0.15,
2786
+ y: rect.y + 0.15,
2787
+ w: colW - 0.3,
2788
+ h: 0.4,
2789
+ fontSize: 14,
2790
+ bold: true,
2791
+ color: this.cleanHexColor(theme.colors.primary),
2792
+ fontFace: cleanFontFace(theme.typography.headingFont)
2793
+ });
2794
+ }
2795
+ }
2796
+ renderMermaid(pptxSlide, pptx, mermaid, rect, theme) {
2797
+ pptxSlide.addShape(pptx.ShapeType.roundRect, {
2798
+ x: rect.x,
2799
+ y: rect.y,
2800
+ w: rect.w,
2801
+ h: rect.h,
2802
+ fill: { color: this.cleanHexColor(theme.colors.surface) },
2803
+ line: { color: this.cleanHexColor(theme.colors.primary), width: 1 },
2804
+ rectRadius: 0.1
2805
+ });
2806
+ pptxSlide.addText(`[Diagram: Mermaid]
2807
+
2808
+ ${mermaid.code}`, {
2809
+ x: rect.x + 0.2,
2810
+ y: rect.y + 0.2,
2811
+ w: rect.w - 0.4,
2812
+ h: rect.h - 0.4,
2813
+ fontSize: 12,
2814
+ color: this.cleanHexColor(theme.colors.text),
2815
+ fontFace: cleanFontFace(theme.typography.codeFont),
2816
+ align: "center",
2817
+ valign: "middle"
2818
+ });
2819
+ }
2361
2820
  toInches(bounds, scaleX, scaleY) {
2362
2821
  return {
2363
2822
  x: Math.max(0, bounds.x * scaleX),
@@ -2461,6 +2920,10 @@ var HtmlRenderer = class {
2461
2920
  <link rel="preconnect" href="https://fonts.googleapis.com">
2462
2921
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
2463
2922
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;600&family=Outfit:wght@600;700;800&display=swap" rel="stylesheet">
2923
+ <script type="module">
2924
+ import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
2925
+ mermaid.initialize({ startOnLoad: true, theme: 'dark', securityLevel: 'loose' });
2926
+ </script>
2464
2927
  <style>
2465
2928
  :root {
2466
2929
  --yumia-bg: ${theme.colors.background};
@@ -2843,6 +3306,172 @@ var HtmlRenderer = class {
2843
3306
  transition: width 0.25s ease;
2844
3307
  }
2845
3308
 
3309
+ /* Badge Directive */
3310
+ .yumia-badge {
3311
+ display: inline-flex;
3312
+ align-items: center;
3313
+ padding: 3px 10px;
3314
+ border-radius: 999px;
3315
+ font-size: 0.8rem;
3316
+ font-weight: 700;
3317
+ letter-spacing: 0.04em;
3318
+ text-transform: uppercase;
3319
+ background: rgba(255, 255, 255, 0.1);
3320
+ color: var(--yumia-text);
3321
+ border: 1px solid var(--yumia-border);
3322
+ margin-bottom: 0.5rem;
3323
+ }
3324
+ .yumia-badge.variant-primary { background: rgba(0, 240, 255, 0.15); color: var(--yumia-primary); border-color: var(--yumia-primary); }
3325
+ .yumia-badge.variant-success { background: rgba(16, 185, 129, 0.15); color: var(--yumia-success); border-color: var(--yumia-success); }
3326
+ .yumia-badge.variant-warning { background: rgba(245, 158, 11, 0.15); color: var(--yumia-warning); border-color: var(--yumia-warning); }
3327
+ .yumia-badge.variant-danger { background: rgba(239, 68, 68, 0.15); color: var(--yumia-danger); border-color: var(--yumia-danger); }
3328
+ .yumia-badge.variant-info { background: rgba(59, 130, 246, 0.15); color: var(--yumia-info); border-color: var(--yumia-info); }
3329
+ .yumia-badge.variant-accent { background: rgba(255, 46, 136, 0.15); color: var(--yumia-accent); border-color: var(--yumia-accent); }
3330
+
3331
+ /* Timeline Directive */
3332
+ .yumia-timeline {
3333
+ display: flex;
3334
+ gap: 16px;
3335
+ margin: 1.2rem 0;
3336
+ width: 100%;
3337
+ }
3338
+ .yumia-timeline.layout-horizontal {
3339
+ flex-direction: row;
3340
+ justify-content: space-between;
3341
+ position: relative;
3342
+ }
3343
+ .yumia-timeline.layout-horizontal::before {
3344
+ content: '';
3345
+ position: absolute;
3346
+ top: 18px;
3347
+ left: 20px;
3348
+ right: 20px;
3349
+ height: 2px;
3350
+ background: var(--yumia-border);
3351
+ z-index: 0;
3352
+ }
3353
+ .yumia-timeline-item {
3354
+ position: relative;
3355
+ z-index: 1;
3356
+ display: flex;
3357
+ flex-direction: column;
3358
+ align-items: center;
3359
+ text-align: center;
3360
+ flex: 1;
3361
+ }
3362
+ .yumia-timeline-dot {
3363
+ width: 14px;
3364
+ height: 14px;
3365
+ border-radius: 50%;
3366
+ background: var(--yumia-primary);
3367
+ border: 3px solid var(--yumia-bg);
3368
+ box-shadow: 0 0 10px var(--yumia-primary);
3369
+ margin-bottom: 10px;
3370
+ }
3371
+ .yumia-timeline-date {
3372
+ font-size: 0.85rem;
3373
+ font-weight: 700;
3374
+ color: var(--yumia-accent);
3375
+ margin-bottom: 4px;
3376
+ font-family: var(--yumia-font-code);
3377
+ }
3378
+ .yumia-timeline-title {
3379
+ font-size: 1.05rem;
3380
+ font-weight: 600;
3381
+ color: var(--yumia-text);
3382
+ margin-bottom: 4px;
3383
+ }
3384
+ .yumia-timeline-desc {
3385
+ font-size: 0.85rem;
3386
+ color: var(--yumia-muted);
3387
+ line-height: 1.4;
3388
+ }
3389
+
3390
+ /* Compare Directive */
3391
+ .yumia-compare {
3392
+ display: grid;
3393
+ grid-template-columns: 1fr auto 1fr;
3394
+ gap: 20px;
3395
+ align-items: stretch;
3396
+ margin: 1.2rem 0;
3397
+ }
3398
+ .yumia-compare-col {
3399
+ background: var(--yumia-surface);
3400
+ border: 1px solid var(--yumia-border);
3401
+ border-radius: var(--yumia-radius-card);
3402
+ padding: 1.5rem;
3403
+ display: flex;
3404
+ flex-direction: column;
3405
+ }
3406
+ .yumia-compare-title {
3407
+ font-size: 1.2rem;
3408
+ font-weight: 700;
3409
+ color: var(--yumia-primary);
3410
+ margin-bottom: 1rem;
3411
+ padding-bottom: 0.5rem;
3412
+ border-bottom: 1px solid var(--yumia-divider);
3413
+ }
3414
+ .yumia-compare-divider {
3415
+ display: flex;
3416
+ align-items: center;
3417
+ justify-content: center;
3418
+ font-weight: 800;
3419
+ font-size: 0.9rem;
3420
+ color: var(--yumia-muted);
3421
+ background: rgba(255, 255, 255, 0.05);
3422
+ border-radius: 50%;
3423
+ width: 36px;
3424
+ height: 36px;
3425
+ align-self: center;
3426
+ border: 1px solid var(--yumia-border);
3427
+ }
3428
+
3429
+ /* Native SVG Chart Container */
3430
+ .yumia-chart-container {
3431
+ background: var(--yumia-surface);
3432
+ border: 1px solid var(--yumia-border);
3433
+ border-radius: var(--yumia-radius-card);
3434
+ padding: 1.25rem;
3435
+ margin: 1rem 0;
3436
+ display: flex;
3437
+ flex-direction: column;
3438
+ align-items: center;
3439
+ width: 100%;
3440
+ }
3441
+ .yumia-chart-title {
3442
+ font-size: 1.1rem;
3443
+ font-weight: 700;
3444
+ color: var(--yumia-text);
3445
+ margin-bottom: 0.75rem;
3446
+ align-self: flex-start;
3447
+ }
3448
+
3449
+ /* Mermaid Container */
3450
+ .mermaid-container {
3451
+ background: rgba(10, 10, 18, 0.6);
3452
+ border: 1px solid var(--yumia-border);
3453
+ border-radius: var(--yumia-radius-card);
3454
+ padding: 1rem;
3455
+ margin: 1rem 0;
3456
+ display: flex;
3457
+ justify-content: center;
3458
+ overflow: auto;
3459
+ width: 100%;
3460
+ }
3461
+
3462
+ /* Progressive Reveal (Step Builds) */
3463
+ .yumia-slide-wrapper [data-step] {
3464
+ transition: opacity 0.25s ease, transform 0.25s ease;
3465
+ }
3466
+ .yumia-slide-wrapper:not(.step-active) [data-step] {
3467
+ opacity: 0.2;
3468
+ transform: translateY(4px);
3469
+ }
3470
+ .yumia-slide-wrapper.step-active [data-step] {
3471
+ opacity: 1;
3472
+ transform: translateY(0);
3473
+ }
3474
+
2846
3475
  /* Notes Drawer */
2847
3476
  .yumia-notes-drawer {
2848
3477
  position: fixed;
@@ -3467,10 +4096,174 @@ var HtmlRenderer = class {
3467
4096
  }).join("\n");
3468
4097
  return `<div class="yumia-columns" style="grid-template-columns: ${ratioTemplate};">${colsHtml}</div>`;
3469
4098
  }
4099
+ case "badge": {
4100
+ return this.renderBadge(element);
4101
+ }
4102
+ case "mermaid": {
4103
+ const m = element;
4104
+ return `
4105
+ <div class="mermaid-container">
4106
+ <pre class="mermaid">${this.escapeHtml(m.code)}</pre>
4107
+ </div>`;
4108
+ }
4109
+ case "chart": {
4110
+ return this.renderChart(element, theme);
4111
+ }
4112
+ case "timeline": {
4113
+ return this.renderTimeline(element);
4114
+ }
4115
+ case "compare": {
4116
+ return this.renderCompare(element, theme);
4117
+ }
3470
4118
  default:
3471
4119
  return "";
3472
4120
  }
3473
4121
  }
4122
+ renderBadge(b) {
4123
+ const variant = b.variant || "default";
4124
+ return `<span class="yumia-badge variant-${variant}">${this.escapeHtml(b.text)}</span>`;
4125
+ }
4126
+ renderTimeline(t) {
4127
+ const layout = t.layout || "horizontal";
4128
+ const itemsHtml = t.items.map((item) => {
4129
+ const dateHtml = item.date ? `<div class="yumia-timeline-date">${this.escapeHtml(item.date)}</div>` : "";
4130
+ const descHtml = item.description ? `<div class="yumia-timeline-desc">${this.formatInline(item.description)}</div>` : "";
4131
+ return `
4132
+ <div class="yumia-timeline-item">
4133
+ <div class="yumia-timeline-dot"></div>
4134
+ ${dateHtml}
4135
+ <div class="yumia-timeline-title">${this.formatInline(item.title)}</div>
4136
+ ${descHtml}
4137
+ </div>`;
4138
+ }).join("\n");
4139
+ return `<div class="yumia-timeline layout-${layout}">${itemsHtml}</div>`;
4140
+ }
4141
+ renderCompare(c, theme) {
4142
+ const leftTitle = c.leftTitle ? `<div class="yumia-compare-title">${this.escapeHtml(c.leftTitle)}</div>` : "";
4143
+ const rightTitle = c.rightTitle ? `<div class="yumia-compare-title">${this.escapeHtml(c.rightTitle)}</div>` : "";
4144
+ const leftInner = c.left.map((el) => this.renderElement(el, theme)).join("\n");
4145
+ const rightInner = c.right.map((el) => this.renderElement(el, theme)).join("\n");
4146
+ return `
4147
+ <div class="yumia-compare">
4148
+ <div class="yumia-compare-col left">
4149
+ ${leftTitle}
4150
+ ${leftInner}
4151
+ </div>
4152
+ <div class="yumia-compare-divider">VS</div>
4153
+ <div class="yumia-compare-col right">
4154
+ ${rightTitle}
4155
+ ${rightInner}
4156
+ </div>
4157
+ </div>`;
4158
+ }
4159
+ renderChart(c, theme) {
4160
+ const titleHtml = c.title ? `<div class="yumia-chart-title">${this.escapeHtml(c.title)}</div>` : "";
4161
+ const labels = c.labels || [];
4162
+ const series = c.series || [];
4163
+ const colors = [
4164
+ theme.colors.primary || "#00F0FF",
4165
+ theme.colors.accent || "#FF2E88",
4166
+ theme.colors.secondary || "#7B2CBF",
4167
+ theme.colors.success || "#10B981",
4168
+ theme.colors.warning || "#F59E0B"
4169
+ ];
4170
+ if (c.chartType === "line") {
4171
+ const allValues = series.flatMap((s) => s.values);
4172
+ const maxVal2 = Math.max(...allValues, 1);
4173
+ const width2 = 500;
4174
+ const height2 = 180;
4175
+ const padding2 = 35;
4176
+ const plotW2 = width2 - padding2 * 2;
4177
+ const plotH2 = height2 - padding2 * 2;
4178
+ let pathsHtml = "";
4179
+ series.forEach((s, sIdx) => {
4180
+ const sColor = s.color || colors[sIdx % colors.length];
4181
+ const pts = s.values.map((v, i) => {
4182
+ const x = padding2 + i / Math.max(s.values.length - 1, 1) * plotW2;
4183
+ const y = height2 - padding2 - v / maxVal2 * plotH2;
4184
+ return `${x},${y}`;
4185
+ });
4186
+ const pointsStr = pts.join(" ");
4187
+ const circles = pts.map((pt) => `<circle cx="${pt.split(",")[0]}" cy="${pt.split(",")[1]}" r="4" fill="${sColor}" />`).join("");
4188
+ pathsHtml += `
4189
+ <polyline fill="none" stroke="${sColor}" stroke-width="3" stroke-linecap="round" points="${pointsStr}" />
4190
+ ${circles}`;
4191
+ });
4192
+ const labelTexts = labels.map((l, i) => {
4193
+ const x = padding2 + i / Math.max(labels.length - 1, 1) * plotW2;
4194
+ return `<text x="${x}" y="${height2 - 10}" text-anchor="middle" fill="${theme.colors.muted || "#94a3b8"}" font-size="11" font-family="sans-serif">${this.escapeHtml(l)}</text>`;
4195
+ }).join("");
4196
+ return `
4197
+ <div class="yumia-chart-container">
4198
+ ${titleHtml}
4199
+ <svg viewBox="0 0 ${width2} ${height2}" style="width:100%; max-height:220px;">
4200
+ <line x1="${padding2}" y1="${height2 - padding2}" x2="${width2 - padding2}" y2="${height2 - padding2}" stroke="rgba(255,255,255,0.15)" stroke-width="1" />
4201
+ ${pathsHtml}
4202
+ ${labelTexts}
4203
+ </svg>
4204
+ </div>`;
4205
+ }
4206
+ if (c.chartType === "pie" || c.chartType === "doughnut") {
4207
+ const values2 = series[0]?.values || [];
4208
+ const total = values2.reduce((a, b) => a + b, 0) || 1;
4209
+ let cumulativePercent = 0;
4210
+ const radius = 60;
4211
+ const cx = 100;
4212
+ const cy = 100;
4213
+ const strokeWidth = c.chartType === "doughnut" ? 24 : 60;
4214
+ const circ = 2 * Math.PI * radius;
4215
+ const slices = values2.map((val, i) => {
4216
+ const percent = val / total;
4217
+ const strokeDasharray = `${percent * circ} ${circ}`;
4218
+ const strokeDashoffset = -cumulativePercent * circ;
4219
+ cumulativePercent += percent;
4220
+ const sColor = colors[i % colors.length];
4221
+ return `<circle cx="${cx}" cy="${cy}" r="${radius}" fill="none" stroke="${sColor}" stroke-width="${strokeWidth}" stroke-dasharray="${strokeDasharray}" stroke-dashoffset="${strokeDashoffset}" />`;
4222
+ }).join("");
4223
+ const legend = labels.map((l, i) => {
4224
+ const sColor = colors[i % colors.length];
4225
+ const pct = Math.round((values2[i] || 0) / total * 100);
4226
+ return `<div style="display:flex; align-items:center; gap:8px; font-size:12px; margin:4px 0;"><span style="width:10px; height:10px; border-radius:50%; background:${sColor};"></span><span style="color:var(--yumia-text);">${this.escapeHtml(l)} (${pct}%)</span></div>`;
4227
+ }).join("");
4228
+ return `
4229
+ <div class="yumia-chart-container">
4230
+ ${titleHtml}
4231
+ <div style="display:flex; align-items:center; justify-content:center; gap:28px; width:100%;">
4232
+ <svg viewBox="0 0 200 200" style="width:160px; height:160px; transform: rotate(-90deg);">
4233
+ ${slices}
4234
+ </svg>
4235
+ <div style="display:flex; flex-direction:column;">${legend}</div>
4236
+ </div>
4237
+ </div>`;
4238
+ }
4239
+ const values = series[0]?.values || [];
4240
+ const maxVal = Math.max(...values, 1);
4241
+ const width = 500;
4242
+ const height = 180;
4243
+ const padding = 35;
4244
+ const plotW = width - padding * 2;
4245
+ const plotH = height - padding * 2;
4246
+ const barWidth = Math.min(48, Math.max(16, plotW / Math.max(values.length, 1) * 0.6));
4247
+ const bars = values.map((val, i) => {
4248
+ const x = padding + (i + 0.5) * (plotW / Math.max(values.length, 1)) - barWidth / 2;
4249
+ const barH = val / maxVal * plotH;
4250
+ const y = height - padding - barH;
4251
+ const color = colors[i % colors.length];
4252
+ const label = labels[i] || "";
4253
+ return `
4254
+ <rect x="${x}" y="${y}" width="${barWidth}" height="${barH}" rx="4" fill="${color}" opacity="0.9" />
4255
+ <text x="${x + barWidth / 2}" y="${y - 6}" text-anchor="middle" fill="${color}" font-size="11" font-weight="600" font-family="sans-serif">${val}</text>
4256
+ <text x="${x + barWidth / 2}" y="${height - 12}" text-anchor="middle" fill="${theme.colors.muted || "#94a3b8"}" font-size="11" font-family="sans-serif">${this.escapeHtml(label)}</text>`;
4257
+ }).join("");
4258
+ return `
4259
+ <div class="yumia-chart-container">
4260
+ ${titleHtml}
4261
+ <svg viewBox="0 0 ${width} ${height}" style="width:100%; max-height:220px;">
4262
+ <line x1="${padding}" y1="${height - padding}" x2="${width - padding}" y2="${height - padding}" stroke="rgba(255,255,255,0.15)" stroke-width="1" />
4263
+ ${bars}
4264
+ </svg>
4265
+ </div>`;
4266
+ }
3474
4267
  formatInline(text) {
3475
4268
  const escaped = this.escapeHtml(text);
3476
4269
  return escaped.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>").replace(/\*(.*?)\*/g, "<em>$1</em>").replace(/`(.*?)`/g, "<code>$1</code>");
@@ -3718,6 +4511,117 @@ var PdfRenderer = class {
3718
4511
  doc.rect(x, y, width, curY - y).strokeColor(theme.colors.border || "rgba(255,255,255,0.1)").stroke();
3719
4512
  return curY;
3720
4513
  }
4514
+ case "badge": {
4515
+ const b = element;
4516
+ const variantColor = this.getVariantColor(b.variant, theme);
4517
+ const text = this.stripFormatting(b.text).toUpperCase();
4518
+ const badgeW = Math.min(180, Math.max(60, text.length * 7 + 20));
4519
+ const badgeH = 22;
4520
+ doc.roundedRect(x, y, badgeW, badgeH, 11).fill(theme.colors.surface || "rgba(255,255,255,0.08)");
4521
+ doc.roundedRect(x, y, badgeW, badgeH, 11).lineWidth(1).strokeColor(variantColor).stroke();
4522
+ doc.font("Helvetica-Bold").fontSize(10).fillColor(variantColor).text(text, x, y + 6, { width: badgeW, align: "center" });
4523
+ return y + badgeH + 6;
4524
+ }
4525
+ case "timeline": {
4526
+ const t = element;
4527
+ const items = t.items || [];
4528
+ if (items.length === 0)
4529
+ return y;
4530
+ const itemW = (width - (items.length - 1) * 12) / items.length;
4531
+ const lineY = y + 14;
4532
+ doc.moveTo(x + 10, lineY).lineTo(x + width - 10, lineY).lineWidth(2).strokeColor(theme.colors.border || "rgba(255,255,255,0.2)").stroke();
4533
+ let maxItemH = 60;
4534
+ items.forEach((item, idx) => {
4535
+ const itemX = x + idx * (itemW + 12);
4536
+ const dotX = itemX + itemW / 2;
4537
+ doc.circle(dotX, lineY, 6).fill(theme.colors.primary);
4538
+ let curItemY = lineY + 12;
4539
+ if (item.date) {
4540
+ doc.font("Helvetica-Bold").fontSize(10).fillColor(theme.colors.accent || theme.colors.primary).text(this.stripFormatting(item.date), itemX, curItemY, {
4541
+ width: itemW,
4542
+ align: "center"
4543
+ });
4544
+ curItemY += 14;
4545
+ }
4546
+ doc.font("Helvetica-Bold").fontSize(12).fillColor(theme.colors.text).text(this.stripFormatting(item.title), itemX, curItemY, {
4547
+ width: itemW,
4548
+ align: "center"
4549
+ });
4550
+ curItemY += 16;
4551
+ if (item.description) {
4552
+ doc.font("Helvetica").fontSize(9).fillColor(theme.colors.muted || "#888888").text(this.stripFormatting(item.description), itemX, curItemY, {
4553
+ width: itemW,
4554
+ align: "center"
4555
+ });
4556
+ curItemY += 24;
4557
+ }
4558
+ if (curItemY - y > maxItemH)
4559
+ maxItemH = curItemY - y;
4560
+ });
4561
+ return y + maxItemH + 8;
4562
+ }
4563
+ case "compare": {
4564
+ const c = element;
4565
+ const colW = (width - 24) / 2;
4566
+ let leftY = y + 12;
4567
+ let rightY = y + 12;
4568
+ if (c.leftTitle) {
4569
+ doc.font("Helvetica-Bold").fontSize(14).fillColor(theme.colors.primary).text(this.stripFormatting(c.leftTitle), x + 12, leftY, { width: colW - 24 });
4570
+ leftY += 22;
4571
+ }
4572
+ for (const el of c.left) {
4573
+ leftY = this.renderElement(doc, el, x + 12, leftY, colW - 24, theme) + 6;
4574
+ }
4575
+ const rightX = x + colW + 24;
4576
+ if (c.rightTitle) {
4577
+ doc.font("Helvetica-Bold").fontSize(14).fillColor(theme.colors.primary).text(this.stripFormatting(c.rightTitle), rightX + 12, rightY, { width: colW - 24 });
4578
+ rightY += 22;
4579
+ }
4580
+ for (const el of c.right) {
4581
+ rightY = this.renderElement(doc, el, rightX + 12, rightY, colW - 24, theme) + 6;
4582
+ }
4583
+ const totalH = Math.max(leftY - y, rightY - y, 60) + 12;
4584
+ doc.roundedRect(x, y, colW, totalH, 8).strokeColor(theme.colors.border || "rgba(255,255,255,0.15)").stroke();
4585
+ doc.roundedRect(rightX, y, colW, totalH, 8).strokeColor(theme.colors.border || "rgba(255,255,255,0.15)").stroke();
4586
+ return y + totalH + 8;
4587
+ }
4588
+ case "chart": {
4589
+ const ch = element;
4590
+ const boxH = 130;
4591
+ doc.roundedRect(x, y, width, boxH, 8).fill(theme.colors.surface || "rgba(255,255,255,0.04)");
4592
+ doc.roundedRect(x, y, width, boxH, 8).strokeColor(theme.colors.border || "rgba(255,255,255,0.1)").stroke();
4593
+ let topY = y + 10;
4594
+ if (ch.title) {
4595
+ doc.font("Helvetica-Bold").fontSize(13).fillColor(theme.colors.text).text(this.stripFormatting(ch.title), x + 14, topY, { width: width - 28 });
4596
+ topY += 20;
4597
+ }
4598
+ const values = ch.series[0]?.values || [];
4599
+ const maxVal = Math.max(...values, 1);
4600
+ const plotH = boxH - (topY - y) - 28;
4601
+ const barW = Math.min(40, (width - 40) / Math.max(values.length, 1) * 0.6);
4602
+ values.forEach((val, idx) => {
4603
+ const barX = x + 24 + idx * ((width - 48) / Math.max(values.length, 1));
4604
+ const h = val / maxVal * plotH;
4605
+ const barY = topY + plotH - h;
4606
+ doc.rect(barX, barY, barW, h).fill(theme.colors.primary);
4607
+ doc.font("Helvetica").fontSize(9).fillColor(theme.colors.text).text(String(val), barX, barY - 12, { width: barW, align: "center" });
4608
+ if (ch.labels[idx]) {
4609
+ doc.font("Helvetica").fontSize(9).fillColor(theme.colors.muted || "#888888").text(this.stripFormatting(ch.labels[idx]), barX - 10, topY + plotH + 4, {
4610
+ width: barW + 20,
4611
+ align: "center"
4612
+ });
4613
+ }
4614
+ });
4615
+ return y + boxH + 8;
4616
+ }
4617
+ case "mermaid": {
4618
+ const m = element;
4619
+ const boxH = 90;
4620
+ doc.roundedRect(x, y, width, boxH, 8).fill(theme.colors.surface || "rgba(255,255,255,0.04)");
4621
+ doc.roundedRect(x, y, width, boxH, 8).strokeColor(theme.colors.primary).stroke();
4622
+ doc.font("Courier").fontSize(11).fillColor(theme.colors.text).text(this.stripFormatting(m.code), x + 12, y + 12, { width: width - 24 });
4623
+ return y + boxH + 8;
4624
+ }
3721
4625
  default:
3722
4626
  return y;
3723
4627
  }
@@ -3849,7 +4753,7 @@ function startDevServer(filePath, options = {}) {
3849
4753
  // src/cli.ts
3850
4754
  import { mkdirSync, readFileSync as readFileSync2, watch as fsWatch, writeFileSync } from "fs";
3851
4755
  import { basename, dirname, extname, join, resolve as resolve2 } from "path";
3852
- var VERSION = "0.1.15";
4756
+ var VERSION = "0.1.16";
3853
4757
  function printHelp() {
3854
4758
  return `
3855
4759
  YumiaMD \u2014 Markdown-based presentation compiler (v${VERSION})
@@ -3866,6 +4770,7 @@ Commands:
3866
4770
  inspect <file> Inspect the AST and geometric layout tree
3867
4771
  schema Output machine-readable JSON schema for AI agents
3868
4772
  build <file> Compile a presentation to PowerPoint (.pptx), PDF (.pdf), or HTML (.html)
4773
+ deploy <file> Export and deploy presentation to static site, GitHub Pages, or Vercel
3869
4774
 
3870
4775
  Theming & Color Options:
3871
4776
  --theme, -t <name> Base theme: default | cyberpunk | minimal | corporate | terminal | academic
@@ -4196,6 +5101,68 @@ ${summary}${isStrict && report.warnings.length > 0 ? " (failed due to --strict)"
4196
5101
  };
4197
5102
  }
4198
5103
  }
5104
+ if (command === "deploy") {
5105
+ if (!target) {
5106
+ const msg = "Error: Please specify a presentation file to deploy (e.g. 'yumia deploy presentation.yumia.md')";
5107
+ return { exitCode: 1, output: isJson ? JSON.stringify({ error: msg }) : msg };
5108
+ }
5109
+ try {
5110
+ const resolvedInput = resolve2(process.cwd(), target);
5111
+ const source = readFileSync2(resolvedInput, "utf-8");
5112
+ const provider = (getFlagValue(args, ["--provider"]) || "static").toLowerCase();
5113
+ const outDir = resolve2(process.cwd(), getFlagValue(args, ["--out", "-o"]) || "dist-site");
5114
+ mkdirSync(outDir, { recursive: true });
5115
+ const compiler = new YumiaCompiler();
5116
+ const htmlRenderer = new HtmlRenderer();
5117
+ const result = await compiler.compile(source, htmlRenderer);
5118
+ const indexPath = join(outDir, "index.html");
5119
+ writeFileSync(indexPath, result.html, "utf-8");
5120
+ if (provider === "gh-pages" || provider === "github") {
5121
+ writeFileSync(join(outDir, ".nojekyll"), "", "utf-8");
5122
+ } else if (provider === "vercel") {
5123
+ const vercelConfig = {
5124
+ version: 2,
5125
+ cleanUrls: true,
5126
+ routes: [{ src: "/(.*)", dest: "/index.html" }]
5127
+ };
5128
+ writeFileSync(join(outDir, "vercel.json"), JSON.stringify(vercelConfig, null, 2), "utf-8");
5129
+ }
5130
+ if (isJson) {
5131
+ return {
5132
+ exitCode: 0,
5133
+ output: JSON.stringify(
5134
+ {
5135
+ success: true,
5136
+ provider,
5137
+ outputDirectory: outDir,
5138
+ indexPath,
5139
+ slideCount: result.slideCount
5140
+ },
5141
+ null,
5142
+ 2
5143
+ )
5144
+ };
5145
+ }
5146
+ return {
5147
+ exitCode: 0,
5148
+ output: [
5149
+ `\u{1F680} YumiaMD Presentation Deployment Ready!`,
5150
+ `\u2713 Standalone interactive deck compiled (${result.slideCount} slides)`,
5151
+ `\u2713 Target Directory: ${outDir}`,
5152
+ `\u2713 Provider Profile: ${provider}`,
5153
+ `\u2713 Entrypoint: ${indexPath}`,
5154
+ ``,
5155
+ provider === "gh-pages" ? `To publish to GitHub Pages: push '${outDir}' contents to 'gh-pages' branch.` : `To deploy to Vercel/Netlify/S3: run 'vercel ${outDir}' or host files from '${outDir}'.`
5156
+ ].join("\n")
5157
+ };
5158
+ } catch (err) {
5159
+ const msg = err instanceof Error ? err.message : String(err);
5160
+ if (isJson) {
5161
+ return { exitCode: 1, output: JSON.stringify({ success: false, error: msg }) };
5162
+ }
5163
+ return { exitCode: 1, output: `\u2717 Deployment build failed: ${msg}` };
5164
+ }
5165
+ }
4199
5166
  if (command === "build" || command === "watch") {
4200
5167
  if (!target) {
4201
5168
  const msg = `Error: Please specify a presentation file to ${command}.`;
@@ -4314,6 +5281,11 @@ export {
4314
5281
  createCode,
4315
5282
  createQuote,
4316
5283
  createTable,
5284
+ createChart,
5285
+ createMermaid,
5286
+ createTimeline,
5287
+ createCompare,
5288
+ createBadge,
4317
5289
  createGroup,
4318
5290
  createColumn,
4319
5291
  createColumns,
package/dist/index.d.ts CHANGED
@@ -9,7 +9,7 @@ export * from '@yumiamd/renderer-pptx';
9
9
  export * from '@yumiamd/renderer-html';
10
10
  export * from '@yumiamd/renderer-pdf';
11
11
 
12
- declare const VERSION = "0.1.15";
12
+ declare const VERSION = "0.1.16";
13
13
  declare function printHelp(): string;
14
14
  declare function runCli(argv: string[]): Promise<{
15
15
  exitCode: number;
package/dist/index.js CHANGED
@@ -13,15 +13,19 @@ import {
13
13
  academicTheme,
14
14
  cleanFontFace,
15
15
  corporateTheme,
16
+ createBadge,
16
17
  createCard,
18
+ createChart,
17
19
  createCode,
18
20
  createColumn,
19
21
  createColumns,
22
+ createCompare,
20
23
  createGroup,
21
24
  createHeading,
22
25
  createImage,
23
26
  createLayoutDirective,
24
27
  createList,
28
+ createMermaid,
25
29
  createMetric,
26
30
  createParagraph,
27
31
  createPresentation,
@@ -29,6 +33,7 @@ import {
29
33
  createSlide,
30
34
  createTable,
31
35
  createTheme,
36
+ createTimeline,
32
37
  cyberpunkTheme,
33
38
  defaultTheme,
34
39
  minimalTheme,
@@ -39,7 +44,7 @@ import {
39
44
  runCli,
40
45
  startDevServer,
41
46
  terminalTheme
42
- } from "./chunk-7A5BHABM.js";
47
+ } from "./chunk-UPUEFJLX.js";
43
48
  export {
44
49
  DEFAULT_VIEWPORT,
45
50
  DefaultLayoutEngine,
@@ -55,15 +60,19 @@ export {
55
60
  academicTheme,
56
61
  cleanFontFace,
57
62
  corporateTheme,
63
+ createBadge,
58
64
  createCard,
65
+ createChart,
59
66
  createCode,
60
67
  createColumn,
61
68
  createColumns,
69
+ createCompare,
62
70
  createGroup,
63
71
  createHeading,
64
72
  createImage,
65
73
  createLayoutDirective,
66
74
  createList,
75
+ createMermaid,
67
76
  createMetric,
68
77
  createParagraph,
69
78
  createPresentation,
@@ -71,6 +80,7 @@ export {
71
80
  createSlide,
72
81
  createTable,
73
82
  createTheme,
83
+ createTimeline,
74
84
  cyberpunkTheme,
75
85
  defaultTheme,
76
86
  minimalTheme,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yumiamd",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "description": "Command line interface and compiler for YumiaMD presentations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -21,15 +21,15 @@
21
21
  },
22
22
  "devDependencies": {
23
23
  "tsup": "^8.5.1",
24
- "@yumiamd/ast": "0.1.15",
25
- "@yumiamd/parser": "0.1.15",
26
- "@yumiamd/core": "0.1.15",
27
- "@yumiamd/renderer-html": "0.1.15",
28
- "@yumiamd/renderer": "0.1.15",
29
- "@yumiamd/layout": "0.1.15",
30
- "@yumiamd/renderer-pptx": "0.1.15",
31
- "@yumiamd/theme": "0.1.15",
32
- "@yumiamd/renderer-pdf": "0.1.15"
24
+ "@yumiamd/core": "0.1.16",
25
+ "@yumiamd/renderer": "0.1.16",
26
+ "@yumiamd/ast": "0.1.16",
27
+ "@yumiamd/layout": "0.1.16",
28
+ "@yumiamd/parser": "0.1.16",
29
+ "@yumiamd/renderer-html": "0.1.16",
30
+ "@yumiamd/renderer-pptx": "0.1.16",
31
+ "@yumiamd/theme": "0.1.16",
32
+ "@yumiamd/renderer-pdf": "0.1.16"
33
33
  },
34
34
  "keywords": [
35
35
  "yumia",