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.

@@ -10568,13 +10568,13 @@ var AIDiagram = (function (exports) {
10568
10568
  </head>
10569
10569
  <body>
10570
10570
  <div class="diagram">${svgStr}</div>
10571
- <details class="dsl"><summary style="cursor:pointer;color:#f0c96a">DSL source</summary><pre>${escapeHtml(dslSource)}</pre></details>
10571
+ <details class="dsl"><summary style="cursor:pointer;color:#f0c96a">DSL source</summary><pre>${escapeHtml$1(dslSource)}</pre></details>
10572
10572
  </body>
10573
10573
  </html>`;
10574
10574
  const blob = new Blob([html], { type: 'text/html;charset=utf-8' });
10575
10575
  download(blob, opts.filename ?? 'diagram.html');
10576
10576
  }
10577
- function escapeHtml(s) {
10577
+ function escapeHtml$1(s) {
10578
10578
  return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
10579
10579
  }
10580
10580
  // ── GIF stub (requires gifshot or gif.js at runtime) ──────
@@ -10800,7 +10800,7 @@ var AIDiagram = (function (exports) {
10800
10800
  .skm-canvas__viewport.is-panning{cursor:grabbing}
10801
10801
  .skm-canvas--dark .skm-canvas__viewport{background:#12100a}
10802
10802
  .skm-canvas__grid{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
10803
- .skm-canvas__world{position:absolute;top:0;left:0;transform-origin:0 0;will-change:transform}
10803
+ .skm-canvas__world{position:absolute;top:0;left:0;transform-origin:0 0;}
10804
10804
  .skm-canvas__controls{position:absolute;right:14px;bottom:14px;display:flex;flex-direction:column;align-items:center;gap:4px;z-index:2}
10805
10805
  .skm-canvas__zoom{min-width:40px;text-align:center;color:#8a6040;font-size:10px}
10806
10806
  .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}
@@ -11450,20 +11450,44 @@ var AIDiagram = (function (exports) {
11450
11450
  color: #fff;
11451
11451
  }
11452
11452
 
11453
- .skm-editor__input {
11453
+ .skm-editor__surface {
11454
+ position: relative;
11454
11455
  flex: 1;
11455
- width: 100%;
11456
11456
  min-height: 0;
11457
- border: 0;
11458
- outline: 0;
11459
- resize: none;
11460
11457
  background: #1c1608;
11461
- color: #e0c898;
11458
+ overflow: hidden;
11459
+ }
11460
+
11461
+ .skm-editor__highlight,
11462
+ .skm-editor__input {
11463
+ position: absolute;
11464
+ inset: 0;
11465
+ width: 100%;
11466
+ height: 100%;
11462
11467
  padding: 12px 14px;
11463
11468
  font: inherit;
11464
11469
  font-size: 12px;
11465
11470
  line-height: 1.7;
11466
11471
  tab-size: 2;
11472
+ white-space: pre-wrap;
11473
+ overflow: auto;
11474
+ }
11475
+
11476
+ .skm-editor__highlight {
11477
+ margin: 0;
11478
+ border: 0;
11479
+ background: #1c1608;
11480
+ color: #e0c898;
11481
+ pointer-events: none;
11482
+ word-break: break-word;
11483
+ }
11484
+
11485
+ .skm-editor__input {
11486
+ border: 0;
11487
+ outline: 0;
11488
+ resize: none;
11489
+ background: transparent;
11490
+ color: transparent;
11467
11491
  caret-color: #f0c96a;
11468
11492
  }
11469
11493
 
@@ -11471,6 +11495,40 @@ var AIDiagram = (function (exports) {
11471
11495
  color: #80633b;
11472
11496
  }
11473
11497
 
11498
+ .skm-editor__input::selection {
11499
+ background: rgba(240, 201, 106, 0.22);
11500
+ }
11501
+
11502
+ .skm-editor__token--keyword {
11503
+ color: #e07040;
11504
+ }
11505
+
11506
+ .skm-editor__token--property {
11507
+ color: #70a8d0;
11508
+ }
11509
+
11510
+ .skm-editor__token--string {
11511
+ color: #8db870;
11512
+ }
11513
+
11514
+ .skm-editor__token--number {
11515
+ color: #d4a020;
11516
+ }
11517
+
11518
+ .skm-editor__token--comment {
11519
+ color: #6a5a3a;
11520
+ }
11521
+
11522
+ .skm-editor__token--connector {
11523
+ color: #c8b070;
11524
+ }
11525
+
11526
+ .skm-editor__token--color {
11527
+ color: var(--skm-editor-color, #f0c96a);
11528
+ box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.08);
11529
+ font-weight: 600;
11530
+ }
11531
+
11474
11532
  .skm-editor__error {
11475
11533
  display: none;
11476
11534
  flex-shrink: 0;
@@ -11487,12 +11545,112 @@ var AIDiagram = (function (exports) {
11487
11545
  display: block;
11488
11546
  }
11489
11547
  `;
11548
+ const CONNECTORS = ["<-->", "<->", "-->", "<--", "---", "--", "->", "<-"];
11549
+ const HEX_COLOR_RE = /#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})\b/g;
11490
11550
  function defaultFormatter(value) {
11491
11551
  return normalizeNewlines(value)
11492
11552
  .split("\n")
11493
11553
  .map((line) => line.replace(/[ \t]+$/g, ""))
11494
11554
  .join("\n");
11495
11555
  }
11556
+ function escapeHtml(value) {
11557
+ return value
11558
+ .replace(/&/g, "&amp;")
11559
+ .replace(/</g, "&lt;")
11560
+ .replace(/>/g, "&gt;")
11561
+ .replace(/"/g, "&quot;");
11562
+ }
11563
+ function wrapToken(kind, value) {
11564
+ return `<span class="skm-editor__token skm-editor__token--${kind}">${escapeHtml(value)}</span>`;
11565
+ }
11566
+ function renderColorLiteral(value) {
11567
+ return `<span class="skm-editor__token skm-editor__token--color" style="--skm-editor-color:${value}">${escapeHtml(value)}</span>`;
11568
+ }
11569
+ function renderStringToken(value) {
11570
+ HEX_COLOR_RE.lastIndex = 0;
11571
+ if (!HEX_COLOR_RE.test(value)) {
11572
+ return wrapToken("string", value);
11573
+ }
11574
+ HEX_COLOR_RE.lastIndex = 0;
11575
+ let html = "";
11576
+ let lastIndex = 0;
11577
+ let match = null;
11578
+ while ((match = HEX_COLOR_RE.exec(value))) {
11579
+ if (match.index > lastIndex) {
11580
+ html += wrapToken("string", value.slice(lastIndex, match.index));
11581
+ }
11582
+ html += renderColorLiteral(match[0]);
11583
+ lastIndex = match.index + match[0].length;
11584
+ }
11585
+ if (lastIndex < value.length) {
11586
+ html += wrapToken("string", value.slice(lastIndex));
11587
+ }
11588
+ return html;
11589
+ }
11590
+ function renderPlainToken(value, nextChar) {
11591
+ if (/^-?\d/.test(value)) {
11592
+ return wrapToken("number", value);
11593
+ }
11594
+ if (nextChar === "=") {
11595
+ return wrapToken("property", value);
11596
+ }
11597
+ if (KEYWORDS.has(value)) {
11598
+ return wrapToken("keyword", value);
11599
+ }
11600
+ return escapeHtml(value);
11601
+ }
11602
+ function highlightLine(line) {
11603
+ let html = "";
11604
+ let index = 0;
11605
+ while (index < line.length) {
11606
+ const rest = line.slice(index);
11607
+ if (rest.startsWith("//") || rest.startsWith("#")) {
11608
+ html += wrapToken("comment", rest);
11609
+ break;
11610
+ }
11611
+ if (line[index] === "\"") {
11612
+ let end = index + 1;
11613
+ while (end < line.length) {
11614
+ if (line[end] === "\"" && line[end - 1] !== "\\") {
11615
+ end += 1;
11616
+ break;
11617
+ }
11618
+ end += 1;
11619
+ }
11620
+ html += renderStringToken(line.slice(index, end));
11621
+ index = end;
11622
+ continue;
11623
+ }
11624
+ const connector = CONNECTORS.find((candidate) => line.startsWith(candidate, index));
11625
+ if (connector) {
11626
+ html += wrapToken("connector", connector);
11627
+ index += connector.length;
11628
+ continue;
11629
+ }
11630
+ const wordMatch = /^[A-Za-z_][A-Za-z0-9_-]*/.exec(rest);
11631
+ if (wordMatch) {
11632
+ const word = wordMatch[0];
11633
+ const nextChar = line[index + word.length] ?? "";
11634
+ html += renderPlainToken(word, nextChar);
11635
+ index += word.length;
11636
+ continue;
11637
+ }
11638
+ const numberMatch = /^-?\d+(?:\.\d+)?/.exec(rest);
11639
+ if (numberMatch) {
11640
+ html += wrapToken("number", numberMatch[0]);
11641
+ index += numberMatch[0].length;
11642
+ continue;
11643
+ }
11644
+ html += escapeHtml(line[index]);
11645
+ index += 1;
11646
+ }
11647
+ return html;
11648
+ }
11649
+ function renderHighlightedValue(value) {
11650
+ const normalized = normalizeNewlines(value);
11651
+ const html = normalized.split("\n").map(highlightLine).join("\n");
11652
+ return html || " ";
11653
+ }
11496
11654
  class SketchmarkEditor {
11497
11655
  constructor(options) {
11498
11656
  this.emitter = new EventEmitter();
@@ -11529,16 +11687,23 @@ var AIDiagram = (function (exports) {
11529
11687
  if (options.showClearButton !== false)
11530
11688
  this.toolbar.appendChild(clearButton);
11531
11689
  this.toolbar.appendChild(hint);
11690
+ this.surface = document.createElement("div");
11691
+ this.surface.className = "skm-editor__surface";
11692
+ this.highlightElement = document.createElement("pre");
11693
+ this.highlightElement.className = "skm-editor__highlight";
11694
+ this.highlightElement.setAttribute("aria-hidden", "true");
11532
11695
  this.textarea = document.createElement("textarea");
11533
11696
  this.textarea.className = "skm-editor__input";
11534
11697
  this.textarea.spellcheck = false;
11535
11698
  this.textarea.placeholder = options.placeholder ?? "diagram\nbox a label=\"Hello\"\nend";
11536
11699
  this.textarea.value = normalizeNewlines(options.value ?? DEFAULT_CLEAR_VALUE);
11537
11700
  this.textarea.addEventListener("input", () => {
11701
+ this.syncHighlight();
11538
11702
  const payload = { value: this.getValue(), editor: this };
11539
11703
  options.onChange?.(payload.value, this);
11540
11704
  this.emitter.emit("change", payload);
11541
11705
  });
11706
+ this.textarea.addEventListener("scroll", () => this.syncScroll());
11542
11707
  this.textarea.addEventListener("keydown", (event) => {
11543
11708
  if ((event.ctrlKey || event.metaKey) && event.key === "Enter") {
11544
11709
  event.preventDefault();
@@ -11550,9 +11715,12 @@ var AIDiagram = (function (exports) {
11550
11715
  if (options.showToolbar !== false) {
11551
11716
  this.root.appendChild(this.toolbar);
11552
11717
  }
11553
- this.root.appendChild(this.textarea);
11718
+ this.surface.appendChild(this.highlightElement);
11719
+ this.surface.appendChild(this.textarea);
11720
+ this.root.appendChild(this.surface);
11554
11721
  this.root.appendChild(this.errorElement);
11555
11722
  host.appendChild(this.root);
11723
+ this.syncHighlight();
11556
11724
  if (options.autoFocus) {
11557
11725
  this.focus();
11558
11726
  }
@@ -11562,6 +11730,7 @@ var AIDiagram = (function (exports) {
11562
11730
  }
11563
11731
  setValue(value, emitChange = false) {
11564
11732
  this.textarea.value = normalizeNewlines(value);
11733
+ this.syncHighlight();
11565
11734
  if (emitChange) {
11566
11735
  const payload = { value: this.getValue(), editor: this };
11567
11736
  this.options.onChange?.(payload.value, this);
@@ -11603,6 +11772,14 @@ var AIDiagram = (function (exports) {
11603
11772
  destroy() {
11604
11773
  this.root.remove();
11605
11774
  }
11775
+ syncHighlight() {
11776
+ this.highlightElement.innerHTML = renderHighlightedValue(this.textarea.value);
11777
+ this.syncScroll();
11778
+ }
11779
+ syncScroll() {
11780
+ this.highlightElement.scrollTop = this.textarea.scrollTop;
11781
+ this.highlightElement.scrollLeft = this.textarea.scrollLeft;
11782
+ }
11606
11783
  }
11607
11784
 
11608
11785
  const EMBED_STYLE_ID = "sketchmark-embed-ui";
@@ -29,6 +29,8 @@ export interface SketchmarkEditorEvents extends Record<string, unknown> {
29
29
  export declare class SketchmarkEditor {
30
30
  readonly root: HTMLDivElement;
31
31
  readonly toolbar: HTMLDivElement;
32
+ readonly surface: HTMLDivElement;
33
+ readonly highlightElement: HTMLPreElement;
32
34
  readonly textarea: HTMLTextAreaElement;
33
35
  readonly errorElement: HTMLDivElement;
34
36
  private readonly emitter;
@@ -44,5 +46,7 @@ export declare class SketchmarkEditor {
44
46
  clearError(): void;
45
47
  on<K extends keyof SketchmarkEditorEvents>(event: K, listener: (payload: SketchmarkEditorEvents[K]) => void): () => void;
46
48
  destroy(): void;
49
+ private syncHighlight;
50
+ private syncScroll;
47
51
  }
48
52
  //# sourceMappingURL=editor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/ui/editor.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,UAAU,CAAC;AAuGlB,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,eAAe,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC7D,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAC3D;AAED,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAuB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACrE,MAAM,EAAE,4BAA4B,CAAC;IACrC,GAAG,EAAE,4BAA4B,CAAC;IAClC,KAAK,EAAE,4BAA4B,CAAC;IACpC,MAAM,EAAE,4BAA4B,CAAC;CACtC;AASD,qBAAa,gBAAgB;IAC3B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,YAAY,EAAE,cAAc,CAAC;IAEtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8C;IACtE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;gBAEtC,OAAO,EAAE,uBAAuB;IAyE5C,QAAQ,IAAI,MAAM;IAIlB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,UAAQ,GAAG,IAAI;IASjD,KAAK,IAAI,IAAI;IAIb,MAAM,IAAI,IAAI;IAOd,KAAK,IAAI,IAAI;IAOb,GAAG,IAAI,IAAI;IAMX,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAKhC,UAAU,IAAI,IAAI;IAKlB,EAAE,CAAC,CAAC,SAAS,MAAM,sBAAsB,EACvC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC,CAAC,KAAK,IAAI,GACrD,MAAM,IAAI;IAKb,OAAO,IAAI,IAAI;CAGhB"}
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/ui/editor.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,UAAU,CAAC;AAiKlB,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,eAAe,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC7D,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAC3D;AAED,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAuB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACrE,MAAM,EAAE,4BAA4B,CAAC;IACrC,GAAG,EAAE,4BAA4B,CAAC;IAClC,KAAK,EAAE,4BAA4B,CAAC;IACpC,MAAM,EAAE,4BAA4B,CAAC;CACtC;AAiID,qBAAa,gBAAgB;IAC3B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,cAAc,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,YAAY,EAAE,cAAc,CAAC;IAEtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8C;IACtE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;gBAEtC,OAAO,EAAE,uBAAuB;IAsF5C,QAAQ,IAAI,MAAM;IAIlB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,UAAQ,GAAG,IAAI;IAUjD,KAAK,IAAI,IAAI;IAIb,MAAM,IAAI,IAAI;IAOd,KAAK,IAAI,IAAI;IAOb,GAAG,IAAI,IAAI;IAMX,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAKhC,UAAU,IAAI,IAAI;IAKlB,EAAE,CAAC,CAAC,SAAS,MAAM,sBAAsB,EACvC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC,CAAC,KAAK,IAAI,GACrD,MAAM,IAAI;IAKb,OAAO,IAAI,IAAI;IAIf,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,UAAU;CAInB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sketchmark",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "A plain-text DSL for hand-drawn diagrams. Write boxes, edges, and groups as code — renders sketchy SVG/Canvas via rough.js with a built-in step-by-step animation system.",
5
5
  "keywords": [
6
6
  "diagram",