Skip to content

Commit

Permalink
feat: 🎸 add globalStyle.sourceMap and globalRule.sourceMap opts
Browse files Browse the repository at this point in the history
  • Loading branch information
kaisermann committed Jun 6, 2020
1 parent 12c3af3 commit 2717c5b
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 36 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
36 changes: 22 additions & 14 deletions src/autoProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ interface Transformers {
postcss?: TransformerOptions<Options.Postcss>;
coffeescript?: TransformerOptions<Options.Coffeescript>;
pug?: TransformerOptions<Options.Pug>;
globalStyle?: TransformerOptions;
globalRule?: TransformerOptions;
globalStyle?: Options.GlobalStyle;
globalRule?: Options.GlobalRule;
replace?: Options.Replace;
[languageName: string]: TransformerOptions;
}
Expand Down Expand Up @@ -53,8 +53,8 @@ type AutoPreprocessOptions = {
babel?: TransformerOptions<Options.Babel>;
coffeescript?: TransformerOptions<Options.Coffeescript>;
pug?: TransformerOptions<Options.Pug>;
globalStyle?: TransformerOptions<Options.Typescript>;
globalRule?: TransformerOptions<Options.Typescript>;
globalStyle?: Options.GlobalStyle;
globalRule?: Options.GlobalRule;
// workaround while we don't have this
// https://github.com/microsoft/TypeScript/issues/17867
[languageName: string]:
Expand Down Expand Up @@ -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;
Expand Down
38 changes: 28 additions & 10 deletions src/transformers/globalRule.ts
Original file line number Diff line number Diff line change
@@ -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<never> = async ({ content, filename }) => {
// todo - this can be merged with the globalStyle
const transformer: Transformer<Options.GlobalRule> = 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 };
};
Expand Down
35 changes: 25 additions & 10 deletions src/transformers/globalStyle.ts
Original file line number Diff line number Diff line change
@@ -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<never> = async ({ content, filename }) => {
const transformer: Transformer<Options.GlobalStyle> = 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 };
};
Expand Down
2 changes: 1 addition & 1 deletion src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ export type Transformer<T> = (

export type TransformerOptions<T = any> =
| boolean
| Record<string, any>
| Record<keyof T | string, T[keyof T] | any>
| Transformer<T>;
8 changes: 8 additions & 0 deletions src/types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,11 @@ export interface Typescript {
transpileOnly?: boolean;
reportDiagnostics?: boolean;
}

export interface GlobalRule {
sourceMap: boolean;
}

export interface GlobalStyle {
sourceMap: boolean;
}
12 changes: 12 additions & 0 deletions test/transformers/globalRule.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ describe('transformer - globalRule', () => {
expect(() => preprocess(template, opts)).not.toThrow();
});

it('adds sourceMap with { sourceMap: true }', async () => {
const template = `<style>:global div{color:red}:global .test{}</style>`;
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 = `<style>:global div{color:red}:global .test{}</style>`;
const opts = autoProcess();
Expand Down
13 changes: 13 additions & 0 deletions test/transformers/globalStyle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = `<style global>div,span{color:red}.test{}</style>`;
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 = `<style global>div{color:red}.test{}</style>`;
const opts = autoProcess();
Expand Down

0 comments on commit 2717c5b

Please sign in to comment.