@parcel/transformer-less 2.0.0-nightly.142 → 2.0.0-nightly.1421

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 = 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,45 @@ 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
94
  exports.default = _default;
66
-
67
95
  function urlPlugin({
68
96
  asset
69
97
  }) {
70
98
  return {
71
99
  install(less, pluginManager) {
100
+ // This is a hack; no such interface exists, even conceptually, in Less.
101
+
72
102
  const visitor = new less.visitors.Visitor({
73
103
  visitUrl(node) {
74
- node.value.value = asset.addURLDependency(node.value.value, node.currentFileInfo.filename);
104
+ const valueNode = node.value;
105
+ const stringValue = valueNode.value;
106
+ if (!stringValue.startsWith('#') // IE's `behavior: url(#default#VML)`)
107
+ ) {
108
+ valueNode.value = asset.addURLDependency(stringValue, {});
109
+ }
75
110
  return node;
76
111
  }
77
-
78
112
  });
113
+
114
+ // $FlowFixMe[method-unbinding]
79
115
  visitor.run = visitor.visit;
80
116
  pluginManager.addVisitor(visitor);
81
117
  }
82
-
83
118
  };
84
119
  }
85
-
86
120
  function resolvePathPlugin({
87
121
  asset,
88
122
  resolve
@@ -93,35 +127,63 @@ function resolvePathPlugin({
93
127
  supports() {
94
128
  return true;
95
129
  }
96
-
97
130
  supportsSync() {
98
131
  return false;
99
132
  }
100
-
101
- async loadFile(rawFilename, ...args) {
133
+ async loadFile(rawFilename, currentDirectory, options) {
102
134
  let filename = rawFilename;
103
-
104
135
  if (WEBPACK_ALIAS_RE.test(filename)) {
105
136
  let correctPath = filename.replace(/^~/, '');
106
137
  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
138
  }
108
139
 
109
- try {
110
- return await super.loadFile(filename, ...args);
111
- } catch (err) {
112
- if (err.type !== 'File') {
113
- throw err;
140
+ // Based on https://github.com/less/less.js/blob/master/packages/less/src/less-node/file-manager.js
141
+ let isAbsoluteFilename = this.isPathAbsolute(filename);
142
+ let paths = isAbsoluteFilename ? [''] : [currentDirectory];
143
+ if (options.paths) {
144
+ paths.push(...options.paths);
145
+ }
146
+ let prefixes = options.prefixes || [''];
147
+ let fileParts = this.extractUrlParts(filename);
148
+ let filePath;
149
+ let contents;
150
+ if (filename[0] !== '~') {
151
+ outer: for (let p of paths) {
152
+ for (let prefix of prefixes) {
153
+ filePath = fileParts.rawPath + prefix + fileParts.filename;
154
+ if (p) {
155
+ filePath = _path().default.join(p, filePath);
156
+ }
157
+ if (options.ext) {
158
+ filePath = this.tryAppendExtension(filePath, options.ext);
159
+ }
160
+ try {
161
+ contents = await asset.fs.readFile(filePath, 'utf8');
162
+ break outer;
163
+ } catch (err) {
164
+ asset.invalidateOnFileCreate({
165
+ filePath
166
+ });
167
+ }
168
+ }
114
169
  }
115
-
116
- filename = await resolve(asset.filePath, filename);
117
- return super.loadFile(filename, ...args);
118
170
  }
171
+ if (!contents) {
172
+ filePath = await resolve(asset.filePath, filename, {
173
+ packageConditions: ['less', 'style']
174
+ });
175
+ contents = await asset.fs.readFile(filePath, 'utf8');
176
+ }
177
+ if (filePath) {
178
+ asset.invalidateOnFileChange(filePath);
179
+ }
180
+ return {
181
+ contents,
182
+ filename: filePath
183
+ };
119
184
  }
120
-
121
185
  }
122
-
123
186
  pluginManager.addFileManager(new LessFileManager());
124
187
  }
125
-
126
188
  };
127
189
  }
@@ -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.142+c87c29dd",
3
+ "version": "2.0.0-nightly.1421+a1391ed8a",
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.1419+a1391ed8a"
17
21
  },
18
22
  "dependencies": {
19
- "@parcel/plugin": "2.0.0-nightly.142+c87c29dd"
20
- },
21
- "devDependencies": {
22
- "less": "^3.9.0"
23
+ "@parcel/plugin": "2.0.0-nightly.1421+a1391ed8a",
24
+ "@parcel/source-map": "^2.1.1",
25
+ "less": "^4.1.1"
23
26
  },
24
- "gitHead": "c87c29dd9ca09832e9677bb4d914d2e64bb2d5b8"
27
+ "gitHead": "a1391ed8a719fc2f976dbadb528ca2dcffa7da12"
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
+ }