@parcel/transformer-less 2.0.0-beta.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,11 +5,45 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- var _path = _interopRequireDefault(require("path"));
8
+ function _path() {
9
+ const data = _interopRequireDefault(require("path"));
9
10
 
10
- var _plugin = require("@parcel/plugin");
11
+ _path = function () {
12
+ return data;
13
+ };
14
+
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 _sourceMap() {
29
+ const data = _interopRequireDefault(require("@parcel/source-map"));
11
30
 
12
- var _sourceMap = _interopRequireDefault(require("@parcel/source-map"));
31
+ _sourceMap = function () {
32
+ return data;
33
+ };
34
+
35
+ return data;
36
+ }
37
+
38
+ function _less() {
39
+ const data = _interopRequireDefault(require("less"));
40
+
41
+ _less = function () {
42
+ return data;
43
+ };
44
+
45
+ return data;
46
+ }
13
47
 
14
48
  var _loadConfig = require("./loadConfig");
15
49
 
@@ -18,7 +52,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
18
52
  // E.g: ~library/file.less
19
53
  const WEBPACK_ALIAS_RE = /^~[^/]/;
20
54
 
21
- var _default = new _plugin.Transformer({
55
+ var _default = new (_plugin().Transformer)({
22
56
  loadConfig({
23
57
  config
24
58
  }) {
@@ -27,12 +61,6 @@ var _default = new _plugin.Transformer({
27
61
  });
28
62
  },
29
63
 
30
- preSerializeConfig({
31
- config
32
- }) {
33
- return (0, _loadConfig.preSerialize)(config);
34
- },
35
-
36
64
  async transform({
37
65
  asset,
38
66
  options,
@@ -41,9 +69,6 @@ var _default = new _plugin.Transformer({
41
69
  }) {
42
70
  asset.type = 'css';
43
71
  asset.meta.hasDependencies = false;
44
- let less = await options.packageManager.require('less', asset.filePath, {
45
- autoinstall: options.autoinstall
46
- });
47
72
  let code = await asset.getCode();
48
73
  let result;
49
74
 
@@ -51,7 +76,7 @@ var _default = new _plugin.Transformer({
51
76
  let lessConfig = config ? { ...config.config
52
77
  } : {};
53
78
 
54
- if (options.sourceMaps) {
79
+ if (asset.env.sourceMap) {
55
80
  lessConfig.sourceMap = {};
56
81
  }
57
82
 
@@ -62,7 +87,7 @@ var _default = new _plugin.Transformer({
62
87
  asset,
63
88
  resolve
64
89
  })];
65
- result = await less.render(code, lessConfig);
90
+ result = await _less().default.render(code, lessConfig);
66
91
  } catch (err) {
67
92
  // For the error reporter
68
93
  err.fileName = err.filename;
@@ -74,10 +99,10 @@ var _default = new _plugin.Transformer({
74
99
  }
75
100
 
76
101
  if (result.map != null) {
77
- let map = new _sourceMap.default();
102
+ let map = new (_sourceMap().default)(options.projectRoot);
78
103
  let rawMap = JSON.parse(result.map);
79
- map.addRawMappings({ ...rawMap,
80
- sources: rawMap.sources.map(s => _path.default.relative(options.projectRoot, s))
104
+ map.addVLQMap({ ...rawMap,
105
+ sources: rawMap.sources.map(s => _path().default.relative(options.projectRoot, s))
81
106
  });
82
107
  asset.setMap(map);
83
108
  }
@@ -95,17 +120,22 @@ function urlPlugin({
95
120
  }) {
96
121
  return {
97
122
  install(less, pluginManager) {
123
+ // This is a hack; no such interface exists, even conceptually, in Less.
98
124
  const visitor = new less.visitors.Visitor({
99
125
  visitUrl(node) {
100
- if (!node.value.value.startsWith('#') // IE's `behavior: url(#default#VML)`)
126
+ const valueNode = node.value;
127
+ const stringValue = valueNode.value;
128
+
129
+ if (!stringValue.startsWith('#') // IE's `behavior: url(#default#VML)`)
101
130
  ) {
102
- node.value.value = asset.addURLDependency(node.value.value, node.currentFileInfo.filename);
103
- }
131
+ valueNode.value = asset.addURLDependency(stringValue, {});
132
+ }
104
133
 
105
134
  return node;
106
135
  }
107
136
 
108
- });
137
+ }); // $FlowFixMe[method-unbinding]
138
+
109
139
  visitor.run = visitor.visit;
110
140
  pluginManager.addVisitor(visitor);
111
141
  }
@@ -128,24 +158,65 @@ function resolvePathPlugin({
128
158
  return false;
129
159
  }
130
160
 
131
- async loadFile(rawFilename, ...args) {
161
+ async loadFile(rawFilename, currentDirectory, options) {
132
162
  let filename = rawFilename;
133
163
 
134
164
  if (WEBPACK_ALIAS_RE.test(filename)) {
135
165
  let correctPath = filename.replace(/^~/, '');
136
166
  throw new Error(`The @import path "${filename}" is using webpack specific syntax, which isn't supported by Parcel.\n\nTo @import files from node_modules, use "${correctPath}"`);
167
+ } // Based on https://github.com/less/less.js/blob/master/packages/less/src/less-node/file-manager.js
168
+
169
+
170
+ let isAbsoluteFilename = this.isPathAbsolute(filename);
171
+ let paths = isAbsoluteFilename ? [''] : [currentDirectory];
172
+
173
+ if (options.paths) {
174
+ paths.push(...options.paths);
137
175
  }
138
176
 
139
- try {
140
- return await super.loadFile(filename, ...args);
141
- } catch (err) {
142
- if (err.type !== 'File') {
143
- throw err;
177
+ let prefixes = options.prefixes || [''];
178
+ let fileParts = this.extractUrlParts(filename);
179
+ let filePath;
180
+ let contents;
181
+
182
+ if (filename[0] !== '~') {
183
+ outer: for (let p of paths) {
184
+ for (let prefix of prefixes) {
185
+ filePath = fileParts.rawPath + prefix + fileParts.filename;
186
+
187
+ if (p) {
188
+ filePath = _path().default.join(p, filePath);
189
+ }
190
+
191
+ if (options.ext) {
192
+ filePath = this.tryAppendExtension(filePath, options.ext);
193
+ }
194
+
195
+ try {
196
+ contents = await asset.fs.readFile(filePath, 'utf8');
197
+ break outer;
198
+ } catch (err) {
199
+ asset.invalidateOnFileCreate({
200
+ filePath
201
+ });
202
+ }
203
+ }
144
204
  }
205
+ }
206
+
207
+ if (!contents) {
208
+ filePath = await resolve(asset.filePath, filename);
209
+ contents = await asset.fs.readFile(filePath, 'utf8');
210
+ }
145
211
 
146
- filename = await resolve(asset.filePath, filename);
147
- return super.loadFile(filename, ...args);
212
+ if (filePath) {
213
+ asset.invalidateOnFileChange(filePath);
148
214
  }
215
+
216
+ return {
217
+ contents,
218
+ filename: filePath
219
+ };
149
220
  }
150
221
 
151
222
  }
package/lib/loadConfig.js CHANGED
@@ -4,9 +4,16 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.load = load;
7
- exports.preSerialize = preSerialize;
8
7
 
9
- var _path = _interopRequireDefault(require("path"));
8
+ function _path() {
9
+ const data = _interopRequireDefault(require("path"));
10
+
11
+ _path = function () {
12
+ return data;
13
+ };
14
+
15
+ return data;
16
+ }
10
17
 
11
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
19
 
@@ -19,30 +26,25 @@ async function load({
19
26
  let configContents = {};
20
27
 
21
28
  if (configFile != null) {
22
- configContents = configFile.contents;
29
+ configContents = configFile.contents; // Resolve relative paths from config file
30
+
31
+ if (configContents.paths) {
32
+ configContents.paths = configContents.paths.map(p => _path().default.resolve(_path().default.dirname(configFile.filePath), p));
33
+ }
23
34
  } // Rewrites urls to be relative to the provided filename
24
35
 
25
36
 
26
37
  configContents.rewriteUrls = 'all';
27
38
  configContents.plugins = configContents.plugins || []; // This should enforce the config to be reloaded on every run as it's JS
28
39
 
29
- let isDynamic = configFile && _path.default.extname(configFile.filePath) === '.js';
40
+ let isDynamic = configFile && _path().default.extname(configFile.filePath) === '.js';
30
41
 
31
42
  if (isDynamic) {
32
- config.shouldInvalidateOnStartup();
33
- config.shouldReload();
43
+ config.invalidateOnStartup();
34
44
  }
35
45
 
36
- return config.setResult({
46
+ return {
37
47
  isStatic: !isDynamic,
38
48
  config: configContents
39
- });
40
- }
41
-
42
- function preSerialize(config) {
43
- if (!config.result) return; // Ensure we dont pass functions to the serialiser
44
-
45
- if (!config.result.isStatic) {
46
- config.result.config = {};
47
- }
49
+ };
48
50
  }
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "@parcel/transformer-less",
3
- "version": "2.0.0-beta.1",
3
+ "version": "2.0.0-nightly.1002+5530a6ef",
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,13 @@
12
16
  "main": "lib/LessTransformer.js",
13
17
  "source": "src/LessTransformer.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.0-nightly.1000+5530a6ef"
17
21
  },
18
22
  "dependencies": {
19
- "@parcel/plugin": "2.0.0-beta.1",
20
- "@parcel/source-map": "2.0.0-alpha.4.13"
21
- },
22
- "devDependencies": {
23
- "less": "^3.9.0"
23
+ "@parcel/plugin": "2.0.0-nightly.1002+5530a6ef",
24
+ "@parcel/source-map": "^2.0.0",
25
+ "less": "^4.1.1"
24
26
  },
25
- "gitHead": "74335525be92e23bac4ed1bf30595443cfb238e3"
27
+ "gitHead": "5530a6eff8b619873353baeb0457ae4ec591e9fa"
26
28
  }
@@ -1,9 +1,11 @@
1
1
  // @flow
2
+ import {typeof default as Less} from 'less';
2
3
  import path from 'path';
3
4
  import {Transformer} from '@parcel/plugin';
4
5
  import SourceMap from '@parcel/source-map';
6
+ import less from 'less';
5
7
 
6
- import {load, preSerialize} from './loadConfig';
8
+ import {load} from './loadConfig';
7
9
 
8
10
  // E.g: ~library/file.less
9
11
  const WEBPACK_ALIAS_RE = /^~[^/]/;
@@ -15,29 +17,21 @@ type LessConfig = {
15
17
  ...
16
18
  };
17
19
 
18
- export default new Transformer({
20
+ export default (new Transformer({
19
21
  loadConfig({config}) {
20
22
  return load({config});
21
23
  },
22
24
 
23
- preSerializeConfig({config}) {
24
- return preSerialize(config);
25
- },
26
-
27
25
  async transform({asset, options, config, resolve}) {
28
26
  asset.type = 'css';
29
27
  asset.meta.hasDependencies = false;
30
28
 
31
- let less = await options.packageManager.require('less', asset.filePath, {
32
- autoinstall: options.autoinstall,
33
- });
34
-
35
29
  let code = await asset.getCode();
36
30
  let result;
37
31
  try {
38
32
  let lessConfig: LessConfig = config ? {...config.config} : {};
39
33
 
40
- if (options.sourceMaps) {
34
+ if (asset.env.sourceMap) {
41
35
  lessConfig.sourceMap = {};
42
36
  }
43
37
 
@@ -60,9 +54,9 @@ export default new Transformer({
60
54
  }
61
55
 
62
56
  if (result.map != null) {
63
- let map = new SourceMap();
57
+ let map = new SourceMap(options.projectRoot);
64
58
  let rawMap = JSON.parse(result.map);
65
- map.addRawMappings({
59
+ map.addVLQMap({
66
60
  ...rawMap,
67
61
  sources: rawMap.sources.map(s => path.relative(options.projectRoot, s)),
68
62
  });
@@ -73,25 +67,28 @@ export default new Transformer({
73
67
 
74
68
  return [asset];
75
69
  },
76
- });
70
+ }): Transformer);
77
71
 
78
72
  function urlPlugin({asset}) {
79
73
  return {
80
- install(less, pluginManager) {
74
+ install(less: Less, pluginManager) {
75
+ // This is a hack; no such interface exists, even conceptually, in Less.
76
+ type LessNodeWithValue = less.tree.Node & {value: any, ...};
77
+
81
78
  const visitor = new less.visitors.Visitor({
82
79
  visitUrl(node) {
80
+ const valueNode = ((node.value: any): LessNodeWithValue);
81
+ const stringValue = (valueNode.value: string);
83
82
  if (
84
- !node.value.value.startsWith('#') // IE's `behavior: url(#default#VML)`)
83
+ !stringValue.startsWith('#') // IE's `behavior: url(#default#VML)`)
85
84
  ) {
86
- node.value.value = asset.addURLDependency(
87
- node.value.value,
88
- node.currentFileInfo.filename,
89
- );
85
+ valueNode.value = asset.addURLDependency(stringValue, {});
90
86
  }
91
87
  return node;
92
88
  },
93
89
  });
94
90
 
91
+ // $FlowFixMe[method-unbinding]
95
92
  visitor.run = visitor.visit;
96
93
  pluginManager.addVisitor(visitor);
97
94
  },
@@ -110,7 +107,7 @@ function resolvePathPlugin({asset, resolve}) {
110
107
  return false;
111
108
  }
112
109
 
113
- async loadFile(rawFilename, ...args) {
110
+ async loadFile(rawFilename, currentDirectory, options) {
114
111
  let filename = rawFilename;
115
112
 
116
113
  if (WEBPACK_ALIAS_RE.test(filename)) {
@@ -120,15 +117,53 @@ function resolvePathPlugin({asset, resolve}) {
120
117
  );
121
118
  }
122
119
 
123
- try {
124
- return await super.loadFile(filename, ...args);
125
- } catch (err) {
126
- if (err.type !== 'File') {
127
- throw err;
120
+ // Based on https://github.com/less/less.js/blob/master/packages/less/src/less-node/file-manager.js
121
+ let isAbsoluteFilename = this.isPathAbsolute(filename);
122
+ let paths = isAbsoluteFilename ? [''] : [currentDirectory];
123
+ if (options.paths) {
124
+ paths.push(...options.paths);
125
+ }
126
+
127
+ let prefixes = options.prefixes || [''];
128
+ let fileParts = this.extractUrlParts(filename);
129
+ let filePath;
130
+ let contents;
131
+
132
+ if (filename[0] !== '~') {
133
+ outer: for (let p of paths) {
134
+ for (let prefix of prefixes) {
135
+ filePath = fileParts.rawPath + prefix + fileParts.filename;
136
+ if (p) {
137
+ filePath = path.join(p, filePath);
138
+ }
139
+
140
+ if (options.ext) {
141
+ filePath = this.tryAppendExtension(filePath, options.ext);
142
+ }
143
+
144
+ try {
145
+ contents = await asset.fs.readFile(filePath, 'utf8');
146
+ break outer;
147
+ } catch (err) {
148
+ asset.invalidateOnFileCreate({filePath});
149
+ }
150
+ }
128
151
  }
129
- filename = await resolve(asset.filePath, filename);
130
- return super.loadFile(filename, ...args);
131
152
  }
153
+
154
+ if (!contents) {
155
+ filePath = await resolve(asset.filePath, filename);
156
+ contents = await asset.fs.readFile(filePath, 'utf8');
157
+ }
158
+
159
+ if (filePath) {
160
+ asset.invalidateOnFileChange(filePath);
161
+ }
162
+
163
+ return {
164
+ contents,
165
+ filename: filePath,
166
+ };
132
167
  }
133
168
  }
134
169
 
package/src/loadConfig.js CHANGED
@@ -2,7 +2,16 @@
2
2
  import type {Config} from '@parcel/types';
3
3
  import path from 'path';
4
4
 
5
- export async function load({config}: {|config: Config|}) {
5
+ type ConfigResult = {|
6
+ isStatic: boolean,
7
+ config: any,
8
+ |};
9
+
10
+ export async function load({
11
+ config,
12
+ }: {|
13
+ config: Config,
14
+ |}): Promise<ConfigResult> {
6
15
  let configFile = await config.getConfig(['.lessrc', '.lessrc.js'], {
7
16
  packageKey: 'less',
8
17
  });
@@ -10,6 +19,13 @@ export async function load({config}: {|config: Config|}) {
10
19
  let configContents = {};
11
20
  if (configFile != null) {
12
21
  configContents = configFile.contents;
22
+
23
+ // Resolve relative paths from config file
24
+ if (configContents.paths) {
25
+ configContents.paths = configContents.paths.map(p =>
26
+ path.resolve(path.dirname(configFile.filePath), p),
27
+ );
28
+ }
13
29
  }
14
30
 
15
31
  // Rewrites urls to be relative to the provided filename
@@ -19,18 +35,8 @@ export async function load({config}: {|config: Config|}) {
19
35
  // This should enforce the config to be reloaded on every run as it's JS
20
36
  let isDynamic = configFile && path.extname(configFile.filePath) === '.js';
21
37
  if (isDynamic) {
22
- config.shouldInvalidateOnStartup();
23
- config.shouldReload();
38
+ config.invalidateOnStartup();
24
39
  }
25
40
 
26
- return config.setResult({isStatic: !isDynamic, config: configContents});
27
- }
28
-
29
- export function preSerialize(config: Config) {
30
- if (!config.result) return;
31
-
32
- // Ensure we dont pass functions to the serialiser
33
- if (!config.result.isStatic) {
34
- config.result.config = {};
35
- }
41
+ return {isStatic: !isDynamic, config: configContents};
36
42
  }