@lvce-editor/preview-worker 2.1.0 → 2.3.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.
@@ -514,7 +514,7 @@ const IpcParentWithMessagePort$1 = {
514
514
 
515
515
  const Two$1 = '2.0';
516
516
  const callbacks$1 = Object.create(null);
517
- const get$3 = id => {
517
+ const get$4 = id => {
518
518
  return callbacks$1[id];
519
519
  };
520
520
  const remove$1 = id => {
@@ -663,7 +663,7 @@ const warn = (...args) => {
663
663
  console.warn(...args);
664
664
  };
665
665
  const resolve = (id, response) => {
666
- const fn = get$3(id);
666
+ const fn = get$4(id);
667
667
  if (!fn) {
668
668
  console.log(response);
669
669
  warn(`callback ${id} may already be disposed`);
@@ -1129,6 +1129,7 @@ const Dt$1 = 67;
1129
1129
  const Iframe$1 = 68;
1130
1130
  const Style = 72;
1131
1131
  const Html = 73;
1132
+ const Canvas$1 = 77;
1132
1133
  const Reference = 100;
1133
1134
 
1134
1135
  const EditorWorker = 99;
@@ -1138,10 +1139,10 @@ const SetDom2 = 'Viewlet.setDom2';
1138
1139
  const SetPatches = 'Viewlet.setPatches';
1139
1140
 
1140
1141
  const rpcs = Object.create(null);
1141
- const set$4 = (id, rpc) => {
1142
+ const set$5 = (id, rpc) => {
1142
1143
  rpcs[id] = rpc;
1143
1144
  };
1144
- const get$2 = id => {
1145
+ const get$3 = id => {
1145
1146
  return rpcs[id];
1146
1147
  };
1147
1148
  const remove = id => {
@@ -1152,18 +1153,18 @@ const remove = id => {
1152
1153
  const create$2 = rpcId => {
1153
1154
  return {
1154
1155
  async dispose() {
1155
- const rpc = get$2(rpcId);
1156
+ const rpc = get$3(rpcId);
1156
1157
  await rpc.dispose();
1157
1158
  },
1158
1159
  // @ts-ignore
1159
1160
  invoke(method, ...params) {
1160
- const rpc = get$2(rpcId);
1161
+ const rpc = get$3(rpcId);
1161
1162
  // @ts-ignore
1162
1163
  return rpc.invoke(method, ...params);
1163
1164
  },
1164
1165
  // @ts-ignore
1165
1166
  invokeAndTransfer(method, ...params) {
1166
- const rpc = get$2(rpcId);
1167
+ const rpc = get$3(rpcId);
1167
1168
  // @ts-ignore
1168
1169
  return rpc.invokeAndTransfer(method, ...params);
1169
1170
  },
@@ -1171,7 +1172,7 @@ const create$2 = rpcId => {
1171
1172
  const mockRpc = createMockRpc({
1172
1173
  commandMap
1173
1174
  });
1174
- set$4(rpcId, mockRpc);
1175
+ set$5(rpcId, mockRpc);
1175
1176
  // @ts-ignore
1176
1177
  mockRpc[Symbol.dispose] = () => {
1177
1178
  remove(rpcId);
@@ -1180,20 +1181,20 @@ const create$2 = rpcId => {
1180
1181
  return mockRpc;
1181
1182
  },
1182
1183
  set(rpc) {
1183
- set$4(rpcId, rpc);
1184
+ set$5(rpcId, rpc);
1184
1185
  }
1185
1186
  };
1186
1187
  };
1187
1188
 
1188
1189
  const {
1189
1190
  invoke: invoke$1,
1190
- set: set$3
1191
+ set: set$4
1191
1192
  } = create$2(EditorWorker);
1192
1193
 
1193
1194
  const {
1194
1195
  invoke,
1195
1196
  invokeAndTransfer,
1196
- set: set$2
1197
+ set: set$3
1197
1198
  } = create$2(RendererWorker);
1198
1199
  const sendMessagePortToEditorWorker = async (port, rpcId) => {
1199
1200
  const command = 'HandleMessagePort.handleMessagePort';
@@ -1293,11 +1294,11 @@ const terminate = () => {
1293
1294
  };
1294
1295
 
1295
1296
  const {
1296
- get: get$1,
1297
+ get: get$2,
1297
1298
  getCommandIds,
1298
1299
  getKeys: getKeys$1,
1299
1300
  registerCommands,
1300
- set: set$1,
1301
+ set: set$2,
1301
1302
  wrapCommand,
1302
1303
  wrapGetter
1303
1304
  } = create$1();
@@ -1318,7 +1319,7 @@ const create = (uid, uri, x, y, width, height, platform, assetDir) => {
1318
1319
  uri,
1319
1320
  warningCount: 0
1320
1321
  };
1321
- set$1(uid, state, state);
1322
+ set$2(uid, state, state);
1322
1323
  };
1323
1324
 
1324
1325
  const iEqual = (oldState, newState) => {
@@ -1359,7 +1360,7 @@ const diff2 = uid => {
1359
1360
  const {
1360
1361
  newState,
1361
1362
  oldState
1362
- } = get$1(uid);
1363
+ } = get$2(uid);
1363
1364
  const result = diff(oldState, newState);
1364
1365
  return result;
1365
1366
  };
@@ -1418,12 +1419,12 @@ const getParsedNodesChildNodeCount = parsedDom => {
1418
1419
 
1419
1420
  /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
1420
1421
 
1421
- const states = new Map();
1422
- const get = uid => {
1423
- return states.get(uid);
1422
+ const states$1 = new Map();
1423
+ const get$1 = uid => {
1424
+ return states$1.get(uid);
1424
1425
  };
1425
- const set = (uid, instance) => {
1426
- states.set(uid, instance);
1426
+ const set$1 = (uid, instance) => {
1427
+ states$1.set(uid, instance);
1427
1428
  };
1428
1429
 
1429
1430
  const text = data => {
@@ -1772,6 +1773,7 @@ const Dt = 'dt';
1772
1773
  const Iframe = 'iframe';
1773
1774
  const Del = 'del';
1774
1775
  const H6 = 'h6';
1776
+ const Canvas = 'canvas';
1775
1777
 
1776
1778
  const getVirtualDomTag = text => {
1777
1779
  switch (text) {
@@ -1787,6 +1789,8 @@ const getVirtualDomTag = text => {
1787
1789
  return Br$1;
1788
1790
  case Button:
1789
1791
  return Button$1;
1792
+ case Canvas:
1793
+ return Canvas$1;
1790
1794
  case Cite:
1791
1795
  return Cite$1;
1792
1796
  case Code:
@@ -2068,7 +2072,7 @@ const handleClick = (state, hdId) => {
2068
2072
  if (!hdId) {
2069
2073
  return state;
2070
2074
  }
2071
- const happyDomInstance = get(state.uid);
2075
+ const happyDomInstance = get$1(state.uid);
2072
2076
  if (!happyDomInstance) {
2073
2077
  return state;
2074
2078
  }
@@ -2086,7 +2090,7 @@ const handleClick = (state, hdId) => {
2086
2090
  const serialized = serialize(happyDomInstance.document, elementMap);
2087
2091
 
2088
2092
  // Update happy-dom state with new element map
2089
- set(state.uid, {
2093
+ set$1(state.uid, {
2090
2094
  document: happyDomInstance.document,
2091
2095
  elementMap,
2092
2096
  window: happyDomInstance.window
@@ -2670,7 +2674,7 @@ const handleEditorChanged = async () => {
2670
2674
  for (const previewUid of previewKeys) {
2671
2675
  const {
2672
2676
  newState: state
2673
- } = get$1(previewUid);
2677
+ } = get$2(previewUid);
2674
2678
 
2675
2679
  // Skip if no URI is set
2676
2680
  if (!state.uri) {
@@ -2701,7 +2705,7 @@ const handleEditorChanged = async () => {
2701
2705
  parsedDom: parseResult.dom,
2702
2706
  scripts: parseResult.scripts
2703
2707
  };
2704
- set$1(previewUid, state, updatedState);
2708
+ set$2(previewUid, state, updatedState);
2705
2709
  } catch (error) {
2706
2710
  // If getting text fails, update with error message
2707
2711
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
@@ -2713,7 +2717,7 @@ const handleEditorChanged = async () => {
2713
2717
  parsedDom: [],
2714
2718
  scripts: []
2715
2719
  };
2716
- set$1(previewUid, state, updatedState);
2720
+ set$2(previewUid, state, updatedState);
2717
2721
  }
2718
2722
  }
2719
2723
  }
@@ -90342,6 +90346,98 @@ const executeScripts = (window, document, scripts) => {
90342
90346
  }
90343
90347
  };
90344
90348
 
90349
+ /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
90350
+
90351
+ const states = new Map();
90352
+ const get = uid => {
90353
+ return states.get(uid);
90354
+ };
90355
+ const set = (uid, entry) => {
90356
+ states.set(uid, entry);
90357
+ };
90358
+ const addAnimationFrameHandle = (uid, handle) => {
90359
+ const entry = states.get(uid);
90360
+ if (entry) {
90361
+ entry.animationFrameHandles.push(handle);
90362
+ }
90363
+ };
90364
+
90365
+ const flushCanvasFrame = uid => {
90366
+ const canvasStateEntry = get(uid);
90367
+ if (!canvasStateEntry) {
90368
+ return;
90369
+ }
90370
+ for (const instance of canvasStateEntry.instances) {
90371
+ try {
90372
+ const bitmap = instance.offscreenCanvas.transferToImageBitmap();
90373
+ // @ts-ignore
90374
+ void invoke('Preview.drawCanvas', uid, instance.dataId, bitmap);
90375
+ } catch {
90376
+ // transferToImageBitmap can fail if canvas is zero-sized
90377
+ }
90378
+ }
90379
+ };
90380
+
90381
+ const FRAME_INTERVAL = 16;
90382
+ const overrideRequestAnimationFrame = (window, uid) => {
90383
+ let nextId = 1;
90384
+ const callbacks = new Map();
90385
+ const tick = () => {
90386
+ const currentCallbacks = [...callbacks.entries()];
90387
+ callbacks.clear();
90388
+ const timestamp = performance.now();
90389
+ for (const [, callback] of currentCallbacks) {
90390
+ try {
90391
+ callback(timestamp);
90392
+ } catch (error) {
90393
+ console.warn('[preview-worker] requestAnimationFrame callback error:', error);
90394
+ }
90395
+ }
90396
+ flushCanvasFrame(uid);
90397
+ };
90398
+ window.requestAnimationFrame = callback => {
90399
+ const id = nextId++;
90400
+ callbacks.set(id, callback);
90401
+ const handle = setTimeout(tick, FRAME_INTERVAL);
90402
+ addAnimationFrameHandle(uid, handle);
90403
+ return id;
90404
+ };
90405
+ window.cancelAnimationFrame = id => {
90406
+ callbacks.delete(id);
90407
+ };
90408
+ };
90409
+
90410
+ const patchCanvasElements = (document, uid) => {
90411
+ const canvasElements = document.querySelectorAll('canvas');
90412
+ if (canvasElements.length === 0) {
90413
+ return;
90414
+ }
90415
+ const instances = [];
90416
+ for (let i = 0; i < canvasElements.length; i++) {
90417
+ const element = canvasElements[i];
90418
+ const width = Number.parseInt(element.getAttribute('width') || '300', 10);
90419
+ const height = Number.parseInt(element.getAttribute('height') || '150', 10);
90420
+ const offscreenCanvas = new OffscreenCanvas(width, height);
90421
+ const dataId = String(i);
90422
+ const context = offscreenCanvas.getContext('2d');
90423
+ element.getContext = contextType => {
90424
+ if (contextType === '2d') {
90425
+ return context;
90426
+ }
90427
+ return undefined;
90428
+ };
90429
+ instances.push({
90430
+ dataId,
90431
+ element,
90432
+ offscreenCanvas
90433
+ });
90434
+ }
90435
+ set(uid, {
90436
+ animationFrameHandles: [],
90437
+ instances
90438
+ });
90439
+ };
90440
+
90345
90441
  /* eslint-disable prefer-destructuring */
90346
90442
 
90347
90443
  const updateContent = async (state, uri) => {
@@ -90367,12 +90463,14 @@ const updateContent = async (state, uri) => {
90367
90463
  document: happyDomDocument,
90368
90464
  window: happyDomWindow
90369
90465
  } = createWindow(content);
90466
+ patchCanvasElements(happyDomDocument, state.uid);
90467
+ overrideRequestAnimationFrame(happyDomWindow, state.uid);
90370
90468
  executeScripts(happyDomWindow, happyDomDocument, scripts);
90371
90469
  const elementMap = new Map();
90372
90470
  const serialized = serialize(happyDomDocument, elementMap);
90373
90471
  parsedDom = serialized.dom;
90374
90472
  css = serialized.css;
90375
- set(state.uid, {
90473
+ set$1(state.uid, {
90376
90474
  document: happyDomDocument,
90377
90475
  elementMap,
90378
90476
  window: happyDomWindow
@@ -90424,6 +90522,56 @@ const handleFileEdited = async state => {
90424
90522
  };
90425
90523
  };
90426
90524
 
90525
+ const dispatchInputEvent = (element, window) => {
90526
+ const inputEvent = new window.Event('input', {
90527
+ bubbles: true
90528
+ });
90529
+ dispatchEvent(element, inputEvent);
90530
+ };
90531
+
90532
+ const handleInput = (state, hdId, value) => {
90533
+ // console.log('input,', hdId, value)
90534
+ if (!hdId) {
90535
+ return state;
90536
+ }
90537
+ const happyDomInstance = get$1(state.uid);
90538
+ if (!happyDomInstance) {
90539
+ return state;
90540
+ }
90541
+ const element = happyDomInstance.elementMap.get(hdId);
90542
+ if (!element) {
90543
+ return state;
90544
+ }
90545
+
90546
+ // console.log({ element })
90547
+ // Update the element's value from the preview
90548
+ element.value = value;
90549
+ // Dispatch input event in happy-dom so event listeners fire
90550
+ dispatchInputEvent(element, happyDomInstance.window);
90551
+
90552
+ // Re-serialize the (potentially mutated) DOM
90553
+ const elementMap = new Map();
90554
+ const serialized = serialize(happyDomInstance.document, elementMap);
90555
+
90556
+ // Update happy-dom state with new element map
90557
+ set$1(state.uid, {
90558
+ document: happyDomInstance.document,
90559
+ elementMap,
90560
+ window: happyDomInstance.window
90561
+ });
90562
+ const parsedDom = serialized.dom;
90563
+ const {
90564
+ css
90565
+ } = serialized;
90566
+ const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
90567
+ return {
90568
+ ...state,
90569
+ css,
90570
+ parsedDom,
90571
+ parsedNodesChildNodeCount
90572
+ };
90573
+ };
90574
+
90427
90575
  const loadContent = async state => {
90428
90576
  // Try to register to receive editor change notifications from the editor worker.
90429
90577
  // Use dynamic access and ignore errors so this is safe in environments where
@@ -90511,6 +90659,7 @@ const renderCss = (oldState, newState) => {
90511
90659
  return ['Viewlet.setCss', uid, cssString];
90512
90660
  };
90513
90661
 
90662
+ const HandleInput = 4;
90514
90663
  const HandleClick = 11;
90515
90664
 
90516
90665
  const getEmptyPreviewDom = () => {
@@ -90543,6 +90692,7 @@ const getPreviewDom = state => {
90543
90692
  childCount: parsedNodesChildNodeCount,
90544
90693
  className: 'Viewlet Preview',
90545
90694
  onClick: HandleClick,
90695
+ onInput: HandleInput,
90546
90696
  type: Div$1
90547
90697
  }, ...parsedDom];
90548
90698
  }
@@ -90550,6 +90700,7 @@ const getPreviewDom = state => {
90550
90700
  childCount: 1,
90551
90701
  className: 'Viewlet Preview',
90552
90702
  onClick: HandleClick,
90703
+ onInput: HandleInput,
90553
90704
  type: Div$1
90554
90705
  }, {
90555
90706
  childCount: 1,
@@ -90608,8 +90759,8 @@ const render2 = (uid, diffResult) => {
90608
90759
  const {
90609
90760
  newState,
90610
90761
  oldState
90611
- } = get$1(uid);
90612
- set$1(uid, newState, newState);
90762
+ } = get$2(uid);
90763
+ set$2(uid, newState, newState);
90613
90764
  const commands = applyRender(oldState, newState, diffResult);
90614
90765
  return commands;
90615
90766
  };
@@ -90619,6 +90770,10 @@ const renderEventListeners = () => {
90619
90770
  capture: true,
90620
90771
  name: HandleClick,
90621
90772
  params: ['handleClick', 'event.target.dataset.id']
90773
+ }, {
90774
+ capture: true,
90775
+ name: HandleInput,
90776
+ params: ['handleInput', 'event.target.dataset.id', 'event.target.value']
90622
90777
  }];
90623
90778
  };
90624
90779
 
@@ -90675,6 +90830,7 @@ const commandMap = {
90675
90830
  'Preview.getCommandIds': getCommandIds,
90676
90831
  'Preview.handleClick': wrapCommand(handleClick),
90677
90832
  'Preview.handleFileEdited': wrapCommand(handleFileEdited),
90833
+ 'Preview.handleInput': wrapCommand(handleInput),
90678
90834
  'Preview.loadContent': wrapCommand(loadContent),
90679
90835
  'Preview.render2': render2,
90680
90836
  'Preview.renderEventListeners': renderEventListeners,
@@ -90690,12 +90846,12 @@ const listen = async () => {
90690
90846
  const rpc = await WebWorkerRpcClient.create({
90691
90847
  commandMap: commandMap
90692
90848
  });
90693
- set$2(rpc);
90849
+ set$3(rpc);
90694
90850
  const editorRpc = await LazyTransferMessagePortRpcParent.create({
90695
90851
  commandMap: {},
90696
90852
  send: port => sendMessagePortToEditorWorker(port, 9112)
90697
90853
  });
90698
- set$3(editorRpc);
90854
+ set$4(editorRpc);
90699
90855
  };
90700
90856
 
90701
90857
  const main = async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/preview-worker",
3
- "version": "2.1.0",
3
+ "version": "2.3.0",
4
4
  "description": "Preview Worker",
5
5
  "repository": {
6
6
  "type": "git",
@@ -11,7 +11,7 @@
11
11
  "type": "module",
12
12
  "main": "dist/previewWorkerMain.js",
13
13
  "dependencies": {
14
- "@lvce-editor/virtual-dom-worker": "^7.2.0",
14
+ "@lvce-editor/virtual-dom-worker": "^7.3.0",
15
15
  "happy-dom-without-node": "^14.12.3"
16
16
  }
17
17
  }