@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.
- package/dist/previewWorkerMain.js +461 -24
- package/package.json +1 -1
|
@@ -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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
2153
|
+
const newNode = {
|
|
1875
2154
|
childCount: 0,
|
|
1876
2155
|
type: getVirtualDomTag(token.text)
|
|
1877
2156
|
};
|
|
1878
|
-
dom.push(
|
|
1879
|
-
|
|
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
|
-
|
|
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 (
|
|
2372
|
+
if (parsedDom && parsedDom.length > 0) {
|
|
1956
2373
|
return [{
|
|
1957
|
-
childCount:
|
|
1958
|
-
// TODO
|
|
2374
|
+
childCount: parsedNodesChildNodeCount,
|
|
1959
2375
|
className: 'Viewlet Preview',
|
|
1960
2376
|
type: Div$1
|
|
1961
|
-
}, ...
|
|
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 () => {
|