Socket
Socket
Sign inDemoInstall

@sveltejs/vite-plugin-svelte

Package Overview
Dependencies
Maintainers
4
Versions
107
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sveltejs/vite-plugin-svelte - npm Package Compare versions

Comparing version 1.3.1 to 1.4.0

dist/preprocess.cjs

19

dist/index.d.ts

@@ -6,4 +6,5 @@ import { UserConfig, Plugin } from 'vite';

export { MarkupPreprocessor, Preprocessor, PreprocessorGroup, Processed } from 'svelte/types/compiler/preprocess';
export { vitePreprocess } from './preprocess.js';
declare type Options = Omit<SvelteOptions, 'vitePlugin'> & PluginOptionsInline;
type Options = Omit<SvelteOptions, 'vitePlugin'> & PluginOptionsInline;
interface PluginOptionsInline extends PluginOptions {

@@ -137,10 +138,2 @@ /**

/**
* If a preprocessor does not provide a sourcemap, a best-effort fallback sourcemap will be provided.
* This option requires `diff-match-patch` to be installed as a peer dependency.
*
* @see https://github.com/google/diff-match-patch
* @default false
*/
generateMissingPreprocessorSourcemaps?: boolean;
/**
* A function to update `compilerOptions` before compilation

@@ -253,9 +246,9 @@ *

}
declare type ModuleFormat = NonNullable<CompileOptions['format']>;
declare type CssHashGetter = NonNullable<CompileOptions['cssHash']>;
declare type Arrayable<T> = T | T[];
type ModuleFormat = NonNullable<CompileOptions['format']>;
type CssHashGetter = NonNullable<CompileOptions['cssHash']>;
type Arrayable<T> = T | T[];
declare function loadSvelteConfig(viteConfig?: UserConfig, inlineOptions?: Partial<Options>): Promise<Partial<SvelteOptions> | undefined>;
declare type SvelteWarningsMessage = {
type SvelteWarningsMessage = {
id: string;

@@ -262,0 +255,0 @@ filename: string;

{
"name": "@sveltejs/vite-plugin-svelte",
"version": "1.3.1",
"version": "1.4.0",
"license": "MIT",

@@ -9,5 +9,3 @@ "author": "dominikg",

"src",
"README.md",
"LICENSE",
"package.json"
"*.d.ts"
],

@@ -54,26 +52,18 @@ "type": "module",

"peerDependencies": {
"diff-match-patch": "^1.0.5",
"svelte": "^3.44.0",
"vite": "^3.0.0"
},
"peerDependenciesMeta": {
"diff-match-patch": {
"optional": true
}
},
"devDependencies": {
"@types/debug": "^4.1.7",
"@types/diff-match-patch": "^1.0.32",
"diff-match-patch": "^1.0.5",
"esbuild": "^0.15.14",
"esbuild": "^0.15.16",
"rollup": "^2.79.1",
"svelte": "^3.53.1",
"tsup": "^6.5.0",
"vite": "^3.2.3"
"vite": "^3.2.4"
},
"scripts": {
"dev": "pnpm build:ci --sourcemap --watch src",
"build:ci": "rimraf dist && tsup-node src/index.ts --format esm,cjs --no-splitting --shims",
"build:ci": "rimraf dist && tsup-node src/index.ts src/preprocess.ts --format esm,cjs --no-splitting --shims",
"build": "pnpm build:ci --dts --sourcemap"
}
}

@@ -23,3 +23,3 @@ import { ModuleNode, HmrContext } from 'vite';

}
const { read, server } = ctx;
const { read, server, modules } = ctx;

@@ -39,27 +39,25 @@ const cachedJS = cache.getJS(svelteRequest);

const affectedModules = new Set<ModuleNode | undefined>();
const affectedModules = [...modules];
const cssModule = server.moduleGraph.getModuleById(svelteRequest.cssId);
const mainModule = server.moduleGraph.getModuleById(svelteRequest.id);
const cssUpdated = cssModule && cssChanged(cachedCss, compileData.compiled.css);
if (cssUpdated) {
log.debug(`handleHotUpdate css changed for ${svelteRequest.cssId}`);
affectedModules.add(cssModule);
const cssIdx = modules.findIndex((m) => m.id === svelteRequest.cssId);
if (cssIdx > -1) {
const cssUpdated = cssChanged(cachedCss, compileData.compiled.css);
if (!cssUpdated) {
log.debug(`skipping unchanged css for ${svelteRequest.cssId}`);
affectedModules.splice(cssIdx, 1);
}
}
const jsUpdated =
mainModule && jsChanged(cachedJS, compileData.compiled.js, svelteRequest.filename);
if (jsUpdated) {
log.debug(`handleHotUpdate js changed for ${svelteRequest.id}`);
affectedModules.add(mainModule);
const jsIdx = modules.findIndex((m) => m.id === svelteRequest.id);
if (jsIdx > -1) {
const jsUpdated = jsChanged(cachedJS, compileData.compiled.js, svelteRequest.filename);
if (!jsUpdated) {
log.debug(`skipping unchanged js for ${svelteRequest.id}`);
affectedModules.splice(jsIdx, 1);
// transform won't be called, log warnings here
logCompilerWarnings(svelteRequest, compileData.compiled.warnings, options);
}
}
if (!jsUpdated) {
// transform won't be called, log warnings here
logCompilerWarnings(svelteRequest, compileData.compiled.warnings, options);
}
const result = [...affectedModules].filter(Boolean) as ModuleNode[];
// TODO is this enough? see also: https://github.com/vitejs/vite/issues/2274
const ssrModulesToInvalidate = result.filter((m) => !!m.ssrTransformResult);
const ssrModulesToInvalidate = affectedModules.filter((m) => !!m.ssrTransformResult);
if (ssrModulesToInvalidate.length > 0) {

@@ -69,8 +67,10 @@ log.debug(`invalidating modules ${ssrModulesToInvalidate.map((m) => m.id).join(', ')}`);

}
if (result.length > 0) {
if (affectedModules.length > 0) {
log.debug(
`handleHotUpdate for ${svelteRequest.id} result: ${result.map((m) => m.id).join(', ')}`
`handleHotUpdate for ${svelteRequest.id} result: ${affectedModules
.map((m) => m.id)
.join(', ')}`
);
}
return result;
return affectedModules;
}

@@ -77,0 +77,0 @@

@@ -7,4 +7,4 @@ import fs from 'fs';

import { log, logCompilerWarnings } from './utils/log';
import { CompileData, createCompileSvelte } from './utils/compile';
import { buildIdParser, IdParser, SvelteRequest } from './utils/id';
import { type CompileSvelte, createCompileSvelte } from './utils/compile';
import { buildIdParser, IdParser } from './utils/id';
import {

@@ -27,2 +27,3 @@ buildExtraViteConfig,

import { VitePluginSvelteCache } from './utils/vite-plugin-svelte-cache';
import { loadRaw } from './utils/load-raw';

@@ -50,7 +51,3 @@ interface PluginAPI {

/* eslint-disable no-unused-vars */
let compileSvelte: (
svelteRequest: SvelteRequest,
code: string,
options: Partial<ResolvedOptions>
) => Promise<CompileData>;
let compileSvelte: CompileSvelte;
/* eslint-enable no-unused-vars */

@@ -109,20 +106,23 @@

load(id, opts) {
async load(id, opts) {
const ssr = !!opts?.ssr;
const svelteRequest = requestParser(id, !!ssr);
if (svelteRequest) {
const { filename, query } = svelteRequest;
// virtual css module
if (query.svelte && query.type === 'style') {
const css = cache.getCSS(svelteRequest);
if (css) {
log.debug(`load returns css for ${filename}`);
return css;
const { filename, query, raw } = svelteRequest;
if (raw) {
return loadRaw(svelteRequest, compileSvelte, options);
} else {
if (query.svelte && query.type === 'style') {
const css = cache.getCSS(svelteRequest);
if (css) {
log.debug(`load returns css for ${filename}`);
return css;
}
}
// prevent vite asset plugin from loading files as url that should be compiled in transform
if (viteConfig.assetsInclude(filename)) {
log.debug(`load returns raw content for ${filename}`);
return fs.readFileSync(filename, 'utf-8');
}
}
// prevent vite asset plugin from loading files as url that should be compiled in transform
if (viteConfig.assetsInclude(filename)) {
log.debug(`load returns raw content for ${filename}`);
return fs.readFileSync(filename, 'utf-8');
}
}

@@ -135,3 +135,3 @@ },

if (svelteRequest?.query.svelte) {
if (svelteRequest.query.type === 'style') {
if (svelteRequest.query.type === 'style' && !svelteRequest.raw) {
// return cssId with root prefix so postcss pipeline of vite finds the directory correctly

@@ -142,4 +142,2 @@ // see https://github.com/sveltejs/vite-plugin-svelte/issues/14

}
log.debug(`resolveId resolved ${importee}`);
return importee; // query with svelte tag, an id we generated, no need for further analysis
}

@@ -197,3 +195,3 @@

const svelteRequest = requestParser(id, ssr);
if (!svelteRequest || svelteRequest.query.svelte) {
if (!svelteRequest || svelteRequest.query.type === 'style' || svelteRequest.raw) {
return;

@@ -248,2 +246,3 @@ }

export { vitePreprocess } from './preprocess';
export { loadSvelteConfig } from './utils/load-svelte-config';

@@ -250,0 +249,0 @@

@@ -9,7 +9,31 @@ import { CompileOptions, ResolvedOptions } from './options';

import { StatCollection } from './vite-plugin-svelte-stats';
//eslint-disable-next-line node/no-missing-import
import type { Processed } from 'svelte/types/compiler/preprocess';
import { createInjectScopeEverythingRulePreprocessorGroup } from './preprocess';
import path from 'path';
const scriptLangRE = /<script [^>]*lang=["']?([^"' >]+)["']?[^>]*>/;
export type CompileSvelte = ReturnType<typeof _createCompileSvelte>;
function mapSourcesToRelative(map: { sources?: string[] }, filename: string) {
// sourcemap sources are relative to the sourcemap itself
// assume the sourcemap location is the same as filename and turn absolute paths to relative
// to avoid leaking fs information like vite root
if (map?.sources) {
map.sources = map.sources.map((s) => {
if (path.isAbsolute(s)) {
const relative = path.relative(filename, s);
// empty string a source is not allowed, use simple filename
return relative === '' ? path.basename(filename) : relative;
} else {
return s;
}
});
}
}
const _createCompileSvelte = (makeHot: Function) => {
let stats: StatCollection | undefined;
const devStylePreprocessor = createInjectScopeEverythingRulePreprocessorGroup();
return async function compileSvelte(

@@ -20,3 +44,3 @@ svelteRequest: SvelteRequest,

): Promise<CompileData> {
const { filename, normalizedFilename, cssId, ssr } = svelteRequest;
const { filename, normalizedFilename, cssId, ssr, raw } = svelteRequest;
const { emitCss = true } = options;

@@ -52,3 +76,3 @@ const dependencies = [];

...options.compilerOptions,
filename,
filename: normalizedFilename, // use normalized here to avoid bleeding absolute fs path
generate: ssr ? 'ssr' : 'dom',

@@ -71,6 +95,16 @@ format: 'esm'

let preprocessed;
if (options.preprocess) {
let preprocessors = options.preprocess;
if (!options.isBuild && options.emitCss && options.hot) {
// inject preprocessor that ensures css hmr works better
if (!Array.isArray(preprocessors)) {
preprocessors = preprocessors
? [preprocessors, devStylePreprocessor]
: [devStylePreprocessor];
} else {
preprocessors = preprocessors.concat(devStylePreprocessor);
}
}
if (preprocessors) {
try {
preprocessed = await preprocess(code, options.preprocess, { filename });
preprocessed = await preprocess(code, preprocessors, { filename }); // full filename here so postcss works
} catch (e) {

@@ -84,2 +118,9 @@ e.message = `Error while preprocessing ${filename}${e.message ? ` - ${e.message}` : ''}`;

}
if (typeof preprocessed?.map === 'object') {
mapSourcesToRelative(preprocessed?.map, filename);
}
if (raw && svelteRequest.query.type === 'preprocessed') {
// shortcut
return { preprocessed: preprocessed ?? { code } } as CompileData;
}
const finalCode = preprocessed ? preprocessed.code : code;

@@ -108,22 +149,27 @@ const dynamicCompileOptions = await options.experimental?.dynamicCompileOptions?.({

}
mapSourcesToRelative(compiled.js?.map, filename);
mapSourcesToRelative(compiled.css?.map, filename);
if (!raw) {
// wire css import and code for hmr
const hasCss = compiled.css?.code?.trim().length > 0;
// compiler might not emit css with mode none or it may be empty
if (emitCss && hasCss) {
// TODO properly update sourcemap?
compiled.js.code += `\nimport ${JSON.stringify(cssId)};\n`;
}
const hasCss = compiled.css?.code?.trim().length > 0;
// compiler might not emit css with mode none or it may be empty
if (emitCss && hasCss) {
// TODO properly update sourcemap?
compiled.js.code += `\nimport ${JSON.stringify(cssId)};\n`;
// only apply hmr when not in ssr context and hot options are set
if (!ssr && makeHot) {
compiled.js.code = makeHot({
id: filename,
compiledCode: compiled.js.code,
//@ts-expect-error hot isn't a boolean at this point
hotOptions: { ...options.hot, injectCss: options.hot?.injectCss === true && hasCss },
compiled,
originalCode: code,
compileOptions: finalCompileOptions
});
}
}
// only apply hmr when not in ssr context and hot options are set
if (!ssr && makeHot) {
compiled.js.code = makeHot({
id: filename,
compiledCode: compiled.js.code,
hotOptions: { ...options.hot, injectCss: options.hot?.injectCss === true && hasCss },
compiled,
originalCode: code,
compileOptions: finalCompileOptions
});
}
compiled.js.dependencies = dependencies;

@@ -138,3 +184,4 @@

ssr,
dependencies
dependencies,
preprocessed: preprocessed ?? { code }
};

@@ -200,2 +247,3 @@ };

dependencies: string[];
preprocessed: Processed;
}

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

import * as fs from 'fs';
//eslint-disable-next-line node/no-missing-import
import { CompileOptions } from 'svelte/types/compiler/interfaces';
import { log } from './log';

@@ -11,4 +14,15 @@ const VITE_FS_PREFIX = '/@fs/';

export type SvelteQueryTypes = 'style' | 'script';
const SUPPORTED_COMPILER_OPTIONS = [
'generate',
'dev',
'css',
'hydratable',
'customElement',
'immutable',
'enableSourcemap'
];
const TYPES_WITH_COMPILER_OPTIONS = ['style', 'script', 'all'];
export type SvelteQueryTypes = 'style' | 'script' | 'preprocessed' | 'all';
export interface RequestQuery {

@@ -18,5 +32,11 @@ // our own

type?: SvelteQueryTypes;
sourcemap?: boolean;
compilerOptions?: Pick<
CompileOptions,
'generate' | 'dev' | 'css' | 'hydratable' | 'customElement' | 'immutable' | 'enableSourcemap'
>;
// vite specific
url?: boolean;
raw?: boolean;
direct?: boolean;
}

@@ -32,2 +52,3 @@

ssr: boolean;
raw: boolean;
}

@@ -51,6 +72,8 @@

const query = parseRequestQuery(rawQuery);
if (query.url || query.raw) {
const rawOrDirect = !!(query.raw || query.direct);
if (query.url || (!query.svelte && rawOrDirect)) {
// skip requests with special vite tags
return;
}
const raw = rawOrDirect;
const normalizedFilename = normalize(filename, root);

@@ -66,3 +89,4 @@ const cssId = createVirtualImportId(filename, root, 'style');

timestamp,
ssr
ssr,
raw
};

@@ -95,2 +119,30 @@ }

}
const compilerOptions = query.compilerOptions;
if (compilerOptions) {
if (!((query.raw || query.direct) && TYPES_WITH_COMPILER_OPTIONS.includes(query.type))) {
throw new Error(
`Invalid compilerOptions in query ${rawQuery}. CompilerOptions are only supported for raw or direct queries with type in "${TYPES_WITH_COMPILER_OPTIONS.join(
', '
)}" e.g. '?svelte&raw&type=script&compilerOptions={"generate":"ssr","dev":false}`
);
}
try {
const parsed = JSON.parse(compilerOptions);
const invalid = Object.keys(parsed).filter(
(key) => !SUPPORTED_COMPILER_OPTIONS.includes(key)
);
if (invalid.length) {
throw new Error(
`Invalid compilerOptions in query ${rawQuery}: ${invalid.join(
', '
)}. Supported: ${SUPPORTED_COMPILER_OPTIONS.join(', ')}`
);
}
query.compilerOptions = parsed;
} catch (e) {
log.error('failed to parse request query compilerOptions', e);
throw e;
}
}
return query as RequestQuery;

@@ -97,0 +149,0 @@ }

@@ -318,2 +318,5 @@ /* eslint-disable no-unused-vars */

}
if ((options.experimental as any)?.generateMissingPreprocessorSourcemaps) {
log.warn('experimental.generateMissingPreprocessorSourcemaps has been removed.');
}
}

@@ -536,2 +539,11 @@

export function patchResolvedViteConfig(viteConfig: ResolvedConfig, options: ResolvedOptions) {
if (options.preprocess) {
for (const preprocessor of arraify(options.preprocess)) {
if (preprocessor.style && '__resolvedConfig' in preprocessor.style) {
preprocessor.style.__resolvedConfig = viteConfig;
}
}
}
// replace facade esbuild plugin with a real one
const facadeEsbuildSveltePlugin = viteConfig.optimizeDeps.esbuildOptions?.plugins?.find(

@@ -545,2 +557,6 @@ (plugin) => plugin.name === facadeEsbuildSveltePluginName

function arraify<T>(value: T | T[]): T[] {
return Array.isArray(value) ? value : [value];
}
export type Options = Omit<SvelteOptions, 'vitePlugin'> & PluginOptionsInline;

@@ -687,11 +703,2 @@

/**
* If a preprocessor does not provide a sourcemap, a best-effort fallback sourcemap will be provided.
* This option requires `diff-match-patch` to be installed as a peer dependency.
*
* @see https://github.com/google/diff-match-patch
* @default false
*/
generateMissingPreprocessorSourcemaps?: boolean;
/**
* A function to update `compilerOptions` before compilation

@@ -698,0 +705,0 @@ *

@@ -1,91 +0,15 @@

import * as vite from 'vite';
import type { ESBuildOptions, ResolvedConfig, Plugin } from 'vite';
import type { ResolvedConfig, Plugin } from 'vite';
import MagicString from 'magic-string';
import { preprocess } from 'svelte/compiler';
import { Preprocessor, PreprocessorGroup, Processed, ResolvedOptions } from './options';
import { PreprocessorGroup, ResolvedOptions } from './options';
import { log } from './log';
import { buildSourceMap } from './sourcemap';
import path from 'path';
import { vitePreprocess } from '../preprocess';
const supportedStyleLangs = ['css', 'less', 'sass', 'scss', 'styl', 'stylus', 'postcss'];
const supportedScriptLangs = ['ts'];
function createViteScriptPreprocessor(): Preprocessor {
return async ({ attributes, content, filename = '' }) => {
const lang = attributes.lang as string;
if (!supportedScriptLangs.includes(lang)) return;
const transformResult = await vite.transformWithEsbuild(content, filename, {
loader: lang as ESBuildOptions['loader'],
target: 'esnext',
tsconfigRaw: {
compilerOptions: {
// svelte typescript needs this flag to work with type imports
importsNotUsedAsValues: 'preserve',
preserveValueImports: true
}
}
});
return {
code: transformResult.code,
map: transformResult.map
};
};
}
function createViteStylePreprocessor(config: ResolvedConfig): Preprocessor {
const transform = getCssTransformFn(config);
return async ({ attributes, content, filename = '' }) => {
const lang = attributes.lang as string;
if (!supportedStyleLangs.includes(lang)) return;
const moduleId = `${filename}.${lang}`;
const result = await transform(content, moduleId);
// patch sourcemap source to point back to original filename
if (result.map?.sources?.[0] === moduleId) {
result.map.sources[0] = path.basename(filename);
}
return {
code: result.code,
map: result.map ?? undefined
};
};
}
// eslint-disable-next-line no-unused-vars
type CssTransform = (code: string, filename: string) => Promise<{ code: string; map?: any }>;
function getCssTransformFn(config: ResolvedConfig): CssTransform {
// API is only available in Vite 3.2 and above
// TODO: Remove Vite plugin hack when bump peer dep to Vite 3.2
if (vite.preprocessCSS) {
return async (code, filename) => {
return vite.preprocessCSS(code, filename, config);
};
} else {
const pluginName = 'vite:css';
const plugin = config.plugins.find((p) => p.name === pluginName);
if (!plugin) {
throw new Error(`failed to find plugin ${pluginName}`);
}
if (!plugin.transform) {
throw new Error(`plugin ${pluginName} has no transform`);
}
// @ts-expect-error
return plugin.transform.bind(null);
}
}
function createVitePreprocessorGroup(config: ResolvedConfig): PreprocessorGroup {
return {
markup({ content, filename }) {
return preprocess(
content,
{
script: createViteScriptPreprocessor(),
style: createViteStylePreprocessor(config)
},
{ filename }
);
return preprocess(content, vitePreprocess({ style: config }), { filename });
}
} as PreprocessorGroup;
};
}

@@ -99,3 +23,3 @@

*/
function createInjectScopeEverythingRulePreprocessorGroup(): PreprocessorGroup {
export function createInjectScopeEverythingRulePreprocessorGroup(): PreprocessorGroup {
return {

@@ -121,3 +45,5 @@ style({ content, filename }) {

if (options.experimental?.useVitePreprocess) {
log.debug('adding vite preprocessor');
log.warn(
'`experimental.useVitePreprocess` is deprecated. Use the `vitePreprocess()` preprocessor instead. See https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/preprocess.md for more information.'
);
prependPreprocessors.push(createVitePreprocessorGroup(config));

@@ -180,6 +106,2 @@ }

if (options.hot && options.emitCss) {
appendPreprocessors.push(createInjectScopeEverythingRulePreprocessorGroup());
}
return { prependPreprocessors, appendPreprocessors };

@@ -200,65 +122,2 @@ }

}
const generateMissingSourceMaps = !!options.experimental?.generateMissingPreprocessorSourcemaps;
if (options.preprocess && generateMissingSourceMaps) {
options.preprocess = Array.isArray(options.preprocess)
? options.preprocess.map((p, i) => validateSourceMapOutputWrapper(p, i))
: validateSourceMapOutputWrapper(options.preprocess, 0);
}
}
function validateSourceMapOutputWrapper(group: PreprocessorGroup, i: number): PreprocessorGroup {
const wrapper: PreprocessorGroup = {};
for (const [processorType, processorFn] of Object.entries(group) as Array<
// eslint-disable-next-line no-unused-vars
[keyof PreprocessorGroup, (options: { filename?: string; content: string }) => Processed]
>) {
wrapper[processorType] = async (options) => {
const result = await processorFn(options);
if (result && result.code !== options.content) {
let invalidMap = false;
if (!result.map) {
invalidMap = true;
log.warn.enabled &&
log.warn.once(
`preprocessor at index ${i} did not return a sourcemap for ${processorType} transform`,
{
filename: options.filename,
type: processorType,
processor: processorFn.toString()
}
);
} else if ((result.map as any)?.mappings === '') {
invalidMap = true;
log.warn.enabled &&
log.warn.once(
`preprocessor at index ${i} returned an invalid empty sourcemap for ${processorType} transform`,
{
filename: options.filename,
type: processorType,
processor: processorFn.toString()
}
);
}
if (invalidMap) {
try {
const map = await buildSourceMap(options.content, result.code, options.filename);
if (map) {
log.debug.enabled &&
log.debug(
`adding generated sourcemap to preprocesor result for ${options.filename}`
);
result.map = map;
}
} catch (e) {
log.error(`failed to build sourcemap`, e);
}
}
}
return result;
};
}
return wrapper;
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc