Skip to content

Commit fdb0e77

Browse files
authored
Merge pull request #3 from facebook/next
Update upstream #2
2 parents 032ceba + 03604a4 commit fdb0e77

File tree

19 files changed

+269
-53
lines changed

19 files changed

+269
-53
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
'use strict';
2+
3+
const { extname } = require('path');
4+
5+
function namedAssetImportPlugin({ types: t }) {
6+
const visited = new WeakSet();
7+
8+
return {
9+
visitor: {
10+
ImportDeclaration(path, { opts: { loaderMap } }) {
11+
const sourcePath = path.node.source.value;
12+
const ext = extname(sourcePath).substr(1);
13+
14+
if (visited.has(path.node) || sourcePath.indexOf('!') !== -1) {
15+
return;
16+
}
17+
18+
if (loaderMap[ext]) {
19+
path.replaceWithMultiple(
20+
path.node.specifiers.map(specifier => {
21+
if (t.isImportDefaultSpecifier(specifier)) {
22+
const newDefaultImport = t.importDeclaration(
23+
[
24+
t.importDefaultSpecifier(
25+
t.identifier(specifier.local.name)
26+
),
27+
],
28+
t.stringLiteral(sourcePath)
29+
);
30+
31+
visited.add(newDefaultImport);
32+
return newDefaultImport;
33+
}
34+
35+
const newImport = t.importDeclaration(
36+
[
37+
t.importSpecifier(
38+
t.identifier(specifier.local.name),
39+
t.identifier(specifier.imported.name)
40+
),
41+
],
42+
t.stringLiteral(
43+
loaderMap[ext][specifier.imported.name]
44+
? loaderMap[ext][specifier.imported.name].replace(
45+
/\[path\]/,
46+
sourcePath
47+
)
48+
: sourcePath
49+
)
50+
);
51+
52+
visited.add(newImport);
53+
return newImport;
54+
})
55+
);
56+
}
57+
},
58+
},
59+
};
60+
}
61+
62+
module.exports = namedAssetImportPlugin;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "babel-plugin-named-asset-import",
3+
"version": "0.1.0",
4+
"description": "Babel plugin for named asset imports in Create React App",
5+
"repository": "facebookincubator/create-react-app",
6+
"license": "MIT",
7+
"bugs": {
8+
"url": "https://github.com/facebookincubator/create-react-app/issues"
9+
},
10+
"main": "index.js",
11+
"files": [
12+
"index.js"
13+
],
14+
"peerDependencies": {
15+
"@babel/core": "7.0.0-beta.38"
16+
}
17+
}

packages/react-dev-utils/launchEditor.js

+7
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ const COMMON_EDITORS_OSX = {
5757
'/Applications/WebStorm.app/Contents/MacOS/webstorm':
5858
'/Applications/WebStorm.app/Contents/MacOS/webstorm',
5959
'/Applications/MacVim.app/Contents/MacOS/MacVim': 'mvim',
60+
'/Applications/GoLand.app/Contents/MacOS/goland':
61+
'/Applications/GoLand.app/Contents/MacOS/goland',
6062
};
6163

6264
const COMMON_EDITORS_LINUX = {
@@ -72,6 +74,7 @@ const COMMON_EDITORS_LINUX = {
7274
sublime_text: 'sublime_text',
7375
vim: 'vim',
7476
'webstorm.sh': 'webstorm',
77+
'goland.sh': 'goland',
7578
};
7679

7780
const COMMON_EDITORS_WIN = [
@@ -93,6 +96,8 @@ const COMMON_EDITORS_WIN = [
9396
'rubymine64.exe',
9497
'webstorm.exe',
9598
'webstorm64.exe',
99+
'goland.exe',
100+
'goland64.exe',
96101
];
97102

98103
function addWorkspaceToArgumentsIfExists(args, workspace) {
@@ -155,6 +160,8 @@ function getArgumentsForLineNumber(
155160
case 'rubymine64':
156161
case 'webstorm':
157162
case 'webstorm64':
163+
case 'goland':
164+
case 'goland64':
158165
return addWorkspaceToArgumentsIfExists(
159166
['--line', lineNumber, fileName],
160167
workspace
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// @remove-on-eject-begin
2+
/**
3+
* Copyright (c) 2018-present, Facebook, Inc.
4+
* Copyright (c) 2016 Remind
5+
*
6+
* This source code is licensed under the MIT license found in the
7+
* LICENSE file in the root directory of this source tree.
8+
*/
9+
// @remove-on-eject-end
10+
'use strict';
11+
12+
const loader = require('graphql-tag/loader');
13+
14+
module.exports = {
15+
process(src) {
16+
return loader.call({ cacheable() {} }, src);
17+
},
18+
};

packages/react-scripts/config/webpack.config.dev.js

+15-23
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,18 @@ module.exports = {
192192
babelrc: false,
193193
// @remove-on-eject-end
194194
presets: [require.resolve('babel-preset-react-app')],
195+
plugins: [
196+
[
197+
require.resolve('babel-plugin-named-asset-import'),
198+
{
199+
loaderMap: {
200+
svg: {
201+
ReactComponent: 'svgr/webpack![path]',
202+
},
203+
},
204+
},
205+
],
206+
],
195207
// This is a feature of `babel-loader` for webpack (not Babel itself).
196208
// It enables caching results in ./node_modules/.cache/babel-loader/
197209
// directory for faster rebuilds.
@@ -266,30 +278,10 @@ module.exports = {
266278
},
267279
],
268280
},
269-
// Allows you to use two kinds of imports for SVG:
270-
// import logoUrl from './logo.svg'; gives you the URL.
271-
// import { ReactComponent as Logo } from './logo.svg'; gives you a component.
281+
// The GraphQL loader preprocesses GraphQL queries in .graphql files.
272282
{
273-
test: /\.svg$/,
274-
use: [
275-
{
276-
loader: require.resolve('babel-loader'),
277-
options: {
278-
// @remove-on-eject-begin
279-
babelrc: false,
280-
// @remove-on-eject-end
281-
presets: [require.resolve('babel-preset-react-app')],
282-
cacheDirectory: true,
283-
},
284-
},
285-
require.resolve('svgr/webpack'),
286-
{
287-
loader: require.resolve('file-loader'),
288-
options: {
289-
name: 'static/media/[name].[hash:8].[ext]',
290-
},
291-
},
292-
],
283+
test: /\.(graphql)$/,
284+
loader: 'graphql-tag/loader',
293285
},
294286
// "file" loader makes sure those assets get served by WebpackDevServer.
295287
// When you `import` an asset, you get its (virtual) filename.

packages/react-scripts/config/webpack.config.prod.js

+15-23
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,18 @@ module.exports = {
200200
babelrc: false,
201201
// @remove-on-eject-end
202202
presets: [require.resolve('babel-preset-react-app')],
203+
plugins: [
204+
[
205+
require.resolve('babel-plugin-named-asset-import'),
206+
{
207+
loaderMap: {
208+
svg: {
209+
ReactComponent: 'svgr/webpack![path]',
210+
},
211+
},
212+
},
213+
],
214+
],
203215
compact: true,
204216
highlightCode: true,
205217
},
@@ -308,30 +320,10 @@ module.exports = {
308320
),
309321
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
310322
},
311-
// Allows you to use two kinds of imports for SVG:
312-
// import logoUrl from './logo.svg'; gives you the URL.
313-
// import { ReactComponent as Logo } from './logo.svg'; gives you a component.
323+
// The GraphQL loader preprocesses GraphQL queries in .graphql files.
314324
{
315-
test: /\.svg$/,
316-
use: [
317-
{
318-
loader: require.resolve('babel-loader'),
319-
options: {
320-
// @remove-on-eject-begin
321-
babelrc: false,
322-
// @remove-on-eject-end
323-
presets: [require.resolve('babel-preset-react-app')],
324-
cacheDirectory: true,
325-
},
326-
},
327-
require.resolve('svgr/webpack'),
328-
{
329-
loader: require.resolve('file-loader'),
330-
options: {
331-
name: 'static/media/[name].[hash:8].[ext]',
332-
},
333-
},
334-
],
325+
test: /\.(graphql)$/,
326+
loader: 'graphql-tag/loader',
335327
},
336328
// "file" loader makes sure assets end up in the `build` folder.
337329
// When you `import` an asset, you get its filename.

packages/react-scripts/fixtures/kitchensink/integration/webpack.test.js

+26
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ describe('Integration', () => {
3131
);
3232
});
3333

34+
it('graphql files inclusion', async () => {
35+
const doc = await initDOM('graphql-inclusion');
36+
const children = doc.getElementById('graphql-inclusion').children;
37+
38+
// .graphql
39+
expect(children[0].textContent.replace(/\s/g, '')).to.equal(
40+
'{"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","variableDefinitions":[],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"test"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"test"},"value":{"kind":"StringValue","value":"test","block":false}}],"directives":[],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"test"},"arguments":[],"directives":[]}]}}]}}],"loc":{"start":0,"end":40,"source":{"body":"{\\ntest(test:\\"test\\"){\\ntest\\n}\\n}\\n","name":"GraphQLrequest","locationOffset":{"line":1,"column":1}}}}'
41+
);
42+
});
43+
3444
it('image inclusion', async () => {
3545
const doc = await initDOM('image-inclusion');
3646

@@ -71,6 +81,22 @@ describe('Integration', () => {
7181
);
7282
});
7383

84+
it('svg component', async () => {
85+
const doc = await initDOM('svg-component');
86+
87+
expect(doc.getElementById('feature-svg-component').textContent).to.equal(
88+
''
89+
);
90+
});
91+
92+
it('svg in css', async () => {
93+
const doc = await initDOM('svg-in-css');
94+
95+
expect(
96+
doc.getElementsByTagName('style')[0].textContent.replace(/\s/g, '')
97+
).to.match(/\/static\/media\/logo\..+\.svg/);
98+
});
99+
74100
it('unknown ext inclusion', async () => {
75101
const doc = await initDOM('unknown-ext-inclusion');
76102

packages/react-scripts/fixtures/kitchensink/src/App.js

+18-3
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,9 @@ class App extends Component {
8282
);
8383
break;
8484
case 'css-modules-inclusion':
85-
import(
86-
'./features/webpack/CssModulesInclusion'
87-
).then(f => this.setFeature(f.default));
85+
import('./features/webpack/CssModulesInclusion').then(f =>
86+
this.setFeature(f.default)
87+
);
8888
break;
8989
case 'custom-interpolation':
9090
import('./features/syntax/CustomInterpolation').then(f =>
@@ -111,6 +111,11 @@ class App extends Component {
111111
this.setFeature(f.default)
112112
);
113113
break;
114+
case 'graphql-inclusion':
115+
import('./features/webpack/GraphQLInclusion').then(f =>
116+
this.setFeature(f.default)
117+
);
118+
break;
114119
case 'image-inclusion':
115120
import('./features/webpack/ImageInclusion').then(f =>
116121
this.setFeature(f.default)
@@ -174,6 +179,16 @@ class App extends Component {
174179
this.setFeature(f.default)
175180
);
176181
break;
182+
case 'svg-component':
183+
import('./features/webpack/SvgComponent').then(f =>
184+
this.setFeature(f.default)
185+
);
186+
break;
187+
case 'svg-in-css':
188+
import('./features/webpack/SvgInCss').then(f =>
189+
this.setFeature(f.default)
190+
);
191+
break;
177192
case 'template-interpolation':
178193
import('./features/syntax/TemplateInterpolation').then(f =>
179194
this.setFeature(f.default)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* Copyright (c) 2018-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import React from 'react';
9+
import A from './assets/graphql.graphql';
10+
11+
export default () => (
12+
<p id="graphql-inclusion">
13+
<span>{JSON.stringify(A)}</span>
14+
</p>
15+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright (c) 2018-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import React from 'react';
9+
import ReactDOM from 'react-dom';
10+
import GraphQLInclusion from './GraphQLInclusion';
11+
12+
describe('graphql files inclusion', () => {
13+
it('renders without crashing', () => {
14+
const div = document.createElement('div');
15+
ReactDOM.render(<GraphQLInclusion />, div);
16+
});
17+
});

packages/react-scripts/fixtures/kitchensink/src/features/webpack/SvgComponent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
import React from 'react';
99
import { ReactComponent as Logo } from './assets/logo.svg';
1010

11-
export default () => <Logo />;
11+
export default () => <Logo id="feature-svg-component" />;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import React from 'react';
2+
import './assets/svg.css';
3+
4+
export default () => <div id="feature-svg-in-css" />;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
import SvgInCss from './SvgInCss';
4+
5+
describe('svg in css', () => {
6+
it('renders without crashing', () => {
7+
const div = document.createElement('div');
8+
ReactDOM.render(<SvgInCss />, div);
9+
});
10+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
test(test: "test") {
3+
test
4+
}
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#feature-svg-in-css {
2+
background-image: url("./logo.svg");
3+
}

0 commit comments

Comments
 (0)