@glissade/core 0.9.0-pre.0 → 0.9.0
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.js +3 -1
- package/dist/sidecar.js +1 -0
- package/dist/studioHost.d.ts +2 -0
- package/dist/studioHost.js +38 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -364,7 +364,9 @@ function parseFormat4(dv, base, into) {
|
|
|
364
364
|
}
|
|
365
365
|
}
|
|
366
366
|
function parseFormat12(dv, base, into) {
|
|
367
|
-
const
|
|
367
|
+
const declared = u32(dv, base + 12);
|
|
368
|
+
const maxGroups = Math.max(0, Math.floor((dv.byteLength - (base + 16)) / 12));
|
|
369
|
+
const nGroups = Math.min(declared, maxGroups);
|
|
368
370
|
let off = base + 16;
|
|
369
371
|
for (let i = 0; i < nGroups; i++, off += 12) {
|
|
370
372
|
const startChar = u32(dv, off);
|
package/dist/sidecar.js
CHANGED
|
@@ -1118,6 +1118,7 @@ function assignKeyIds(keys) {
|
|
|
1118
1118
|
* with no baseline). Keys get stable `k<N>` ids. Returns a new document.
|
|
1119
1119
|
*/
|
|
1120
1120
|
function setSidecarTrack(doc, timelineId, target, type, keys, codeBaselineKeys) {
|
|
1121
|
+
if (!isEditableNodeId(targetNodeId(target))) throw new TrackValidationError(target, "structural/un-id'd nodes cannot host editor tracks (§6.5) — only nodes with an explicit id");
|
|
1121
1122
|
const tl = doc.timelines[timelineId] ?? { tracks: {} };
|
|
1122
1123
|
const entry = {
|
|
1123
1124
|
type,
|
package/dist/studioHost.d.ts
CHANGED
|
@@ -16,10 +16,12 @@ type TimelinePatch = {
|
|
|
16
16
|
type: ValueTypeId;
|
|
17
17
|
keys: Key[];
|
|
18
18
|
baseHash?: string | null;
|
|
19
|
+
verbatim?: boolean;
|
|
19
20
|
} | {
|
|
20
21
|
op: 'removeTrack';
|
|
21
22
|
timelineId: string;
|
|
22
23
|
target: string;
|
|
24
|
+
prune?: boolean;
|
|
23
25
|
} | {
|
|
24
26
|
op: 'addKey';
|
|
25
27
|
timelineId: string;
|
package/dist/studioHost.js
CHANGED
|
@@ -38,11 +38,20 @@ function putEntry(doc, timelineId, target, entry) {
|
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
-
function removeEntry(doc, timelineId, target) {
|
|
41
|
+
function removeEntry(doc, timelineId, target, prune = false) {
|
|
42
42
|
const tl = doc.timelines[timelineId];
|
|
43
43
|
if (!tl?.tracks[target]) return doc;
|
|
44
44
|
const tracks = { ...tl.tracks };
|
|
45
45
|
delete tracks[target];
|
|
46
|
+
const labels = tl.labels;
|
|
47
|
+
if (prune && Object.keys(tracks).length === 0 && (!labels || Object.keys(labels).length === 0)) {
|
|
48
|
+
const timelines = { ...doc.timelines };
|
|
49
|
+
delete timelines[timelineId];
|
|
50
|
+
return {
|
|
51
|
+
...doc,
|
|
52
|
+
timelines
|
|
53
|
+
};
|
|
54
|
+
}
|
|
46
55
|
return {
|
|
47
56
|
...doc,
|
|
48
57
|
timelines: {
|
|
@@ -54,11 +63,16 @@ function removeEntry(doc, timelineId, target) {
|
|
|
54
63
|
}
|
|
55
64
|
};
|
|
56
65
|
}
|
|
57
|
-
/**
|
|
58
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Apply a key-list edit. `verbatim` restores keys EXACTLY as given (the inverse
|
|
68
|
+
* path — it is replaying a prior valid state, so re-normalizing would re-pin
|
|
69
|
+
* springs / re-nudge collisions and break byte-exact undo). The forward editor
|
|
70
|
+
* path normalizes (§2.7 spring re-pin + collision nudge) and (re)assigns ids.
|
|
71
|
+
*/
|
|
72
|
+
function withKeys(entry, keys, verbatim = false) {
|
|
59
73
|
return {
|
|
60
74
|
...entry,
|
|
61
|
-
keys: assignKeyIds(normalizeEditedKeys(keys))
|
|
75
|
+
keys: verbatim ? keys.map((k) => ({ ...k })) : assignKeyIds(normalizeEditedKeys(keys))
|
|
62
76
|
};
|
|
63
77
|
}
|
|
64
78
|
/**
|
|
@@ -72,7 +86,9 @@ function applyPatches(doc, patches, baseline) {
|
|
|
72
86
|
let work = doc;
|
|
73
87
|
const trackSnap = /* @__PURE__ */ new Map();
|
|
74
88
|
const labelSnap = /* @__PURE__ */ new Map();
|
|
89
|
+
const tlExisted = /* @__PURE__ */ new Map();
|
|
75
90
|
const snapTrack = (timelineId, target) => {
|
|
91
|
+
if (!tlExisted.has(timelineId)) tlExisted.set(timelineId, work.timelines[timelineId] !== void 0);
|
|
76
92
|
const k = refKey(timelineId, target);
|
|
77
93
|
if (!trackSnap.has(k)) trackSnap.set(k, work.timelines[timelineId]?.tracks[target] ?? null);
|
|
78
94
|
};
|
|
@@ -82,13 +98,17 @@ function applyPatches(doc, patches, baseline) {
|
|
|
82
98
|
};
|
|
83
99
|
for (const p of patches) switch (p.op) {
|
|
84
100
|
case "setTrackKeys": {
|
|
101
|
+
if (!p.verbatim && !isEditableNodeId(targetNodeId(p.target))) return {
|
|
102
|
+
ok: false,
|
|
103
|
+
error: `setTrackKeys: '${p.target}' is not an editable host (structural/un-id'd nodes cannot host tracks, §6.5)`
|
|
104
|
+
};
|
|
85
105
|
snapTrack(p.timelineId, p.target);
|
|
86
106
|
const prev = work.timelines[p.timelineId]?.tracks[p.target];
|
|
87
107
|
const entry = withKeys({
|
|
88
108
|
type: p.type,
|
|
89
109
|
baseHash: p.baseHash !== void 0 ? p.baseHash : prev?.baseHash ?? null,
|
|
90
110
|
keys: []
|
|
91
|
-
}, p.keys.map((k) => ({ ...k })));
|
|
111
|
+
}, p.keys.map((k) => ({ ...k })), p.verbatim);
|
|
92
112
|
work = putEntry(work, p.timelineId, p.target, entry);
|
|
93
113
|
break;
|
|
94
114
|
}
|
|
@@ -98,9 +118,13 @@ function applyPatches(doc, patches, baseline) {
|
|
|
98
118
|
error: `removeTrack: no sidecar track '${p.target}'`
|
|
99
119
|
};
|
|
100
120
|
snapTrack(p.timelineId, p.target);
|
|
101
|
-
work = removeEntry(work, p.timelineId, p.target);
|
|
121
|
+
work = removeEntry(work, p.timelineId, p.target, p.prune);
|
|
102
122
|
break;
|
|
103
123
|
case "addKey": {
|
|
124
|
+
if (!isEditableNodeId(targetNodeId(p.target))) return {
|
|
125
|
+
ok: false,
|
|
126
|
+
error: `addKey: '${p.target}' is not an editable host (structural/un-id'd nodes cannot host tracks, §6.5)`
|
|
127
|
+
};
|
|
104
128
|
const entry = resolveEntry(work, p, baseline);
|
|
105
129
|
if (!entry) return {
|
|
106
130
|
ok: false,
|
|
@@ -191,7 +215,12 @@ function applyPatches(doc, patches, baseline) {
|
|
|
191
215
|
const inverse = [];
|
|
192
216
|
for (const [k, snap] of trackSnap) {
|
|
193
217
|
const [timelineId, target] = parseRefKey(k);
|
|
194
|
-
if (snap === null) inverse.push({
|
|
218
|
+
if (snap === null) inverse.push(tlExisted.get(timelineId) === false ? {
|
|
219
|
+
op: "removeTrack",
|
|
220
|
+
timelineId,
|
|
221
|
+
target,
|
|
222
|
+
prune: true
|
|
223
|
+
} : {
|
|
195
224
|
op: "removeTrack",
|
|
196
225
|
timelineId,
|
|
197
226
|
target
|
|
@@ -202,7 +231,8 @@ function applyPatches(doc, patches, baseline) {
|
|
|
202
231
|
target,
|
|
203
232
|
type: snap.type,
|
|
204
233
|
keys: snap.keys.map((x) => ({ ...x })),
|
|
205
|
-
baseHash: snap.baseHash
|
|
234
|
+
baseHash: snap.baseHash,
|
|
235
|
+
verbatim: true
|
|
206
236
|
});
|
|
207
237
|
}
|
|
208
238
|
for (const [k, value] of labelSnap) {
|
package/package.json
CHANGED