Skip to content

Makes more typesafe for hoistSelectors#248

Merged
github-actions[bot] merged 3 commits intomainfrom
type-fixes
Oct 4, 2025
Merged

Makes more typesafe for hoistSelectors#248
github-actions[bot] merged 3 commits intomainfrom
type-fixes

Conversation

@black7375
Copy link
Contributor

@black7375 black7375 commented Oct 4, 2025

Description

Make typesafe hoistSelectors()

Related Issue

Summary by CodeRabbit

  • New Features
    • Conditional CSS now supports a selectors property for more expressive nested selectors.
  • Bug Fixes
    • Selector hoisting is more consistent across deeply nested at-rules and empty inputs.
    • Improved validation to guard against malformed style structures.
  • Refactor
    • Hoisting logic rewritten for stronger type-safety and clearer behavior.
  • Tests
    • Expanded test coverage for hoisting and edge cases.
  • Chores
    • Added a changeset entry for release.

Additional context

Checklist

@changeset-bot
Copy link

changeset-bot bot commented Oct 4, 2025

🦋 Changeset detected

Latest commit: f1ca15c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@mincho-js/transform-to-vanilla Patch
@mincho-js/css Patch
@mincho-js/vite Patch
@mincho-js/react Patch
react-babel Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Oct 4, 2025

Triggered from #248 by @​black7375.

Checking if we can fast forward main (d9445d5) to type-fixes (5409319).

Target branch (main):

commit d9445d541aae580053755bfc3a5f9e07620241d0 (HEAD -> main, origin/main)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Thu Jul 31 00:00:00 2025 +0900

    Feat: `selector()` API implement #236

Pull request (type-fixes):

commit 540931907d8a0498b57d45243e33192e317cd478 (pull_request/type-fixes)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Thu Aug 7 00:00:00 2025 +0900

    Refactor: `hoistSelectors` makes to type-safe

It is possible to fast forward main (d9445d5) to type-fixes (5409319). If you have write access to the target repository, you can add a comment with /fast-forward to fast forward main to type-fixes.

@coderabbitai
Copy link

coderabbitai bot commented Oct 4, 2025

Walkthrough

Adds a changeset and public API update introducing a selectors property on CSSConditions, refactors hoistSelectors to a type-safe, path-based traversal with new AtRulePath/TypeSafeHoistResult types and type guards, and updates transform-to-vanilla selector-related type declarations.

Changes

Cohort / File(s) Summary
Changeset / Release note
.changeset/vast-apples-cry.md
Adds patch changeset for @mincho-js/transform-to-vanilla documenting that selectors was added to CSSConditions.
Type-safe selector hoisting (core CSS logic)
packages/css/src/css/index.ts
Rewrites hoistSelectors to a path-based, type-safe traversal; introduces AtRulePath, TypeSafeHoistResult, and type guards (hasSelectorsProperty, isAtRuleKey, isAtRuleObject); imports AtRulesKeywords; updates return type and test coverage.
Transform-to-vanilla types (selector surface)
packages/transform-to-vanilla/src/types/style-rule.ts
Removes CSSRule's direct SelectorProperty extension, adds an internal SelectorProperty<StyleType>, and composes selectors into CSSConditions (public surface adjusted to include selectors).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Caller
  participant Hoist as hoistSelectors
  participant Types as Type Guards / AtRulesKeywords
  participant Result as TypeSafeHoistResult

  Caller->>Hoist: hoistSelectors(input)
  Hoist->>Types: isAtRuleKey(key)? / isAtRuleObject(val)?
  alt At-rule encountered
    Hoist->>Hoist: Recurse with AtRulePath ([@rule,...])
    Hoist->>Hoist: Merge nested style objects along path
  else Selector encountered
    Hoist->>Hoist: Collect selectors into selectors map
  end
  Hoist->>Result: assemble { selectors, hoisted, ... }
  Result-->>Caller: return TypeSafeHoistResult
  note right of Types: type guards validate shapes during traversal
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

In burrows of braces I nibble and nest,
Hoisting selectors to where they rest.
At-rules align as I hop through the night,
Paths typed and tidy beneath moonlight.
Notes stamped and shipped — carrot crumbs of delight. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description includes the template headings but most sections remain empty or contain only placeholder comments, resulting in an incomplete description that omits a related issue reference, the auto-generated summary invocation, additional context, and checklist details. The author should populate the Related Issue section or explicitly state none, invoke the @coderabbitai summary for an auto-generated overview, and provide relevant additional context and checklist items to fully satisfy the template.
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title clearly summarizes the main change of adding type safety to the hoistSelectors function and directly reflects the core update in the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch type-fixes

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5409319 and f1ca15c.

📒 Files selected for processing (1)
  • packages/css/src/css/index.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/css/src/css/index.ts (1)
packages/transform-to-vanilla/src/types/style-rule.ts (2)
  • CSSRule (33-33)
  • AtRulesKeywords (193-193)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@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: 0

🧹 Nitpick comments (2)
packages/css/src/css/index.ts (1)

109-119: Consider making the at-rule check more maintainable.

The current implementation manually checks each at-rule type. This could be refactored to iterate over the AtRulesKeywords type for better maintainability.

Apply this diff to make the function more maintainable:

 function isAtRuleKey(
   key: string
 ): key is `@${AtRulesKeywords}` | `@${AtRulesKeywords} ${string}` {
-  return (
-    key.startsWith("@") &&
-    (key.startsWith("@media") ||
-      key.startsWith("@supports") ||
-      key.startsWith("@container") ||
-      key.startsWith("@layer"))
-  );
+  if (!key.startsWith("@")) return false;
+  const atRules: AtRulesKeywords[] = ["media", "supports", "container", "layer"];
+  return atRules.some(rule => key.startsWith(`@${rule}`));
 }
.changeset/vast-apples-cry.md (1)

5-5: Fix markdown formatting for consistency.

The markdown linter suggests using a heading instead of emphasis for "type". While this is a minor formatting issue, it's good practice to follow markdown conventions.

Apply this diff:

 
-**type**
+### Type Changes
 
 - add `selectors` property to CSSConditions
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d9445d5 and 5409319.

📒 Files selected for processing (3)
  • .changeset/vast-apples-cry.md (1 hunks)
  • packages/css/src/css/index.ts (4 hunks)
  • packages/transform-to-vanilla/src/types/style-rule.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/css/src/css/index.ts (1)
packages/transform-to-vanilla/src/types/style-rule.ts (2)
  • CSSRule (33-33)
  • AtRulesKeywords (193-193)
🪛 markdownlint-cli2 (0.18.1)
.changeset/vast-apples-cry.md

5-5: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🔇 Additional comments (7)
packages/transform-to-vanilla/src/types/style-rule.ts (1)

33-33: LGTM! Clean type hierarchy refactor.

The changes correctly introduce SelectorProperty as an internal interface and compose it into CSSConditions, which ultimately makes the selectors property available on CSSRule through the type hierarchy chain. This modular approach improves type organization and aligns with the PR's goal of making hoistSelectors more type-safe.

Also applies to: 158-171

packages/css/src/css/index.ts (6)

10-11: LGTM! Necessary imports for type-safe at-rule handling.

The GlobalCSSRule and AtRulesKeywords imports enable the new type guards and type-safe hoisting logic.


44-47: LGTM! Well-defined types for path-based hoisting.

AtRulePath and TypeSafeHoistResult clearly express the intent of the new implementation, using readonly modifiers appropriately for immutability guarantees.


54-93: Verify the type casts are necessary.

The implementation uses several type casts (lines 63, 68, 72, 86) to work around TypeScript's type inference. While the logic appears correct, these casts reduce compile-time safety guarantees.

Consider if the type definitions can be improved to avoid these casts, or add runtime assertions to validate the casts are safe. The current implementation assumes the structure is correct but doesn't validate it beyond the type guards.

For example, at line 86, you cast nestedRule to CSSRule, but there's only a check that it's an object. You might want to add a helper that validates the structure more thoroughly:

function isCSSRule(value: unknown): value is CSSRule {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

Then use this guard before the cast to make the intent clearer and add runtime safety.


49-97: LGTM! Solid implementation of type-safe hoisting.

The refactored hoistSelectors function correctly implements path-based traversal to hoist selectors out of nested at-rules. The recursive approach with explicit path tracking is appropriate for this use case. The algorithm correctly:

  1. Identifies selectors within at-rules using type guards
  2. Builds the inverted structure with selectors at the top level
  3. Preserves the nesting path for each selector

99-123: LGTM! Type guards provide good runtime safety.

The three type guard functions (hasSelectorsProperty, isAtRuleKey, isAtRuleObject) add necessary runtime checks to validate the structure during hoisting. They follow TypeScript best practices for type predicates.


279-595: Excellent test coverage!

The test suite comprehensively covers:

  • Simple and complex selector hoisting scenarios
  • Nested at-rule structures (up to 3 levels deep)
  • Multiple selectors and at-rule combinations
  • Edge cases (empty inputs, malformed data, missing selectors)
  • Type guard behavior
  • Complex selector strings

This thorough coverage gives high confidence in the implementation's correctness.

Also applies to: 966-1122

@github-actions
Copy link
Contributor

github-actions bot commented Oct 4, 2025

Triggered from #248 by @​black7375.

Checking if we can fast forward main (d9445d5) to type-fixes (f1ca15c).

Target branch (main):

commit d9445d541aae580053755bfc3a5f9e07620241d0 (HEAD -> main, origin/main)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Thu Jul 31 00:00:00 2025 +0900

    Feat: `selector()` API implement #236

Pull request (type-fixes):

commit f1ca15cac81f1356b267060896b2c63cd871cfad (pull_request/type-fixes)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Thu Aug 7 00:00:00 2025 +0900

    Refactor: `hoistSelectors` makes to type-safe

It is possible to fast forward main (d9445d5) to type-fixes (f1ca15c). If you have write access to the target repository, you can add a comment with /fast-forward to fast forward main to type-fixes.

@black7375
Copy link
Contributor Author

/fast-forward

@github-actions
Copy link
Contributor

github-actions bot commented Oct 4, 2025

Triggered from #248 (comment) by @​black7375.

Trying to fast forward main (d9445d5) to type-fixes (f1ca15c).

Target branch (main):

commit d9445d541aae580053755bfc3a5f9e07620241d0 (HEAD -> main, origin/main)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Thu Jul 31 00:00:00 2025 +0900

    Feat: `selector()` API implement #236

Pull request (type-fixes):

commit f1ca15cac81f1356b267060896b2c63cd871cfad (pull_request/type-fixes)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Thu Aug 7 00:00:00 2025 +0900

    Refactor: `hoistSelectors` makes to type-safe

Fast forwarding main (d9445d5) to type-fixes (f1ca15c).

$ git push origin f1ca15cac81f1356b267060896b2c63cd871cfad:main
To https://github.com/mincho-js/mincho.git
   d9445d5..f1ca15c  f1ca15cac81f1356b267060896b2c63cd871cfad -> main

@github-actions github-actions bot merged commit f1ca15c into main Oct 4, 2025
12 checks passed
@github-actions github-actions bot deleted the type-fixes branch October 4, 2025 15:03
@github-actions github-actions bot mentioned this pull request Oct 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant