diff --git a/docs/preprocessing.md b/docs/preprocessing.md index fb92333d..4ac94027 100644 --- a/docs/preprocessing.md +++ b/docs/preprocessing.md @@ -369,11 +369,12 @@ Note: `svelte-preprocess` automatically configures inclusion paths for your root ### TypeScript -| Option | Default | Description | -| ------------------- | ----------- | ----------------------------------------------------------------------------------------------------------- | -| `tsconfigDirectory` | `undefined` | optional `string` that specifies from where to load the tsconfig from.

i.e `'./configs'` | -| `tsconfigFile` | `undefined` | optional `string` pointing torwards a `tsconfig` file.

i.e `'./tsconfig.app.json'` | -| `compilerOptions` | `undefined` | optional compiler options configuration. These will be merged with options from the tsconfig file if found. | +| Option | Default | Description | +| -------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `tsconfigDirectory` | `undefined` | optional `string` that specifies from where to load the tsconfig from.

i.e `'./configs'` | +| `tsconfigFile` | `undefined` | optional `string` pointing torwards a `tsconfig` file.

i.e `'./tsconfig.app.json'` | +| `compilerOptions` | `undefined` | optional compiler options configuration. These will be merged with options from the tsconfig file if found. | +| `handleMixedImports` | inferred | optional `boolean` that defines the transpilation strategy. If set to `true`, you don't need to strictly separate types and values in imports. You need at least Svelte version 3.39 if you want to use this. `true` by default if you meet the minimum version requirement, else `false`. | You can check the [`compilerOptions` reference](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) for specific TypeScript options. @@ -381,8 +382,6 @@ You can check the [`compilerOptions` reference](https://www.typescriptlang.org/d - Since `v4`, `svelte-preprocess` doesn't type-check your component, its only concern is to transpile it into valid JavaScript for the compiler. If you want to have your components type-checked, you can use [svelte-check](https://github.com/sveltejs/language-tools/blob/master/packages/svelte-check/README.md). -- As we're only transpiling, it's not possible to import types or interfaces into your svelte component without using the new TS 3.8 `type` import modifier: `import type { SomeInterface } from './MyModule'` otherwise bundlers will complain that the name is not exported by `MyModule`. - - Using TypeScript inside a component's markup is currently **not** supported. See [#318](https://github.com/sveltejs/svelte-preprocess/issues/318) for development updates to this. ### `globalStyle` diff --git a/package.json b/package.json index 6a84f61d..1a70d6ac 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ "sass": "^1.26.8", "stylus": "^0.54.7", "sugarss": "^2.0.0", - "svelte": "^3.23.0", + "svelte": "^3.42.0", "ts-jest": "^25.1.0", "typescript": "^3.9.5" }, @@ -93,6 +93,8 @@ "@types/pug": "^2.0.4", "@types/sass": "^1.16.0", "detect-indent": "^6.0.0", + "magic-string": "^0.25.7", + "sorcery": "^0.10.0", "strip-indent": "^3.0.0" }, "peerDependencies": { diff --git a/src/autoProcess.ts b/src/autoProcess.ts index 44b6efec..9826d38e 100644 --- a/src/autoProcess.ts +++ b/src/autoProcess.ts @@ -24,7 +24,7 @@ import { transformMarkup } from './modules/markup'; export const transform = async ( name: string, options: TransformerOptions, - { content, map, filename, attributes }: TransformerArgs, + { content, markup, map, filename, attributes }: TransformerArgs, ): Promise => { if (options === false) { return { code: content }; @@ -39,6 +39,7 @@ export const transform = async ( return transformer({ content, + markup, filename, map, attributes, @@ -115,6 +116,7 @@ export function sveltePreprocess( ): Preprocessor => async (svelteFile) => { let { content, + markup, filename, lang, alias, @@ -151,6 +153,7 @@ export function sveltePreprocess( const transformed = await transform(lang, transformerOptions, { content, + markup, filename, attributes, }); @@ -169,6 +172,7 @@ export function sveltePreprocess( if (transformers.replace) { const transformed = await transform('replace', transformers.replace, { content, + markup: content, filename, }); @@ -185,11 +189,13 @@ export function sveltePreprocess( const script: PreprocessorGroup['script'] = async ({ content, attributes, + markup: fullMarkup, filename, }) => { const transformResult: Processed = await scriptTransformer({ content, attributes, + markup: fullMarkup, filename, }); @@ -199,7 +205,7 @@ export function sveltePreprocess( const transformed = await transform( 'babel', getTransformerOptions('babel'), - { content: code, map, filename, attributes }, + { content: code, markup: fullMarkup, map, filename, attributes }, ); code = transformed.code; @@ -214,11 +220,13 @@ export function sveltePreprocess( const style: PreprocessorGroup['style'] = async ({ content, attributes, + markup: fullMarkup, filename, }) => { const transformResult = await cssTransformer({ content, attributes, + markup: fullMarkup, filename, }); @@ -239,6 +247,7 @@ export function sveltePreprocess( const transformed = await transform('postcss', postcssOptions, { content: code, + markup: fullMarkup, map, filename, attributes, @@ -252,7 +261,7 @@ export function sveltePreprocess( const transformed = await transform( 'globalStyle', getTransformerOptions('globalStyle'), - { content: code, map, filename, attributes }, + { content: code, markup: fullMarkup, map, filename, attributes }, ); code = transformed.code; diff --git a/src/modules/markup.ts b/src/modules/markup.ts index 704842fd..16aba061 100644 --- a/src/modules/markup.ts +++ b/src/modules/markup.ts @@ -1,5 +1,35 @@ import type { Transformer, Preprocessor } from '../types'; +/** Create a tag matching regexp. */ +export function createTagRegex(tagName: string, flags?: string): RegExp { + return new RegExp( + `/|<${tagName}(\\s[^]*?)?(?:>([^]*?)<\\/${tagName}>|\\/>)`, + flags, + ); +} + +/** Strip script and style tags from markup. */ +export function stripTags(markup: string): string { + return markup + .replace(createTagRegex('style', 'gi'), '') + .replace(createTagRegex('script', 'gi'), ''); +} + +/** Transform an attribute string into a key-value object */ +export function parseAttributes(attributesStr: string): Record { + return attributesStr + .split(/\s+/) + .filter(Boolean) + .reduce((acc: Record, attr) => { + const [name, value] = attr.split('='); + + // istanbul ignore next + acc[name] = value ? value.replace(/['"]/g, '') : true; + + return acc; + }, {}); +} + export async function transformMarkup( { content, filename }: { content: string; filename: string }, transformer: Preprocessor | Transformer, @@ -9,35 +39,29 @@ export async function transformMarkup( markupTagName = markupTagName.toLocaleLowerCase(); - const markupPattern = new RegExp( - `/|<${markupTagName}(\\s[^]*?)?(?:>([^]*?)<\\/${markupTagName}>|\\/>)`, - ); + const markupPattern = createTagRegex(markupTagName); const templateMatch = content.match(markupPattern); /** If no