yumiamd 0.1.34 → 0.1.36

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-VTY4XT47.js";
4
+ } from "./chunk-EZEUXKPI.js";
5
5
 
6
6
  // src/bin.ts
7
7
  var result = await runCli(process.argv);
@@ -40,12 +40,13 @@ function createImage(src, alt, caption, options) {
40
40
  ...options || {}
41
41
  };
42
42
  }
43
- function createCard(elements, title, variant) {
43
+ function createCard(elements, title, variant, icon) {
44
44
  return {
45
45
  type: "card",
46
46
  elements,
47
47
  ...title ? { title } : {},
48
- ...variant ? { variant } : {}
48
+ ...variant ? { variant } : {},
49
+ ...icon ? { icon } : {}
49
50
  };
50
51
  }
51
52
  function createMetric(value, label, variant, description, unit, change) {
@@ -1814,10 +1815,10 @@ var NativeYumiaParser = class {
1814
1815
  return { element: heroEl, nextIdx };
1815
1816
  }
1816
1817
  case "callout": {
1817
- const titleMatch = tok.args.match(/title=["']([^"']+)["']/);
1818
- const sevMatch = tok.args.match(/\b(?:severity|variant)=["']?([^"'\s]+)["']?/);
1819
- const iconMatch = tok.args.match(/\bicon=["']?([^"'\s]+)["']?/);
1820
- let text = this.stripQuotes(tok.args.replace(/title=["'][^"']+["']/, "").replace(/(?:severity|variant|icon)=["']?[^"'\s]+["']?/g, ""));
1818
+ const titleVal = this.extractAttr(tok.args, "title");
1819
+ const sevVal = this.extractAttr(tok.args, "severity") ?? this.extractAttr(tok.args, "variant");
1820
+ const iconVal = this.extractAttr(tok.args, "icon");
1821
+ let text = this.stripQuotes(tok.args.replace(/\btitle=(?:"[^"]*"|'[^']*'|\S+)/g, "").replace(/\b(?:severity|variant|icon)=(?:"[^"]*"|'[^']*'|\S+)/g, ""));
1821
1822
  let nextIdx = idx + 1;
1822
1823
  if (!text) {
1823
1824
  const cLines = [];
@@ -1827,7 +1828,7 @@ var NativeYumiaParser = class {
1827
1828
  }
1828
1829
  text = cLines.join(" ");
1829
1830
  }
1830
- const calloutEl = createCallout(text || "Note", sevMatch ? sevMatch[1] : "info", titleMatch ? titleMatch[1] : void 0, iconMatch ? iconMatch[1] : void 0);
1831
+ const calloutEl = createCallout(text || "Note", sevVal ? sevVal : "info", titleVal, iconVal);
1831
1832
  calloutEl.loc = {
1832
1833
  start: { line: tok.lineNum, column: 1 },
1833
1834
  end: { line: tok.lineNum, column: tok.text.length }
@@ -1888,10 +1889,11 @@ var NativeYumiaParser = class {
1888
1889
  };
1889
1890
  }
1890
1891
  case "card": {
1891
- const titleMatch = tok.args.match(/title=["']([^"']+)["']/);
1892
- const variantMatch = tok.args.match(/variant=["']?([^"'\s]+)["']?/);
1893
- const title = titleMatch ? titleMatch[1] : this.stripQuotes(tok.args) || void 0;
1894
- const variant = variantMatch ? variantMatch[1] : "default";
1892
+ const titleVal = this.extractAttr(tok.args, "title");
1893
+ const variantVal = this.extractAttr(tok.args, "variant");
1894
+ const iconVal = this.extractAttr(tok.args, "icon");
1895
+ const title = titleVal ?? (this.stripQuotes(tok.args) || void 0);
1896
+ const variant = variantVal ? variantVal : "default";
1895
1897
  const children = [];
1896
1898
  let nextIdx = idx + 1;
1897
1899
  while (nextIdx < tokens.length && tokens[nextIdx].indent > baseIndent) {
@@ -1903,7 +1905,7 @@ var NativeYumiaParser = class {
1903
1905
  nextIdx++;
1904
1906
  }
1905
1907
  }
1906
- return { element: createCard(children, title, variant), nextIdx };
1908
+ return { element: createCard(children, title, variant, iconVal), nextIdx };
1907
1909
  }
1908
1910
  case "column": {
1909
1911
  const children = [];
@@ -1974,14 +1976,14 @@ var NativeYumiaParser = class {
1974
1976
  };
1975
1977
  }
1976
1978
  case "metric": {
1977
- const valMatch = tok.args.match(/^(?:value=)?["']([^"']+)["']/);
1978
- const labelMatch = tok.args.match(/\blabel=["']([^"']+)["']/);
1979
- const diffMatch = tok.args.match(/\bdiff=["']([^"']+)["']/);
1980
- const variantMatch = tok.args.match(/\bvariant=["']?([^"'\s]+)["']?/);
1981
- const value = valMatch ? valMatch[1] : "0";
1982
- const label = labelMatch ? labelMatch[1] : "Metric";
1979
+ const valVal = this.extractAttr(tok.args, "value") ?? this.extractAttr(tok.args);
1980
+ const labelVal = this.extractAttr(tok.args, "label");
1981
+ const diffVal = this.extractAttr(tok.args, "diff") ?? this.extractAttr(tok.args, "change");
1982
+ const variantVal = this.extractAttr(tok.args, "variant");
1983
+ const value = valVal || "0";
1984
+ const label = labelVal || "Metric";
1983
1985
  return {
1984
- element: createMetric(value, label, variantMatch ? variantMatch[1] : "primary", void 0, void 0, diffMatch ? diffMatch[1] : void 0),
1986
+ element: createMetric(value, label, variantVal || "primary", void 0, void 0, diffVal),
1985
1987
  nextIdx: idx + 1
1986
1988
  };
1987
1989
  }
@@ -2451,10 +2453,8 @@ var NativeYumiaParser = class {
2451
2453
  return { element: classEl, nextIdx };
2452
2454
  }
2453
2455
  case "compare": {
2454
- const leftTitleMatch = tok.args.match(/\bleft(?:Title)?=["']([^"']+)["']/);
2455
- const rightTitleMatch = tok.args.match(/\bright(?:Title)?=["']([^"']+)["']/);
2456
- const leftTitle = leftTitleMatch ? leftTitleMatch[1] : void 0;
2457
- const rightTitle = rightTitleMatch ? rightTitleMatch[1] : void 0;
2456
+ const leftTitle = this.extractAttr(tok.args, "left") ?? this.extractAttr(tok.args, "leftTitle");
2457
+ const rightTitle = this.extractAttr(tok.args, "right") ?? this.extractAttr(tok.args, "rightTitle");
2458
2458
  const leftEls = [];
2459
2459
  const rightEls = [];
2460
2460
  let currentSide = "left";
@@ -2491,13 +2491,13 @@ var NativeYumiaParser = class {
2491
2491
  while (nextIdx < tokens.length && tokens[nextIdx].indent > baseIndent) {
2492
2492
  const sub = tokens[nextIdx];
2493
2493
  if (sub.command === "item") {
2494
- const dateMatch = sub.args.match(/date=["']([^"']+)["']/);
2495
- const titleMatch = sub.args.match(/title=["']([^"']+)["']/);
2496
- const descMatch = sub.args.match(/desc(?:ription)?=["']([^"']+)["']/);
2494
+ const dateVal = this.extractAttr(sub.args, "date");
2495
+ const titleVal = this.extractAttr(sub.args, "title");
2496
+ const descVal = this.extractAttr(sub.args, "desc") ?? this.extractAttr(sub.args, "description");
2497
2497
  items.push({
2498
- date: dateMatch ? dateMatch[1] : "2026",
2499
- title: titleMatch ? titleMatch[1] : "Milestone",
2500
- description: descMatch ? descMatch[1] : void 0
2498
+ date: dateVal || "2026",
2499
+ title: titleVal || "Milestone",
2500
+ description: descVal
2501
2501
  });
2502
2502
  }
2503
2503
  nextIdx++;
@@ -6513,11 +6513,26 @@ var PptxRenderer = class {
6513
6513
  fill: { color: borderColor },
6514
6514
  rectRadius: 0.03
6515
6515
  });
6516
+ let titleOffset = 0.25;
6517
+ if (card.icon) {
6518
+ try {
6519
+ const raster = rasterizeIcon(card.icon, 32, "#" + titleColor);
6520
+ pptxSlide.addImage({
6521
+ data: `image/png;base64,${raster.png.toString("base64")}`,
6522
+ x: rect.x + 0.22,
6523
+ y: rect.y + 0.14,
6524
+ w: 0.24,
6525
+ h: 0.24
6526
+ });
6527
+ titleOffset = 0.52;
6528
+ } catch {
6529
+ }
6530
+ }
6516
6531
  if (card.title) {
6517
6532
  pptxSlide.addText(card.title, {
6518
- x: rect.x + 0.25,
6533
+ x: rect.x + titleOffset,
6519
6534
  y: rect.y + 0.12,
6520
- w: rect.w - 0.5,
6535
+ w: rect.w - titleOffset - 0.25,
6521
6536
  h: 0.3,
6522
6537
  fontSize: themeSizeToPptxPoints(theme.typography.sizes?.h4, 22),
6523
6538
  bold: true,
@@ -6714,12 +6729,27 @@ var PptxRenderer = class {
6714
6729
  line: { color: sevColor, width: 2 },
6715
6730
  rectRadius: 0.08
6716
6731
  });
6732
+ let titleOffset = 0.2;
6733
+ if (callout.icon) {
6734
+ try {
6735
+ const raster = rasterizeIcon(callout.icon, 32, "#" + sevColor);
6736
+ pptxSlide.addImage({
6737
+ data: `image/png;base64,${raster.png.toString("base64")}`,
6738
+ x: rect.x + 0.2,
6739
+ y: rect.y + 0.16,
6740
+ w: 0.22,
6741
+ h: 0.22
6742
+ });
6743
+ titleOffset = 0.48;
6744
+ } catch {
6745
+ }
6746
+ }
6717
6747
  const titleH = callout.title ? 0.38 : 0;
6718
6748
  if (callout.title) {
6719
6749
  pptxSlide.addText(callout.title, {
6720
- x: rect.x + 0.2,
6750
+ x: rect.x + titleOffset,
6721
6751
  y: rect.y + 0.16,
6722
- w: rect.w - 0.4,
6752
+ w: rect.w - titleOffset - 0.2,
6723
6753
  h: 0.3,
6724
6754
  fontSize: 13,
6725
6755
  bold: true,
@@ -9687,7 +9717,9 @@ var HtmlRenderer = class {
9687
9717
  const c = element;
9688
9718
  const sev = c.severity || "info";
9689
9719
  const colorVar = sev === "warning" ? "var(--yumia-warning)" : sev === "danger" ? "var(--yumia-danger)" : sev === "success" ? "var(--yumia-success)" : "var(--yumia-info)";
9690
- const titleHtml = c.title ? `<div style="font-weight:700; font-size:1.05rem; color:${colorVar}; margin-bottom:4px;">${this.formatInline(c.title)}</div>` : "";
9720
+ const iconSvg = c.icon ? defaultIconResolver.toSvg(c.icon, 20, colorVar, "yumia-callout-icon") : "";
9721
+ const iconSpan = iconSvg ? `<span style="display:inline-flex; align-items:center; margin-right:8px; vertical-align:middle;">${iconSvg}</span>` : "";
9722
+ const titleHtml = c.title ? `<div style="font-weight:700; font-size:1.05rem; color:${colorVar}; margin-bottom:4px; display:flex; align-items:center;">${iconSpan}${this.formatInline(c.title)}</div>` : iconSpan ? `<div style="margin-bottom:4px;">${iconSpan}</div>` : "";
9691
9723
  return `
9692
9724
  <div class="yumia-callout" data-severity="${sev}" data-yumia-role="callout" style="background:var(--yumia-surface); border-left:4px solid ${colorVar}; border-radius:var(--yumia-radius-card); padding:1rem 1.4rem; margin:0.8rem 0; width:100%; display:flex; flex-direction:column; gap:6px; box-sizing:border-box;">
9693
9725
  ${titleHtml}
@@ -9862,7 +9894,9 @@ var HtmlRenderer = class {
9862
9894
  case "card": {
9863
9895
  const card = element;
9864
9896
  const variant = card.variant || "default";
9865
- const titleHtml = card.title ? `<div class="yumia-card-title">${this.escapeHtml(card.title)}</div>` : "";
9897
+ const iconSvg = card.icon ? defaultIconResolver.toSvg(card.icon, 20, "currentColor", "yumia-card-icon") : "";
9898
+ const iconHtml = iconSvg ? `<span class="yumia-card-icon" style="display:inline-flex; align-items:center; vertical-align:middle;">${iconSvg}</span>` : "";
9899
+ const titleHtml = card.title ? `<div class="yumia-card-title" style="display:flex; align-items:center; gap:8px;">${iconHtml}<span>${this.escapeHtml(card.title)}</span></div>` : iconHtml ? `<div class="yumia-card-title">${iconHtml}</div>` : "";
9866
9900
  const innerHtml = card.elements ? card.elements.map((child) => this.renderElement(child, theme)).join("\n") : "";
9867
9901
  return `
9868
9902
  <div class="yumia-card" data-variant="${variant}">
@@ -10932,9 +10966,20 @@ var PdfRenderer = class {
10932
10966
  doc.roundedRect(x, y, width, totalH, 6).fill(theme.colors.surface || "#151522");
10933
10967
  doc.rect(x, y, 4, totalH).fill(sevColor);
10934
10968
  let curY = y + 8;
10969
+ let titleOffset = 16;
10970
+ if (c.icon) {
10971
+ try {
10972
+ const raster = rasterizeIcon(c.icon, 18, sevColor);
10973
+ doc.image(raster.png, x + 16, curY - 1, { width: 16, height: 16 });
10974
+ titleOffset = 38;
10975
+ } catch {
10976
+ }
10977
+ }
10935
10978
  if (c.title) {
10936
10979
  doc.font(this.getPdfFont(theme, "bold")).fontSize(12).fillColor(sevColor);
10937
- doc.text(this.stripFormatting(c.title), x + 16, curY, { width: width - 26 });
10980
+ doc.text(this.stripFormatting(c.title), x + titleOffset, curY, {
10981
+ width: width - titleOffset - 10
10982
+ });
10938
10983
  curY += 18;
10939
10984
  }
10940
10985
  doc.font(this.getPdfFont(theme, "regular")).fontSize(12).fillColor(theme.colors.text);
@@ -11114,11 +11159,22 @@ var PdfRenderer = class {
11114
11159
  doc.roundedRect(x, y, width, totalCardHeight, 8).lineWidth(1.5).strokeColor(variantColor).stroke();
11115
11160
  doc.restore();
11116
11161
  let renderTop = y + cardPad;
11162
+ let titleOffset = cardPad;
11163
+ if (card.icon) {
11164
+ try {
11165
+ const raster = rasterizeIcon(card.icon, 20, variantColor);
11166
+ doc.image(raster.png, x + cardPad, renderTop - 1, { width: 16, height: 16 });
11167
+ titleOffset = cardPad + 22;
11168
+ } catch {
11169
+ }
11170
+ }
11117
11171
  if (card.title) {
11118
- doc.font(this.getPdfFont(theme, "bold")).fontSize(15).fillColor(variantColor).text(this.stripFormatting(card.title), x + cardPad, renderTop, {
11119
- width: width - cardPad * 2
11172
+ doc.font(this.getPdfFont(theme, "bold")).fontSize(15).fillColor(variantColor).text(this.stripFormatting(card.title), x + titleOffset, renderTop, {
11173
+ width: width - cardPad - titleOffset
11120
11174
  });
11121
- renderTop += doc.heightOfString(this.stripFormatting(card.title), { width: width - cardPad * 2 }) + 8;
11175
+ renderTop += doc.heightOfString(this.stripFormatting(card.title), {
11176
+ width: width - cardPad - titleOffset
11177
+ }) + 8;
11122
11178
  }
11123
11179
  if (card.elements) {
11124
11180
  for (const child of card.elements) {
@@ -12061,7 +12117,7 @@ function startDevServer(filePath, options = {}) {
12061
12117
  // src/cli.ts
12062
12118
  import { mkdirSync, readFileSync as readFileSync3, watch as fsWatch, writeFileSync } from "fs";
12063
12119
  import { basename, dirname, extname, join, resolve as resolve3 } from "path";
12064
- var VERSION = "0.1.34";
12120
+ var VERSION = "0.1.36";
12065
12121
  function printHelp() {
12066
12122
  return `
12067
12123
  YumiaMD \u2014 Markdown-based presentation compiler (v${VERSION})
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.34";
12
+ declare const VERSION = "0.1.36";
13
13
  declare function printHelp(): string;
14
14
  declare function runCli(argv: string[]): Promise<{
15
15
  exitCode: number;
package/dist/index.js CHANGED
@@ -92,7 +92,7 @@ import {
92
92
  themeSizeToPptxPoints,
93
93
  tokyoNightTheme,
94
94
  validate
95
- } from "./chunk-VTY4XT47.js";
95
+ } from "./chunk-EZEUXKPI.js";
96
96
  export {
97
97
  DEFAULT_VIEWPORT,
98
98
  DefaultLayoutEngine,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yumiamd",
3
- "version": "0.1.34",
3
+ "version": "0.1.36",
4
4
  "description": "Command line interface and compiler for YumiaMD presentations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,15 +22,15 @@
22
22
  },
23
23
  "devDependencies": {
24
24
  "tsup": "^8.5.1",
25
- "@yumiamd/ast": "0.1.34",
26
- "@yumiamd/parser": "0.1.34",
27
- "@yumiamd/layout": "0.1.34",
28
- "@yumiamd/core": "0.1.34",
29
- "@yumiamd/renderer-pdf": "0.1.34",
30
- "@yumiamd/renderer": "0.1.34",
31
- "@yumiamd/renderer-pptx": "0.1.34",
32
- "@yumiamd/renderer-html": "0.1.34",
33
- "@yumiamd/theme": "0.1.34"
25
+ "@yumiamd/ast": "0.1.36",
26
+ "@yumiamd/layout": "0.1.36",
27
+ "@yumiamd/renderer-pdf": "0.1.36",
28
+ "@yumiamd/core": "0.1.36",
29
+ "@yumiamd/renderer": "0.1.36",
30
+ "@yumiamd/parser": "0.1.36",
31
+ "@yumiamd/renderer-pptx": "0.1.36",
32
+ "@yumiamd/renderer-html": "0.1.36",
33
+ "@yumiamd/theme": "0.1.36"
34
34
  },
35
35
  "keywords": [
36
36
  "yumia",