@parcel/transformer-css 2.0.0-nightly.97 → 2.1.0

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
+ }
13
47
 
14
- var _postcssValueParser = _interopRequireDefault(require("postcss-value-parser"));
48
+ function _nullthrows() {
49
+ const data = _interopRequireDefault(require("nullthrows"));
15
50
 
16
- var _semver = _interopRequireDefault(require("semver"));
51
+ _nullthrows = function () {
52
+ return data;
53
+ };
54
+
55
+ return data;
56
+ }
57
+
58
+ function _postcssValueParser() {
59
+ const data = _interopRequireDefault(require("postcss-value-parser"));
60
+
61
+ _postcssValueParser = function () {
62
+ return data;
63
+ };
64
+
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,21 +106,20 @@ 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
125
  // Normalize the asset's environment so that properties that only affect JS don't cause CSS to be duplicated.
@@ -69,105 +128,139 @@ var _default = new _plugin.Transformer({
69
128
  context: 'browser',
70
129
  engines: {
71
130
  browsers: asset.env.engines.browsers
72
- }
73
- }); // When this asset is an bundle entry, allow that bundle to be split to load shared assets separately.
74
- // Only set here if it is null to allow previous transformers to override this behavior.
75
-
76
- if (asset.isSplittable == null) {
77
- asset.isSplittable = true;
78
- }
79
-
80
- let ast = asset.ast; // Check for `hasDependencies` being false here as well, as it's possible
131
+ },
132
+ shouldOptimize: asset.env.shouldOptimize,
133
+ sourceMap: asset.env.sourceMap
134
+ }); // Check for `hasDependencies` being false here as well, as it's possible
81
135
  // another transformer (such as PostCSSTransformer) has already parsed an
82
136
  // ast and CSSTransformer's parse was never called.
83
137
 
138
+ let ast = await asset.getAST();
139
+
84
140
  if (!ast || asset.meta.hasDependencies === false) {
85
141
  return [asset];
86
142
  }
87
143
 
88
- ast.program.walkAtRules('import', rule => {
89
- 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);
90
161
  let [name, ...media] = params.nodes;
91
- let moduleSpecifier;
162
+ let specifier;
92
163
 
93
164
  if (name.type === 'function' && name.value === 'url' && name.nodes.length) {
94
165
  name = name.nodes[0];
95
166
  }
96
167
 
97
- moduleSpecifier = name.value;
168
+ specifier = name.value;
98
169
 
99
- if (!moduleSpecifier) {
100
- throw new Error('Could not find import name for ' + rule);
101
- }
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 {
102
180
 
103
- if ((0, _utils.isURL)(moduleSpecifier)) {
104
- name.value = asset.addURLDependency(moduleSpecifier, {
105
- loc: (0, _utils.createDependencyLocation)(rule.source.start, moduleSpecifier, 0, 8)
106
- });
107
- } else {
108
- // If this came from an inline <style> tag, don't inline the imported file. Replace with the correct URL instead.
109
- // TODO: run CSSPackager on inline style tags.
110
- // let inlineHTML =
111
- // this.options.rendition && this.options.rendition.inlineHTML;
112
- // if (inlineHTML) {
113
- // name.value = asset.addURLDependency(dep, {loc: rule.source.start});
114
- // rule.params = params.toString();
115
- // } else {
116
- media = _postcssValueParser.default.stringify(media).trim();
117
- let dep = {
118
- moduleSpecifier,
119
- // Offset by 8 as it does not include `@import `
120
- loc: (0, _utils.createDependencyLocation)(rule.source.start, moduleSpecifier, 0, 8),
121
- meta: {
122
- media
123
- }
124
- };
125
- asset.addDependency(dep);
126
- rule.remove(); // }
127
- }
128
181
 
129
- 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;
130
198
  });
131
- ast.program.walkDecls(decl => {
199
+ program.walkDecls(decl => {
132
200
  if (URL_RE.test(decl.value)) {
133
- let parsed = (0, _postcssValueParser.default)(decl.value);
134
- let isDirty = false;
201
+ let parsed = (0, _postcssValueParser().default)(decl.value);
202
+ let isDeclDirty = false;
135
203
  parsed.walk(node => {
136
204
  if (node.type === 'function' && node.value === 'url' && node.nodes.length > 0 && !node.nodes[0].value.startsWith('#') // IE's `behavior: url(#default#VML)`
137
205
  ) {
138
- node.nodes[0].value = asset.addURLDependency(node.nodes[0].value, {
139
- 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)
140
208
  });
141
- isDirty = true;
209
+ isDeclDirty = node.nodes[0].value !== url;
210
+ node.nodes[0].value = url;
142
211
  }
143
212
  });
144
213
 
145
- if (isDirty) {
214
+ if (isDeclDirty) {
146
215
  decl.value = parsed.toString();
147
- ast.isDirty = true;
216
+ isDirty = true;
148
217
  }
149
218
  }
150
219
  });
220
+
221
+ if (isDirty) {
222
+ asset.setAST({ ...ast,
223
+ program: program.toJSON()
224
+ });
225
+ }
226
+
151
227
  return [asset];
152
228
  },
153
229
 
154
230
  async generate({
155
- asset
231
+ asset,
232
+ ast,
233
+ options
156
234
  }) {
157
- 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();
158
249
 
159
- if (!asset.ast || !asset.ast.isDirty) {
160
- code = await asset.getCode();
161
- } else {
162
- code = '';
250
+ if (result.map != null) {
251
+ map = new (_sourceMap().default)(options.projectRoot);
252
+ map.addVLQMap(result.map.toJSON());
163
253
 
164
- _postcss.default.stringify(asset.ast.program, c => {
165
- code += c;
166
- });
254
+ if (originalSourceMap) {
255
+ map.extends(originalSourceMap.toBuffer());
256
+ }
257
+ } else {
258
+ map = originalSourceMap;
167
259
  }
168
260
 
169
261
  return {
170
- code
262
+ content: result.css,
263
+ map
171
264
  };
172
265
  }
173
266
 
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "@parcel/transformer-css",
3
- "version": "2.0.0-nightly.97+a63f3fc9",
3
+ "version": "2.1.0",
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.1.0"
17
21
  },
18
22
  "dependencies": {
19
- "@parcel/plugin": "2.0.0-nightly.97+a63f3fc9",
20
- "@parcel/utils": "2.0.0-nightly.97+a63f3fc9",
21
- "postcss": "^7.0.5",
22
- "postcss-value-parser": "^3.3.1",
23
- "semver": "^5.4.1"
23
+ "@parcel/plugin": "^2.1.0",
24
+ "@parcel/source-map": "^2.0.0",
25
+ "@parcel/utils": "^2.1.0",
26
+ "nullthrows": "^1.1.1",
27
+ "postcss": "^8.3.0",
28
+ "postcss-value-parser": "^4.1.0",
29
+ "semver": "^5.7.1"
24
30
  },
25
- "gitHead": "a63f3fc9726483219412920faeb255e035f90747"
31
+ "gitHead": "5a80fbe4af8797d0aab248a66f5254f42f00e83e"
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,21 +35,22 @@ 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}) {
53
+ async transform({asset}) {
50
54
  // Normalize the asset's environment so that properties that only affect JS don't cause CSS to be duplicated.
51
55
  // For example, with ESModule and CommonJS targets, only a single shared CSS bundle should be produced.
52
56
  asset.setEnvironment({
@@ -54,26 +58,38 @@ export default new Transformer({
54
58
  engines: {
55
59
  browsers: asset.env.engines.browsers,
56
60
  },
61
+ shouldOptimize: asset.env.shouldOptimize,
62
+ sourceMap: asset.env.sourceMap,
57
63
  });
58
64
 
59
- // When this asset is an bundle entry, allow that bundle to be split to load shared assets separately.
60
- // Only set here if it is null to allow previous transformers to override this behavior.
61
- if (asset.isSplittable == null) {
62
- asset.isSplittable = true;
63
- }
64
-
65
- let ast = asset.ast;
66
65
  // Check for `hasDependencies` being false here as well, as it's possible
67
66
  // another transformer (such as PostCSSTransformer) has already parsed an
68
67
  // ast and CSSTransformer's parse was never called.
68
+ let ast = await asset.getAST();
69
69
  if (!ast || asset.meta.hasDependencies === false) {
70
70
  return [asset];
71
71
  }
72
72
 
73
- 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 => {
74
90
  let params = valueParser(rule.params);
75
91
  let [name, ...media] = params.nodes;
76
- let moduleSpecifier;
92
+ let specifier;
77
93
  if (
78
94
  name.type === 'function' &&
79
95
  name.value === 'url' &&
@@ -82,55 +98,42 @@ export default new Transformer({
82
98
  name = name.nodes[0];
83
99
  }
84
100
 
85
- moduleSpecifier = name.value;
101
+ specifier = name.value;
86
102
 
87
- if (!moduleSpecifier) {
88
- 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));
89
105
  }
90
106
 
91
- if (isURL(moduleSpecifier)) {
92
- name.value = asset.addURLDependency(moduleSpecifier, {
93
- loc: createDependencyLocation(
94
- rule.source.start,
95
- moduleSpecifier,
96
- 0,
97
- 8,
98
- ),
99
- });
100
- } else {
101
- // If this came from an inline <style> tag, don't inline the imported file. Replace with the correct URL instead.
102
- // TODO: run CSSPackager on inline style tags.
103
- // let inlineHTML =
104
- // this.options.rendition && this.options.rendition.inlineHTML;
105
- // if (inlineHTML) {
106
- // name.value = asset.addURLDependency(dep, {loc: rule.source.start});
107
- // rule.params = params.toString();
108
- // } else {
109
- media = valueParser.stringify(media).trim();
110
- let dep = {
111
- moduleSpecifier,
112
- // Offset by 8 as it does not include `@import `
113
- loc: createDependencyLocation(
114
- rule.source.start,
115
- moduleSpecifier,
116
- 0,
117
- 8,
118
- ),
119
- meta: {
120
- media,
121
- },
122
- };
123
- asset.addDependency(dep);
124
- rule.remove();
125
- // }
126
- }
127
- 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;
128
131
  });
129
132
 
130
- ast.program.walkDecls(decl => {
133
+ program.walkDecls(decl => {
131
134
  if (URL_RE.test(decl.value)) {
132
135
  let parsed = valueParser(decl.value);
133
- let isDirty = false;
136
+ let isDeclDirty = false;
134
137
 
135
138
  parsed.walk(node => {
136
139
  if (
@@ -139,39 +142,68 @@ export default new Transformer({
139
142
  node.nodes.length > 0 &&
140
143
  !node.nodes[0].value.startsWith('#') // IE's `behavior: url(#default#VML)`
141
144
  ) {
142
- node.nodes[0].value = asset.addURLDependency(node.nodes[0].value, {
143
- loc: createDependencyLocation(
144
- decl.source.start,
145
- node.nodes[0].value,
146
- ),
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
+ ),
147
155
  });
148
- isDirty = true;
156
+ isDeclDirty = node.nodes[0].value !== url;
157
+ node.nodes[0].value = url;
149
158
  }
150
159
  });
151
160
 
152
- if (isDirty) {
161
+ if (isDeclDirty) {
153
162
  decl.value = parsed.toString();
154
- ast.isDirty = true;
163
+ isDirty = true;
155
164
  }
156
165
  }
157
166
  });
158
167
 
168
+ if (isDirty) {
169
+ asset.setAST({
170
+ ...ast,
171
+ program: program.toJSON(),
172
+ });
173
+ }
174
+
159
175
  return [asset];
160
176
  },
161
177
 
162
- async generate({asset}) {
163
- let code;
164
- if (!asset.ast || !asset.ast.isDirty) {
165
- 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
+ }
166
200
  } else {
167
- code = '';
168
- postcss.stringify(asset.ast.program, c => {
169
- code += c;
170
- });
201
+ map = originalSourceMap;
171
202
  }
172
203
 
173
204
  return {
174
- code,
205
+ content: result.css,
206
+ map,
175
207
  };
176
208
  },
177
- });
209
+ }): Transformer);