@lvce-editor/preview-worker 1.3.0 → 1.4.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.
@@ -417,6 +417,100 @@ const IpcChildWithModuleWorkerAndMessagePort$1 = {
417
417
  listen: listen$6,
418
418
  wrap: wrap$e
419
419
  };
420
+ const addListener = (emitter, type, callback) => {
421
+ if ('addEventListener' in emitter) {
422
+ emitter.addEventListener(type, callback);
423
+ } else {
424
+ emitter.on(type, callback);
425
+ }
426
+ };
427
+ const removeListener = (emitter, type, callback) => {
428
+ if ('removeEventListener' in emitter) {
429
+ emitter.removeEventListener(type, callback);
430
+ } else {
431
+ emitter.off(type, callback);
432
+ }
433
+ };
434
+ const getFirstEvent = (eventEmitter, eventMap) => {
435
+ const {
436
+ promise,
437
+ resolve
438
+ } = Promise.withResolvers();
439
+ const listenerMap = Object.create(null);
440
+ const cleanup = value => {
441
+ for (const event of Object.keys(eventMap)) {
442
+ removeListener(eventEmitter, event, listenerMap[event]);
443
+ }
444
+ resolve(value);
445
+ };
446
+ for (const [event, type] of Object.entries(eventMap)) {
447
+ const listener = event => {
448
+ cleanup({
449
+ event,
450
+ type
451
+ });
452
+ };
453
+ addListener(eventEmitter, event, listener);
454
+ listenerMap[event] = listener;
455
+ }
456
+ return promise;
457
+ };
458
+ const Message$1 = 3;
459
+ const create$5$1 = async ({
460
+ isMessagePortOpen,
461
+ messagePort
462
+ }) => {
463
+ if (!isMessagePort(messagePort)) {
464
+ throw new IpcError('port must be of type MessagePort');
465
+ }
466
+ if (isMessagePortOpen) {
467
+ return messagePort;
468
+ }
469
+ const eventPromise = getFirstEvent(messagePort, {
470
+ message: Message$1
471
+ });
472
+ messagePort.start();
473
+ const {
474
+ event,
475
+ type
476
+ } = await eventPromise;
477
+ if (type !== Message$1) {
478
+ throw new IpcError('Failed to wait for ipc message');
479
+ }
480
+ if (event.data !== readyMessage) {
481
+ throw new IpcError('unexpected first message');
482
+ }
483
+ return messagePort;
484
+ };
485
+ const signal$1 = messagePort => {
486
+ messagePort.start();
487
+ };
488
+ class IpcParentWithMessagePort extends Ipc {
489
+ getData = getData$2;
490
+ send(message) {
491
+ this._rawIpc.postMessage(message);
492
+ }
493
+ sendAndTransfer(message) {
494
+ const transfer = getTransferrables(message);
495
+ this._rawIpc.postMessage(message, transfer);
496
+ }
497
+ dispose() {
498
+ this._rawIpc.close();
499
+ }
500
+ onMessage(callback) {
501
+ this._rawIpc.addEventListener('message', callback);
502
+ }
503
+ onClose(callback) {}
504
+ }
505
+ const wrap$5 = messagePort => {
506
+ return new IpcParentWithMessagePort(messagePort);
507
+ };
508
+ const IpcParentWithMessagePort$1 = {
509
+ __proto__: null,
510
+ create: create$5$1,
511
+ signal: signal$1,
512
+ wrap: wrap$5
513
+ };
420
514
 
421
515
  const Two$1 = '2.0';
422
516
  const callbacks = Object.create(null);
@@ -632,7 +726,7 @@ const getErrorResponse = (id, error, preparePrettyError, logError) => {
632
726
  const errorProperty = getErrorProperty(error, prettyError);
633
727
  return create$1$1(id, errorProperty);
634
728
  };
635
- const create$3 = (message, result) => {
729
+ const create$4 = (message, result) => {
636
730
  return {
637
731
  jsonrpc: Two$1,
638
732
  id: message.id,
@@ -641,7 +735,7 @@ const create$3 = (message, result) => {
641
735
  };
642
736
  const getSuccessResponse = (message, result) => {
643
737
  const resultProperty = result ?? null;
644
- return create$3(message, resultProperty);
738
+ return create$4(message, resultProperty);
645
739
  };
646
740
  const getErrorResponseSimple = (id, error) => {
647
741
  return {
@@ -869,6 +963,86 @@ const listen$1 = async (module, options) => {
869
963
  const ipc = module.wrap(rawIpc);
870
964
  return ipc;
871
965
  };
966
+
967
+ /* eslint-disable @typescript-eslint/no-misused-promises */
968
+
969
+ const createSharedLazyRpc = factory => {
970
+ let rpcPromise;
971
+ const getOrCreate = () => {
972
+ if (!rpcPromise) {
973
+ rpcPromise = factory();
974
+ }
975
+ return rpcPromise;
976
+ };
977
+ return {
978
+ async dispose() {
979
+ const rpc = await getOrCreate();
980
+ await rpc.dispose();
981
+ },
982
+ async invoke(method, ...params) {
983
+ const rpc = await getOrCreate();
984
+ return rpc.invoke(method, ...params);
985
+ },
986
+ async invokeAndTransfer(method, ...params) {
987
+ const rpc = await getOrCreate();
988
+ return rpc.invokeAndTransfer(method, ...params);
989
+ },
990
+ async send(method, ...params) {
991
+ const rpc = await getOrCreate();
992
+ rpc.send(method, ...params);
993
+ }
994
+ };
995
+ };
996
+ const create$j = async ({
997
+ commandMap,
998
+ isMessagePortOpen,
999
+ send
1000
+ }) => {
1001
+ return createSharedLazyRpc(() => {
1002
+ return create$3({
1003
+ commandMap,
1004
+ isMessagePortOpen,
1005
+ send
1006
+ });
1007
+ });
1008
+ };
1009
+ const LazyTransferMessagePortRpcParent = {
1010
+ __proto__: null,
1011
+ create: create$j
1012
+ };
1013
+ const create$5 = async ({
1014
+ commandMap,
1015
+ isMessagePortOpen = true,
1016
+ messagePort
1017
+ }) => {
1018
+ // TODO create a commandMap per rpc instance
1019
+ register(commandMap);
1020
+ const rawIpc = await IpcParentWithMessagePort$1.create({
1021
+ isMessagePortOpen,
1022
+ messagePort
1023
+ });
1024
+ const ipc = IpcParentWithMessagePort$1.wrap(rawIpc);
1025
+ handleIpc(ipc);
1026
+ const rpc = createRpc(ipc);
1027
+ messagePort.start();
1028
+ return rpc;
1029
+ };
1030
+ const create$3 = async ({
1031
+ commandMap,
1032
+ isMessagePortOpen,
1033
+ send
1034
+ }) => {
1035
+ const {
1036
+ port1,
1037
+ port2
1038
+ } = new MessageChannel();
1039
+ await send(port1);
1040
+ return create$5({
1041
+ commandMap,
1042
+ isMessagePortOpen,
1043
+ messagePort: port2
1044
+ });
1045
+ };
872
1046
  const create$2$1 = async ({
873
1047
  commandMap
874
1048
  }) => {
@@ -903,15 +1077,25 @@ const createMockRpc = ({
903
1077
  return mockRpc;
904
1078
  };
905
1079
 
1080
+ const Button$1 = 1;
906
1081
  const Div$1 = 4;
907
1082
  const H1$1 = 5;
1083
+ const Input$1 = 6;
908
1084
  const Span$1 = 8;
1085
+ const Table$1 = 9;
1086
+ const TBody$1 = 10;
1087
+ const Td$1 = 11;
909
1088
  const Text$1 = 12;
1089
+ const Th$1 = 13;
1090
+ const THead$1 = 14;
1091
+ const Tr$1 = 15;
910
1092
  const Img$1 = 17;
1093
+ const Del$1 = 21;
911
1094
  const H2$1 = 22;
912
1095
  const H3$1 = 23;
913
1096
  const H4$1 = 24;
914
1097
  const H5$1 = 25;
1098
+ const H6$1 = 26;
915
1099
  const Article$1 = 27;
916
1100
  const Aside$1 = 28;
917
1101
  const Footer$1 = 29;
@@ -935,17 +1119,26 @@ const Cite$1 = 56;
935
1119
  const Data$1 = 57;
936
1120
  const Time$1 = 58;
937
1121
  const Tfoot$1 = 59;
1122
+ const Ul$1 = 60;
1123
+ const TextArea$1 = 62;
1124
+ const Select$1 = 63;
1125
+ const Option$1 = 64;
1126
+ const Code$1 = 65;
1127
+ const Label$1 = 66;
1128
+ const Dt$1 = 67;
1129
+ const Iframe$1 = 68;
938
1130
  const Reference = 100;
939
1131
 
940
1132
  const TargetName = 'event.target.name';
941
1133
 
1134
+ const EditorWorker = 99;
942
1135
  const RendererWorker = 1;
943
1136
 
944
1137
  const SetDom2 = 'Viewlet.setDom2';
945
1138
  const SetPatches = 'Viewlet.setPatches';
946
1139
 
947
1140
  const rpcs = Object.create(null);
948
- const set$2 = (id, rpc) => {
1141
+ const set$3 = (id, rpc) => {
949
1142
  rpcs[id] = rpc;
950
1143
  };
951
1144
  const get$1 = id => {
@@ -978,7 +1171,7 @@ const create$2 = rpcId => {
978
1171
  const mockRpc = createMockRpc({
979
1172
  commandMap
980
1173
  });
981
- set$2(rpcId, mockRpc);
1174
+ set$3(rpcId, mockRpc);
982
1175
  // @ts-ignore
983
1176
  mockRpc[Symbol.dispose] = () => {
984
1177
  remove(rpcId);
@@ -987,15 +1180,25 @@ const create$2 = rpcId => {
987
1180
  return mockRpc;
988
1181
  },
989
1182
  set(rpc) {
990
- set$2(rpcId, rpc);
1183
+ set$3(rpcId, rpc);
991
1184
  }
992
1185
  };
993
1186
  };
994
1187
 
1188
+ const {
1189
+ invoke: invoke$1,
1190
+ set: set$2
1191
+ } = create$2(EditorWorker);
1192
+
995
1193
  const {
996
1194
  invoke,
1195
+ invokeAndTransfer,
997
1196
  set: set$1
998
1197
  } = create$2(RendererWorker);
1198
+ const sendMessagePortToEditorWorker = async (port, rpcId) => {
1199
+ const command = 'HandleMessagePort.handleMessagePort';
1200
+ await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToEditorWorker', port, command, rpcId);
1201
+ };
999
1202
  const readFile = async uri => {
1000
1203
  return invoke('FileSystem.readFile', uri);
1001
1204
  };
@@ -1092,6 +1295,7 @@ const terminate = () => {
1092
1295
  const {
1093
1296
  get,
1094
1297
  getCommandIds,
1298
+ getKeys: getKeys$1,
1095
1299
  registerCommands,
1096
1300
  set,
1097
1301
  wrapCommand,
@@ -1106,6 +1310,7 @@ const create = (uid, uri, x, y, width, height, platform, assetDir) => {
1106
1310
  errorMessage: '',
1107
1311
  initial: true,
1108
1312
  parsedDom: [],
1313
+ parsedNodesChildNodeCount: 0,
1109
1314
  platform,
1110
1315
  uid,
1111
1316
  uri,
@@ -1115,7 +1320,7 @@ const create = (uid, uri, x, y, width, height, platform, assetDir) => {
1115
1320
  };
1116
1321
 
1117
1322
  const isEqual = (oldState, newState) => {
1118
- return oldState.warningCount === newState.warningCount && oldState.initial === newState.initial && oldState.content === newState.content && oldState.parsedDom === newState.parsedDom;
1323
+ return oldState.warningCount === newState.warningCount && oldState.initial === newState.initial && oldState.content === newState.content && oldState.parsedDom === newState.parsedDom && oldState.parsedNodesChildNodeCount === newState.parsedNodesChildNodeCount;
1119
1324
  };
1120
1325
 
1121
1326
  const RenderItems = 4;
@@ -1471,6 +1676,25 @@ const Cite = 'cite';
1471
1676
  const Data = 'data';
1472
1677
  const Time = 'time';
1473
1678
  const Tfoot = 'tfoot';
1679
+ const Button = 'button';
1680
+ const Input = 'input';
1681
+ const Code = 'code';
1682
+ const Form = 'form';
1683
+ const Table = 'table';
1684
+ const TBody = 'tbody';
1685
+ const THead = 'thead';
1686
+ const Tr = 'tr';
1687
+ const Td = 'td';
1688
+ const Th = 'th';
1689
+ const Ul = 'ul';
1690
+ const TextArea = 'textarea';
1691
+ const Select = 'select';
1692
+ const Option = 'option';
1693
+ const Label = 'label';
1694
+ const Dt = 'dt';
1695
+ const Iframe = 'iframe';
1696
+ const Del = 'del';
1697
+ const H6 = 'h6';
1474
1698
 
1475
1699
  const getVirtualDomTag = text => {
1476
1700
  switch (text) {
@@ -1484,22 +1708,32 @@ const getVirtualDomTag = text => {
1484
1708
  return Aside$1;
1485
1709
  case Br:
1486
1710
  return Br$1;
1711
+ case Button:
1712
+ return Button$1;
1487
1713
  case Cite:
1488
1714
  return Cite$1;
1715
+ case Code:
1716
+ return Code$1;
1489
1717
  case Data:
1490
1718
  return Data$1;
1491
1719
  case Dd:
1492
1720
  return Dd$1;
1721
+ case Del:
1722
+ return Del$1;
1493
1723
  case Div:
1494
1724
  return Div$1;
1495
1725
  case Dl:
1496
1726
  return Dl$1;
1727
+ case Dt:
1728
+ return Dt$1;
1497
1729
  case Figcaption:
1498
1730
  return Figcaption$1;
1499
1731
  case Figure:
1500
1732
  return Figure$1;
1501
1733
  case Footer:
1502
1734
  return Footer$1;
1735
+ case Form:
1736
+ return Div$1;
1503
1737
  case H1:
1504
1738
  return H1$1;
1505
1739
  case H2:
@@ -1510,18 +1744,28 @@ const getVirtualDomTag = text => {
1510
1744
  return H4$1;
1511
1745
  case H5:
1512
1746
  return H5$1;
1747
+ case H6:
1748
+ return H6$1;
1513
1749
  case Header:
1514
1750
  return Header$1;
1515
1751
  case Hr:
1516
1752
  return Hr$1;
1753
+ case Iframe:
1754
+ return Iframe$1;
1517
1755
  case Img:
1518
1756
  return Img$1;
1757
+ case Input:
1758
+ return Input$1;
1759
+ case Label:
1760
+ return Label$1;
1519
1761
  case Li:
1520
1762
  return Li$1;
1521
1763
  case Nav:
1522
1764
  return Nav$1;
1523
1765
  case Ol:
1524
1766
  return Ol$1;
1767
+ case Option:
1768
+ return Option$1;
1525
1769
  case P:
1526
1770
  return P$1;
1527
1771
  case Pre:
@@ -1530,12 +1774,30 @@ const getVirtualDomTag = text => {
1530
1774
  return Search$1;
1531
1775
  case Section:
1532
1776
  return Section$1;
1777
+ case Select:
1778
+ return Select$1;
1533
1779
  case Span:
1534
1780
  return Span$1;
1781
+ case Table:
1782
+ return Table$1;
1783
+ case TBody:
1784
+ return TBody$1;
1785
+ case Td:
1786
+ return Td$1;
1787
+ case TextArea:
1788
+ return TextArea$1;
1535
1789
  case Tfoot:
1536
1790
  return Tfoot$1;
1791
+ case Th:
1792
+ return Th$1;
1793
+ case THead:
1794
+ return THead$1;
1537
1795
  case Time:
1538
1796
  return Time$1;
1797
+ case Tr:
1798
+ return Tr$1;
1799
+ case Ul:
1800
+ return Ul$1;
1539
1801
  default:
1540
1802
  return Div$1;
1541
1803
  }
@@ -1566,7 +1828,10 @@ const CommentStart = 21;
1566
1828
 
1567
1829
  const isSelfClosingTag = tag => {
1568
1830
  switch (tag) {
1831
+ case Br:
1832
+ case Hr:
1569
1833
  case Img:
1834
+ case Input:
1570
1835
  return true;
1571
1836
  default:
1572
1837
  return false;
@@ -1847,44 +2112,159 @@ const parseHtml = (html, allowedAttributes) => {
1847
2112
  let current = root;
1848
2113
  const stack = [root];
1849
2114
  let attributeName = '';
2115
+ let lastTagWasSelfClosing = false;
1850
2116
  for (const token of tokens) {
1851
2117
  switch (token.type) {
1852
2118
  case AttributeName:
1853
2119
  attributeName = token.text;
1854
- if (attributeName === 'class') {
1855
- attributeName = 'className';
1856
- }
1857
2120
  break;
1858
2121
  case AttributeValue:
1859
2122
  if (allowedAttributes.includes(attributeName)) {
1860
- current[attributeName] = token.text;
2123
+ const finalAttributeName = attributeName === 'class' ? 'className' : attributeName;
2124
+ current[finalAttributeName] = token.text;
1861
2125
  }
1862
2126
  attributeName = '';
1863
2127
  break;
2128
+ case ClosingAngleBracket:
2129
+ // Handle boolean attributes (attributes without values)
2130
+ if (attributeName && allowedAttributes.includes(attributeName)) {
2131
+ const finalAttributeName = attributeName === 'class' ? 'className' : attributeName;
2132
+ current[finalAttributeName] = attributeName;
2133
+ }
2134
+ attributeName = '';
2135
+ // Return to parent if the current tag is self-closing
2136
+ if (lastTagWasSelfClosing) {
2137
+ current = stack.at(-1) || root;
2138
+ lastTagWasSelfClosing = false;
2139
+ }
2140
+ break;
1864
2141
  case Content:
1865
2142
  current.childCount++;
1866
2143
  dom.push(text(parseText(token.text)));
1867
2144
  break;
1868
2145
  case TagNameEnd:
1869
- stack.pop();
2146
+ if (stack.length > 1) {
2147
+ stack.pop();
2148
+ }
1870
2149
  current = stack.at(-1) || root;
1871
2150
  break;
1872
2151
  case TagNameStart:
1873
2152
  current.childCount++;
1874
- current = {
2153
+ const newNode = {
1875
2154
  childCount: 0,
1876
2155
  type: getVirtualDomTag(token.text)
1877
2156
  };
1878
- dom.push(current);
1879
- if (!isSelfClosingTag(token.text)) {
2157
+ dom.push(newNode);
2158
+ current = newNode;
2159
+ lastTagWasSelfClosing = isSelfClosingTag(token.text);
2160
+ if (!lastTagWasSelfClosing) {
1880
2161
  stack.push(current);
1881
2162
  }
1882
2163
  break;
2164
+ case WhitespaceInsideOpeningTag:
2165
+ // Handle boolean attributes (attributes without values)
2166
+ if (attributeName && allowedAttributes.includes(attributeName)) {
2167
+ const finalAttributeName = attributeName === 'class' ? 'className' : attributeName;
2168
+ current[finalAttributeName] = attributeName;
2169
+ }
2170
+ attributeName = '';
2171
+ break;
1883
2172
  }
1884
2173
  }
2174
+ try {
2175
+ Object.defineProperty(dom, 'rootChildCount', {
2176
+ configurable: true,
2177
+ enumerable: false,
2178
+ value: root.childCount
2179
+ });
2180
+ } catch {
2181
+ dom.rootChildCount = root.childCount;
2182
+ }
1885
2183
  return dom;
1886
2184
  };
1887
2185
 
2186
+ const handleEditorChanged = async () => {
2187
+ // Get all preview instance keys
2188
+ const previewKeys = getKeys$1();
2189
+
2190
+ // Get all editor keys from the editor worker
2191
+ const editorKeys = await invoke$1('Editor.getKeys');
2192
+
2193
+ // For each preview instance
2194
+ for (const previewUid of previewKeys) {
2195
+ const {
2196
+ newState: state
2197
+ } = get(previewUid);
2198
+
2199
+ // Skip if no URI is set
2200
+ if (!state.uri) {
2201
+ continue;
2202
+ }
2203
+
2204
+ // Find the editor that matches our preview's URI
2205
+ let matchingEditorUid = null;
2206
+ for (const editorKey of editorKeys) {
2207
+ const editorUid = Number.parseFloat(editorKey);
2208
+ const editorUri = await invoke$1('Editor.getUri', editorUid);
2209
+ if (editorUri === state.uri) {
2210
+ matchingEditorUid = editorUid;
2211
+ break;
2212
+ }
2213
+ }
2214
+
2215
+ // If we found a matching editor, get its text and update the preview
2216
+ if (matchingEditorUid !== null) {
2217
+ try {
2218
+ const content = await invoke$1('Editor.getText', matchingEditorUid);
2219
+ const parsedDom = parseHtml(content, []);
2220
+ const updatedState = {
2221
+ ...state,
2222
+ content,
2223
+ errorMessage: '',
2224
+ parsedDom
2225
+ };
2226
+ set(previewUid, state, updatedState);
2227
+ } catch (error) {
2228
+ // If getting text fails, update with error message
2229
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
2230
+ const updatedState = {
2231
+ ...state,
2232
+ content: '',
2233
+ errorMessage,
2234
+ parsedDom: []
2235
+ };
2236
+ set(previewUid, state, updatedState);
2237
+ }
2238
+ }
2239
+ }
2240
+
2241
+ // Rerender all previews after updates are complete
2242
+ await invoke('Preview.rerender');
2243
+ };
2244
+
2245
+ const getParsedNodesChildNodeCount = parsedDom => {
2246
+ array(parsedDom);
2247
+ const rootCountFromParse = parsedDom.rootChildCount;
2248
+ if (typeof rootCountFromParse === 'number') {
2249
+ return rootCountFromParse;
2250
+ }
2251
+ let rootChildCount = 0;
2252
+ let i = 0;
2253
+ while (i < parsedDom.length) {
2254
+ rootChildCount++;
2255
+
2256
+ // skip the entire subtree of the current node
2257
+ let toSkip = parsedDom[i].childCount;
2258
+ i++;
2259
+ while (toSkip > 0 && i < parsedDom.length) {
2260
+ toSkip -= 1;
2261
+ toSkip += parsedDom[i].childCount;
2262
+ i++;
2263
+ }
2264
+ }
2265
+ return rootChildCount;
2266
+ };
2267
+
1888
2268
  const updateContent = async (state, uri) => {
1889
2269
  try {
1890
2270
  // Read the file content using RendererWorker RPC
@@ -1893,10 +2273,12 @@ const updateContent = async (state, uri) => {
1893
2273
 
1894
2274
  // Parse the content into virtual DOM
1895
2275
  const parsedDom = parseHtml(content, []);
2276
+ const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
1896
2277
  return {
1897
2278
  content,
1898
2279
  errorMessage: '',
1899
- parsedDom
2280
+ parsedDom,
2281
+ parsedNodesChildNodeCount
1900
2282
  };
1901
2283
  } catch (error) {
1902
2284
  // If file reading or parsing fails, return empty content and parsedDom with error message
@@ -1904,7 +2286,8 @@ const updateContent = async (state, uri) => {
1904
2286
  return {
1905
2287
  content: '',
1906
2288
  errorMessage,
1907
- parsedDom: []
2289
+ parsedDom: [],
2290
+ parsedNodesChildNodeCount: 0
1908
2291
  };
1909
2292
  }
1910
2293
  };
@@ -1913,21 +2296,50 @@ const handleFileEdited = async state => {
1913
2296
  const {
1914
2297
  content,
1915
2298
  errorMessage,
1916
- parsedDom
2299
+ parsedDom,
2300
+ parsedNodesChildNodeCount
1917
2301
  } = await updateContent(state, state.uri);
1918
2302
  return {
1919
2303
  ...state,
1920
2304
  content,
1921
2305
  errorMessage,
1922
- parsedDom
2306
+ parsedDom,
2307
+ parsedNodesChildNodeCount
1923
2308
  };
1924
2309
  };
1925
2310
 
1926
2311
  const loadContent = async state => {
2312
+ // Try to register to receive editor change notifications from the editor worker.
2313
+ // Use dynamic access and ignore errors so this is safe in environments where
2314
+ // the EditorWorker / ListenerType are not available (e.g. unit tests).
2315
+ const EditorChange = 1;
2316
+ const rpcId = 9112;
2317
+ try {
2318
+ await invoke$1('Listener.register', EditorChange, rpcId);
2319
+ } catch (error) {
2320
+ console.error(error);
2321
+ }
2322
+
2323
+ // Read and parse file contents if we have a URI
2324
+ const {
2325
+ content,
2326
+ errorMessage,
2327
+ parsedDom,
2328
+ parsedNodesChildNodeCount
2329
+ } = state.uri ? await updateContent(state, state.uri) : {
2330
+ content: state.content,
2331
+ errorMessage: state.errorMessage,
2332
+ parsedDom: state.parsedDom,
2333
+ parsedNodesChildNodeCount: state.parsedNodesChildNodeCount
2334
+ };
1927
2335
  return {
1928
2336
  ...state,
2337
+ content,
1929
2338
  errorCount: 0,
2339
+ errorMessage,
1930
2340
  initial: false,
2341
+ parsedDom,
2342
+ parsedNodesChildNodeCount,
1931
2343
  warningCount: 1
1932
2344
  };
1933
2345
  };
@@ -1947,18 +2359,22 @@ const getEmptyPreviewDom = () => {
1947
2359
  };
1948
2360
 
1949
2361
  const getPreviewDom = state => {
1950
- if (!state.uri) {
2362
+ const {
2363
+ parsedDom,
2364
+ parsedNodesChildNodeCount,
2365
+ uri
2366
+ } = state;
2367
+ if (!uri) {
1951
2368
  return getEmptyPreviewDom();
1952
2369
  }
1953
2370
 
1954
2371
  // If parsedDom is available, render it as children of the wrapper
1955
- if (state.parsedDom && state.parsedDom.length > 0) {
2372
+ if (parsedDom && parsedDom.length > 0) {
1956
2373
  return [{
1957
- childCount: 1,
1958
- // TODO
2374
+ childCount: parsedNodesChildNodeCount,
1959
2375
  className: 'Viewlet Preview',
1960
2376
  type: Div$1
1961
- }, ...state.parsedDom];
2377
+ }, ...parsedDom];
1962
2378
  }
1963
2379
  return [{
1964
2380
  childCount: 1,
@@ -2034,6 +2450,18 @@ const renderEventListeners = () => {
2034
2450
  }];
2035
2451
  };
2036
2452
 
2453
+ const rerender = state => {
2454
+ // Create a new copy of parsedDom array to trigger diff
2455
+ const parsedDom = [...state.parsedDom];
2456
+
2457
+ // Return a new state object with the copied parsedDom
2458
+ // This will cause DiffItems.isEqual to return false since parsedDom reference changed
2459
+ return {
2460
+ ...state,
2461
+ parsedDom
2462
+ };
2463
+ };
2464
+
2037
2465
  const resize = (state, dimensions) => {
2038
2466
  return {
2039
2467
  ...state,
@@ -2051,18 +2479,21 @@ const setUri = async (state, uri) => {
2051
2479
  const {
2052
2480
  content,
2053
2481
  errorMessage,
2054
- parsedDom
2482
+ parsedDom,
2483
+ parsedNodesChildNodeCount
2055
2484
  } = await updateContent(state, uri);
2056
2485
  return {
2057
2486
  ...state,
2058
2487
  content,
2059
2488
  errorMessage,
2060
2489
  parsedDom,
2490
+ parsedNodesChildNodeCount,
2061
2491
  uri
2062
2492
  };
2063
2493
  };
2064
2494
 
2065
2495
  const commandMap = {
2496
+ handleEditorChanged: handleEditorChanged,
2066
2497
  'Preview.create': create,
2067
2498
  'Preview.diff2': diff2,
2068
2499
  'Preview.getCommandIds': getCommandIds,
@@ -2070,6 +2501,7 @@ const commandMap = {
2070
2501
  'Preview.loadContent': wrapCommand(loadContent),
2071
2502
  'Preview.render2': render2,
2072
2503
  'Preview.renderEventListeners': renderEventListeners,
2504
+ 'Preview.rerender': wrapCommand(rerender),
2073
2505
  'Preview.resize': wrapCommand(resize),
2074
2506
  'Preview.saveState': wrapGetter(saveState),
2075
2507
  'Preview.setUri': wrapCommand(setUri),
@@ -2082,6 +2514,11 @@ const listen = async () => {
2082
2514
  commandMap: commandMap
2083
2515
  });
2084
2516
  set$1(rpc);
2517
+ const editorRpc = await LazyTransferMessagePortRpcParent.create({
2518
+ commandMap: {},
2519
+ send: port => sendMessagePortToEditorWorker(port, 9112)
2520
+ });
2521
+ set$2(editorRpc);
2085
2522
  };
2086
2523
 
2087
2524
  const main = async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/preview-worker",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Preview Worker",
5
5
  "repository": {
6
6
  "type": "git",