@markdy/renderer-dom 1.0.18 → 1.0.19
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/README.md +10 -10
- package/dist/index.d.ts +2 -2
- package/dist/index.js +152 -156
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ Web Animations API renderer for [MarkdyScript](../../docs/SYNTAX.md) scenes. Tra
|
|
|
13
13
|
- **Seek-safe** — manual `currentTime` control enables reliable `seek()` in any direction
|
|
14
14
|
- **Playback-rate controls** — set normalized timeline speed to slow down or speed up diagrams without rebuilding animations
|
|
15
15
|
- **Interactive viewport** — opt into wheel zoom and drag pan while click-to-pause stays available
|
|
16
|
-
- **Embed controls** — opt into
|
|
16
|
+
- **Embed controls** — opt into only the playback, timeline, viewport, export, and sharing controls a scene needs
|
|
17
17
|
- **Semantic themes** — `paper`, `editorial`, `nebula`, `midnight`, `blueprint`, and `graphite`, with per-role node and edge colors
|
|
18
18
|
- **Single dependency** — only `@markdy/core`
|
|
19
19
|
|
|
@@ -70,21 +70,21 @@ diagram.destroy(); // clean up DOM + cancel animations
|
|
|
70
70
|
|---|---|---|---|
|
|
71
71
|
| `container` | `HTMLElement` | *(required)* | DOM element to mount the scene into |
|
|
72
72
|
| `code` | `string` | *(required)* | MarkdyScript source code |
|
|
73
|
-
| `autoplay` | `boolean` | `
|
|
74
|
-
| `loop` | `boolean` | `
|
|
75
|
-
| `copyright` | `boolean` | `
|
|
73
|
+
| `autoplay` | `boolean` | `player.playback.autoplay ?? true` | Override whether playback starts immediately |
|
|
74
|
+
| `loop` | `boolean` | `player.playback.loop ?? true` | Override whether playback loops at the end |
|
|
75
|
+
| `copyright` | `boolean` | `player.chrome.badge ?? true` | Show the linked badge at the footer's right edge |
|
|
76
76
|
| `progressBar` | `boolean \| string` | `true` | Deprecated compatibility flag for the scene-boundary progress bar |
|
|
77
|
-
| `sceneBoundaryProgress` | `boolean \| string` | `
|
|
78
|
-
| `progressColor` | `string` | `
|
|
79
|
-
| `playbackRate` | `number` | `
|
|
80
|
-
| `interactiveViewport` | `boolean` | `
|
|
81
|
-
| `controls` | `boolean` | `player.controls` |
|
|
77
|
+
| `sceneBoundaryProgress` | `boolean \| string` | `player.chrome.progress` | Override boundary progress, or pass a custom color/gradient |
|
|
78
|
+
| `progressColor` | `string` | `player.chrome.color` or rainbow | Override the progress color or gradient |
|
|
79
|
+
| `playbackRate` | `number` | `player.playback.rate ?? 1` | Override the initial timeline multiplier |
|
|
80
|
+
| `interactiveViewport` | `boolean` | `player.interaction` | `true` supplies default gestures; `false` suppresses script gestures |
|
|
81
|
+
| `controls` | `boolean` | `player.controls` | `true` supplies legacy toolbar defaults; `false` suppresses script controls |
|
|
82
82
|
| `shareUrl` | `string` | Markdy playground | Base URL used by the Share control when building `#code=` links |
|
|
83
83
|
| `onWarning` | `(warning: Diagnostic) => void` | `console.warn` | Called for each soft parse warning |
|
|
84
84
|
| `onTimeUpdate` | `(seconds: number, durationSeconds: number) => void` | — | Called whenever playback or seek changes the current time |
|
|
85
85
|
| `onPlayStateChange` | `(playing: boolean) => void` | — | Called when playback starts or pauses |
|
|
86
86
|
|
|
87
|
-
> **Note:**
|
|
87
|
+
> **Note:** Prefer grouped `player:` configuration in MarkdyScript. Omitted host options preserve it; host `false` suppresses controls or interaction, while host `true` supplies legacy defaults for leaves the script does not set. A speed selector renders only with at least two distinct positive `speeds` values.
|
|
88
88
|
|
|
89
89
|
### `Diagram`
|
|
90
90
|
|
package/dist/index.d.ts
CHANGED
|
@@ -26,11 +26,11 @@ interface DiagramOptions {
|
|
|
26
26
|
progressBarColor?: string;
|
|
27
27
|
/** Playback speed multiplier. Defaults to 1, where 1 is Markdy's normal pace. */
|
|
28
28
|
playbackRate?: number;
|
|
29
|
-
/**
|
|
29
|
+
/** Host interaction override. `true` enables default gestures; `false` suppresses script interaction. */
|
|
30
30
|
interactiveViewport?: boolean;
|
|
31
31
|
/** Base URL for the Share control. Defaults to the Markdy playground. */
|
|
32
32
|
shareUrl?: string;
|
|
33
|
-
/**
|
|
33
|
+
/** Host controls override. `true` enables the legacy default set; `false` suppresses script controls. */
|
|
34
34
|
controls?: boolean;
|
|
35
35
|
onWarning?: (warning: Diagnostic) => void;
|
|
36
36
|
onTimeUpdate?: (seconds: number, durationSeconds: number) => void;
|
package/dist/index.js
CHANGED
|
@@ -2511,6 +2511,7 @@ function ensureSceneStyles(doc) {
|
|
|
2511
2511
|
justify-content: space-between;
|
|
2512
2512
|
gap: 8px;
|
|
2513
2513
|
padding: 6px 12px;
|
|
2514
|
+
color: var(--md-text, #f8fafc);
|
|
2514
2515
|
background: var(--md-footer-bg, rgba(15, 23, 42, 0.85));
|
|
2515
2516
|
backdrop-filter: blur(16px);
|
|
2516
2517
|
-webkit-backdrop-filter: blur(16px);
|
|
@@ -2521,7 +2522,9 @@ function ensureSceneStyles(doc) {
|
|
|
2521
2522
|
display: flex;
|
|
2522
2523
|
align-items: center;
|
|
2523
2524
|
justify-content: flex-start;
|
|
2524
|
-
|
|
2525
|
+
flex: 1 1 auto;
|
|
2526
|
+
width: auto;
|
|
2527
|
+
min-width: 0;
|
|
2525
2528
|
gap: 8px;
|
|
2526
2529
|
max-width: 100%;
|
|
2527
2530
|
overflow-x: auto;
|
|
@@ -2555,7 +2558,6 @@ function ensureSceneStyles(doc) {
|
|
|
2555
2558
|
align-items: center;
|
|
2556
2559
|
gap: 4px;
|
|
2557
2560
|
flex-shrink: 0;
|
|
2558
|
-
margin-left: auto;
|
|
2559
2561
|
}
|
|
2560
2562
|
.markdy-control-divider {
|
|
2561
2563
|
width: 1px;
|
|
@@ -2626,37 +2628,24 @@ function ensureSceneStyles(doc) {
|
|
|
2626
2628
|
transform: translateY(-1px) scale(1.02);
|
|
2627
2629
|
}
|
|
2628
2630
|
.markdy-badge {
|
|
2629
|
-
position: absolute;
|
|
2630
|
-
top: 10px;
|
|
2631
|
-
right: 12px;
|
|
2632
|
-
z-index: 25;
|
|
2633
2631
|
display: inline-flex;
|
|
2634
2632
|
align-items: center;
|
|
2635
|
-
|
|
2636
|
-
font-family:
|
|
2633
|
+
text-align: right;
|
|
2634
|
+
font-family: system-ui, sans-serif;
|
|
2637
2635
|
font-size: 10px;
|
|
2638
|
-
font-weight:
|
|
2639
|
-
|
|
2640
|
-
color: var(--md-text-muted, #94a3b8);
|
|
2636
|
+
font-weight: 400;
|
|
2637
|
+
color: var(--md-control-text, #94a3b8);
|
|
2641
2638
|
text-decoration: none;
|
|
2642
|
-
padding:
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
-
|
|
2648
|
-
opacity: 0.65;
|
|
2649
|
-
transition: all 0.2s ease;
|
|
2650
|
-
pointer-events: auto;
|
|
2651
|
-
user-select: none;
|
|
2639
|
+
padding: 0;
|
|
2640
|
+
opacity: 0.7;
|
|
2641
|
+
margin-left: auto;
|
|
2642
|
+
flex-shrink: 0;
|
|
2643
|
+
transition: opacity 0.15s ease, color 0.15s ease;
|
|
2644
|
+
white-space: nowrap;
|
|
2652
2645
|
}
|
|
2653
2646
|
.markdy-badge:hover {
|
|
2654
2647
|
opacity: 1;
|
|
2655
|
-
color: var(--
|
|
2656
|
-
border-color: var(--accent, #10b981);
|
|
2657
|
-
background: var(--md-surface-raised, rgba(15, 23, 42, 0.75));
|
|
2658
|
-
transform: translateY(-1px);
|
|
2659
|
-
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
|
|
2648
|
+
color: var(--md-text, #f8fafc);
|
|
2660
2649
|
}
|
|
2661
2650
|
.markdy-speed-group {
|
|
2662
2651
|
display: inline-flex;
|
|
@@ -2689,57 +2678,6 @@ function ensureSceneStyles(doc) {
|
|
|
2689
2678
|
color: #ffffff !important;
|
|
2690
2679
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25) !important;
|
|
2691
2680
|
}
|
|
2692
|
-
.markdy-control-seek {
|
|
2693
|
-
appearance: none;
|
|
2694
|
-
-webkit-appearance: none;
|
|
2695
|
-
width: 100%;
|
|
2696
|
-
height: 5px;
|
|
2697
|
-
border-radius: 999px;
|
|
2698
|
-
background: linear-gradient(
|
|
2699
|
-
to right,
|
|
2700
|
-
var(--accent, #10b981) 0%,
|
|
2701
|
-
var(--accent, #10b981) var(--seek-pct, 0%),
|
|
2702
|
-
rgba(148, 163, 184, 0.22) var(--seek-pct, 0%),
|
|
2703
|
-
rgba(148, 163, 184, 0.22) 100%
|
|
2704
|
-
);
|
|
2705
|
-
outline: none;
|
|
2706
|
-
cursor: pointer;
|
|
2707
|
-
margin: 0;
|
|
2708
|
-
transition: height 0.15s ease;
|
|
2709
|
-
}
|
|
2710
|
-
.markdy-control-seek:hover {
|
|
2711
|
-
height: 7px;
|
|
2712
|
-
}
|
|
2713
|
-
.markdy-control-seek::-webkit-slider-thumb {
|
|
2714
|
-
appearance: none;
|
|
2715
|
-
-webkit-appearance: none;
|
|
2716
|
-
width: 12px;
|
|
2717
|
-
height: 12px;
|
|
2718
|
-
border-radius: 50%;
|
|
2719
|
-
background: #ffffff;
|
|
2720
|
-
border: 2px solid var(--accent, #10b981);
|
|
2721
|
-
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
|
|
2722
|
-
cursor: pointer;
|
|
2723
|
-
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
|
2724
|
-
}
|
|
2725
|
-
.markdy-control-seek:hover::-webkit-slider-thumb {
|
|
2726
|
-
transform: scale(1.25);
|
|
2727
|
-
box-shadow: 0 0 8px var(--accent-glow, rgba(16, 185, 129, 0.6));
|
|
2728
|
-
}
|
|
2729
|
-
.markdy-control-seek::-moz-range-thumb {
|
|
2730
|
-
width: 12px;
|
|
2731
|
-
height: 12px;
|
|
2732
|
-
border-radius: 50%;
|
|
2733
|
-
background: #ffffff;
|
|
2734
|
-
border: 2px solid var(--accent, #10b981);
|
|
2735
|
-
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
|
|
2736
|
-
cursor: pointer;
|
|
2737
|
-
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
|
2738
|
-
}
|
|
2739
|
-
.markdy-control-seek:hover::-moz-range-thumb {
|
|
2740
|
-
transform: scale(1.25);
|
|
2741
|
-
box-shadow: 0 0 8px var(--accent-glow, rgba(16, 185, 129, 0.6));
|
|
2742
|
-
}
|
|
2743
2681
|
.markdy-control-time {
|
|
2744
2682
|
font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
2745
2683
|
font-size: 10px;
|
|
@@ -2925,44 +2863,61 @@ function ensureSceneStyles(doc) {
|
|
|
2925
2863
|
.markdy-control-seek::-webkit-slider-runnable-track {
|
|
2926
2864
|
width: 100%;
|
|
2927
2865
|
height: 4.5px;
|
|
2928
|
-
background:
|
|
2866
|
+
background: linear-gradient(
|
|
2867
|
+
to right,
|
|
2868
|
+
var(--accent, #10b981) 0%,
|
|
2869
|
+
var(--accent, #10b981) var(--seek-pct, 0%),
|
|
2870
|
+
rgba(148, 163, 184, 0.35) var(--seek-pct, 0%),
|
|
2871
|
+
rgba(148, 163, 184, 0.35) 100%
|
|
2872
|
+
);
|
|
2929
2873
|
border-radius: 9999px;
|
|
2930
|
-
transition: background 0.15s ease;
|
|
2931
|
-
}
|
|
2932
|
-
.markdy-control-seek:hover::-webkit-slider-runnable-track {
|
|
2933
|
-
background: rgba(148, 163, 184, 0.55);
|
|
2934
2874
|
}
|
|
2935
2875
|
.markdy-control-seek::-webkit-slider-thumb {
|
|
2876
|
+
appearance: none;
|
|
2936
2877
|
-webkit-appearance: none;
|
|
2937
2878
|
height: 13px;
|
|
2938
2879
|
width: 13px;
|
|
2939
2880
|
border-radius: 50%;
|
|
2940
|
-
background: #
|
|
2881
|
+
background: var(--accent, #10b981);
|
|
2941
2882
|
border: 2px solid #ffffff;
|
|
2942
2883
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
|
2943
2884
|
margin-top: -4.25px;
|
|
2944
2885
|
cursor: grab;
|
|
2945
|
-
transition: transform 0.1s ease,
|
|
2886
|
+
transition: transform 0.1s ease, box-shadow 0.15s ease;
|
|
2887
|
+
}
|
|
2888
|
+
.markdy-control-seek:hover::-webkit-slider-thumb {
|
|
2889
|
+
transform: scale(1.2);
|
|
2890
|
+
box-shadow: 0 0 8px var(--accent-glow, rgba(16, 185, 129, 0.6));
|
|
2946
2891
|
}
|
|
2947
2892
|
.markdy-control-seek:active::-webkit-slider-thumb {
|
|
2948
2893
|
cursor: grabbing;
|
|
2949
2894
|
transform: scale(1.2);
|
|
2950
|
-
background: #1d4ed8;
|
|
2951
2895
|
}
|
|
2952
2896
|
.markdy-control-seek::-moz-range-track {
|
|
2953
2897
|
width: 100%;
|
|
2954
2898
|
height: 4.5px;
|
|
2955
|
-
background:
|
|
2899
|
+
background: linear-gradient(
|
|
2900
|
+
to right,
|
|
2901
|
+
var(--accent, #10b981) 0%,
|
|
2902
|
+
var(--accent, #10b981) var(--seek-pct, 0%),
|
|
2903
|
+
rgba(148, 163, 184, 0.35) var(--seek-pct, 0%),
|
|
2904
|
+
rgba(148, 163, 184, 0.35) 100%
|
|
2905
|
+
);
|
|
2956
2906
|
border-radius: 9999px;
|
|
2957
2907
|
}
|
|
2958
2908
|
.markdy-control-seek::-moz-range-thumb {
|
|
2959
2909
|
height: 13px;
|
|
2960
2910
|
width: 13px;
|
|
2961
2911
|
border-radius: 50%;
|
|
2962
|
-
background: #
|
|
2912
|
+
background: var(--accent, #10b981);
|
|
2963
2913
|
border: 2px solid #ffffff;
|
|
2964
2914
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
|
2965
2915
|
cursor: grab;
|
|
2916
|
+
transition: transform 0.1s ease, box-shadow 0.15s ease;
|
|
2917
|
+
}
|
|
2918
|
+
.markdy-control-seek:hover::-moz-range-thumb {
|
|
2919
|
+
transform: scale(1.2);
|
|
2920
|
+
box-shadow: 0 0 8px var(--accent-glow, rgba(16, 185, 129, 0.6));
|
|
2966
2921
|
}
|
|
2967
2922
|
|
|
2968
2923
|
[data-markdy-theme="midnight"] .markdy-controls button,
|
|
@@ -2983,9 +2938,9 @@ function ensureSceneStyles(doc) {
|
|
|
2983
2938
|
[data-markdy-theme="nebula"] .markdy-controls button:hover:not([aria-pressed="true"]),
|
|
2984
2939
|
:root[data-theme="dark"] .markdy-controls button:hover:not([aria-pressed="true"]),
|
|
2985
2940
|
.theme-dark .markdy-controls button:hover:not([aria-pressed="true"]) {
|
|
2986
|
-
background: rgba(51, 65, 85, 0.95);
|
|
2987
|
-
color: #f8fafc;
|
|
2988
|
-
border-color: #94a3b8;
|
|
2941
|
+
background: var(--md-control-hover-bg, rgba(51, 65, 85, 0.95));
|
|
2942
|
+
color: var(--md-control-hover-text, #f8fafc);
|
|
2943
|
+
border-color: var(--md-control-hover-border, #94a3b8);
|
|
2989
2944
|
}
|
|
2990
2945
|
[data-markdy-theme="midnight"] .markdy-controls button[aria-pressed="true"],
|
|
2991
2946
|
[data-markdy-theme="blueprint"] .markdy-controls button[aria-pressed="true"],
|
|
@@ -2994,10 +2949,10 @@ function ensureSceneStyles(doc) {
|
|
|
2994
2949
|
[data-markdy-theme="nebula"] .markdy-controls button[aria-pressed="true"],
|
|
2995
2950
|
:root[data-theme="dark"] .markdy-controls button[aria-pressed="true"],
|
|
2996
2951
|
.theme-dark .markdy-controls button[aria-pressed="true"] {
|
|
2997
|
-
background: #3b82f6 !important;
|
|
2952
|
+
background: var(--accent, #3b82f6) !important;
|
|
2998
2953
|
color: #ffffff !important;
|
|
2999
|
-
border-color: #3b82f6 !important;
|
|
3000
|
-
box-shadow: 0 0 10px rgba(59, 130, 246, 0.5) !important;
|
|
2954
|
+
border-color: var(--accent, #3b82f6) !important;
|
|
2955
|
+
box-shadow: 0 0 10px var(--accent-glow, rgba(59, 130, 246, 0.5)) !important;
|
|
3001
2956
|
}
|
|
3002
2957
|
.markdy-footer a {
|
|
3003
2958
|
transition: opacity 0.15s ease, color 0.15s ease;
|
|
@@ -3091,41 +3046,56 @@ function ensureSceneStyles(doc) {
|
|
|
3091
3046
|
`;
|
|
3092
3047
|
doc.head.appendChild(style);
|
|
3093
3048
|
}
|
|
3094
|
-
function
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
if (theme.
|
|
3113
|
-
if (theme.
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3049
|
+
function applyThemeVariables(element, theme) {
|
|
3050
|
+
element.style.setProperty("--md-canvas", theme.canvas);
|
|
3051
|
+
element.style.setProperty("--md-surface", theme.surface);
|
|
3052
|
+
element.style.setProperty("--md-surface-raised", theme.surfaceRaised);
|
|
3053
|
+
element.style.setProperty("--md-border", theme.border);
|
|
3054
|
+
element.style.setProperty("--md-text", theme.text);
|
|
3055
|
+
element.style.setProperty("--md-text-muted", theme.textMuted);
|
|
3056
|
+
element.style.setProperty("--md-paper", theme.paper ?? theme.canvas);
|
|
3057
|
+
element.style.setProperty("--md-ink", theme.ink ?? theme.text);
|
|
3058
|
+
element.style.setProperty("--md-muted", theme.muted ?? theme.textMuted);
|
|
3059
|
+
element.style.setProperty("--md-rule", theme.rule ?? theme.border);
|
|
3060
|
+
element.style.setProperty("--md-grid-minor", theme.gridMinor);
|
|
3061
|
+
element.style.setProperty("--md-grid-major", theme.gridMajor);
|
|
3062
|
+
element.style.setProperty("--md-vignette", theme.vignette);
|
|
3063
|
+
element.style.setProperty("--md-accent", theme.accent);
|
|
3064
|
+
element.style.setProperty("--accent", theme.accent);
|
|
3065
|
+
element.style.setProperty("--accent-glow", `color-mix(in srgb, ${theme.accent} 40%, transparent)`);
|
|
3066
|
+
element.style.setProperty("--accent-light", theme.accentTint ?? `color-mix(in srgb, ${theme.accent} 15%, transparent)`);
|
|
3067
|
+
if (theme.link) element.style.setProperty("--md-link", theme.link);
|
|
3068
|
+
if (theme.soft) element.style.setProperty("--md-soft", theme.soft);
|
|
3069
|
+
if (theme.accentTint) element.style.setProperty("--md-accent-tint", theme.accentTint);
|
|
3070
|
+
element.style.setProperty("--md-node-surface", theme.nodeSurface ?? theme.surface);
|
|
3071
|
+
element.style.setProperty("--md-node-surface-raised", theme.nodeSurfaceRaised ?? theme.surfaceRaised);
|
|
3072
|
+
element.style.setProperty("--md-hairline", theme.hairline ?? `color-mix(in srgb, ${theme.border} 50%, transparent)`);
|
|
3073
|
+
element.style.setProperty("--md-shadow", theme.shadow ?? "rgba(2, 6, 23, 0.55)");
|
|
3074
|
+
element.style.setProperty("--md-footer-bg", `color-mix(in srgb, ${theme.surface} 92%, transparent)`);
|
|
3075
|
+
element.style.setProperty("--md-footer-border", theme.border);
|
|
3076
|
+
element.style.setProperty("--md-control-bg", theme.surfaceRaised);
|
|
3077
|
+
element.style.setProperty("--md-control-border", theme.border);
|
|
3078
|
+
element.style.setProperty("--md-control-text", theme.textMuted);
|
|
3079
|
+
element.style.setProperty("--md-control-hover-bg", theme.canvas);
|
|
3080
|
+
element.style.setProperty("--md-control-hover-text", theme.text);
|
|
3081
|
+
element.style.setProperty("--md-control-hover-border", theme.accent);
|
|
3082
|
+
element.style.setProperty("--md-divider", theme.border);
|
|
3083
|
+
if (theme.fonts?.title) element.style.setProperty("--md-font-title", theme.fonts.title);
|
|
3084
|
+
if (theme.fonts?.nodeName) element.style.setProperty("--md-font-node", theme.fonts.nodeName);
|
|
3085
|
+
if (theme.fonts?.mono) element.style.setProperty("--md-font-mono", theme.fonts.mono);
|
|
3086
|
+
if (theme.radiusMd) element.style.setProperty("--md-radius-md", `${theme.radiusMd}px`);
|
|
3122
3087
|
if (theme.spacing) {
|
|
3123
3088
|
for (const [key, value] of Object.entries(theme.spacing)) {
|
|
3124
|
-
|
|
3089
|
+
element.style.setProperty(`--md-space-${key}`, `${value}px`);
|
|
3125
3090
|
}
|
|
3126
3091
|
}
|
|
3127
|
-
|
|
3128
|
-
if (theme.flatCards)
|
|
3092
|
+
element.dataset.markdyTheme = theme.name;
|
|
3093
|
+
if (theme.flatCards) element.dataset.flat = "1";
|
|
3094
|
+
}
|
|
3095
|
+
function applyThemeToScene(scene, theme) {
|
|
3096
|
+
applyThemeVariables(scene, theme);
|
|
3097
|
+
scene.style.background = theme.canvas;
|
|
3098
|
+
scene.style.color = theme.text;
|
|
3129
3099
|
}
|
|
3130
3100
|
|
|
3131
3101
|
// src/diagram.ts
|
|
@@ -3296,11 +3266,12 @@ function createDiagram(opts) {
|
|
|
3296
3266
|
if (footer) return footer;
|
|
3297
3267
|
footer = document.createElement("div");
|
|
3298
3268
|
footer.className = "markdy-footer";
|
|
3269
|
+
applyThemeVariables(footer, plan.theme);
|
|
3299
3270
|
Object.assign(footer.style, {
|
|
3300
3271
|
display: "flex",
|
|
3301
3272
|
alignItems: "center",
|
|
3302
3273
|
justifyContent: "space-between",
|
|
3303
|
-
flexWrap: "
|
|
3274
|
+
flexWrap: "nowrap",
|
|
3304
3275
|
gap: "6px",
|
|
3305
3276
|
width: "100%",
|
|
3306
3277
|
boxSizing: "border-box",
|
|
@@ -3310,6 +3281,21 @@ function createDiagram(opts) {
|
|
|
3310
3281
|
else container.appendChild(footer);
|
|
3311
3282
|
return footer;
|
|
3312
3283
|
}
|
|
3284
|
+
let badge = null;
|
|
3285
|
+
if (copyright) {
|
|
3286
|
+
badge = document.createElement("a");
|
|
3287
|
+
badge.className = "markdy-badge";
|
|
3288
|
+
badge.href = `${MARKDY_PLAYGROUND_URL}#code=${encodeCodeForPlaygroundHash(code)}`;
|
|
3289
|
+
badge.target = "_blank";
|
|
3290
|
+
badge.rel = "noopener noreferrer";
|
|
3291
|
+
badge.title = "Open and edit in Markdy Playground";
|
|
3292
|
+
badge.textContent = "Powered by Markdy";
|
|
3293
|
+
ensureFooter().appendChild(badge);
|
|
3294
|
+
const badgeLink = badge;
|
|
3295
|
+
void compressMarkdyToUrlHash(code).then((hash) => {
|
|
3296
|
+
badgeLink.href = `${MARKDY_PLAYGROUND_URL}#code=${hash}`;
|
|
3297
|
+
}).catch(() => void 0);
|
|
3298
|
+
}
|
|
3313
3299
|
ensureSceneStyles(document);
|
|
3314
3300
|
ensureNodeStyles(document);
|
|
3315
3301
|
const scene = document.createElement("div");
|
|
@@ -3326,17 +3312,6 @@ function createDiagram(opts) {
|
|
|
3326
3312
|
});
|
|
3327
3313
|
applyThemeToScene(scene, plan.theme);
|
|
3328
3314
|
viewport.appendChild(scene);
|
|
3329
|
-
let badge = null;
|
|
3330
|
-
if (copyright) {
|
|
3331
|
-
badge = document.createElement("a");
|
|
3332
|
-
badge.className = "markdy-badge";
|
|
3333
|
-
badge.href = "https://markdy.com";
|
|
3334
|
-
badge.target = "_blank";
|
|
3335
|
-
badge.rel = "noopener noreferrer";
|
|
3336
|
-
badge.title = "Powered by Markdy - Diagram as Code";
|
|
3337
|
-
badge.textContent = "Powered by Markdy";
|
|
3338
|
-
viewport.appendChild(badge);
|
|
3339
|
-
}
|
|
3340
3315
|
const viewportTransform = document.createElement("div");
|
|
3341
3316
|
viewportTransform.className = "markdy-viewport-transform";
|
|
3342
3317
|
Object.assign(viewportTransform.style, {
|
|
@@ -3548,6 +3523,7 @@ function createDiagram(opts) {
|
|
|
3548
3523
|
let controlsSeekBar = null;
|
|
3549
3524
|
let controlsTimeEl = null;
|
|
3550
3525
|
let controlsFitButton = null;
|
|
3526
|
+
let closeCodePanel = null;
|
|
3551
3527
|
let fitViewActive = false;
|
|
3552
3528
|
const ICONS2 = {
|
|
3553
3529
|
play: '<svg class="markdy-icon" width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>',
|
|
@@ -3767,8 +3743,9 @@ function createDiagram(opts) {
|
|
|
3767
3743
|
for (const anim of allAnims) anim.cancel();
|
|
3768
3744
|
resizeObserver?.disconnect();
|
|
3769
3745
|
removeFullscreenListeners?.();
|
|
3746
|
+
closeCodePanel?.();
|
|
3747
|
+
closeCodePanel = null;
|
|
3770
3748
|
if (progressEl?.parentNode === viewport) viewport.removeChild(progressEl);
|
|
3771
|
-
if (badge?.parentNode) badge.parentNode.removeChild(badge);
|
|
3772
3749
|
if (footer?.parentNode) footer.parentNode.removeChild(footer);
|
|
3773
3750
|
if (viewport.parentNode === container) container.removeChild(viewport);
|
|
3774
3751
|
}
|
|
@@ -3935,19 +3912,33 @@ function createDiagram(opts) {
|
|
|
3935
3912
|
}
|
|
3936
3913
|
function tintCode(raw) {
|
|
3937
3914
|
return raw.split("\n").map((line) => {
|
|
3938
|
-
if (/^\s*\/\//.test(line)) {
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
line = line.replace(/(->|<-|~>|--|<~)/g, '<span class="t-edge">$1</span>');
|
|
3942
|
-
line = line.replace(/"([^"]*)"/g, '"<span class="t-string">$1</span>"');
|
|
3943
|
-
line = line.replace(
|
|
3944
|
-
/^(\s*)(scene|beat|group|player|show|frame|glow|focus|layout|edge|annotation|start|end|decision|service|browser|gateway|database|cache|queue|worker|function|pod|user|client|hub|station|metric|mobile)\b/,
|
|
3945
|
-
'$1<span class="t-keyword">$2</span>'
|
|
3915
|
+
if (/^\s*\/\//.test(line)) return `<span class="t-comment">${escHtml(line)}</span>`;
|
|
3916
|
+
const keyword = line.match(
|
|
3917
|
+
/^(\s*)(scene|beat|group|player|show|frame|glow|focus|layout|edge|annotation|start|end|decision|service|browser|gateway|database|cache|queue|worker|function|pod|user|client|hub|station|metric|mobile)\b/
|
|
3946
3918
|
);
|
|
3947
|
-
|
|
3948
|
-
return line;
|
|
3919
|
+
const prefix = keyword ? `${escHtml(keyword[1])}<span class="t-keyword">${keyword[2]}</span>` : "";
|
|
3920
|
+
return prefix + tintInlineCode(line.slice(keyword?.[0].length ?? 0));
|
|
3949
3921
|
}).join("\n");
|
|
3950
3922
|
}
|
|
3923
|
+
function tintInlineCode(raw) {
|
|
3924
|
+
const tokenPattern = /"[^"]*"|->|<-|~>|--|<~|\b\d[\d.]*(?:ms|px|s)?\b/g;
|
|
3925
|
+
let output = "";
|
|
3926
|
+
let cursor = 0;
|
|
3927
|
+
for (const match of raw.matchAll(tokenPattern)) {
|
|
3928
|
+
const token = match[0];
|
|
3929
|
+
const index = match.index ?? 0;
|
|
3930
|
+
output += escHtml(raw.slice(cursor, index));
|
|
3931
|
+
if (token.startsWith('"')) {
|
|
3932
|
+
output += `"<span class="t-string">${escHtml(token.slice(1, -1))}</span>"`;
|
|
3933
|
+
} else if (/^\d/.test(token)) {
|
|
3934
|
+
output += `<span class="t-number">${token}</span>`;
|
|
3935
|
+
} else {
|
|
3936
|
+
output += `<span class="t-edge">${escHtml(token)}</span>`;
|
|
3937
|
+
}
|
|
3938
|
+
cursor = index + token.length;
|
|
3939
|
+
}
|
|
3940
|
+
return output + escHtml(raw.slice(cursor));
|
|
3941
|
+
}
|
|
3951
3942
|
function escHtml(str) {
|
|
3952
3943
|
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
3953
3944
|
}
|
|
@@ -3957,6 +3948,7 @@ function createDiagram(opts) {
|
|
|
3957
3948
|
button.className = "markdy-control-code";
|
|
3958
3949
|
button.setAttribute("aria-haspopup", "dialog");
|
|
3959
3950
|
button.addEventListener("click", () => {
|
|
3951
|
+
closeCodePanel?.();
|
|
3960
3952
|
const overlay = document.createElement("div");
|
|
3961
3953
|
overlay.className = "markdy-code-panel-overlay";
|
|
3962
3954
|
overlay.setAttribute("role", "dialog");
|
|
@@ -4014,24 +4006,28 @@ function createDiagram(opts) {
|
|
|
4014
4006
|
overlay.appendChild(panel);
|
|
4015
4007
|
document.body.appendChild(overlay);
|
|
4016
4008
|
closeBtn.focus();
|
|
4009
|
+
let closing = false;
|
|
4010
|
+
function removePanel() {
|
|
4011
|
+
document.removeEventListener("keydown", handleEscape);
|
|
4012
|
+
overlay.remove();
|
|
4013
|
+
if (closeCodePanel === removePanel) closeCodePanel = null;
|
|
4014
|
+
}
|
|
4017
4015
|
function closePanel() {
|
|
4016
|
+
if (closing) return;
|
|
4017
|
+
closing = true;
|
|
4018
4018
|
overlay.dataset.closing = "1";
|
|
4019
|
-
|
|
4019
|
+
document.removeEventListener("keydown", handleEscape);
|
|
4020
|
+
overlay.addEventListener("animationend", removePanel, { once: true });
|
|
4020
4021
|
}
|
|
4021
4022
|
closeBtn.addEventListener("click", closePanel);
|
|
4022
4023
|
overlay.addEventListener("click", (e) => {
|
|
4023
4024
|
if (e.target === overlay) closePanel();
|
|
4024
4025
|
});
|
|
4025
4026
|
function handleEscape(e) {
|
|
4026
|
-
if (e.key === "Escape")
|
|
4027
|
-
closePanel();
|
|
4028
|
-
document.removeEventListener("keydown", handleEscape);
|
|
4029
|
-
}
|
|
4027
|
+
if (e.key === "Escape") closePanel();
|
|
4030
4028
|
}
|
|
4031
4029
|
document.addEventListener("keydown", handleEscape);
|
|
4032
|
-
|
|
4033
|
-
if (overlay.dataset.closing === "1") document.removeEventListener("keydown", handleEscape);
|
|
4034
|
-
}, { once: true });
|
|
4030
|
+
closeCodePanel = removePanel;
|
|
4035
4031
|
});
|
|
4036
4032
|
toolbar.appendChild(button);
|
|
4037
4033
|
}
|
|
@@ -4238,7 +4234,7 @@ function createDiagram(opts) {
|
|
|
4238
4234
|
mountCodeControl(toolsGroup);
|
|
4239
4235
|
}
|
|
4240
4236
|
if (toolsGroup.children.length > 0) toolbar.appendChild(toolsGroup);
|
|
4241
|
-
ensureFooter().
|
|
4237
|
+
ensureFooter().insertBefore(toolbar, badge);
|
|
4242
4238
|
syncControls();
|
|
4243
4239
|
}
|
|
4244
4240
|
viewport.style.cursor = interactiveViewport ? "grab" : "pointer";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markdy/renderer-dom",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.19",
|
|
4
4
|
"description": "Browser renderer for diagram-native animated MarkdyScript architecture diagrams, built on the Web Animations API.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -45,14 +45,14 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"html2canvas": "^1.4.1",
|
|
48
|
-
"@markdy/core": "1.0.
|
|
48
|
+
"@markdy/core": "1.0.19"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"jsdom": "^29.1.1",
|
|
52
52
|
"tsup": "^8.5.1",
|
|
53
53
|
"typescript": "^5.9.3",
|
|
54
54
|
"vitest": "^4.1.7",
|
|
55
|
-
"@markdy/stdlib-systems": "1.0.
|
|
55
|
+
"@markdy/stdlib-systems": "1.0.19"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "tsup",
|