@parcel/transformer-css 2.0.0-nightly.92 → 2.0.1

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,15 +5,75 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- var _plugin = require("@parcel/plugin");
8
+ function _sourceMap() {
9
+ const data = _interopRequireDefault(require("@parcel/source-map"));
9
10
 
10
- var _utils = require("@parcel/utils");
11
+ _sourceMap = function () {
12
+ return data;
13
+ };
11
14
 
12
- var _postcss = _interopRequireDefault(require("postcss"));
15
+ return data;
16
+ }
17
+
18
+ function _plugin() {
19
+ const data = require("@parcel/plugin");
20
+
21
+ _plugin = function () {
22
+ return data;
23
+ };
24
+
25
+ return data;
26
+ }
27
+
28
+ function _utils() {
29
+ const data = require("@parcel/utils");
30
+
31
+ _utils = function () {
32
+ return data;
33
+ };
34
+
35
+ return data;
36
+ }
37
+
38
+ function _postcss() {
39
+ const data = _interopRequireDefault(require("postcss"));
40
+
41
+ _postcss = function () {
42
+ return data;
43
+ };
44
+
45
+ return data;
46
+ }
47
+
48
+ function _nullthrows() {
49
+ const data = _interopRequireDefault(require("nullthrows"));
50
+
51
+ _nullthrows = function () {
52
+ return data;
53
+ };
54
+
55
+ return data;
56
+ }
57
+
58
+ function _postcssValueParser() {
59
+ const data = _interopRequireDefault(require("postcss-value-parser"));
13
60
 
14
- var _postcssValueParser = _interopRequireDefault(require("postcss-value-parser"));
61
+ _postcssValueParser = function () {
62
+ return data;
63
+ };
15
64
 
16
- var _semver = _interopRequireDefault(require("semver"));
65
+ return data;
66
+ }
67
+
68
+ function _semver() {
69
+ const data = _interopRequireDefault(require("semver"));
70
+
71
+ _semver = function () {
72
+ return data;
73
+ };
74
+
75
+ return data;
76
+ }
17
77
 
18
78
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
79
 
@@ -24,11 +84,11 @@ function canHaveDependencies(filePath, code) {
24
84
  return !/\.css$/.test(filePath) || IMPORT_RE.test(code) || URL_RE.test(code);
25
85
  }
26
86
 
27
- var _default = new _plugin.Transformer({
87
+ var _default = new (_plugin().Transformer)({
28
88
  canReuseAST({
29
89
  ast
30
90
  }) {
31
- return ast.type === 'postcss' && _semver.default.satisfies(ast.version, '^7.0.0');
91
+ return ast.type === 'postcss' && _semver().default.satisfies(ast.version, '^8.2.1');
32
92
  },
33
93
 
34
94
  async parse({
@@ -46,120 +106,161 @@ var _default = new _plugin.Transformer({
46
106
 
47
107
  let code = await asset.getCode();
48
108
 
49
- if (!canHaveDependencies(asset.filePath, code)) {
109
+ if (code != null && !canHaveDependencies(asset.filePath, code)) {
50
110
  return null;
51
111
  }
52
112
 
53
113
  return {
54
114
  type: 'postcss',
55
- version: '7.0.0',
56
- isDirty: false,
57
- program: _postcss.default.parse(code, {
115
+ version: '8.2.1',
116
+ program: _postcss().default.parse(code, {
58
117
  from: asset.filePath
59
- })
118
+ }).toJSON()
60
119
  };
61
120
  },
62
121
 
63
- transform({
122
+ async transform({
64
123
  asset
65
124
  }) {
66
- // When this asset is an bundle entry, allow that bundle to be split to load shared assets separately.
67
- // Only set here if it is null to allow previous transformers to override this behavior.
68
- if (asset.isSplittable == null) {
69
- asset.isSplittable = true;
70
- }
71
-
72
- let ast = asset.ast; // Check for `hasDependencies` being false here as well, as it's possible
125
+ // Normalize the asset's environment so that properties that only affect JS don't cause CSS to be duplicated.
126
+ // For example, with ESModule and CommonJS targets, only a single shared CSS bundle should be produced.
127
+ asset.setEnvironment({
128
+ context: 'browser',
129
+ engines: {
130
+ browsers: asset.env.engines.browsers
131
+ },
132
+ shouldOptimize: asset.env.shouldOptimize,
133
+ sourceMap: asset.env.sourceMap
134
+ }); // Check for `hasDependencies` being false here as well, as it's possible
73
135
  // another transformer (such as PostCSSTransformer) has already parsed an
74
136
  // ast and CSSTransformer's parse was never called.
75
137
 
138
+ let ast = await asset.getAST();
139
+
76
140
  if (!ast || asset.meta.hasDependencies === false) {
77
141
  return [asset];
78
142
  }
79
143
 
80
- ast.program.walkAtRules('import', rule => {
81
- let params = (0, _postcssValueParser.default)(rule.params);
144
+ let program = _postcss().default.fromJSON(ast.program);
145
+
146
+ let originalSourceMap = await asset.getMap();
147
+
148
+ let createLoc = (start, specifier, lineOffset, colOffset) => {
149
+ let loc = (0, _utils().createDependencyLocation)(start, specifier, lineOffset, colOffset);
150
+
151
+ if (originalSourceMap) {
152
+ loc = (0, _utils().remapSourceLocation)(loc, originalSourceMap);
153
+ }
154
+
155
+ return loc;
156
+ };
157
+
158
+ let isDirty = false;
159
+ program.walkAtRules('import', rule => {
160
+ let params = (0, _postcssValueParser().default)(rule.params);
82
161
  let [name, ...media] = params.nodes;
83
- let moduleSpecifier;
162
+ let specifier;
84
163
 
85
164
  if (name.type === 'function' && name.value === 'url' && name.nodes.length) {
86
165
  name = name.nodes[0];
87
166
  }
88
167
 
89
- moduleSpecifier = name.value;
168
+ specifier = name.value;
90
169
 
91
- if (!moduleSpecifier) {
92
- throw new Error('Could not find import name for ' + rule);
93
- }
170
+ if (!specifier) {
171
+ throw new Error('Could not find import name for ' + String(rule));
172
+ } // If this came from an inline <style> tag, don't inline the imported file. Replace with the correct URL instead.
173
+ // TODO: run CSSPackager on inline style tags.
174
+ // let inlineHTML =
175
+ // this.options.rendition && this.options.rendition.inlineHTML;
176
+ // if (inlineHTML) {
177
+ // name.value = asset.addURLDependency(dep, {loc: rule.source.start});
178
+ // rule.params = params.toString();
179
+ // } else {
94
180
 
95
- if ((0, _utils.isURL)(moduleSpecifier)) {
96
- name.value = asset.addURLDependency(moduleSpecifier, {
97
- loc: (0, _utils.createDependencyLocation)(rule.source.start, moduleSpecifier, 0, 8)
98
- });
99
- } else {
100
- // If this came from an inline <style> tag, don't inline the imported file. Replace with the correct URL instead.
101
- // TODO: run CSSPackager on inline style tags.
102
- // let inlineHTML =
103
- // this.options.rendition && this.options.rendition.inlineHTML;
104
- // if (inlineHTML) {
105
- // name.value = asset.addURLDependency(dep, {loc: rule.source.start});
106
- // rule.params = params.toString();
107
- // } else {
108
- media = _postcssValueParser.default.stringify(media).trim();
109
- let dep = {
110
- moduleSpecifier,
111
- // Offset by 8 as it does not include `@import `
112
- loc: (0, _utils.createDependencyLocation)(rule.source.start, moduleSpecifier, 0, 8),
113
- meta: {
114
- media
115
- }
116
- };
117
- asset.addDependency(dep);
118
- rule.remove(); // }
119
- }
120
181
 
121
- ast.isDirty = true;
182
+ media = _postcssValueParser().default.stringify(media).trim();
183
+ let dep = {
184
+ specifier,
185
+ specifierType: 'url',
186
+ // Offset by 8 as it does not include `@import `
187
+ loc: createLoc((0, _nullthrows().default)(rule.source.start), specifier, 0, 8),
188
+ meta: {
189
+ // For the glob resolver to distinguish between `@import` and other URL dependencies.
190
+ isCSSImport: true,
191
+ media
192
+ }
193
+ };
194
+ asset.addDependency(dep);
195
+ rule.remove(); // }
196
+
197
+ isDirty = true;
122
198
  });
123
- ast.program.walkDecls(decl => {
199
+ program.walkDecls(decl => {
124
200
  if (URL_RE.test(decl.value)) {
125
- let parsed = (0, _postcssValueParser.default)(decl.value);
126
- let isDirty = false;
201
+ let parsed = (0, _postcssValueParser().default)(decl.value);
202
+ let isDeclDirty = false;
127
203
  parsed.walk(node => {
128
204
  if (node.type === 'function' && node.value === 'url' && node.nodes.length > 0 && !node.nodes[0].value.startsWith('#') // IE's `behavior: url(#default#VML)`
129
205
  ) {
130
- node.nodes[0].value = asset.addURLDependency(node.nodes[0].value, {
131
- loc: (0, _utils.createDependencyLocation)(decl.source.start, node.nodes[0].value)
206
+ let url = asset.addURLDependency(node.nodes[0].value, {
207
+ loc: decl.source && decl.source.start && createLoc(decl.source.start, node.nodes[0].value, 0, node.nodes[0].sourceIndex)
132
208
  });
133
- isDirty = true;
209
+ isDeclDirty = node.nodes[0].value !== url;
210
+ node.nodes[0].value = url;
134
211
  }
135
212
  });
136
213
 
137
- if (isDirty) {
214
+ if (isDeclDirty) {
138
215
  decl.value = parsed.toString();
139
- ast.isDirty = true;
216
+ isDirty = true;
140
217
  }
141
218
  }
142
219
  });
220
+
221
+ if (isDirty) {
222
+ asset.setAST({ ...ast,
223
+ program: program.toJSON()
224
+ });
225
+ }
226
+
143
227
  return [asset];
144
228
  },
145
229
 
146
230
  async generate({
147
- asset
231
+ asset,
232
+ ast,
233
+ options
148
234
  }) {
149
- let code;
235
+ let result = await (0, _postcss().default)().process(_postcss().default.fromJSON(ast.program), {
236
+ from: undefined,
237
+ to: options.projectRoot + '/index',
238
+ map: {
239
+ annotation: false,
240
+ inline: false,
241
+ sourcesContent: false
242
+ },
243
+ // Pass postcss's own stringifier to it to silence its warning
244
+ // as we don't want to perform any transformations -- only generate
245
+ stringifier: _postcss().default.stringify
246
+ });
247
+ let map = null;
248
+ let originalSourceMap = await asset.getMap();
150
249
 
151
- if (!asset.ast || !asset.ast.isDirty) {
152
- code = await asset.getCode();
153
- } else {
154
- code = '';
250
+ if (result.map != null) {
251
+ map = new (_sourceMap().default)(options.projectRoot);
252
+ map.addVLQMap(result.map.toJSON());
155
253
 
156
- _postcss.default.stringify(asset.ast.program, c => {
157
- code += c;
158
- });
254
+ if (originalSourceMap) {
255
+ map.extends(originalSourceMap.toBuffer());
256
+ }
257
+ } else {
258
+ map = originalSourceMap;
159
259
  }
160
260
 
161
261
  return {
162
- code
262
+ content: result.css,
263
+ map
163
264
  };
164
265
  }
165
266
 
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "@parcel/transformer-css",
3
- "version": "2.0.0-nightly.92+c0655c56",
3
+ "version": "2.0.1",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
+ "funding": {
9
+ "type": "opencollective",
10
+ "url": "https://opencollective.com/parcel"
11
+ },
8
12
  "repository": {
9
13
  "type": "git",
10
14
  "url": "https://github.com/parcel-bundler/parcel.git"
@@ -12,15 +16,17 @@
12
16
  "main": "lib/CSSTransformer.js",
13
17
  "source": "src/CSSTransformer.js",
14
18
  "engines": {
15
- "node": ">= 10.0.0",
16
- "parcel": "^2.0.0-alpha.1.1"
19
+ "node": ">= 12.0.0",
20
+ "parcel": "^2.0.1"
17
21
  },
18
22
  "dependencies": {
19
- "@parcel/plugin": "2.0.0-nightly.92+c0655c56",
20
- "@parcel/utils": "2.0.0-nightly.92+c0655c56",
21
- "postcss": "^7.0.5",
22
- "postcss-value-parser": "^3.3.1",
23
+ "@parcel/plugin": "^2.0.1",
24
+ "@parcel/source-map": "^2.0.0",
25
+ "@parcel/utils": "^2.0.1",
26
+ "nullthrows": "^1.1.1",
27
+ "postcss": "^8.3.0",
28
+ "postcss-value-parser": "^4.1.0",
23
29
  "semver": "^5.4.1"
24
30
  },
25
- "gitHead": "c0655c56f7973492fdb28671029ddd923f17a244"
31
+ "gitHead": "28b47e6bdca7de2a06b7cc39a4a0b1df89f3fe15"
26
32
  }
@@ -1,10 +1,13 @@
1
1
  // @flow
2
2
 
3
+ import type {Root} from 'postcss';
3
4
  import type {FilePath} from '@parcel/types';
4
5
 
6
+ import SourceMap from '@parcel/source-map';
5
7
  import {Transformer} from '@parcel/plugin';
6
- import {createDependencyLocation, isURL} from '@parcel/utils';
8
+ import {createDependencyLocation, remapSourceLocation} from '@parcel/utils';
7
9
  import postcss from 'postcss';
10
+ import nullthrows from 'nullthrows';
8
11
  import valueParser from 'postcss-value-parser';
9
12
  import semver from 'semver';
10
13
 
@@ -15,9 +18,9 @@ function canHaveDependencies(filePath: FilePath, code: string) {
15
18
  return !/\.css$/.test(filePath) || IMPORT_RE.test(code) || URL_RE.test(code);
16
19
  }
17
20
 
18
- export default new Transformer({
21
+ export default (new Transformer({
19
22
  canReuseAST({ast}) {
20
- return ast.type === 'postcss' && semver.satisfies(ast.version, '^7.0.0');
23
+ return ast.type === 'postcss' && semver.satisfies(ast.version, '^8.2.1');
21
24
  },
22
25
 
23
26
  async parse({asset}) {
@@ -32,39 +35,61 @@ export default new Transformer({
32
35
  }
33
36
 
34
37
  let code = await asset.getCode();
35
- if (!canHaveDependencies(asset.filePath, code)) {
38
+ if (code != null && !canHaveDependencies(asset.filePath, code)) {
36
39
  return null;
37
40
  }
38
41
 
39
42
  return {
40
43
  type: 'postcss',
41
- version: '7.0.0',
42
- isDirty: false,
43
- program: postcss.parse(code, {
44
- from: asset.filePath,
45
- }),
44
+ version: '8.2.1',
45
+ program: postcss
46
+ .parse(code, {
47
+ from: asset.filePath,
48
+ })
49
+ .toJSON(),
46
50
  };
47
51
  },
48
52
 
49
- transform({asset}) {
50
- // When this asset is an bundle entry, allow that bundle to be split to load shared assets separately.
51
- // Only set here if it is null to allow previous transformers to override this behavior.
52
- if (asset.isSplittable == null) {
53
- asset.isSplittable = true;
54
- }
53
+ async transform({asset}) {
54
+ // Normalize the asset's environment so that properties that only affect JS don't cause CSS to be duplicated.
55
+ // For example, with ESModule and CommonJS targets, only a single shared CSS bundle should be produced.
56
+ asset.setEnvironment({
57
+ context: 'browser',
58
+ engines: {
59
+ browsers: asset.env.engines.browsers,
60
+ },
61
+ shouldOptimize: asset.env.shouldOptimize,
62
+ sourceMap: asset.env.sourceMap,
63
+ });
55
64
 
56
- let ast = asset.ast;
57
65
  // Check for `hasDependencies` being false here as well, as it's possible
58
66
  // another transformer (such as PostCSSTransformer) has already parsed an
59
67
  // ast and CSSTransformer's parse was never called.
68
+ let ast = await asset.getAST();
60
69
  if (!ast || asset.meta.hasDependencies === false) {
61
70
  return [asset];
62
71
  }
63
72
 
64
- ast.program.walkAtRules('import', rule => {
73
+ let program: Root = postcss.fromJSON(ast.program);
74
+ let originalSourceMap = await asset.getMap();
75
+ let createLoc = (start, specifier, lineOffset, colOffset) => {
76
+ let loc = createDependencyLocation(
77
+ start,
78
+ specifier,
79
+ lineOffset,
80
+ colOffset,
81
+ );
82
+ if (originalSourceMap) {
83
+ loc = remapSourceLocation(loc, originalSourceMap);
84
+ }
85
+ return loc;
86
+ };
87
+
88
+ let isDirty = false;
89
+ program.walkAtRules('import', rule => {
65
90
  let params = valueParser(rule.params);
66
91
  let [name, ...media] = params.nodes;
67
- let moduleSpecifier;
92
+ let specifier;
68
93
  if (
69
94
  name.type === 'function' &&
70
95
  name.value === 'url' &&
@@ -73,55 +98,42 @@ export default new Transformer({
73
98
  name = name.nodes[0];
74
99
  }
75
100
 
76
- moduleSpecifier = name.value;
101
+ specifier = name.value;
77
102
 
78
- if (!moduleSpecifier) {
79
- throw new Error('Could not find import name for ' + rule);
103
+ if (!specifier) {
104
+ throw new Error('Could not find import name for ' + String(rule));
80
105
  }
81
106
 
82
- if (isURL(moduleSpecifier)) {
83
- name.value = asset.addURLDependency(moduleSpecifier, {
84
- loc: createDependencyLocation(
85
- rule.source.start,
86
- moduleSpecifier,
87
- 0,
88
- 8,
89
- ),
90
- });
91
- } else {
92
- // If this came from an inline <style> tag, don't inline the imported file. Replace with the correct URL instead.
93
- // TODO: run CSSPackager on inline style tags.
94
- // let inlineHTML =
95
- // this.options.rendition && this.options.rendition.inlineHTML;
96
- // if (inlineHTML) {
97
- // name.value = asset.addURLDependency(dep, {loc: rule.source.start});
98
- // rule.params = params.toString();
99
- // } else {
100
- media = valueParser.stringify(media).trim();
101
- let dep = {
102
- moduleSpecifier,
103
- // Offset by 8 as it does not include `@import `
104
- loc: createDependencyLocation(
105
- rule.source.start,
106
- moduleSpecifier,
107
- 0,
108
- 8,
109
- ),
110
- meta: {
111
- media,
112
- },
113
- };
114
- asset.addDependency(dep);
115
- rule.remove();
116
- // }
117
- }
118
- ast.isDirty = true;
107
+ // If this came from an inline <style> tag, don't inline the imported file. Replace with the correct URL instead.
108
+ // TODO: run CSSPackager on inline style tags.
109
+ // let inlineHTML =
110
+ // this.options.rendition && this.options.rendition.inlineHTML;
111
+ // if (inlineHTML) {
112
+ // name.value = asset.addURLDependency(dep, {loc: rule.source.start});
113
+ // rule.params = params.toString();
114
+ // } else {
115
+ media = valueParser.stringify(media).trim();
116
+ let dep = {
117
+ specifier,
118
+ specifierType: 'url',
119
+ // Offset by 8 as it does not include `@import `
120
+ loc: createLoc(nullthrows(rule.source.start), specifier, 0, 8),
121
+ meta: {
122
+ // For the glob resolver to distinguish between `@import` and other URL dependencies.
123
+ isCSSImport: true,
124
+ media,
125
+ },
126
+ };
127
+ asset.addDependency(dep);
128
+ rule.remove();
129
+ // }
130
+ isDirty = true;
119
131
  });
120
132
 
121
- ast.program.walkDecls(decl => {
133
+ program.walkDecls(decl => {
122
134
  if (URL_RE.test(decl.value)) {
123
135
  let parsed = valueParser(decl.value);
124
- let isDirty = false;
136
+ let isDeclDirty = false;
125
137
 
126
138
  parsed.walk(node => {
127
139
  if (
@@ -130,39 +142,68 @@ export default new Transformer({
130
142
  node.nodes.length > 0 &&
131
143
  !node.nodes[0].value.startsWith('#') // IE's `behavior: url(#default#VML)`
132
144
  ) {
133
- node.nodes[0].value = asset.addURLDependency(node.nodes[0].value, {
134
- loc: createDependencyLocation(
135
- decl.source.start,
136
- node.nodes[0].value,
137
- ),
145
+ let url = asset.addURLDependency(node.nodes[0].value, {
146
+ loc:
147
+ decl.source &&
148
+ decl.source.start &&
149
+ createLoc(
150
+ decl.source.start,
151
+ node.nodes[0].value,
152
+ 0,
153
+ node.nodes[0].sourceIndex,
154
+ ),
138
155
  });
139
- isDirty = true;
156
+ isDeclDirty = node.nodes[0].value !== url;
157
+ node.nodes[0].value = url;
140
158
  }
141
159
  });
142
160
 
143
- if (isDirty) {
161
+ if (isDeclDirty) {
144
162
  decl.value = parsed.toString();
145
- ast.isDirty = true;
163
+ isDirty = true;
146
164
  }
147
165
  }
148
166
  });
149
167
 
168
+ if (isDirty) {
169
+ asset.setAST({
170
+ ...ast,
171
+ program: program.toJSON(),
172
+ });
173
+ }
174
+
150
175
  return [asset];
151
176
  },
152
177
 
153
- async generate({asset}) {
154
- let code;
155
- if (!asset.ast || !asset.ast.isDirty) {
156
- code = await asset.getCode();
178
+ async generate({asset, ast, options}) {
179
+ let result = await postcss().process(postcss.fromJSON(ast.program), {
180
+ from: undefined,
181
+ to: options.projectRoot + '/index',
182
+ map: {
183
+ annotation: false,
184
+ inline: false,
185
+ sourcesContent: false,
186
+ },
187
+ // Pass postcss's own stringifier to it to silence its warning
188
+ // as we don't want to perform any transformations -- only generate
189
+ stringifier: postcss.stringify,
190
+ });
191
+
192
+ let map = null;
193
+ let originalSourceMap = await asset.getMap();
194
+ if (result.map != null) {
195
+ map = new SourceMap(options.projectRoot);
196
+ map.addVLQMap(result.map.toJSON());
197
+ if (originalSourceMap) {
198
+ map.extends(originalSourceMap.toBuffer());
199
+ }
157
200
  } else {
158
- code = '';
159
- postcss.stringify(asset.ast.program, c => {
160
- code += c;
161
- });
201
+ map = originalSourceMap;
162
202
  }
163
203
 
164
204
  return {
165
- code,
205
+ content: result.css,
206
+ map,
166
207
  };
167
208
  },
168
- });
209
+ }): Transformer);