@parcel/transformer-postcss 2.0.0-beta.3.1 → 2.0.0-nightly.1002
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/PostCSSTransformer.js +103 -69
- package/lib/constants.js +8 -0
- package/lib/loadConfig.js +15 -29
- package/package.json +9 -10
- package/src/PostCSSTransformer.js +94 -40
- package/src/constants.js +3 -0
- package/src/loadConfig.js +29 -22
|
@@ -5,30 +5,30 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
-
function
|
|
9
|
-
const data = require("@parcel/
|
|
8
|
+
function _hash() {
|
|
9
|
+
const data = require("@parcel/hash");
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
_hash = function () {
|
|
12
12
|
return data;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
return data;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
function
|
|
19
|
-
const data = require("@parcel/
|
|
18
|
+
function _utils() {
|
|
19
|
+
const data = require("@parcel/utils");
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
_utils = function () {
|
|
22
22
|
return data;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
return data;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
function
|
|
29
|
-
const data =
|
|
28
|
+
function _plugin() {
|
|
29
|
+
const data = require("@parcel/plugin");
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
_plugin = function () {
|
|
32
32
|
return data;
|
|
33
33
|
};
|
|
34
34
|
|
|
@@ -75,30 +75,16 @@ function _postcssValueParser() {
|
|
|
75
75
|
return data;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
const data = _interopRequireDefault(require("postcss-modules"));
|
|
78
|
+
var _loadConfig = require("./loadConfig");
|
|
80
79
|
|
|
81
|
-
|
|
82
|
-
return data;
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
return data;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function _loadConfig() {
|
|
89
|
-
const data = require("./loadConfig");
|
|
90
|
-
|
|
91
|
-
_loadConfig = function () {
|
|
92
|
-
return data;
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
return data;
|
|
96
|
-
}
|
|
80
|
+
var _constants = require("./constants");
|
|
97
81
|
|
|
98
82
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
99
83
|
|
|
100
84
|
const COMPOSES_RE = /composes:.+from\s*("|').*("|')\s*;?/;
|
|
101
85
|
const FROM_IMPORT_RE = /.+from\s*(?:"|')(.*)(?:"|')\s*;?/;
|
|
86
|
+
const LEGACY_MODULE_RE = /@value|(:global|:local)(?!\s*\()/i;
|
|
87
|
+
const MODULE_BY_NAME_RE = /\.module\./;
|
|
102
88
|
|
|
103
89
|
var _default = new (_plugin().Transformer)({
|
|
104
90
|
loadConfig({
|
|
@@ -106,7 +92,7 @@ var _default = new (_plugin().Transformer)({
|
|
|
106
92
|
options,
|
|
107
93
|
logger
|
|
108
94
|
}) {
|
|
109
|
-
return (0, _loadConfig
|
|
95
|
+
return (0, _loadConfig.load)({
|
|
110
96
|
config,
|
|
111
97
|
options,
|
|
112
98
|
logger
|
|
@@ -116,7 +102,7 @@ var _default = new (_plugin().Transformer)({
|
|
|
116
102
|
canReuseAST({
|
|
117
103
|
ast
|
|
118
104
|
}) {
|
|
119
|
-
return ast.type === 'postcss' && _semver().default.satisfies(ast.version,
|
|
105
|
+
return ast.type === 'postcss' && _semver().default.satisfies(ast.version, _constants.POSTCSS_RANGE);
|
|
120
106
|
},
|
|
121
107
|
|
|
122
108
|
async parse({
|
|
@@ -124,7 +110,9 @@ var _default = new (_plugin().Transformer)({
|
|
|
124
110
|
config,
|
|
125
111
|
options
|
|
126
112
|
}) {
|
|
127
|
-
|
|
113
|
+
let isLegacy = await isLegacyCssModule(asset);
|
|
114
|
+
|
|
115
|
+
if (!config && !isLegacy) {
|
|
128
116
|
return;
|
|
129
117
|
}
|
|
130
118
|
|
|
@@ -145,51 +133,70 @@ var _default = new (_plugin().Transformer)({
|
|
|
145
133
|
resolve
|
|
146
134
|
}) {
|
|
147
135
|
asset.type = 'css';
|
|
136
|
+
let isLegacy = await isLegacyCssModule(asset);
|
|
137
|
+
|
|
138
|
+
if (isLegacy && !config) {
|
|
139
|
+
config = {
|
|
140
|
+
hydrated: {
|
|
141
|
+
plugins: [],
|
|
142
|
+
from: asset.filePath,
|
|
143
|
+
to: asset.filePath,
|
|
144
|
+
modules: {}
|
|
145
|
+
}
|
|
146
|
+
}; // TODO: warning?
|
|
147
|
+
}
|
|
148
148
|
|
|
149
149
|
if (!config) {
|
|
150
150
|
return [asset];
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
const postcss = await loadPostcss(options, asset.filePath);
|
|
154
|
+
let ast = (0, _nullthrows().default)(await asset.getAST());
|
|
155
|
+
let program = postcss.fromJSON(ast.program);
|
|
154
156
|
let plugins = [...config.hydrated.plugins];
|
|
155
157
|
let cssModules = null;
|
|
156
158
|
|
|
157
159
|
if (config.hydrated.modules) {
|
|
158
|
-
|
|
160
|
+
asset.meta.cssModulesCompiled = true; // TODO: should this be resolved from the project root?
|
|
161
|
+
|
|
162
|
+
let postcssModules = await options.packageManager.require('postcss-modules', asset.filePath, {
|
|
163
|
+
range: '^4.3.0',
|
|
164
|
+
saveDev: true,
|
|
165
|
+
shouldAutoInstall: options.shouldAutoInstall
|
|
166
|
+
});
|
|
167
|
+
plugins.push(postcssModules({
|
|
159
168
|
getJSON: (filename, json) => cssModules = json,
|
|
160
|
-
Loader: createLoader(asset, resolve),
|
|
161
|
-
generateScopedName: (name, filename) =>
|
|
169
|
+
Loader: await createLoader(asset, resolve, options),
|
|
170
|
+
generateScopedName: (name, filename) => `${name}_${(0, _hash().hashString)(_path().default.relative(options.projectRoot, filename)).substr(0, 6)}`,
|
|
162
171
|
...config.hydrated.modules
|
|
163
172
|
}));
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
line: decl.source.start.line,
|
|
185
|
-
column: decl.source.start.column + importPath.length
|
|
173
|
+
let code = asset.isASTDirty() ? null : await asset.getCode();
|
|
174
|
+
|
|
175
|
+
if (code == null || COMPOSES_RE.test(code)) {
|
|
176
|
+
program.walkDecls(decl => {
|
|
177
|
+
let [, importPath] = FROM_IMPORT_RE.exec(decl.value) || [];
|
|
178
|
+
|
|
179
|
+
if (decl.prop === 'composes' && importPath != null) {
|
|
180
|
+
let parsed = (0, _postcssValueParser().default)(decl.value);
|
|
181
|
+
parsed.walk(node => {
|
|
182
|
+
if (node.type === 'string') {
|
|
183
|
+
asset.addDependency({
|
|
184
|
+
specifier: importPath,
|
|
185
|
+
specifierType: 'url',
|
|
186
|
+
loc: {
|
|
187
|
+
filePath: asset.filePath,
|
|
188
|
+
start: decl.source.start,
|
|
189
|
+
end: {
|
|
190
|
+
line: decl.source.start.line,
|
|
191
|
+
column: decl.source.start.column + importPath.length
|
|
192
|
+
}
|
|
186
193
|
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
193
200
|
} // $FlowFixMe Added in Flow 0.121.0 upgrade in #4381
|
|
194
201
|
|
|
195
202
|
|
|
@@ -205,7 +212,22 @@ var _default = new (_plugin().Transformer)({
|
|
|
205
212
|
|
|
206
213
|
for (let msg of messages) {
|
|
207
214
|
if (msg.type === 'dependency') {
|
|
208
|
-
asset.
|
|
215
|
+
asset.invalidateOnFileChange(msg.file);
|
|
216
|
+
} else if (msg.type === 'dir-dependency') {
|
|
217
|
+
var _msg$glob;
|
|
218
|
+
|
|
219
|
+
let pattern = `${msg.dir}/${(_msg$glob = msg.glob) !== null && _msg$glob !== void 0 ? _msg$glob : '**/*'}`;
|
|
220
|
+
let files = await (0, _utils().glob)(pattern, asset.fs, {
|
|
221
|
+
onlyFiles: true
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
for (let file of files) {
|
|
225
|
+
asset.invalidateOnFileChange(_path().default.normalize(file));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
asset.invalidateOnFileCreate({
|
|
229
|
+
glob: pattern
|
|
230
|
+
});
|
|
209
231
|
}
|
|
210
232
|
}
|
|
211
233
|
|
|
@@ -214,12 +236,12 @@ var _default = new (_plugin().Transformer)({
|
|
|
214
236
|
if (cssModules) {
|
|
215
237
|
// $FlowFixMe
|
|
216
238
|
let cssModulesList = Object.entries(cssModules);
|
|
217
|
-
let deps = asset.getDependencies().filter(dep =>
|
|
239
|
+
let deps = asset.getDependencies().filter(dep => dep.priority === 'sync');
|
|
218
240
|
let code;
|
|
219
241
|
|
|
220
242
|
if (deps.length > 0) {
|
|
221
243
|
code = `
|
|
222
|
-
module.exports = Object.assign({}, ${deps.map(dep => `require(${JSON.stringify(dep.
|
|
244
|
+
module.exports = Object.assign({}, ${deps.map(dep => `require(${JSON.stringify(dep.specifier)})`).join(', ')}, ${JSON.stringify(cssModules, null, 2)});
|
|
223
245
|
`;
|
|
224
246
|
} else {
|
|
225
247
|
code = cssModulesList.map( // This syntax enables shaking the invidual statements, so that unused classes don't even exist in JS.
|
|
@@ -235,7 +257,6 @@ var _default = new (_plugin().Transformer)({
|
|
|
235
257
|
asset.symbols.set('default', 'default');
|
|
236
258
|
assets.push({
|
|
237
259
|
type: 'js',
|
|
238
|
-
filePath: asset.filePath + '.js',
|
|
239
260
|
content: code
|
|
240
261
|
});
|
|
241
262
|
}
|
|
@@ -262,8 +283,11 @@ var _default = new (_plugin().Transformer)({
|
|
|
262
283
|
|
|
263
284
|
exports.default = _default;
|
|
264
285
|
|
|
265
|
-
function createLoader(asset, resolve) {
|
|
266
|
-
|
|
286
|
+
async function createLoader(asset, resolve, options) {
|
|
287
|
+
let {
|
|
288
|
+
default: FileSystemLoader
|
|
289
|
+
} = await options.packageManager.require('postcss-modules/build/css-loader-core/loader', asset.filePath);
|
|
290
|
+
return class extends FileSystemLoader {
|
|
267
291
|
async fetch(composesPath, relativeTo) {
|
|
268
292
|
let importPath = composesPath.replace(/^["']|["']$/g, '');
|
|
269
293
|
let resolved = await resolve(relativeTo, importPath);
|
|
@@ -281,7 +305,8 @@ function createLoader(asset, resolve) {
|
|
|
281
305
|
let source = await asset.fs.readFile(resolved, 'utf-8');
|
|
282
306
|
let {
|
|
283
307
|
exportTokens
|
|
284
|
-
} = await this.core.load(source, rootRelativePath, undefined,
|
|
308
|
+
} = await this.core.load(source, rootRelativePath, undefined, // $FlowFixMe[method-unbinding]
|
|
309
|
+
this.fetch.bind(this));
|
|
285
310
|
return exportTokens;
|
|
286
311
|
}
|
|
287
312
|
|
|
@@ -294,8 +319,17 @@ function createLoader(asset, resolve) {
|
|
|
294
319
|
|
|
295
320
|
function loadPostcss(options, from) {
|
|
296
321
|
return options.packageManager.require('postcss', from, {
|
|
297
|
-
range:
|
|
322
|
+
range: _constants.POSTCSS_RANGE,
|
|
298
323
|
saveDev: true,
|
|
299
324
|
shouldAutoInstall: options.shouldAutoInstall
|
|
300
325
|
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async function isLegacyCssModule(asset) {
|
|
329
|
+
if (!MODULE_BY_NAME_RE.test(asset.filePath)) {
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
let code = await asset.getCode();
|
|
334
|
+
return LEGACY_MODULE_RE.test(code);
|
|
301
335
|
}
|
package/lib/constants.js
ADDED
package/lib/loadConfig.js
CHANGED
|
@@ -45,32 +45,13 @@ function _clone() {
|
|
|
45
45
|
return data;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
const data = _interopRequireDefault(require("./loadPlugins"));
|
|
48
|
+
var _constants = require("./constants");
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
return data;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
return data;
|
|
56
|
-
}
|
|
50
|
+
var _loadPlugins = _interopRequireDefault(require("./loadPlugins"));
|
|
57
51
|
|
|
58
52
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
59
53
|
|
|
60
|
-
const MODULE_BY_NAME_RE = /\.module\./;
|
|
61
|
-
|
|
62
54
|
async function configHydrator(configFile, config, resolveFrom, options) {
|
|
63
|
-
// Use a basic, modules-only PostCSS config if the file opts in by a name
|
|
64
|
-
// like foo.module.css
|
|
65
|
-
if (configFile == null && config.searchPath.match(MODULE_BY_NAME_RE)) {
|
|
66
|
-
configFile = {
|
|
67
|
-
plugins: {
|
|
68
|
-
'postcss-modules': {}
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
resolveFrom = __filename;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
55
|
if (configFile == null) {
|
|
75
56
|
return;
|
|
76
57
|
} // Load the custom config...
|
|
@@ -88,7 +69,7 @@ async function configHydrator(configFile, config, resolveFrom, options) {
|
|
|
88
69
|
modulesConfig = {};
|
|
89
70
|
}
|
|
90
71
|
|
|
91
|
-
let plugins = await (0, _loadPlugins
|
|
72
|
+
let plugins = await (0, _loadPlugins.default)(configFilePlugins, (0, _nullthrows().default)(resolveFrom), options); // contents is either:
|
|
92
73
|
// from JSON: { plugins: { 'postcss-foo': { ...opts } } }
|
|
93
74
|
// from JS (v8): { plugins: [ { postcssPlugin: 'postcss-foo', ...visitor callback functions } ]
|
|
94
75
|
// from JS (v7): { plugins: [ [Function: ...] ]
|
|
@@ -98,13 +79,13 @@ async function configHydrator(configFile, config, resolveFrom, options) {
|
|
|
98
79
|
for (let p of pluginArray) {
|
|
99
80
|
if (typeof p === 'string') {
|
|
100
81
|
config.addDevDependency({
|
|
101
|
-
|
|
82
|
+
specifier: p,
|
|
102
83
|
resolveFrom: (0, _nullthrows().default)(resolveFrom)
|
|
103
84
|
});
|
|
104
85
|
}
|
|
105
86
|
}
|
|
106
87
|
|
|
107
|
-
|
|
88
|
+
return {
|
|
108
89
|
raw: configFile,
|
|
109
90
|
hydrated: {
|
|
110
91
|
plugins,
|
|
@@ -112,7 +93,7 @@ async function configHydrator(configFile, config, resolveFrom, options) {
|
|
|
112
93
|
to: config.searchPath,
|
|
113
94
|
modules: modulesConfig
|
|
114
95
|
}
|
|
115
|
-
}
|
|
96
|
+
};
|
|
116
97
|
}
|
|
117
98
|
|
|
118
99
|
async function load({
|
|
@@ -120,6 +101,10 @@ async function load({
|
|
|
120
101
|
options,
|
|
121
102
|
logger
|
|
122
103
|
}) {
|
|
104
|
+
if (!config.isSource) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
123
108
|
let configFile = await config.getConfig(['.postcssrc', '.postcssrc.json', '.postcssrc.js', 'postcss.config.js'], {
|
|
124
109
|
packageKey: 'postcss'
|
|
125
110
|
});
|
|
@@ -127,8 +112,9 @@ async function load({
|
|
|
127
112
|
|
|
128
113
|
if (configFile) {
|
|
129
114
|
config.addDevDependency({
|
|
130
|
-
|
|
131
|
-
resolveFrom: config.searchPath
|
|
115
|
+
specifier: 'postcss',
|
|
116
|
+
resolveFrom: config.searchPath,
|
|
117
|
+
range: _constants.POSTCSS_RANGE
|
|
132
118
|
});
|
|
133
119
|
contents = configFile.contents;
|
|
134
120
|
let isDynamic = configFile && _path().default.extname(configFile.filePath) === '.js';
|
|
@@ -139,10 +125,10 @@ async function load({
|
|
|
139
125
|
logger.warn({
|
|
140
126
|
message: 'WARNING: Using a JavaScript PostCSS config file means losing out on caching features of Parcel. Use a .postcssrc(.json) file whenever possible.'
|
|
141
127
|
});
|
|
142
|
-
config.
|
|
128
|
+
config.invalidateOnStartup(); // Also add the config as a dev dependency so we attempt to reload in watch mode.
|
|
143
129
|
|
|
144
130
|
config.addDevDependency({
|
|
145
|
-
|
|
131
|
+
specifier: (0, _utils().relativePath)(_path().default.dirname(config.searchPath), configFile.filePath),
|
|
146
132
|
resolveFrom: config.searchPath
|
|
147
133
|
});
|
|
148
134
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parcel/transformer-postcss",
|
|
3
|
-
"version": "2.0.0-
|
|
3
|
+
"version": "2.0.0-nightly.1002+5530a6ef",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -17,20 +17,19 @@
|
|
|
17
17
|
"source": "src/PostCSSTransformer.js",
|
|
18
18
|
"engines": {
|
|
19
19
|
"node": ">= 12.0.0",
|
|
20
|
-
"parcel": "
|
|
20
|
+
"parcel": "2.0.0-nightly.1000+5530a6ef"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@parcel/
|
|
24
|
-
"@parcel/
|
|
23
|
+
"@parcel/hash": "2.3.2-nightly.2625+5530a6ef",
|
|
24
|
+
"@parcel/plugin": "2.0.0-nightly.1002+5530a6ef",
|
|
25
|
+
"@parcel/utils": "2.0.0-nightly.1002+5530a6ef",
|
|
25
26
|
"clone": "^2.1.1",
|
|
26
|
-
"css-modules-loader-core": "^1.1.0",
|
|
27
27
|
"nullthrows": "^1.1.1",
|
|
28
|
-
"postcss-
|
|
29
|
-
"
|
|
30
|
-
"semver": "^5.4.1"
|
|
28
|
+
"postcss-value-parser": "^4.2.0",
|
|
29
|
+
"semver": "^5.7.1"
|
|
31
30
|
},
|
|
32
31
|
"devDependencies": {
|
|
33
|
-
"postcss": "^8.
|
|
32
|
+
"postcss": "^8.4.5"
|
|
34
33
|
},
|
|
35
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "5530a6eff8b619873353baeb0457ae4ec591e9fa"
|
|
36
35
|
}
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
|
|
3
|
-
import type {FilePath, MutableAsset, PluginOptions} from '@parcel/types';
|
|
3
|
+
import type {FilePath, Asset, MutableAsset, PluginOptions} from '@parcel/types';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {hashString} from '@parcel/hash';
|
|
6
|
+
import {glob} from '@parcel/utils';
|
|
6
7
|
import {Transformer} from '@parcel/plugin';
|
|
7
|
-
import FileSystemLoader from 'css-modules-loader-core/lib/file-system-loader';
|
|
8
8
|
import nullthrows from 'nullthrows';
|
|
9
9
|
import path from 'path';
|
|
10
10
|
import semver from 'semver';
|
|
11
11
|
import valueParser from 'postcss-value-parser';
|
|
12
|
-
import postcssModules from 'postcss-modules';
|
|
13
12
|
import typeof * as Postcss from 'postcss';
|
|
14
13
|
|
|
15
14
|
import {load} from './loadConfig';
|
|
15
|
+
import {POSTCSS_RANGE} from './constants';
|
|
16
16
|
|
|
17
17
|
const COMPOSES_RE = /composes:.+from\s*("|').*("|')\s*;?/;
|
|
18
18
|
const FROM_IMPORT_RE = /.+from\s*(?:"|')(.*)(?:"|')\s*;?/;
|
|
19
|
+
const LEGACY_MODULE_RE = /@value|(:global|:local)(?!\s*\()/i;
|
|
20
|
+
const MODULE_BY_NAME_RE = /\.module\./;
|
|
19
21
|
|
|
20
22
|
export default (new Transformer({
|
|
21
23
|
loadConfig({config, options, logger}) {
|
|
@@ -23,11 +25,14 @@ export default (new Transformer({
|
|
|
23
25
|
},
|
|
24
26
|
|
|
25
27
|
canReuseAST({ast}) {
|
|
26
|
-
return
|
|
28
|
+
return (
|
|
29
|
+
ast.type === 'postcss' && semver.satisfies(ast.version, POSTCSS_RANGE)
|
|
30
|
+
);
|
|
27
31
|
},
|
|
28
32
|
|
|
29
33
|
async parse({asset, config, options}) {
|
|
30
|
-
|
|
34
|
+
let isLegacy = await isLegacyCssModule(asset);
|
|
35
|
+
if (!config && !isLegacy) {
|
|
31
36
|
return;
|
|
32
37
|
}
|
|
33
38
|
|
|
@@ -46,54 +51,82 @@ export default (new Transformer({
|
|
|
46
51
|
|
|
47
52
|
async transform({asset, config, options, resolve}) {
|
|
48
53
|
asset.type = 'css';
|
|
54
|
+
let isLegacy = await isLegacyCssModule(asset);
|
|
55
|
+
if (isLegacy && !config) {
|
|
56
|
+
config = {
|
|
57
|
+
hydrated: {
|
|
58
|
+
plugins: [],
|
|
59
|
+
from: asset.filePath,
|
|
60
|
+
to: asset.filePath,
|
|
61
|
+
modules: {},
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// TODO: warning?
|
|
66
|
+
}
|
|
67
|
+
|
|
49
68
|
if (!config) {
|
|
50
69
|
return [asset];
|
|
51
70
|
}
|
|
52
71
|
|
|
53
72
|
const postcss: Postcss = await loadPostcss(options, asset.filePath);
|
|
73
|
+
let ast = nullthrows(await asset.getAST());
|
|
74
|
+
let program = postcss.fromJSON(ast.program);
|
|
54
75
|
|
|
55
76
|
let plugins = [...config.hydrated.plugins];
|
|
56
77
|
let cssModules: ?{|[string]: string|} = null;
|
|
57
78
|
if (config.hydrated.modules) {
|
|
79
|
+
asset.meta.cssModulesCompiled = true;
|
|
80
|
+
|
|
81
|
+
// TODO: should this be resolved from the project root?
|
|
82
|
+
let postcssModules = await options.packageManager.require(
|
|
83
|
+
'postcss-modules',
|
|
84
|
+
asset.filePath,
|
|
85
|
+
{
|
|
86
|
+
range: '^4.3.0',
|
|
87
|
+
saveDev: true,
|
|
88
|
+
shouldAutoInstall: options.shouldAutoInstall,
|
|
89
|
+
},
|
|
90
|
+
);
|
|
91
|
+
|
|
58
92
|
plugins.push(
|
|
59
93
|
postcssModules({
|
|
60
94
|
getJSON: (filename, json) => (cssModules = json),
|
|
61
|
-
Loader: createLoader(asset, resolve),
|
|
95
|
+
Loader: await createLoader(asset, resolve, options),
|
|
62
96
|
generateScopedName: (name, filename) =>
|
|
63
|
-
|
|
97
|
+
`${name}_${hashString(
|
|
64
98
|
path.relative(options.projectRoot, filename),
|
|
65
99
|
).substr(0, 6)}`,
|
|
66
100
|
...config.hydrated.modules,
|
|
67
101
|
}),
|
|
68
102
|
);
|
|
69
|
-
}
|
|
70
103
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
104
|
+
let code = asset.isASTDirty() ? null : await asset.getCode();
|
|
105
|
+
if (code == null || COMPOSES_RE.test(code)) {
|
|
106
|
+
program.walkDecls(decl => {
|
|
107
|
+
let [, importPath] = FROM_IMPORT_RE.exec(decl.value) || [];
|
|
108
|
+
if (decl.prop === 'composes' && importPath != null) {
|
|
109
|
+
let parsed = valueParser(decl.value);
|
|
110
|
+
|
|
111
|
+
parsed.walk(node => {
|
|
112
|
+
if (node.type === 'string') {
|
|
113
|
+
asset.addDependency({
|
|
114
|
+
specifier: importPath,
|
|
115
|
+
specifierType: 'url',
|
|
116
|
+
loc: {
|
|
117
|
+
filePath: asset.filePath,
|
|
118
|
+
start: decl.source.start,
|
|
119
|
+
end: {
|
|
120
|
+
line: decl.source.start.line,
|
|
121
|
+
column: decl.source.start.column + importPath.length,
|
|
122
|
+
},
|
|
90
123
|
},
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
97
130
|
}
|
|
98
131
|
|
|
99
132
|
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381
|
|
@@ -108,7 +141,14 @@ export default (new Transformer({
|
|
|
108
141
|
});
|
|
109
142
|
for (let msg of messages) {
|
|
110
143
|
if (msg.type === 'dependency') {
|
|
111
|
-
asset.
|
|
144
|
+
asset.invalidateOnFileChange(msg.file);
|
|
145
|
+
} else if (msg.type === 'dir-dependency') {
|
|
146
|
+
let pattern = `${msg.dir}/${msg.glob ?? '**/*'}`;
|
|
147
|
+
let files = await glob(pattern, asset.fs, {onlyFiles: true});
|
|
148
|
+
for (let file of files) {
|
|
149
|
+
asset.invalidateOnFileChange(path.normalize(file));
|
|
150
|
+
}
|
|
151
|
+
asset.invalidateOnFileCreate({glob: pattern});
|
|
112
152
|
}
|
|
113
153
|
}
|
|
114
154
|
|
|
@@ -118,12 +158,12 @@ export default (new Transformer({
|
|
|
118
158
|
let cssModulesList = (Object.entries(cssModules): Array<
|
|
119
159
|
[string, string],
|
|
120
160
|
>);
|
|
121
|
-
let deps = asset.getDependencies().filter(dep =>
|
|
161
|
+
let deps = asset.getDependencies().filter(dep => dep.priority === 'sync');
|
|
122
162
|
let code: string;
|
|
123
163
|
if (deps.length > 0) {
|
|
124
164
|
code = `
|
|
125
165
|
module.exports = Object.assign({}, ${deps
|
|
126
|
-
.map(dep => `require(${JSON.stringify(dep.
|
|
166
|
+
.map(dep => `require(${JSON.stringify(dep.specifier)})`)
|
|
127
167
|
.join(', ')}, ${JSON.stringify(cssModules, null, 2)});
|
|
128
168
|
`;
|
|
129
169
|
} else {
|
|
@@ -146,7 +186,6 @@ export default (new Transformer({
|
|
|
146
186
|
|
|
147
187
|
assets.push({
|
|
148
188
|
type: 'js',
|
|
149
|
-
filePath: asset.filePath + '.js',
|
|
150
189
|
content: code,
|
|
151
190
|
});
|
|
152
191
|
}
|
|
@@ -167,10 +206,15 @@ export default (new Transformer({
|
|
|
167
206
|
},
|
|
168
207
|
}): Transformer);
|
|
169
208
|
|
|
170
|
-
function createLoader(
|
|
209
|
+
async function createLoader(
|
|
171
210
|
asset: MutableAsset,
|
|
172
211
|
resolve: (from: FilePath, to: string) => Promise<FilePath>,
|
|
212
|
+
options: PluginOptions,
|
|
173
213
|
) {
|
|
214
|
+
let {default: FileSystemLoader} = await options.packageManager.require(
|
|
215
|
+
'postcss-modules/build/css-loader-core/loader',
|
|
216
|
+
asset.filePath,
|
|
217
|
+
);
|
|
174
218
|
return class ParcelFileSystemLoader extends FileSystemLoader {
|
|
175
219
|
async fetch(composesPath, relativeTo) {
|
|
176
220
|
let importPath = composesPath.replace(/^["']|["']$/g, '');
|
|
@@ -188,6 +232,7 @@ function createLoader(
|
|
|
188
232
|
source,
|
|
189
233
|
rootRelativePath,
|
|
190
234
|
undefined,
|
|
235
|
+
// $FlowFixMe[method-unbinding]
|
|
191
236
|
this.fetch.bind(this),
|
|
192
237
|
);
|
|
193
238
|
return exportTokens;
|
|
@@ -201,8 +246,17 @@ function createLoader(
|
|
|
201
246
|
|
|
202
247
|
function loadPostcss(options: PluginOptions, from: FilePath): Promise<Postcss> {
|
|
203
248
|
return options.packageManager.require('postcss', from, {
|
|
204
|
-
range:
|
|
249
|
+
range: POSTCSS_RANGE,
|
|
205
250
|
saveDev: true,
|
|
206
251
|
shouldAutoInstall: options.shouldAutoInstall,
|
|
207
252
|
});
|
|
208
253
|
}
|
|
254
|
+
|
|
255
|
+
async function isLegacyCssModule(asset: Asset | MutableAsset) {
|
|
256
|
+
if (!MODULE_BY_NAME_RE.test(asset.filePath)) {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
let code = await asset.getCode();
|
|
261
|
+
return LEGACY_MODULE_RE.test(code);
|
|
262
|
+
}
|
package/src/constants.js
ADDED
package/src/loadConfig.js
CHANGED
|
@@ -1,32 +1,34 @@
|
|
|
1
1
|
// @flow
|
|
2
|
-
import type {
|
|
3
|
-
|
|
2
|
+
import type {
|
|
3
|
+
Config,
|
|
4
|
+
FilePath,
|
|
5
|
+
PluginOptions,
|
|
6
|
+
PluginLogger,
|
|
7
|
+
} from '@parcel/types';
|
|
4
8
|
import path from 'path';
|
|
5
9
|
import {relativePath} from '@parcel/utils';
|
|
6
10
|
import nullthrows from 'nullthrows';
|
|
7
11
|
import clone from 'clone';
|
|
12
|
+
import {POSTCSS_RANGE} from './constants';
|
|
8
13
|
|
|
9
14
|
import loadExternalPlugins from './loadPlugins';
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
type ConfigResult = {|
|
|
17
|
+
raw: any,
|
|
18
|
+
hydrated: {|
|
|
19
|
+
plugins: Array<any>,
|
|
20
|
+
from: FilePath,
|
|
21
|
+
to: FilePath,
|
|
22
|
+
modules: any,
|
|
23
|
+
|},
|
|
24
|
+
|};
|
|
12
25
|
|
|
13
26
|
async function configHydrator(
|
|
14
27
|
configFile: any,
|
|
15
28
|
config: Config,
|
|
16
29
|
resolveFrom: ?FilePath,
|
|
17
30
|
options: PluginOptions,
|
|
18
|
-
) {
|
|
19
|
-
// Use a basic, modules-only PostCSS config if the file opts in by a name
|
|
20
|
-
// like foo.module.css
|
|
21
|
-
if (configFile == null && config.searchPath.match(MODULE_BY_NAME_RE)) {
|
|
22
|
-
configFile = {
|
|
23
|
-
plugins: {
|
|
24
|
-
'postcss-modules': {},
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
resolveFrom = __filename;
|
|
28
|
-
}
|
|
29
|
-
|
|
31
|
+
): Promise<?ConfigResult> {
|
|
30
32
|
if (configFile == null) {
|
|
31
33
|
return;
|
|
32
34
|
}
|
|
@@ -63,13 +65,13 @@ async function configHydrator(
|
|
|
63
65
|
for (let p of pluginArray) {
|
|
64
66
|
if (typeof p === 'string') {
|
|
65
67
|
config.addDevDependency({
|
|
66
|
-
|
|
68
|
+
specifier: p,
|
|
67
69
|
resolveFrom: nullthrows(resolveFrom),
|
|
68
70
|
});
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
return {
|
|
73
75
|
raw: configFile,
|
|
74
76
|
hydrated: {
|
|
75
77
|
plugins,
|
|
@@ -77,7 +79,7 @@ async function configHydrator(
|
|
|
77
79
|
to: config.searchPath,
|
|
78
80
|
modules: modulesConfig,
|
|
79
81
|
},
|
|
80
|
-
}
|
|
82
|
+
};
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
export async function load({
|
|
@@ -88,7 +90,11 @@ export async function load({
|
|
|
88
90
|
config: Config,
|
|
89
91
|
options: PluginOptions,
|
|
90
92
|
logger: PluginLogger,
|
|
91
|
-
|}): Promise
|
|
93
|
+
|}): Promise<?ConfigResult> {
|
|
94
|
+
if (!config.isSource) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
92
98
|
let configFile: any = await config.getConfig(
|
|
93
99
|
['.postcssrc', '.postcssrc.json', '.postcssrc.js', 'postcss.config.js'],
|
|
94
100
|
{packageKey: 'postcss'},
|
|
@@ -97,8 +103,9 @@ export async function load({
|
|
|
97
103
|
let contents = null;
|
|
98
104
|
if (configFile) {
|
|
99
105
|
config.addDevDependency({
|
|
100
|
-
|
|
106
|
+
specifier: 'postcss',
|
|
101
107
|
resolveFrom: config.searchPath,
|
|
108
|
+
range: POSTCSS_RANGE,
|
|
102
109
|
});
|
|
103
110
|
|
|
104
111
|
contents = configFile.contents;
|
|
@@ -111,11 +118,11 @@ export async function load({
|
|
|
111
118
|
'WARNING: Using a JavaScript PostCSS config file means losing out on caching features of Parcel. Use a .postcssrc(.json) file whenever possible.',
|
|
112
119
|
});
|
|
113
120
|
|
|
114
|
-
config.
|
|
121
|
+
config.invalidateOnStartup();
|
|
115
122
|
|
|
116
123
|
// Also add the config as a dev dependency so we attempt to reload in watch mode.
|
|
117
124
|
config.addDevDependency({
|
|
118
|
-
|
|
125
|
+
specifier: relativePath(
|
|
119
126
|
path.dirname(config.searchPath),
|
|
120
127
|
configFile.filePath,
|
|
121
128
|
),
|