Skip to content

Commit 97cd2e4

Browse files
committed
feat: Use Babel 7 for JSX parsing to better enable tyed languages.
1 parent 84a797a commit 97cd2e4

File tree

7 files changed

+172
-77
lines changed

7 files changed

+172
-77
lines changed

packages/@css-blocks/jsx/package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@
5656
"@css-blocks/core": "^0.18.0",
5757
"@opticss/template-api": "^0.3.0",
5858
"@opticss/util": "^0.3.0",
59-
"babel-traverse": "^6.24.1",
60-
"babel-types": "^6.24.1",
61-
"babylon": "^6.17.4",
59+
"babel-traverse": "7.0.0-beta.3",
60+
"babel-types": "7.0.0-beta.3",
61+
"babylon": "7.0.0-beta.46",
6262
"debug": "^2.6.8",
6363
"minimatch": "^3.0.4",
6464
"object.values": "^1.0.4",
6565
"opticss": "^0.3.0"
6666
}
67-
}
67+
}

packages/@css-blocks/jsx/src/Analyzer/index.ts

-16
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import * as babylon from "babylon";
1010
import * as debugGenerator from "debug";
1111
import * as fs from "fs";
1212
import * as path from "path";
13-
import * as typescript from "typescript";
1413

1514
import { CssBlocksJSXOptions } from "../options";
1615
import { JSXParseError } from "../utils/Errors";
@@ -86,21 +85,6 @@ export class CSSBlocksJSXAnalyzer extends Analyzer<TEMPLATE_TYPE> {
8685

8786
// Parse the file into an AST.
8887
try {
89-
90-
// Babylon currently has...abysmal support for typescript. We need to transpile
91-
// it with the standard typescript library first.
92-
// TODO: When Typescript support lands in Babylon, remove this: https://github.com/babel/babylon/issues/320
93-
if (path.parse(template.identifier).ext === ".tsx") {
94-
let wat = typescript.transpileModule(template.data, {
95-
compilerOptions: {
96-
module: typescript.ModuleKind.ES2015,
97-
jsx: typescript.JsxEmit.Preserve,
98-
target: typescript.ScriptTarget.Latest,
99-
},
100-
});
101-
template.data = wat.outputText;
102-
}
103-
10488
analysis.template.ast = some(babylon.parse(template.data, this.options.parserOptions));
10589
} catch (e) {
10690
process.chdir(oldDir);
+49-19
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,64 @@
11
import { ResolvedConfiguration, resolveConfiguration } from "@css-blocks/core";
22
import { ObjectDictionary } from "@opticss/util";
33

4-
/**
5-
* Default parser options.
6-
*/
7-
const DEFAULT_PARSER_OPTS: object = {
8-
sourceType: "module",
9-
plugins: [
10-
"jsx",
11-
"flow",
12-
"decorators",
13-
"classProperties",
14-
"exportExtensions",
15-
"asyncGenerators",
16-
"functionBind",
17-
"functionSent",
18-
"dynamicImport",
19-
],
20-
};
4+
import { BabylonOptions, PluginName } from "babylon";
5+
6+
// We are only using the output Babylon AST to collect analysis data here,
7+
// so, we can safely enable EVERY feature possible without worrying about
8+
// which the consumer actually uses, or if the features needs a runtime.
9+
// TODO: Remove this tslint disable when types for Babylon 7 are published.
10+
// tslint:disable-next-line:prefer-whatever-to-any
11+
const BABEL_PLUGINS: any = [
12+
"jsx",
13+
"doExpressions",
14+
"objectRestSpread",
15+
"decorators",
16+
"classProperties",
17+
"classPrivateProperties",
18+
"classPrivateMethods",
19+
"exportDefaultFrom",
20+
"exportNamespaceFrom",
21+
"asyncGenerators",
22+
"functionBind",
23+
"functionSent",
24+
"dynamicImport",
25+
"numericSeparator",
26+
"optionalChaining",
27+
"importMeta",
28+
"bigInt",
29+
"optionalCatchBinding",
30+
"throwExpressions",
31+
"pipelineOperator",
32+
"nullishCoalescingOperator",
33+
];
2134

2235
export class CssBlocksJSXOptions {
2336
public baseDir: string;
24-
public parserOptions: object;
37+
public types: "typescript" | "flow" | "none";
2538
public aliases: ObjectDictionary<string>;
2639
public compilationOptions: ResolvedConfiguration;
40+
public parserOptions: BabylonOptions;
2741

2842
constructor(opts: Partial<CssBlocksJSXOptions>) {
2943
this.baseDir = opts.baseDir || ".";
30-
this.parserOptions = opts.parserOptions || DEFAULT_PARSER_OPTS;
44+
this.types = opts.types || "none";
3145
this.aliases = opts.aliases || {};
3246
this.compilationOptions = resolveConfiguration(opts.compilationOptions);
47+
this.parserOptions = {
48+
sourceType: "module",
49+
allowImportExportEverywhere: true,
50+
allowReturnOutsideFunction: true,
51+
allowSuperOutsideMethod: true,
52+
plugins: BABEL_PLUGINS.slice(0),
53+
};
54+
55+
if (this.types === "typescript") {
56+
this.parserOptions.plugins!.push("typescript" as PluginName);
57+
}
58+
59+
else if (this.types === "flow") {
60+
this.parserOptions.plugins!.push("flow" as PluginName);
61+
this.parserOptions.plugins!.push("flowComments" as PluginName);
62+
}
3363
}
3464
}

packages/@css-blocks/jsx/test/multi-file-discover/multi-file-test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export class Test {
3030

3131
@test "finds dependents of dependents"() {
3232
let base = path.resolve(__dirname, "../../../test/fixtures/deep-multifile");
33-
return parseFile("index.tsx", { baseDir: base }).then((analyzer: Analyzer) => {
33+
return parseFile("index.tsx", { baseDir: base, types: "typescript" }).then((analyzer: Analyzer) => {
3434
assert.equal(analyzer.analysisCount(), 3);
3535
assert.equal(analyzer.blockPromises.size, 3);
3636
assert.equal(analyzer.styleCount(), 4);

packages/@css-blocks/website/config/webpack.config.dev.js

+19-16
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ const paths = require('./paths');
1313

1414
const jsxCompilationOptions = {
1515
compilationOptions: {},
16+
types: "typescript",
17+
aliases: {},
1618
optimization: {
1719
rewriteIdents: true,
1820
mergeDeclarations: true,
1921
removeUnusedStyles: true,
2022
conflictResolution: true,
2123
enabled: false,
2224
},
23-
aliases: {}
2425
};
2526

2627
const CssBlocks = require("@css-blocks/jsx");
@@ -100,7 +101,7 @@ module.exports = {
100101
// for React Native Web.
101102
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx', '.ts', '.tsx'],
102103
alias: {
103-
104+
104105
// Support React Native Web
105106
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
106107
'react-native': 'react-native-web',
@@ -126,16 +127,14 @@ module.exports = {
126127
{
127128
test: /\.(js|jsx|mjs)$/,
128129
enforce: 'pre',
129-
use: [
130-
{
131-
options: {
132-
formatter: eslintFormatter,
133-
eslintPath: require.resolve('eslint'),
134-
135-
},
136-
loader: require.resolve('eslint-loader'),
130+
use: [{
131+
options: {
132+
formatter: eslintFormatter,
133+
eslintPath: require.resolve('eslint'),
134+
137135
},
138-
],
136+
loader: require.resolve('eslint-loader'),
137+
}, ],
139138
include: paths.appSrc,
140139
},
141140
{
@@ -214,7 +213,13 @@ module.exports = {
214213
cacheDirectory: true,
215214
compact: true,
216215
parserOpts: {
217-
plugins: [ "jsx" ]
216+
plugins: [
217+
"jsx",
218+
"doExpressions",
219+
"objectRestSpread",
220+
"decorators",
221+
"classProperties",
222+
]
218223
}
219224
}
220225
},
@@ -233,8 +238,6 @@ module.exports = {
233238
rewriter: CssBlockRewriter
234239
}
235240
},
236-
237-
238241
]
239242
},
240243

@@ -270,7 +273,7 @@ module.exports = {
270273
optimization: jsxCompilationOptions.optimization
271274
}),
272275

273-
cssAssets({minify: false, inlineSourceMaps: true}),
276+
cssAssets({ minify: false, inlineSourceMaps: true }),
274277

275278
// Makes some environment variables available in index.html.
276279
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
@@ -320,4 +323,4 @@ module.exports = {
320323
performance: {
321324
hints: false,
322325
},
323-
};
326+
};

packages/@css-blocks/website/config/webpack.config.prod.js

+23-19
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const CssBlocksPlugin = require("@css-blocks/webpack").CssBlocksPlugin;
1717

1818
const jsxCompilationOptions = {
1919
compilationOptions: {},
20+
types: "typescript",
2021
optimization: {
2122
rewriteIdents: true,
2223
mergeDeclarations: true,
@@ -57,10 +58,9 @@ const cssFilename = 'static/css/[name].[contenthash:8].css';
5758
// (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
5859
// However, our output is structured with css, js and media folders.
5960
// To have this structure working with relative paths, we have to use custom options.
60-
const extractTextPluginOptions = shouldUseRelativeAssetPaths
61-
? // Making sure that the publicPath goes back to to build folder.
62-
{ publicPath: Array(cssFilename.split('/').length).join('../') }
63-
: {};
61+
const extractTextPluginOptions = shouldUseRelativeAssetPaths ? // Making sure that the publicPath goes back to to build folder.
62+
{ publicPath: Array(cssFilename.split('/').length).join('../') } :
63+
{};
6464

6565
// This is the production configuration.
6666
// It compiles slowly and is focused on producing a fast and minimal bundle.
@@ -86,8 +86,8 @@ module.exports = {
8686
// Point sourcemap entries to original disk location (format as URL on Windows)
8787
devtoolModuleFilenameTemplate: info =>
8888
path
89-
.relative(paths.appSrc, info.absoluteResourcePath)
90-
.replace(/\\/g, '/'),
89+
.relative(paths.appSrc, info.absoluteResourcePath)
90+
.replace(/\\/g, '/'),
9191
},
9292
resolve: {
9393
// This allows you to set a fallback for where Webpack should look for modules.
@@ -106,7 +106,7 @@ module.exports = {
106106
// for React Native Web.
107107
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx', '.tsx', '.ts'],
108108
alias: {
109-
109+
110110
// Support React Native Web
111111
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
112112
'react-native': 'react-native-web',
@@ -132,16 +132,14 @@ module.exports = {
132132
{
133133
test: /\.(js|jsx|mjs)$/,
134134
enforce: 'pre',
135-
use: [
136-
{
137-
options: {
138-
formatter: eslintFormatter,
139-
eslintPath: require.resolve('eslint'),
140-
141-
},
142-
loader: require.resolve('eslint-loader'),
135+
use: [{
136+
options: {
137+
formatter: eslintFormatter,
138+
eslintPath: require.resolve('eslint'),
139+
143140
},
144-
],
141+
loader: require.resolve('eslint-loader'),
142+
}, ],
145143
include: paths.appSrc,
146144
},
147145

@@ -236,7 +234,13 @@ module.exports = {
236234
cacheDirectory: false,
237235
compact: true,
238236
parserOpts: {
239-
plugins: [ "jsx" ]
237+
plugins: [
238+
"jsx",
239+
"doExpressions",
240+
"objectRestSpread",
241+
"decorators",
242+
"classProperties",
243+
]
240244
}
241245
},
242246
},
@@ -291,7 +295,7 @@ module.exports = {
291295
optimization: jsxCompilationOptions.optimization
292296
}),
293297

294-
cssAssets({minify: true, inlineSourceMaps: false}),
298+
cssAssets({ minify: true, inlineSourceMaps: false }),
295299

296300
// Makes some environment variables available in index.html.
297301
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
@@ -398,4 +402,4 @@ module.exports = {
398402
tls: 'empty',
399403
child_process: 'empty',
400404
},
401-
};
405+
};

0 commit comments

Comments
 (0)