@sveltejs/vite-plugin-svelte
Advanced tools
Comparing version 3.0.0-next.0 to 3.0.0-next.1
{ | ||
"name": "@sveltejs/vite-plugin-svelte", | ||
"version": "3.0.0-next.0", | ||
"version": "3.0.0-next.1", | ||
"license": "MIT", | ||
@@ -37,9 +37,9 @@ "author": "dominikg", | ||
"dependencies": { | ||
"@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", | ||
"@sveltejs/vite-plugin-svelte-inspector": "^2.0.0-next.0" | ||
"vitefu": "^0.2.5" | ||
}, | ||
@@ -51,6 +51,6 @@ "peerDependencies": { | ||
"devDependencies": { | ||
"@types/debug": "^4.1.8", | ||
"esbuild": "^0.19.3", | ||
"svelte": "^4.2.0", | ||
"vite": "^5.0.0-beta.1" | ||
"@types/debug": "^4.1.9", | ||
"esbuild": "^0.19.4", | ||
"svelte": "^4.2.1", | ||
"vite": "^5.0.0-beta.7" | ||
}, | ||
@@ -57,0 +57,0 @@ "scripts": { |
@@ -124,16 +124,3 @@ import type { InlineConfig, ResolvedConfig, UserConfig, Plugin } from 'vite'; | ||
compilerOptions?: Omit<CompileOptions, 'filename' | 'format' | 'generate'>; | ||
/** | ||
* Handles warning emitted from the Svelte compiler | ||
*/ | ||
onwarn?: (warning: Warning, defaultHandler?: (warning: Warning) => void) => void; | ||
/** | ||
* Options for vite-plugin-svelte | ||
*/ | ||
vitePlugin?: PluginOptions; | ||
} | ||
/** | ||
* These options are considered experimental and breaking changes to them can occur in any release | ||
*/ | ||
interface ExperimentalOptions { | ||
/** | ||
@@ -163,3 +150,18 @@ * A function to update `compilerOptions` before compilation | ||
}) => Promise<Partial<CompileOptions> | void> | Partial<CompileOptions> | void; | ||
/** | ||
* Handles warning emitted from the Svelte compiler | ||
*/ | ||
onwarn?: (warning: Warning, defaultHandler?: (warning: Warning) => void) => void; | ||
/** | ||
* Options for vite-plugin-svelte | ||
*/ | ||
vitePlugin?: PluginOptions; | ||
} | ||
/** | ||
* These options are considered experimental and breaking changes to them can occur in any release | ||
*/ | ||
interface ExperimentalOptions { | ||
/** | ||
* send a websocket message with svelte compiler warnings during dev | ||
@@ -166,0 +168,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,6 +8,5 @@ | ||
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'; | ||
@@ -17,3 +16,3 @@ /** @type {import('./index.d.ts').vitePreprocess} */ | ||
/** @type {import('svelte/types/compiler/preprocess').PreprocessorGroup} */ | ||
const preprocessor = {}; | ||
const preprocessor = { name: 'vite-preprocess' }; | ||
if (opts?.script !== false) { | ||
@@ -68,4 +67,4 @@ preprocessor.script = viteScript().script; | ||
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) { | ||
@@ -88,3 +87,3 @@ /** @type {import('vite').ResolvedConfig} */ | ||
} | ||
const suffix = `${lang_sep}${lang}`; | ||
const suffix = `${lang_sep}${ext}`; | ||
const moduleId = `${filename}${suffix}`; | ||
@@ -91,0 +90,0 @@ const { code, map, deps } = await transform(content, moduleId); |
@@ -7,4 +7,8 @@ import { compile, preprocess, walk } from 'svelte/compiler'; | ||
import { createInjectScopeEverythingRulePreprocessorGroup } from './preprocess.js'; | ||
import { | ||
checkPreprocessDependencies, | ||
createInjectScopeEverythingRulePreprocessorGroup | ||
} from './preprocess.js'; | ||
import { mapToRelative } from './sourcemaps.js'; | ||
import { enhanceCompileError } from './error.js'; | ||
@@ -25,3 +29,6 @@ const scriptLangRE = /<script [^>]*lang=["']?([^"' >]+)["']?[^>]*>/; | ||
const { emitCss = true } = options; | ||
/** @type {string[]} */ | ||
const dependencies = []; | ||
/** @type {import('svelte/types/compiler/interfaces').Warning[]} */ | ||
const warnings = []; | ||
@@ -91,3 +98,12 @@ if (options.stats) { | ||
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; | ||
@@ -105,3 +121,3 @@ } | ||
const finalCode = preprocessed ? preprocessed.code : code; | ||
const dynamicCompileOptions = await options.experimental?.dynamicCompileOptions?.({ | ||
const dynamicCompileOptions = await options?.dynamicCompileOptions?.({ | ||
filename, | ||
@@ -126,3 +142,10 @@ code: finalCode, | ||
const endStat = stats?.start(filename); | ||
const compiled = compile(finalCode, finalCompileOptions); | ||
/** @type {import('svelte/types/compiler/interfaces').CompileResult} */ | ||
let compiled; | ||
try { | ||
compiled = compile(finalCode, finalCompileOptions); | ||
} catch (e) { | ||
enhanceCompileError(e, code, preprocessors); | ||
throw e; | ||
} | ||
@@ -134,2 +157,8 @@ if (endStat) { | ||
mapToRelative(compiled.css?.map, filename); | ||
if (warnings.length) { | ||
if (!compiled.warnings) { | ||
compiled.warnings = []; | ||
} | ||
compiled.warnings.push(...warnings); | ||
} | ||
if (!raw) { | ||
@@ -136,0 +165,0 @@ // wire css import and code for hmr |
@@ -103,1 +103,77 @@ 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('../index.js').Arrayable<import('svelte/types/compiler/preprocess').PreprocessorGroup>} [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/800f6c076be5dd87dd4d2e9d66c59b973d54d84b/packages/svelte/src/compiler/preprocess/index.js#L262 | ||
const scriptRe = /<script(\s[^]*?)?(?:>([^]*?)<\/script>|\/>)/gi; | ||
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') { | ||
const styleRe = /<style(\s[^]*?)?(?:>([^]*?)<\/style>|\/>)/gi; | ||
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]; | ||
} |
@@ -84,3 +84,3 @@ import { readFileSync } from 'node:fs'; | ||
const dynamicCompileOptions = await options.experimental?.dynamicCompileOptions?.({ | ||
const dynamicCompileOptions = await options?.dynamicCompileOptions?.({ | ||
filename, | ||
@@ -92,3 +92,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' | ||
); | ||
} | ||
@@ -95,0 +99,0 @@ |
@@ -62,3 +62,4 @@ import { createRequire } from 'node:module'; | ||
? esmRequire ?? (esmRequire = createRequire(import.meta.url)) | ||
: require; | ||
: // eslint-disable-next-line no-undef | ||
require; | ||
@@ -65,0 +66,0 @@ // avoid loading cached version on reload |
@@ -39,2 +39,3 @@ /* eslint-disable no-unused-vars */ | ||
'inspector', | ||
'dynamicCompileOptions', | ||
'experimental' | ||
@@ -320,3 +321,3 @@ ]); | ||
if (experimental) { | ||
for (const promoted of ['prebundleSvelteLibraries', 'inspector']) { | ||
for (const promoted of ['prebundleSvelteLibraries', 'inspector', 'dynamicCompileOptions']) { | ||
if (experimental[promoted]) { | ||
@@ -327,3 +328,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.` | ||
); | ||
@@ -330,0 +331,0 @@ } |
import MagicString from 'magic-string'; | ||
import { log } from './log.js'; | ||
import path from 'node:path'; | ||
import { normalizePath } from 'vite'; | ||
@@ -15,2 +16,3 @@ /** | ||
return { | ||
name: 'inject-scope-everything-rule', | ||
style({ content, filename }) { | ||
@@ -124,1 +126,50 @@ const s = new MagicString(content); | ||
} | ||
/** | ||
* | ||
* @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 | ||
}; | ||
} |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
113432
3432
9