@lvce-editor/preview-worker 2.4.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/previewWorkerMain.js +141 -41
- package/package.json +2 -2
|
@@ -1411,6 +1411,9 @@ const dispatchEvent = (element, event) => {
|
|
|
1411
1411
|
if (typeof handler === 'function') {
|
|
1412
1412
|
handler.call(element, event);
|
|
1413
1413
|
} else if (handler === null || handler === undefined) {
|
|
1414
|
+
if (!element.getAttribute) {
|
|
1415
|
+
return;
|
|
1416
|
+
}
|
|
1414
1417
|
// Check if there's an inline HTML attribute that wasn't converted to a property
|
|
1415
1418
|
const attrValue = element.getAttribute(handlerName);
|
|
1416
1419
|
if (attrValue && typeof attrValue === 'string' && element.ownerDocument && element.ownerDocument.defaultView) {
|
|
@@ -90366,12 +90369,89 @@ const alert = message => {
|
|
|
90366
90369
|
void invoke('ConfirmPrompt.prompt', message);
|
|
90367
90370
|
};
|
|
90368
90371
|
|
|
90372
|
+
// const FUNCTION_REGEX = /(?:^|[\n;])\s*function\s+([a-zA-Z_$][\w$]*)/g
|
|
90373
|
+
|
|
90369
90374
|
const getTopLevelFunctionNames = script => {
|
|
90370
90375
|
const names = [];
|
|
90371
|
-
|
|
90372
|
-
let
|
|
90373
|
-
while (
|
|
90374
|
-
|
|
90376
|
+
let braceDepth = 0;
|
|
90377
|
+
let i = 0;
|
|
90378
|
+
while (i < script.length) {
|
|
90379
|
+
const char = script[i];
|
|
90380
|
+
|
|
90381
|
+
// Skip strings
|
|
90382
|
+
if (char === '"' || char === "'" || char === '`') {
|
|
90383
|
+
const quote = char;
|
|
90384
|
+
i++;
|
|
90385
|
+
while (i < script.length) {
|
|
90386
|
+
if (script[i] === '\\') {
|
|
90387
|
+
i += 2;
|
|
90388
|
+
continue;
|
|
90389
|
+
}
|
|
90390
|
+
if (script[i] === quote) {
|
|
90391
|
+
i++;
|
|
90392
|
+
break;
|
|
90393
|
+
}
|
|
90394
|
+
i++;
|
|
90395
|
+
}
|
|
90396
|
+
continue;
|
|
90397
|
+
}
|
|
90398
|
+
|
|
90399
|
+
// Skip comments
|
|
90400
|
+
if (char === '/' && script[i + 1] === '/') {
|
|
90401
|
+
// Line comment
|
|
90402
|
+
i += 2;
|
|
90403
|
+
while (i < script.length && script[i] !== '\n') {
|
|
90404
|
+
i++;
|
|
90405
|
+
}
|
|
90406
|
+
continue;
|
|
90407
|
+
}
|
|
90408
|
+
if (char === '/' && script[i + 1] === '*') {
|
|
90409
|
+
// Block comment
|
|
90410
|
+
i += 2;
|
|
90411
|
+
while (i < script.length - 1) {
|
|
90412
|
+
if (script[i] === '*' && script[i + 1] === '/') {
|
|
90413
|
+
i += 2;
|
|
90414
|
+
break;
|
|
90415
|
+
}
|
|
90416
|
+
i++;
|
|
90417
|
+
}
|
|
90418
|
+
continue;
|
|
90419
|
+
}
|
|
90420
|
+
|
|
90421
|
+
// Track braces
|
|
90422
|
+
if (char === '{') {
|
|
90423
|
+
braceDepth++;
|
|
90424
|
+
i++;
|
|
90425
|
+
continue;
|
|
90426
|
+
}
|
|
90427
|
+
if (char === '}') {
|
|
90428
|
+
braceDepth--;
|
|
90429
|
+
i++;
|
|
90430
|
+
continue;
|
|
90431
|
+
}
|
|
90432
|
+
|
|
90433
|
+
// Only look for functions at depth 0
|
|
90434
|
+
if (braceDepth === 0 && char === 'f' && script.slice(i, i + 8) === 'function') {
|
|
90435
|
+
// Check if 'function' is a complete word
|
|
90436
|
+
const charBefore = i > 0 ? script[i - 1] : ' ';
|
|
90437
|
+
const charAfter = script[i + 8] ?? ' ';
|
|
90438
|
+
const isValidBefore = /\s|^|;|{|}/.test(charBefore);
|
|
90439
|
+
const isValidAfter = /\s/.test(charAfter);
|
|
90440
|
+
if (isValidBefore && isValidAfter) {
|
|
90441
|
+
i += 8;
|
|
90442
|
+
// Skip whitespace
|
|
90443
|
+
while (i < script.length && /\s/.test(script[i])) {
|
|
90444
|
+
i++;
|
|
90445
|
+
}
|
|
90446
|
+
// Extract function name
|
|
90447
|
+
const nameMatch = script.slice(i).match(/^([a-zA-Z_$][\w$]*)/);
|
|
90448
|
+
if (nameMatch) {
|
|
90449
|
+
names.push(nameMatch[1]);
|
|
90450
|
+
}
|
|
90451
|
+
continue;
|
|
90452
|
+
}
|
|
90453
|
+
}
|
|
90454
|
+
i++;
|
|
90375
90455
|
}
|
|
90376
90456
|
return names;
|
|
90377
90457
|
};
|
|
@@ -90403,40 +90483,6 @@ const states = new Map();
|
|
|
90403
90483
|
const set = (uid, entry) => {
|
|
90404
90484
|
states.set(uid, entry);
|
|
90405
90485
|
};
|
|
90406
|
-
const addAnimationFrameHandle = (uid, handle) => {
|
|
90407
|
-
const entry = states.get(uid);
|
|
90408
|
-
if (entry) {
|
|
90409
|
-
entry.animationFrameHandles.push(handle);
|
|
90410
|
-
}
|
|
90411
|
-
};
|
|
90412
|
-
|
|
90413
|
-
const FRAME_INTERVAL = 16;
|
|
90414
|
-
const overrideRequestAnimationFrame = (window, uid) => {
|
|
90415
|
-
let nextId = 1;
|
|
90416
|
-
const callbacks = new Map();
|
|
90417
|
-
const tick = () => {
|
|
90418
|
-
const currentCallbacks = [...callbacks.entries()];
|
|
90419
|
-
callbacks.clear();
|
|
90420
|
-
const timestamp = performance.now();
|
|
90421
|
-
for (const [, callback] of currentCallbacks) {
|
|
90422
|
-
try {
|
|
90423
|
-
callback(timestamp);
|
|
90424
|
-
} catch (error) {
|
|
90425
|
-
console.warn('[preview-worker] requestAnimationFrame callback error:', error);
|
|
90426
|
-
}
|
|
90427
|
-
}
|
|
90428
|
-
};
|
|
90429
|
-
window.requestAnimationFrame = callback => {
|
|
90430
|
-
const id = nextId++;
|
|
90431
|
-
callbacks.set(id, callback);
|
|
90432
|
-
const handle = setTimeout(tick, FRAME_INTERVAL);
|
|
90433
|
-
addAnimationFrameHandle(uid, handle);
|
|
90434
|
-
return id;
|
|
90435
|
-
};
|
|
90436
|
-
window.cancelAnimationFrame = id => {
|
|
90437
|
-
callbacks.delete(id);
|
|
90438
|
-
};
|
|
90439
|
-
};
|
|
90440
90486
|
|
|
90441
90487
|
const patchCanvasElements = async (document, uid) => {
|
|
90442
90488
|
const canvasElements = document.querySelectorAll('canvas');
|
|
@@ -90480,7 +90526,6 @@ const patchCanvasElements = async (document, uid) => {
|
|
|
90480
90526
|
const updateContent = async (state, uri) => {
|
|
90481
90527
|
try {
|
|
90482
90528
|
// Read the file content using RendererWorker RPC
|
|
90483
|
-
// @ts-ignore
|
|
90484
90529
|
const content = await readFile(uri);
|
|
90485
90530
|
|
|
90486
90531
|
// Parse the content into virtual DOM and CSS
|
|
@@ -90501,7 +90546,6 @@ const updateContent = async (state, uri) => {
|
|
|
90501
90546
|
window: happyDomWindow
|
|
90502
90547
|
} = createWindow(content);
|
|
90503
90548
|
await patchCanvasElements(happyDomDocument, state.uid);
|
|
90504
|
-
overrideRequestAnimationFrame(happyDomWindow, state.uid);
|
|
90505
90549
|
executeScripts(happyDomWindow, happyDomDocument, scripts);
|
|
90506
90550
|
const elementMap = new Map();
|
|
90507
90551
|
const serialized = serialize(happyDomDocument, elementMap);
|
|
@@ -90512,7 +90556,8 @@ const updateContent = async (state, uri) => {
|
|
|
90512
90556
|
elementMap,
|
|
90513
90557
|
window: happyDomWindow
|
|
90514
90558
|
});
|
|
90515
|
-
} catch {
|
|
90559
|
+
} catch (error) {
|
|
90560
|
+
console.error(error);
|
|
90516
90561
|
// If script execution fails, fall back to static HTML parsing
|
|
90517
90562
|
}
|
|
90518
90563
|
}
|
|
@@ -90609,6 +90654,51 @@ const handleInput = (state, hdId, value) => {
|
|
|
90609
90654
|
};
|
|
90610
90655
|
};
|
|
90611
90656
|
|
|
90657
|
+
const dispatchKeydownEvent = (element, window, key, code) => {
|
|
90658
|
+
const keydownEvent = new window.KeyboardEvent('keydown', {
|
|
90659
|
+
bubbles: true,
|
|
90660
|
+
code,
|
|
90661
|
+
key
|
|
90662
|
+
});
|
|
90663
|
+
dispatchEvent(element, keydownEvent);
|
|
90664
|
+
};
|
|
90665
|
+
|
|
90666
|
+
const handleKeydown = (state, hdId, key, code) => {
|
|
90667
|
+
const happyDomInstance = get(state.uid);
|
|
90668
|
+
if (!happyDomInstance) {
|
|
90669
|
+
return state;
|
|
90670
|
+
}
|
|
90671
|
+
const element = hdId ? happyDomInstance.elementMap.get(hdId) : happyDomInstance.document;
|
|
90672
|
+
if (!element) {
|
|
90673
|
+
return state;
|
|
90674
|
+
}
|
|
90675
|
+
|
|
90676
|
+
// Dispatch keydown event in happy-dom so event listeners fire
|
|
90677
|
+
dispatchKeydownEvent(element, happyDomInstance.window, key, code);
|
|
90678
|
+
|
|
90679
|
+
// Re-serialize the (potentially mutated) DOM
|
|
90680
|
+
const elementMap = new Map();
|
|
90681
|
+
const serialized = serialize(happyDomInstance.document, elementMap);
|
|
90682
|
+
|
|
90683
|
+
// Update happy-dom state with new element map
|
|
90684
|
+
set$1(state.uid, {
|
|
90685
|
+
document: happyDomInstance.document,
|
|
90686
|
+
elementMap,
|
|
90687
|
+
window: happyDomInstance.window
|
|
90688
|
+
});
|
|
90689
|
+
const parsedDom = serialized.dom;
|
|
90690
|
+
const {
|
|
90691
|
+
css
|
|
90692
|
+
} = serialized;
|
|
90693
|
+
const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
|
|
90694
|
+
return {
|
|
90695
|
+
...state,
|
|
90696
|
+
css,
|
|
90697
|
+
parsedDom,
|
|
90698
|
+
parsedNodesChildNodeCount
|
|
90699
|
+
};
|
|
90700
|
+
};
|
|
90701
|
+
|
|
90612
90702
|
const loadContent = async state => {
|
|
90613
90703
|
// Try to register to receive editor change notifications from the editor worker.
|
|
90614
90704
|
// Use dynamic access and ignore errors so this is safe in environments where
|
|
@@ -90698,6 +90788,7 @@ const renderCss = (oldState, newState) => {
|
|
|
90698
90788
|
|
|
90699
90789
|
const HandleInput = 4;
|
|
90700
90790
|
const HandleClick = 11;
|
|
90791
|
+
const HandleKeydown = 12;
|
|
90701
90792
|
|
|
90702
90793
|
const getEmptyPreviewDom = () => {
|
|
90703
90794
|
return [{
|
|
@@ -90730,6 +90821,8 @@ const getPreviewDom = state => {
|
|
|
90730
90821
|
className: 'Viewlet Preview',
|
|
90731
90822
|
onClick: HandleClick,
|
|
90732
90823
|
onInput: HandleInput,
|
|
90824
|
+
onKeyDown: HandleKeydown,
|
|
90825
|
+
tabIndex: 0,
|
|
90733
90826
|
type: Div$1
|
|
90734
90827
|
}, ...parsedDom];
|
|
90735
90828
|
}
|
|
@@ -90738,6 +90831,8 @@ const getPreviewDom = state => {
|
|
|
90738
90831
|
className: 'Viewlet Preview',
|
|
90739
90832
|
onClick: HandleClick,
|
|
90740
90833
|
onInput: HandleInput,
|
|
90834
|
+
onKeyDown: HandleKeydown,
|
|
90835
|
+
tabIndex: 0,
|
|
90741
90836
|
type: Div$1
|
|
90742
90837
|
}, {
|
|
90743
90838
|
childCount: 1,
|
|
@@ -90811,6 +90906,10 @@ const renderEventListeners = () => {
|
|
|
90811
90906
|
capture: true,
|
|
90812
90907
|
name: HandleInput,
|
|
90813
90908
|
params: ['handleInput', 'event.target.dataset.id', 'event.target.value']
|
|
90909
|
+
}, {
|
|
90910
|
+
capture: true,
|
|
90911
|
+
name: HandleKeydown,
|
|
90912
|
+
params: ['handleKeyDown', 'event.target.dataset.id', 'event.key', 'event.code']
|
|
90814
90913
|
}];
|
|
90815
90914
|
};
|
|
90816
90915
|
|
|
@@ -90869,6 +90968,7 @@ const commandMap = {
|
|
|
90869
90968
|
'Preview.handleClick': wrapCommand(handleClick),
|
|
90870
90969
|
'Preview.handleFileEdited': wrapCommand(handleFileEdited),
|
|
90871
90970
|
'Preview.handleInput': wrapCommand(handleInput),
|
|
90971
|
+
'Preview.handleKeyDown': wrapCommand(handleKeydown),
|
|
90872
90972
|
'Preview.loadContent': wrapCommand(loadContent),
|
|
90873
90973
|
'Preview.render2': render2,
|
|
90874
90974
|
'Preview.renderEventListeners': renderEventListeners,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/preview-worker",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "Preview Worker",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"type": "module",
|
|
12
12
|
"main": "dist/previewWorkerMain.js",
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@lvce-editor/virtual-dom-worker": "^
|
|
14
|
+
"@lvce-editor/virtual-dom-worker": "^8.0.0",
|
|
15
15
|
"happy-dom-without-node": "^14.12.3"
|
|
16
16
|
}
|
|
17
17
|
}
|