@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.
@@ -5,30 +5,30 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- function _utils() {
9
- const data = require("@parcel/utils");
8
+ function _hash() {
9
+ const data = require("@parcel/hash");
10
10
 
11
- _utils = function () {
11
+ _hash = function () {
12
12
  return data;
13
13
  };
14
14
 
15
15
  return data;
16
16
  }
17
17
 
18
- function _plugin() {
19
- const data = require("@parcel/plugin");
18
+ function _utils() {
19
+ const data = require("@parcel/utils");
20
20
 
21
- _plugin = function () {
21
+ _utils = function () {
22
22
  return data;
23
23
  };
24
24
 
25
25
  return data;
26
26
  }
27
27
 
28
- function _fileSystemLoader() {
29
- const data = _interopRequireDefault(require("css-modules-loader-core/lib/file-system-loader"));
28
+ function _plugin() {
29
+ const data = require("@parcel/plugin");
30
30
 
31
- _fileSystemLoader = function () {
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
- function _postcssModules() {
79
- const data = _interopRequireDefault(require("postcss-modules"));
78
+ var _loadConfig = require("./loadConfig");
80
79
 
81
- _postcssModules = function () {
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().load)({
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, '^8.2.1');
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
- if (!config) {
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
- plugins.push((0, _postcssModules().default)({
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) => `_${name}_${(0, _utils().md5FromString)(_path().default.relative(options.projectRoot, filename)).substr(0, 6)}`,
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
- let ast = (0, _nullthrows().default)(await asset.getAST());
167
- let program = postcss.fromJSON(ast.program);
168
- let code = asset.isASTDirty() ? null : await asset.getCode();
169
-
170
- if (code == null || COMPOSES_RE.test(code)) {
171
- program.walkDecls(decl => {
172
- let [, importPath] = FROM_IMPORT_RE.exec(decl.value) || [];
173
-
174
- if (decl.prop === 'composes' && importPath != null) {
175
- let parsed = (0, _postcssValueParser().default)(decl.value);
176
- parsed.walk(node => {
177
- if (node.type === 'string') {
178
- asset.addDependency({
179
- moduleSpecifier: importPath,
180
- loc: {
181
- filePath: asset.filePath,
182
- start: decl.source.start,
183
- end: {
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.addIncludedFile(msg.file);
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 => !dep.isURL);
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.moduleSpecifier)})`).join(', ')}, ${JSON.stringify(cssModules, null, 2)});
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
- return class extends _fileSystemLoader().default {
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, this.fetch.bind(this));
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: '^8.2.1',
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
  }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.POSTCSS_RANGE = void 0;
7
+ const POSTCSS_RANGE = '^8.2.1';
8
+ exports.POSTCSS_RANGE = POSTCSS_RANGE;
package/lib/loadConfig.js CHANGED
@@ -45,32 +45,13 @@ function _clone() {
45
45
  return data;
46
46
  }
47
47
 
48
- function _loadPlugins() {
49
- const data = _interopRequireDefault(require("./loadPlugins"));
48
+ var _constants = require("./constants");
50
49
 
51
- _loadPlugins = function () {
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().default)(configFilePlugins, (0, _nullthrows().default)(resolveFrom), options); // contents is either:
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
- moduleSpecifier: p,
82
+ specifier: p,
102
83
  resolveFrom: (0, _nullthrows().default)(resolveFrom)
103
84
  });
104
85
  }
105
86
  }
106
87
 
107
- config.setResult({
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
- moduleSpecifier: 'postcss',
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.shouldInvalidateOnStartup(); // Also add the config as a dev dependency so we attempt to reload in watch mode.
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
- moduleSpecifier: (0, _utils().relativePath)(_path().default.dirname(config.searchPath), configFile.filePath),
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-beta.3.1",
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": "^2.0.0-beta.1"
20
+ "parcel": "2.0.0-nightly.1000+5530a6ef"
21
21
  },
22
22
  "dependencies": {
23
- "@parcel/plugin": "2.0.0-beta.3.1",
24
- "@parcel/utils": "2.0.0-beta.3.1",
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-modules": "^3.2.2",
29
- "postcss-value-parser": "^4.1.0",
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.2.1"
32
+ "postcss": "^8.4.5"
34
33
  },
35
- "gitHead": "daece49d003ba804bbdaa3a7ed3d6aaf446f166d"
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 {md5FromString} from '@parcel/utils';
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 ast.type === 'postcss' && semver.satisfies(ast.version, '^8.2.1');
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
- if (!config) {
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
- `_${name}_${md5FromString(
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
- let ast = nullthrows(await asset.getAST());
72
- let program = postcss.fromJSON(ast.program);
73
- let code = asset.isASTDirty() ? null : await asset.getCode();
74
- if (code == null || COMPOSES_RE.test(code)) {
75
- program.walkDecls(decl => {
76
- let [, importPath] = FROM_IMPORT_RE.exec(decl.value) || [];
77
- if (decl.prop === 'composes' && importPath != null) {
78
- let parsed = valueParser(decl.value);
79
-
80
- parsed.walk(node => {
81
- if (node.type === 'string') {
82
- asset.addDependency({
83
- moduleSpecifier: importPath,
84
- loc: {
85
- filePath: asset.filePath,
86
- start: decl.source.start,
87
- end: {
88
- line: decl.source.start.line,
89
- column: decl.source.start.column + importPath.length,
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.addIncludedFile(msg.file);
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 => !dep.isURL);
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.moduleSpecifier)})`)
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: '^8.2.1',
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
+ }
@@ -0,0 +1,3 @@
1
+ // @flow
2
+
3
+ export const POSTCSS_RANGE = '^8.2.1';
package/src/loadConfig.js CHANGED
@@ -1,32 +1,34 @@
1
1
  // @flow
2
- import type {Config, FilePath, PluginOptions} from '@parcel/types';
3
- import type {PluginLogger} from '@parcel/logger';
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
- const MODULE_BY_NAME_RE = /\.module\./;
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
- moduleSpecifier: p,
68
+ specifier: p,
67
69
  resolveFrom: nullthrows(resolveFrom),
68
70
  });
69
71
  }
70
72
  }
71
73
 
72
- config.setResult({
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<void> {
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
- moduleSpecifier: 'postcss',
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.shouldInvalidateOnStartup();
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
- moduleSpecifier: relativePath(
125
+ specifier: relativePath(
119
126
  path.dirname(config.searchPath),
120
127
  configFile.filePath,
121
128
  ),