Skip to content

feat(genui-sdk-vue): add code generation capabilities#121

Open
yy-wow wants to merge 41 commits into
devfrom
feat/vue-generator
Open

feat(genui-sdk-vue): add code generation capabilities#121
yy-wow wants to merge 41 commits into
devfrom
feat/vue-generator

Conversation

@yy-wow

@yy-wow yy-wow commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator
  1. schema 卡片增加导出源码按钮
  2. 增加简版 vue 源码生成

Summary by CodeRabbit

  • New Features

    • Export generated Vue source from the schema renderer via a hover-revealed "导出源码" button
    • Generate and download complete Vue SFC files (imports, template, reactive state, event bindings)
    • Built-in SFC validation to surface compile/template/style issues before download
  • Chores

    • Added Vue toolchain and formatting packages (including Prettier) to the framework package
    • Updated submodule reference for the tiny schema renderer project

@coderabbitai

coderabbitai Bot commented Apr 3, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a Vue SFC code-generation pipeline and UI export: new code-generator modules (template, state, event, utils, constants, validator), integrates an export button into SchemaCardRenderer to download generated .vue files, updates Vue compiler devDependencies and related packages, and advances a submodule pointer.

Changes

Cohort / File(s) Summary
Dependency Setup
packages/frameworks/vue/package.json
Add devDependencies @vue/compiler-sfc, @vue/shared (^3.5.18) and escape-string-regexp; add prettier to dependencies; reorder/re-add several existing package entries (no script changes).
Renderer Integration
packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue
Add export UI overlay/button, build componentsMap from rendererConfig.materialsList, downloadTextFile helper, generateCode handler calling code-generator, and switch to scoped lang="less" styles with overlay transitions.
Generator Core & Types
packages/frameworks/vue/src/code-generator/code-generator.ts, packages/frameworks/vue/src/code-generator/types.ts, packages/frameworks/vue/src/code-generator/index.ts
New core generator exporting generateCode/generatePageCode, SFC assembly (imports, template, script setup, style), component deduplication, optional Prettier formatting, and TypeScript types/interfaces; re-export entry added.
Template & State Generation
packages/frameworks/vue/src/code-generator/template-generator.ts, packages/frameworks/vue/src/code-generator/state-generator.ts
Template rendering (Vue & JSX-like) and state transformer to unwrap protocol types (expressions/functions/slots/resources/i18n), traverse state and emit executable expressions/temporary state keys.
Event Binding & Utils
packages/frameworks/vue/src/code-generator/event-binding.ts, packages/frameworks/vue/src/code-generator/utils.ts, packages/frameworks/vue/src/code-generator/constants.ts
Helpers for event key conversion (toEventKey, isOn), string utilities (hyphenate, capitalize), and codegen constants/markers (UNWRAP_QUOTES, JS_* constants).
SFC Validation
packages/frameworks/vue/src/code-generator/vue-sfc-validator.ts
Add validateByCompile(filename, code) using @vue/compiler-sfc to parse/compile SFC parts and normalize/locate errors with code frames; returns standardized error messages.
Misc / Submodule
projects/tiny-schema-renderer
Advance submodule ref from 45fa58e -> 0f1ab90 (submodule pointer update).

Sequence Diagram

sequenceDiagram
    participant User
    participant Renderer as SchemaCardRenderer.vue
    participant Generator as code-generator
    participant StateGen as state-generator
    participant TemplateGen as template-generator
    participant Validator as vue-sfc-validator
    participant Browser

    User->>Renderer: Click Export button
    Renderer->>Generator: generateCode(pageInfo, componentsMap)
    Generator->>Generator: sanitize & dedupe componentsMap
    Generator->>StateGen: traverseState(schema.state)
    StateGen-->>Generator: transformed state (expressions/functions/slots handled)
    Generator->>TemplateGen: generateTemplate(schema, state)
    TemplateGen-->>Generator: template string
    Generator->>Validator: validateByCompile(filename, code)
    Validator-->>Generator: errors[]
    Generator-->>Renderer: { panelName, panelValue, errors }
    Renderer->>Browser: downloadTextFile(panelValue, filename)
    Browser-->>User: .vue file downloaded
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 I nibble props and stitch a view,
State unwinds, templates bloom anew,
Click—an export hops into the light,
A .vue bundle, tidy and bright,
Hooray, the renderer left a trace.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(genui-sdk-vue): add code generation capabilities' directly and accurately summarizes the main objective of adding code generation and export functionality to the Vue framework package.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/vue-generator

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 11

🧹 Nitpick comments (7)
packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue (2)

197-200: Consider using i18n for the button label.

The label "导出源码" is hardcoded in Chinese. For consistency with the rest of the component (which uses t() for translations, e.g., line 54), consider adding this string to the i18n resources.

♻️ Proposed i18n usage
       <div class="schema-export-button" `@click.stop.prevent`="generateCode">
         <TinyIconDownload class="schema-export-icon" />
-        <span class="schema-export-label">导出源码</span>
+        <span class="schema-export-label">{{ t('renderer.exportSource') }}</span>
       </div>

Add the corresponding translation key to your i18n resources.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue` around lines 197
- 200, The button label "导出源码" is hardcoded; replace it with a translation call
(e.g., use t('schema.exportSource') or t('schema.exportCodeLabel') where the
template currently renders the span inside the div with class
"schema-export-button" and keep the click handler generateCode and
TinyIconDownload unchanged), and add the same key with Chinese and other locale
values to your i18n resource files so the component (which already uses t())
will render the localized label.

132-144: Unused prettierOpts variable.

prettierOpts is destructured from the generator result but never used. Either remove it or apply formatting with it.

♻️ Remove unused variable
 const generateCode = async () => {
-  const { panelValue: code, panelName: fileName, errors, prettierOpts } = generateVueCode({
+  const { panelValue: code, panelName: fileName, errors } = generateVueCode({
     pageInfo: { schema: displaySchema.value },
     componentsMap,
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue` around lines 132
- 144, The destructured prettierOpts from generateVueCode in generateCode is
unused; either remove prettierOpts from the destructuring or apply it to format
the generated code before saving (e.g., call prettier.format(code, prettierOpts)
or an existing format helper) and pass the formatted result to downloadTextFile;
update the generateCode function to use the chosen approach and keep references
to generateVueCode, prettierOpts, code, and downloadTextFile consistent.
packages/frameworks/vue/src/renderer/code-generator/template-generator.ts (3)

1-1: Unused import: capitalize.

capitalize is imported from @vue/shared but is not used anywhere in this file. Consider removing it to keep imports clean.

♻️ Suggested fix
-import { capitalize, hyphenate } from '@vue/shared';
+import { hyphenate } from '@vue/shared';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/renderer/code-generator/template-generator.ts` at
line 1, The import list in template-generator.ts includes an unused symbol
`capitalize` from `@vue/shared`; remove `capitalize` from the import so the
statement only imports `hyphenate` (and run linter/formatting to ensure imports
are updated). Locate the import statement that reads `import { capitalize,
hyphenate } from '@vue/shared'` and delete `capitalize` while keeping
`hyphenate`.

211-214: VOID_ELEMENTS list may be incomplete.

The HTML specification defines more void elements than listed here (e.g., area, base, col, embed, meta, param, source, track, wbr). If these elements appear in schemas, they won't be self-closed properly. Consider expanding the list or extracting it as a shared constant.

♻️ Suggested expanded list
-  const VOID_ELEMENTS = ['img', 'input', 'br', 'hr', 'link'];
+  const VOID_ELEMENTS = [
+    'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',
+    'link', 'meta', 'param', 'source', 'track', 'wbr'
+  ];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/renderer/code-generator/template-generator.ts`
around lines 211 - 214, The VOID_ELEMENTS array used in template-generator.ts is
incomplete (currently only ['img','input','br','hr','link']) which causes some
HTML void tags to not be self-closed; update VOID_ELEMENTS to include the full
set of HTML void elements (e.g., area, base, col, embed, meta, param, source,
track, wbr, etc.) or extract it into a shared constant used by the generator,
and ensure the existing branch that checks VOID_ELEMENTS.includes(component) and
calls result.push(' />') continues to apply to the expanded/shared list.

248-250: Duplicate VOID_ELEMENTS constant.

The VOID_ELEMENTS array is duplicated here and at line 212. Consider extracting it to a shared constant to maintain consistency and avoid divergence.

♻️ Suggested refactor

Add at the top of the file:

const VOID_ELEMENTS = [
  'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',
  'link', 'meta', 'param', 'source', 'track', 'wbr'
];

Then remove the inline definitions at lines 212 and 249.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/renderer/code-generator/template-generator.ts`
around lines 248 - 250, There is a duplicated VOID_ELEMENTS array in
template-generator.ts; extract a single shared constant named VOID_ELEMENTS at
the top of the file (as suggested) and remove the inline array definitions
around the checks that reference VOID_ELEMENTS (the blocks that check if
(VOID_ELEMENTS.includes(component)) near where component is resolved); update
all references in this file to use the single top-level VOID_ELEMENTS constant
so both locations (previously at line ~212 and ~249) use the same shared symbol.
packages/frameworks/vue/src/renderer/code-generator/code-generator.ts (2)

28-30: Simplify single-element array.

importsFromVue is an array with one element that is immediately joined. This can be simplified to a direct string.

♻️ Suggested simplification
-  const importsFromVue = ['import * as vue from "vue"'];
-
-  imports.push(importsFromVue.join('\n'));
+  imports.push('import * as vue from "vue"');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/renderer/code-generator/code-generator.ts` around
lines 28 - 30, The variable importsFromVue is an unnecessary single-element
array that’s immediately joined; replace it with a direct string and push that
string into imports instead. Locate the declaration/imports push in
code-generator.ts (the importsFromVue variable and the subsequent
imports.push(importsFromVue.join('\n')) call) and change it to push the literal
string 'import * as vue from "vue"' (or assign a const importFromVueString =
'import * as vue from "vue"' and push that) to remove the redundant array and
join.

148-157: prettierOpts is defined but formatting is not applied.

The prettier options are returned in the panel object but the code is never actually formatted. If formatting is intended to happen downstream, this is fine. Otherwise, consider either applying Prettier here or removing the unused options.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/renderer/code-generator/code-generator.ts` around
lines 148 - 157, prettierOpts is declared but never used, so either format the
generated code with Prettier using those options or remove the unused config;
update the code in code-generator.ts to call Prettier.format(generatedCode,
prettierOpts) (or the equivalent async API) and assign the formatted result into
the property you return on the panel object (the same field where unformatted
code is currently set), ensuring you import/require Prettier where needed, or
delete prettierOpts and its return from the panel if formatting is handled
downstream.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/frameworks/vue/src/renderer/code-generator/code-generator.ts`:
- Around line 144-145: The current deep copy using
JSON.parse(JSON.stringify(originSchema)) in code-generator.ts (creating const
schema) strips function values; replace it with a cloning approach that
preserves functions (e.g., use structuredClone(originSchema) if available or a
deep-clone utility such as lodash.cloneDeep or a project deepClone helper) so
schema retains function expressions; update the creation of schema to use that
cloning method and ensure any imports (e.g., cloneDeep) are added where used.
- Around line 74-89: The Function branch in the properties loop accesses
defaultValue.value without a null check which can throw; update the Function
handling in code-generator.ts (inside the properties.forEach/content.forEach
where propType is computed) to guard defaultValue (e.g., use defaultValue?.value
or check defaultValue != null) and fall back to a safe default (such as
undefined or an empty function expression) before assigning propValue and
pushing into propsArr so missing schema data won't cause a TypeError.

In `@packages/frameworks/vue/src/renderer/code-generator/event-binding.ts`:
- Around line 17-23: Remove the unused helper function toPascalCase: locate the
function declaration named toPascalCase in event-binding.ts and delete it
(including its JSDoc comment) since it's not exported or referenced anywhere;
ensure no other code depends on it and run tests/lint to confirm no remaining
references.
- Around line 5-6: Remove the unused and duplicate regex exports thisBindRe and
thisPropsBindRe from event-binding.ts; delete both exported constants (they both
equal /this\.(props\.)?/g) and ensure no other module imports them (replace or
consolidate any inline uses in template-generator.ts to reference a single
in-file literal or a new shared constant if desired). Also run a quick
project-wide search for thisBindRe and thisPropsBindRe to confirm there are no
remaining references before committing.

In `@packages/frameworks/vue/src/renderer/code-generator/state-generator.ts`:
- Around line 51-56: The code that handles [JS_FUNCTION] unconditionally
destructures getFunctionInfo(value) which can return null; update the
[JS_FUNCTION] handler to guard the getFunctionInfo result (call
getFunctionInfo(value) into a local like info), check for null/undefined and
return the original value (or a safe fallback string) early if parsing failed,
otherwise destructure info to obtain type, params, body and build inlineFunc as
before; ensure you still reference start and end when returning the
reconstructed string.

In `@packages/frameworks/vue/src/renderer/code-generator/template-generator.ts`:
- Line 244: The call handleBinding(props, attrsArr, description, {}) wrongly
passes an empty state object so temp variables from handleLiteralBinding are
written to a throwaway object; replace the {} with the actual binding state
object used by this generator (e.g., the existing `state` or `bindingState`
variable used elsewhere in this module) or create/preserve a persistent
bindingState before the call and pass that so temporary bindings like those
created by handleLiteralBinding are stored and referenced correctly in the
generated JSX.
- Around line 77-87: The handleSlotBinding function can emit strings like
"#[object Object]" when name is falsy and item is an object; update
handleSlotBinding to compute a safe name fallback (e.g., const slotName = name
|| (typeof item === 'string' ? item : 'default')) and use slotName for all
generated strings so you never interpolate the raw object; keep the same params
logic but reference slotName when building `#${...}` for the array and string
branches to ensure valid template output.
- Around line 89-107: handleEventBinding currently returns an empty string for
non-JSExpression items which gets pushed into attrsArr and creates spurious
empty attributes; change the function (handleEventBinding) to return a falsy
value (e.g., null or undefined) instead of '' when no binding is produced
(change the eventBinding default and final return), and ensure the caller that
builds attrsArr filters falsy values before pushing (or only pushes when
handleEventBinding returns a truthy string) so attrsArr never contains empty
strings.
- Around line 140-147: The code clears the shared description.internalTypes
inside the canotBind branch causing global side effects; instead of mutating
description.internalTypes, create and use a local Set for this binding (e.g.,
const localInternalTypes = new Set(description.internalTypes) or new Set()) when
preparing the temporary state binding in the canotBind block, and leave
description.internalTypes untouched; keep the rest of the logic that computes
valueKey (avoidDuplicateString), assigns state[valueKey] = item, and pushes
attrsArr.push(`:${key}="state.${valueKey}"`) unchanged.

In `@packages/frameworks/vue/src/renderer/code-generator/vue-sfc-validator.ts`:
- Around line 107-122: The locateErrorMessage function currently assumes
loc.start.line exists within originalSource lines causing errorLineCode to be
undefined when line is out of bounds; update locateErrorMessage to validate and
clamp the line index (derived from loc.start.line) against
originalSource.split(/\r?\n/) length (or bail out and return the original
message if line is invalid), only compute scopeCode and call generateCodeFrame
when errorLineCode is defined, and ensure column is also clamped within the
errorLineCode length; reference locateErrorMessage, originalSource, error,
loc.start, and generateCodeFrame when making the change.
- Around line 60-71: The code uses descriptor.template without guarding for
null; add a null/undefined check before calling compileTemplate so we only
access template.content when descriptor.template exists (e.g., if
(descriptor.template) ...), or early-return/skip validation when template is
missing; update the block around the compileTemplate call (referencing
descriptor, template, scoped and the compileTemplate invocation that produces
templateResult) to avoid calling template.content when template is null.

---

Nitpick comments:
In `@packages/frameworks/vue/src/renderer/code-generator/code-generator.ts`:
- Around line 28-30: The variable importsFromVue is an unnecessary
single-element array that’s immediately joined; replace it with a direct string
and push that string into imports instead. Locate the declaration/imports push
in code-generator.ts (the importsFromVue variable and the subsequent
imports.push(importsFromVue.join('\n')) call) and change it to push the literal
string 'import * as vue from "vue"' (or assign a const importFromVueString =
'import * as vue from "vue"' and push that) to remove the redundant array and
join.
- Around line 148-157: prettierOpts is declared but never used, so either format
the generated code with Prettier using those options or remove the unused
config; update the code in code-generator.ts to call
Prettier.format(generatedCode, prettierOpts) (or the equivalent async API) and
assign the formatted result into the property you return on the panel object
(the same field where unformatted code is currently set), ensuring you
import/require Prettier where needed, or delete prettierOpts and its return from
the panel if formatting is handled downstream.

In `@packages/frameworks/vue/src/renderer/code-generator/template-generator.ts`:
- Line 1: The import list in template-generator.ts includes an unused symbol
`capitalize` from `@vue/shared`; remove `capitalize` from the import so the
statement only imports `hyphenate` (and run linter/formatting to ensure imports
are updated). Locate the import statement that reads `import { capitalize,
hyphenate } from '@vue/shared'` and delete `capitalize` while keeping
`hyphenate`.
- Around line 211-214: The VOID_ELEMENTS array used in template-generator.ts is
incomplete (currently only ['img','input','br','hr','link']) which causes some
HTML void tags to not be self-closed; update VOID_ELEMENTS to include the full
set of HTML void elements (e.g., area, base, col, embed, meta, param, source,
track, wbr, etc.) or extract it into a shared constant used by the generator,
and ensure the existing branch that checks VOID_ELEMENTS.includes(component) and
calls result.push(' />') continues to apply to the expanded/shared list.
- Around line 248-250: There is a duplicated VOID_ELEMENTS array in
template-generator.ts; extract a single shared constant named VOID_ELEMENTS at
the top of the file (as suggested) and remove the inline array definitions
around the checks that reference VOID_ELEMENTS (the blocks that check if
(VOID_ELEMENTS.includes(component)) near where component is resolved); update
all references in this file to use the single top-level VOID_ELEMENTS constant
so both locations (previously at line ~212 and ~249) use the same shared symbol.

In `@packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue`:
- Around line 197-200: The button label "导出源码" is hardcoded; replace it with a
translation call (e.g., use t('schema.exportSource') or
t('schema.exportCodeLabel') where the template currently renders the span inside
the div with class "schema-export-button" and keep the click handler
generateCode and TinyIconDownload unchanged), and add the same key with Chinese
and other locale values to your i18n resource files so the component (which
already uses t()) will render the localized label.
- Around line 132-144: The destructured prettierOpts from generateVueCode in
generateCode is unused; either remove prettierOpts from the destructuring or
apply it to format the generated code before saving (e.g., call
prettier.format(code, prettierOpts) or an existing format helper) and pass the
formatted result to downloadTextFile; update the generateCode function to use
the chosen approach and keep references to generateVueCode, prettierOpts, code,
and downloadTextFile consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 80a81b08-01e6-4bb5-98aa-d3a88e5ee06c

📥 Commits

Reviewing files that changed from the base of the PR and between dd0c82a and ef950d5.

📒 Files selected for processing (10)
  • packages/frameworks/vue/package.json
  • packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue
  • packages/frameworks/vue/src/renderer/code-generator/code-generator.ts
  • packages/frameworks/vue/src/renderer/code-generator/constants.ts
  • packages/frameworks/vue/src/renderer/code-generator/event-binding.ts
  • packages/frameworks/vue/src/renderer/code-generator/index.ts
  • packages/frameworks/vue/src/renderer/code-generator/state-generator.ts
  • packages/frameworks/vue/src/renderer/code-generator/template-generator.ts
  • packages/frameworks/vue/src/renderer/code-generator/types.ts
  • packages/frameworks/vue/src/renderer/code-generator/vue-sfc-validator.ts

Comment thread packages/frameworks/vue/src/code-generator/code-generator.ts Outdated
Comment thread packages/frameworks/vue/src/code-generator/code-generator.ts Outdated
Comment thread packages/frameworks/vue/src/renderer/code-generator/event-binding.ts Outdated
Comment thread packages/frameworks/vue/src/renderer/code-generator/event-binding.ts Outdated
Comment thread packages/frameworks/vue/src/code-generator/state-generator.ts Outdated
Comment thread packages/frameworks/vue/src/code-generator/template-generator.ts Outdated
Comment thread packages/frameworks/vue/src/code-generator/template-generator.ts Outdated
Comment thread packages/frameworks/vue/src/renderer/code-generator/template-generator.ts Outdated
Comment thread packages/frameworks/vue/src/renderer/code-generator/vue-sfc-validator.ts Outdated
Comment thread packages/frameworks/vue/src/code-generator/vue-sfc-validator.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/frameworks/vue/src/renderer/code-generator/code-generator.ts`:
- Around line 109-126: The generated <script setup> block in code-generator.ts
doesn't include a lang attribute when JSX is required (description.hasJSX is set
by state-generator.ts for slot content); update the template generation (the
multi-line string building the <template>...<script setup> block) to
conditionally emit <script setup lang="jsx"> (or the appropriate JSX/TSX variant
if your description indicates) when description.hasJSX is true, otherwise emit
the plain <script setup>; locate the code that constructs the string
(references: description.hasJSX, imports, propsArr, emitsArr, iconStatement,
reactiveStatement, methodsArr) and inject the conditional lang attribute into
the opening script tag.

In `@packages/frameworks/vue/src/renderer/code-generator/state-generator.ts`:
- Around line 106-117: The array branch in traverseState skips calling
transformType for array entries, letting raw protocol nodes leak into the
reactive initializer; update the Array.isArray branch in traverseState so that
for each element you first call transformType(element, /*prop=*/ undefined,
description, rootState) (or use the element's index as the prop string) and then
call traverseState(element, description, rootState) so built-in protocol nodes
inside arrays are transformed before recursion; keep using the existing
traverseState and transformType symbols and preserve rootState propagation.
- Around line 78-84: The current JS_SLOT generator concatenates children with
.join('') producing empty or invalid multi-root bodies; change the
implementation in JS_SLOT to map items via generateJSXTemplate into an array
(e.g., slotNodes), then: if slotNodes.length === 0 return the string 'null'; if
slotNodes.length === 1 use slotNodes[0]; otherwise wrap them as an array string
like `[${slotNodes.join(',')}]`; finally build the return using params (e.g., ({
${params.join(',')} }, h) => <body>) so start/end and the JS_SLOT function
produce a valid single-root or array root render body.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2676d20d-4e84-4267-b4e9-f700e12c711b

📥 Commits

Reviewing files that changed from the base of the PR and between ef950d5 and eff2678.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • packages/frameworks/vue/src/renderer/code-generator/code-generator.ts
  • packages/frameworks/vue/src/renderer/code-generator/event-binding.ts
  • packages/frameworks/vue/src/renderer/code-generator/state-generator.ts
  • packages/frameworks/vue/src/renderer/code-generator/template-generator.ts
  • packages/frameworks/vue/src/renderer/code-generator/vue-sfc-validator.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/frameworks/vue/src/renderer/code-generator/template-generator.ts

Comment thread packages/frameworks/vue/src/code-generator/code-generator.ts Outdated
Comment thread packages/frameworks/vue/src/code-generator/code-generator.ts Outdated
Comment thread packages/frameworks/vue/src/code-generator/state-generator.ts Outdated
Comment thread packages/frameworks/vue/src/code-generator/state-generator.ts Outdated
…templates, event binding, and state management

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (4)
packages/frameworks/vue/src/code-generator/state-generator.ts (2)

109-110: ⚠️ Potential issue | 🟠 Major

Transform protocol nodes inside arrays before recursing.

Line 110 only descends into each array element. If an element itself is a built-in protocol node, transformType never runs for that entry, so the raw { type, ... } object leaks into the generated reactive(...) initializer.

🛠️ Suggested fix
   if (Array.isArray(current)) {
-    current.forEach((prop) => traverseState(prop, description, rootState));
+    current.forEach((_, index) => {
+      transformType(current, index, description, rootState);
+      traverseState(current[index], description, rootState);
+    });
   } else if (typeof current === 'object') {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/code-generator/state-generator.ts` around lines
109 - 110, Array elements that are protocol nodes aren't being transformed
before recursion: update the Array branch in traverseState so each element is
passed through transformType (e.g., let transformed = transformType(prop,
description, rootState) or assign back to prop) before calling traverseState on
it; specifically, in the current.forEach callback call transformType(prop,
description, rootState) and use its result when recursing to ensure protocol
nodes inside arrays are converted prior to generating the reactive initializer.

78-84: ⚠️ Potential issue | 🟠 Major

Generate a valid JSX body for empty and multi-node slots.

Line 81 concatenates every slot child into one string. That leaves ({ row }, h) => with no body when value is empty, and emits adjacent roots like <A /><B /> when there are multiple children. Both forms are invalid once unwrapped into the generated slot render function.

🛠️ Suggested fix
   [JS_SLOT]: ({ value = [], params = ['row'] }, description, rootState) => {
     description.hasJSX = true;
 
-    const slotValues = value.map((item) => generateJSXTemplate(item, description, rootState)).join('');
+    const slotNodes = value.map((item) => generateJSXTemplate(item, description, rootState));
+    const slotBody =
+      slotNodes.length === 0 ? 'null' : slotNodes.length === 1 ? slotNodes[0] : `[${slotNodes.join(',')}]`;
 
     // 默认解构参数 row,因为jsx slot 必须有第二个参数 h
-    return `${start}({ ${params.join(',')} }, h) => ${slotValues}${end}`;
+    return `${start}({ ${params.join(',')} }, h) => ${slotBody}${end}`;
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/code-generator/state-generator.ts` around lines
78 - 84, The current JS_SLOT generator builds slotValues by concatenating
children which yields an empty body when value is empty and adjacent roots when
there are multiple children; change it to: compute children via
generateJSXTemplate for each item, then if value.length === 0 set the body to
"null", if value.length === 1 use the single child string, otherwise wrap the
joined children in a JSX fragment (e.g. `<>${joined}</>`) so the returned string
from JS_SLOT (the `${start}({ ${params.join(',')} }, h) => ${body}${end}`
expression) is always a valid JSX function body; keep the existing
description.hasJSX flag and use the same symbols (JS_SLOT, generateJSXTemplate,
slotValues/start/end/params) when implementing.
packages/frameworks/vue/src/code-generator/code-generator.ts (2)

24-57: ⚠️ Potential issue | 🔴 Critical

Declare the helper symbols that generated code can reference.

Lines 24-57 only import Vue and component dependencies, and Lines 117-124 never declare any runtime helpers. generateTemplate(...) and traverseState(...) can still emit t(...), utils.*, and bridge.*, so schemas using i18n or JS_RESOURCE currently download a component with unresolved identifiers.

Also applies to: 68-69, 117-124

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/code-generator/code-generator.ts` around lines 24
- 57, The generated code currently only imports Vue and component packages in
generateImports, but does not declare runtime helper symbols (e.g., t, utils.*,
bridge.*), so code emitted by generateTemplate and traverseState can contain
unresolved identifiers; update generateImports to also declare and export or
return helper bindings for these symbols (t, utils, bridge and any subhelpers
used by generateTemplate/traverseState) so they are always defined for generated
SFCs—ensure the helpers are derived from vue (or appropriate runtime modules) or
stubbed consistently with how generateTemplate/traverseState expect them to be
referenced and include them alongside the existing imports in the returned
structure.

114-114: ⚠️ Potential issue | 🟠 Major

Switch the script block to JSX mode when slot code is emitted.

JS_SLOT generates arrow functions whose bodies come from generateJSXTemplate(...). With the current plain <script setup>, Vue parses that block as standard JS, so any slot render function containing <Comp /> fails during compileScript. Emit lang="jsx" whenever description.hasJSX is set.

🛠️ Suggested fix
-<script setup>
+<script setup${description.hasJSX ? ' lang="jsx"' : ''}>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/code-generator/code-generator.ts` at line 114,
The script block is currently emitted as plain JavaScript which breaks when
JS_SLOT generates arrow functions using generateJSXTemplate(...) that contain
JSX; update the emitter that writes the <script setup> block to emit lang="jsx"
whenever description.hasJSX is true so Vue treats the block as JSX. Locate the
code that outputs the <script setup> tag (where JS_SLOT and generateJSXTemplate
are used) and conditionally add the lang="jsx" attribute based on
description.hasJSX.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/frameworks/vue/src/code-generator/template-generator.ts`:
- Around line 100-103: The generated eventBinding currently calls
`${eventHandler}(eventArgs, ${extendParams})` which passes all emitted args as
one array; change it to spread emitted args so handlers receive positional args
by generating a call like `(...eventArgs) => ${eventHandler}(...eventArgs,
${extendParams})` (use the same `item.params`, `eventKey`, `eventHandler`, and
`eventBinding` variables) so emitted args are forwarded positionally and
additional params follow.
- Around line 32-74: handleBinding currently emits Vue template directives
(":prop", "@event", "v-model", "#slot") and is reused when generating JSX,
producing invalid output; split responsibilities by creating a JSX-specific
binding path and switching callers based on output format/state. Add a new
function (e.g., handleJSXBinding) that mirrors handleBinding's intent but emits
JSX-appropriate syntax (convert `:key="expr"` -> `key={expr}`,
`@event="handler"` -> `onEvent={handler}` using camelCase event names, translate
`v-model` into value + onInput/onChange pair or appropriate controlled prop, and
convert slot bindings into prop/children-compatible JSX patterns), keep existing
handleBinding as handleTemplateBinding for Vue directives, and update usages
such as generateJSXTemplate/generateJSX (and any callers referenced by
state-generator) to call handleJSXBinding when state indicates JSX output; reuse
helper functions like handleEventBinding/handleLiteralBinding by extracting
JSExpression-to-JSX-expression conversion logic so both binding handlers can
share parsing logic but emit different syntaxes.

---

Duplicate comments:
In `@packages/frameworks/vue/src/code-generator/code-generator.ts`:
- Around line 24-57: The generated code currently only imports Vue and component
packages in generateImports, but does not declare runtime helper symbols (e.g.,
t, utils.*, bridge.*), so code emitted by generateTemplate and traverseState can
contain unresolved identifiers; update generateImports to also declare and
export or return helper bindings for these symbols (t, utils, bridge and any
subhelpers used by generateTemplate/traverseState) so they are always defined
for generated SFCs—ensure the helpers are derived from vue (or appropriate
runtime modules) or stubbed consistently with how generateTemplate/traverseState
expect them to be referenced and include them alongside the existing imports in
the returned structure.
- Line 114: The script block is currently emitted as plain JavaScript which
breaks when JS_SLOT generates arrow functions using generateJSXTemplate(...)
that contain JSX; update the emitter that writes the <script setup> block to
emit lang="jsx" whenever description.hasJSX is true so Vue treats the block as
JSX. Locate the code that outputs the <script setup> tag (where JS_SLOT and
generateJSXTemplate are used) and conditionally add the lang="jsx" attribute
based on description.hasJSX.

In `@packages/frameworks/vue/src/code-generator/state-generator.ts`:
- Around line 109-110: Array elements that are protocol nodes aren't being
transformed before recursion: update the Array branch in traverseState so each
element is passed through transformType (e.g., let transformed =
transformType(prop, description, rootState) or assign back to prop) before
calling traverseState on it; specifically, in the current.forEach callback call
transformType(prop, description, rootState) and use its result when recursing to
ensure protocol nodes inside arrays are converted prior to generating the
reactive initializer.
- Around line 78-84: The current JS_SLOT generator builds slotValues by
concatenating children which yields an empty body when value is empty and
adjacent roots when there are multiple children; change it to: compute children
via generateJSXTemplate for each item, then if value.length === 0 set the body
to "null", if value.length === 1 use the single child string, otherwise wrap the
joined children in a JSX fragment (e.g. `<>${joined}</>`) so the returned string
from JS_SLOT (the `${start}({ ${params.join(',')} }, h) => ${body}${end}`
expression) is always a valid JSX function body; keep the existing
description.hasJSX flag and use the same symbols (JS_SLOT, generateJSXTemplate,
slotValues/start/end/params) when implementing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ab6f9385-d864-40e6-b81f-2a63fdbdcefb

📥 Commits

Reviewing files that changed from the base of the PR and between eff2678 and 94504c9.

📒 Files selected for processing (10)
  • packages/frameworks/vue/src/code-generator/code-generator.ts
  • packages/frameworks/vue/src/code-generator/constants.ts
  • packages/frameworks/vue/src/code-generator/event-binding.ts
  • packages/frameworks/vue/src/code-generator/index.ts
  • packages/frameworks/vue/src/code-generator/state-generator.ts
  • packages/frameworks/vue/src/code-generator/template-generator.ts
  • packages/frameworks/vue/src/code-generator/types.ts
  • packages/frameworks/vue/src/code-generator/vue-sfc-validator.ts
  • packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue
  • projects/tiny-schema-renderer
✅ Files skipped from review due to trivial changes (2)
  • packages/frameworks/vue/src/code-generator/index.ts
  • packages/frameworks/vue/src/code-generator/types.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue

Comment thread packages/frameworks/vue/src/code-generator/template-generator.ts Outdated
Comment thread packages/frameworks/vue/src/code-generator/template-generator.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/frameworks/vue/src/code-generator/state-generator.ts (1)

79-86: ⚠️ Potential issue | 🟠 Major

Generate valid render bodies for empty and multi-node slots.

Line 82 joins slot children with .join(''), which produces invalid output in two cases:

  • Empty slots: Arrow function body is empty (({ row }, h) => ), which is a syntax error.
  • Multiple nodes: Adjacent JSX elements are concatenated (<A/><B/>) without array wrapping, which violates Vue render function requirements.

Vue render functions require either a single root or an explicit array.

🐛 Proposed fix
  [JS_SLOT]: ({ value = [], params = ['row'] }: { value?: any[]; params?: string[] }, description: ICodegenDescription, rootState: Record<string, any>) => {
    description.hasJSX = true;

-   const slotValues = value.map((item) => generateJSXTemplate(item, description, rootState)).join('');
+   const slotItems = value.map((item) => generateJSXTemplate(item, description, rootState));
+   const slotBody =
+     slotItems.length === 0
+       ? 'null'
+       : slotItems.length === 1
+         ? slotItems[0]
+         : `[${slotItems.join(', ')}]`;

    // 默认解构参数 row,因为jsx slot 必须有第二个参数 h
-   return `${start}({ ${params.join(',')} }, h) => ${slotValues}${end}`;
+   return `${start}({ ${params.join(',')} }, h) => ${slotBody}${end}`;
  },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/code-generator/state-generator.ts` around lines
79 - 86, The JS_SLOT handler builds slotValues with value.map(...).join('')
which yields invalid render bodies for empty or multi-node slots; update the
JS_SLOT implementation (referencing JS_SLOT, generateJSXTemplate, params, start,
end, and slotValues) to first map into an array of node strings, then: if the
array is empty return a render null body (`... => null`), if it has one item
return that single node as before, and if it has multiple items return an
explicit array (`... => [node1, node2, ...]`) so Vue's render function always
receives a valid single root or array. Ensure description.hasJSX remains set to
true.
🧹 Nitpick comments (1)
packages/frameworks/vue/src/code-generator/event-binding.ts (1)

7-13: Consider adding a guard for empty string in lowerFirst.

While lowerFirst is currently always called with a non-empty string (guaranteed by isOnUpdate requiring onUpdate:\w+), it will throw a TypeError if passed an empty string since str[0] would be undefined.

For defensive coding, a simple guard could prevent potential future issues if the function is reused elsewhere.

🛡️ Optional: Add empty-string guard
 /** 字符串首字符转小写。 */
-const lowerFirst = (str: string) => str[0].toLowerCase() + str.slice(1)
+const lowerFirst = (str: string) => (str ? str[0].toLowerCase() + str.slice(1) : '')
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/code-generator/event-binding.ts` around lines 7 -
13, The helper lowerFirst currently does str[0].toLowerCase() + str.slice(1) and
will throw on an empty string; update lowerFirst to guard for empty input (e.g.,
return str if !str or str.length === 0) so callers like isOnUpdate / other
consumers are safe if an empty string is ever passed; keep the function name
lowerFirst and ensure behavior for non-empty strings remains unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/frameworks/vue/src/code-generator/state-generator.ts`:
- Around line 119-120: The array branch in traverseState fails to transform
protocol nodes because it only recurses into elements and never calls
transformType; update the Array.isArray(current) branch in traverseState to call
transformType for each element (e.g., invoke transformType(prop, description,
rootState) or replace current[i] with the transformed result) before/after
recursing so protocol objects inside arrays are unwrapped into their JS
expression form and do not leak into the reactive(...) initializer.

---

Duplicate comments:
In `@packages/frameworks/vue/src/code-generator/state-generator.ts`:
- Around line 79-86: The JS_SLOT handler builds slotValues with
value.map(...).join('') which yields invalid render bodies for empty or
multi-node slots; update the JS_SLOT implementation (referencing JS_SLOT,
generateJSXTemplate, params, start, end, and slotValues) to first map into an
array of node strings, then: if the array is empty return a render null body
(`... => null`), if it has one item return that single node as before, and if it
has multiple items return an explicit array (`... => [node1, node2, ...]`) so
Vue's render function always receives a valid single root or array. Ensure
description.hasJSX remains set to true.

---

Nitpick comments:
In `@packages/frameworks/vue/src/code-generator/event-binding.ts`:
- Around line 7-13: The helper lowerFirst currently does str[0].toLowerCase() +
str.slice(1) and will throw on an empty string; update lowerFirst to guard for
empty input (e.g., return str if !str or str.length === 0) so callers like
isOnUpdate / other consumers are safe if an empty string is ever passed; keep
the function name lowerFirst and ensure behavior for non-empty strings remains
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 132e7118-47d4-4328-81e1-d030eaf69e29

📥 Commits

Reviewing files that changed from the base of the PR and between 94504c9 and 95aaf82.

📒 Files selected for processing (7)
  • packages/frameworks/vue/src/code-generator/code-generator.ts
  • packages/frameworks/vue/src/code-generator/event-binding.ts
  • packages/frameworks/vue/src/code-generator/state-generator.ts
  • packages/frameworks/vue/src/code-generator/template-generator.ts
  • packages/frameworks/vue/src/code-generator/types.ts
  • packages/frameworks/vue/src/code-generator/utils.ts
  • packages/frameworks/vue/src/code-generator/vue-sfc-validator.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/frameworks/vue/src/code-generator/utils.ts
  • packages/frameworks/vue/src/code-generator/types.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/frameworks/vue/src/code-generator/vue-sfc-validator.ts
  • packages/frameworks/vue/src/code-generator/code-generator.ts
  • packages/frameworks/vue/src/code-generator/template-generator.ts

Comment thread packages/frameworks/vue/src/code-generator/state-generator.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (2)
packages/frameworks/vue/src/code-generator/code-generator.ts (2)

94-96: ⚠️ Potential issue | 🟠 Major

Preserve JSX mode when slot generation marks it.

traverseState(...) is where slot state can flag JSX usage, but Line 113 always emits a plain <script setup>. Vue SFCs use the lang attribute to opt into non-default script syntaxes, and Vue documents JSX / TSX as a separate authoring mode, so this needs verification before slot-based exports ship. (vuejs.org)

🛠️ Proposed fix
-<script setup>
+<script setup${description.hasJSX ? ' lang="jsx"' : ''}>
 ${imports.join('\n')}
In Vue 3 SFCs, should a `<script setup>` block that contains JSX be emitted with `lang="jsx"` / `lang="tsx"` for the SFC parser to handle it correctly?

Also applies to: 113-125

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/code-generator/code-generator.ts` around lines 94
- 96, traverseState(...) can mark that generated slot code requires JSX/TSX, but
the code that emits the <script setup> block (where reactiveStatement and slot
exports are written) always outputs a plain <script setup>; update the emitter
to detect the JSX/TSX flag set by traverseState (e.g., a boolean like
state.isJSX or state.jsxMode) and, when present, emit the script tag with the
appropriate lang attribute ("jsx" or "tsx" depending on whether TypeScript mode
is in use) so the SFC parser handles JSX correctly; ensure the decision uses the
same state object inspected by traverseState and propagate that flag into the
script emitter that writes the reactiveStatement and slot export code.

62-68: ⚠️ Potential issue | 🔴 Critical

Emit the runtime helpers recorded in description.

After generateTemplate(...) and traverseState(...), this file only consumes componentSet and iconComponents. The collected resource/i18n metadata never becomes imports or setup bindings here, so schemas that emit t(...), utils.*, or bridge.* references will download as uncompilable SFCs. Please materialize those helpers in <script setup> or report them through errors instead of returning a clean panel.

Also applies to: 70-71, 94-125

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frameworks/vue/src/code-generator/code-generator.ts` around lines 62
- 68, The code never materializes the runtime helpers recorded in the local
description object (description.jsResource, description.stateAccessor, i18n/t
references) after generateTemplate(...) and traverseState(...), so update the
generator (after calls to generateTemplate and traverseState in
code-generator.ts) to 1) inspect description.jsResource.utils and
description.jsResource.bridge and emit corresponding import lines and setup
bindings into the <script setup> output (or add them to the script's top-level
bindings), 2) convert any entries in description.stateAccessor and
description.iconComponents into usable bindings or imports in the generated
script, and 3) if a required runtime helper (e.g. t(...), utils.*, bridge.*)
cannot be resolved, push a descriptive error into the errors array instead of
returning a clean panel; reference the description variable, generateTemplate,
traverseState, description.jsResource, description.stateAccessor, and
description.iconComponents when making these changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/frameworks/vue/src/code-generator/code-generator.ts`:
- Line 61: The schema's lifeCycles object is destructured into lifeCycles but
never emitted into the generated <script setup> and the errors array remains
hard-coded to [], so mounted/unmounted logic is dropped silently; update the
code-generator to either include lifeCycles content into the emitted script
(e.g., incorporate lifeCycles entries into the generated lifecycle hooks within
the script output where script generation is assembled) or, if lifecycles are
intentionally unsupported, push a descriptive validation error into errors (and
remove the hard-coded []). Specifically, modify the code surrounding the
lifeCycles destructuring and the script generation routines (references:
lifeCycles, errors, and the script-generation function that builds the <script
setup>) to serialize lifecycle hook bodies into the output or add an explicit
error entry explaining lifecycles are unsupported.
- Around line 127-129: The Prettier browser formatting for Vue SFCs is missing
the PostCSS plugin; update formatWithPrettierCode to import the PostCSS plugin
(postcss) used by Prettier's css parser and pass it via the plugins option to
prettier.format so embedded <style> blocks are formatted correctly;
specifically, add the postcss plugin import at the top of code-generator.ts and
include it in the plugins array passed into formatWithPrettierCode's call to
prettier.format (alongside any existing plugins and the parser: "vue"/"css"
selection).

In `@packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue`:
- Around line 193-201: The export control is a non-focusable <div> revealed only
on :hover, making it inaccessible to keyboard and touch users; update the
element with class "schema-export-button" in SchemaCardRenderer.vue to be an
actual interactive element (change to a <button> or add tabindex="0" and
role="button"), add keyboard handlers to invoke generateCode on Enter/Space,
include an accessible label via aria-label or visible text, ensure the reveal
styles are triggered on :focus/:focus-visible (and not only :hover) so
keyboard/touch users can access it, and apply the same changes to the similar
export block around lines 229-289 so both export controls are keyboard/touch
accessible.
- Around line 82-116: generateComponentsMap currently builds componentsMap only
from rendererConfig.materialsList so custom components passed in via
props.customComponents aren’t included and exports can miss imports; update the
logic that computes componentsMap (the call sites for generateComponentsMap and
the variable componentsMap) to merge in caller-supplied import metadata
(props.customComponents or a newly exposed prop) into the deduped map so entries
from props override/augment rendererConfig entries, and add a validation step
before export that checks every component referenced in props.customComponents
and the schema resolves to an entry in the merged map and throws/blocks the
export (or surfaces an error) if any component name cannot be resolved.

---

Duplicate comments:
In `@packages/frameworks/vue/src/code-generator/code-generator.ts`:
- Around line 94-96: traverseState(...) can mark that generated slot code
requires JSX/TSX, but the code that emits the <script setup> block (where
reactiveStatement and slot exports are written) always outputs a plain <script
setup>; update the emitter to detect the JSX/TSX flag set by traverseState
(e.g., a boolean like state.isJSX or state.jsxMode) and, when present, emit the
script tag with the appropriate lang attribute ("jsx" or "tsx" depending on
whether TypeScript mode is in use) so the SFC parser handles JSX correctly;
ensure the decision uses the same state object inspected by traverseState and
propagate that flag into the script emitter that writes the reactiveStatement
and slot export code.
- Around line 62-68: The code never materializes the runtime helpers recorded in
the local description object (description.jsResource, description.stateAccessor,
i18n/t references) after generateTemplate(...) and traverseState(...), so update
the generator (after calls to generateTemplate and traverseState in
code-generator.ts) to 1) inspect description.jsResource.utils and
description.jsResource.bridge and emit corresponding import lines and setup
bindings into the <script setup> output (or add them to the script's top-level
bindings), 2) convert any entries in description.stateAccessor and
description.iconComponents into usable bindings or imports in the generated
script, and 3) if a required runtime helper (e.g. t(...), utils.*, bridge.*)
cannot be resolved, push a descriptive error into the errors array instead of
returning a clean panel; reference the description variable, generateTemplate,
traverseState, description.jsResource, description.stateAccessor, and
description.iconComponents when making these changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c0a1dfcd-dcbe-4d98-b768-92dc42513426

📥 Commits

Reviewing files that changed from the base of the PR and between 95aaf82 and 1f013ae.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • packages/frameworks/vue/package.json
  • packages/frameworks/vue/src/code-generator/code-generator.ts
  • packages/frameworks/vue/src/code-generator/types.ts
  • packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue
✅ Files skipped from review due to trivial changes (1)
  • packages/frameworks/vue/src/code-generator/types.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/frameworks/vue/package.json

Comment thread packages/frameworks/vue/src/code-generator/code-generator.ts Outdated
Comment thread packages/frameworks/vue/src/code-generator/code-generator.ts Outdated
Comment thread packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue Outdated
Comment thread packages/frameworks/vue/src/renderer/SchemaCardRenderer.vue Outdated
Comment thread packages/frameworks/vue/src/chat/GenuiChat.vue Outdated
Comment thread packages/frameworks/vue/package.json Outdated
Comment thread packages/frameworks/vue/src/code-generator/index.ts Outdated
Comment thread packages/frameworks/vue/src/code-generator/vue-code-generator.ts Outdated
Comment thread packages/frameworks/vue/src/code-generator/vue-code-generator.ts Outdated
Comment thread packages/frameworks/vue/src/chat/GenuiChat.vue Outdated
Comment thread packages/frameworks/vue/src/chat/GenuiChat.vue Outdated
Comment thread packages/frameworks/vue/src/code-generator/constants.ts Outdated
Comment thread sites/playground/web/package.json
Comment thread packages/frameworks/vue/src/code-generator/constants.ts Outdated
Comment thread packages/frameworks/vue/src/chat/GenuiChat.vue
Comment thread sites/playground/web/src/App.vue
Comment thread packages/frameworks/vue/package.json Outdated
yy-wow added 4 commits July 16, 2026 17:14
- Updated dependencies in pnpm-lock.yaml, including postcss and sass versions.
- Added new dependencies for Vue framework: @vue/compiler-sfc, @vue/shared, and prettier.
- Removed unused dependency '@opentiny/tiny-engine-builtin-component' from package.json.
…map generation

- Replaced IRendererConfig with IMaterialsMeta and updated related logic in getComponentsMap.
- Enhanced type definitions for materialsList and componentsMapCache.
- Simplified the useExportVueCode hook to utilize materialsMeta by default.
…etupMethods

- Updated the method generation logic in buildScriptSetupMethods to support async functions and improved parameter handling.
- Introduced a new function info extraction to streamline the creation of method definitions, enhancing code readability and maintainability.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants