@diagrammo/dgmo 0.1.6 → 0.2.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/index.js CHANGED
@@ -549,6 +549,15 @@ var init_colors = __esm({
549
549
  }
550
550
  });
551
551
 
552
+ // src/fonts.ts
553
+ var FONT_FAMILY;
554
+ var init_fonts = __esm({
555
+ "src/fonts.ts"() {
556
+ "use strict";
557
+ FONT_FAMILY = "Inter, system-ui, Avenir, Helvetica, Arial, sans-serif";
558
+ }
559
+ });
560
+
552
561
  // src/palettes/registry.ts
553
562
  function isValidHex(value) {
554
563
  return /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value);
@@ -1595,15 +1604,6 @@ var init_palettes = __esm({
1595
1604
  }
1596
1605
  });
1597
1606
 
1598
- // src/fonts.ts
1599
- var FONT_FAMILY;
1600
- var init_fonts = __esm({
1601
- "src/fonts.ts"() {
1602
- "use strict";
1603
- FONT_FAMILY = "Inter, system-ui, Avenir, Helvetica, Arial, sans-serif";
1604
- }
1605
- });
1606
-
1607
1607
  // src/sequence/renderer.ts
1608
1608
  var renderer_exports = {};
1609
1609
  __export(renderer_exports, {
@@ -2456,16 +2456,16 @@ var init_renderer = __esm({
2456
2456
  // src/dgmo-router.ts
2457
2457
  init_parser();
2458
2458
  var DGMO_CHART_TYPE_MAP = {
2459
- // Chart.js
2460
- bar: "chartjs",
2461
- line: "chartjs",
2462
- "multi-line": "chartjs",
2463
- area: "chartjs",
2464
- pie: "chartjs",
2465
- doughnut: "chartjs",
2466
- radar: "chartjs",
2467
- "polar-area": "chartjs",
2468
- "bar-stacked": "chartjs",
2459
+ // Standard charts (via ECharts)
2460
+ bar: "echart",
2461
+ line: "echart",
2462
+ "multi-line": "echart",
2463
+ area: "echart",
2464
+ pie: "echart",
2465
+ doughnut: "echart",
2466
+ radar: "echart",
2467
+ "polar-area": "echart",
2468
+ "bar-stacked": "echart",
2469
2469
  // ECharts
2470
2470
  scatter: "echart",
2471
2471
  sankey: "echart",
@@ -2498,10 +2498,8 @@ function parseDgmoChartType(content) {
2498
2498
  return null;
2499
2499
  }
2500
2500
 
2501
- // src/chartjs.ts
2501
+ // src/chart.ts
2502
2502
  init_colors();
2503
- init_palettes();
2504
- import "chartjs-plugin-datalabels";
2505
2503
  var VALID_TYPES = /* @__PURE__ */ new Set([
2506
2504
  "bar",
2507
2505
  "line",
@@ -2515,7 +2513,7 @@ var VALID_TYPES = /* @__PURE__ */ new Set([
2515
2513
  var TYPE_ALIASES = {
2516
2514
  "multi-line": "line"
2517
2515
  };
2518
- function parseChartJs(content, palette) {
2516
+ function parseChart(content, palette) {
2519
2517
  const lines = content.split("\n");
2520
2518
  const result = {
2521
2519
  type: "bar",
@@ -2633,459 +2631,12 @@ function parseChartJs(content, palette) {
2633
2631
  }
2634
2632
  return result;
2635
2633
  }
2636
- function buildChartJsConfig(parsed, palette, _isDark) {
2637
- const textColor = palette.text;
2638
- const gridColor = palette.border + "80";
2639
- const crosshairColor = palette.border + "60";
2640
- const colors = getSeriesColors(palette);
2641
- const verticalCrosshairPlugin = {
2642
- id: "verticalCrosshair",
2643
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2644
- afterDraw(chart) {
2645
- const tooltip = chart.tooltip;
2646
- if (!tooltip || !tooltip.getActiveElements().length) return;
2647
- const { ctx, chartArea } = chart;
2648
- const x = tooltip.caretX;
2649
- ctx.save();
2650
- ctx.beginPath();
2651
- ctx.moveTo(x, chartArea.top);
2652
- ctx.lineTo(x, chartArea.bottom);
2653
- ctx.lineWidth = 1;
2654
- ctx.strokeStyle = crosshairColor;
2655
- ctx.stroke();
2656
- ctx.restore();
2657
- }
2658
- };
2659
- const labels = parsed.data.map((d) => d.label);
2660
- const values = parsed.data.map((d) => d.value);
2661
- const perPointColors = parsed.data.map(
2662
- (d, i) => d.color ?? colors[i % colors.length]
2663
- );
2664
- const titlePlugin = parsed.title ? {
2665
- display: true,
2666
- text: parsed.title,
2667
- color: textColor,
2668
- font: { size: 18, weight: "bold" },
2669
- padding: { bottom: 16 }
2670
- } : { display: false };
2671
- const tooltipConfig = {
2672
- backgroundColor: palette.surface,
2673
- titleColor: palette.text,
2674
- bodyColor: palette.text,
2675
- borderColor: palette.border,
2676
- borderWidth: 1
2677
- };
2678
- const isHorizontalChart = parsed.orientation === "horizontal";
2679
- const resolvedXLabel = parsed.xlabel ?? (isHorizontalChart ? parsed.label : void 0);
2680
- const resolvedYLabel = parsed.ylabel ?? (isHorizontalChart ? void 0 : parsed.label);
2681
- const xAxisTitle = resolvedXLabel ? { display: true, text: resolvedXLabel, color: textColor } : void 0;
2682
- const yAxisTitle = resolvedYLabel ? { display: true, text: resolvedYLabel, color: textColor } : void 0;
2683
- if (parsed.type === "radar") {
2684
- const radarColor = parsed.color ?? parsed.seriesNameColors?.[0] ?? palette.primary;
2685
- const radarGridColor = palette.border + "60";
2686
- const radarGridOverlayPlugin = {
2687
- id: "radarGridOverlay",
2688
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2689
- afterDatasetsDraw(chart) {
2690
- const scale = chart.scales.r;
2691
- if (!scale) return;
2692
- const ticks = scale.ticks;
2693
- if (!ticks || ticks.length < 1) return;
2694
- const { ctx } = chart;
2695
- const pointCount = chart.data.labels?.length ?? 0;
2696
- if (pointCount < 3) return;
2697
- ctx.save();
2698
- ctx.strokeStyle = radarGridColor;
2699
- ctx.lineWidth = 1;
2700
- for (let i = 0; i < ticks.length; i++) {
2701
- const dist = scale.getDistanceFromCenterForValue(
2702
- ticks[i].value
2703
- );
2704
- if (dist <= 0) continue;
2705
- ctx.beginPath();
2706
- for (let p = 0; p < pointCount; p++) {
2707
- const pos = scale.getPointPosition(p, dist);
2708
- if (p === 0) ctx.moveTo(pos.x, pos.y);
2709
- else ctx.lineTo(pos.x, pos.y);
2710
- }
2711
- ctx.closePath();
2712
- ctx.stroke();
2713
- }
2714
- const outerDist = scale.getDistanceFromCenterForValue(
2715
- ticks[ticks.length - 1].value
2716
- );
2717
- for (let p = 0; p < pointCount; p++) {
2718
- const pos = scale.getPointPosition(p, outerDist);
2719
- ctx.beginPath();
2720
- ctx.moveTo(scale.xCenter, scale.yCenter);
2721
- ctx.lineTo(pos.x, pos.y);
2722
- ctx.stroke();
2723
- }
2724
- ctx.restore();
2725
- }
2726
- };
2727
- return {
2728
- type: "radar",
2729
- data: {
2730
- labels,
2731
- datasets: [
2732
- {
2733
- label: parsed.series ?? "Value",
2734
- data: values,
2735
- backgroundColor: radarColor,
2736
- borderColor: "transparent",
2737
- borderWidth: 0,
2738
- pointBackgroundColor: radarColor,
2739
- pointRadius: 5
2740
- }
2741
- ]
2742
- },
2743
- options: {
2744
- responsive: true,
2745
- maintainAspectRatio: false,
2746
- animation: false,
2747
- plugins: {
2748
- legend: { display: false },
2749
- title: titlePlugin,
2750
- tooltip: tooltipConfig,
2751
- datalabels: {
2752
- display: true,
2753
- color: textColor,
2754
- backgroundColor: palette.bg + "cc",
2755
- borderRadius: 3,
2756
- padding: { top: 2, bottom: 2, left: 4, right: 4 },
2757
- font: { size: 11, weight: "bold" },
2758
- anchor: "center",
2759
- align: "center",
2760
- formatter: (value) => value.toString()
2761
- }
2762
- },
2763
- scales: {
2764
- r: {
2765
- beginAtZero: true,
2766
- ticks: {
2767
- // Hide tick labels - we show actual values on data points instead
2768
- display: false
2769
- },
2770
- grid: {
2771
- // Hide default grid - we draw it on top via plugin
2772
- display: false
2773
- },
2774
- angleLines: {
2775
- // Hide default angle lines - we draw them on top via plugin
2776
- display: false
2777
- },
2778
- pointLabels: {
2779
- color: textColor,
2780
- font: { size: 12, weight: "bold" }
2781
- }
2782
- }
2783
- }
2784
- },
2785
- plugins: [radarGridOverlayPlugin]
2786
- };
2787
- }
2788
- if (parsed.type === "polar-area") {
2789
- const polarConnectorPlugin = {
2790
- id: "polarConnectorLines",
2791
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2792
- afterDatasetsDraw(chart) {
2793
- const meta = chart.getDatasetMeta(0);
2794
- if (!meta?.data?.length) return;
2795
- const { ctx } = chart;
2796
- ctx.save();
2797
- ctx.strokeStyle = textColor;
2798
- ctx.lineWidth = 1;
2799
- meta.data.forEach((arc) => {
2800
- const {
2801
- startAngle,
2802
- endAngle,
2803
- outerRadius,
2804
- x: cx,
2805
- y: cy
2806
- } = arc.getProps(["startAngle", "endAngle", "outerRadius", "x", "y"]);
2807
- const midAngle = (startAngle + endAngle) / 2;
2808
- const r1 = outerRadius + 2;
2809
- const r2 = outerRadius + 14;
2810
- ctx.beginPath();
2811
- ctx.moveTo(
2812
- cx + Math.cos(midAngle) * r1,
2813
- cy + Math.sin(midAngle) * r1
2814
- );
2815
- ctx.lineTo(
2816
- cx + Math.cos(midAngle) * r2,
2817
- cy + Math.sin(midAngle) * r2
2818
- );
2819
- ctx.stroke();
2820
- });
2821
- ctx.restore();
2822
- }
2823
- };
2824
- const polarTitlePlugin = parsed.title ? {
2825
- display: true,
2826
- text: parsed.title,
2827
- color: textColor,
2828
- font: { size: 18, weight: "bold" },
2829
- padding: { bottom: 24 }
2830
- } : { display: false };
2831
- return {
2832
- type: "polarArea",
2833
- data: {
2834
- labels,
2835
- datasets: [
2836
- {
2837
- label: parsed.series ?? "Value",
2838
- data: values,
2839
- backgroundColor: perPointColors,
2840
- borderWidth: 0
2841
- }
2842
- ]
2843
- },
2844
- options: {
2845
- responsive: true,
2846
- maintainAspectRatio: false,
2847
- animation: false,
2848
- layout: { padding: { top: 10, bottom: 40, left: 60, right: 60 } },
2849
- plugins: {
2850
- legend: { display: false },
2851
- title: polarTitlePlugin,
2852
- tooltip: tooltipConfig,
2853
- datalabels: {
2854
- display: true,
2855
- color: textColor,
2856
- font: { weight: "bold" },
2857
- formatter: (_value, ctx) => labels[ctx.dataIndex] ?? "",
2858
- anchor: "end",
2859
- align: "end",
2860
- offset: 16
2861
- }
2862
- },
2863
- scales: {
2864
- r: {
2865
- ticks: { display: false },
2866
- grid: { color: gridColor }
2867
- }
2868
- }
2869
- },
2870
- plugins: [polarConnectorPlugin]
2871
- };
2872
- }
2873
- if (parsed.type === "pie" || parsed.type === "doughnut") {
2874
- const pieConnectorPlugin = {
2875
- id: "pieConnectorLines",
2876
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2877
- afterDatasetsDraw(chart) {
2878
- const meta = chart.getDatasetMeta(0);
2879
- if (!meta?.data?.length) return;
2880
- const { ctx } = chart;
2881
- ctx.save();
2882
- ctx.strokeStyle = textColor;
2883
- ctx.lineWidth = 1;
2884
- meta.data.forEach((arc) => {
2885
- const {
2886
- startAngle,
2887
- endAngle,
2888
- outerRadius,
2889
- x: cx,
2890
- y: cy
2891
- } = arc.getProps(["startAngle", "endAngle", "outerRadius", "x", "y"]);
2892
- const midAngle = (startAngle + endAngle) / 2;
2893
- const r1 = outerRadius + 2;
2894
- const r2 = outerRadius + 14;
2895
- ctx.beginPath();
2896
- ctx.moveTo(
2897
- cx + Math.cos(midAngle) * r1,
2898
- cy + Math.sin(midAngle) * r1
2899
- );
2900
- ctx.lineTo(
2901
- cx + Math.cos(midAngle) * r2,
2902
- cy + Math.sin(midAngle) * r2
2903
- );
2904
- ctx.stroke();
2905
- });
2906
- ctx.restore();
2907
- }
2908
- };
2909
- const pieTitlePlugin = parsed.title ? {
2910
- display: true,
2911
- text: parsed.title,
2912
- color: textColor,
2913
- font: { size: 18, weight: "bold" },
2914
- padding: { bottom: 24 }
2915
- } : { display: false };
2916
- return {
2917
- type: parsed.type,
2918
- data: {
2919
- labels,
2920
- datasets: [
2921
- {
2922
- label: parsed.series ?? "Value",
2923
- data: values,
2924
- backgroundColor: perPointColors,
2925
- borderWidth: 0
2926
- }
2927
- ]
2928
- },
2929
- options: {
2930
- responsive: true,
2931
- maintainAspectRatio: false,
2932
- animation: false,
2933
- // radius is valid for pie/doughnut at runtime but not in the strict type
2934
- radius: "70%",
2935
- layout: { padding: { top: 10, bottom: 40, left: 60, right: 60 } },
2936
- plugins: {
2937
- legend: { display: false },
2938
- title: pieTitlePlugin,
2939
- tooltip: tooltipConfig,
2940
- datalabels: {
2941
- display: true,
2942
- color: textColor,
2943
- font: { weight: "bold" },
2944
- formatter: (_value, ctx) => labels[ctx.dataIndex] ?? "",
2945
- anchor: "end",
2946
- align: "end",
2947
- offset: 16
2948
- }
2949
- }
2950
- },
2951
- plugins: [pieConnectorPlugin]
2952
- };
2953
- }
2954
- const isMultiSeries = parsed.type === "bar-stacked" || parsed.type === "line" && parsed.seriesNames;
2955
- if (isMultiSeries) {
2956
- const seriesNames = parsed.seriesNames ?? ["Value"];
2957
- const isHorizontal2 = parsed.orientation === "horizontal";
2958
- const isMultiLine = parsed.type === "line";
2959
- const datasets = seriesNames.map((name, seriesIdx) => {
2960
- const data = parsed.data.map((dp) => {
2961
- if (seriesIdx === 0) return dp.value;
2962
- return dp.extraValues?.[seriesIdx - 1] ?? 0;
2963
- });
2964
- const color = parsed.seriesNameColors?.[seriesIdx] ?? colors[seriesIdx % colors.length];
2965
- if (isMultiLine) {
2966
- return {
2967
- label: name,
2968
- data,
2969
- borderColor: color,
2970
- backgroundColor: color + "40",
2971
- borderWidth: 3,
2972
- pointBackgroundColor: color,
2973
- pointRadius: 4,
2974
- tension: 0,
2975
- fill: false
2976
- };
2977
- }
2978
- return {
2979
- label: name,
2980
- data,
2981
- backgroundColor: color,
2982
- borderColor: color,
2983
- borderWidth: 1
2984
- };
2985
- });
2986
- const scaleOptions = isMultiLine ? {
2987
- x: {
2988
- grid: { color: gridColor },
2989
- ticks: { color: textColor },
2990
- ...xAxisTitle && { title: xAxisTitle }
2991
- },
2992
- y: {
2993
- grid: { color: gridColor },
2994
- ticks: { color: textColor },
2995
- ...yAxisTitle && { title: yAxisTitle }
2996
- }
2997
- } : {
2998
- x: {
2999
- stacked: true,
3000
- grid: { color: gridColor },
3001
- ticks: { color: textColor },
3002
- ...xAxisTitle && { title: xAxisTitle }
3003
- },
3004
- y: {
3005
- stacked: true,
3006
- grid: { color: gridColor },
3007
- ticks: { color: textColor },
3008
- ...yAxisTitle && { title: yAxisTitle }
3009
- }
3010
- };
3011
- return {
3012
- type: isMultiLine ? "line" : "bar",
3013
- data: {
3014
- labels,
3015
- datasets
3016
- },
3017
- options: {
3018
- indexAxis: isHorizontal2 ? "y" : "x",
3019
- responsive: true,
3020
- maintainAspectRatio: false,
3021
- animation: false,
3022
- plugins: {
3023
- legend: { position: "top", labels: { color: textColor } },
3024
- title: titlePlugin,
3025
- tooltip: tooltipConfig,
3026
- datalabels: { display: false }
3027
- },
3028
- ...isMultiLine ? { interaction: { mode: "index", intersect: false } } : {},
3029
- scales: scaleOptions
3030
- },
3031
- ...isMultiLine ? { plugins: [verticalCrosshairPlugin] } : {}
3032
- };
3033
- }
3034
- const isHorizontal = parsed.orientation === "horizontal";
3035
- const isLine = parsed.type === "line" || parsed.type === "area";
3036
- const isArea = parsed.type === "area";
3037
- const lineColor = parsed.color ?? parsed.seriesNameColors?.[0] ?? palette.primary;
3038
- return {
3039
- type: isLine ? "line" : "bar",
3040
- data: {
3041
- labels,
3042
- datasets: [
3043
- {
3044
- label: parsed.series ?? "Value",
3045
- data: values,
3046
- backgroundColor: isLine ? isArea ? lineColor + "40" : lineColor : perPointColors,
3047
- borderColor: isLine ? lineColor : void 0,
3048
- borderWidth: isLine ? 3 : 0,
3049
- pointBackgroundColor: isLine ? lineColor : void 0,
3050
- pointRadius: isLine ? 4 : void 0,
3051
- tension: isLine ? 0 : void 0,
3052
- fill: isArea ? true : void 0
3053
- }
3054
- ]
3055
- },
3056
- options: {
3057
- indexAxis: isHorizontal ? "y" : "x",
3058
- responsive: true,
3059
- maintainAspectRatio: false,
3060
- animation: false,
3061
- ...isLine && !isArea ? { interaction: { mode: "index", intersect: false } } : {},
3062
- plugins: {
3063
- legend: { display: false },
3064
- title: titlePlugin,
3065
- tooltip: tooltipConfig,
3066
- datalabels: { display: false }
3067
- },
3068
- scales: {
3069
- x: {
3070
- grid: { color: gridColor },
3071
- ticks: { color: textColor },
3072
- ...xAxisTitle && { title: xAxisTitle }
3073
- },
3074
- y: {
3075
- grid: { color: gridColor },
3076
- ticks: { color: textColor },
3077
- ...yAxisTitle && { title: yAxisTitle }
3078
- }
3079
- }
3080
- },
3081
- ...isLine && !isArea ? { plugins: [verticalCrosshairPlugin] } : {}
3082
- };
3083
- }
3084
2634
 
3085
2635
  // src/echarts.ts
3086
2636
  init_fonts();
3087
2637
  init_colors();
3088
2638
  init_palettes();
2639
+ import * as echarts from "echarts";
3089
2640
  function parseEChart(content, palette) {
3090
2641
  const lines = content.split("\n");
3091
2642
  const result = {
@@ -3959,6 +3510,431 @@ function buildFunnelOption(parsed, textColor, colors, titleConfig, tooltipTheme)
3959
3510
  ]
3960
3511
  };
3961
3512
  }
3513
+ function resolveAxisLabels(parsed) {
3514
+ const isHorizontal = parsed.orientation === "horizontal";
3515
+ return {
3516
+ xLabel: parsed.xlabel ?? (isHorizontal ? parsed.label : void 0),
3517
+ yLabel: parsed.ylabel ?? (isHorizontal ? void 0 : parsed.label)
3518
+ };
3519
+ }
3520
+ function makeGridAxis(type, textColor, axisLineColor, splitLineColor, label, data) {
3521
+ return {
3522
+ type,
3523
+ ...data && { data },
3524
+ axisLine: { lineStyle: { color: axisLineColor } },
3525
+ axisLabel: { color: textColor, fontFamily: FONT_FAMILY },
3526
+ splitLine: { lineStyle: { color: splitLineColor } },
3527
+ ...label && {
3528
+ name: label,
3529
+ nameLocation: "middle",
3530
+ nameGap: 30,
3531
+ nameTextStyle: { color: textColor, fontSize: 12, fontFamily: FONT_FAMILY }
3532
+ }
3533
+ };
3534
+ }
3535
+ function buildEChartsOptionFromChart(parsed, palette, _isDark) {
3536
+ if (parsed.error) return {};
3537
+ const textColor = palette.text;
3538
+ const axisLineColor = palette.border;
3539
+ const splitLineColor = palette.overlay;
3540
+ const colors = getSeriesColors(palette);
3541
+ const titleConfig = parsed.title ? {
3542
+ text: parsed.title,
3543
+ left: "center",
3544
+ textStyle: {
3545
+ color: textColor,
3546
+ fontSize: 18,
3547
+ fontWeight: "bold",
3548
+ fontFamily: FONT_FAMILY
3549
+ }
3550
+ } : void 0;
3551
+ const tooltipTheme = {
3552
+ backgroundColor: palette.surface,
3553
+ borderColor: palette.border,
3554
+ textStyle: { color: palette.text }
3555
+ };
3556
+ switch (parsed.type) {
3557
+ case "bar":
3558
+ return buildBarOption(parsed, textColor, axisLineColor, splitLineColor, colors, titleConfig, tooltipTheme);
3559
+ case "bar-stacked":
3560
+ return buildBarStackedOption(parsed, textColor, axisLineColor, splitLineColor, colors, titleConfig, tooltipTheme);
3561
+ case "line":
3562
+ return parsed.seriesNames ? buildMultiLineOption(parsed, textColor, axisLineColor, splitLineColor, colors, titleConfig, tooltipTheme) : buildLineOption(parsed, palette, textColor, axisLineColor, splitLineColor, titleConfig, tooltipTheme);
3563
+ case "area":
3564
+ return buildAreaOption(parsed, palette, textColor, axisLineColor, splitLineColor, titleConfig, tooltipTheme);
3565
+ case "pie":
3566
+ return buildPieOption(parsed, textColor, colors, titleConfig, tooltipTheme, false);
3567
+ case "doughnut":
3568
+ return buildPieOption(parsed, textColor, colors, titleConfig, tooltipTheme, true);
3569
+ case "radar":
3570
+ return buildRadarOption(parsed, palette, textColor, colors, titleConfig, tooltipTheme);
3571
+ case "polar-area":
3572
+ return buildPolarAreaOption(parsed, textColor, colors, titleConfig, tooltipTheme);
3573
+ }
3574
+ }
3575
+ function buildBarOption(parsed, textColor, axisLineColor, splitLineColor, colors, titleConfig, tooltipTheme) {
3576
+ const { xLabel, yLabel } = resolveAxisLabels(parsed);
3577
+ const isHorizontal = parsed.orientation === "horizontal";
3578
+ const labels = parsed.data.map((d) => d.label);
3579
+ const data = parsed.data.map((d, i) => ({
3580
+ value: d.value,
3581
+ itemStyle: { color: d.color ?? colors[i % colors.length] }
3582
+ }));
3583
+ const categoryAxis = makeGridAxis("category", textColor, axisLineColor, splitLineColor, isHorizontal ? yLabel : xLabel, labels);
3584
+ const valueAxis = makeGridAxis("value", textColor, axisLineColor, splitLineColor, isHorizontal ? xLabel : yLabel);
3585
+ return {
3586
+ backgroundColor: "transparent",
3587
+ animation: false,
3588
+ title: titleConfig,
3589
+ tooltip: {
3590
+ trigger: "axis",
3591
+ ...tooltipTheme,
3592
+ axisPointer: { type: "shadow" }
3593
+ },
3594
+ grid: {
3595
+ left: "3%",
3596
+ right: "4%",
3597
+ bottom: "3%",
3598
+ top: parsed.title ? "15%" : "5%",
3599
+ containLabel: true
3600
+ },
3601
+ xAxis: isHorizontal ? valueAxis : categoryAxis,
3602
+ yAxis: isHorizontal ? categoryAxis : valueAxis,
3603
+ series: [
3604
+ {
3605
+ type: "bar",
3606
+ data
3607
+ }
3608
+ ]
3609
+ };
3610
+ }
3611
+ function buildLineOption(parsed, palette, textColor, axisLineColor, splitLineColor, titleConfig, tooltipTheme) {
3612
+ const { xLabel, yLabel } = resolveAxisLabels(parsed);
3613
+ const lineColor = parsed.color ?? parsed.seriesNameColors?.[0] ?? palette.primary;
3614
+ const labels = parsed.data.map((d) => d.label);
3615
+ const values = parsed.data.map((d) => d.value);
3616
+ return {
3617
+ backgroundColor: "transparent",
3618
+ animation: false,
3619
+ title: titleConfig,
3620
+ tooltip: {
3621
+ trigger: "axis",
3622
+ ...tooltipTheme,
3623
+ axisPointer: { type: "line" }
3624
+ },
3625
+ grid: {
3626
+ left: "3%",
3627
+ right: "4%",
3628
+ bottom: "3%",
3629
+ top: parsed.title ? "15%" : "5%",
3630
+ containLabel: true
3631
+ },
3632
+ xAxis: makeGridAxis("category", textColor, axisLineColor, splitLineColor, xLabel, labels),
3633
+ yAxis: makeGridAxis("value", textColor, axisLineColor, splitLineColor, yLabel),
3634
+ series: [
3635
+ {
3636
+ type: "line",
3637
+ data: values,
3638
+ smooth: false,
3639
+ symbolSize: 8,
3640
+ lineStyle: { color: lineColor, width: 3 },
3641
+ itemStyle: { color: lineColor }
3642
+ }
3643
+ ]
3644
+ };
3645
+ }
3646
+ function buildMultiLineOption(parsed, textColor, axisLineColor, splitLineColor, colors, titleConfig, tooltipTheme) {
3647
+ const { xLabel, yLabel } = resolveAxisLabels(parsed);
3648
+ const seriesNames = parsed.seriesNames ?? [];
3649
+ const labels = parsed.data.map((d) => d.label);
3650
+ const series = seriesNames.map((name, idx) => {
3651
+ const color = parsed.seriesNameColors?.[idx] ?? colors[idx % colors.length];
3652
+ const data = parsed.data.map(
3653
+ (dp) => idx === 0 ? dp.value : dp.extraValues?.[idx - 1] ?? 0
3654
+ );
3655
+ return {
3656
+ name,
3657
+ type: "line",
3658
+ data,
3659
+ smooth: false,
3660
+ symbolSize: 8,
3661
+ lineStyle: { color, width: 3 },
3662
+ itemStyle: { color }
3663
+ };
3664
+ });
3665
+ return {
3666
+ backgroundColor: "transparent",
3667
+ animation: false,
3668
+ title: titleConfig,
3669
+ tooltip: {
3670
+ trigger: "axis",
3671
+ ...tooltipTheme,
3672
+ axisPointer: { type: "line" }
3673
+ },
3674
+ legend: {
3675
+ data: seriesNames,
3676
+ bottom: 10,
3677
+ textStyle: { color: textColor }
3678
+ },
3679
+ grid: {
3680
+ left: "3%",
3681
+ right: "4%",
3682
+ bottom: "15%",
3683
+ top: parsed.title ? "15%" : "5%",
3684
+ containLabel: true
3685
+ },
3686
+ xAxis: makeGridAxis("category", textColor, axisLineColor, splitLineColor, xLabel, labels),
3687
+ yAxis: makeGridAxis("value", textColor, axisLineColor, splitLineColor, yLabel),
3688
+ series
3689
+ };
3690
+ }
3691
+ function buildAreaOption(parsed, palette, textColor, axisLineColor, splitLineColor, titleConfig, tooltipTheme) {
3692
+ const { xLabel, yLabel } = resolveAxisLabels(parsed);
3693
+ const lineColor = parsed.color ?? parsed.seriesNameColors?.[0] ?? palette.primary;
3694
+ const labels = parsed.data.map((d) => d.label);
3695
+ const values = parsed.data.map((d) => d.value);
3696
+ return {
3697
+ backgroundColor: "transparent",
3698
+ animation: false,
3699
+ title: titleConfig,
3700
+ tooltip: {
3701
+ trigger: "axis",
3702
+ ...tooltipTheme,
3703
+ axisPointer: { type: "line" }
3704
+ },
3705
+ grid: {
3706
+ left: "3%",
3707
+ right: "4%",
3708
+ bottom: "3%",
3709
+ top: parsed.title ? "15%" : "5%",
3710
+ containLabel: true
3711
+ },
3712
+ xAxis: makeGridAxis("category", textColor, axisLineColor, splitLineColor, xLabel, labels),
3713
+ yAxis: makeGridAxis("value", textColor, axisLineColor, splitLineColor, yLabel),
3714
+ series: [
3715
+ {
3716
+ type: "line",
3717
+ data: values,
3718
+ smooth: false,
3719
+ symbolSize: 8,
3720
+ lineStyle: { color: lineColor, width: 3 },
3721
+ itemStyle: { color: lineColor },
3722
+ areaStyle: { opacity: 0.25 }
3723
+ }
3724
+ ]
3725
+ };
3726
+ }
3727
+ function buildPieOption(parsed, textColor, colors, titleConfig, tooltipTheme, isDoughnut) {
3728
+ const data = parsed.data.map((d, i) => ({
3729
+ name: d.label,
3730
+ value: d.value,
3731
+ itemStyle: { color: d.color ?? colors[i % colors.length] }
3732
+ }));
3733
+ return {
3734
+ backgroundColor: "transparent",
3735
+ animation: false,
3736
+ title: titleConfig,
3737
+ tooltip: {
3738
+ trigger: "item",
3739
+ ...tooltipTheme
3740
+ },
3741
+ series: [
3742
+ {
3743
+ type: "pie",
3744
+ radius: isDoughnut ? ["40%", "70%"] : ["0%", "70%"],
3745
+ data,
3746
+ label: {
3747
+ position: "outside",
3748
+ formatter: "{b}",
3749
+ color: textColor,
3750
+ fontFamily: FONT_FAMILY
3751
+ },
3752
+ labelLine: { show: true }
3753
+ }
3754
+ ]
3755
+ };
3756
+ }
3757
+ function buildRadarOption(parsed, palette, textColor, colors, titleConfig, tooltipTheme) {
3758
+ const radarColor = parsed.color ?? parsed.seriesNameColors?.[0] ?? palette.primary;
3759
+ const values = parsed.data.map((d) => d.value);
3760
+ const maxValue = Math.max(...values) * 1.15;
3761
+ const gridOpacity = 0.6;
3762
+ const indicator = parsed.data.map((d) => ({
3763
+ name: d.label,
3764
+ max: maxValue
3765
+ }));
3766
+ return {
3767
+ backgroundColor: "transparent",
3768
+ animation: false,
3769
+ title: titleConfig,
3770
+ tooltip: {
3771
+ trigger: "item",
3772
+ ...tooltipTheme
3773
+ },
3774
+ radar: {
3775
+ indicator,
3776
+ axisName: {
3777
+ color: textColor,
3778
+ fontFamily: FONT_FAMILY
3779
+ },
3780
+ splitLine: {
3781
+ lineStyle: { color: palette.border, opacity: gridOpacity }
3782
+ },
3783
+ axisLine: {
3784
+ lineStyle: { color: palette.border, opacity: gridOpacity }
3785
+ },
3786
+ splitArea: { show: false }
3787
+ },
3788
+ series: [
3789
+ {
3790
+ type: "radar",
3791
+ data: [
3792
+ {
3793
+ value: values,
3794
+ name: parsed.series ?? "Value",
3795
+ areaStyle: { color: radarColor, opacity: 0.25 },
3796
+ lineStyle: { color: radarColor },
3797
+ itemStyle: { color: radarColor },
3798
+ symbol: "circle",
3799
+ symbolSize: 8,
3800
+ label: {
3801
+ show: true,
3802
+ formatter: "{c}",
3803
+ color: textColor,
3804
+ fontSize: 11,
3805
+ fontFamily: FONT_FAMILY
3806
+ }
3807
+ }
3808
+ ]
3809
+ }
3810
+ ]
3811
+ };
3812
+ }
3813
+ function buildPolarAreaOption(parsed, textColor, colors, titleConfig, tooltipTheme) {
3814
+ const data = parsed.data.map((d, i) => ({
3815
+ name: d.label,
3816
+ value: d.value,
3817
+ itemStyle: { color: d.color ?? colors[i % colors.length] }
3818
+ }));
3819
+ return {
3820
+ backgroundColor: "transparent",
3821
+ animation: false,
3822
+ title: titleConfig,
3823
+ tooltip: {
3824
+ trigger: "item",
3825
+ ...tooltipTheme
3826
+ },
3827
+ series: [
3828
+ {
3829
+ type: "pie",
3830
+ roseType: "radius",
3831
+ radius: ["10%", "70%"],
3832
+ data,
3833
+ label: {
3834
+ position: "outside",
3835
+ formatter: "{b}",
3836
+ color: textColor,
3837
+ fontFamily: FONT_FAMILY
3838
+ },
3839
+ labelLine: { show: true }
3840
+ }
3841
+ ]
3842
+ };
3843
+ }
3844
+ function buildBarStackedOption(parsed, textColor, axisLineColor, splitLineColor, colors, titleConfig, tooltipTheme) {
3845
+ const { xLabel, yLabel } = resolveAxisLabels(parsed);
3846
+ const isHorizontal = parsed.orientation === "horizontal";
3847
+ const seriesNames = parsed.seriesNames ?? [];
3848
+ const labels = parsed.data.map((d) => d.label);
3849
+ const series = seriesNames.map((name, idx) => {
3850
+ const color = parsed.seriesNameColors?.[idx] ?? colors[idx % colors.length];
3851
+ const data = parsed.data.map(
3852
+ (dp) => idx === 0 ? dp.value : dp.extraValues?.[idx - 1] ?? 0
3853
+ );
3854
+ return {
3855
+ name,
3856
+ type: "bar",
3857
+ stack: "total",
3858
+ data,
3859
+ itemStyle: { color }
3860
+ };
3861
+ });
3862
+ const categoryAxis = makeGridAxis("category", textColor, axisLineColor, splitLineColor, isHorizontal ? yLabel : xLabel, labels);
3863
+ const valueAxis = makeGridAxis("value", textColor, axisLineColor, splitLineColor, isHorizontal ? xLabel : yLabel);
3864
+ return {
3865
+ backgroundColor: "transparent",
3866
+ animation: false,
3867
+ title: titleConfig,
3868
+ tooltip: {
3869
+ trigger: "axis",
3870
+ ...tooltipTheme,
3871
+ axisPointer: { type: "shadow" }
3872
+ },
3873
+ legend: {
3874
+ data: seriesNames,
3875
+ bottom: 10,
3876
+ textStyle: { color: textColor }
3877
+ },
3878
+ grid: {
3879
+ left: "3%",
3880
+ right: "4%",
3881
+ bottom: "15%",
3882
+ top: parsed.title ? "15%" : "5%",
3883
+ containLabel: true
3884
+ },
3885
+ xAxis: isHorizontal ? valueAxis : categoryAxis,
3886
+ yAxis: isHorizontal ? categoryAxis : valueAxis,
3887
+ series
3888
+ };
3889
+ }
3890
+ var ECHART_EXPORT_WIDTH = 1200;
3891
+ var ECHART_EXPORT_HEIGHT = 800;
3892
+ var STANDARD_CHART_TYPES = /* @__PURE__ */ new Set([
3893
+ "bar",
3894
+ "line",
3895
+ "multi-line",
3896
+ "area",
3897
+ "pie",
3898
+ "doughnut",
3899
+ "radar",
3900
+ "polar-area",
3901
+ "bar-stacked"
3902
+ ]);
3903
+ async function renderEChartsForExport(content, theme, palette) {
3904
+ const isDark = theme === "dark";
3905
+ const { getPalette: getPalette2 } = await Promise.resolve().then(() => (init_palettes(), palettes_exports));
3906
+ const effectivePalette = palette ?? (isDark ? getPalette2("nord").dark : getPalette2("nord").light);
3907
+ const chartLine = content.match(/^chart\s*:\s*(.+)/im);
3908
+ const chartType = chartLine?.[1]?.trim().toLowerCase();
3909
+ let option;
3910
+ if (chartType && STANDARD_CHART_TYPES.has(chartType)) {
3911
+ const parsed = parseChart(content, effectivePalette);
3912
+ if (parsed.error) return "";
3913
+ option = buildEChartsOptionFromChart(parsed, effectivePalette, isDark);
3914
+ } else {
3915
+ const parsed = parseEChart(content, effectivePalette);
3916
+ if (parsed.error) return "";
3917
+ option = buildEChartsOption(parsed, effectivePalette, isDark);
3918
+ }
3919
+ if (!option || Object.keys(option).length === 0) return "";
3920
+ const chart = echarts.init(null, null, {
3921
+ renderer: "svg",
3922
+ ssr: true,
3923
+ width: ECHART_EXPORT_WIDTH,
3924
+ height: ECHART_EXPORT_HEIGHT
3925
+ });
3926
+ try {
3927
+ chart.setOption(option);
3928
+ const svgString = chart.renderToSVGString();
3929
+ if (!svgString) return "";
3930
+ return svgString.replace(
3931
+ /^<svg /,
3932
+ `<svg style="font-family: ${FONT_FAMILY}" `
3933
+ );
3934
+ } finally {
3935
+ chart.dispose();
3936
+ }
3937
+ }
3962
3938
 
3963
3939
  // src/d3.ts
3964
3940
  init_fonts();
@@ -6753,8 +6729,8 @@ export {
6753
6729
  applyGroupOrdering,
6754
6730
  applyPositionOverrides,
6755
6731
  boldPalette,
6756
- buildChartJsConfig,
6757
6732
  buildEChartsOption,
6733
+ buildEChartsOptionFromChart,
6758
6734
  buildMermaidQuadrant,
6759
6735
  buildMermaidThemeVars,
6760
6736
  buildRenderSequence,
@@ -6783,7 +6759,7 @@ export {
6783
6759
  nordPalette,
6784
6760
  oneDarkPalette,
6785
6761
  orderArcNodes,
6786
- parseChartJs,
6762
+ parseChart,
6787
6763
  parseD3,
6788
6764
  parseDgmoChartType,
6789
6765
  parseEChart,
@@ -6793,6 +6769,7 @@ export {
6793
6769
  registerPalette,
6794
6770
  renderArcDiagram,
6795
6771
  renderD3ForExport,
6772
+ renderEChartsForExport,
6796
6773
  renderQuadrant,
6797
6774
  renderSequenceDiagram,
6798
6775
  renderSlopeChart,