@diagrammo/dgmo 0.50.1 → 0.50.2

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/auto.mjs CHANGED
@@ -13545,6 +13545,8 @@ function parseChart(content, palette) {
13545
13545
  result.solidFill = true;
13546
13546
  } else if (firstToken === "no-title") {
13547
13547
  result.noTitle = true;
13548
+ } else if (firstToken === "no-auto-y") {
13549
+ result.noAutoY = true;
13548
13550
  } else if (firstToken === "fill") {
13549
13551
  result.fill = true;
13550
13552
  } else if (firstToken === "hole") {
@@ -13839,6 +13841,7 @@ var init_chart = __esm({
13839
13841
  "orientation-horizontal",
13840
13842
  "solid-fill",
13841
13843
  "no-title",
13844
+ "no-auto-y",
13842
13845
  "fill",
13843
13846
  "hole"
13844
13847
  ]);
@@ -31924,7 +31927,14 @@ function renderLine(svg, chart, width, height, colors, palette, isDark, textColo
31924
31927
  hi = Math.max(hi, v);
31925
31928
  }
31926
31929
  if (!isFinite(lo)) return [0, 1];
31927
- if (lo > 0) lo = 0;
31930
+ if (chart.noAutoY) {
31931
+ if (lo > 0) lo = 0;
31932
+ } else {
31933
+ const pad3 = (hi - lo) * 0.05 || Math.abs(hi) * 0.05 || 1;
31934
+ const nlo = lo - pad3;
31935
+ lo = lo >= 0 && nlo < 0 ? 0 : nlo;
31936
+ hi = hi + pad3;
31937
+ }
31928
31938
  if (lo === hi) hi = lo + 1;
31929
31939
  return [lo, hi];
31930
31940
  };
@@ -72501,6 +72511,7 @@ function haloRect(svg, x, y, w, h, rx, C) {
72501
72511
  function pickBand(nowMs, resolvedMs, hasTime) {
72502
72512
  const days = dayDelta(nowMs, resolvedMs);
72503
72513
  if (hasTime && days <= 0) return "clock";
72514
+ if (days > 3 * 365) return "years";
72504
72515
  if (days > 365) return "year";
72505
72516
  if (days > 92) return "months";
72506
72517
  if (days > 18) return "monthgrid";
@@ -72531,9 +72542,31 @@ function monthGridLayout(nowMs, resolvedMs, contentW) {
72531
72542
  }
72532
72543
  return { months, dim };
72533
72544
  }
72545
+ function yearsLayout(nowMs, resolvedMs) {
72546
+ const y0 = new Date(nowMs).getFullYear();
72547
+ const y1 = new Date(resolvedMs).getFullYear();
72548
+ const d0 = Math.floor(y0 / 10) * 10;
72549
+ const d1 = Math.floor(y1 / 10) * 10;
72550
+ return { d0, d1, rows: (d1 - d0) / 10 + 1 };
72551
+ }
72534
72552
  function bandHeightFor(kind, nowMs, resolvedMs, contentW) {
72535
72553
  const clamp5 = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
72536
72554
  switch (kind) {
72555
+ case "years": {
72556
+ const { rows } = yearsLayout(nowMs, resolvedMs);
72557
+ const rowGap = 11;
72558
+ const labW = 54;
72559
+ const gap = 7;
72560
+ const cellW = (contentW - labW - 10 * gap) / 10;
72561
+ let cellH = clamp5(cellW * 0.5, 26, 40);
72562
+ const MAX = 380;
72563
+ let total = rows * cellH + (rows - 1) * rowGap;
72564
+ if (total > MAX) {
72565
+ cellH = Math.max(9, (MAX - (rows - 1) * rowGap) / rows);
72566
+ total = rows * cellH + (rows - 1) * rowGap;
72567
+ }
72568
+ return total;
72569
+ }
72537
72570
  case "year": {
72538
72571
  const R = new Date(resolvedMs).getFullYear() - new Date(nowMs).getFullYear() + 1;
72539
72572
  const yearW = 66;
@@ -72572,6 +72605,61 @@ function bandHeightFor(kind, nowMs, resolvedMs, contentW) {
72572
72605
  return clamp5(contentW * 0.22, 125, 170);
72573
72606
  }
72574
72607
  }
72608
+ function vizYears(svg, g, nowMs, resolvedMs, C) {
72609
+ const now = new Date(nowMs);
72610
+ const ev = new Date(resolvedMs);
72611
+ const nowY = now.getFullYear();
72612
+ const evY = ev.getFullYear();
72613
+ const { d0, rows } = yearsLayout(nowMs, resolvedMs);
72614
+ const labW = 54;
72615
+ const gap = 7;
72616
+ const rowGap = 11;
72617
+ const rowH = (g.height - rowGap * (rows - 1)) / rows;
72618
+ const cellH = rowH;
72619
+ const cellW = (g.contentW - labW - 10 * gap) / 10;
72620
+ const rx = Math.min(6, Math.min(cellW, cellH) * 0.22);
72621
+ const showLabel = cellH >= 18 && cellW >= 22;
72622
+ const yrFont = Math.min(12, cellW * 0.34, cellH * 0.5);
72623
+ for (let r = 0; r < rows; r++) {
72624
+ const dec = d0 + r * 10;
72625
+ const ry = g.top + r * (rowH + rowGap);
72626
+ aText(
72627
+ svg,
72628
+ g.left + labW - 12,
72629
+ ry + rowH / 2,
72630
+ Math.min(14, rowH * 0.5),
72631
+ C.muted,
72632
+ 800,
72633
+ "end",
72634
+ `${dec}s`,
72635
+ { "dominant-baseline": "central" }
72636
+ );
72637
+ for (let i = 0; i < 10; i++) {
72638
+ const yr = dec + i;
72639
+ const before = yr < nowY;
72640
+ const isNow = yr === nowY;
72641
+ const isEv = yr === evY;
72642
+ const between = yr > nowY && yr < evY;
72643
+ const st = isEv ? roleStyle(C, "event") : isNow ? roleStyle(C, "today") : between ? gradStyle(C, (yr - nowY) / (evY - nowY)) : roleStyle(C, before ? "past" : "future");
72644
+ const x = g.left + labW + i * (cellW + gap);
72645
+ aRect(svg, x, ry, cellW, cellH, rx, st.fill, st.stroke, 1);
72646
+ if (isEv) haloRect(svg, x, ry, cellW, cellH, rx, C);
72647
+ if (showLabel) {
72648
+ aText(
72649
+ svg,
72650
+ x + cellW / 2,
72651
+ ry + cellH / 2,
72652
+ yrFont,
72653
+ st.text,
72654
+ isNow || isEv ? 800 : 650,
72655
+ "middle",
72656
+ String(yr),
72657
+ { "dominant-baseline": "central" }
72658
+ );
72659
+ }
72660
+ }
72661
+ }
72662
+ }
72575
72663
  function vizYear(svg, g, nowMs, resolvedMs, C) {
72576
72664
  const now = new Date(nowMs);
72577
72665
  const ev = new Date(resolvedMs);
@@ -73083,6 +73171,8 @@ function pad22(n) {
73083
73171
  }
73084
73172
  function drawBand2(svg, kind, g, nowMs, resolvedMs, C) {
73085
73173
  switch (kind) {
73174
+ case "years":
73175
+ return vizYears(svg, g, nowMs, resolvedMs, C);
73086
73176
  case "year":
73087
73177
  return vizYear(svg, g, nowMs, resolvedMs, C);
73088
73178
  case "months":
@@ -73762,13 +73852,13 @@ function drawRow(svg, entry, index, parsed, now, rowTop, rowH, geom, col) {
73762
73852
  const mainFont = 48;
73763
73853
  const baseY = center + 16;
73764
73854
  const capTop = baseY - mainFont * 0.7;
73765
- g.append("text").attr("data-dgmo-clock-digital", "").attr("data-dgmo-clock-digital-part", "main").attr("x", contentLeft).attr("y", baseY).attr("fill", timeColor).attr("font-family", FONT_FAMILY).attr("font-size", mainFont).attr("font-weight", 600).style("font-variant-numeric", "tabular-nums").text(ts.main);
73766
73855
  const sf = 20;
73767
73856
  const mainW = [...ts.main].reduce(
73768
- (w, c) => w + mainFont * (c === ":" ? 0.28 : 0.6),
73857
+ (w, c) => w + mainFont * (c === ":" ? 0.334 : 0.6),
73769
73858
  0
73770
73859
  );
73771
73860
  const stackX = contentLeft + mainW + 5;
73861
+ g.append("text").attr("data-dgmo-clock-digital", "").attr("data-dgmo-clock-digital-part", "main").attr("x", contentLeft).attr("y", baseY).attr("fill", timeColor).attr("font-family", FONT_FAMILY).attr("font-size", mainFont).attr("font-weight", 600).attr("textLength", mainW).attr("lengthAdjust", "spacing").style("font-variant-numeric", "tabular-nums").text(ts.main);
73772
73862
  g.append("text").attr("data-dgmo-clock-digital-part", "sec").attr("x", stackX).attr("y", capTop + sf * 0.72).attr("fill", muted).attr("font-family", FONT_FAMILY).attr("font-size", sf).attr("font-weight", 600).style("font-variant-numeric", "tabular-nums").text(`:${ts.sec}`);
73773
73863
  if (ts.ap)
73774
73864
  g.append("text").attr("data-dgmo-clock-digital-part", "ap").attr("x", stackX).attr("y", baseY).attr("fill", muted).attr("font-family", FONT_FAMILY).attr("font-size", sf).attr("font-weight", 600).text(ts.ap);
@@ -73907,13 +73997,13 @@ function drawColumns(body, parsed, now, top, geom, col) {
73907
73997
  const sf = 13;
73908
73998
  const tf = fitFont(ts.main, 44, innerW - 30, 20);
73909
73999
  const mainW = [...ts.main].reduce(
73910
- (w, c) => w + tf * (c === ":" ? 0.28 : 0.6),
74000
+ (w, c) => w + tf * (c === ":" ? 0.334 : 0.6),
73911
74001
  0
73912
74002
  );
73913
74003
  const stackW = Math.max(estWidth(`:${ts.sec}`, sf), estWidth(ts.ap, sf));
73914
74004
  const gLeft = cx - (mainW + 7 + stackW) / 2;
73915
74005
  const baseY = cy + tf * 0.34;
73916
- g.append("text").attr("data-dgmo-clock-digital", "").attr("data-dgmo-clock-digital-part", "main").attr("x", gLeft).attr("y", baseY).attr("fill", timeColor).attr("font-family", FONT_FAMILY).attr("font-size", tf).attr("font-weight", 600).style("font-variant-numeric", "tabular-nums").text(ts.main);
74006
+ g.append("text").attr("data-dgmo-clock-digital", "").attr("data-dgmo-clock-digital-part", "main").attr("x", gLeft).attr("y", baseY).attr("fill", timeColor).attr("font-family", FONT_FAMILY).attr("font-size", tf).attr("font-weight", 600).attr("textLength", mainW).attr("lengthAdjust", "spacing").style("font-variant-numeric", "tabular-nums").text(ts.main);
73917
74007
  const stackX = gLeft + mainW + 7;
73918
74008
  g.append("text").attr("data-dgmo-clock-digital-part", "sec").attr("x", stackX).attr("y", baseY - tf * 0.32).attr("fill", muted).attr("font-family", FONT_FAMILY).attr("font-size", sf).attr("font-weight", 500).text(`:${ts.sec}`);
73919
74009
  if (ts.ap)
@@ -81465,7 +81555,7 @@ async function render(content, options) {
81465
81555
  try {
81466
81556
  const raw = await renderDataChartD3(renderContent, theme, paletteColors);
81467
81557
  const svg2 = injectHoverStyles(raw, chartType, { bakeHover });
81468
- return { svg: svg2, diagnostics };
81558
+ return { svg: svg2, diagnostics, chartType: chartType ?? void 0 };
81469
81559
  } finally {
81470
81560
  releaseDom();
81471
81561
  }
@@ -81506,7 +81596,7 @@ async function render(content, options) {
81506
81596
  } catch {
81507
81597
  }
81508
81598
  }
81509
- return { svg, diagnostics };
81599
+ return { svg, diagnostics, chartType: chartType ?? void 0 };
81510
81600
  }
81511
81601
 
81512
81602
  // src/countdown/ticker.ts
@@ -82714,6 +82804,7 @@ function resolveBlockOptions(opts) {
82714
82804
  mode,
82715
82805
  palette: opts.palette ?? "slate",
82716
82806
  colorMode: opts.colorMode ?? "auto",
82807
+ background: opts.background ?? "auto",
82717
82808
  showSource: opts.showSource ?? showcase,
82718
82809
  showCopy: opts.showCopy ?? showcase,
82719
82810
  showExpand: opts.showExpand ?? showcase,
@@ -82816,7 +82907,7 @@ var CSS = AUTO_BASE_CSS + "\n" + BLOCK_CSS + "\n" + darkScopedBlockCss(BLOCK_CSS
82816
82907
 
82817
82908
  // src/auto/shared.ts
82818
82909
  init_safe_href();
82819
- var VERSION = "0.50.1";
82910
+ var VERSION = "0.50.2";
82820
82911
  var ARIA_LABEL_MAX = 200;
82821
82912
  var COPIED_INTERACTION_MS = 1500;
82822
82913
  var LOG_PREFIX = "[dgmo]";
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Canonical stylesheet for the standard DGMO embed block (BL-114).
3
+ *
4
+ * Shipped two ways: `dist/block.css` (extracted at build time by
5
+ * tsup.config.ts, same regex mechanism as auto.css) for `<link>`/import
6
+ * consumers, and the `BLOCK_CSS` string export for embedders that inject a
7
+ * `<style>` tag.
8
+ *
9
+ * Dark mode keys off `[data-theme="dark"]`. Hosts with a different signal
10
+ * (`html.dark`, `body.theme-dark`) rewrite the selector at their build step —
11
+ * fumadocs-dgmo/nextra-dgmo's build-css.mjs is the reference adapter.
12
+ *
13
+ * The `.dgmo-tok-*` role colors mirror LIGHT_ROLE_STYLES (light) and
14
+ * NORD_ROLE_STYLES (dark) from editor/highlight-api.ts. A parity test
15
+ * (tests/block.test.ts) guards against drift — update both when either
16
+ * changes.
17
+ *
18
+ * IMPORTANT: keep this a single pure template literal — the build extracts it
19
+ * with a regex, so no interpolation or computed values.
20
+ */
21
+ declare const BLOCK_CSS: string;
22
+
23
+ /**
24
+ * Standard DGMO embed block (BL-114) — the ONE canonical
25
+ * "diagram + source chrome" HTML builder shared by every embed surface:
26
+ * remark-dgmo (and through it the astro/docusaurus/fumadocs/nextra/vitepress
27
+ * wrappers), the `/auto` script-tag drop-in, `<dgmo-diagram>`, dgmo-mcp HTML
28
+ * reports, the marketing site, and the Obsidian plugin.
29
+ *
30
+ * Chrome contract (user-approved 2026-07-05): the diagram is the star. A slim
31
+ * icon toolbar sits in a reserved row below the SVG, invisible until the
32
+ * block is hovered/focused or the source is open. Four wordless icon
33
+ * buttons — `</>` toggles the hidden source panel, expand (full-screen),
34
+ * copy, open-in-editor. No disclosure triangle, no text labels. The toolbar
35
+ * IS the <summary> of a native <details>, so show/hide works with zero
36
+ * JavaScript; copy and expand need a small delegated click handler
37
+ * (remark-dgmo's `bindDgmo` is the reference — expand's lightbox helper is
38
+ * mirrored across every client surface, same as copy).
39
+ *
40
+ * Markup vocabulary: `figure.dgmo` (`--diagram`/`--showcase`/`--error`),
41
+ * `.dgmo-light`/`.dgmo-dark` (dual color-mode) or `.dgmo-svg` (single),
42
+ * `details.dgmo-source-wrap > summary.dgmo-toolbar`, `.dgmo-source-inner`,
43
+ * `pre.dgmo-pre > span.dgmo-code` with `.dgmo-tok-<role>` token spans. While
44
+ * the source is open the wrapper gets one shared frame (`:has()` rule) so
45
+ * diagram + code read as a single unit. No visible caption — `title` becomes
46
+ * the wrapper's aria-label. Styles ship as `BLOCK_CSS` / `dist/block.css`.
47
+ */
48
+
49
+ /** Default hosted editor used by "Open in editor" links. */
50
+ declare const EDITOR_BASE_URL = "https://online.diagrammo.app";
51
+ type BlockMode = 'diagram' | 'showcase';
52
+ /**
53
+ * Color-mode strategy for the emitted SVG(s).
54
+ * - `auto` — render twice (light + dark) and let CSS flip visibility.
55
+ * - `light` / `dark` / `transparent` — single render with that theme.
56
+ */
57
+ type BlockColorMode = 'auto' | 'light' | 'dark' | 'transparent';
58
+ interface DgmoBlockOptions {
59
+ /** `diagram` (default): SVG only. `showcase`: SVG + source chrome. */
60
+ mode?: BlockMode;
61
+ /** Palette name. Default `slate`; unknown names warn + fall back. */
62
+ palette?: string;
63
+ /** Default `auto` (dual light/dark render). */
64
+ colorMode?: BlockColorMode;
65
+ /**
66
+ * Embed background. `auto` (default) strips the theme's opaque root
67
+ * background so the diagram blends into the host page — except for
68
+ * background-meaningful types like `map`, which stay opaque. `transparent` /
69
+ * `opaque` force the choice regardless of type (the embedder opt-out).
70
+ */
71
+ background?: 'auto' | 'transparent' | 'opaque';
72
+ /** Default: true in showcase mode, false in diagram mode. */
73
+ showSource?: boolean;
74
+ /** Default: true in showcase mode, false in diagram mode. */
75
+ showCopy?: boolean;
76
+ /**
77
+ * Show the expand (full-screen) toolbar button. Default: true in showcase
78
+ * mode, false in diagram mode. Needs the client lightbox handler to do
79
+ * anything (mirrored across surfaces); markup-only surfaces can omit it.
80
+ */
81
+ showExpand?: boolean;
82
+ /** Default: true in showcase mode, false in diagram mode. */
83
+ showOpenInEditor?: boolean;
84
+ /** Base URL for the open-in-editor link. Default: online.diagrammo.app. */
85
+ editorBaseUrl?: string;
86
+ /** Outer wrapper element. Default `figure`. */
87
+ wrapper?: 'figure' | 'div';
88
+ /** Base class for the wrapper (styling hook). Default `dgmo`. */
89
+ className?: string;
90
+ /** Extra classes appended to every emitted wrapper (compat shims). */
91
+ legacyClassNames?: string[];
92
+ /**
93
+ * Accessible name for the block (`aria-label` on the wrapper). NOT rendered
94
+ * visually — the chart's visible title belongs in the DGMO source itself.
95
+ */
96
+ title?: string;
97
+ /** Receives palette-fallback warnings. Default: console.warn. */
98
+ onWarn?: (message: string) => void;
99
+ }
100
+ interface DgmoBlockResult {
101
+ html: string;
102
+ diagnostics: Array<{
103
+ message: string;
104
+ line?: number;
105
+ severity?: string;
106
+ }>;
107
+ }
108
+ /**
109
+ * Render one ```dgmo source block to the standard embed HTML. Async because
110
+ * it runs the full dgmo render pipeline (once per color mode).
111
+ *
112
+ * Render errors are NOT caught here — callers decide between throwing,
113
+ * `errorBlockHtml()`, or their own fallback.
114
+ */
115
+ declare function renderDgmoBlock(source: string, options?: DgmoBlockOptions): Promise<DgmoBlockResult>;
116
+ /**
117
+ * Assemble the standard block around already-rendered SVG markup. Exposed for
118
+ * surfaces that render through their own pipeline (e.g. dgmo-mcp's
119
+ * renderPipeline) but must emit the canonical chrome. `svgsHtml` must be the
120
+ * `.dgmo-light`+`.dgmo-dark` (or `.dgmo-svg`) wrapper divs.
121
+ */
122
+ declare function buildDgmoBlockHtml(source: string, svgsHtml: string, options?: DgmoBlockOptions): string;
123
+ /**
124
+ * Standard error card for a block that failed to parse/render. Same shape on
125
+ * every surface: `.dgmo--error` with `role="alert"`, message + offending
126
+ * source.
127
+ */
128
+ declare function errorBlockHtml(err: unknown, source: string, options?: Pick<DgmoBlockOptions, 'className' | 'legacyClassNames'>): string;
129
+
130
+ export { BLOCK_CSS, type BlockColorMode, type BlockMode, type DgmoBlockOptions, type DgmoBlockResult, EDITOR_BASE_URL, buildDgmoBlockHtml, errorBlockHtml, renderDgmoBlock };
package/dist/block.js CHANGED
@@ -1,16 +1,17 @@
1
1
  import {
2
+ defaultEmbedBackground,
2
3
  normalizeSvgForEmbed,
3
4
  renderErrorCard
4
- } from "./chunk-YIA4LEX4.js";
5
+ } from "./chunk-DN66GPY5.js";
5
6
  import {
6
7
  encodeDiagramUrl,
7
8
  render
8
- } from "./chunk-ZAD4HV2G.js";
9
+ } from "./chunk-SVTI362O.js";
9
10
  import "./chunk-66RUL3XF.js";
10
11
  import "./chunk-YRYKTYMQ.js";
11
12
  import "./chunk-YYVTBZZC.js";
12
13
  import "./chunk-HEVYAHLW.js";
13
- import "./chunk-VVZRV54S.js";
14
+ import "./chunk-KQ57MHRO.js";
14
15
  import "./chunk-Q4V4XQWV.js";
15
16
  import "./chunk-BTUTZMPT.js";
16
17
  import {
@@ -22,7 +23,7 @@ import "./chunk-QXKWYZNR.js";
22
23
  import "./chunk-PGEGPSCZ.js";
23
24
  import "./chunk-3UIKSPFB.js";
24
25
  import "./chunk-BDXC7MDK.js";
25
- import "./chunk-4S52SK6G.js";
26
+ import "./chunk-QJJZSROI.js";
26
27
  import "./chunk-HGN652MU.js";
27
28
  import "./chunk-U6EQI3U6.js";
28
29
  import "./chunk-7UEMZREK.js";
@@ -30,7 +31,7 @@ import "./chunk-A4GOY3PE.js";
30
31
  import "./chunk-6KFWC4CO.js";
31
32
  import "./chunk-HQCHYB5F.js";
32
33
  import "./chunk-5LWQH6QV.js";
33
- import "./chunk-XDXNDSKO.js";
34
+ import "./chunk-XEGTMVYY.js";
34
35
  import "./chunk-I2WKW7C7.js";
35
36
  import "./chunk-TSA237IM.js";
36
37
  import "./chunk-6IAA2QQ2.js";
@@ -952,6 +953,7 @@ function resolveBlockOptions(opts) {
952
953
  mode,
953
954
  palette: opts.palette ?? "slate",
954
955
  colorMode: opts.colorMode ?? "auto",
956
+ background: opts.background ?? "auto",
955
957
  showSource: opts.showSource ?? showcase,
956
958
  showCopy: opts.showCopy ?? showcase,
957
959
  showExpand: opts.showExpand ?? showcase,
@@ -969,8 +971,10 @@ async function renderDgmoBlock(source, options = {}) {
969
971
  const trimmed = source.trim();
970
972
  const palette = resolvePaletteOrFallback(opts.palette, opts.onWarn);
971
973
  const diagnostics = [];
974
+ let chartType;
972
975
  const renderTheme = async (theme) => {
973
976
  const r = await render(trimmed, { palette: palette.id, theme });
977
+ chartType = r.chartType;
974
978
  diagnostics.push(...r.diagnostics);
975
979
  const errors = r.diagnostics.filter((d) => d.severity === "error");
976
980
  return errors.length ? renderErrorCard(errors, trimmed, palette, theme) : r.svg;
@@ -981,10 +985,12 @@ async function renderDgmoBlock(source, options = {}) {
981
985
  renderTheme("light"),
982
986
  renderTheme("dark")
983
987
  ]);
984
- svgsHtml = `<div class="${escapeAttr(innerClasses(opts, "dgmo-light"))}">${normalizeSvgForEmbed(light)}</div><div class="${escapeAttr(innerClasses(opts, "dgmo-dark"))}">${normalizeSvgForEmbed(dark)}</div>`;
988
+ const background = opts.background === "auto" ? defaultEmbedBackground(chartType) : opts.background;
989
+ svgsHtml = `<div class="${escapeAttr(innerClasses(opts, "dgmo-light"))}">${normalizeSvgForEmbed(light, { background })}</div><div class="${escapeAttr(innerClasses(opts, "dgmo-dark"))}">${normalizeSvgForEmbed(dark, { background })}</div>`;
985
990
  } else {
986
991
  const svg = await renderTheme(opts.colorMode);
987
- svgsHtml = `<div class="${escapeAttr(innerClasses(opts, "dgmo-svg"))}">${normalizeSvgForEmbed(svg)}</div>`;
992
+ const background = opts.background === "auto" ? defaultEmbedBackground(chartType) : opts.background;
993
+ svgsHtml = `<div class="${escapeAttr(innerClasses(opts, "dgmo-svg"))}">${normalizeSvgForEmbed(svg, { background })}</div>`;
988
994
  }
989
995
  return { html: assembleBlock(trimmed, svgsHtml, opts), diagnostics };
990
996
  }
@@ -2,7 +2,7 @@ import {
2
2
  D3_DATA_CHART_TYPES,
3
3
  renderDataChartD3,
4
4
  supportsD3DataChart
5
- } from "./chunk-4S52SK6G.js";
5
+ } from "./chunk-QJJZSROI.js";
6
6
  import "./chunk-HGN652MU.js";
7
7
  import "./chunk-U6EQI3U6.js";
8
8
  import "./chunk-7UEMZREK.js";
@@ -10,7 +10,7 @@ import "./chunk-A4GOY3PE.js";
10
10
  import "./chunk-6KFWC4CO.js";
11
11
  import "./chunk-HQCHYB5F.js";
12
12
  import "./chunk-5LWQH6QV.js";
13
- import "./chunk-XDXNDSKO.js";
13
+ import "./chunk-XEGTMVYY.js";
14
14
  import "./chunk-R3XI2VC7.js";
15
15
  import "./chunk-P6T66CCZ.js";
16
16
  import "./chunk-FJUNPCYI.js";
@@ -23,4 +23,4 @@ export {
23
23
  renderDataChartD3,
24
24
  supportsD3DataChart
25
25
  };
26
- //# sourceMappingURL=charts-d3-LR6D3D7A.js.map
26
+ //# sourceMappingURL=charts-d3-MUW3LTML.js.map
@@ -457,13 +457,13 @@ function drawRow(svg, entry, index, parsed, now, rowTop, rowH, geom, col) {
457
457
  const mainFont = 48;
458
458
  const baseY = center + 16;
459
459
  const capTop = baseY - mainFont * 0.7;
460
- g.append("text").attr("data-dgmo-clock-digital", "").attr("data-dgmo-clock-digital-part", "main").attr("x", contentLeft).attr("y", baseY).attr("fill", timeColor).attr("font-family", FONT_FAMILY).attr("font-size", mainFont).attr("font-weight", 600).style("font-variant-numeric", "tabular-nums").text(ts.main);
461
460
  const sf = 20;
462
461
  const mainW = [...ts.main].reduce(
463
- (w, c) => w + mainFont * (c === ":" ? 0.28 : 0.6),
462
+ (w, c) => w + mainFont * (c === ":" ? 0.334 : 0.6),
464
463
  0
465
464
  );
466
465
  const stackX = contentLeft + mainW + 5;
466
+ g.append("text").attr("data-dgmo-clock-digital", "").attr("data-dgmo-clock-digital-part", "main").attr("x", contentLeft).attr("y", baseY).attr("fill", timeColor).attr("font-family", FONT_FAMILY).attr("font-size", mainFont).attr("font-weight", 600).attr("textLength", mainW).attr("lengthAdjust", "spacing").style("font-variant-numeric", "tabular-nums").text(ts.main);
467
467
  g.append("text").attr("data-dgmo-clock-digital-part", "sec").attr("x", stackX).attr("y", capTop + sf * 0.72).attr("fill", muted).attr("font-family", FONT_FAMILY).attr("font-size", sf).attr("font-weight", 600).style("font-variant-numeric", "tabular-nums").text(`:${ts.sec}`);
468
468
  if (ts.ap)
469
469
  g.append("text").attr("data-dgmo-clock-digital-part", "ap").attr("x", stackX).attr("y", baseY).attr("fill", muted).attr("font-family", FONT_FAMILY).attr("font-size", sf).attr("font-weight", 600).text(ts.ap);
@@ -602,13 +602,13 @@ function drawColumns(body, parsed, now, top, geom, col) {
602
602
  const sf = 13;
603
603
  const tf = fitFont(ts.main, 44, innerW - 30, 20);
604
604
  const mainW = [...ts.main].reduce(
605
- (w, c) => w + tf * (c === ":" ? 0.28 : 0.6),
605
+ (w, c) => w + tf * (c === ":" ? 0.334 : 0.6),
606
606
  0
607
607
  );
608
608
  const stackW = Math.max(estWidth(`:${ts.sec}`, sf), estWidth(ts.ap, sf));
609
609
  const gLeft = cx - (mainW + 7 + stackW) / 2;
610
610
  const baseY = cy + tf * 0.34;
611
- g.append("text").attr("data-dgmo-clock-digital", "").attr("data-dgmo-clock-digital-part", "main").attr("x", gLeft).attr("y", baseY).attr("fill", timeColor).attr("font-family", FONT_FAMILY).attr("font-size", tf).attr("font-weight", 600).style("font-variant-numeric", "tabular-nums").text(ts.main);
611
+ g.append("text").attr("data-dgmo-clock-digital", "").attr("data-dgmo-clock-digital-part", "main").attr("x", gLeft).attr("y", baseY).attr("fill", timeColor).attr("font-family", FONT_FAMILY).attr("font-size", tf).attr("font-weight", 600).attr("textLength", mainW).attr("lengthAdjust", "spacing").style("font-variant-numeric", "tabular-nums").text(ts.main);
612
612
  const stackX = gLeft + mainW + 7;
613
613
  g.append("text").attr("data-dgmo-clock-digital-part", "sec").attr("x", stackX).attr("y", baseY - tf * 0.32).attr("fill", muted).attr("font-family", FONT_FAMILY).attr("font-size", sf).attr("font-weight", 500).text(`:${ts.sec}`);
614
614
  if (ts.ap)
@@ -678,4 +678,4 @@ export {
678
678
  renderClock,
679
679
  renderClockForExport
680
680
  };
681
- //# sourceMappingURL=chunk-7PQYTZMA.js.map
681
+ //# sourceMappingURL=chunk-5WFIYXQ6.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  encodeDiagramUrl
3
- } from "./chunk-ZAD4HV2G.js";
3
+ } from "./chunk-SVTI362O.js";
4
4
  import {
5
5
  FONT_FAMILY
6
6
  } from "./chunk-6KFWC4CO.js";
@@ -176,8 +176,11 @@ function escapeXml(s) {
176
176
  }
177
177
 
178
178
  // src/utils/svg-embed.ts
179
- function normalizeSvgForEmbed(input) {
179
+ function normalizeSvgForEmbed(input, opts = {}) {
180
180
  let svg = input;
181
+ if ((opts.background ?? "transparent") === "transparent") {
182
+ svg = stripRootBackground(svg);
183
+ }
181
184
  const rootMatch = svg.match(/<svg[^>]*>/);
182
185
  const rootTag = rootMatch?.[0] ?? "";
183
186
  if (rootTag && !rootTag.includes("viewBox")) {
@@ -207,6 +210,73 @@ function normalizeSvgForEmbed(input) {
207
210
  svg = svg.replace(/<svg\s{2,}/g, "<svg ");
208
211
  return svg;
209
212
  }
213
+ var BG_MEANINGFUL_TYPES = /* @__PURE__ */ new Set(["map"]);
214
+ function defaultEmbedBackground(chartType) {
215
+ return chartType && BG_MEANINGFUL_TYPES.has(chartType) ? "opaque" : "transparent";
216
+ }
217
+ function stripRootBackground(svg) {
218
+ const rootMatch = svg.match(/<svg\b[^>]*>/);
219
+ if (!rootMatch) return svg;
220
+ const rootTag = rootMatch[0];
221
+ const styleMatch = rootTag.match(/style="([^"]*)"/);
222
+ const style = styleMatch?.[1] ?? "";
223
+ const bgMatch = style.match(/background:\s*([^;]+)/);
224
+ const bgColor = bgMatch ? normalizeColor(bgMatch[1]) : null;
225
+ const canvas = rootCanvas(rootTag, svg);
226
+ let out = svg;
227
+ if (bgMatch) {
228
+ const cleaned = style.replace(/background:\s*[^;]+;?/i, "").replace(/\s{2,}/g, " ").replace(/;\s*$/, "").trim();
229
+ const newRoot = (cleaned ? rootTag.replace(/style="[^"]*"/, `style="${cleaned}"`) : rootTag.replace(/\s*style="[^"]*"/, "")).replace(/<svg\s{2,}/, "<svg ");
230
+ out = out.replace(rootTag, newRoot);
231
+ }
232
+ if (bgColor && canvas) {
233
+ out = out.replace(
234
+ /<rect\b[^>]*?\/?>(?:\s*<\/rect>)?/g,
235
+ (m) => isFullCanvasFill(m, bgColor, canvas) ? "" : m
236
+ );
237
+ }
238
+ return out;
239
+ }
240
+ function isFullCanvasFill(tag, bgColor, canvas) {
241
+ const fm = tag.match(/\bfill="([^"]*)"/);
242
+ if (!fm || normalizeColor(fm[1]) !== bgColor) return false;
243
+ const w = numAttr(tag, "width");
244
+ const h = numAttr(tag, "height");
245
+ if (w === null || h === null) return false;
246
+ const x = numAttr(tag, "x") ?? 0;
247
+ const y = numAttr(tag, "y") ?? 0;
248
+ const T = 1.5;
249
+ return Math.abs(x) <= T && Math.abs(y) <= T && Math.abs(w - canvas.w) <= T && Math.abs(h - canvas.h) <= T;
250
+ }
251
+ function rootCanvas(rootTag, svg) {
252
+ const wm = rootTag.match(/\bwidth="([\d.]+)"/);
253
+ const hm = rootTag.match(/\bheight="([\d.]+)"/);
254
+ if (wm && hm) return { w: parseFloat(wm[1]), h: parseFloat(hm[1]) };
255
+ const vb = readViewBox(svg);
256
+ return vb ? { w: vb.width, h: vb.height } : null;
257
+ }
258
+ function numAttr(tag, name) {
259
+ const m = tag.match(new RegExp(`\\b${name}="([^"]*)"`));
260
+ if (!m) return null;
261
+ const n = parseFloat(m[1]);
262
+ return Number.isFinite(n) ? n : null;
263
+ }
264
+ function normalizeColor(c) {
265
+ const s = c.trim().toLowerCase();
266
+ const hex6 = s.match(/^#([0-9a-f]{6})$/);
267
+ if (hex6) {
268
+ const n = parseInt(hex6[1], 16);
269
+ return `${n >> 16 & 255},${n >> 8 & 255},${n & 255}`;
270
+ }
271
+ const hex3 = s.match(/^#([0-9a-f]{3})$/);
272
+ if (hex3) {
273
+ const [r, g, b] = hex3[1].split("").map((ch) => parseInt(ch + ch, 16));
274
+ return `${r},${g},${b}`;
275
+ }
276
+ const rgb = s.match(/^rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/);
277
+ if (rgb) return `${+rgb[1]},${+rgb[2]},${+rgb[3]}`;
278
+ return null;
279
+ }
210
280
  function getEmbedSvgViewBox(svg) {
211
281
  const tight = computeBBox(svg);
212
282
  if (!tight || tight.width <= 0 || tight.height <= 0) return null;
@@ -334,6 +404,7 @@ function computeBBox(svg) {
334
404
  export {
335
405
  renderErrorCard,
336
406
  normalizeSvgForEmbed,
407
+ defaultEmbedBackground,
337
408
  getEmbedSvgViewBox
338
409
  };
339
- //# sourceMappingURL=chunk-YIA4LEX4.js.map
410
+ //# sourceMappingURL=chunk-DN66GPY5.js.map
@@ -25,7 +25,7 @@ import {
25
25
  parseHeatmap,
26
26
  parseSankey,
27
27
  parseScatter
28
- } from "./chunk-XDXNDSKO.js";
28
+ } from "./chunk-XEGTMVYY.js";
29
29
  import {
30
30
  parseWireframe
31
31
  } from "./chunk-I2WKW7C7.js";
@@ -2162,4 +2162,4 @@ export {
2162
2162
  knownChartTypeIds,
2163
2163
  parseDgmo
2164
2164
  };
2165
- //# sourceMappingURL=chunk-VVZRV54S.js.map
2165
+ //# sourceMappingURL=chunk-KQ57MHRO.js.map
@@ -32,7 +32,7 @@ import {
32
32
  getSimpleChartLegendGroups,
33
33
  parseChart,
34
34
  parseExtendedChart
35
- } from "./chunk-XDXNDSKO.js";
35
+ } from "./chunk-XEGTMVYY.js";
36
36
  import {
37
37
  contrastText,
38
38
  getSegmentColors,
@@ -438,7 +438,14 @@ function renderLine(svg, chart, width, height, colors, palette, isDark, textColo
438
438
  hi = Math.max(hi, v);
439
439
  }
440
440
  if (!isFinite(lo)) return [0, 1];
441
- if (lo > 0) lo = 0;
441
+ if (chart.noAutoY) {
442
+ if (lo > 0) lo = 0;
443
+ } else {
444
+ const pad = (hi - lo) * 0.05 || Math.abs(hi) * 0.05 || 1;
445
+ const nlo = lo - pad;
446
+ lo = lo >= 0 && nlo < 0 ? 0 : nlo;
447
+ hi = hi + pad;
448
+ }
442
449
  if (lo === hi) hi = lo + 1;
443
450
  return [lo, hi];
444
451
  };
@@ -1694,4 +1701,4 @@ export {
1694
1701
  supportsD3DataChart,
1695
1702
  renderDataChartD3
1696
1703
  };
1697
- //# sourceMappingURL=chunk-4S52SK6G.js.map
1704
+ //# sourceMappingURL=chunk-QJJZSROI.js.map