Socket
Socket
Sign inDemoInstall

@sveltejs/vite-plugin-svelte

Package Overview
Dependencies
7
Maintainers
4
Versions
102
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.5.3 to 3.0.1

src/public.d.ts

40

package.json
{
"name": "@sveltejs/vite-plugin-svelte",
"version": "2.5.3",
"version": "3.0.1",
"license": "MIT",
"author": "dominikg",
"files": [
"src"
"src",
"types"
],
"type": "module",
"types": "src/index.d.ts",
"types": "types/index.d.ts",
"exports": {
".": {
"types": "./src/index.d.ts",
"import": "./src/index.js"
},
"./package.json": "./package.json"
"import": {
"types": "./types/index.d.ts",
"default": "./src/index.js"
}
}
},
"engines": {
"node": "^14.18.0 || >= 16"
"node": "^18.0.0 || >=20"
},

@@ -37,24 +39,26 @@ "repository": {

"dependencies": {
"@sveltejs/vite-plugin-svelte-inspector": "^1.0.4",
"@sveltejs/vite-plugin-svelte-inspector": "^2.0.0-next.0 || ^2.0.0",
"debug": "^4.3.4",
"deepmerge": "^4.3.1",
"kleur": "^4.1.5",
"magic-string": "^0.30.3",
"magic-string": "^0.30.5",
"svelte-hmr": "^0.15.3",
"vitefu": "^0.2.4"
"vitefu": "^0.2.5"
},
"peerDependencies": {
"svelte": "^3.54.0 || ^4.0.0 || ^5.0.0-next.0",
"vite": "^4.0.0"
"svelte": "^4.0.0 || ^5.0.0-next.0",
"vite": "^5.0.0"
},
"devDependencies": {
"@types/debug": "^4.1.8",
"esbuild": "^0.19.3",
"svelte": "^4.2.0",
"vite": "^4.4.9"
"@types/debug": "^4.1.12",
"esbuild": "^0.19.7",
"sass": "^1.69.5",
"svelte": "^4.2.7",
"vite": "^5.0.2"
},
"scripts": {
"check:publint": "publint --strict",
"check:types": "tsc --noEmit"
"check:types": "tsc --noEmit",
"generate:types": "dts-buddy -m \"@sveltejs/vite-plugin-svelte:src/public.d.ts\""
}
}

@@ -10,3 +10,3 @@ import { log, logCompilerWarnings } from './utils/log.js';

* @param {import('./types/id.d.ts').SvelteRequest} svelteRequest
* @param {import('./utils/vite-plugin-svelte-cache').VitePluginSvelteCache} cache
* @param {import('./utils/vite-plugin-svelte-cache.js').VitePluginSvelteCache} cache
* @param {import('./types/options.d.ts').ResolvedOptions} options

@@ -18,3 +18,7 @@ * @returns {Promise<import('vite').ModuleNode[] | void>}

// file hasn't been requested yet (e.g. async component)
log.debug(`handleHotUpdate called before initial transform for ${svelteRequest.id}`);
log.debug(
`handleHotUpdate called before initial transform for ${svelteRequest.id}`,
undefined,
'hmr'
);
return;

@@ -44,3 +48,3 @@ }

if (!cssUpdated) {
log.debug(`skipping unchanged css for ${svelteRequest.cssId}`);
log.debug(`skipping unchanged css for ${svelteRequest.cssId}`, undefined, 'hmr');
affectedModules.splice(cssIdx, 1);

@@ -53,3 +57,3 @@ }

if (!jsUpdated) {
log.debug(`skipping unchanged js for ${svelteRequest.id}`);
log.debug(`skipping unchanged js for ${svelteRequest.id}`, undefined, 'hmr');
affectedModules.splice(jsIdx, 1);

@@ -64,3 +68,7 @@ // transform won't be called, log warnings here

if (ssrModulesToInvalidate.length > 0) {
log.debug(`invalidating modules ${ssrModulesToInvalidate.map((m) => m.id).join(', ')}`);
log.debug(
`invalidating modules ${ssrModulesToInvalidate.map((m) => m.id).join(', ')}`,
undefined,
'hmr'
);
ssrModulesToInvalidate.forEach((moduleNode) => server.moduleGraph.invalidateModule(moduleNode));

@@ -72,3 +80,5 @@ }

.map((m) => m.id)
.join(', ')}`
.join(', ')}`,
undefined,
'hmr'
);

@@ -103,4 +113,6 @@ }

if (!isStrictEqual && isLooseEqual) {
log.warn(
`ignoring compiler output js change for ${filename} as it is equal to previous output after normalization`
log.debug(
`ignoring compiler output js change for ${filename} as it is equal to previous output after normalization`,
undefined,
'hmr'
);

@@ -107,0 +119,0 @@ }

import fs from 'node:fs';
import { version as viteVersion } from 'vite';
import * as svelteCompiler from 'svelte/compiler';
import { svelteInspector } from '@sveltejs/vite-plugin-svelte-inspector';
import { isDepExcluded } from 'vitefu';
import { handleHotUpdate } from './handle-hot-update.js';
import { log, logCompilerWarnings } from './utils/log.js';
import { log, logCompilerWarnings, logSvelte5Warning } from './utils/log.js';
import { createCompileSvelte } from './utils/compile.js';

@@ -21,4 +18,2 @@ import { buildIdParser, buildModuleIdParser } from './utils/id.js';

import { ensureWatchedFile, setupWatchers } from './utils/watch.js';
import { resolveViaPackageJsonSvelte } from './utils/resolve.js';
import { toRollupError } from './utils/error.js';

@@ -28,8 +23,9 @@ import { saveSvelteMetadata } from './utils/optimizer.js';

import { loadRaw } from './utils/load-raw.js';
import { FAQ_LINK_CONFLICTS_IN_SVELTE_RESOLVE } from './utils/constants.js';
import { isSvelte3, isSvelte5 } from './utils/svelte-version.js';
import { isSvelte5 } from './utils/svelte-version.js';
import * as svelteCompiler from 'svelte/compiler';
const isVite4_0 = viteVersion.startsWith('4.0');
/** @type {import('./index.d.ts').svelte} */
/**
* @param {Partial<import('./public.d.ts').Options>} [inlineOptions]
* @returns {import('vite').Plugin[]}
*/
export function svelte(inlineOptions) {

@@ -50,11 +46,5 @@ if (process.env.DEBUG != null) {

let viteConfig;
/** @type {import('./types/compile.d.ts').CompileSvelte} */
let compileSvelte;
/* eslint-enable no-unused-vars */
/** @type {Promise<import('vite').Rollup.PartialResolvedId | null>} */
let resolvedSvelteSSR;
/** @type {Set<string>} */
let packagesWithResolveWarnings;
/** @type {import('./types/plugin-api.d.ts').PluginAPI} */

@@ -80,3 +70,3 @@ const api = {};

const extraViteConfig = await buildExtraViteConfig(options, config);
log.debug('additional vite config', extraViteConfig);
log.debug('additional vite config', extraViteConfig, 'config');
return extraViteConfig;

@@ -93,7 +83,6 @@ },

api.options = options;
log.debug('resolved options', options);
log.debug('resolved options', options, 'config');
},
async buildStart() {
packagesWithResolveWarnings = new Set();
if (!options.prebundleSvelteLibraries) return;

@@ -119,3 +108,10 @@ const isSvelteMetadataChanged = await saveSvelteMetadata(viteConfig.cacheDir, options);

if (raw) {
return loadRaw(svelteRequest, compileSvelte, options);
const code = await loadRaw(svelteRequest, compileSvelte, options);
// prevent vite from injecting sourcemaps in the results.
return {
code,
map: {
mappings: ''
}
};
} else {

@@ -125,3 +121,2 @@ if (query.svelte && query.type === 'style') {

if (css) {
log.debug(`load returns css for ${filename}`);
return css;

@@ -132,3 +127,3 @@ }

if (viteConfig.assetsInclude(filename)) {
log.debug(`load returns raw content for ${filename}`);
log.debug(`load returns raw content for ${filename}`, undefined, 'load');
return fs.readFileSync(filename, 'utf-8');

@@ -147,76 +142,10 @@ }

// see https://github.com/sveltejs/vite-plugin-svelte/issues/14
log.debug(`resolveId resolved virtual css module ${svelteRequest.cssId}`);
log.debug(
`resolveId resolved virtual css module ${svelteRequest.cssId}`,
undefined,
'resolve'
);
return svelteRequest.cssId;
}
}
// TODO: remove this after bumping peerDep on Vite to 4.1+ or Svelte to 4.0+
if (isVite4_0 && isSvelte3 && ssr && importee === 'svelte') {
if (!resolvedSvelteSSR) {
resolvedSvelteSSR = this.resolve('svelte/ssr', undefined, { skipSelf: true }).then(
(svelteSSR) => {
log.debug('resolved svelte to svelte/ssr');
return svelteSSR;
},
(err) => {
log.debug(
'failed to resolve svelte to svelte/ssr. Update svelte to a version that exports it',
err
);
return null; // returning null here leads to svelte getting resolved regularly
}
);
}
return resolvedSvelteSSR;
}
//@ts-expect-error scan
const scan = !!opts?.scan; // scanner phase of optimizeDeps
const isPrebundled =
options.prebundleSvelteLibraries &&
viteConfig.optimizeDeps?.disabled !== true &&
viteConfig.optimizeDeps?.disabled !== (options.isBuild ? 'build' : 'dev') &&
!isDepExcluded(importee, viteConfig.optimizeDeps?.exclude ?? []);
// for prebundled libraries we let vite resolve the prebundling result
// for ssr, during scanning and non-prebundled, we do it
if (ssr || scan || !isPrebundled) {
try {
const isFirstResolve = !cache.hasResolvedSvelteField(importee, importer);
const resolved = await resolveViaPackageJsonSvelte(importee, importer, cache);
if (isFirstResolve && resolved) {
const packageInfo = await cache.getPackageInfo(resolved);
const packageVersion = `${packageInfo.name}@${packageInfo.version}`;
log.debug.once(
`resolveId resolved ${importee} to ${resolved} via package.json svelte field of ${packageVersion}`
);
try {
const viteResolved = (
await this.resolve(importee, importer, { ...opts, skipSelf: true })
)?.id;
if (resolved !== viteResolved) {
packagesWithResolveWarnings.add(packageVersion);
log.debug.enabled &&
log.debug.once(
`resolve difference for ${packageVersion} ${importee} - svelte: "${resolved}", vite: "${viteResolved}"`
);
}
} catch (e) {
packagesWithResolveWarnings.add(packageVersion);
log.debug.enabled &&
log.debug.once(
`resolve error for ${packageVersion} ${importee} - svelte: "${resolved}", vite: ERROR`,
e
);
}
}
return resolved;
} catch (e) {
log.debug.once(
`error trying to resolve ${importee} from ${importer} via package.json svelte field `,
e
);
// this error most likely happens due to non-svelte related importee/importers so swallow it here
// in case it really way a svelte library, users will notice anyway. (lib not working due to failed resolve)
}
}
},

@@ -250,3 +179,2 @@

}
log.debug(`transform returns compiled js for ${svelteRequest.filename}`);
return {

@@ -273,24 +201,7 @@ ...compileData.compiled.js,

await options.stats?.finishAll();
if (
!options.experimental?.disableSvelteResolveWarnings &&
packagesWithResolveWarnings?.size > 0
) {
log.warn(
`WARNING: The following packages use a svelte resolve configuration in package.json that has conflicting results and is going to cause problems future.\n\n${[
...packagesWithResolveWarnings
].join('\n')}\n\nPlease see ${FAQ_LINK_CONFLICTS_IN_SVELTE_RESOLVE} for details.`
);
}
}
}
];
if (!isSvelte5) {
plugins.push(svelteInspector()); // TODO reenable once svelte5 has support
}
if (isSvelte5) {
log.warn(
'svelte 5 support in v-p-s is experimental, breaking changes can occur in any release until this notice is removed'
);
log.warn('svelte 5 does not support svelte-inspector yet, disabling it');
logSvelte5Warning();
// TODO move to separate file

@@ -310,3 +221,3 @@ plugins.push({

try {
// @ts-ignore doesn't exist in Svelte 4
// @ts-expect-error compileModule does not exist in svelte4
const compileResult = await svelteCompiler.compileModule(code, {

@@ -324,3 +235,6 @@ generate: ssr ? 'server' : 'client',

}
if (!isSvelte5) {
// TODO reenable once svelte5 has support and update utils/log.js#logSvelte5Warning
plugins.push(svelteInspector());
}
return plugins;

@@ -327,0 +241,0 @@ }

@@ -1,2 +0,2 @@

import { preprocessCSS, resolveConfig, transformWithEsbuild } from 'vite';
import { isCSSRequest, preprocessCSS, resolveConfig, transformWithEsbuild } from 'vite';
import { mapToRelative, removeLangSuffix } from './utils/sourcemaps.js';

@@ -8,11 +8,13 @@

const supportedStyleLangs = ['css', 'less', 'sass', 'scss', 'styl', 'stylus', 'postcss', 'sss'];
const supportedScriptLangs = ['ts'];
export const lang_sep = '.vite-preprocess.';
export const lang_sep = '.vite-preprocess';
/** @type {import('./index.d.ts').vitePreprocess} */
/**
* @param {import('./public.d.ts').VitePreprocessOptions} [opts]
* @returns {import('svelte/compiler').PreprocessorGroup}
*/
export function vitePreprocess(opts) {
/** @type {import('svelte/types/compiler/preprocess').PreprocessorGroup} */
const preprocessor = {};
/** @type {import('svelte/compiler').PreprocessorGroup} */
const preprocessor = { name: 'vite-preprocess' };
if (opts?.script !== false) {

@@ -29,3 +31,3 @@ preprocessor.script = viteScript().script;

/**
* @returns {{ script: import('svelte/types/compiler/preprocess').Preprocessor }}
* @returns {{ script: import('svelte/compiler').Preprocessor }}
*/

@@ -61,3 +63,3 @@ function viteScript() {

* @param {import('vite').ResolvedConfig | import('vite').InlineConfig} config
* @returns {{ style: import('svelte/types/compiler/preprocess').Preprocessor }}
* @returns {{ style: import('svelte/compiler').Preprocessor }}
*/

@@ -67,6 +69,6 @@ function viteStyle(config = {}) {

let transform;
/** @type {import('svelte/types/compiler/preprocess').Preprocessor} */
/** @type {import('svelte/compiler').Preprocessor} */
const style = async ({ attributes, content, filename = '' }) => {
const lang = /** @type {string} */ (attributes.lang);
if (!supportedStyleLangs.includes(lang)) return;
const ext = attributes.lang ? `.${attributes.lang}` : '.css';
if (attributes.lang && !isCSSRequest(ext)) return;
if (!transform) {

@@ -89,3 +91,3 @@ /** @type {import('vite').ResolvedConfig} */

}
const suffix = `${lang_sep}${lang}`;
const suffix = `${lang_sep}${ext}`;
const moduleId = `${filename}${suffix}`;

@@ -92,0 +94,0 @@ const { code, map, deps } = await transform(content, moduleId);

@@ -1,2 +0,2 @@

import type { Processed } from 'svelte/types/compiler/preprocess';
import type { Processed, CompileResult } from 'svelte/compiler';
import type { SvelteRequest } from './id.d.ts';

@@ -17,25 +17,2 @@ import type { ResolvedOptions } from './options.d.ts';

export interface Compiled {
js: Code;
css: Code;
ast: any; // TODO type
warnings: any[]; // TODO type
vars: Array<{
name: string;
export_name: string;
injected: boolean;
module: boolean;
mutated: boolean;
reassigned: boolean;
referenced: boolean;
writable: boolean;
referenced_from_script: boolean;
}>;
stats: {
timings: {
total: number;
};
};
}
export interface CompileData {

@@ -45,3 +22,3 @@ filename: string;

lang: string;
compiled: Compiled;
compiled: CompileResult;
ssr: boolean | undefined;

@@ -48,0 +25,0 @@ dependencies: string[];

@@ -41,3 +41,2 @@ import type { CompileOptions } from 'svelte/types/compiler/interfaces';

export type IdParser = (id: string, ssr: boolean, timestamp?: number) => SvelteRequest | undefined;
export type ModuleIdParser = (

@@ -44,0 +43,0 @@ id: string,

@@ -1,2 +0,2 @@

import type { Warning } from '../index.d.ts';
import type { Warning } from 'svelte/types/compiler/interfaces';

@@ -3,0 +3,0 @@ export interface LogFn extends SimpleLogFn {

import type { CompileOptions } from 'svelte/types/compiler/interfaces';
import type { ViteDevServer } from 'vite';
import { VitePluginSvelteStats } from '../utils/vite-plugin-svelte-stats.js';
import type { Options } from '../index.d.ts';
import type { Options } from '../public.d.ts';

@@ -6,0 +6,0 @@ export interface PreResolvedOptions extends Options {

@@ -7,10 +7,16 @@ import * as svelte from 'svelte/compiler';

import { createInjectScopeEverythingRulePreprocessorGroup } from './preprocess.js';
import {
checkPreprocessDependencies,
createInjectScopeEverythingRulePreprocessorGroup
} from './preprocess.js';
import { mapToRelative } from './sourcemaps.js';
import { enhanceCompileError } from './error.js';
import { isSvelte5 } from './svelte-version.js';
// TODO this is a patched version of https://github.com/sveltejs/vite-plugin-svelte/pull/796/files#diff-3bce0b33034aad4b35ca094893671f7e7ddf4d27254ae7b9b0f912027a001b15R10
// which is closer to the other regexes in at least not falling into commented script
// but ideally would be shared exactly with svelte and other tools that use it
const scriptLangRE =
/<script (?:[^>]*|(?:[^=>'"/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)\s+)*)lang=["']?([^"' >]+)["']?[^>]*>/;
/<!--[^]*?-->|<script (?:[^>]*|(?:[^=>'"/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)\s+)*)lang=["']?([^"' >]+)["']?[^>]*>/;
import { isSvelte3, isSvelte5 } from './svelte-version.js';
/**

@@ -28,3 +34,6 @@ * @param {Function} [makeHot]

const { emitCss = true } = options;
/** @type {string[]} */
const dependencies = [];
/** @type {import('svelte/types/compiler/interfaces').Warning[]} */
const warnings = [];

@@ -55,16 +64,12 @@ if (options.stats) {

}
/** @type {import('../index.d.ts').CompileOptions} */
/** @type {import('svelte/compiler').CompileOptions} */
const compileOptions = {
...options.compilerOptions,
filename,
// @ts-expect-error generate type is different for svelte5
// @ts-expect-error svelte5 uses server/client, svelte4 uses ssr/dom
generate: isSvelte5 ? (ssr ? 'server' : 'client') : ssr ? 'ssr' : 'dom'
};
if (isSvelte3) {
// @ts-ignore
compileOptions.format = 'esm';
}
if (options.hot && options.emitCss) {
const hash = `s-${safeBase64Hash(normalizedFilename)}`;
log.debug(`setting cssHash ${hash} for ${normalizedFilename}`);
compileOptions.cssHash = () => hash;

@@ -100,3 +105,12 @@ }

if (preprocessed.dependencies) dependencies.push(...preprocessed.dependencies);
if (preprocessed.dependencies?.length) {
const checked = checkPreprocessDependencies(filename, preprocessed.dependencies);
if (checked.warnings.length) {
warnings.push(...checked.warnings);
}
if (checked.dependencies.length) {
dependencies.push(...checked.dependencies);
}
}
if (preprocessed.map) compileOptions.sourcemap = preprocessed.map;

@@ -114,3 +128,3 @@ }

const finalCode = preprocessed ? preprocessed.code : code;
const dynamicCompileOptions = await options.experimental?.dynamicCompileOptions?.({
const dynamicCompileOptions = await options?.dynamicCompileOptions?.({
filename,

@@ -122,3 +136,5 @@ code: finalCode,

log.debug(
`dynamic compile options for ${filename}: ${JSON.stringify(dynamicCompileOptions)}`
`dynamic compile options for ${filename}: ${JSON.stringify(dynamicCompileOptions)}`,
undefined,
'compile'
);

@@ -134,13 +150,11 @@ }

const endStat = stats?.start(filename);
const compiled = svelte.compile(finalCode, finalCompileOptions);
/** @type {import('svelte/types/compiler/interfaces').CompileResult} */
let compiled;
try {
compiled = svelte.compile(finalCode, finalCompileOptions);
} catch (e) {
enhanceCompileError(e, code, preprocessors);
throw e;
}
if (isSvelte3) {
// prevent dangling pure comments
// see https://github.com/sveltejs/kit/issues/9492#issuecomment-1487704985
// uses regex replace with whitespace to keep sourcemap/character count unmodified
compiled.js.code = compiled.js.code.replace(
/\/\* [@#]__PURE__ \*\/(\s*)$/gm,
' $1'
);
}
if (endStat) {

@@ -151,2 +165,8 @@ endStat();

mapToRelative(compiled.css?.map, filename);
if (warnings.length) {
if (!compiled.warnings) {
compiled.warnings = [];
}
compiled.warnings.push(...warnings);
}
if (!raw) {

@@ -200,3 +220,2 @@ // wire css import and code for hmr

return createMakeHot({
// TODO Svelte 5 doesn't expose walk anymore. If we decide to make v-p-s 2 work with Svelte 5 HMR, we need to import walk from estree-walker
walk: svelte.walk,

@@ -203,0 +222,0 @@ hotApi,

@@ -1,4 +0,4 @@

import { isSvelte3 } from './svelte-version.js';
import { isSvelte5 } from './svelte-version.js';
export const VITE_RESOLVE_MAIN_FIELDS = ['module', 'jsnext:main', 'jsnext'];
export const VITE_RESOLVE_MAIN_FIELDS = ['browser', 'module', 'jsnext:main', 'jsnext'];

@@ -11,2 +11,3 @@ export const SVELTE_RESOLVE_MAIN_FIELDS = ['svelte'];

'svelte/internal',
'svelte/internal/disclose-version',
'svelte/motion',

@@ -18,6 +19,2 @@ 'svelte/ssr',

];
// TODO add to global list after dropping svelte 3
if (!isSvelte3) {
SVELTE_IMPORTS.push('svelte/internal/disclose-version');
}

@@ -30,5 +27,10 @@ export const SVELTE_HMR_IMPORTS = [

if (isSvelte5) {
SVELTE_IMPORTS.push('svelte/server', 'svelte/internal/server', 'svelte/legacy');
SVELTE_HMR_IMPORTS.length = 0; // truncate, svelte-hmr isn't used with svelte5
}
export const SVELTE_EXPORT_CONDITIONS = ['svelte'];
export const FAQ_LINK_CONFLICTS_IN_SVELTE_RESOLVE =
'https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#conflicts-in-svelte-resolve';
export const FAQ_LINK_MISSING_EXPORTS_CONDITION =
'https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#missing-exports-condition';

@@ -103,1 +103,80 @@ import { buildExtendedLogMessage } from './log.js';

}
/**
* @param {import('svelte/types/compiler/interfaces').Warning & Error} err a svelte compiler error, which is a mix of Warning and an error
* @param {string} originalCode
* @param {import('../public.d.ts').Options['preprocess']} [preprocessors]
*/
export function enhanceCompileError(err, originalCode, preprocessors) {
preprocessors = arraify(preprocessors ?? []);
/** @type {string[]} */
const additionalMessages = [];
// Handle incorrect TypeScript usage
if (err.code === 'parse-error') {
// Reference from Svelte: https://github.com/sveltejs/svelte/blob/9926347ad9dbdd0f3324d5538e25dcb7f5e442f8/packages/svelte/src/compiler/preprocess/index.js#L259
const scriptRe =
/<!--[^]*?-->|<script((?:\s+[^=>'"/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"/]+)*\s*)(?:\/>|>([\S\s]*?)<\/script>)/g;
const errIndex = err.pos ?? -1;
let m;
while ((m = scriptRe.exec(originalCode))) {
const matchStart = m.index;
const matchEnd = matchStart + m[0].length;
const isErrorInScript = matchStart <= errIndex && errIndex <= matchEnd;
if (isErrorInScript) {
// Warn missing lang="ts"
const hasLangTs = m[1]?.includes('lang="ts"');
if (!hasLangTs) {
additionalMessages.push('Did you forget to add lang="ts" to your script tag?');
}
// Warn missing script preprocessor
if (preprocessors.every((p) => p.script == null)) {
const preprocessorType = hasLangTs ? 'TypeScript' : 'script';
additionalMessages.push(
`Did you forget to add a ${preprocessorType} preprocessor? See https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/preprocess.md for more information.`
);
}
}
}
}
// Handle incorrect CSS preprocessor usage
if (err.code === 'css-syntax-error') {
// Reference from Svelte: https://github.com/sveltejs/svelte/blob/9926347ad9dbdd0f3324d5538e25dcb7f5e442f8/packages/svelte/src/compiler/preprocess/index.js#L257
const styleRe =
/<!--[^]*?-->|<style((?:\s+[^=>'"/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"/]+)*\s*)(?:\/>|>([\S\s]*?)<\/style>)/g;
let m;
while ((m = styleRe.exec(originalCode))) {
// Warn missing lang attribute
if (!m[1]?.includes('lang=')) {
additionalMessages.push('Did you forget to add a lang attribute to your style tag?');
}
// Warn missing style preprocessor
if (
preprocessors.every((p) => p.style == null || p.name === 'inject-scope-everything-rule')
) {
const preprocessorType = m[1]?.match(/lang="(.+?)"/)?.[1] ?? 'style';
additionalMessages.push(
`Did you forget to add a ${preprocessorType} preprocessor? See https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/preprocess.md for more information.`
);
}
}
}
if (additionalMessages.length) {
err.message += '\n\n- ' + additionalMessages.join('\n- ');
}
return err;
}
/**
* @param {T | T[]} value
* @template T
*/
function arraify(value) {
return Array.isArray(value) ? value : [value];
}

@@ -5,3 +5,3 @@ import { readFileSync } from 'node:fs';

import { toESBuildError } from './error.js';
import { isSvelte3, isSvelte5 } from './svelte-version.js';
import { isSvelte5 } from './svelte-version.js';

@@ -66,3 +66,3 @@ /**

const endStat = statsCollection?.start(filename);
// @ts-ignore doesn't exist in Svelte 4
// @ts-expect-error compileModule does not exist in svelte4
const compiled = svelte.compileModule(code, {

@@ -79,3 +79,2 @@ filename,

}
let css = options.compilerOptions.css;

@@ -86,3 +85,3 @@ if (css !== 'none') {

}
/** @type {import('../index.d.ts').CompileOptions} */
/** @type {import('svelte/compiler').CompileOptions} */
const compileOptions = {

@@ -92,9 +91,6 @@ ...options.compilerOptions,

filename,
// @ts-expect-error generate type is different for svelte5
// @ts-expect-error svelte4 uses 'dom', svelte5 uses 'client'
generate: isSvelte5 ? 'client' : 'dom'
};
if (isSvelte3) {
// @ts-ignore
compileOptions.format = 'esm';
}
let preprocessed;

@@ -114,3 +110,3 @@

const dynamicCompileOptions = await options.experimental?.dynamicCompileOptions?.({
const dynamicCompileOptions = await options?.dynamicCompileOptions?.({
filename,

@@ -122,3 +118,7 @@ code: finalCode,

if (dynamicCompileOptions && log.debug.enabled) {
log.debug(`dynamic compile options for ${filename}: ${JSON.stringify(dynamicCompileOptions)}`);
log.debug(
`dynamic compile options for ${filename}: ${JSON.stringify(dynamicCompileOptions)}`,
undefined,
'compile'
);
}

@@ -125,0 +125,0 @@

@@ -162,4 +162,4 @@ import { createFilter, normalizePath } from 'vite';

/**
* @param {import('../index.d.ts').Arrayable<string> | undefined} include
* @param {import('../index.d.ts').Arrayable<string> | undefined} exclude
* @param {import('../public.d.ts').Options['include'] | undefined} include
* @param {import('../public.d.ts').Options['exclude'] | undefined} exclude
* @param {string[]} extensions

@@ -188,2 +188,3 @@ * @returns {(filename: string) => boolean}

}
/**

@@ -190,0 +191,0 @@ * @param {import('../types/options.d.ts').ResolvedOptions} options

import fs from 'node:fs';
import { toRollupError } from './error.js';
import { log } from './log.js';
import { isSvelte4 } from './svelte-version.js';
/**

@@ -21,3 +21,4 @@ * utility function to compile ?raw and ?direct requests in load hook

//avoid compileSvelte doing extra ssr stuff unless requested
svelteRequest.ssr = query.compilerOptions?.generate === 'ssr';
//@ts-ignore //@ts-expect-error generate value differs between svelte4 and 5
svelteRequest.ssr = query.compilerOptions?.generate === (isSvelte4 ? 'ssr' : 'server');
const type = query.type;

@@ -29,4 +30,3 @@ compileData = await compileSvelte(svelteRequest, source, {

dev: false,
css: false,
hydratable: false,
css: 'external',
enableSourcemap: query.sourcemap

@@ -69,3 +69,3 @@ ? {

}
log.debug(`load returns direct result for ${id}`);
log.debug(`load returns direct result for ${id}`, undefined, 'load');
let directOutput = result.code;

@@ -82,3 +82,3 @@ if (query.sourcemap && result.map?.toUrl) {

} else if (query.raw) {
log.debug(`load returns raw result for ${id}`);
log.debug(`load returns raw result for ${id}`, undefined, 'load');
return toRawExports(result);

@@ -85,0 +85,0 @@ } else {

@@ -19,12 +19,15 @@ import { createRequire } from 'node:module';

// hide dynamic import from ts transform to prevent it turning into a require
// see https://github.com/microsoft/TypeScript/issues/43329#issuecomment-811606238
// also use timestamp query to avoid caching on reload
const dynamicImportDefault = new Function(
'path',
'timestamp',
'return import(path + "?t=" + timestamp).then(m => m.default)'
);
/**
* @param {string} filePath
* @param {number} timestamp
*/
async function dynamicImportDefault(filePath, timestamp) {
return await import(filePath + '?t=' + timestamp).then((m) => m.default);
}
/** @type {import('../index.d.ts').loadSvelteConfig} */
/**
* @param {import('vite').UserConfig} [viteConfig]
* @param {Partial<import('../public.d.ts').Options>} [inlineOptions]
* @returns {Promise<Partial<import('../public.d.ts').SvelteConfig> | undefined>}
*/
export async function loadSvelteConfig(viteConfig, inlineOptions) {

@@ -63,3 +66,4 @@ if (inlineOptions?.configFile === false) {

? esmRequire ?? (esmRequire = createRequire(import.meta.url))
: require;
: // eslint-disable-next-line no-undef
require;

@@ -91,3 +95,3 @@ // avoid loading cached version on reload

* @param {import('vite').UserConfig | undefined} viteConfig
* @param {Partial<import('../index.d.ts').Options> | undefined} inlineOptions
* @param {Partial<import('../public.d.ts').Options> | undefined} inlineOptions
* @returns {string | undefined}

@@ -110,3 +114,3 @@ */

if (existingKnownConfigFiles.length === 0) {
log.debug(`no svelte config found at ${root}`);
log.debug(`no svelte config found at ${root}`, undefined, 'config');
return;

@@ -113,0 +117,0 @@ } else if (existingKnownConfigFiles.length > 1) {

/* eslint-disable no-console */
import { cyan, red, yellow } from 'kleur/colors';
import debug from 'debug';
import { VERSION } from 'svelte/compiler';

@@ -11,3 +12,3 @@ /** @type {import('../types/log.d.ts').LogLevel[]} */

debug: {
log: debug(`vite:${prefix}`),
log: debug(`${prefix}`),
enabled: false,

@@ -69,3 +70,9 @@ isDebug: true

if (logger.isDebug) {
const log = namespace ? logger.log.extend(namespace) : logger.log;
let log = logger.log;
if (namespace) {
if (!isDebugNamespaceEnabled(namespace)) {
return;
}
log = logger.log.extend(namespace);
}
payload !== undefined ? log(message, payload) : log(message);

@@ -256,3 +263,12 @@ } else {

export function isDebugNamespaceEnabled(namespace) {
return debug.enabled(`vite:${prefix}:${namespace}`);
return debug.enabled(`${prefix}:${namespace}`);
}
export function logSvelte5Warning() {
const notice = `Your are using Svelte ${VERSION}. Svelte 5 support is experimental, breaking changes can occur in any release until this notice is removed.`;
const wip = [
'svelte-inspector is disabled until dev mode implements node to code mapping',
'hmr for .svelte files is disabled until hmr api is implemented'
];
log.warn(`${notice}\nwork in progress:\n - ${wip.join('\n - ')}\n`);
}

@@ -6,2 +6,3 @@ /* eslint-disable no-unused-vars */

import {
FAQ_LINK_MISSING_EXPORTS_CONDITION,
SVELTE_EXPORT_CONDITIONS,

@@ -40,2 +41,3 @@ SVELTE_HMR_IMPORTS,

'inspector',
'dynamicCompileOptions',
'experimental'

@@ -49,3 +51,3 @@ ]);

/**
* @param {Partial<import('../index.d.ts').Options>} [inlineOptions]
* @param {Partial<import('../public.d.ts').Options>} [inlineOptions]
*/

@@ -62,4 +64,4 @@ export function validateInlineOptions(inlineOptions) {

/**
* @param {Partial<import('../index.d.ts').SvelteOptions>} [config]
* @returns {Partial<import('../index.d.ts').Options> | undefined}
* @param {Partial<import('../public.d.ts').SvelteConfig>} [config]
* @returns {Partial<import('../public.d.ts').Options> | undefined}
*/

@@ -114,3 +116,3 @@ function convertPluginOptions(config) {

}
/** @type {import('../index.d.ts').Options} */
/** @type {import('../public.d.ts').Options} */
const result = {

@@ -128,3 +130,3 @@ ...config,

* used in config phase, merges the default options, svelte config, and inline options
* @param {Partial<import('../index.d.ts').Options> | undefined} inlineOptions
* @param {Partial<import('../public.d.ts').Options> | undefined} inlineOptions
* @param {import('vite').UserConfig} viteUserConfig

@@ -199,3 +201,3 @@ * @param {import('vite').ConfigEnv} viteEnv

const css = preResolveOptions.emitCss ? 'external' : 'injected';
/** @type {Partial<import('../index.d.ts').Options>} */
/** @type {Partial<import('../public.d.ts').Options>} */
const defaultOptions = {

@@ -239,3 +241,3 @@ hot: viteConfig.isProduction

if (isSvelte5) {
log.warn('svelte 5 does not support hmr api yet, disabling it for now');
// TODO add hmr options for svelte5 once it is supported and update utils/log.js#logSvelte5Warning
options.hot = false;

@@ -331,3 +333,3 @@ }

if (experimental) {
for (const promoted of ['prebundleSvelteLibraries', 'inspector']) {
for (const promoted of ['prebundleSvelteLibraries', 'inspector', 'dynamicCompileOptions']) {
if (experimental[promoted]) {

@@ -338,3 +340,3 @@ //@ts-expect-error untyped assign

log.warn(
`Option "vitePlugin.experimental.${promoted}" is no longer experimental and has moved to "vitePlugin.${promoted}". Please update your svelte config.`
`Option "experimental.${promoted}" is no longer experimental and has moved to "${promoted}". Please update your Svelte or Vite config.`
);

@@ -446,3 +448,3 @@ }

) {
log.debug('enabling "experimental.hmrPartialAccept" in vite config');
log.debug('enabling "experimental.hmrPartialAccept" in vite config', undefined, 'config');
extraViteConfig.experimental = { hmrPartialAccept: true };

@@ -500,2 +502,3 @@ }

// extra handling for svelte dependencies in the project
const packagesWithoutSvelteExportsCondition = new Set();
const depsConfig = await crawlFrameworkPkgs({

@@ -516,3 +519,7 @@ root: options.root,

}
return hasSvelteCondition || !!pkgJson.svelte;
const hasSvelteField = !!pkgJson.svelte;
if (hasSvelteField && !hasSvelteCondition) {
packagesWithoutSvelteExportsCondition.add(`${pkgJson.name}@${pkgJson.version}`);
}
return hasSvelteCondition || hasSvelteField;
},

@@ -531,5 +538,14 @@ isSemiFrameworkPkgByJson(pkgJson) {

});
if (
!options.experimental?.disableSvelteResolveWarnings &&
packagesWithoutSvelteExportsCondition?.size > 0
) {
log.warn(
`WARNING: The following packages have a svelte field in their package.json but no exports condition for svelte.\n\n${[
...packagesWithoutSvelteExportsCondition
].join('\n')}\n\nPlease see ${FAQ_LINK_MISSING_EXPORTS_CONDITION} for details.`
);
}
log.debug('extra config for dependencies generated by vitefu', depsConfig, 'config');
log.debug('extra config for dependencies generated by vitefu', depsConfig);
if (options.prebundleSvelteLibraries) {

@@ -567,3 +583,3 @@ // prebundling enabled, so we don't need extra dependency excludes

log.debug('post-processed extra config for dependencies', depsConfig);
log.debug('post-processed extra config for dependencies', depsConfig, 'config');

@@ -585,7 +601,13 @@ return depsConfig;

log.debug(
`adding bare svelte packages to optimizeDeps.include: ${svelteImportsToInclude.join(', ')} `
`adding bare svelte packages to optimizeDeps.include: ${svelteImportsToInclude.join(', ')} `,
undefined,
'config'
);
include.push(...svelteImportsToInclude);
} else {
log.debug('"svelte" is excluded in optimizeDeps.exclude, skipped adding it to include.');
log.debug(
'"svelte" is excluded in optimizeDeps.exclude, skipped adding it to include.',
undefined,
'config'
);
}

@@ -592,0 +614,0 @@ /** @type {(string | RegExp)[]} */

import MagicString from 'magic-string';
import { log } from './log.js';
import path from 'node:path';
import { normalizePath } from 'vite';

@@ -11,6 +12,7 @@ /**

*
* @returns {import('svelte/types/compiler/preprocess').PreprocessorGroup}
* @returns {import('svelte/compiler').PreprocessorGroup}
*/
export function createInjectScopeEverythingRulePreprocessorGroup() {
return {
name: 'inject-scope-everything-rule',
style({ content, filename }) {

@@ -34,10 +36,10 @@ const s = new MagicString(content);

* @returns {{
* prependPreprocessors: import('svelte/types/compiler/preprocess').PreprocessorGroup[],
* appendPreprocessors: import('svelte/types/compiler/preprocess').PreprocessorGroup[]
* prependPreprocessors: import('svelte/compiler').PreprocessorGroup[],
* appendPreprocessors: import('svelte/compiler').PreprocessorGroup[]
* }}
*/
function buildExtraPreprocessors(options, config) {
/** @type {import('svelte/types/compiler/preprocess').PreprocessorGroup[]} */
/** @type {import('svelte/compiler').PreprocessorGroup[]} */
const prependPreprocessors = [];
/** @type {import('svelte/types/compiler/preprocess').PreprocessorGroup[]} */
/** @type {import('svelte/compiler').PreprocessorGroup[]} */
const appendPreprocessors = [];

@@ -89,3 +91,5 @@

.map((p) => p.name)
.join(', ')}`
.join(', ')}`,
undefined,
'preprocess'
);

@@ -97,3 +101,5 @@ }

.map((p) => p.name)
.join(', ')}`
.join(', ')}`,
undefined,
'preprocess'
);

@@ -123,1 +129,50 @@ appendPreprocessors.push(...pluginsWithPreprocessors.map((p) => p.api.sveltePreprocess));

}
/**
*
* @param filename {string}
* @param dependencies {string[]}
* @returns {({dependencies: string[], warnings:import('svelte/types/compiler/interfaces').Warning[] })}
*/
export function checkPreprocessDependencies(filename, dependencies) {
/** @type {import('svelte/types/compiler/interfaces').Warning[]} */
const warnings = [];
// to find self, we have to compare normalized filenames, but must keep the original values in `dependencies`
// because otherwise file watching on windows doesn't work
// so we track idx and filter by that in the end
/** @type {number[]} */
const selfIdx = [];
const normalizedFullFilename = normalizePath(filename);
const normalizedDeps = dependencies.map(normalizePath);
for (let i = 0; i < normalizedDeps.length; i++) {
if (normalizedDeps[i] === normalizedFullFilename) {
selfIdx.push(i);
}
}
const hasSelfDependency = selfIdx.length > 0;
if (hasSelfDependency) {
warnings.push({
code: 'vite-plugin-svelte-preprocess-depends-on-self',
message:
'svelte.preprocess returned this file as a dependency of itself. This can be caused by an invalid configuration or importing generated code that depends on .svelte files (eg. tailwind base css)',
filename
});
}
if (dependencies.length > 10) {
warnings.push({
code: 'vite-plugin-svelte-preprocess-many-dependencies',
message: `svelte.preprocess depends on more than 10 external files which can cause slow builds and poor DX, try to reduce them. Found: ${dependencies.join(
', '
)}`,
filename
});
}
return {
dependencies: hasSelfDependency
? dependencies.filter((_, i) => !selfIdx.includes(i)) // remove self dependency
: dependencies,
warnings
};
}

@@ -6,3 +6,3 @@ import { VERSION } from 'svelte/compiler';

*/
export const isSvelte3 = VERSION.startsWith('3.');
export const isSvelte4 = VERSION.startsWith('4.');

@@ -9,0 +9,0 @@ /**

@@ -27,4 +27,2 @@ import { readFileSync } from 'node:fs';

#dependants = new Map();
/** @type {Map<string, string>} */
#resolvedSvelteFields = new Map();
/** @type {Map<string, any>} */

@@ -173,41 +171,2 @@ #errors = new Map();

/**
* @param {string} name
* @param {string} [importer]
* @returns {string|void}
*/
getResolvedSvelteField(name, importer) {
return this.#resolvedSvelteFields.get(this.#getResolvedSvelteFieldKey(name, importer));
}
/**
* @param {string} name
* @param {string} [importer]
* @returns {boolean}
*/
hasResolvedSvelteField(name, importer) {
return this.#resolvedSvelteFields.has(this.#getResolvedSvelteFieldKey(name, importer));
}
/**
*
* @param {string} importee
* @param {string | undefined} importer
* @param {string} resolvedSvelte
*/
setResolvedSvelteField(importee, importer, resolvedSvelte) {
this.#resolvedSvelteFields.set(
this.#getResolvedSvelteFieldKey(importee, importer),
resolvedSvelte
);
}
/**
* @param {string} importee
* @param {string | undefined} importer
* @returns {string}
*/
#getResolvedSvelteFieldKey(importee, importer) {
return importer ? `${importer} > ${importee}` : importee;
}
/**
* @param {string} file

@@ -214,0 +173,0 @@ * @returns {Promise<PackageInfo>}

@@ -8,3 +8,3 @@ import fs from 'node:fs';

* @param {import('../types/options.d.ts').ResolvedOptions} options
* @param {import('./vite-plugin-svelte-cache').VitePluginSvelteCache} cache
* @param {import('./vite-plugin-svelte-cache.js').VitePluginSvelteCache} cache
* @param {import('../types/id.d.ts').IdParser} requestParser

@@ -26,3 +26,5 @@ * @returns {void}

log.debug(
`emitting virtual change event for "${dependant}" because depdendency "${filename}" changed`
`emitting virtual change event for "${dependant}" because depdendency "${filename}" changed`,
undefined,
'hmr'
);

@@ -39,3 +41,3 @@ watcher.emit('change', dependant);

if (removedFromCache) {
log.debug(`cleared VitePluginSvelteCache for deleted file ${filename}`);
log.debug(`cleared VitePluginSvelteCache for deleted file ${filename}`, undefined, 'hmr');
}

@@ -42,0 +44,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc