@lvce-editor/preview-worker 2.5.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.
@@ -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
- const regex = /(?:^|[\n;])\s*function\s+([a-zA-Z_$][\w$]*)/g;
90372
- let match;
90373
- while ((match = regex.exec(script)) !== null) {
90374
- names.push(match[1]);
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
  };
@@ -90574,6 +90654,51 @@ const handleInput = (state, hdId, value) => {
90574
90654
  };
90575
90655
  };
90576
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
+
90577
90702
  const loadContent = async state => {
90578
90703
  // Try to register to receive editor change notifications from the editor worker.
90579
90704
  // Use dynamic access and ignore errors so this is safe in environments where
@@ -90663,6 +90788,7 @@ const renderCss = (oldState, newState) => {
90663
90788
 
90664
90789
  const HandleInput = 4;
90665
90790
  const HandleClick = 11;
90791
+ const HandleKeydown = 12;
90666
90792
 
90667
90793
  const getEmptyPreviewDom = () => {
90668
90794
  return [{
@@ -90695,6 +90821,8 @@ const getPreviewDom = state => {
90695
90821
  className: 'Viewlet Preview',
90696
90822
  onClick: HandleClick,
90697
90823
  onInput: HandleInput,
90824
+ onKeyDown: HandleKeydown,
90825
+ tabIndex: 0,
90698
90826
  type: Div$1
90699
90827
  }, ...parsedDom];
90700
90828
  }
@@ -90703,6 +90831,8 @@ const getPreviewDom = state => {
90703
90831
  className: 'Viewlet Preview',
90704
90832
  onClick: HandleClick,
90705
90833
  onInput: HandleInput,
90834
+ onKeyDown: HandleKeydown,
90835
+ tabIndex: 0,
90706
90836
  type: Div$1
90707
90837
  }, {
90708
90838
  childCount: 1,
@@ -90776,6 +90906,10 @@ const renderEventListeners = () => {
90776
90906
  capture: true,
90777
90907
  name: HandleInput,
90778
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']
90779
90913
  }];
90780
90914
  };
90781
90915
 
@@ -90834,6 +90968,7 @@ const commandMap = {
90834
90968
  'Preview.handleClick': wrapCommand(handleClick),
90835
90969
  'Preview.handleFileEdited': wrapCommand(handleFileEdited),
90836
90970
  'Preview.handleInput': wrapCommand(handleInput),
90971
+ 'Preview.handleKeyDown': wrapCommand(handleKeydown),
90837
90972
  'Preview.loadContent': wrapCommand(loadContent),
90838
90973
  'Preview.render2': render2,
90839
90974
  'Preview.renderEventListeners': renderEventListeners,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/preview-worker",
3
- "version": "2.5.0",
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": "^7.3.0",
14
+ "@lvce-editor/virtual-dom-worker": "^8.0.0",
15
15
  "happy-dom-without-node": "^14.12.3"
16
16
  }
17
17
  }