Skip to content

Feat: theme - Support alias method#272

Merged
github-actions[bot] merged 1 commit intomainfrom
theme-alias-api
Nov 4, 2025
Merged

Feat: theme - Support alias method#272
github-actions[bot] merged 1 commit intomainfrom
theme-alias-api

Conversation

@black7375
Copy link
Contributor

@black7375 black7375 commented Nov 4, 2025

Description

Implement alias method for theme

Related Issue

Summary by CodeRabbit

  • New Features
    • Extended the theme API surface with theme() function and fallbackVar() method for greater customization flexibility
    • Introduced alias() utility for semantic tokens, allowing selective CSS variable generation based on token paths
    • Enhanced semantic token resolution to support alternative references through the new alias mechanism, providing more control over CSS variable creation

Additional context

Checklist

@changeset-bot
Copy link

changeset-bot bot commented Nov 4, 2025

🦋 Changeset detected

Latest commit: 4a185b4

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

This PR includes changesets to release 4 packages
Name Type
@mincho-js/css Minor
@mincho-js/react Patch
@mincho-js/vite 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 Nov 4, 2025

Triggered from #272 by @​black7375.

Checking if we can fast forward main (50145b3) to theme-alias-api (4a185b4).

Target branch (main):

commit 50145b3eca703e9884113b58eecd0c6ecb8631d3 (HEAD -> main, origin/main)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Thu Sep 25 00:00:00 2025 +0900

    Feat: `theme` - Support `raw` method #268

Pull request (theme-alias-api):

commit 4a185b470a8d24ecc6badcb46ea4c0408e486a07 (pull_request/theme-alias-api)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Sat Sep 27 00:00:00 2025 +0900

    Feat: `theme` - Support `alias` method #270

It is possible to fast forward main (50145b3) to theme-alias-api (4a185b4). If you have write access to the target repository, you can add a comment with /fast-forward to fast forward main to theme-alias-api.

@coderabbitai
Copy link

coderabbitai bot commented Nov 4, 2025

Walkthrough

A changeset documents a minor version bump for @mincho-js/css. Core changes add an alias mechanism to semantic tokens in the theme API, enabling tokens to reference other tokens without creating separate CSS variables, while maintaining existing behavior for non-aliased tokens.

Changes

Cohort / File(s) Change Summary
Version Bump Documentation
.changeset/honest-dingos-push.md
Documents minor version update for @mincho-js/css with new theme API surface additions: theme() function and this.fallbackVar().
Theme Token Alias Mechanism
packages/css/src/theme/index.ts
Introduces alias(varReference: unknown): string method to ThemeSubFunctions for marking semantic tokens as aliases. Adds aliasMap and currentProcessingPath to TokenProcessingContext for tracking alias status during two-pass token resolution. Aliases skip CSS variable creation while preserving existing behavior for non-aliased tokens. Adds stripHash helper for hash removal in comparisons. Extends token resolution to propagate aliasMap through nested processing. Updates test coverage for alias reference validation.

Sequence Diagram(s)

sequenceDiagram
    participant Pass1 as Pass 1: Token Marking
    participant Context as TokenProcessingContext
    participant Pass2 as Pass 2: Token Resolution
    participant Output as CSS Output

    Pass1->>Context: Process semantic token getter
    Pass1->>Context: Call alias(varReference) if applicable
    Context->>Context: Mark path in aliasMap
    Pass1->>Context: Store currentProcessingPath

    Pass2->>Context: Resolve semantic token
    Context->>Context: Check if path in aliasMap
    
    alt Is Alias
        Context->>Output: Skip CSS variable creation
        Context->>Output: Use unhashed token reference
    else Not Alias
        Context->>Output: Create CSS variable
        Context->>Output: Set var() reference
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Attention areas:
    • Two-pass token resolution logic modifications and the interaction between Pass 1 (alias marking) and Pass 2 (conditional CSS variable creation)
    • stripHash helper correctness for hash removal in both CSS variable names and var() references
    • Propagation of aliasMap through nested token processing contexts to ensure consistency
    • Test coverage validation that aliased tokens genuinely skip CSS variable creation while non-aliased tokens maintain original behavior

Possibly related PRs

Poem

🐰 A token by alias, needs no CSS name,
We mark it in passes, no variables to claim!
Two-pass processing, clean and refined,
Semantic tokens linked, of similar kind.

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main feature addition: implementing the alias method for the theme API.
Description check ✅ Passed The description includes the required template sections with a clear purpose (implementing alias method) and related issue reference, though checklist is not populated.
✨ 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 theme-alias-api

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: 1

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

541-557: Consider refactoring to avoid module-level mutable state.

The module-level currentProcessingPath variable works for the current synchronous execution model but is a code smell that could cause issues if the code is ever called in parallel contexts or if execution order changes. Additionally, there's no validation that alias() is called within the correct context (inside a getter during pass 2).

Consider passing the current path through the context instead. For example, extend the context to include a getCurrentPath() function that's only available during getter execution:

interface TokenProcessingContext {
  prefix: string;
  path: string[];
  parentPath: string;
  cssVarMap: CSSVarMap;
  aliasMap: Set<string>;
  currentPath?: string[]; // Add current processing path to context
}

function createAliasFunction(context: TokenProcessingContext) {
  return function alias(varReference: unknown): string {
    // Validate that we're in a getter context
    if (!context.currentPath) {
      throw new Error('alias() can only be called within a token getter');
    }
    
    const currentPathStr = context.currentPath.join(".");
    context.aliasMap.add(currentPathStr);
    return String(varReference);
  };
}

Then update the getter execution in resolveSemanticTokens:

if (typeof descriptor.get === "function") {
  // Set the current path in context
  const updatedContext = { ...context, currentPath };
  
  try {
    const computedValue = descriptor.get.call(resolvedTokens);
    // ... rest of logic
  } finally {
    // Context is naturally cleaned up as it goes out of scope
  }
  continue;
}

However, this would require passing the context to the getter functions, which may not fit the current API design. The current approach is acceptable for now.


541-557: Consider adding JSDoc for the alias mechanism.

The createAliasFunction and currentProcessingPath pattern could benefit from more detailed documentation explaining:

  • When and how alias() should be used
  • The constraint that it only works within getters during pass 2
  • Why module-level state is used (coupling with resolveSemanticTokens)

For example:

+/**
+ * Creates a function that marks semantic tokens as aliases.
+ * 
+ * When a token is marked as an alias, it references another token's CSS variable
+ * directly without creating its own CSS variable. This is useful for semantic
+ * tokens that should simply point to base tokens.
+ * 
+ * Note: alias() must be called within a token getter during pass 2 resolution.
+ * The current processing path is tracked via module-level state that's set by
+ * resolveSemanticTokens before each getter execution.
+ * 
+ * @param context - The token processing context containing the aliasMap
+ * @returns A function that marks the current token path as an alias
+ * 
+ * @example
+ * ```typescript
+ * semantic: {
+ *   get primary(): string {
+ *     return this.alias(this.color.base.blue);
+ *   }
+ * }
+ * ```
+ */
 function createAliasFunction(context: TokenProcessingContext) {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 50145b3 and 4a185b4.

📒 Files selected for processing (2)
  • .changeset/honest-dingos-push.md (1 hunks)
  • packages/css/src/theme/index.ts (11 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
.changeset/honest-dingos-push.md (1)
packages/css/src/theme/types.ts (2)
  • myTheme (331-415)
  • it (223-416)
🪛 markdownlint-cli2 (0.18.1)
.changeset/honest-dingos-push.md

5-5: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🔇 Additional comments (7)
packages/css/src/theme/index.ts (7)

39-39: LGTM!

The alias method addition follows the same pattern as the existing raw() utility and integrates cleanly with the ThemeSubFunctions interface.


129-138: LGTM!

The context initialization properly sets up the aliasMap tracking structure for the two-pass token resolution algorithm.


157-162: LGTM!

The alias utility is properly configured as a non-enumerable helper function, following the same pattern as the existing raw utility.


170-177: LGTM!

The stripHash utility correctly removes hash suffixes from CSS variable names using an appropriate regex pattern.


241-242: LGTM!

The aliasMap is correctly propagated through all nested token processing contexts, ensuring consistent alias tracking across the entire token tree.

Also applies to: 304-305, 379-380, 392-393


338-359: Verify the getter execution context is always properly cleaned up.

The currentProcessingPath is set before getter execution and cleared after. While this works, the pattern is fragile—if an exception occurs during getter execution or if code is added between lines 342 and 344, the path might not be cleared properly.

Consider wrapping the getter execution in a try-finally block:

     // Handle getters (semantic tokens)
     if (typeof descriptor.get === "function") {
       // Set the current path for alias() to access
       currentProcessingPath = currentPath;
-      // Call getter with resolvedTokens as this context
-      // This allows semantic tokens to reference other tokens
-      const computedValue = descriptor.get.call(resolvedTokens);
-      // Clear the current path after getter execution
-      currentProcessingPath = [];
+      try {
+        // Call getter with resolvedTokens as this context
+        // This allows semantic tokens to reference other tokens
+        const computedValue = descriptor.get.call(resolvedTokens);
+        
-      // Check if this path is marked as an alias
-      const currentPathStr = currentPath.join(".");
+        // Check if this path is marked as an alias
+        const currentPathStr = currentPath.join(".");

-      if (context.aliasMap.has(currentPathStr)) {
-        // Don't create a CSS variable for aliases
-        // Just update resolvedTokens with the aliased reference (unhashed)
-        const unhashedValue = stripHash(computedValue);
-        setByPath(resolvedTokens, currentPath, unhashedValue);
-      } else {
-        // Normal flow: create CSS variable
-        const cssVar = getCSSVarByPath(varPath, context);
-        vars[cssVar] = computedValue;
-        setByPath(resolvedTokens, currentPath, computedValue);
+        if (context.aliasMap.has(currentPathStr)) {
+          // Don't create a CSS variable for aliases
+          // Just update resolvedTokens with the aliased reference (unhashed)
+          const unhashedValue = stripHash(computedValue);
+          setByPath(resolvedTokens, currentPath, unhashedValue);
+        } else {
+          // Normal flow: create CSS variable
+          const cssVar = getCSSVarByPath(varPath, context);
+          vars[cssVar] = computedValue;
+          setByPath(resolvedTokens, currentPath, computedValue);
+        }
+      } finally {
+        // Clear the current path after getter execution
+        currentProcessingPath = [];
       }
       continue;
     }

946-1000: LGTM!

The test case comprehensively validates the alias functionality:

  • Confirms aliased tokens don't generate CSS variables
  • Confirms non-aliased tokens continue to generate CSS variables as expected
  • Validates all resolved tokens use correct var() references

"@mincho-js/css": minor
---

**theme**
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use a proper heading instead of bold emphasis.

Markdownlint flags this line because **theme** uses emphasis rather than a heading. For better document structure, use a proper heading level.

Apply this diff:

-**theme**
+## theme
📝 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
**theme**
## theme
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

5-5: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🤖 Prompt for AI Agents
.changeset/honest-dingos-push.md around line 5: the line uses bold emphasis
"**theme**" instead of a markdown heading; replace it with an appropriate
heading (e.g., "## theme" or "# theme" depending on desired level) so the file
uses a proper heading syntax and satisfies markdownlint.

@black7375
Copy link
Contributor Author

/fast-forward

@github-actions
Copy link
Contributor

github-actions bot commented Nov 4, 2025

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

Trying to fast forward main (50145b3) to theme-alias-api (4a185b4).

Target branch (main):

commit 50145b3eca703e9884113b58eecd0c6ecb8631d3 (HEAD -> main, origin/main)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Thu Sep 25 00:00:00 2025 +0900

    Feat: `theme` - Support `raw` method #268

Pull request (theme-alias-api):

commit 4a185b470a8d24ecc6badcb46ea4c0408e486a07 (pull_request/theme-alias-api)
Author: alstjr7375 <alstjr7375@daum.net>
Date:   Sat Sep 27 00:00:00 2025 +0900

    Feat: `theme` - Support `alias` method #270

Fast forwarding main (50145b3) to theme-alias-api (4a185b4).

$ git push origin 4a185b470a8d24ecc6badcb46ea4c0408e486a07:main
To https://github.com/mincho-js/mincho.git
   50145b3..4a185b4  4a185b470a8d24ecc6badcb46ea4c0408e486a07 -> main

@github-actions github-actions bot merged commit 4a185b4 into main Nov 4, 2025
12 checks passed
@github-actions github-actions bot deleted the theme-alias-api branch November 4, 2025 16:50
@github-actions github-actions bot mentioned this pull request Nov 3, 2025
@coderabbitai coderabbitai bot mentioned this pull request Nov 11, 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