diff --git a/README.md b/README.md index 640d39b8..ef6d00c3 100644 --- a/README.md +++ b/README.md @@ -557,7 +557,15 @@ const options = { [/@endawait$/gim, '{/await}'], [/@debug\s*\((.*?)\)$/gim, '{@debug $1}'], [/@html\s*\((.*?)\)$/gim, '{@html $1}'], - ]; + ], + + /** Configure globalStyle and globalRule source map options */ + globalStyle: { + sourceMap: true, + }, + globalRule: { + sourceMap: true, + }, }; svelte.preprocess(input, sveltePreprocess(options)); diff --git a/src/autoProcess.ts b/src/autoProcess.ts index 106fe6aa..531a7082 100644 --- a/src/autoProcess.ts +++ b/src/autoProcess.ts @@ -24,8 +24,8 @@ interface Transformers { postcss?: TransformerOptions; coffeescript?: TransformerOptions; pug?: TransformerOptions; - globalStyle?: TransformerOptions; - globalRule?: TransformerOptions; + globalStyle?: Options.GlobalStyle; + globalRule?: Options.GlobalRule; replace?: Options.Replace; [languageName: string]: TransformerOptions; } @@ -53,8 +53,8 @@ type AutoPreprocessOptions = { babel?: TransformerOptions; coffeescript?: TransformerOptions; pug?: TransformerOptions; - globalStyle?: TransformerOptions; - globalRule?: TransformerOptions; + globalStyle?: Options.GlobalStyle; + globalRule?: Options.GlobalRule; // workaround while we don't have this // https://github.com/microsoft/TypeScript/issues/17867 [languageName: string]: @@ -263,21 +263,29 @@ export function autoPreprocess( if (await hasPostCssInstalled()) { if (attributes.global) { - const transformed = await runTransformer('globalStyle', null, { - content: code, - map, - filename, - }); + const transformed = await runTransformer( + 'globalStyle', + transformers?.globalStyle, + { + content: code, + map, + filename, + }, + ); code = transformed.code; map = transformed.map; } - const transformed = await runTransformer('globalRule', null, { - content: code, - map, - filename, - }); + const transformed = await runTransformer( + 'globalRule', + transformers?.globalRule, + { + content: code, + map, + filename, + }, + ); code = transformed.code; map = transformed.map; diff --git a/src/transformers/globalRule.ts b/src/transformers/globalRule.ts index 65872d2d..a3010963 100644 --- a/src/transformers/globalRule.ts +++ b/src/transformers/globalRule.ts @@ -1,25 +1,43 @@ import postcss from 'postcss'; -import { Transformer } from '../types'; +import { Transformer, Options } from '../types'; import { globalifySelector } from '../modules/globalifySelector'; const selectorPattern = /:global(?!\()/; -const globalifyRulePlugin = (root: any) => { - root.walkRules(selectorPattern, (rule: any) => { - const [beginning, ...rest] = rule.selector.split(selectorPattern); +const globalifyRulePlugin: postcss.Transformer = (root) => { + root.walkRules(selectorPattern, (rule) => { + const modifiedSelectors = rule.selectors.map((selector) => { + const [beginning, ...rest] = selector.split(selectorPattern); - rule.selector = [beginning, ...rest.map(globalifySelector)] - .map((str) => str.trim()) - .join(' ') - .trim(); + if (rest.length === 0) return; + + return [beginning, ...rest.map(globalifySelector)] + .map((str) => str.trim()) + .join(' ') + .trim(); + }); + + rule.replaceWith( + rule.clone({ + selectors: modifiedSelectors, + }), + ); }); }; -const transformer: Transformer = async ({ content, filename }) => { +// todo - this can be merged with the globalStyle +const transformer: Transformer = async ({ + content, + filename, + options, +}) => { const { css, map: newMap } = await postcss() .use(globalifyRulePlugin) - .process(content, { from: filename, map: false }); + .process(content, { + from: filename, + map: options?.sourceMap ?? false, + }); return { code: css, map: newMap }; }; diff --git a/src/transformers/globalStyle.ts b/src/transformers/globalStyle.ts index 547eff1a..e19215ed 100644 --- a/src/transformers/globalStyle.ts +++ b/src/transformers/globalStyle.ts @@ -1,28 +1,43 @@ -import postcss from 'postcss'; +import postcss, { AtRule } from 'postcss'; -import { Transformer } from '../types'; +import { Transformer, Options } from '../types'; import { globalifySelector } from '../modules/globalifySelector'; -const globalifyPlugin = (root: any) => { - root.walkAtRules(/keyframes$/, (atrule: any) => { +const globalifyPlugin = (root: postcss.Root) => { + root.walkAtRules(/keyframes$/, (atrule) => { if (!atrule.params.startsWith('-global-')) { - atrule.params = `-global-${atrule.params}`; + atrule.replaceWith( + atrule.clone({ + params: `-global-${atrule.params}`, + }), + ); } }); - root.walkRules((rule: any) => { - if (rule.parent && rule.parent.name === 'keyframes') { + root.walkRules((rule) => { + if ((rule?.parent as AtRule)?.name === 'keyframes') { return; } - rule.selectors = rule.selectors.map(globalifySelector); + rule.replaceWith( + rule.clone({ + selectors: rule.selectors.map(globalifySelector), + }), + ); }); }; -const transformer: Transformer = async ({ content, filename }) => { +const transformer: Transformer = async ({ + content, + filename, + options, +}) => { const { css, map: newMap } = await postcss() .use(globalifyPlugin) - .process(content, { from: filename, map: false }); + .process(content, { + from: filename, + map: options?.sourceMap ?? false, + }); return { code: css, map: newMap }; }; diff --git a/src/types/index.ts b/src/types/index.ts index 265441c2..501e4052 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -35,5 +35,5 @@ export type Transformer = ( export type TransformerOptions = | boolean - | Record + | Record | Transformer; diff --git a/src/types/options.ts b/src/types/options.ts index 17a98d98..7a822dd6 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -67,3 +67,11 @@ export interface Typescript { transpileOnly?: boolean; reportDiagnostics?: boolean; } + +export interface GlobalRule { + sourceMap: boolean; +} + +export interface GlobalStyle { + sourceMap: boolean; +} diff --git a/test/transformers/globalRule.test.ts b/test/transformers/globalRule.test.ts index df8d08d6..9b76a5e8 100644 --- a/test/transformers/globalRule.test.ts +++ b/test/transformers/globalRule.test.ts @@ -9,6 +9,18 @@ describe('transformer - globalRule', () => { expect(() => preprocess(template, opts)).not.toThrow(); }); + it('adds sourceMap with { sourceMap: true }', async () => { + const template = ``; + const opts = autoProcess({ + globalRule: { + sourceMap: true, + }, + }); + const preprocessed = await preprocess(template, opts); + + expect(preprocessed.toString()).toContain(`sourceMappingURL`); + }); + it('wraps selector in :global(...) modifier', async () => { const template = ``; const opts = autoProcess(); diff --git a/test/transformers/globalStyle.test.ts b/test/transformers/globalStyle.test.ts index 3e32caac..946d8794 100644 --- a/test/transformers/globalStyle.test.ts +++ b/test/transformers/globalStyle.test.ts @@ -2,6 +2,19 @@ import autoProcess from '../../src'; import { preprocess } from '../utils'; describe('transformer - globalStyle', () => { + // todo: why it isn't generating a sourcemap? + it.skip('adds sourceMap with { sourceMap: true }', async () => { + const template = ``; + const opts = autoProcess({ + globalStyle: { + sourceMap: true, + }, + }); + const preprocessed = await preprocess(template, opts); + + expect(preprocessed.toString()).toContain(`sourceMappingURL`); + }); + it('wraps selector in :global(...) modifier', async () => { const template = ``; const opts = autoProcess();