Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 113 additions & 66 deletions README.md

Large diffs are not rendered by default.

16 changes: 13 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

112 changes: 112 additions & 0 deletions test/__snapshots__/builtInCss.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing

exports[`built-in CSS support of webpack should emit an error on invalid syntax: errors 1`] = `
[
"ModuleBuildError: Module build failed (from \`replaced original path\`):

SyntaxError

(1:3) /test/fixtures/css/style.css Unnecessary curly bracket

> 1 | a {
| ^
2 | color: black;
3 | }
",
]
`;

exports[`built-in CSS support of webpack should emit an error on invalid syntax: warnings 1`] = `[]`;

exports[`built-in CSS support of webpack should generate source maps: errors 1`] = `[]`;

exports[`built-in CSS support of webpack should generate source maps: warnings 1`] = `[]`;

exports[`built-in CSS support of webpack should work with CSS modules: errors 1`] = `[]`;

exports[`built-in CSS support of webpack should work with CSS modules: warnings 1`] = `[]`;

exports[`built-in CSS support of webpack should work with SugarSS: css 1`] = `
"/*!***************************!*\\
!*** css ./sss/style.sss ***!
\\***************************/
a {
color: black
}

"
`;

exports[`built-in CSS support of webpack should work with SugarSS: errors 1`] = `[]`;

exports[`built-in CSS support of webpack should work with SugarSS: warnings 1`] = `[]`;

exports[`built-in CSS support of webpack should work with the "execute" option and CSS-in-JS: css 1`] = `
"/*!*************************************!*\\
!*** css ./jss/postcss-js/style.js ***!
\\*************************************/
a {
color: yellow
}
"
`;

exports[`built-in CSS support of webpack should work with the "execute" option and CSS-in-JS: errors 1`] = `[]`;

exports[`built-in CSS support of webpack should work with the "execute" option and CSS-in-JS: warnings 1`] = `[]`;

exports[`built-in CSS support of webpack should work: css 1`] = `
"/*!***************************!*\\
!*** css ./css/style.css ***!
\\***************************/
a {
color: black;
}

a {
color: red;
}

a {
color: green;
}

a {
color: blue;
}

.class {
-x-border-color: blue blue *;
-x-color: * #fafafa;
}

.class-foo {
-z-border-color: blue blue *;
-z-color: * #fafafa;
}

.phone_title {
width: 500px;
}

@media (max-width: 500px) {

.phone_title {
width: auto
}
}

body.is_dark .phone_title {
color: white;
}

.phone img {
display: block;
}

"
`;

exports[`built-in CSS support of webpack should work: errors 1`] = `[]`;

exports[`built-in CSS support of webpack should work: warnings 1`] = `[]`;
124 changes: 124 additions & 0 deletions test/builtInCss.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import path from "node:path";

import {
compile,
getCssCompiler,
getErrors,
getWarnings,
readAsset,
} from "./helpers/index";

describe("built-in CSS support of webpack", () => {
it("should work", async () => {
const compiler = getCssCompiler("./builtin-css/index.js", {
postcssOptions: {
plugins: ["postcss-nested"],
},
});
const stats = await compile(compiler);

expect(readAsset("main.css", compiler, stats)).toMatchSnapshot("css");
expect(getWarnings(stats)).toMatchSnapshot("warnings");
expect(getErrors(stats)).toMatchSnapshot("errors");
});

it("should work with CSS modules", async () => {
const compiler = getCssCompiler("./builtin-css/modules.js", {
postcssOptions: {
plugins: ["postcss-nested"],
},
});
const stats = await compile(compiler);
const css = readAsset("main.css", compiler, stats);

// The class name is generated by webpack, only check that it was renamed
expect(css).not.toContain(".link {");
expect(css).toContain("color: black");
expect(css).toContain("color: red");
expect(getWarnings(stats)).toMatchSnapshot("warnings");
expect(getErrors(stats)).toMatchSnapshot("errors");
});

it("should work with SugarSS", async () => {
const compiler = getCssCompiler("./builtin-css/sss.js", {
postcssOptions: {
parser: "sugarss",
hideNothingWarning: true,
},
});
const stats = await compile(compiler);

expect(readAsset("main.css", compiler, stats)).toMatchSnapshot("css");
expect(getWarnings(stats)).toMatchSnapshot("warnings");
expect(getErrors(stats)).toMatchSnapshot("errors");
});

it('should work with the "execute" option and CSS-in-JS', async () => {
const compiler = getCssCompiler(
"./builtin-css/jss.js",
{},
{
module: {
rules: [
{
test: /style\.js$/i,
type: "css/auto",
use: [
{
loader: path.resolve(__dirname, "../src"),
options: {
postcssOptions: {
parser: "postcss-js",
},
execute: true,
},
},
],
},
],
},
},
);
const stats = await compile(compiler);

expect(readAsset("main.css", compiler, stats)).toMatchSnapshot("css");
expect(getWarnings(stats)).toMatchSnapshot("warnings");
expect(getErrors(stats)).toMatchSnapshot("errors");
});

it("should generate source maps", async () => {
const compiler = getCssCompiler(
"./builtin-css/index.js",
{
sourceMap: true,
postcssOptions: {
plugins: ["postcss-nested"],
},
},
{
devtool: "source-map",
},
);
const stats = await compile(compiler);
const sourceMap = JSON.parse(readAsset("main.css.map", compiler, stats));

expect(
sourceMap.sources.some((source) => source.endsWith("css/style.css")),
).toBe(true);
expect(getWarnings(stats)).toMatchSnapshot("warnings");
expect(getErrors(stats)).toMatchSnapshot("errors");
});

it("should emit an error on invalid syntax", async () => {
const compiler = getCssCompiler("./builtin-css/index.js", {
postcssOptions: {
hideNothingWarning: true,
parser: "sugarss",
},
});
const stats = await compile(compiler);

expect(getWarnings(stats)).toMatchSnapshot("warnings");
expect(getErrors(stats)).toMatchSnapshot("errors");
});
});
1 change: 1 addition & 0 deletions test/fixtures/builtin-css/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "../css/style.css";
1 change: 1 addition & 0 deletions test/fixtures/builtin-css/jss.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "../jss/postcss-js/style.js";
3 changes: 3 additions & 0 deletions test/fixtures/builtin-css/modules.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { link } from "./style.module.css";

export default link;
1 change: 1 addition & 0 deletions test/fixtures/builtin-css/sss.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "../sss/style.sss";
7 changes: 7 additions & 0 deletions test/fixtures/builtin-css/style.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.link {
color: black;

&:hover {
color: red;
}
}
6 changes: 5 additions & 1 deletion test/fixtures/esparser/runManual.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,22 @@ const compiler = webpack({
devtool: false,
context: path.resolve(rootDir, "../fixtures"),
entry: path.resolve(rootDir, "../fixtures", "./sss/index.js"),
experiments: {
css: true,
},
output: {
path: path.resolve(rootDir, "../outputs"),
filename: "[name].bundle.js",
chunkFilename: "[name].chunk.js",
cssFilename: "[name].css",
publicPath: "/webpack/public/path/",
},
module: {
rules: [
{
test: /\.(css|sss)$/i,
type: "css/auto",
use: [
'css-loader',
{
loader: path.resolve(rootDir, "../../dist"),
options: {
Expand Down
55 changes: 55 additions & 0 deletions test/helpers/getCssCompiler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import path from "node:path";

import { Volume, createFsFromVolume } from "memfs";
import webpack from "webpack";

// Compiles a fixture using the built-in CSS support of webpack
// (i.e. `experiments.css` and the `css/auto` module type), so no
// `css-loader`/`style-loader` are involved.
export default (fixture, loaderOptions = {}, config = {}) => {
const fullConfig = {
mode: "development",
devtool: config.devtool || false,
context: path.resolve(__dirname, "../fixtures"),
entry: path.resolve(__dirname, "../fixtures", fixture),
experiments: {
css: true,
},
output: {
path: path.resolve(__dirname, "../outputs"),
filename: "[name].bundle.js",
chunkFilename: "[name].chunk.js",
cssFilename: "[name].css",
cssChunkFilename: "[name].chunk.css",
publicPath: "/webpack/public/path/",
},
module: {
rules: [
{
test: /\.(css|sss)$/i,
type: "css/auto",
use: [
{
loader: path.resolve(__dirname, "../../src"),
options: loaderOptions || {},
},
],
},
],
},
plugins: [],
...config,
};

const compiler = webpack(fullConfig);

if (!config.outputFileSystem) {
const outputFileSystem = createFsFromVolume(new Volume());

outputFileSystem.join = path.join.bind(path);

compiler.outputFileSystem = outputFileSystem;
}

return compiler;
};
1 change: 1 addition & 0 deletions test/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { default as normalizeErrors } from "./normalizeErrors";
export { default as execute } from "./execute";
export { default as getCompiler } from "./getCompiler";
export { default as getCodeFromBundle } from "./getCodeFromBundle";
export { default as getCssCompiler } from "./getCssCompiler";
export { default as getExecutedCode } from "./getExecutedCode";
export { default as getErrors } from "./getErrors";
export { default as readAsset } from "./readAsset";
Expand Down
Loading