Skip to content

Commit

Permalink
fix: remove getJSON: true option in favor of only callback
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenkao committed Mar 11, 2024
1 parent e97b4c3 commit 0009dd9
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 86 deletions.
70 changes: 45 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,9 +327,7 @@ type modules =
| "dashesOnly"
| ((name: string) => string);
exportOnlyLocals: boolean;
getJSON:
| string
| ((resourcePath: string, json: object, outputPath: string) => any);
getJSON: (resourcePath: string, json: object) => any;
};
```

Expand Down Expand Up @@ -595,7 +593,7 @@ module.exports = {
namedExport: true,
exportLocalsConvention: "camelCase",
exportOnlyLocals: false,
getJSON: false,
getJSON: (resourcePath, json) => {},
},
},
},
Expand Down Expand Up @@ -1381,25 +1379,41 @@ module.exports = {
Type:

```ts
type getJSON =
| boolean
| ((resourcePath: string, json: object, outputPath: string) => any);
type getJSON = (resourcePath: string, json: object) => any;
```

Default: `undefined`

Enables the outputting of the CSS modules mapping JSON. This can be omitted or set to a falsy value to disable any output.
Enables a callback to output the CSS modules mapping JSON. The callback is invoked with two arguments:

###### `boolean`
- `resourcePath`: the absolutely path of the original resource, e.g., /foo/bar/baz.css
- `json`: the CSS modules map object, e.g.,

Possible values:
```
/* baz.css */
- `true` - writes a JSON file next located in the same directory as the loaded resource file. For example, given a resource file located at /foo/bar/baz.css, this would write the CSS modules mapping JSON to /foo/bar/baz.css.json
- `false` - disables CSS modules mapping JSON output
.a {
background-color: aliceblue;
}
.b {
background-color: burlywood;
}
```

`json` will be something like the following (depending on your other `modules` settings):

```
{
"a": "a__uRkh1",
"b": "b__pjFcy"
}
```

**webpack.config.js**

```js
// supports a synchronous callback
module.exports = {
module: {
rules: [
Expand All @@ -1408,22 +1422,24 @@ module.exports = {
loader: "css-loader",
options: {
modules: {
getJSON: true,
getJSON: (resourcePath, json) => {
// synchronously write a .json mapping file in the same directory as the resource
const outputPath = path.resolve(
path.dirname(resourcePath),
`${path.basename(resourcePath)}.json`
);

const fs = require("fs");
fs.writeFileSync(outputPath, JSON.stringify(json));
},
},
},
},
],
},
};
```

###### `function`

Enables custom handling of the CSS modules mapping JSON output. The return value of the function is not used for anything internally and is only intended to customize output.

**webpack.config.js**

```js
// same as above, just asynchronous
module.exports = {
module: {
rules: [
Expand All @@ -1432,10 +1448,14 @@ module.exports = {
loader: "css-loader",
options: {
modules: {
getJSON: (resourcePath, json, outputPath) => {
// `resourcePath` is the original resource file path, e.g., /foo/bar/baz.css
// `json` is the CSS modules map
// `outputPath` is the expected output file path, e.g., /foo/bar/baz.css.json
getJSON: async (resourcePath, json) => {
const outputPath = path.resolve(
path.dirname(resourcePath),
`${path.basename(resourcePath)}.json`
);

const fsp = require("fs/promises");
await fsp.writeFile(outputPath, JSON.stringify(json));
},
},
},
Expand Down
21 changes: 12 additions & 9 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import {
stringifyRequest,
warningFactory,
syntaxErrorFactory,
writeModulesMap,
} from "./utils";

export default async function loader(content, map, meta) {
Expand Down Expand Up @@ -275,15 +274,19 @@ export default async function loader(content, map, meta) {
isTemplateLiteralSupported
);

try {
const { getJSON } = options.modules;
if (getJSON) {
await writeModulesMap(getJSON, resourcePath, exports);
}
} catch (error) {
callback(error);
const { getJSON } = options.modules;
if (typeof getJSON === "function") {
try {
const json = exports.reduce((acc, { name, value }) => {
return { ...acc, [name]: value };
}, {});

return;
await getJSON(resourcePath, json);
} catch (error) {
callback(error);

return;
}
}

callback(null, `${importCode}${moduleCode}${exportCode}`);
Expand Down
11 changes: 2 additions & 9 deletions src/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,16 +171,9 @@
"type": "boolean"
},
"getJSON": {
"description": "Output CSS modules mapping to a JSON file or through a callback.",
"description": "Output CSS modules mapping through a callback.",
"link": "https://github.com/webpack-contrib/css-loader#getJSON",
"anyOf": [
{
"type": "boolean"
},
{
"instanceof": "Function"
}
]
"instanceof": "Function"
}
}
}
Expand Down
22 changes: 0 additions & 22 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
*/
import { fileURLToPath } from "url";
import path from "path";
import fsp from "fs/promises";

import modulesValues from "postcss-modules-values";
import localByDefault from "postcss-modules-local-by-default";
Expand Down Expand Up @@ -1413,26 +1412,6 @@ function syntaxErrorFactory(error) {
return obj;
}

async function writeModulesMap(getJSON, resourcePath, exports) {
const json = exports.reduce((acc, { name, value }) => {
return { ...acc, [name]: value };
}, {});

const outputPath = path.resolve(
path.dirname(resourcePath),
`${path.basename(resourcePath)}.json`
);

if (getJSON === true) {
// If true, output a JSON CSS modules mapping file in the same directory as the resource
await fsp.writeFile(outputPath, JSON.stringify(json));
} else if (typeof getJSON === "function") {
// If function, call function with call getJSON with similar args as postcss-modules#getJSON
// https://github.com/madyankin/postcss-modules/tree/master?tab=readme-ov-file#saving-exported-classes
getJSON(resourcePath, json, outputPath);
}
}

export {
normalizeOptions,
shouldUseModulesPlugins,
Expand Down Expand Up @@ -1460,5 +1439,4 @@ export {
defaultGetLocalIdent,
warningFactory,
syntaxErrorFactory,
writeModulesMap,
};
138 changes: 138 additions & 0 deletions test/__snapshots__/modules-option.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,144 @@ Array [

exports[`"modules" option should invoke the custom getJSON function with getJSON as a function: warnings 1`] = `Array []`;

exports[`"modules" option should invoke the custom getJSON function with getJSON as a synchronous function: errors 1`] = `Array []`;

exports[`"modules" option should invoke the custom getJSON function with getJSON as a synchronous function: mapping 1`] = `
Object {
"a": "RT7ktT7mB7tfBR25sJDZ",
"b": "IZmhTnK9CIeu6ww6Zjbv",
"c": "PV11nPFlF7mzEgCXkQw4",
}
`;

exports[`"modules" option should invoke the custom getJSON function with getJSON as a synchronous function: module 1`] = `
"// Imports
import ___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___ from \\"../../../../src/runtime/noSourceMaps.js\\";
import ___CSS_LOADER_API_IMPORT___ from \\"../../../../src/runtime/api.js\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___);
// Module
___CSS_LOADER_EXPORT___.push([module.id, \`.RT7ktT7mB7tfBR25sJDZ {
background-color: aliceblue;
}

.IZmhTnK9CIeu6ww6Zjbv {
background-color: burlywood;
}

.PV11nPFlF7mzEgCXkQw4 {
background-color: chartreuse;
}

.d {
background-color: darkgoldenrod
}
\`, \\"\\"]);
// Exports
___CSS_LOADER_EXPORT___.locals = {
\\"a\\": \`RT7ktT7mB7tfBR25sJDZ\`,
\\"b\\": \`IZmhTnK9CIeu6ww6Zjbv\`,
\\"c\\": \`PV11nPFlF7mzEgCXkQw4\`
};
export default ___CSS_LOADER_EXPORT___;
"
`;

exports[`"modules" option should invoke the custom getJSON function with getJSON as a synchronous function: result 1`] = `
Array [
Array [
"./modules/getJSON/source.css",
".RT7ktT7mB7tfBR25sJDZ {
background-color: aliceblue;
}

.IZmhTnK9CIeu6ww6Zjbv {
background-color: burlywood;
}

.PV11nPFlF7mzEgCXkQw4 {
background-color: chartreuse;
}

.d {
background-color: darkgoldenrod
}
",
"",
],
]
`;

exports[`"modules" option should invoke the custom getJSON function with getJSON as a synchronous function: warnings 1`] = `Array []`;

exports[`"modules" option should invoke the custom getJSON function with getJSON as an asynchronous function: errors 1`] = `Array []`;

exports[`"modules" option should invoke the custom getJSON function with getJSON as an asynchronous function: mapping 1`] = `
Object {
"a": "RT7ktT7mB7tfBR25sJDZ",
"b": "IZmhTnK9CIeu6ww6Zjbv",
"c": "PV11nPFlF7mzEgCXkQw4",
}
`;

exports[`"modules" option should invoke the custom getJSON function with getJSON as an asynchronous function: module 1`] = `
"// Imports
import ___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___ from \\"../../../../src/runtime/noSourceMaps.js\\";
import ___CSS_LOADER_API_IMPORT___ from \\"../../../../src/runtime/api.js\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___);
// Module
___CSS_LOADER_EXPORT___.push([module.id, \`.RT7ktT7mB7tfBR25sJDZ {
background-color: aliceblue;
}

.IZmhTnK9CIeu6ww6Zjbv {
background-color: burlywood;
}

.PV11nPFlF7mzEgCXkQw4 {
background-color: chartreuse;
}

.d {
background-color: darkgoldenrod
}
\`, \\"\\"]);
// Exports
___CSS_LOADER_EXPORT___.locals = {
\\"a\\": \`RT7ktT7mB7tfBR25sJDZ\`,
\\"b\\": \`IZmhTnK9CIeu6ww6Zjbv\`,
\\"c\\": \`PV11nPFlF7mzEgCXkQw4\`
};
export default ___CSS_LOADER_EXPORT___;
"
`;

exports[`"modules" option should invoke the custom getJSON function with getJSON as an asynchronous function: result 1`] = `
Array [
Array [
"./modules/getJSON/source.css",
".RT7ktT7mB7tfBR25sJDZ {
background-color: aliceblue;
}

.IZmhTnK9CIeu6ww6Zjbv {
background-color: burlywood;
}

.PV11nPFlF7mzEgCXkQw4 {
background-color: chartreuse;
}

.d {
background-color: darkgoldenrod
}
",
"",
],
]
`;

exports[`"modules" option should invoke the custom getJSON function with getJSON as an asynchronous function: warnings 1`] = `Array []`;

exports[`"modules" option should keep order: errors 1`] = `Array []`;

exports[`"modules" option should keep order: module 1`] = `
Expand Down

0 comments on commit 0009dd9

Please sign in to comment.