-
Notifications
You must be signed in to change notification settings - Fork 1
VisualEditor
🌐 This page in: English · Português
A first-party VS Code extension that turns the SDK into a visual development environment: a screen renders beside the file that produces it, from the buffer you are typing in, and every rendered element knows which C# expression built it.
The preview is the real web realizer running the real compiled module. It is not a lookalike, and that is the point: a preview that renders is evidence the page renders. Nothing new draws pixels.
Status. The design host and the identity mechanism ship and are covered by tests. The extension itself is early — it is built from source, not installed from the Marketplace, and only the preview and the source-span identity are in place. Editing from the canvas is ahead. Track E in the Roadmap has the milestones.
Since 0.2.0-preview.30
eqdesign is a long-lived process that holds the project's Roslyn compilation and compiles the
editor's buffer — not the file on disk. That distinction is the whole reason it exists: eqc
reads files and the hot-reload service watches the filesystem, so neither can show you the text you
are currently looking at, only the text you last saved.
It speaks newline-delimited JSON over stdio. No port to choose, nothing to authorise, nothing left listening if the window dies, and it works unchanged over Remote-SSH because the extension host runs on the remote machine anyway.
Measured on samples/DefaultUIDashboard (16 source files, 316 references):
| Step | Time |
|---|---|
| Build the compilation, once at activation | 271 ms |
Compile an edit (662-line PaymentsPage, warm) |
p50 293 ms |
| Diagnostics only (bind, no transpile) | 36 ms |
Hence two cadences: errors are re-checked after a 150 ms pause in typing, the preview recompiles after 400 ms. A C# error stops the compile before anything is emitted — Roslyn parses leniently, so a missing brace still yields a tree the transpiler would walk, producing a module that mounts and throws, which arrives on screen as a blank frame with nothing to explain it.
The host refuses to start if the reference list is empty, rather than compiling against an incomplete model. That failure is otherwise invisible: without the semantic model, named arguments are emitted in syntactic order, and the screen renders with its values in the wrong slots and no error anywhere.
Since 0.2.0-preview.30
VisualNode carries an Origin — the source span of the expression that constructed it, or null,
which is what every shipped build is. A design-mode compilation fills it in:
var compiler = new ComponentCompiler { DesignMode = true };
// Every node construction is emitted wrapped, so the built node remembers where it came from:
// $eq.origin(UI.text(…), "…/PaymentsPage.cs|28:12|28:73")Both realizers carry it into the DOM as data-eq-origin, attached at their single dispatch:
<div data-eq-origin="/src/Screens/PaymentsPage.cs|27:8|34:10">
<span data-eq-origin="/src/Screens/PaymentsPage.cs|28:12|28:73">Count: 0</span>
</div>The format is path|startLine:startColumn|endLine:endColumn, zero-based — the editor's own
coordinates.
Why not source maps. The obvious answer does not work. The whole Build body is converted to one
flat string and emitted through a single call, so the finest position a V3 map can name is the start
of the method: one shipped module has a 942-character line. An origin is exact instead — and because
it is a plain string on the abstract node, the native (Photon) track inherits the same mechanism the
day it wants it.
Only constructions are stamped, never references. Stamping a variable where it is merely mentioned
would overwrite the construction's origin with the span of a use, and select the wrong line. A node
built inside a foreach carries the span of the one expression that builds it — which is the only
editable thing there anyway.
Design mode is off by default and never on in an SDK build: the wrapper is real emitted code, and
shipping it would put a design tool's concern in every user's bundle. A production render contains no
data-eq-origin at all, and the SSR/hydration fingerprint test pins that.
The extension is built from source and points at the design host in the same checkout:
cd extensions/vscode && npm install && npm run compileThen open a C# page or component and run eQuantic UI: Open Preview. The project must have been
built once — the preview stands on an ordinary build's output (the reference list the SDK writes, and
wwwroot/_equantic/runtime.js), so "build the project once" is the honest instruction when a piece is
missing.
- No editing from the canvas. Selection and inspection come first; property write-back and the component palette are the phases after.
-
No native preview. Identity is already solved on Photon (
LayoutNodecarries the node, absolute bounds and a stable path); only getting frames into a webview is missing. -
No
[ServerAction]calls. Action ids come from a startup assembly scan, so an ad-hoc preview class is never in the registry. - The baseline theme. An app selects its theme at startup, and reading that back means running the app's composition root. Shapes and layout are exact; a rebranded palette is not yet reflected.
- Debugging & Development Tools — the logger and error overlay the preview reuses.
- Compiler — how C# becomes the module the preview runs.
- Roadmap — Track E and what is ahead of it.
🌐 English · Português
🏁 Start here
📱 Write-once
- Write-Once Components
- Declarative Surface
- Photon Engine
- Design System
- Capabilities
- Storage
- Forms
- Code Editor
- Markdown
- Mermaid
- Email Rendering
🏗️ Architecture
⚙️ Compilation
- Compiler
- Compile-Time Evaluation
- Supported C# Features
- External Type Resolution
- Build Flow
- Diagnostics
⚡ Runtime
🔌 Server
🎨 Ecosystem
🚀 Development