Skip to content

Commit 0c3d1cb

Browse files
committed
Support for postcss plugin messages
1 parent 9686865 commit 0c3d1cb

File tree

5 files changed

+91
-49
lines changed

5 files changed

+91
-49
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77

88
## [Unreleased]
99

10+
### Added
11+
12+
* `postcss-container-query`
13+
* Now uses messages to provide the metadata.
14+
* `getMetadataFromMessages` to help extracting metadata from an array of messages
15+
* `saveMeta` function to save the extracted metadata alongside the CSS file
16+
17+
### Deprecated
18+
19+
* `postcss-container-query`
20+
* `getJSON` will be removed, in favour of `getMetadataFromMessages` and `saveMeta`
21+
1022
## [2.6.0]
1123

1224
### Added

packages/postcss-container-query/src/containerQuery.js

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import postcss from "postcss";
22
import hasContainerDefinition from "./hasContainerDefinition";
33
import extractPropsFromNode from "./extractPropsFromNode";
4-
import saveJSON from "./saveJSON";
4+
import saveMeta from "./saveMeta";
55
import MetaBuilder from "@zeecoder/container-query-meta-builder";
66

7+
const plugin = "postcss-container-query";
8+
79
const isContainerQuery = node =>
810
node.type === "atrule" && node.name === "container";
911

@@ -61,10 +63,10 @@ const walkRules = (root, opts, ruleHandler) => {
6163
* }} options
6264
*/
6365
function containerQuery(options = {}) {
64-
const getJSON = options.getJSON || saveJSON;
66+
const getJSON = options.getJSON || saveMeta;
6567
const singleContainer = options.singleContainer !== false;
6668

67-
return function(root) {
69+
return function(root, result) {
6870
const containers = {};
6971
let currentContainerSelector = null;
7072

@@ -141,12 +143,41 @@ function containerQuery(options = {}) {
141143
containers[selector] = containers[selector].build();
142144
}
143145

144-
const response = !singleContainer
146+
const meta = !singleContainer
145147
? containers
146148
: currentContainerSelector ? containers[currentContainerSelector] : {};
147149

148-
getJSON(root.source.input.file, response);
150+
const filepath = root.source.input.file;
151+
152+
result.messages.push({
153+
type: "metadata",
154+
plugin,
155+
meta,
156+
filepath
157+
});
158+
159+
getJSON(filepath, meta);
149160
};
150161
}
151162

152-
export default postcss.plugin("postcss-container-query", containerQuery);
163+
/**
164+
* @param {Array<{plugin: string, type: string, [meta]: {}}>} messages
165+
* @return {null|{}}
166+
*/
167+
export function getMetadataFromMessages(messages) {
168+
const filteredMessages = messages.filter(
169+
message =>
170+
message.plugin === "postcss-container-query" &&
171+
message.type === "metadata"
172+
);
173+
174+
if (!filteredMessages.length) {
175+
return null;
176+
}
177+
178+
return filteredMessages[0].meta;
179+
}
180+
181+
export { saveMeta };
182+
183+
export default postcss.plugin(plugin, containerQuery);

packages/postcss-container-query/src/containerQuery.spec.js

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import postcss from "postcss";
2-
import containerQuery from "./containerQuery";
2+
import containerQuery, { getMetadataFromMessages } from "./containerQuery";
33
import Root from "../__mocks__/Root";
44
import * as regularTest from "./test/regular";
55
import * as customPropertiesTest from "./test/custom-properties";
@@ -11,57 +11,56 @@ import * as missingDeclarationWithRUnitsTest from "./test/missing-declaration-wi
1111
import * as selfTest from "./test/self";
1212
import * as simpleTest from "./test/simple";
1313

14-
jest.mock("./saveJSON");
14+
jest.mock("./saveMeta");
1515

1616
/**
17-
* @param {string} css Raw CSS containing container queries
18-
* @param {{}} options plugin options
17+
* @param {string} rawCSS Raw CSS containing container queries
18+
* @param {{}} [options] plugin options
1919
* @return {Promise<{
2020
* css: string,
2121
* meta: {},
2222
* }>}
2323
*/
24-
const processCss = (css, options = {}) =>
25-
Promise.resolve().then(() => {
26-
let meta = null;
27-
options.getJSON = (path, metaJson) => (meta = metaJson);
28-
29-
return postcss([containerQuery(options)])
30-
.process(css, { from: "from.css", to: "to.css" })
31-
.then(({ css }) => ({ css, meta }));
32-
});
24+
const processCss = async (rawCSS, options = {}) => {
25+
let getJsonMeta = null;
26+
options.getJSON = (path, meta) => (getJsonMeta = meta);
27+
28+
const { css, messages } = await postcss([containerQuery(options)]).process(
29+
rawCSS,
30+
{ from: "from.css", to: "to.css" }
31+
);
32+
33+
const meta = getMetadataFromMessages(messages);
34+
35+
// As long as the `getJSON` option is supported, this is important
36+
expect(getJsonMeta).toEqual(meta);
37+
38+
return { css, meta };
39+
};
3340

3441
/**
3542
* @param {{
3643
* cssInput: string,
3744
* cssOutput: string,
3845
* meta: {},
3946
* }} testObj
40-
* @param {{}} options plugin options
41-
* @return {Promise<{
42-
* cssOutput: string,
43-
* meta: {},
44-
* }>}
47+
* @param {{}} [options] plugin options
4548
*/
46-
const assertProcessingResult = (testObj, options = {}) =>
47-
processCss(testObj.cssInput, options).then(({ css, meta }) => {
48-
expect(css).toBe(testObj.cssOutput);
49-
expect(meta).toEqual(testObj.meta);
50-
51-
return {
52-
cssOutput: css,
53-
meta: meta
54-
};
55-
});
49+
const assertProcessingResult = async (testObj, options = {}) => {
50+
const { css, meta } = await processCss(testObj.cssInput, options);
51+
52+
expect(css).toBe(testObj.cssOutput);
53+
expect(meta).toEqual(testObj.meta);
54+
};
5655

5756
test("should use the default json saving function if none was supplied", () => {
58-
const saveJSON = require("./saveJSON").default;
57+
const saveMeta = require("./saveMeta").default;
5958

6059
const pluginInstance = containerQuery();
6160

62-
pluginInstance(new Root());
61+
pluginInstance(new Root(), { messages: [] });
6362

64-
expect(saveJSON).toHaveBeenCalledTimes(1);
63+
expect(saveMeta).toHaveBeenCalledTimes(1);
6564
});
6665

6766
test("should throw on missing container declaration", () => {
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { readFile, writeFile } from "fs";
22

3-
const saveJSON = (cssFile, json) =>
3+
const saveMeta = (cssFile, meta) =>
44
new Promise(resolve => {
5-
const jsonData = JSON.stringify(json);
5+
const stringMeta = JSON.stringify(meta);
66
const jsonFilePath = `${cssFile}.json`;
77

88
const writeJson = () =>
9-
writeFile(jsonFilePath, jsonData, e => {
9+
writeFile(jsonFilePath, stringMeta, e => {
1010
if (e) {
1111
console.error(`Failed to save container query json file: ${e}`);
1212
}
@@ -16,12 +16,12 @@ const saveJSON = (cssFile, json) =>
1616

1717
readFile(jsonFilePath, "utf8", (e, contents) => {
1818
// Write file if it doesn't exist yet, or if the contents changed
19-
if (e || contents !== jsonData) {
19+
if (e || contents !== stringMeta) {
2020
writeJson();
2121
} else {
2222
resolve();
2323
}
2424
});
2525
});
2626

27-
export default saveJSON;
27+
export default saveMeta;

packages/postcss-container-query/src/saveJSON.spec.js renamed to packages/postcss-container-query/src/saveMeta.spec.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import saveJSON from "./saveJSON";
1+
import saveMeta from "./saveMeta";
22

33
jest.mock("fs");
44

55
test("should write contents when file does not exist", () => {
66
const fs = require("fs");
7-
const cssFilePath = __dirname + "/tmp/saveJSON.test.css";
7+
const cssFilePath = __dirname + "/tmp/saveMeta.test.css";
88
const jsonFilePath = `${cssFilePath}.json`;
99
const json = { some: "JSON" };
1010

@@ -14,7 +14,7 @@ test("should write contents when file does not exist", () => {
1414
expect.hasAssertions();
1515

1616
return Promise.resolve()
17-
.then(() => saveJSON(cssFilePath, json))
17+
.then(() => saveMeta(cssFilePath, json))
1818
.then(() => {
1919
expect(fs.readFile).toHaveBeenCalledTimes(1);
2020
expect(fs.writeFile).toHaveBeenCalledTimes(1);
@@ -25,7 +25,7 @@ test("should write contents when file does not exist", () => {
2525

2626
test("should not write contents when file already with same contents", () => {
2727
const fs = require("fs");
28-
const cssFilePath = __dirname + "/tmp/saveJSON.test.css";
28+
const cssFilePath = __dirname + "/tmp/saveMeta.test.css";
2929
const jsonFilePath = `${cssFilePath}.json`;
3030
const json = { some: "JSON" };
3131

@@ -35,7 +35,7 @@ test("should not write contents when file already with same contents", () => {
3535
expect.hasAssertions();
3636

3737
return Promise.resolve()
38-
.then(() => saveJSON(cssFilePath, json))
38+
.then(() => saveMeta(cssFilePath, json))
3939
.then(() => {
4040
expect(fs.readFile).toHaveBeenCalledTimes(1);
4141
expect(fs.writeFile).toHaveBeenCalledTimes(0);
@@ -44,7 +44,7 @@ test("should not write contents when file already with same contents", () => {
4444

4545
test("should log error in case there's an issue writing the file", () => {
4646
const fs = require("fs");
47-
const cssFilePath = __dirname + "/tmp/saveJSON.test.css";
47+
const cssFilePath = __dirname + "/tmp/saveMeta.test.css";
4848
const jsonFilePath = `${cssFilePath}.json`;
4949
const json = { some: "JSON" };
5050

@@ -55,7 +55,7 @@ test("should log error in case there's an issue writing the file", () => {
5555
expect.hasAssertions();
5656

5757
return Promise.resolve()
58-
.then(() => saveJSON(cssFilePath, json))
58+
.then(() => saveMeta(cssFilePath, json))
5959
.then(() => {
6060
expect(fs.readFile).toHaveBeenCalledTimes(1);
6161
expect(fs.writeFile).toHaveBeenCalledTimes(1);

0 commit comments

Comments
 (0)