├── .github
└── workflows
│ ├── docs.yml
│ ├── e2e-test.yml
│ └── swc.yml
├── .gitignore
├── CHANGELOG.md
├── README.md
├── babel.commonjs.cjs
├── babel.config.cjs
├── babel
├── hash.cjs
└── index.cjs
├── docs
├── .babelrc
├── .linariarc
├── build.js
├── next-env.d.ts
├── next.config.js
├── package.json
├── pages
│ ├── CodeExample.tsx
│ ├── Theme.tsx
│ └── index.page.tsx
├── public
│ └── static
│ │ └── favicon.png
└── tsconfig.json
├── examples
└── styled-components
│ ├── babel.config.js
│ ├── next-env.d.ts
│ ├── next.config.js
│ ├── package.json
│ ├── pages
│ ├── gradient
│ │ ├── index.page.tsx
│ │ └── text-gradient.ts
│ └── index.page.tsx
│ └── tsconfig.json
├── jest.config.cjs
├── license
├── package.json
├── src
└── index.ts
├── swc
├── Cargo.lock
├── Cargo.toml
├── README.md
├── package.json
├── swc-plugin-css-variable
│ ├── Cargo.toml
│ └── src
│ │ └── lib.rs
└── transform
│ ├── Cargo.toml
│ ├── benches
│ ├── bench_main.rs
│ ├── nested.js
│ └── styledPage.tsx
│ ├── src
│ ├── hash.rs
│ └── lib.rs
│ └── tests
│ └── __swc_snapshots__
│ └── src
│ └── lib.rs
│ ├── adds_camel_case_variable_name_with_display_name.js
│ ├── adds_multiple_variable_names.js
│ ├── adds_variable_name.js
│ ├── adds_variable_name_for_renamed.js
│ ├── adds_variable_name_with_display_name.js
│ ├── adds_variable_name_with_value.js
│ └── ignores_unknwon_modules.js
├── test
├── __snapshots__
│ └── babel.test.js.snap
├── babel.test.js
├── examples.js
├── fixtures
│ ├── CSSVariable.js
│ ├── createVar.js
│ └── renamed.js
├── package.json
├── swc
│ ├── jest.config.js
│ └── swc.test.js
└── without-babel.test.js
└── tsconfig.json
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: docs
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | paths:
8 | - "docs/**"
9 | - ".github/workflows/docs.yml"
10 |
11 | jobs:
12 | deploy:
13 | runs-on: ubuntu-latest
14 |
15 | strategy:
16 | matrix:
17 | node-version: [20]
18 |
19 | steps:
20 | - uses: actions/checkout@v4
21 | - name: Use Node.js ${{ matrix.node-version }}
22 | uses: actions/setup-node@v4
23 | with:
24 | node-version: ${{ matrix.node-version }}
25 | - name: RustUp
26 | run: rustup target add wasm32-wasip1
27 | - run: npm install
28 | - run: (cd docs && npm install)
29 | - run: npm run prepublishOnly
30 | env:
31 | CI: true
32 | - run: npm run docs
33 | - name: Deploy
34 | uses: peaceiris/actions-gh-pages@v3
35 | with:
36 | github_token: ${{ secrets.GITHUB_TOKEN }}
37 | publish_dir: ./docs/out
38 |
--------------------------------------------------------------------------------
/.github/workflows/e2e-test.yml:
--------------------------------------------------------------------------------
1 | name: e2e test
2 |
3 | on: [push]
4 |
5 | jobs:
6 | build:
7 | runs-on: ubuntu-latest
8 |
9 | strategy:
10 | matrix:
11 | node-version: [20]
12 |
13 | steps:
14 | - uses: actions/checkout@v4
15 | - name: Use Node.js ${{ matrix.node-version }}
16 | uses: actions/setup-node@v4
17 | with:
18 | node-version: ${{ matrix.node-version }}
19 | - run: npm install
20 | - run: npm run build
21 | - run: npm test
22 | env:
23 | CI: true
24 | NODE_OPTIONS: --openssl-legacy-provider
25 | - run: npx bundlesize -f dist/index.min.mjs
26 |
--------------------------------------------------------------------------------
/.github/workflows/swc.yml:
--------------------------------------------------------------------------------
1 | name: SWC validation
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 |
9 | env:
10 | CARGO_TERM_COLOR: always
11 |
12 | jobs:
13 | rust:
14 | name: Rust tests & lints
15 | runs-on: ubuntu-latest
16 | steps:
17 | - name: Checkout sources
18 | uses: actions/checkout@v4
19 | - name: Install stable toolchain
20 | uses: dtolnay/rust-toolchain@stable
21 | - name: Enable caching
22 | uses: Swatinem/rust-cache@v2
23 | with:
24 | workspaces: swc
25 | - name: Run cargo check
26 | run: cargo check --manifest-path swc/Cargo.toml
27 | - name: Run cargo test
28 | run: cargo test --manifest-path swc/Cargo.toml
29 | - name: Run cargo fmt
30 | run: cargo fmt --manifest-path swc/Cargo.toml --all -- --check
31 | - name: Run cargo clippy
32 | run: cargo clippy --manifest-path swc/Cargo.toml -- -D warnings
33 |
34 | wasm:
35 | name: Wasm plugin tests
36 | strategy:
37 | fail-fast: false
38 | matrix:
39 | os: [ubuntu-latest, windows-latest]
40 | runs-on: ${{ matrix.os }}
41 | steps:
42 | - name: Checkout sources
43 | uses: actions/checkout@v4
44 | - name: Add wasm32-wasip1 target
45 | run: rustup target add wasm32-wasip1
46 | - name: Enable caching
47 | uses: Swatinem/rust-cache@v2
48 | with:
49 | workspaces: swc
50 | - name: Use Node.js 20
51 | uses: actions/setup-node@v4
52 | with:
53 | node-version: 20
54 | - name: Install NPM dependencies
55 | run: npm i
56 | - name: Build JS
57 | run: npm run build
58 | - name: Build SWC plugin
59 | run: npm run build:swc
60 | - name: Run tests
61 | run: npm run test:swc:jest
62 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .next
3 | .swc
4 | .linaria-cache
5 | dist
6 | target
7 | package-lock.json
8 | yarn.lock
9 | yarn-error.log
10 | out
11 | *.tgz
12 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4 |
5 | ## 6.0.0 (2025-02-27)
6 |
7 |
8 | ### ⚠ BREAKING CHANGES
9 |
10 | * **swc:** Update to swc_core 16.0.0 (compatible with @swc/core@1.11.1)
11 |
12 | ## 5.0.0 (2024-12-10)
13 |
14 |
15 | ### ⚠ BREAKING CHANGES
16 |
17 | * **swc** Update to swc_core 5.x (compatible with @swc/core@1.9.2) [#43](https://github.com/jantimon/css-variable/issues/43)
18 |
19 | ### Features
20 |
21 | * add support for Next.js 15.0.4 ([#43](https://github.com/jantimon/css-variable/issues/43)) ([0f9a5a6](https://github.com/jantimon/css-variable/commit/0f9a5a6e8b6ab586dad0460ae0ab4c09948e5aa0))
22 |
23 |
24 | ## [4.0.0](https://github.com/jantimon/css-variable/compare/v3.10.2...v4.0.0) (2024-05-21)
25 |
26 |
27 | ### ⚠ BREAKING CHANGES
28 |
29 | * **swc:** Update to swc_core 0.90.x (compatible with @swc/core@1.4.x) (#34)
30 |
31 | ### Features
32 |
33 | * **swc:** Update to swc_core 0.90.x (compatible with @swc/core@1.4.x) ([#34](https://github.com/jantimon/css-variable/issues/34)) ([5daebad](https://github.com/jantimon/css-variable/commit/5daebadc893b77428da797b300f9037ab7482da6))
34 |
35 | ### [3.10.2](https://github.com/jantimon/css-variable/compare/v3.10.1...v3.10.2) (2023-07-20)
36 |
37 | ### [3.10.1](https://github.com/jantimon/css-variable/compare/v3.10.0...v3.10.1) (2023-01-26)
38 |
39 |
40 | ### Bug Fixes
41 |
42 | * **swc:** include package.json properly ([#28](https://github.com/jantimon/css-variable/issues/28)) ([2077ec6](https://github.com/jantimon/css-variable/commit/2077ec6e01c9f9f58091326ddbe1dfdc2799e29f))
43 |
44 | ## [3.10.0](https://github.com/jantimon/css-variable/compare/v3.9.0...v3.10.0) (2023-01-26)
45 |
46 | ### Features
47 |
48 | * faster hash generation with more readable hashes ([1a0006f](https://github.com/jantimon/css-variable/commit/1a0006f9f150231b319be74ccaf757eb257da764))
49 |
50 | ### Bug Fixes
51 |
52 | * update dev dependencies ([d3dabe2](https://github.com/jantimon/css-variable/commit/d3dabe2c7ca948f080a67e9439074c40c71d13bc))
53 |
54 | ### [3.9.1](https://github.com/jantimon/css-variable/compare/v3.9.0...v3.9.1) (2022-11-23)
55 |
56 | ### Features
57 |
58 | * add type declarations to exports field ([13e6696](https://github.com/jantimon/css-variable/commit/13e669626747d248d4f695ccf9d4f919f757bcf3)) in package.json. closes [#18]
59 |
60 | ### Bug Fixes
61 |
62 | * update dev dependencies ([9d6132e](https://github.com/jantimon/css-variable/commit/9d6132e06342d7e4aa17e746d920b5fc5f7d7f1b))
63 |
64 | ## [3.9.0](https://github.com/jantimon/css-variable/compare/v3.8.0...v3.9.0) (2022-11-03)
65 |
66 | ### Features
67 |
68 | * improve css variable names ([2bd733f](https://github.com/jantimon/css-variable/commit/2bd733f793453bf1c954e87933a98b44998bd95f))
69 |
70 | ## [3.8.0](https://github.com/jantimon/css-variable/compare/v3.7.0...v3.8.0) (2022-08-02)
71 |
72 |
73 | ### Features
74 |
75 | * update @swc/core ([9318847](https://github.com/jantimon/css-variable/commit/93188474cb7c6026a1f3458161f57c97d6b8b550))
76 |
77 | # 3.7.0 (2022-07-15)
78 |
79 |
80 | ### Bug Fixes
81 |
82 | * **swc:** convert window paths to posix ([1f2fec0](https://github.com/jantimon/css-variable/commit/1f2fec0707f68ee6713dccb652bf733768e9b2a9)), closes [#6](https://github.com/jantimon/css-variable/issues/6)
83 |
84 |
85 | ### Features
86 |
87 | * add createVar, createGlobalTheme and assignVars ([7cde9d0](https://github.com/jantimon/css-variable/commit/7cde9d032bf3045484d8a9370cc5f414412bdf24))
88 | * add displayName babel plugin option ([5843862](https://github.com/jantimon/css-variable/commit/58438622e3e58bfd0b199d9dc665db0211eae198))
89 | * add full path to the dev variable name when using the swc plugin ([2af5985](https://github.com/jantimon/css-variable/commit/2af598512ce0596bb9a7890e32befacee9fb7708))
90 | * add swc plugin ([#2](https://github.com/jantimon/css-variable/issues/2)) ([e7e09c7](https://github.com/jantimon/css-variable/commit/e7e09c717b505578089550e5a903c411fa1ae89e))
91 | * reduze bundle size ([b726748](https://github.com/jantimon/css-variable/commit/b72674819369afc3f3cf6f95f5d19230c6e1ec79))
92 | * replace random fallback id ([00c569d](https://github.com/jantimon/css-variable/commit/00c569df081f41463a64f3eadddc720b36d113d6))
93 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # css-variable
2 |
3 | [](npmjs.com/package/css-variable) [](https://github.com/jantimon/css-variable/actions/workflows/e2e-test.yml)   
4 |
5 | Tiny ( ~0.3 kb ) treeshakable library to define CSS custom properties (variables) in JS.
6 | Compatible with 👩🎤 Emotion / 💅 StyledComponents / Linaria and similar CSS-in-JS solutions.
7 |
8 | ## Install
9 |
10 | ```bash
11 | npm i css-variable
12 | ```
13 |
14 | ## Docs
15 |
16 | [http://css-variable.js.org](http://css-variable.js.org)
17 |
18 |
19 | ## License
20 |
21 | Licensed under MIT
22 | Crafted with <3 [@jantimon](https://twitter.com/jantimon)
23 |
24 | Special thanks to [@4alpine](https://twitter.com/4lpine) for donating the package name.
--------------------------------------------------------------------------------
/babel.commonjs.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "presets": ["@babel/preset-typescript"],
3 | "plugins": [
4 | ["@babel/plugin-transform-modules-commonjs", {
5 | "allowTopLevelThis": false,
6 | "importInterop": "none"
7 | }]
8 | ]
9 | }
--------------------------------------------------------------------------------
/babel.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "presets": ["@babel/preset-typescript"],
3 | "plugins": [
4 | ]
5 | }
--------------------------------------------------------------------------------
/babel/hash.cjs:
--------------------------------------------------------------------------------
1 | /**
2 | * JS Implementation of MurmurHash2
3 | *
4 | * @author Gary Court
5 | * @see http://github.com/garycourt/murmurhash-js
6 | * @author Austin Appleby
7 | * @see http://sites.google.com/site/murmurhash/
8 | *
9 | * @param {string} str ASCII only
10 | * @return {string} Base 36 encoded hash result
11 | */
12 | function murmurhash2_32_gc(str) {
13 | let l = str.length
14 | let h = l
15 | let i = 0
16 | let k
17 |
18 | while (l >= 4) {
19 | k =
20 | (str.charCodeAt(i) & 0xff) |
21 | ((str.charCodeAt(++i) & 0xff) << 8) |
22 | ((str.charCodeAt(++i) & 0xff) << 16) |
23 | ((str.charCodeAt(++i) & 0xff) << 24)
24 |
25 | k = (k & 0xffff) * 0x5bd1e995 + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)
26 | k ^= k >>> 24
27 | k = (k & 0xffff) * 0x5bd1e995 + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)
28 |
29 | h =
30 | ((h & 0xffff) * 0x5bd1e995 +
31 | ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^
32 | k
33 |
34 | l -= 4
35 | ++i
36 | } // forgive existing code
37 |
38 | /* eslint-disable no-fallthrough */ switch (l) {
39 | case 3:
40 | h ^= (str.charCodeAt(i + 2) & 0xff) << 16
41 | case 2:
42 | h ^= (str.charCodeAt(i + 1) & 0xff) << 8
43 | case 1:
44 | h ^= str.charCodeAt(i) & 0xff
45 | h =
46 | (h & 0xffff) * 0x5bd1e995 + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)
47 | }
48 | /* eslint-enable no-fallthrough */
49 |
50 | h ^= h >>> 13
51 | h = (h & 0xffff) * 0x5bd1e995 + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)
52 | h ^= h >>> 15
53 |
54 | return (h >>> 0).toString(36)
55 | }
56 |
57 | module.exports = murmurhash2_32_gc;
--------------------------------------------------------------------------------
/babel/index.cjs:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | const PACKAGE_NAME = "css-variable";
3 | const hash = require("./hash.cjs");
4 | const pathRelative = require("path").relative;
5 |
6 | /** @typedef {import("@babel/core")} babel */
7 |
8 | /**
9 | * The context of a babel plugin run
10 | * @typedef {{
11 | * minifyVariables: boolean,
12 | * varCount: number,
13 | * varPrefix: string,
14 | * isImportedInCurrentFile: boolean,
15 | * localVarNames: string[],
16 | * opts: babel.PluginOptions & { displayName?: boolean }
17 | * } & babel.PluginPass} PluginPass
18 | */
19 |
20 | /**
21 | * @param {babel} babel
22 | * @returns {babel.PluginObj}
23 | */
24 | module.exports = function (babel) {
25 | const {
26 | types: { stringLiteral },
27 | } = babel;
28 |
29 | /**
30 | * @param {babel.NodePath | babel.NodePath} path;
31 | * @param {PluginPass} pluginPass
32 | */
33 | const injectVariableName = (path, pluginPass) => {
34 | // Skip if no import statements where found
35 | if (!pluginPass.localVarNames.length) {
36 | return;
37 | }
38 | const callee = path.node.callee;
39 | if (
40 | !("name" in callee) ||
41 | !pluginPass.localVarNames.includes(callee.name)
42 | ) {
43 | return;
44 | }
45 | const readableName =
46 | !pluginPass.minifyVariables && dashed(getNameByUsage(path));
47 | const readablePrefix = readableName ? `${readableName}--` : "";
48 | //
49 | // Inject the variable prefix
50 | //
51 | // E.g. CSSVariable() -> CSSVariable("1isaui4-0")
52 | // E.g. CSSVariable({value: "10px"}) -> CSSVariable("1isaui4-0", {value: "10px"})
53 | //
54 | const constructorArguments = path.node.arguments;
55 | const firstArg = constructorArguments[0];
56 | if (!firstArg || firstArg.type !== "StringLiteral") {
57 | constructorArguments.unshift(
58 | stringLiteral(
59 | readablePrefix + getUniqueHash(pluginPass) + pluginPass.varCount++
60 | )
61 | );
62 | }
63 | //
64 | // Inject @__PURE__ comment to tell terser that
65 | // creating s CSSVariable class instance will cause no
66 | // side effects and is save to be removed
67 | //
68 | path.addComment("leading", "@__PURE__");
69 | };
70 |
71 | return {
72 | name: `${PACKAGE_NAME} unique variable name injector`,
73 | pre() {
74 | this.isImportedInCurrentFile = false;
75 | this.varCount = 0;
76 | this.minifyVariables =
77 | this.opts.displayName !== undefined
78 | ? !this.opts.displayName
79 | : this.file.opts.envName !== "development";
80 | this.localVarNames = [];
81 | },
82 | visitor: {
83 | ImportDeclaration({ node }) {
84 | // Search for `import {CSSVariable} from "css-variable";`
85 | // Search for `import {CSSVariable as CustomName} from "css-variable";`
86 | const isLib = node.source.value === PACKAGE_NAME;
87 | if (!isLib) {
88 | return;
89 | }
90 | node.specifiers.forEach((specifier) => {
91 | const importSpecifier = "imported" in specifier && specifier.imported;
92 | if (!importSpecifier || !("name" in importSpecifier)) {
93 | return;
94 | }
95 | const localSpecifier =
96 | ("local" in specifier && specifier.local) || importSpecifier;
97 | if (
98 | importSpecifier.name === "CSSVariable" ||
99 | importSpecifier.name === "createVar"
100 | ) {
101 | this.localVarNames.push(localSpecifier.name);
102 | }
103 | });
104 | this.isImportedInCurrentFile = this.localVarNames.length > 0;
105 | },
106 | CallExpression(path) {
107 | return injectVariableName(path, this);
108 | },
109 | NewExpression(path) {
110 | return injectVariableName(path, this);
111 | },
112 | },
113 | };
114 | };
115 |
116 | /**
117 | * Tries to extract the name for readable names in developments
118 | * e.g.:
119 | *
120 | * `const fontSize = createVar()` -> fontSize
121 | * `const theme = { primary: createVar() }` -> primary
122 | *
123 | * @param {babel.NodePath} path
124 | */
125 | function getNameByUsage(path) {
126 | const parent = path.parent;
127 | if (!parent) return "";
128 | if (parent.type === "ObjectProperty") {
129 | const key = parent.key;
130 | if (key && key.type === "Identifier" && key.name) {
131 | return key.name;
132 | }
133 | }
134 | if (parent.type === "VariableDeclarator") {
135 | const id = parent.id;
136 | if (id && id.type === "Identifier" && id.name) {
137 | return id.name;
138 | }
139 | }
140 | return "";
141 | }
142 |
143 | /** @param {string} val*/
144 | function dashed(val) {
145 | /** handle camelCase and CONSTANT_CASE */
146 | return val
147 | .replace(/([0-9a-z])([A-Z])/g, "$1-$2")
148 | .toLowerCase()
149 | .replace(/_/g, "-");
150 | }
151 |
152 | /** @type {WeakMap} */
153 | const prefixCache = new WeakMap();
154 | /**
155 | * Returns a unique name based on the processed filename
156 | *
157 | * @param {babel.PluginPass} pass
158 | */
159 | function getUniqueHash(pass) {
160 | const fromCache = prefixCache.get(pass);
161 | if (fromCache) {
162 | return fromCache;
163 | }
164 | // Variables should keep the same generated name for
165 | // multiple builds.
166 | //
167 | // This is possible by hashing the source filename
168 | // which includes the CSSVariable.
169 | //
170 | // As an absolute file might be different from system to system
171 | // the relative filename is used instead
172 | const relativeFileName = pass.file.opts.filename
173 | ? pathRelative(__dirname, pass.file.opts.filename).replace(/\\/g, "/")
174 | : "jantimon";
175 | const prefix = hash(relativeFileName);
176 | prefixCache.set(pass, prefix);
177 | return prefix;
178 | }
179 |
--------------------------------------------------------------------------------
/docs/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "next/babel",
4 | "linaria/babel"
5 | ],
6 | "plugins": [
7 | "css-variable/babel"
8 | ]
9 | }
--------------------------------------------------------------------------------
/docs/.linariarc:
--------------------------------------------------------------------------------
1 | {
2 | babelOptions: {
3 | "presets": [
4 | "next/babel",
5 | "linaria/babel"
6 | ],
7 | "plugins": [
8 | "css-variable/babel"
9 | ]
10 | }
11 | }
--------------------------------------------------------------------------------
/docs/build.js:
--------------------------------------------------------------------------------
1 | /// @ts-check
2 | /*
3 | * This script generates a static export for the docs
4 | */
5 | const fs = require("fs");
6 | const child_process = require("child_process");
7 |
8 | async function run () {
9 | await spawnAsync("npm", ["install"], { cwd: __dirname, stdio: "inherit" }).promise;
10 | await spawnAsync("npm", ["run", "build"], { cwd: __dirname, stdio: "inherit" }).promise;
11 | await spawnAsync("npm", ["run", "export"], { cwd: __dirname, stdio: "inherit" }).promise;
12 | // CNAME for js.org
13 | fs.writeFileSync(__dirname + '/out/CNAME', 'css-variable.js.org');
14 | }
15 |
16 | run();
17 | function spawnAsync(command, args, options) {
18 | const child = child_process.spawn(command, args, options);
19 | return {child, promise: new Promise((resolve, reject) => {
20 | child.on("close", (code) => {
21 | if (code) {
22 | reject(new Error(`${command} failed - exit code: ${code}`));
23 | } else {
24 | resolve();
25 | }
26 | });
27 | })};
28 | }
29 |
--------------------------------------------------------------------------------
/docs/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/docs/next.config.js:
--------------------------------------------------------------------------------
1 | const withLinaria = require('next-linaria');
2 |
3 | module.exports = withLinaria({
4 | pageExtensions: ['page.tsx'],
5 | webpack(config, options) {
6 | return config;
7 | },
8 | });
--------------------------------------------------------------------------------
/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "docs",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "export": "next export"
10 | },
11 | "dependencies": {
12 | "@babel/core": "7.15.5",
13 | "@babel/preset-env": "^7.15.4",
14 | "classnames": "2.3.1",
15 | "css-variable": "file:../",
16 | "linaria": "2.1.0",
17 | "next": "12.2.3",
18 | "next-linaria": "0.11.0",
19 | "react": "18.2.0",
20 | "react-dom": "18.2.0",
21 | "react-syntax-highlighter": "^15.4.4",
22 | "typescript": "^4.4.3"
23 | },
24 | "devDependencies": {
25 | "@types/react": "^18.0.15",
26 | "@types/react-dom": "^18.0.6"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/docs/pages/CodeExample.tsx:
--------------------------------------------------------------------------------
1 | import { css } from "linaria";
2 | import { styled } from "linaria/react";
3 | import classnames from "classnames";
4 | import { useState } from "react";
5 | import SyntaxHighlighter from "react-syntax-highlighter";
6 | import dark from "react-syntax-highlighter/dist/cjs/styles/hljs/a11y-dark";
7 |
8 | const codeExampleStyles = css`
9 | margin: 0 auto;
10 | width: 100%;
11 | max-width: 600px;
12 | min-height: 50px;
13 | box-shadow: rgb(20 20 20 / 27%) 0.555556px 0.555556px 11.1111px;
14 | // Overrule react-syntax-highlighter style
15 | padding: 10px 20px !important;
16 | `;
17 |
18 | /** @param {{children, className?: string}} props */
19 | export const CodeExample = ({ children, className }) => (
20 |
25 | {children}
26 |
27 | );
28 |
29 | const CodeExampleWrapper = styled.div`
30 | display: grid;
31 | max-width: 600px;
32 | margin: 0 auto;
33 | width: 100%;
34 | `;
35 |
36 | const gridOverlay = css`
37 | grid-column-start: 1;
38 | grid-column-end: 1;
39 | grid-row-start: 2;
40 | grid-row-end: 2;
41 | `;
42 | const invisble = css`
43 | opacity: 0;
44 | pointer-events: none;
45 | `
46 |
47 | const CodeButtonWrapper = styled.div`
48 | grid-column-start: 1;
49 | grid-column-end: 1;
50 | grid-row-start: 1;
51 | grid-row-end: 1;
52 | justify-self: end;
53 | white-space: nowrap;
54 | margin-top: -5px;
55 | `;
56 |
57 | const MultiCodeButton = styled.button<{active?: boolean}>`
58 | background: #2b2b2b;
59 | transition: color 300ms;
60 | color: ${(props) => props.active ? 'rgba(230,230,230, 1)' : 'rgba(230,230,230, 0.7)'};
61 | &:hover {
62 | color: rgba(230,230,230, 1);
63 | }
64 | position: relative;
65 | top: 5px;
66 | border: 0;
67 | margin: 0;
68 | padding: 5px 20px;
69 | cursor: pointer;
70 | & + & {
71 | box-shadow: -8px 0px 1px -7px white;
72 | }
73 | `
74 |
75 | export const CodeExamples = ({ children }: {children: Record}) => {
76 | const keys = Object.keys(children);
77 | const [activeKey, setActiveKeys] = useState(keys[0]);
78 | return
79 |
80 | {keys.length > 1 && keys.map((key) => (
81 | setActiveKeys(key)}>{key}
82 | ))}
83 |
84 | {
85 | keys.map((key) => (
86 | {children[key]}
87 | ))
88 | }
89 |
90 | }
--------------------------------------------------------------------------------
/docs/pages/Theme.tsx:
--------------------------------------------------------------------------------
1 | /// @ts-check
2 | import { createVar, createGlobalTheme } from "css-variable";
3 | import { css } from "linaria";
4 | import { styled } from "linaria/react";
5 |
6 | export const theme = {
7 | fontSize: createVar("FontSize"),
8 | spacings: {
9 | s: createVar(),
10 | m: createVar(),
11 | l: createVar(),
12 | },
13 | colors: {
14 | base: createVar("base"),
15 | primary: createVar("primary"),
16 | secondary: createVar("secondary"),
17 | backgroundPrimary: createVar(),
18 | backgroundSecondary: createVar(),
19 | },
20 | };
21 |
22 | export const Font = css`
23 | :global {
24 | @import url("https://fonts.googleapis.com/css?family=Noto%20Sans");
25 | body {
26 | font-family: "Noto Sans";
27 | }
28 | }
29 | `;
30 |
31 | export const Base = css`
32 | :global {
33 | * { box-sizing: inherit }
34 | body {
35 | min-width: min-content;
36 | margin: 0;
37 | padding: 0;
38 | background: ${theme.colors.backgroundPrimary.val};
39 | box-sizing: border-box;
40 | }
41 | }
42 | `;
43 |
44 | const lightTheme = /*@__PURE__*/createGlobalTheme("", theme, {
45 | fontSize: "12px",
46 | spacings: {
47 | s: "10px",
48 | m: "20px",
49 | l: "30px",
50 | },
51 | colors: {
52 | base: "#24292e",
53 | primary: "#6290C3",
54 | secondary: "#C2E7DA",
55 | backgroundPrimary: "#efefef",
56 | backgroundSecondary: "#e8e8e7",
57 | },
58 | });
59 | const darkTheme = /*@__PURE__*/createGlobalTheme("", theme, {
60 | fontSize: "12px",
61 | spacings: {
62 | s: "10px",
63 | m: "20px",
64 | l: "30px",
65 | },
66 | colors: {
67 | base: "#efefef",
68 | primary: "#6290C3",
69 | secondary: "#C2E7DA",
70 | backgroundPrimary: "#24292e",
71 | backgroundSecondary: "#393939",
72 | },
73 | });
74 |
75 | const invertedTheme = css`
76 | ${darkTheme}
77 | @media (prefers-color-scheme: dark) {
78 | ${lightTheme}
79 | }
80 | `;
81 |
82 | const ThemeSwitchButton = styled.button`
83 | border: none;
84 | background: transparent;
85 | padding: 0;
86 | position: relative;
87 | overflow: hidden;
88 | font-size: 80%;
89 | cursor: pointer;
90 | :before {
91 | transition: transform 300ms ease-in-out;
92 | content: "🌙";
93 | display: block;
94 | ${`.${invertedTheme}`} & {
95 | transform: translateY(-120%);
96 | }
97 | }
98 | :after {
99 | transition: transform 300ms ease-in-out;
100 | position: absolute;
101 | left: 0;
102 | top: 0;
103 | content: "☀️";
104 | transform: translateY(240%);
105 | ${`.${invertedTheme}`} & {
106 | transform: translateY(0);
107 | }
108 | }
109 | `;
110 |
111 | export const ThemeSwitch = () => (
112 | document.body.classList.toggle(invertedTheme)}
114 | title="Toggle Light/Dark Mode"
115 | />
116 | );
117 |
118 | export const DefaultTheme = css`
119 | :global() {
120 | :root {
121 | ${lightTheme}
122 | }
123 | @media (prefers-color-scheme: dark) {
124 | :root {
125 | ${darkTheme}
126 | }
127 | }
128 | }
129 | `;
130 |
--------------------------------------------------------------------------------
/docs/pages/index.page.tsx:
--------------------------------------------------------------------------------
1 | import { styled } from "linaria/lib/react";
2 | import Head from "next/head";
3 | import { CodeExamples } from "./CodeExample";
4 | import "./Theme";
5 | import { theme, ThemeSwitch } from "./Theme";
6 |
7 | const HeaderWrapper = styled.header`
8 | background: ${theme.colors.backgroundSecondary.val};
9 | position: fixed;
10 | top: 0;
11 | width: 100%;
12 | padding: 5px 10px;
13 | z-index: 10;
14 | `;
15 |
16 | const Header = styled.div`
17 | display: grid;
18 | grid-template-columns: auto max-content max-content max-content;
19 | grid-template-rows: 1fr;
20 | gap: 10px;
21 | color: ${theme.colors.base.val};
22 | align-items: end;
23 | max-width: 1200px;
24 | margin: 0 auto;
25 | `;
26 |
27 | const TextLogo = styled.h1`
28 | font-size: 18px;
29 | margin: 0;
30 | letter-spacing: -1px;
31 | `;
32 |
33 | const HeaderLink = styled.a`
34 | font-size: 14px;
35 | color: ${theme.colors.base.val};
36 | text-decoration: none;
37 | `;
38 |
39 | const Main = styled.main`
40 | padding: 80px 50px 0px;
41 | width: 100%;
42 | max-width: 900px;
43 | margin: 0 auto;
44 | display: flex;
45 | flex-direction: column;
46 | gap: ${theme.spacings.m.val};
47 |
48 | @media (min-width: 860px) {
49 | padding-left: 10px;
50 | padding-right: 10px;
51 | }
52 | `;
53 |
54 | const Section = styled.section<{ reverse?: boolean }>`
55 | display: flex;
56 | gap: 30px;
57 | flex-wrap: wrap;
58 | flex-direction: ${({ reverse }) => (reverse ? "row-reverse" : "row")};
59 | margin-bottom: 80px;
60 | @media (min-width: 860px) {
61 | flex-wrap: nowrap;
62 | margin-bottom: 120px;
63 | }
64 | `;
65 |
66 | const SectionContent = styled.div`
67 | display: flex;
68 | max-width: 600px;
69 | margin: 0 auto;
70 | gap: ${theme.spacings.m.val};
71 | flex-direction: column;
72 | flex-grow: 0;
73 | flex-shrink: 1;
74 | width: 100%;
75 | @media (min-width: 860px) {
76 | flex-wrap: nowrap;
77 | margin-bottom: 40px;
78 | }
79 | `;
80 |
81 | const SectionExample = styled.div`
82 | display: flex;
83 | gap: 10px;
84 | flex-direction: column;
85 | flex-grow: 0;
86 | flex-shrink: 0;
87 | width: 100%;
88 | @media (min-width: 860px) {
89 | width: 65%;
90 | }
91 | `;
92 |
93 | const Intro = styled.h2`
94 | font-size: 20px;
95 | color: ${theme.colors.base.val};
96 | text-align: center;
97 | margin-bottom: 40px;
98 | `;
99 |
100 | const Headline = styled.h2`
101 | font-size: 18px;
102 | color: ${theme.colors.base.val};
103 | margin: 0 0 5px 0;
104 | `;
105 |
106 | const Text = styled.p`
107 | font-size: 16px;
108 | color: ${theme.colors.base.val};
109 | margin: 0 0 15px 0;
110 | `;
111 |
112 | const Footer = styled.footer`
113 | font-size: 14px;
114 | background: ${theme.colors.backgroundSecondary.val};
115 | color: ${theme.colors.base.val};
116 | padding: 20px;
117 | `;
118 |
119 | const FooterContent = styled.div`
120 | max-width: 1200px;
121 | width: 100%;
122 | margin: 0 auto;
123 | text-align: center;
124 | `;
125 |
126 | const Badges = styled.div`
127 | display: inline-flex;
128 | gap: 8px;
129 | margin-right: 8px;
130 | margin-bottom: 8px;
131 | line-height: 0;
132 | `;
133 |
134 | const Index = () => (
135 | <>
136 |
137 |
138 |
139 |
140 |
141 | CSS Variable
142 |
143 | GitHub
144 |
145 |
146 |
147 |
148 |
149 | CSS Variables for your CSS-in-JS solution
150 |
151 |
152 |
153 | Built with high focus on performance
154 |
155 | ✨ better css minification
156 |
157 |
158 | ✨ smaller virtual DOM updates
159 |
160 |
161 | ✨ less crititcal SSR CSS
162 |
163 |
164 | ✨ unique variable names
165 |
166 |
167 |
168 |
169 | {{
170 | base: `
171 | import { createVar } from 'css-variable';
172 |
173 | export const tokens = {
174 | primary: createVar(),
175 | secondary: createVar(),
176 | };
177 | `,
178 | }}
179 |
180 |
181 |
182 | {{
183 | "styled-components": `
184 | import { createGlobalTheme } from 'css-variable';
185 | import { createGlobalStyle } from 'styled-components';
186 | import { tokens } from './tokens';
187 |
188 | export const GlobalStyles = createGlobalStyle\`
189 | $\{createGlobalTheme(":root", tokens, {
190 | primary: '#3a5779',
191 | secondary: '#23374e',
192 | })}
193 | \`;
194 | `,
195 |
196 | emotion: `
197 | import { createGlobalTheme } from 'css-variable';
198 | import { Global, css } from '@emotion/react';
199 | import { tokens } from './tokens';
200 |
201 | export const GlobalStyles = () =>
202 | ;
208 | `,
209 |
210 | linaria: `
211 | import { createGlobalTheme } from 'css-variable';
212 | import { css } from 'linaria';
213 | import { tokens } from './tokens';
214 |
215 | export const globalStyles = css\`:global() {
216 | $\{createGlobalTheme(":root", tokens, {
217 | primary: '#3a5779',
218 | secondary: '#23374e',
219 | })
220 | }\`;
221 | `,
222 | }}
223 |
224 |
225 |
226 | {{
227 | "js source": `
228 | import { tokens } from './tokens';
229 |
230 | export const Headline = styled.h1\`
231 | color: \${tokens.primary};
232 | \`;
233 | `,
234 | "css result": `
235 | .se7gjt0-headline {
236 | color: var(--primary--1isauia0);
237 | }
238 | `,
239 | }}
240 |
241 |
242 |
243 |
244 |
245 |
246 | Create themable CSS Snippets
247 |
248 | Define which parts of your reusable css are customizable without
249 | overwrites
250 |
251 |
252 |
253 |
254 | {{
255 | base: `
256 | export const startColor = createVar({value: '#238f97'});
257 | export const endColor = createVar({value: '#5442bb'});
258 |
259 | export const gradientHover = css\`
260 | background: linear-gradient(to right,
261 | \${gradientStartColor.val},
262 | \${gradientEndColor.val});
263 |
264 | background-size: 200% 200%;
265 | animation: rainbow 2s ease-in-out infinite;
266 | background-clip: text;
267 |
268 | :focus, :hover {
269 | color:rgba(0,0,0,0);
270 | }
271 | @keyframes rainbow {
272 | 0%{background-position:left}
273 | 50%{background-position:right}
274 | 100%{background-position:left}
275 | }
276 | \`;
277 | `,
278 | }}
279 |
280 |
281 | {{
282 | "js source": `
283 | import { startColor, endColor, gradientHover } from './gradient';
284 |
285 | export const Button = styled.button\`
286 | \${startColor.toStyle('#f5ab35')}
287 | \${endColor.toStyle('#8d1d1d')}
288 | \${gradientHover}
289 | \`;
290 | `,
291 | "css result": `
292 | .se7gjt0-button {
293 | --1isauia0: #f5ab35;
294 | --1isauia1: #8d1d1d;
295 | /* the css from gradientHover */
296 | }
297 | `,
298 | }}
299 |
300 |
301 |
302 |
303 |
304 |
305 | Unique and consistent variable names
306 |
307 | The recommended babel plugin generates unique variable names during
308 | build time
309 |
310 |
311 | Automatic DX
312 |
313 | All babel generated variable names will have human readable names
314 | during development
315 |
316 |
317 |
318 |
319 | {{
320 | babel: `
321 | {
322 | "plugins": [
323 | "css-variable/babel"
324 | ]
325 | }
326 | `,
327 | swc: `
328 | {
329 | "plugins": [
330 | "css-variable/swc", { "basePath": __dirname },
331 | ]
332 | }
333 | `,
334 | withOptions: `
335 | {
336 | "plugins": [
337 | ["css-variable/babel", {
338 | // Prefix vairables with a readable name e.g. 'primary--1isauia0'
339 | // Default for production: false
340 | // Default for development: true
341 | displayName: true
342 | }]
343 | ]
344 | }
345 | `,
346 | }}
347 |
348 |
349 | {{
350 | original: `
351 | import { createVar } from 'css-variable';
352 |
353 | export const theme = {
354 | primary: createVar(),
355 | secondary: createVar(),
356 | };
357 | `,
358 | "transpiled dev": `
359 | import { createVar } from 'css-variable';
360 |
361 | export const theme = {
362 | primary: /*@__PURE__*/createVar("primary--1isauia0"),
363 | secondary: /*@__PURE__*/createVar("secondary--1isauia1"),
364 | };
365 | `,
366 | "transpiled prod": `
367 | import { createVar } from 'css-variable';
368 |
369 | export const theme = {
370 | primary: /*@__PURE__*/createVar("1isauia0"),
371 | secondary: /*@__PURE__*/createVar("1isauia1"),
372 | };
373 | `,
374 | }}
375 |
376 |
377 |
378 |
379 |
380 |
381 | Typed Contracts
382 |
383 | By default any string is a valid value for a CSSVariable.
384 |
385 |
386 | But it doesn't end here - the generic interface allows to define
387 | explicitly which values are assignable
388 |
389 |
390 |
391 |
392 | {{
393 | base: `
394 | import { createVar } from 'css-variable';
395 | import type { CSSHexColor, CSSPixelValue } from 'css-variable';
396 |
397 | export const tokens = {
398 | colors: {
399 | primary: createVar(),
400 | secondary: createVar(),
401 | },
402 | spacing: {
403 | large: createVar()
404 | }
405 | };
406 | `,
407 | }}
408 |
409 |
410 |
411 |
412 |
459 | >
460 | );
461 |
462 | export default Index;
463 |
--------------------------------------------------------------------------------
/docs/public/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jantimon/css-variable/ef9b6c8e8998a5c31ad8764e1771d892b1d373fc/docs/public/static/favicon.png
--------------------------------------------------------------------------------
/docs/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "strict": false,
12 | "forceConsistentCasingInFileNames": true,
13 | "noEmit": true,
14 | "esModuleInterop": true,
15 | "module": "esnext",
16 | "moduleResolution": "node",
17 | "resolveJsonModule": true,
18 | "isolatedModules": true,
19 | "jsx": "preserve",
20 | "incremental": true
21 | },
22 | "include": [
23 | "next-env.d.ts",
24 | "**/*.ts",
25 | "**/*.tsx"
26 | ],
27 | "exclude": [
28 | "node_modules"
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/examples/styled-components/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (api) {
2 | api.cache(true);
3 | return {
4 | presets: ["next/babel"],
5 | plugins: [
6 | ["css-variable/babel", { async: false }],
7 | ["babel-plugin-styled-components", { ssr: true }],
8 | ],
9 | };
10 | };
11 |
--------------------------------------------------------------------------------
/examples/styled-components/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
6 |
--------------------------------------------------------------------------------
/examples/styled-components/next.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | pageExtensions: ["page.tsx"],
3 | };
4 |
--------------------------------------------------------------------------------
/examples/styled-components/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@example/styled-components",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start"
9 | },
10 | "dependencies": {
11 | "@types/react": "17.0.20",
12 | "@types/react-dom": "17.0.9",
13 | "@types/styled-components": "5.1.14",
14 | "babel-plugin-styled-components": "^1.13.2",
15 | "css-variable": "file:../../",
16 | "next": "^14.2.3",
17 | "react": "^18.2.0",
18 | "react-dom": "^18.2.0",
19 | "styled-components": "^6.1.11",
20 | "typescript": "5.4.5"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/examples/styled-components/pages/gradient/index.page.tsx:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 | import {
3 | gradientEndColor,
4 | gradientHover,
5 | gradientStartColor,
6 | } from "./text-gradient";
7 |
8 | const Link = styled.a`
9 | font-family: Arial, Helvetica, sans-serif;
10 | font-size: 20px;
11 | ${gradientStartColor.toStyle("#5610a5")};
12 | ${gradientEndColor.toStyle("#2286ad")};
13 | ${gradientHover};
14 | `;
15 |
16 | const Page = () => Click me;
17 |
18 | export default Page;
19 |
--------------------------------------------------------------------------------
/examples/styled-components/pages/gradient/text-gradient.ts:
--------------------------------------------------------------------------------
1 | import { createVar, CSSHexColor } from "css-variable";
2 | import { css } from "styled-components";
3 |
4 | export const fontColor = createVar({value: "currentColor"});
5 | /** The linear gradient start color during hover */
6 | export const gradientStartColor = createVar();
7 | /** The linear gradient end color during hover */
8 | export const gradientEndColor = createVar();
9 |
10 | export const gradientHover = css`
11 | color: ${fontColor.val};
12 | background: linear-gradient(to right, ${gradientStartColor.val}, ${gradientEndColor.val});
13 | background-size: 200% 200%;
14 | animation: rainbow 2s ease-in-out infinite;
15 | background-clip: text;
16 | -webkit-background-clip:text;
17 | transition: color .2s ease-in-out;
18 | }
19 | :focus,
20 | :hover{
21 | color:rgba(0,0,0,0);
22 | }
23 | @keyframes rainbow {
24 | 0%{background-position:left}
25 | 50%{background-position:right}
26 | 100%{background-position:left}
27 | }
28 | `;
29 |
30 |
--------------------------------------------------------------------------------
/examples/styled-components/pages/index.page.tsx:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 | import { CSSPixelValue, createVar, createGlobalTheme } from "css-variable";
3 |
4 | const theme = {
5 | fontSize: createVar("FontSize"),
6 | spacings: {
7 | s: createVar(),
8 | m: createVar(),
9 | l: createVar(),
10 | },
11 | colors: {
12 | primary: createVar("primary"),
13 | secondary: createVar("secondary"),
14 | },
15 | };
16 |
17 | const ThemeA = styled.div`
18 | ${createGlobalTheme("", theme, {
19 | fontSize: "12px",
20 | spacings: {
21 | s: "10px",
22 | m: "20px",
23 | l: "30px",
24 | },
25 | colors: {
26 | primary: "#6290C3",
27 | secondary: "#C2E7DA",
28 | },
29 | })}
30 | `;
31 |
32 | const ThemeB = styled.div`
33 | ${createGlobalTheme("", theme, {
34 | fontSize: "24px",
35 | spacings: {
36 | s: "20px",
37 | m: "40px",
38 | l: "60px",
39 | },
40 | colors: {
41 | primary: "#7C9EB2",
42 | secondary: "#52528C",
43 | },
44 | })}
45 | `;
46 |
47 | const colorVar = createVar({ value: theme.colors.primary });
48 | const xVar = createVar({ value: "0" });
49 |
50 | const StyledHeadline = styled.h1`
51 | font-family: Arial, Helvetica, sans-serif;
52 | font-size: ${theme.fontSize.val};
53 | color: ${colorVar.val};
54 | transform: translateX(${xVar.val});
55 | width: calc(100% - 1 * ${xVar.val});
56 | `;
57 |
58 | const FancyComponent: React.FunctionComponent<{color?:string}> = ({ color, children }) => {
59 | return (
60 |
61 | {children}
62 |
63 | );
64 | };
65 |
66 | const BigBox = styled.div`
67 | background: ${theme.colors.secondary.val};
68 | padding: ${theme.spacings.m.val};
69 |
70 | ${colorVar.toStyle("grey")}
71 | ${xVar.toStyle('20px')}
72 |
73 | @media (min-width: 500px) {
74 | ${xVar.toStyle('250px')};
75 | }
76 | `;
77 |
78 | const Demo = () => (
79 | <>
80 | Demo
81 |
82 | xOffset
83 |
84 |
85 | Inside Box
86 |
87 | >
88 | );
89 |
90 | const Index = () => (
91 | <>
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | >
101 | );
102 |
103 | export default Index;
104 |
--------------------------------------------------------------------------------
/examples/styled-components/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "strict": false,
12 | "forceConsistentCasingInFileNames": true,
13 | "noEmit": true,
14 | "esModuleInterop": true,
15 | "module": "esnext",
16 | "moduleResolution": "node",
17 | "resolveJsonModule": true,
18 | "isolatedModules": true,
19 | "jsx": "preserve",
20 | "incremental": true
21 | },
22 | "include": [
23 | "next-env.d.ts",
24 | "**/*.ts",
25 | "**/*.tsx"
26 | ],
27 | "exclude": [
28 | "node_modules"
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/jest.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "testPathIgnorePatterns" : [
3 | // don't run swc tests during babel jest runs
4 | "/test/swc/*.*"
5 | ]
6 | };
--------------------------------------------------------------------------------
/license:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Jan Nicklas
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "css-variable",
3 | "version": "6.0.0",
4 | "description": "define CSS custom properties (variables) in JS",
5 | "main": "./dist/index.cjs",
6 | "module": "./dist/index.mjs",
7 | "type": "module",
8 | "exports": {
9 | ".": {
10 | "types": "./dist/index.d.ts",
11 | "import": "./dist/index.mjs",
12 | "require": "./dist/index.cjs"
13 | },
14 | "./babel": "./babel/index.cjs",
15 | "./swc": "./swc/target/wasm32-wasip1/release/swc_plugin_css_variable.wasm"
16 | },
17 | "types": "./dist/index.d.ts",
18 | "files": [
19 | "src",
20 | "dist",
21 | "babel",
22 | "swc/package.json",
23 | "swc/target/wasm32-wasip1/release/swc_plugin_css_variable.wasm"
24 | ],
25 | "sideEffects": false,
26 | "scripts": {
27 | "prepublishOnly": "npm run build && npm run build:swc",
28 | "build": "npm run build:types && npm run build:commonjs && npm run build:module && npm run build:modulemin",
29 | "build:commonjs": "babel --config-file=./babel.commonjs.cjs -o dist/index.cjs src/index.ts",
30 | "build:module": "babel --config-file=./babel.config.cjs -o dist/index.mjs src/index.ts",
31 | "build:types": "tsc --skipLibCheck --emitDeclarationOnly --declaration --target ESNext --outDir dist src/index.ts",
32 | "build:modulemin": "terser ./dist/index.mjs -o ./dist/index.min.mjs -m --ecma 2017 --module --toplevel -b -c",
33 | "build:swc": "cargo build --manifest-path ./swc/Cargo.toml --release --target=wasm32-wasip1",
34 | "changelog": "npx standard-version",
35 | "test": "npm run test:e2e && npm run test:jest",
36 | "test:e2e": "node ./test/examples.js",
37 | "test:jest": "jest",
38 | "test:swc": "npm run test:swc:cargo && npm run build:swc && npm run test:swc:jest",
39 | "test:swc:jest": "jest --config test/swc/jest.config.js",
40 | "test:swc:cargo": "cargo test --manifest-path ./swc/Cargo.toml",
41 | "docs": "node ./docs/build.js"
42 | },
43 | "repository": {
44 | "type": "git",
45 | "url": "git+https://github.com/jantimon/css-variable.git"
46 | },
47 | "release": {
48 | "branches": [
49 | "main"
50 | ]
51 | },
52 | "keywords": [
53 | "css"
54 | ],
55 | "author": "Jan Nicklas",
56 | "license": "MIT",
57 | "bugs": {
58 | "url": "https://github.com/jantimon/css-variable/issues"
59 | },
60 | "homepage": "https://css-variable.js.org/",
61 | "devDependencies": {
62 | "@babel/cli": "7.19.3",
63 | "@babel/core": "7.22.0",
64 | "@babel/plugin-transform-modules-commonjs": "^7.19.6",
65 | "@babel/preset-typescript": "^7.18.6",
66 | "@babel/runtime": "^7.20.1",
67 | "@babel/types": "^7.22.0",
68 | "@swc/core": "1.11.1",
69 | "@swc/jest": "^0.2.37",
70 | "@types/jest": "^29.2.3",
71 | "jest": "^29.3.1",
72 | "terser": "5.15.1",
73 | "typescript": "^5.4.5"
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export type CSSPixelValue = '0' | `${string}px`;
2 | export type CSSLengthValue = '0' | `${string}${| "%"
3 | | "ch"
4 | | "cm"
5 | | "em"
6 | | "ex"
7 | | "in"
8 | | "mm"
9 | | "pc"
10 | | "pt"
11 | | "px"
12 | | "rem"
13 | | "vh"
14 | | "vmax"
15 | | "vmin"
16 | | "vw"
17 | }`;
18 | export type CSSAngleValue = `${string}${| "deg"
19 | | "grad"
20 | | "rad"
21 | | "turn"
22 | }`;
23 | export type CSSHexColor = `#${string}`;
24 |
25 | type CSSVariableOptions = { value: TValue | CSSVariable };
26 |
27 | /**
28 | * Usually css-variable should always be used with its babel plugin
29 | *
30 | * However in some scenarios e.g. storybook / jest it might be difficult
31 | * to setup.
32 | * For those cases this counter provides a very basic fallback to generate
33 | * different ids.
34 | */
35 | let fallbackId = 9 ** 9;
36 |
37 | export class CSSVariable extends (
38 | // Inherit from String to be compatible to most CSS-in-JS solutions
39 | // Hacky cast to any for reduced autocomplete
40 | String as any as { new(base: string): { toString: () => string } }
41 | ) {
42 | /** Name e.g. `--baseSize` */
43 | readonly name: string;
44 | /** Value e.g. `var(--baseSize, 12px)` */
45 | readonly val: string;
46 | /**
47 | * Creates a new CSS Variable with a unique autogenerated name
48 | *
49 | * E.g. `var(--1isaui4-0)`
50 | */
51 | constructor();
52 | /**
53 | * Creates a new CSS Variable with a custom defined name
54 | *
55 | * E.g. `var(--baseSize)`
56 | */
57 | constructor(uniqueName: string);
58 | /**
59 | * Creates a new CSS Variable with a unique autogenerated name
60 | * and a fallback value
61 | *
62 | * E.g. `var(--1isaui4-0, 12px)`
63 | */
64 | constructor(options: CSSVariableOptions);
65 | /**
66 | * Creates a new CSS Variable with a unique autogenerated name
67 | * and a fallback value
68 | *
69 | * E.g. `var(--baseSize, 12px)`
70 | */
71 | constructor(uniqueName: string, options: CSSVariableOptions);
72 | /*#__PURE__*/
73 | constructor(
74 | ...args: Array>
75 | ) {
76 | const optionArg = args.find(
77 | (arg): arg is CSSVariableOptions => typeof arg === "object"
78 | );
79 | const name =
80 | "--" +
81 | (args.filter((arg): arg is string => typeof arg === "string").join('-').toLowerCase() ||
82 | // Fallback if babel plugin is missing
83 | (fallbackId++).toString(16));
84 | const val = `var(${name}${optionArg ? `, ${optionArg.value}` : ""})`;
85 | super(val);
86 | this.val = val;
87 | this.name = name;
88 | }
89 | /** Returns the variable name e.g. `--baseSize` */
90 | getName() {
91 | return this.name;
92 | }
93 | /** Create a CSS Object e.g. `{ "--baseSize": '12px' }` */
94 | toStyle(newValue: TValue | CSSVariable) {
95 | return { [this.name]: (`${newValue}` as unknown as TValue) };
96 | }
97 | /** Create a CSS String e.g. `--baseSize:12px;` */
98 | toCSS(newValue: TValue | CSSVariable) {
99 | return `${this.name}:${newValue};`;
100 | }
101 | }
102 |
103 |
104 | type ICreateVar = {
105 | /**
106 | * Creates a new CSS Variable with a unique autogenerated name
107 | *
108 | * E.g. `var(--1isaui4-0)`
109 | */
110 | (): CSSVariable;
111 | /**
112 | * Creates a new CSS Variable with a custom defined name
113 | *
114 | * E.g. `var(--baseSize)`
115 | */
116 | (uniqueName: string): CSSVariable;
117 | /**
118 | * Creates a new CSS Variable with a unique autogenerated name
119 | * and a fallback value
120 | *
121 | * E.g. `var(--1isaui4-0, 12px)`
122 | */
123 | (options: CSSVariableOptions): CSSVariable;
124 | /**
125 | * Creates a new CSS Variable with a unique autogenerated name
126 | * and a fallback value
127 | *
128 | * E.g. `var(--baseSize, 12px)`
129 | */
130 | (uniqueName: string, options: CSSVariableOptions): CSSVariable;
131 | }
132 | export const createVar: ICreateVar = (...args: any[]) => new (CSSVariable as any)(...args);
133 |
134 | /**
135 | * A theme structure groups multiple CSSVariable instances
136 | * in a nested object structure e.g.:
137 | *
138 | * ```ts
139 | * const theme = {
140 | * colors: {
141 | * primary: createVar(),
142 | * secondary: createVar()
143 | * },
144 | * spacings: {
145 | * small: createVar(),
146 | * large: createVar()
147 | * }
148 | * }
149 | * ```
150 | */
151 | type ThemeStructure = { [key: string]: CSSVariable | ThemeStructure };
152 |
153 | /** The allowed value type for the given CSSVariable */
154 | export type CSSVariableValueArgument = T extends CSSVariable ? U : T
155 | /**
156 | * The ThemeValues type is a helper to map a ThemeStructure to a value type
157 | * to guarantee that the structure and values in createGlobalTheme match
158 | */
159 | type ThemeValues = {
160 | [Property in keyof TThemeStructure]: TThemeStructure[Property] extends CSSVariable
161 | ? CSSVariableValueArgument | CSSVariable>
162 | : TThemeStructure[Property] extends ThemeStructure
163 | ? ThemeValues
164 | : never;
165 | };
166 |
167 | type DeepPartial = T extends Function ? T : (T extends object ? { [P in keyof T]?: DeepPartial; } : T);
168 |
169 | /**
170 | * Assign multiple CSSVariables for a given flat or nested Theme Contract
171 | *
172 | * @example
173 | * ```js
174 | * const theme = {
175 | * colors: {
176 | * primary: createVar(),
177 | * secondary: createVar(),
178 | * }
179 | * }
180 | *
181 | * const brightThemeCSS = assignVars(theme, {
182 | * colors: {
183 | * primary: "#6290C3",
184 | * }
185 | * })
186 | *
187 | * console.log(brightThemeCSS) // -> `--1isaui4-0:#6290C3;`
188 | * ```
189 | */
190 | export const assignVars = (
191 | cssVariables: TTheme,
192 | cssVariableValues: DeepPartial>
193 | ): string =>
194 | Object.keys(cssVariableValues)
195 | .map((key) =>
196 | typeof cssVariableValues[key] === "string"
197 | ? (cssVariables[key] as CSSVariable).toCSS(cssVariableValues[key] as string)
198 | : assignVars(
199 | cssVariables[key] as ThemeStructure,
200 | cssVariableValues[key] as ThemeValues
201 | )
202 | )
203 | .join("");
204 |
205 | /**
206 | * Serialize all CSS Variable values for an entire nested or flat Theme Contract
207 | *
208 | * @example
209 | * ```js
210 | * const theme = {
211 | * colors: {
212 | * primary: createVar(),
213 | * secondary: createVar(),
214 | * }
215 | * }
216 | *
217 | * const brightThemeCSS = createGlobalTheme(":root", theme, {
218 | * colors: {
219 | * primary: "#6290C3",
220 | * secondary: "#C2E7DA",
221 | * }
222 | * })
223 | *
224 | * console.log(brightThemeCSS) // -> `:root { --1isaui4-0:#6290C3; --1isaui4-1:#C2E7DA; }`
225 | * ```
226 | */
227 | export const createGlobalTheme = (scope: string | undefined | null,
228 | cssVariables: TTheme,
229 | cssVariableValues: ThemeValues): string => `${scope ? `${scope}{` : ''}${assignVars(cssVariables, cssVariableValues as DeepPartial>)}${scope ? '}' : ''}`;
--------------------------------------------------------------------------------
/swc/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 4
4 |
5 | [[package]]
6 | name = "ahash"
7 | version = "0.8.11"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
10 | dependencies = [
11 | "cfg-if",
12 | "once_cell",
13 | "version_check",
14 | "zerocopy",
15 | ]
16 |
17 | [[package]]
18 | name = "aho-corasick"
19 | version = "1.1.3"
20 | source = "registry+https://github.com/rust-lang/crates.io-index"
21 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
22 | dependencies = [
23 | "memchr",
24 | ]
25 |
26 | [[package]]
27 | name = "allocator-api2"
28 | version = "0.2.21"
29 | source = "registry+https://github.com/rust-lang/crates.io-index"
30 | checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
31 |
32 | [[package]]
33 | name = "anes"
34 | version = "0.1.6"
35 | source = "registry+https://github.com/rust-lang/crates.io-index"
36 | checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
37 |
38 | [[package]]
39 | name = "ansi_term"
40 | version = "0.12.1"
41 | source = "registry+https://github.com/rust-lang/crates.io-index"
42 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
43 | dependencies = [
44 | "winapi",
45 | ]
46 |
47 | [[package]]
48 | name = "anstyle"
49 | version = "1.0.10"
50 | source = "registry+https://github.com/rust-lang/crates.io-index"
51 | checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
52 |
53 | [[package]]
54 | name = "anyhow"
55 | version = "1.0.97"
56 | source = "registry+https://github.com/rust-lang/crates.io-index"
57 | checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
58 |
59 | [[package]]
60 | name = "ascii"
61 | version = "1.1.0"
62 | source = "registry+https://github.com/rust-lang/crates.io-index"
63 | checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
64 |
65 | [[package]]
66 | name = "ast_node"
67 | version = "3.0.0"
68 | source = "registry+https://github.com/rust-lang/crates.io-index"
69 | checksum = "91fb5864e2f5bf9fd9797b94b2dfd1554d4c3092b535008b27d7e15c86675a2f"
70 | dependencies = [
71 | "proc-macro2",
72 | "quote",
73 | "swc_macros_common",
74 | "syn",
75 | ]
76 |
77 | [[package]]
78 | name = "autocfg"
79 | version = "1.4.0"
80 | source = "registry+https://github.com/rust-lang/crates.io-index"
81 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
82 |
83 | [[package]]
84 | name = "base62"
85 | version = "2.2.1"
86 | source = "registry+https://github.com/rust-lang/crates.io-index"
87 | checksum = "10e52a7bcb1d6beebee21fb5053af9e3cbb7a7ed1a4909e534040e676437ab1f"
88 | dependencies = [
89 | "rustversion",
90 | ]
91 |
92 | [[package]]
93 | name = "base64"
94 | version = "0.22.1"
95 | source = "registry+https://github.com/rust-lang/crates.io-index"
96 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
97 |
98 | [[package]]
99 | name = "base64-simd"
100 | version = "0.7.0"
101 | source = "registry+https://github.com/rust-lang/crates.io-index"
102 | checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5"
103 | dependencies = [
104 | "simd-abstraction",
105 | ]
106 |
107 | [[package]]
108 | name = "better_scoped_tls"
109 | version = "1.0.0"
110 | source = "registry+https://github.com/rust-lang/crates.io-index"
111 | checksum = "50fd297a11c709be8348aec039c8b91de16075d2b2bdaee1bd562c0875993664"
112 | dependencies = [
113 | "scoped-tls",
114 | ]
115 |
116 | [[package]]
117 | name = "bitflags"
118 | version = "2.9.0"
119 | source = "registry+https://github.com/rust-lang/crates.io-index"
120 | checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
121 |
122 | [[package]]
123 | name = "bitvec"
124 | version = "1.0.1"
125 | source = "registry+https://github.com/rust-lang/crates.io-index"
126 | checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
127 | dependencies = [
128 | "funty",
129 | "radium",
130 | "tap",
131 | "wyz",
132 | ]
133 |
134 | [[package]]
135 | name = "block-buffer"
136 | version = "0.10.4"
137 | source = "registry+https://github.com/rust-lang/crates.io-index"
138 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
139 | dependencies = [
140 | "generic-array",
141 | ]
142 |
143 | [[package]]
144 | name = "bumpalo"
145 | version = "3.17.0"
146 | source = "registry+https://github.com/rust-lang/crates.io-index"
147 | checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
148 | dependencies = [
149 | "allocator-api2",
150 | ]
151 |
152 | [[package]]
153 | name = "bytecheck"
154 | version = "0.8.1"
155 | source = "registry+https://github.com/rust-lang/crates.io-index"
156 | checksum = "50690fb3370fb9fe3550372746084c46f2ac8c9685c583d2be10eefd89d3d1a3"
157 | dependencies = [
158 | "bytecheck_derive",
159 | "ptr_meta",
160 | "rancor",
161 | "simdutf8",
162 | ]
163 |
164 | [[package]]
165 | name = "bytecheck_derive"
166 | version = "0.8.1"
167 | source = "registry+https://github.com/rust-lang/crates.io-index"
168 | checksum = "efb7846e0cb180355c2dec69e721edafa36919850f1a9f52ffba4ebc0393cb71"
169 | dependencies = [
170 | "proc-macro2",
171 | "quote",
172 | "syn",
173 | ]
174 |
175 | [[package]]
176 | name = "bytes"
177 | version = "1.10.0"
178 | source = "registry+https://github.com/rust-lang/crates.io-index"
179 | checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9"
180 |
181 | [[package]]
182 | name = "camino"
183 | version = "1.1.9"
184 | source = "registry+https://github.com/rust-lang/crates.io-index"
185 | checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3"
186 | dependencies = [
187 | "serde",
188 | ]
189 |
190 | [[package]]
191 | name = "cargo-platform"
192 | version = "0.1.9"
193 | source = "registry+https://github.com/rust-lang/crates.io-index"
194 | checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea"
195 | dependencies = [
196 | "serde",
197 | ]
198 |
199 | [[package]]
200 | name = "cargo_metadata"
201 | version = "0.18.1"
202 | source = "registry+https://github.com/rust-lang/crates.io-index"
203 | checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037"
204 | dependencies = [
205 | "camino",
206 | "cargo-platform",
207 | "semver 1.0.26",
208 | "serde",
209 | "serde_json",
210 | "thiserror 1.0.69",
211 | ]
212 |
213 | [[package]]
214 | name = "cargo_metadata"
215 | version = "0.19.2"
216 | source = "registry+https://github.com/rust-lang/crates.io-index"
217 | checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba"
218 | dependencies = [
219 | "camino",
220 | "cargo-platform",
221 | "semver 1.0.26",
222 | "serde",
223 | "serde_json",
224 | "thiserror 2.0.12",
225 | ]
226 |
227 | [[package]]
228 | name = "cast"
229 | version = "0.3.0"
230 | source = "registry+https://github.com/rust-lang/crates.io-index"
231 | checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
232 |
233 | [[package]]
234 | name = "castaway"
235 | version = "0.2.3"
236 | source = "registry+https://github.com/rust-lang/crates.io-index"
237 | checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5"
238 | dependencies = [
239 | "rustversion",
240 | ]
241 |
242 | [[package]]
243 | name = "cc"
244 | version = "1.2.16"
245 | source = "registry+https://github.com/rust-lang/crates.io-index"
246 | checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c"
247 | dependencies = [
248 | "shlex",
249 | ]
250 |
251 | [[package]]
252 | name = "cfg-if"
253 | version = "1.0.0"
254 | source = "registry+https://github.com/rust-lang/crates.io-index"
255 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
256 |
257 | [[package]]
258 | name = "ciborium"
259 | version = "0.2.2"
260 | source = "registry+https://github.com/rust-lang/crates.io-index"
261 | checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
262 | dependencies = [
263 | "ciborium-io",
264 | "ciborium-ll",
265 | "serde",
266 | ]
267 |
268 | [[package]]
269 | name = "ciborium-io"
270 | version = "0.2.2"
271 | source = "registry+https://github.com/rust-lang/crates.io-index"
272 | checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
273 |
274 | [[package]]
275 | name = "ciborium-ll"
276 | version = "0.2.2"
277 | source = "registry+https://github.com/rust-lang/crates.io-index"
278 | checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
279 | dependencies = [
280 | "ciborium-io",
281 | "half",
282 | ]
283 |
284 | [[package]]
285 | name = "clap"
286 | version = "4.5.31"
287 | source = "registry+https://github.com/rust-lang/crates.io-index"
288 | checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767"
289 | dependencies = [
290 | "clap_builder",
291 | ]
292 |
293 | [[package]]
294 | name = "clap_builder"
295 | version = "4.5.31"
296 | source = "registry+https://github.com/rust-lang/crates.io-index"
297 | checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863"
298 | dependencies = [
299 | "anstyle",
300 | "clap_lex",
301 | ]
302 |
303 | [[package]]
304 | name = "clap_lex"
305 | version = "0.7.4"
306 | source = "registry+https://github.com/rust-lang/crates.io-index"
307 | checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
308 |
309 | [[package]]
310 | name = "compact_str"
311 | version = "0.7.1"
312 | source = "registry+https://github.com/rust-lang/crates.io-index"
313 | checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f"
314 | dependencies = [
315 | "castaway",
316 | "cfg-if",
317 | "itoa",
318 | "ryu",
319 | "static_assertions",
320 | ]
321 |
322 | [[package]]
323 | name = "cpufeatures"
324 | version = "0.2.17"
325 | source = "registry+https://github.com/rust-lang/crates.io-index"
326 | checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
327 | dependencies = [
328 | "libc",
329 | ]
330 |
331 | [[package]]
332 | name = "criterion"
333 | version = "0.5.1"
334 | source = "registry+https://github.com/rust-lang/crates.io-index"
335 | checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
336 | dependencies = [
337 | "anes",
338 | "cast",
339 | "ciborium",
340 | "clap",
341 | "criterion-plot",
342 | "is-terminal",
343 | "itertools",
344 | "num-traits",
345 | "once_cell",
346 | "oorandom",
347 | "regex",
348 | "serde",
349 | "serde_derive",
350 | "serde_json",
351 | "tinytemplate",
352 | "walkdir",
353 | ]
354 |
355 | [[package]]
356 | name = "criterion-plot"
357 | version = "0.5.0"
358 | source = "registry+https://github.com/rust-lang/crates.io-index"
359 | checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
360 | dependencies = [
361 | "cast",
362 | "itertools",
363 | ]
364 |
365 | [[package]]
366 | name = "crunchy"
367 | version = "0.2.3"
368 | source = "registry+https://github.com/rust-lang/crates.io-index"
369 | checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
370 |
371 | [[package]]
372 | name = "crypto-common"
373 | version = "0.1.6"
374 | source = "registry+https://github.com/rust-lang/crates.io-index"
375 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
376 | dependencies = [
377 | "generic-array",
378 | "typenum",
379 | ]
380 |
381 | [[package]]
382 | name = "darling"
383 | version = "0.20.10"
384 | source = "registry+https://github.com/rust-lang/crates.io-index"
385 | checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
386 | dependencies = [
387 | "darling_core",
388 | "darling_macro",
389 | ]
390 |
391 | [[package]]
392 | name = "darling_core"
393 | version = "0.20.10"
394 | source = "registry+https://github.com/rust-lang/crates.io-index"
395 | checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
396 | dependencies = [
397 | "fnv",
398 | "ident_case",
399 | "proc-macro2",
400 | "quote",
401 | "strsim",
402 | "syn",
403 | ]
404 |
405 | [[package]]
406 | name = "darling_macro"
407 | version = "0.20.10"
408 | source = "registry+https://github.com/rust-lang/crates.io-index"
409 | checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
410 | dependencies = [
411 | "darling_core",
412 | "quote",
413 | "syn",
414 | ]
415 |
416 | [[package]]
417 | name = "data-encoding"
418 | version = "2.8.0"
419 | source = "registry+https://github.com/rust-lang/crates.io-index"
420 | checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010"
421 |
422 | [[package]]
423 | name = "debugid"
424 | version = "0.8.0"
425 | source = "registry+https://github.com/rust-lang/crates.io-index"
426 | checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d"
427 | dependencies = [
428 | "serde",
429 | "uuid",
430 | ]
431 |
432 | [[package]]
433 | name = "derive_builder"
434 | version = "0.20.2"
435 | source = "registry+https://github.com/rust-lang/crates.io-index"
436 | checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947"
437 | dependencies = [
438 | "derive_builder_macro",
439 | ]
440 |
441 | [[package]]
442 | name = "derive_builder_core"
443 | version = "0.20.2"
444 | source = "registry+https://github.com/rust-lang/crates.io-index"
445 | checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
446 | dependencies = [
447 | "darling",
448 | "proc-macro2",
449 | "quote",
450 | "syn",
451 | ]
452 |
453 | [[package]]
454 | name = "derive_builder_macro"
455 | version = "0.20.2"
456 | source = "registry+https://github.com/rust-lang/crates.io-index"
457 | checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
458 | dependencies = [
459 | "derive_builder_core",
460 | "syn",
461 | ]
462 |
463 | [[package]]
464 | name = "diff"
465 | version = "0.1.13"
466 | source = "registry+https://github.com/rust-lang/crates.io-index"
467 | checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
468 |
469 | [[package]]
470 | name = "difference"
471 | version = "2.0.0"
472 | source = "registry+https://github.com/rust-lang/crates.io-index"
473 | checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
474 |
475 | [[package]]
476 | name = "digest"
477 | version = "0.10.7"
478 | source = "registry+https://github.com/rust-lang/crates.io-index"
479 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
480 | dependencies = [
481 | "block-buffer",
482 | "crypto-common",
483 | ]
484 |
485 | [[package]]
486 | name = "displaydoc"
487 | version = "0.2.5"
488 | source = "registry+https://github.com/rust-lang/crates.io-index"
489 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
490 | dependencies = [
491 | "proc-macro2",
492 | "quote",
493 | "syn",
494 | ]
495 |
496 | [[package]]
497 | name = "either"
498 | version = "1.14.0"
499 | source = "registry+https://github.com/rust-lang/crates.io-index"
500 | checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d"
501 |
502 | [[package]]
503 | name = "equivalent"
504 | version = "1.0.2"
505 | source = "registry+https://github.com/rust-lang/crates.io-index"
506 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
507 |
508 | [[package]]
509 | name = "errno"
510 | version = "0.3.10"
511 | source = "registry+https://github.com/rust-lang/crates.io-index"
512 | checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
513 | dependencies = [
514 | "libc",
515 | "windows-sys",
516 | ]
517 |
518 | [[package]]
519 | name = "fastrand"
520 | version = "2.3.0"
521 | source = "registry+https://github.com/rust-lang/crates.io-index"
522 | checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
523 |
524 | [[package]]
525 | name = "fnv"
526 | version = "1.0.7"
527 | source = "registry+https://github.com/rust-lang/crates.io-index"
528 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
529 |
530 | [[package]]
531 | name = "form_urlencoded"
532 | version = "1.2.1"
533 | source = "registry+https://github.com/rust-lang/crates.io-index"
534 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
535 | dependencies = [
536 | "percent-encoding",
537 | ]
538 |
539 | [[package]]
540 | name = "from_variant"
541 | version = "2.0.0"
542 | source = "registry+https://github.com/rust-lang/crates.io-index"
543 | checksum = "8d7ccf961415e7aa17ef93dcb6c2441faaa8e768abe09e659b908089546f74c5"
544 | dependencies = [
545 | "proc-macro2",
546 | "swc_macros_common",
547 | "syn",
548 | ]
549 |
550 | [[package]]
551 | name = "funty"
552 | version = "2.0.0"
553 | source = "registry+https://github.com/rust-lang/crates.io-index"
554 | checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
555 |
556 | [[package]]
557 | name = "generic-array"
558 | version = "0.14.7"
559 | source = "registry+https://github.com/rust-lang/crates.io-index"
560 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
561 | dependencies = [
562 | "typenum",
563 | "version_check",
564 | ]
565 |
566 | [[package]]
567 | name = "getrandom"
568 | version = "0.3.1"
569 | source = "registry+https://github.com/rust-lang/crates.io-index"
570 | checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
571 | dependencies = [
572 | "cfg-if",
573 | "libc",
574 | "wasi",
575 | "windows-targets",
576 | ]
577 |
578 | [[package]]
579 | name = "glob"
580 | version = "0.3.2"
581 | source = "registry+https://github.com/rust-lang/crates.io-index"
582 | checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
583 |
584 | [[package]]
585 | name = "half"
586 | version = "2.4.1"
587 | source = "registry+https://github.com/rust-lang/crates.io-index"
588 | checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
589 | dependencies = [
590 | "cfg-if",
591 | "crunchy",
592 | ]
593 |
594 | [[package]]
595 | name = "hashbrown"
596 | version = "0.14.5"
597 | source = "registry+https://github.com/rust-lang/crates.io-index"
598 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
599 | dependencies = [
600 | "ahash",
601 | "allocator-api2",
602 | ]
603 |
604 | [[package]]
605 | name = "hashbrown"
606 | version = "0.15.2"
607 | source = "registry+https://github.com/rust-lang/crates.io-index"
608 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
609 |
610 | [[package]]
611 | name = "heck"
612 | version = "0.5.0"
613 | source = "registry+https://github.com/rust-lang/crates.io-index"
614 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
615 |
616 | [[package]]
617 | name = "hermit-abi"
618 | version = "0.3.9"
619 | source = "registry+https://github.com/rust-lang/crates.io-index"
620 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
621 |
622 | [[package]]
623 | name = "hermit-abi"
624 | version = "0.4.0"
625 | source = "registry+https://github.com/rust-lang/crates.io-index"
626 | checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
627 |
628 | [[package]]
629 | name = "hex"
630 | version = "0.4.3"
631 | source = "registry+https://github.com/rust-lang/crates.io-index"
632 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
633 |
634 | [[package]]
635 | name = "hstr"
636 | version = "1.0.0"
637 | source = "registry+https://github.com/rust-lang/crates.io-index"
638 | checksum = "71399f53a92ef72ee336a4b30201c6e944827e14e0af23204c291aad9c24cc85"
639 | dependencies = [
640 | "hashbrown 0.14.5",
641 | "new_debug_unreachable",
642 | "once_cell",
643 | "phf",
644 | "rustc-hash 2.1.1",
645 | "triomphe",
646 | ]
647 |
648 | [[package]]
649 | name = "icu_collections"
650 | version = "1.5.0"
651 | source = "registry+https://github.com/rust-lang/crates.io-index"
652 | checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
653 | dependencies = [
654 | "displaydoc",
655 | "yoke",
656 | "zerofrom",
657 | "zerovec",
658 | ]
659 |
660 | [[package]]
661 | name = "icu_locid"
662 | version = "1.5.0"
663 | source = "registry+https://github.com/rust-lang/crates.io-index"
664 | checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
665 | dependencies = [
666 | "displaydoc",
667 | "litemap",
668 | "tinystr",
669 | "writeable",
670 | "zerovec",
671 | ]
672 |
673 | [[package]]
674 | name = "icu_locid_transform"
675 | version = "1.5.0"
676 | source = "registry+https://github.com/rust-lang/crates.io-index"
677 | checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
678 | dependencies = [
679 | "displaydoc",
680 | "icu_locid",
681 | "icu_locid_transform_data",
682 | "icu_provider",
683 | "tinystr",
684 | "zerovec",
685 | ]
686 |
687 | [[package]]
688 | name = "icu_locid_transform_data"
689 | version = "1.5.0"
690 | source = "registry+https://github.com/rust-lang/crates.io-index"
691 | checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
692 |
693 | [[package]]
694 | name = "icu_normalizer"
695 | version = "1.5.0"
696 | source = "registry+https://github.com/rust-lang/crates.io-index"
697 | checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
698 | dependencies = [
699 | "displaydoc",
700 | "icu_collections",
701 | "icu_normalizer_data",
702 | "icu_properties",
703 | "icu_provider",
704 | "smallvec",
705 | "utf16_iter",
706 | "utf8_iter",
707 | "write16",
708 | "zerovec",
709 | ]
710 |
711 | [[package]]
712 | name = "icu_normalizer_data"
713 | version = "1.5.0"
714 | source = "registry+https://github.com/rust-lang/crates.io-index"
715 | checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
716 |
717 | [[package]]
718 | name = "icu_properties"
719 | version = "1.5.1"
720 | source = "registry+https://github.com/rust-lang/crates.io-index"
721 | checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
722 | dependencies = [
723 | "displaydoc",
724 | "icu_collections",
725 | "icu_locid_transform",
726 | "icu_properties_data",
727 | "icu_provider",
728 | "tinystr",
729 | "zerovec",
730 | ]
731 |
732 | [[package]]
733 | name = "icu_properties_data"
734 | version = "1.5.0"
735 | source = "registry+https://github.com/rust-lang/crates.io-index"
736 | checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
737 |
738 | [[package]]
739 | name = "icu_provider"
740 | version = "1.5.0"
741 | source = "registry+https://github.com/rust-lang/crates.io-index"
742 | checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
743 | dependencies = [
744 | "displaydoc",
745 | "icu_locid",
746 | "icu_provider_macros",
747 | "stable_deref_trait",
748 | "tinystr",
749 | "writeable",
750 | "yoke",
751 | "zerofrom",
752 | "zerovec",
753 | ]
754 |
755 | [[package]]
756 | name = "icu_provider_macros"
757 | version = "1.5.0"
758 | source = "registry+https://github.com/rust-lang/crates.io-index"
759 | checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
760 | dependencies = [
761 | "proc-macro2",
762 | "quote",
763 | "syn",
764 | ]
765 |
766 | [[package]]
767 | name = "ident_case"
768 | version = "1.0.1"
769 | source = "registry+https://github.com/rust-lang/crates.io-index"
770 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
771 |
772 | [[package]]
773 | name = "idna"
774 | version = "1.0.3"
775 | source = "registry+https://github.com/rust-lang/crates.io-index"
776 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
777 | dependencies = [
778 | "idna_adapter",
779 | "smallvec",
780 | "utf8_iter",
781 | ]
782 |
783 | [[package]]
784 | name = "idna_adapter"
785 | version = "1.2.0"
786 | source = "registry+https://github.com/rust-lang/crates.io-index"
787 | checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
788 | dependencies = [
789 | "icu_normalizer",
790 | "icu_properties",
791 | ]
792 |
793 | [[package]]
794 | name = "if_chain"
795 | version = "1.0.2"
796 | source = "registry+https://github.com/rust-lang/crates.io-index"
797 | checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
798 |
799 | [[package]]
800 | name = "indexmap"
801 | version = "2.7.1"
802 | source = "registry+https://github.com/rust-lang/crates.io-index"
803 | checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
804 | dependencies = [
805 | "equivalent",
806 | "hashbrown 0.15.2",
807 | ]
808 |
809 | [[package]]
810 | name = "is-macro"
811 | version = "0.3.7"
812 | source = "registry+https://github.com/rust-lang/crates.io-index"
813 | checksum = "1d57a3e447e24c22647738e4607f1df1e0ec6f72e16182c4cd199f647cdfb0e4"
814 | dependencies = [
815 | "heck",
816 | "proc-macro2",
817 | "quote",
818 | "syn",
819 | ]
820 |
821 | [[package]]
822 | name = "is-terminal"
823 | version = "0.4.15"
824 | source = "registry+https://github.com/rust-lang/crates.io-index"
825 | checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37"
826 | dependencies = [
827 | "hermit-abi 0.4.0",
828 | "libc",
829 | "windows-sys",
830 | ]
831 |
832 | [[package]]
833 | name = "itertools"
834 | version = "0.10.5"
835 | source = "registry+https://github.com/rust-lang/crates.io-index"
836 | checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
837 | dependencies = [
838 | "either",
839 | ]
840 |
841 | [[package]]
842 | name = "itoa"
843 | version = "1.0.15"
844 | source = "registry+https://github.com/rust-lang/crates.io-index"
845 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
846 |
847 | [[package]]
848 | name = "lazy_static"
849 | version = "1.5.0"
850 | source = "registry+https://github.com/rust-lang/crates.io-index"
851 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
852 |
853 | [[package]]
854 | name = "libc"
855 | version = "0.2.170"
856 | source = "registry+https://github.com/rust-lang/crates.io-index"
857 | checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
858 |
859 | [[package]]
860 | name = "linux-raw-sys"
861 | version = "0.4.15"
862 | source = "registry+https://github.com/rust-lang/crates.io-index"
863 | checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
864 |
865 | [[package]]
866 | name = "litemap"
867 | version = "0.7.5"
868 | source = "registry+https://github.com/rust-lang/crates.io-index"
869 | checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
870 |
871 | [[package]]
872 | name = "lock_api"
873 | version = "0.4.12"
874 | source = "registry+https://github.com/rust-lang/crates.io-index"
875 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
876 | dependencies = [
877 | "autocfg",
878 | "scopeguard",
879 | ]
880 |
881 | [[package]]
882 | name = "log"
883 | version = "0.4.26"
884 | source = "registry+https://github.com/rust-lang/crates.io-index"
885 | checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
886 |
887 | [[package]]
888 | name = "matchers"
889 | version = "0.1.0"
890 | source = "registry+https://github.com/rust-lang/crates.io-index"
891 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
892 | dependencies = [
893 | "regex-automata 0.1.10",
894 | ]
895 |
896 | [[package]]
897 | name = "memchr"
898 | version = "2.7.4"
899 | source = "registry+https://github.com/rust-lang/crates.io-index"
900 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
901 |
902 | [[package]]
903 | name = "miette"
904 | version = "7.5.0"
905 | source = "registry+https://github.com/rust-lang/crates.io-index"
906 | checksum = "1a955165f87b37fd1862df2a59547ac542c77ef6d17c666f619d1ad22dd89484"
907 | dependencies = [
908 | "cfg-if",
909 | "miette-derive",
910 | "owo-colors",
911 | "textwrap",
912 | "thiserror 1.0.69",
913 | "unicode-width 0.1.14",
914 | ]
915 |
916 | [[package]]
917 | name = "miette-derive"
918 | version = "7.5.0"
919 | source = "registry+https://github.com/rust-lang/crates.io-index"
920 | checksum = "bf45bf44ab49be92fd1227a3be6fc6f617f1a337c06af54981048574d8783147"
921 | dependencies = [
922 | "proc-macro2",
923 | "quote",
924 | "syn",
925 | ]
926 |
927 | [[package]]
928 | name = "munge"
929 | version = "0.4.3"
930 | source = "registry+https://github.com/rust-lang/crates.io-index"
931 | checksum = "a0091202c98cf06da46c279fdf50cccb6b1c43b4521abdf6a27b4c7e71d5d9d7"
932 | dependencies = [
933 | "munge_macro",
934 | ]
935 |
936 | [[package]]
937 | name = "munge_macro"
938 | version = "0.4.3"
939 | source = "registry+https://github.com/rust-lang/crates.io-index"
940 | checksum = "734799cf91479720b2f970c61a22850940dd91e27d4f02b1c6fc792778df2459"
941 | dependencies = [
942 | "proc-macro2",
943 | "quote",
944 | "syn",
945 | ]
946 |
947 | [[package]]
948 | name = "new_debug_unreachable"
949 | version = "1.0.6"
950 | source = "registry+https://github.com/rust-lang/crates.io-index"
951 | checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
952 |
953 | [[package]]
954 | name = "nu-ansi-term"
955 | version = "0.46.0"
956 | source = "registry+https://github.com/rust-lang/crates.io-index"
957 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
958 | dependencies = [
959 | "overload",
960 | "winapi",
961 | ]
962 |
963 | [[package]]
964 | name = "num-bigint"
965 | version = "0.4.6"
966 | source = "registry+https://github.com/rust-lang/crates.io-index"
967 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
968 | dependencies = [
969 | "num-integer",
970 | "num-traits",
971 | "serde",
972 | ]
973 |
974 | [[package]]
975 | name = "num-integer"
976 | version = "0.1.46"
977 | source = "registry+https://github.com/rust-lang/crates.io-index"
978 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
979 | dependencies = [
980 | "num-traits",
981 | ]
982 |
983 | [[package]]
984 | name = "num-traits"
985 | version = "0.2.19"
986 | source = "registry+https://github.com/rust-lang/crates.io-index"
987 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
988 | dependencies = [
989 | "autocfg",
990 | ]
991 |
992 | [[package]]
993 | name = "num_cpus"
994 | version = "1.16.0"
995 | source = "registry+https://github.com/rust-lang/crates.io-index"
996 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
997 | dependencies = [
998 | "hermit-abi 0.3.9",
999 | "libc",
1000 | ]
1001 |
1002 | [[package]]
1003 | name = "once_cell"
1004 | version = "1.20.3"
1005 | source = "registry+https://github.com/rust-lang/crates.io-index"
1006 | checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
1007 |
1008 | [[package]]
1009 | name = "oorandom"
1010 | version = "11.1.4"
1011 | source = "registry+https://github.com/rust-lang/crates.io-index"
1012 | checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
1013 |
1014 | [[package]]
1015 | name = "outref"
1016 | version = "0.1.0"
1017 | source = "registry+https://github.com/rust-lang/crates.io-index"
1018 | checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4"
1019 |
1020 | [[package]]
1021 | name = "overload"
1022 | version = "0.1.1"
1023 | source = "registry+https://github.com/rust-lang/crates.io-index"
1024 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
1025 |
1026 | [[package]]
1027 | name = "owo-colors"
1028 | version = "4.2.0"
1029 | source = "registry+https://github.com/rust-lang/crates.io-index"
1030 | checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564"
1031 |
1032 | [[package]]
1033 | name = "parking_lot"
1034 | version = "0.12.3"
1035 | source = "registry+https://github.com/rust-lang/crates.io-index"
1036 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
1037 | dependencies = [
1038 | "lock_api",
1039 | "parking_lot_core",
1040 | ]
1041 |
1042 | [[package]]
1043 | name = "parking_lot_core"
1044 | version = "0.9.10"
1045 | source = "registry+https://github.com/rust-lang/crates.io-index"
1046 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
1047 | dependencies = [
1048 | "cfg-if",
1049 | "libc",
1050 | "redox_syscall",
1051 | "smallvec",
1052 | "windows-targets",
1053 | ]
1054 |
1055 | [[package]]
1056 | name = "pathdiff"
1057 | version = "0.2.3"
1058 | source = "registry+https://github.com/rust-lang/crates.io-index"
1059 | checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
1060 |
1061 | [[package]]
1062 | name = "percent-encoding"
1063 | version = "2.3.1"
1064 | source = "registry+https://github.com/rust-lang/crates.io-index"
1065 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
1066 |
1067 | [[package]]
1068 | name = "phf"
1069 | version = "0.11.3"
1070 | source = "registry+https://github.com/rust-lang/crates.io-index"
1071 | checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
1072 | dependencies = [
1073 | "phf_macros",
1074 | "phf_shared",
1075 | ]
1076 |
1077 | [[package]]
1078 | name = "phf_generator"
1079 | version = "0.11.3"
1080 | source = "registry+https://github.com/rust-lang/crates.io-index"
1081 | checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
1082 | dependencies = [
1083 | "phf_shared",
1084 | "rand",
1085 | ]
1086 |
1087 | [[package]]
1088 | name = "phf_macros"
1089 | version = "0.11.3"
1090 | source = "registry+https://github.com/rust-lang/crates.io-index"
1091 | checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
1092 | dependencies = [
1093 | "phf_generator",
1094 | "phf_shared",
1095 | "proc-macro2",
1096 | "quote",
1097 | "syn",
1098 | ]
1099 |
1100 | [[package]]
1101 | name = "phf_shared"
1102 | version = "0.11.3"
1103 | source = "registry+https://github.com/rust-lang/crates.io-index"
1104 | checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
1105 | dependencies = [
1106 | "siphasher 1.0.1",
1107 | ]
1108 |
1109 | [[package]]
1110 | name = "pin-project-lite"
1111 | version = "0.2.16"
1112 | source = "registry+https://github.com/rust-lang/crates.io-index"
1113 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
1114 |
1115 | [[package]]
1116 | name = "pretty_assertions"
1117 | version = "1.4.1"
1118 | source = "registry+https://github.com/rust-lang/crates.io-index"
1119 | checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
1120 | dependencies = [
1121 | "diff",
1122 | "yansi",
1123 | ]
1124 |
1125 | [[package]]
1126 | name = "proc-macro2"
1127 | version = "1.0.94"
1128 | source = "registry+https://github.com/rust-lang/crates.io-index"
1129 | checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
1130 | dependencies = [
1131 | "unicode-ident",
1132 | ]
1133 |
1134 | [[package]]
1135 | name = "psm"
1136 | version = "0.1.25"
1137 | source = "registry+https://github.com/rust-lang/crates.io-index"
1138 | checksum = "f58e5423e24c18cc840e1c98370b3993c6649cd1678b4d24318bcf0a083cbe88"
1139 | dependencies = [
1140 | "cc",
1141 | ]
1142 |
1143 | [[package]]
1144 | name = "ptr_meta"
1145 | version = "0.3.0"
1146 | source = "registry+https://github.com/rust-lang/crates.io-index"
1147 | checksum = "fe9e76f66d3f9606f44e45598d155cb13ecf09f4a28199e48daf8c8fc937ea90"
1148 | dependencies = [
1149 | "ptr_meta_derive",
1150 | ]
1151 |
1152 | [[package]]
1153 | name = "ptr_meta_derive"
1154 | version = "0.3.0"
1155 | source = "registry+https://github.com/rust-lang/crates.io-index"
1156 | checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1"
1157 | dependencies = [
1158 | "proc-macro2",
1159 | "quote",
1160 | "syn",
1161 | ]
1162 |
1163 | [[package]]
1164 | name = "quote"
1165 | version = "1.0.39"
1166 | source = "registry+https://github.com/rust-lang/crates.io-index"
1167 | checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801"
1168 | dependencies = [
1169 | "proc-macro2",
1170 | ]
1171 |
1172 | [[package]]
1173 | name = "radium"
1174 | version = "0.7.0"
1175 | source = "registry+https://github.com/rust-lang/crates.io-index"
1176 | checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
1177 |
1178 | [[package]]
1179 | name = "rancor"
1180 | version = "0.1.0"
1181 | source = "registry+https://github.com/rust-lang/crates.io-index"
1182 | checksum = "caf5f7161924b9d1cea0e4cabc97c372cea92b5f927fc13c6bca67157a0ad947"
1183 | dependencies = [
1184 | "ptr_meta",
1185 | ]
1186 |
1187 | [[package]]
1188 | name = "rand"
1189 | version = "0.8.5"
1190 | source = "registry+https://github.com/rust-lang/crates.io-index"
1191 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
1192 | dependencies = [
1193 | "rand_core",
1194 | ]
1195 |
1196 | [[package]]
1197 | name = "rand_core"
1198 | version = "0.6.4"
1199 | source = "registry+https://github.com/rust-lang/crates.io-index"
1200 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
1201 |
1202 | [[package]]
1203 | name = "redox_syscall"
1204 | version = "0.5.10"
1205 | source = "registry+https://github.com/rust-lang/crates.io-index"
1206 | checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1"
1207 | dependencies = [
1208 | "bitflags",
1209 | ]
1210 |
1211 | [[package]]
1212 | name = "regex"
1213 | version = "1.11.1"
1214 | source = "registry+https://github.com/rust-lang/crates.io-index"
1215 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
1216 | dependencies = [
1217 | "aho-corasick",
1218 | "memchr",
1219 | "regex-automata 0.4.9",
1220 | "regex-syntax 0.8.5",
1221 | ]
1222 |
1223 | [[package]]
1224 | name = "regex-automata"
1225 | version = "0.1.10"
1226 | source = "registry+https://github.com/rust-lang/crates.io-index"
1227 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
1228 | dependencies = [
1229 | "regex-syntax 0.6.29",
1230 | ]
1231 |
1232 | [[package]]
1233 | name = "regex-automata"
1234 | version = "0.4.9"
1235 | source = "registry+https://github.com/rust-lang/crates.io-index"
1236 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
1237 | dependencies = [
1238 | "aho-corasick",
1239 | "memchr",
1240 | "regex-syntax 0.8.5",
1241 | ]
1242 |
1243 | [[package]]
1244 | name = "regex-syntax"
1245 | version = "0.6.29"
1246 | source = "registry+https://github.com/rust-lang/crates.io-index"
1247 | checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
1248 |
1249 | [[package]]
1250 | name = "regex-syntax"
1251 | version = "0.8.5"
1252 | source = "registry+https://github.com/rust-lang/crates.io-index"
1253 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
1254 |
1255 | [[package]]
1256 | name = "relative-path"
1257 | version = "1.9.3"
1258 | source = "registry+https://github.com/rust-lang/crates.io-index"
1259 | checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2"
1260 |
1261 | [[package]]
1262 | name = "rend"
1263 | version = "0.5.2"
1264 | source = "registry+https://github.com/rust-lang/crates.io-index"
1265 | checksum = "a35e8a6bf28cd121053a66aa2e6a2e3eaffad4a60012179f0e864aa5ffeff215"
1266 | dependencies = [
1267 | "bytecheck",
1268 | ]
1269 |
1270 | [[package]]
1271 | name = "rkyv"
1272 | version = "0.8.10"
1273 | source = "registry+https://github.com/rust-lang/crates.io-index"
1274 | checksum = "1e147371c75553e1e2fcdb483944a8540b8438c31426279553b9a8182a9b7b65"
1275 | dependencies = [
1276 | "bytecheck",
1277 | "bytes",
1278 | "hashbrown 0.15.2",
1279 | "indexmap",
1280 | "munge",
1281 | "ptr_meta",
1282 | "rancor",
1283 | "rend",
1284 | "rkyv_derive",
1285 | "tinyvec",
1286 | "uuid",
1287 | ]
1288 |
1289 | [[package]]
1290 | name = "rkyv_derive"
1291 | version = "0.8.10"
1292 | source = "registry+https://github.com/rust-lang/crates.io-index"
1293 | checksum = "246b40ac189af6c675d124b802e8ef6d5246c53e17367ce9501f8f66a81abb7a"
1294 | dependencies = [
1295 | "proc-macro2",
1296 | "quote",
1297 | "syn",
1298 | ]
1299 |
1300 | [[package]]
1301 | name = "rustc-hash"
1302 | version = "1.1.0"
1303 | source = "registry+https://github.com/rust-lang/crates.io-index"
1304 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
1305 |
1306 | [[package]]
1307 | name = "rustc-hash"
1308 | version = "2.1.1"
1309 | source = "registry+https://github.com/rust-lang/crates.io-index"
1310 | checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
1311 |
1312 | [[package]]
1313 | name = "rustc_version"
1314 | version = "0.2.3"
1315 | source = "registry+https://github.com/rust-lang/crates.io-index"
1316 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
1317 | dependencies = [
1318 | "semver 0.9.0",
1319 | ]
1320 |
1321 | [[package]]
1322 | name = "rustix"
1323 | version = "0.38.44"
1324 | source = "registry+https://github.com/rust-lang/crates.io-index"
1325 | checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
1326 | dependencies = [
1327 | "bitflags",
1328 | "errno",
1329 | "libc",
1330 | "linux-raw-sys",
1331 | "windows-sys",
1332 | ]
1333 |
1334 | [[package]]
1335 | name = "rustversion"
1336 | version = "1.0.20"
1337 | source = "registry+https://github.com/rust-lang/crates.io-index"
1338 | checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
1339 |
1340 | [[package]]
1341 | name = "ryu"
1342 | version = "1.0.20"
1343 | source = "registry+https://github.com/rust-lang/crates.io-index"
1344 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
1345 |
1346 | [[package]]
1347 | name = "ryu-js"
1348 | version = "1.0.2"
1349 | source = "registry+https://github.com/rust-lang/crates.io-index"
1350 | checksum = "dd29631678d6fb0903b69223673e122c32e9ae559d0960a38d574695ebc0ea15"
1351 |
1352 | [[package]]
1353 | name = "same-file"
1354 | version = "1.0.6"
1355 | source = "registry+https://github.com/rust-lang/crates.io-index"
1356 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
1357 | dependencies = [
1358 | "winapi-util",
1359 | ]
1360 |
1361 | [[package]]
1362 | name = "scoped-tls"
1363 | version = "1.0.1"
1364 | source = "registry+https://github.com/rust-lang/crates.io-index"
1365 | checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
1366 |
1367 | [[package]]
1368 | name = "scopeguard"
1369 | version = "1.2.0"
1370 | source = "registry+https://github.com/rust-lang/crates.io-index"
1371 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
1372 |
1373 | [[package]]
1374 | name = "semver"
1375 | version = "0.9.0"
1376 | source = "registry+https://github.com/rust-lang/crates.io-index"
1377 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
1378 | dependencies = [
1379 | "semver-parser",
1380 | ]
1381 |
1382 | [[package]]
1383 | name = "semver"
1384 | version = "1.0.26"
1385 | source = "registry+https://github.com/rust-lang/crates.io-index"
1386 | checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
1387 | dependencies = [
1388 | "serde",
1389 | ]
1390 |
1391 | [[package]]
1392 | name = "semver-parser"
1393 | version = "0.7.0"
1394 | source = "registry+https://github.com/rust-lang/crates.io-index"
1395 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
1396 |
1397 | [[package]]
1398 | name = "serde"
1399 | version = "1.0.218"
1400 | source = "registry+https://github.com/rust-lang/crates.io-index"
1401 | checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
1402 | dependencies = [
1403 | "serde_derive",
1404 | ]
1405 |
1406 | [[package]]
1407 | name = "serde_derive"
1408 | version = "1.0.218"
1409 | source = "registry+https://github.com/rust-lang/crates.io-index"
1410 | checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
1411 | dependencies = [
1412 | "proc-macro2",
1413 | "quote",
1414 | "syn",
1415 | ]
1416 |
1417 | [[package]]
1418 | name = "serde_json"
1419 | version = "1.0.140"
1420 | source = "registry+https://github.com/rust-lang/crates.io-index"
1421 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
1422 | dependencies = [
1423 | "itoa",
1424 | "memchr",
1425 | "ryu",
1426 | "serde",
1427 | ]
1428 |
1429 | [[package]]
1430 | name = "sha2"
1431 | version = "0.10.8"
1432 | source = "registry+https://github.com/rust-lang/crates.io-index"
1433 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
1434 | dependencies = [
1435 | "cfg-if",
1436 | "cpufeatures",
1437 | "digest",
1438 | ]
1439 |
1440 | [[package]]
1441 | name = "sharded-slab"
1442 | version = "0.1.7"
1443 | source = "registry+https://github.com/rust-lang/crates.io-index"
1444 | checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
1445 | dependencies = [
1446 | "lazy_static",
1447 | ]
1448 |
1449 | [[package]]
1450 | name = "shlex"
1451 | version = "1.3.0"
1452 | source = "registry+https://github.com/rust-lang/crates.io-index"
1453 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
1454 |
1455 | [[package]]
1456 | name = "simd-abstraction"
1457 | version = "0.7.1"
1458 | source = "registry+https://github.com/rust-lang/crates.io-index"
1459 | checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987"
1460 | dependencies = [
1461 | "outref",
1462 | ]
1463 |
1464 | [[package]]
1465 | name = "simdutf8"
1466 | version = "0.1.5"
1467 | source = "registry+https://github.com/rust-lang/crates.io-index"
1468 | checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
1469 |
1470 | [[package]]
1471 | name = "siphasher"
1472 | version = "0.3.11"
1473 | source = "registry+https://github.com/rust-lang/crates.io-index"
1474 | checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
1475 |
1476 | [[package]]
1477 | name = "siphasher"
1478 | version = "1.0.1"
1479 | source = "registry+https://github.com/rust-lang/crates.io-index"
1480 | checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
1481 |
1482 | [[package]]
1483 | name = "smallvec"
1484 | version = "1.14.0"
1485 | source = "registry+https://github.com/rust-lang/crates.io-index"
1486 | checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
1487 |
1488 | [[package]]
1489 | name = "smartstring"
1490 | version = "1.0.1"
1491 | source = "registry+https://github.com/rust-lang/crates.io-index"
1492 | checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
1493 | dependencies = [
1494 | "autocfg",
1495 | "static_assertions",
1496 | "version_check",
1497 | ]
1498 |
1499 | [[package]]
1500 | name = "sourcemap"
1501 | version = "9.1.2"
1502 | source = "registry+https://github.com/rust-lang/crates.io-index"
1503 | checksum = "27c4ea7042fd1a155ad95335b5d505ab00d5124ea0332a06c8390d200bb1a76a"
1504 | dependencies = [
1505 | "base64-simd",
1506 | "bitvec",
1507 | "data-encoding",
1508 | "debugid",
1509 | "if_chain",
1510 | "rustc-hash 1.1.0",
1511 | "rustc_version",
1512 | "serde",
1513 | "serde_json",
1514 | "unicode-id-start",
1515 | "url",
1516 | ]
1517 |
1518 | [[package]]
1519 | name = "stable_deref_trait"
1520 | version = "1.2.0"
1521 | source = "registry+https://github.com/rust-lang/crates.io-index"
1522 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
1523 |
1524 | [[package]]
1525 | name = "stacker"
1526 | version = "0.1.19"
1527 | source = "registry+https://github.com/rust-lang/crates.io-index"
1528 | checksum = "d9156ebd5870ef293bfb43f91c7a74528d363ec0d424afe24160ed5a4343d08a"
1529 | dependencies = [
1530 | "cc",
1531 | "cfg-if",
1532 | "libc",
1533 | "psm",
1534 | "windows-sys",
1535 | ]
1536 |
1537 | [[package]]
1538 | name = "static_assertions"
1539 | version = "1.1.0"
1540 | source = "registry+https://github.com/rust-lang/crates.io-index"
1541 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
1542 |
1543 | [[package]]
1544 | name = "string_enum"
1545 | version = "1.0.0"
1546 | source = "registry+https://github.com/rust-lang/crates.io-index"
1547 | checksum = "c9fe66b8ee349846ce2f9557a26b8f1e74843c4a13fb381f9a3d73617a5f956a"
1548 | dependencies = [
1549 | "proc-macro2",
1550 | "quote",
1551 | "swc_macros_common",
1552 | "syn",
1553 | ]
1554 |
1555 | [[package]]
1556 | name = "strsim"
1557 | version = "0.11.1"
1558 | source = "registry+https://github.com/rust-lang/crates.io-index"
1559 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
1560 |
1561 | [[package]]
1562 | name = "swc-plugin-css-variable"
1563 | version = "0.1.0"
1564 | dependencies = [
1565 | "lazy_static",
1566 | "pathdiff",
1567 | "regex",
1568 | "serde_json",
1569 | "swc_core",
1570 | "transform",
1571 | ]
1572 |
1573 | [[package]]
1574 | name = "swc_allocator"
1575 | version = "4.0.0"
1576 | source = "registry+https://github.com/rust-lang/crates.io-index"
1577 | checksum = "cc6b926f0d94bbb34031fe5449428cfa1268cdc0b31158d6ad9c97e0fc1e79dd"
1578 | dependencies = [
1579 | "allocator-api2",
1580 | "bumpalo",
1581 | "hashbrown 0.14.5",
1582 | "ptr_meta",
1583 | "rustc-hash 2.1.1",
1584 | "triomphe",
1585 | ]
1586 |
1587 | [[package]]
1588 | name = "swc_atoms"
1589 | version = "5.0.0"
1590 | source = "registry+https://github.com/rust-lang/crates.io-index"
1591 | checksum = "9d7077ba879f95406459bc0c81f3141c529b34580bc64d7ab7bd15e7118a0391"
1592 | dependencies = [
1593 | "bytecheck",
1594 | "hstr",
1595 | "once_cell",
1596 | "rancor",
1597 | "rkyv",
1598 | "rustc-hash 2.1.1",
1599 | "serde",
1600 | ]
1601 |
1602 | [[package]]
1603 | name = "swc_common"
1604 | version = "8.0.0"
1605 | source = "registry+https://github.com/rust-lang/crates.io-index"
1606 | checksum = "26fbd21a1179166b5635d4b7a6b5930cf34b803a7361e0297b04f84dc820db04"
1607 | dependencies = [
1608 | "anyhow",
1609 | "ast_node",
1610 | "better_scoped_tls",
1611 | "bytecheck",
1612 | "cfg-if",
1613 | "either",
1614 | "from_variant",
1615 | "new_debug_unreachable",
1616 | "num-bigint",
1617 | "once_cell",
1618 | "parking_lot",
1619 | "rancor",
1620 | "rkyv",
1621 | "rustc-hash 2.1.1",
1622 | "serde",
1623 | "siphasher 0.3.11",
1624 | "sourcemap",
1625 | "swc_allocator",
1626 | "swc_atoms",
1627 | "swc_eq_ignore_macros",
1628 | "swc_visit",
1629 | "termcolor",
1630 | "tracing",
1631 | "unicode-width 0.1.14",
1632 | "url",
1633 | ]
1634 |
1635 | [[package]]
1636 | name = "swc_core"
1637 | version = "16.3.1"
1638 | source = "registry+https://github.com/rust-lang/crates.io-index"
1639 | checksum = "f653564e81bd21b1fe89c433e83cc9bdefc84992ad4df0654af3c345b4fdb71e"
1640 | dependencies = [
1641 | "once_cell",
1642 | "swc_allocator",
1643 | "swc_atoms",
1644 | "swc_common",
1645 | "swc_ecma_ast",
1646 | "swc_ecma_parser",
1647 | "swc_ecma_transforms_base",
1648 | "swc_ecma_transforms_testing",
1649 | "swc_ecma_visit",
1650 | "swc_plugin",
1651 | "swc_plugin_macro",
1652 | "swc_plugin_proxy",
1653 | "vergen",
1654 | ]
1655 |
1656 | [[package]]
1657 | name = "swc_ecma_ast"
1658 | version = "8.0.0"
1659 | source = "registry+https://github.com/rust-lang/crates.io-index"
1660 | checksum = "c66db1e9b31f0f91ee0964aba014b4d2dfdc6c558732d106d762b43bedad2c4a"
1661 | dependencies = [
1662 | "bitflags",
1663 | "bytecheck",
1664 | "is-macro",
1665 | "num-bigint",
1666 | "phf",
1667 | "rancor",
1668 | "rkyv",
1669 | "scoped-tls",
1670 | "string_enum",
1671 | "swc_atoms",
1672 | "swc_common",
1673 | "swc_visit",
1674 | "unicode-id-start",
1675 | ]
1676 |
1677 | [[package]]
1678 | name = "swc_ecma_codegen"
1679 | version = "8.0.2"
1680 | source = "registry+https://github.com/rust-lang/crates.io-index"
1681 | checksum = "92103aa982740f265d6850bb3ffffbf6c3c1dee30ab0ed25117ca553f0d7467d"
1682 | dependencies = [
1683 | "ascii",
1684 | "compact_str",
1685 | "memchr",
1686 | "num-bigint",
1687 | "once_cell",
1688 | "regex",
1689 | "rustc-hash 2.1.1",
1690 | "serde",
1691 | "sourcemap",
1692 | "swc_allocator",
1693 | "swc_atoms",
1694 | "swc_common",
1695 | "swc_ecma_ast",
1696 | "swc_ecma_codegen_macros",
1697 | "tracing",
1698 | ]
1699 |
1700 | [[package]]
1701 | name = "swc_ecma_codegen_macros"
1702 | version = "1.0.1"
1703 | source = "registry+https://github.com/rust-lang/crates.io-index"
1704 | checksum = "4ac2ff0957329e0dfcde86a1ac465382e189bf42a5989720d3476bea78eaa31a"
1705 | dependencies = [
1706 | "proc-macro2",
1707 | "quote",
1708 | "swc_macros_common",
1709 | "syn",
1710 | ]
1711 |
1712 | [[package]]
1713 | name = "swc_ecma_parser"
1714 | version = "10.0.0"
1715 | source = "registry+https://github.com/rust-lang/crates.io-index"
1716 | checksum = "f9e336f2b460882df2c132328b3c29ab3e680e1db681a05ec3e406940d98320a"
1717 | dependencies = [
1718 | "either",
1719 | "new_debug_unreachable",
1720 | "num-bigint",
1721 | "num-traits",
1722 | "phf",
1723 | "rustc-hash 2.1.1",
1724 | "serde",
1725 | "smallvec",
1726 | "smartstring",
1727 | "stacker",
1728 | "swc_atoms",
1729 | "swc_common",
1730 | "swc_ecma_ast",
1731 | "tracing",
1732 | "typed-arena",
1733 | ]
1734 |
1735 | [[package]]
1736 | name = "swc_ecma_testing"
1737 | version = "8.0.0"
1738 | source = "registry+https://github.com/rust-lang/crates.io-index"
1739 | checksum = "5e72a43b7acd904fa0c6d244a72aeda66febbc5a9720975481cb836d6804b604"
1740 | dependencies = [
1741 | "anyhow",
1742 | "hex",
1743 | "sha2",
1744 | "testing",
1745 | "tracing",
1746 | ]
1747 |
1748 | [[package]]
1749 | name = "swc_ecma_transforms_base"
1750 | version = "11.2.0"
1751 | source = "registry+https://github.com/rust-lang/crates.io-index"
1752 | checksum = "39889063ff4819eae414dfe6426aa5cd72ebb0f9f48739a1fa1e7eb82d0adc78"
1753 | dependencies = [
1754 | "better_scoped_tls",
1755 | "bitflags",
1756 | "indexmap",
1757 | "once_cell",
1758 | "phf",
1759 | "rustc-hash 2.1.1",
1760 | "serde",
1761 | "smallvec",
1762 | "swc_atoms",
1763 | "swc_common",
1764 | "swc_ecma_ast",
1765 | "swc_ecma_parser",
1766 | "swc_ecma_utils",
1767 | "swc_ecma_visit",
1768 | "swc_parallel",
1769 | "tracing",
1770 | ]
1771 |
1772 | [[package]]
1773 | name = "swc_ecma_transforms_testing"
1774 | version = "11.0.1"
1775 | source = "registry+https://github.com/rust-lang/crates.io-index"
1776 | checksum = "13c4d8c48a36ad5d02626f853edcf52ae82b65d238389e7e76270ddf564b69ab"
1777 | dependencies = [
1778 | "ansi_term",
1779 | "anyhow",
1780 | "base64",
1781 | "hex",
1782 | "serde",
1783 | "serde_json",
1784 | "sha2",
1785 | "sourcemap",
1786 | "swc_allocator",
1787 | "swc_common",
1788 | "swc_ecma_ast",
1789 | "swc_ecma_codegen",
1790 | "swc_ecma_parser",
1791 | "swc_ecma_testing",
1792 | "swc_ecma_transforms_base",
1793 | "swc_ecma_utils",
1794 | "swc_ecma_visit",
1795 | "tempfile",
1796 | "testing",
1797 | ]
1798 |
1799 | [[package]]
1800 | name = "swc_ecma_utils"
1801 | version = "11.0.0"
1802 | source = "registry+https://github.com/rust-lang/crates.io-index"
1803 | checksum = "721dc779e7de200da96ac4002c710bc32c988e3e1ebf62b39d32bf99f14d9765"
1804 | dependencies = [
1805 | "indexmap",
1806 | "num_cpus",
1807 | "once_cell",
1808 | "rustc-hash 2.1.1",
1809 | "ryu-js",
1810 | "swc_atoms",
1811 | "swc_common",
1812 | "swc_ecma_ast",
1813 | "swc_ecma_visit",
1814 | "swc_parallel",
1815 | "tracing",
1816 | "unicode-id",
1817 | ]
1818 |
1819 | [[package]]
1820 | name = "swc_ecma_visit"
1821 | version = "8.0.0"
1822 | source = "registry+https://github.com/rust-lang/crates.io-index"
1823 | checksum = "2f7a65fa06d0c0f709f1df4e820ccdc4eca7b3db7f9d131545e20c2ac2f1cd23"
1824 | dependencies = [
1825 | "new_debug_unreachable",
1826 | "num-bigint",
1827 | "swc_atoms",
1828 | "swc_common",
1829 | "swc_ecma_ast",
1830 | "swc_visit",
1831 | "tracing",
1832 | ]
1833 |
1834 | [[package]]
1835 | name = "swc_eq_ignore_macros"
1836 | version = "1.0.0"
1837 | source = "registry+https://github.com/rust-lang/crates.io-index"
1838 | checksum = "e96e15288bf385ab85eb83cff7f9e2d834348da58d0a31b33bdb572e66ee413e"
1839 | dependencies = [
1840 | "proc-macro2",
1841 | "quote",
1842 | "syn",
1843 | ]
1844 |
1845 | [[package]]
1846 | name = "swc_error_reporters"
1847 | version = "9.0.0"
1848 | source = "registry+https://github.com/rust-lang/crates.io-index"
1849 | checksum = "10ad5f4690758cedc202cf0f4c9d2369372c6692307f65bd40031de494662cfa"
1850 | dependencies = [
1851 | "anyhow",
1852 | "miette",
1853 | "once_cell",
1854 | "parking_lot",
1855 | "swc_common",
1856 | ]
1857 |
1858 | [[package]]
1859 | name = "swc_macros_common"
1860 | version = "1.0.0"
1861 | source = "registry+https://github.com/rust-lang/crates.io-index"
1862 | checksum = "a509f56fca05b39ba6c15f3e58636c3924c78347d63853632ed2ffcb6f5a0ac7"
1863 | dependencies = [
1864 | "proc-macro2",
1865 | "quote",
1866 | "syn",
1867 | ]
1868 |
1869 | [[package]]
1870 | name = "swc_parallel"
1871 | version = "1.2.0"
1872 | source = "registry+https://github.com/rust-lang/crates.io-index"
1873 | checksum = "e5f75f1094d69174ef628e3665fff0f81d58e9f568802e3c90d332c72b0b6026"
1874 | dependencies = [
1875 | "once_cell",
1876 | ]
1877 |
1878 | [[package]]
1879 | name = "swc_plugin"
1880 | version = "1.0.0"
1881 | source = "registry+https://github.com/rust-lang/crates.io-index"
1882 | checksum = "6b45099a38ed45528bef939d0eac1a0c1347749d0c67d3dd744d545316c5fd05"
1883 | dependencies = [
1884 | "once_cell",
1885 | ]
1886 |
1887 | [[package]]
1888 | name = "swc_plugin_macro"
1889 | version = "1.0.0"
1890 | source = "registry+https://github.com/rust-lang/crates.io-index"
1891 | checksum = "0917ccfdcd3fa6cf41bdacef2388702a3b274f9ea708d930e1e8db37c7c3e1c6"
1892 | dependencies = [
1893 | "proc-macro2",
1894 | "quote",
1895 | "syn",
1896 | ]
1897 |
1898 | [[package]]
1899 | name = "swc_plugin_proxy"
1900 | version = "8.0.0"
1901 | source = "registry+https://github.com/rust-lang/crates.io-index"
1902 | checksum = "a18c199683d9f946db8dfca444212a3551e74a7c563196b154d5ac30f3bf9de6"
1903 | dependencies = [
1904 | "better_scoped_tls",
1905 | "bytecheck",
1906 | "rancor",
1907 | "rkyv",
1908 | "rustc-hash 2.1.1",
1909 | "swc_common",
1910 | "swc_ecma_ast",
1911 | "swc_trace_macro",
1912 | "tracing",
1913 | ]
1914 |
1915 | [[package]]
1916 | name = "swc_trace_macro"
1917 | version = "2.0.0"
1918 | source = "registry+https://github.com/rust-lang/crates.io-index"
1919 | checksum = "4c78717a841565df57f811376a3d19c9156091c55175e12d378f3a522de70cef"
1920 | dependencies = [
1921 | "proc-macro2",
1922 | "quote",
1923 | "syn",
1924 | ]
1925 |
1926 | [[package]]
1927 | name = "swc_visit"
1928 | version = "2.0.0"
1929 | source = "registry+https://github.com/rust-lang/crates.io-index"
1930 | checksum = "9138b6a36bbe76dd6753c4c0794f7e26480ea757bee499738bedbbb3ae3ec5f3"
1931 | dependencies = [
1932 | "either",
1933 | "new_debug_unreachable",
1934 | ]
1935 |
1936 | [[package]]
1937 | name = "syn"
1938 | version = "2.0.99"
1939 | source = "registry+https://github.com/rust-lang/crates.io-index"
1940 | checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2"
1941 | dependencies = [
1942 | "proc-macro2",
1943 | "quote",
1944 | "unicode-ident",
1945 | ]
1946 |
1947 | [[package]]
1948 | name = "synstructure"
1949 | version = "0.13.1"
1950 | source = "registry+https://github.com/rust-lang/crates.io-index"
1951 | checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
1952 | dependencies = [
1953 | "proc-macro2",
1954 | "quote",
1955 | "syn",
1956 | ]
1957 |
1958 | [[package]]
1959 | name = "tap"
1960 | version = "1.0.1"
1961 | source = "registry+https://github.com/rust-lang/crates.io-index"
1962 | checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
1963 |
1964 | [[package]]
1965 | name = "tempfile"
1966 | version = "3.17.1"
1967 | source = "registry+https://github.com/rust-lang/crates.io-index"
1968 | checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230"
1969 | dependencies = [
1970 | "cfg-if",
1971 | "fastrand",
1972 | "getrandom",
1973 | "once_cell",
1974 | "rustix",
1975 | "windows-sys",
1976 | ]
1977 |
1978 | [[package]]
1979 | name = "termcolor"
1980 | version = "1.4.1"
1981 | source = "registry+https://github.com/rust-lang/crates.io-index"
1982 | checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
1983 | dependencies = [
1984 | "winapi-util",
1985 | ]
1986 |
1987 | [[package]]
1988 | name = "testing"
1989 | version = "8.0.0"
1990 | source = "registry+https://github.com/rust-lang/crates.io-index"
1991 | checksum = "8d32ddc0e2ebd072cbffe7424087267da990708a5bc3ae29e075904468450275"
1992 | dependencies = [
1993 | "ansi_term",
1994 | "cargo_metadata 0.18.1",
1995 | "difference",
1996 | "once_cell",
1997 | "pretty_assertions",
1998 | "regex",
1999 | "rustc-hash 2.1.1",
2000 | "serde",
2001 | "serde_json",
2002 | "swc_common",
2003 | "swc_error_reporters",
2004 | "testing_macros",
2005 | "tracing",
2006 | "tracing-subscriber",
2007 | ]
2008 |
2009 | [[package]]
2010 | name = "testing_macros"
2011 | version = "1.0.0"
2012 | source = "registry+https://github.com/rust-lang/crates.io-index"
2013 | checksum = "a2d27bf245b90a80d5aa231133418ae7db98f032855ce5292e12071ab29c4b26"
2014 | dependencies = [
2015 | "anyhow",
2016 | "glob",
2017 | "once_cell",
2018 | "proc-macro2",
2019 | "quote",
2020 | "regex",
2021 | "relative-path",
2022 | "syn",
2023 | ]
2024 |
2025 | [[package]]
2026 | name = "textwrap"
2027 | version = "0.16.2"
2028 | source = "registry+https://github.com/rust-lang/crates.io-index"
2029 | checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
2030 | dependencies = [
2031 | "unicode-linebreak",
2032 | "unicode-width 0.2.0",
2033 | ]
2034 |
2035 | [[package]]
2036 | name = "thiserror"
2037 | version = "1.0.69"
2038 | source = "registry+https://github.com/rust-lang/crates.io-index"
2039 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
2040 | dependencies = [
2041 | "thiserror-impl 1.0.69",
2042 | ]
2043 |
2044 | [[package]]
2045 | name = "thiserror"
2046 | version = "2.0.12"
2047 | source = "registry+https://github.com/rust-lang/crates.io-index"
2048 | checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
2049 | dependencies = [
2050 | "thiserror-impl 2.0.12",
2051 | ]
2052 |
2053 | [[package]]
2054 | name = "thiserror-impl"
2055 | version = "1.0.69"
2056 | source = "registry+https://github.com/rust-lang/crates.io-index"
2057 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
2058 | dependencies = [
2059 | "proc-macro2",
2060 | "quote",
2061 | "syn",
2062 | ]
2063 |
2064 | [[package]]
2065 | name = "thiserror-impl"
2066 | version = "2.0.12"
2067 | source = "registry+https://github.com/rust-lang/crates.io-index"
2068 | checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
2069 | dependencies = [
2070 | "proc-macro2",
2071 | "quote",
2072 | "syn",
2073 | ]
2074 |
2075 | [[package]]
2076 | name = "thread_local"
2077 | version = "1.1.8"
2078 | source = "registry+https://github.com/rust-lang/crates.io-index"
2079 | checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
2080 | dependencies = [
2081 | "cfg-if",
2082 | "once_cell",
2083 | ]
2084 |
2085 | [[package]]
2086 | name = "tinystr"
2087 | version = "0.7.6"
2088 | source = "registry+https://github.com/rust-lang/crates.io-index"
2089 | checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
2090 | dependencies = [
2091 | "displaydoc",
2092 | "zerovec",
2093 | ]
2094 |
2095 | [[package]]
2096 | name = "tinytemplate"
2097 | version = "1.2.1"
2098 | source = "registry+https://github.com/rust-lang/crates.io-index"
2099 | checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
2100 | dependencies = [
2101 | "serde",
2102 | "serde_json",
2103 | ]
2104 |
2105 | [[package]]
2106 | name = "tinyvec"
2107 | version = "1.9.0"
2108 | source = "registry+https://github.com/rust-lang/crates.io-index"
2109 | checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71"
2110 | dependencies = [
2111 | "tinyvec_macros",
2112 | ]
2113 |
2114 | [[package]]
2115 | name = "tinyvec_macros"
2116 | version = "0.1.1"
2117 | source = "registry+https://github.com/rust-lang/crates.io-index"
2118 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
2119 |
2120 | [[package]]
2121 | name = "tracing"
2122 | version = "0.1.41"
2123 | source = "registry+https://github.com/rust-lang/crates.io-index"
2124 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
2125 | dependencies = [
2126 | "pin-project-lite",
2127 | "tracing-attributes",
2128 | "tracing-core",
2129 | ]
2130 |
2131 | [[package]]
2132 | name = "tracing-attributes"
2133 | version = "0.1.28"
2134 | source = "registry+https://github.com/rust-lang/crates.io-index"
2135 | checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
2136 | dependencies = [
2137 | "proc-macro2",
2138 | "quote",
2139 | "syn",
2140 | ]
2141 |
2142 | [[package]]
2143 | name = "tracing-core"
2144 | version = "0.1.33"
2145 | source = "registry+https://github.com/rust-lang/crates.io-index"
2146 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
2147 | dependencies = [
2148 | "once_cell",
2149 | "valuable",
2150 | ]
2151 |
2152 | [[package]]
2153 | name = "tracing-log"
2154 | version = "0.2.0"
2155 | source = "registry+https://github.com/rust-lang/crates.io-index"
2156 | checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
2157 | dependencies = [
2158 | "log",
2159 | "once_cell",
2160 | "tracing-core",
2161 | ]
2162 |
2163 | [[package]]
2164 | name = "tracing-subscriber"
2165 | version = "0.3.19"
2166 | source = "registry+https://github.com/rust-lang/crates.io-index"
2167 | checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
2168 | dependencies = [
2169 | "matchers",
2170 | "nu-ansi-term",
2171 | "once_cell",
2172 | "regex",
2173 | "sharded-slab",
2174 | "smallvec",
2175 | "thread_local",
2176 | "tracing",
2177 | "tracing-core",
2178 | "tracing-log",
2179 | ]
2180 |
2181 | [[package]]
2182 | name = "transform"
2183 | version = "0.1.0"
2184 | dependencies = [
2185 | "base62",
2186 | "criterion",
2187 | "serde",
2188 | "swc_core",
2189 | "xxhash-rust",
2190 | ]
2191 |
2192 | [[package]]
2193 | name = "triomphe"
2194 | version = "0.1.14"
2195 | source = "registry+https://github.com/rust-lang/crates.io-index"
2196 | checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85"
2197 | dependencies = [
2198 | "serde",
2199 | "stable_deref_trait",
2200 | ]
2201 |
2202 | [[package]]
2203 | name = "typed-arena"
2204 | version = "2.0.2"
2205 | source = "registry+https://github.com/rust-lang/crates.io-index"
2206 | checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
2207 |
2208 | [[package]]
2209 | name = "typenum"
2210 | version = "1.18.0"
2211 | source = "registry+https://github.com/rust-lang/crates.io-index"
2212 | checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
2213 |
2214 | [[package]]
2215 | name = "unicode-id"
2216 | version = "0.3.5"
2217 | source = "registry+https://github.com/rust-lang/crates.io-index"
2218 | checksum = "10103c57044730945224467c09f71a4db0071c123a0648cc3e818913bde6b561"
2219 |
2220 | [[package]]
2221 | name = "unicode-id-start"
2222 | version = "1.3.1"
2223 | source = "registry+https://github.com/rust-lang/crates.io-index"
2224 | checksum = "2f322b60f6b9736017344fa0635d64be2f458fbc04eef65f6be22976dd1ffd5b"
2225 |
2226 | [[package]]
2227 | name = "unicode-ident"
2228 | version = "1.0.18"
2229 | source = "registry+https://github.com/rust-lang/crates.io-index"
2230 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
2231 |
2232 | [[package]]
2233 | name = "unicode-linebreak"
2234 | version = "0.1.5"
2235 | source = "registry+https://github.com/rust-lang/crates.io-index"
2236 | checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
2237 |
2238 | [[package]]
2239 | name = "unicode-width"
2240 | version = "0.1.14"
2241 | source = "registry+https://github.com/rust-lang/crates.io-index"
2242 | checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
2243 |
2244 | [[package]]
2245 | name = "unicode-width"
2246 | version = "0.2.0"
2247 | source = "registry+https://github.com/rust-lang/crates.io-index"
2248 | checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
2249 |
2250 | [[package]]
2251 | name = "url"
2252 | version = "2.5.4"
2253 | source = "registry+https://github.com/rust-lang/crates.io-index"
2254 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
2255 | dependencies = [
2256 | "form_urlencoded",
2257 | "idna",
2258 | "percent-encoding",
2259 | ]
2260 |
2261 | [[package]]
2262 | name = "utf16_iter"
2263 | version = "1.0.5"
2264 | source = "registry+https://github.com/rust-lang/crates.io-index"
2265 | checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
2266 |
2267 | [[package]]
2268 | name = "utf8_iter"
2269 | version = "1.0.4"
2270 | source = "registry+https://github.com/rust-lang/crates.io-index"
2271 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
2272 |
2273 | [[package]]
2274 | name = "uuid"
2275 | version = "1.15.1"
2276 | source = "registry+https://github.com/rust-lang/crates.io-index"
2277 | checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587"
2278 |
2279 | [[package]]
2280 | name = "valuable"
2281 | version = "0.1.1"
2282 | source = "registry+https://github.com/rust-lang/crates.io-index"
2283 | checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
2284 |
2285 | [[package]]
2286 | name = "vergen"
2287 | version = "9.0.4"
2288 | source = "registry+https://github.com/rust-lang/crates.io-index"
2289 | checksum = "e0d2f179f8075b805a43a2a21728a46f0cc2921b3c58695b28fa8817e103cd9a"
2290 | dependencies = [
2291 | "anyhow",
2292 | "cargo_metadata 0.19.2",
2293 | "derive_builder",
2294 | "regex",
2295 | "rustversion",
2296 | "vergen-lib",
2297 | ]
2298 |
2299 | [[package]]
2300 | name = "vergen-lib"
2301 | version = "0.1.6"
2302 | source = "registry+https://github.com/rust-lang/crates.io-index"
2303 | checksum = "9b07e6010c0f3e59fcb164e0163834597da68d1f864e2b8ca49f74de01e9c166"
2304 | dependencies = [
2305 | "anyhow",
2306 | "derive_builder",
2307 | "rustversion",
2308 | ]
2309 |
2310 | [[package]]
2311 | name = "version_check"
2312 | version = "0.9.5"
2313 | source = "registry+https://github.com/rust-lang/crates.io-index"
2314 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
2315 |
2316 | [[package]]
2317 | name = "walkdir"
2318 | version = "2.5.0"
2319 | source = "registry+https://github.com/rust-lang/crates.io-index"
2320 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
2321 | dependencies = [
2322 | "same-file",
2323 | "winapi-util",
2324 | ]
2325 |
2326 | [[package]]
2327 | name = "wasi"
2328 | version = "0.13.3+wasi-0.2.2"
2329 | source = "registry+https://github.com/rust-lang/crates.io-index"
2330 | checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
2331 | dependencies = [
2332 | "wit-bindgen-rt",
2333 | ]
2334 |
2335 | [[package]]
2336 | name = "winapi"
2337 | version = "0.3.9"
2338 | source = "registry+https://github.com/rust-lang/crates.io-index"
2339 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
2340 | dependencies = [
2341 | "winapi-i686-pc-windows-gnu",
2342 | "winapi-x86_64-pc-windows-gnu",
2343 | ]
2344 |
2345 | [[package]]
2346 | name = "winapi-i686-pc-windows-gnu"
2347 | version = "0.4.0"
2348 | source = "registry+https://github.com/rust-lang/crates.io-index"
2349 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
2350 |
2351 | [[package]]
2352 | name = "winapi-util"
2353 | version = "0.1.9"
2354 | source = "registry+https://github.com/rust-lang/crates.io-index"
2355 | checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
2356 | dependencies = [
2357 | "windows-sys",
2358 | ]
2359 |
2360 | [[package]]
2361 | name = "winapi-x86_64-pc-windows-gnu"
2362 | version = "0.4.0"
2363 | source = "registry+https://github.com/rust-lang/crates.io-index"
2364 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
2365 |
2366 | [[package]]
2367 | name = "windows-sys"
2368 | version = "0.59.0"
2369 | source = "registry+https://github.com/rust-lang/crates.io-index"
2370 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
2371 | dependencies = [
2372 | "windows-targets",
2373 | ]
2374 |
2375 | [[package]]
2376 | name = "windows-targets"
2377 | version = "0.52.6"
2378 | source = "registry+https://github.com/rust-lang/crates.io-index"
2379 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
2380 | dependencies = [
2381 | "windows_aarch64_gnullvm",
2382 | "windows_aarch64_msvc",
2383 | "windows_i686_gnu",
2384 | "windows_i686_gnullvm",
2385 | "windows_i686_msvc",
2386 | "windows_x86_64_gnu",
2387 | "windows_x86_64_gnullvm",
2388 | "windows_x86_64_msvc",
2389 | ]
2390 |
2391 | [[package]]
2392 | name = "windows_aarch64_gnullvm"
2393 | version = "0.52.6"
2394 | source = "registry+https://github.com/rust-lang/crates.io-index"
2395 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
2396 |
2397 | [[package]]
2398 | name = "windows_aarch64_msvc"
2399 | version = "0.52.6"
2400 | source = "registry+https://github.com/rust-lang/crates.io-index"
2401 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
2402 |
2403 | [[package]]
2404 | name = "windows_i686_gnu"
2405 | version = "0.52.6"
2406 | source = "registry+https://github.com/rust-lang/crates.io-index"
2407 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
2408 |
2409 | [[package]]
2410 | name = "windows_i686_gnullvm"
2411 | version = "0.52.6"
2412 | source = "registry+https://github.com/rust-lang/crates.io-index"
2413 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
2414 |
2415 | [[package]]
2416 | name = "windows_i686_msvc"
2417 | version = "0.52.6"
2418 | source = "registry+https://github.com/rust-lang/crates.io-index"
2419 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
2420 |
2421 | [[package]]
2422 | name = "windows_x86_64_gnu"
2423 | version = "0.52.6"
2424 | source = "registry+https://github.com/rust-lang/crates.io-index"
2425 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
2426 |
2427 | [[package]]
2428 | name = "windows_x86_64_gnullvm"
2429 | version = "0.52.6"
2430 | source = "registry+https://github.com/rust-lang/crates.io-index"
2431 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
2432 |
2433 | [[package]]
2434 | name = "windows_x86_64_msvc"
2435 | version = "0.52.6"
2436 | source = "registry+https://github.com/rust-lang/crates.io-index"
2437 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
2438 |
2439 | [[package]]
2440 | name = "wit-bindgen-rt"
2441 | version = "0.33.0"
2442 | source = "registry+https://github.com/rust-lang/crates.io-index"
2443 | checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
2444 | dependencies = [
2445 | "bitflags",
2446 | ]
2447 |
2448 | [[package]]
2449 | name = "write16"
2450 | version = "1.0.0"
2451 | source = "registry+https://github.com/rust-lang/crates.io-index"
2452 | checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
2453 |
2454 | [[package]]
2455 | name = "writeable"
2456 | version = "0.5.5"
2457 | source = "registry+https://github.com/rust-lang/crates.io-index"
2458 | checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
2459 |
2460 | [[package]]
2461 | name = "wyz"
2462 | version = "0.5.1"
2463 | source = "registry+https://github.com/rust-lang/crates.io-index"
2464 | checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
2465 | dependencies = [
2466 | "tap",
2467 | ]
2468 |
2469 | [[package]]
2470 | name = "xxhash-rust"
2471 | version = "0.8.15"
2472 | source = "registry+https://github.com/rust-lang/crates.io-index"
2473 | checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3"
2474 |
2475 | [[package]]
2476 | name = "yansi"
2477 | version = "1.0.1"
2478 | source = "registry+https://github.com/rust-lang/crates.io-index"
2479 | checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
2480 |
2481 | [[package]]
2482 | name = "yoke"
2483 | version = "0.7.5"
2484 | source = "registry+https://github.com/rust-lang/crates.io-index"
2485 | checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
2486 | dependencies = [
2487 | "serde",
2488 | "stable_deref_trait",
2489 | "yoke-derive",
2490 | "zerofrom",
2491 | ]
2492 |
2493 | [[package]]
2494 | name = "yoke-derive"
2495 | version = "0.7.5"
2496 | source = "registry+https://github.com/rust-lang/crates.io-index"
2497 | checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
2498 | dependencies = [
2499 | "proc-macro2",
2500 | "quote",
2501 | "syn",
2502 | "synstructure",
2503 | ]
2504 |
2505 | [[package]]
2506 | name = "zerocopy"
2507 | version = "0.7.35"
2508 | source = "registry+https://github.com/rust-lang/crates.io-index"
2509 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
2510 | dependencies = [
2511 | "zerocopy-derive",
2512 | ]
2513 |
2514 | [[package]]
2515 | name = "zerocopy-derive"
2516 | version = "0.7.35"
2517 | source = "registry+https://github.com/rust-lang/crates.io-index"
2518 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
2519 | dependencies = [
2520 | "proc-macro2",
2521 | "quote",
2522 | "syn",
2523 | ]
2524 |
2525 | [[package]]
2526 | name = "zerofrom"
2527 | version = "0.1.6"
2528 | source = "registry+https://github.com/rust-lang/crates.io-index"
2529 | checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
2530 | dependencies = [
2531 | "zerofrom-derive",
2532 | ]
2533 |
2534 | [[package]]
2535 | name = "zerofrom-derive"
2536 | version = "0.1.6"
2537 | source = "registry+https://github.com/rust-lang/crates.io-index"
2538 | checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
2539 | dependencies = [
2540 | "proc-macro2",
2541 | "quote",
2542 | "syn",
2543 | "synstructure",
2544 | ]
2545 |
2546 | [[package]]
2547 | name = "zerovec"
2548 | version = "0.10.4"
2549 | source = "registry+https://github.com/rust-lang/crates.io-index"
2550 | checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
2551 | dependencies = [
2552 | "yoke",
2553 | "zerofrom",
2554 | "zerovec-derive",
2555 | ]
2556 |
2557 | [[package]]
2558 | name = "zerovec-derive"
2559 | version = "0.10.3"
2560 | source = "registry+https://github.com/rust-lang/crates.io-index"
2561 | checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
2562 | dependencies = [
2563 | "proc-macro2",
2564 | "quote",
2565 | "syn",
2566 | ]
2567 |
--------------------------------------------------------------------------------
/swc/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | members = ["swc-plugin-css-variable", "transform"]
3 | resolver = "2"
4 |
5 | [profile.release]
6 | # This profile results in small binary size with acceptable impact on
7 | # performance, but there may well be further optimizations to be had.
8 | strip = "debuginfo"
9 | codegen-units = 1
10 | lto = true
11 | opt-level = "z"
12 |
--------------------------------------------------------------------------------
/swc/README.md:
--------------------------------------------------------------------------------
1 | # swc-plugin-css-variable
2 |
3 | This is the SWC counterpart to the babel plugin of this library.
4 |
5 | ## Structure
6 |
7 | This is a workspace with two crates:
8 |
9 | - `swc-plugin-css-variable` is the outer shell and only contains what's
10 | necessary to interface with SWC, which is essentially the main function that
11 | is decorated with `#[plugin_transform]`
12 | - `transform` has everything else, most importantly the visitor implementation
13 |
14 | The reason for the split is to enable benchmarking inside Wasm runtimes. If the
15 | code under test (the visitor) were in the same crate as `#[plugin_transform]`,
16 | code would be generated that requires functions to be linked in for accessing
17 | the environment and emitting diagnostics. Normally these are provided at
18 | runtime by SWC, but for only running benchmarks we don't want to have to
19 | fake them.
20 |
21 | ## Benchmarking
22 |
23 | The benchmarks can be run easily with `cargo bench`. Note that this builds and
24 | runs native code on your machine, which may not exhibit the exact same
25 | performance characteristics as a Wasm module in a runtime, as is the case for
26 | SWC transformations.
27 |
28 | To account for this, it's also possible to build a benchmark executable in Wasm
29 | format and execute it in your runtime of choice. Since SWC internally uses
30 | [Wasmer](https://wasmer.io), it makes sense to install this one. Then, it's
31 | just a matter of
32 |
33 | ```console
34 | $ cargo build --bench bench_main --release --target wasm32-wasip1
35 | # Get the name of the Wasm module we just built
36 | $ ls -t target/wasm32-wasip1/release/deps/*.wasm | head -n 1
37 | target/wasm32-wasip1/release/deps/bench_main-9530540cc15e2e67.wasm
38 | # Execute the benchmark
39 | $ wasmer target/wasm32-wasip1/release/deps/bench_main-9530540cc15e2e67.wasm -- --bench
40 | ```
41 |
42 | With this you get the most accurate runtime behavior and can observe the
43 | difference to native code. However, you'll most likely find it negligible, with
44 | Wasm being just slightly slower and everything else scaling mostly linearly. A
45 | typical example:
46 |
47 | - `wasmer: visitor styledPage time: [6.6177 µs 6.6316 µs 6.6495 µs]`
48 | - `native: visitor styledPage time: [5.4191 µs 5.4736 µs 5.5150 µs]`
49 |
50 | For most changes that aren't Wasm-specific, it's therefore often good enough to
51 | just run the benchmarks normally with `cargo bench`.
52 |
--------------------------------------------------------------------------------
/swc/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "swc-plugin-css-variable",
3 | "version": "0.1.0",
4 | "description": "",
5 | "author": "",
6 | "license": "MIT",
7 | "keywords": [
8 | "swc-plugin"
9 | ],
10 | "main": "target/wasm32-wasip1/release/swc_plugin_css_variable.wasm",
11 | "scripts": {
12 | "prepublishOnly": "cargo build --release"
13 | },
14 | "files": []
15 | }
16 |
--------------------------------------------------------------------------------
/swc/swc-plugin-css-variable/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "swc-plugin-css-variable"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [lib]
7 | # cdylib is for dynamic system library and necessary to produce the Wasm plugin
8 | crate-type = ["cdylib"]
9 |
10 | [dependencies]
11 | lazy_static = "1.4.0"
12 | pathdiff = "0.2.1"
13 | regex = "1.10.3"
14 | serde_json = "1.0.111"
15 | swc_core = { version = "16.0.0", features = ["ecma_plugin_transform"] }
16 |
17 | transform = { path = "../transform" }
18 |
--------------------------------------------------------------------------------
/swc/swc-plugin-css-variable/src/lib.rs:
--------------------------------------------------------------------------------
1 | use pathdiff::diff_paths;
2 | use swc_core::{
3 | ecma::{ast::*, visit::visit_mut_pass},
4 | plugin::{
5 | metadata::TransformPluginMetadataContextKind, plugin_transform,
6 | proxies::TransformPluginProgramMetadata,
7 | },
8 | };
9 |
10 | use transform::{hash, Config, TransformVisitor};
11 |
12 | use regex::Regex;
13 | #[macro_use]
14 | extern crate lazy_static;
15 |
16 | /// Transforms a [`Program`].
17 | #[plugin_transform]
18 | pub fn process_transform(program: Program, metadata: TransformPluginProgramMetadata) -> Program {
19 | let config: Config = serde_json::from_str(
20 | &metadata
21 | .get_transform_plugin_config()
22 | .expect("failed to get plugin config for swc-plugin-css-variable"),
23 | )
24 | .expect("failed to parse plugin config");
25 |
26 | let file_name = metadata
27 | .get_context(&TransformPluginMetadataContextKind::Filename)
28 | .expect("failed to get filename");
29 | let deterministic_path = relative_posix_path(&config.base_path, &file_name);
30 | let hashed_filename = hash(&deterministic_path);
31 |
32 | program.apply(visit_mut_pass(&mut TransformVisitor::new(
33 | config,
34 | hashed_filename,
35 | )))
36 | }
37 |
38 | /// Returns a relative POSIX path from the `base_path` to the filename.
39 | ///
40 | /// For example:
41 | /// - "/foo/", "/bar/baz.txt" -> "../bar/baz.txt"
42 | /// - "C:\foo\", "C:\foo\baz.txt" -> "../bar/baz.txt"
43 | ///
44 | /// The format of `base_path` and `filename` must match the current OS.
45 | fn relative_posix_path(base_path: &str, filename: &str) -> String {
46 | let normalized_base_path = convert_path_to_posix(base_path);
47 | let normalized_filename = convert_path_to_posix(filename);
48 | let relative_filename = diff_paths(normalized_filename, normalized_base_path)
49 | .expect("Could not create relative path");
50 | let path_parts = relative_filename
51 | .components()
52 | .map(|component| component.as_os_str().to_str().unwrap())
53 | .collect::>();
54 |
55 | path_parts.join("/")
56 | }
57 |
58 | /// Returns the path converted to a POSIX path (naive approach).
59 | ///
60 | /// For example:
61 | /// - "C:\foo\bar" -> "c/foo/bar"
62 | /// - "/foo/bar" -> "/foo/bar"
63 | fn convert_path_to_posix(path: &str) -> String {
64 | lazy_static! {
65 | static ref PATH_REPLACEMENT_REGEX: Regex = Regex::new(r":\\|\\|:/").unwrap();
66 | }
67 |
68 | PATH_REPLACEMENT_REGEX.replace_all(path, "/").to_string()
69 | }
70 |
71 | #[cfg(test)]
72 | mod tests {
73 | use super::*;
74 |
75 | #[test]
76 | fn test_relative_path_unix() {
77 | assert_eq!(
78 | relative_posix_path("/foo/", "/bar/baz.txt"),
79 | "../bar/baz.txt"
80 | );
81 | }
82 |
83 | #[test]
84 | fn test_relative_path_windows() {
85 | assert_eq!(
86 | relative_posix_path(r"C:\foo\", r"C:\bar\baz.txt"),
87 | "../bar/baz.txt"
88 | );
89 | }
90 |
91 | #[test]
92 | fn test_relative_path_windows_forward_slash() {
93 | assert_eq!(
94 | relative_posix_path(r"E:\foo", "E:/foo/bar/file.tsx"),
95 | "bar/file.tsx"
96 | );
97 | }
98 |
99 | #[test]
100 | fn test_convert_unix_path() {
101 | assert_eq!(convert_path_to_posix(r"/foo/bar"), "/foo/bar");
102 | }
103 |
104 | #[test]
105 | fn test_convert_windows_path() {
106 | assert_eq!(convert_path_to_posix(r"C:\foo\bar"), "C/foo/bar");
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/swc/transform/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "transform"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [dependencies]
7 | base62 = "2.0.2"
8 | serde = { version = "1.0.195", features = ["derive"] }
9 | swc_core = "16.0.0"
10 | xxhash-rust = { version = "0.8.8", features = ["xxh32"] }
11 |
12 | [dev-dependencies]
13 | criterion = { version = "0.5.1", default-features = false }
14 | swc_core = { version = "16.0.0", features = ["ecma_parser", "ecma_plugin_transform"] }
15 |
16 | [[bench]]
17 | name = "bench_main"
18 | harness = false
19 |
--------------------------------------------------------------------------------
/swc/transform/benches/bench_main.rs:
--------------------------------------------------------------------------------
1 | use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion};
2 | use swc_core::{
3 | common::{sync::Lrc, FileName, SourceMap},
4 | ecma::{parser, visit::VisitMutWith},
5 | };
6 |
7 | use transform::{Config, TransformVisitor};
8 |
9 | pub fn styled_page(c: &mut Criterion) {
10 | let source_map: Lrc = Default::default();
11 | let source_file = source_map.new_source_file(
12 | Lrc::new(FileName::Custom("styledPage.tsx".into())),
13 | include_str!("styledPage.tsx").into(),
14 | );
15 |
16 | let program = parser::parse_file_as_program(
17 | &source_file,
18 | Default::default(),
19 | Default::default(),
20 | None,
21 | &mut vec![],
22 | )
23 | .unwrap();
24 |
25 | c.bench_function("visitor styledPage", |b| {
26 | b.iter_batched(
27 | || {
28 | (
29 | program.clone(),
30 | TransformVisitor::new(Default::default(), String::from("hashed")),
31 | )
32 | },
33 | |(mut program, mut visitor)| program.visit_mut_with(&mut visitor),
34 | BatchSize::SmallInput,
35 | )
36 | });
37 |
38 | c.bench_function("visitor styledPage display_name", |b| {
39 | b.iter_batched(
40 | || {
41 | (
42 | program.clone(),
43 | TransformVisitor::new(
44 | Config {
45 | display_name: true,
46 | ..Default::default()
47 | },
48 | String::from("hashed"),
49 | ),
50 | )
51 | },
52 | |(mut program, mut visitor)| program.visit_mut_with(&mut visitor),
53 | BatchSize::SmallInput,
54 | )
55 | });
56 | }
57 |
58 | pub fn nested(c: &mut Criterion) {
59 | let source_map: Lrc = Default::default();
60 | let source_file = source_map.new_source_file(
61 | Lrc::new(FileName::Custom("nested.js".into())),
62 | include_str!("nested.js").into(),
63 | );
64 |
65 | let program = parser::parse_file_as_program(
66 | &source_file,
67 | Default::default(),
68 | Default::default(),
69 | None,
70 | &mut vec![],
71 | )
72 | .unwrap();
73 |
74 | c.bench_function("visitor nested", |b| {
75 | b.iter_batched(
76 | || {
77 | (
78 | program.clone(),
79 | TransformVisitor::new(Default::default(), String::from("hashed")),
80 | )
81 | },
82 | |(mut program, mut visitor)| program.visit_mut_with(&mut visitor),
83 | BatchSize::SmallInput,
84 | )
85 | });
86 |
87 | c.bench_function("visitor nested display_name", |b| {
88 | b.iter_batched(
89 | || {
90 | (
91 | program.clone(),
92 | TransformVisitor::new(
93 | Config {
94 | display_name: true,
95 | ..Default::default()
96 | },
97 | String::from("hashed"),
98 | ),
99 | )
100 | },
101 | |(mut program, mut visitor)| program.visit_mut_with(&mut visitor),
102 | BatchSize::SmallInput,
103 | )
104 | });
105 | }
106 |
107 | pub fn short_hash(c: &mut Criterion) {
108 | c.bench_function("short filename hash", |b| {
109 | b.iter(|| transform::hash(black_box("fileName.ts")))
110 | });
111 | }
112 |
113 | pub fn longer_hash(c: &mut Criterion) {
114 | c.bench_function("longer filename hash", |b| {
115 | b.iter(|| {
116 | transform::hash(
117 | black_box("some/slightly/somewhat/much/very/much/longer/harder/better/faster/stronger/convoluted/fileName.ts")
118 | )
119 | })
120 | });
121 | }
122 |
123 | criterion_group!(benches, styled_page, nested, short_hash, longer_hash);
124 | criterion_main!(benches);
125 |
--------------------------------------------------------------------------------
/swc/transform/benches/nested.js:
--------------------------------------------------------------------------------
1 | import { createVar } from "css-variable";
2 |
3 | export const tokens = {
4 | one: {
5 | two: {
6 | three: {
7 | four: {
8 | five: {
9 | six: {
10 | seven: {
11 | eight: {
12 | nine: {
13 | ten: {
14 | eleven: {
15 | twelve: {
16 | thirteen: {
17 | fourteen: {
18 | fifteen: {
19 | sixteen: {
20 | seventeen: {
21 | eighteen: {
22 | nineteen: {
23 | twenty: createVar(),
24 | },
25 | },
26 | },
27 | },
28 | },
29 | },
30 | },
31 | },
32 | },
33 | },
34 | },
35 | },
36 | },
37 | },
38 | },
39 | },
40 | },
41 | },
42 | },
43 | };
44 |
--------------------------------------------------------------------------------
/swc/transform/benches/styledPage.tsx:
--------------------------------------------------------------------------------
1 | /// @ts-check
2 | import { CSSPixelValue, createVar, createGlobalTheme } from "css-variable";
3 | import { styled } from "linaria/react";
4 |
5 | const theme = {
6 | fontSize: createVar(),
7 | spacings: {
8 | s: createVar(),
9 | m: createVar(),
10 | l: createVar(),
11 | },
12 | colors: {
13 | primary: createVar(),
14 | secondary: createVar(),
15 | },
16 | };
17 |
18 | const ThemeA = styled.div`
19 | ${createGlobalTheme("", theme, {
20 | fontSize: "12px",
21 | spacings: {
22 | s: "10px",
23 | m: "20px",
24 | l: "30px",
25 | },
26 | colors: {
27 | primary: "#6290C3",
28 | secondary: "#C2E7DA",
29 | },
30 | })}
31 | `;
32 |
33 | const ThemeB = styled.div`
34 | ${createGlobalTheme("", theme, {
35 | fontSize: "24px",
36 | spacings: {
37 | s: "20px",
38 | m: "40px",
39 | l: "60px",
40 | },
41 | colors: {
42 | primary: "#7C9EB2",
43 | secondary: "#52528C",
44 | },
45 | })}
46 | `;
47 |
48 | const colorVar = createVar({ value: theme.colors.primary });
49 | const xVar = createVar({ value: "0" });
50 |
51 | const StyledHeadline = styled.h1`
52 | font-family: Arial, Helvetica, sans-serif;
53 | font-size: ${theme.fontSize.val};
54 | color: ${colorVar.val};
55 | transform: translateX(${xVar.val});
56 | width: calc(100% - 1 * ${xVar.val});
57 | `;
58 |
--------------------------------------------------------------------------------
/swc/transform/src/hash.rs:
--------------------------------------------------------------------------------
1 | use xxhash_rust::xxh32::xxh32;
2 |
3 | /// Creates a CSS identifier using xxHash (https://cyan4973.github.io/xxHash/).
4 | /// Shortened to base62 (https://en.wikipedia.org/wiki/Base62) to avoid invalid characters.
5 | pub fn hash(data: &str) -> String {
6 | let hash = xxh32(data.as_bytes(), 0);
7 | base62::encode(hash)
8 | }
9 |
10 | #[cfg(test)]
11 | mod tests {
12 | use super::*;
13 |
14 | #[test]
15 | fn short() {
16 | assert_eq!(hash("hey"), "2Hy69D");
17 | }
18 |
19 | #[test]
20 | fn longer() {
21 | assert_eq!(hash("hey how are you doing?"), "34D1Ek");
22 | }
23 |
24 | #[test]
25 | fn longest() {
26 | assert_eq!(
27 | hash("hey how are you doing? I am doing fine, thanks for asking."),
28 | "1XQ5hm"
29 | );
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/swc/transform/src/lib.rs:
--------------------------------------------------------------------------------
1 | use serde::Deserialize;
2 | use std::{collections::HashSet, fmt::Write};
3 | use swc_core::{
4 | common::DUMMY_SP,
5 | ecma::{
6 | ast::*,
7 | visit::{VisitMut, VisitMutWith},
8 | },
9 | };
10 |
11 | mod hash;
12 |
13 | pub use hash::hash;
14 |
15 | /// Static plugin configuration.
16 | #[derive(Default, Deserialize)]
17 | #[serde(rename_all = "camelCase")]
18 | #[serde(deny_unknown_fields)]
19 | pub struct Config {
20 | /// Prefix variables with a readable name, e.g. `primary--2Hy69D0`.
21 | #[serde(default = "bool::default")]
22 | pub display_name: bool,
23 | /// The hash for a css-variable depends on the file name including createVar().
24 | /// To ensure that the hash is consistent accross multiple systems the relative path
25 | /// from the base dir to the source file is used.
26 | #[serde()]
27 | pub base_path: String,
28 | }
29 |
30 | pub struct TransformVisitor {
31 | config: Config,
32 | filename_hash: String,
33 | local_idents: HashSet,
34 | variable_count: u32,
35 | current_var_declarator: Option,
36 | current_object_prop_declarators: Vec,
37 | }
38 |
39 | impl TransformVisitor {
40 | pub fn new(config: Config, filename_hash: String) -> Self {
41 | Self {
42 | config,
43 | filename_hash,
44 | local_idents: HashSet::new(),
45 | variable_count: 0,
46 | current_var_declarator: None,
47 | current_object_prop_declarators: vec![],
48 | }
49 | }
50 | }
51 |
52 | impl VisitMut for TransformVisitor {
53 | /// Searches all local names for `createVar`.
54 | ///
55 | /// For example:
56 | /// ```javascript
57 | /// import { createVar } from "css-variable";
58 | /// import { createVar as x} from "css-variable";
59 | /// import { foo as x, createVar as y } from "css-variable";
60 | /// ```
61 | fn visit_mut_import_decl(&mut self, import_decl: &mut ImportDecl) {
62 | if &import_decl.src.value != "css-variable" {
63 | return;
64 | }
65 |
66 | for specifier in &import_decl.specifiers {
67 | if let ImportSpecifier::Named(local) = specifier {
68 | let imported_ident = match &local.imported {
69 | Some(ModuleExportName::Ident(module_export)) => &module_export.sym,
70 | // import {createVar} from "css-variable";
71 | _ => &local.local.sym,
72 | };
73 |
74 | if imported_ident == "createVar" {
75 | self.local_idents.insert(String::from(&*local.local.sym));
76 | }
77 | }
78 | }
79 | }
80 |
81 | fn visit_mut_var_declarator(&mut self, var_declarator: &mut VarDeclarator) {
82 | self.current_var_declarator =
83 | if let Pat::Ident(BindingIdent { id, .. }) = &var_declarator.name {
84 | Some(id.sym.to_string())
85 | } else {
86 | None
87 | };
88 |
89 | var_declarator.visit_mut_children_with(self);
90 |
91 | self.current_var_declarator = None;
92 | }
93 |
94 | fn visit_mut_key_value_prop(&mut self, key_value: &mut KeyValueProp) {
95 | if let PropName::Ident(id) = &key_value.key {
96 | self.current_object_prop_declarators
97 | .push(id.sym.to_string());
98 | }
99 |
100 | key_value.visit_mut_children_with(self);
101 |
102 | self.current_object_prop_declarators.pop();
103 | }
104 |
105 | fn visit_mut_call_expr(&mut self, call_expr: &mut CallExpr) {
106 | // Skip entire execution if no import call was found, see visit_mut_import_decl
107 | if self.local_idents.is_empty() {
108 | return;
109 | }
110 |
111 | call_expr.visit_mut_children_with(self);
112 |
113 | if let Callee::Expr(expr) = &call_expr.callee {
114 | if let Expr::Ident(id) = &**expr {
115 | if self.local_idents.contains(&*id.sym) {
116 | let mut variable_name = String::new();
117 |
118 | if self.config.display_name {
119 | for object_prop_declarator in
120 | self.current_object_prop_declarators.iter().rev()
121 | {
122 | write!(&mut variable_name, "{object_prop_declarator}--").unwrap();
123 | }
124 |
125 | if let Some(var_declarator) = &self.current_var_declarator {
126 | write!(&mut variable_name, "{var_declarator}--").unwrap();
127 | }
128 | }
129 |
130 | write!(
131 | &mut variable_name,
132 | "{}{}",
133 | self.filename_hash, self.variable_count
134 | )
135 | .unwrap();
136 | self.variable_count += 1;
137 |
138 | call_expr.args.insert(
139 | 0,
140 | ExprOrSpread {
141 | spread: None,
142 | expr: Box::new(Expr::Lit(Lit::Str(Str {
143 | span: DUMMY_SP,
144 | value: variable_name.into(),
145 | raw: None,
146 | }))),
147 | },
148 | );
149 | }
150 | }
151 | }
152 | }
153 | }
154 |
155 | #[cfg(test)]
156 | mod tests {
157 | use swc_core::ecma::{
158 | transforms::testing::test,
159 | visit::{visit_mut_pass, VisitMutPass},
160 | };
161 |
162 | use super::*;
163 |
164 | fn transform_visitor(config: Config) -> VisitMutPass {
165 | visit_mut_pass(TransformVisitor::new(config, String::from("hashed")))
166 | }
167 |
168 | test!(
169 | Default::default(),
170 | |_| transform_visitor(Default::default()),
171 | adds_variable_name,
172 | r#"import {createVar} from "css-variable";
173 | createVar();"#
174 | );
175 |
176 | test!(
177 | Default::default(),
178 | |_| transform_visitor(Default::default()),
179 | adds_multiple_variable_names,
180 | r#"import {createVar} from "css-variable";
181 | createVar();
182 | createVar();
183 | createVar();"#
184 | );
185 |
186 | test!(
187 | Default::default(),
188 | |_| transform_visitor(Default::default()),
189 | ignores_unknwon_modules,
190 | r#"import {createVar} from "unknown";
191 | createVar();"#
192 | );
193 |
194 | test!(
195 | Default::default(),
196 | |_| transform_visitor(Default::default()),
197 | adds_variable_name_with_value,
198 | r#"import {createVar} from "css-variable";
199 | createVar({ value: '0px' });"#
200 | );
201 |
202 | test!(
203 | Default::default(),
204 | |_| transform_visitor(Default::default()),
205 | adds_variable_name_for_renamed,
206 | r#"import {createVar as create} from "css-variable";
207 | create("hello world");"#
208 | );
209 |
210 | test!(
211 | Default::default(),
212 | |_| transform_visitor(Config {
213 | display_name: true,
214 | base_path: "/".to_owned()
215 | }),
216 | adds_camel_case_variable_name_with_display_name,
217 | r#"import {createVar} from "css-variable";
218 | const camelCase = createVar();"#
219 | );
220 |
221 | test!(
222 | Default::default(),
223 | |_| transform_visitor(Config {
224 | display_name: true,
225 | base_path: "/".to_owned()
226 | }),
227 | adds_variable_name_with_display_name,
228 | r#"import {createVar} from "css-variable";
229 | const primary = createVar();
230 | const theme = {
231 | colors: {
232 | primary: createVar(),
233 | secondary: {
234 | inner: createVar()
235 | }
236 | }
237 | };"#
238 | );
239 | }
240 |
--------------------------------------------------------------------------------
/swc/transform/tests/__swc_snapshots__/src/lib.rs/adds_camel_case_variable_name_with_display_name.js:
--------------------------------------------------------------------------------
1 | import { createVar } from "css-variable";
2 | const camelCase = createVar("camelCase--hashed0");
3 |
--------------------------------------------------------------------------------
/swc/transform/tests/__swc_snapshots__/src/lib.rs/adds_multiple_variable_names.js:
--------------------------------------------------------------------------------
1 | import { createVar } from "css-variable";
2 | createVar("hashed0");
3 | createVar("hashed1");
4 | createVar("hashed2");
5 |
--------------------------------------------------------------------------------
/swc/transform/tests/__swc_snapshots__/src/lib.rs/adds_variable_name.js:
--------------------------------------------------------------------------------
1 | import { createVar } from "css-variable";
2 | createVar("hashed0");
3 |
--------------------------------------------------------------------------------
/swc/transform/tests/__swc_snapshots__/src/lib.rs/adds_variable_name_for_renamed.js:
--------------------------------------------------------------------------------
1 | import { createVar as create } from "css-variable";
2 | create("hashed0", "hello world");
3 |
--------------------------------------------------------------------------------
/swc/transform/tests/__swc_snapshots__/src/lib.rs/adds_variable_name_with_display_name.js:
--------------------------------------------------------------------------------
1 | import { createVar } from "css-variable";
2 | const primary = createVar("primary--hashed0");
3 | const theme = {
4 | colors: {
5 | primary: createVar("primary--colors--theme--hashed1"),
6 | secondary: {
7 | inner: createVar("inner--secondary--colors--theme--hashed2"),
8 | },
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/swc/transform/tests/__swc_snapshots__/src/lib.rs/adds_variable_name_with_value.js:
--------------------------------------------------------------------------------
1 | import { createVar } from "css-variable";
2 | createVar("hashed0", {
3 | value: '0px'
4 | });
5 |
--------------------------------------------------------------------------------
/swc/transform/tests/__swc_snapshots__/src/lib.rs/ignores_unknwon_modules.js:
--------------------------------------------------------------------------------
1 | import { createVar } from "unknown";
2 | createVar();
3 |
--------------------------------------------------------------------------------
/test/__snapshots__/babel.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`development transform CSSVariable 1`] = `
4 | "import { CSSVariable } from "css-variable";
5 | const primary = /*@__PURE__*/new CSSVariable("primary--mobtag0");
6 | const secondary = /*@__PURE__*/new CSSVariable("secondary--mobtag1", {
7 | value: '#fff'
8 | });
9 | const theme = {
10 | colors: {
11 | primary: /*@__PURE__*/new CSSVariable("primary--mobtag2")
12 | }
13 | };
14 | const generated = allColors.map(color => /*@__PURE__*/new CSSVariable("mobtag3", color));
15 | const generatedWithFallback = allColors.map(color => /*@__PURE__*/new CSSVariable("mobtag4", color, {
16 | value: '#000'
17 | }));"
18 | `;
19 |
20 | exports[`development transform createVar 1`] = `
21 | "import { createVar } from "css-variable";
22 | const primary = /*@__PURE__*/createVar("primary--1c6m1ot0");
23 | const secondary = /*@__PURE__*/createVar("secondary--1c6m1ot1", {
24 | value: '#fff'
25 | });
26 | const theme = {
27 | colors: {
28 | primary: /*@__PURE__*/createVar("primary--1c6m1ot2")
29 | }
30 | };
31 | const generated = allColors.map(color => /*@__PURE__*/createVar("1c6m1ot3", color));
32 | const generatedWithFallback = allColors.map(color => /*@__PURE__*/createVar("1c6m1ot4", color, {
33 | value: '#000'
34 | }));"
35 | `;
36 |
37 | exports[`development transform renamed 1`] = `
38 | "import { CSSVariable as CSSVar, createVar as createVariable } from "css-variable";
39 | const primary = /*@__PURE__*/new CSSVar("primary--1ynmbls0");
40 | const secondary = /*@__PURE__*/createVariable("secondary--1ynmbls1");"
41 | `;
42 |
43 | exports[`production transform CSSVariable 1`] = `
44 | "import { CSSVariable } from "css-variable";
45 | const primary = /*@__PURE__*/new CSSVariable("mobtag0");
46 | const secondary = /*@__PURE__*/new CSSVariable("mobtag1", {
47 | value: '#fff'
48 | });
49 | const theme = {
50 | colors: {
51 | primary: /*@__PURE__*/new CSSVariable("mobtag2")
52 | }
53 | };
54 | const generated = allColors.map(color => /*@__PURE__*/new CSSVariable("mobtag3", color));
55 | const generatedWithFallback = allColors.map(color => /*@__PURE__*/new CSSVariable("mobtag4", color, {
56 | value: '#000'
57 | }));"
58 | `;
59 |
60 | exports[`production transform createVar 1`] = `
61 | "import { createVar } from "css-variable";
62 | const primary = /*@__PURE__*/createVar("1c6m1ot0");
63 | const secondary = /*@__PURE__*/createVar("1c6m1ot1", {
64 | value: '#fff'
65 | });
66 | const theme = {
67 | colors: {
68 | primary: /*@__PURE__*/createVar("1c6m1ot2")
69 | }
70 | };
71 | const generated = allColors.map(color => /*@__PURE__*/createVar("1c6m1ot3", color));
72 | const generatedWithFallback = allColors.map(color => /*@__PURE__*/createVar("1c6m1ot4", color, {
73 | value: '#000'
74 | }));"
75 | `;
76 |
77 | exports[`production transform renamed 1`] = `
78 | "import { CSSVariable as CSSVar, createVar as createVariable } from "css-variable";
79 | const primary = /*@__PURE__*/new CSSVar("1ynmbls0");
80 | const secondary = /*@__PURE__*/createVariable("1ynmbls1");"
81 | `;
82 |
83 | exports[`production transform with displayName CSSVariable 1`] = `
84 | "import { CSSVariable } from "css-variable";
85 | const primary = /*@__PURE__*/new CSSVariable("primary--mobtag0");
86 | const secondary = /*@__PURE__*/new CSSVariable("secondary--mobtag1", {
87 | value: '#fff'
88 | });
89 | const theme = {
90 | colors: {
91 | primary: /*@__PURE__*/new CSSVariable("primary--mobtag2")
92 | }
93 | };
94 | const generated = allColors.map(color => /*@__PURE__*/new CSSVariable("mobtag3", color));
95 | const generatedWithFallback = allColors.map(color => /*@__PURE__*/new CSSVariable("mobtag4", color, {
96 | value: '#000'
97 | }));"
98 | `;
99 |
100 | exports[`production transform with displayName createVar 1`] = `
101 | "import { createVar } from "css-variable";
102 | const primary = /*@__PURE__*/createVar("primary--1c6m1ot0");
103 | const secondary = /*@__PURE__*/createVar("secondary--1c6m1ot1", {
104 | value: '#fff'
105 | });
106 | const theme = {
107 | colors: {
108 | primary: /*@__PURE__*/createVar("primary--1c6m1ot2")
109 | }
110 | };
111 | const generated = allColors.map(color => /*@__PURE__*/createVar("1c6m1ot3", color));
112 | const generatedWithFallback = allColors.map(color => /*@__PURE__*/createVar("1c6m1ot4", color, {
113 | value: '#000'
114 | }));"
115 | `;
116 |
117 | exports[`production transform with displayName renamed 1`] = `
118 | "import { CSSVariable as CSSVar, createVar as createVariable } from "css-variable";
119 | const primary = /*@__PURE__*/new CSSVar("primary--1ynmbls0");
120 | const secondary = /*@__PURE__*/createVariable("secondary--1ynmbls1");"
121 | `;
122 |
--------------------------------------------------------------------------------
/test/babel.test.js:
--------------------------------------------------------------------------------
1 | const transformFileSync = require("@babel/core").transformFileSync;
2 | const path = require("path");
3 | const plugin = require("../babel");
4 |
5 | describe("production transform", () => {
6 | it("CSSVariable", () => {
7 | const { code } = transformFileSync(
8 | path.join(__dirname, "fixtures/CSSVariable.js"),
9 | {
10 | plugins: [[plugin]],
11 | babelrc: false,
12 | }
13 | );
14 | expect(code).toMatchSnapshot();
15 | });
16 | it("createVar", () => {
17 | const { code } = transformFileSync(
18 | path.join(__dirname, "fixtures/createVar.js"),
19 | {
20 | plugins: [[plugin]],
21 | babelrc: false,
22 | }
23 | );
24 | expect(code).toMatchSnapshot();
25 | });
26 | it("renamed", () => {
27 | const { code } = transformFileSync(
28 | path.join(__dirname, "fixtures/renamed.js"),
29 | {
30 | plugins: [[plugin]],
31 | babelrc: false,
32 | }
33 | );
34 | expect(code).toMatchSnapshot();
35 | });
36 | });
37 |
38 | describe("development transform", () => {
39 | it("CSSVariable", () => {
40 | const { code } = transformFileSync(
41 | path.join(__dirname, "fixtures/CSSVariable.js"),
42 | {
43 | plugins: [[plugin]],
44 | babelrc: false,
45 | envName: "development"
46 | }
47 | );
48 | expect(code).toMatchSnapshot();
49 | });
50 | it("createVar", () => {
51 | const { code } = transformFileSync(
52 | path.join(__dirname, "fixtures/createVar.js"),
53 | {
54 | plugins: [[plugin]],
55 | babelrc: false,
56 | envName: "development"
57 | }
58 | );
59 | expect(code).toMatchSnapshot();
60 | });
61 | it("renamed", () => {
62 | const { code } = transformFileSync(
63 | path.join(__dirname, "fixtures/renamed.js"),
64 | {
65 | plugins: [[plugin]],
66 | babelrc: false,
67 | envName: "development"
68 | }
69 | );
70 | expect(code).toMatchSnapshot();
71 | });
72 | });
73 |
74 | describe("production transform with displayName", () => {
75 | it("CSSVariable", () => {
76 | const { code } = transformFileSync(
77 | path.join(__dirname, "fixtures/CSSVariable.js"),
78 | {
79 | plugins: [[plugin, { displayName: true }]],
80 | babelrc: false,
81 | }
82 | );
83 | expect(code).toMatchSnapshot();
84 | });
85 | it("createVar", () => {
86 | const { code } = transformFileSync(
87 | path.join(__dirname, "fixtures/createVar.js"),
88 | {
89 | plugins: [[plugin, { displayName: true }]],
90 | babelrc: false,
91 | }
92 | );
93 | expect(code).toMatchSnapshot();
94 | });
95 | it("renamed", () => {
96 | const { code } = transformFileSync(
97 | path.join(__dirname, "fixtures/renamed.js"),
98 | {
99 | plugins: [[plugin, { displayName: true }]],
100 | babelrc: false,
101 | }
102 | );
103 | expect(code).toMatchSnapshot();
104 | });
105 | });
--------------------------------------------------------------------------------
/test/examples.js:
--------------------------------------------------------------------------------
1 | /// @ts-check
2 | const path = require("path");
3 | const child_process = require("child_process");
4 | const assert = require("assert");
5 | let port = 47841;
6 | let runningChildren = new Set();
7 |
8 | runTest().then(
9 | () => {
10 | console.log("\n\n✅ Next integration tests passed");
11 | process.exit(0);
12 | },
13 | (e) => {
14 | console.error("🤷♂️ Test failed because of ", e);
15 | process.exit(1);
16 | }
17 | );
18 |
19 | async function runTest() {
20 | console.log("📦 install puppeteer");
21 | await spawnAsync("npm", ["install"], { cwd: __dirname, stdio: "inherit" }).promise;
22 | console.log("🚀 test next <-> styled-component integration");
23 | await launchExample(path.resolve(__dirname, "../examples/styled-components"));
24 | }
25 |
26 | /** @param {string} url */
27 | async function testExample(url) {
28 |
29 | console.log("💻 start browser and open nextjs app");
30 | const puppeteer = require('puppeteer');
31 | const browser = await puppeteer.launch();
32 | const page = await browser.newPage();
33 | await page.goto(url, {
34 | waitUntil: 'networkidle2',
35 | });
36 | const {fontSize,color} = await page.evaluate(() => {
37 | const styles = window.getComputedStyle(document.querySelector("h1"));
38 | return {
39 | fontSize: styles.fontSize,
40 | color: styles.color,
41 | };
42 | });
43 |
44 | assert(fontSize, '12px');
45 | assert(color, 'rgb(255, 165, 0)');
46 |
47 | console.log("✅ fontSize and color match");
48 |
49 | await browser.close();
50 | }
51 |
52 | /** @param {string} cwd */
53 | async function launchExample(cwd) {
54 | const testPort = port++
55 | console.log(`🧹 remove ${path.join(cwd, 'node_modules')}`);
56 | await removeDir(path.join(cwd, '.next'));
57 | await removeDir(path.join(cwd, 'node_modules'));
58 | await removeDir(path.join(cwd, '.linaria-cache'));
59 | console.log("📦 install example dependencies");
60 | await spawnAsync("npm", ["install"], { cwd, stdio: "inherit" }).promise;
61 | console.log("🚀 build & launch nextjs");
62 | await spawnAsync("npm", ["run", "build"], { cwd, stdio: "inherit" }).promise;
63 | const {child: server, promise: serverClosed} = spawnAsync("npm", ["start", "--", "-p", String(testPort)], { cwd, stdio: "inherit" });
64 | await new Promise((resolve) => setTimeout(resolve, 500));
65 | await Promise.race([
66 | testExample(`http://localhost:${testPort}`),
67 | serverClosed
68 | ]);
69 | server.kill();
70 | }
71 |
72 | function removeDir(directory) {
73 | return new Promise((resolve) => {
74 | require("rimraf")(directory, () => {
75 | resolve(true);
76 | });
77 | });
78 | }
79 |
80 | function spawnAsync(command, args, options) {
81 | const child = child_process.spawn(command, args, options);
82 | runningChildren.add(child);
83 | return {child, promise: new Promise((resolve, reject) => {
84 | child.on("close", (code) => {
85 | runningChildren.delete(child);
86 | if (code) {
87 | reject(new Error(`${command} failed - exit code: ${code}`));
88 | } else {
89 | resolve();
90 | }
91 | });
92 | })};
93 | }
94 |
95 | process.stdin.resume();
96 | function exitHandler(exitCode) {
97 | Array.from(runningChildren).forEach((child) => {
98 | child.kill();
99 | });
100 | process.exit(exitCode || 0);
101 | }
102 | process.on('exit', exitHandler.bind(null));
103 | process.on('SIGINT', exitHandler.bind(null));
104 | process.on('SIGUSR1', exitHandler.bind(null));
105 | process.on('SIGUSR2', exitHandler.bind(null));
106 | process.on('uncaughtException', exitHandler.bind(null));
--------------------------------------------------------------------------------
/test/fixtures/CSSVariable.js:
--------------------------------------------------------------------------------
1 | import { CSSVariable } from "css-variable";
2 |
3 | const primary = new CSSVariable();
4 | const secondary = new CSSVariable({ value: '#fff' });
5 |
6 | const theme = {
7 | colors: {
8 | primary: new CSSVariable()
9 | }
10 | };
11 |
12 | const generated = allColors.map((color) => new CSSVariable(color));
13 |
14 | const generatedWithFallback = allColors.map((color) => new CSSVariable(color, { value: '#000' }));
15 |
--------------------------------------------------------------------------------
/test/fixtures/createVar.js:
--------------------------------------------------------------------------------
1 | import { createVar } from "css-variable";
2 |
3 | const primary = createVar();
4 | const secondary = createVar({ value: '#fff' });
5 |
6 | const theme = {
7 | colors: {
8 | primary: createVar()
9 | }
10 | };
11 |
12 | const generated = allColors.map((color) => createVar(color));
13 |
14 | const generatedWithFallback = allColors.map((color) => createVar(color, { value: '#000' }));
15 |
--------------------------------------------------------------------------------
/test/fixtures/renamed.js:
--------------------------------------------------------------------------------
1 | import { CSSVariable as CSSVar, createVar as createVariable } from "css-variable";
2 |
3 | const primary = new CSSVar();
4 | const secondary = createVariable();
--------------------------------------------------------------------------------
/test/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "test": "node ./examples.js"
7 | },
8 | "dependencies": {
9 | "puppeteer": "^10.2.0",
10 | "rimraf": "3.0.2"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/test/swc/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | rootDir: __dirname,
3 | moduleNameMapper: {
4 | "css-variable$": "../../",
5 | },
6 | transform: {
7 | "^.+\\.(t|j)sx?$": [
8 | "@swc/jest",
9 | {
10 | jsc: {
11 | experimental: {
12 | plugins: [
13 | [
14 | require.resolve(
15 | "../../swc/target/wasm32-wasip1/release/swc_plugin_css_variable.wasm"
16 | ),
17 | {
18 | basePath: __dirname,
19 | displayName: true,
20 | },
21 | ],
22 | ],
23 | },
24 | },
25 | },
26 | ],
27 | },
28 | };
29 |
--------------------------------------------------------------------------------
/test/swc/swc.test.js:
--------------------------------------------------------------------------------
1 | import {createVar} from "css-variable";
2 |
3 | describe("createVar", () => {
4 | it("generates a variable name with swc plugin", () => {
5 | const foo = createVar();
6 | const bar = createVar();
7 | const baz = createVar();
8 | expect(foo.name).toMatchInlineSnapshot(`"--foo--2hzhhy0"`);
9 | expect(bar.name).toMatchInlineSnapshot( `"--bar--2hzhhy1"`);
10 | expect(baz.name).toMatchInlineSnapshot( `"--baz--2hzhhy2"`);
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/test/without-babel.test.js:
--------------------------------------------------------------------------------
1 | const {createVar} = require("../");
2 |
3 | describe("createVar", () => {
4 | it("generates a variable name automatically", () => {
5 | const foo = createVar();
6 | const bar = createVar();
7 | const baz = createVar();
8 | expect(foo.name).toMatch("--17179149");
9 | expect(bar.name).toMatch("--1717914a");
10 | expect(baz.name).toMatch("--1717914b");
11 | });
12 |
13 | it("allows to define a fallback variable", () => {
14 | const foo = createVar({value: "red"});
15 | expect(foo.val).toMatch("var(--1717914c, red)");
16 | });
17 |
18 | });
19 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */
4 |
5 | /* Projects */
6 | // "incremental": true, /* Enable incremental compilation */
7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8 | // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12 |
13 | /* Language and Environment */
14 | "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16 | // "jsx": "preserve", /* Specify what JSX code is generated. */
17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
22 | // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25 |
26 | /* Modules */
27 | "module": "commonjs", /* Specify what module code is generated. */
28 | // "rootDir": "./", /* Specify the root folder within your source files. */
29 | // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
30 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
31 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
32 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
33 | // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
34 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */
35 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
36 | // "resolveJsonModule": true, /* Enable importing .json files */
37 | // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */
38 |
39 | /* JavaScript Support */
40 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
41 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
42 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
43 |
44 | /* Emit */
45 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
46 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */
47 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
48 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
49 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
50 | // "outDir": "./", /* Specify an output folder for all emitted files. */
51 | // "removeComments": true, /* Disable emitting comments. */
52 | // "noEmit": true, /* Disable emitting files from a compilation. */
53 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
54 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
55 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
56 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
58 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
59 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
60 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
61 | // "newLine": "crlf", /* Set the newline character for emitting files. */
62 | // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
63 | // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
64 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
65 | // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
66 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
67 |
68 | /* Interop Constraints */
69 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
70 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
71 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
72 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
73 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
74 |
75 | /* Type Checking */
76 | "strict": true, /* Enable all strict type-checking options. */
77 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
78 | // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
79 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
80 | // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
81 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
82 | // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
83 | // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
84 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
85 | // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
86 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
87 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
88 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
89 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
90 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
91 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
92 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
93 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
94 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
95 |
96 | /* Completeness */
97 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
98 | "skipLibCheck": true /* Skip type checking all .d.ts files. */
99 | },
100 | }
--------------------------------------------------------------------------------