Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
b6984e6
fix(bun-plugin): emit the stylesheet in Bun.build and compile alias a…
owjs3901 Sep 30, 2026
71a5984
fix(webpack-plugin,rsbuild-plugin): keep every extracted style in the…
owjs3901 Sep 30, 2026
383ca05
fix(next-plugin): isolate coordinator port file and explain unreachab…
owjs3901 Oct 2, 2026
2314d8f
Merge remote-tracking branch 'origin/fix/coordinator-port-isolation' …
owjs3901 Oct 3, 2026
8ab7c3e
Merge remote-tracking branch 'origin/fix/bun-plugin' into feat/determ…
owjs3901 Oct 3, 2026
1d6a14a
feat(plugins): number files and name classes independently of process…
owjs3901 Oct 3, 2026
1fc5744
chore: remove files test runs left behind
owjs3901 Oct 3, 2026
ffd7dc7
fix(plugins): number buckets and extracted files only, leave vite css…
owjs3901 Oct 3, 2026
4f1f953
chore: merge main into deterministic numbering
owjs3901 Oct 4, 2026
c64f08c
chore: merge main for the RSC CSS forwarding fix
owjs3901 Oct 4, 2026
5fd383b
chore: merge the updated deterministic numbering stack
owjs3901 Oct 4, 2026
187261f
fix(plugin-utils): report config failures and inheritance cycles
owjs3901 Oct 4, 2026
a2dcd45
fix(plugin-utils): match literal packages and normalize project roots
owjs3901 Oct 4, 2026
0e5d730
fix(plugin-utils): resolve inherited aliases and complete source graphs
owjs3901 Oct 4, 2026
349f4ce
fix(plugin-utils): remap compiled MDX diagnostics through source maps
owjs3901 Oct 4, 2026
7f99ae8
feat(plugin-utils): export shared plugin integration helpers
owjs3901 Oct 4, 2026
c85701e
fix(extractor): parse compiled MDX with real source identities
owjs3901 Oct 4, 2026
13b033b
fix(wasm): skip source maps and surface located resolver failures
owjs3901 Oct 4, 2026
4ca51f9
fix(vite-plugin): align roots and compiled MDX without changing RSC f…
owjs3901 Oct 4, 2026
bdbdc91
fix(webpack-plugin): reuse rooted graphs and bundler conditions
owjs3901 Oct 4, 2026
f4674eb
fix(webpack-plugin): isolate loader resolution and map MDX errors
owjs3901 Oct 4, 2026
d2a0aab
fix(rsbuild-plugin): complete rooted setup and shared CSS splitting
owjs3901 Oct 4, 2026
2755f02
fix(bun-plugin): preserve source dependency edges and module loaders
owjs3901 Oct 4, 2026
951d858
fix(bun-plugin): compile project MDX before extraction
owjs3901 Oct 4, 2026
3e6d1bc
fix(bun-plugin): align runtime roots conditions and debug defaults
owjs3901 Oct 4, 2026
362476c
test(next-plugin): align shared regex and canonical config mocks
owjs3901 Oct 4, 2026
d2ee4cc
docs(plugins): explain compiled and consumer-extracted library contracts
owjs3901 Oct 4, 2026
f631df9
chore: record patch releases for plugin core fixes
owjs3901 Oct 4, 2026
e4bb458
fix(plugin-utils): opt in to compiled MDX graph discovery
owjs3901 Oct 4, 2026
c1cfdbb
fix(webpack-plugin): normalize loader entry resources before prewarm
owjs3901 Oct 4, 2026
e81d7f3
test(vite-plugin): isolate watched config diagnostics
owjs3901 Oct 4, 2026
fd269ce
chore: record plugin CI recovery patch releases
owjs3901 Oct 4, 2026
a16a469
fix(plugin-utils): number MDX only for compiler-owning callers
owjs3901 Oct 4, 2026
6615744
fix(vite-plugin): prepare complete library CSS before optimization
owjs3901 Oct 4, 2026
394a049
test(bun-plugin): cover internal setup and source callbacks completely
owjs3901 Oct 4, 2026
abaf1b5
docs(vite-plugin): describe complete aggregate CSS and located limits
owjs3901 Oct 4, 2026
d05fac1
feat(plugin-utils): prepare graph sources with shared selection alias…
owjs3901 Oct 4, 2026
9a4fef7
docs(plugin-utils): define prepared graph and resolver option contracts
owjs3901 Oct 4, 2026
e46ae77
feat(plugin-utils): prepare synchronous resolver modules and remap er…
owjs3901 Oct 4, 2026
059972c
docs(plugin-utils): explain prepared resolver mapping and importing-s…
owjs3901 Oct 4, 2026
9cc58a2
feat(plugin-utils): resolve ordered alias candidate arrays
owjs3901 Oct 4, 2026
21b1a12
docs(plugin-utils): specify ordered alias candidates and terminal errors
owjs3901 Oct 4, 2026
03d8e84
fix(plugin-utils): place alias integration in the committed resolver
owjs3901 Oct 4, 2026
e8abf15
fix(plugin-utils): make import edges parser independent
owjs3901 Oct 5, 2026
179fa6d
fix(wasm): preserve source types for compiled MDX modules
owjs3901 Oct 5, 2026
a6a094d
fix(plugins): guard definitely used untransformed MDX exports
owjs3901 Oct 5, 2026
28dc9a1
fix(wasm): preserve explicit ignored alias module semantics
owjs3901 Oct 6, 2026
93846b9
test(extractor): cover ignored object serialization and style paths
owjs3901 Oct 6, 2026
fce47fe
fix(plugins): preserve ordered native alias descriptor options
owjs3901 Oct 6, 2026
76a5918
fix(plugin-utils): resolve aliased directory package entries
owjs3901 Oct 6, 2026
c4e8c2e
docs(plugins): explain ignored aliases and guarded MDX boundaries
owjs3901 Oct 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changepacks/changepack_log_bun_plugin_build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"changes": {
"packages/bun-plugin/package.json": "Patch"
},
"note": "Bun plugin works with Bun.build: `DevupUI()` (from `@devup-ui/bun-plugin/register`) serves the generated stylesheet to the bundler's CSS loader once every other module is loaded, so the build emits a CSS output with the styles of the whole bundle instead of an empty module; class names are short there and readable under the runtime (`debug` option). Files importing the packages Devup UI takes the place of (`@emotion/react`, `@emotion/styled`, `styled-components`, `@vanilla-extract/css`), `@stylexjs/stylex`, or a subpath or re-export of these or `@devup-ui/react`, are compiled instead of skipped",
"date": "2026-09-30T00:00:00.000Z"
}
7 changes: 7 additions & 0 deletions .changepacks/changepack_log_coordinator_port_isolation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"changes": {
"packages/next-plugin/package.json": "Patch"
},
"note": "Isolate the coordinator port file per owning process when another live next dev/build holds it, record the owner pid, and report port, pid and recovery when the coordinator is missing or unreachable",
"date": "2026-10-02T12:41:12.3693972Z"
}
9 changes: 9 additions & 0 deletions .changepacks/changepack_log_css_snapshot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"changes": {
"packages/webpack-plugin/package.json": "Patch",
"packages/rsbuild-plugin/package.json": "Patch",
"packages/plugin-utils/package.json": "Patch"
},
"note": "Webpack and Rsbuild builds hold every style in their stylesheets: a stylesheet module is built on its first import, so styles extracted later (the global styles of files webpack or Rsbuild reached late, often outside `src`) were missing from the output. The files the entries reach under `src` are now extracted before the build, the shared base on disk is kept current, and when a stylesheet still changed during the build it is compiled once more, writing only the complete result. Rsbuild serves each stylesheet from the current sheet instead of a module-wide string kept only when it grew, which left edits that shortened the CSS and later builds in the same process stale. plugin-utils adds computeReachableFiles",
"date": "2026-09-30T00:00:00.000Z"
}
13 changes: 13 additions & 0 deletions .changepacks/changepack_log_deterministic_numbering.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"changes": {
"bindings/devup-ui-wasm/package.json": "Patch",
"packages/plugin-utils/package.json": "Patch",
"packages/vite-plugin/package.json": "Patch",
"packages/webpack-plugin/package.json": "Patch",
"packages/rsbuild-plugin/package.json": "Patch",
"packages/next-plugin/package.json": "Patch",
"packages/bun-plugin/package.json": "Patch"
},
"note": "Class names and file numbers no longer depend on the order files are processed in. Every plugin walks the files it can extract (the project's source and the included packages) before the first transform and numbers them in path order (a file collapsed into a bucket is numbered as the bucket, and only files that mention the package, StyleX or an aliased package take numbers) through the new seedFileMap, so identical builds give identical class prefixes, CSS file names and output hashes; in development, files that appear later are numbered after the existing ones. Styles are given class names in a fixed order, not the order of a hash set. The exported class, file and canonical maps are canonical JSON (sorted keys). Stylesheet evaluation (vanilla-extract) refuses Math.random(), Date.now(), new Date() and Date(), which differ between builds, with a build error; fixed dates such as new Date(0) are unchanged. resetBuildState starts a build from its own options: the prefix, atom hoisting, routes, buckets, names, numbers and styles an earlier build in the process left are cleared, and the prefix is set on every setup even when it is absent. Engine snapshots from concurrent transforms are written one after another per file, so an older snapshot is never written last. File lists are ordered by code point rather than the locale",
"date": "2026-10-01T00:00:00.000Z"
}
13 changes: 13 additions & 0 deletions .changepacks/changepack_log_plugin_core.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"changes": {
"bindings/devup-ui-wasm/package.json": "Patch",
"packages/plugin-utils/package.json": "Patch",
"packages/vite-plugin/package.json": "Patch",
"packages/webpack-plugin/package.json": "Patch",
"packages/rsbuild-plugin/package.json": "Patch",
"packages/bun-plugin/package.json": "Patch",
"packages/next-plugin/package.json": "Patch"
},
"note": "Use bundler project roots and active export conditions for build-time module resolution, resolve inherited tsconfig paths and dotted module specifiers, transform modern modules and compiled MDX, match included packages literally, and refresh empty theme declarations. Skip unrequested source maps, surface resolver faults before stylesheet mutation, and report WASM panic locations. Malformed or cyclic configuration, resolver failures, requested graph/prewarm failures and disabled Rsbuild shared splitting now stop builds with context; optional numbering fallback warns about its deterministic impact. Bun defaults to compact names and retains imported build-time dependency watch edges.",
"date": "2026-10-01T00:00:00.000Z"
}
10 changes: 10 additions & 0 deletions .changepacks/changepack_log_plugin_core_ci.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": {
"packages/plugin-utils/package.json": "Patch",
"packages/vite-plugin/package.json": "Patch",
"packages/webpack-plugin/package.json": "Patch",
"packages/rsbuild-plugin/package.json": "Patch"
},
"note": "Keep raw MDX out of static import graphs unless the caller compiles MDX before extraction, preserving Next production prewarm behavior while MDX-aware plugins opt in. Normalize Webpack inline-loader entry resources before filesystem lookup and skip virtual or pitch-only entries without swallowing real I/O failures. Isolate watched-config regression diagnostics while preserving the prior theme on invalid configuration. No new build-error category is introduced.",
"date": "2026-10-01T00:00:00.000Z"
}
7 changes: 7 additions & 0 deletions .changepacks/changepack_log_plugin_core_mdx.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"changes": {
"bindings/devup-ui-wasm/package.json": "Patch"
},
"note": "Extract compiled MDX with its real source filename, including JSX-preserving alias imports and exact static computations. Raw or invalid MDX and unsupported extraction extensions now produce located build errors instead of untransformed styling placeholders.",
"date": "2026-10-01T00:00:00.000Z"
}
144 changes: 88 additions & 56 deletions bindings/devup-ui-wasm/README.md
Original file line number Diff line number Diff line change
@@ -1,85 +1,117 @@
<div align="center">
# @devup-ui/wasm

<h1><code>wasm-pack-template</code></h1>
Build-time CSS extraction bindings used by the Devup UI bundler plugins.

<strong>A template for kick starting a Rust and WebAssembly project using <a href="https://github.com/rustwasm/wasm-pack">wasm-pack</a>.</strong>
## Extraction boundaries

<p>
<a href="https://travis-ci.org/rustwasm/wasm-pack-template"><img src="https://img.shields.io/travis/rustwasm/wasm-pack-template.svg?style=flat-square" alt="Build Status" /></a>
</p>
`codeExtract` generates a source map. `codeExtractWithoutSourceMap` skips map
generation, including when a module resolver is installed; its `map` getter is
`undefined`. Both functions return transformed source and watched dependencies.

<h3>
<a href="https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html">Tutorial</a>
<span> | </span>
<a href="https://discordapp.com/channels/442252698964721669/443151097398296587">Chat</a>
</h3>
`setModuleResolver` accepts a synchronous `(specifier, importer)` callback.
Return `{ path: string, code: string }` for a resolved module, or
`{ ignored: true }` for an explicitly ignored native alias. An ignored result
has no source/path and never reads `path`, `code` or `sourceType` getters.
`null` and `undefined` mean ordinary unresolved imports. Thrown exceptions, property-getter
and reflection failures, and missing/non-string fields instead fail extraction:

<sub>Built with 🦀🕸 by <a href="https://rustwasm.github.io/">The Rust and WebAssembly Working Group</a></sub>

</div>

## About
```text
/src/App.tsx:1:1: module resolver cannot use `./tokens` at build time: original cause
```

[**📚 Read this template tutorial! 📚**][template-docs]
The importer includes transitive importers. The resolver contract does not
provide an import span, so this boundary reports `1:1` rather than guessing a
position from source text. The first resolver fault takes precedence over the
extractor's unresolved-module fallback and is checked **before** sheet updates.
The previous stylesheet contribution therefore survives a failed re-extraction.
Class/file numbering performed inside extraction is not rolled back.

This template is designed for compiling Rust libraries into WebAssembly and
publishing the resulting package to NPM.
Ignored imports are empty CommonJS modules, not renamed or virtual files. Missing
named values are `undefined`, defaults follow the existing CommonJS interop, and
namespace/require values are empty objects. No ignored file becomes a watched
dependency or is sent through the parser. The `ignored` discriminator must be
`true` or absent; malformed discriminators retain the same located resolver-fault
priority and previous-sheet preservation as malformed file results.

Be sure to check out [other `wasm-pack` tutorials online][tutorials] for other
templates and usages of `wasm-pack`.
## Panic diagnostics

[tutorials]: https://rustwasm.github.io/docs/wasm-pack/tutorials/index.html
[template-docs]: https://rustwasm.github.io/docs/wasm-pack/tutorials/npm-browser-packages/index.html
WASM initialization installs this binding's own `std::panic::set_hook`, with no
additional dependency or feature flag. It reports Rust's panic payload and
`file:line:column` location to `console.error` before the trap. A failing host
console does not replace the original panic. This is diagnostic reporting, not
panic recovery: with `panic=abort`, a panic still traps and the instance should
be discarded. Normal resolver/configuration failures use fallible JS errors.

## 🚴 Usage
Owned binding code does not unwrap user input or explicitly panic. Sheet mutex
poisoning is recovered, and no resolver callback is called while holding a sheet
lock or a thread-local resolver borrow. Panics originating in downstream crates
remain outside this binding's recovery contract.

### 🐑 Use `cargo generate` to Clone this Template
## Verification

[Learn more about `cargo generate` here.](https://github.com/ashleygwilliams/cargo-generate)
From the repository root:

```
cargo generate --git https://github.com/rustwasm/wasm-pack-template.git --name my-project
cd my-project
```sh
cargo test -p devup-ui-wasm boundary_ -- --nocapture
```

### 🛠️ Build with `wasm-pack build`
After rebuilding `pkg` with this package's `bun run build`, run from the
repository root:

```
wasm-pack build
```sh
node bindings/devup-ui-wasm/boundary-regressions.mjs
node bindings/devup-ui-wasm/ignored-alias-regressions.mjs
```

### 🔬 Test in Headless Browsers with `wasm-pack test`
This standalone runner loads the real generated JS and WASM, outside Bun's
coverage mocks. It exercises both extraction exports, map skipping with and
without resolution, unresolved null/undefined, valid resolved dependencies,
callback exceptions, getters, proxy reflection, malformed fields and hostile
exception objects. Every fault case verifies the previous sheet is unchanged.
Native tests cover every branch of the internal fault-precedence helper.

```
wasm-pack test --headless --firefox
```
## Explicit Compiler Source Type

### 🎁 Publish to NPM with `wasm-pack publish`
Both extraction functions accept an optional ninth argument after
`import_aliases`: `sourceType?: 'compiled-mdx'`. Use it for project-compiled MDX
under a custom extension, without changing the real filename:

```ts
const output = codeExtract(
'src/page.mdown', compiledCode, '@devup-ui/react', 'df',
true, false, false, {}, 'compiled-mdx',
)
```
wasm-pack publish
```

## 🔋 Batteries Included

- [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) for communicating
between WebAssembly and JavaScript.
- [`console_error_panic_hook`](https://github.com/rustwasm/console_error_panic_hook)
for logging panic messages to the developer console.
- `LICENSE-APACHE` and `LICENSE-MIT`: most Rust projects are licensed this way, so these are included for you
The value means JavaScript with JSX, not TypeScript or raw Markdown. Omission
keeps filename-derived parsing, including compiled JavaScript/JSX for `.md` and
`.mdx`. Unknown extensions without an override fail with a located error even
when the source has no styling import. Invalid source-type values also fail
before stylesheet publication.

## License
Resolved modules may return `{ path, code, sourceType: 'compiled-mdx' }`. The
child's own type reaches imported constants, reexports, stylesheet evaluation
and stripping caches; it never inherits the importing file's override. This
includes an ordinary TSX file importing a constant after JSX in compiled `.md`
or `.mdown`. Parser/source-type failures preserve the previous stylesheet.
Existing imported-value coordinate limitations remain owned by #757.

Licensed under either of
After rebuilding the bindings, run the real project-compiler/WASM matrix:

- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
```sh
node bindings/devup-ui-wasm/source-type-regressions.mjs
```

at your option.
The same JS runner also uses the installed `@mdx-js/mdx` compiler, resolved through
`@mdx-js/loader` in `apps/landing` (no added dependency). Both default `_jsx`
output and `jsx: true` output are extracted under real `.mdx` and `.md` filenames.
It checks CSS, the relevance gate, source-map filename identity and rejection of
raw Markdown. Compiled MDX is parsed as JSX JavaScript, not TSX. Its source-map
coordinates refer to compiler output; bundler integrations must compose input
maps to recover Markdown positions, or identify diagnostics as compiled MDX.

### Contribution
Focused native MDX verification:

Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the Apache-2.0
license, shall be dual licensed as above, without any additional terms or
conditions.
```sh
cargo test -p extractor mdx_ -- --nocapture
```
Loading
Loading