feat: Vue-to-Studio importer — first-class import of frappe app pages#179
Draft
rmehta wants to merge 1 commit into
Draft
feat: Vue-to-Studio importer — first-class import of frappe app pages#179rmehta wants to merge 1 commit into
rmehta wants to merge 1 commit into
Conversation
Adds a complete pipeline that reads Vue SFC files from an installed
frappe app's frontend and imports them as Studio Pages, Studio
Components, variables, resources and watchers — no manual rebuild
required.
## What's included
### Node.js parser (`tools/vue-importer/`)
- `router-parser.js` — walks the app's Vue Router config to discover
page routes and their source files
- `classifier.js` — maps Vue/HTML tag names to Studio component names
(Container, TextBlock, frappe-ui components, custom components)
- `template-walker.js` — converts Vue template AST to Studio block
trees; handles containers, text/interpolation nodes, v-if, v-for,
Teleport, named slots; extracts Tailwind classes and inline styles;
rewrites component-prop references to `inputs.propName` so Studio's
evaluation context resolves them correctly
- `script-analyzer.js` — extracts `createResource` calls, `ref`
variables, `watch` watchers and `defineProps`/`defineModel` props
from `<script setup>` blocks
### Python importer (`studio/importer.py`)
- Invokes the Node parser via subprocess, receives a JSON manifest
- Upserts Studio App, Studio Pages and Studio Components
- Builds correct variable rows (JSON-encodes String type values so
`codeStore.evaluateDynamicValues` can parse them)
- `Studio Import Log` doctype tracks status, counts and errors
### API & UI
- `studio/api.py` — three whitelisted endpoints:
`get_importable_apps`, `preview_import`, `start_import`
- `ImportPanel.vue` — left-panel tab that lists importable apps,
shows a page/component preview with checkboxes, and runs the import
- `StudioLeftPanel.vue` — adds "Import" tab to the sidebar
## Rendering fixes discovered during testing (CRM)
| Issue | Fix |
|---|---|
| `componentName` case mismatch (PascalCase vs kebab-case) | `toComponentId()` in classifier maps custom component names to `component_id` |
| `JSON.parse` crash on empty variable initial values | `json.dumps()` for String type; `"null"` for empty Object type |
| Empty canvas — `canHaveChildren()` always false | `buildRootBlock` sets `componentId:"root"` + `originalElement:"div"` |
| Empty custom components (Teleport/slot) | Teleport → transparent; `<slot>` → render fallback children; `isComponentContext` flag suppresses v-if conditions that reference component-local state |
| Missing text content | `walkNode` handles `NodeTypes.TEXT` and `INTERPOLATION`; `extractTextContent` collects COMPOUND_EXPRESSION parts |
| Dynamic classes / inline styles | `extractClasses` captures `:class="[...]"` quoted literals; `extractInlineStyles` parses CSS strings and `:style` objects into camelCase property maps |
| Component-prop expressions not resolving | Template walker rewrites `{{ routeName }}` → `{{ inputs.routeName }}` when parsing component templates, matching Studio's `{ inputs: {...} }` evaluation context; `defineModel` variables are mapped to their underlying prop (`modelValue`) |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Original prompt
What this does
Adds a pipeline that reads Vue SFC files from an installed frappe app's frontend and imports them as Studio Pages + Studio Components — no manual rebuild or mapping required. Tested end-to-end with CRM (16 pages, 91 components).
Follow-up prompts that drove the rendering fixes
What's included
Node.js parser (tools/vue-importer/)
Python importer (studio/importer.py)
API & UI
Rendering bugs fixed during CRM testing
Plan / what's next