@atlaspack/transformer-postcss 2.12.1-canary.3354
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.
- package/LICENSE +201 -0
- package/lib/PostCSSTransformer.js +346 -0
- package/lib/constants.js +7 -0
- package/lib/loadConfig.js +162 -0
- package/lib/loadPlugins.js +29 -0
- package/package.json +33 -0
- package/src/PostCSSTransformer.js +342 -0
- package/src/constants.js +3 -0
- package/src/loadConfig.js +215 -0
- package/src/loadPlugins.js +69 -0
|
@@ -0,0 +1,162 @@
|
|
|
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 _diagnostic() {
|
|
15
|
+
const data = require("@atlaspack/diagnostic");
|
|
16
|
+
_diagnostic = function () {
|
|
17
|
+
return data;
|
|
18
|
+
};
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
21
|
+
function _nullthrows() {
|
|
22
|
+
const data = _interopRequireDefault(require("nullthrows"));
|
|
23
|
+
_nullthrows = function () {
|
|
24
|
+
return data;
|
|
25
|
+
};
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
function _clone() {
|
|
29
|
+
const data = _interopRequireDefault(require("clone"));
|
|
30
|
+
_clone = function () {
|
|
31
|
+
return data;
|
|
32
|
+
};
|
|
33
|
+
return data;
|
|
34
|
+
}
|
|
35
|
+
var _constants = require("./constants");
|
|
36
|
+
var _loadPlugins = _interopRequireDefault(require("./loadPlugins"));
|
|
37
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
38
|
+
async function configHydrator(configFile, config, resolveFrom, options, logger) {
|
|
39
|
+
if (configFile == null) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Load the custom config...
|
|
44
|
+
let modulesConfig;
|
|
45
|
+
let configFilePlugins = (0, _clone().default)(configFile.plugins);
|
|
46
|
+
if (configFilePlugins != null && typeof configFilePlugins === 'object' && configFilePlugins['postcss-modules'] != null) {
|
|
47
|
+
modulesConfig = configFilePlugins['postcss-modules'];
|
|
48
|
+
delete configFilePlugins['postcss-modules'];
|
|
49
|
+
}
|
|
50
|
+
if (!modulesConfig && configFile.modules) {
|
|
51
|
+
modulesConfig = {};
|
|
52
|
+
}
|
|
53
|
+
let plugins = await (0, _loadPlugins.default)(configFilePlugins, (0, _nullthrows().default)(resolveFrom), options);
|
|
54
|
+
|
|
55
|
+
// contents is either:
|
|
56
|
+
// from JSON: { plugins: { 'postcss-foo': { ...opts } } }
|
|
57
|
+
// from JS (v8): { plugins: [ { postcssPlugin: 'postcss-foo', ...visitor callback functions } ]
|
|
58
|
+
// from JS (v7): { plugins: [ [Function: ...] ]
|
|
59
|
+
let pluginArray = Array.isArray(configFilePlugins) ? configFilePlugins : Object.keys(configFilePlugins);
|
|
60
|
+
for (let p of pluginArray) {
|
|
61
|
+
if (typeof p === 'string') {
|
|
62
|
+
config.addDevDependency({
|
|
63
|
+
specifier: p,
|
|
64
|
+
resolveFrom: (0, _nullthrows().default)(resolveFrom)
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
let redundantPlugins = pluginArray.filter(p => p === 'autoprefixer' || p === 'postcss-preset-env');
|
|
69
|
+
if (redundantPlugins.length > 0) {
|
|
70
|
+
let filename = _path().default.basename(resolveFrom);
|
|
71
|
+
let isPackageJson = filename === 'package.json';
|
|
72
|
+
let message;
|
|
73
|
+
let hints = [];
|
|
74
|
+
if (!isPackageJson && redundantPlugins.length === pluginArray.length) {
|
|
75
|
+
message = (0, _diagnostic().md)`Atlaspack includes CSS transpilation and vendor prefixing by default. PostCSS config __${filename}__ contains only redundant plugins. Deleting it may significantly improve build performance.`;
|
|
76
|
+
hints.push((0, _diagnostic().md)`Delete __${filename}__`);
|
|
77
|
+
} else {
|
|
78
|
+
message = (0, _diagnostic().md)`Atlaspack includes CSS transpilation and vendor prefixing by default. PostCSS config __${filename}__ contains the following redundant plugins: ${[...redundantPlugins].map(p => _diagnostic().md.underline(p))}. Removing these may improve build performance.`;
|
|
79
|
+
hints.push((0, _diagnostic().md)`Remove the above plugins from __${filename}__`);
|
|
80
|
+
}
|
|
81
|
+
let codeFrames;
|
|
82
|
+
if (_path().default.extname(filename) !== '.js') {
|
|
83
|
+
let contents = await options.inputFS.readFile(resolveFrom, 'utf8');
|
|
84
|
+
let prefix = isPackageJson ? '/postcss' : '';
|
|
85
|
+
codeFrames = [{
|
|
86
|
+
language: 'json',
|
|
87
|
+
filePath: resolveFrom,
|
|
88
|
+
code: contents,
|
|
89
|
+
codeHighlights: (0, _diagnostic().generateJSONCodeHighlights)(contents, redundantPlugins.map(plugin => ({
|
|
90
|
+
key: `${prefix}/plugins/${plugin}`,
|
|
91
|
+
type: 'key'
|
|
92
|
+
})))
|
|
93
|
+
}];
|
|
94
|
+
} else {
|
|
95
|
+
codeFrames = [{
|
|
96
|
+
filePath: resolveFrom,
|
|
97
|
+
codeHighlights: [{
|
|
98
|
+
start: {
|
|
99
|
+
line: 1,
|
|
100
|
+
column: 1
|
|
101
|
+
},
|
|
102
|
+
end: {
|
|
103
|
+
line: 1,
|
|
104
|
+
column: 1
|
|
105
|
+
}
|
|
106
|
+
}]
|
|
107
|
+
}];
|
|
108
|
+
}
|
|
109
|
+
logger.warn({
|
|
110
|
+
message,
|
|
111
|
+
hints,
|
|
112
|
+
documentationURL: 'https://parceljs.org/languages/css/#default-plugins',
|
|
113
|
+
codeFrames
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
raw: configFile,
|
|
118
|
+
filePath: resolveFrom,
|
|
119
|
+
hydrated: {
|
|
120
|
+
plugins,
|
|
121
|
+
from: config.searchPath,
|
|
122
|
+
to: config.searchPath,
|
|
123
|
+
modules: modulesConfig
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
async function load({
|
|
128
|
+
config,
|
|
129
|
+
options,
|
|
130
|
+
logger
|
|
131
|
+
}) {
|
|
132
|
+
if (!config.isSource) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
let configFile = await config.getConfig(['.postcssrc', '.postcssrc.json', '.postcssrc.js', '.postcssrc.cjs', '.postcssrc.mjs', 'postcss.config.js', 'postcss.config.cjs', 'postcss.config.mjs'], {
|
|
136
|
+
packageKey: 'postcss'
|
|
137
|
+
});
|
|
138
|
+
let contents = null;
|
|
139
|
+
if (configFile) {
|
|
140
|
+
config.addDevDependency({
|
|
141
|
+
specifier: 'postcss',
|
|
142
|
+
resolveFrom: config.searchPath,
|
|
143
|
+
range: _constants.POSTCSS_RANGE
|
|
144
|
+
});
|
|
145
|
+
contents = configFile.contents;
|
|
146
|
+
let isDynamic = configFile && _path().default.extname(configFile.filePath).endsWith('js');
|
|
147
|
+
if (isDynamic) {
|
|
148
|
+
// We have to invalidate on startup in case the config is non-deterministic,
|
|
149
|
+
// e.g. using unknown environment variables, reading from the filesystem, etc.
|
|
150
|
+
logger.warn({
|
|
151
|
+
message: 'WARNING: Using a JavaScript PostCSS config file means losing out on caching features of Atlaspack. Use a .postcssrc(.json) file whenever possible.'
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
if (typeof contents !== 'object') {
|
|
155
|
+
throw new Error('PostCSS config should be an object.');
|
|
156
|
+
}
|
|
157
|
+
if (contents.plugins == null || typeof contents.plugins !== 'object' || Object.keys(contents.plugins).length === 0) {
|
|
158
|
+
throw new Error('PostCSS config must have plugins');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return configHydrator(contents, config, configFile === null || configFile === void 0 ? void 0 : configFile.filePath, options, logger);
|
|
162
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = loadExternalPlugins;
|
|
7
|
+
async function loadExternalPlugins(plugins, relative, options) {
|
|
8
|
+
if (Array.isArray(plugins)) {
|
|
9
|
+
return Promise.all(plugins.map(p => loadPlugin(p, relative, null, options.packageManager, options.shouldAutoInstall)).filter(Boolean));
|
|
10
|
+
} else if (typeof plugins === 'object') {
|
|
11
|
+
let mapPlugins = await Promise.all(Object.keys(plugins).map(p => loadPlugin(p, relative, plugins[p], options.packageManager, options.shouldAutoInstall)));
|
|
12
|
+
return mapPlugins.filter(Boolean);
|
|
13
|
+
} else {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async function loadPlugin(pluginArg, relative, options = {}, packageManager, shouldAutoInstall) {
|
|
18
|
+
if (typeof pluginArg !== 'string') {
|
|
19
|
+
return pluginArg;
|
|
20
|
+
}
|
|
21
|
+
let plugin = await packageManager.require(pluginArg, relative, {
|
|
22
|
+
shouldAutoInstall
|
|
23
|
+
});
|
|
24
|
+
plugin = plugin.default || plugin;
|
|
25
|
+
if (options != null && typeof options === 'object' && Object.keys(options).length > 0) {
|
|
26
|
+
plugin = plugin(options);
|
|
27
|
+
}
|
|
28
|
+
return plugin.default || plugin;
|
|
29
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaspack/transformer-postcss",
|
|
3
|
+
"version": "2.12.1-canary.3354+7bb54d46a",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/atlassian-labs/atlaspack.git"
|
|
11
|
+
},
|
|
12
|
+
"main": "lib/PostCSSTransformer.js",
|
|
13
|
+
"source": "src/PostCSSTransformer.js",
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">= 16.0.0",
|
|
16
|
+
"atlaspack": "2.12.1-canary.3354+7bb54d46a"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@atlaspack/diagnostic": "2.12.1-canary.3354+7bb54d46a",
|
|
20
|
+
"@atlaspack/plugin": "2.12.1-canary.3354+7bb54d46a",
|
|
21
|
+
"@atlaspack/rust": "2.12.1-canary.3354+7bb54d46a",
|
|
22
|
+
"@atlaspack/utils": "2.12.1-canary.3354+7bb54d46a",
|
|
23
|
+
"clone": "^2.1.1",
|
|
24
|
+
"nullthrows": "^1.1.1",
|
|
25
|
+
"postcss-value-parser": "^4.2.0",
|
|
26
|
+
"semver": "^7.5.2"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"postcss": "^8.4.5",
|
|
30
|
+
"postcss-modules": "^4.3.1"
|
|
31
|
+
},
|
|
32
|
+
"gitHead": "7bb54d46a00c5ba9cdbc2ee426dcbe82c8d79a3e"
|
|
33
|
+
}
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
FilePath,
|
|
5
|
+
Asset,
|
|
6
|
+
MutableAsset,
|
|
7
|
+
PluginOptions,
|
|
8
|
+
} from '@atlaspack/types';
|
|
9
|
+
|
|
10
|
+
import {hashString} from '@atlaspack/rust';
|
|
11
|
+
import {glob} from '@atlaspack/utils';
|
|
12
|
+
import {Transformer} from '@atlaspack/plugin';
|
|
13
|
+
import nullthrows from 'nullthrows';
|
|
14
|
+
import path from 'path';
|
|
15
|
+
import semver from 'semver';
|
|
16
|
+
import valueParser from 'postcss-value-parser';
|
|
17
|
+
import typeof * as Postcss from 'postcss';
|
|
18
|
+
|
|
19
|
+
import {load} from './loadConfig';
|
|
20
|
+
import {POSTCSS_RANGE} from './constants';
|
|
21
|
+
import {md, generateJSONCodeHighlights} from '@atlaspack/diagnostic';
|
|
22
|
+
|
|
23
|
+
const COMPOSES_RE = /composes:.+from\s*("|').*("|')\s*;?/;
|
|
24
|
+
const FROM_IMPORT_RE = /.+from\s*(?:"|')(.*)(?:"|')\s*;?/;
|
|
25
|
+
const LEGACY_MODULE_RE = /@value|:export|(:global|:local|:import)(?!\s*\()/i;
|
|
26
|
+
const MODULE_BY_NAME_RE = /\.module\./;
|
|
27
|
+
|
|
28
|
+
export default (new Transformer({
|
|
29
|
+
loadConfig({config, options, logger}) {
|
|
30
|
+
return load({config, options, logger});
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
canReuseAST({ast}) {
|
|
34
|
+
return (
|
|
35
|
+
ast.type === 'postcss' && semver.satisfies(ast.version, POSTCSS_RANGE)
|
|
36
|
+
);
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
async parse({asset, config, options}) {
|
|
40
|
+
let isLegacy = await isLegacyCssModule(asset);
|
|
41
|
+
if (!config && !isLegacy) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const postcss = await loadPostcss(options, asset.filePath);
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
type: 'postcss',
|
|
49
|
+
version: '8.2.1',
|
|
50
|
+
program: postcss
|
|
51
|
+
.parse(await asset.getCode(), {
|
|
52
|
+
from: asset.filePath,
|
|
53
|
+
})
|
|
54
|
+
.toJSON(),
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
async transform({asset, config, options, resolve, logger}) {
|
|
59
|
+
asset.type = 'css';
|
|
60
|
+
let isLegacy = await isLegacyCssModule(asset);
|
|
61
|
+
if (isLegacy && !config) {
|
|
62
|
+
config = {
|
|
63
|
+
raw: {},
|
|
64
|
+
filePath: '',
|
|
65
|
+
hydrated: {
|
|
66
|
+
plugins: [],
|
|
67
|
+
from: asset.filePath,
|
|
68
|
+
to: asset.filePath,
|
|
69
|
+
modules: {},
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// TODO: warning?
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!config) {
|
|
77
|
+
return [asset];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const postcss: Postcss = await loadPostcss(options, asset.filePath);
|
|
81
|
+
let ast = nullthrows(await asset.getAST());
|
|
82
|
+
let program = postcss.fromJSON(ast.program);
|
|
83
|
+
|
|
84
|
+
let plugins = [...config.hydrated.plugins];
|
|
85
|
+
let cssModules: ?{|[string]: string|} = null;
|
|
86
|
+
if (config.hydrated.modules) {
|
|
87
|
+
asset.meta.cssModulesCompiled = 'postcss';
|
|
88
|
+
|
|
89
|
+
let code = asset.isASTDirty() ? null : await asset.getCode();
|
|
90
|
+
if (
|
|
91
|
+
Object.keys(config.hydrated.modules).length === 0 &&
|
|
92
|
+
code &&
|
|
93
|
+
!isLegacy &&
|
|
94
|
+
!LEGACY_MODULE_RE.test(code)
|
|
95
|
+
) {
|
|
96
|
+
let filename = path.basename(config.filePath);
|
|
97
|
+
let message;
|
|
98
|
+
let configKey;
|
|
99
|
+
let hint;
|
|
100
|
+
if (config.raw.modules) {
|
|
101
|
+
message = md`The "modules" option in __${filename}__ can be replaced with configuration for @atlaspack/transformer-css to improve build performance.`;
|
|
102
|
+
configKey = '/modules';
|
|
103
|
+
hint = md`Remove the "modules" option from __${filename}__`;
|
|
104
|
+
} else {
|
|
105
|
+
message = md`The "postcss-modules" plugin in __${filename}__ can be replaced with configuration for @atlaspack/transformer-css to improve build performance.`;
|
|
106
|
+
configKey = '/plugins/postcss-modules';
|
|
107
|
+
hint = md`Remove the "postcss-modules" plugin from __${filename}__`;
|
|
108
|
+
}
|
|
109
|
+
if (filename === 'package.json') {
|
|
110
|
+
configKey = `/postcss${configKey}`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let hints = [
|
|
114
|
+
'Enable the "cssModules" option for "@atlaspack/transformer-css" in your package.json',
|
|
115
|
+
];
|
|
116
|
+
if (plugins.length === 0) {
|
|
117
|
+
message += md` Since there are no other plugins, __${filename}__ can be deleted safely.`;
|
|
118
|
+
hints.push(md`Delete __${filename}__`);
|
|
119
|
+
} else {
|
|
120
|
+
hints.push(hint);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
let codeFrames;
|
|
124
|
+
if (path.extname(filename) !== '.js') {
|
|
125
|
+
let contents = await asset.fs.readFile(config.filePath, 'utf8');
|
|
126
|
+
codeFrames = [
|
|
127
|
+
{
|
|
128
|
+
language: 'json',
|
|
129
|
+
filePath: config.filePath,
|
|
130
|
+
code: contents,
|
|
131
|
+
codeHighlights: generateJSONCodeHighlights(contents, [
|
|
132
|
+
{
|
|
133
|
+
key: configKey,
|
|
134
|
+
type: 'key',
|
|
135
|
+
},
|
|
136
|
+
]),
|
|
137
|
+
},
|
|
138
|
+
];
|
|
139
|
+
} else {
|
|
140
|
+
codeFrames = [
|
|
141
|
+
{
|
|
142
|
+
filePath: config.filePath,
|
|
143
|
+
codeHighlights: [
|
|
144
|
+
{
|
|
145
|
+
start: {line: 1, column: 1},
|
|
146
|
+
end: {line: 1, column: 1},
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
logger.warn({
|
|
154
|
+
message,
|
|
155
|
+
hints,
|
|
156
|
+
documentationURL:
|
|
157
|
+
'https://parceljs.org/languages/css/#enabling-css-modules-globally',
|
|
158
|
+
codeFrames,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// TODO: should this be resolved from the project root?
|
|
163
|
+
let postcssModules = await options.packageManager.require(
|
|
164
|
+
'postcss-modules',
|
|
165
|
+
asset.filePath,
|
|
166
|
+
{
|
|
167
|
+
range: '^4.3.0',
|
|
168
|
+
saveDev: true,
|
|
169
|
+
shouldAutoInstall: options.shouldAutoInstall,
|
|
170
|
+
},
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
plugins.push(
|
|
174
|
+
postcssModules({
|
|
175
|
+
getJSON: (filename, json) => (cssModules = json),
|
|
176
|
+
Loader: await createLoader(asset, resolve, options),
|
|
177
|
+
generateScopedName: (name, filename) =>
|
|
178
|
+
`${name}_${hashString(
|
|
179
|
+
path.relative(options.projectRoot, filename),
|
|
180
|
+
).substr(0, 6)}`,
|
|
181
|
+
...config.hydrated.modules,
|
|
182
|
+
}),
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
if (code == null || COMPOSES_RE.test(code)) {
|
|
186
|
+
program.walkDecls(decl => {
|
|
187
|
+
let [, importPath] = FROM_IMPORT_RE.exec(decl.value) || [];
|
|
188
|
+
if (decl.prop === 'composes' && importPath != null) {
|
|
189
|
+
let parsed = valueParser(decl.value);
|
|
190
|
+
|
|
191
|
+
parsed.walk(node => {
|
|
192
|
+
if (node.type === 'string') {
|
|
193
|
+
asset.addDependency({
|
|
194
|
+
specifier: importPath,
|
|
195
|
+
specifierType: 'url',
|
|
196
|
+
loc: {
|
|
197
|
+
filePath: asset.filePath,
|
|
198
|
+
start: decl.source.start,
|
|
199
|
+
end: {
|
|
200
|
+
line: decl.source.start.line,
|
|
201
|
+
column: decl.source.start.column + importPath.length,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381
|
|
213
|
+
let {messages, root} = await postcss(plugins).process(
|
|
214
|
+
program,
|
|
215
|
+
config.hydrated,
|
|
216
|
+
);
|
|
217
|
+
asset.setAST({
|
|
218
|
+
type: 'postcss',
|
|
219
|
+
version: '8.2.1',
|
|
220
|
+
program: root.toJSON(),
|
|
221
|
+
});
|
|
222
|
+
for (let msg of messages) {
|
|
223
|
+
if (msg.type === 'dependency') {
|
|
224
|
+
asset.invalidateOnFileChange(msg.file);
|
|
225
|
+
} else if (msg.type === 'dir-dependency') {
|
|
226
|
+
let pattern = `${msg.dir}/${msg.glob ?? '**/*'}`;
|
|
227
|
+
let files = await glob(pattern, asset.fs, {onlyFiles: true});
|
|
228
|
+
for (let file of files) {
|
|
229
|
+
asset.invalidateOnFileChange(path.normalize(file));
|
|
230
|
+
}
|
|
231
|
+
asset.invalidateOnFileCreate({glob: pattern});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let assets = [asset];
|
|
236
|
+
if (cssModules) {
|
|
237
|
+
// $FlowFixMe
|
|
238
|
+
let cssModulesList = (Object.entries(cssModules): Array<
|
|
239
|
+
[string, string],
|
|
240
|
+
>);
|
|
241
|
+
let deps = asset.getDependencies().filter(dep => dep.priority === 'sync');
|
|
242
|
+
let code: string;
|
|
243
|
+
if (deps.length > 0) {
|
|
244
|
+
code = `
|
|
245
|
+
module.exports = Object.assign({}, ${deps
|
|
246
|
+
.map(dep => `require(${JSON.stringify(dep.specifier)})`)
|
|
247
|
+
.join(', ')}, ${JSON.stringify(cssModules, null, 2)});
|
|
248
|
+
`;
|
|
249
|
+
} else {
|
|
250
|
+
code = cssModulesList
|
|
251
|
+
.map(
|
|
252
|
+
// This syntax enables shaking the invidual statements, so that unused classes don't even exist in JS.
|
|
253
|
+
([className, classNameHashed]) =>
|
|
254
|
+
`module.exports[${JSON.stringify(className)}] = ${JSON.stringify(
|
|
255
|
+
classNameHashed,
|
|
256
|
+
)};`,
|
|
257
|
+
)
|
|
258
|
+
.join('\n');
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
asset.symbols.ensure();
|
|
262
|
+
for (let [k, v] of cssModulesList) {
|
|
263
|
+
asset.symbols.set(k, v);
|
|
264
|
+
}
|
|
265
|
+
asset.symbols.set('default', 'default');
|
|
266
|
+
|
|
267
|
+
assets.push({
|
|
268
|
+
type: 'js',
|
|
269
|
+
content: code,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
return assets;
|
|
273
|
+
},
|
|
274
|
+
|
|
275
|
+
async generate({asset, ast, options}) {
|
|
276
|
+
const postcss: Postcss = await loadPostcss(options, asset.filePath);
|
|
277
|
+
|
|
278
|
+
let code = '';
|
|
279
|
+
postcss.stringify(postcss.fromJSON(ast.program), c => {
|
|
280
|
+
code += c;
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
return {
|
|
284
|
+
content: code,
|
|
285
|
+
};
|
|
286
|
+
},
|
|
287
|
+
}): Transformer);
|
|
288
|
+
|
|
289
|
+
async function createLoader(
|
|
290
|
+
asset: MutableAsset,
|
|
291
|
+
resolve: (from: FilePath, to: string) => Promise<FilePath>,
|
|
292
|
+
options: PluginOptions,
|
|
293
|
+
) {
|
|
294
|
+
let {default: FileSystemLoader} = await options.packageManager.require(
|
|
295
|
+
'postcss-modules/build/css-loader-core/loader',
|
|
296
|
+
asset.filePath,
|
|
297
|
+
);
|
|
298
|
+
return class AtlaspackFileSystemLoader extends FileSystemLoader {
|
|
299
|
+
async fetch(composesPath, relativeTo) {
|
|
300
|
+
let importPath = composesPath.replace(/^["']|["']$/g, '');
|
|
301
|
+
let resolved = await resolve(relativeTo, importPath);
|
|
302
|
+
let rootRelativePath = path.resolve(path.dirname(relativeTo), resolved);
|
|
303
|
+
let root = path.resolve('/');
|
|
304
|
+
// fixes an issue on windows which is part of the css-modules-loader-core
|
|
305
|
+
// see https://github.com/css-modules/css-modules-loader-core/issues/230
|
|
306
|
+
if (rootRelativePath.startsWith(root)) {
|
|
307
|
+
rootRelativePath = rootRelativePath.substr(root.length);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
let source = await asset.fs.readFile(resolved, 'utf-8');
|
|
311
|
+
let {exportTokens} = await this.core.load(
|
|
312
|
+
source,
|
|
313
|
+
rootRelativePath,
|
|
314
|
+
undefined,
|
|
315
|
+
// $FlowFixMe[method-unbinding]
|
|
316
|
+
this.fetch.bind(this),
|
|
317
|
+
);
|
|
318
|
+
return exportTokens;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
get finalSource() {
|
|
322
|
+
return '';
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function loadPostcss(options: PluginOptions, from: FilePath): Promise<Postcss> {
|
|
328
|
+
return options.packageManager.require('postcss', from, {
|
|
329
|
+
range: POSTCSS_RANGE,
|
|
330
|
+
saveDev: true,
|
|
331
|
+
shouldAutoInstall: options.shouldAutoInstall,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
async function isLegacyCssModule(asset: Asset | MutableAsset) {
|
|
336
|
+
if (!MODULE_BY_NAME_RE.test(asset.filePath)) {
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
let code = await asset.getCode();
|
|
341
|
+
return LEGACY_MODULE_RE.test(code);
|
|
342
|
+
}
|
package/src/constants.js
ADDED