@sveltejs/vite-plugin-svelte 2.1.1 → 2.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/vite-plugin-svelte",
3
- "version": "2.1.1",
3
+ "version": "2.2.0",
4
4
  "license": "MIT",
5
5
  "author": "dominikg",
6
6
  "files": [
@@ -50,11 +50,11 @@
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/debug": "^4.1.7",
53
- "esbuild": "^0.17.17",
54
- "rollup": "^2.79.1",
53
+ "esbuild": "^0.17.18",
54
+ "rollup": "^3.21.2",
55
55
  "svelte": "^3.58.0",
56
56
  "tsup": "^6.7.0",
57
- "vite": "^4.3.1"
57
+ "vite": "^4.3.3"
58
58
  },
59
59
  "scripts": {
60
60
  "dev": "pnpm build:ci --sourcemap --watch src",
package/src/index.ts CHANGED
@@ -273,10 +273,10 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin[] {
273
273
  );
274
274
  }
275
275
  }
276
- }
276
+ },
277
+ svelteInspector()
277
278
  ];
278
- plugins.push(svelteInspector());
279
- return plugins.filter(Boolean);
279
+ return plugins;
280
280
  }
281
281
 
282
282
  export { vitePreprocess } from './preprocess';
@@ -6,6 +6,7 @@
6
6
  const toggle_combo = options.toggleKeyCombo?.toLowerCase().split('-');
7
7
  const nav_keys = Object.values(options.navKeys).map((k) => k.toLowerCase());
8
8
  let enabled = false;
9
+ let hasOpened = false;
9
10
 
10
11
  const icon = `data:image/svg+xml;base64,${btoa(
11
12
  `
@@ -123,7 +124,8 @@
123
124
  function open_editor(event) {
124
125
  if (file_loc) {
125
126
  stop(event);
126
- fetch(`/__open-in-editor?file=${encodeURIComponent(file_loc)}`);
127
+ fetch(`${options.__internal.base}/__open-in-editor?file=${encodeURIComponent(file_loc)}`);
128
+ hasOpened = true;
127
129
  if (options.holdMode && is_holding()) {
128
130
  disable();
129
131
  }
@@ -247,6 +249,7 @@
247
249
 
248
250
  function disable() {
249
251
  enabled = false;
252
+ hasOpened = false;
250
253
  enabled_ts = null;
251
254
  const b = document.body;
252
255
  listeners(b, enabled);
@@ -257,6 +260,18 @@
257
260
  active_el = null;
258
261
  }
259
262
 
263
+ function visibilityChange() {
264
+ if (document.visibilityState === 'hidden') {
265
+ onLeave();
266
+ }
267
+ }
268
+
269
+ function onLeave() {
270
+ if (hasOpened) {
271
+ disable();
272
+ }
273
+ }
274
+
260
275
  onMount(() => {
261
276
  const s = document.createElement('style');
262
277
  s.setAttribute('type', 'text/css');
@@ -269,6 +284,8 @@
269
284
  document.body.addEventListener('keyup', keyup);
270
285
  }
271
286
  }
287
+ document.addEventListener('visibilitychange', visibilityChange);
288
+ document.documentElement.addEventListener('mouseleave', onLeave);
272
289
  return () => {
273
290
  // make sure we get rid of everything
274
291
  disable();
@@ -279,9 +296,11 @@
279
296
  if (toggle_combo) {
280
297
  document.body.removeEventListener('keydown', keydown);
281
298
  if (options.holdMode) {
282
- document.body.addEventListener('keyup', keyup);
299
+ document.body.removeEventListener('keyup', keyup);
283
300
  }
284
301
  }
302
+ document.removeEventListener('visibilitychange', visibilityChange);
303
+ document.documentElement.removeEventListener('mouseleave', onLeave);
285
304
  };
286
305
  });
287
306
  </script>
@@ -8,7 +8,7 @@ function create_inspector_host() {
8
8
  }
9
9
  const el = document.createElement('div');
10
10
  el.setAttribute('id', id);
11
- document.getElementsByTagName('body')[0].appendChild(el);
11
+ document.documentElement.appendChild(el);
12
12
  return el;
13
13
  }
14
14
 
@@ -0,0 +1,131 @@
1
+ import * as process from 'process';
2
+ import { log } from '../../utils/log';
3
+ import { loadEnv, ResolvedConfig } from 'vite';
4
+ export const defaultInspectorOptions: InspectorOptions = {
5
+ toggleKeyCombo: process.platform === 'darwin' ? 'meta-shift' : 'control-shift',
6
+ navKeys: { parent: 'ArrowUp', child: 'ArrowDown', next: 'ArrowRight', prev: 'ArrowLeft' },
7
+ openKey: 'Enter',
8
+ holdMode: true,
9
+ showToggleButton: 'active',
10
+ toggleButtonPos: 'top-right',
11
+ customStyles: true
12
+ };
13
+
14
+ export function parseEnvironmentOptions(
15
+ config: ResolvedConfig
16
+ ): Partial<InspectorOptions> | boolean | void {
17
+ const env = loadEnv(config.mode, config.envDir ?? process.cwd(), 'SVELTE_INSPECTOR');
18
+ const options = env?.SVELTE_INSPECTOR_OPTIONS;
19
+ const toggle = env?.SVELTE_INSPECTOR_TOGGLE;
20
+ if (options) {
21
+ try {
22
+ const parsed = JSON.parse(options);
23
+ const parsedType = typeof parsed;
24
+ if (parsedType === 'boolean') {
25
+ return parsed;
26
+ } else if (parsedType === 'object') {
27
+ if (Array.isArray(parsed)) {
28
+ throw new Error('invalid type, expected object map but got array');
29
+ }
30
+ const parsedKeys = Object.keys(parsed);
31
+ const defaultKeys = Object.keys(defaultInspectorOptions);
32
+ const unknownKeys = parsedKeys.filter((k) => !defaultKeys.includes(k));
33
+ if (unknownKeys.length) {
34
+ log.warn(
35
+ `ignoring unknown options in environment SVELTE_INSPECTOR_OPTIONS: ${unknownKeys.join(
36
+ ', '
37
+ )}.`,
38
+ undefined,
39
+ 'inspector'
40
+ );
41
+ for (const key of unknownKeys) {
42
+ delete parsed[key];
43
+ }
44
+ }
45
+ log.debug('loaded environment config', parsed, 'inspector');
46
+ return parsed;
47
+ }
48
+ } catch (e) {
49
+ log.error(
50
+ `failed to parse inspector options from environment SVELTE_INSPECTOR_OPTIONS="${options}"`,
51
+ e,
52
+ 'inspector'
53
+ );
54
+ }
55
+ } else if (toggle) {
56
+ const keyConfig = {
57
+ toggleKeyCombo: toggle
58
+ };
59
+ log.debug('loaded environment config', keyConfig, 'inspector');
60
+ return keyConfig;
61
+ }
62
+ }
63
+
64
+ export interface InspectorOptions {
65
+ /**
66
+ * define a key combo to toggle inspector,
67
+ * @default 'meta-shift' on mac, 'control-shift' on other os
68
+ *
69
+ * any number of modifiers `control` `shift` `alt` `meta` followed by zero or one regular key, separated by -
70
+ * examples: control-shift, control-o, control-alt-s meta-x control-meta
71
+ * Some keys have native behavior (e.g. alt-s opens history menu on firefox).
72
+ * To avoid conflicts or accidentally typing into inputs, modifier only combinations are recommended.
73
+ */
74
+ toggleKeyCombo?: string;
75
+
76
+ /**
77
+ * define keys to select elements with via keyboard
78
+ * @default {parent: 'ArrowUp', child: 'ArrowDown', next: 'ArrowRight', prev: 'ArrowLeft' }
79
+ *
80
+ * improves accessibility and also helps when you want to select elements that do not have a hoverable surface area
81
+ * due to tight wrapping
82
+ *
83
+ * A note for users of screen-readers:
84
+ * If you are using arrow keys to navigate the page itself, change the navKeys to avoid conflicts.
85
+ * e.g. navKeys: {parent: 'w', prev: 'a', child: 's', next: 'd'}
86
+ *
87
+ *
88
+ * parent: select closest parent
89
+ * child: select first child (or grandchild)
90
+ * next: next sibling (or parent if no next sibling exists)
91
+ * prev: previous sibling (or parent if no prev sibling exists)
92
+ */
93
+ navKeys?: { parent: string; child: string; next: string; prev: string };
94
+
95
+ /**
96
+ * define key to open the editor for the currently selected dom node
97
+ *
98
+ * @default 'Enter'
99
+ */
100
+ openKey?: string;
101
+
102
+ /**
103
+ * inspector is automatically disabled when releasing toggleKeyCombo after holding it for a longpress
104
+ * @default true
105
+ */
106
+ holdMode?: boolean;
107
+ /**
108
+ * when to show the toggle button
109
+ * @default 'active'
110
+ */
111
+ showToggleButton?: 'always' | 'active' | 'never';
112
+
113
+ /**
114
+ * where to display the toggle button
115
+ * @default top-right
116
+ */
117
+ toggleButtonPos?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
118
+
119
+ /**
120
+ * inject custom styles when inspector is active
121
+ */
122
+ customStyles?: boolean;
123
+
124
+ /**
125
+ * internal options that are automatically set, not to be set or used by users
126
+ */
127
+ __internal?: {
128
+ // vite base url
129
+ base: string;
130
+ };
131
+ }
@@ -1,20 +1,10 @@
1
1
  import { Plugin, normalizePath } from 'vite';
2
2
  import { log } from '../../utils/log';
3
- import { InspectorOptions } from '../../utils/options';
4
3
  import path from 'path';
5
4
  import { fileURLToPath } from 'url';
6
5
  import fs from 'fs';
7
6
  import { idToFile } from './utils';
8
-
9
- const defaultInspectorOptions: InspectorOptions = {
10
- toggleKeyCombo: process.platform === 'win32' ? 'control-shift' : 'meta-shift',
11
- navKeys: { parent: 'ArrowUp', child: 'ArrowDown', next: 'ArrowRight', prev: 'ArrowLeft' },
12
- openKey: 'Enter',
13
- holdMode: false,
14
- showToggleButton: 'active',
15
- toggleButtonPos: 'top-right',
16
- customStyles: true
17
- };
7
+ import { defaultInspectorOptions, type InspectorOptions, parseEnvironmentOptions } from './options';
18
8
 
19
9
  function getInspectorPath() {
20
10
  const pluginPath = normalizePath(path.dirname(fileURLToPath(import.meta.url)));
@@ -25,7 +15,6 @@ export function svelteInspector(): Plugin {
25
15
  const inspectorPath = getInspectorPath();
26
16
  log.debug.enabled && log.debug(`svelte inspector path: ${inspectorPath}`);
27
17
  let inspectorOptions: InspectorOptions;
28
- let appendTo: string | undefined;
29
18
  let disabled = false;
30
19
 
31
20
  return {
@@ -35,23 +24,30 @@ export function svelteInspector(): Plugin {
35
24
 
36
25
  configResolved(config) {
37
26
  const vps = config.plugins.find((p) => p.name === 'vite-plugin-svelte');
38
- const options = vps?.api?.options?.experimental?.inspector;
39
- if (!vps || !options) {
40
- log.debug('inspector disabled, could not find config');
27
+ if (!vps) {
28
+ log.warn('vite-plugin-svelte is missing, inspector disabled', undefined, 'inspector');
41
29
  disabled = true;
42
30
  return;
43
31
  }
44
- inspectorOptions = {
45
- ...defaultInspectorOptions,
46
- ...options
47
- };
48
- const isSvelteKit = config.plugins.some((p) => p.name.startsWith('vite-plugin-sveltekit'));
49
- if (isSvelteKit && !inspectorOptions.appendTo) {
50
- // this could append twice if a user had a file that ends with /generated/root.svelte
51
- // but that should be rare and inspector doesn't execute twice
52
- inspectorOptions.appendTo = `/generated/root.svelte`;
32
+ const configFileOptions = vps?.api?.options?.inspector;
33
+ const environmentOptions = parseEnvironmentOptions(config);
34
+ if (!configFileOptions && !environmentOptions) {
35
+ log.debug('no options found, inspector disabled', undefined, 'inspector');
36
+ disabled = true;
37
+ return;
38
+ }
39
+ if (environmentOptions === true) {
40
+ inspectorOptions = defaultInspectorOptions;
41
+ } else {
42
+ inspectorOptions = {
43
+ ...defaultInspectorOptions,
44
+ ...configFileOptions,
45
+ ...(environmentOptions || {})
46
+ };
53
47
  }
54
- appendTo = inspectorOptions.appendTo;
48
+ inspectorOptions.__internal = {
49
+ base: config.base?.replace(/\/$/, '') || ''
50
+ };
55
51
  },
56
52
 
57
53
  async resolveId(importee: string, importer, options) {
@@ -62,7 +58,8 @@ export function svelteInspector(): Plugin {
62
58
  return importee;
63
59
  } else if (importee.startsWith('virtual:svelte-inspector-path:')) {
64
60
  const resolved = importee.replace('virtual:svelte-inspector-path:', inspectorPath);
65
- log.debug.enabled && log.debug(`resolved ${importee} with ${resolved}`);
61
+ log.debug.enabled &&
62
+ log.debug(`resolved ${importee} with ${resolved}`, undefined, 'inspector');
66
63
  return resolved;
67
64
  }
68
65
  },
@@ -79,37 +76,22 @@ export function svelteInspector(): Plugin {
79
76
  if (fs.existsSync(file)) {
80
77
  return await fs.promises.readFile(file, 'utf-8');
81
78
  } else {
82
- log.error(`failed to find file for svelte-inspector: ${file}, referenced by id ${id}.`);
79
+ log.error(
80
+ `failed to find file for svelte-inspector: ${file}, referenced by id ${id}.`,
81
+ undefined,
82
+ 'inspector'
83
+ );
83
84
  }
84
85
  }
85
86
  },
86
87
 
87
- transform(code: string, id: string, options?: { ssr?: boolean }) {
88
- if (options?.ssr || disabled || !appendTo) {
88
+ transform(code, id, options) {
89
+ if (options?.ssr || disabled) {
89
90
  return;
90
91
  }
91
- if (id.endsWith(appendTo)) {
92
- return { code: `${code}\nimport 'virtual:svelte-inspector-path:load-inspector.js'` };
92
+ if (id.includes('vite/dist/client/client.mjs')) {
93
+ return { code: `${code}\nimport('virtual:svelte-inspector-path:load-inspector.js')` };
93
94
  }
94
- },
95
- transformIndexHtml(html) {
96
- if (disabled || appendTo) {
97
- return;
98
- }
99
- return {
100
- html,
101
- tags: [
102
- {
103
- tag: 'script',
104
- injectTo: 'body',
105
- attrs: {
106
- type: 'module',
107
- // /@id/ is needed, otherwise the virtual: is seen as protocol by browser and cors error happens
108
- src: '/@id/virtual:svelte-inspector-path:load-inspector.js'
109
- }
110
- }
111
- ]
112
- };
113
95
  }
114
96
  };
115
97
  }
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable no-unused-vars */
2
- import { ConfigEnv, ResolvedConfig, UserConfig, ViteDevServer, normalizePath } from 'vite';
2
+ import { ConfigEnv, normalizePath, ResolvedConfig, UserConfig, ViteDevServer } from 'vite';
3
3
  import { isDebugNamespaceEnabled, log } from './log';
4
4
  import { loadSvelteConfig } from './load-svelte-config';
5
5
  import {
@@ -35,6 +35,7 @@ import {
35
35
  import { isCommonDepWithoutSvelteField } from './dependencies';
36
36
  import { VitePluginSvelteStats } from './vite-plugin-svelte-stats';
37
37
  import { VitePluginSvelteCache } from './vite-plugin-svelte-cache';
38
+ import type { InspectorOptions } from '../ui/inspector/options';
38
39
 
39
40
  const allowedPluginOptions = new Set([
40
41
  'include',
@@ -44,17 +45,13 @@ const allowedPluginOptions = new Set([
44
45
  'ignorePluginPreprocessors',
45
46
  'disableDependencyReinclusion',
46
47
  'prebundleSvelteLibraries',
48
+ 'inspector',
47
49
  'experimental'
48
50
  ]);
49
51
 
50
52
  const knownRootOptions = new Set(['extensions', 'compilerOptions', 'preprocess', 'onwarn']);
51
53
 
52
- const allowedInlineOptions = new Set([
53
- 'configFile',
54
- 'kit', // only for internal use by sveltekit
55
- ...allowedPluginOptions,
56
- ...knownRootOptions
57
- ]);
54
+ const allowedInlineOptions = new Set(['configFile', ...allowedPluginOptions, ...knownRootOptions]);
58
55
 
59
56
  export function validateInlineOptions(inlineOptions?: Partial<Options>) {
60
57
  const invalidKeys = Object.keys(inlineOptions || {}).filter(
@@ -203,7 +200,6 @@ export function resolveOptions(
203
200
 
204
201
  removeIgnoredOptions(merged);
205
202
  handleDeprecatedOptions(merged);
206
- addSvelteKitOptions(merged);
207
203
  addExtraPreprocessors(merged, viteConfig);
208
204
  enforceOptionsForHmr(merged);
209
205
  enforceOptionsForProduction(merged);
@@ -291,24 +287,22 @@ function removeIgnoredOptions(options: ResolvedOptions) {
291
287
  }
292
288
  }
293
289
 
294
- // some SvelteKit options need compilerOptions to work, so set them here.
295
- function addSvelteKitOptions(options: ResolvedOptions) {
296
- // @ts-expect-error kit is not typed to avoid dependency on sveltekit
297
- if (options?.kit != null && options.compilerOptions.hydratable == null) {
298
- log.debug(`Setting compilerOptions.hydratable = true for SvelteKit`);
299
- options.compilerOptions.hydratable = true;
300
- }
301
- }
302
-
303
290
  function handleDeprecatedOptions(options: ResolvedOptions) {
304
- if ((options.experimental as any)?.prebundleSvelteLibraries) {
305
- options.prebundleSvelteLibraries = (options.experimental as any)?.prebundleSvelteLibraries;
306
- log.warn(
307
- 'experimental.prebundleSvelteLibraries is no longer experimental and has moved to prebundleSvelteLibraries'
308
- );
309
- }
310
- if ((options.experimental as any)?.generateMissingPreprocessorSourcemaps) {
311
- log.warn('experimental.generateMissingPreprocessorSourcemaps has been removed.');
291
+ const experimental = options.experimental as any;
292
+ if (experimental) {
293
+ for (const promoted of ['prebundleSvelteLibraries', 'inspector']) {
294
+ if (experimental[promoted]) {
295
+ //@ts-expect-error untyped assign
296
+ options[promoted] = experimental[promoted];
297
+ delete experimental[promoted];
298
+ log.warn(
299
+ `Option "vitePlugin.experimental.${promoted}" is no longer experimental and has moved to "vitePlugin.${promoted}". Please update your svelte config.`
300
+ );
301
+ }
302
+ }
303
+ if (experimental.generateMissingPreprocessorSourcemaps) {
304
+ log.warn('experimental.generateMissingPreprocessorSourcemaps has been removed.');
305
+ }
312
306
  }
313
307
  }
314
308
 
@@ -643,6 +637,13 @@ export interface PluginOptions {
643
637
  */
644
638
  prebundleSvelteLibraries?: boolean;
645
639
 
640
+ /**
641
+ * toggle/configure Svelte Inspector
642
+ *
643
+ * @default true
644
+ */
645
+ inspector?: InspectorOptions | boolean;
646
+
646
647
  /**
647
648
  * These options are considered experimental and breaking changes to them can occur in any release
648
649
  */
@@ -713,11 +714,6 @@ export interface ExperimentalOptions {
713
714
  compileOptions: Partial<CompileOptions>;
714
715
  }) => Promise<Partial<CompileOptions> | void> | Partial<CompileOptions> | void;
715
716
 
716
- /**
717
- * enable svelte inspector
718
- */
719
- inspector?: InspectorOptions | boolean;
720
-
721
717
  /**
722
718
  * send a websocket message with svelte compiler warnings during dev
723
719
  *
@@ -732,76 +728,6 @@ export interface ExperimentalOptions {
732
728
  disableSvelteResolveWarnings?: boolean;
733
729
  }
734
730
 
735
- export interface InspectorOptions {
736
- /**
737
- * define a key combo to toggle inspector,
738
- * @default 'control-shift' on windows, 'meta-shift' on other os
739
- *
740
- * any number of modifiers `control` `shift` `alt` `meta` followed by zero or one regular key, separated by -
741
- * examples: control-shift, control-o, control-alt-s meta-x control-meta
742
- * Some keys have native behavior (e.g. alt-s opens history menu on firefox).
743
- * To avoid conflicts or accidentally typing into inputs, modifier only combinations are recommended.
744
- */
745
- toggleKeyCombo?: string;
746
-
747
- /**
748
- * define keys to select elements with via keyboard
749
- * @default {parent: 'ArrowUp', child: 'ArrowDown', next: 'ArrowRight', prev: 'ArrowLeft' }
750
- *
751
- * improves accessibility and also helps when you want to select elements that do not have a hoverable surface area
752
- * due to tight wrapping
753
- *
754
- * A note for users of screen-readers:
755
- * If you are using arrow keys to navigate the page itself, change the navKeys to avoid conflicts.
756
- * e.g. navKeys: {parent: 'w', prev: 'a', child: 's', next: 'd'}
757
- *
758
- *
759
- * parent: select closest parent
760
- * child: select first child (or grandchild)
761
- * next: next sibling (or parent if no next sibling exists)
762
- * prev: previous sibling (or parent if no prev sibling exists)
763
- */
764
- navKeys?: { parent: string; child: string; next: string; prev: string };
765
-
766
- /**
767
- * define key to open the editor for the currently selected dom node
768
- *
769
- * @default 'Enter'
770
- */
771
- openKey?: string;
772
-
773
- /**
774
- * inspector is automatically disabled when releasing toggleKeyCombo after holding it for a longpress
775
- * @default false
776
- */
777
- holdMode?: boolean;
778
- /**
779
- * when to show the toggle button
780
- * @default 'active'
781
- */
782
- showToggleButton?: 'always' | 'active' | 'never';
783
-
784
- /**
785
- * where to display the toggle button
786
- * @default top-right
787
- */
788
- toggleButtonPos?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
789
-
790
- /**
791
- * inject custom styles when inspector is active
792
- */
793
- customStyles?: boolean;
794
-
795
- /**
796
- * append an import to the module id ending with `appendTo` instead of adding a script into body
797
- * useful for frameworks that do not support trannsformIndexHtml hook
798
- *
799
- * WARNING: only set this if you know exactly what it does.
800
- * Regular users of vite-plugin-svelte or SvelteKit do not need it
801
- */
802
- appendTo?: string;
803
- }
804
-
805
731
  export interface PreResolvedOptions extends Options {
806
732
  // these options are non-nullable after resolve
807
733
  compilerOptions: CompileOptions;