├── .npmignore ├── .husky ├── pre-commit └── commit-msg ├── test ├── fixtures │ ├── style.css │ ├── style-other.css │ ├── create-nonce.js │ ├── nested │ │ └── style.css │ ├── other-nested │ │ └── style.css │ ├── singleton-one.css │ ├── singleton-two.css │ ├── css-modules-local-scoped.css │ ├── hot.js │ ├── multiple.js │ ├── nonce-import.js │ ├── simple.js │ ├── singleton.js │ ├── es-modules.js │ ├── lazy-es-modules.js │ ├── nonce-require.js │ ├── commonjs-modules.js │ ├── lazy-commonjs-modules.js │ ├── lazy-nonce-import.js │ ├── lazy-negative-refs.js │ ├── lazy-nonce-require.js │ ├── lazy-simple.js │ ├── insert-options.js │ ├── es-modules.css │ ├── lazy-multiple.js │ ├── insert-test-shadow.js │ ├── lazy-options.js │ ├── css-modules.css │ ├── lazy-options-use-unuse.js │ ├── element.js │ ├── named-export.css │ ├── styleTagTransformAdditionalStyles.js │ ├── styleTagTransform.js │ ├── lazy-element.js │ ├── css-modules-link.js │ ├── css-modules.js │ ├── named-export.js │ ├── lazy-css-modules.js │ ├── insert-top.js │ ├── insertFn.js │ └── insert-to-existing-style.js ├── manual │ ├── src │ │ ├── duplicate.css │ │ ├── order-1.css │ │ ├── order-2.css │ │ ├── use-unuse.lazy.css │ │ ├── toogle.lazy.css │ │ ├── modules │ │ │ ├── common.module.css │ │ │ ├── one.module.css │ │ │ ├── two.module.css │ │ │ ├── page.module.css │ │ │ └── toolbar.module.css │ │ ├── nested.css │ │ ├── logo.png │ │ ├── nested │ │ │ └── style.css │ │ ├── bottom.css │ │ ├── custom-square.custom.css │ │ ├── style.css │ │ ├── style.link.css │ │ ├── top.css │ │ ├── style.lazy.css │ │ ├── middle.css │ │ ├── style.named-export.module.css │ │ ├── other-style.scss │ │ ├── style.named-export.lazy.module.css │ │ ├── other-style.lazy.scss │ │ ├── component.module.css │ │ ├── component.lazy.module.css │ │ ├── order.css │ │ ├── custom-square.js │ │ └── index.js │ ├── index.html │ └── webpack.config.js ├── helpers │ ├── getErrors.js │ ├── getWarnings.js │ ├── compile.js │ ├── getEntryByInjectType.js │ ├── readAssets.js │ ├── normalizeErrors.js │ ├── execute.js │ ├── index.js │ ├── readAsset.js │ ├── runInJsDom.js │ └── getCompiler.js ├── cjs.test.js ├── base-option.test.js ├── __snapshots__ │ ├── base-option.test.js.snap │ ├── lazyStyleTag-options.test.js.snap │ ├── styleTagTransform-option.test.js.snap │ ├── validate-options.test.js.snap │ ├── injectType-option.test.js.snap │ └── attributes-option.test.js.snap ├── injectType-option.test.js ├── lazyStyleTag-options.test.js ├── runtime │ ├── isEqualLocals.test.js │ ├── __snapshots__ │ │ ├── injectStylesIntoLinkTag.test.js.snap │ │ └── injectStylesIntoStyleTag.test.js.snap │ └── injectStylesIntoLinkTag.test.js ├── validate-options.test.js ├── attributes-option.test.js ├── styleTagTransform-option.test.js ├── esModule-option.test.js ├── insert-option.test.js └── loader.test.js ├── .prettierignore ├── src ├── cjs.js ├── runtime │ ├── setAttributesWithAttributesAndNonce.js │ ├── insertStyleElement.js │ ├── setAttributesWithoutAttributes.js │ ├── styleTagTransform.js │ ├── setAttributesWithAttributes.js │ ├── isEqualLocals.js │ ├── isOldIE.js │ ├── injectStylesIntoLinkTag.js │ ├── insertBySelector.js │ ├── styleDomAPI.js │ ├── singletonStyleDomAPI.js │ └── injectStylesIntoStyleTag.js ├── options.json ├── index.js └── utils.js ├── .gitattributes ├── lint-staged.config.js ├── commitlint.config.js ├── eslint.config.mjs ├── .editorconfig ├── .gitignore ├── .github └── workflows │ ├── dependency-review.yml │ └── nodejs.yml ├── .cspell.json ├── babel.config.js ├── LICENSE └── package.json /.npmignore: -------------------------------------------------------------------------------- 1 | fixtures/ 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | lint-staged 2 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | commitlint --edit $1 2 | -------------------------------------------------------------------------------- /test/fixtures/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: red; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/style-other.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: blue; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/create-nonce.js: -------------------------------------------------------------------------------- 1 | __webpack_nonce__ = '12345678'; 2 | -------------------------------------------------------------------------------- /test/fixtures/nested/style.css: -------------------------------------------------------------------------------- 1 | .foo { 2 | color: red; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/other-nested/style.css: -------------------------------------------------------------------------------- 1 | .bar { 2 | color: blue; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/singleton-one.css: -------------------------------------------------------------------------------- 1 | .class-one { 2 | color: red; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/singleton-two.css: -------------------------------------------------------------------------------- 1 | .class-two { 2 | color: red; 3 | } 4 | -------------------------------------------------------------------------------- /test/manual/src/duplicate.css: -------------------------------------------------------------------------------- 1 | .duplicate { 2 | color: red; 3 | } 4 | -------------------------------------------------------------------------------- /test/manual/src/order-1.css: -------------------------------------------------------------------------------- 1 | .order { 2 | background: red; 3 | } 4 | -------------------------------------------------------------------------------- /test/manual/src/order-2.css: -------------------------------------------------------------------------------- 1 | .order { 2 | background: blue; 3 | } 4 | -------------------------------------------------------------------------------- /test/manual/src/use-unuse.lazy.css: -------------------------------------------------------------------------------- 1 | .use { 2 | color: red; 3 | } 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | /coverage 2 | /dist 3 | /node_modules 4 | /test/fixtures 5 | CHANGELOG.md -------------------------------------------------------------------------------- /test/manual/src/toogle.lazy.css: -------------------------------------------------------------------------------- 1 | #toggle-section { 2 | background-color: red; 3 | } 4 | -------------------------------------------------------------------------------- /src/cjs.js: -------------------------------------------------------------------------------- 1 | const loader = require("./index"); 2 | 3 | module.exports = loader.default; 4 | -------------------------------------------------------------------------------- /test/manual/src/modules/common.module.css: -------------------------------------------------------------------------------- 1 | .common { 2 | background-color: yellow; 3 | } 4 | -------------------------------------------------------------------------------- /test/manual/src/nested.css: -------------------------------------------------------------------------------- 1 | @import "./nested/style.css"; 2 | @import "./duplicate.css"; 3 | -------------------------------------------------------------------------------- /test/fixtures/css-modules-local-scoped.css: -------------------------------------------------------------------------------- 1 | :local(.className) { 2 | background: red; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/hot.js: -------------------------------------------------------------------------------- 1 | import style from './style.css'; 2 | 3 | window.hotApi = module.hot; 4 | -------------------------------------------------------------------------------- /test/fixtures/multiple.js: -------------------------------------------------------------------------------- 1 | import './nested/style.css'; 2 | import './other-nested/style.css'; 3 | -------------------------------------------------------------------------------- /test/fixtures/nonce-import.js: -------------------------------------------------------------------------------- 1 | import './create-nonce'; 2 | import './style.css'; 3 | 4 | 5 | -------------------------------------------------------------------------------- /test/fixtures/simple.js: -------------------------------------------------------------------------------- 1 | import a from './style.css'; 2 | import b from './style-other.css'; 3 | -------------------------------------------------------------------------------- /test/fixtures/singleton.js: -------------------------------------------------------------------------------- 1 | import './singleton-one.css'; 2 | import './singleton-two.css'; 3 | -------------------------------------------------------------------------------- /test/fixtures/es-modules.js: -------------------------------------------------------------------------------- 1 | import * as mod from './es-modules.css'; 2 | 3 | window.__cssLoader = mod; 4 | -------------------------------------------------------------------------------- /test/manual/src/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webpack/style-loader/HEAD/test/manual/src/logo.png -------------------------------------------------------------------------------- /test/fixtures/lazy-es-modules.js: -------------------------------------------------------------------------------- 1 | import * as mod from './es-modules.css'; 2 | 3 | window.__cssLoader = mod; 4 | -------------------------------------------------------------------------------- /test/fixtures/nonce-require.js: -------------------------------------------------------------------------------- 1 | __webpack_nonce__ = '12345678'; 2 | 3 | require('./style.css'); 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/manual/src/nested/style.css: -------------------------------------------------------------------------------- 1 | @import "../duplicate.css"; 2 | 3 | .duplicate { 4 | color: blue; 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/commonjs-modules.js: -------------------------------------------------------------------------------- 1 | const styles = require('./es-modules.css'); 2 | 3 | window.__cssLoader = styles; 4 | -------------------------------------------------------------------------------- /test/manual/src/bottom.css: -------------------------------------------------------------------------------- 1 | .bottom { 2 | color: blue; 3 | } 4 | 5 | .media-and-supports { 6 | color: blue; 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/lazy-commonjs-modules.js: -------------------------------------------------------------------------------- 1 | const styles = require('./es-modules.css'); 2 | 3 | window.__cssLoader = styles; 4 | -------------------------------------------------------------------------------- /test/manual/src/custom-square.custom.css: -------------------------------------------------------------------------------- 1 | div { 2 | width: 50px; 3 | height: 50px; 4 | background-color: red; 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/lazy-nonce-import.js: -------------------------------------------------------------------------------- 1 | import './create-nonce'; 2 | import styles from './style.css'; 3 | 4 | styles.use(); 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/fixtures/lazy-negative-refs.js: -------------------------------------------------------------------------------- 1 | import api from './style.css'; 2 | 3 | // ref still 0 4 | api.unuse(); 5 | // ref 1 6 | api.use(); 7 | -------------------------------------------------------------------------------- /test/manual/src/modules/one.module.css: -------------------------------------------------------------------------------- 1 | .selector1 { 2 | composes: common from "./common.module.css"; 3 | background-color: red; 4 | } 5 | -------------------------------------------------------------------------------- /test/manual/src/modules/two.module.css: -------------------------------------------------------------------------------- 1 | .selector2 { 2 | composes: common from "./common.module.css"; 3 | background-color: navy; 4 | } 5 | -------------------------------------------------------------------------------- /test/manual/src/modules/page.module.css: -------------------------------------------------------------------------------- 1 | .page-btn { 2 | composes: selector1 from "./one.module.css"; 3 | 4 | background: crimson; 5 | } 6 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Treats the lock file as binary & prevents conflict hell 2 | yarn.lock -diff 3 | * text=auto 4 | package-lock.json -diff 5 | bin/* eol=lf -------------------------------------------------------------------------------- /test/fixtures/lazy-nonce-require.js: -------------------------------------------------------------------------------- 1 | __webpack_nonce__ = '12345678'; 2 | 3 | const styles = require('./style.css'); 4 | 5 | styles.use(); 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/manual/src/modules/toolbar.module.css: -------------------------------------------------------------------------------- 1 | @value common from './common.module.css'; 2 | 3 | .toolbar > .common { 4 | background: orange; 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/lazy-simple.js: -------------------------------------------------------------------------------- 1 | import style from './style.css'; 2 | import styleOther from './style-other.css'; 3 | 4 | style.use(); 5 | styleOther.use(); 6 | -------------------------------------------------------------------------------- /test/helpers/getErrors.js: -------------------------------------------------------------------------------- 1 | import normalizeErrors from "./normalizeErrors"; 2 | 3 | export default (stats) => normalizeErrors(stats.compilation.errors); 4 | -------------------------------------------------------------------------------- /test/manual/src/style.css: -------------------------------------------------------------------------------- 1 | .red { 2 | color: red; 3 | } 4 | 5 | .green { 6 | color: green; 7 | } 8 | 9 | .blue { 10 | color: blue; 11 | } 12 | -------------------------------------------------------------------------------- /test/fixtures/insert-options.js: -------------------------------------------------------------------------------- 1 | function insert(styleTag, options) { 2 | options.insertInto.appendChild(styleTag); 3 | } 4 | 5 | module.exports = insert; 6 | -------------------------------------------------------------------------------- /test/helpers/getWarnings.js: -------------------------------------------------------------------------------- 1 | import normalizeErrors from "./normalizeErrors"; 2 | 3 | export default (stats) => normalizeErrors(stats.compilation.warnings); 4 | -------------------------------------------------------------------------------- /test/fixtures/es-modules.css: -------------------------------------------------------------------------------- 1 | .foo { 2 | color: red; 3 | } 4 | 5 | .bar { 6 | color: blue; 7 | } 8 | 9 | .baz { 10 | color: coral; 11 | } 12 | -------------------------------------------------------------------------------- /test/fixtures/lazy-multiple.js: -------------------------------------------------------------------------------- 1 | import style from './nested/style.css'; 2 | import otherStyle from './other-nested/style.css'; 3 | 4 | style.use(); 5 | otherStyle.use(); 6 | -------------------------------------------------------------------------------- /test/fixtures/insert-test-shadow.js: -------------------------------------------------------------------------------- 1 | function insert(element) { 2 | document.querySelector("#test-shadow").appendChild(element); 3 | } 4 | 5 | 6 | module.exports = insert; 7 | -------------------------------------------------------------------------------- /test/manual/src/style.link.css: -------------------------------------------------------------------------------- 1 | .link-red { 2 | color: red; 3 | } 4 | 5 | .link-green { 6 | color: green; 7 | } 8 | 9 | .link-blue { 10 | color: blue; 11 | } 12 | -------------------------------------------------------------------------------- /test/fixtures/lazy-options.js: -------------------------------------------------------------------------------- 1 | import style from './style.css'; 2 | 3 | style.use({ 4 | insertInto: document.body, 5 | additionalStyles: '.some-element {color: red;}' 6 | }); 7 | 8 | -------------------------------------------------------------------------------- /test/cjs.test.js: -------------------------------------------------------------------------------- 1 | import src from "../src"; 2 | import cjs from "../src/cjs"; 3 | 4 | describe("cjs", () => { 5 | it("should exported", () => { 6 | expect(cjs).toEqual(src); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /lint-staged.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "*": [ 3 | "prettier --cache --write --ignore-unknown", 4 | "cspell --cache --no-must-find-files", 5 | ], 6 | "*.js": ["eslint --cache --fix"], 7 | }; 8 | -------------------------------------------------------------------------------- /test/fixtures/css-modules.css: -------------------------------------------------------------------------------- 1 | :local(.myClassName) { 2 | background: red; 3 | } 4 | 5 | :local(.myComposingClass) { 6 | composes: className from './css-modules-local-scoped.css'; 7 | color: blue; 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/lazy-options-use-unuse.js: -------------------------------------------------------------------------------- 1 | import style from './style.css'; 2 | 3 | style.use({ 4 | insertInto: document.body, 5 | additionalStyles: '.some-element {color: red;}' 6 | }); 7 | 8 | style.unuse(); 9 | -------------------------------------------------------------------------------- /test/fixtures/element.js: -------------------------------------------------------------------------------- 1 | const element = document.createElement('div'); 2 | 3 | element.id = "test-shadow"; 4 | document.body.appendChild(element); 5 | 6 | require('./style.css'); 7 | require('./style-other.css'); 8 | -------------------------------------------------------------------------------- /test/fixtures/named-export.css: -------------------------------------------------------------------------------- 1 | :local(.myClassName) { 2 | background: red; 3 | } 4 | 5 | :local(.myComposingClass) { 6 | composes: className from './css-modules-local-scoped.css'; 7 | color: blue; 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/styleTagTransformAdditionalStyles.js: -------------------------------------------------------------------------------- 1 | function styleTagTransform(css, style, options) { 2 | style.innerHTML = `${css}\n${options.additionalStyles}\n`; 3 | } 4 | 5 | module.exports = styleTagTransform; 6 | -------------------------------------------------------------------------------- /test/manual/src/top.css: -------------------------------------------------------------------------------- 1 | @import url("./middle.css") supports(display: flex) screen and 2 | (min-width: 400px); 3 | 4 | .top { 5 | color: red; 6 | } 7 | 8 | .media-and-supports { 9 | color: red; 10 | } 11 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ["@commitlint/config-conventional"], 3 | rules: { 4 | "header-max-length": [0], 5 | "body-max-line-length": [0], 6 | "footer-max-line-length": [0], 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "eslint/config"; 2 | import configs from "eslint-config-webpack/configs.js"; 3 | 4 | export default defineConfig([ 5 | { 6 | extends: [configs["recommended-dirty"]], 7 | }, 8 | ]); 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /test/fixtures/styleTagTransform.js: -------------------------------------------------------------------------------- 1 | function styleTagTransform(css, style) { 2 | // eslint-disable-next-line no-param-reassign 3 | style.innerHTML = `${css}.modify{}\n`; 4 | 5 | document.head.appendChild(style); 6 | } 7 | 8 | module.exports = styleTagTransform; 9 | -------------------------------------------------------------------------------- /test/helpers/compile.js: -------------------------------------------------------------------------------- 1 | export default (compiler) => 2 | new Promise((resolve, reject) => { 3 | compiler.run((error, stats) => { 4 | if (error) { 5 | return reject(error); 6 | } 7 | 8 | return resolve(stats); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/helpers/getEntryByInjectType.js: -------------------------------------------------------------------------------- 1 | function getEntryByInjectType(testId, injectType) { 2 | const isLazy = injectType && injectType.toLowerCase().includes("lazy"); 3 | 4 | return `./${isLazy ? "lazy-" : ""}${testId}`; 5 | } 6 | 7 | export default getEntryByInjectType; 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | .idea/ 3 | /coverage 4 | logs 5 | *.log 6 | npm-debug.log* 7 | .eslintcache 8 | .cspellcache 9 | /dist 10 | /local 11 | /reports 12 | .DS_Store 13 | Thumbs.db 14 | .idea 15 | *.iml 16 | .vscode 17 | *.sublime-project 18 | *.sublime-workspace 19 | -------------------------------------------------------------------------------- /test/manual/src/style.lazy.css: -------------------------------------------------------------------------------- 1 | .lazy-red { 2 | color: red; 3 | } 4 | 5 | .lazy-green { 6 | color: green; 7 | } 8 | 9 | .lazy-blue { 10 | color: blue; 11 | } 12 | 13 | .lazy-background { 14 | height: 1200px; 15 | background: url("./logo.png") center no-repeat; 16 | } 17 | -------------------------------------------------------------------------------- /test/manual/src/middle.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Open+Sans&display=swap"); 2 | @import url("./bottom.css") supports(display: grid) screen and 3 | (max-width: 2400px); 4 | 5 | .middle { 6 | color: green; 7 | } 8 | 9 | .media-and-supports { 10 | color: green; 11 | } 12 | -------------------------------------------------------------------------------- /test/fixtures/lazy-element.js: -------------------------------------------------------------------------------- 1 | const element = document.createElement('div'); 2 | 3 | element.id = "test-shadow"; 4 | document.body.appendChild(element); 5 | 6 | const styles = require('./style.css').default; 7 | const stylesOther = require('./style-other.css').default; 8 | 9 | styles.use(); 10 | stylesOther.use(); 11 | -------------------------------------------------------------------------------- /src/runtime/setAttributesWithAttributesAndNonce.js: -------------------------------------------------------------------------------- 1 | /* istanbul ignore next */ 2 | function setAttributesWithoutAttributes(styleElement, attributes) { 3 | for (const key of Object.keys(attributes)) { 4 | styleElement.setAttribute(key, attributes[key]); 5 | } 6 | } 7 | 8 | module.exports = setAttributesWithoutAttributes; 9 | -------------------------------------------------------------------------------- /test/helpers/readAssets.js: -------------------------------------------------------------------------------- 1 | import readAsset from "./readAsset"; 2 | 3 | export default function readAssets(compiler, stats) { 4 | const assets = {}; 5 | 6 | for (const asset of Object.keys(stats.compilation.assets)) { 7 | assets[asset] = readAsset(asset, compiler, stats); 8 | } 9 | 10 | return assets; 11 | } 12 | -------------------------------------------------------------------------------- /test/manual/src/style.named-export.module.css: -------------------------------------------------------------------------------- 1 | .named-export-red { 2 | color: red; 3 | } 4 | 5 | .named-export-green { 6 | color: green; 7 | } 8 | 9 | .named-export-blue { 10 | color: blue; 11 | } 12 | 13 | .named-export-background { 14 | height: 1200px; 15 | background: url("./logo.png") center no-repeat; 16 | } 17 | -------------------------------------------------------------------------------- /test/manual/src/other-style.scss: -------------------------------------------------------------------------------- 1 | $red: red; 2 | $green: green; 3 | $blue: blue; 4 | 5 | .sass-red { 6 | color: $red; 7 | } 8 | 9 | .sass-green { 10 | color: $green; 11 | } 12 | 13 | .sass-blue { 14 | color: $blue; 15 | } 16 | 17 | .sass-background { 18 | height: 1200px; 19 | background: url("./logo.png") center no-repeat; 20 | } 21 | -------------------------------------------------------------------------------- /test/manual/src/style.named-export.lazy.module.css: -------------------------------------------------------------------------------- 1 | .named-export-lazy-red { 2 | color: red; 3 | } 4 | 5 | .named-export-lazy-green { 6 | color: green; 7 | } 8 | 9 | .named-export-lazy-blue { 10 | color: blue; 11 | } 12 | 13 | .named-export-lazy-background { 14 | height: 1200px; 15 | background: url("./logo.png") center no-repeat; 16 | } 17 | -------------------------------------------------------------------------------- /test/manual/src/other-style.lazy.scss: -------------------------------------------------------------------------------- 1 | $red: red; 2 | $green: green; 3 | $blue: blue; 4 | 5 | .sass-lazy-red { 6 | color: $red; 7 | } 8 | 9 | .sass-lazy-green { 10 | color: $green; 11 | } 12 | 13 | .sass-lazy-blue { 14 | color: $blue; 15 | } 16 | 17 | .sass-lazy-background { 18 | height: 1200px; 19 | background: url("./logo.png") center no-repeat; 20 | } 21 | -------------------------------------------------------------------------------- /src/runtime/insertStyleElement.js: -------------------------------------------------------------------------------- 1 | /* global document */ 2 | /* istanbul ignore next */ 3 | function insertStyleElement(options) { 4 | const element = document.createElement("style"); 5 | 6 | options.setAttributes(element, options.attributes); 7 | options.insert(element, options.options); 8 | 9 | return element; 10 | } 11 | 12 | module.exports = insertStyleElement; 13 | -------------------------------------------------------------------------------- /test/manual/src/component.module.css: -------------------------------------------------------------------------------- 1 | @value v-red: red; 2 | @value v-green: green; 3 | @value v-blue: blue; 4 | 5 | .module-red { 6 | color: v-red; 7 | } 8 | 9 | .module-green { 10 | color: v-green; 11 | } 12 | 13 | .module-blue { 14 | color: v-blue; 15 | } 16 | 17 | .module-background { 18 | height: 1200px; 19 | background: url("./logo.png") center no-repeat; 20 | } 21 | -------------------------------------------------------------------------------- /test/manual/src/component.lazy.module.css: -------------------------------------------------------------------------------- 1 | @value v-red: red; 2 | @value v-green: green; 3 | @value v-blue: blue; 4 | 5 | .module-red { 6 | color: v-red; 7 | } 8 | 9 | .module-green { 10 | color: v-green; 11 | } 12 | 13 | .module-blue { 14 | color: v-blue; 15 | } 16 | 17 | .module-background { 18 | height: 1200px; 19 | background: url("./logo.png") center no-repeat; 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/dependency-review.yml: -------------------------------------------------------------------------------- 1 | name: "Dependency Review" 2 | on: [pull_request] 3 | 4 | permissions: 5 | contents: read 6 | 7 | jobs: 8 | dependency-review: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: "Checkout Repository" 12 | uses: actions/checkout@v5 13 | - name: "Dependency Review" 14 | uses: actions/dependency-review-action@v4 15 | -------------------------------------------------------------------------------- /src/runtime/setAttributesWithoutAttributes.js: -------------------------------------------------------------------------------- 1 | /* global __webpack_nonce__ */ 2 | /* istanbul ignore next */ 3 | function setAttributesWithoutAttributes(styleElement) { 4 | const nonce = 5 | typeof __webpack_nonce__ !== "undefined" ? __webpack_nonce__ : null; 6 | 7 | if (nonce) { 8 | styleElement.setAttribute("nonce", nonce); 9 | } 10 | } 11 | 12 | module.exports = setAttributesWithoutAttributes; 13 | -------------------------------------------------------------------------------- /test/fixtures/css-modules-link.js: -------------------------------------------------------------------------------- 1 | import './css-modules.css'; 2 | 3 | const node1 = document.createElement("DIV"); 4 | const textNode1 = document.createTextNode("Water"); 5 | 6 | node1.appendChild(textNode1); 7 | 8 | document.body.appendChild(node1); 9 | 10 | const node2 = document.createElement("DIV"); 11 | const textNode2 = document.createTextNode("Ground"); 12 | 13 | node2.appendChild(textNode2); 14 | 15 | document.body.appendChild(node2); 16 | -------------------------------------------------------------------------------- /test/helpers/normalizeErrors.js: -------------------------------------------------------------------------------- 1 | function removeCWD(str) { 2 | const isWin = process.platform === "win32"; 3 | let cwd = process.cwd(); 4 | 5 | if (isWin) { 6 | str = str.replaceAll("\\", "/"); 7 | 8 | cwd = cwd.replaceAll("\\", "/"); 9 | } 10 | 11 | return str.replaceAll(new RegExp(cwd, "g"), ""); 12 | } 13 | 14 | export default (errors) => 15 | errors.map((error) => 16 | removeCWD(error.toString().split("\n").slice(0, 2).join("\n")), 17 | ); 18 | -------------------------------------------------------------------------------- /src/runtime/styleTagTransform.js: -------------------------------------------------------------------------------- 1 | /* global document */ 2 | /* istanbul ignore next */ 3 | function styleTagTransform(css, styleElement) { 4 | if (styleElement.styleSheet) { 5 | styleElement.styleSheet.cssText = css; 6 | } else { 7 | while (styleElement.firstChild) { 8 | styleElement.removeChild(styleElement.firstChild); 9 | } 10 | 11 | styleElement.appendChild(document.createTextNode(css)); 12 | } 13 | } 14 | 15 | module.exports = styleTagTransform; 16 | -------------------------------------------------------------------------------- /.cspell.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2", 3 | "language": "en,en-gb", 4 | "words": [ 5 | "commitlint", 6 | "unuse", 7 | "concat", 8 | "getdom", 9 | "Browserhacks", 10 | "toogle", 11 | "camelcase", 12 | "EAAE", 13 | "Unse", 14 | "memfs" 15 | ], 16 | 17 | "ignorePaths": [ 18 | "CHANGELOG.md", 19 | "package.json", 20 | "dist/**", 21 | "**/__snapshots__/**", 22 | "package-lock.json", 23 | "node_modules", 24 | "coverage", 25 | "*.log" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /src/runtime/setAttributesWithAttributes.js: -------------------------------------------------------------------------------- 1 | /* global __webpack_nonce__ */ 2 | /* istanbul ignore next */ 3 | function setAttributesWithoutAttributes(styleElement, attributes) { 4 | const nonce = 5 | typeof __webpack_nonce__ !== "undefined" ? __webpack_nonce__ : null; 6 | 7 | if (nonce) { 8 | attributes.nonce = nonce; 9 | } 10 | 11 | for (const key of Object.keys(attributes)) { 12 | styleElement.setAttribute(key, attributes[key]); 13 | } 14 | } 15 | 16 | module.exports = setAttributesWithoutAttributes; 17 | -------------------------------------------------------------------------------- /test/fixtures/css-modules.js: -------------------------------------------------------------------------------- 1 | import * as styles from './css-modules.css'; 2 | 3 | const node1 = document.createElement("DIV"); 4 | const textNode1 = document.createTextNode("Water"); 5 | 6 | node1.appendChild(textNode1); 7 | node1.className = styles.myClassName; 8 | 9 | document.body.appendChild(node1); 10 | 11 | const node2 = document.createElement("DIV"); 12 | const textNode2 = document.createTextNode("Ground"); 13 | 14 | node2.appendChild(textNode2); 15 | node2.className = styles.myComposingClass; 16 | 17 | document.body.appendChild(node2); 18 | -------------------------------------------------------------------------------- /test/fixtures/named-export.js: -------------------------------------------------------------------------------- 1 | import { myClassName, myComposingClass } from './named-export.css'; 2 | 3 | const node1 = document.createElement("DIV"); 4 | const textNode1 = document.createTextNode("Water"); 5 | 6 | node1.appendChild(textNode1); 7 | node1.className = myClassName; 8 | 9 | document.body.appendChild(node1); 10 | 11 | const node2 = document.createElement("DIV"); 12 | const textNode2 = document.createTextNode("Ground"); 13 | 14 | node2.appendChild(textNode2); 15 | node2.className = myComposingClass; 16 | 17 | document.body.appendChild(node2); 18 | -------------------------------------------------------------------------------- /test/helpers/execute.js: -------------------------------------------------------------------------------- 1 | import Module from "node:module"; 2 | import path from "node:path"; 3 | 4 | const parentModule = module; 5 | 6 | export default (code) => { 7 | const resource = "test.js"; 8 | const module = new Module(resource, parentModule); 9 | 10 | module.paths = Module._nodeModulePaths( 11 | path.resolve(__dirname, "../fixtures"), 12 | ); 13 | module.filename = resource; 14 | 15 | module._compile( 16 | `let __export__;${code};module.exports = __export__;`, 17 | resource, 18 | ); 19 | 20 | return module.exports; 21 | }; 22 | -------------------------------------------------------------------------------- /test/manual/src/order.css: -------------------------------------------------------------------------------- 1 | @import url("./order-1.css"); 2 | @import url("https://fonts.googleapis.com/css?family=Roboto&display=swap"); 3 | @import url("./order-2.css"); 4 | @import url("https://fonts.googleapis.com/css?family=Roboto&display=swap"); 5 | @import url("./order-1.css"); 6 | @import url("https://fonts.googleapis.com/css?family=Roboto&display=swap"); 7 | @import url("./order-2.css") screen and (min-width: 2000px); 8 | @import url("https://fonts.googleapis.com/css?family=Roboto&display=swap"); 9 | 10 | .order { 11 | width: 100%; 12 | padding: 10px; 13 | } 14 | -------------------------------------------------------------------------------- /test/fixtures/lazy-css-modules.js: -------------------------------------------------------------------------------- 1 | import styles, { myClassName, myComposingClass } from './css-modules.css'; 2 | 3 | styles.use(); 4 | 5 | const node1 = document.createElement("DIV"); 6 | const textNode1 = document.createTextNode("Water"); 7 | 8 | node1.appendChild(textNode1); 9 | node1.className = myClassName; 10 | 11 | document.body.appendChild(node1); 12 | 13 | const node2 = document.createElement("DIV"); 14 | const textNode2 = document.createTextNode("Ground"); 15 | 16 | node2.appendChild(textNode2); 17 | node2.className = myComposingClass; 18 | 19 | document.body.appendChild(node2); 20 | -------------------------------------------------------------------------------- /test/helpers/index.js: -------------------------------------------------------------------------------- 1 | export { default as compile } from "./compile"; 2 | export { default as getCompiler } from "./getCompiler"; 3 | export { default as execute } from "./execute"; 4 | export { default as getErrors } from "./getErrors"; 5 | export { default as getEntryByInjectType } from "./getEntryByInjectType"; 6 | export { default as normalizeErrors } from "./normalizeErrors"; 7 | export { default as getWarnings } from "./getWarnings"; 8 | export { default as readsAssets } from "./readAssets"; 9 | export { default as readAsset } from "./readAsset"; 10 | export { default as runInJsDom } from "./runInJsDom"; 11 | -------------------------------------------------------------------------------- /test/helpers/readAsset.js: -------------------------------------------------------------------------------- 1 | import path from "node:path"; 2 | 3 | export default (asset, compiler, stats) => { 4 | const usedFs = compiler.outputFileSystem; 5 | const outputPath = stats.compilation.outputOptions.path; 6 | 7 | let data = ""; 8 | let targetFile = asset; 9 | 10 | const queryStringIdx = targetFile.indexOf("?"); 11 | 12 | if (queryStringIdx >= 0) { 13 | targetFile = targetFile.slice(0, queryStringIdx); 14 | } 15 | 16 | try { 17 | data = usedFs.readFileSync(path.join(outputPath, targetFile)).toString(); 18 | } catch { 19 | data = "Error reading file"; 20 | } 21 | 22 | return data; 23 | }; 24 | -------------------------------------------------------------------------------- /src/runtime/isEqualLocals.js: -------------------------------------------------------------------------------- 1 | function isEqualLocals(a, b, isNamedExport) { 2 | if ((!a && b) || (a && !b)) { 3 | return false; 4 | } 5 | 6 | let property; 7 | 8 | for (property in a) { 9 | if (isNamedExport && property === "default") { 10 | continue; 11 | } 12 | 13 | if (a[property] !== b[property]) { 14 | return false; 15 | } 16 | } 17 | 18 | for (property in b) { 19 | if (isNamedExport && property === "default") { 20 | continue; 21 | } 22 | 23 | if (!a[property]) { 24 | return false; 25 | } 26 | } 27 | 28 | return true; 29 | } 30 | 31 | module.exports = isEqualLocals; 32 | -------------------------------------------------------------------------------- /test/base-option.test.js: -------------------------------------------------------------------------------- 1 | import { 2 | compile, 3 | getCompiler, 4 | getErrors, 5 | getWarnings, 6 | runInJsDom, 7 | } from "./helpers/index"; 8 | 9 | describe('"base" option', () => { 10 | it("should work", async () => { 11 | expect.assertions(3); 12 | 13 | const compiler = getCompiler("./simple.js", { base: 1000 }); 14 | const stats = await compile(compiler); 15 | 16 | runInJsDom("main.bundle.js", compiler, stats, (dom) => { 17 | expect(dom.serialize()).toMatchSnapshot("DOM"); 18 | }); 19 | 20 | expect(getWarnings(stats)).toMatchSnapshot("warnings"); 21 | expect(getErrors(stats)).toMatchSnapshot("errors"); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/__snapshots__/base-option.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`"base" option should work: DOM 1`] = ` 4 | "
5 |