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