@parcel/transformer-less 2.0.0-nightly.149 → 2.0.0-nightly.1490

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.
@@ -4,46 +4,71 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
- var _plugin = require("@parcel/plugin");
9
-
7
+ function _path() {
8
+ const data = _interopRequireDefault(require("path"));
9
+ _path = function () {
10
+ return data;
11
+ };
12
+ return data;
13
+ }
14
+ function _plugin() {
15
+ const data = require("@parcel/plugin");
16
+ _plugin = function () {
17
+ return data;
18
+ };
19
+ return data;
20
+ }
21
+ function _sourceMap() {
22
+ const data = _interopRequireDefault(require("@parcel/source-map"));
23
+ _sourceMap = function () {
24
+ return data;
25
+ };
26
+ return data;
27
+ }
28
+ function _less() {
29
+ const data = _interopRequireDefault(require("less"));
30
+ _less = function () {
31
+ return data;
32
+ };
33
+ return data;
34
+ }
35
+ var _loadConfig = require("./loadConfig");
36
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
37
  // E.g: ~library/file.less
11
38
  const WEBPACK_ALIAS_RE = /^~[^/]/;
12
-
13
- var _default = new _plugin.Transformer({
14
- async getConfig({
15
- asset,
16
- resolve
39
+ var _default = exports.default = new (_plugin().Transformer)({
40
+ loadConfig({
41
+ config
17
42
  }) {
18
- let config = await asset.getConfig(['.lessrc', '.lessrc.js'], {
19
- packageKey: 'less'
43
+ return (0, _loadConfig.load)({
44
+ config
20
45
  });
21
-
22
- if (config === null) {
23
- config = {};
24
- }
25
-
26
- config.filename = asset.filePath;
27
- config.plugins = [...(config.plugins || []), urlPlugin({
28
- asset
29
- }), resolvePathPlugin({
30
- asset,
31
- resolve
32
- })];
33
- return config;
34
46
  },
35
-
36
47
  async transform({
37
48
  asset,
38
49
  options,
39
- config
50
+ config,
51
+ resolve
40
52
  }) {
41
- const less = await options.packageManager.require('less', asset.filePath);
42
- const code = await asset.getCode();
43
- let css;
44
-
53
+ asset.type = 'css';
54
+ asset.meta.hasDependencies = false;
55
+ let code = await asset.getCode();
56
+ let result;
45
57
  try {
46
- css = (await less.render(code, config)).css;
58
+ let lessConfig = config ? {
59
+ ...config.config
60
+ } : {};
61
+ if (asset.env.sourceMap) {
62
+ lessConfig.sourceMap = {};
63
+ }
64
+ lessConfig.filename = asset.filePath;
65
+ lessConfig.plugins = [...(lessConfig.plugins || []), urlPlugin({
66
+ asset
67
+ }), resolvePathPlugin({
68
+ asset,
69
+ resolve
70
+ })];
71
+ result = await _less().default.render(code, lessConfig);
47
72
  } catch (err) {
48
73
  // For the error reporter
49
74
  err.fileName = err.filename;
@@ -53,36 +78,44 @@ var _default = new _plugin.Transformer({
53
78
  };
54
79
  throw err;
55
80
  }
56
-
57
- asset.type = 'css';
58
- asset.setCode(css);
59
- asset.meta.hasDependencies = false;
81
+ if (result.map != null) {
82
+ let map = new (_sourceMap().default)(options.projectRoot);
83
+ let rawMap = JSON.parse(result.map);
84
+ map.addVLQMap({
85
+ ...rawMap,
86
+ sources: rawMap.sources.map(s => _path().default.relative(options.projectRoot, s))
87
+ });
88
+ asset.setMap(map);
89
+ }
90
+ asset.setCode(result.css);
60
91
  return [asset];
61
92
  }
62
-
63
93
  });
64
-
65
- exports.default = _default;
66
-
67
94
  function urlPlugin({
68
95
  asset
69
96
  }) {
70
97
  return {
71
98
  install(less, pluginManager) {
99
+ // This is a hack; no such interface exists, even conceptually, in Less.
100
+
72
101
  const visitor = new less.visitors.Visitor({
73
102
  visitUrl(node) {
74
- node.value.value = asset.addURLDependency(node.value.value, node.currentFileInfo.filename);
103
+ const valueNode = node.value;
104
+ const stringValue = valueNode.value;
105
+ if (!stringValue.startsWith('#') // IE's `behavior: url(#default#VML)`)
106
+ ) {
107
+ valueNode.value = asset.addURLDependency(stringValue, {});
108
+ }
75
109
  return node;
76
110
  }
77
-
78
111
  });
112
+
113
+ // $FlowFixMe[method-unbinding]
79
114
  visitor.run = visitor.visit;
80
115
  pluginManager.addVisitor(visitor);
81
116
  }
82
-
83
117
  };
84
118
  }
85
-
86
119
  function resolvePathPlugin({
87
120
  asset,
88
121
  resolve
@@ -93,35 +126,63 @@ function resolvePathPlugin({
93
126
  supports() {
94
127
  return true;
95
128
  }
96
-
97
129
  supportsSync() {
98
130
  return false;
99
131
  }
100
-
101
- async loadFile(rawFilename, ...args) {
132
+ async loadFile(rawFilename, currentDirectory, options) {
102
133
  let filename = rawFilename;
103
-
104
134
  if (WEBPACK_ALIAS_RE.test(filename)) {
105
135
  let correctPath = filename.replace(/^~/, '');
106
136
  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}"`);
107
137
  }
108
138
 
109
- try {
110
- return await super.loadFile(filename, ...args);
111
- } catch (err) {
112
- if (err.type !== 'File') {
113
- throw err;
139
+ // Based on https://github.com/less/less.js/blob/master/packages/less/src/less-node/file-manager.js
140
+ let isAbsoluteFilename = this.isPathAbsolute(filename);
141
+ let paths = isAbsoluteFilename ? [''] : [currentDirectory];
142
+ if (options.paths) {
143
+ paths.push(...options.paths);
144
+ }
145
+ let prefixes = options.prefixes || [''];
146
+ let fileParts = this.extractUrlParts(filename);
147
+ let filePath;
148
+ let contents;
149
+ if (filename[0] !== '~') {
150
+ outer: for (let p of paths) {
151
+ for (let prefix of prefixes) {
152
+ filePath = fileParts.rawPath + prefix + fileParts.filename;
153
+ if (p) {
154
+ filePath = _path().default.join(p, filePath);
155
+ }
156
+ if (options.ext) {
157
+ filePath = this.tryAppendExtension(filePath, options.ext);
158
+ }
159
+ try {
160
+ contents = await asset.fs.readFile(filePath, 'utf8');
161
+ break outer;
162
+ } catch (err) {
163
+ asset.invalidateOnFileCreate({
164
+ filePath
165
+ });
166
+ }
167
+ }
114
168
  }
115
-
116
- filename = await resolve(asset.filePath, filename);
117
- return super.loadFile(filename, ...args);
118
169
  }
170
+ if (!contents) {
171
+ filePath = await resolve(asset.filePath, filename, {
172
+ packageConditions: ['less', 'style']
173
+ });
174
+ contents = await asset.fs.readFile(filePath, 'utf8');
175
+ }
176
+ if (filePath) {
177
+ asset.invalidateOnFileChange(filePath);
178
+ }
179
+ return {
180
+ contents,
181
+ filename: filePath
182
+ };
119
183
  }
120
-
121
184
  }
122
-
123
185
  pluginManager.addFileManager(new LessFileManager());
124
186
  }
125
-
126
187
  };
127
188
  }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.load = load;
7
+ function _path() {
8
+ const data = _interopRequireDefault(require("path"));
9
+ _path = function () {
10
+ return data;
11
+ };
12
+ return data;
13
+ }
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+ async function load({
16
+ config
17
+ }) {
18
+ let configFile = await config.getConfig(['.lessrc', '.lessrc.js', '.lessrc.cjs', '.lessrc.mjs'], {
19
+ packageKey: 'less'
20
+ });
21
+ let configContents = {};
22
+ if (configFile != null) {
23
+ configContents = configFile.contents;
24
+
25
+ // Resolve relative paths from config file
26
+ if (configContents.paths) {
27
+ configContents.paths = configContents.paths.map(p => _path().default.resolve(_path().default.dirname(configFile.filePath), p));
28
+ }
29
+ }
30
+
31
+ // Rewrites urls to be relative to the provided filename
32
+ configContents.rewriteUrls = 'all';
33
+ configContents.plugins = configContents.plugins || [];
34
+ return {
35
+ config: configContents
36
+ };
37
+ }
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "@parcel/transformer-less",
3
- "version": "2.0.0-nightly.149+453f7b0b",
3
+ "version": "2.0.0-nightly.1490+642d9cabc",
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,14 +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.1488+642d9cabc"
17
21
  },
18
22
  "dependencies": {
19
- "@parcel/plugin": "2.0.0-nightly.149+453f7b0b"
20
- },
21
- "devDependencies": {
22
- "less": "^3.9.0"
23
+ "@parcel/plugin": "2.0.0-nightly.1490+642d9cabc",
24
+ "@parcel/source-map": "^2.1.1",
25
+ "less": "^4.1.1"
23
26
  },
24
- "gitHead": "453f7b0bf295e6a7cbec5d24fab4c48e21e6168f"
27
+ "gitHead": "642d9cabc600bcb4681bbee0be168e05f5a8ffe5"
25
28
  }
@@ -1,36 +1,48 @@
1
- // @flow strict-local
2
-
1
+ // @flow
2
+ import {typeof default as Less} from 'less';
3
+ import path from 'path';
3
4
  import {Transformer} from '@parcel/plugin';
5
+ import SourceMap from '@parcel/source-map';
6
+ import less from 'less';
7
+
8
+ import {load} from './loadConfig';
4
9
 
5
10
  // E.g: ~library/file.less
6
11
  const WEBPACK_ALIAS_RE = /^~[^/]/;
7
12
 
8
- export default new Transformer({
9
- async getConfig({asset, resolve}) {
10
- let config = await asset.getConfig(['.lessrc', '.lessrc.js'], {
11
- packageKey: 'less',
12
- });
13
-
14
- if (config === null) {
15
- config = {};
16
- }
13
+ type LessConfig = {
14
+ sourceMap: any,
15
+ filename: string,
16
+ plugins: Array<any>,
17
+ ...
18
+ };
17
19
 
18
- config.filename = asset.filePath;
19
- config.plugins = [
20
- ...(config.plugins || []),
21
- urlPlugin({asset}),
22
- resolvePathPlugin({asset, resolve}),
23
- ];
24
-
25
- return config;
20
+ export default (new Transformer({
21
+ loadConfig({config}) {
22
+ return load({config});
26
23
  },
27
24
 
28
- async transform({asset, options, config}) {
29
- const less = await options.packageManager.require('less', asset.filePath);
30
- const code = await asset.getCode();
31
- let css;
25
+ async transform({asset, options, config, resolve}) {
26
+ asset.type = 'css';
27
+ asset.meta.hasDependencies = false;
28
+
29
+ let code = await asset.getCode();
30
+ let result;
32
31
  try {
33
- css = (await less.render(code, config)).css;
32
+ let lessConfig: LessConfig = config ? {...config.config} : {};
33
+
34
+ if (asset.env.sourceMap) {
35
+ lessConfig.sourceMap = {};
36
+ }
37
+
38
+ lessConfig.filename = asset.filePath;
39
+ lessConfig.plugins = [
40
+ ...(lessConfig.plugins || []),
41
+ urlPlugin({asset}),
42
+ resolvePathPlugin({asset, resolve}),
43
+ ];
44
+
45
+ result = await less.render(code, lessConfig);
34
46
  } catch (err) {
35
47
  // For the error reporter
36
48
  err.fileName = err.filename;
@@ -41,26 +53,42 @@ export default new Transformer({
41
53
  throw err;
42
54
  }
43
55
 
44
- asset.type = 'css';
45
- asset.setCode(css);
46
- asset.meta.hasDependencies = false;
56
+ if (result.map != null) {
57
+ let map = new SourceMap(options.projectRoot);
58
+ let rawMap = JSON.parse(result.map);
59
+ map.addVLQMap({
60
+ ...rawMap,
61
+ sources: rawMap.sources.map(s => path.relative(options.projectRoot, s)),
62
+ });
63
+ asset.setMap(map);
64
+ }
65
+
66
+ asset.setCode(result.css);
67
+
47
68
  return [asset];
48
69
  },
49
- });
70
+ }): Transformer);
50
71
 
51
72
  function urlPlugin({asset}) {
52
73
  return {
53
- 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
+
54
78
  const visitor = new less.visitors.Visitor({
55
79
  visitUrl(node) {
56
- node.value.value = asset.addURLDependency(
57
- node.value.value,
58
- node.currentFileInfo.filename,
59
- );
80
+ const valueNode = ((node.value: any): LessNodeWithValue);
81
+ const stringValue = (valueNode.value: string);
82
+ if (
83
+ !stringValue.startsWith('#') // IE's `behavior: url(#default#VML)`)
84
+ ) {
85
+ valueNode.value = asset.addURLDependency(stringValue, {});
86
+ }
60
87
  return node;
61
88
  },
62
89
  });
63
90
 
91
+ // $FlowFixMe[method-unbinding]
64
92
  visitor.run = visitor.visit;
65
93
  pluginManager.addVisitor(visitor);
66
94
  },
@@ -79,7 +107,7 @@ function resolvePathPlugin({asset, resolve}) {
79
107
  return false;
80
108
  }
81
109
 
82
- async loadFile(rawFilename, ...args) {
110
+ async loadFile(rawFilename, currentDirectory, options) {
83
111
  let filename = rawFilename;
84
112
 
85
113
  if (WEBPACK_ALIAS_RE.test(filename)) {
@@ -89,15 +117,55 @@ function resolvePathPlugin({asset, resolve}) {
89
117
  );
90
118
  }
91
119
 
92
- try {
93
- return await super.loadFile(filename, ...args);
94
- } catch (err) {
95
- if (err.type !== 'File') {
96
- 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
+ }
97
151
  }
98
- filename = await resolve(asset.filePath, filename);
99
- return super.loadFile(filename, ...args);
100
152
  }
153
+
154
+ if (!contents) {
155
+ filePath = await resolve(asset.filePath, filename, {
156
+ packageConditions: ['less', 'style'],
157
+ });
158
+ contents = await asset.fs.readFile(filePath, 'utf8');
159
+ }
160
+
161
+ if (filePath) {
162
+ asset.invalidateOnFileChange(filePath);
163
+ }
164
+
165
+ return {
166
+ contents,
167
+ filename: filePath,
168
+ };
101
169
  }
102
170
  }
103
171
 
@@ -0,0 +1,38 @@
1
+ // @flow
2
+ import type {Config} from '@parcel/types';
3
+ import path from 'path';
4
+
5
+ type ConfigResult = {|
6
+ config: any,
7
+ |};
8
+
9
+ export async function load({
10
+ config,
11
+ }: {|
12
+ config: Config,
13
+ |}): Promise<ConfigResult> {
14
+ let configFile = await config.getConfig(
15
+ ['.lessrc', '.lessrc.js', '.lessrc.cjs', '.lessrc.mjs'],
16
+ {
17
+ packageKey: 'less',
18
+ },
19
+ );
20
+
21
+ let configContents = {};
22
+ if (configFile != null) {
23
+ configContents = configFile.contents;
24
+
25
+ // Resolve relative paths from config file
26
+ if (configContents.paths) {
27
+ configContents.paths = configContents.paths.map(p =>
28
+ path.resolve(path.dirname(configFile.filePath), p),
29
+ );
30
+ }
31
+ }
32
+
33
+ // Rewrites urls to be relative to the provided filename
34
+ configContents.rewriteUrls = 'all';
35
+ configContents.plugins = configContents.plugins || [];
36
+
37
+ return {config: configContents};
38
+ }