Repository navigation
Releases: jayeshmepani/cssforge
Release list
v0.7.0 — Shared-State `:is()` Factoring (Review Specificity)
What's new
Review required: :is() can raise specificity
:is() is not a comma list. Each selector in a, button { } keeps its own specificity. :is(a, button) uses max(a, button).
/* 0.6.1 — no plan (missing pattern) */
a:hover,
button:hover,
[role="button"]:hover,
.clickable:hover {
cursor: pointer;
}
/* 0.7.0 — applied on refactor */
:is(a, button, [role="button"], .clickable):hover {
cursor: pointer;
}| Branch | Before | After :is() |
|---|---|---|
a:hover, button:hover |
(0, 1, 1) |
(0, 2, 0) |
[role="button"]:hover, .clickable:hover |
(0, 2, 0) |
(0, 2, 0) |
a:hover / button:hover get class-level weight. That can change which rule wins. Read the unified diff before you keep the file.
Still REVIEW (not auto-applied):
:is()that includes an ID (for example:is(.alpha, #hero) .title)modernize-where—:where()zeros specificity to(0, 0, 0)
Use --allow-review only if you intend those.
Use :is(), not ::is(). ::is is invalid CSS.
Bugfix: shared-state :is() was missing
modernize-is already knew same-base different states:
.button:hover, .button:focus → .button:is(:hover, :focus) (same spec → SAFE in 0.6.1)
It did not know different bases with the same state (a:hover, button:hover). That produced no plan. That hole is filled. Still 28 rules; this is not a 29th rule.
Bugfix: identical-body merge is a comma list, not :is()
::selection { background: Highlight !important; color: HighlightText !important; }
.button--primary { background: Highlight !important; color: HighlightText !important; }becomes:
::selection,
.button--primary {
background: Highlight !important;
color: HighlightText !important;
}This is merge-identical-rule-bodies. A comma list does not change each selector’s specificity. 0.6.1 marked mixed-spec merges REVIEW as if they were :is(), so the TUI never applied them. They are SAFE now.
Do not write :is(::selection, .button--primary). Pseudo-elements cannot go in :is() / :where() / :not().
Official multi-platform binaries
| Platform | Architecture | Archive |
|---|---|---|
| Windows | Intel / AMD x64 | cssforge-v0.7.0-windows-x64.zip |
| Windows | Snapdragon / ARM64 | cssforge-v0.7.0-windows-arm64.zip |
| Linux | Intel / AMD x64 | cssforge-v0.7.0-linux-x64.tar.gz |
| Linux | Snapdragon / ARM64 | cssforge-v0.7.0-linux-arm64.tar.gz |
| macOS | Apple Silicon M-Series | cssforge-v0.7.0-macos-arm64.tar.gz |
Installation
Cargo
cargo install cssforge --version 0.7.0Linux
tar -xvf cssforge-v0.7.0-linux-x64.tar.gz
cp cssforge-v0.7.0-linux-x64/cssforge ~/.local/bin/
chmod +x ~/.local/bin/cssforge
cssforge --versionChecksums
SHA256 checksums are included with the release in SHA256SUMS.txt.
sha256sum -c SHA256SUMS.txtVerification
This release was verified with:
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
cargo build --release --workspacev0.6.1 — Valid Multiline Values & Mixed-Media Gather
What's new
CSSForge 0.6.1 is a patch on shipped v0.6.0. The 28th rule from 0.6.0 is unchanged. This release fixes Refactor apply producing invalid CSS and dropping declarations from mixed @media blocks. Transformations stay forward-only, range-based, and reviewable. Cascade order is not rewritten.
v0.6.0 added dedupe-identical-declarations and stopped gather from cloning already-nested descendants. Use 0.6.1 instead of 0.6.0 if you apply the Refactor preset.
Multiline values stay one declaration
Refactor no longer treats each line of a value as its own declaration. Parentheses, brackets, strings, and continuation lines are tracked so these stay intact:
-
filter: drop-shadow(...) drop-shadow(...)(including a line break between functions) -
background: linear-gradient( … )/radial-gradient( … )split across lines -
Multiline custom properties such as
--shadow:filter: drop-shadow(0 2px 20px rgba(45, 212, 191, 0.14)) drop-shadow(0 8px 30px rgba(0, 0, 0, 0.75));
stays one
filterdeclaration. 0.6.0 could emit a straydrop-shadow(...);(unknown word) andbackground: linear-gradient(;.
Body re-indent no longer injects ; onto continuation lines.
Mixed @media parent declarations survive gather
When an already-nested @media contains both parent declarations and a child rule, gather still nests the child under its home but no longer deletes the parent declarations.
.split-layout {
lottie-player { max-width: 440px; }
@media (width >= 840px) {
grid-template-columns: 1.2fr 0.8fr;
align-items: center;
lottie-player { max-width: 100%; }
}
}grid-template-columns and align-items remain on .split-layout. 0.6.0 could drop them and leave a stray }.
Conflicting identical selectors are not concatenated
Adjacent or gathered copies of the same selector are not merged when they declare the same property with different values (including !important vs not). Exact duplicates are still removed by dedupe-identical-declarations.
Example: :focus-visible { outline: 3px solid Highlight; } and :focus-visible { outline: 2px solid Highlight !important; } stay two rules so cascade order does not collapse into a single block with duplicate properties.
From 0.6.0 (unchanged)
- 28th rule
dedupe-identical-declarations: exact-duplicate declarations and identical nested copies in the same block, first occurrence kept; different values left untouched; custom property names case-sensitive. - Gather applies that cleanup when merging and does not re-absorb nodes already nested in the home rule (the 32-pass clone loop).
Documentation and versioning
This is a Cargo 0.x patch on 0.6.0. No new public RuleId. RuleId::ALL remains [RuleId; 28].
Official multi-platform binaries
| Platform | Architecture | Archive |
|---|---|---|
| Windows | Intel / AMD x64 | cssforge-v0.6.1-windows-x64.zip |
| Windows | Snapdragon / ARM64 | cssforge-v0.6.1-windows-arm64.zip |
| Linux | Intel / AMD x64 | cssforge-v0.6.1-linux-x64.tar.gz |
| Linux | Snapdragon / ARM64 | cssforge-v0.6.1-linux-arm64.tar.gz |
| macOS | Apple Silicon M-Series | cssforge-v0.6.1-macos-arm64.tar.gz |
Installation
Cargo
cargo install cssforge --version 0.6.1Linux
tar -xvf cssforge-v0.6.1-linux-x64.tar.gz
cp cssforge-v0.6.1-linux-x64/cssforge ~/.local/bin/
chmod +x ~/.local/bin/cssforge
cssforge --versionChecksums
SHA256 checksums are included with the release in SHA256SUMS.txt.
sha256sum -c SHA256SUMS.txtVerification
This release was verified with:
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace --all-targets
cargo build --release --workspacev0.6.0 — Dedupe Identical Declarations & Stable Gather
What's new
CSSForge 0.6.0 adds a 28th transformation rule for exact-duplicate cleanup and stops gather from cloning work it has already nested. Transformations stay forward-only, range-based, and reviewable. Cascade order is not rewritten.
28th rule — dedupe-identical-declarations
-
Removes exact-duplicate declarations in the same block, keeping the first occurrence.
-
Removes identical nested rule copies in the same block, keeping the first copy.
-
Does not drop later declarations that have a different value.
color: red;followed bycolor: blue;is left intact so the winning cascade value does not change. -
Does not treat
color: redandcolor: red !importantas the same declaration. -
Treats custom property names as case-sensitive (
--tokenis not--Token). -
Enabled in Conservative, Modern, Refactor, and Aggressive.
.card { color: red; color: red; display: none; display: none; color: blue; }
becomes:
.card { color: red; display: none; color: blue; }
Gather no longer clones already-nested descendants
gather-related-selector-rulesstill selects the same related selectors.- When gather merges those rules, it now applies the same exact-duplicate cleanup.
- Nodes that are already nested inside the home rule are not re-absorbed as extra copies.
- This reaches a fixed point on repeated runs instead of growing the stylesheet every pass.
Previously, Refactor apply could fail on real nested stylesheets with:
Error: CSS transformations did not reach a stable result after 32 passes
because gather kept appending duplicate nested declarations such as extra display: none; and extra & > .cluster { ... } blocks. That loop is closed.
Documentation and rule catalog
The README and HTML documentation now describe all 28 transformation rules, including dedupe-identical-declarations. RuleId::ALL is [RuleId; 28]. This is a Cargo 0.x minor bump from 0.5.1 because a public enum variant was added.
Official multi-platform binaries
| Platform | Architecture | Archive |
|---|---|---|
| Windows | Intel / AMD x64 | cssforge-v0.6.0-windows-x64.zip |
| Windows | Snapdragon / ARM64 | cssforge-v0.6.0-windows-arm64.zip |
| Linux | Intel / AMD x64 | cssforge-v0.6.0-linux-x64.tar.gz |
| Linux | Snapdragon / ARM64 | cssforge-v0.6.0-linux-arm64.tar.gz |
| macOS | Apple Silicon M-Series | cssforge-v0.6.0-macos-arm64.tar.gz |
Installation
Cargo
cargo install cssforge --version 0.6.0Linux
tar -xvf cssforge-v0.6.0-linux-x64.tar.gz
cp cssforge-v0.6.0-linux-x64/cssforge ~/.local/bin/
chmod +x ~/.local/bin/cssforge
cssforge --versionChecksums
SHA256 checksums are included with the release in SHA256SUMS.txt.
sha256sum -c SHA256SUMS.txtVerification
This release was verified with:
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace --all-targets
cargo build --release --workspacev0.5.1 — Restore Complete Gather & Spec-Accurate Nesting Selector
What's new
CSSForge 0.5.1 is a patch for 0.5.0. Complete gather of related selectors was already in 0.4.0 and earlier. Nesting-safety work in 0.5.0 made that gather lossy: nested @supports / @media were skipped, a wide REVIEW span hid SAFE nests, and & was rewritten as if it were a Sass parent pointer. This release restores that gather and makes native & match the spec.
Restore complete gather
Prefix-related rules for the same selector gather into the first home again, including nested conditionals:
.stack-card {
&:last-child { margin-bottom: 0; }
&:hover {
.project-card-marvel__media {
img { transform: scale(1.035); }
&::after { left: 160%; }
}
}
@supports (animation-timeline: view()) {
@media (prefers-reduced-motion: no-preference) {
.card-inner { animation-name: recede; }
&:last-child .card-inner { animation: none; }
}
}
}@supports { @media { .home .child } }is no longer skipped. The at-rule chain inverts under.home; inner selectors stay relative (.card-inner,&:last-child .card-inner).- Hover chains factor as before:
&:hover .media imgand&:hover .media::afterbecome&:hover { .media { img; &::after } }. - Gather replaces only the home rule. Remote members are separate delete plans, so a gather span cannot hide unrelated SAFE nests between the first and last related rule.
- Mixed
@mediablocks that also contain other selectors (for example:rootand.card-innerbeside.stack-card) stay grouped and are not exploded into each parent. nest-layer-by-selectorand other cascade-order changes remain REVIEW.
Native & is :is(parent)
The nesting selector substitutes the parent selector list, not a parent element and not a text paste. A later pass must not wrap that result as if & still meant the original subject.
/* invalid — `&` is .card-inner, so this is .card-inner:last-child .card-inner */
.card-inner {
&:last-child & { animation: none; }
}
/* valid — `&` is still .stack-card */
.stack-card {
&:last-child .card-inner { animation: none; }
}-
Does not nest
tr:last-child tdundertdastd { tr { &:last-child & } }. That desugars totd trand matches nothing in a table. -
Nests from the row instead:
.archive-table { tr { &:last-child td { border-bottom: none; } &:hover td { background: transparent; } } }
-
Valid reverse-
&cases are unchanged:.featured .card→.card { .featured & { } },:not(.card)→:not(&). -
Selectors that already contain
&are not treated as a state base, sotr:last-child &is not rewritten totr { &:last-child & }.
Stable application
- SAFE local nests win over overlapping REVIEW gathers, so refactor no longer stalls while valid nests sit inside a gather span.
- Prefix-safe gather applies again on the refactor preset (TUI and
cssforge apply --preset refactor) without--allow-review. - Appended (reverse-
&) gathers stay REVIEW when they would change matching. - Fixed-point apply is unchanged: overlapping plans still run until the source is stable.
Official multi-platform binaries
| Platform | Architecture | Archive |
|---|---|---|
| Windows | Intel / AMD x64 | cssforge-v0.5.1-windows-x64.zip |
| Windows | Snapdragon / ARM64 | cssforge-v0.5.1-windows-arm64.zip |
| Linux | Intel / AMD x64 | cssforge-v0.5.1-linux-x64.tar.gz |
| Linux | Snapdragon / ARM64 | cssforge-v0.5.1-linux-arm64.tar.gz |
| macOS | Apple Silicon M-Series | cssforge-v0.5.1-macos-arm64.tar.gz |
Installation
Cargo
cargo install cssforge --version 0.5.1Linux
tar -xvf cssforge-v0.5.1-linux-x64.tar.gz
cp cssforge-v0.5.1-linux-x64/cssforge ~/.local/bin/
chmod +x ~/.local/bin/cssforge
cssforge --versionChecksums
SHA256 checksums are included with the release in SHA256SUMS.txt.
sha256sum -c SHA256SUMS.txtVerification
This release was verified with:
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
cargo build --release --workspacev0.5.0 — Native Nesting Safety, Embedded Templates & Stable Refactoring
What's new
CSSForge 0.5.0 strengthens the refactoring engine around native CSS nesting, modern selector functions, conditional at-rules, and real-world template files. The release keeps transformations forward-only, range-based, and reviewable.
Native nesting safety
-
Generates valid native nesting for child, sibling, descendant, pseudo-class, attribute, and compound-selector relationships.
-
Emits an explicit nesting selector when a combinator needs an anchored parent:
.c-command-hero { & > .c-bolt { z-index: 4; } }
-
Rejects malformed Sass-style structures such as a bare
> { ... }block and avoids re-parenting selectors that are already nested or relative. -
Preserves existing nesting selectors and reaches a fixed point on repeated runs, preventing transformation loops and partial multi-run application.
Modern selector handling
- Factors safe selector alternatives into
:is(...)only when the matching behavior and specificity are preserved. - Preserves the different semantics of
:is(),:where(),:has(), and:not(). - Calculates functional-pseudo specificity using the highest argument specificity where required.
- Does not combine pseudo-elements such as
::before,::after,:before, or:afterinto functional pseudo-classes, because that produces invalid selectors. - Keeps
:has()relative arguments intact and does not rewrite selector-list logic inside functional pseudo-classes.
Conditional at-rules and layers
- Supports safe nesting and planning inside nestable
@media,@supports,@container,@scope,@layer, and@starting-styleblocks. - Keeps
@starting-styleselector relationships exact so opening-state transitions are not accidentally broadened. - Merges adjacent compatible conditional blocks while preserving unrelated siblings and nested conditional content.
- Keeps
gather-related-selector-ruleslayer-scoped; declarations are not moved between named layers. - Preserves named layer identity and declaration order when applying
nest-layer-by-selector.
Embedded framework and template files
CSSForge can discover and transform CSS inside <style>...</style> blocks in supported template sources, including Blade/PHP, HTML, Vue, Svelte, Astro, Twig, ERB, and Handlebars-style files. Only the style-content ranges are transformed; surrounding template code is preserved.
Stable application and review behavior
- Applies overlapping plans until the source reaches a stable result without repeatedly requiring manual re-runs.
- Prevents broad gather candidates from hiding more precise selector plans.
- Emits one spanning plan where overlapping edits could otherwise orphan deletion-only plans.
- Keeps potentially cascade-changing transformations marked for review instead of silently applying them.
- Preserves UTF-8 declaration values and multiline custom-property content.
Documentation and rule catalog
The README and HTML documentation now describe all 27 transformation rules, including nest-layer-by-selector, embedded style-block support, selector safety, and the fixed-point application model.
Official multi-platform binaries
| Platform | Architecture | Archive |
|---|---|---|
| Windows | Intel / AMD x64 | cssforge-v0.5.0-windows-x64.zip |
| Windows | Snapdragon / ARM64 | cssforge-v0.5.0-windows-arm64.zip |
| Linux | Intel / AMD x64 | cssforge-v0.5.0-linux-x64.tar.gz |
| Linux | Snapdragon / ARM64 | cssforge-v0.5.0-linux-arm64.tar.gz |
| macOS | Apple Silicon M-Series | cssforge-v0.5.0-macos-arm64.tar.gz |
Installation
Cargo
cargo install cssforge --version 0.5.0Linux
tar -xvf cssforge-v0.5.0-linux-x64.tar.gz
cp cssforge-v0.5.0-linux-x64/cssforge ~/.local/bin/
chmod +x ~/.local/bin/cssforge
cssforge --versionChecksums
SHA256 checksums are included with the release in SHA256SUMS.txt.
sha256sum -c SHA256SUMS.txtVerification
This release was verified with:
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
cargo build --release --workspacev0.4.0 — Layer-Safe Gather & Nest Layers by Selector
What's new
nest-layer-by-selector (27th rule)
The same exact selector in multiple named @layer blocks is hoisted and rewritten as nested @layer blocks. Layer identity and first-declared order stay the same. This does not create a child layer such as tokens.base.
@layer tokens { :root { A } }
@layer base { :root { B } }
/* becomes */
:root {
@layer tokens { A }
@layer base { B }
}An existing @layer reset, tokens, base, … list still defines order. The rule does not hoist when an unlayered rule sits between the layers.
Gather is layer-scoped
gather-related-selector-rules only merges related rules inside the same named layer (or both unlayered). It will not copy @layer base declarations into @layer tokens.
At-rule preludes (@layer tokens, @media …) are not treated as selector prefixes, so a second apply cannot smash named layers into @layer { tokens {} base {} }.
Other gather fixes
- Mixed
@supportswith a dominant home (for example.custom-selectplusselectedcontent) inverts into that home instead of dropping chrome. - Gather emits one spanning plan so overlapping nest plans cannot orphan delete-only plans.
- Related nests factor deeper:
button { &:hover },&:open { … },&.compact { … }. - Prefix-only sibling nesting — no
&:open &/&:focus &rewrite of descendants.
README and the HTML catalog now list all 27 rules, including nest-layer-by-selector.
Official multi-platform binaries
| Platform | Architecture | Archive |
|---|---|---|
| Windows | Intel / AMD x64 | cssforge-v0.4.0-windows-x64.zip |
| Windows | Snapdragon / ARM64 | cssforge-v0.4.0-windows-arm64.zip |
| Linux | Intel / AMD x64 | cssforge-v0.4.0-linux-x64.tar.gz |
| Linux | Snapdragon / ARM64 | cssforge-v0.4.0-linux-arm64.tar.gz |
| macOS | Apple Silicon M-Series | cssforge-v0.4.0-macos-arm64.tar.gz |
Checksums
SHA256 checksums are in SHA256SUMS.txt.
sha256sum -c SHA256SUMS.txtv0.3.1 — Comment Carry & Nest Merge
Safety-first semantic CSS refactoring and modernization workbench.
🩹 Patch on 0.3.0
Gather/nest selectors are unchanged from 0.3.0 (including :focus-visible { .skip-link:focus:not(&) }). This release only fixes how comments and duplicate nested blocks are assembled.
- Leading comments travel with gathered rules: a
/* … */immediately above a moved rule is copied into the parent (just above the nest) and removed from the old location. No more orphan comments after gather. - Same nested selector merges:
&.flash { animation }plus&.flash { @media { animation: none } }become one&.flashblock.
📦 Version
0.3.0 → 0.3.1
Compatible with 0.3 (cssforge-core = "0.3" will pick this up).
Official Multi-Platform Binaries
| Platform | Architecture | Archive File |
|---|---|---|
| Windows | Intel / AMD x64 | cssforge-v0.3.1-windows-x64.zip |
| Windows | Snapdragon / ARM64 | cssforge-v0.3.1-windows-arm64.zip |
| Linux | Intel / AMD x64 | cssforge-v0.3.1-linux-x64.tar.gz |
| Linux | Snapdragon / ARM64 | cssforge-v0.3.1-linux-arm64.tar.gz |
| macOS | Apple Silicon M-Series | cssforge-v0.3.1-macos-arm64.tar.gz |
Checksums
SHA256 checksums are available in SHA256SUMS.txt.
Verification Example
sha256sum -c SHA256SUMS.txtv0.3.0 — Smart Gather & Nesting
Safety-first semantic CSS refactoring and modernization workbench.
🧠 Smart Gather & Nesting
gather-related-selector-rules and the nest family now pick one home per rule instead of copying the same declarations into every matching parent.
- Strongest existing parent wins: specificity first (
.skip-linkbeats*; a class beatsbody). On a tie, prefix nesting (+ *,&:has(*)) beats appended&. - Appended
&(MDN): when no stronger prefix home exists, reverse the context —.featured .card→.card { .featured & { } },:not(.card)→:not(&). - Gather through conditionals: related rules inside
@media/@supports/@container/@starting-stylecan invert into the parent (.skip-link { :not(*) { @media (width <= 1024px) { … } } }). - Busy at-rules stay grouped: if an at-block has 3+ inner style rules that would land in 2+ different homes, the
@media(etc.) is left populated. One or two inners, or every inner assigned to the same home, still nest into that selector. - Universal / document roots are weak homes:
*,html,body,:root, and:hostno longer absorb component rules via appended&(no more.skip-link+&/.skip-link:has(&)inside*).
🛡️ Safer Transformations
- Selector lists are not combinators:
::view-transition-old(root), ::view-transition-new(root)is no longer rewritten as::view-transition-new(root) { ::view-transition-old(root), & { } }. A comma list stays a list. - Pseudo-elements are not gather homes:
&cannot represent::…, so::view-transition-*/::beforerules are not used as merge targets for other selectors. - Selector-list lines stay intact:
&,/&::before,/&:hover,are not treated as declarations, so they no longer become&::before,;or a stray;. - Missing semicolons repaired: last declarations without
;get one before a nested{, sodisplay: block !importantno longer runs into+ .tabpanel {. - Media range syntax modernizes features with or without spaces:
(max-width:60rem)→(width <= 60rem).
📦 Version
0.2.1 → 0.3.0
This is a 0.x minor: same CLI and the same 26 rule IDs, but default gather/nest output can change. Dependents pinned to 0.2 will not pick this up automatically.
Official Multi-Platform Binaries
| Platform | Architecture | Archive File |
|---|---|---|
| Windows | Intel / AMD x64 | cssforge-v0.3.0-windows-x64.zip |
| Windows | Snapdragon / ARM64 | cssforge-v0.3.0-windows-arm64.zip |
| Linux | Intel / AMD x64 | cssforge-v0.3.0-linux-x64.tar.gz |
| Linux | Snapdragon / ARM64 | cssforge-v0.3.0-linux-arm64.tar.gz |
| macOS | Apple Silicon M-Series | cssforge-v0.3.0-macos-arm64.tar.gz |
Checksums
SHA256 checksums are available in SHA256SUMS.txt.
Verification Example
sha256sum -c SHA256SUMS.txtv0.2.1 — Smart Safe File Discovery
Safety-first semantic CSS refactoring and modernization workbench.
📁 Smart Safe File Discovery Engine
CSSForge now applies zero-config safety ignore filters when scanning workspaces recursively, protecting build artifacts and preventing recursion loops:
- Generated & Artifact Exclusions: Automatically ignores
*.modern.css(prevents recursive re-modernization on output files),*.min.css,*.bundle.css,*.chunk.css,*.map.css, and backup files (*.bak.css,*.backup.css). - Directory Exclusions: Automatically skips
node_modules/,target/,dist/,build/,out/,.next/,.nuxt/,.turbo/,.svelte-kit/,vendor/,.git/,.hg/,.svn/, and.cache/. - Explicit Target Override: Explicitly targeting any file path directly (e.g.
cssforge interactive ./dist/bundle.min.css) continues to process the requested file.
📦 Version
0.2.0 → 0.2.1
Official Multi-Platform Binaries
| Platform | Architecture | Archive File |
|---|---|---|
| Windows | Intel / AMD x64 | cssforge-v0.2.1-windows-x64.zip |
| Windows | Snapdragon / ARM64 | cssforge-v0.2.1-windows-arm64.zip |
| Linux | Intel / AMD x64 | cssforge-v0.2.1-linux-x64.tar.gz |
| Linux | Snapdragon / ARM64 | cssforge-v0.2.1-linux-arm64.tar.gz |
| macOS | Apple Silicon M-Series | cssforge-v0.2.1-macos-arm64.tar.gz |
Checksums
SHA256 checksums are available in SHA256SUMS.txt.
Verification Example
sha256sum -c SHA256SUMS.txtv0.2.0 — Gather Related Selectors, Select All & Windows TUI Scroll Fix
Safety-first semantic CSS refactoring and modernization workbench.
Gather related selector rules
CSSForge can now gather scattered, non-adjacent occurrences of the same selector into one canonical rule block.
/* before — same selector, far apart */
.skip-link { position: absolute; font-weight: 700; }
/* …unrelated rules, comments, @keyframes… */
.skip-link { font: optional; }
.skip-link+* { display: block; }
.skip-link::backdrop { background-color: gray; }
.skip-link:has(*) { color: #27ca3f; }/* after */
.skip-link {
position: absolute;
font-weight: 700;
font: optional;
+ * { display: block; }
&::backdrop { background-color: gray; }
&:has(*) { color: #27ca3f; }
}What is gathered:
- Exact selector duplicates — later blocks merge into the first; declarations are promoted to the top of that block
- Directly attached pseudo-classes / elements →
&:hover,&:has(*),&::backdrop - Combinator variants →
+ *,> .child,~ .peer - Whitespace descendants →
:not(*),.child(no spurious&)
Intervening rules, comments, and @keyframes are left untouched.
Safety: REVIEW. Requires --allow-review on the CLI, or enabling the rule in the TUI. Verify cascade order after apply.
TUI
- Windows scroll fix on Select Rules: wrapped descriptions no longer bleed into the next row or desync the cursor. Each rule is one clipped line; only the list pane scrolls; header and enabled-count stay fixed.
PgUp/PgDnmove the rules (and files) cursor by a page.- Select All (
a) on the rules screen — same toggle-all behavior as files. Press again to deselect all.
Fixes
- Worktree preservation:
GatherRelatedSelectorRulespreviously replacedfirst.start..last.end, deleting everything between non-adjacent matches (including@keyframes). It now writes one replacement atfirst.start..first.endand a deletion plan per later occurrence. - Descendant
&prefix:extract_related_nested_selectorno longer prepends&to whitespace-separated descendants..skip-link :not(*)nests as:not(*), not&:not(*).
Version
0.1.0 → 0.2.0
Official Multi-Platform Binaries
| Platform | Architecture | Archive File |
|---|---|---|
| Windows | Intel / AMD x64 | cssforge-v0.2.0-windows-x64.zip |
| Windows | Snapdragon / ARM64 | cssforge-v0.2.0-windows-arm64.zip |
| Linux | Intel / AMD x64 | cssforge-v0.2.0-linux-x64.tar.gz |
| Linux | Snapdragon / ARM64 | cssforge-v0.2.0-linux-arm64.tar.gz |
| macOS | Apple Silicon M-Series | cssforge-v0.2.0-macos-arm64.tar.gz |
Checksums
SHA256 checksums are available in SHA256SUMS.txt.
Verification Example
sha256sum -c SHA256SUMS.txt