Skip to content

Major bundler refactor [WIP]#523

Open
Brentlok wants to merge 9 commits intomainfrom
major-refactor
Open

Major bundler refactor [WIP]#523
Brentlok wants to merge 9 commits intomainfrom
major-refactor

Conversation

@Brentlok
Copy link
Copy Markdown
Contributor

@Brentlok Brentlok commented May 7, 2026

Summary by CodeRabbit

  • New Features

    • Improved bundler support for Metro and Vite with automatic Tailwind CSS compilation, platform-aware CSS output, and generated theme artifacts.
    • useCSSVariable hook extended to accept arrays plus a new helper to resolve CSS variables.
  • Refactor

    • Internal bundler and adapter reorganization for smoother build/runtime integration and more consistent theme handling.
  • Chores

    • Jest config mapping for local imports and added package documentation.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e92c1adf-ae3a-47ec-aa51-090053fbe5e4

📥 Commits

Reviewing files that changed from the base of the PR and between 52ba715 and f823b7c.

📒 Files selected for processing (4)
  • context.md
  • packages/uniwind/src/bundler/adapters/metro/metro.ts
  • packages/uniwind/src/bundler/artifacts/css/themes.ts
  • packages/uniwind/src/bundler/config.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/uniwind/src/bundler/artifacts/css/themes.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/uniwind/src/bundler/adapters/metro/metro.ts
  • packages/uniwind/src/bundler/config.ts

📝 Walkthrough

Walkthrough

Refactors Uniwind’s bundler: central UniwindBundlerConfig, platform Tailwind→CSS compilers, Metro/Vite adapter entries under bundler/adapters, moved constants/types to src/common, path/alias and Jest mappings, widespread import/type-only cleanup, and test/build wiring updates.

Changes

Bundler Architecture & Configuration Refactor

Layer / File(s) Summary
Types & Constants
src/common/consts.ts, src/bundler/types.ts, src/core/types.ts, src/types.ts
Move style enums to src/common/consts.ts; add bundler types in src/bundler/types.ts; consolidate core type exports.
Build Configuration & Paths
build.config.ts, tsconfig.json, jest.config.native.js, jest.config.web.js
Add srcPath helper, new adapter-based rollup/mkdist entries (including metro transformer), emit to dist/metro & dist/vite, add @/bundler alias, set rootDir: src and paths, and map ^@/(.*)$<rootDir>/src/$1 for Jest.
Bundler Configuration Class
src/bundler/config.ts
Add UniwindBundlerConfig with fromMetroConfig/fromViteConfig, getters (cssPath, themes, cssVisitor, polyfills, stringifiedThemes), toMetroConfig(), and generateArtifacts(cssArtifactPath).
CSS Compilation Pipeline
src/bundler/css-compiler/*, src/bundler/artifacts/css/index.ts, src/bundler/artifacts/dts.ts
Add compileTailwind, compileCSS, compileWebCSS, compileNativeCSS; change buildCSS to accept cssFilePath; make DTS module identity static (declare module 'uniwind').
CSS Processor & Visitor Reorg
src/bundler/css-processor/*, src/bundler/css-visitor/*
Re-home shared consts to @/common/consts; convert many imports to import type; add a css-processor barrel and update serialize logger path.
Metro Adapter & Transformer
src/bundler/adapters/metro/*
Implement Metro adapter using UniwindBundlerConfig; add transformer that selects metro worker, intercepts injected web module and CSS entry, compiles/injects platform code, emits uniwind.css, delegates to worker, and adjusts cache flags.
Vite Adapter Refactor
src/bundler/adapters/vite/vite.ts
Vite plugin now builds a bundlerConfig via fromViteConfig, uses cssVisitor/stringifiedThemes, and delegates artifact generation to bundlerConfig.generateArtifacts.
Components & Hooks: Type-only Imports
src/components/*, src/hooks/*, src/hoc/*, src/core/*
Convert many prop/type imports to import type and update imports to use @/common/consts for StyleDependency/ColorScheme/Orientation.
Tests / Setup & Cleanup
tests/*, src/metro/*
Tests updated to use bundler pipeline; remove or stop re-exporting legacy src/metro/* modules and barrels; add internal docs and lint rule.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • uni-stack/uniwind#521: Related — useCSSVariable/getCSSVariable changes overlap with this PR’s hook updates.
  • uni-stack/uniwind#485: Related — Metro transformer CSS-entry handling overlaps with the new transformer logic.
  • uni-stack/uniwind#483: Related — Metro transformer CSS detection/transform logic changes are similar to this migration.

Suggested reviewers

  • jpudysz

"🐰 I hopped through code and thread,
Bundler maps and types ahead,
Themes compiled, adapters moved,
Imports cleaned and paths improved —
A little hop for devs well-fed."

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch major-refactor

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/uniwind/src/hooks/useCSSVariable/useCSSVariable.ts (1)

77-85: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Resync immediately when the Uniwind context changes.

Lines 77-85 resubscribe on uniwindContext changes but never recompute the current value. After a provider swap, this hook keeps the old context's variable values until Theme or Variables emits again.

Suggested fix
     useLayoutEffect(() => {
         const updateValue = () => setValue(getCSSVariable(nameRef.current, uniwindContext))
+        updateValue()
         const dispose = UniwindListener.subscribe(
             updateValue,
             [StyleDependency.Theme, StyleDependency.Variables],
         )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/uniwind/src/hooks/useCSSVariable/useCSSVariable.ts` around lines 77
- 85, The hook currently resubscribes on uniwindContext change but doesn't
recompute the variable value immediately; inside the useLayoutEffect in
useCSSVariable, call updateValue() (which uses getCSSVariable(nameRef.current,
uniwindContext) and setValue) right before creating the subscription (or
immediately after) so the value reflects the new uniwindContext immediately,
then create the UniwindListener.subscribe(...) and return dispose as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/uniwind/src/bundler/adapters/metro/transformer.ts`:
- Around line 33-35: The path comparisons in the isCss check and the
metro-injected.js check are brittle across platforms; normalize and resolve both
sides before comparing. Concretely, compute normalized absolute paths (e.g.,
cssEntryPath = path.normalize(path.resolve(process.cwd(),
config.uniwind.cssEntryFile)) and normalizedFilePath =
path.normalize(path.resolve(projectRoot, filePath))) and use strict equality
(cssEntryPath === normalizedFilePath) instead of joining then comparing; for the
injected file replace the endsWith('/components/web/metro-injected.js') test
with the same normalized-resolved comparison against
path.normalize(path.resolve(projectRoot, 'components', 'web',
'metro-injected.js')) so matching works on Windows and in monorepos while
keeping the options.type !== 'asset' check.

In `@packages/uniwind/src/bundler/adapters/vite/vite.ts`:
- Around line 81-84: The injected Uniwind.__reinit call is concatenated directly
to the transformed module text (variable code), which can break when the
original ends with comments or relies on ASI; update the return in the
normalizedId branch so you add an explicit statement boundary before calling
Uniwind.__reinit (e.g., prepend a semicolon or newline+semicolon to the injected
snippet) when building the code string that uses
bundlerConfig.stringifiedThemes, ensuring the injected call is always a separate
statement.

In `@packages/uniwind/src/bundler/config.ts`:
- Around line 67-69: The stringifiedThemes getter emits raw single-quoted theme
names which can break when a theme contains quotes or backslashes; replace its
manual quoting with a proper JSON serialization by returning
JSON.stringify(this.themes) from the stringifiedThemes getter (i.e., update the
stringifiedThemes getter that references this.themes to use JSON.stringify to
produce a safe JS array literal).
- Around line 45-47: The cssPath getter currently uses process.cwd() which
breaks monorepos; update UniwindBundlerConfig to accept and store an explicit
project root (e.g., projectRoot or root) via its constructor or factory, replace
process.cwd() in the cssPath getter with that stored property so cssPath returns
path.join(this.projectRoot, this.config.cssEntryFile), and ensure callers that
construct UniwindBundlerConfig are updated to pass the correct app root.

In `@packages/uniwind/src/bundler/css-compiler/compileNativeCSS.ts`:
- Around line 24-26: The code that builds serializedScopedVars interpolates
scopedVarsName directly into a JS string literal, which breaks/permits injection
if the key contains " or \; update the serialization in compileNativeCSS.ts so
scopedVarsName is escaped before embedding (e.g., use
JSON.stringify(scopedVarsName) or an escape helper) when constructing
serializedScopedVars, keeping the same output shape (`"name": ({ ... }),`) and
preserving the trailing comma; ensure you apply this change where
serializedScopedVars is computed so both quotes and backslashes are properly
escaped.

In `@packages/uniwind/src/bundler/css-compiler/compileTailwind.ts`:
- Line 8: The compileTailwind code currently uses blocking I/O via
fs.readFileSync when loading bundlerConfig.cssPath; change this to non-blocking
fs.promises.readFile and await the result (e.g., await
fs.promises.readFile(bundlerConfig.cssPath, 'utf-8')) so the function does not
block the event loop—ensure the surrounding function (e.g., compileTailwind) is
async or already awaits this call and replace the sync variable assignment
(const css = fs.readFileSync(...)) with the awaited promise-based read.

In `@packages/uniwind/tsconfig.json`:
- Around line 13-19: tsconfig.json contains broken path aliases "@/metro" and
"@/utils/*" that point to non-existent targets; update the "paths" section so
"@/metro" either points to the actual metro adapter entry (replace the current
target) or remove the "@/metro" alias and import via "@/bundler/adapters/metro",
and either remove or correct the "@/utils/*" alias to point to a real utils
directory (or create a re-export shim if you prefer keeping the alias); ensure
the "@/bundler/*" mapping remains correct and run type-checking to confirm the
fixes.

---

Outside diff comments:
In `@packages/uniwind/src/hooks/useCSSVariable/useCSSVariable.ts`:
- Around line 77-85: The hook currently resubscribes on uniwindContext change
but doesn't recompute the variable value immediately; inside the useLayoutEffect
in useCSSVariable, call updateValue() (which uses
getCSSVariable(nameRef.current, uniwindContext) and setValue) right before
creating the subscription (or immediately after) so the value reflects the new
uniwindContext immediately, then create the UniwindListener.subscribe(...) and
return dispose as before.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a1fba412-f33d-4235-8134-8f7501a66b47

📥 Commits

Reviewing files that changed from the base of the PR and between a2406b8 and d7e458f.

📒 Files selected for processing (69)
  • packages/uniwind/build.config.ts
  • packages/uniwind/jest.config.native.js
  • packages/uniwind/jest.config.web.js
  • packages/uniwind/src/bundler/adapters/metro/index.d.ts
  • packages/uniwind/src/bundler/adapters/metro/index.ts
  • packages/uniwind/src/bundler/adapters/metro/metro.ts
  • packages/uniwind/src/bundler/adapters/metro/patches.ts
  • packages/uniwind/src/bundler/adapters/metro/resolvers.ts
  • packages/uniwind/src/bundler/adapters/metro/transformer.ts
  • packages/uniwind/src/bundler/adapters/vite/index.d.ts
  • packages/uniwind/src/bundler/adapters/vite/index.ts
  • packages/uniwind/src/bundler/adapters/vite/vite.ts
  • packages/uniwind/src/bundler/artifacts/css/extraUtilities.ts
  • packages/uniwind/src/bundler/artifacts/css/index.ts
  • packages/uniwind/src/bundler/artifacts/css/insets.ts
  • packages/uniwind/src/bundler/artifacts/css/overwrite.ts
  • packages/uniwind/src/bundler/artifacts/css/themes.ts
  • packages/uniwind/src/bundler/artifacts/css/variants.ts
  • packages/uniwind/src/bundler/artifacts/dts.ts
  • packages/uniwind/src/bundler/config.ts
  • packages/uniwind/src/bundler/css-compiler/compileCSS.ts
  • packages/uniwind/src/bundler/css-compiler/compileNativeCSS.ts
  • packages/uniwind/src/bundler/css-compiler/compileTailwind.ts
  • packages/uniwind/src/bundler/css-compiler/compileWebCSS.ts
  • packages/uniwind/src/bundler/css-compiler/index.ts
  • packages/uniwind/src/bundler/css-processor/addMetaToStylesTemplate.ts
  • packages/uniwind/src/bundler/css-processor/color.ts
  • packages/uniwind/src/bundler/css-processor/css.ts
  • packages/uniwind/src/bundler/css-processor/functions.ts
  • packages/uniwind/src/bundler/css-processor/index.ts
  • packages/uniwind/src/bundler/css-processor/mq.ts
  • packages/uniwind/src/bundler/css-processor/processor.ts
  • packages/uniwind/src/bundler/css-processor/rn.ts
  • packages/uniwind/src/bundler/css-processor/serialize.ts
  • packages/uniwind/src/bundler/css-processor/types.ts
  • packages/uniwind/src/bundler/css-processor/units.ts
  • packages/uniwind/src/bundler/css-processor/utils.ts
  • packages/uniwind/src/bundler/css-processor/var.ts
  • packages/uniwind/src/bundler/css-visitor/function-visitor.ts
  • packages/uniwind/src/bundler/css-visitor/index.ts
  • packages/uniwind/src/bundler/css-visitor/rule-visitor.ts
  • packages/uniwind/src/bundler/css-visitor/visitor.ts
  • packages/uniwind/src/bundler/logger.ts
  • packages/uniwind/src/bundler/types.ts
  • packages/uniwind/src/common/consts.ts
  • packages/uniwind/src/components/web/rnw.ts
  • packages/uniwind/src/core/config/config.common.ts
  • packages/uniwind/src/core/config/config.native.ts
  • packages/uniwind/src/core/config/config.ts
  • packages/uniwind/src/core/listener.ts
  • packages/uniwind/src/core/native/runtime.ts
  • packages/uniwind/src/core/native/store.ts
  • packages/uniwind/src/core/types.ts
  • packages/uniwind/src/core/web/cssListener.ts
  • packages/uniwind/src/hoc/withUniwind.native.tsx
  • packages/uniwind/src/hooks/useCSSVariable/useCSSVariable.ts
  • packages/uniwind/src/hooks/useUniwind.ts
  • packages/uniwind/src/index.ts
  • packages/uniwind/src/metro/compileVirtual.ts
  • packages/uniwind/src/metro/index.ts
  • packages/uniwind/src/metro/injectThemes.ts
  • packages/uniwind/src/metro/metro-transformer.ts
  • packages/uniwind/src/metro/processor/index.ts
  • packages/uniwind/src/metro/utils/index.ts
  • packages/uniwind/src/types.ts
  • packages/uniwind/src/utils/stringifyThemes.ts
  • packages/uniwind/tests/e2e/global-setup.ts
  • packages/uniwind/tests/setup.native.ts
  • packages/uniwind/tsconfig.json
💤 Files with no reviewable changes (8)
  • packages/uniwind/src/metro/utils/index.ts
  • packages/uniwind/src/utils/stringifyThemes.ts
  • packages/uniwind/src/metro/injectThemes.ts
  • packages/uniwind/src/metro/processor/index.ts
  • packages/uniwind/src/metro/index.ts
  • packages/uniwind/src/types.ts
  • packages/uniwind/src/metro/compileVirtual.ts
  • packages/uniwind/src/metro/metro-transformer.ts

Comment thread packages/uniwind/src/bundler/adapters/metro/transformer.ts
Comment thread packages/uniwind/src/bundler/adapters/vite/vite.ts
Comment thread packages/uniwind/src/bundler/config.ts
Comment thread packages/uniwind/src/bundler/config.ts
Comment thread packages/uniwind/src/bundler/css-compiler/compileNativeCSS.ts
Comment thread packages/uniwind/src/bundler/css-compiler/compileTailwind.ts Outdated
Comment thread packages/uniwind/tsconfig.json
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (2)
packages/uniwind/src/bundler/adapters/metro/transformer.ts (1)

35-37: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Normalize/resolve paths before matching special files.

Current comparisons are brittle across Windows and some monorepo layouts, which can skip both CSS compilation and metro-injected.js handling.

Proposed fix
-    const isCss = options.type !== 'asset' && path.join(process.cwd(), config.uniwind.cssEntryFile) === path.join(projectRoot, filePath)
+    const normalizedFilePath = path.normalize(path.resolve(projectRoot, filePath))
+    const cssEntryPath = path.normalize(path.resolve(process.cwd(), config.uniwind.cssEntryFile))
+    const injectedPath = path.normalize(path.resolve(projectRoot, 'components', 'web', 'metro-injected.js'))
+    const isCss = options.type !== 'asset' && normalizedFilePath === cssEntryPath
 
-    if (filePath.endsWith('/components/web/metro-injected.js')) {
+    if (normalizedFilePath === injectedPath) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/uniwind/src/bundler/adapters/metro/transformer.ts` around lines 35 -
37, The path comparisons are brittle; normalize and resolve both sides before
matching: for the CSS check (isCss) resolve/normalize
config.uniwind.cssEntryFile against process.cwd() and resolve/normalize
projectRoot + filePath (or resolve filePath) before comparing, and for the
special file check resolve/normalize the target string (e.g.,
path.join('components','web','metro-injected.js')) and compare it against a
resolved/normalized filePath instead of using filePath.endsWith(...); update the
logic around the isCss computation and the if that references
'/components/web/metro-injected.js' to use these normalized/resolved paths so
comparisons work cross-platform and in monorepos.
packages/uniwind/src/bundler/css-compiler/compileNativeCSS.ts (1)

24-26: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Escape scopedVarsName before embedding generated JS.

scopedVarsName is interpolated raw into a quoted key, so keys containing " or \ can produce invalid/generated-injectable code.

Proposed fix
 const serializedScopedVars = Object.entries(scopedVars)
-    .map(([scopedVarsName, scopedVars]) => `"${scopedVarsName}": ({ ${scopedVars} }),`)
+    .map(([scopedVarsName, scopedVars]) => `${JSON.stringify(scopedVarsName)}: ({ ${scopedVars} }),`)
     .join('')
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/uniwind/src/bundler/css-compiler/compileNativeCSS.ts` around lines
24 - 26, The generated JS embeds scopedVarsName raw into a quoted key which can
break if the name contains `"` or `\`; update the serializedScopedVars
construction in compileNativeCSS.ts (the const serializedScopedVars) to escape
scopedVarsName before embedding (e.g., use JSON.stringify(scopedVarsName) or
explicitly replace `\` and `"` with `\\`/`\"`) so the produced key is a valid JS
string literal and cannot inject invalid code.
🧹 Nitpick comments (3)
context.md (2)

157-158: ⚡ Quick win

Consider varying sentence structure.

Two consecutive sentences begin with "Web wrappers", which slightly impacts readability.

✨ Suggested improvement
 - Web wrappers import from `react-native` as resolved by bundler aliases.
-- Web wrappers map `className` to RNW CSS style markers through `toRNWClassName`.
-- Web wrappers pass generated `dataSet` so data attribute variants can match.
+- The `className` prop is mapped to RNW CSS style markers through `toRNWClassName`.
+- Generated `dataSet` is passed so data attribute variants can match.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@context.md` around lines 157 - 158, Two consecutive sentences both starting
with "Web wrappers" reduce readability; rephrase one to vary sentence structure
and improve flow. For example, transform the first sentence that mentions
mapping into an active clause referencing the function name toRNWClassName
(e.g., "toRNWClassName maps className to RNW CSS style markers") and rework the
second to lead with the outcome or purpose mentioning dataSet (e.g., "They also
pass the generated dataSet so data attribute variants can match"), or combine
them into a single sentence that includes both toRNWClassName and dataSet for
clarity.

120-121: ⚡ Quick win

Consider varying sentence structure.

Three consecutive sentences begin with "Vite", which slightly impacts readability. Consider varying the structure for better flow.

✨ Suggested improvement
 - Vite aliases `react-native` to Uniwind web components, except imports from Uniwind internals resolve back to `react-native-web`.
-- Vite replaces RNW `createOrderedCSSStyleSheet` with Uniwind's ordered stylesheet implementation.
-- Vite uses Lightning CSS with `UniwindCSSVisitor`.
-- Vite generates artifacts on `buildStart` and `generateBundle`.
+- The RNW `createOrderedCSSStyleSheet` is replaced with Uniwind's ordered stylesheet implementation.
+- Lightning CSS is used with `UniwindCSSVisitor`.
+- Artifacts are generated on `buildStart` and `generateBundle`.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@context.md` around lines 120 - 121, The three consecutive sentences that
begin with "Vite" (the lines stating "Vite uses Lightning CSS with
`UniwindCSSVisitor`." and "Vite generates artifacts on `buildStart` and
`generateBundle`.") make the paragraph repetitive; rephrase one or two of them
to vary sentence openings and improve flow (for example, start one sentence with
the technology or a gerund/passive phrase like "Using Lightning CSS, Vite..." or
"Artifacts are generated during `buildStart` and `generateBundle`"), or combine
related ideas into a single sentence to avoid repeating the subject.
packages/uniwind/src/bundler/adapters/vite/vite.ts (1)

87-91: ⚡ Quick win

Avoid regenerating the same artifacts in both build hooks.

Vite calls buildStart during both serve and build, while output-generation hooks like generateBundle only run during build. With the current wiring, vite build will execute bundlerConfig.generateArtifacts(cssArtifactPath) twice for the same output. Prefer running it in buildStart only for serve and in generateBundle only for build, or guard it with a once-per-run flag. (vite.dev)

♻️ Possible adjustment
 export const uniwind = (config: UniwindConfig): Plugin => {
     const bundlerConfig = UniwindBundlerConfig.fromViteConfig(config)
+    let command: 'serve' | 'build'

     return {
         name: 'uniwind',
         enforce: 'pre',
+        config: (_, env) => {
+            command = env.command
+            return {
+                css: {
+                    transformer: 'lightningcss',
+                    lightningcss: {
+                        visitor: bundlerConfig.cssVisitor,
+                    },
+                },
+                optimizeDeps: {
+                    exclude: ['uniwind', 'react-native'],
+                    esbuildOptions: {
+                        plugins: [{
+                            name: 'uniwind-esbuild-plugin',
+                            setup: build => {
+                                build.onResolve(
+                                    { filter: /^\.\/createOrderedCSSStyleSheet$/ },
+                                    args => {
+                                        if (normalizePath(args.importer).includes('react-native-web/dist/exports/StyleSheet')) {
+                                            return { path: styleSheetPath }
+                                        }
+                                    },
+                                )
+                            },
+                        }],
+                    },
+                },
+                resolve: {
+                    alias: [
+                        {
+                            find: /^react-native$/,
+                            replacement: componentPath,
+                            customResolver: {
+                                resolveId(_, importer) {
+                                    if (importer !== undefined && normalizePath(importer).includes('uniwind/dist')) {
+                                        return this.resolve('react-native-web')
+                                    }
+
+                                    return componentPath
+                                },
+                            },
+                        },
+                    ],
+                },
+            }
+        },
-        config: () => ({
-            css: {
-                transformer: 'lightningcss',
-                lightningcss: {
-                    visitor: bundlerConfig.cssVisitor,
-                },
-            },
-            optimizeDeps: {
-                exclude: ['uniwind', 'react-native'],
-                esbuildOptions: {
-                    plugins: [{
-                        name: 'uniwind-esbuild-plugin',
-                        setup: build => {
-                            build.onResolve(
-                                { filter: /^\.\/createOrderedCSSStyleSheet$/ },
-                                args => {
-                                    if (normalizePath(args.importer).includes('react-native-web/dist/exports/StyleSheet')) {
-                                        return { path: styleSheetPath }
-                                    }
-                                },
-                            )
-                        },
-                    }],
-                },
-            },
-            resolve: {
-                alias: [
-                    {
-                        find: /^react-native$/,
-                        replacement: componentPath,
-                        customResolver: {
-                            resolveId(_, importer) {
-                                if (importer !== undefined && normalizePath(importer).includes('uniwind/dist')) {
-                                    return this.resolve('react-native-web')
-                                }
-
-                                return componentPath
-                            },
-                        },
-                    },
-                ],
-            },
-        }),
         transform: (code, id) => {
             const normalizedId = normalizePath(id)

             if (normalizedId.includes('uniwind/dist') && normalizedId.includes('config/config.js')) {
                 return {
                     code: `${code}\n;Uniwind.__reinit(() => ({}), ${bundlerConfig.stringifiedThemes})`,
                 }
             }
         },
         buildStart: async () => {
-            await bundlerConfig.generateArtifacts(cssArtifactPath)
+            if (command === 'serve') {
+                await bundlerConfig.generateArtifacts(cssArtifactPath)
+            }
         },
         generateBundle: async () => {
-            await bundlerConfig.generateArtifacts(cssArtifactPath)
+            if (command === 'build') {
+                await bundlerConfig.generateArtifacts(cssArtifactPath)
+            }
         },
     }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/uniwind/src/bundler/adapters/vite/vite.ts` around lines 87 - 91, The
plugin currently calls bundlerConfig.generateArtifacts(cssArtifactPath) in both
buildStart and generateBundle causing duplicate work; modify the Vite hooks so
artifacts are generated only once per run by either 1) adding a module-scoped
boolean flag (e.g., artifactsGenerated) that buildStart and generateBundle
check/set before calling bundlerConfig.generateArtifacts(cssArtifactPath), or 2)
moving the call to buildStart for dev/serve and to generateBundle only for
actual builds (use the presence of this.getWatchMode() or hook semantics to
distinguish serve vs build); update the buildStart and generateBundle handlers
(the functions named buildStart and generateBundle) accordingly to ensure a
single invocation per process.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@context.md`:
- Line 82: Update the phrasing in the documentation string containing
Uniwind.setTheme(theme | 'system') to hyphenate the compound adjective: change
"system adaptive light/dark" to "system-adaptive light/dark" so the description
reads that Uniwind.setTheme switches explicit themes or returns to
system-adaptive light/dark.
- Line 117: The phrase in the documentation for uniwind(config) uses "pre Vite
plugin" and should be hyphenated; update the text that says "`uniwind(config)`
returns a pre Vite plugin." to read "`uniwind(config)` returns a pre-Vite
plugin." ensuring the compound adjective "pre-Vite" is hyphenated wherever this
wording appears.
- Around line 129-130: Update the phrasing describing scoped CSS variables to
use correct compound modifier hyphenation: change the phrase "theme and platform
scoped variables" (in the description of scopedVars) to "theme- and
platform-scoped variables" so that "platform-scoped" is hyphenated and the
shared "scoped" modifier is applied correctly to both "theme" and "platform".

---

Duplicate comments:
In `@packages/uniwind/src/bundler/adapters/metro/transformer.ts`:
- Around line 35-37: The path comparisons are brittle; normalize and resolve
both sides before matching: for the CSS check (isCss) resolve/normalize
config.uniwind.cssEntryFile against process.cwd() and resolve/normalize
projectRoot + filePath (or resolve filePath) before comparing, and for the
special file check resolve/normalize the target string (e.g.,
path.join('components','web','metro-injected.js')) and compare it against a
resolved/normalized filePath instead of using filePath.endsWith(...); update the
logic around the isCss computation and the if that references
'/components/web/metro-injected.js' to use these normalized/resolved paths so
comparisons work cross-platform and in monorepos.

In `@packages/uniwind/src/bundler/css-compiler/compileNativeCSS.ts`:
- Around line 24-26: The generated JS embeds scopedVarsName raw into a quoted
key which can break if the name contains `"` or `\`; update the
serializedScopedVars construction in compileNativeCSS.ts (the const
serializedScopedVars) to escape scopedVarsName before embedding (e.g., use
JSON.stringify(scopedVarsName) or explicitly replace `\` and `"` with `\\`/`\"`)
so the produced key is a valid JS string literal and cannot inject invalid code.

---

Nitpick comments:
In `@context.md`:
- Around line 157-158: Two consecutive sentences both starting with "Web
wrappers" reduce readability; rephrase one to vary sentence structure and
improve flow. For example, transform the first sentence that mentions mapping
into an active clause referencing the function name toRNWClassName (e.g.,
"toRNWClassName maps className to RNW CSS style markers") and rework the second
to lead with the outcome or purpose mentioning dataSet (e.g., "They also pass
the generated dataSet so data attribute variants can match"), or combine them
into a single sentence that includes both toRNWClassName and dataSet for
clarity.
- Around line 120-121: The three consecutive sentences that begin with "Vite"
(the lines stating "Vite uses Lightning CSS with `UniwindCSSVisitor`." and "Vite
generates artifacts on `buildStart` and `generateBundle`.") make the paragraph
repetitive; rephrase one or two of them to vary sentence openings and improve
flow (for example, start one sentence with the technology or a gerund/passive
phrase like "Using Lightning CSS, Vite..." or "Artifacts are generated during
`buildStart` and `generateBundle`"), or combine related ideas into a single
sentence to avoid repeating the subject.

In `@packages/uniwind/src/bundler/adapters/vite/vite.ts`:
- Around line 87-91: The plugin currently calls
bundlerConfig.generateArtifacts(cssArtifactPath) in both buildStart and
generateBundle causing duplicate work; modify the Vite hooks so artifacts are
generated only once per run by either 1) adding a module-scoped boolean flag
(e.g., artifactsGenerated) that buildStart and generateBundle check/set before
calling bundlerConfig.generateArtifacts(cssArtifactPath), or 2) moving the call
to buildStart for dev/serve and to generateBundle only for actual builds (use
the presence of this.getWatchMode() or hook semantics to distinguish serve vs
build); update the buildStart and generateBundle handlers (the functions named
buildStart and generateBundle) accordingly to ensure a single invocation per
process.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f6a86f50-ca6f-4933-bcd7-4302fdb8f667

📥 Commits

Reviewing files that changed from the base of the PR and between d7e458f and 52ba715.

📒 Files selected for processing (83)
  • context.md
  • packages/uniwind/.oxlintrc.json
  • packages/uniwind/build.config.ts
  • packages/uniwind/src/bundler/adapters/metro/patches.ts
  • packages/uniwind/src/bundler/adapters/metro/resolvers.ts
  • packages/uniwind/src/bundler/adapters/metro/transformer.ts
  • packages/uniwind/src/bundler/adapters/vite/vite.ts
  • packages/uniwind/src/bundler/artifacts/css/extraUtilities.ts
  • packages/uniwind/src/bundler/css-compiler/compileCSS.ts
  • packages/uniwind/src/bundler/css-compiler/compileNativeCSS.ts
  • packages/uniwind/src/bundler/css-compiler/compileTailwind.ts
  • packages/uniwind/src/bundler/css-compiler/compileWebCSS.ts
  • packages/uniwind/src/bundler/css-processor/addMetaToStylesTemplate.ts
  • packages/uniwind/src/bundler/css-processor/color.ts
  • packages/uniwind/src/bundler/css-processor/css.ts
  • packages/uniwind/src/bundler/css-processor/functions.ts
  • packages/uniwind/src/bundler/css-processor/mq.ts
  • packages/uniwind/src/bundler/css-processor/processor.ts
  • packages/uniwind/src/bundler/css-processor/types.ts
  • packages/uniwind/src/bundler/css-processor/units.ts
  • packages/uniwind/src/bundler/css-processor/var.ts
  • packages/uniwind/src/bundler/css-visitor/function-visitor.ts
  • packages/uniwind/src/bundler/css-visitor/rule-visitor.ts
  • packages/uniwind/src/bundler/css-visitor/visitor.ts
  • packages/uniwind/src/components/ScopedTheme/ScopedTheme.native.tsx
  • packages/uniwind/src/components/native/ActivityIndicator.tsx
  • packages/uniwind/src/components/native/Button.tsx
  • packages/uniwind/src/components/native/FlatList.tsx
  • packages/uniwind/src/components/native/Image.tsx
  • packages/uniwind/src/components/native/ImageBackground.tsx
  • packages/uniwind/src/components/native/InputAccessoryView.tsx
  • packages/uniwind/src/components/native/KeyboardAvoidingView.tsx
  • packages/uniwind/src/components/native/Modal.tsx
  • packages/uniwind/src/components/native/Pressable.tsx
  • packages/uniwind/src/components/native/RefreshControl.tsx
  • packages/uniwind/src/components/native/SafeAreaView.tsx
  • packages/uniwind/src/components/native/ScrollView.tsx
  • packages/uniwind/src/components/native/SectionList.tsx
  • packages/uniwind/src/components/native/Switch.tsx
  • packages/uniwind/src/components/native/Text.tsx
  • packages/uniwind/src/components/native/TextInput.tsx
  • packages/uniwind/src/components/native/TouchableHighlight.tsx
  • packages/uniwind/src/components/native/TouchableNativeFeedback.tsx
  • packages/uniwind/src/components/native/TouchableOpacity.tsx
  • packages/uniwind/src/components/native/TouchableWithoutFeedback.tsx
  • packages/uniwind/src/components/native/View.tsx
  • packages/uniwind/src/components/native/VirtualizedList.tsx
  • packages/uniwind/src/components/native/useAccentColor.ts
  • packages/uniwind/src/components/native/useStyle.ts
  • packages/uniwind/src/components/web/ActivityIndicator.tsx
  • packages/uniwind/src/components/web/Button.tsx
  • packages/uniwind/src/components/web/FlatList.tsx
  • packages/uniwind/src/components/web/Image.tsx
  • packages/uniwind/src/components/web/ImageBackground.tsx
  • packages/uniwind/src/components/web/KeyboardAvoidingView.tsx
  • packages/uniwind/src/components/web/Modal.tsx
  • packages/uniwind/src/components/web/Pressable.tsx
  • packages/uniwind/src/components/web/RefreshControl.tsx
  • packages/uniwind/src/components/web/SafeAreaView.tsx
  • packages/uniwind/src/components/web/ScrollView.tsx
  • packages/uniwind/src/components/web/SectionList.tsx
  • packages/uniwind/src/components/web/Switch.tsx
  • packages/uniwind/src/components/web/Text.tsx
  • packages/uniwind/src/components/web/TextInput.tsx
  • packages/uniwind/src/components/web/TouchableHighlight.tsx
  • packages/uniwind/src/components/web/TouchableOpacity.tsx
  • packages/uniwind/src/components/web/TouchableWithoutFeedback.tsx
  • packages/uniwind/src/components/web/View.tsx
  • packages/uniwind/src/components/web/VirtualizedList.tsx
  • packages/uniwind/src/core/config/config.common.ts
  • packages/uniwind/src/core/config/config.native.ts
  • packages/uniwind/src/core/config/config.ts
  • packages/uniwind/src/core/native/store.ts
  • packages/uniwind/src/core/types.ts
  • packages/uniwind/src/core/web/getWebStyles.ts
  • packages/uniwind/src/hoc/types.ts
  • packages/uniwind/src/hoc/withUniwind.native.tsx
  • packages/uniwind/src/hoc/withUniwind.tsx
  • packages/uniwind/src/hooks/useCSSVariable/getVariableValue.native.ts
  • packages/uniwind/src/hooks/useCSSVariable/useCSSVariable.ts
  • packages/uniwind/src/hooks/useResolveClassNames.ts
  • packages/uniwind/src/hooks/useUniwind.ts
  • packages/uniwind/tsconfig.json
✅ Files skipped from review due to trivial changes (70)
  • packages/uniwind/src/components/native/useStyle.ts
  • packages/uniwind/src/components/native/useAccentColor.ts
  • packages/uniwind/src/components/web/ImageBackground.tsx
  • packages/uniwind/src/bundler/css-processor/units.ts
  • packages/uniwind/src/components/ScopedTheme/ScopedTheme.native.tsx
  • packages/uniwind/src/hooks/useResolveClassNames.ts
  • packages/uniwind/src/components/web/TextInput.tsx
  • packages/uniwind/src/hooks/useCSSVariable/getVariableValue.native.ts
  • packages/uniwind/src/bundler/css-processor/functions.ts
  • packages/uniwind/src/components/web/TouchableOpacity.tsx
  • packages/uniwind/src/components/native/ImageBackground.tsx
  • packages/uniwind/src/components/native/View.tsx
  • packages/uniwind/src/bundler/artifacts/css/extraUtilities.ts
  • packages/uniwind/src/components/native/ActivityIndicator.tsx
  • packages/uniwind/src/hoc/withUniwind.native.tsx
  • packages/uniwind/src/components/native/KeyboardAvoidingView.tsx
  • packages/uniwind/src/components/native/Button.tsx
  • packages/uniwind/src/components/native/TouchableWithoutFeedback.tsx
  • packages/uniwind/src/components/native/ScrollView.tsx
  • packages/uniwind/src/components/web/Image.tsx
  • packages/uniwind/src/components/web/View.tsx
  • packages/uniwind/src/components/web/VirtualizedList.tsx
  • packages/uniwind/src/bundler/css-visitor/visitor.ts
  • packages/uniwind/src/components/web/Button.tsx
  • packages/uniwind/src/hoc/types.ts
  • packages/uniwind/src/components/native/Image.tsx
  • packages/uniwind/src/components/native/TouchableOpacity.tsx
  • packages/uniwind/src/components/native/TouchableHighlight.tsx
  • packages/uniwind/src/components/web/KeyboardAvoidingView.tsx
  • packages/uniwind/src/components/native/VirtualizedList.tsx
  • packages/uniwind/src/components/native/Text.tsx
  • packages/uniwind/src/components/native/SectionList.tsx
  • packages/uniwind/src/core/native/store.ts
  • packages/uniwind/src/components/web/ScrollView.tsx
  • packages/uniwind/src/components/native/SafeAreaView.tsx
  • packages/uniwind/src/components/native/InputAccessoryView.tsx
  • packages/uniwind/src/hoc/withUniwind.tsx
  • packages/uniwind/src/bundler/css-processor/css.ts
  • packages/uniwind/src/bundler/css-processor/processor.ts
  • packages/uniwind/src/bundler/css-visitor/rule-visitor.ts
  • packages/uniwind/src/components/web/ActivityIndicator.tsx
  • packages/uniwind/src/components/web/Switch.tsx
  • packages/uniwind/src/bundler/css-processor/var.ts
  • packages/uniwind/src/components/web/TouchableWithoutFeedback.tsx
  • packages/uniwind/src/components/native/TouchableNativeFeedback.tsx
  • packages/uniwind/src/components/web/FlatList.tsx
  • packages/uniwind/src/components/native/FlatList.tsx
  • packages/uniwind/src/bundler/css-compiler/compileTailwind.ts
  • packages/uniwind/src/bundler/css-visitor/function-visitor.ts
  • packages/uniwind/src/components/web/RefreshControl.tsx
  • packages/uniwind/src/components/native/TextInput.tsx
  • packages/uniwind/src/components/native/Pressable.tsx
  • packages/uniwind/src/bundler/adapters/metro/patches.ts
  • packages/uniwind/src/components/web/SafeAreaView.tsx
  • packages/uniwind/src/components/web/SectionList.tsx
  • packages/uniwind/src/components/web/Modal.tsx
  • packages/uniwind/src/core/web/getWebStyles.ts
  • packages/uniwind/src/components/native/Modal.tsx
  • packages/uniwind/src/components/native/RefreshControl.tsx
  • packages/uniwind/src/core/config/config.common.ts
  • packages/uniwind/src/components/web/Pressable.tsx
  • packages/uniwind/src/bundler/css-processor/addMetaToStylesTemplate.ts
  • packages/uniwind/.oxlintrc.json
  • packages/uniwind/src/core/config/config.ts
  • packages/uniwind/src/bundler/css-processor/mq.ts
  • packages/uniwind/src/hooks/useUniwind.ts
  • packages/uniwind/src/bundler/adapters/metro/resolvers.ts
  • packages/uniwind/src/components/native/Switch.tsx
  • packages/uniwind/src/components/web/TouchableHighlight.tsx
  • packages/uniwind/src/components/web/Text.tsx
🚧 Files skipped from review as they are similar to previous changes (8)
  • packages/uniwind/src/core/config/config.native.ts
  • packages/uniwind/src/bundler/css-compiler/compileCSS.ts
  • packages/uniwind/src/bundler/css-processor/color.ts
  • packages/uniwind/src/bundler/css-processor/types.ts
  • packages/uniwind/src/bundler/css-compiler/compileWebCSS.ts
  • packages/uniwind/src/core/types.ts
  • packages/uniwind/build.config.ts
  • packages/uniwind/src/hooks/useCSSVariable/useCSSVariable.ts

Comment thread context.md

Shared runtime:

- `Uniwind.setTheme(theme | 'system')` switches explicit themes or returns to system adaptive light/dark.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix compound adjective hyphenation.

The compound adjective should be hyphenated for clarity: "system-adaptive light/dark" instead of "system adaptive light/dark".

📝 Proposed fix
-- `Uniwind.setTheme(theme | 'system')` switches explicit themes or returns to system adaptive light/dark.
+- `Uniwind.setTheme(theme | 'system')` switches explicit themes or returns to system-adaptive light/dark.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `Uniwind.setTheme(theme | 'system')` switches explicit themes or returns to system adaptive light/dark.
- `Uniwind.setTheme(theme | 'system')` switches explicit themes or returns to system-adaptive light/dark.
🧰 Tools
🪛 LanguageTool

[grammar] ~82-~82: Use a hyphen to join words.
Context: ...hes explicit themes or returns to system adaptive light/dark. - `Uniwind.currentT...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@context.md` at line 82, Update the phrasing in the documentation string
containing Uniwind.setTheme(theme | 'system') to hyphenate the compound
adjective: change "system adaptive light/dark" to "system-adaptive light/dark"
so the description reads that Uniwind.setTheme switches explicit themes or
returns to system-adaptive light/dark.

Comment thread context.md

Vite integration:

- `uniwind(config)` returns a pre Vite plugin.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix compound adjective hyphenation.

The compound adjective should be hyphenated: "pre-Vite plugin" instead of "pre Vite plugin".

📝 Proposed fix
-- `uniwind(config)` returns a pre Vite plugin.
+- `uniwind(config)` returns a pre-Vite plugin.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `uniwind(config)` returns a pre Vite plugin.
- `uniwind(config)` returns a pre-Vite plugin.
🧰 Tools
🪛 LanguageTool

[grammar] ~117-~117: Use a hyphen to join words.
Context: ...tion: - uniwind(config) returns a pre Vite plugin. - Vite aliases `react-nativ...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@context.md` at line 117, The phrase in the documentation for uniwind(config)
uses "pre Vite plugin" and should be hyphenated; update the text that says
"`uniwind(config)` returns a pre Vite plugin." to read "`uniwind(config)`
returns a pre-Vite plugin." ensuring the compound adjective "pre-Vite" is
hyphenated wherever this wording appears.

Comment thread context.md
Comment on lines +129 to +130
- A `Style` record stores entries, breakpoint bounds, orientation, theme, RTL, native flag, dependencies, source index, class name, important properties, selector complexity, pseudo states, and data attributes.
- CSS variables live in `vars`; theme and platform scoped variables live in `scopedVars` with internal prefixes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix compound modifier hyphens.

Two compound modifiers should be hyphenated for clarity and correctness.

📝 Proposed fix
-- A `Style` record stores entries, breakpoint bounds, orientation, theme, RTL, native flag, dependencies, source index, class name, important properties, selector complexity, pseudo states, and data attributes.
-- CSS variables live in `vars`; theme and platform scoped variables live in `scopedVars` with internal prefixes.
+- A `Style` record stores entries, breakpoint bounds, orientation, theme, RTL, native flag, dependencies, source index, class name, important properties, selector complexity, pseudo-states, and data attributes.
+- CSS variables live in `vars`; theme and platform-scoped variables live in `scopedVars` with internal prefixes.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- A `Style` record stores entries, breakpoint bounds, orientation, theme, RTL, native flag, dependencies, source index, class name, important properties, selector complexity, pseudo states, and data attributes.
- CSS variables live in `vars`; theme and platform scoped variables live in `scopedVars` with internal prefixes.
- A `Style` record stores entries, breakpoint bounds, orientation, theme, RTL, native flag, dependencies, source index, class name, important properties, selector complexity, pseudo-states, and data attributes.
- CSS variables live in `vars`; theme and platform-scoped variables live in `scopedVars` with internal prefixes.
🧰 Tools
🪛 LanguageTool

[grammar] ~129-~129: Use a hyphen to join words.
Context: ... properties, selector complexity, pseudo states, and data attributes. - CSS varia...

(QB_NEW_EN_HYPHEN)


[grammar] ~130-~130: Use a hyphen to join words.
Context: ...ables live in vars; theme and platform scoped variables live in scopedVars wi...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@context.md` around lines 129 - 130, Update the phrasing describing scoped CSS
variables to use correct compound modifier hyphenation: change the phrase "theme
and platform scoped variables" (in the description of scopedVars) to "theme- and
platform-scoped variables" so that "platform-scoped" is hyphenated and the
shared "scoped" modifier is applied correctly to both "theme" and "platform".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant