Skip to content

Commit

Permalink
fix(postcss-syntax): throw error when parsing TS (#553)
Browse files Browse the repository at this point in the history
* add presets/plugins to transform

* Change files

* transform source

* lint
  • Loading branch information
YuanboXue-Amber committed May 10, 2024
1 parent 2cb5dd0 commit 1767ae3
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 23 deletions.
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "fix: use plugins/presets from options.babelOptions to transform source.",
"packageName": "@griffel/postcss-syntax",
"email": "yuanboxue@microsoft.com",
"dependentChangeType": "patch"
}
6 changes: 3 additions & 3 deletions packages/postcss-syntax/src/parse.ts
Expand Up @@ -11,15 +11,15 @@ import type { BabelPluginOptions } from '@griffel/babel-preset';

export type PostCSSParserOptions = Pick<postcss.ProcessOptions<postcss.Document | postcss.Root>, 'from' | 'map'>;

export interface ParserOptions extends PostCSSParserOptions, BabelPluginOptions {}
export interface ParserOptions extends Pick<PostCSSParserOptions, 'from'>, BabelPluginOptions {}

/**
* Generates CSS rules from a JavaScript file. Each slot in `makeStyles` and each `makeResetStyles` will be one line in the output.
* It returns a PostCSS AST that parses the generated CSS rules. For each node in AST, attaches information about its related slot location from the original js file.
*/
export const parse = (css: string | { toString(): string }, opts?: ParserOptions) => {
const { from: filename = 'postcss-syntax.styles.ts' } = opts ?? {};
const griffelPluginOptions = extractGrifellBabelPluginOptions(opts);
const griffelPluginOptions = extractGriffelBabelPluginOptions(opts);
const code = css.toString();
const { metadata } = transformSync(code, {
filename,
Expand Down Expand Up @@ -65,7 +65,7 @@ export const parse = (css: string | { toString(): string }, opts?: ParserOptions
return root;
};

const extractGrifellBabelPluginOptions = (opts: ParserOptions = {}) => {
const extractGriffelBabelPluginOptions = (opts: ParserOptions = {}) => {
const { babelOptions, evaluationRules, generateMetadata, modules } = opts;
const babelPluginOptions: BabelPluginOptions = {};
if (babelOptions) {
Expand Down
65 changes: 65 additions & 0 deletions packages/postcss-syntax/src/transform-sync.test.ts
@@ -0,0 +1,65 @@
import transformSync, { type TransformOptions } from './transform-sync';

describe('transformSync', () => {
it('should parse TS and return metadata that contains css location', () => {
const sourceCode = `
import type { GriffelStyle } from '@griffel/react'
import { makeStyles } from '@griffel/react';
const mixin = (): GriffelStyle => ({
marginTop: '4px',
})
export const useStyles = makeStyles({
root: {
color: 'red',
backgroundColor: 'green',
...mixin()
}
})
`;
const options: TransformOptions = {
filename: 'test.styles.ts',
pluginOptions: {
babelOptions: {
presets: ['@babel/preset-typescript'],
},
generateMetadata: true,
},
};

const result = transformSync(sourceCode, options);

expect(result.metadata.cssEntries).toMatchInlineSnapshot(`
Object {
"useStyles": Object {
"root": Array [
".fe3e8s9{color:red;}",
".fcnqdeg{background-color:green;}",
".fvjh0tl{margin-top:4px;}",
],
},
}
`);
expect(result.metadata.locations).toMatchInlineSnapshot(`
Object {
"useStyles": Object {
"root": Object {
"end": Position {
"column": 7,
"index": 317,
"line": 14,
},
"filename": undefined,
"identifierName": undefined,
"start": Position {
"column": 6,
"index": 227,
"line": 10,
},
},
},
}
`);
});
});
24 changes: 4 additions & 20 deletions packages/postcss-syntax/src/transform-sync.ts
Expand Up @@ -13,29 +13,13 @@ export type TransformOptions = {
* Transforms passed source code with Babel, uses user's config for parsing, but ignores it for transforms.
*/
export default function transformSync(sourceCode: string, options: TransformOptions) {
// Parse the code first so Babel will use user's babel config for parsing
// During transforms we don't want to use user's config
const babelAST = Babel.parseSync(sourceCode, {
caller: { name: 'griffel' },
filename: options.filename,
sourceMaps: true,
// TODO - we might need to add some babel config in the eslint rule options
// if the user doesn't want to use their normal babel config for this
// but let's only add it if it becomes necessary
});

if (babelAST === null) {
throw new Error(`Failed to create AST for "${options.filename}" due unknown Babel error...`);
}

const babelFileResult = Babel.transformFromAstSync(babelAST, sourceCode, {
const { plugins, presets } = options.pluginOptions.babelOptions ?? { plugins: [], presets: [] };
const babelFileResult = Babel.transformSync(sourceCode, {
// Ignore all user's configs and apply only our plugin
babelrc: false,
configFile: false,
presets: [
[griffelPreset, options.pluginOptions],
[locationPreset, options.pluginOptions],
],
plugins,
presets: [...(presets ?? []), [griffelPreset, options.pluginOptions], [locationPreset, options.pluginOptions]],

filename: options.filename,
sourceFileName: options.filename,
Expand Down

0 comments on commit 1767ae3

Please sign in to comment.