sketchmark 1.0.0 → 1.0.1
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/animation/index.d.ts +1 -0
- package/dist/animation/index.d.ts.map +1 -1
- package/dist/index.cjs +24 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -10
- package/dist/index.js.map +1 -1
- package/dist/sketchmark.iife.js +24 -10
- package/package.json +1 -1
package/dist/sketchmark.iife.js
CHANGED
|
@@ -7181,6 +7181,7 @@ var AIDiagram = (function (exports) {
|
|
|
7181
7181
|
this._pointerType = 'none';
|
|
7182
7182
|
// ── TTS ──
|
|
7183
7183
|
this._tts = false;
|
|
7184
|
+
this._speechDone = null;
|
|
7184
7185
|
this.drawTargetEdges = getDrawTargetEdgeIds(steps);
|
|
7185
7186
|
this.drawTargetNodes = getDrawTargetNodeIds(steps);
|
|
7186
7187
|
// Groups: non-edge draw steps whose target has a #group-{id} element in the SVG.
|
|
@@ -7311,7 +7312,11 @@ var AIDiagram = (function (exports) {
|
|
|
7311
7312
|
while (this.canNext) {
|
|
7312
7313
|
const nextStep = this.steps[this._step + 1];
|
|
7313
7314
|
this.next();
|
|
7314
|
-
|
|
7315
|
+
// Wait for timer AND speech to finish (whichever is longer)
|
|
7316
|
+
await Promise.all([
|
|
7317
|
+
new Promise((r) => setTimeout(r, this._playbackWaitMs(nextStep, msPerStep))),
|
|
7318
|
+
this._speechDone ?? Promise.resolve(),
|
|
7319
|
+
]);
|
|
7315
7320
|
}
|
|
7316
7321
|
}
|
|
7317
7322
|
goTo(index) {
|
|
@@ -7349,8 +7354,13 @@ var AIDiagram = (function (exports) {
|
|
|
7349
7354
|
// Compute minimum time the step actually needs to finish
|
|
7350
7355
|
let minNeeded = 0;
|
|
7351
7356
|
if (step.action === "narrate") {
|
|
7357
|
+
const text = step.value ?? "";
|
|
7352
7358
|
// Typing effect: chars × typeMs + fade buffer
|
|
7353
|
-
|
|
7359
|
+
const typingMs = text.length * ANIMATION.narrationTypeMs + ANIMATION.narrationFadeMs;
|
|
7360
|
+
// TTS estimate: ~150ms per word + 500ms buffer for engine latency
|
|
7361
|
+
const wordCount = text.split(/\s+/).filter(Boolean).length;
|
|
7362
|
+
const ttsMs = this._tts ? wordCount * 150 + 500 : 0;
|
|
7363
|
+
minNeeded = Math.max(typingMs, ttsMs);
|
|
7354
7364
|
}
|
|
7355
7365
|
else if (step.action === "circle" || step.action === "underline" ||
|
|
7356
7366
|
step.action === "crossout" || step.action === "bracket") {
|
|
@@ -7895,8 +7905,8 @@ var AIDiagram = (function (exports) {
|
|
|
7895
7905
|
}
|
|
7896
7906
|
// ── narration ───────────────────────────────────────────
|
|
7897
7907
|
_initCaption() {
|
|
7898
|
-
|
|
7899
|
-
|
|
7908
|
+
// Remove any leftover caption from a previous instance
|
|
7909
|
+
document.querySelector('.skm-caption')?.remove();
|
|
7900
7910
|
const cap = document.createElement("div");
|
|
7901
7911
|
cap.className = "skm-caption";
|
|
7902
7912
|
cap.style.cssText = `
|
|
@@ -7926,7 +7936,7 @@ var AIDiagram = (function (exports) {
|
|
|
7926
7936
|
this._captionTextEl.textContent = text;
|
|
7927
7937
|
return;
|
|
7928
7938
|
}
|
|
7929
|
-
// Fire TTS
|
|
7939
|
+
// Fire TTS as full sentence — play() waits for _speechDone
|
|
7930
7940
|
if (this._tts && text)
|
|
7931
7941
|
this._speak(text);
|
|
7932
7942
|
// Typing effect
|
|
@@ -7949,11 +7959,17 @@ var AIDiagram = (function (exports) {
|
|
|
7949
7959
|
utter.rate = 0.95;
|
|
7950
7960
|
utter.pitch = 1;
|
|
7951
7961
|
utter.lang = "en-US";
|
|
7962
|
+
// Track when speech actually finishes
|
|
7963
|
+
this._speechDone = new Promise((resolve) => {
|
|
7964
|
+
utter.onend = () => resolve();
|
|
7965
|
+
utter.onerror = () => resolve();
|
|
7966
|
+
});
|
|
7952
7967
|
speechSynthesis.speak(utter);
|
|
7953
7968
|
}
|
|
7954
7969
|
_cancelSpeech() {
|
|
7955
7970
|
if (typeof speechSynthesis !== "undefined")
|
|
7956
7971
|
speechSynthesis.cancel();
|
|
7972
|
+
this._speechDone = null;
|
|
7957
7973
|
}
|
|
7958
7974
|
/** Pre-warm the speech engine with a silent utterance to eliminate cold-start delay */
|
|
7959
7975
|
_warmUpSpeech() {
|
|
@@ -8460,12 +8476,10 @@ var AIDiagram = (function (exports) {
|
|
|
8460
8476
|
interactive: true,
|
|
8461
8477
|
onNodeClick,
|
|
8462
8478
|
});
|
|
8463
|
-
// Create rough.js instance for annotations
|
|
8479
|
+
// Create rough.js instance for annotations (same import as SVG renderer)
|
|
8464
8480
|
let rc = null;
|
|
8465
8481
|
try {
|
|
8466
|
-
|
|
8467
|
-
if (roughMod?.svg)
|
|
8468
|
-
rc = roughMod.svg(svg);
|
|
8482
|
+
rc = rough.svg(svg);
|
|
8469
8483
|
}
|
|
8470
8484
|
catch { /* rough.js not available — annotations disabled */ }
|
|
8471
8485
|
const containerEl = el instanceof SVGSVGElement ? undefined : el;
|
|
@@ -8474,7 +8488,7 @@ var AIDiagram = (function (exports) {
|
|
|
8474
8488
|
onReady?.(anim, svg);
|
|
8475
8489
|
const instance = {
|
|
8476
8490
|
scene, anim, svg, canvas,
|
|
8477
|
-
update: (newDsl) => render({ ...options, dsl: newDsl }),
|
|
8491
|
+
update: (newDsl) => { anim?.destroy(); return render({ ...options, dsl: newDsl }); },
|
|
8478
8492
|
exportSVG: (filename = 'diagram.svg') => {
|
|
8479
8493
|
if (svg) {
|
|
8480
8494
|
Promise.resolve().then(function () { return index; }).then(m => m.exportSVG(svg, { filename }));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sketchmark",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
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",
|