@t-yamauchi/wireflow
v2.1.5
Published
DSL-based interactive flow, ER, component, class, and sequence diagram renderer.
Readme
Wireflow
Wireflow is a DSL-based JavaScript diagram renderer for flow diagrams, screen flows, ER diagrams, component diagrams, class diagrams, and sequence diagrams.
It can be used from npm, CDN, or a local bundled file.
Official site: https://wireflow.jp/
Stability
The stable DSL and API contract is maintained in SPEC.md. Public JavaScript APIs are summarized in API.md, and compatibility-sensitive changes are tracked in MIGRATION.md.
Install
Wireflow v1 remains on the npm latest tag. Install Wireflow v2 explicitly
from the v2-latest dist-tag:
npm install @t-yamauchi/wireflow@v2-latestUse npm install @t-yamauchi/wireflow only when you intentionally want the
current latest tag.
import { Wireflow } from "@t-yamauchi/wireflow";
const wf = new Wireflow("#canvas", {
autoFit: true,
});
wf.render(`
layout:
mode: horizontal
auto-fit: true
Start:
Start
---
kind: start
Review:
Review
---
kind: process
Done:
Done
---
kind: end
Start -> Review
Review -> Done
`);Axis-specific fit is available when only one direction should determine the
initial zoom. auto-fit-y: yes fits the diagram height to the current viewport
and aligns the scene from its starting edge.
layout:
auto-fit-y: yesLarge horizontal diagrams keep a readable minimum zoom while auto-fit is
applied. Set auto-fit-min-scale in DSL or
autoFitMinScale in JavaScript when a diagram should fit more aggressively or
stay more readable.
layout:
auto-fit: true
auto-fit-min-scale: 0.45You can also load DSL from a text-like file. Markdown files render the first
fenced code block tagged wireflow.
const wf = new Wireflow("#canvas", { autoFit: true });
await wf.render("./flows/checkout.md");
await wf.renderFile("./flows/checkout.md");For large diagrams, Wireflow bounds expensive routing work automatically. Tune
smartAnchorLimit (default 32), routeObstacleFilterThreshold, routeObstaclePadding,
gridFallbackObstacleLimit, bridgeDetectionLimit, and maxEdgeBends only
when you need to trade render speed for more automatic edge cleanup or broader
global detours.
For troubleshooting, pass { debug: true } to emit wireflow:debug events and
console logs. Use { debug: "panel" } to show the latest render, layout,
auto-fit, viewport, and drag steps inside the canvas.
Viewport pan is a view-only interaction. Dragging the whole flow updates the
visible transform without rewriting DSL or triggering wireflow:dsl-change;
write adjustments.viewport explicitly when an initial pan must be persisted.
For display or approval screens, use view-only: true in DSL or { viewOnly:
true } in JavaScript. Pan and zoom remain available, but edge selection,
anchor edits, edge movement, route clearing, and node movement are blocked. Add
view-mode-toggle: true or { viewModeToggle: true } to show an optional
in-canvas switch button for toggling between view-only mode and edit mode.
AI Quality Layer
Wireflow v2 can treat the DSL as a process-quality contract. Add quality:
rules: and per-node contract: metadata, then run the checker from JavaScript
or CI. kind: start nodes are treated as flow entry markers and are excluded
from uncovered-node traceability counts unless you explicitly add contract
metadata to them.
quality:
rules:
- db_write_requires_auth
- external_api_requires_timeout
- error_path_requires_log
policies:
- all_paths_before:effect=db-write,contract=auth
Auth:
Auth check
---
kind: process
contract:
type: auth
Save:
Save order
---
kind: process
contract:
effect: db-write
req-id: R-001
risk: data-lossconst report = Wireflow.check(dsl);
// or, after rendering, highlight issue nodes:
const report = wf.check();wireflow check ./flows/checkout.dsl
wireflow report ./flows/checkout.dslConvert older YAML-like or brace DSL into the full YAML form with nodes:,
view, and readable top-level arrow edge keys:
wireflow convert ./flows/legacy.dsl --out ./flows/legacy.yamlAt runtime, flow DSL written in older YAML-like or brace styles is also
normalized into this full YAML form and stored in model.source. Renderer
interactions such as drag-created coordinates and edge route edits use that
cached YAML source from the first render onward. The original input is retained
as model.originalSource for inspection. Automatic resize re-renders continue
from the original input until an interaction changes the cached YAML, so
responsive orientation is still resolved normally.
For deterministic source, annotation, DSL-contract, and test-contract review, use the guard command:
wireflow guard --cwd . --spec ./flows/spec.dsl --actual ./flows/actual.dsl --src ./src --tests ./testsRecommended AI-development workflow:
- Ask the AI to output Wireflow DSL with
contract:metadata for auth, validation, side effects, error handling, and logging. - Review the rendered flow instead of reading every generated code path.
- Ask the AI to extract the implemented process as Wireflow DSL and compare it with the approved specification flow.
- Run
wireflow checkandwireflow comparein CI so rule violations and implementation drift fail the build. - Use
wireflow reportto produce a human-readable quality, traceability, and risk summary for review artifacts. - During execution tests, feed process events into the animation API to verify that the real process follows the approved flow.
wireflow compare ./flows/spec.dsl ./flows/actual.dslFor language-independent implementation extraction, put @wireflow
annotations next to the relevant code. Add evidence= so stale comments are
detected when the implementation changes.
// @wireflow node Auth kind=process contract.type=auth evidence=requireAuth
await requireAuth(user);
// @wireflow node Save kind=process contract.effect=db-write contract.requires=auth evidence=db.order.create
await db.order.create(order);
// @wireflow edge Auth -> SaveQuality annotations can also seed the extracted DSL. Use rule= for built-in
rules and policy= for compact policies with parameters:
// @wireflow quality rule=db_write_requires_auth,db_write_requires_validation
// @wireflow quality policy=all_paths_before:effect=db-write,contract=authwireflow extract ./src --out ./flows/actual.dslFor repeatable AI-agent work, this repository includes a verified development
kit under docs/ai/ and a repo-local Codex skill at
.codex/skills/wireflow-verified-dev/. The kit gives agents a smaller,
task-focused reference for the spec-first workflow, annotation rules, common
mistakes, and a gate runner:
node docs/ai/scripts/verify-wireflow-cycle.mjs --cwd trial-projects/report-api --test "npm test"The single Codex entry point is
docs/ai/CODEX_WIREFLOW_FRAMEWORK.md. It defines the full requirements ->
DSL -> implementation -> tests -> verification -> fix loop.
For screen-based web apps, use docs/ai/PROMPT_WEB_APP_TEMPLATE.md so the
agent contracts UI surfaces, user operations, client validation, loading/error
states, accessibility, and visual proof before writing DSL or code.
For new projects, start from templates/wireflow-verified-project/ or the
archive templates/wireflow-verified-project.zip.
For existing systems, use docs/ai/WIREFLOW_EXISTING_SYSTEM_ADOPTION.md.
Codex first inventories current code, tests, docs, and runtime behavior,
classifies findings as observed, documented, assumed, unknown, or risky, asks
human judgment questions for unknown/risky items, then creates a verified
baseline before changing behavior. For modifications, requested changes are
treated as a delta contract and compare differences are classified as intended
change, implementation drift, spec gap, annotation gap, test gap, or accepted
risk.
Before DSL generation, the kit requires a requirements contract: feature scope,
normal paths, error paths, warning paths, auth/authz, validation, side effects,
timeouts/retries, logging/redaction, risk, data, req-id, and test-id.
If any of these are ambiguous, the agent should ask the user for a concrete
decision instead of assuming one.
For stricter flows, add contract.test-id to quality-relevant DSL nodes and
place @wireflow-test <id> outcome=success|error|warning route=NodeA->NodeB requires=...
above the matching product tests. The deterministic guard then checks that
contracts, implementation annotations, test routes, failure edges, and test
assertions stay linked. The guard also compares spec DSL and actual DSL
internally, validates risk / data against a known vocabulary, and rejects
weak log checks such as asserting that a string literal exists instead of
checking a logged event field.
For runtime route proof, instrument the implementation with a trace recorder, write a trace JSON file from product tests, and pass it to guard:
import { createWireflowTraceStore } from "@t-yamauchi/wireflow";
import fs from "node:fs";
import path from "node:path";
const tracePath = ".wireflow/runtime-traces.json";
const traceStore = createWireflowTraceStore({
onChange(report) {
fs.mkdirSync(path.dirname(tracePath), { recursive: true });
fs.writeFileSync(tracePath, JSON.stringify(report, null, 2));
},
});
const trace = traceStore.recorder("T-AUTH-FAIL");
trace.visit("Request").visit("Auth").visit("AuthFailedLog").visit("AuthError").finish("error");Runtime traces can also record side-effect evidence:
trace
.visit("SaveRequest")
.effect("db-write", { nodeId: "SaveRequest", status: "failed" })
.visit("FailureLog")
.effect("log", { nodeId: "FailureLog", event: "processing_failed" })
.finish("error");wireflow guard --cwd . --spec ./flows/spec.dsl --actual ./flows/actual.dsl --src ./src --tests ./tests --trace .wireflow/runtime-traces.jsonWhen --trace is supplied, guard verifies that each @wireflow-test route=...
matches the route actually recorded while the test ran. The trace file format
is specified in docs/ai/WIREFLOW_RUNTIME_TRACE_SPEC.md, and
createWireflowTraceMiddleware(store) instruments connect/Express-style apps
per request via an x-wireflow-test-id header.
For CI, wireflow guard --sarif guard.sarif exports findings as SARIF 2.1.0,
and legacy projects can freeze existing findings with
wireflow guard --baseline .wireflow/guard-baseline.json --update-baseline
so only new violations fail afterwards.
For top-down proof from human/AI requirements to implementation and tests, write a structured requirements contract:
requirements:
- id: REQ-DB-001
title: Successful requests save a DB record and DB failures are exposed safely.
req-id: R-005
test-id: T-SUCCESS,T-DB-FAIL
nodes: SaveRequest,FailureLog,ErrorResponse
effect: db-write
risk: data-loss
data: internal
paths: success,error
assertions: db-completed,db-failed,status-500
assert-effects: db-write:SaveRequest,log:processing_failed
forbid-effects: file-write
required-route: SaveRequest
forbid-nodes: WriteFile
runtime: requiredThen run:
wireflow requirements requirements/main.requirements.dsl --cwd . --spec ./flows/spec.dsl --actual ./flows/actual.dsl --tests ./tests --trace .wireflow/runtime-traces.jsonThe requirements gate checks that each structured requirement links to Spec
DSL, Actual DSL, @wireflow-test, and runtime trace evidence through stable
req-id and test-id values. Optional logical fields move more of the review
from AI judgement into deterministic checks:
assertions: required@wireflow-test requires=entries. Built-in assertions such asrequest-id,db-completed,db-failed,rejects,status-400,status-401,status-403,status-500,no-db,audit-log,retry-success, andlog-*are checked against the test block. JavaScript tests are parsed with an AST first, with regex fallback for legacy and project-defined patterns.assert-effects: runtime side effects that must be recorded bytrace.effect(...), such asdb-write:SaveRequestorlog:processing_failed.forbid-effects: runtime side effects that must not be recorded.required-route: node ids that must appear in linked test routes and runtime traces.forbid-nodes: node ids that must not appear in linked test routes or runtime traces.runtime: required: at least one linked runtime trace must exist.
Projects can extend assertion vocabulary with wireflow.guard.json:
{
"strictVerification": true,
"strictSourceEffects": true,
"sourceEffectWindow": 20,
"assertionVocabulary": {
"status-202": {
"ast": {
"assertCall": true,
"identifiers": ["statusCode"],
"literals": [202]
}
},
"log-domain_event": {
"event": "domain_event"
}
}
}wireflow guard also parses JavaScript source with AST-based source gates. It
fails on common secret fields in logger calls, public responses that expose
stack, empty catch {} blocks, missing timeout markers for external-api
contracts, and missing path-sanitization markers for file-write contracts.
When "strictSourceEffects": true is enabled, detected DB/file/external source
effects must have a nearby matching @wireflow node contract.effect=...
annotation, turning unannotated implementation effects into CI failures.
When "strictVerification": true is enabled, regex-only assertion proof and
AST parse failures are treated as errors. Built-in assertions such as
db-completed, db-failed, status-401, and no-db use semantic argument
matching, so unrelated identifiers and literals in the same test block no
longer count as proof.
Generate one route-animation DSL per contract-linked test with wireflow
test-flows. Each file contains an animation.routes preset and auto-play
for the test route, so the test case can be inspected visually in Wireflow:
wireflow test-flows --cwd . --spec ./flows/spec.dsl --tests ./tests --out ./flows/testsWhen screenshots are available, pass --screenshots. Files named
<test-id>_<node-id>.png are attached to the matching node as popup payloads:
wireflow test-flows --cwd . --spec ./flows/spec.dsl --tests ./tests --out ./flows/tests --screenshots ./screenshotsThe verified project template includes a Playwright-based helper for capturing
screen states from wireflow.visual.json:
npm run visual:capture
npm run visual:flowsFor level-6 completion judgment, run wireflow verify. It runs product tests,
extracts actual DSL, checks spec and actual, compares them, creates quality
reports, runs guard, checks runtime traces when supplied, cross-checks trace
claims against Istanbul/c8 coverage when --coverage is supplied, generates
per-test route-animation DSLs, attaches screenshot evidence when supplied, and
writes completion artifacts:
wireflow verify --cwd . --requirements requirements/main.requirements.dsl --spec ./flows/spec.dsl --actual ./flows/actual.dsl --src ./src --tests ./tests --test "npm test" --trace .wireflow/runtime-traces.json --coverage coverage/coverage-final.jsonThe result is written to .wireflow/verification/verification-result.json,
.wireflow/verification/verification-report.md,
.wireflow/verification/verification-report.html, plus CI-friendly
verification-result.sarif (SARIF 2.1.0) and verification-junit.xml (one
JUnit test case per gate). The HTML report is a single
decision dashboard with a fixed menu and a consistent section order: approval
summary, verified scope and limitations, requirement evidence, quality gates,
and artifacts. It embeds Wireflow rendering, embeds screenshot evidence when
available, and shows generated test route animations inside the related
traceability rows instead of as a separate route list. The dashboard also lists every DSL req-id, explains why
requirement counts and test-id counts may differ, and shows how each
requirement is connected to structured requirements, implementation nodes,
tests, runtime traces, risk nodes, and the final conclusion in one
accordion-style traceability table. The traceability table keeps one compact
record per requirement where possible. The closed row shows only the
requirement id, status, and requirement text; conclusion, review points,
creation/verification evidence, quality gates, and route animations are shown
inside the expanded row. The list paginates in groups of 10 so projects with
hundreds of requirements remain
reviewable. Test ids and assertion keys are translated into Japanese
human-readable explanations in the dashboard, while the stable ids remain as
small trace hints for engineers. Route animations inside an expanded
traceability row render automatically when the row is opened. The dashboard
navigation is opened from a hamburger menu so the report remains usable on
small screens.
Per-test route DSLs are written under
.wireflow/verification/test-flows/, and the visual review index is written to
.wireflow/verification/visual-review.md.
wireflow verify also writes a requirement-centric specification document for
human review: .wireflow/verification/spec-document.md and
spec-document.html. It reorganizes the same deterministic artifacts (node
contracts, gate results, @wireflow-test declarations, runtime traces) into a
requirements list with verification status, per-requirement chapters with a
highlighted flow diagram, a security-viewpoint matrix (authentication,
authorization, input validation, audit logging, secret handling, external
dependency resilience, failure-path consistency), a test list, and a remaining
issues section. Every verdict in the document links back to a machine check;
no judgment is generated by inference. Structured requirements may carry
description: and rationale: fields whose prose is shown in the document.
The document can be regenerated standalone:
wireflow spec-doc --cwd . --spec ./flows/spec.dsl --tests ./tests --trace .wireflow/runtime-traces.jsonFor stricter, deterministic source/test review gates, run the guard against a
trial project such as invoice-workflow:
wireflow guard --cwd trial-projects/invoice-workflow --spec flows/specs/invoice-workflow.dsl --actual flows/actual/invoice-workflow.dsl --src src --tests testsRendered process flows can be animated from JavaScript. runRouteAnimation()
is the canonical execution entry point. Display differences such as pending
dimming, progress glow, speed, and final status are controlled through options.
The legacy playRouteAnimation() and playRouteSteps() helpers remain as
compatibility wrappers.
await wf.runRouteAnimation(["Start", "Review", "Done"], {
terminalStatus: "success",
});Reusable animation routes may be declared in the DSL and played by name.
animation:
auto-play: normal
routes:
normal:
nodes:
Start: Success
Review: Success
Done: Successawait wf.runRouteAnimation("normal");Step-based animation uses the same entry point with mode: "steps".
await wf.runRouteAnimation({
mode: "steps",
steps: ["Start", "Review", "Done"],
terminalStatus: "success",
});For live execution, create a session and add steps as each process starts or finishes:
const run = wf.createRouteAnimationSession({ duration: 700 });
await run.step("Start", { status: "success", wait: 5000 });
await run.step("Fetch", { status: "error", wait: 5000 });
await run.finish("error");The process-style helper is terser for live applications:
const process = wf.createProcessAnimation();
await process.next("Start", "running");
await process.next("Fetch", "running"); // Start is auto-completed as success.
await process.next("Fetch", "error");For DSL-defined process flows, start() and empty next() calls keep the host
code short. Wireflow follows the outgoing DSL edge automatically, and
next("error") follows the matching failure route:
const process = wf.createProcessAnimation();
process.start();
await fetchData();
process.next();
await saveData();
process.next("error");If no matching outgoing route exists, Wireflow opens a route-not-found popup and
emits wireflow:route-animation-missing-route.
When the host only needs to choose the terminal route status, run() can drive
the process from the DSL and update a status element with DSL node labels:
const process = wf.createProcessAnimation({
stepWait: 5000,
statusTarget: "#status",
});
process.run("warning");For interactive step-by-step playback, use the built-in controller:
const wf = new Wireflow("#canvas");
wf.render(dsl);
wf.process.run();
wf.process.result("success");
wf.process.result("error");When the actual process already emits events, feed those events to
wf.process.push(). Communication stays in the host app; Wireflow receives only
the process status, optional log, and optional expect value for strict tests.
wf.process.configure({ strict: true });
wf.process.push({ status: "running", log: "Fetch started" });
wf.process.push({ status: "success", log: "Fetch completed" });
wf.process.push({ expect: "Check", status: "error", log: "Check failed" });
expect(wf.process.history()).toMatchObject([
{ nodeId: "Start", status: "success" },
{ nodeId: "Fetch", status: "success" },
{ nodeId: "Check", status: "error" },
]);When auto-play is omitted, the normal route is played automatically if it
exists. Use auto-play: false when the DSL should only define presets.
The repository includes a runnable HTML sample at
wireflow_examples/examples/route-animation.html.
Swimlanes normally follow the active layout direction. Use lane-orientation
when the flow direction and lane direction need to be chosen explicitly.
layout:
mode: horizontal
lane-orientation: vertical
lane-order: User, System, AIlane-order places the listed lanes first in the given order. With horizontal
lane orientation the first lane is shown at the top; with vertical lane
orientation the first lane is shown at the left. Lanes omitted from the list use
the normal stable automatic order after the listed lanes.
CDN
<div data-wireflow-viewport style="height: 420px">
<div id="canvas"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/@t-yamauchi/wireflow/dist/wireflow.min.js"></script>
<script>
const WF = window.WireflowLib;
const wf = new WF.Wireflow("#canvas", {
autoFit: true,
});
wf.render(`
layout:
mode: horizontal
auto-fit: true
Input:
Input
---
kind: screen
state: accent
Validate:
Validate
---
kind: decision
Save:
Save
---
kind: process
Input -> Validate
Validate -> Save:
on-success: true
`);
</script>unpkg is also supported:
<script src="https://unpkg.com/@t-yamauchi/wireflow/dist/wireflow.min.js"></script>DSL Basics
Wireflow accepts the original YAML-like DSL and a full YAML object form.
layout:
mode: horizontal
auto-fit: true
Home:
Home
---
kind: screen
state: accent
payload:
title: Home
desc: |
Node details
Detail:
Detail
---
kind: screen
Home:right -> Detail:left:
label: openThe text above --- is rendered as the node label. The lines below --- are attributes.
Full YAML can use nodes: and edges: as arrays or maps. Nested objects such
as payload:, contract:, animation.routes, and adjustments: are parsed
with the YAML parser before Wireflow normalizes them into the same model.
layout:
mode: horizontal
auto-fit: true
animation:
auto-play: normal
routes:
normal:
nodes: [Start, Check, Done]
nodes:
- id: Start
kind: start
view: Start
contract:
req-id: REQ-1
test-id: [T-1]
- id: Check
kind: decision
view: |
Check
Input
payload:
title: Review
desc: YAML object payload
- id: Done
kind: end
view: Done
edges:
- from: Start
to: Check
label: begin
- from: Check
to: Done
from-anchor: right
to-anchor: left
label: ok
adjustments:
Start:
x: 10
y: 20When using full YAML, view is the preferred field for the node text shown in
the diagram. text and label remain accepted aliases. Edge arrays are useful
for generators, but the top-level arrow form also works when readability is more
important:
nodes:
Start:
kind: start
view: Start
Check:
kind: decision
view: Check
Start -> Check:
from: right
to: left
label: beginFor top-level arrow keys, from and to mean endpoint anchors. In edges:
arrays they remain endpoint node ids, so use from-anchor and to-anchor
there.
animation:
auto-play: normal
routes:
normal:
nodes: [Start, Check]
duration: 500Supported Diagram Types
- Flow diagrams
- Screen flows
- ER diagrams
- Component diagrams
- Class diagrams
- Sequence diagrams
- Notes / comments
Node Attributes
Common node attributes:
| Attribute | Example | Description |
|---|---|---|
| kind | kind: screen | Node kind such as screen, process, file, database (db), decision, start, end, entity, note |
| state | state: success | Visual preset: accent, success, warning, error, muted |
| lane | lane: customer | Swimlane name |
| x, y | x: 120 | Manual position |
| dx, dy | dx: 16 | Position fine tuning |
| payload | payload: + nested YAML-style fields | Data passed to interaction events. Nodes and edges with payload open the default popup by default |
| popup | popup: CustomPopup | Optional explicit popup id override |
| link | link: https://example.com | Opens a URL on click |
| target | target: _blank | Link target |
| flow-ref | flow-ref: checkout/main | Subflow reference badge and event |
Edge Syntax
A -> B
A --> B
A - B
A -- B
A:right! -> B:left!:
label: forced portsCommon edge attributes:
| Attribute | Example | Description |
|---|---|---|
| label | label: submit | Edge label |
| stroke | stroke: #15803d | Edge color |
| stroke-width | stroke-width: 4 | Edge width |
| marker-end | marker-end: none | Removes arrow marker |
| route | route: perimeter | Route strategy |
| on-success | on-success: true | Success path styling |
| on-failure | on-failure: true | Failure path styling |
| from-anchor-offset | from-anchor-offset: 8 | Moves the source anchor along the selected node side. from-offset is kept as a compatible alias. |
| to-anchor-offset | to-anchor-offset: -6 | Moves the target anchor along the selected node side. to-offset is kept as a compatible alias. |
| from-anchor-dx, from-anchor-dy | from-anchor-dy: 12 | Force-shifts the source anchor point by X/Y pixels. Useful when several lines share one side. |
| to-anchor-dx, to-anchor-dy | to-anchor-dx: -10 | Force-shifts the target anchor point by X/Y pixels. |
| parallel-group | parallel-group: stream-1 | Parallel edge separation |
| bus | bus: api-bus | Shared bus routing |
Example:
Landing:right! -> Login:left!:
label: Login
from-anchor-dy: 12
to-anchor-dy: -8ER Diagram
layout:
mode: horizontal
auto-fit: true
User:
PK id bigint
email varchar(255) UNIQUE NOT NULL
---
kind: entity
Order:
PK id bigint
FK user_id bigint NOT NULL
status varchar(20) NOT NULL
---
kind: entity
User 1--0< Order: "orders"Field mapping can be written with repeated key: lines.
Order 1--0< OrderLog "audit":
key: id--order_id
key: user_id--user_idComponent Diagram
layout:
mode: horizontal
auto-fit: true
component Order:
Order
---
x: 80
y: 170
component Product:
Product
---
x: 560
y: 80
component Account:
Account
---
x: 560
y: 300
Order:right! -|o- Product:left!:
Item Code
Order:bottom! -|--o- Account:left!:
Account Details-|o- renders a provided interface connection. -|--o- renders an assembly-style connection where the middle segment is dashed.
Sequence Diagram
sequence:
participants:
- id: User
kind: actor
view: User
- id: App
kind: participant
view: App
- id: API
kind: participant
view: API
steps:
- from: User
to: App
label: Submit
- from: App
to: API
label: POST /orders
- from: API
to: App
arrow: -->
label: 201 Created
- from: App
to: User
arrow: -->
label: DoneNotes
Input:
Input
---
kind: screen
Validate:
Validate
---
kind: process
note Rule:
Required fields and format checks
---
target: Validate
state: warning
Input -> ValidatePublic API
import {
Wireflow,
renderWireflow,
parseDsl,
createPopup,
createDefaultPopupRenderer,
popupHtml,
escapeHtml,
parseMdWireflow,
createFlowNavigator,
schema,
listNodeKinds,
} from "@t-yamauchi/wireflow";Browser global:
const {
Wireflow,
renderWireflow,
parseDsl,
createPopup,
createDefaultPopupRenderer,
popupHtml,
escapeHtml,
schema,
listNodeKinds,
} = window.WireflowLib;エディタ補完用スキーマ
schema は Wireflow DSL の補完候補として使える属性、列挙値、スニペットを公開します。schema.version はパッケージの version と同じ値です。
import { schema, listNodeKinds } from "@t-yamauchi/wireflow";
const kindValues = listNodeKinds();
const layoutAttributes = schema.attributes.filter((attr) => attr.scope === "layout");Popup
For the shortest setup, let the static helper create the instance, inject styles, attach the default popup, and render immediately:
Wireflow.render("#canvas", dsl);Disable the default popup only when you need full custom handling:
Wireflow.render("#canvas", dsl, { popup: false });
const wf = new Wireflow("#canvas", { defaultPopup: false });The default popup reads payload fields such as title, desc, note, image, html, and imageAlt.
If image or html is true, Wireflow derives the file name from the element/popup id in lowercase:
Test:
Test
---
payload:
image: true
# -> images/test.svg
Review:
Review
---
payload:
html: true
# -> htmls/review.htmlIf both image: true and html: true are set, html wins and the image is not shown.
Explicit media file names are also supported:
payload:
title: Preview
image: dashboard.svg
htmlUrl: review.htmlYou can change those folders at initialization time:
Wireflow.render("#canvas", dsl, {
popup: {
imageBasePath: "/assets/images/",
htmlBasePath: "/assets/htmls/",
imageExtension: ".png",
htmlExtension: ".html",
},
});createPopup("#canvas", {
render: ({ id, data, html }) => html`
<h2>${data.title ?? id}</h2>
<p>${data.desc ?? ""}</p>
`,
});data is the normalized object payload, and html escapes interpolated values automatically.
If you need raw HTML, return an Element instead.
Nodes with a payload emit popup events automatically.
Use popup: CustomPopup only when you want to override the popup id.
Editor History
Wireflow supports undo/redo for DSL-changing interactions.
- Undo:
Ctrl + Z/Cmd + Z - Redo:
Ctrl + Y/Cmd + Y/Ctrl + Shift + Z - Change event:
wireflow:dsl-change
When a node is moved, manual route points on edges connected to that node are cleared so those routes can be recalculated from the new node position.
License
MIT
