diff --git a/CHANGELOG.md b/CHANGELOG.md index 01f041ab..cbab2638 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [6.0.2](https://github.com/sveltejs/svelte-preprocess/compare/v6.0.1...v6.0.2) (2024-07-09) + + +### Bug Fixes + +* remove customConditions tsconfig option ([#648](https://github.com/sveltejs/svelte-preprocess/issues/648)) ([afb80ae](https://github.com/sveltejs/svelte-preprocess/commit/afb80ae3fa1cafcf5293c1ab274e99b1966c632f)), closes [#646](https://github.com/sveltejs/svelte-preprocess/issues/646) + + + ## [6.0.1](https://github.com/sveltejs/svelte-preprocess/compare/v5.1.4...v6.0.1) (2024-06-14) ### Bug Fixes diff --git a/docs/migration-guide.md b/docs/migration-guide.md index e4b83bc8..84c0bd33 100644 --- a/docs/migration-guide.md +++ b/docs/migration-guide.md @@ -9,6 +9,7 @@ - [Executing some function before preprocessing](#executing-some-function-before-preprocessing) - [Defining preprocessor properties](#defining-preprocessor-properties) - [Type-checking components](#type-checking-components) +- [From `v5` to `v6`](#from-v5-to-v6) @@ -95,7 +96,8 @@ In `v4`, your TypeScript code will only be transpiled into JavaScript, with no t - Svelte 4 or higher is required now - Node 18 or higher is required now -- When using TypeScript, the minimum required version is now 5.0, `"verbatimModuleSyntax": true` is now required in your `tsconfig.json`, and the mixed imports transpiler (`handleMixedImports`) was removed +- When using TypeScript, the minimum required version is now 5.0 +- When using TypeScript, `"verbatimModuleSyntax": true` is now required in your `tsconfig.json` (instead of the deprecated `preserveValueImports` and `importsNotUsedAsValues` options). As a consequence, the mixed imports transpiler (`handleMixedImports`) was removed from the TypeScript preprocessor. This means that you now need to specify for each import if it's a type or value import. For example instead of `import { value, Type } from 'somewhere'` you now need to write `import { value, type Type } from 'somewhere'` - The `preserve` option was removed as it's obsolete - The default export is deprecated in favor of its new named export: diff --git a/package.json b/package.json index fdd234cc..1cdc8cb0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte-preprocess", - "version": "6.0.1", + "version": "6.0.2", "license": "MIT", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -84,10 +84,6 @@ "typescript": "^5.0.2", "vitest": "^1.6.0" }, - "dependencies": { - "detect-indent": "^6.1.0", - "strip-indent": "^3.0.0" - }, "peerDependencies": { "@babel/core": "^7.10.2", "coffeescript": "^2.5.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f5c1446b..aab9c168 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,13 +7,6 @@ settings: importers: .: - dependencies: - detect-indent: - specifier: ^6.1.0 - version: 6.1.0 - strip-indent: - specifier: ^3.0.0 - version: 3.0.0 devDependencies: '@babel/core': specifier: ^7.23.6 @@ -1974,10 +1967,6 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} - detect-indent@6.1.0: - resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} - engines: {node: '>=8'} - detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} @@ -6564,8 +6553,6 @@ snapshots: dequal@2.0.3: {} - detect-indent@6.1.0: {} - detect-newline@3.1.0: optional: true diff --git a/src/modules/prepareContent.ts b/src/modules/prepareContent.ts index b296edb5..5dadf5d9 100644 --- a/src/modules/prepareContent.ts +++ b/src/modules/prepareContent.ts @@ -1,6 +1,4 @@ -import stripIndent from 'strip-indent'; - -// todo: could use magig-string and generate some sourcemaps 🗺 +// todo: could use magic-string and generate some sourcemaps 🗺 export function prepareContent({ options, content, @@ -22,3 +20,27 @@ export function prepareContent({ return content; } + +/** Get the shortest leading whitespace from lines in a string */ +function minIndent(s: string) { + const match = s.match(/^[ \t]*(?=\S)/gm); + + if (!match) { + return 0; + } + + return match.reduce((r, a) => Math.min(r, a.length), Infinity); +} + +/** Strip leading whitespace from each line in a string */ +function stripIndent(s: string) { + const indent = minIndent(s); + + if (indent === 0) { + return s; + } + + const regex = new RegExp(`^[ \\t]{${indent}}`, 'gm'); + + return s.replace(regex, ''); +} diff --git a/src/transformers/pug.ts b/src/transformers/pug.ts index b02192bf..dfad0609 100644 --- a/src/transformers/pug.ts +++ b/src/transformers/pug.ts @@ -1,4 +1,3 @@ -import detectIndent from 'detect-indent'; import pug from 'pug'; import type { Transformer, Options } from '../types'; @@ -67,8 +66,8 @@ const transformer: Transformer = async ({ ...options, }; - const { type: indentationType } = detectIndent(content); - const input = `${GET_MIXINS(indentationType ?? 'space')}\n${content}`; + const spaces = guessIndentString(content); + const input = `${GET_MIXINS(spaces ? 'space' : 'tab')}\n${content}`; const compiled = pug.compile( input, pugOptions, @@ -94,4 +93,41 @@ const transformer: Transformer = async ({ }; }; +// Sourced from `golden-fleece` +// https://github.com/Rich-Harris/golden-fleece/blob/f2446f331640f325e13609ed99b74b6a45e755c2/src/patch.ts#L302 +function guessIndentString(str: string): number | undefined { + const lines = str.split('\n'); + + let tabs = 0; + let spaces = 0; + let minSpaces = 8; + + lines.forEach((line) => { + const match = /^(?: +|\t+)/.exec(line); + + if (!match) return; + + const [whitespace] = match; + + if (whitespace.length === line.length) return; + + if (whitespace[0] === '\t') { + tabs += 1; + } else { + spaces += 1; + if (whitespace.length > 1 && whitespace.length < minSpaces) { + minSpaces = whitespace.length; + } + } + }); + + if (spaces > tabs) { + let result = ''; + + while (minSpaces--) result += ' '; + + return result.length; + } +} + export { transformer }; diff --git a/src/transformers/typescript.ts b/src/transformers/typescript.ts index d652a563..27fd6a41 100644 --- a/src/transformers/typescript.ts +++ b/src/transformers/typescript.ts @@ -47,12 +47,15 @@ function getCompilerOptions({ options: Options.Typescript; basePath: string; }): CompilerOptions { - const inputOptions = options.compilerOptions ?? {}; + const inputOptions = ts.convertCompilerOptionsFromJson( + options.compilerOptions ?? {}, + basePath, + ); const { errors, options: convertedCompilerOptions } = options.tsconfigFile !== false || options.tsconfigDirectory ? loadTsconfig(inputOptions, filename, options) - : ts.convertCompilerOptionsFromJson(inputOptions, basePath); + : inputOptions; if (errors.length) { throw new Error(formatDiagnostics(errors, basePath)); @@ -60,12 +63,17 @@ function getCompilerOptions({ const compilerOptions: CompilerOptions = { target: ts.ScriptTarget.ES2015, - ...(convertedCompilerOptions as CompilerOptions), + ...convertedCompilerOptions, // force module(resolution) to esnext and a compatible moduleResolution. Reason: // transpileModule treats NodeNext as CommonJS because it doesn't read the package.json. // Also see https://github.com/microsoft/TypeScript/issues/53022 (the filename workaround doesn't work). module: ts.ModuleKind.ESNext, - moduleResolution: ts.ModuleResolutionKind.Node10, + moduleResolution: + convertedCompilerOptions.moduleResolution === + ts.ModuleResolutionKind.Bundler + ? ts.ModuleResolutionKind.Bundler + : ts.ModuleResolutionKind.Node10, + customConditions: undefined, // fails when using an invalid moduleResolution combination which could happen when we force moduleResolution to Node10 allowNonTsExtensions: true, // Clear outDir since it causes source map issues when the files aren't actually written to disk. outDir: undefined, @@ -74,8 +82,16 @@ function getCompilerOptions({ if (!warned_verbatim && !compilerOptions.verbatimModuleSyntax) { warned_verbatim = true; console.warn( + '\x1b[1m%s\x1b[0m', 'The TypeScript option verbatimModuleSyntax is now required when using Svelte files with lang="ts". Please add it to your tsconfig.json.', ); + // best effort to still add it, if possible, in case no config was found whatsoever + if ( + Object.keys(inputOptions.options).length === 0 && + convertedCompilerOptions === inputOptions.options + ) { + compilerOptions.verbatimModuleSyntax = true; + } } if ( @@ -138,12 +154,18 @@ function transpileTs({ } export function loadTsconfig( - compilerOptionsJSON: any, + fallback: { + options: ts.CompilerOptions; + errors: ts.Diagnostic[]; + }, filename: string, tsOptions: Options.Typescript, -) { +): { + options: ts.CompilerOptions; + errors: ts.Diagnostic[]; +} { if (typeof tsOptions.tsconfigFile === 'boolean') { - return { errors: [], options: compilerOptionsJSON }; + return fallback; } let basePath = process.cwd(); @@ -156,7 +178,7 @@ export function loadTsconfig( ts.findConfigFile(fileDirectory, ts.sys.fileExists); if (!tsconfigFile) { - return { errors: [], options: compilerOptionsJSON }; + return fallback; } tsconfigFile = isAbsolute(tsconfigFile) @@ -185,7 +207,7 @@ export function loadTsconfig( config, ts.sys, basePath, - compilerOptionsJSON, + fallback.options, tsconfigFile, ); diff --git a/src/types/modules.d.ts b/src/types/modules.d.ts index e7626816..6b524a71 100644 --- a/src/types/modules.d.ts +++ b/src/types/modules.d.ts @@ -1,6 +1,5 @@ declare module 'svelte/package.json'; declare module 'coffeescript'; -declare module 'strip-indent'; declare module 'postcss-load-config'; declare module 'less'; declare module 'sorcery'; diff --git a/test/transformers/typescript.test.ts b/test/transformers/typescript.test.ts index 53c67e93..756affc3 100644 --- a/test/transformers/typescript.test.ts +++ b/test/transformers/typescript.test.ts @@ -12,7 +12,7 @@ import { import type { Processed } from '../../src/types'; import type { Diagnostic } from 'typescript'; -spyConsole({ silent: true }); +spyConsole({ silent: false }); const EXPECTED_SCRIPT = getFixtureContent('script.js'); @@ -203,5 +203,22 @@ describe('transformer - typescript', () => { expect(code).not.toContain('&&='); expect(code).not.toContain('||='); }); + + it('should remove customConditions option if necessary to prevent config error', async () => { + const opts = sveltePreprocess({ + typescript: { + tsconfigFile: false, + compilerOptions: { + // we force a different module resolution in our transformer which + // would fail if we wouldn't also remove the customConditions + moduleResolution: 'NodeNext', + customConditions: ['development'], + }, + }, + }); + const preprocessed = await preprocess(template, opts); + + expect(preprocessed.toString?.()).toContain('export var hello'); + }); }); }); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy