@diagrammo/dgmo 0.25.3 → 0.25.5

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/index.cjs CHANGED
@@ -55801,6 +55801,59 @@ function getRotateFn(mode) {
55801
55801
  if (mode === "angled") return () => Math.round(Math.random() * 30 - 15);
55802
55802
  return () => 0;
55803
55803
  }
55804
+ function hasCanvas2d() {
55805
+ try {
55806
+ if (typeof document === "undefined") return false;
55807
+ const canvas = document.createElement("canvas");
55808
+ return typeof canvas.getContext === "function" && !!canvas.getContext("2d");
55809
+ } catch {
55810
+ return false;
55811
+ }
55812
+ }
55813
+ function estimateWordWidth(text, size) {
55814
+ return text.length * size * WORDCLOUD_GLYPH_ADVANCE;
55815
+ }
55816
+ function layoutWordsNoCanvas(words, width, height, padding, rotateFn) {
55817
+ const sorted = [...words].sort((a, b) => b.size - a.size);
55818
+ const placed = [];
55819
+ const maxR = Math.sqrt(width * width + height * height) / 2;
55820
+ const aspect = width > 0 ? height / width : 1;
55821
+ for (const w of sorted) {
55822
+ const rotate = rotateFn();
55823
+ const rawW = estimateWordWidth(w.text, w.size) + padding * 2;
55824
+ const rawH = w.size + padding * 2;
55825
+ const rad = rotate * Math.PI / 180;
55826
+ const cos = Math.abs(Math.cos(rad));
55827
+ const sin = Math.abs(Math.sin(rad));
55828
+ const halfW = (rawW * cos + rawH * sin) / 2;
55829
+ const halfH = (rawW * sin + rawH * cos) / 2;
55830
+ let spot = null;
55831
+ for (let t = 0; t < 4e3; t++) {
55832
+ const a = t * 0.25;
55833
+ const r = a * 1.4;
55834
+ if (r > maxR) break;
55835
+ const x = Math.cos(a) * r;
55836
+ const y = Math.sin(a) * r * aspect;
55837
+ if (x - halfW < -width / 2 || x + halfW > width / 2 || y - halfH < -height / 2 || y + halfH > height / 2) {
55838
+ continue;
55839
+ }
55840
+ let collides = false;
55841
+ for (const p of placed) {
55842
+ if (Math.abs(x - p.x) < halfW + p.halfW && Math.abs(y - p.y) < halfH + p.halfH) {
55843
+ collides = true;
55844
+ break;
55845
+ }
55846
+ }
55847
+ if (!collides) {
55848
+ spot = { x, y };
55849
+ break;
55850
+ }
55851
+ }
55852
+ if (!spot) continue;
55853
+ placed.push({ ...w, rotate, x: spot.x, y: spot.y, halfW, halfH });
55854
+ }
55855
+ return placed;
55856
+ }
55804
55857
  function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
55805
55858
  return new Promise((resolve) => {
55806
55859
  d3Selection23.select(container).selectAll(":not([data-d3-tooltip])").remove();
@@ -55837,13 +55890,19 @@ function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
55837
55890
  "transform",
55838
55891
  `translate(${width / 2},${titleHeight + cloudHeight / 2})`
55839
55892
  );
55840
- (0, import_d3_cloud.default)().size([width, cloudHeight]).words(words.map((w) => ({ ...w, size: fontSize(w.weight) }))).padding(2).rotate(rotateFn).fontSize((d) => d.size).font(FONT_FAMILY).on("end", (layoutWords) => {
55893
+ const sized = words.map((w) => ({ ...w, size: fontSize(w.weight) }));
55894
+ const draw = (layoutWords) => {
55841
55895
  g.selectAll("text").data(layoutWords).join("text").style("font-size", (d) => `${d.size}px`).style("font-family", FONT_FAMILY).style("font-weight", "600").style("fill", (_d, i) => colors[i % colors.length]).attr("text-anchor", "middle").attr(
55842
55896
  "transform",
55843
55897
  (d) => `translate(${d.x},${d.y}) rotate(${d.rotate})`
55844
55898
  ).text((d) => d.text);
55845
55899
  resolve();
55846
- }).start();
55900
+ };
55901
+ if (!hasCanvas2d()) {
55902
+ draw(layoutWordsNoCanvas(sized, width, cloudHeight, 2, rotateFn));
55903
+ return;
55904
+ }
55905
+ (0, import_d3_cloud.default)().size([width, cloudHeight]).words(sized).padding(2).rotate(rotateFn).fontSize((d) => d.size).font(FONT_FAMILY).on("end", draw).start();
55847
55906
  });
55848
55907
  }
55849
55908
  function fitCirclesToContainerAsymmetric(circles, w, h, mLeft, mRight, mTop, mBottom) {
@@ -57654,7 +57713,7 @@ async function renderForExport(content, theme, palette, viewState, options) {
57654
57713
  }
57655
57714
  return finalizeSvgExport(container, theme, effectivePalette);
57656
57715
  }
57657
- var d3Scale2, d3Selection23, d3Shape11, d3Array, import_d3_cloud, DEFAULT_CLOUD_OPTIONS, STOP_WORDS, SLOPE_MARGIN, SLOPE_LABEL_FONT_SIZE, SLOPE_CHAR_WIDTH, ARC_MARGIN_TOP, ARC_MARGIN_RIGHT, ARC_MARGIN_BOTTOM, ARC_MARGIN_LEFT, ARC_MARGIN_LEFT_VERTICAL, ARC_NODE_RADIUS, ARC_NODE_STROKE_WIDTH, ARC_NODE_LABEL_FONT, ARC_GROUP_LABEL_FONT, ARC_BAND_HALF_W, ARC_BAND_HALF_H, ARC_BAND_RADIUS, ARC_BAND_LABEL_X_OFFSET, ARC_BAND_LABEL_Y_OFFSET, ARC_BAND_LABEL_BOTTOM_OFFSET, ARC_NODE_LABEL_X_OFFSET, ARC_NODE_LABEL_Y_OFFSET, ARC_STROKE_MIN, ARC_STROKE_MAX, ARC_BASELINE_STROKE_WIDTH, timelineCollapseState, tlBandClipCounter, EXPORT_WIDTH, EXPORT_HEIGHT;
57716
+ var d3Scale2, d3Selection23, d3Shape11, d3Array, import_d3_cloud, DEFAULT_CLOUD_OPTIONS, STOP_WORDS, SLOPE_MARGIN, SLOPE_LABEL_FONT_SIZE, SLOPE_CHAR_WIDTH, ARC_MARGIN_TOP, ARC_MARGIN_RIGHT, ARC_MARGIN_BOTTOM, ARC_MARGIN_LEFT, ARC_MARGIN_LEFT_VERTICAL, ARC_NODE_RADIUS, ARC_NODE_STROKE_WIDTH, ARC_NODE_LABEL_FONT, ARC_GROUP_LABEL_FONT, ARC_BAND_HALF_W, ARC_BAND_HALF_H, ARC_BAND_RADIUS, ARC_BAND_LABEL_X_OFFSET, ARC_BAND_LABEL_Y_OFFSET, ARC_BAND_LABEL_BOTTOM_OFFSET, ARC_NODE_LABEL_X_OFFSET, ARC_NODE_LABEL_Y_OFFSET, ARC_STROKE_MIN, ARC_STROKE_MAX, ARC_BASELINE_STROKE_WIDTH, timelineCollapseState, tlBandClipCounter, WORDCLOUD_GLYPH_ADVANCE, EXPORT_WIDTH, EXPORT_HEIGHT;
57658
57717
  var init_d3 = __esm({
57659
57718
  "src/d3.ts"() {
57660
57719
  "use strict";
@@ -57820,6 +57879,7 @@ var init_d3 = __esm({
57820
57879
  ARC_BASELINE_STROKE_WIDTH = 1;
57821
57880
  timelineCollapseState = /* @__PURE__ */ new WeakMap();
57822
57881
  tlBandClipCounter = 0;
57882
+ WORDCLOUD_GLYPH_ADVANCE = 0.62;
57823
57883
  EXPORT_WIDTH = 1200;
57824
57884
  EXPORT_HEIGHT = 800;
57825
57885
  }
@@ -58306,31 +58366,52 @@ init_d3();
58306
58366
  init_echarts();
58307
58367
  init_dgmo_router();
58308
58368
  init_registry();
58309
- async function ensureDom() {
58310
- if (typeof document !== "undefined") return;
58369
+ var DOM_GLOBALS = [
58370
+ "document",
58371
+ "window",
58372
+ "navigator",
58373
+ "HTMLElement",
58374
+ "SVGElement"
58375
+ ];
58376
+ var domRefCount = 0;
58377
+ var domInstallPromise = null;
58378
+ var domInstalledByUs = false;
58379
+ async function installDom() {
58311
58380
  const { JSDOM } = await loadJsdom();
58312
- const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
58313
- const win = dom.window;
58314
- Object.defineProperty(globalThis, "document", {
58315
- value: win.document,
58316
- configurable: true
58317
- });
58318
- Object.defineProperty(globalThis, "window", {
58319
- value: win,
58320
- configurable: true
58321
- });
58322
- Object.defineProperty(globalThis, "navigator", {
58323
- value: win.navigator,
58324
- configurable: true
58325
- });
58326
- Object.defineProperty(globalThis, "HTMLElement", {
58327
- value: win.HTMLElement,
58328
- configurable: true
58329
- });
58330
- Object.defineProperty(globalThis, "SVGElement", {
58331
- value: win.SVGElement,
58332
- configurable: true
58381
+ const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>", {
58382
+ url: "http://localhost/"
58333
58383
  });
58384
+ const win = dom.window;
58385
+ const values = {
58386
+ document: win.document,
58387
+ window: win,
58388
+ navigator: win.navigator,
58389
+ HTMLElement: win.HTMLElement,
58390
+ SVGElement: win.SVGElement
58391
+ };
58392
+ for (const key of DOM_GLOBALS) {
58393
+ Object.defineProperty(globalThis, key, {
58394
+ value: values[key],
58395
+ configurable: true
58396
+ });
58397
+ }
58398
+ domInstalledByUs = true;
58399
+ }
58400
+ async function acquireDom() {
58401
+ if (typeof document !== "undefined" && !domInstalledByUs) return;
58402
+ domRefCount++;
58403
+ if (!domInstallPromise) domInstallPromise = installDom();
58404
+ await domInstallPromise;
58405
+ }
58406
+ function releaseDom() {
58407
+ if (!domInstalledByUs) return;
58408
+ if (--domRefCount > 0) return;
58409
+ for (const key of DOM_GLOBALS) {
58410
+ delete globalThis[key];
58411
+ }
58412
+ domInstalledByUs = false;
58413
+ domInstallPromise = null;
58414
+ domRefCount = 0;
58334
58415
  }
58335
58416
  async function loadJsdom() {
58336
58417
  const spec = ["js", "dom"].join("");
@@ -58364,16 +58445,21 @@ async function render(content, options) {
58364
58445
  );
58365
58446
  return { svg: svg2, diagnostics };
58366
58447
  }
58367
- await ensureDom();
58368
- const svg = await renderForExport(content, theme, paletteColors, viewState, {
58369
- ...options?.c4Level !== void 0 && { c4Level: options.c4Level },
58370
- ...options?.c4System !== void 0 && { c4System: options.c4System },
58371
- ...options?.c4Container !== void 0 && {
58372
- c4Container: options.c4Container
58373
- },
58374
- ...options?.tagGroup !== void 0 && { tagGroup: options.tagGroup },
58375
- ...options?.mapData !== void 0 && { mapData: options.mapData }
58376
- });
58448
+ await acquireDom();
58449
+ let svg;
58450
+ try {
58451
+ svg = await renderForExport(content, theme, paletteColors, viewState, {
58452
+ ...options?.c4Level !== void 0 && { c4Level: options.c4Level },
58453
+ ...options?.c4System !== void 0 && { c4System: options.c4System },
58454
+ ...options?.c4Container !== void 0 && {
58455
+ c4Container: options.c4Container
58456
+ },
58457
+ ...options?.tagGroup !== void 0 && { tagGroup: options.tagGroup },
58458
+ ...options?.mapData !== void 0 && { mapData: options.mapData }
58459
+ });
58460
+ } finally {
58461
+ releaseDom();
58462
+ }
58377
58463
  if (chartType === "map") {
58378
58464
  try {
58379
58465
  const [{ parseMap: parseMap2 }, { resolveMap: resolveMap2 }, { loadMapData: loadMapData2 }] = await Promise.all(
package/dist/index.js CHANGED
@@ -55830,6 +55830,59 @@ function getRotateFn(mode) {
55830
55830
  if (mode === "angled") return () => Math.round(Math.random() * 30 - 15);
55831
55831
  return () => 0;
55832
55832
  }
55833
+ function hasCanvas2d() {
55834
+ try {
55835
+ if (typeof document === "undefined") return false;
55836
+ const canvas = document.createElement("canvas");
55837
+ return typeof canvas.getContext === "function" && !!canvas.getContext("2d");
55838
+ } catch {
55839
+ return false;
55840
+ }
55841
+ }
55842
+ function estimateWordWidth(text, size) {
55843
+ return text.length * size * WORDCLOUD_GLYPH_ADVANCE;
55844
+ }
55845
+ function layoutWordsNoCanvas(words, width, height, padding, rotateFn) {
55846
+ const sorted = [...words].sort((a, b) => b.size - a.size);
55847
+ const placed = [];
55848
+ const maxR = Math.sqrt(width * width + height * height) / 2;
55849
+ const aspect = width > 0 ? height / width : 1;
55850
+ for (const w of sorted) {
55851
+ const rotate = rotateFn();
55852
+ const rawW = estimateWordWidth(w.text, w.size) + padding * 2;
55853
+ const rawH = w.size + padding * 2;
55854
+ const rad = rotate * Math.PI / 180;
55855
+ const cos = Math.abs(Math.cos(rad));
55856
+ const sin = Math.abs(Math.sin(rad));
55857
+ const halfW = (rawW * cos + rawH * sin) / 2;
55858
+ const halfH = (rawW * sin + rawH * cos) / 2;
55859
+ let spot = null;
55860
+ for (let t = 0; t < 4e3; t++) {
55861
+ const a = t * 0.25;
55862
+ const r = a * 1.4;
55863
+ if (r > maxR) break;
55864
+ const x = Math.cos(a) * r;
55865
+ const y = Math.sin(a) * r * aspect;
55866
+ if (x - halfW < -width / 2 || x + halfW > width / 2 || y - halfH < -height / 2 || y + halfH > height / 2) {
55867
+ continue;
55868
+ }
55869
+ let collides = false;
55870
+ for (const p of placed) {
55871
+ if (Math.abs(x - p.x) < halfW + p.halfW && Math.abs(y - p.y) < halfH + p.halfH) {
55872
+ collides = true;
55873
+ break;
55874
+ }
55875
+ }
55876
+ if (!collides) {
55877
+ spot = { x, y };
55878
+ break;
55879
+ }
55880
+ }
55881
+ if (!spot) continue;
55882
+ placed.push({ ...w, rotate, x: spot.x, y: spot.y, halfW, halfH });
55883
+ }
55884
+ return placed;
55885
+ }
55833
55886
  function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
55834
55887
  return new Promise((resolve) => {
55835
55888
  d3Selection23.select(container).selectAll(":not([data-d3-tooltip])").remove();
@@ -55866,13 +55919,19 @@ function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
55866
55919
  "transform",
55867
55920
  `translate(${width / 2},${titleHeight + cloudHeight / 2})`
55868
55921
  );
55869
- cloud().size([width, cloudHeight]).words(words.map((w) => ({ ...w, size: fontSize(w.weight) }))).padding(2).rotate(rotateFn).fontSize((d) => d.size).font(FONT_FAMILY).on("end", (layoutWords) => {
55922
+ const sized = words.map((w) => ({ ...w, size: fontSize(w.weight) }));
55923
+ const draw = (layoutWords) => {
55870
55924
  g.selectAll("text").data(layoutWords).join("text").style("font-size", (d) => `${d.size}px`).style("font-family", FONT_FAMILY).style("font-weight", "600").style("fill", (_d, i) => colors[i % colors.length]).attr("text-anchor", "middle").attr(
55871
55925
  "transform",
55872
55926
  (d) => `translate(${d.x},${d.y}) rotate(${d.rotate})`
55873
55927
  ).text((d) => d.text);
55874
55928
  resolve();
55875
- }).start();
55929
+ };
55930
+ if (!hasCanvas2d()) {
55931
+ draw(layoutWordsNoCanvas(sized, width, cloudHeight, 2, rotateFn));
55932
+ return;
55933
+ }
55934
+ cloud().size([width, cloudHeight]).words(sized).padding(2).rotate(rotateFn).fontSize((d) => d.size).font(FONT_FAMILY).on("end", draw).start();
55876
55935
  });
55877
55936
  }
55878
55937
  function fitCirclesToContainerAsymmetric(circles, w, h, mLeft, mRight, mTop, mBottom) {
@@ -57683,7 +57742,7 @@ async function renderForExport(content, theme, palette, viewState, options) {
57683
57742
  }
57684
57743
  return finalizeSvgExport(container, theme, effectivePalette);
57685
57744
  }
57686
- var DEFAULT_CLOUD_OPTIONS, STOP_WORDS, SLOPE_MARGIN, SLOPE_LABEL_FONT_SIZE, SLOPE_CHAR_WIDTH, ARC_MARGIN_TOP, ARC_MARGIN_RIGHT, ARC_MARGIN_BOTTOM, ARC_MARGIN_LEFT, ARC_MARGIN_LEFT_VERTICAL, ARC_NODE_RADIUS, ARC_NODE_STROKE_WIDTH, ARC_NODE_LABEL_FONT, ARC_GROUP_LABEL_FONT, ARC_BAND_HALF_W, ARC_BAND_HALF_H, ARC_BAND_RADIUS, ARC_BAND_LABEL_X_OFFSET, ARC_BAND_LABEL_Y_OFFSET, ARC_BAND_LABEL_BOTTOM_OFFSET, ARC_NODE_LABEL_X_OFFSET, ARC_NODE_LABEL_Y_OFFSET, ARC_STROKE_MIN, ARC_STROKE_MAX, ARC_BASELINE_STROKE_WIDTH, timelineCollapseState, tlBandClipCounter, EXPORT_WIDTH, EXPORT_HEIGHT;
57745
+ var DEFAULT_CLOUD_OPTIONS, STOP_WORDS, SLOPE_MARGIN, SLOPE_LABEL_FONT_SIZE, SLOPE_CHAR_WIDTH, ARC_MARGIN_TOP, ARC_MARGIN_RIGHT, ARC_MARGIN_BOTTOM, ARC_MARGIN_LEFT, ARC_MARGIN_LEFT_VERTICAL, ARC_NODE_RADIUS, ARC_NODE_STROKE_WIDTH, ARC_NODE_LABEL_FONT, ARC_GROUP_LABEL_FONT, ARC_BAND_HALF_W, ARC_BAND_HALF_H, ARC_BAND_RADIUS, ARC_BAND_LABEL_X_OFFSET, ARC_BAND_LABEL_Y_OFFSET, ARC_BAND_LABEL_BOTTOM_OFFSET, ARC_NODE_LABEL_X_OFFSET, ARC_NODE_LABEL_Y_OFFSET, ARC_STROKE_MIN, ARC_STROKE_MAX, ARC_BASELINE_STROKE_WIDTH, timelineCollapseState, tlBandClipCounter, WORDCLOUD_GLYPH_ADVANCE, EXPORT_WIDTH, EXPORT_HEIGHT;
57687
57746
  var init_d3 = __esm({
57688
57747
  "src/d3.ts"() {
57689
57748
  "use strict";
@@ -57844,6 +57903,7 @@ var init_d3 = __esm({
57844
57903
  ARC_BASELINE_STROKE_WIDTH = 1;
57845
57904
  timelineCollapseState = /* @__PURE__ */ new WeakMap();
57846
57905
  tlBandClipCounter = 0;
57906
+ WORDCLOUD_GLYPH_ADVANCE = 0.62;
57847
57907
  EXPORT_WIDTH = 1200;
57848
57908
  EXPORT_HEIGHT = 800;
57849
57909
  }
@@ -58311,31 +58371,52 @@ init_d3();
58311
58371
  init_echarts();
58312
58372
  init_dgmo_router();
58313
58373
  init_registry();
58314
- async function ensureDom() {
58315
- if (typeof document !== "undefined") return;
58374
+ var DOM_GLOBALS = [
58375
+ "document",
58376
+ "window",
58377
+ "navigator",
58378
+ "HTMLElement",
58379
+ "SVGElement"
58380
+ ];
58381
+ var domRefCount = 0;
58382
+ var domInstallPromise = null;
58383
+ var domInstalledByUs = false;
58384
+ async function installDom() {
58316
58385
  const { JSDOM } = await loadJsdom();
58317
- const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
58318
- const win = dom.window;
58319
- Object.defineProperty(globalThis, "document", {
58320
- value: win.document,
58321
- configurable: true
58322
- });
58323
- Object.defineProperty(globalThis, "window", {
58324
- value: win,
58325
- configurable: true
58326
- });
58327
- Object.defineProperty(globalThis, "navigator", {
58328
- value: win.navigator,
58329
- configurable: true
58330
- });
58331
- Object.defineProperty(globalThis, "HTMLElement", {
58332
- value: win.HTMLElement,
58333
- configurable: true
58334
- });
58335
- Object.defineProperty(globalThis, "SVGElement", {
58336
- value: win.SVGElement,
58337
- configurable: true
58386
+ const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>", {
58387
+ url: "http://localhost/"
58338
58388
  });
58389
+ const win = dom.window;
58390
+ const values = {
58391
+ document: win.document,
58392
+ window: win,
58393
+ navigator: win.navigator,
58394
+ HTMLElement: win.HTMLElement,
58395
+ SVGElement: win.SVGElement
58396
+ };
58397
+ for (const key of DOM_GLOBALS) {
58398
+ Object.defineProperty(globalThis, key, {
58399
+ value: values[key],
58400
+ configurable: true
58401
+ });
58402
+ }
58403
+ domInstalledByUs = true;
58404
+ }
58405
+ async function acquireDom() {
58406
+ if (typeof document !== "undefined" && !domInstalledByUs) return;
58407
+ domRefCount++;
58408
+ if (!domInstallPromise) domInstallPromise = installDom();
58409
+ await domInstallPromise;
58410
+ }
58411
+ function releaseDom() {
58412
+ if (!domInstalledByUs) return;
58413
+ if (--domRefCount > 0) return;
58414
+ for (const key of DOM_GLOBALS) {
58415
+ delete globalThis[key];
58416
+ }
58417
+ domInstalledByUs = false;
58418
+ domInstallPromise = null;
58419
+ domRefCount = 0;
58339
58420
  }
58340
58421
  async function loadJsdom() {
58341
58422
  const spec = ["js", "dom"].join("");
@@ -58369,16 +58450,21 @@ async function render(content, options) {
58369
58450
  );
58370
58451
  return { svg: svg2, diagnostics };
58371
58452
  }
58372
- await ensureDom();
58373
- const svg = await renderForExport(content, theme, paletteColors, viewState, {
58374
- ...options?.c4Level !== void 0 && { c4Level: options.c4Level },
58375
- ...options?.c4System !== void 0 && { c4System: options.c4System },
58376
- ...options?.c4Container !== void 0 && {
58377
- c4Container: options.c4Container
58378
- },
58379
- ...options?.tagGroup !== void 0 && { tagGroup: options.tagGroup },
58380
- ...options?.mapData !== void 0 && { mapData: options.mapData }
58381
- });
58453
+ await acquireDom();
58454
+ let svg;
58455
+ try {
58456
+ svg = await renderForExport(content, theme, paletteColors, viewState, {
58457
+ ...options?.c4Level !== void 0 && { c4Level: options.c4Level },
58458
+ ...options?.c4System !== void 0 && { c4System: options.c4System },
58459
+ ...options?.c4Container !== void 0 && {
58460
+ c4Container: options.c4Container
58461
+ },
58462
+ ...options?.tagGroup !== void 0 && { tagGroup: options.tagGroup },
58463
+ ...options?.mapData !== void 0 && { mapData: options.mapData }
58464
+ });
58465
+ } finally {
58466
+ releaseDom();
58467
+ }
58382
58468
  if (chartType === "map") {
58383
58469
  try {
58384
58470
  const [{ parseMap: parseMap2 }, { resolveMap: resolveMap2 }, { loadMapData: loadMapData2 }] = await Promise.all(
package/dist/internal.cjs CHANGED
@@ -56088,6 +56088,59 @@ function getRotateFn(mode) {
56088
56088
  if (mode === "angled") return () => Math.round(Math.random() * 30 - 15);
56089
56089
  return () => 0;
56090
56090
  }
56091
+ function hasCanvas2d() {
56092
+ try {
56093
+ if (typeof document === "undefined") return false;
56094
+ const canvas = document.createElement("canvas");
56095
+ return typeof canvas.getContext === "function" && !!canvas.getContext("2d");
56096
+ } catch {
56097
+ return false;
56098
+ }
56099
+ }
56100
+ function estimateWordWidth(text, size) {
56101
+ return text.length * size * WORDCLOUD_GLYPH_ADVANCE;
56102
+ }
56103
+ function layoutWordsNoCanvas(words, width, height, padding, rotateFn) {
56104
+ const sorted = [...words].sort((a, b) => b.size - a.size);
56105
+ const placed = [];
56106
+ const maxR = Math.sqrt(width * width + height * height) / 2;
56107
+ const aspect = width > 0 ? height / width : 1;
56108
+ for (const w of sorted) {
56109
+ const rotate = rotateFn();
56110
+ const rawW = estimateWordWidth(w.text, w.size) + padding * 2;
56111
+ const rawH = w.size + padding * 2;
56112
+ const rad = rotate * Math.PI / 180;
56113
+ const cos = Math.abs(Math.cos(rad));
56114
+ const sin = Math.abs(Math.sin(rad));
56115
+ const halfW = (rawW * cos + rawH * sin) / 2;
56116
+ const halfH = (rawW * sin + rawH * cos) / 2;
56117
+ let spot = null;
56118
+ for (let t = 0; t < 4e3; t++) {
56119
+ const a = t * 0.25;
56120
+ const r = a * 1.4;
56121
+ if (r > maxR) break;
56122
+ const x = Math.cos(a) * r;
56123
+ const y = Math.sin(a) * r * aspect;
56124
+ if (x - halfW < -width / 2 || x + halfW > width / 2 || y - halfH < -height / 2 || y + halfH > height / 2) {
56125
+ continue;
56126
+ }
56127
+ let collides = false;
56128
+ for (const p of placed) {
56129
+ if (Math.abs(x - p.x) < halfW + p.halfW && Math.abs(y - p.y) < halfH + p.halfH) {
56130
+ collides = true;
56131
+ break;
56132
+ }
56133
+ }
56134
+ if (!collides) {
56135
+ spot = { x, y };
56136
+ break;
56137
+ }
56138
+ }
56139
+ if (!spot) continue;
56140
+ placed.push({ ...w, rotate, x: spot.x, y: spot.y, halfW, halfH });
56141
+ }
56142
+ return placed;
56143
+ }
56091
56144
  function renderWordCloud(container, parsed, palette, _isDark, onClickItem, exportDims) {
56092
56145
  const { words, cloudOptions } = parsed;
56093
56146
  const title = parsed.noTitle ? null : parsed.title;
@@ -56128,21 +56181,24 @@ function renderWordCloud(container, parsed, palette, _isDark, onClickItem, expor
56128
56181
  "transform",
56129
56182
  `translate(${width / 2},${sTitleHeight + cloudHeight / 2})`
56130
56183
  );
56131
- (0, import_d3_cloud.default)().size([width, cloudHeight]).words(words.map((w) => ({ ...w, size: fontSize(w.weight) }))).padding(sPadding).rotate(rotateFn).fontSize((d) => d.size).font(FONT_FAMILY).on("end", (layoutWords) => {
56184
+ const sized = words.map((w) => ({ ...w, size: fontSize(w.weight) }));
56185
+ const draw = (layoutWords) => {
56132
56186
  g.selectAll("text").data(layoutWords).join("text").style("font-size", (d) => `${d.size}px`).style("font-family", FONT_FAMILY).style("font-weight", "600").style("fill", (_d, i) => colors[i % colors.length]).style(
56133
56187
  "cursor",
56134
56188
  (d) => onClickItem && d.lineNumber ? "pointer" : "default"
56135
- ).attr("text-anchor", "middle").attr(
56136
- "transform",
56137
- (d) => `translate(${d.x},${d.y}) rotate(${d.rotate})`
56138
- ).attr("data-line-number", (d) => {
56189
+ ).attr("text-anchor", "middle").attr("transform", (d) => `translate(${d.x},${d.y}) rotate(${d.rotate})`).attr("data-line-number", (d) => {
56139
56190
  const ln = d.lineNumber;
56140
56191
  return ln ? String(ln) : null;
56141
56192
  }).text((d) => d.text).on("click", (_event, d) => {
56142
56193
  const ln = d.lineNumber;
56143
56194
  if (onClickItem && ln) onClickItem(ln);
56144
56195
  });
56145
- }).start();
56196
+ };
56197
+ if (!hasCanvas2d()) {
56198
+ draw(layoutWordsNoCanvas(sized, width, cloudHeight, sPadding, rotateFn));
56199
+ return;
56200
+ }
56201
+ (0, import_d3_cloud.default)().size([width, cloudHeight]).words(sized).padding(sPadding).rotate(rotateFn).fontSize((d) => d.size).font(FONT_FAMILY).on("end", draw).start();
56146
56202
  }
56147
56203
  function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
56148
56204
  return new Promise((resolve) => {
@@ -56180,13 +56236,19 @@ function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
56180
56236
  "transform",
56181
56237
  `translate(${width / 2},${titleHeight + cloudHeight / 2})`
56182
56238
  );
56183
- (0, import_d3_cloud.default)().size([width, cloudHeight]).words(words.map((w) => ({ ...w, size: fontSize(w.weight) }))).padding(2).rotate(rotateFn).fontSize((d) => d.size).font(FONT_FAMILY).on("end", (layoutWords) => {
56239
+ const sized = words.map((w) => ({ ...w, size: fontSize(w.weight) }));
56240
+ const draw = (layoutWords) => {
56184
56241
  g.selectAll("text").data(layoutWords).join("text").style("font-size", (d) => `${d.size}px`).style("font-family", FONT_FAMILY).style("font-weight", "600").style("fill", (_d, i) => colors[i % colors.length]).attr("text-anchor", "middle").attr(
56185
56242
  "transform",
56186
56243
  (d) => `translate(${d.x},${d.y}) rotate(${d.rotate})`
56187
56244
  ).text((d) => d.text);
56188
56245
  resolve();
56189
- }).start();
56246
+ };
56247
+ if (!hasCanvas2d()) {
56248
+ draw(layoutWordsNoCanvas(sized, width, cloudHeight, 2, rotateFn));
56249
+ return;
56250
+ }
56251
+ (0, import_d3_cloud.default)().size([width, cloudHeight]).words(sized).padding(2).rotate(rotateFn).fontSize((d) => d.size).font(FONT_FAMILY).on("end", draw).start();
56190
56252
  });
56191
56253
  }
56192
56254
  function fitCirclesToContainerAsymmetric(circles, w, h, mLeft, mRight, mTop, mBottom) {
@@ -57997,7 +58059,7 @@ async function renderForExport(content, theme, palette, viewState, options) {
57997
58059
  }
57998
58060
  return finalizeSvgExport(container, theme, effectivePalette);
57999
58061
  }
58000
- var d3Scale2, d3Selection23, d3Shape11, d3Array, import_d3_cloud, DEFAULT_CLOUD_OPTIONS, STOP_WORDS, SLOPE_MARGIN, SLOPE_LABEL_FONT_SIZE, SLOPE_CHAR_WIDTH, ARC_MARGIN_TOP, ARC_MARGIN_RIGHT, ARC_MARGIN_BOTTOM, ARC_MARGIN_LEFT, ARC_MARGIN_LEFT_VERTICAL, ARC_NODE_RADIUS, ARC_NODE_STROKE_WIDTH, ARC_NODE_LABEL_FONT, ARC_GROUP_LABEL_FONT, ARC_BAND_HALF_W, ARC_BAND_HALF_H, ARC_BAND_RADIUS, ARC_BAND_LABEL_X_OFFSET, ARC_BAND_LABEL_Y_OFFSET, ARC_BAND_LABEL_BOTTOM_OFFSET, ARC_NODE_LABEL_X_OFFSET, ARC_NODE_LABEL_Y_OFFSET, ARC_STROKE_MIN, ARC_STROKE_MAX, ARC_BASELINE_STROKE_WIDTH, timelineCollapseState, tlBandClipCounter, EXPORT_WIDTH, EXPORT_HEIGHT;
58062
+ var d3Scale2, d3Selection23, d3Shape11, d3Array, import_d3_cloud, DEFAULT_CLOUD_OPTIONS, STOP_WORDS, SLOPE_MARGIN, SLOPE_LABEL_FONT_SIZE, SLOPE_CHAR_WIDTH, ARC_MARGIN_TOP, ARC_MARGIN_RIGHT, ARC_MARGIN_BOTTOM, ARC_MARGIN_LEFT, ARC_MARGIN_LEFT_VERTICAL, ARC_NODE_RADIUS, ARC_NODE_STROKE_WIDTH, ARC_NODE_LABEL_FONT, ARC_GROUP_LABEL_FONT, ARC_BAND_HALF_W, ARC_BAND_HALF_H, ARC_BAND_RADIUS, ARC_BAND_LABEL_X_OFFSET, ARC_BAND_LABEL_Y_OFFSET, ARC_BAND_LABEL_BOTTOM_OFFSET, ARC_NODE_LABEL_X_OFFSET, ARC_NODE_LABEL_Y_OFFSET, ARC_STROKE_MIN, ARC_STROKE_MAX, ARC_BASELINE_STROKE_WIDTH, timelineCollapseState, tlBandClipCounter, WORDCLOUD_GLYPH_ADVANCE, EXPORT_WIDTH, EXPORT_HEIGHT;
58001
58063
  var init_d3 = __esm({
58002
58064
  "src/d3.ts"() {
58003
58065
  "use strict";
@@ -58164,6 +58226,7 @@ var init_d3 = __esm({
58164
58226
  ARC_BASELINE_STROKE_WIDTH = 1;
58165
58227
  timelineCollapseState = /* @__PURE__ */ new WeakMap();
58166
58228
  tlBandClipCounter = 0;
58229
+ WORDCLOUD_GLYPH_ADVANCE = 0.62;
58167
58230
  EXPORT_WIDTH = 1200;
58168
58231
  EXPORT_HEIGHT = 800;
58169
58232
  }
@@ -58913,31 +58976,52 @@ init_d3();
58913
58976
  init_echarts();
58914
58977
  init_dgmo_router();
58915
58978
  init_registry();
58916
- async function ensureDom() {
58917
- if (typeof document !== "undefined") return;
58979
+ var DOM_GLOBALS = [
58980
+ "document",
58981
+ "window",
58982
+ "navigator",
58983
+ "HTMLElement",
58984
+ "SVGElement"
58985
+ ];
58986
+ var domRefCount = 0;
58987
+ var domInstallPromise = null;
58988
+ var domInstalledByUs = false;
58989
+ async function installDom() {
58918
58990
  const { JSDOM } = await loadJsdom();
58919
- const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
58920
- const win = dom.window;
58921
- Object.defineProperty(globalThis, "document", {
58922
- value: win.document,
58923
- configurable: true
58924
- });
58925
- Object.defineProperty(globalThis, "window", {
58926
- value: win,
58927
- configurable: true
58928
- });
58929
- Object.defineProperty(globalThis, "navigator", {
58930
- value: win.navigator,
58931
- configurable: true
58932
- });
58933
- Object.defineProperty(globalThis, "HTMLElement", {
58934
- value: win.HTMLElement,
58935
- configurable: true
58936
- });
58937
- Object.defineProperty(globalThis, "SVGElement", {
58938
- value: win.SVGElement,
58939
- configurable: true
58991
+ const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>", {
58992
+ url: "http://localhost/"
58940
58993
  });
58994
+ const win = dom.window;
58995
+ const values = {
58996
+ document: win.document,
58997
+ window: win,
58998
+ navigator: win.navigator,
58999
+ HTMLElement: win.HTMLElement,
59000
+ SVGElement: win.SVGElement
59001
+ };
59002
+ for (const key of DOM_GLOBALS) {
59003
+ Object.defineProperty(globalThis, key, {
59004
+ value: values[key],
59005
+ configurable: true
59006
+ });
59007
+ }
59008
+ domInstalledByUs = true;
59009
+ }
59010
+ async function acquireDom() {
59011
+ if (typeof document !== "undefined" && !domInstalledByUs) return;
59012
+ domRefCount++;
59013
+ if (!domInstallPromise) domInstallPromise = installDom();
59014
+ await domInstallPromise;
59015
+ }
59016
+ function releaseDom() {
59017
+ if (!domInstalledByUs) return;
59018
+ if (--domRefCount > 0) return;
59019
+ for (const key of DOM_GLOBALS) {
59020
+ delete globalThis[key];
59021
+ }
59022
+ domInstalledByUs = false;
59023
+ domInstallPromise = null;
59024
+ domRefCount = 0;
58941
59025
  }
58942
59026
  async function loadJsdom() {
58943
59027
  const spec = ["js", "dom"].join("");
@@ -58971,16 +59055,21 @@ async function render(content, options) {
58971
59055
  );
58972
59056
  return { svg: svg2, diagnostics };
58973
59057
  }
58974
- await ensureDom();
58975
- const svg = await renderForExport(content, theme, paletteColors, viewState, {
58976
- ...options?.c4Level !== void 0 && { c4Level: options.c4Level },
58977
- ...options?.c4System !== void 0 && { c4System: options.c4System },
58978
- ...options?.c4Container !== void 0 && {
58979
- c4Container: options.c4Container
58980
- },
58981
- ...options?.tagGroup !== void 0 && { tagGroup: options.tagGroup },
58982
- ...options?.mapData !== void 0 && { mapData: options.mapData }
58983
- });
59058
+ await acquireDom();
59059
+ let svg;
59060
+ try {
59061
+ svg = await renderForExport(content, theme, paletteColors, viewState, {
59062
+ ...options?.c4Level !== void 0 && { c4Level: options.c4Level },
59063
+ ...options?.c4System !== void 0 && { c4System: options.c4System },
59064
+ ...options?.c4Container !== void 0 && {
59065
+ c4Container: options.c4Container
59066
+ },
59067
+ ...options?.tagGroup !== void 0 && { tagGroup: options.tagGroup },
59068
+ ...options?.mapData !== void 0 && { mapData: options.mapData }
59069
+ });
59070
+ } finally {
59071
+ releaseDom();
59072
+ }
58984
59073
  if (chartType === "map") {
58985
59074
  try {
58986
59075
  const [{ parseMap: parseMap2 }, { resolveMap: resolveMap2 }, { loadMapData: loadMapData2 }] = await Promise.all(