@lvce-editor/preview-sandbox-worker 1.1.0 → 1.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.
- package/dist/previewSandBoxWorkerMain.js +343 -1957
- package/package.json +1 -1
|
@@ -96,12 +96,6 @@ const array = value => {
|
|
|
96
96
|
throw new AssertionError('expected value to be of type array');
|
|
97
97
|
}
|
|
98
98
|
};
|
|
99
|
-
const string = value => {
|
|
100
|
-
const type = getType(value);
|
|
101
|
-
if (type !== String$1) {
|
|
102
|
-
throw new AssertionError('expected value to be of type string');
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
99
|
|
|
106
100
|
const isMessagePort = value => {
|
|
107
101
|
return value && value instanceof MessagePort;
|
|
@@ -514,7 +508,7 @@ const IpcParentWithMessagePort$1 = {
|
|
|
514
508
|
|
|
515
509
|
const Two$1 = '2.0';
|
|
516
510
|
const callbacks$1 = Object.create(null);
|
|
517
|
-
const get$
|
|
511
|
+
const get$2 = id => {
|
|
518
512
|
return callbacks$1[id];
|
|
519
513
|
};
|
|
520
514
|
const remove$1 = id => {
|
|
@@ -663,7 +657,7 @@ const warn = (...args) => {
|
|
|
663
657
|
console.warn(...args);
|
|
664
658
|
};
|
|
665
659
|
const resolve = (id, response) => {
|
|
666
|
-
const fn = get$
|
|
660
|
+
const fn = get$2(id);
|
|
667
661
|
if (!fn) {
|
|
668
662
|
console.log(response);
|
|
669
663
|
warn(`callback ${id} may already be disposed`);
|
|
@@ -713,7 +707,7 @@ const getErrorProperty = (error, prettyError) => {
|
|
|
713
707
|
}
|
|
714
708
|
};
|
|
715
709
|
};
|
|
716
|
-
const create$1
|
|
710
|
+
const create$1 = (id, error) => {
|
|
717
711
|
return {
|
|
718
712
|
jsonrpc: Two$1,
|
|
719
713
|
id,
|
|
@@ -724,9 +718,9 @@ const getErrorResponse = (id, error, preparePrettyError, logError) => {
|
|
|
724
718
|
const prettyError = preparePrettyError(error);
|
|
725
719
|
logError(error, prettyError);
|
|
726
720
|
const errorProperty = getErrorProperty(error, prettyError);
|
|
727
|
-
return create$1
|
|
721
|
+
return create$1(id, errorProperty);
|
|
728
722
|
};
|
|
729
|
-
const create$
|
|
723
|
+
const create$3 = (message, result) => {
|
|
730
724
|
return {
|
|
731
725
|
jsonrpc: Two$1,
|
|
732
726
|
id: message.id,
|
|
@@ -735,7 +729,7 @@ const create$4 = (message, result) => {
|
|
|
735
729
|
};
|
|
736
730
|
const getSuccessResponse = (message, result) => {
|
|
737
731
|
const resultProperty = result ?? null;
|
|
738
|
-
return create$
|
|
732
|
+
return create$3(message, resultProperty);
|
|
739
733
|
};
|
|
740
734
|
const getErrorResponseSimple = (id, error) => {
|
|
741
735
|
return {
|
|
@@ -963,53 +957,6 @@ const listen$1 = async (module, options) => {
|
|
|
963
957
|
const ipc = module.wrap(rawIpc);
|
|
964
958
|
return ipc;
|
|
965
959
|
};
|
|
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
960
|
const create$5 = async ({
|
|
1014
961
|
commandMap,
|
|
1015
962
|
isMessagePortOpen = true,
|
|
@@ -1031,23 +978,7 @@ const PlainMessagePortRpc = {
|
|
|
1031
978
|
__proto__: null,
|
|
1032
979
|
create: create$5
|
|
1033
980
|
};
|
|
1034
|
-
const create$
|
|
1035
|
-
commandMap,
|
|
1036
|
-
isMessagePortOpen,
|
|
1037
|
-
send
|
|
1038
|
-
}) => {
|
|
1039
|
-
const {
|
|
1040
|
-
port1,
|
|
1041
|
-
port2
|
|
1042
|
-
} = new MessageChannel();
|
|
1043
|
-
await send(port1);
|
|
1044
|
-
return create$5({
|
|
1045
|
-
commandMap,
|
|
1046
|
-
isMessagePortOpen,
|
|
1047
|
-
messagePort: port2
|
|
1048
|
-
});
|
|
1049
|
-
};
|
|
1050
|
-
const create$2$1 = async ({
|
|
981
|
+
const create$2 = async ({
|
|
1051
982
|
commandMap
|
|
1052
983
|
}) => {
|
|
1053
984
|
// TODO create a commandMap per rpc instance
|
|
@@ -1059,7 +990,7 @@ const create$2$1 = async ({
|
|
|
1059
990
|
};
|
|
1060
991
|
const WebWorkerRpcClient = {
|
|
1061
992
|
__proto__: null,
|
|
1062
|
-
create: create$2
|
|
993
|
+
create: create$2
|
|
1063
994
|
};
|
|
1064
995
|
const createMockRpc = ({
|
|
1065
996
|
commandMap
|
|
@@ -1089,7 +1020,7 @@ const Span$1 = 8;
|
|
|
1089
1020
|
const Table$1 = 9;
|
|
1090
1021
|
const TBody$1 = 10;
|
|
1091
1022
|
const Td$1 = 11;
|
|
1092
|
-
const Text
|
|
1023
|
+
const Text = 12;
|
|
1093
1024
|
const Th$1 = 13;
|
|
1094
1025
|
const THead$1 = 14;
|
|
1095
1026
|
const Tr$1 = 15;
|
|
@@ -1136,17 +1067,13 @@ const Html = 73;
|
|
|
1136
1067
|
const Canvas$1 = 77;
|
|
1137
1068
|
const Reference = 100;
|
|
1138
1069
|
|
|
1139
|
-
const EditorWorker = 99;
|
|
1140
1070
|
const RendererWorker = 1;
|
|
1141
1071
|
|
|
1142
|
-
const SetDom2 = 'Viewlet.setDom2';
|
|
1143
|
-
const SetPatches = 'Viewlet.setPatches';
|
|
1144
|
-
|
|
1145
1072
|
const rpcs = Object.create(null);
|
|
1146
|
-
const set$
|
|
1073
|
+
const set$4 = (id, rpc) => {
|
|
1147
1074
|
rpcs[id] = rpc;
|
|
1148
1075
|
};
|
|
1149
|
-
const get$
|
|
1076
|
+
const get$1 = id => {
|
|
1150
1077
|
return rpcs[id];
|
|
1151
1078
|
};
|
|
1152
1079
|
const remove = id => {
|
|
@@ -1154,21 +1081,21 @@ const remove = id => {
|
|
|
1154
1081
|
};
|
|
1155
1082
|
|
|
1156
1083
|
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
1157
|
-
const create
|
|
1084
|
+
const create = rpcId => {
|
|
1158
1085
|
return {
|
|
1159
1086
|
async dispose() {
|
|
1160
|
-
const rpc = get$
|
|
1087
|
+
const rpc = get$1(rpcId);
|
|
1161
1088
|
await rpc.dispose();
|
|
1162
1089
|
},
|
|
1163
1090
|
// @ts-ignore
|
|
1164
1091
|
invoke(method, ...params) {
|
|
1165
|
-
const rpc = get$
|
|
1092
|
+
const rpc = get$1(rpcId);
|
|
1166
1093
|
// @ts-ignore
|
|
1167
1094
|
return rpc.invoke(method, ...params);
|
|
1168
1095
|
},
|
|
1169
1096
|
// @ts-ignore
|
|
1170
1097
|
invokeAndTransfer(method, ...params) {
|
|
1171
|
-
const rpc = get$
|
|
1098
|
+
const rpc = get$1(rpcId);
|
|
1172
1099
|
// @ts-ignore
|
|
1173
1100
|
return rpc.invokeAndTransfer(method, ...params);
|
|
1174
1101
|
},
|
|
@@ -1176,7 +1103,7 @@ const create$2 = rpcId => {
|
|
|
1176
1103
|
const mockRpc = createMockRpc({
|
|
1177
1104
|
commandMap
|
|
1178
1105
|
});
|
|
1179
|
-
set$
|
|
1106
|
+
set$4(rpcId, mockRpc);
|
|
1180
1107
|
// @ts-ignore
|
|
1181
1108
|
mockRpc[Symbol.dispose] = () => {
|
|
1182
1109
|
remove(rpcId);
|
|
@@ -1185,202 +1112,27 @@ const create$2 = rpcId => {
|
|
|
1185
1112
|
return mockRpc;
|
|
1186
1113
|
},
|
|
1187
1114
|
set(rpc) {
|
|
1188
|
-
set$
|
|
1115
|
+
set$4(rpcId, rpc);
|
|
1189
1116
|
}
|
|
1190
1117
|
};
|
|
1191
1118
|
};
|
|
1192
1119
|
|
|
1193
1120
|
const {
|
|
1194
1121
|
invoke: invoke$1,
|
|
1195
|
-
set: set$
|
|
1196
|
-
} = create
|
|
1122
|
+
set: set$3
|
|
1123
|
+
} = create(3211);
|
|
1197
1124
|
|
|
1198
1125
|
const {
|
|
1199
1126
|
invoke,
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
} = create$2(RendererWorker);
|
|
1203
|
-
const sendMessagePortToEditorWorker = async (port, rpcId) => {
|
|
1204
|
-
const command = 'HandleMessagePort.handleMessagePort';
|
|
1205
|
-
await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToEditorWorker', port, command, rpcId);
|
|
1206
|
-
};
|
|
1207
|
-
const readFile = async uri => {
|
|
1208
|
-
return invoke('FileSystem.readFile', uri);
|
|
1209
|
-
};
|
|
1127
|
+
set: set$2
|
|
1128
|
+
} = create(RendererWorker);
|
|
1210
1129
|
|
|
1211
|
-
const toCommandId = key => {
|
|
1212
|
-
const dotIndex = key.indexOf('.');
|
|
1213
|
-
return key.slice(dotIndex + 1);
|
|
1214
|
-
};
|
|
1215
|
-
const create$1 = () => {
|
|
1216
|
-
const states = Object.create(null);
|
|
1217
|
-
const commandMapRef = {};
|
|
1218
|
-
return {
|
|
1219
|
-
clear() {
|
|
1220
|
-
for (const key of Object.keys(states)) {
|
|
1221
|
-
delete states[key];
|
|
1222
|
-
}
|
|
1223
|
-
},
|
|
1224
|
-
diff(uid, modules, numbers) {
|
|
1225
|
-
const {
|
|
1226
|
-
newState,
|
|
1227
|
-
oldState
|
|
1228
|
-
} = states[uid];
|
|
1229
|
-
const diffResult = [];
|
|
1230
|
-
for (let i = 0; i < modules.length; i++) {
|
|
1231
|
-
const fn = modules[i];
|
|
1232
|
-
if (!fn(oldState, newState)) {
|
|
1233
|
-
diffResult.push(numbers[i]);
|
|
1234
|
-
}
|
|
1235
|
-
}
|
|
1236
|
-
return diffResult;
|
|
1237
|
-
},
|
|
1238
|
-
dispose(uid) {
|
|
1239
|
-
delete states[uid];
|
|
1240
|
-
},
|
|
1241
|
-
get(uid) {
|
|
1242
|
-
return states[uid];
|
|
1243
|
-
},
|
|
1244
|
-
getCommandIds() {
|
|
1245
|
-
const keys = Object.keys(commandMapRef);
|
|
1246
|
-
const ids = keys.map(toCommandId);
|
|
1247
|
-
return ids;
|
|
1248
|
-
},
|
|
1249
|
-
getKeys() {
|
|
1250
|
-
return Object.keys(states).map(key => {
|
|
1251
|
-
return Number.parseInt(key);
|
|
1252
|
-
});
|
|
1253
|
-
},
|
|
1254
|
-
registerCommands(commandMap) {
|
|
1255
|
-
Object.assign(commandMapRef, commandMap);
|
|
1256
|
-
},
|
|
1257
|
-
set(uid, oldState, newState) {
|
|
1258
|
-
states[uid] = {
|
|
1259
|
-
newState,
|
|
1260
|
-
oldState
|
|
1261
|
-
};
|
|
1262
|
-
},
|
|
1263
|
-
wrapCommand(fn) {
|
|
1264
|
-
const wrapped = async (uid, ...args) => {
|
|
1265
|
-
const {
|
|
1266
|
-
newState,
|
|
1267
|
-
oldState
|
|
1268
|
-
} = states[uid];
|
|
1269
|
-
const newerState = await fn(newState, ...args);
|
|
1270
|
-
if (oldState === newerState || newState === newerState) {
|
|
1271
|
-
return;
|
|
1272
|
-
}
|
|
1273
|
-
const latestOld = states[uid];
|
|
1274
|
-
const latestNew = {
|
|
1275
|
-
...latestOld.newState,
|
|
1276
|
-
...newerState
|
|
1277
|
-
};
|
|
1278
|
-
states[uid] = {
|
|
1279
|
-
newState: latestNew,
|
|
1280
|
-
oldState: latestOld.oldState
|
|
1281
|
-
};
|
|
1282
|
-
};
|
|
1283
|
-
return wrapped;
|
|
1284
|
-
},
|
|
1285
|
-
wrapGetter(fn) {
|
|
1286
|
-
const wrapped = (uid, ...args) => {
|
|
1287
|
-
const {
|
|
1288
|
-
newState
|
|
1289
|
-
} = states[uid];
|
|
1290
|
-
return fn(newState, ...args);
|
|
1291
|
-
};
|
|
1292
|
-
return wrapped;
|
|
1293
|
-
}
|
|
1294
|
-
};
|
|
1295
|
-
};
|
|
1296
1130
|
const terminate = () => {
|
|
1297
1131
|
globalThis.close();
|
|
1298
1132
|
};
|
|
1299
1133
|
|
|
1300
|
-
const createSandboxRpc = async () => {
|
|
1301
|
-
const sandboxRpc = await LazyTransferMessagePortRpcParent.create({
|
|
1302
|
-
commandMap: {},
|
|
1303
|
-
send: async port => await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToPreviewSandBoxWorker', port, 'SandBox.handleMessagePort')
|
|
1304
|
-
});
|
|
1305
|
-
return sandboxRpc;
|
|
1306
|
-
};
|
|
1307
|
-
|
|
1308
|
-
const {
|
|
1309
|
-
get: get$1,
|
|
1310
|
-
registerCommands,
|
|
1311
|
-
set: set$2,
|
|
1312
|
-
wrapCommand} = create$1();
|
|
1313
|
-
|
|
1314
|
-
const create = async (uid, uri, x, y, width, height, platform, assetDir) => {
|
|
1315
|
-
const sandboxRpc = await createSandboxRpc();
|
|
1316
|
-
const state = {
|
|
1317
|
-
assetDir,
|
|
1318
|
-
content: '',
|
|
1319
|
-
css: [],
|
|
1320
|
-
errorCount: 0,
|
|
1321
|
-
errorMessage: '',
|
|
1322
|
-
height,
|
|
1323
|
-
initial: true,
|
|
1324
|
-
parsedDom: [],
|
|
1325
|
-
parsedNodesChildNodeCount: 0,
|
|
1326
|
-
platform,
|
|
1327
|
-
sandboxRpc,
|
|
1328
|
-
scripts: [],
|
|
1329
|
-
uid,
|
|
1330
|
-
uri,
|
|
1331
|
-
useSandboxWorker: false,
|
|
1332
|
-
warningCount: 0,
|
|
1333
|
-
width,
|
|
1334
|
-
x,
|
|
1335
|
-
y
|
|
1336
|
-
};
|
|
1337
|
-
set$2(uid, state, state);
|
|
1338
|
-
};
|
|
1339
|
-
|
|
1340
|
-
const iEqual = (oldState, newState) => {
|
|
1341
|
-
if (oldState.css.length !== newState.css.length) {
|
|
1342
|
-
return false;
|
|
1343
|
-
}
|
|
1344
|
-
for (let i = 0; i < oldState.css.length; i++) {
|
|
1345
|
-
if (oldState.css[i] !== newState.css[i]) {
|
|
1346
|
-
return false;
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1349
|
-
return true;
|
|
1350
|
-
};
|
|
1351
|
-
|
|
1352
|
-
const isEqual = (oldState, newState) => {
|
|
1353
|
-
return oldState.warningCount === newState.warningCount && oldState.initial === newState.initial && oldState.content === newState.content && oldState.parsedDom === newState.parsedDom && oldState.parsedNodesChildNodeCount === newState.parsedNodesChildNodeCount && oldState.css === newState.css && oldState.scripts === newState.scripts;
|
|
1354
|
-
};
|
|
1355
|
-
|
|
1356
|
-
const RenderItems = 4;
|
|
1357
|
-
const RenderCss = 10;
|
|
1358
|
-
const RenderIncremental = 11;
|
|
1359
|
-
|
|
1360
|
-
const modules = [isEqual, iEqual];
|
|
1361
|
-
const numbers = [RenderIncremental, RenderCss];
|
|
1362
|
-
|
|
1363
|
-
const diff = (oldState, newState) => {
|
|
1364
|
-
const diffResult = [];
|
|
1365
|
-
for (let i = 0; i < modules.length; i++) {
|
|
1366
|
-
const fn = modules[i];
|
|
1367
|
-
if (!fn(oldState, newState)) {
|
|
1368
|
-
diffResult.push(numbers[i]);
|
|
1369
|
-
}
|
|
1370
|
-
}
|
|
1371
|
-
return diffResult;
|
|
1372
|
-
};
|
|
1373
|
-
|
|
1374
|
-
const diff2 = uid => {
|
|
1375
|
-
const {
|
|
1376
|
-
newState,
|
|
1377
|
-
oldState
|
|
1378
|
-
} = get$1(uid);
|
|
1379
|
-
const result = diff(oldState, newState);
|
|
1380
|
-
return result;
|
|
1381
|
-
};
|
|
1382
|
-
|
|
1383
1134
|
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
1135
|
+
|
|
1384
1136
|
const callBacks = Object.create(null);
|
|
1385
1137
|
let id = 0;
|
|
1386
1138
|
const registerCallback = () => {
|
|
@@ -1404,12 +1156,13 @@ const executeCallback = (id, ...args) => {
|
|
|
1404
1156
|
console.warn(`[preview-sandbox-worker] No callback found for id ${id}`);
|
|
1405
1157
|
}
|
|
1406
1158
|
};
|
|
1407
|
-
const getOffscreenCanvas = async (width, height) => {
|
|
1159
|
+
const getOffscreenCanvas = async (uid, width, height) => {
|
|
1160
|
+
// TODO ask preview worker
|
|
1408
1161
|
const {
|
|
1409
1162
|
id,
|
|
1410
1163
|
promise
|
|
1411
1164
|
} = registerCallback();
|
|
1412
|
-
await invoke('
|
|
1165
|
+
await invoke$1('Preview.createOffscreenCanvas', uid, id, width, height);
|
|
1413
1166
|
const [offscreenCanvas, canvasId] = await promise;
|
|
1414
1167
|
return {
|
|
1415
1168
|
canvasId,
|
|
@@ -1417,61 +1170,6 @@ const getOffscreenCanvas = async (width, height) => {
|
|
|
1417
1170
|
};
|
|
1418
1171
|
};
|
|
1419
1172
|
|
|
1420
|
-
const dispatchEvent = (element, event) => {
|
|
1421
|
-
element.dispatchEvent(event);
|
|
1422
|
-
|
|
1423
|
-
// Also invoke direct on* handler if set (e.g. element.onclick = function(){})
|
|
1424
|
-
const handlerName = `on${event.type}`;
|
|
1425
|
-
const handler = element[handlerName];
|
|
1426
|
-
if (typeof handler === 'function') {
|
|
1427
|
-
handler.call(element, event);
|
|
1428
|
-
} else if (handler === null || handler === undefined) {
|
|
1429
|
-
if (!element.getAttribute) {
|
|
1430
|
-
return;
|
|
1431
|
-
}
|
|
1432
|
-
// Check if there's an inline HTML attribute that wasn't converted to a property
|
|
1433
|
-
const attrValue = element.getAttribute(handlerName);
|
|
1434
|
-
if (attrValue && typeof attrValue === 'string' && element.ownerDocument && element.ownerDocument.defaultView) {
|
|
1435
|
-
const window = element.ownerDocument.defaultView;
|
|
1436
|
-
// Handle inline event handlers like onclick="someFunction(2)"
|
|
1437
|
-
// Evaluate in the context of the window so functions are in scope
|
|
1438
|
-
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
1439
|
-
const fn = new Function('event', `with(this) { ${attrValue} }`);
|
|
1440
|
-
fn.call(window, event);
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
};
|
|
1444
|
-
|
|
1445
|
-
const dispatchClickEvent = (element, window) => {
|
|
1446
|
-
const clickEvent = new window.MouseEvent('click', {
|
|
1447
|
-
bubbles: true
|
|
1448
|
-
});
|
|
1449
|
-
dispatchEvent(element, clickEvent);
|
|
1450
|
-
};
|
|
1451
|
-
|
|
1452
|
-
const getParsedNodesChildNodeCount = parsedDom => {
|
|
1453
|
-
array(parsedDom);
|
|
1454
|
-
const rootCountFromParse = parsedDom.rootChildCount;
|
|
1455
|
-
if (typeof rootCountFromParse === 'number') {
|
|
1456
|
-
return rootCountFromParse;
|
|
1457
|
-
}
|
|
1458
|
-
let rootChildCount = 0;
|
|
1459
|
-
let i = 0;
|
|
1460
|
-
while (i < parsedDom.length) {
|
|
1461
|
-
rootChildCount++;
|
|
1462
|
-
|
|
1463
|
-
// skip the entire subtree of the current node
|
|
1464
|
-
let toSkip = parsedDom[i].childCount;
|
|
1465
|
-
i++;
|
|
1466
|
-
while (toSkip > 0 && i < parsedDom.length) {
|
|
1467
|
-
toSkip -= 1;
|
|
1468
|
-
toSkip += parsedDom[i].childCount;
|
|
1469
|
-
i++;
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
|
-
return rootChildCount;
|
|
1473
|
-
};
|
|
1474
|
-
|
|
1475
1173
|
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
1476
1174
|
|
|
1477
1175
|
const states$1 = new Map();
|
|
@@ -1486,298 +1184,10 @@ const text = data => {
|
|
|
1486
1184
|
return {
|
|
1487
1185
|
childCount: 0,
|
|
1488
1186
|
text: data,
|
|
1489
|
-
type: Text
|
|
1490
|
-
};
|
|
1491
|
-
};
|
|
1492
|
-
|
|
1493
|
-
const SetText = 1;
|
|
1494
|
-
const Replace = 2;
|
|
1495
|
-
const SetAttribute = 3;
|
|
1496
|
-
const RemoveAttribute = 4;
|
|
1497
|
-
const Add = 6;
|
|
1498
|
-
const NavigateChild = 7;
|
|
1499
|
-
const NavigateParent = 8;
|
|
1500
|
-
const RemoveChild = 9;
|
|
1501
|
-
const NavigateSibling = 10;
|
|
1502
|
-
const SetReferenceNodeUid = 11;
|
|
1503
|
-
|
|
1504
|
-
const isKey = key => {
|
|
1505
|
-
return key !== 'type' && key !== 'childCount';
|
|
1506
|
-
};
|
|
1507
|
-
|
|
1508
|
-
const getKeys = node => {
|
|
1509
|
-
const keys = Object.keys(node).filter(isKey);
|
|
1510
|
-
return keys;
|
|
1511
|
-
};
|
|
1512
|
-
|
|
1513
|
-
const arrayToTree = nodes => {
|
|
1514
|
-
const result = [];
|
|
1515
|
-
let i = 0;
|
|
1516
|
-
while (i < nodes.length) {
|
|
1517
|
-
const node = nodes[i];
|
|
1518
|
-
const {
|
|
1519
|
-
children,
|
|
1520
|
-
nodesConsumed
|
|
1521
|
-
} = getChildrenWithCount(nodes, i + 1, node.childCount || 0);
|
|
1522
|
-
result.push({
|
|
1523
|
-
node,
|
|
1524
|
-
children
|
|
1525
|
-
});
|
|
1526
|
-
i += 1 + nodesConsumed;
|
|
1527
|
-
}
|
|
1528
|
-
return result;
|
|
1529
|
-
};
|
|
1530
|
-
const getChildrenWithCount = (nodes, startIndex, childCount) => {
|
|
1531
|
-
if (childCount === 0) {
|
|
1532
|
-
return {
|
|
1533
|
-
children: [],
|
|
1534
|
-
nodesConsumed: 0
|
|
1535
|
-
};
|
|
1536
|
-
}
|
|
1537
|
-
const children = [];
|
|
1538
|
-
let i = startIndex;
|
|
1539
|
-
let remaining = childCount;
|
|
1540
|
-
let totalConsumed = 0;
|
|
1541
|
-
while (remaining > 0 && i < nodes.length) {
|
|
1542
|
-
const node = nodes[i];
|
|
1543
|
-
const nodeChildCount = node.childCount || 0;
|
|
1544
|
-
const {
|
|
1545
|
-
children: nodeChildren,
|
|
1546
|
-
nodesConsumed
|
|
1547
|
-
} = getChildrenWithCount(nodes, i + 1, nodeChildCount);
|
|
1548
|
-
children.push({
|
|
1549
|
-
node,
|
|
1550
|
-
children: nodeChildren
|
|
1551
|
-
});
|
|
1552
|
-
const nodeSize = 1 + nodesConsumed;
|
|
1553
|
-
i += nodeSize;
|
|
1554
|
-
totalConsumed += nodeSize;
|
|
1555
|
-
remaining--;
|
|
1556
|
-
}
|
|
1557
|
-
return {
|
|
1558
|
-
children,
|
|
1559
|
-
nodesConsumed: totalConsumed
|
|
1187
|
+
type: Text
|
|
1560
1188
|
};
|
|
1561
1189
|
};
|
|
1562
1190
|
|
|
1563
|
-
const compareNodes = (oldNode, newNode) => {
|
|
1564
|
-
const patches = [];
|
|
1565
|
-
// Check if node type changed - return null to signal incompatible nodes
|
|
1566
|
-
// (caller should handle this with a Replace operation)
|
|
1567
|
-
if (oldNode.type !== newNode.type) {
|
|
1568
|
-
return null;
|
|
1569
|
-
}
|
|
1570
|
-
// Handle reference nodes - special handling for uid changes
|
|
1571
|
-
if (oldNode.type === Reference) {
|
|
1572
|
-
if (oldNode.uid !== newNode.uid) {
|
|
1573
|
-
patches.push({
|
|
1574
|
-
type: SetReferenceNodeUid,
|
|
1575
|
-
uid: newNode.uid
|
|
1576
|
-
});
|
|
1577
|
-
}
|
|
1578
|
-
return patches;
|
|
1579
|
-
}
|
|
1580
|
-
// Handle text nodes
|
|
1581
|
-
if (oldNode.type === Text$2 && newNode.type === Text$2) {
|
|
1582
|
-
if (oldNode.text !== newNode.text) {
|
|
1583
|
-
patches.push({
|
|
1584
|
-
type: SetText,
|
|
1585
|
-
value: newNode.text
|
|
1586
|
-
});
|
|
1587
|
-
}
|
|
1588
|
-
return patches;
|
|
1589
|
-
}
|
|
1590
|
-
// Compare attributes
|
|
1591
|
-
const oldKeys = getKeys(oldNode);
|
|
1592
|
-
const newKeys = getKeys(newNode);
|
|
1593
|
-
// Check for attribute changes
|
|
1594
|
-
for (const key of newKeys) {
|
|
1595
|
-
if (oldNode[key] !== newNode[key]) {
|
|
1596
|
-
patches.push({
|
|
1597
|
-
type: SetAttribute,
|
|
1598
|
-
key,
|
|
1599
|
-
value: newNode[key]
|
|
1600
|
-
});
|
|
1601
|
-
}
|
|
1602
|
-
}
|
|
1603
|
-
// Check for removed attributes
|
|
1604
|
-
for (const key of oldKeys) {
|
|
1605
|
-
if (!(key in newNode)) {
|
|
1606
|
-
patches.push({
|
|
1607
|
-
type: RemoveAttribute,
|
|
1608
|
-
key
|
|
1609
|
-
});
|
|
1610
|
-
}
|
|
1611
|
-
}
|
|
1612
|
-
return patches;
|
|
1613
|
-
};
|
|
1614
|
-
|
|
1615
|
-
const treeToArray = node => {
|
|
1616
|
-
const result = [node.node];
|
|
1617
|
-
for (const child of node.children) {
|
|
1618
|
-
result.push(...treeToArray(child));
|
|
1619
|
-
}
|
|
1620
|
-
return result;
|
|
1621
|
-
};
|
|
1622
|
-
|
|
1623
|
-
const diffChildren = (oldChildren, newChildren, patches) => {
|
|
1624
|
-
const maxLength = Math.max(oldChildren.length, newChildren.length);
|
|
1625
|
-
// Track where we are: -1 means at parent, >= 0 means at child index
|
|
1626
|
-
let currentChildIndex = -1;
|
|
1627
|
-
// Collect indices of children to remove (we'll add these patches at the end in reverse order)
|
|
1628
|
-
const indicesToRemove = [];
|
|
1629
|
-
for (let i = 0; i < maxLength; i++) {
|
|
1630
|
-
const oldNode = oldChildren[i];
|
|
1631
|
-
const newNode = newChildren[i];
|
|
1632
|
-
if (!oldNode && !newNode) {
|
|
1633
|
-
continue;
|
|
1634
|
-
}
|
|
1635
|
-
if (!oldNode) {
|
|
1636
|
-
// Add new node - we should be at the parent
|
|
1637
|
-
if (currentChildIndex >= 0) {
|
|
1638
|
-
// Navigate back to parent
|
|
1639
|
-
patches.push({
|
|
1640
|
-
type: NavigateParent
|
|
1641
|
-
});
|
|
1642
|
-
currentChildIndex = -1;
|
|
1643
|
-
}
|
|
1644
|
-
// Flatten the entire subtree so renderInternal can handle it
|
|
1645
|
-
const flatNodes = treeToArray(newNode);
|
|
1646
|
-
patches.push({
|
|
1647
|
-
type: Add,
|
|
1648
|
-
nodes: flatNodes
|
|
1649
|
-
});
|
|
1650
|
-
} else if (newNode) {
|
|
1651
|
-
// Compare nodes to see if we need any patches
|
|
1652
|
-
const nodePatches = compareNodes(oldNode.node, newNode.node);
|
|
1653
|
-
// If nodePatches is null, the node types are incompatible - need to replace
|
|
1654
|
-
if (nodePatches === null) {
|
|
1655
|
-
// Navigate to this child
|
|
1656
|
-
if (currentChildIndex === -1) {
|
|
1657
|
-
patches.push({
|
|
1658
|
-
type: NavigateChild,
|
|
1659
|
-
index: i
|
|
1660
|
-
});
|
|
1661
|
-
currentChildIndex = i;
|
|
1662
|
-
} else if (currentChildIndex !== i) {
|
|
1663
|
-
patches.push({
|
|
1664
|
-
type: NavigateSibling,
|
|
1665
|
-
index: i
|
|
1666
|
-
});
|
|
1667
|
-
currentChildIndex = i;
|
|
1668
|
-
}
|
|
1669
|
-
// Replace the entire subtree
|
|
1670
|
-
const flatNodes = treeToArray(newNode);
|
|
1671
|
-
patches.push({
|
|
1672
|
-
type: Replace,
|
|
1673
|
-
nodes: flatNodes
|
|
1674
|
-
});
|
|
1675
|
-
// After replace, we're at the new element (same position)
|
|
1676
|
-
continue;
|
|
1677
|
-
}
|
|
1678
|
-
// Check if we need to recurse into children
|
|
1679
|
-
const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
|
|
1680
|
-
// Only navigate to this element if we need to do something
|
|
1681
|
-
if (nodePatches.length > 0 || hasChildrenToCompare) {
|
|
1682
|
-
// Navigate to this child if not already there
|
|
1683
|
-
if (currentChildIndex === -1) {
|
|
1684
|
-
patches.push({
|
|
1685
|
-
type: NavigateChild,
|
|
1686
|
-
index: i
|
|
1687
|
-
});
|
|
1688
|
-
currentChildIndex = i;
|
|
1689
|
-
} else if (currentChildIndex !== i) {
|
|
1690
|
-
patches.push({
|
|
1691
|
-
type: NavigateSibling,
|
|
1692
|
-
index: i
|
|
1693
|
-
});
|
|
1694
|
-
currentChildIndex = i;
|
|
1695
|
-
}
|
|
1696
|
-
// Apply node patches (these apply to the current element, not children)
|
|
1697
|
-
if (nodePatches.length > 0) {
|
|
1698
|
-
patches.push(...nodePatches);
|
|
1699
|
-
}
|
|
1700
|
-
// Compare children recursively
|
|
1701
|
-
if (hasChildrenToCompare) {
|
|
1702
|
-
diffChildren(oldNode.children, newNode.children, patches);
|
|
1703
|
-
}
|
|
1704
|
-
}
|
|
1705
|
-
} else {
|
|
1706
|
-
// Remove old node - collect the index for later removal
|
|
1707
|
-
indicesToRemove.push(i);
|
|
1708
|
-
}
|
|
1709
|
-
}
|
|
1710
|
-
// Navigate back to parent if we ended at a child
|
|
1711
|
-
if (currentChildIndex >= 0) {
|
|
1712
|
-
patches.push({
|
|
1713
|
-
type: NavigateParent
|
|
1714
|
-
});
|
|
1715
|
-
currentChildIndex = -1;
|
|
1716
|
-
}
|
|
1717
|
-
// Add remove patches in reverse order (highest index first)
|
|
1718
|
-
// This ensures indices remain valid as we remove
|
|
1719
|
-
for (let j = indicesToRemove.length - 1; j >= 0; j--) {
|
|
1720
|
-
patches.push({
|
|
1721
|
-
type: RemoveChild,
|
|
1722
|
-
index: indicesToRemove[j]
|
|
1723
|
-
});
|
|
1724
|
-
}
|
|
1725
|
-
};
|
|
1726
|
-
const diffTrees = (oldTree, newTree, patches, path) => {
|
|
1727
|
-
// At the root level (path.length === 0), we're already AT the element
|
|
1728
|
-
// So we compare the root node directly, then compare its children
|
|
1729
|
-
if (path.length === 0 && oldTree.length === 1 && newTree.length === 1) {
|
|
1730
|
-
const oldNode = oldTree[0];
|
|
1731
|
-
const newNode = newTree[0];
|
|
1732
|
-
// Compare root nodes
|
|
1733
|
-
const nodePatches = compareNodes(oldNode.node, newNode.node);
|
|
1734
|
-
// If nodePatches is null, the root node types are incompatible - need to replace
|
|
1735
|
-
if (nodePatches === null) {
|
|
1736
|
-
const flatNodes = treeToArray(newNode);
|
|
1737
|
-
patches.push({
|
|
1738
|
-
type: Replace,
|
|
1739
|
-
nodes: flatNodes
|
|
1740
|
-
});
|
|
1741
|
-
return;
|
|
1742
|
-
}
|
|
1743
|
-
if (nodePatches.length > 0) {
|
|
1744
|
-
patches.push(...nodePatches);
|
|
1745
|
-
}
|
|
1746
|
-
// Compare children
|
|
1747
|
-
if (oldNode.children.length > 0 || newNode.children.length > 0) {
|
|
1748
|
-
diffChildren(oldNode.children, newNode.children, patches);
|
|
1749
|
-
}
|
|
1750
|
-
} else {
|
|
1751
|
-
// Non-root level or multiple root elements - use the regular comparison
|
|
1752
|
-
diffChildren(oldTree, newTree, patches);
|
|
1753
|
-
}
|
|
1754
|
-
};
|
|
1755
|
-
|
|
1756
|
-
const removeTrailingNavigationPatches = patches => {
|
|
1757
|
-
// Find the last non-navigation patch
|
|
1758
|
-
let lastNonNavigationIndex = -1;
|
|
1759
|
-
for (let i = patches.length - 1; i >= 0; i--) {
|
|
1760
|
-
const patch = patches[i];
|
|
1761
|
-
if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling) {
|
|
1762
|
-
lastNonNavigationIndex = i;
|
|
1763
|
-
break;
|
|
1764
|
-
}
|
|
1765
|
-
}
|
|
1766
|
-
// Return patches up to and including the last non-navigation patch
|
|
1767
|
-
return lastNonNavigationIndex === -1 ? [] : patches.slice(0, lastNonNavigationIndex + 1);
|
|
1768
|
-
};
|
|
1769
|
-
|
|
1770
|
-
const diffTree = (oldNodes, newNodes) => {
|
|
1771
|
-
// Step 1: Convert flat arrays to tree structures
|
|
1772
|
-
const oldTree = arrayToTree(oldNodes);
|
|
1773
|
-
const newTree = arrayToTree(newNodes);
|
|
1774
|
-
// Step 3: Compare the trees
|
|
1775
|
-
const patches = [];
|
|
1776
|
-
diffTrees(oldTree, newTree, patches, []);
|
|
1777
|
-
// Remove trailing navigation patches since they serve no purpose
|
|
1778
|
-
return removeTrailingNavigationPatches(patches);
|
|
1779
|
-
};
|
|
1780
|
-
|
|
1781
1191
|
const Div = 'div';
|
|
1782
1192
|
const H1 = 'h1';
|
|
1783
1193
|
const H2 = 'h2';
|
|
@@ -1985,7 +1395,7 @@ const isDefaultAllowedAttribute = (attributeName, defaultAllowedAttributes) => {
|
|
|
1985
1395
|
const TAGS_TO_SKIP = new Set(['script', 'meta', 'title']);
|
|
1986
1396
|
|
|
1987
1397
|
// Tags to skip but process children
|
|
1988
|
-
const TAGS_TO_SKIP_TAG_ONLY
|
|
1398
|
+
const TAGS_TO_SKIP_TAG_ONLY = new Set(['html', 'body', 'head']);
|
|
1989
1399
|
|
|
1990
1400
|
// Tags where we extract content as CSS
|
|
1991
1401
|
const CSS_TAGS = new Set(['style']);
|
|
@@ -2026,7 +1436,7 @@ const serializeNode = (node, dom, css, context) => {
|
|
|
2026
1436
|
}
|
|
2027
1437
|
|
|
2028
1438
|
// For html/body tags, serialize children only
|
|
2029
|
-
if (TAGS_TO_SKIP_TAG_ONLY
|
|
1439
|
+
if (TAGS_TO_SKIP_TAG_ONLY.has(tagName)) {
|
|
2030
1440
|
let childCount = 0;
|
|
2031
1441
|
const {
|
|
2032
1442
|
childNodes
|
|
@@ -2136,62 +1546,261 @@ const serialize = (document, elementMap) => {
|
|
|
2136
1546
|
};
|
|
2137
1547
|
};
|
|
2138
1548
|
|
|
2139
|
-
const
|
|
2140
|
-
const
|
|
2141
|
-
|
|
2142
|
-
uid
|
|
2143
|
-
}
|
|
2144
|
-
await sandboxRpc.invoke('SandBox.handleClick', uid, hdId);
|
|
2145
|
-
const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', uid);
|
|
2146
|
-
const parsedDom = serialized.dom;
|
|
1549
|
+
const getSerializedDom = uid => {
|
|
1550
|
+
const item = get(uid);
|
|
1551
|
+
if (!item) {
|
|
1552
|
+
throw new Error(`No HappyDom instance found for uid ${uid}`);
|
|
1553
|
+
}
|
|
2147
1554
|
const {
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
1555
|
+
document,
|
|
1556
|
+
elementMap
|
|
1557
|
+
} = item;
|
|
1558
|
+
const serialized = serialize(document, elementMap);
|
|
1559
|
+
return serialized;
|
|
1560
|
+
};
|
|
1561
|
+
|
|
1562
|
+
const dispatchEvent = (element, event) => {
|
|
1563
|
+
element.dispatchEvent(event);
|
|
1564
|
+
|
|
1565
|
+
// Also invoke direct on* handler if set (e.g. element.onclick = function(){})
|
|
1566
|
+
const handlerName = `on${event.type}`;
|
|
1567
|
+
const handler = element[handlerName];
|
|
1568
|
+
if (typeof handler === 'function') {
|
|
1569
|
+
handler.call(element, event);
|
|
1570
|
+
} else if (handler === null || handler === undefined) {
|
|
1571
|
+
if (!element.getAttribute) {
|
|
1572
|
+
return;
|
|
1573
|
+
}
|
|
1574
|
+
// Check if there's an inline HTML attribute that wasn't converted to a property
|
|
1575
|
+
const attrValue = element.getAttribute(handlerName);
|
|
1576
|
+
if (attrValue && typeof attrValue === 'string' && element.ownerDocument && element.ownerDocument.defaultView) {
|
|
1577
|
+
const window = element.ownerDocument.defaultView;
|
|
1578
|
+
// Handle inline event handlers like onclick="someFunction(2)"
|
|
1579
|
+
// Evaluate in the context of the window so functions are in scope
|
|
1580
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
1581
|
+
const fn = new Function('event', `with(this) { ${attrValue} }`);
|
|
1582
|
+
fn.call(window, event);
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
};
|
|
1586
|
+
|
|
1587
|
+
const dispatchClickEvent = (element, window) => {
|
|
1588
|
+
const clickEvent = new window.MouseEvent('click', {
|
|
1589
|
+
bubbles: true
|
|
1590
|
+
});
|
|
1591
|
+
dispatchEvent(element, clickEvent);
|
|
2157
1592
|
};
|
|
2158
|
-
|
|
2159
|
-
|
|
1593
|
+
|
|
1594
|
+
const handleClickLocal = (uid, hdId) => {
|
|
1595
|
+
const happyDomInstance = get(uid);
|
|
2160
1596
|
if (!happyDomInstance) {
|
|
2161
|
-
return
|
|
1597
|
+
return;
|
|
2162
1598
|
}
|
|
2163
1599
|
const element = happyDomInstance.elementMap.get(hdId);
|
|
2164
1600
|
if (!element) {
|
|
2165
|
-
return
|
|
1601
|
+
return;
|
|
2166
1602
|
}
|
|
2167
1603
|
dispatchClickEvent(element, happyDomInstance.window);
|
|
2168
1604
|
const elementMap = new Map();
|
|
2169
|
-
|
|
2170
|
-
set$1(state.uid, {
|
|
1605
|
+
set$1(uid, {
|
|
2171
1606
|
document: happyDomInstance.document,
|
|
2172
1607
|
elementMap,
|
|
2173
1608
|
window: happyDomInstance.window
|
|
2174
1609
|
});
|
|
2175
|
-
const parsedDom = serialized.dom;
|
|
2176
|
-
const {
|
|
2177
|
-
css
|
|
2178
|
-
} = serialized;
|
|
2179
|
-
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
2180
|
-
return {
|
|
2181
|
-
...state,
|
|
2182
|
-
css,
|
|
2183
|
-
parsedDom,
|
|
2184
|
-
parsedNodesChildNodeCount
|
|
2185
|
-
};
|
|
2186
1610
|
};
|
|
2187
|
-
const handleClick = (
|
|
2188
|
-
|
|
2189
|
-
|
|
1611
|
+
const handleClick = (uid, hdId) => {
|
|
1612
|
+
return handleClickLocal(uid, hdId);
|
|
1613
|
+
};
|
|
1614
|
+
|
|
1615
|
+
const dispatchInputEvent = (element, window) => {
|
|
1616
|
+
const inputEvent = new window.Event('input', {
|
|
1617
|
+
bubbles: true
|
|
1618
|
+
});
|
|
1619
|
+
dispatchEvent(element, inputEvent);
|
|
1620
|
+
};
|
|
1621
|
+
|
|
1622
|
+
const handleInputLocal = (uid, hdId, value) => {
|
|
1623
|
+
const happyDomInstance = get(uid);
|
|
1624
|
+
if (!happyDomInstance) {
|
|
1625
|
+
return;
|
|
1626
|
+
}
|
|
1627
|
+
const element = happyDomInstance.elementMap.get(hdId);
|
|
1628
|
+
if (!element) {
|
|
1629
|
+
return;
|
|
1630
|
+
}
|
|
1631
|
+
element.value = value;
|
|
1632
|
+
dispatchInputEvent(element, happyDomInstance.window);
|
|
1633
|
+
const elementMap = new Map();
|
|
1634
|
+
set$1(uid, {
|
|
1635
|
+
document: happyDomInstance.document,
|
|
1636
|
+
elementMap,
|
|
1637
|
+
window: happyDomInstance.window
|
|
1638
|
+
});
|
|
1639
|
+
};
|
|
1640
|
+
const handleInput = (uid, hdId, value) => {
|
|
1641
|
+
return handleInputLocal(uid, hdId, value);
|
|
1642
|
+
};
|
|
1643
|
+
|
|
1644
|
+
const dispatchKeydownEvent = (element, window, key, code) => {
|
|
1645
|
+
const keydownEvent = new window.KeyboardEvent('keydown', {
|
|
1646
|
+
bubbles: true,
|
|
1647
|
+
code,
|
|
1648
|
+
key
|
|
1649
|
+
});
|
|
1650
|
+
dispatchEvent(element, keydownEvent);
|
|
1651
|
+
};
|
|
1652
|
+
|
|
1653
|
+
const handleKeydownLocal = (uid, hdId, key, code) => {
|
|
1654
|
+
const happyDomInstance = get(uid);
|
|
1655
|
+
if (!happyDomInstance) {
|
|
1656
|
+
return;
|
|
1657
|
+
}
|
|
1658
|
+
const element = hdId ? happyDomInstance.elementMap.get(hdId) : happyDomInstance.document;
|
|
1659
|
+
if (!element) {
|
|
1660
|
+
return;
|
|
1661
|
+
}
|
|
1662
|
+
dispatchKeydownEvent(element, happyDomInstance.window, key, code);
|
|
1663
|
+
const elementMap = new Map();
|
|
1664
|
+
set$1(uid, {
|
|
1665
|
+
document: happyDomInstance.document,
|
|
1666
|
+
elementMap,
|
|
1667
|
+
window: happyDomInstance.window
|
|
1668
|
+
});
|
|
1669
|
+
};
|
|
1670
|
+
const handleKeydown = (uid, hdId, key, code) => {
|
|
1671
|
+
return handleKeydownLocal(uid, hdId, key, code);
|
|
1672
|
+
};
|
|
1673
|
+
|
|
1674
|
+
const dispatchKeyupEvent = (element, window, key, code) => {
|
|
1675
|
+
const keyupEvent = new window.KeyboardEvent('keyup', {
|
|
1676
|
+
bubbles: true,
|
|
1677
|
+
code,
|
|
1678
|
+
key
|
|
1679
|
+
});
|
|
1680
|
+
dispatchEvent(element, keyupEvent);
|
|
1681
|
+
};
|
|
1682
|
+
|
|
1683
|
+
const handleKeyupLocal = (uid, hdId, key, code) => {
|
|
1684
|
+
const happyDomInstance = get(uid);
|
|
1685
|
+
if (!happyDomInstance) {
|
|
1686
|
+
return;
|
|
1687
|
+
}
|
|
1688
|
+
const element = hdId ? happyDomInstance.elementMap.get(hdId) : happyDomInstance.document;
|
|
1689
|
+
if (!element) {
|
|
1690
|
+
return;
|
|
1691
|
+
}
|
|
1692
|
+
dispatchKeyupEvent(element, happyDomInstance.window, key, code);
|
|
1693
|
+
const elementMap = new Map();
|
|
1694
|
+
set$1(uid, {
|
|
1695
|
+
document: happyDomInstance.document,
|
|
1696
|
+
elementMap,
|
|
1697
|
+
window: happyDomInstance.window
|
|
1698
|
+
});
|
|
1699
|
+
};
|
|
1700
|
+
const handleKeyup = (uid, hdId, key, code) => {
|
|
1701
|
+
return handleKeyupLocal(uid, hdId, key, code);
|
|
1702
|
+
};
|
|
1703
|
+
|
|
1704
|
+
const handleMessagePort = async port => {
|
|
1705
|
+
const rpc = await PlainMessagePortRpc.create({
|
|
1706
|
+
commandMap: {},
|
|
1707
|
+
messagePort: port
|
|
1708
|
+
});
|
|
1709
|
+
set$3(rpc);
|
|
1710
|
+
};
|
|
1711
|
+
|
|
1712
|
+
const dispatchMousedownEvent = (element, window, clientX = 0, clientY = 0) => {
|
|
1713
|
+
const mousedownEvent = new window.MouseEvent('mousedown', {
|
|
1714
|
+
bubbles: true,
|
|
1715
|
+
clientX,
|
|
1716
|
+
clientY
|
|
1717
|
+
});
|
|
1718
|
+
dispatchEvent(element, mousedownEvent);
|
|
1719
|
+
};
|
|
1720
|
+
|
|
1721
|
+
const handleMousedownLocal = (uid, hdId, clientX, clientY, x, y) => {
|
|
1722
|
+
const happyDomInstance = get(uid);
|
|
1723
|
+
if (!happyDomInstance) {
|
|
1724
|
+
return;
|
|
1725
|
+
}
|
|
1726
|
+
const element = happyDomInstance.elementMap.get(hdId);
|
|
1727
|
+
if (!element) {
|
|
1728
|
+
return;
|
|
1729
|
+
}
|
|
1730
|
+
const adjustedClientX = clientX - x;
|
|
1731
|
+
const adjustedClientY = clientY - y;
|
|
1732
|
+
dispatchMousedownEvent(element, happyDomInstance.window, adjustedClientX, adjustedClientY);
|
|
1733
|
+
const elementMap = new Map();
|
|
1734
|
+
set$1(uid, {
|
|
1735
|
+
document: happyDomInstance.document,
|
|
1736
|
+
elementMap,
|
|
1737
|
+
window: happyDomInstance.window
|
|
1738
|
+
});
|
|
1739
|
+
};
|
|
1740
|
+
const handleMousedown = (uid, hdId, clientX, clientY, x, y) => {
|
|
1741
|
+
return handleMousedownLocal(uid, hdId, clientX, clientY, x, y);
|
|
1742
|
+
};
|
|
1743
|
+
|
|
1744
|
+
const dispatchMousemoveEvent = (element, window, clientX = 0, clientY = 0) => {
|
|
1745
|
+
const mousemoveEvent = new window.MouseEvent('mousemove', {
|
|
1746
|
+
bubbles: true,
|
|
1747
|
+
clientX,
|
|
1748
|
+
clientY
|
|
1749
|
+
});
|
|
1750
|
+
dispatchEvent(element, mousemoveEvent);
|
|
1751
|
+
};
|
|
1752
|
+
|
|
1753
|
+
const handleMousemoveLocal = (uid, hdId, clientX, clientY, x, y) => {
|
|
1754
|
+
const happyDomInstance = get(uid);
|
|
1755
|
+
if (!happyDomInstance) {
|
|
1756
|
+
return;
|
|
1757
|
+
}
|
|
1758
|
+
const element = happyDomInstance.elementMap.get(hdId);
|
|
1759
|
+
if (!element) {
|
|
1760
|
+
return;
|
|
1761
|
+
}
|
|
1762
|
+
const adjustedClientX = clientX - x;
|
|
1763
|
+
const adjustedClientY = clientY - y;
|
|
1764
|
+
dispatchMousemoveEvent(element, happyDomInstance.window, adjustedClientX, adjustedClientY);
|
|
1765
|
+
const elementMap = new Map();
|
|
1766
|
+
set$1(uid, {
|
|
1767
|
+
document: happyDomInstance.document,
|
|
1768
|
+
elementMap,
|
|
1769
|
+
window: happyDomInstance.window
|
|
1770
|
+
});
|
|
1771
|
+
};
|
|
1772
|
+
const handleMousemove = (uid, hdId, clientX, clientY, x, y) => {
|
|
1773
|
+
return handleMousemoveLocal(uid, hdId, clientX, clientY, x, y);
|
|
1774
|
+
};
|
|
1775
|
+
|
|
1776
|
+
const dispatchMouseupEvent = (element, window, clientX = 0, clientY = 0) => {
|
|
1777
|
+
const mouseupEvent = new window.MouseEvent('mouseup', {
|
|
1778
|
+
bubbles: true,
|
|
1779
|
+
clientX,
|
|
1780
|
+
clientY
|
|
1781
|
+
});
|
|
1782
|
+
dispatchEvent(element, mouseupEvent);
|
|
1783
|
+
};
|
|
1784
|
+
|
|
1785
|
+
const handleMouseupLocal = (uid, hdId) => {
|
|
1786
|
+
const happyDomInstance = get(uid);
|
|
1787
|
+
if (!happyDomInstance) {
|
|
1788
|
+
return;
|
|
2190
1789
|
}
|
|
2191
|
-
|
|
2192
|
-
|
|
1790
|
+
const element = happyDomInstance.elementMap.get(hdId);
|
|
1791
|
+
if (!element) {
|
|
1792
|
+
return;
|
|
2193
1793
|
}
|
|
2194
|
-
|
|
1794
|
+
dispatchMouseupEvent(element, happyDomInstance.window);
|
|
1795
|
+
const elementMap = new Map();
|
|
1796
|
+
set$1(uid, {
|
|
1797
|
+
document: happyDomInstance.document,
|
|
1798
|
+
elementMap,
|
|
1799
|
+
window: happyDomInstance.window
|
|
1800
|
+
});
|
|
1801
|
+
};
|
|
1802
|
+
const handleMouseup = (uid, hdId) => {
|
|
1803
|
+
return handleMouseupLocal(uid, hdId);
|
|
2195
1804
|
};
|
|
2196
1805
|
|
|
2197
1806
|
function getDefaultExportFromCjs (x) {
|
|
@@ -89933,6 +89542,29 @@ const executeScripts = (window, document, scripts, width = 0, height = 0) => {
|
|
|
89933
89542
|
}
|
|
89934
89543
|
};
|
|
89935
89544
|
|
|
89545
|
+
const getParsedNodesChildNodeCount = parsedDom => {
|
|
89546
|
+
array(parsedDom);
|
|
89547
|
+
const rootCountFromParse = parsedDom.rootChildCount;
|
|
89548
|
+
if (typeof rootCountFromParse === 'number') {
|
|
89549
|
+
return rootCountFromParse;
|
|
89550
|
+
}
|
|
89551
|
+
let rootChildCount = 0;
|
|
89552
|
+
let i = 0;
|
|
89553
|
+
while (i < parsedDom.length) {
|
|
89554
|
+
rootChildCount++;
|
|
89555
|
+
|
|
89556
|
+
// skip the entire subtree of the current node
|
|
89557
|
+
let toSkip = parsedDom[i].childCount;
|
|
89558
|
+
i++;
|
|
89559
|
+
while (toSkip > 0 && i < parsedDom.length) {
|
|
89560
|
+
toSkip -= 1;
|
|
89561
|
+
toSkip += parsedDom[i].childCount;
|
|
89562
|
+
i++;
|
|
89563
|
+
}
|
|
89564
|
+
}
|
|
89565
|
+
return rootChildCount;
|
|
89566
|
+
};
|
|
89567
|
+
|
|
89936
89568
|
/* eslint-disable @typescript-eslint/no-floating-promises */
|
|
89937
89569
|
const observers = new Map();
|
|
89938
89570
|
const handleMutations = async uid => {
|
|
@@ -89947,22 +89579,17 @@ const handleMutations = async uid => {
|
|
|
89947
89579
|
elementMap,
|
|
89948
89580
|
window: happyDomInstance.window
|
|
89949
89581
|
});
|
|
89950
|
-
const {
|
|
89951
|
-
newState: state,
|
|
89952
|
-
oldState
|
|
89953
|
-
} = get$1(uid);
|
|
89954
89582
|
const parsedDom = serialized.dom;
|
|
89955
|
-
|
|
89956
|
-
|
|
89957
|
-
|
|
89958
|
-
const
|
|
89959
|
-
|
|
89960
|
-
|
|
89961
|
-
|
|
89962
|
-
|
|
89963
|
-
|
|
89964
|
-
|
|
89965
|
-
set$2(uid, oldState, updatedState);
|
|
89583
|
+
// @ts-ignore
|
|
89584
|
+
getParsedNodesChildNodeCount(parsedDom);
|
|
89585
|
+
|
|
89586
|
+
// const updatedState = {
|
|
89587
|
+
// css,
|
|
89588
|
+
// parsedDom,
|
|
89589
|
+
// parsedNodesChildNodeCount,
|
|
89590
|
+
// }
|
|
89591
|
+
|
|
89592
|
+
// TODO notify
|
|
89966
89593
|
try {
|
|
89967
89594
|
await invoke('Preview.rerender', uid);
|
|
89968
89595
|
} catch {
|
|
@@ -89986,561 +89613,6 @@ const observe = (uid, document, window) => {
|
|
|
89986
89613
|
observers.set(uid, observer);
|
|
89987
89614
|
};
|
|
89988
89615
|
|
|
89989
|
-
const None = 0;
|
|
89990
|
-
const OpeningAngleBracket = 1;
|
|
89991
|
-
const ClosingAngleBracket = 2;
|
|
89992
|
-
const TagNameStart = 3;
|
|
89993
|
-
const TagNameEnd = 4;
|
|
89994
|
-
const Content = 5;
|
|
89995
|
-
const ClosingTagSlash = 6;
|
|
89996
|
-
const WhitespaceInsideOpeningTag = 7;
|
|
89997
|
-
const AttributeName = 8;
|
|
89998
|
-
const AttributeEqualSign = 9;
|
|
89999
|
-
const AttributeQuoteStart = 10;
|
|
90000
|
-
const AttributeValue = 11;
|
|
90001
|
-
const AttributeQuoteEnd = 12;
|
|
90002
|
-
const WhitespaceAfterClosingTagSlash = 13;
|
|
90003
|
-
const WhitespaceAfterOpeningTagOpenAngleBracket = 14;
|
|
90004
|
-
const ExclamationMark = 15;
|
|
90005
|
-
const Doctype = 16;
|
|
90006
|
-
const StartCommentDashes = 17;
|
|
90007
|
-
const Comment = 18;
|
|
90008
|
-
const EndCommentTag = 19;
|
|
90009
|
-
const Text = 20;
|
|
90010
|
-
const CommentStart = 21;
|
|
90011
|
-
|
|
90012
|
-
const isSelfClosingTag = tag => {
|
|
90013
|
-
switch (tag.toLowerCase()) {
|
|
90014
|
-
case 'area':
|
|
90015
|
-
case 'base':
|
|
90016
|
-
case 'col':
|
|
90017
|
-
case Br:
|
|
90018
|
-
case Hr:
|
|
90019
|
-
case Img:
|
|
90020
|
-
case Input:
|
|
90021
|
-
case 'embed':
|
|
90022
|
-
case 'link':
|
|
90023
|
-
case 'meta':
|
|
90024
|
-
case 'param':
|
|
90025
|
-
case 'source':
|
|
90026
|
-
case 'track':
|
|
90027
|
-
case 'wbr':
|
|
90028
|
-
return true;
|
|
90029
|
-
default:
|
|
90030
|
-
return false;
|
|
90031
|
-
}
|
|
90032
|
-
};
|
|
90033
|
-
|
|
90034
|
-
const parseText = text => {
|
|
90035
|
-
return text.replaceAll('>', '>').replaceAll('<', '<').replaceAll('&', '&');
|
|
90036
|
-
};
|
|
90037
|
-
|
|
90038
|
-
class UnexpectedTokenError extends Error {
|
|
90039
|
-
constructor() {
|
|
90040
|
-
super('Unexpected token');
|
|
90041
|
-
this.name = 'UnexpectedTokenError';
|
|
90042
|
-
}
|
|
90043
|
-
}
|
|
90044
|
-
|
|
90045
|
-
const State = {
|
|
90046
|
-
AfterAttributeEqualSign: 8,
|
|
90047
|
-
AfterAttributeName: 7,
|
|
90048
|
-
AfterAttributeValueClosingQuote: 11,
|
|
90049
|
-
AfterAttributeValueInsideDoubleQuote: 10,
|
|
90050
|
-
AfterClosingTagName: 5,
|
|
90051
|
-
AfterClosingTagSlash: 4,
|
|
90052
|
-
AfterExclamationMark: 16,
|
|
90053
|
-
AfterOpeningAngleBracket: 2,
|
|
90054
|
-
InsideAttributeAfterDoubleQuote: 9,
|
|
90055
|
-
InsideComment: 17,
|
|
90056
|
-
InsideOpeningTag: 3,
|
|
90057
|
-
InsideOpeningTagAfterWhitespace: 6,
|
|
90058
|
-
InsideRawTextElement: 18,
|
|
90059
|
-
TopLevelContent: 1
|
|
90060
|
-
};
|
|
90061
|
-
|
|
90062
|
-
// Raw-text elements whose content should not be parsed as HTML
|
|
90063
|
-
const RAW_TEXT_ELEMENTS = new Set(['script', 'style']);
|
|
90064
|
-
const RE_ANGLE_BRACKET_OPEN = /^</;
|
|
90065
|
-
const RE_ANGLE_BRACKET_OPEN_TAG = /^<(?![\s%])/;
|
|
90066
|
-
const RE_ANGLE_BRACKET_CLOSE = /^>/;
|
|
90067
|
-
const RE_SLASH = /^\//;
|
|
90068
|
-
const RE_TAGNAME = /^[a-zA-Z\d$]+/;
|
|
90069
|
-
const RE_CONTENT = /^[^<>]+/;
|
|
90070
|
-
const RE_WHITESPACE = /^\s+/;
|
|
90071
|
-
const RE_ATTRIBUTE_NAME = /^[a-zA-Z\d-]+/;
|
|
90072
|
-
const RE_EQUAL_SIGN = /^=/;
|
|
90073
|
-
const RE_DOUBLE_QUOTE = /^"/;
|
|
90074
|
-
const RE_ATTRIBUTE_VALUE_INSIDE_DOUBLE_QUOTE = /^[^"\n]+/;
|
|
90075
|
-
const RE_TEXT = /^[^<>]+/;
|
|
90076
|
-
const RE_EXCLAMATION_MARK = /^!/;
|
|
90077
|
-
const RE_DASH_DASH = /^--/;
|
|
90078
|
-
const RE_DOCTYPE = /^doctype/i;
|
|
90079
|
-
const RE_BLOCK_COMMENT_CONTENT = /^[a-zA-Z\s]+/;
|
|
90080
|
-
const RE_COMMENT_END = /^-->/;
|
|
90081
|
-
const RE_TAG_TEXT = /^[^\s>]+/;
|
|
90082
|
-
const RE_ANY_TEXT = /^[^\n]+/;
|
|
90083
|
-
const RE_ATTRIBUTE_TEXT = /^[^\n<>/\s]+/;
|
|
90084
|
-
const RE_BLOCK_COMMENT_START = /^<!--/;
|
|
90085
|
-
const RE_SELF_CLOSING = /^\/>/;
|
|
90086
|
-
const tokenizeHtml = text => {
|
|
90087
|
-
string(text);
|
|
90088
|
-
let state = State.TopLevelContent;
|
|
90089
|
-
let index = 0;
|
|
90090
|
-
let next;
|
|
90091
|
-
const tokens = [];
|
|
90092
|
-
let token = None;
|
|
90093
|
-
let rawTextTagName = ''; // Track which raw-text element we're inside
|
|
90094
|
-
while (index < text.length) {
|
|
90095
|
-
const part = text.slice(index);
|
|
90096
|
-
switch (state) {
|
|
90097
|
-
case State.AfterAttributeEqualSign:
|
|
90098
|
-
if (next = part.match(RE_DOUBLE_QUOTE)) {
|
|
90099
|
-
token = AttributeQuoteStart;
|
|
90100
|
-
state = State.InsideAttributeAfterDoubleQuote;
|
|
90101
|
-
} else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
|
|
90102
|
-
token = ClosingAngleBracket;
|
|
90103
|
-
state = State.TopLevelContent;
|
|
90104
|
-
} else if (next = part.match(RE_ATTRIBUTE_TEXT)) {
|
|
90105
|
-
token = AttributeValue;
|
|
90106
|
-
state = State.InsideOpeningTag;
|
|
90107
|
-
} else {
|
|
90108
|
-
throw new UnexpectedTokenError();
|
|
90109
|
-
}
|
|
90110
|
-
break;
|
|
90111
|
-
case State.AfterAttributeName:
|
|
90112
|
-
if (next = part.match(RE_EQUAL_SIGN)) {
|
|
90113
|
-
token = AttributeEqualSign;
|
|
90114
|
-
state = State.AfterAttributeEqualSign;
|
|
90115
|
-
} else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
|
|
90116
|
-
token = ClosingAngleBracket;
|
|
90117
|
-
state = State.TopLevelContent;
|
|
90118
|
-
} else if (next = part.match(RE_WHITESPACE)) {
|
|
90119
|
-
token = WhitespaceInsideOpeningTag;
|
|
90120
|
-
state = State.InsideOpeningTagAfterWhitespace;
|
|
90121
|
-
} else if (next = part.match(RE_ANGLE_BRACKET_OPEN)) {
|
|
90122
|
-
token = OpeningAngleBracket;
|
|
90123
|
-
state = State.AfterOpeningAngleBracket;
|
|
90124
|
-
} else {
|
|
90125
|
-
text.slice(index); // ?
|
|
90126
|
-
throw new UnexpectedTokenError();
|
|
90127
|
-
}
|
|
90128
|
-
break;
|
|
90129
|
-
case State.AfterAttributeValueClosingQuote:
|
|
90130
|
-
if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
|
|
90131
|
-
token = ClosingAngleBracket;
|
|
90132
|
-
state = State.TopLevelContent;
|
|
90133
|
-
} else if (next = part.match(RE_WHITESPACE)) {
|
|
90134
|
-
token = WhitespaceInsideOpeningTag;
|
|
90135
|
-
state = State.InsideOpeningTagAfterWhitespace;
|
|
90136
|
-
} else if (next = part.match(RE_SELF_CLOSING)) {
|
|
90137
|
-
token = ClosingAngleBracket;
|
|
90138
|
-
state = State.TopLevelContent;
|
|
90139
|
-
} else {
|
|
90140
|
-
throw new UnexpectedTokenError();
|
|
90141
|
-
}
|
|
90142
|
-
break;
|
|
90143
|
-
case State.AfterAttributeValueInsideDoubleQuote:
|
|
90144
|
-
if (next = part.match(RE_DOUBLE_QUOTE)) {
|
|
90145
|
-
token = AttributeQuoteEnd;
|
|
90146
|
-
state = State.AfterAttributeValueClosingQuote;
|
|
90147
|
-
} else {
|
|
90148
|
-
throw new UnexpectedTokenError();
|
|
90149
|
-
}
|
|
90150
|
-
break;
|
|
90151
|
-
case State.AfterClosingTagName:
|
|
90152
|
-
if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
|
|
90153
|
-
token = ClosingAngleBracket;
|
|
90154
|
-
state = State.TopLevelContent;
|
|
90155
|
-
} else if (next = part.match(RE_WHITESPACE)) {
|
|
90156
|
-
token = Content;
|
|
90157
|
-
state = State.TopLevelContent;
|
|
90158
|
-
} else {
|
|
90159
|
-
throw new UnexpectedTokenError();
|
|
90160
|
-
}
|
|
90161
|
-
break;
|
|
90162
|
-
case State.AfterClosingTagSlash:
|
|
90163
|
-
if (next = part.match(RE_TAGNAME)) {
|
|
90164
|
-
token = TagNameEnd;
|
|
90165
|
-
state = State.AfterClosingTagName;
|
|
90166
|
-
} else if (next = part.match(RE_WHITESPACE)) {
|
|
90167
|
-
token = WhitespaceAfterClosingTagSlash;
|
|
90168
|
-
state = State.TopLevelContent;
|
|
90169
|
-
} else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
|
|
90170
|
-
token = ClosingAngleBracket;
|
|
90171
|
-
state = State.TopLevelContent;
|
|
90172
|
-
} else {
|
|
90173
|
-
throw new UnexpectedTokenError();
|
|
90174
|
-
}
|
|
90175
|
-
break;
|
|
90176
|
-
case State.AfterExclamationMark:
|
|
90177
|
-
if (next = part.match(RE_DASH_DASH)) {
|
|
90178
|
-
token = StartCommentDashes;
|
|
90179
|
-
state = State.InsideComment;
|
|
90180
|
-
} else if (next = part.match(RE_DOCTYPE)) {
|
|
90181
|
-
token = Doctype;
|
|
90182
|
-
state = State.InsideOpeningTag;
|
|
90183
|
-
} else {
|
|
90184
|
-
text.slice(index); // ?
|
|
90185
|
-
throw new UnexpectedTokenError();
|
|
90186
|
-
}
|
|
90187
|
-
break;
|
|
90188
|
-
case State.AfterOpeningAngleBracket:
|
|
90189
|
-
if (next = part.match(RE_TAGNAME)) {
|
|
90190
|
-
token = TagNameStart;
|
|
90191
|
-
state = State.InsideOpeningTag;
|
|
90192
|
-
// Track raw-text elements so we can switch to raw content mode after >
|
|
90193
|
-
if (RAW_TEXT_ELEMENTS.has(next[0].toLowerCase())) {
|
|
90194
|
-
rawTextTagName = next[0].toLowerCase();
|
|
90195
|
-
}
|
|
90196
|
-
} else if (next = part.match(RE_SLASH)) {
|
|
90197
|
-
token = ClosingTagSlash;
|
|
90198
|
-
state = State.AfterClosingTagSlash;
|
|
90199
|
-
} else if (next = part.match(RE_WHITESPACE)) {
|
|
90200
|
-
token = WhitespaceAfterOpeningTagOpenAngleBracket;
|
|
90201
|
-
state = State.TopLevelContent;
|
|
90202
|
-
} else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
|
|
90203
|
-
token = ClosingAngleBracket;
|
|
90204
|
-
state = State.TopLevelContent;
|
|
90205
|
-
} else if (next = part.match(RE_EXCLAMATION_MARK)) {
|
|
90206
|
-
token = ExclamationMark;
|
|
90207
|
-
state = State.AfterExclamationMark;
|
|
90208
|
-
} else if (next = part.match(RE_ANY_TEXT)) {
|
|
90209
|
-
token = Text;
|
|
90210
|
-
state = State.TopLevelContent;
|
|
90211
|
-
} else {
|
|
90212
|
-
text.slice(index); // ?
|
|
90213
|
-
throw new UnexpectedTokenError();
|
|
90214
|
-
}
|
|
90215
|
-
break;
|
|
90216
|
-
case State.InsideAttributeAfterDoubleQuote:
|
|
90217
|
-
if (next = text.slice(index).match(RE_ATTRIBUTE_VALUE_INSIDE_DOUBLE_QUOTE)) {
|
|
90218
|
-
token = AttributeValue;
|
|
90219
|
-
state = State.AfterAttributeValueInsideDoubleQuote;
|
|
90220
|
-
} else if (next = part.match(RE_DOUBLE_QUOTE)) {
|
|
90221
|
-
token = AttributeQuoteEnd;
|
|
90222
|
-
state = State.AfterAttributeValueClosingQuote;
|
|
90223
|
-
} else {
|
|
90224
|
-
throw new UnexpectedTokenError();
|
|
90225
|
-
}
|
|
90226
|
-
break;
|
|
90227
|
-
case State.InsideComment:
|
|
90228
|
-
if (next = part.match(RE_BLOCK_COMMENT_CONTENT)) {
|
|
90229
|
-
token = Comment;
|
|
90230
|
-
state = State.InsideComment;
|
|
90231
|
-
} else if (next = part.match(RE_COMMENT_END)) {
|
|
90232
|
-
token = EndCommentTag;
|
|
90233
|
-
state = State.TopLevelContent;
|
|
90234
|
-
} else {
|
|
90235
|
-
text.slice(index); // ?
|
|
90236
|
-
throw new UnexpectedTokenError();
|
|
90237
|
-
}
|
|
90238
|
-
break;
|
|
90239
|
-
case State.InsideOpeningTag:
|
|
90240
|
-
if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
|
|
90241
|
-
token = ClosingAngleBracket;
|
|
90242
|
-
state = State.TopLevelContent;
|
|
90243
|
-
} else if (next = part.match(RE_WHITESPACE)) {
|
|
90244
|
-
token = WhitespaceInsideOpeningTag;
|
|
90245
|
-
state = State.InsideOpeningTagAfterWhitespace;
|
|
90246
|
-
} else if (next = part.match(RE_TAG_TEXT)) {
|
|
90247
|
-
token = Text;
|
|
90248
|
-
state = State.TopLevelContent;
|
|
90249
|
-
} else {
|
|
90250
|
-
throw new UnexpectedTokenError();
|
|
90251
|
-
}
|
|
90252
|
-
break;
|
|
90253
|
-
case State.InsideOpeningTagAfterWhitespace:
|
|
90254
|
-
if (next = part.match(RE_ATTRIBUTE_NAME)) {
|
|
90255
|
-
token = AttributeName;
|
|
90256
|
-
state = State.AfterAttributeName;
|
|
90257
|
-
} else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
|
|
90258
|
-
token = ClosingAngleBracket;
|
|
90259
|
-
state = State.TopLevelContent;
|
|
90260
|
-
} else if (next = part.match(RE_SELF_CLOSING)) {
|
|
90261
|
-
token = ClosingAngleBracket;
|
|
90262
|
-
state = State.TopLevelContent;
|
|
90263
|
-
} else if (next = part.match(RE_TEXT)) {
|
|
90264
|
-
token = AttributeName;
|
|
90265
|
-
state = State.AfterAttributeName;
|
|
90266
|
-
} else {
|
|
90267
|
-
text.slice(index).match(RE_TEXT); // ?
|
|
90268
|
-
text.slice(index); // ?
|
|
90269
|
-
throw new UnexpectedTokenError();
|
|
90270
|
-
}
|
|
90271
|
-
break;
|
|
90272
|
-
case State.InsideRawTextElement:
|
|
90273
|
-
{
|
|
90274
|
-
// Match everything up to the closing tag for the current raw-text element
|
|
90275
|
-
const closingTagPattern = new RegExp(`^([\\s\\S]*?)(<\\/${rawTextTagName}>)`, 'i');
|
|
90276
|
-
const rawMatch = part.match(closingTagPattern);
|
|
90277
|
-
if (rawMatch) {
|
|
90278
|
-
// Emit content before the closing tag (if any)
|
|
90279
|
-
if (rawMatch[1].length > 0) {
|
|
90280
|
-
tokens.push({
|
|
90281
|
-
text: rawMatch[1],
|
|
90282
|
-
type: Content
|
|
90283
|
-
});
|
|
90284
|
-
index += rawMatch[1].length;
|
|
90285
|
-
}
|
|
90286
|
-
// Now emit the closing tag tokens: <, /, tagname, >
|
|
90287
|
-
// < token
|
|
90288
|
-
tokens.push({
|
|
90289
|
-
text: '<',
|
|
90290
|
-
type: OpeningAngleBracket
|
|
90291
|
-
});
|
|
90292
|
-
index += 1;
|
|
90293
|
-
// / token
|
|
90294
|
-
tokens.push({
|
|
90295
|
-
text: '/',
|
|
90296
|
-
type: ClosingTagSlash
|
|
90297
|
-
});
|
|
90298
|
-
index += 1;
|
|
90299
|
-
// tagname token
|
|
90300
|
-
tokens.push({
|
|
90301
|
-
text: rawTextTagName,
|
|
90302
|
-
type: TagNameEnd
|
|
90303
|
-
});
|
|
90304
|
-
index += rawTextTagName.length;
|
|
90305
|
-
// > token
|
|
90306
|
-
tokens.push({
|
|
90307
|
-
text: '>',
|
|
90308
|
-
type: ClosingAngleBracket
|
|
90309
|
-
});
|
|
90310
|
-
index += 1;
|
|
90311
|
-
rawTextTagName = '';
|
|
90312
|
-
state = State.TopLevelContent;
|
|
90313
|
-
continue;
|
|
90314
|
-
}
|
|
90315
|
-
// No closing tag found — consume everything as content
|
|
90316
|
-
next = [part];
|
|
90317
|
-
token = Content;
|
|
90318
|
-
rawTextTagName = '';
|
|
90319
|
-
state = State.TopLevelContent;
|
|
90320
|
-
break;
|
|
90321
|
-
}
|
|
90322
|
-
case State.TopLevelContent:
|
|
90323
|
-
if (next = part.match(RE_ANGLE_BRACKET_OPEN_TAG)) {
|
|
90324
|
-
token = OpeningAngleBracket;
|
|
90325
|
-
state = State.AfterOpeningAngleBracket;
|
|
90326
|
-
} else if (next = part.match(RE_CONTENT)) {
|
|
90327
|
-
token = Content;
|
|
90328
|
-
state = State.TopLevelContent;
|
|
90329
|
-
} else if (next = part.match(RE_BLOCK_COMMENT_START)) {
|
|
90330
|
-
token = CommentStart;
|
|
90331
|
-
state = State.InsideComment;
|
|
90332
|
-
} else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
|
|
90333
|
-
token = Content;
|
|
90334
|
-
state = State.TopLevelContent;
|
|
90335
|
-
} else if (next = part.match(RE_ANGLE_BRACKET_OPEN)) {
|
|
90336
|
-
token = Text;
|
|
90337
|
-
state = State.TopLevelContent;
|
|
90338
|
-
} else {
|
|
90339
|
-
throw new UnexpectedTokenError();
|
|
90340
|
-
}
|
|
90341
|
-
break;
|
|
90342
|
-
default:
|
|
90343
|
-
throw new UnexpectedTokenError();
|
|
90344
|
-
}
|
|
90345
|
-
const tokenText = next[0];
|
|
90346
|
-
// After closing angle bracket of a raw-text element opening tag,
|
|
90347
|
-
// switch to raw text content mode instead of top-level content
|
|
90348
|
-
if (rawTextTagName && token === ClosingAngleBracket && state === State.TopLevelContent) {
|
|
90349
|
-
state = State.InsideRawTextElement;
|
|
90350
|
-
}
|
|
90351
|
-
tokens.push({
|
|
90352
|
-
text: tokenText,
|
|
90353
|
-
type: token
|
|
90354
|
-
});
|
|
90355
|
-
index += tokenText.length;
|
|
90356
|
-
}
|
|
90357
|
-
return tokens;
|
|
90358
|
-
};
|
|
90359
|
-
|
|
90360
|
-
// Tags that should be completely skipped (both tag and content)
|
|
90361
|
-
const TAGS_TO_SKIP_COMPLETELY = new Set(['meta', 'title']);
|
|
90362
|
-
|
|
90363
|
-
// Tags that should have their opening/closing tags skipped but content processed
|
|
90364
|
-
const TAGS_TO_SKIP_TAG_ONLY = new Set(['html', 'head']);
|
|
90365
|
-
|
|
90366
|
-
// Tags where we capture content as CSS
|
|
90367
|
-
const TAGS_TO_CAPTURE_AS_CSS = new Set(['style']);
|
|
90368
|
-
|
|
90369
|
-
// Tags where we capture content as JavaScript
|
|
90370
|
-
const TAGS_TO_CAPTURE_AS_JS = new Set(['script']);
|
|
90371
|
-
const parseHtml = (html, allowedAttributes = [], defaultAllowedAttributes = []) => {
|
|
90372
|
-
string(html);
|
|
90373
|
-
array(allowedAttributes);
|
|
90374
|
-
array(defaultAllowedAttributes);
|
|
90375
|
-
|
|
90376
|
-
// Combine default allowed attributes with any additional ones provided
|
|
90377
|
-
const allAllowedAttributes = new Set([...defaultAllowedAttributes, ...allowedAttributes]);
|
|
90378
|
-
const useBuiltInDefaults = allowedAttributes.length === 0;
|
|
90379
|
-
const tokens = tokenizeHtml(html);
|
|
90380
|
-
const dom = [];
|
|
90381
|
-
const css = [];
|
|
90382
|
-
const scripts = [];
|
|
90383
|
-
const root = {
|
|
90384
|
-
childCount: 0,
|
|
90385
|
-
type: 0
|
|
90386
|
-
};
|
|
90387
|
-
let current = root;
|
|
90388
|
-
const stack = [root];
|
|
90389
|
-
const tagStack = []; // Track tag names to match closing tags
|
|
90390
|
-
let attributeName = '';
|
|
90391
|
-
let lastTagWasSelfClosing = false;
|
|
90392
|
-
let skipDepth = 0; // Track how many levels deep we are in skipped content
|
|
90393
|
-
let captureCss = false; // Track if we're inside a style tag
|
|
90394
|
-
let cssContent = ''; // Accumulate CSS content
|
|
90395
|
-
let captureJs = false; // Track if we're inside a script tag
|
|
90396
|
-
let jsContent = ''; // Accumulate JavaScript content
|
|
90397
|
-
|
|
90398
|
-
for (const token of tokens) {
|
|
90399
|
-
switch (token.type) {
|
|
90400
|
-
case AttributeName:
|
|
90401
|
-
if (skipDepth === 0 && !captureCss && !captureJs) {
|
|
90402
|
-
attributeName = token.text;
|
|
90403
|
-
}
|
|
90404
|
-
break;
|
|
90405
|
-
case AttributeValue:
|
|
90406
|
-
if (skipDepth === 0 && !captureCss && !captureJs && (allAllowedAttributes.has(attributeName) || useBuiltInDefaults && isDefaultAllowedAttribute(attributeName, defaultAllowedAttributes))) {
|
|
90407
|
-
let finalAttributeName = attributeName;
|
|
90408
|
-
if (attributeName === 'class') finalAttributeName = 'className';else if (attributeName === 'type') finalAttributeName = 'inputType';
|
|
90409
|
-
current[finalAttributeName] = token.text;
|
|
90410
|
-
}
|
|
90411
|
-
attributeName = '';
|
|
90412
|
-
break;
|
|
90413
|
-
case ClosingAngleBracket:
|
|
90414
|
-
if (skipDepth === 0 && !captureCss && !captureJs) {
|
|
90415
|
-
// Handle boolean attributes (attributes without values)
|
|
90416
|
-
if (attributeName && (allAllowedAttributes.has(attributeName) || useBuiltInDefaults && isDefaultAllowedAttribute(attributeName, defaultAllowedAttributes))) {
|
|
90417
|
-
let finalAttributeName = attributeName;
|
|
90418
|
-
if (attributeName === 'class') finalAttributeName = 'className';else if (attributeName === 'type') finalAttributeName = 'inputType';
|
|
90419
|
-
current[finalAttributeName] = attributeName;
|
|
90420
|
-
}
|
|
90421
|
-
attributeName = '';
|
|
90422
|
-
// Return to parent if the current tag is self-closing
|
|
90423
|
-
if (lastTagWasSelfClosing) {
|
|
90424
|
-
current = stack.at(-1) || root;
|
|
90425
|
-
lastTagWasSelfClosing = false;
|
|
90426
|
-
}
|
|
90427
|
-
}
|
|
90428
|
-
break;
|
|
90429
|
-
case Content:
|
|
90430
|
-
if (captureCss) {
|
|
90431
|
-
cssContent += token.text;
|
|
90432
|
-
} else if (captureJs) {
|
|
90433
|
-
jsContent += token.text;
|
|
90434
|
-
} else if (skipDepth === 0) {
|
|
90435
|
-
current.childCount++;
|
|
90436
|
-
dom.push(text(parseText(token.text)));
|
|
90437
|
-
}
|
|
90438
|
-
break;
|
|
90439
|
-
case Doctype:
|
|
90440
|
-
// Ignore DOCTYPE - it's parsed but not rendered since we're in a div
|
|
90441
|
-
break;
|
|
90442
|
-
case TagNameEnd:
|
|
90443
|
-
const tagNameToClose = tagStack.pop()?.toLowerCase() || '';
|
|
90444
|
-
if (TAGS_TO_CAPTURE_AS_CSS.has(tagNameToClose)) {
|
|
90445
|
-
// Finished capturing CSS
|
|
90446
|
-
if (cssContent.trim()) {
|
|
90447
|
-
css.push(cssContent);
|
|
90448
|
-
}
|
|
90449
|
-
cssContent = '';
|
|
90450
|
-
captureCss = false;
|
|
90451
|
-
} else if (TAGS_TO_CAPTURE_AS_JS.has(tagNameToClose)) {
|
|
90452
|
-
// Finished capturing JavaScript
|
|
90453
|
-
if (jsContent.trim()) {
|
|
90454
|
-
scripts.push(jsContent);
|
|
90455
|
-
}
|
|
90456
|
-
jsContent = '';
|
|
90457
|
-
captureJs = false;
|
|
90458
|
-
} else if (TAGS_TO_SKIP_COMPLETELY.has(tagNameToClose)) {
|
|
90459
|
-
// We were skipping this content, so decrement skipDepth
|
|
90460
|
-
skipDepth--;
|
|
90461
|
-
} else if (TAGS_TO_SKIP_TAG_ONLY.has(tagNameToClose)) ; else {
|
|
90462
|
-
// Normal tag - pop from stack
|
|
90463
|
-
if (stack.length > 1) {
|
|
90464
|
-
stack.pop();
|
|
90465
|
-
}
|
|
90466
|
-
current = stack.at(-1) || root;
|
|
90467
|
-
}
|
|
90468
|
-
break;
|
|
90469
|
-
case TagNameStart:
|
|
90470
|
-
const tagNameLower = token.text.toLowerCase();
|
|
90471
|
-
lastTagWasSelfClosing = isSelfClosingTag(token.text);
|
|
90472
|
-
|
|
90473
|
-
// Check if this tag captures CSS content
|
|
90474
|
-
if (TAGS_TO_CAPTURE_AS_CSS.has(tagNameLower)) {
|
|
90475
|
-
captureCss = true;
|
|
90476
|
-
cssContent = '';
|
|
90477
|
-
tagStack.push(token.text);
|
|
90478
|
-
}
|
|
90479
|
-
// Check if this tag captures JavaScript content
|
|
90480
|
-
else if (TAGS_TO_CAPTURE_AS_JS.has(tagNameLower)) {
|
|
90481
|
-
captureJs = true;
|
|
90482
|
-
jsContent = '';
|
|
90483
|
-
tagStack.push(token.text);
|
|
90484
|
-
}
|
|
90485
|
-
// Check if this tag should be completely skipped (meta, title)
|
|
90486
|
-
else if (TAGS_TO_SKIP_COMPLETELY.has(tagNameLower)) {
|
|
90487
|
-
if (!lastTagWasSelfClosing) {
|
|
90488
|
-
// For non-self-closing tags like title, mark as skipped
|
|
90489
|
-
skipDepth++;
|
|
90490
|
-
tagStack.push(token.text);
|
|
90491
|
-
}
|
|
90492
|
-
// For self-closing tags like meta, we just skip them without tracking
|
|
90493
|
-
}
|
|
90494
|
-
// Check if this tag should have its opening/closing tags skipped (html, head)
|
|
90495
|
-
else if (TAGS_TO_SKIP_TAG_ONLY.has(tagNameLower)) {
|
|
90496
|
-
if (!lastTagWasSelfClosing) {
|
|
90497
|
-
// Track the tag name for matching the closing tag
|
|
90498
|
-
tagStack.push(token.text);
|
|
90499
|
-
}
|
|
90500
|
-
}
|
|
90501
|
-
// Normal tag processing
|
|
90502
|
-
else if (skipDepth === 0) {
|
|
90503
|
-
current.childCount++;
|
|
90504
|
-
const newNode = {
|
|
90505
|
-
childCount: 0,
|
|
90506
|
-
type: getVirtualDomTag(token.text)
|
|
90507
|
-
};
|
|
90508
|
-
dom.push(newNode);
|
|
90509
|
-
current = newNode;
|
|
90510
|
-
if (!lastTagWasSelfClosing) {
|
|
90511
|
-
stack.push(current);
|
|
90512
|
-
tagStack.push(token.text);
|
|
90513
|
-
}
|
|
90514
|
-
}
|
|
90515
|
-
break;
|
|
90516
|
-
case WhitespaceInsideOpeningTag:
|
|
90517
|
-
if (skipDepth === 0 && !captureCss && !captureJs &&
|
|
90518
|
-
// Handle boolean attributes (attributes without values)
|
|
90519
|
-
attributeName && (allAllowedAttributes.has(attributeName) || useBuiltInDefaults && isDefaultAllowedAttribute(attributeName, defaultAllowedAttributes))) {
|
|
90520
|
-
let finalAttributeName = attributeName;
|
|
90521
|
-
if (attributeName === 'class') finalAttributeName = 'className';else if (attributeName === 'type') finalAttributeName = 'inputType';
|
|
90522
|
-
current[finalAttributeName] = attributeName;
|
|
90523
|
-
}
|
|
90524
|
-
attributeName = '';
|
|
90525
|
-
break;
|
|
90526
|
-
}
|
|
90527
|
-
}
|
|
90528
|
-
try {
|
|
90529
|
-
Object.defineProperty(dom, 'rootChildCount', {
|
|
90530
|
-
configurable: true,
|
|
90531
|
-
enumerable: false,
|
|
90532
|
-
value: root.childCount
|
|
90533
|
-
});
|
|
90534
|
-
} catch {
|
|
90535
|
-
dom.rootChildCount = root.childCount;
|
|
90536
|
-
}
|
|
90537
|
-
return {
|
|
90538
|
-
css,
|
|
90539
|
-
dom,
|
|
90540
|
-
scripts
|
|
90541
|
-
};
|
|
90542
|
-
};
|
|
90543
|
-
|
|
90544
89616
|
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
90545
89617
|
|
|
90546
89618
|
const states = new Map();
|
|
@@ -90559,6 +89631,8 @@ const toNumber = value => {
|
|
|
90559
89631
|
return 0;
|
|
90560
89632
|
};
|
|
90561
89633
|
|
|
89634
|
+
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
89635
|
+
|
|
90562
89636
|
const patchCanvasElements = async (document, uid) => {
|
|
90563
89637
|
const canvasElements = document.querySelectorAll('canvas');
|
|
90564
89638
|
if (canvasElements.length === 0) {
|
|
@@ -90569,17 +89643,22 @@ const patchCanvasElements = async (document, uid) => {
|
|
|
90569
89643
|
const element = canvasElements[i];
|
|
90570
89644
|
const width = toNumber(element.getAttribute('width') || 300);
|
|
90571
89645
|
const height = toNumber(element.getAttribute('height') || 300);
|
|
89646
|
+
// @ts-ignore
|
|
90572
89647
|
element.width = width;
|
|
89648
|
+
// @ts-ignore
|
|
90573
89649
|
element.height = height;
|
|
90574
89650
|
const {
|
|
90575
89651
|
canvasId,
|
|
90576
89652
|
offscreenCanvas
|
|
90577
|
-
} = await getOffscreenCanvas(width, height);
|
|
89653
|
+
} = await getOffscreenCanvas(uid, width, height);
|
|
90578
89654
|
const dataId = String(canvasId);
|
|
89655
|
+
// @ts-ignore
|
|
90579
89656
|
element.__canvasId = canvasId;
|
|
89657
|
+
// @ts-ignore
|
|
90580
89658
|
element.__offscreenCanvas = offscreenCanvas;
|
|
90581
89659
|
element.dataset.id = dataId;
|
|
90582
89660
|
const context = offscreenCanvas.getContext('2d');
|
|
89661
|
+
// @ts-ignore
|
|
90583
89662
|
element.getContext = contextType => {
|
|
90584
89663
|
if (contextType === '2d') {
|
|
90585
89664
|
return context;
|
|
@@ -90601,6 +89680,7 @@ const patchCanvasElements = async (document, uid) => {
|
|
|
90601
89680
|
get: () => widthValue,
|
|
90602
89681
|
set: newWidth => {
|
|
90603
89682
|
widthValue = toNumber(newWidth);
|
|
89683
|
+
// @ts-ignore
|
|
90604
89684
|
element.__offscreenCanvas.width = widthValue;
|
|
90605
89685
|
}
|
|
90606
89686
|
});
|
|
@@ -90613,6 +89693,7 @@ const patchCanvasElements = async (document, uid) => {
|
|
|
90613
89693
|
get: () => heightValue,
|
|
90614
89694
|
set: newHeight => {
|
|
90615
89695
|
heightValue = toNumber(newHeight);
|
|
89696
|
+
// @ts-ignore
|
|
90616
89697
|
element.__offscreenCanvas.height = heightValue;
|
|
90617
89698
|
}
|
|
90618
89699
|
});
|
|
@@ -90629,729 +89710,44 @@ const patchCanvasElements = async (document, uid) => {
|
|
|
90629
89710
|
});
|
|
90630
89711
|
};
|
|
90631
89712
|
|
|
90632
|
-
|
|
90633
|
-
|
|
90634
|
-
const updateContent = async (state, uri) => {
|
|
89713
|
+
const updateContent = async (uid, width, height, content, scripts) => {
|
|
90635
89714
|
try {
|
|
90636
|
-
// Read the file content using RendererWorker RPC
|
|
90637
|
-
const content = await readFile(uri);
|
|
90638
|
-
|
|
90639
|
-
// Parse the content into virtual DOM and CSS
|
|
90640
|
-
const parseResult = parseHtml(content);
|
|
90641
|
-
let parsedDom = parseResult.dom;
|
|
90642
|
-
let {
|
|
90643
|
-
css
|
|
90644
|
-
} = parseResult;
|
|
90645
89715
|
const {
|
|
90646
|
-
|
|
90647
|
-
|
|
90648
|
-
|
|
90649
|
-
|
|
90650
|
-
|
|
90651
|
-
|
|
90652
|
-
|
|
90653
|
-
|
|
90654
|
-
|
|
90655
|
-
|
|
90656
|
-
|
|
90657
|
-
|
|
90658
|
-
const elementMap = new Map();
|
|
90659
|
-
const serialized = serialize(happyDomDocument, elementMap);
|
|
90660
|
-
parsedDom = serialized.dom;
|
|
90661
|
-
css = serialized.css;
|
|
90662
|
-
set$1(state.uid, {
|
|
90663
|
-
document: happyDomDocument,
|
|
90664
|
-
elementMap,
|
|
90665
|
-
window: happyDomWindow
|
|
90666
|
-
});
|
|
90667
|
-
observe(state.uid, happyDomDocument, happyDomWindow);
|
|
90668
|
-
} catch (error) {
|
|
90669
|
-
console.error(error);
|
|
90670
|
-
// If script execution fails, fall back to static HTML parsing
|
|
90671
|
-
}
|
|
90672
|
-
}
|
|
90673
|
-
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
89716
|
+
document: happyDomDocument,
|
|
89717
|
+
window: happyDomWindow
|
|
89718
|
+
} = createWindow(content);
|
|
89719
|
+
await patchCanvasElements(happyDomDocument, uid);
|
|
89720
|
+
executeScripts(happyDomWindow, happyDomDocument, scripts, width, height);
|
|
89721
|
+
const elementMap = new Map();
|
|
89722
|
+
set$1(uid, {
|
|
89723
|
+
document: happyDomDocument,
|
|
89724
|
+
elementMap,
|
|
89725
|
+
window: happyDomWindow
|
|
89726
|
+
});
|
|
89727
|
+
observe(uid, happyDomDocument, happyDomWindow);
|
|
90674
89728
|
return {
|
|
90675
|
-
|
|
90676
|
-
css,
|
|
90677
|
-
errorMessage: '',
|
|
90678
|
-
parsedDom,
|
|
90679
|
-
parsedNodesChildNodeCount,
|
|
90680
|
-
scripts
|
|
89729
|
+
errorMessage: ''
|
|
90681
89730
|
};
|
|
90682
89731
|
} catch (error) {
|
|
90683
89732
|
// If file reading or parsing fails, return empty content and parsedDom with error message
|
|
90684
89733
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
90685
89734
|
return {
|
|
90686
|
-
|
|
90687
|
-
css: [],
|
|
90688
|
-
errorMessage,
|
|
90689
|
-
parsedDom: [],
|
|
90690
|
-
parsedNodesChildNodeCount: 0,
|
|
90691
|
-
scripts: []
|
|
89735
|
+
errorMessage
|
|
90692
89736
|
};
|
|
90693
89737
|
}
|
|
90694
89738
|
};
|
|
90695
89739
|
|
|
90696
|
-
const
|
|
90697
|
-
const {
|
|
90698
|
-
content,
|
|
90699
|
-
css,
|
|
90700
|
-
errorMessage,
|
|
90701
|
-
parsedDom,
|
|
90702
|
-
parsedNodesChildNodeCount,
|
|
90703
|
-
scripts
|
|
90704
|
-
} = await updateContent(state, state.uri);
|
|
90705
|
-
return {
|
|
90706
|
-
...state,
|
|
90707
|
-
content,
|
|
90708
|
-
css,
|
|
90709
|
-
errorMessage,
|
|
90710
|
-
parsedDom,
|
|
90711
|
-
parsedNodesChildNodeCount,
|
|
90712
|
-
scripts
|
|
90713
|
-
};
|
|
90714
|
-
};
|
|
90715
|
-
|
|
90716
|
-
const dispatchInputEvent = (element, window) => {
|
|
90717
|
-
const inputEvent = new window.Event('input', {
|
|
90718
|
-
bubbles: true
|
|
90719
|
-
});
|
|
90720
|
-
dispatchEvent(element, inputEvent);
|
|
90721
|
-
};
|
|
90722
|
-
|
|
90723
|
-
const handleInputSandbox = async (state, hdId, value) => {
|
|
90724
|
-
const {
|
|
90725
|
-
sandboxRpc,
|
|
90726
|
-
uid
|
|
90727
|
-
} = state;
|
|
90728
|
-
await sandboxRpc.invoke('SandBox.handleInput', uid, hdId, value);
|
|
90729
|
-
const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', uid);
|
|
90730
|
-
const parsedDom = serialized.dom;
|
|
90731
|
-
const {
|
|
90732
|
-
css
|
|
90733
|
-
} = serialized;
|
|
90734
|
-
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
90735
|
-
return {
|
|
90736
|
-
...state,
|
|
90737
|
-
css,
|
|
90738
|
-
parsedDom,
|
|
90739
|
-
parsedNodesChildNodeCount
|
|
90740
|
-
};
|
|
90741
|
-
};
|
|
90742
|
-
const handleInputLocal = (state, hdId, value) => {
|
|
90743
|
-
const happyDomInstance = get(state.uid);
|
|
90744
|
-
if (!happyDomInstance) {
|
|
90745
|
-
return state;
|
|
90746
|
-
}
|
|
90747
|
-
const element = happyDomInstance.elementMap.get(hdId);
|
|
90748
|
-
if (!element) {
|
|
90749
|
-
return state;
|
|
90750
|
-
}
|
|
90751
|
-
element.value = value;
|
|
90752
|
-
dispatchInputEvent(element, happyDomInstance.window);
|
|
90753
|
-
const elementMap = new Map();
|
|
90754
|
-
const serialized = serialize(happyDomInstance.document, elementMap);
|
|
90755
|
-
set$1(state.uid, {
|
|
90756
|
-
document: happyDomInstance.document,
|
|
90757
|
-
elementMap,
|
|
90758
|
-
window: happyDomInstance.window
|
|
90759
|
-
});
|
|
90760
|
-
const parsedDom = serialized.dom;
|
|
90761
|
-
const {
|
|
90762
|
-
css
|
|
90763
|
-
} = serialized;
|
|
90764
|
-
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
90765
|
-
return {
|
|
90766
|
-
...state,
|
|
90767
|
-
css,
|
|
90768
|
-
parsedDom,
|
|
90769
|
-
parsedNodesChildNodeCount
|
|
90770
|
-
};
|
|
90771
|
-
};
|
|
90772
|
-
const handleInput = (state, hdId, value) => {
|
|
90773
|
-
if (!hdId) {
|
|
90774
|
-
return state;
|
|
90775
|
-
}
|
|
90776
|
-
if (state.useSandboxWorker) {
|
|
90777
|
-
return handleInputSandbox(state, hdId, value);
|
|
90778
|
-
}
|
|
90779
|
-
return handleInputLocal(state, hdId, value);
|
|
90780
|
-
};
|
|
90781
|
-
|
|
90782
|
-
const dispatchKeydownEvent = (element, window, key, code) => {
|
|
90783
|
-
const keydownEvent = new window.KeyboardEvent('keydown', {
|
|
90784
|
-
bubbles: true,
|
|
90785
|
-
code,
|
|
90786
|
-
key
|
|
90787
|
-
});
|
|
90788
|
-
dispatchEvent(element, keydownEvent);
|
|
90789
|
-
};
|
|
90790
|
-
|
|
90791
|
-
const handleKeydownSandbox = async (state, hdId, key, code) => {
|
|
90792
|
-
const {
|
|
90793
|
-
sandboxRpc,
|
|
90794
|
-
uid
|
|
90795
|
-
} = state;
|
|
90796
|
-
await sandboxRpc.invoke('SandBox.handleKeyDown', uid, hdId, key, code);
|
|
90797
|
-
const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', uid);
|
|
90798
|
-
const parsedDom = serialized.dom;
|
|
90799
|
-
const {
|
|
90800
|
-
css
|
|
90801
|
-
} = serialized;
|
|
90802
|
-
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
90803
|
-
return {
|
|
90804
|
-
...state,
|
|
90805
|
-
css,
|
|
90806
|
-
parsedDom,
|
|
90807
|
-
parsedNodesChildNodeCount
|
|
90808
|
-
};
|
|
90809
|
-
};
|
|
90810
|
-
const handleKeydownLocal = (state, hdId, key, code) => {
|
|
90811
|
-
const happyDomInstance = get(state.uid);
|
|
90812
|
-
if (!happyDomInstance) {
|
|
90813
|
-
return state;
|
|
90814
|
-
}
|
|
90815
|
-
const element = hdId ? happyDomInstance.elementMap.get(hdId) : happyDomInstance.document;
|
|
90816
|
-
if (!element) {
|
|
90817
|
-
return state;
|
|
90818
|
-
}
|
|
90819
|
-
dispatchKeydownEvent(element, happyDomInstance.window, key, code);
|
|
90820
|
-
const elementMap = new Map();
|
|
90821
|
-
const serialized = serialize(happyDomInstance.document, elementMap);
|
|
90822
|
-
set$1(state.uid, {
|
|
90823
|
-
document: happyDomInstance.document,
|
|
90824
|
-
elementMap,
|
|
90825
|
-
window: happyDomInstance.window
|
|
90826
|
-
});
|
|
90827
|
-
const parsedDom = serialized.dom;
|
|
90828
|
-
const {
|
|
90829
|
-
css
|
|
90830
|
-
} = serialized;
|
|
90831
|
-
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
90832
|
-
return {
|
|
90833
|
-
...state,
|
|
90834
|
-
css,
|
|
90835
|
-
parsedDom,
|
|
90836
|
-
parsedNodesChildNodeCount
|
|
90837
|
-
};
|
|
90838
|
-
};
|
|
90839
|
-
const handleKeydown = (state, hdId, key, code) => {
|
|
90840
|
-
if (state.useSandboxWorker) {
|
|
90841
|
-
return handleKeydownSandbox(state, hdId, key, code);
|
|
90842
|
-
}
|
|
90843
|
-
return handleKeydownLocal(state, hdId, key, code);
|
|
90844
|
-
};
|
|
90845
|
-
|
|
90846
|
-
const dispatchKeyupEvent = (element, window, key, code) => {
|
|
90847
|
-
const keyupEvent = new window.KeyboardEvent('keyup', {
|
|
90848
|
-
bubbles: true,
|
|
90849
|
-
code,
|
|
90850
|
-
key
|
|
90851
|
-
});
|
|
90852
|
-
dispatchEvent(element, keyupEvent);
|
|
90853
|
-
};
|
|
90854
|
-
|
|
90855
|
-
const handleKeyupSandbox = async (state, hdId, key, code) => {
|
|
90856
|
-
const {
|
|
90857
|
-
sandboxRpc,
|
|
90858
|
-
uid
|
|
90859
|
-
} = state;
|
|
90860
|
-
await sandboxRpc.invoke('SandBox.handleKeyUp', uid, hdId, key, code);
|
|
90861
|
-
const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', uid);
|
|
90862
|
-
const parsedDom = serialized.dom;
|
|
90863
|
-
const {
|
|
90864
|
-
css
|
|
90865
|
-
} = serialized;
|
|
90866
|
-
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
90867
|
-
return {
|
|
90868
|
-
...state,
|
|
90869
|
-
css,
|
|
90870
|
-
parsedDom,
|
|
90871
|
-
parsedNodesChildNodeCount
|
|
90872
|
-
};
|
|
90873
|
-
};
|
|
90874
|
-
const handleKeyupLocal = (state, hdId, key, code) => {
|
|
90875
|
-
const happyDomInstance = get(state.uid);
|
|
90876
|
-
if (!happyDomInstance) {
|
|
90877
|
-
return state;
|
|
90878
|
-
}
|
|
90879
|
-
const element = hdId ? happyDomInstance.elementMap.get(hdId) : happyDomInstance.document;
|
|
90880
|
-
if (!element) {
|
|
90881
|
-
return state;
|
|
90882
|
-
}
|
|
90883
|
-
dispatchKeyupEvent(element, happyDomInstance.window, key, code);
|
|
90884
|
-
const elementMap = new Map();
|
|
90885
|
-
const serialized = serialize(happyDomInstance.document, elementMap);
|
|
90886
|
-
set$1(state.uid, {
|
|
90887
|
-
document: happyDomInstance.document,
|
|
90888
|
-
elementMap,
|
|
90889
|
-
window: happyDomInstance.window
|
|
90890
|
-
});
|
|
90891
|
-
const parsedDom = serialized.dom;
|
|
90892
|
-
const {
|
|
90893
|
-
css
|
|
90894
|
-
} = serialized;
|
|
90895
|
-
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
90896
|
-
return {
|
|
90897
|
-
...state,
|
|
90898
|
-
css,
|
|
90899
|
-
parsedDom,
|
|
90900
|
-
parsedNodesChildNodeCount
|
|
90901
|
-
};
|
|
90902
|
-
};
|
|
90903
|
-
const handleKeyup = (state, hdId, key, code) => {
|
|
90904
|
-
if (state.useSandboxWorker) {
|
|
90905
|
-
return handleKeyupSandbox(state, hdId, key, code);
|
|
90906
|
-
}
|
|
90907
|
-
return handleKeyupLocal(state, hdId, key, code);
|
|
90908
|
-
};
|
|
90909
|
-
|
|
90910
|
-
const handleMessagePort = async port => {
|
|
90911
|
-
await PlainMessagePortRpc.create({
|
|
90912
|
-
commandMap: {},
|
|
90913
|
-
messagePort: port
|
|
90914
|
-
});
|
|
90915
|
-
};
|
|
90916
|
-
|
|
90917
|
-
const dispatchMousedownEvent = (element, window, clientX = 0, clientY = 0) => {
|
|
90918
|
-
const mousedownEvent = new window.MouseEvent('mousedown', {
|
|
90919
|
-
bubbles: true,
|
|
90920
|
-
clientX,
|
|
90921
|
-
clientY
|
|
90922
|
-
});
|
|
90923
|
-
dispatchEvent(element, mousedownEvent);
|
|
90924
|
-
};
|
|
90925
|
-
|
|
90926
|
-
const handleMousedownSandbox = async (state, hdId) => {
|
|
90927
|
-
const {
|
|
90928
|
-
sandboxRpc,
|
|
90929
|
-
uid
|
|
90930
|
-
} = state;
|
|
90931
|
-
await sandboxRpc.invoke('SandBox.handleMousedown', uid, hdId);
|
|
90932
|
-
const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', uid);
|
|
90933
|
-
const parsedDom = serialized.dom;
|
|
90934
|
-
const {
|
|
90935
|
-
css
|
|
90936
|
-
} = serialized;
|
|
90937
|
-
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
90938
|
-
return {
|
|
90939
|
-
...state,
|
|
90940
|
-
css,
|
|
90941
|
-
parsedDom,
|
|
90942
|
-
parsedNodesChildNodeCount
|
|
90943
|
-
};
|
|
90944
|
-
};
|
|
90945
|
-
const handleMousedownLocal = (state, hdId, clientX, clientY) => {
|
|
90946
|
-
const happyDomInstance = get(state.uid);
|
|
90947
|
-
if (!happyDomInstance) {
|
|
90948
|
-
return state;
|
|
90949
|
-
}
|
|
90950
|
-
const element = happyDomInstance.elementMap.get(hdId);
|
|
90951
|
-
if (!element) {
|
|
90952
|
-
return state;
|
|
90953
|
-
}
|
|
90954
|
-
const adjustedClientX = clientX - state.x;
|
|
90955
|
-
const adjustedClientY = clientY - state.y;
|
|
90956
|
-
dispatchMousedownEvent(element, happyDomInstance.window, adjustedClientX, adjustedClientY);
|
|
90957
|
-
const elementMap = new Map();
|
|
90958
|
-
const serialized = serialize(happyDomInstance.document, elementMap);
|
|
90959
|
-
set$1(state.uid, {
|
|
90960
|
-
document: happyDomInstance.document,
|
|
90961
|
-
elementMap,
|
|
90962
|
-
window: happyDomInstance.window
|
|
90963
|
-
});
|
|
90964
|
-
const parsedDom = serialized.dom;
|
|
90965
|
-
const {
|
|
90966
|
-
css
|
|
90967
|
-
} = serialized;
|
|
90968
|
-
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
90969
|
-
return {
|
|
90970
|
-
...state,
|
|
90971
|
-
css,
|
|
90972
|
-
parsedDom,
|
|
90973
|
-
parsedNodesChildNodeCount
|
|
90974
|
-
};
|
|
90975
|
-
};
|
|
90976
|
-
const handleMousedown = (state, hdId, clientX, clientY) => {
|
|
90977
|
-
if (!hdId) {
|
|
90978
|
-
return state;
|
|
90979
|
-
}
|
|
90980
|
-
if (state.useSandboxWorker) {
|
|
90981
|
-
return handleMousedownSandbox(state, hdId);
|
|
90982
|
-
}
|
|
90983
|
-
return handleMousedownLocal(state, hdId, clientX, clientY);
|
|
90984
|
-
};
|
|
90985
|
-
|
|
90986
|
-
const dispatchMousemoveEvent = (element, window, clientX = 0, clientY = 0) => {
|
|
90987
|
-
const mousemoveEvent = new window.MouseEvent('mousemove', {
|
|
90988
|
-
bubbles: true,
|
|
90989
|
-
clientX,
|
|
90990
|
-
clientY
|
|
90991
|
-
});
|
|
90992
|
-
dispatchEvent(element, mousemoveEvent);
|
|
90993
|
-
};
|
|
90994
|
-
|
|
90995
|
-
const handleMousemoveSandbox = async (state, hdId) => {
|
|
90996
|
-
const {
|
|
90997
|
-
sandboxRpc,
|
|
90998
|
-
uid
|
|
90999
|
-
} = state;
|
|
91000
|
-
await sandboxRpc.invoke('SandBox.handleMousemove', uid, hdId);
|
|
91001
|
-
const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', uid);
|
|
91002
|
-
const parsedDom = serialized.dom;
|
|
91003
|
-
const {
|
|
91004
|
-
css
|
|
91005
|
-
} = serialized;
|
|
91006
|
-
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
91007
|
-
return {
|
|
91008
|
-
...state,
|
|
91009
|
-
css,
|
|
91010
|
-
parsedDom,
|
|
91011
|
-
parsedNodesChildNodeCount
|
|
91012
|
-
};
|
|
91013
|
-
};
|
|
91014
|
-
const handleMousemoveLocal = (state, hdId, clientX, clientY) => {
|
|
91015
|
-
const happyDomInstance = get(state.uid);
|
|
91016
|
-
if (!happyDomInstance) {
|
|
91017
|
-
return state;
|
|
91018
|
-
}
|
|
91019
|
-
const element = happyDomInstance.elementMap.get(hdId);
|
|
91020
|
-
if (!element) {
|
|
91021
|
-
return state;
|
|
91022
|
-
}
|
|
91023
|
-
const adjustedClientX = clientX - state.x;
|
|
91024
|
-
const adjustedClientY = clientY - state.y;
|
|
91025
|
-
dispatchMousemoveEvent(element, happyDomInstance.window, adjustedClientX, adjustedClientY);
|
|
91026
|
-
const elementMap = new Map();
|
|
91027
|
-
const serialized = serialize(happyDomInstance.document, elementMap);
|
|
91028
|
-
set$1(state.uid, {
|
|
91029
|
-
document: happyDomInstance.document,
|
|
91030
|
-
elementMap,
|
|
91031
|
-
window: happyDomInstance.window
|
|
91032
|
-
});
|
|
91033
|
-
const parsedDom = serialized.dom;
|
|
91034
|
-
const {
|
|
91035
|
-
css
|
|
91036
|
-
} = serialized;
|
|
91037
|
-
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
91038
|
-
return {
|
|
91039
|
-
...state,
|
|
91040
|
-
css,
|
|
91041
|
-
parsedDom,
|
|
91042
|
-
parsedNodesChildNodeCount
|
|
91043
|
-
};
|
|
91044
|
-
};
|
|
91045
|
-
const handleMousemove = (state, hdId, clientX, clientY) => {
|
|
91046
|
-
if (!hdId) {
|
|
91047
|
-
return state;
|
|
91048
|
-
}
|
|
91049
|
-
if (state.useSandboxWorker) {
|
|
91050
|
-
return handleMousemoveSandbox(state, hdId);
|
|
91051
|
-
}
|
|
91052
|
-
return handleMousemoveLocal(state, hdId, clientX, clientY);
|
|
91053
|
-
};
|
|
91054
|
-
|
|
91055
|
-
const dispatchMouseupEvent = (element, window, clientX = 0, clientY = 0) => {
|
|
91056
|
-
const mouseupEvent = new window.MouseEvent('mouseup', {
|
|
91057
|
-
bubbles: true,
|
|
91058
|
-
clientX,
|
|
91059
|
-
clientY
|
|
91060
|
-
});
|
|
91061
|
-
dispatchEvent(element, mouseupEvent);
|
|
91062
|
-
};
|
|
91063
|
-
|
|
91064
|
-
const handleMouseupSandbox = async (state, hdId) => {
|
|
91065
|
-
const {
|
|
91066
|
-
sandboxRpc,
|
|
91067
|
-
uid
|
|
91068
|
-
} = state;
|
|
91069
|
-
await sandboxRpc.invoke('SandBox.handleMouseup', uid, hdId);
|
|
91070
|
-
const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', uid);
|
|
91071
|
-
const parsedDom = serialized.dom;
|
|
91072
|
-
const {
|
|
91073
|
-
css
|
|
91074
|
-
} = serialized;
|
|
91075
|
-
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
91076
|
-
return {
|
|
91077
|
-
...state,
|
|
91078
|
-
css,
|
|
91079
|
-
parsedDom,
|
|
91080
|
-
parsedNodesChildNodeCount
|
|
91081
|
-
};
|
|
91082
|
-
};
|
|
91083
|
-
const handleMouseupLocal = (state, hdId) => {
|
|
91084
|
-
const happyDomInstance = get(state.uid);
|
|
91085
|
-
if (!happyDomInstance) {
|
|
91086
|
-
return state;
|
|
91087
|
-
}
|
|
91088
|
-
const element = happyDomInstance.elementMap.get(hdId);
|
|
91089
|
-
if (!element) {
|
|
91090
|
-
return state;
|
|
91091
|
-
}
|
|
91092
|
-
dispatchMouseupEvent(element, happyDomInstance.window);
|
|
91093
|
-
const elementMap = new Map();
|
|
91094
|
-
const serialized = serialize(happyDomInstance.document, elementMap);
|
|
91095
|
-
set$1(state.uid, {
|
|
91096
|
-
document: happyDomInstance.document,
|
|
91097
|
-
elementMap,
|
|
91098
|
-
window: happyDomInstance.window
|
|
91099
|
-
});
|
|
91100
|
-
const parsedDom = serialized.dom;
|
|
91101
|
-
const {
|
|
91102
|
-
css
|
|
91103
|
-
} = serialized;
|
|
91104
|
-
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
91105
|
-
return {
|
|
91106
|
-
...state,
|
|
91107
|
-
css,
|
|
91108
|
-
parsedDom,
|
|
91109
|
-
parsedNodesChildNodeCount
|
|
91110
|
-
};
|
|
91111
|
-
};
|
|
91112
|
-
const handleMouseup = (state, hdId) => {
|
|
91113
|
-
if (!hdId) {
|
|
91114
|
-
return state;
|
|
91115
|
-
}
|
|
91116
|
-
if (state.useSandboxWorker) {
|
|
91117
|
-
return handleMouseupSandbox(state, hdId);
|
|
91118
|
-
}
|
|
91119
|
-
return handleMouseupLocal(state, hdId);
|
|
91120
|
-
};
|
|
91121
|
-
|
|
91122
|
-
const loadContent = async state => {
|
|
89740
|
+
const loadContent = async (uid, width, height, content, scripts) => {
|
|
91123
89741
|
// Try to register to receive editor change notifications from the editor worker.
|
|
91124
89742
|
// Use dynamic access and ignore errors so this is safe in environments where
|
|
91125
89743
|
// the EditorWorker / ListenerType are not available (e.g. unit tests).
|
|
91126
|
-
const EditorChange = 1;
|
|
91127
|
-
const rpcId = 9112;
|
|
91128
|
-
try {
|
|
91129
|
-
await invoke$1('Listener.register', EditorChange, rpcId);
|
|
91130
|
-
} catch (error) {
|
|
91131
|
-
console.error(error);
|
|
91132
|
-
}
|
|
91133
89744
|
|
|
91134
89745
|
// Read and parse file contents if we have a URI
|
|
91135
89746
|
const {
|
|
91136
|
-
|
|
91137
|
-
|
|
91138
|
-
errorMessage,
|
|
91139
|
-
parsedDom,
|
|
91140
|
-
parsedNodesChildNodeCount,
|
|
91141
|
-
scripts
|
|
91142
|
-
} = state.uri ? await updateContent(state, state.uri) : {
|
|
91143
|
-
content: state.content,
|
|
91144
|
-
css: state.css,
|
|
91145
|
-
errorMessage: state.errorMessage,
|
|
91146
|
-
parsedDom: state.parsedDom,
|
|
91147
|
-
parsedNodesChildNodeCount: state.parsedNodesChildNodeCount,
|
|
91148
|
-
scripts: state.scripts
|
|
91149
|
-
};
|
|
91150
|
-
const {
|
|
91151
|
-
sandboxRpc
|
|
91152
|
-
} = state;
|
|
91153
|
-
let finalParsedDom = parsedDom;
|
|
91154
|
-
let finalCss = css;
|
|
91155
|
-
let finalParsedNodesChildNodeCount = parsedNodesChildNodeCount;
|
|
91156
|
-
if (state.useSandboxWorker && scripts.length > 0) {
|
|
91157
|
-
await sandboxRpc.invoke('SandBox.initialize', state.uid, content, scripts);
|
|
91158
|
-
const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', state.uid);
|
|
91159
|
-
finalParsedDom = serialized.dom;
|
|
91160
|
-
finalCss = serialized.css;
|
|
91161
|
-
finalParsedNodesChildNodeCount = finalParsedDom.length > 0 ? finalParsedDom[0].childCount || 0 : 0;
|
|
91162
|
-
}
|
|
91163
|
-
return {
|
|
91164
|
-
...state,
|
|
91165
|
-
content,
|
|
91166
|
-
css: finalCss,
|
|
91167
|
-
errorCount: 0,
|
|
91168
|
-
errorMessage,
|
|
91169
|
-
initial: false,
|
|
91170
|
-
parsedDom: finalParsedDom,
|
|
91171
|
-
parsedNodesChildNodeCount: finalParsedNodesChildNodeCount,
|
|
91172
|
-
sandboxRpc,
|
|
91173
|
-
scripts,
|
|
91174
|
-
warningCount: 1
|
|
91175
|
-
};
|
|
91176
|
-
};
|
|
91177
|
-
|
|
91178
|
-
const BODY_SELECTOR_REGEX = /\bbody\b/g;
|
|
91179
|
-
const HTML_SELECTOR_REGEX = /\bhtml\b/g;
|
|
91180
|
-
|
|
91181
|
-
/**
|
|
91182
|
-
* Wraps CSS in a CSS nesting block (.Preview { ... }) and replaces 'html' and 'body'
|
|
91183
|
-
* selectors with '&' (the parent selector in CSS nesting).
|
|
91184
|
-
* This approach uses CSS nesting to automatically scope all selectors to the preview div.
|
|
91185
|
-
* Other selectors like 'button' or '*' are automatically scoped within the nesting.
|
|
91186
|
-
*
|
|
91187
|
-
* @param css The CSS string to process
|
|
91188
|
-
* @returns The CSS string wrapped in .Preview nesting block with proper selector replacements
|
|
91189
|
-
*/
|
|
91190
|
-
const replaceCssBodySelector = css => {
|
|
91191
|
-
if (!css.trim()) {
|
|
91192
|
-
return css;
|
|
91193
|
-
}
|
|
91194
|
-
|
|
91195
|
-
// Replace 'html' selector with '&' (CSS nesting parent selector)
|
|
91196
|
-
let result = css.replaceAll(HTML_SELECTOR_REGEX, '&');
|
|
91197
|
-
|
|
91198
|
-
// Replace 'body' selector with '&' (CSS nesting parent selector)
|
|
91199
|
-
result = result.replaceAll(BODY_SELECTOR_REGEX, '&');
|
|
91200
|
-
|
|
91201
|
-
// Wrap the entire CSS in .Preview nesting block
|
|
91202
|
-
result = `.Preview {\n${result}\n}`;
|
|
91203
|
-
return result;
|
|
91204
|
-
};
|
|
91205
|
-
|
|
91206
|
-
const renderCss = (oldState, newState) => {
|
|
91207
|
-
const {
|
|
91208
|
-
css,
|
|
91209
|
-
uid
|
|
91210
|
-
} = newState;
|
|
91211
|
-
|
|
91212
|
-
// Combine all CSS strings into a single string
|
|
91213
|
-
let cssString = css.join('\n');
|
|
91214
|
-
|
|
91215
|
-
// Replace body selector with .Preview since we render the preview in a div element, not a body
|
|
91216
|
-
cssString = replaceCssBodySelector(cssString);
|
|
91217
|
-
|
|
91218
|
-
// Return command in format that can be handled by the viewlet
|
|
91219
|
-
// The 'Viewlet.setCss' is a method that should be called on the viewlet
|
|
91220
|
-
return ['Viewlet.setCss', uid, cssString];
|
|
91221
|
-
};
|
|
91222
|
-
|
|
91223
|
-
const HandleInput = 4;
|
|
91224
|
-
const HandleClick = 11;
|
|
91225
|
-
const HandleKeydown = 12;
|
|
91226
|
-
const HandleKeyup = 13;
|
|
91227
|
-
const HandleMousedown = 14;
|
|
91228
|
-
const HandleMousemove = 15;
|
|
91229
|
-
const HandleMouseup = 16;
|
|
91230
|
-
|
|
91231
|
-
const getEmptyPreviewDom = () => {
|
|
91232
|
-
return [{
|
|
91233
|
-
childCount: 1,
|
|
91234
|
-
className: 'Viewlet Preview',
|
|
91235
|
-
type: Div$1
|
|
91236
|
-
}, {
|
|
91237
|
-
childCount: 1,
|
|
91238
|
-
type: H1$1
|
|
91239
|
-
}, {
|
|
91240
|
-
text: 'No URI has been specified',
|
|
91241
|
-
type: Text$2
|
|
91242
|
-
}];
|
|
91243
|
-
};
|
|
91244
|
-
|
|
91245
|
-
const getPreviewDom = state => {
|
|
91246
|
-
const {
|
|
91247
|
-
parsedDom,
|
|
91248
|
-
parsedNodesChildNodeCount,
|
|
91249
|
-
uri
|
|
91250
|
-
} = state;
|
|
91251
|
-
if (!uri) {
|
|
91252
|
-
return getEmptyPreviewDom();
|
|
91253
|
-
}
|
|
91254
|
-
|
|
91255
|
-
// If parsedDom is available, render it as children of the wrapper
|
|
91256
|
-
if (parsedDom && parsedDom.length > 0) {
|
|
91257
|
-
return [{
|
|
91258
|
-
childCount: parsedNodesChildNodeCount,
|
|
91259
|
-
className: 'Viewlet Preview',
|
|
91260
|
-
onClick: HandleClick,
|
|
91261
|
-
onInput: HandleInput,
|
|
91262
|
-
onKeyDown: HandleKeydown,
|
|
91263
|
-
onKeyUp: HandleKeyup,
|
|
91264
|
-
onMouseDown: HandleMousedown,
|
|
91265
|
-
onMouseMove: HandleMousemove,
|
|
91266
|
-
onMouseUp: HandleMouseup,
|
|
91267
|
-
tabIndex: 0,
|
|
91268
|
-
type: Div$1
|
|
91269
|
-
}, ...parsedDom];
|
|
91270
|
-
}
|
|
91271
|
-
return [{
|
|
91272
|
-
childCount: 1,
|
|
91273
|
-
className: 'Viewlet Preview',
|
|
91274
|
-
onClick: HandleClick,
|
|
91275
|
-
onInput: HandleInput,
|
|
91276
|
-
onKeyDown: HandleKeydown,
|
|
91277
|
-
onKeyUp: HandleKeyup,
|
|
91278
|
-
onMouseDown: HandleMousedown,
|
|
91279
|
-
onMouseMove: HandleMousemove,
|
|
91280
|
-
onMouseUp: HandleMouseup,
|
|
91281
|
-
tabIndex: 0,
|
|
91282
|
-
type: Div$1
|
|
91283
|
-
}, {
|
|
91284
|
-
childCount: 1,
|
|
91285
|
-
type: H1$1
|
|
91286
|
-
}, {
|
|
91287
|
-
text: 'Edit the file on the left to get started.',
|
|
91288
|
-
type: Text$2
|
|
91289
|
-
}];
|
|
91290
|
-
};
|
|
91291
|
-
|
|
91292
|
-
const renderItems = (oldState, newState) => {
|
|
91293
|
-
const {
|
|
91294
|
-
initial,
|
|
91295
|
-
uid
|
|
91296
|
-
} = newState;
|
|
91297
|
-
if (initial) {
|
|
91298
|
-
return [SetDom2, uid, []];
|
|
91299
|
-
}
|
|
91300
|
-
const dom = getPreviewDom(newState);
|
|
91301
|
-
return [SetDom2, uid, dom];
|
|
91302
|
-
};
|
|
91303
|
-
|
|
91304
|
-
const renderIncremental = (oldState, newState) => {
|
|
91305
|
-
const oldDom = renderItems(oldState, oldState)[2];
|
|
91306
|
-
const newDom = renderItems(newState, newState)[2];
|
|
91307
|
-
const patches = diffTree(oldDom, newDom);
|
|
91308
|
-
return [SetPatches, newState.uid, patches];
|
|
91309
|
-
};
|
|
91310
|
-
|
|
91311
|
-
const getRenderer = diffType => {
|
|
91312
|
-
switch (diffType) {
|
|
91313
|
-
case RenderCss:
|
|
91314
|
-
return renderCss;
|
|
91315
|
-
case RenderIncremental:
|
|
91316
|
-
return renderIncremental;
|
|
91317
|
-
case RenderItems:
|
|
91318
|
-
return renderItems;
|
|
91319
|
-
default:
|
|
91320
|
-
throw new Error('unknown renderer');
|
|
91321
|
-
}
|
|
91322
|
-
};
|
|
91323
|
-
|
|
91324
|
-
const applyRender = (oldState, newState, diffResult) => {
|
|
91325
|
-
const commands = [];
|
|
91326
|
-
for (const item of diffResult) {
|
|
91327
|
-
const fn = getRenderer(item);
|
|
91328
|
-
const result = fn(oldState, newState);
|
|
91329
|
-
if (result.length > 0) {
|
|
91330
|
-
commands.push(result);
|
|
91331
|
-
}
|
|
91332
|
-
}
|
|
91333
|
-
return commands;
|
|
91334
|
-
};
|
|
91335
|
-
|
|
91336
|
-
const render2 = (uid, diffResult) => {
|
|
91337
|
-
const {
|
|
91338
|
-
newState,
|
|
91339
|
-
oldState
|
|
91340
|
-
} = get$1(uid);
|
|
91341
|
-
set$2(uid, newState, newState);
|
|
91342
|
-
const commands = applyRender(oldState, newState, diffResult);
|
|
91343
|
-
return commands;
|
|
91344
|
-
};
|
|
91345
|
-
|
|
91346
|
-
const rerender = state => {
|
|
91347
|
-
// Create a new copy of parsedDom array to trigger diff
|
|
91348
|
-
const parsedDom = [...state.parsedDom];
|
|
91349
|
-
|
|
91350
|
-
// Return a new state object with the copied parsedDom
|
|
91351
|
-
// This will cause DiffItems.isEqual to return false since parsedDom reference changed
|
|
89747
|
+
errorMessage
|
|
89748
|
+
} = await updateContent(uid, width, height, content, scripts);
|
|
91352
89749
|
return {
|
|
91353
|
-
|
|
91354
|
-
parsedDom
|
|
89750
|
+
errorMessage
|
|
91355
89751
|
};
|
|
91356
89752
|
};
|
|
91357
89753
|
|
|
@@ -91363,36 +89759,26 @@ const resize = (state, dimensions) => {
|
|
|
91363
89759
|
};
|
|
91364
89760
|
|
|
91365
89761
|
const commandMap = {
|
|
91366
|
-
'
|
|
91367
|
-
'
|
|
91368
|
-
'
|
|
91369
|
-
'
|
|
91370
|
-
'
|
|
91371
|
-
'
|
|
91372
|
-
'
|
|
91373
|
-
'
|
|
91374
|
-
'
|
|
91375
|
-
'
|
|
91376
|
-
'
|
|
91377
|
-
'
|
|
91378
|
-
'
|
|
91379
|
-
'PreviewSandBox.render2': render2,
|
|
91380
|
-
'PreviewSandBox.rerender': wrapCommand(rerender),
|
|
91381
|
-
'PreviewSandBox.resize': wrapCommand(resize),
|
|
91382
|
-
'PreviewSandBox.terminate': terminate
|
|
89762
|
+
'SandBox.executeCallback': executeCallback,
|
|
89763
|
+
'SandBox.getSerializedDom': getSerializedDom,
|
|
89764
|
+
'SandBox.handleClick': handleClick,
|
|
89765
|
+
'SandBox.handleInput': handleInput,
|
|
89766
|
+
'SandBox.handleKeyDown': handleKeydown,
|
|
89767
|
+
'SandBox.handleKeyUp': handleKeyup,
|
|
89768
|
+
'SandBox.handleMessagePort': handleMessagePort,
|
|
89769
|
+
'SandBox.handleMousedown': handleMousedown,
|
|
89770
|
+
'SandBox.handleMousemove': handleMousemove,
|
|
89771
|
+
'SandBox.handleMouseup': handleMouseup,
|
|
89772
|
+
'SandBox.loadContent': loadContent,
|
|
89773
|
+
'SandBox.resize': resize,
|
|
89774
|
+
'SandBox.terminate': terminate
|
|
91383
89775
|
};
|
|
91384
89776
|
|
|
91385
89777
|
const listen = async () => {
|
|
91386
|
-
registerCommands(commandMap);
|
|
91387
89778
|
const rpc = await WebWorkerRpcClient.create({
|
|
91388
89779
|
commandMap: commandMap
|
|
91389
89780
|
});
|
|
91390
|
-
set$
|
|
91391
|
-
const editorRpc = await LazyTransferMessagePortRpcParent.create({
|
|
91392
|
-
commandMap: {},
|
|
91393
|
-
send: port => sendMessagePortToEditorWorker(port, 9112)
|
|
91394
|
-
});
|
|
91395
|
-
set$4(editorRpc);
|
|
89781
|
+
set$2(rpc);
|
|
91396
89782
|
};
|
|
91397
89783
|
|
|
91398
89784
|
const main = async () => {
|