Skip to content

Commit

Permalink
feat: support postcss 8 (#114)
Browse files Browse the repository at this point in the history
* feat: support postcss 8

* deps: move postcss to peerDeps

* fix: use OnceExit
  • Loading branch information
yyx990803 committed Nov 29, 2020
1 parent 447e797 commit ff77512
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 168 deletions.
15 changes: 9 additions & 6 deletions package.json
Expand Up @@ -21,15 +21,17 @@
"generic-names": "^2.0.1",
"icss-replace-symbols": "^1.1.0",
"lodash.camelcase": "^4.3.0",
"postcss": "^7.0.32",
"postcss-modules-extract-imports": "^2.0.0",
"postcss-modules-local-by-default": "^3.0.2",
"postcss-modules-scope": "^2.2.0",
"postcss-modules-values": "^3.0.0",
"postcss-modules-extract-imports": "^3.0.0",
"postcss-modules-local-by-default": "^4.0.0",
"postcss-modules-scope": "^3.0.0",
"postcss-modules-values": "^4.0.0",
"string-hash": "^1.1.1"
},
"peerDependencies": {
"postcss": "^8.0.0"
},
"devDependencies": {
"autoprefixer": "^9.6.1",
"autoprefixer": "^10.0.2",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-eslint": "^10.1.0",
Expand All @@ -40,6 +42,7 @@
"husky": "^4.2.5",
"jest": "^26.0.1",
"lint-staged": "^10.2.11",
"postcss": "^8.1.9",
"prettier": "^2.0.5"
},
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion src/css-loader-core/loader.js
Expand Up @@ -14,7 +14,7 @@ class Core {
load(sourceString, sourcePath, trace, pathFetcher) {
let parser = new Parser(pathFetcher, trace);

return postcss(this.plugins.concat([parser.plugin]))
return postcss(this.plugins.concat([parser.plugin()]))
.process(sourceString, { from: "/" + sourcePath })
.then((result) => {
return {
Expand Down
14 changes: 10 additions & 4 deletions src/css-loader-core/parser.js
Expand Up @@ -12,10 +12,16 @@ export default class Parser {
this.trace = trace;
}

plugin(css) {
return Promise.all(this.fetchAllImports(css))
.then(() => this.linkImportedSymbols(css))
.then(() => this.extractExports(css));
plugin() {
const parser = this;
return {
postcssPlugin: "css-modules-parser",
OnceExit(css) {
return Promise.all(parser.fetchAllImports(css))
.then(() => parser.linkImportedSymbols(css))
.then(() => parser.extractExports(css));
},
};
}

fetchAllImports(css) {
Expand Down
136 changes: 70 additions & 66 deletions src/index.js
Expand Up @@ -71,73 +71,77 @@ function dashesCamelCase(string) {
);
}

module.exports = postcss.plugin(PLUGIN_NAME, (opts = {}) => {
const getJSON = opts.getJSON || saveJSON;

return async (css, result) => {
const inputFile = css.source.input.file;
const pluginList = getDefaultPluginsList(opts, inputFile);
const resultPluginIndex = result.processor.plugins.findIndex((plugin) => isOurPlugin(plugin));
if (resultPluginIndex === -1) {
throw new Error('Plugin missing from options.');
}
const earlierPlugins = result.processor.plugins.slice(0, resultPluginIndex);
const loaderPlugins = [...earlierPlugins, ...pluginList];
const loader = getLoader(opts, loaderPlugins);
const parser = new Parser(loader.fetch.bind(loader));

await postcss([...pluginList, parser.plugin]).process(css, {
from: inputFile,
});

const out = loader.finalSource;
if (out) css.prepend(out);

if (opts.localsConvention) {
const isFunc = typeof opts.localsConvention === "function";

parser.exportTokens = Object.entries(parser.exportTokens).reduce(
(tokens, [className, value]) => {
if (isFunc) {
tokens[opts.localsConvention(className, value, inputFile)] = value;
module.exports = (opts = {}) => {
return {
postcssPlugin: PLUGIN_NAME,
async OnceExit(css, { result }) {
const getJSON = opts.getJSON || saveJSON;
const inputFile = css.source.input.file;
const pluginList = getDefaultPluginsList(opts, inputFile);
const resultPluginIndex = result.processor.plugins.findIndex((plugin) => isOurPlugin(plugin));
if (resultPluginIndex === -1) {
throw new Error('Plugin missing from options.');
}
const earlierPlugins = result.processor.plugins.slice(0, resultPluginIndex);
const loaderPlugins = [...earlierPlugins, ...pluginList];
const loader = getLoader(opts, loaderPlugins);
const parser = new Parser(loader.fetch.bind(loader));

await postcss([...pluginList, parser.plugin()]).process(css, {
from: inputFile,
});

const out = loader.finalSource;
if (out) css.prepend(out);

if (opts.localsConvention) {
const isFunc = typeof opts.localsConvention === "function";

parser.exportTokens = Object.entries(parser.exportTokens).reduce(
(tokens, [className, value]) => {
if (isFunc) {
tokens[opts.localsConvention(className, value, inputFile)] = value;

return tokens;
}

switch (opts.localsConvention) {
case "camelCase":
tokens[className] = value;
tokens[camelCase(className)] = value;

break;
case "camelCaseOnly":
tokens[camelCase(className)] = value;

break;
case "dashes":
tokens[className] = value;
tokens[dashesCamelCase(className)] = value;

break;
case "dashesOnly":
tokens[dashesCamelCase(className)] = value;

break;
}

return tokens;
}

switch (opts.localsConvention) {
case "camelCase":
tokens[className] = value;
tokens[camelCase(className)] = value;

break;
case "camelCaseOnly":
tokens[camelCase(className)] = value;

break;
case "dashes":
tokens[className] = value;
tokens[dashesCamelCase(className)] = value;

break;
case "dashesOnly":
tokens[dashesCamelCase(className)] = value;

break;
}

return tokens;
},
{}
);
},
{}
);
}

result.messages.push({
type: "export",
plugin: "postcss-modules",
exportTokens: parser.exportTokens,
});

// getJSON may return a promise
return getJSON(css.source.input.file, parser.exportTokens, result.opts.to);
}

result.messages.push({
type: "export",
plugin: "postcss-modules",
exportTokens: parser.exportTokens,
});

// getJSON may return a promise
return getJSON(css.source.input.file, parser.exportTokens, result.opts.to);
};
});
};

module.exports.postcss = true;
8 changes: 5 additions & 3 deletions test/__snapshots__/test.js.snap
Expand Up @@ -120,7 +120,7 @@ exports[`only calls plugins once when it allows to make CSS global: plugins once
`;

exports[`only calls plugins once when it composes rules: plugins once - composes rules - CSS 1`] = `
"/* validator-2-start (composes.css) *//* validator-1-start (composes.a.css) */._composes_a_another-mixin {
"/* validator-1-start (composes.a.css) */._composes_a_another-mixin {
display: -webkit-flex;
display: -moz-box;
display: flex;
Expand All @@ -140,6 +140,8 @@ exports[`only calls plugins once when it composes rules: plugins once - composes
border: 1px solid red;
}/* validator-1-end (composes.mixins.css) */
/* validator-2-start (composes.css) */
/* validator-1-start (composes.css) */
.page {
Expand Down Expand Up @@ -224,8 +226,8 @@ exports[`only calls plugins once when it processes classes: plugins once - proce
`;

exports[`only calls plugins once when it processes values: plugins once - processes values - CSS 1`] = `
"/* validator-2-start (values.css) *//* validator-1-start (values.colors.css) *//* validator-1-end (values.colors.css) */
"/* validator-1-start (values.colors.css) *//* validator-1-end (values.colors.css) */
/* validator-2-start (values.css) */
/* validator-1-start (values.css) */
._values_title {
Expand Down
17 changes: 13 additions & 4 deletions test/test.js
Expand Up @@ -7,6 +7,15 @@ import { behaviours } from "../src/behaviours";

const fixturesPath = path.resolve(__dirname, "./fixtures");

function createPlugin(name, processor) {
const plugin = () => ({
postcssPlugin: name,
Once: processor
})
plugin.postcss = true
return plugin
}

const cases = {
plugins: "saves origin plugins",
classes: "processes classes",
Expand Down Expand Up @@ -65,9 +74,9 @@ Object.keys(cases).forEach((name) => {

const plugins = [
autoprefixer,
postcss.plugin(
createPlugin(
'validator-1',
() => (root) => {
(root) => {
if (rootsSeenBeforePlugin.has(root)) {
throw new Error('Plugin before ours was called multiple times.')
}
Expand All @@ -81,9 +90,9 @@ Object.keys(cases).forEach((name) => {
generateScopedName: scopedNameGenerator,
getJSON: () => {},
}),
postcss.plugin(
createPlugin(
'validator-2',
() => (root) => {
(root) => {
if (rootsSeenAfterPlugin.has(root)) {
throw new Error('Plugin after ours was called multiple times.')
}
Expand Down

0 comments on commit ff77512

Please sign in to comment.