sketchmark 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +187 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +187 -10
- package/dist/index.js.map +1 -1
- package/dist/sketchmark.iife.js +187 -10
- package/dist/ui/editor.d.ts +4 -0
- package/dist/ui/editor.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -10567,13 +10567,13 @@ function exportHTML(svg, dslSource, opts = {}) {
|
|
|
10567
10567
|
</head>
|
|
10568
10568
|
<body>
|
|
10569
10569
|
<div class="diagram">${svgStr}</div>
|
|
10570
|
-
<details class="dsl"><summary style="cursor:pointer;color:#f0c96a">DSL source</summary><pre>${escapeHtml(dslSource)}</pre></details>
|
|
10570
|
+
<details class="dsl"><summary style="cursor:pointer;color:#f0c96a">DSL source</summary><pre>${escapeHtml$1(dslSource)}</pre></details>
|
|
10571
10571
|
</body>
|
|
10572
10572
|
</html>`;
|
|
10573
10573
|
const blob = new Blob([html], { type: 'text/html;charset=utf-8' });
|
|
10574
10574
|
download(blob, opts.filename ?? 'diagram.html');
|
|
10575
10575
|
}
|
|
10576
|
-
function escapeHtml(s) {
|
|
10576
|
+
function escapeHtml$1(s) {
|
|
10577
10577
|
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
10578
10578
|
}
|
|
10579
10579
|
// ── GIF stub (requires gifshot or gif.js at runtime) ──────
|
|
@@ -10799,7 +10799,7 @@ const CANVAS_CSS = `
|
|
|
10799
10799
|
.skm-canvas__viewport.is-panning{cursor:grabbing}
|
|
10800
10800
|
.skm-canvas--dark .skm-canvas__viewport{background:#12100a}
|
|
10801
10801
|
.skm-canvas__grid{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
|
|
10802
|
-
.skm-canvas__world{position:absolute;top:0;left:0;transform-origin:0 0;
|
|
10802
|
+
.skm-canvas__world{position:absolute;top:0;left:0;transform-origin:0 0;}
|
|
10803
10803
|
.skm-canvas__controls{position:absolute;right:14px;bottom:14px;display:flex;flex-direction:column;align-items:center;gap:4px;z-index:2}
|
|
10804
10804
|
.skm-canvas__zoom{min-width:40px;text-align:center;color:#8a6040;font-size:10px}
|
|
10805
10805
|
.skm-canvas__minimap{position:absolute;left:14px;bottom:14px;width:120px;height:80px;background:rgba(255,248,234,.94);border:1px solid #caba98;border-radius:6px;overflow:hidden;z-index:2}
|
|
@@ -11449,20 +11449,44 @@ const EDITOR_CSS = `
|
|
|
11449
11449
|
color: #fff;
|
|
11450
11450
|
}
|
|
11451
11451
|
|
|
11452
|
-
.skm-
|
|
11452
|
+
.skm-editor__surface {
|
|
11453
|
+
position: relative;
|
|
11453
11454
|
flex: 1;
|
|
11454
|
-
width: 100%;
|
|
11455
11455
|
min-height: 0;
|
|
11456
|
-
border: 0;
|
|
11457
|
-
outline: 0;
|
|
11458
|
-
resize: none;
|
|
11459
11456
|
background: #1c1608;
|
|
11460
|
-
|
|
11457
|
+
overflow: hidden;
|
|
11458
|
+
}
|
|
11459
|
+
|
|
11460
|
+
.skm-editor__highlight,
|
|
11461
|
+
.skm-editor__input {
|
|
11462
|
+
position: absolute;
|
|
11463
|
+
inset: 0;
|
|
11464
|
+
width: 100%;
|
|
11465
|
+
height: 100%;
|
|
11461
11466
|
padding: 12px 14px;
|
|
11462
11467
|
font: inherit;
|
|
11463
11468
|
font-size: 12px;
|
|
11464
11469
|
line-height: 1.7;
|
|
11465
11470
|
tab-size: 2;
|
|
11471
|
+
white-space: pre-wrap;
|
|
11472
|
+
overflow: auto;
|
|
11473
|
+
}
|
|
11474
|
+
|
|
11475
|
+
.skm-editor__highlight {
|
|
11476
|
+
margin: 0;
|
|
11477
|
+
border: 0;
|
|
11478
|
+
background: #1c1608;
|
|
11479
|
+
color: #e0c898;
|
|
11480
|
+
pointer-events: none;
|
|
11481
|
+
word-break: break-word;
|
|
11482
|
+
}
|
|
11483
|
+
|
|
11484
|
+
.skm-editor__input {
|
|
11485
|
+
border: 0;
|
|
11486
|
+
outline: 0;
|
|
11487
|
+
resize: none;
|
|
11488
|
+
background: transparent;
|
|
11489
|
+
color: transparent;
|
|
11466
11490
|
caret-color: #f0c96a;
|
|
11467
11491
|
}
|
|
11468
11492
|
|
|
@@ -11470,6 +11494,40 @@ const EDITOR_CSS = `
|
|
|
11470
11494
|
color: #80633b;
|
|
11471
11495
|
}
|
|
11472
11496
|
|
|
11497
|
+
.skm-editor__input::selection {
|
|
11498
|
+
background: rgba(240, 201, 106, 0.22);
|
|
11499
|
+
}
|
|
11500
|
+
|
|
11501
|
+
.skm-editor__token--keyword {
|
|
11502
|
+
color: #e07040;
|
|
11503
|
+
}
|
|
11504
|
+
|
|
11505
|
+
.skm-editor__token--property {
|
|
11506
|
+
color: #70a8d0;
|
|
11507
|
+
}
|
|
11508
|
+
|
|
11509
|
+
.skm-editor__token--string {
|
|
11510
|
+
color: #8db870;
|
|
11511
|
+
}
|
|
11512
|
+
|
|
11513
|
+
.skm-editor__token--number {
|
|
11514
|
+
color: #d4a020;
|
|
11515
|
+
}
|
|
11516
|
+
|
|
11517
|
+
.skm-editor__token--comment {
|
|
11518
|
+
color: #6a5a3a;
|
|
11519
|
+
}
|
|
11520
|
+
|
|
11521
|
+
.skm-editor__token--connector {
|
|
11522
|
+
color: #c8b070;
|
|
11523
|
+
}
|
|
11524
|
+
|
|
11525
|
+
.skm-editor__token--color {
|
|
11526
|
+
color: var(--skm-editor-color, #f0c96a);
|
|
11527
|
+
box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.08);
|
|
11528
|
+
font-weight: 600;
|
|
11529
|
+
}
|
|
11530
|
+
|
|
11473
11531
|
.skm-editor__error {
|
|
11474
11532
|
display: none;
|
|
11475
11533
|
flex-shrink: 0;
|
|
@@ -11486,12 +11544,112 @@ const EDITOR_CSS = `
|
|
|
11486
11544
|
display: block;
|
|
11487
11545
|
}
|
|
11488
11546
|
`;
|
|
11547
|
+
const CONNECTORS = ["<-->", "<->", "-->", "<--", "---", "--", "->", "<-"];
|
|
11548
|
+
const HEX_COLOR_RE = /#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})\b/g;
|
|
11489
11549
|
function defaultFormatter(value) {
|
|
11490
11550
|
return normalizeNewlines(value)
|
|
11491
11551
|
.split("\n")
|
|
11492
11552
|
.map((line) => line.replace(/[ \t]+$/g, ""))
|
|
11493
11553
|
.join("\n");
|
|
11494
11554
|
}
|
|
11555
|
+
function escapeHtml(value) {
|
|
11556
|
+
return value
|
|
11557
|
+
.replace(/&/g, "&")
|
|
11558
|
+
.replace(/</g, "<")
|
|
11559
|
+
.replace(/>/g, ">")
|
|
11560
|
+
.replace(/"/g, """);
|
|
11561
|
+
}
|
|
11562
|
+
function wrapToken(kind, value) {
|
|
11563
|
+
return `<span class="skm-editor__token skm-editor__token--${kind}">${escapeHtml(value)}</span>`;
|
|
11564
|
+
}
|
|
11565
|
+
function renderColorLiteral(value) {
|
|
11566
|
+
return `<span class="skm-editor__token skm-editor__token--color" style="--skm-editor-color:${value}">${escapeHtml(value)}</span>`;
|
|
11567
|
+
}
|
|
11568
|
+
function renderStringToken(value) {
|
|
11569
|
+
HEX_COLOR_RE.lastIndex = 0;
|
|
11570
|
+
if (!HEX_COLOR_RE.test(value)) {
|
|
11571
|
+
return wrapToken("string", value);
|
|
11572
|
+
}
|
|
11573
|
+
HEX_COLOR_RE.lastIndex = 0;
|
|
11574
|
+
let html = "";
|
|
11575
|
+
let lastIndex = 0;
|
|
11576
|
+
let match = null;
|
|
11577
|
+
while ((match = HEX_COLOR_RE.exec(value))) {
|
|
11578
|
+
if (match.index > lastIndex) {
|
|
11579
|
+
html += wrapToken("string", value.slice(lastIndex, match.index));
|
|
11580
|
+
}
|
|
11581
|
+
html += renderColorLiteral(match[0]);
|
|
11582
|
+
lastIndex = match.index + match[0].length;
|
|
11583
|
+
}
|
|
11584
|
+
if (lastIndex < value.length) {
|
|
11585
|
+
html += wrapToken("string", value.slice(lastIndex));
|
|
11586
|
+
}
|
|
11587
|
+
return html;
|
|
11588
|
+
}
|
|
11589
|
+
function renderPlainToken(value, nextChar) {
|
|
11590
|
+
if (/^-?\d/.test(value)) {
|
|
11591
|
+
return wrapToken("number", value);
|
|
11592
|
+
}
|
|
11593
|
+
if (nextChar === "=") {
|
|
11594
|
+
return wrapToken("property", value);
|
|
11595
|
+
}
|
|
11596
|
+
if (KEYWORDS.has(value)) {
|
|
11597
|
+
return wrapToken("keyword", value);
|
|
11598
|
+
}
|
|
11599
|
+
return escapeHtml(value);
|
|
11600
|
+
}
|
|
11601
|
+
function highlightLine(line) {
|
|
11602
|
+
let html = "";
|
|
11603
|
+
let index = 0;
|
|
11604
|
+
while (index < line.length) {
|
|
11605
|
+
const rest = line.slice(index);
|
|
11606
|
+
if (rest.startsWith("//") || rest.startsWith("#")) {
|
|
11607
|
+
html += wrapToken("comment", rest);
|
|
11608
|
+
break;
|
|
11609
|
+
}
|
|
11610
|
+
if (line[index] === "\"") {
|
|
11611
|
+
let end = index + 1;
|
|
11612
|
+
while (end < line.length) {
|
|
11613
|
+
if (line[end] === "\"" && line[end - 1] !== "\\") {
|
|
11614
|
+
end += 1;
|
|
11615
|
+
break;
|
|
11616
|
+
}
|
|
11617
|
+
end += 1;
|
|
11618
|
+
}
|
|
11619
|
+
html += renderStringToken(line.slice(index, end));
|
|
11620
|
+
index = end;
|
|
11621
|
+
continue;
|
|
11622
|
+
}
|
|
11623
|
+
const connector = CONNECTORS.find((candidate) => line.startsWith(candidate, index));
|
|
11624
|
+
if (connector) {
|
|
11625
|
+
html += wrapToken("connector", connector);
|
|
11626
|
+
index += connector.length;
|
|
11627
|
+
continue;
|
|
11628
|
+
}
|
|
11629
|
+
const wordMatch = /^[A-Za-z_][A-Za-z0-9_-]*/.exec(rest);
|
|
11630
|
+
if (wordMatch) {
|
|
11631
|
+
const word = wordMatch[0];
|
|
11632
|
+
const nextChar = line[index + word.length] ?? "";
|
|
11633
|
+
html += renderPlainToken(word, nextChar);
|
|
11634
|
+
index += word.length;
|
|
11635
|
+
continue;
|
|
11636
|
+
}
|
|
11637
|
+
const numberMatch = /^-?\d+(?:\.\d+)?/.exec(rest);
|
|
11638
|
+
if (numberMatch) {
|
|
11639
|
+
html += wrapToken("number", numberMatch[0]);
|
|
11640
|
+
index += numberMatch[0].length;
|
|
11641
|
+
continue;
|
|
11642
|
+
}
|
|
11643
|
+
html += escapeHtml(line[index]);
|
|
11644
|
+
index += 1;
|
|
11645
|
+
}
|
|
11646
|
+
return html;
|
|
11647
|
+
}
|
|
11648
|
+
function renderHighlightedValue(value) {
|
|
11649
|
+
const normalized = normalizeNewlines(value);
|
|
11650
|
+
const html = normalized.split("\n").map(highlightLine).join("\n");
|
|
11651
|
+
return html || " ";
|
|
11652
|
+
}
|
|
11495
11653
|
class SketchmarkEditor {
|
|
11496
11654
|
constructor(options) {
|
|
11497
11655
|
this.emitter = new EventEmitter();
|
|
@@ -11528,16 +11686,23 @@ class SketchmarkEditor {
|
|
|
11528
11686
|
if (options.showClearButton !== false)
|
|
11529
11687
|
this.toolbar.appendChild(clearButton);
|
|
11530
11688
|
this.toolbar.appendChild(hint);
|
|
11689
|
+
this.surface = document.createElement("div");
|
|
11690
|
+
this.surface.className = "skm-editor__surface";
|
|
11691
|
+
this.highlightElement = document.createElement("pre");
|
|
11692
|
+
this.highlightElement.className = "skm-editor__highlight";
|
|
11693
|
+
this.highlightElement.setAttribute("aria-hidden", "true");
|
|
11531
11694
|
this.textarea = document.createElement("textarea");
|
|
11532
11695
|
this.textarea.className = "skm-editor__input";
|
|
11533
11696
|
this.textarea.spellcheck = false;
|
|
11534
11697
|
this.textarea.placeholder = options.placeholder ?? "diagram\nbox a label=\"Hello\"\nend";
|
|
11535
11698
|
this.textarea.value = normalizeNewlines(options.value ?? DEFAULT_CLEAR_VALUE);
|
|
11536
11699
|
this.textarea.addEventListener("input", () => {
|
|
11700
|
+
this.syncHighlight();
|
|
11537
11701
|
const payload = { value: this.getValue(), editor: this };
|
|
11538
11702
|
options.onChange?.(payload.value, this);
|
|
11539
11703
|
this.emitter.emit("change", payload);
|
|
11540
11704
|
});
|
|
11705
|
+
this.textarea.addEventListener("scroll", () => this.syncScroll());
|
|
11541
11706
|
this.textarea.addEventListener("keydown", (event) => {
|
|
11542
11707
|
if ((event.ctrlKey || event.metaKey) && event.key === "Enter") {
|
|
11543
11708
|
event.preventDefault();
|
|
@@ -11549,9 +11714,12 @@ class SketchmarkEditor {
|
|
|
11549
11714
|
if (options.showToolbar !== false) {
|
|
11550
11715
|
this.root.appendChild(this.toolbar);
|
|
11551
11716
|
}
|
|
11552
|
-
this.
|
|
11717
|
+
this.surface.appendChild(this.highlightElement);
|
|
11718
|
+
this.surface.appendChild(this.textarea);
|
|
11719
|
+
this.root.appendChild(this.surface);
|
|
11553
11720
|
this.root.appendChild(this.errorElement);
|
|
11554
11721
|
host.appendChild(this.root);
|
|
11722
|
+
this.syncHighlight();
|
|
11555
11723
|
if (options.autoFocus) {
|
|
11556
11724
|
this.focus();
|
|
11557
11725
|
}
|
|
@@ -11561,6 +11729,7 @@ class SketchmarkEditor {
|
|
|
11561
11729
|
}
|
|
11562
11730
|
setValue(value, emitChange = false) {
|
|
11563
11731
|
this.textarea.value = normalizeNewlines(value);
|
|
11732
|
+
this.syncHighlight();
|
|
11564
11733
|
if (emitChange) {
|
|
11565
11734
|
const payload = { value: this.getValue(), editor: this };
|
|
11566
11735
|
this.options.onChange?.(payload.value, this);
|
|
@@ -11602,6 +11771,14 @@ class SketchmarkEditor {
|
|
|
11602
11771
|
destroy() {
|
|
11603
11772
|
this.root.remove();
|
|
11604
11773
|
}
|
|
11774
|
+
syncHighlight() {
|
|
11775
|
+
this.highlightElement.innerHTML = renderHighlightedValue(this.textarea.value);
|
|
11776
|
+
this.syncScroll();
|
|
11777
|
+
}
|
|
11778
|
+
syncScroll() {
|
|
11779
|
+
this.highlightElement.scrollTop = this.textarea.scrollTop;
|
|
11780
|
+
this.highlightElement.scrollLeft = this.textarea.scrollLeft;
|
|
11781
|
+
}
|
|
11605
11782
|
}
|
|
11606
11783
|
|
|
11607
11784
|
const EMBED_STYLE_ID = "sketchmark-embed-ui";
|