@diagrammo/dgmo 0.44.1 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/element.mjs CHANGED
@@ -28035,7 +28035,7 @@ var init_renderer2 = __esm({
28035
28035
  COLLAPSED = "dgmo-evt-collapsed";
28036
28036
  OFF = "dgmo-evt-off";
28037
28037
  HIDDEN_ATTR = "data-evt-hidden";
28038
- HOVER_CSS = `.dgmo-event-dot{transition:transform .12s ease;transform-box:fill-box;transform-origin:center}.dgmo-event-leader,.dgmo-event-card,.dgmo-event-era{transition:opacity .12s ease,filter .12s ease}.dgmo-event-dot,.dgmo-event-card,.dgmo-event-era{cursor:default}[data-legend-entry]{cursor:pointer}.${DIM}{opacity:.2}.dgmo-event-dot.${HL}{transform:scale(1.55)}.dgmo-event-leader.${HL}{stroke-opacity:1;stroke-width:2.5}.dgmo-event-card.${HL}{filter:drop-shadow(0 2px 5px rgba(0,0,0,.22))}.dgmo-event-era.${ERA_HL}{filter:drop-shadow(0 1px 2px rgba(0,0,0,.28))}.dgmo-event-card.${COLLAPSED},.dgmo-event-leader.${COLLAPSED}{opacity:0;pointer-events:none}.dgmo-event-card.${COLLAPSED}.${HL},.dgmo-event-leader.${COLLAPSED}.${HL}{opacity:1;pointer-events:auto}[data-legend-entry].${OFF} text{text-decoration:line-through;opacity:.5}`;
28038
+ HOVER_CSS = `.dgmo-event-dot{transition:transform .12s ease;transform-box:fill-box;transform-origin:center}.dgmo-event-leader,.dgmo-event-card,.dgmo-event-era{transition:opacity .12s ease,filter .12s ease}.dgmo-event-dot,.dgmo-event-card,.dgmo-event-era{cursor:default}[data-legend-entry]{cursor:pointer}.${DIM}{opacity:.2}.dgmo-event-dot.${HL}{transform:scale(1.55)}.dgmo-event-leader.${HL}{stroke-opacity:1;stroke-width:2.5}.dgmo-event-card.${HL}{filter:drop-shadow(0 2px 5px rgba(0,0,0,.22))}.dgmo-event-era.${ERA_HL}{filter:drop-shadow(0 1px 2px rgba(0,0,0,.28))}.dgmo-event-card.${COLLAPSED},.dgmo-event-leader.${COLLAPSED}{opacity:0;pointer-events:none}.dgmo-event-card.${COLLAPSED}.${HL},.dgmo-event-leader.${COLLAPSED}.${HL}{opacity:1;pointer-events:auto}[data-legend-entry].${OFF} text{opacity:.5}`;
28039
28039
  DIMMABLE_SEL = ".dgmo-event-dot,.dgmo-event-leader,.dgmo-event-card,.dgmo-event-era";
28040
28040
  PIN_ATTR = "data-evt-pin";
28041
28041
  }
@@ -37264,7 +37264,7 @@ function renderSwimlaneForExport(container, parsed, layout, palette, isDark, opt
37264
37264
  const titleOffset = parsed.title ? 40 : 0;
37265
37265
  const width = opts.exportDims?.width ?? layout.width;
37266
37266
  const height = (opts.exportDims?.height ?? layout.height) + 0;
37267
- const svg = d3Selection14.select(container).append("svg").attr("xmlns", "http://www.w3.org/2000/svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).style("font-family", FONT_FAMILY);
37267
+ const svg = d3Selection14.select(container).append("svg").attr("xmlns", "http://www.w3.org/2000/svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("preserveAspectRatio", "xMidYMin meet").style("font-family", FONT_FAMILY);
37268
37268
  const defs = svg.append("defs");
37269
37269
  const baseBg = themeBaseBg(palette, isDark);
37270
37270
  const ev = {
@@ -69866,7 +69866,7 @@ pre.dgmo, code.language-dgmo, pre > code.language-dgmo,
69866
69866
 
69867
69867
  // src/auto/shared.ts
69868
69868
  init_safe_href();
69869
- var VERSION = "0.44.1";
69869
+ var VERSION = "0.45.0";
69870
69870
  var EDITOR_BASE_URL = "https://online.diagrammo.app";
69871
69871
  var ARIA_LABEL_MAX = 200;
69872
69872
  var COPIED_INTERACTION_MS = 1200;
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var highlight_api_exports = {};
22
22
  __export(highlight_api_exports, {
23
23
  ATTRIBUTE_KEYS: () => ATTRIBUTE_KEYS,
24
+ LIGHT_ROLE_STYLES: () => LIGHT_ROLE_STYLES,
24
25
  NODE_TO_ROLE: () => NODE_TO_ROLE,
25
26
  NORD_ROLE_STYLES: () => NORD_ROLE_STYLES,
26
27
  ROLE_TO_ANSI: () => ROLE_TO_ANSI,
@@ -747,6 +748,35 @@ var NORD_ROLE_STYLES = {
747
748
  noteContent: { color: "#616E88", fontStyle: "italic" },
748
749
  default: {}
749
750
  };
751
+ var LIGHT_ROLE_STYLES = {
752
+ keyword: { color: "#3b6ea5", fontWeight: "bold" },
753
+ // slate blue
754
+ controlKeyword: { color: "#7d5ba6", fontWeight: "bold" },
755
+ // purple
756
+ definitionKeyword: { color: "#2f5a86", fontWeight: "bold" },
757
+ // deep blue
758
+ modifier: { color: "#7d5ba6" },
759
+ chartType: { color: "#b8691f", fontWeight: "bold" },
760
+ // amber
761
+ operator: { color: "#c0504d", fontWeight: "bold" },
762
+ // red
763
+ number: { color: "#7d5ba6" },
764
+ comment: { color: "#677483", fontStyle: "italic" },
765
+ // muted gray
766
+ heading: { color: "#b8691f", fontWeight: "bold" },
767
+ bracket: { color: "#5b6672" },
768
+ separator: { color: "#2d7268" },
769
+ // deep teal
770
+ deprecatedSyntax: { color: "#c0504d", textDecoration: "line-through" },
771
+ url: { color: "#3b6ea5", textDecoration: "underline" },
772
+ colorAnnotation: { color: "#b8691f", fontStyle: "italic" },
773
+ punctuation: { color: "#677483" },
774
+ propertyName: { color: "#2d7268" },
775
+ string: { color: "#3f7a3b" },
776
+ // forest green
777
+ noteContent: { color: "#677483", fontStyle: "italic" },
778
+ default: {}
779
+ };
750
780
  var ROLE_TO_ANSI = {
751
781
  comment: "\x1B[3;90m",
752
782
  // italic dim
@@ -812,6 +842,7 @@ function renderAnsi(tokens, useColor) {
812
842
  // Annotate the CommonJS export names for ESM import in node:
813
843
  0 && (module.exports = {
814
844
  ATTRIBUTE_KEYS,
845
+ LIGHT_ROLE_STYLES,
815
846
  NODE_TO_ROLE,
816
847
  NORD_ROLE_STYLES,
817
848
  ROLE_TO_ANSI,
@@ -31,10 +31,19 @@ declare function highlightDgmo(source: string): HighlightToken[];
31
31
  */
32
32
  declare const ATTRIBUTE_KEYS: Set<string>;
33
33
  declare const NORD_ROLE_STYLES: Record<string, Record<string, string>>;
34
+ /**
35
+ * Light-background counterpart of NORD_ROLE_STYLES for static contexts
36
+ * (marketing site, light-mode source panels). Same role keys — a parity test
37
+ * (tests/block.test.ts) guards the two maps and the `.dgmo-tok-*` rules in
38
+ * block/css.ts against drift. Colors are darker AA-targeting tones tuned for
39
+ * a light code panel (bg ~#f3f5f8). Moved here from the site repo's
40
+ * hand-maintained mirror (BL-114).
41
+ */
42
+ declare const LIGHT_ROLE_STYLES: Record<string, Record<string, string>>;
34
43
  declare const ROLE_TO_ANSI: Record<string, string>;
35
44
  /**
36
45
  * Render highlighted tokens to an ANSI string for terminal display.
37
46
  */
38
47
  declare function renderAnsi(tokens: HighlightToken[], useColor: boolean): string;
39
48
 
40
- export { ATTRIBUTE_KEYS, type HighlightToken, NODE_TO_ROLE, NORD_ROLE_STYLES, ROLE_TO_ANSI, highlightDgmo, renderAnsi };
49
+ export { ATTRIBUTE_KEYS, type HighlightToken, LIGHT_ROLE_STYLES, NODE_TO_ROLE, NORD_ROLE_STYLES, ROLE_TO_ANSI, highlightDgmo, renderAnsi };
@@ -31,10 +31,19 @@ declare function highlightDgmo(source: string): HighlightToken[];
31
31
  */
32
32
  declare const ATTRIBUTE_KEYS: Set<string>;
33
33
  declare const NORD_ROLE_STYLES: Record<string, Record<string, string>>;
34
+ /**
35
+ * Light-background counterpart of NORD_ROLE_STYLES for static contexts
36
+ * (marketing site, light-mode source panels). Same role keys — a parity test
37
+ * (tests/block.test.ts) guards the two maps and the `.dgmo-tok-*` rules in
38
+ * block/css.ts against drift. Colors are darker AA-targeting tones tuned for
39
+ * a light code panel (bg ~#f3f5f8). Moved here from the site repo's
40
+ * hand-maintained mirror (BL-114).
41
+ */
42
+ declare const LIGHT_ROLE_STYLES: Record<string, Record<string, string>>;
34
43
  declare const ROLE_TO_ANSI: Record<string, string>;
35
44
  /**
36
45
  * Render highlighted tokens to an ANSI string for terminal display.
37
46
  */
38
47
  declare function renderAnsi(tokens: HighlightToken[], useColor: boolean): string;
39
48
 
40
- export { ATTRIBUTE_KEYS, type HighlightToken, NODE_TO_ROLE, NORD_ROLE_STYLES, ROLE_TO_ANSI, highlightDgmo, renderAnsi };
49
+ export { ATTRIBUTE_KEYS, type HighlightToken, LIGHT_ROLE_STYLES, NODE_TO_ROLE, NORD_ROLE_STYLES, ROLE_TO_ANSI, highlightDgmo, renderAnsi };
package/dist/highlight.js CHANGED
@@ -716,6 +716,35 @@ var NORD_ROLE_STYLES = {
716
716
  noteContent: { color: "#616E88", fontStyle: "italic" },
717
717
  default: {}
718
718
  };
719
+ var LIGHT_ROLE_STYLES = {
720
+ keyword: { color: "#3b6ea5", fontWeight: "bold" },
721
+ // slate blue
722
+ controlKeyword: { color: "#7d5ba6", fontWeight: "bold" },
723
+ // purple
724
+ definitionKeyword: { color: "#2f5a86", fontWeight: "bold" },
725
+ // deep blue
726
+ modifier: { color: "#7d5ba6" },
727
+ chartType: { color: "#b8691f", fontWeight: "bold" },
728
+ // amber
729
+ operator: { color: "#c0504d", fontWeight: "bold" },
730
+ // red
731
+ number: { color: "#7d5ba6" },
732
+ comment: { color: "#677483", fontStyle: "italic" },
733
+ // muted gray
734
+ heading: { color: "#b8691f", fontWeight: "bold" },
735
+ bracket: { color: "#5b6672" },
736
+ separator: { color: "#2d7268" },
737
+ // deep teal
738
+ deprecatedSyntax: { color: "#c0504d", textDecoration: "line-through" },
739
+ url: { color: "#3b6ea5", textDecoration: "underline" },
740
+ colorAnnotation: { color: "#b8691f", fontStyle: "italic" },
741
+ punctuation: { color: "#677483" },
742
+ propertyName: { color: "#2d7268" },
743
+ string: { color: "#3f7a3b" },
744
+ // forest green
745
+ noteContent: { color: "#677483", fontStyle: "italic" },
746
+ default: {}
747
+ };
719
748
  var ROLE_TO_ANSI = {
720
749
  comment: "\x1B[3;90m",
721
750
  // italic dim
@@ -780,6 +809,7 @@ function renderAnsi(tokens, useColor) {
780
809
  }
781
810
  export {
782
811
  ATTRIBUTE_KEYS,
812
+ LIGHT_ROLE_STYLES,
783
813
  NODE_TO_ROLE,
784
814
  NORD_ROLE_STYLES,
785
815
  ROLE_TO_ANSI,
package/dist/index.cjs CHANGED
@@ -28040,7 +28040,7 @@ var init_renderer2 = __esm({
28040
28040
  COLLAPSED = "dgmo-evt-collapsed";
28041
28041
  OFF = "dgmo-evt-off";
28042
28042
  HIDDEN_ATTR = "data-evt-hidden";
28043
- HOVER_CSS = `.dgmo-event-dot{transition:transform .12s ease;transform-box:fill-box;transform-origin:center}.dgmo-event-leader,.dgmo-event-card,.dgmo-event-era{transition:opacity .12s ease,filter .12s ease}.dgmo-event-dot,.dgmo-event-card,.dgmo-event-era{cursor:default}[data-legend-entry]{cursor:pointer}.${DIM}{opacity:.2}.dgmo-event-dot.${HL}{transform:scale(1.55)}.dgmo-event-leader.${HL}{stroke-opacity:1;stroke-width:2.5}.dgmo-event-card.${HL}{filter:drop-shadow(0 2px 5px rgba(0,0,0,.22))}.dgmo-event-era.${ERA_HL}{filter:drop-shadow(0 1px 2px rgba(0,0,0,.28))}.dgmo-event-card.${COLLAPSED},.dgmo-event-leader.${COLLAPSED}{opacity:0;pointer-events:none}.dgmo-event-card.${COLLAPSED}.${HL},.dgmo-event-leader.${COLLAPSED}.${HL}{opacity:1;pointer-events:auto}[data-legend-entry].${OFF} text{text-decoration:line-through;opacity:.5}`;
28043
+ HOVER_CSS = `.dgmo-event-dot{transition:transform .12s ease;transform-box:fill-box;transform-origin:center}.dgmo-event-leader,.dgmo-event-card,.dgmo-event-era{transition:opacity .12s ease,filter .12s ease}.dgmo-event-dot,.dgmo-event-card,.dgmo-event-era{cursor:default}[data-legend-entry]{cursor:pointer}.${DIM}{opacity:.2}.dgmo-event-dot.${HL}{transform:scale(1.55)}.dgmo-event-leader.${HL}{stroke-opacity:1;stroke-width:2.5}.dgmo-event-card.${HL}{filter:drop-shadow(0 2px 5px rgba(0,0,0,.22))}.dgmo-event-era.${ERA_HL}{filter:drop-shadow(0 1px 2px rgba(0,0,0,.28))}.dgmo-event-card.${COLLAPSED},.dgmo-event-leader.${COLLAPSED}{opacity:0;pointer-events:none}.dgmo-event-card.${COLLAPSED}.${HL},.dgmo-event-leader.${COLLAPSED}.${HL}{opacity:1;pointer-events:auto}[data-legend-entry].${OFF} text{opacity:.5}`;
28044
28044
  DIMMABLE_SEL = ".dgmo-event-dot,.dgmo-event-leader,.dgmo-event-card,.dgmo-event-era";
28045
28045
  PIN_ATTR = "data-evt-pin";
28046
28046
  }
@@ -37268,7 +37268,7 @@ function renderSwimlaneForExport(container, parsed, layout, palette, isDark, opt
37268
37268
  const titleOffset = parsed.title ? 40 : 0;
37269
37269
  const width = opts.exportDims?.width ?? layout.width;
37270
37270
  const height = (opts.exportDims?.height ?? layout.height) + 0;
37271
- const svg = d3Selection14.select(container).append("svg").attr("xmlns", "http://www.w3.org/2000/svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).style("font-family", FONT_FAMILY);
37271
+ const svg = d3Selection14.select(container).append("svg").attr("xmlns", "http://www.w3.org/2000/svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("preserveAspectRatio", "xMidYMin meet").style("font-family", FONT_FAMILY);
37272
37272
  const defs = svg.append("defs");
37273
37273
  const baseBg = themeBaseBg(palette, isDark);
37274
37274
  const ev = {
package/dist/index.js CHANGED
@@ -28035,7 +28035,7 @@ var init_renderer2 = __esm({
28035
28035
  COLLAPSED = "dgmo-evt-collapsed";
28036
28036
  OFF = "dgmo-evt-off";
28037
28037
  HIDDEN_ATTR = "data-evt-hidden";
28038
- HOVER_CSS = `.dgmo-event-dot{transition:transform .12s ease;transform-box:fill-box;transform-origin:center}.dgmo-event-leader,.dgmo-event-card,.dgmo-event-era{transition:opacity .12s ease,filter .12s ease}.dgmo-event-dot,.dgmo-event-card,.dgmo-event-era{cursor:default}[data-legend-entry]{cursor:pointer}.${DIM}{opacity:.2}.dgmo-event-dot.${HL}{transform:scale(1.55)}.dgmo-event-leader.${HL}{stroke-opacity:1;stroke-width:2.5}.dgmo-event-card.${HL}{filter:drop-shadow(0 2px 5px rgba(0,0,0,.22))}.dgmo-event-era.${ERA_HL}{filter:drop-shadow(0 1px 2px rgba(0,0,0,.28))}.dgmo-event-card.${COLLAPSED},.dgmo-event-leader.${COLLAPSED}{opacity:0;pointer-events:none}.dgmo-event-card.${COLLAPSED}.${HL},.dgmo-event-leader.${COLLAPSED}.${HL}{opacity:1;pointer-events:auto}[data-legend-entry].${OFF} text{text-decoration:line-through;opacity:.5}`;
28038
+ HOVER_CSS = `.dgmo-event-dot{transition:transform .12s ease;transform-box:fill-box;transform-origin:center}.dgmo-event-leader,.dgmo-event-card,.dgmo-event-era{transition:opacity .12s ease,filter .12s ease}.dgmo-event-dot,.dgmo-event-card,.dgmo-event-era{cursor:default}[data-legend-entry]{cursor:pointer}.${DIM}{opacity:.2}.dgmo-event-dot.${HL}{transform:scale(1.55)}.dgmo-event-leader.${HL}{stroke-opacity:1;stroke-width:2.5}.dgmo-event-card.${HL}{filter:drop-shadow(0 2px 5px rgba(0,0,0,.22))}.dgmo-event-era.${ERA_HL}{filter:drop-shadow(0 1px 2px rgba(0,0,0,.28))}.dgmo-event-card.${COLLAPSED},.dgmo-event-leader.${COLLAPSED}{opacity:0;pointer-events:none}.dgmo-event-card.${COLLAPSED}.${HL},.dgmo-event-leader.${COLLAPSED}.${HL}{opacity:1;pointer-events:auto}[data-legend-entry].${OFF} text{opacity:.5}`;
28039
28039
  DIMMABLE_SEL = ".dgmo-event-dot,.dgmo-event-leader,.dgmo-event-card,.dgmo-event-era";
28040
28040
  PIN_ATTR = "data-evt-pin";
28041
28041
  }
@@ -37264,7 +37264,7 @@ function renderSwimlaneForExport(container, parsed, layout, palette, isDark, opt
37264
37264
  const titleOffset = parsed.title ? 40 : 0;
37265
37265
  const width = opts.exportDims?.width ?? layout.width;
37266
37266
  const height = (opts.exportDims?.height ?? layout.height) + 0;
37267
- const svg = d3Selection14.select(container).append("svg").attr("xmlns", "http://www.w3.org/2000/svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).style("font-family", FONT_FAMILY);
37267
+ const svg = d3Selection14.select(container).append("svg").attr("xmlns", "http://www.w3.org/2000/svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("preserveAspectRatio", "xMidYMin meet").style("font-family", FONT_FAMILY);
37268
37268
  const defs = svg.append("defs");
37269
37269
  const baseBg = themeBaseBg(palette, isDark);
37270
37270
  const ev = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diagrammo/dgmo",
3
- "version": "0.44.1",
3
+ "version": "0.45.0",
4
4
  "description": "DGMO diagram markup language — parser, renderer, and color system",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -89,7 +89,18 @@
89
89
  "default": "./dist/element.cjs"
90
90
  }
91
91
  },
92
- "./fonts/*": "./fonts/*"
92
+ "./fonts/*": "./fonts/*",
93
+ "./block": {
94
+ "import": {
95
+ "types": "./dist/block.d.ts",
96
+ "default": "./dist/block.js"
97
+ },
98
+ "require": {
99
+ "types": "./dist/block.d.cts",
100
+ "default": "./dist/block.cjs"
101
+ }
102
+ },
103
+ "./block.css": "./dist/block.css"
93
104
  },
94
105
  "files": [
95
106
  "dist/*.js",
@@ -500,6 +500,40 @@ export const NORD_ROLE_STYLES: Record<string, Record<string, string>> = {
500
500
  default: {},
501
501
  };
502
502
 
503
+ // ============================================================
504
+ // LIGHT_ROLE_STYLES — slate-light companion to NORD_ROLE_STYLES
505
+ // ============================================================
506
+
507
+ /**
508
+ * Light-background counterpart of NORD_ROLE_STYLES for static contexts
509
+ * (marketing site, light-mode source panels). Same role keys — a parity test
510
+ * (tests/block.test.ts) guards the two maps and the `.dgmo-tok-*` rules in
511
+ * block/css.ts against drift. Colors are darker AA-targeting tones tuned for
512
+ * a light code panel (bg ~#f3f5f8). Moved here from the site repo's
513
+ * hand-maintained mirror (BL-114).
514
+ */
515
+ export const LIGHT_ROLE_STYLES: Record<string, Record<string, string>> = {
516
+ keyword: { color: '#3b6ea5', fontWeight: 'bold' }, // slate blue
517
+ controlKeyword: { color: '#7d5ba6', fontWeight: 'bold' }, // purple
518
+ definitionKeyword: { color: '#2f5a86', fontWeight: 'bold' }, // deep blue
519
+ modifier: { color: '#7d5ba6' },
520
+ chartType: { color: '#b8691f', fontWeight: 'bold' }, // amber
521
+ operator: { color: '#c0504d', fontWeight: 'bold' }, // red
522
+ number: { color: '#7d5ba6' },
523
+ comment: { color: '#677483', fontStyle: 'italic' }, // muted gray
524
+ heading: { color: '#b8691f', fontWeight: 'bold' },
525
+ bracket: { color: '#5b6672' },
526
+ separator: { color: '#2d7268' }, // deep teal
527
+ deprecatedSyntax: { color: '#c0504d', textDecoration: 'line-through' },
528
+ url: { color: '#3b6ea5', textDecoration: 'underline' },
529
+ colorAnnotation: { color: '#b8691f', fontStyle: 'italic' },
530
+ punctuation: { color: '#677483' },
531
+ propertyName: { color: '#2d7268' },
532
+ string: { color: '#3f7a3b' }, // forest green
533
+ noteContent: { color: '#677483', fontStyle: 'italic' },
534
+ default: {},
535
+ };
536
+
503
537
  // ============================================================
504
538
  // ROLE_TO_ANSI — ANSI escape codes for CLI output
505
539
  // ============================================================
@@ -0,0 +1,312 @@
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
+ export const BLOCK_CSS: string = `
22
+ /* @diagrammo/dgmo block — standard embed chrome.
23
+ * Override the [data-theme="dark"] selectors if your site uses .dark or
24
+ * another color-mode convention. */
25
+
26
+ /* === Color-mode visibility (dual-render) === */
27
+ .dgmo-dark {
28
+ display: none;
29
+ }
30
+ [data-theme="dark"] .dgmo-light {
31
+ display: none;
32
+ }
33
+ [data-theme="dark"] .dgmo-dark {
34
+ display: block;
35
+ }
36
+
37
+ /* === Diagram sizing ===
38
+ * SVGs are emitted with viewBox only (no fixed width/height). Force them to
39
+ * fill their wrapper so light and dark variants render at identical sizes. */
40
+ .dgmo-light > svg,
41
+ .dgmo-dark > svg,
42
+ .dgmo-svg > svg {
43
+ display: block;
44
+ width: 100%;
45
+ height: auto;
46
+ max-width: 100%;
47
+ }
48
+
49
+ /* === Toolbar ===
50
+ * The diagram is the star: the toolbar is a slim reserved row below the SVG
51
+ * (height always in flow — no layout shift) that stays fully transparent
52
+ * until the block is hovered or focused, or the source panel is open. It is
53
+ * the <summary> of the source <details>, so toggling works without any JS.
54
+ * No text labels, no disclosure triangle — three wordless icon buttons. */
55
+ .dgmo-source-wrap {
56
+ margin: 0;
57
+ }
58
+ .dgmo-toolbar {
59
+ display: flex;
60
+ align-items: center;
61
+ justify-content: flex-end;
62
+ gap: 0.25em;
63
+ min-height: 1.9em;
64
+ padding: 0.15em 0;
65
+ opacity: 0;
66
+ transition: opacity 0.15s ease;
67
+ cursor: pointer;
68
+ list-style: none;
69
+ user-select: none;
70
+ color: rgba(127, 127, 127, 0.9);
71
+ }
72
+ .dgmo-toolbar::-webkit-details-marker {
73
+ display: none;
74
+ }
75
+ /* Reveal is keyed to the diagram IMAGE (the svg wrappers), not the whole
76
+ * figure — hovering the open code panel keeps the page quiet. The toolbar's
77
+ * own :hover keeps it alive while the pointer travels down from the image
78
+ * (they're adjacent, so there's no dead gap). focus-within covers keyboard
79
+ * and touch-tap. */
80
+ .dgmo-light:hover ~ .dgmo-source-wrap > .dgmo-toolbar,
81
+ .dgmo-dark:hover ~ .dgmo-source-wrap > .dgmo-toolbar,
82
+ .dgmo-svg:hover ~ .dgmo-source-wrap > .dgmo-toolbar,
83
+ .dgmo-toolbar:hover,
84
+ .dgmo:focus-within .dgmo-toolbar {
85
+ opacity: 1;
86
+ }
87
+ /* Touch devices have no hover: keep the icons faintly visible so the
88
+ * affordance is discoverable at all. */
89
+ @media (hover: none) {
90
+ .dgmo-toolbar {
91
+ opacity: 0.5;
92
+ }
93
+ }
94
+
95
+ .dgmo-toggle,
96
+ .dgmo-toolbar-btn {
97
+ display: inline-flex;
98
+ align-items: center;
99
+ justify-content: center;
100
+ width: 1.9em;
101
+ height: 1.9em;
102
+ border-radius: 0.35em;
103
+ background: none;
104
+ border: 0;
105
+ padding: 0;
106
+ color: inherit;
107
+ cursor: pointer;
108
+ opacity: 0.75;
109
+ transition:
110
+ opacity 0.15s ease,
111
+ background-color 0.15s ease;
112
+ }
113
+ .dgmo-toggle:hover,
114
+ .dgmo-toolbar-btn:hover {
115
+ opacity: 1;
116
+ background: rgba(127, 127, 127, 0.12);
117
+ }
118
+ .dgmo-toggle svg,
119
+ .dgmo-toolbar-btn svg {
120
+ width: 1em;
121
+ height: 1em;
122
+ }
123
+ /* Active state while the source panel is open. */
124
+ .dgmo-source-wrap[open] > .dgmo-toolbar .dgmo-toggle {
125
+ opacity: 1;
126
+ background: rgba(127, 127, 127, 0.15);
127
+ }
128
+ .dgmo-copy--success {
129
+ color: #5cba7a;
130
+ opacity: 1;
131
+ }
132
+
133
+ /* === Open state: frame the whole block ===
134
+ * When the source panel is open, diagram + toolbar + code get one shared
135
+ * border so the code visibly belongs to the chart above it, not to the
136
+ * surrounding prose. Closed blocks stay frameless. */
137
+ .dgmo:has(> .dgmo-source-wrap[open]) {
138
+ border: 1px solid rgba(127, 127, 127, 0.3);
139
+ border-radius: 0.6em;
140
+ padding: 0.75em 0.75em 0.5em;
141
+ }
142
+
143
+ /* === Source panel (hidden until toggled) === */
144
+ .dgmo-source-inner {
145
+ border-top: 1px solid rgba(127, 127, 127, 0.25);
146
+ background: rgba(127, 127, 127, 0.06);
147
+ overflow: hidden;
148
+ margin: 0 -0.75em -0.5em;
149
+ border-radius: 0 0 0.6em 0.6em;
150
+ }
151
+ .dgmo-pre {
152
+ white-space: pre;
153
+ overflow-x: auto;
154
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
155
+ font-size: 0.85em;
156
+ line-height: 1.5;
157
+ margin: 0;
158
+ padding: 1em;
159
+ }
160
+ .dgmo-code {
161
+ display: block;
162
+ }
163
+
164
+ /* === Error card === */
165
+ .dgmo--error {
166
+ border: 1px solid rgba(220, 80, 80, 0.5);
167
+ border-radius: 0.5em;
168
+ padding: 0.75em 1em;
169
+ }
170
+ .dgmo--error pre {
171
+ white-space: pre;
172
+ overflow-x: auto;
173
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
174
+ font-size: 0.85em;
175
+ margin: 0.5em 0 0;
176
+ }
177
+
178
+ /* === Source highlight roles ===
179
+ * Light values mirror LIGHT_ROLE_STYLES; dark overrides mirror
180
+ * NORD_ROLE_STYLES. Guarded by the parity test in tests/block.test.ts. */
181
+ .dgmo-tok-keyword {
182
+ color: #3b6ea5;
183
+ font-weight: bold;
184
+ }
185
+ .dgmo-tok-controlKeyword {
186
+ color: #7d5ba6;
187
+ font-weight: bold;
188
+ }
189
+ .dgmo-tok-definitionKeyword {
190
+ color: #2f5a86;
191
+ font-weight: bold;
192
+ }
193
+ .dgmo-tok-modifier {
194
+ color: #7d5ba6;
195
+ }
196
+ .dgmo-tok-chartType {
197
+ color: #b8691f;
198
+ font-weight: bold;
199
+ }
200
+ .dgmo-tok-operator {
201
+ color: #c0504d;
202
+ font-weight: bold;
203
+ }
204
+ .dgmo-tok-number {
205
+ color: #7d5ba6;
206
+ }
207
+ .dgmo-tok-comment {
208
+ color: #677483;
209
+ font-style: italic;
210
+ }
211
+ .dgmo-tok-heading {
212
+ color: #b8691f;
213
+ font-weight: bold;
214
+ }
215
+ .dgmo-tok-bracket {
216
+ color: #5b6672;
217
+ }
218
+ .dgmo-tok-separator {
219
+ color: #2d7268;
220
+ }
221
+ .dgmo-tok-deprecatedSyntax {
222
+ color: #c0504d;
223
+ text-decoration: line-through;
224
+ }
225
+ .dgmo-tok-url {
226
+ color: #3b6ea5;
227
+ text-decoration: underline;
228
+ }
229
+ .dgmo-tok-colorAnnotation {
230
+ color: #b8691f;
231
+ font-style: italic;
232
+ }
233
+ .dgmo-tok-punctuation {
234
+ color: #677483;
235
+ }
236
+ .dgmo-tok-propertyName {
237
+ color: #2d7268;
238
+ }
239
+ .dgmo-tok-string {
240
+ color: #3f7a3b;
241
+ }
242
+ .dgmo-tok-noteContent {
243
+ color: #677483;
244
+ font-style: italic;
245
+ }
246
+
247
+ [data-theme="dark"] .dgmo-tok-keyword {
248
+ color: #81a1c1;
249
+ font-weight: bold;
250
+ }
251
+ [data-theme="dark"] .dgmo-tok-controlKeyword {
252
+ color: #b48ead;
253
+ font-weight: bold;
254
+ }
255
+ [data-theme="dark"] .dgmo-tok-definitionKeyword {
256
+ color: #5e81ac;
257
+ font-weight: bold;
258
+ }
259
+ [data-theme="dark"] .dgmo-tok-modifier {
260
+ color: #b48ead;
261
+ }
262
+ [data-theme="dark"] .dgmo-tok-chartType {
263
+ color: #d08770;
264
+ font-weight: bold;
265
+ }
266
+ [data-theme="dark"] .dgmo-tok-operator {
267
+ color: #bf616a;
268
+ font-weight: bold;
269
+ }
270
+ [data-theme="dark"] .dgmo-tok-number {
271
+ color: #b48ead;
272
+ }
273
+ [data-theme="dark"] .dgmo-tok-comment {
274
+ color: #616e88;
275
+ font-style: italic;
276
+ }
277
+ [data-theme="dark"] .dgmo-tok-heading {
278
+ color: #d08770;
279
+ font-weight: bold;
280
+ }
281
+ [data-theme="dark"] .dgmo-tok-bracket {
282
+ color: #5e81ac;
283
+ }
284
+ [data-theme="dark"] .dgmo-tok-separator {
285
+ color: #88c0d0;
286
+ }
287
+ [data-theme="dark"] .dgmo-tok-deprecatedSyntax {
288
+ color: #bf616a;
289
+ text-decoration: line-through;
290
+ }
291
+ [data-theme="dark"] .dgmo-tok-url {
292
+ color: #88c0d0;
293
+ text-decoration: underline;
294
+ }
295
+ [data-theme="dark"] .dgmo-tok-colorAnnotation {
296
+ color: #d08770;
297
+ font-style: italic;
298
+ }
299
+ [data-theme="dark"] .dgmo-tok-punctuation {
300
+ color: #616e88;
301
+ }
302
+ [data-theme="dark"] .dgmo-tok-propertyName {
303
+ color: #88c0d0;
304
+ }
305
+ [data-theme="dark"] .dgmo-tok-string {
306
+ color: #a3be8c;
307
+ }
308
+ [data-theme="dark"] .dgmo-tok-noteContent {
309
+ color: #616e88;
310
+ font-style: italic;
311
+ }
312
+ `;
@@ -0,0 +1,15 @@
1
+ const HTML_ENTITIES: Record<string, string> = {
2
+ '&': '&amp;',
3
+ '<': '&lt;',
4
+ '>': '&gt;',
5
+ '"': '&quot;',
6
+ "'": '&#39;',
7
+ };
8
+
9
+ export function escapeHtml(s: string): string {
10
+ return s.replace(/[&<>"']/g, (ch) => HTML_ENTITIES[ch] ?? ch);
11
+ }
12
+
13
+ export function escapeAttr(s: string): string {
14
+ return s.replace(/[&<>"']/g, (ch) => HTML_ENTITIES[ch] ?? ch);
15
+ }