Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Props hoc #3084

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open

Props hoc #3084

wants to merge 4 commits into from

Conversation

hashiqi12138
Copy link
Contributor

@hashiqi12138 hashiqi12138 commented Mar 8, 2025

PR

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

What is the current behavior?

为 vue3及 vue2 增加 WithDesignConfigPropsDefineComponent 方法

组件中引入 defineComponent 的地方改为 WithDesignConfigPropsDefineComponent
import { $props, $prefix, $setup, WithDesignConfigPropsDefineComponent as defineComponent } from '@opentiny/vue-common'

目前仅 Button 进行了调整,Vue2,Vue3中都达到了预期的效果,Button 组件Vue3版本单元测试也能正常通过

Issue Number: #2940

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Enhanced UI components now support global design configuration, offering improved customization and consistent styling—especially noticeable in button behaviors.
    • Introduced a new <config-provider> component for better button property configuration.
    • Added a new Higher-Order Component (HOC) for improved design configuration integration.
  • Tests

    • Upgraded the unit testing experience with an interactive testing interface for more intuitive validation.

Copy link

coderabbitai bot commented Mar 8, 2025

Walkthrough

This pull request introduces design configuration enhancements across components. The button demo now wraps <tiny-button> components within a new <config-provider> and <tiny-row> and defines a design data property. The unit test command in package.json is updated to use vitest --ui, with an upgraded dependency. Additionally, new Higher-Order Components (HOC) and helper functions—DesignConfigPropsHOC and WithDesignConfigPropsDefineComponent—are added to both Vue 2 and Vue 3 adapter modules for integrating global design configurations. The button component import is updated to use the new HOC.

Changes

File(s) Changes
examples/.../button/basic-usage.vue Wrapped <tiny-button> components with <config-provider> inside <tiny-row>; added design data property (with resetTime: 0, size: 'mini').
examples/vue3/package.json Updated test script from "vitest" to "vitest --ui" and upgraded @vitest/ui from ^0.31.0 to ^2.1.9.
packages/vue-common/src/adapter/vue{2,2.7,3}/*
packages/vue-common/src/index.ts
Added new HOC DesignConfigPropsHOC and helper function WithDesignConfigPropsDefineComponent for injecting global design configurations; updated module exports accordingly.
packages/vue/src/button/src/index.ts Replaced the direct import of defineComponent with WithDesignConfigPropsDefineComponent as defineComponent to incorporate design configuration.
internals/unplugin-hoc-plugin/... Introduced new package @opentiny-internal/unplugin-hoc-plugin with various files for plugin functionality, including configuration, types, and integration with build tools.
package.json Added script for building the @opentiny-internal/unplugin-hoc-plugin and a patched dependency for @opentiny/vue-vite-import.

Sequence Diagram(s)

Loading
sequenceDiagram
    participant User
    participant CP as ConfigProvider
    participant TR as TinyRow
    participant TB as TinyButton

    User->>CP: Initiate button interaction
    CP->>TR: Wraps TinyButton(s)
    TR->>TB: Supplies design settings (resetTime=0, size='mini')
    TB->>User: Renders configured button
Loading
sequenceDiagram
    participant BC as BaseComponent
    participant HOC as WithDesignConfigPropsDefineComponent
    participant GC as GlobalDesignConfig
    participant Render as EnhancedComponent

    BC->>HOC: Wrapped by HOC
    HOC->>GC: Inject global design config
    GC-->>HOC: Returns design properties
    HOC->>Render: Merge props and render component
    Render->>User: Display enhanced component

Suggested labels

enhancement

Suggested reviewers

  • zzcr

Poem

I'm hopping through lines of code so bright,
With buttons wrapped in config light.
HOCs and functions join the parade,
In Vue's realm, fresh changes are made.
CodeRabbit hops with glee and cheer,
Celebrating each update far and near!
🐰✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

examples/sites/demos/pc/app/button/basic-usage.vue

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-vue".

(The package "eslint-plugin-vue" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-vue@latest --save-dev

The plugin "eslint-plugin-vue" was referenced from the config file in ".eslintrc.js » @antfu/eslint-config » @antfu/eslint-config-vue".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

examples/vue3/vite.config.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-vue".

(The package "eslint-plugin-vue" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-vue@latest --save-dev

The plugin "eslint-plugin-vue" was referenced from the config file in ".eslintrc.js » @antfu/eslint-config » @antfu/eslint-config-vue".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

internals/unplugin-hoc-plugin/src/esbuild.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-vue".

(The package "eslint-plugin-vue" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-vue@latest --save-dev

The plugin "eslint-plugin-vue" was referenced from the config file in ".eslintrc.js » @antfu/eslint-config » @antfu/eslint-config-vue".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

  • 13 others
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

Walkthrough

This PR introduces a new feature by adding the WithDesignConfigPropsDefineComponent method for both Vue 2 and Vue 3. It replaces instances of defineComponent with WithDesignConfigPropsDefineComponent in components, specifically adjusting the Button component to achieve the desired effect in both Vue 2 and Vue 3 environments.

Changes

Files Summary
examples/sites/demos/pc/app/button/basic-usage.vue Wrapped tiny-button components with config-provider and added design configuration.
packages/vue-common/src/adapter/vue2.7/hoc.tsx
packages/vue-common/src/adapter/vue2/hoc.tsx
packages/vue-common/src/adapter/vue3/hoc.tsx
Added DesignConfigPropsHOC function to inject design configuration into components.
packages/vue-common/src/adapter/vue2.7/index.ts
packages/vue-common/src/adapter/vue2/index.ts
packages/vue-common/src/adapter/vue3/index.ts
Introduced WithDesignConfigPropsDefineComponent function to wrap components with design configuration.
packages/vue-common/src/index.ts Exported WithDesignConfigPropsDefineComponent from adapter.
packages/vue/src/button/src/index.ts Replaced defineComponent with WithDesignConfigPropsDefineComponent.

methods: {
// 解包可能存在的响应式对象
unwrap(config) {
if (config && typeof config === 'object' && 'value' in config) {

Choose a reason for hiding this comment

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

Ensure that the unwrap method correctly handles all possible types of reactive objects to avoid unexpected behavior.

Copy link

github-actions bot commented Mar 8, 2025

[e2e-test-warn]
The component to be tested is missing.

The title of the Pull request should look like "fix(vue-renderless): [action-menu, alert] fix xxx bug".

Please make sure you've read our contributing guide

methods: {
// 解包可能存在的响应式对象
unwrap(config) {
if (config && typeof config === 'object' && 'value' in config) {

Choose a reason for hiding this comment

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

Ensure that the unwrap method correctly handles all possible types of reactive objects to avoid unexpected behavior.

// 获取组件级配置和全局配置(inject需要带有默认值,否则控制台会报警告)
let globalDesignConfig = hooks.inject(design.configKey, {})
// globalDesignConfig 可能是响应式对象,比如 computed
globalDesignConfig = globalDesignConfig?.value || globalDesignConfig || {}

Choose a reason for hiding this comment

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

Ensure that the globalDesignConfig is correctly unwrapped to handle all possible types of reactive objects to avoid unexpected behavior.

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 (3)
packages/vue-common/src/adapter/vue2/hoc.tsx (3)

14-28: Consider adding error handling for method exposure

The method exposure implementation watches for changes to innerRef and copies methods to the wrapper instance. While functional, this approach could be more robust.

Consider adding error handling to prevent potential issues when accessing methods:

created() {
  // 暴露实例方法
  this.$watch(
    () => this.innerRef,
    (val) => {
      if (val) {
        Object.keys(val).forEach((key) => {
          if (!(key in this)) {
+           try {
              this[key] = val[key]
+           } catch (err) {
+             console.warn(`[DesignConfigHOC] Failed to expose method ${key}:`, err)
+           }
          }
        })
      }
    }
  )
}

34-48: Consider adding component name to HOC for better debugging

The HOC name is currently hardcoded as 'DesignConfigHOC', which may make debugging difficult when multiple components are wrapped.

Consider including the base component name in the HOC name:

export default function DesignConfigPropsHOC(BaseComponent) {
+  const componentName = BaseComponent.name || (BaseComponent.options && BaseComponent.options.name) || 'Unknown'
  return Vue.extend({
-    name: 'DesignConfigHOC',
+    name: `DesignConfigHOC(${componentName})`,
    functional: false,
    // rest of the implementation...

50-57: Enhance unwrap method to handle more reactive types

The current implementation may not handle all types of reactive objects in Vue ecosystem.

Consider expanding the unwrap method to handle more types of reactive objects:

unwrap(config) {
  if (config && typeof config === 'object') {
    // Handle Vue 2 reactivity
    if ('value' in config && typeof config.value !== 'undefined') {
      return config.value
    }
+   // Handle ref-like objects
+   if (typeof config.getValue === 'function') {
+     return config.getValue()
+   }
  }
  return config || {}
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd468ac and 4d9f398.

📒 Files selected for processing (10)
  • examples/sites/demos/pc/app/button/basic-usage.vue (3 hunks)
  • examples/vue3/package.json (3 hunks)
  • packages/vue-common/src/adapter/vue2.7/hoc.tsx (1 hunks)
  • packages/vue-common/src/adapter/vue2.7/index.ts (2 hunks)
  • packages/vue-common/src/adapter/vue2/hoc.tsx (1 hunks)
  • packages/vue-common/src/adapter/vue2/index.ts (2 hunks)
  • packages/vue-common/src/adapter/vue3/hoc.tsx (1 hunks)
  • packages/vue-common/src/adapter/vue3/index.ts (2 hunks)
  • packages/vue-common/src/index.ts (2 hunks)
  • packages/vue/src/button/src/index.ts (1 hunks)
🔇 Additional comments (27)
packages/vue/src/button/src/index.ts (1)

12-12: Import updated to use WithDesignConfigPropsDefineComponent

The import statement has been modified to use the new WithDesignConfigPropsDefineComponent (aliased as defineComponent) instead of the direct defineComponent from @opentiny/vue-common. This change enables the Button component to support global design configurations.

packages/vue-common/src/adapter/vue3/index.ts (2)

16-16: Added DesignConfigPropsHOC import

This import is required for the new WithDesignConfigPropsDefineComponent function.


481-488: Added WithDesignConfigPropsDefineComponent function

This new function implements a Higher-Order Component pattern to enhance components with design configuration capabilities. The implementation correctly wraps the component definition with the DesignConfigPropsHOC after processing it with Vue's defineComponent.

The commented example code also provides good guidance on usage.

examples/sites/demos/pc/app/button/basic-usage.vue (4)

5-12: Added ConfigProvider to demonstrate design prop configuration

The basic buttons section has been wrapped with the new ConfigProvider component, demonstrating how to provide design configuration to button components. This serves as an excellent usage example for the new feature.


45-45: Added ConfigProvider to imports

The ConfigProvider component has been properly imported from the @opentiny/vue package.


52-54: Registered ConfigProvider in components object

ConfigProvider has been correctly added to the components registration.


63-72: Added design configuration to component data

This data property defines the design configuration that will be provided to all Button components within the ConfigProvider. The structure is well-organized with proper nesting for component-specific props.

examples/vue3/package.json (2)

15-15: Updated unit test command to use the UI interface

The unit test command now includes the --ui flag to enable the Vitest UI interface, which provides a better testing experience.


40-40: Updated @vitest/ui dependency to a newer version

The @vitest/ui package has been upgraded from ^0.31.0 to ^2.1.9, which is a significant version bump that provides newer features and bug fixes for the test UI interface.

packages/vue-common/src/adapter/vue2/index.ts (2)

6-6: Import addition looks good

This correctly imports the DesignConfigPropsHOC from the local HOC implementation file.


346-353: Well-structured HOC implementation with good documentation

The implementation of WithDesignConfigPropsDefineComponent follows the correct pattern for a higher-order component that wraps Vue's defineComponent. The commented example provides clear guidance on how to use this new function.

A few observations:

  • The function correctly takes a BaseComponent as input
  • It properly composes the HOC with defineComponent
  • TypeScript typing is correctly applied
  • The example demonstrates the intended use case

This implementation will allow components to receive design configuration properties while maintaining compatibility with Vue's component definition API.

packages/vue-common/src/adapter/vue2.7/index.ts (2)

16-16: Import addition looks good

This correctly imports the DesignConfigPropsHOC from the Vue 2.7-specific HOC implementation.


345-352: Consistent implementation across Vue versions

The implementation of WithDesignConfigPropsDefineComponent for Vue 2.7 matches the Vue 2 implementation, ensuring consistent behavior across Vue versions. The comment example is also helpful for developers.

packages/vue-common/src/adapter/vue3/hoc.tsx (4)

1-4: Appropriate imports for Vue 3 HOC

The imports are well structured:

  • Using Vue 3's type system with SetupContext
  • Importing design utilities and hooks from the common index
  • Importing the helper function getComponentName from the adapter

This sets up the necessary dependencies for the HOC implementation.


5-20: Well-designed global configuration injection

The HOC implementation correctly:

  1. Preserves the original component's properties
  2. Sets up a ref for exposing the inner component
  3. Injects the global design configuration with a default empty object
  4. Handles potentially reactive configuration objects
  5. Retrieves component-specific configuration
  6. Merges configuration props with passed attrs

This approach ensures design configurations are properly injected while maintaining component functionality.


20-33: Effective method exposure through proxy pattern

The implementation uses a Proxy to expose the inner component's methods, which is a clean approach to forward method calls and property access to the wrapped component. This maintains the component's public API.


34-43: Clean rendering implementation for Vue 3

The render function correctly:

  1. Returns a JSX implementation of the BaseComponent
  2. Spreads the merged props to the component
  3. Passes the inner ref for method exposure
  4. Passes through slots

This completes the HOC pattern appropriately for Vue 3's composition API.

packages/vue-common/src/adapter/vue2.7/hoc.tsx (6)

1-3: Appropriate imports for Vue 2.7 HOC

The imports include Vue and the required design utilities while keeping the dependencies minimal.


4-14: Effective dependency injection setup

The HOC implementation correctly:

  1. Uses Vue.extend for Vue 2.7 compatibility
  2. Sets up dependency injection for the design configuration
  3. Provides a default empty object to prevent errors

This approach ensures consistent behavior with Vue 2.7's component model.


14-33: Clean method exposure pattern

The created hook and watcher setup provide an elegant solution for exposing the inner component's methods to the outer component instance. The data initialization for innerRef is appropriately defined.


34-48: Well-designed computed properties

The computed properties correctly:

  1. Extract the component name by removing the prefix
  2. Handle the unwrapping of potentially reactive configuration objects
  3. Merge component-specific props with passed attributes

This ensures the design configuration is properly applied to the component.


49-57: Robust configuration handling

The unwrap method properly handles different types of configuration objects, including reactive objects with a .value property. This ensures compatibility with both direct objects and computed properties.


58-73: Appropriate render implementation for Vue 2.7

The render function correctly:

  1. Creates the BaseComponent with h function
  2. Sets up the ref callback to store the component instance
  3. Passes merged props as attrs
  4. Forwards listeners and slots

This completes the HOC pattern appropriately for Vue 2.7's rendering model.

packages/vue-common/src/index.ts (2)

24-24: LGTM: Import line updated to include WithDesignConfigPropsDefineComponent

The import now includes the new Higher-Order Component for design configuration, which aligns with the PR objective.


40-40: LGTM: Export updated to include WithDesignConfigPropsDefineComponent

The export correctly makes the new HOC available to other components in the application.

packages/vue-common/src/adapter/vue2/hoc.tsx (2)

4-73: Implementation of DesignConfigPropsHOC looks good

This HOC effectively wraps components with design configuration capabilities, allowing for global design props to be merged with component-specific attributes.

The implementation:

  1. Correctly injects the global design configuration
  2. Computes component name by removing the prefix
  3. Merges component-specific design props with passed attributes
  4. Handles exposing inner component methods to the wrapper component
  5. Properly renders the base component with all necessary props and slots

58-71: LGTM: Render function implementation

The render function correctly passes all necessary props, listeners, and slots to the base component while setting up the reference for method exposure.

@@ -9,7 +9,7 @@
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import { $props, $prefix, $setup, defineComponent } from '@opentiny/vue-common'
import { $props, $prefix, $setup, WithDesignConfigPropsDefineComponent as defineComponent } from '@opentiny/vue-common'
Copy link
Member

Choose a reason for hiding this comment

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

如果这样修改可能会对现有业务造成影响,你这操作相当于包了一层组件转发下props,能不能通过某一个全局配置可以让用户自己选择是否开启这个功能,不要对存量业务造成影响

@kagol kagol added the enhancement New feature or request (功能增强) label Mar 24, 2025
@hashiqi12138
Copy link
Contributor Author

我看了下 vue-common 中的逻辑,目前组件应该都是两层组件的,可以在 vue-common 中统一处理第一层接收进来的 props,

我目前的思路是:
1、先获取当前组件或者上级组件的 props 配置,通过配置得出各个 prop 对应的默认值,再结合传入的 prop 值以及 designConfig 中注入的值,
2、判断 当前 props 值是否是默认值,如果是默认值且与 designConfig 注入的值不同,则将当前 props 改为 designConfig 的值,并传入下一层组件,
3、如果当前 prop 值不是默认值,则表明用户传入了值,此时忽略 designConfig 的值,以用户传入值为准

需要兼容之前的业务,可以全局增加公共 prop tiny_props_hoc,如果第一层组件传入了改 props,才执行替换逻辑,否则走原本逻辑,对原有业务不影响

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


I looked at the logic in vue-common. Currently, the components should be of two-layer components. The props received in the first layer can be uniformly processed in vue-common.

My current thinking is:

  1. First get the props configuration of the current component or the superior component, obtain the default values ​​corresponding to each prop through configuration, and then combine the passed prop value and the value injected in designConfig.
  2. Determine whether the current props value is the default value. If it is the default value and is different from the value injected by designConfig, change the current props to the value of designConfig and pass it into the next layer of component.
  3. If the current prop value is not the default value, it means that the user has passed in the value. At this time, the value of designConfig is ignored, and the value passed in by the user shall prevail.

It needs to be compatible with previous businesses, and you can add public prop tiny_props_hoc globally. If the first layer component passes in modified props, the replacement logic will be executed. Otherwise, the original logic will not affect the original business.

@github-actions github-actions bot removed the enhancement New feature or request (功能增强) label Mar 25, 2025
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: 2

🧹 Nitpick comments (14)
internals/unplugin-virtual-template/src/core/transformVirtualTemplate.ts (4)

17-19: Typo in property name "tiny_experimetal_props_hoc"

The property name contains a typo: "experimetal" instead of "experimental". This should be corrected for consistency and to avoid confusion. Search for this property name throughout the codebase to ensure all instances are updated.

-  if(props.tiny_experimetal_props_hoc) {
+  if(props.tiny_experimental_props_hoc) {

35-39: Duplicate conditional logic for Props HOC feature

The conditional logic checking for props.tiny_experimetal_props_hoc is duplicated here and in lines 17-21. Consider extracting this to a helper function for better maintainability.

// Add this helper function before the result declaration
+ const getImportGlob = (pattern, props) => {
+   if(props.tiny_experimental_props_hoc) {
+     return import.meta.glob(pattern, { eager: true, query: { withPropsHOC: true } })
+   } else {
+     return import.meta.glob(pattern, { eager: true })
+   }
+ }

// Then use it in both places
-  if(props.tiny_experimetal_props_hoc) {
-    result = import.meta.glob('./{pc,mobile,mobile-first}.vue', { eager: true, query: { withPropsHOC: true } })
-  } else {
-    result = import.meta.glob('./{pc,mobile,mobile-first}.vue', { eager: true })
-  }
+  result = getImportGlob('./{pc,mobile,mobile-first}.vue', props)

46-47: Remove debugging console.log statement

Remove the console.log(props) statement as it shouldn't be included in production code. Consider using proper logging with log levels if debugging information is necessary.

-  console.log(props)
-

30-40: Update function signature to match actual usage

Since the props parameter is now required for the conditional logic, you should update the function signature to handle the case when it's not provided. This will prevent unexpected errors if the component is used without passing the props.

-const ${localName} = (mode, props) => {
+const ${localName} = (mode, props = {}) => {
  let result

  // #v-ifndef VITE_TINY_MODE
    const params = {}
  if(props.tiny_experimetal_props_hoc) {
    result = import.meta.glob('./{pc,mobile,mobile-first}.vue', { eager: true, query: { withPropsHOC: true } })
  } else {
    result = import.meta.glob('./{pc,mobile,mobile-first}.vue', { eager: true })
  }
internals/unplugin-hoc-plugin/test/index.test.ts (2)

4-23: Add tests for edge cases in the transformVirtualTemplate function

The current tests don't cover edge cases such as how the function behaves when:

  1. The input doesn't match the expected format
  2. Different combinations of props values are provided

Consider adding tests for these scenarios to ensure robust behavior.

Example additional tests:

it('handles non-matching input correctly', () => {
  const input = "import template from 'some-other-import'";
  expect(transformVirtualTemplate(input)).toBe(input); // Should return unchanged
});

it('handles multiple virtual template imports in the same file', () => {
  const input = `
    import template1 from 'virtual:template?pc'
    import template2 from 'virtual:template?mobile'
  `;
  const result = transformVirtualTemplate(input);
  expect(result.match(/const template\d+/g).length).toBe(2);
});

25-43: Consider adding functional tests beyond snapshots

While snapshot tests are useful for detecting unexpected changes, they don't explicitly verify that the transformed code functions as expected. Consider adding tests that actually evaluate the generated code with various inputs to verify its runtime behavior.

Example approach for more complete testing:

it('generated function behaves correctly with different props', () => {
  // This is a more advanced test that would require:
  // 1. A mock for import.meta.glob
  // 2. A way to evaluate the generated function
  // 3. Assertions on the expected behavior

  // This might be better as an integration test that:
  // - Creates a temporary file
  // - Applies the transformation
  // - Uses the resulting code in a test Vue component
  // - Verifies the component behavior
});
patches/@opentiny__vue-vite-import@1.2.0.patch (1)

11-14: Improved module ID handling for import with query parameters

The patch correctly addresses the handling of module IDs with query strings by introducing idWithoutQuery. This ensures that files with the ?withPropsHOC=true query parameter are properly processed.

Consider using a more general approach to handle query strings in case other query parameters are introduced in the future:

-const idWithoutQuery = id.replace('?withPropsHOC=true', '')
+const idWithoutQuery = id.split('?')[0]

This would handle any query string, not just the specific ?withPropsHOC=true parameter.

internals/unplugin-hoc-plugin/src/types.ts (1)

1-18: Well-designed TypeScript type definitions for plugin options

The type definitions provide a clear contract for configuring the plugin:

  1. Options interface with well-documented defaults for include/exclude patterns
  2. UserOptions as a partial of Options allows for optional user configuration
  3. ResolvedOptions provides type safety for the resolved configuration

The use of FilterPattern from @rollup/pluginutils is appropriate for defining include/exclude patterns, following the standard practice in Rollup/Vite plugins.

Consider adding JSDoc comments for the UserOptions and ResolvedOptions types to explain their purpose, similar to the documentation for properties in the Options interface.

internals/unplugin-hoc-plugin/src/index.ts (2)

14-21: Consider removing console.log comments

The code contains commented out console.log statements that should be removed before merging to production.

-      // console.log(filename, query)
-      if (filename.endsWith('.vue') && query) {
-        // console.log(id)
+      if (filename.endsWith('.vue') && query) {
         const params = new URLSearchParams(query)
         if (params.has('withPropsHOC')) {
-          // console.log('enter')

40-48: Consider adding documentation comments

This plugin implements an important feature for props handling, but lacks documentation comments to explain the purpose and usage of the transformation.

 export default createUnplugin<UserOptions>((options = {}) => {
   const filter = createFilter(options.include || ['**/*'], options.exclude || [])

   return {
     name: '@opentiny/unplugin-hoc-plugin',
     enforce: 'pre',
     transformInclude(id) {
       return filter(id)
     },
+    /**
+     * Transforms Vue component files to use WithDesignConfigPropsDefineComponent.
+     * This enables props to be enhanced with design configuration values while maintaining backward compatibility.
+     * Only transforms files with the 'withPropsHOC' query parameter.
+     * 
+     * @param code - Source code content
+     * @param id - File identifier with potential query parameters
+     * @returns Transformed code or null if no transformation needed
+     */
     transform(code, id) {
packages/vue-common/src/adapter/vue3/hoc.tsx (4)

18-19: Document the prop merging strategy.

The current implementation merges designConfigProps with attrs, correctly prioritizing user-provided attributes over design configuration. Consider adding a comment to explicitly document this prioritization strategy for maintainability.

      const designConfig = globalDesignConfig?.components?.[getComponentName().replace($prefix, '')]
      const designConfigProps = designConfig?.props || {}
+     // Priority: user-provided attributes (attrs) > design configuration props
      const mergedProps = { ...designConfigProps, ...attrs }

16-17: Add error handling for component name resolution.

The current implementation assumes getComponentName() will always return a valid string. Consider adding defensive code to handle cases where the component name might not be correctly determined.

      globalDesignConfig = globalDesignConfig?.value || globalDesignConfig || {}
-      const designConfig = globalDesignConfig?.components?.[getComponentName().replace($prefix, '')]
+      const componentName = getComponentName()
+      const designConfig = componentName ? globalDesignConfig?.components?.[componentName.replace($prefix, '')] : {}
      const designConfigProps = designConfig?.props || {}

46-52: Remove commented out code.

The commented-out code provides an alternative implementation that's not being used. Consider removing it to improve code cleanliness and maintainability.

      })

-      // return () => {
-      //   return (
-      //     <BaseComponent {...mergedProps} ref={innerRef}>
-      //       {slots}
-      //     </BaseComponent>
-      //   )
-      // }
    }

34-45:

❓ Verification inconclusive

Consider directly passing slots to $setup.

The current implementation passes the entire context to $setup but then manually uses slots in the template function. Consider passing slots directly to the template for consistency with how they're used.

      return $setup({
        props,
        context,
        template: () => {
          return (
            <BaseComponent {...mergedProps} ref={innerRef}>
-              {slots}
+              {Object.entries(slots).map(([name, slot]) => 
+                slot && name === 'default' ? slot() : slot && <template slot={name}>{slot()}</template>
+              )}
            </BaseComponent>
          )
        }
      })

Let's check how slots are typically handled in other components:


🏁 Script executed:

#!/bin/bash
# Search for slot usage patterns in existing components
echo "Checking slot usage patterns in components..."
rg -i "slots" --type tsx --context 5 | grep -A 5 "return ("

Length of output: 188


Below is a new shell script to re-check the slot usage patterns while targeting the appropriate file type. It appears that searching for “tsx” didn’t work because that file type wasn’t recognized. This script uses the “typescriptreact” type (which covers TSX files) so we can see how slots are handled elsewhere.

Please run this script and verify if the slot usage in similar components follows the pattern of passing slots directly to $setup (or via a similar standardized approach) rather than manually mapping them in a template. Once you have the output, we can finalize whether the suggested diff is consistent with the rest of the codebase.


🏁 Script executed:

#!/bin/bash
echo "Re-checking slot usage patterns in components with typescriptreact file type..."
rg -t typescriptreact "slots" --context 5 | grep -A 5 "return ("

Length of output: 395


Action Required: Verify Consistent Slot Handling

The proposed diff changes how slots are passed by mapping them directly in the template instead of simply forwarding the context. However, our automated search for similar slot usage patterns in the repository was inconclusive. Please manually verify that this approach is consistent with slot handling in other components, and that it doesn’t inadvertently alter behavior elsewhere.

  • File: packages/vue-common/src/adapter/vue3/hoc.tsx (lines 34–45)
  • Suggestion: Instead of manually inserting {slots}, update the code to directly pass slots according to the diff snippet below.
      return $setup({
        props,
        context,
        template: () => {
          return (
            <BaseComponent {...mergedProps} ref={innerRef}>
-              {slots}
+              {Object.entries(slots).map(([name, slot]) => 
+                slot && name === 'default' ? slot() : slot && <template slot={name}>{slot()}</template>
+              )}
            </BaseComponent>
          )
        }
      })

Please review and confirm that this change aligns with how slots are managed throughout the project.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4d9f398 and f4031d4.

⛔ Files ignored due to path filters (1)
  • internals/unplugin-hoc-plugin/test/__snapshots__/index.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (22)
  • examples/sites/demos/pc/app/button/basic-usage.vue (3 hunks)
  • examples/vue3/package.json (3 hunks)
  • examples/vue3/vite.config.ts (1 hunks)
  • internals/unplugin-hoc-plugin/README.md (1 hunks)
  • internals/unplugin-hoc-plugin/package.json (1 hunks)
  • internals/unplugin-hoc-plugin/scripts/postbuild.ts (1 hunks)
  • internals/unplugin-hoc-plugin/src/esbuild.ts (1 hunks)
  • internals/unplugin-hoc-plugin/src/index.ts (1 hunks)
  • internals/unplugin-hoc-plugin/src/nuxt.ts (1 hunks)
  • internals/unplugin-hoc-plugin/src/rollup.ts (1 hunks)
  • internals/unplugin-hoc-plugin/src/types.ts (1 hunks)
  • internals/unplugin-hoc-plugin/src/vite.ts (1 hunks)
  • internals/unplugin-hoc-plugin/src/webpack.ts (1 hunks)
  • internals/unplugin-hoc-plugin/test/index.test.ts (1 hunks)
  • internals/unplugin-hoc-plugin/tsconfig.json (1 hunks)
  • internals/unplugin-hoc-plugin/tsup.config.ts (1 hunks)
  • internals/unplugin-virtual-template/src/core/transformVirtualTemplate.ts (1 hunks)
  • package.json (2 hunks)
  • packages/vue-common/src/adapter/vue3/hoc.tsx (1 hunks)
  • packages/vue-common/src/index.ts (5 hunks)
  • packages/vue/src/button/src/index.ts (2 hunks)
  • patches/@opentiny__vue-vite-import@1.2.0.patch (1 hunks)
✅ Files skipped from review due to trivial changes (10)
  • internals/unplugin-hoc-plugin/src/webpack.ts
  • internals/unplugin-hoc-plugin/src/esbuild.ts
  • examples/vue3/vite.config.ts
  • internals/unplugin-hoc-plugin/src/rollup.ts
  • internals/unplugin-hoc-plugin/src/vite.ts
  • internals/unplugin-hoc-plugin/tsup.config.ts
  • internals/unplugin-hoc-plugin/README.md
  • internals/unplugin-hoc-plugin/package.json
  • packages/vue/src/button/src/index.ts
  • internals/unplugin-hoc-plugin/tsconfig.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • examples/sites/demos/pc/app/button/basic-usage.vue
  • examples/vue3/package.json
  • packages/vue-common/src/index.ts
🧰 Additional context used
🧬 Code Definitions (4)
internals/unplugin-hoc-plugin/test/index.test.ts (1)
internals/unplugin-virtual-template/src/core/transformVirtualTemplate.ts (1)
  • transformVirtualTemplate (1-54)
internals/unplugin-hoc-plugin/src/index.ts (1)
internals/unplugin-hoc-plugin/src/types.ts (1)
  • UserOptions (16-16)
packages/vue-common/src/adapter/vue3/hoc.tsx (4)
packages/vue-common/src/index.ts (5)
  • props (54-72)
  • hooks (420-420)
  • design (174-177)
  • $prefix (42-42)
  • $setup (136-171)
packages/vue-common/src/adapter/vue2.7/index.ts (1)
  • getComponentName (42-51)
packages/vue-common/src/adapter/vue2/index.ts (1)
  • getComponentName (53-62)
packages/vue-common/src/adapter/vue3/index.ts (1)
  • getComponentName (42-51)
internals/unplugin-hoc-plugin/src/nuxt.ts (1)
internals/unplugin-hoc-plugin/src/types.ts (1)
  • UserOptions (16-16)
🔇 Additional comments (15)
internals/unplugin-hoc-plugin/scripts/postbuild.ts (1)

1-24: Well-structured post-build script for fixing CJS exports

This script effectively addresses a common issue with CommonJS module exports when working with tools that generate both ESM and CJS outputs. It locates CJS files and modifies their export statements to ensure compatibility with both import and require patterns.

The approach of replacing exports.default = with module.exports = and appending exports.default = module.exports; ensures dual compatibility with both:

  • ES modules consumers: import foo from 'package'
  • CommonJS consumers: const foo = require('package')
internals/unplugin-hoc-plugin/src/nuxt.ts (1)

1-16: Well-implemented Nuxt integration for the HOC plugin

The function correctly integrates the HOC plugin with both Webpack and Vite in a Nuxt environment.

Note the intentional difference in plugin placement:

  • Webpack: Plugin is added to the beginning of the plugins array with unshift()
  • Vite: Plugin is added to the end of the plugins array with push()

This approach is correct since plugin execution order often differs between Webpack and Vite, and this placement ensures proper operation in both environments.

patches/@opentiny__vue-vite-import@1.2.0.patch (1)

28-32: Fixed module identification for files with query parameters

Similar to the previous section, the patch introduces proper handling of module IDs with query strings.

package.json (2)

67-67: Added build script for HOC plugin

A new build script has been added to manage the Higher-Order Component plugin, which aligns with the PR objective of implementing WithDesignConfigPropsDefineComponent functionality.


157-158: New patched dependency added

A patch has been added for the @opentiny/vue-vite-import package, which is likely needed to support the Higher-Order Component (HOC) functionality being implemented in this PR.

internals/unplugin-hoc-plugin/src/index.ts (5)

1-4: LGTM! Import statements are appropriate

The imports include the necessary dependencies for creating an unplugin and handling file filtering.


5-13: Well-structured plugin initialization

The plugin is properly initialized with configurable include/exclude options and a clear name. The filter setup and transformInclude implementation follow best practices.


22-39: Import transformation looks correct

The code effectively transforms the import statements, replacing defineComponent with WithDesignConfigPropsDefineComponent as defineComponent for Vue files with the withPropsHOC query parameter. This aligns with the PR objective to enable design configuration props handling.


1-49:

❓ Verification inconclusive

Verify integration with other components

The PR objectives mention that only the Button component has been adjusted to use this method so far. Please ensure that this plugin correctly integrates with other components that will use this feature in the future.


🏁 Script executed:

#!/bin/bash
# Check if any Vue components are already using the WithDesignConfigPropsDefineComponent
echo "Searching for components that might already be using WithDesignConfigPropsDefineComponent..."
rg "WithDesignConfigPropsDefineComponent" --type vue

# Check the Button component implementation to verify correct usage
echo "Checking Button component implementation..."
fd "Button.vue" --type file | xargs rg -l "import.*from.*@opentiny/vue-common" | xargs cat

Length of output: 71861


Action Required: Verify Plugin Transformation in All Vue Components

The current verification steps did not yield conclusive evidence. The search for occurrences of “WithDesignConfigPropsDefineComponent” using “rg --type vue” failed due to an unrecognized file type, and the output from checking Button.vue only shows standard imports from “@opentiny/vue-common” without indication of the expected transformation.

Please manually verify (or use an alternative file search approach such as using “fd -e vue” with grep) the following:

  • That components intended to use the “withPropsHOC” feature—beyond Button.vue—are receiving the correct import transformation (i.e., that “defineComponent” is replaced with “WithDesignConfigPropsDefineComponent as defineComponent”).
  • That in a Vue file where the query parameter “withPropsHOC” is applied, the plugin’s transformation logic is executed and the resulting output reflects the intended changes.

1-49:

❓ Verification inconclusive

Check for the HOC implementation

This plugin references WithDesignConfigPropsDefineComponent, but we should verify that this function is properly implemented in the Vue 2 and Vue 3 adapters mentioned in the PR summary.


🌐 Web query:

What is a Higher-Order Component (HOC) in Vue?

💡 Result:

Higher-Order Components (HOCs) in Vue.js are advanced design patterns for enhancing component reusability by wrapping components with extended functionality. Inspired by React's implementation but adapted for Vue's ecosystem, HOCs act as component factories that transform existing components into enhanced versions with added capabilities.

Core Mechanics
An HOC is a function that:

  1. Accepts a base component as input
  2. Returns a new component with:
    • Additional props or state
    • Modified template behavior
    • Extended styling or lifecycle hooks
    • New methods or computed properties

Key benefits include:

  • Code reuse across multiple component variants
  • Logic isolation for complex behaviors
  • Non-invasive enhancement without modifying original components
  • Structural consistency in UI patterns

Implementation Example
This HOC adds styling capabilities to any component:

// withCustomStyle.js
export default function withCustomStyle(Component, customStyle) {
  return {
    render(createElement) {
      return createElement(Component, {
        style: customStyle,
      });
    }
  };
}

Usage in components:

<script>
import BaseComponent from './BaseComponent.vue';
import withCustomStyle from './withCustomStyle';

const EnhancedComponent = withCustomStyle(BaseComponent, {
  color: 'red',
  fontSize: '24px'
});

export default {
  components: { EnhancedComponent }
};
</script>

Practical Applications

  1. UI Pattern Wrapping
    Create consistent card variations while maintaining a single source of truth:
<!-- ArticleCard.vue -->
<template>
  <Card :border="'grey'">
    <template #actions>
      <a :href="link">Read more</a>
    </template>
  </Card>
</template>

<!-- ProductCard.vue --> 
<template>
  <Card :border="'none'">
    <template #actions>
      <BuyNowButton />
    </template>
  </Card>
</template>
  1. State Management
    Share counter functionality across components using Composition API integration [5]:
// WithCounter.js
function WithCounter(WrappedComponent, incrementValue = 1) {
  return {
    data: () => ({ count: 0 }),
    methods: {
      increment() { this.count += incrementValue }
    },
    render() {
      return h(WrappedComponent, {
        count: this.count,
        increment: this.increment
      });
    }
  };
}

Best Practices

  • Use Vue 3's Composition API for complex HOCs to maintain reactivity
  • Prefer props/default slots for content projection over direct template manipulation
  • Apply HOCs at component declaration level to prevent unnecessary re-renders
  • Combine with dependency injection for deep hierarchy support when needed

This pattern proves particularly valuable when building component libraries or managing cross-cutting concerns like analytics tracking, permission gating, or data fetching layers. While Vue's Composition API offers alternative composition patterns, HOCs remain a powerful tool for creating declarative, template-based component enhancements.

Citations:


Attention: Verify External HOC Implementation

The plugin’s transformation logic—with the replacement of defineComponent by WithDesignConfigPropsDefineComponent from @opentiny/vue-common—properly sets up the HOC mechanism. However, as this relies on the external package, please ensure that:

  • Existence & Implementation: The WithDesignConfigPropsDefineComponent function is correctly implemented in both the Vue 2 and Vue 3 adapter modules (as noted in the PR summary) so that it properly wraps and enhances components as expected by HOC patterns in Vue.
  • Functionality Check: Its behavior (i.e., supplying additional props, managing internal state, etc.) aligns with the intended higher-order component design principles and does not introduce unexpected side effects.

Make sure to verify these aspects in @opentiny/vue-common to confirm consistent behavior across Vue versions.

packages/vue-common/src/adapter/vue3/hoc.tsx (5)

15-15: Ensure robust handling of reactive objects.

The code correctly unwraps reactive objects by checking for a .value property, but might benefit from more defensive checks or a helper function for clarity, especially since this handles various reactive object types from Vue 3 (ref, computed, etc.).


1-4: LGTM: Clean import statements with appropriate dependencies.

The import statements correctly bring in the necessary dependencies for the HOC implementation.


5-9: LGTM: Well-structured HOC implementation.

The HOC pattern is correctly implemented, preserving the original component's properties while adding the design configuration integration functionality.


38-42:

✅ Verification successful

Verify JSX rendering in Vue 3 environment.

The JSX syntax used here assumes the environment is properly configured for JSX with Vue 3. Ensure this works correctly across different build configurations and environments.


🏁 Script executed:

#!/bin/bash
# Check for JSX/TSX configuration in the project
echo "Checking for JSX/TSX configuration..."
fd -e json -e js "tsconfig|babel" --exec cat {} | grep -E "jsx|tsx"

# Check for other components using JSX syntax
echo "Checking for other components using JSX syntax..."
fd -e tsx . --exec grep -l "<.*>" {} | head -5

Length of output: 998


JSX Configuration Verified for Vue 3 Environment

  • The project’s tsconfig/babel files consistently set JSX to "preserve", confirming correct TSX handling.
  • Similar TSX usage in other components (as seen in test files) supports that the overall JSX setup is robust.
  • The <BaseComponent {...mergedProps} ref={innerRef}> pattern in the HOC is aligned with the established practices across the codebase.

No changes are required regarding JSX rendering in Vue 3.


20-32:

❓ Verification inconclusive

Clever proxy implementation, but needs thorough testing.

The proxy implementation elegantly exposes the inner component's methods and properties. However, ensure it's thoroughly tested with different property access patterns and edge cases (undefined refs, non-existent properties, etc.).


🏁 Script executed:

#!/bin/bash
# Search for existing tests for this HOC implementation
echo "Searching for tests related to DesignConfigPropsHOC..."
rg -i "DesignConfigPropsHOC.*test|test.*DesignConfigPropsHOC" --type ts --type tsx --type js --type jsx

# Check if any components are already using this HOC
echo "Checking for components using DesignConfigPropsHOC..."
rg -i "DesignConfigPropsHOC" --type ts --type tsx --type js --type jsx

Length of output: 468


Thoroughly test proxy edge cases in the HOC implementation.
The proxy pattern here is a clever solution for exposing inner component properties and methods. However, our automated search for tests was inconclusive (partly due to file type recognition issues). Please ensure you add or verify unit tests covering scenarios such as:

  • Cases where innerRef.value is undefined or null.
  • Accessing properties that don’t exist (confirming that the proxy returns undefined safely).
  • Diverse property access patterns to avoid any unexpected side effects.

Manual verification of test coverage is recommended.


🏁 Script executed:

#!/bin/bash
# Re-run tests related to DesignConfigPropsHOC using file glob patterns to include tsx files
echo "Searching for tests related to DesignConfigPropsHOC..."
rg -i "DesignConfigPropsHOC.*test|test.*DesignConfigPropsHOC" --glob "*.tsx" --glob "*.ts" --glob "*.js" --glob "*.jsx"

echo "Checking for components using DesignConfigPropsHOC..."
rg -i "DesignConfigPropsHOC" --glob "*.tsx" --glob "*.ts" --glob "*.js" --glob "*.jsx"

Length of output: 1501


Action Required: Enhance Test Coverage for Proxy Implementation

The proxy pattern here is a clever solution for exposing inner component properties and methods, but our investigation shows that tests for this behavior (especially within the Vue3 adapter) might not fully cover edge cases. Please make sure to verify and, if necessary, add tests that address the following:

  • Cases where innerRef.value is undefined or null;
  • Access to non-existent properties, ensuring that the proxy safely returns undefined;
  • Various property access patterns to confirm that no unexpected side effects occur;
  • Consistent test coverage in both Vue2 and Vue3 implementations where the HOC is used.

Manual verification of test coverage is strongly recommended, as our automated search did not conclusively locate the necessary tests.

Comment on lines +16 to +22
const params = {}
if(props.tiny_experimetal_props_hoc) {
result = import.meta.glob('./${value}.vue', { eager: true, query: { withPropsHOC: true } })
} else {
result = import.meta.glob('./${value}.vue', { eager: true, query: params })
}

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistent query parameter handling between code branches

In the first branch with withPropsHOC: true, you specify the query parameter directly, but in the else branch, you're passing the empty params object. This inconsistency may lead to unexpected behavior.

  const params = {}
  if(props.tiny_experimetal_props_hoc) {
    result = import.meta.glob('./${value}.vue', { eager: true, query: { withPropsHOC: true } })
  } else {
-    result = import.meta.glob('./${value}.vue', { eager: true, query: params })
+    result = import.meta.glob('./${value}.vue', { eager: true })
  }
📝 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
const params = {}
if(props.tiny_experimetal_props_hoc) {
result = import.meta.glob('./${value}.vue', { eager: true, query: { withPropsHOC: true } })
} else {
result = import.meta.glob('./${value}.vue', { eager: true, query: params })
}
const params = {}
if(props.tiny_experimetal_props_hoc) {
result = import.meta.glob('./${value}.vue', { eager: true, query: { withPropsHOC: true } })
} else {
result = import.meta.glob('./${value}.vue', { eager: true })
}

Comment on lines +1 to +44
import { describe, expect, it } from 'vitest'
import { transformVirtualTemplate, transformVirtualTemplateForBuild } from '../src/core/index'

describe('index', () => {
describe('transformVirtualTemplate', () => {
it('pc|mobile|mobile-first', () => {
expect(
transformVirtualTemplate("import template from 'virtual:template?pc|mobile|mobile-first'")
).toMatchSnapshot()
})

it('pc|mobile=pc|mobile-first', () => {
expect(
transformVirtualTemplate("import template from 'virtual:template?pc|mobile=pc|mobile-first'")
).toMatchSnapshot()
})

it('pc|mobile|mobile-first=pc', () => {
expect(
transformVirtualTemplate("import template from 'virtual:template?pc|mobile|mobile-first=pc'")
).toMatchSnapshot()
})
})

describe('transformVirtualTemplateForBuild', () => {
it('pc|mobile|mobile-first', () => {
expect(
transformVirtualTemplateForBuild("import template from 'virtual:template?pc|mobile|mobile-first'")
).toMatchSnapshot()
})

it('pc|mobile=pc|mobile-first', () => {
expect(
transformVirtualTemplateForBuild("import template from 'virtual:template?pc|mobile=pc|mobile-first'")
).toMatchSnapshot()
})

it('pc|mobile|mobile-first=pc', () => {
expect(
transformVirtualTemplateForBuild("import template from 'virtual:template?pc|mobile|mobile-first=pc'")
).toMatchSnapshot()
})
})
})
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Tests are missing validation of the new tiny_experimetal_props_hoc functionality

The tests only verify that the transformation works for different template string formats, but don't validate the behavior with the tiny_experimetal_props_hoc property, which is a key part of the changes. Consider adding tests that specifically verify this new functionality.

Add tests that simulate both cases where props.tiny_experimetal_props_hoc is defined and undefined:

it('handles props.tiny_experimental_props_hoc correctly', () => {
  const transformed = transformVirtualTemplate("import template from 'virtual:template?pc|mobile'");
  
  // Extract the generated function and test it with different props
  // This is a simplified approach; you might need to use a more complex parsing strategy
  const funcStr = transformed.match(/const template = \([\s\S]+?\}\s*$/)[0];
  
  // Create a test to verify behavior with tiny_experimental_props_hoc=true
  expect(funcStr.includes('withPropsHOC: true')).toBe(true);
  
  // Optionally, you could use Function constructor to evaluate the generated code
  // But that would require more complex setup and might be better as an integration test
});

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

✨ [Feature]: 组件增加HOC,实现支持在design Config中全局配置默认props
4 participants