Chris asked that we "merge" @stacksjs/ts-css and this project, since the rename collided with a name that was already his. This does that.
They turn out to be opposite halves of one pipeline, so this is mostly packaging — the toolkit reads CSS (parse / what / select / optimize, a TS rewrite of the css-tree/css-select/csso stack), this framework writes it. Overlap is near zero: parser.ts sounds like a duplicate but parses class names, not CSS.
One repo, two published packages. The toolkit keeps its name and its 0.1.x line — it has real dependents and is already in our own dependency tree — and the framework now consumes it.
What's here
packages/toolkit | @stacksjs/ts-css @ 0.1.4, grafted with all 36 commits of history |
packages/ts-css | the framework — name still TBD, currently @ts-css/core |
packages/vscode | scoped alongside |
Subtree merge, not a squashed import. The merge commit has two real parents, so stacksjs/ts-css history is preserved and browsable.
Config collision resolved. Both packages called loadConfig({ name: 'css' }) through bunfig, so any project using both handed the same css.config.ts to two incompatible schemas. The toolkit moves to ts-css.config.ts — matching its own package and bin name — as the cheaper side: two keys, one docs mention, nothing in tests. The framework keeps css.config.ts, which its docs and cssx init already emit.
The one place this buys real code. The framework's minifier was eight chained regexes that couldn't tell a space inside a string or url() from a space between tokens. It now calls the toolkit's AST-based minifyBlock. Both are synchronous, so toCSS() is unchanged.
Two incidental fixes. The toolkit's tokenizer tripped this repo's pickier config on a discarded resize temporary (its two siblings already had the disable comment), and buddy-bot was pointed at stacksjs/ts-css — a different project — so its dependency PRs were being opened against the wrong repo.
Things that resolved themselves
- The circular dependency is gone.
@stacksjs/ts-cssnow resolves toworkspace:packages/toolkit, so@stacksjs/ts-svg's^0.1.0is satisfied in-repo rather than pulling an older, different version of the same name. - No build ordering needed. The toolkit's export map points at
./dist/optimize/index.jsanddist/is gitignored, so this looked like it would need the toolkit built first. Bun bundles it from source instead — the optimizer is inlined into the framework's chunk with no external reference, exactly asbunfigalready is. CI needs no sequencing change.
Verification
2003 tests pass, 0 fail across 56 files (both suites in one run), typecheck clean, lint 0 errors. The minifier swap was checked end-to-end rather than by test count alone: p-4 m-2 → .p-4{padding:1rem}.m-2{margin:0.5rem} through the toolkit's AST path.
Still open — not in this PR
- What does the framework publish as? It no longer needs the contested name.
@stacksjs/cssxand@stacksjs/crosswindare free;@cwcss/ts-cssand@cwcss/coreare free in a scope we already own and where the token demonstrably works (@cwcss/crosswind@0.2.19shipped through it). - Which org holds the merged repo?
No tag has moved and nothing has been published.
Correction to an earlier version of this description. It claimed the toolkit should publish first because it "needs no new npm permissions", and that the last three release runs failed because the token could not create a package. Both are wrong:
- Both packages publish via npm OIDC trusted publishing, not
NPM_TOKEN. Registry metadata shows_npmUser: GitHub Actions / npm-oidc-no-reply@github.comwith atrustedPublisheron each (oidc:58d3b276…for@stacksjs/ts-css,oidc:90abc85a…for@cwcss/crosswind). A trusted publisher is bound to a specific owner/repo/workflow, so publishing@stacksjs/ts-cssfrom this repo fails on repo mismatch until its publisher is repointed — and that failure would take the rootpantry publishdown with it, on a live package with dependents. - The three failures were a rename regression, not a permissions problem.
v0.2.20never reached npm at all — it died inbun installon a stale lockfile.v0.2.21andv0.3.0404'd on the bare namests-css/ts-css-vscode, which simply do not exist. Roughly two hours before the first failure, this same repo, workflow and credential published 2/2 packages with provenance.
The real blocker is therefore host-independent: the framework's published name has to be settled and created on npm once by hand, because trusted publishing structurally cannot create a package that has no publisher config yet.