schematex 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/ai-sdk.cjs +9 -9
- package/dist/ai/ai-sdk.d.cts +1 -1
- package/dist/ai/ai-sdk.d.ts +1 -1
- package/dist/ai/ai-sdk.js +4 -4
- package/dist/ai/index.cjs +15 -15
- package/dist/ai/index.js +4 -4
- package/dist/browser.cjs +10 -10
- package/dist/browser.js +4 -4
- package/dist/{chunk-ST5YRTTV.cjs → chunk-2F45Y2ON.cjs} +44 -5
- package/dist/chunk-2F45Y2ON.cjs.map +1 -0
- package/dist/{chunk-V4RO5KYY.cjs → chunk-3JAI3OVG.cjs} +81 -47
- package/dist/chunk-3JAI3OVG.cjs.map +1 -0
- package/dist/{chunk-P63S7P6N.js → chunk-ITUPR7G5.js} +263 -48
- package/dist/chunk-ITUPR7G5.js.map +1 -0
- package/dist/{chunk-7AFW2J6J.js → chunk-IZWKJVIC.js} +125 -15
- package/dist/chunk-IZWKJVIC.js.map +1 -0
- package/dist/{chunk-UWA5MWCI.js → chunk-JVAJ6ZLO.js} +81 -47
- package/dist/chunk-JVAJ6ZLO.js.map +1 -0
- package/dist/{chunk-25ZON47K.cjs → chunk-KSNUMQGS.cjs} +127 -17
- package/dist/chunk-KSNUMQGS.cjs.map +1 -0
- package/dist/{chunk-6URNSB6G.js → chunk-P26FCZP3.js} +44 -5
- package/dist/chunk-P26FCZP3.js.map +1 -0
- package/dist/{chunk-YVDUEUFV.cjs → chunk-SD6VDTQR.cjs} +265 -50
- package/dist/chunk-SD6VDTQR.cjs.map +1 -0
- package/dist/diagrams/circuit/index.cjs +7 -7
- package/dist/diagrams/circuit/index.js +1 -1
- package/dist/diagrams/timing/index.cjs +4 -4
- package/dist/diagrams/timing/index.js +1 -1
- package/dist/index.cjs +26 -26
- package/dist/index.js +5 -5
- package/dist/react.cjs +4 -4
- package/dist/react.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-25ZON47K.cjs.map +0 -1
- package/dist/chunk-6URNSB6G.js.map +0 -1
- package/dist/chunk-7AFW2J6J.js.map +0 -1
- package/dist/chunk-P63S7P6N.js.map +0 -1
- package/dist/chunk-ST5YRTTV.cjs.map +0 -1
- package/dist/chunk-UWA5MWCI.js.map +0 -1
- package/dist/chunk-V4RO5KYY.cjs.map +0 -1
- package/dist/chunk-YVDUEUFV.cjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseResult, renderResult } from './chunk-
|
|
1
|
+
import { parseResult, renderResult } from './chunk-IZWKJVIC.js';
|
|
2
2
|
|
|
3
3
|
// src/ai/registry.ts
|
|
4
4
|
var DIAGRAM_REGISTRY = [
|
|
@@ -482,6 +482,25 @@ var EXAMPLES = [
|
|
|
482
482
|
"dsl": 'bpmn\ndirection: LR\ntitle: "Pizza order"\n\npool "Customer" blackbox\n\npool "Pizzeria" {\n lane "Clerk" {\n A: start message "Order received"\n B: task user "Take order"\n }\n lane "Chef" {\n C: task manual "Make pizza"\n G1: gateway xor "Pizza ok?"\n D: task manual "Rework"\n }\n lane "Delivery" {\n E: task send "Deliver"\n F: end "Done"\n }\n}\n\nflows\nA --> B\nB --> C\nC --> G1\nG1 --? "yes" --> E\nG1 --* "no" --> D\nD --> C\nE --> F\n"Customer" ~~> A : "Place order"\nE ~~> "Customer" : "Pizza delivered"',
|
|
483
483
|
"notes": 'This is the OMG-tutorial *hello world* for BPMN \u2014 every BPM textbook and certification course uses some version of it. It\'s a deceptively rich example: in 12 elements it covers every concept that distinguishes BPMN from a generic flowchart.\n\n**Black-box pool.** The customer\'s internal process is unknown (and irrelevant) to the pizzeria, so Customer is rendered as an empty rectangle with no flow objects. Schematex enforces this \u2014 adding a lane or a task inside a `blackbox` pool fails the parse. Black-box pools exist purely as message-flow endpoints.\n\n**Message flows cross pools, sequence flows do not.** The two `~~>` connectors are dashed with an open arrowhead and a small unfilled circle at the source. That\'s the *only* legal way information crosses a pool boundary in BPMN. Schematex\'s parser will reject `A --> "Customer"` with a clear error.\n\n**Rework loop.** `D --> C` creates a back-edge. The layout\'s longest-path layering would normally fail on cycles; Schematex\'s DFS-based cycle-break tags `D \u2192 C` as a back edge, runs longest-path on the remaining DAG, then routes the loop manually. This is exactly how real processes look \u2014 quality gates always have a "go back and redo it" branch.\n\n**Task markers communicate intent.** `start message` (envelope) means "wait for an inbound message before starting"; `task manual` means a person performs the work without software ("hand-toss the dough"); `task send` means "send a message and continue". An LLM picking markers correctly turns a vague flowchart into a precise process spec.'
|
|
484
484
|
},
|
|
485
|
+
{
|
|
486
|
+
"slug": "bpmn-refund-escalation-compensation",
|
|
487
|
+
"diagram": "bpmn",
|
|
488
|
+
"title": "Refund escalation workflow",
|
|
489
|
+
"description": "BPMN process for refund handling across Support, Risk, Finance, and an external payment processor, with SLA timer escalation and customer-facing message flows.",
|
|
490
|
+
"standard": "OMG BPMN 2.0.2 / ISO/IEC 19510:2013",
|
|
491
|
+
"tags": [
|
|
492
|
+
"bpmn",
|
|
493
|
+
"refund",
|
|
494
|
+
"escalation",
|
|
495
|
+
"timer",
|
|
496
|
+
"finance",
|
|
497
|
+
"support"
|
|
498
|
+
],
|
|
499
|
+
"complexity": 3,
|
|
500
|
+
"featured": false,
|
|
501
|
+
"dsl": 'bpmn\ndirection: LR\ntitle: "Refund escalation"\n\npool "Customer" blackbox\npool "Payment Processor" blackbox\n\npool "Merchant" {\n lane "Support" {\n S: start message "Refund request"\n TRIAGE: task user "Triage request"\n DOCS: gateway xor "Enough evidence?"\n ASK: task send "Ask for documents"\n SLA: intermediate timer "48h SLA"\n ESC: task user "Escalate case"\n }\n lane "Risk" {\n RISK: task user "Risk review"\n G1: gateway xor "Policy breach?"\n DENY: task send "Deny refund"\n }\n lane "Finance" {\n CALC: task service "Calculate amount"\n APPROVE: task user "Approve refund"\n ISSUE: task send "Issue refund"\n ENDOK: end message "Refund sent"\n ENDDENY: end message "Denied"\n }\n}\n\nflows\nS --> TRIAGE\nTRIAGE --> DOCS\nDOCS --? "missing" --> ASK\nASK --> SLA\nSLA --> ESC\nESC --> RISK\nDOCS --* "complete" --> RISK\nRISK --> G1\nG1 --? "yes" --> DENY\nDENY --> ENDDENY\nG1 --* "no" --> CALC\nCALC --> APPROVE\nAPPROVE --> ISSUE\nISSUE --> ENDOK\n"Customer" ~~> S : "Refund request"\nASK ~~> "Customer" : "Need documents"\nDENY ~~> "Customer" : "Denial notice"\nISSUE ~~> "Payment Processor" : "Refund API"\n"Payment Processor" ~~> ENDOK : "Refund confirmed"',
|
|
502
|
+
"notes": "## Scenario\n\nRefund handling is a process-governance problem: support receives the customer request, risk decides whether policy blocks the refund, finance approves and issues the money movement, and the payment processor confirms settlement. BPMN is the right notation because lanes and message flows are part of the meaning.\n\n## Annotation key\n\n- The `48h SLA` timer event makes escalation a timed process milestone rather than a vague task.\n- Message flows (`~~>`) cross pool boundaries for customer and processor communication.\n- The XOR gateway separates policy denial from the refund issuance path."
|
|
503
|
+
},
|
|
485
504
|
{
|
|
486
505
|
"slug": "breadboard-blink-led",
|
|
487
506
|
"diagram": "breadboard",
|
|
@@ -595,6 +614,25 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
595
614
|
"dsl": 'circuit "Inverting Op-Amp (netlist)" netlist\nVin vin 0 AC1V\nRin vin inv 10k\nRf out inv 100k\nU1 noninv inv out type=opamp label="U1 TL072"\nRbias noninv 0 10k\nVp vcc 0 +12V\nVn vee 0 -12V',
|
|
596
615
|
"notes": "## Scenario\n\nAn analog engineer documents a standard inverting gain stage before moving to PCB layout. The two resistors make the gain visible in the schematic: `Rf / Rin = 10`, so the output is an inverted, amplified version of the input.\n\n## Annotation key\n\n- `type=opamp` selects the three-pin op-amp symbol in netlist mode.\n- `Rin` and `Rf` are ordinary SPICE-style resistor lines.\n- `noninv`, `inv`, and `out` are named nets, not pixel coordinates.\n\n## How to read\n\nThe input signal enters through `Rin` into the inverting input. `Rf` feeds the output back to the same node, closing the negative feedback loop. The non-inverting input is tied to ground through `Rbias`, giving the stage a stable reference."
|
|
597
616
|
},
|
|
617
|
+
{
|
|
618
|
+
"slug": "circuit-pullup-orientation-hint",
|
|
619
|
+
"diagram": "circuit",
|
|
620
|
+
"title": "Pull-up resistor circuit with dir= orientation hint",
|
|
621
|
+
"description": "A netlist-mode circuit that uses the optional dir= orientation hint to draw the pull-up resistor vertically, showing lightweight layout control on top of automatic placement.",
|
|
622
|
+
"standard": "IEEE 315 / IEC 60617",
|
|
623
|
+
"tags": [
|
|
624
|
+
"netlist",
|
|
625
|
+
"pull-up",
|
|
626
|
+
"dir",
|
|
627
|
+
"orientation",
|
|
628
|
+
"push-button",
|
|
629
|
+
"SPICE"
|
|
630
|
+
],
|
|
631
|
+
"complexity": 1,
|
|
632
|
+
"featured": false,
|
|
633
|
+
"dsl": 'circuit "Pull-up + push button" netlist\nV1 vcc 0 5V\nR1 vcc sig 10k dir=down\nSW1 sig 0 type=switch\nC1 sig 0 100n',
|
|
634
|
+
"notes": "## Scenario\n\nAn embedded engineer documents a classic active-low input: a pull-up resistor\nholds the signal high, a push button pulls it to ground, and a small capacitor\ndebounces it. The connectivity is written as a SPICE-style netlist \u2014 the engine\nplaces everything from the node names \u2014 and one optional hint refines the look.\n\n## Annotation key\n\n- **netlist line** \u2014 `id node-A node-B value`; components that share a node name\n are wired together. `0` is ground.\n- **`dir=down`** \u2014 the optional orientation hint. `R1` connects `vcc` to `sig`;\n by default the engine would lay it horizontally, but a pull-up reads best drawn\n vertically from the supply rail down to the signal node, so `dir=down` rotates\n just that symbol. Connectivity is unchanged \u2014 `dir=` only rotates the glyph.\n- **`type=switch`** \u2014 the `SW1` id prefix is ambiguous, so the component type is\n made explicit.\n\n## How to read\n\n`R1` ties `sig` up to `vcc` (drawn vertically thanks to `dir=down`). `SW1` and the\ndebounce cap `C1` both go from `sig` to ground, so the engine recognises them as\nshunt legs and drops them beneath the node. Pressing the button shorts `sig` to\nground, pulling the input low."
|
|
635
|
+
},
|
|
598
636
|
{
|
|
599
637
|
"slug": "decisiontree-investment-analysis",
|
|
600
638
|
"diagram": "decisiontree",
|
|
@@ -773,6 +811,25 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
773
811
|
"dsl": 'entity-structure "Acme Inc. \u2014 post Series A"\nentity acme "Acme Inc." corp@DE\nentity founders "Founders (2)" individual\nentity seed "Seed Fund I" lp@DE\nentity lead "Sequoia Series A" lp@DE\nentity angels "Angel group" individual\nentity esop "Employee Option Pool" trust@DE\nfounders -> acme : 45%\nseed -> acme : 12%\nlead -> acme : 22%\nangels -> acme : 6%\nesop -> acme : 15%',
|
|
774
812
|
"notes": "## Scenario\n\nA startup attorney or CFO documents the post-Series A ownership table for a 409A valuation, board consent, or investor report. The cap table diagram makes the dilution story visual \u2014 founders can immediately see their post-money percentage, and the VC can verify their ownership stake before signing the term sheet.\n\n## Annotation key\n\n- `-> acme : 45%` \u2014 ownership arrow with percentage label; all percentages should sum to 100%\n- `individual` \u2014 natural person (founder, angel)\n- `lp` \u2014 institutional investor entity (fund/LP)\n- `trust` \u2014 the ESOP/option pool (typically a Delaware trust or reserved pool)\n- `corp@DE` \u2014 the issuer (Delaware C-corp)\n\n## How to read\n\nAcme Inc. (Delaware C-corp) sits at the bottom as the issuer. Five shareholder classes flow down with their ownership arrows: founders at 45%, the lead Series A investor at 22%, the employee option pool at 15%, the seed fund at 12%, and angels at 6%. Percentages sum to 100%, representing a clean fully-diluted cap table on the day of Series A close."
|
|
775
813
|
},
|
|
814
|
+
{
|
|
815
|
+
"slug": "erd-billing-ledger-audit-trail",
|
|
816
|
+
"diagram": "erd",
|
|
817
|
+
"title": "Billing ledger and audit trail",
|
|
818
|
+
"description": "Crow's-foot ERD for an immutable SaaS billing ledger with customers, invoices, payments, refunds, ledger entries, and audit events.",
|
|
819
|
+
"standard": "Crow's-foot ERD",
|
|
820
|
+
"tags": [
|
|
821
|
+
"erd",
|
|
822
|
+
"billing",
|
|
823
|
+
"ledger",
|
|
824
|
+
"audit-trail",
|
|
825
|
+
"finance",
|
|
826
|
+
"schema"
|
|
827
|
+
],
|
|
828
|
+
"complexity": 3,
|
|
829
|
+
"featured": false,
|
|
830
|
+
"dsl": 'erd\ntitle: "Billing Ledger"\ndirection: LR\n\ntable Customer {\n customer_id uuid PK\n email varchar UK\n billing_currency char NN\n}\ntable Subscription {\n subscription_id uuid PK\n customer_id uuid FK -> Customer.customer_id\n status varchar NN\n current_period_end timestamptz\n}\ntable Invoice {\n invoice_id uuid PK\n customer_id uuid FK -> Customer.customer_id\n subscription_id uuid FK -> Subscription.subscription_id\n number varchar UK\n total_cents bigint NN\n status varchar NN\n}\ntable Payment {\n payment_id uuid PK\n invoice_id uuid FK -> Invoice.invoice_id\n provider_ref varchar UK\n amount_cents bigint NN\n captured_at timestamptz\n}\ntable Refund {\n refund_id uuid PK\n payment_id uuid FK -> Payment.payment_id\n amount_cents bigint NN\n reason varchar\n}\ntable LedgerEntry {\n entry_id uuid PK\n customer_id uuid FK -> Customer.customer_id\n invoice_id uuid FK -> Invoice.invoice_id\n payment_id uuid FK -> Payment.payment_id\n refund_id uuid FK -> Refund.refund_id\n entry_type varchar NN\n amount_cents bigint NN\n posted_at timestamptz NN\n}\ntable AuditEvent {\n event_id uuid PK\n actor_id uuid\n entity_type varchar NN\n entity_id uuid NN\n action varchar NN\n created_at timestamptz NN\n}\n\nref Subscription.customer_id many-mandatory -- one-mandatory Customer.customer_id : "belongs to"\nref Invoice.customer_id many-mandatory -- one-mandatory Customer.customer_id : "billed to"\nref Invoice.subscription_id many-optional .. one-optional Subscription.subscription_id : "for plan"\nref Payment.invoice_id many-optional -- one-mandatory Invoice.invoice_id : "settles"\nref Refund.payment_id many-optional -- one-mandatory Payment.payment_id : "reverses"\nref LedgerEntry.customer_id many-mandatory -- one-mandatory Customer.customer_id : "posts for"\nref LedgerEntry.invoice_id many-optional .. one-optional Invoice.invoice_id : "source invoice"\nref LedgerEntry.payment_id many-optional .. one-optional Payment.payment_id : "source payment"\nref LedgerEntry.refund_id many-optional .. one-optional Refund.refund_id : "source refund"',
|
|
831
|
+
"notes": "## Scenario\n\nBilling schemas become risky when money movement and auditability are mixed into mutable order tables. This ERD separates commercial objects from immutable ledger entries, making it clear which facts can change and which entries are accounting evidence.\n\n## Annotation key\n\n- `LedgerEntry` points optionally to invoices, payments, and refunds because each entry has exactly one accounting source.\n- Solid `--` relationships show identifying operational ownership.\n- Dashed `..` relationships show optional audit/source references that should not control the lifecycle of the ledger row."
|
|
832
|
+
},
|
|
776
833
|
{
|
|
777
834
|
"slug": "erd-ecommerce-schema",
|
|
778
835
|
"diagram": "erd",
|
|
@@ -940,6 +997,24 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
940
997
|
"dsl": "flowchart TD\n commit([Push to main]) --> build[Build artifact]\n build --> unit{Unit tests pass?}\n unit -->|No| fail([Fail build])\n unit -->|Yes| scan[Security scan]\n scan --> vuln{High-severity CVEs?}\n vuln -->|Yes| fail\n vuln -->|No| stage[Deploy to staging]\n stage --> smoke{Smoke tests green?}\n smoke -->|No| fail\n smoke -->|Yes| approve{Manual approval?}\n approve -->|No| wait([Await approver])\n approve -->|Yes| prod[Deploy to production]\n prod --> health{Post-deploy health check?}\n health -->|Yes| done([Release complete])\n health -->|No| rollback[Automatic rollback]\n rollback --> done",
|
|
941
998
|
"notes": "## Scenario\n\nA platform engineer is documenting the team's trunk-based pipeline for a new-hire runbook. The diagram makes the four automated gates (tests \u2192 scan \u2192 smoke \u2192 post-deploy health) and the single human gate (manual approval) obvious at a glance, and shows that every failure path terminates the pipeline rather than silently continuing.\n\n## Annotation key\n\n- `([\u2026])` \u2014 stadium; start and terminal nodes\n- `{\u2026}` \u2014 diamond; automated or manual gate\n- `[\u2026]` \u2014 rectangle; build / deploy / scan step\n- `-->|Yes/No|` \u2014 branch labels on each gate\n\n## How to read\n\nStart at *Push to main*. Every diamond is a gate \u2014 a *No* on any of unit tests, CVE scan, or smoke tests terminates at *Fail build*. Manual approval is the only human gate; it can park the pipeline at *Await approver* without failing. The post-deploy health check guards production: a failure triggers automatic rollback, which still completes at *Release complete* because the rollback itself is a successful outcome."
|
|
942
999
|
},
|
|
1000
|
+
{
|
|
1001
|
+
"slug": "flowchart-insurance-claim-adjudication",
|
|
1002
|
+
"diagram": "flowchart",
|
|
1003
|
+
"title": "Insurance claim adjudication",
|
|
1004
|
+
"description": "ISO-style flowchart for a claims team triaging coverage, fraud risk, document completeness, manual review, and payment or denial outcomes.",
|
|
1005
|
+
"standard": "ISO 5807:1985",
|
|
1006
|
+
"tags": [
|
|
1007
|
+
"flowchart",
|
|
1008
|
+
"insurance",
|
|
1009
|
+
"claims",
|
|
1010
|
+
"adjudication",
|
|
1011
|
+
"manual-review"
|
|
1012
|
+
],
|
|
1013
|
+
"complexity": 3,
|
|
1014
|
+
"featured": false,
|
|
1015
|
+
"dsl": "flowchart LR\n start([Claim submitted])\n intake[/Capture FNOL data/]\n docs{Documents complete?}\n request[Request missing documents]\n coverage{Policy active on loss date?}\n deny1[Issue coverage denial]\n fraud{Fraud score high?}\n review[[Manual SIU review]]\n liability{Liability accepted?}\n estimate[Calculate covered amount]\n approve{Adjuster approval?}\n pay[(Payment ledger)]\n denial[Send denial letter]\n close([Close claim])\n\n start --> intake\n intake --> docs\n docs -->|No| request\n request -.->|Resubmitted| docs\n docs -->|Yes| coverage\n coverage -->|No| deny1\n deny1 --> close\n coverage -->|Yes| fraud\n fraud -->|Yes| review\n review --> liability\n fraud -->|No| liability\n liability -->|No| denial\n denial --> close\n liability -->|Yes| estimate\n estimate --> approve\n approve -->|Needs changes| estimate\n approve -->|Approved| pay\n pay --> close",
|
|
1016
|
+
"notes": "## Scenario\n\nClaim adjudication is not a straight line. The same claim can bounce for missing documents, route to special investigation, return for estimate changes, or close through denial. A flowchart is appropriate here because the core question is operational routing, not ownership lanes or event semantics.\n\n## Annotation key\n\n- Parallelogram `[/.../]` marks intake data capture.\n- `[[...]]` marks a predefined manual review subprocess.\n- Dotted retry edge shows a resubmission loop without making it the main path."
|
|
1017
|
+
},
|
|
943
1018
|
{
|
|
944
1019
|
"slug": "flowchart-order-fulfillment",
|
|
945
1020
|
"diagram": "flowchart",
|
|
@@ -1406,6 +1481,26 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
1406
1481
|
"dsl": 'network "DC Fabric"\n layout: spine-leaf\n spines: sp1 sp2\n leaves: lf1 lf2 lf3 lf4\n server h1\n server h2\n server h3\n lf1 -- h1 : 25G\n lf2 -- h2 : 25G\n lf4 -- h3 : 25G',
|
|
1407
1482
|
"notes": "## Scenario\n\nA data-center architect wants the fabric drawn without hand-typing every spine-to-leaf cable. In `layout: spine-leaf` mode you declare the spines and leaves, and the engine **auto-meshes every leaf to every spine** \u2014 here that's 2 \xD7 4 = 8 generated links \u2014 leaving you to add only the host attachments.\n\n## What the diagram shows\n\n- **`spines:` / `leaves:`** declare the two fabric rows. The devices don't need a separate `kind` line \u2014 spines become L3 switches, leaves become switches.\n- **Auto-mesh** \u2014 every spine\u2194leaf link is generated; you never type them. Add or remove a leaf and the mesh updates.\n- **Host attachments** \u2014 `lf1 -- h1 : 25G` hangs a server below its leaf at 25 Gbps.\n\n## Annotation key\n\n| Element | Meaning |\n|---|---|\n| Top row | Spine switches |\n| Middle row | Leaf switches (fully meshed to spines) |\n| Bottom row | Hosts, under their leaf |\n\nThis is the modern east-west fabric; for a traditional north-south campus use `layout: tiered` with `tier:` bands instead."
|
|
1408
1483
|
},
|
|
1484
|
+
{
|
|
1485
|
+
"slug": "network-zero-trust-cloud-vpc",
|
|
1486
|
+
"diagram": "network",
|
|
1487
|
+
"title": "Zero-trust cloud VPC topology",
|
|
1488
|
+
"description": "Network topology for a zero-trust SaaS VPC with VPN entry, DMZ, private application subnet, database subnet, firewall segmentation, and annotated VPN/fiber/trunk links.",
|
|
1489
|
+
"standard": "Cisco-convention topology icons + security-zone topology",
|
|
1490
|
+
"tags": [
|
|
1491
|
+
"network",
|
|
1492
|
+
"zero-trust",
|
|
1493
|
+
"vpc",
|
|
1494
|
+
"dmz",
|
|
1495
|
+
"vpn",
|
|
1496
|
+
"firewall",
|
|
1497
|
+
"cloud"
|
|
1498
|
+
],
|
|
1499
|
+
"complexity": 3,
|
|
1500
|
+
"featured": false,
|
|
1501
|
+
"dsl": 'network "Zero-trust SaaS VPC"\n layout: tiered\n internet inet "Internet"\n cloud idp "Identity Provider"\n vpngw vpn "Client VPN" tier: edge\n firewall fw "Segmentation FW" tier: edge\n loadbalancer alb "Public ALB" tier: distribution\n\n zone dmz "DMZ" {\n proxy edgeproxy "Reverse Proxy" tier: distribution\n }\n subnet appnet "10.20.10.0/24" {\n server api1 "API 1" ip: 10.20.10.11\n server api2 "API 2" ip: 10.20.10.12\n }\n subnet dbnet "10.20.30.0/24" {\n storage db "Postgres HA" ip: 10.20.30.20\n }\n zone admin "Admin Zone" {\n laptop admin1 "Admin Laptop"\n }\n\n inet -- alb : fiber 10G\n inet -- vpn : vpn\n idp -- vpn : vpn "OIDC"\n vpn -- fw : vpn "device posture"\n alb -- edgeproxy : 1G\n edgeproxy -- fw : trunk vlan: 110\n fw -- api1 : access vlan: 210 1G\n fw -- api2 : access vlan: 210 1G\n fw -- db : access vlan: 230 1G\n admin1 -- vpn : wireless vpn',
|
|
1502
|
+
"notes": "## Scenario\n\nZero-trust diagrams need to show both the physical/logical topology and the policy boundary: public traffic reaches only the DMZ, administrators enter through VPN and identity checks, and application servers reach the database through a segmented firewall path.\n\n## Annotation key\n\n- `zone` and `subnet` groups distinguish security policy from IP address space.\n- VPN links are dashed and annotated, making identity/device-posture paths visible.\n- VLAN labels document segmentation at the firewall boundary."
|
|
1503
|
+
},
|
|
1409
1504
|
{
|
|
1410
1505
|
"slug": "orgchart-matrix-reporting",
|
|
1411
1506
|
"diagram": "orgchart",
|
|
@@ -1951,6 +2046,25 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
1951
2046
|
"dsl": "sequence\n participant Factory\n Factory -> *Worker : \xABcreate\xBB\n o-> Worker : external trigger\n Worker -x : fire-and-forget\n destroy Worker",
|
|
1952
2047
|
"notes": 'UML interactions model not just messages but the *birth and death* of participants \u2014 the part most text-to-diagram tools skip. This tiny diagram shows all four markers.\n\n**Create.** `Factory -> *Worker` \u2014 the `*` prefix creates `Worker`; its arrow lands on the *side of the new participant\'s box*, which appears partway down rather than at the top, the UML convention for "instantiated here."\n\n**Found and lost.** `o-> Worker` is a *found* message \u2014 it starts from a filled circle, meaning "from outside the modelled scope" (an external trigger). `Worker -x` is a *lost* message \u2014 it ends at a circle, a fire-and-forget whose receiver isn\'t shown.\n\n**Destroy.** `destroy Worker` terminates the lifeline with the \u2715 marker, so the diagram shows exactly when the object ceases to exist.'
|
|
1953
2048
|
},
|
|
2049
|
+
{
|
|
2050
|
+
"slug": "sequence-retry-timeout-circuit-breaker",
|
|
2051
|
+
"diagram": "sequence",
|
|
2052
|
+
"title": "Retry, timeout, and circuit breaker",
|
|
2053
|
+
"description": "UML sequence diagram for a gateway calling a payment service through a circuit breaker, with retry attempts, timeout handling, a break fragment for an open breaker, and an asynchronous fallback event.",
|
|
2054
|
+
"standard": "OMG UML 2.5.1",
|
|
2055
|
+
"tags": [
|
|
2056
|
+
"sequence",
|
|
2057
|
+
"uml",
|
|
2058
|
+
"retry",
|
|
2059
|
+
"timeout",
|
|
2060
|
+
"circuit-breaker",
|
|
2061
|
+
"resilience"
|
|
2062
|
+
],
|
|
2063
|
+
"complexity": 3,
|
|
2064
|
+
"featured": false,
|
|
2065
|
+
"dsl": 'sequence "Checkout payment resilience"\n autonumber 1 1\n actor Client\n boundary API as "Checkout API"\n control Breaker as "Circuit Breaker"\n participant Payment as "Payment Provider"\n queue Jobs as "Fallback Queue"\n\n Client ->+ API : POST /checkout/pay\n API -> Breaker : allowRequest()\n alt [breaker closed]\n Breaker --> API : permit\n loop (1,3)\n API ->+ Payment : authorize(amount)\n alt [response before timeout]\n Payment -->- API : auth result\n break [authorized]\n API -->- Client : 200 Authorized\n end\n else [timeout]\n API -> Breaker : recordFailure(timeout)\n API ->> Jobs : enqueue retry context\n end\n end\n API -->- Client : 202 Pending verification\n else [breaker open]\n Breaker --> API : reject\n API ->> Jobs : enqueue deferred payment\n API -->- Client : 503 Retry later\n end',
|
|
2066
|
+
"notes": "## Scenario\n\nA checkout API must protect itself from a slow or failing payment provider. The diagram makes the resilience policy reviewable: the gateway checks the breaker, retries bounded attempts, records timeouts, and falls back to asynchronous recovery instead of blocking the customer forever.\n\n## Annotation key\n\n- `loop (1,3)` documents the bounded retry policy.\n- `alt` separates fast responses, timeouts, and open-breaker rejection.\n- `break [authorized]` exits the retry loop once a successful authorization arrives.\n- `->>` marks asynchronous fallback work queued outside the request path."
|
|
2067
|
+
},
|
|
1954
2068
|
{
|
|
1955
2069
|
"slug": "sfc-bake-cool-concurrent",
|
|
1956
2070
|
"diagram": "sfc",
|
|
@@ -2224,6 +2338,24 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
2224
2338
|
"dsl": 'state "E-Commerce Order Lifecycle"\n\ninitial i\ni -> Pending\n\nPending -> Confirmed : place_order [items_in_stock] / reserveInventory()\nPending -> Cancelled : cancel\n\nchoice PayRoute\nConfirmed -> PayRoute : pay\nPayRoute -> Processing : [method == "card"]\nPayRoute -> Processing : [method == "wallet"]\nPayRoute -> AwaitingTransfer : [method == "bank_transfer"]\n\nAwaitingTransfer -> Processing : transfer_received [amount_correct]\nAwaitingTransfer -> Cancelled : transfer_timeout\n\ncomposite Processing {\n initial pi\n final pf\n\n pi -> Picking\n Picking -> Packing : picked / updateWarehouse()\n Packing -> Shipped : label_printed\n Shipped -> pf : carrier_confirmed\n}\n\nProcessing -> Delivered : delivered / notifyCustomer()\nProcessing -> Failed : fulfillment_error\n\nDelivered -> Refunded : return_request [within_30_days] / initiateRefund()\nFailed -> Pending : retry [attempt < 3]\nFailed -> Cancelled : retry [attempt >= 3]\n\nfinal f\nDelivered -> f\nRefunded -> f\nCancelled -> f\n\nnote right_of AwaitingTransfer : SLA: 48 h before timeout.',
|
|
2225
2339
|
"notes": 'Order state machines are one of the most common backend design artifacts, and one of the most commonly under-specified. Teams often start with a simple enum (`PENDING / PAID / SHIPPED / DELIVERED`) and then bolt on edge cases over time: partial shipments, payment holds, carrier errors, refund windows. Six months later the enum has twelve values, the transition logic is scattered across three services, and nobody can explain what sequence of events gets an order from `FAILED` to `CANCELLED` versus from `FAILED` back to `PENDING`. A UML state diagram catches all of this upfront.\n\n**Guard conditions on `place_order`.** The transition from `Pending` to `Confirmed` carries `[items_in_stock]` \u2014 a guard. Guards are boolean predicates that must be true for the transition to fire even when the trigger event (`place_order`) occurs. If the guard is false, the trigger is silently absorbed and the system stays in `Pending`. In practice this means inventory is checked synchronously during order placement, and the transition only proceeds if stock is available. The action `/ reserveInventory()` fires when the transition does go through, atomically.\n\n**Choice pseudo-state for payment routing.** `PayRoute` is a UML choice pseudo-state (drawn as a diamond). When the `pay` trigger fires from `Confirmed`, the machine immediately evaluates the guards on all outgoing transitions from `PayRoute`. If `method == "card"` or `method == "wallet"`, control goes directly to `Processing`. If `method == "bank_transfer"`, it goes to `AwaitingTransfer` \u2014 a waiting state with its own 48-hour SLA note. Choice pseudo-states do not dwell; they route. This is the correct model for "take different paths based on a value computed at runtime."\n\n**Composite state for fulfillment.** `Processing` is a composite state \u2014 it contains its own internal state machine with `Picking`, `Packing`, and `Shipped`. From the outside, the system is "in Processing" whether it\'s picking, packing, or confirming with the carrier. From the inside, the sub-machine tracks exactly where the warehouse is. The composite state has its own `initial` and `final` pseudo-states: the machine enters at `pi` (starts picking) and exits through `pf` (carrier confirmed), which fires the outer transition to `Delivered`. Cross-composite transitions to `Failed` are also valid \u2014 a fulfillment error at any sub-state terminates the Processing phase and moves to the outer `Failed` state.\n\n**Retry with bounded attempts.** `Failed` has two outgoing transitions back to `Pending` and `Cancelled`, both triggered by `retry` but guarded on `attempt`. This is the explicit model for "retry up to N times, then give up." Without the state diagram, this logic typically lives in a cron job or a dead-letter queue processor that nobody fully understands. Here it is the specification: anyone reading the diagram knows the retry policy without digging through queue configurations.\n\n**Final state convergence.** `Delivered`, `Refunded`, and `Cancelled` all transition to the same `final` pseudo-state. In implementation, "final" might mean the order record is archived, the event bus receives an `order.closed` event, and no further state transitions are accepted. The model is silent on what happens after final \u2014 that\'s intentional. The state machine is done; downstream processes (analytics, accounting, data retention) are separate concerns.'
|
|
2226
2340
|
},
|
|
2341
|
+
{
|
|
2342
|
+
"slug": "state-subscription-lifecycle",
|
|
2343
|
+
"diagram": "state",
|
|
2344
|
+
"title": "SaaS subscription lifecycle",
|
|
2345
|
+
"description": "UML statechart for a subscription moving through trial, active service, payment recovery, pause, cancellation, and reactivation.",
|
|
2346
|
+
"standard": "OMG UML 2.5.1",
|
|
2347
|
+
"tags": [
|
|
2348
|
+
"statechart",
|
|
2349
|
+
"subscription",
|
|
2350
|
+
"billing",
|
|
2351
|
+
"lifecycle",
|
|
2352
|
+
"guards"
|
|
2353
|
+
],
|
|
2354
|
+
"complexity": 3,
|
|
2355
|
+
"featured": false,
|
|
2356
|
+
"dsl": 'state "Subscription Lifecycle" [direction: LR]\n\ninitial start\nstart -> Trialing\n\nTrialing -> Active : trial_end [payment_method_valid] / startBilling()\nTrialing -> Incomplete : trial_end [payment_method_missing] / requestPaymentMethod()\nTrialing -> Cancelled : cancel\n\ncomposite Active {\n entry / provisionWorkspace()\n exit / syncEntitlements()\n initial ai\n ai -> Current\n Current -> GracePeriod : invoice_failed\n GracePeriod -> Current : payment_succeeded / restoreAccess()\n GracePeriod -> PastDue : grace_expired\n PastDue -> Current : payment_succeeded / clearDunning()\n final af\n Current -> af : cancel_at_period_end\n}\n\nActive -> Paused : pause [plan_allows_pause] / suspendBilling()\nPaused -> Active : resume / resumeBilling()\nActive -> Cancelled : cancel_now / revokeAccess()\nIncomplete -> Active : payment_method_added / retryInvoice()\nIncomplete -> Cancelled : expires\nActive -> Cancelled : period_end\nCancelled -> Active : reactivate [within_retention_window] / restoreSubscription()\n\nfinal done\nCancelled -> done : purge_after_retention\n\nnote right_of Active : Composite state keeps dunning detail inside active service.',
|
|
2357
|
+
"notes": "## Scenario\n\nSubscription logic is where simple status enums drift out of sync with billing providers. This statechart makes the product contract explicit: trial conversion, incomplete setup, dunning recovery, pause, cancellation, and reactivation are separate transitions with guards and actions.\n\n## Annotation key\n\n- `Active` is a composite state because payment recovery happens while the product is still notionally active.\n- Guard labels such as `[payment_method_valid]` document provider-dependent branching.\n- Entry and exit actions mark entitlement provisioning and sync points."
|
|
2358
|
+
},
|
|
2227
2359
|
{
|
|
2228
2360
|
"slug": "state-traffic-light",
|
|
2229
2361
|
"diagram": "state",
|
|
@@ -2297,6 +2429,25 @@ If the LED doesn't light up, three things to check, in order: LED polarity (the
|
|
|
2297
2429
|
"dsl": 'timeline "Platform v2 Launch"\nconfig: style = gantt\n\n2025-07-01 - 2025-08-15: "Engineering build" [category: "engineering"]\n2025-07-15 - 2025-08-31: "Design polish" [category: "design"]\n2025-08-01 - 2025-09-10: "Marketing collateral" [category: "marketing"]\n2025-08-20: milestone "Feature freeze" [color: #E53935]\n2025-08-20 - 2025-09-05: "QA hardening" [category: "engineering"]\n2025-09-01 - 2025-09-12: "Press embargo outreach" [category: "marketing"]\n2025-09-15: milestone "Public launch" [color: #2E7D32]',
|
|
2298
2430
|
"notes": '## Scenario\n\nThe launch PM shares this in weekly exec status. Overlapping bars show where workstreams parallelize (design polishing while engineering still builds) and the feature-freeze diamond makes the handoff between build and QA unmissable. The second milestone (public launch) anchors the entire timeline and is the reason every other bar exists.\n\n## Annotation key\n\n- `DATE - DATE: "Label"` \u2014 range (bar) event\n- `DATE: milestone "Label"` \u2014 point milestone (diamond)\n- `[category: \u2026]` \u2014 group colour in the gantt legend\n- `[color: #hex]` \u2014 explicit marker colour\n\n## How to read\n\nTime flows left to right. Horizontal bars are continuous work; diamonds are instantaneous events. Overlapping bars mean two teams are working simultaneously \u2014 fine, so long as they coordinate. The red *Feature freeze* marks the transition from net-new work to hardening; any engineering bar extending past it needs an exception. The green *Public launch* is the terminal milestone every other bar is serving.'
|
|
2299
2431
|
},
|
|
2432
|
+
{
|
|
2433
|
+
"slug": "timing-clock-rle-shorthand",
|
|
2434
|
+
"diagram": "timing",
|
|
2435
|
+
"title": "Timing diagram with clock and run-length shorthands",
|
|
2436
|
+
"description": "A synchronous bus-read timing diagram written with the clock and rle shorthands so signals stay aligned without hand-counting wave characters.",
|
|
2437
|
+
"standard": "WaveDrom / IEEE 1497",
|
|
2438
|
+
"tags": [
|
|
2439
|
+
"clock",
|
|
2440
|
+
"run-length",
|
|
2441
|
+
"rle",
|
|
2442
|
+
"WaveDrom",
|
|
2443
|
+
"synchronous",
|
|
2444
|
+
"bus-read"
|
|
2445
|
+
],
|
|
2446
|
+
"complexity": 1,
|
|
2447
|
+
"featured": false,
|
|
2448
|
+
"dsl": 'timing "Synchronous Bus Read"\nCLK: clock 8\nRST: rle 1*2 0*6\nEN: rle 0*2 1*4 0*2\nDATA: zz====zz data: ["D0","D1","D2","D3"]',
|
|
2449
|
+
"notes": "## Scenario\n\nA digital designer documents an 8-cycle synchronous read. Rather than typing\n`pppppppp` for the clock and counting `0`/`1` runs by hand for reset and enable \u2014\nthe most common source of misaligned waveforms \u2014 the diagram uses the two\nlength-explicit shorthands.\n\n## Annotation key\n\n- **`clock N`** \u2014 a clock generator with `N` periods. `CLK: clock 8` expands to\n `pppppppp`; add `neg` for a negedge clock. No character-counting.\n- **`rle <state>*<count> \u2026`** \u2014 run-length segments. `RST: rle 1*2 0*6` expands to\n `11000000`; `EN: rle 0*2 1*4 0*2` expands to `00111100`. Every signal's total\n cell count is explicit, so the waves line up.\n- **raw wave string** \u2014 `DATA: zz====zz` keeps per-cell control where it matters;\n `data: [...]` labels the four `=` bus segments.\n\n## How to read\n\nThe clock runs 8 cycles. Reset is asserted for the first 2 cycles, then drops.\nEnable rises for the middle 4 cycles. The data bus is high-impedance until enable,\nthen presents four stable bytes `D0\u2026D3`, returning to high-Z after. Because\n`clock` and `rle` make each signal exactly 8 cells, the edges align without manual\ncounting."
|
|
2450
|
+
},
|
|
2300
2451
|
{
|
|
2301
2452
|
"slug": "timing-i2c-read-burst",
|
|
2302
2453
|
"diagram": "timing",
|
|
@@ -2432,7 +2583,7 @@ var SYNTAX = {
|
|
|
2432
2583
|
},
|
|
2433
2584
|
"timing": {
|
|
2434
2585
|
"title": "Timing diagram",
|
|
2435
|
-
"content": '## 1. Your first timing diagram\n\nThe smallest useful timing diagram: a clock and one data signal
|
|
2586
|
+
"content": '## 1. Your first timing diagram\n\nThe smallest useful timing diagram: a clock and one data signal. The friendliest way to write it avoids counting characters entirely:\n\n```\ntiming\nCLK: clock 8\nRST: rle 1*2 0*6\nDATA: 0011==00 data: ["A","B"]\n```\n\nThree rules cover 80% of usage:\n\n1. Start with the keyword `timing`, optionally followed by a quoted title and `[hscale: N]`.\n2. Each signal is one line: `NAME: <wave>` \u2014 name, colon, then the waveform. The waveform can be:\n - **`clock N`** \u2014 a clock generator with `N` periods (add `neg` for a negedge clock). No character-counting.\n - **`rle <state>*<count> \u2026`** \u2014 run-length segments, e.g. `rle 1*2 0*6` = `11000000`. Auto-aligns length.\n - **a raw WaveDrom wave string** \u2014 a contiguous run of state characters (no internal spaces) for fine control.\n3. Add `data: ["val1", "val2"]` after a raw wave string to label bus segments.\n\n> **Tip for alignment:** the #1 cause of a broken timing diagram is signals of unequal length. `clock N` and `rle` make every signal\'s cell count explicit, so they line up. Use raw wave strings only when you need per-cell control.\n\n> Comments must start with `#` on their own line.\n\n---\n\n## 2. Wave characters\n\nThe wave string is a sequence of characters, one per time period. The parser accepts these:\n\n| Character | State | Meaning |\n|---|---|---|\n| `0` | Logic low | Signal at GND / VSS |\n| `1` | Logic high | Signal at VDD |\n| `x` | Unknown | Don\'t-care, undefined, or uninitialized |\n| `z` | High-Z | Tri-state / high-impedance |\n| `p` | Clock pulse (positive) | Rising-edge-active clock; one `p` = one full period (low\u2192high\u2192low) |\n| `P` | Clock pulse (positive, tall) | Same as `p`, visually taller |\n| `n` | Clock pulse (negative) | Falling-edge-active; one `n` = one full period (high\u2192low\u2192high) |\n| `N` | Clock pulse (negative, tall) | Same as `n`, visually taller |\n| `=` | Bus data | Parallel-bus segment; add labels via `data: [\u2026]` |\n| `2`\u2013`9` | Named bus segment | Same as `=`, indexed into `data: [\u2026]` by position |\n| `.` | Hold / continue | Extend the previous state for one more period |\n| `h` / `H` | Hold high | Force-high for this period |\n| `l` / `L` | Hold low | Force-low for this period |\n| `u` | Rising edge | Diagonal from low to high (transition only) |\n| `d` / `D` | Falling edge | Diagonal from high to low (transition only) |\n\n```\ntiming "Wave character reference"\nclk: pppppppppp\nhigh: 1111111111\nlow: 0000000000\nunkn: xxxxxxxxxx\nhiz: zzzzzzzzzz\nbus: x========x data: ["ADDR","DATA","","","","","",""]\nhold: 0..1..0..1\nrise: 0u1\nfall: 1d0\n```\n\n---\n\n## 3. Data labels\n\nWhen a signal carries a bus value, tag the wave with `data: ["label1", "label2", \u2026]`. Each non-empty quoted string is placed inside the corresponding `=` (or `2`\u2013`9`) segment.\n\n```\nMOSI: x======= data: ["0xAB","0xCD","0xEF","0x01","0x02","0x03","0x04","0x05"]\n```\n\nEmpty strings `""` leave a segment unlabeled (useful for segments that extend a previous value).\n\n```\nMISO: zzzz==== data: ["","","","","0xFF","0x12","0x34","0x56"]\n# first four z-periods have no label; four = segments get labels starting at 0xFF\n```\n\n```\ntiming "I2C read burst"\nSCL: ppppppppppp\nSDA: x1=======1x data: ["ADDR+R","ACK","D0","D1","D2","D3","D4","D5","NACK"]\n```\n\n---\n\n## 4. Grouping signals\n\nWrap related signals in a `[GroupName]` block. A `---` line closes the group and also acts as a visual separator between groups.\n\n```\n[Control]\nCLK: pppppppp\nCS_N: 10000001\n---\n[Data]\nMOSI: x======= data: ["0xAB","0xCD","0xEF","0x01","0x02","0x03","0x04","0x05"]\nMISO: zzzz==== data: ["","","","","0xFF","0x12","0x34","0x56"]\n```\n\nAlternative `group "name" { \u2026 }` syntax is also accepted (closing `}` closes the group).\n\n```\ntiming "UART frame"\n[Clock & control]\nCLK: pppppppppppp\nTX_EN: 0111111110\n---\n[Data lines]\nTX: 1========== data: ["START","D0","D1","D2","D3","D4","D5","D6","D7","STOP"]\nRX: zz1=======1 data: ["","","D0","D1","D2","D3","D4","D5","D6","D7"]\n```\n\n---\n\n## 5. Title and hscale\n\n**Title:** `timing "SPI Transaction"` \u2014 appears at the top of the diagram.\n\n**hscale:** `timing "title" [hscale: 2]` \u2014 scales the width of each time period. Default is 1. Use 2 for wider periods when data labels need more room.\n\n```\ntiming "Wide bus" [hscale: 2]\nCLK: pppp\nDATA: ==== data: ["long label here","another","third","fourth"]\n```\n\n---\n\n## 6. Labels & comments\n\n- **Signal name:** anything before the first `:` on a signal line. Names with spaces are fine \u2014 the colon is the delimiter.\n- **Data labels:** `data: ["a", "b"]` after the wave string.\n- **Title:** first token after `timing` keyword, quoted.\n- **Comments:** `#` at the start of a line (after leading whitespace).\n\n```\ntiming "Demo"\n# this is a comment\nCLK: pppp # \u2190 inline trailing comment is NOT supported\n```\n\n---\n\n## 7. Common mistakes\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `CLK: p p p p` (spaces in wave) | Wave string parsed as `p` only; the rest is treated as data clause | Remove spaces: `CLK: pppp` |\n| `DATA: =====` with no `data:` | Segments render as unlabeled bus cells | Add `data: ["A","B","C","D","E"]` |\n| Wave character `s` or `r` | `TimingParseError: Invalid wave string` | Only the characters listed in \xA72 are valid |\n| `CLK pppp` (no colon) | Line does not match signal pattern; silently skipped | The colon after the signal name is required |\n| `data: [A, B, C]` (unquoted) | Values not recognized \u2014 parser looks for `"\u2026"` | Quote each value: `data: ["A","B","C"]` |\n| `[Group Name with spaces]` | Group label is `Group Name with spaces` \u2014 parsed fine | Supported |\n| `hscale: 2` on its own line | Not recognized (hscale goes on the header line) | `timing "title" [hscale: 2]` |\n\n---\n\n## 8. Grammar (EBNF)\n\n```text\ndocument = header (blank | comment | group-open | group-close | separator | signal)*\n\nheader = "timing" ( WS quoted-string )? ( WS "[" "hscale:" number "]" )? NEWLINE\nquoted-string = \'"\' any-char-but-quote* \'"\'\n\ngroup-open = "[" label "]" NEWLINE\n | "group" WS quoted-string WS "{"? NEWLINE\ngroup-close = "}" NEWLINE\nseparator = "---" NEWLINE\n\nsignal = name ":" WS wave-string ( WS data-clause )? NEWLINE\nname = any text before the first ":"\nwave-string = wave-char+\nwave-char = "0"|"1"|"x"|"z"\n | "p"|"P"|"n"|"N"\n | "h"|"H"|"l"|"L"\n | "u"|"d"|"D"\n | "="|"."|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"\n\ndata-clause = "data:" WS ( "[" quoted-string ("," quoted-string)* "]"\n | quoted-string+ )\n\ncomment = "#" any NEWLINE\n```\n\nAuthoritative source: `src/diagrams/timing/parser.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
2436
2587
|
},
|
|
2437
2588
|
"logic": {
|
|
2438
2589
|
"title": "Logic gate diagram",
|
|
@@ -2440,7 +2591,7 @@ var SYNTAX = {
|
|
|
2440
2591
|
},
|
|
2441
2592
|
"circuit": {
|
|
2442
2593
|
"title": "Circuit schematic",
|
|
2443
|
-
"content": '## 1. A minimal circuit\n\nThe smallest useful positional circuit: a voltage source, a resistor, and a ground.\n\n```\ncircuit "Voltage divider"\nV1: voltage_source down value="5V"\nwire right\nR1: resistor right value="10k"\nwire right\nground\n```\n\nFour rules cover 80% of positional-mode usage:\n\n1. Start with the keyword `circuit`, optionally followed by a quoted title.\n2. Each component is `id: type direction` \u2014 or just `type direction` for anonymous components.\n3. Each component\'s output end becomes the starting point for the next component (the "cursor").\n4. `at: id.end` (or `at: id.start`) jumps the cursor to any named anchor \u2014 use this to branch.\n\n> Comments must start with `#` on their own line.\n\n---\n\n## 2. Components\n\n### 2.1 Positional mode syntax\n\nA named component line has the form:\n\n```\nid: type direction [value="\u2026"] [label="\u2026"]\n```\n\nAn anonymous component omits the `id:` prefix \u2014 the parser assigns an auto ID.\n\n```\nR1: resistor right value="4.7k" label="R1"\ncapacitor down value="100n"\n```\n\n**Direction** is one of `right` (default), `left`, `up`, `down`. It controls which way the component extends from the current cursor position.\n\n### 2.2 Passive components\n\n| DSL type | Description |\n|---|---|\n| `resistor` | Zigzag (ANSI) or rectangle (IEC) |\n| `potentiometer` | Resistor + wiper arrow, 3-pin |\n| `rheostat` | 2-pin variable resistor |\n| `thermistor_ntc` | NTC thermistor (also: `therm`, `ntc`) |\n| `thermistor_ptc` | PTC thermistor (also: `ptc`) |\n| `ldr` | Light-dependent resistor |\n| `varistor` | Voltage-dependent resistor |\n| `fuse` | Standard fuse |\n| `fuse_slow` | Slow-blow fuse (`T` designation) |\n| `capacitor` | Non-polar capacitor |\n| `electrolytic_cap` | Polar/electrolytic capacitor (also: `ecap`) |\n| `variable_cap` | Variable capacitor |\n| `inductor` | Air-core inductor |\n| `inductor_iron` | Iron-core inductor |\n| `inductor_ferrite` | Ferrite-core inductor |\n| `variable_inductor` | Variable inductor |\n| `ferrite_bead` | EMI ferrite bead |\n| `crystal` | Quartz crystal oscillator (also: `xtal`) |\n| `transformer` | Coupled coils (also: `xfmr`) |\n\n```\ncircuit "Passive components gallery"\n# Row 1: resistor \u2192 capacitor \u2192 inductor\nR1: resistor right value="1k"\nwire right\nC1: capacitor right value="100n"\nwire right\nL1: inductor right value="10u"\n# Row 2: crystal and transformer, offset below\nat: R1.start\nwire down\nwire down\nX1: crystal right\nwire right\nwire right\nT1: transformer right\n```\n\n### 2.3 Sources and power\n\n| DSL type | Description |\n|---|---|\n| `voltage_source` | Circle + polarity (also: `vsource`) |\n| `current_source` | Circle + arrow (also: `isource`) |\n| `ac_source` | Circle + sine symbol (also: `acsource`) |\n| `battery` | Alternating long/short terminal lines |\n| `vcc` | Power rail arrow (pointing up) |\n| `ground` | Earth ground \u2014 3 decreasing lines (also: `gnd`) |\n| `gnd_signal` | Signal ground \u2014 solid triangle |\n| `gnd_chassis` | Chassis ground |\n| `gnd_digital` | Digital ground |\n\n```\ncircuit "Sources and power gallery"\n# voltage source with ground\nV1: voltage_source down value="5V"\nwire down\nground\nat: V1.start\nwire right\nwire right\n# battery\nB1: battery down value="9V"\nwire down\nground\nat: B1.start\nwire right\nwire right\n# ac source\nA1: ac_source down value="120V"\nwire down\nground\nat: A1.start\nwire right\nwire right\n# vcc rail\nvcc up\nwire down\ngnd_signal down\n```\n\n### 2.4 Semiconductors \u2014 diodes\n\n| DSL type | Description |\n|---|---|\n| `diode` | Triangle + cathode bar |\n| `zener` | Diode + bent cathode bar |\n| `schottky` | Diode + S-bar |\n| `led` | Diode + outward emission arrows |\n| `photodiode` | Diode + inward light arrows |\n| `varactor` | Diode + variable capacitor |\n| `tvs_diode` | Bidirectional TVS (two bent bars) |\n| `bridge_rectifier` | 4-diode bridge, 4-pin |\n\n```\ncircuit "Diode types gallery"\nD1: diode right\nwire right\nD2: zener right\nwire right\nD3: led right\nwire right\nD4: schottky right\nwire right\nD5: photodiode right\nwire right\nground\nat: D1.start\nwire left\nground\n```\n\n### 2.5 Semiconductors \u2014 transistors\n\n| DSL type | Description |\n|---|---|\n| `npn` | NPN BJT (also: `transistor`, `bjt_npn`) |\n| `pnp` | PNP BJT (also: `bjt_pnp`) |\n| `darlington_npn` | NPN Darlington pair |\n| `darlington_pnp` | PNP Darlington pair |\n| `nmos` | N-channel MOSFET enhancement (also: `mosfet_n`) |\n| `pmos` | P-channel MOSFET enhancement (also: `mosfet_p`) |\n| `nmos_depletion` | N-channel MOSFET depletion |\n| `jfet_n` | N-channel JFET |\n| `jfet_p` | P-channel JFET |\n| `igbt` | IGBT |\n| `scr` | SCR / thyristor |\n| `triac` | TRIAC |\n| `diac` | DIAC |\n| `phototransistor` | NPN with light arrows |\n| `optocoupler` | LED + phototransistor in isolation box |\n\n```\ncircuit "Transistor types gallery"\n# NPN BJT\nQ1: npn right\nwire right\nwire right\n# PNP BJT\nQ2: pnp right\nwire right\nwire right\n# N-channel MOSFET\nQ3: nmos right\nwire right\nwire right\n# P-channel MOSFET\nQ4: pmos right\n```\n\n### 2.6 Analog ICs and op-amps\n\n| DSL type | Description |\n|---|---|\n| `opamp` | Triangle: +/\u2212 inputs, output |\n| `comparator` | Same shape, open-collector output |\n| `schmitt_buffer` | Buffer + hysteresis symbol |\n| `tri_state_buffer` | Buffer + enable pin |\n| `instrumentation_amp` | Three-op-amp INA block |\n| `generic_ic` | Configurable rect with labeled pins (also: `ic`) |\n| `voltage_regulator` | 3-terminal block: IN/GND/OUT (also: `reg`) |\n| `dc_dc_converter` | 2-port block with DC/DC label |\n| `555_timer` | 8-pin 555 pinout block (also: `timer555`) |\n\n```\ncircuit "Analog IC gallery"\n# op-amp with input/output wires\nwire right\nU1: opamp right\nwire right\nwire right\nwire right\n# comparator\nU2: comparator right\nwire right\nwire right\nwire right\n# generic IC block\nU3: generic_ic right\n```\n\n### 2.7 Switches and relays\n\n| DSL type | Description |\n|---|---|\n| `switch_spst` | Single-pole single-throw |\n| `switch_spdt` | Single-pole double-throw |\n| `switch_dpdt` | Double-pole double-throw |\n| `push_no` | Push button normally-open |\n| `push_nc` | Push button normally-closed |\n| `relay_coil` | Relay coil (2-pin rect) |\n| `relay_no` | Relay contact normally-open |\n| `relay_nc` | Relay contact normally-closed |\n\n```\ncircuit "Switch and relay gallery"\n# SPST switch\nS1: switch_spst right\nwire right\nwire right\n# SPDT switch\nS2: switch_spdt right\nwire right\nwire right\n# normally-open push button\nS3: push_no right\nwire right\nwire right\n# relay coil + contact pair\nK1: relay_coil right\nwire right\nK2: relay_no right\n```\n\n### 2.8 Electromechanical and measurement\n\n| DSL type | Description |\n|---|---|\n| `motor` | Circle + M |\n| `speaker` | Cone + box |\n| `microphone` | Capsule symbol |\n| `buzzer` | Piezo buzzer |\n| `ammeter` | Circle + A |\n| `voltmeter` | Circle + V |\n| `wattmeter` | Circle + W |\n| `oscilloscope` | Circle + waveform |\n\n### 2.9 Connectors and annotations\n\n| DSL type | Description |\n|---|---|\n| `wire` | Plain wire segment |\n| `dot` | Junction dot (T-junction marker) |\n| `label` | Net label / flag |\n| `port` | Named port (hollow circle) |\n| `test_point` | TP marker |\n| `no_connect` | X \u2014 intentionally unconnected pin |\n| `antenna` | Antenna stub |\n\n```\ncircuit "Passive components"\nR1: resistor right value="1k" label="R1"\nwire right\nC1: capacitor down value="100n" label="C1"\nwire down\nground\nat: R1.start\nwire up\nbattery up label="9V"\n```\n\n---\n\n## 3. Wiring and branching\n\n### 3.1 Wire segments\n\n`wire direction [N]` draws a bare wire from the current cursor in the given direction. An optional number sets the length in pixels.\n\n```\nwire right\nwire down 40\nwire left 20\n```\n\n### 3.2 Jumping the cursor with `at:`\n\n`at: id.end` moves the cursor to a named anchor without drawing anything. Use it to branch from a previously placed component.\n\n```\nR1: resistor right value="10k"\nat: R1.end\nC1: capacitor down value="100n"\n```\n\nNamed anchor suffixes: `end`, `start`. Components retain their ID across the whole diagram, so you can jump back to any previously placed component.\n\n### 3.3 Junction dots\n\nPlace a `dot` (or use `net NAME: dot`) to mark a T-junction \u2014 a point where three or more wires meet. Without a dot, crossed wires are drawn as a crossover (no connection).\n\n```\nR1: resistor right\ndot\nwire right # continues from R1.end\nat: R1.end\nC1: capacitor down # branches down from the same point\n```\n\n### 3.4 Named nets\n\n`net NAME` declares a named net. `net NAME: dot` declares the net and places a junction dot at the current cursor, remembering that location. Later, `at: NAME` jumps back to that net\'s anchor.\n\n```\nnet VOUT: dot\nR2: resistor right value="10k"\nat: VOUT\nC1: capacitor down value="470n"\n```\n\n### 3.5 Net labels\n\n`label "text" direction?` places a text label at the current cursor position. Labels do not advance the cursor. They are useful for naming power rails or inter-sheet connections.\n\n```\nlabel "VCC" up\nlabel "GND" down\n```\n\n```\ncircuit "RC filter"\nV1: voltage_source down value="5V"\nwire right\nR1: resistor right value="1k" label="R1"\nnet OUT: dot\nwire right\nlabel "Vout" right\nat: OUT\nC1: capacitor down value="100n" label="C1"\nwire down\nground\n```\n\n---\n\n## 4. Netlist mode\n\nAdd `netlist` after the title on the header line to switch to SPICE-style netlist parsing. The auto-layout engine computes component positions from the net connectivity.\n\n```\ncircuit "Low-pass filter" netlist\n```\n\n### 4.1 Netlist line format\n\nEach line is: `ID net1 net2 [net3\u2026] [value] [key=value\u2026]`\n\n- **ID** \u2014 component identifier. The first letter determines the default type (SPICE prefix convention).\n- **net1, net2, \u2026** \u2014 net names the pins connect to. Net names matching `0`, `gnd`, `ground`, `earth`, `pe`, `agnd`, `dgnd`, `gnda`, `gndd`, `vss`, or `com` (case-insensitive, with optional `_<word>` or numeric suffix \u2014 e.g. `gnd_ref`, `AGND_DIG`, `EARTH1`) all canonicalize to the ground net.\n- **value** (optional bare token) \u2014 component value or model name.\n- **key=value** (optional) \u2014 `label=`, `value=`, `type=` overrides.\n\n### 4.2 SPICE prefix \u2192 component type\n\n| Prefix | Default type | Pin order |\n|---|---|---|\n| `R` | `resistor` | p1, p2 |\n| `C` | `capacitor` | p1, p2 |\n| `L` | `inductor` | p1, p2 |\n| `D` | `diode` | anode (start), cathode (end) |\n| `V` | `voltage_source` | plus, minus |\n| `I` | `current_source` | plus, minus |\n| `Q` | `npn` | c, b, e |\n| `M` | `nmos` | d, g, s |\n| `J` | `jfet_n` | d, g, s |\n| `S` | `switch_spst` | p1, p2 |\n| `F` | `fuse` | p1, p2 |\n| `B` | `battery` | plus, minus |\n| `K` | `relay_coil` | p1, p2 |\n| `U`, `X` | `generic_ic` | custom via `pins=` |\n| `W` | `wire` | start, end |\n| `T` | `terminal_block` | custom via `pins=` (also `type=junction_box`) |\n\n> **Scope:** schematex circuit covers **electrical schematics only** (IEEE 315 / IEC 60617). Hydraulic and pneumatic schematics (ISO 1219) use a fundamentally different visual grammar \u2014 directional valve envelopes, cylinder symbols, line styles for pressure/return/drain \u2014 and are not supported by this engine. Hydraulic prefixes such as `EV*` (electrovalve), `BOMBA*` (pump), `TANK*`, `DIPOSIT*` will be rejected with a "cannot infer type" error.\n\n### 4.3 Transistor model override\n\nFor `Q` lines, a trailing model name overrides the type:\n\n```\nQ1 c b e npn # NPN BJT\nQ2 c b e pnp # PNP BJT\nM1 d g s nmos # N-channel MOSFET\nM2 d g s pmos # P-channel MOSFET\n```\n\nFor `D` lines, similarly:\n\n```\nD1 anode cathode zener\nD2 anode cathode led\nD3 anode cathode schottky\nD4 anode cathode photodiode\n```\n\n### 4.4 Netlist example\n\n```\ncircuit "CE Amp (netlist)" netlist\nV1 vcc 0 9V\nRc vcc c 2.2k\nRb vcc b 100k\nQ1 c b e npn\nRe e 0 1k\n```\n\n---\n\n## 5. Attributes\n\nBoth positional and netlist modes accept these key=value attributes:\n\n| Attribute | Accepted by | Effect |\n|---|---|---|\n| `label="\u2026"` | all components | Display label (reference designator) |\n| `value="\u2026"` | all components | Value annotation (1k\u03A9, 100nF, 5V) |\n| `at=id.end` | positional components | Start this component at a named anchor |\n| `length=N` | `wire`, some passives | Length in pixels |\n\nIn positional mode, `at=` inside the component line is equivalent to a preceding `at:` line:\n\n```\nC1: capacitor down at=R1.end value="100n"\n```\n\n---\n\n## 6. Labels & comments\n\n- **Diagram title:** `circuit "RC Filter"` \u2014 first line only.\n- **Component label:** `label="R1"` attribute \u2014 reference designator shown beside the symbol.\n- **Value annotation:** `value="4.7k"` \u2014 shown beside or below the component.\n- **Net label:** `label "VOUT" right` \u2014 standalone net flag at the current cursor.\n- **Comments:** `#` at the start of a line (after leading whitespace).\n\n---\n\n## 7. Reserved words & escaping\n\n**Reserved at line start (positional):** `circuit` (header), `at:`, `net`, `wire`, `label`.\n\n**Reserved in netlist mode:** same header rules apply; all other lines are SPICE component lines.\n\n**Ground net aliases (netlist only):** `0`, `gnd`, `GND`, `Gnd`, `ground`, `Ground` \u2014 all treated as the same node.\n\n**Component IDs** must match `[a-zA-Z_][a-zA-Z0-9_]*`. Spaces in values must be quoted: `value="10 k\u03A9"`.\n\n---\n\n## 8. Common mistakes\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `resistor right 1k` (bare value without `value=`) | `1k` is parsed as an unknown attribute flag and ignored | Use `value="1k"`: `resistor right value="1k"` |\n| `at: R1.center` | `center` is not a recognized anchor suffix \u2014 cursor stays at current position | Use `at: R1.end` or `at: R1.start` |\n| `wire 40` (no direction) | Direction defaults to `right`; length `40` is accepted | Explicit direction recommended: `wire right 40` |\n| `R1 vcc out 10k` in positional mode | Line matches the bare-type pattern; `R1` is read as a type name, fails lookup | In positional mode, use `R1: resistor right value="10k"` |\n| `Q1 c b e` (netlist, no model) | Type defaults to `npn` from `Q` prefix \u2014 correct | OK; add `npn` explicitly for clarity |\n| `net OUT` then `at: OUT` without `net OUT: dot` | `OUT` net exists but has no anchor; jump has no destination | Use `net OUT: dot` to register the cursor position |\n| `label VCC up` (unquoted label) | `VCC` is parsed as a direction token, then `up` \u2014 the label text is lost | Quote the text: `label "VCC" up` |\n\n---\n\n## 9. Grammar (EBNF)\n\n```text\ndocument = header statement*\n\n-- Positional mode --\nheader = "circuit" ( WS quoted-string )? NEWLINE\nstatement = blank | comment | component | wire | at | net-decl | label-stmt\n\ncomponent = ( id ":" WS )? type WS direction? attrs* NEWLINE\nwire = "wire" ( WS direction )? ( WS integer )? NEWLINE\nat = "at:" WS anchor NEWLINE\nanchor = id "." ( "start" | "end" )\n | id // net name anchor\n\nnet-decl = "net" WS id NEWLINE // declare net only\n | "net" WS id ":" WS "dot" NEWLINE // declare + place dot\n\nlabel-stmt = "label" WS quoted-string ( WS direction )? NEWLINE\n\ncomponent-attr = "value=" quoted-string\n | "label=" quoted-string\n | "at=" anchor\n | "length=" integer\n\ndirection = "right" | "left" | "up" | "down"\ntype = // any value from \xA72 component tables\n\n-- Netlist mode --\nnetlist-header = "circuit" ( WS quoted-string )? WS "netlist" NEWLINE\nnetlist-stmt = id WS net-ref+ ( WS kv-pair )* NEWLINE\n | comment\nnet-ref = id | "0" // net name or ground alias\nkv-pair = id "=" ( quoted-string | bare-value )\n\nid = [a-zA-Z_] [a-zA-Z0-9_]*\ninteger = [0-9]+\nquoted-string = \'"\' any-char-but-quote* \'"\'\ncomment = "#" any NEWLINE\n```\n\nAuthoritative source: `src/diagrams/circuit/parser.ts` and `src/diagrams/circuit/netlist.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
2594
|
+
"content": '## 1. A minimal circuit (netlist mode \u2014 recommended)\n\nThe smallest useful circuit: a voltage source, a resistor, and a capacitor to ground \u2014 an RC low-pass filter.\n\n```\ncircuit "RC Low-Pass" netlist\nV1 in 0 5V\nR1 in out 1k\nC1 out 0 100n\n```\n\nThree rules cover ~90% of netlist usage:\n\n1. Start with `circuit "Title" netlist` (the `netlist` keyword switches on this mode).\n2. Each line is `componentId nodeA nodeB value` \u2014 one component, the two (or more) named nodes it connects to, then its value.\n3. **Two components that share a node name are wired together.** `0`, `gnd`, or `GND` is the ground net (a ground symbol is drawn automatically).\n\nThe component-id prefix sets the symbol: `R*`\u2192resistor, `C*`\u2192capacitor, `L*`\u2192inductor, `V*`\u2192voltage source, `D*`\u2192diode, `Q*`\u2192BJT. When the prefix is ambiguous, add `type=` (e.g. `X1 a b type=opamp`). You never compute coordinates \u2014 the engine derives placement from the connectivity.\n\n> Comments must start with `#` on their own line.\n\n---\n\n## 2. Components\n\n### 2.1 Netlist mode syntax\n\nA netlist line has the form:\n\n```\ncomponentId node... [value] [type=\u2026] [label="\u2026"]\n```\n\nThe positional nodes come first; a trailing token that doesn\'t look like a node becomes the value. Example \u2014 a transistor (4 nodes) and a resistor:\n\n```\nQ1 c b e npn # collector, base, emitter nodes + model\nRc vcc c 2.2k # two nodes + value\n```\n\n**Optional orientation hint.** The engine auto-orients symbols by role (sources up, ground down, the rest horizontal). To nudge a single symbol, add `dir=right|left|up|down` \u2014 connectivity is unchanged, only the symbol\'s facing rotates:\n\n```\nC1 out 0 100n dir=down # draw C1 as a shunt cap hanging to ground\n```\n\nThis is the lightweight layout-control layer (like Lcapy\'s per-component orientation): netlist connectivity does the heavy lifting, `dir=` only refines appearance. For full geometric control, use positional mode below.\n\n### 2.2 Positional mode syntax (hand-drawing)\n\n> Positional mode is for manually laying out a schematic geometrically. **Prefer netlist mode for generated output** \u2014 positional mode requires tracking a moving "cursor" across lines, which is error-prone for LLMs.\n\nA named component line has the form:\n\n```\nid: type direction [value="\u2026"] [label="\u2026"]\n```\n\nAn anonymous component omits the `id:` prefix \u2014 the parser assigns an auto ID.\n\n```\nR1: resistor right value="4.7k" label="R1"\ncapacitor down value="100n"\n```\n\n**Direction** is one of `right` (default), `left`, `up`, `down`. It controls which way the component extends from the current cursor position.\n\n### 2.3 Passive components\n\n| DSL type | Description |\n|---|---|\n| `resistor` | Zigzag (ANSI) or rectangle (IEC) |\n| `potentiometer` | Resistor + wiper arrow, 3-pin |\n| `rheostat` | 2-pin variable resistor |\n| `thermistor_ntc` | NTC thermistor (also: `therm`, `ntc`) |\n| `thermistor_ptc` | PTC thermistor (also: `ptc`) |\n| `ldr` | Light-dependent resistor |\n| `varistor` | Voltage-dependent resistor |\n| `fuse` | Standard fuse |\n| `fuse_slow` | Slow-blow fuse (`T` designation) |\n| `capacitor` | Non-polar capacitor |\n| `electrolytic_cap` | Polar/electrolytic capacitor (also: `ecap`) |\n| `variable_cap` | Variable capacitor |\n| `inductor` | Air-core inductor |\n| `inductor_iron` | Iron-core inductor |\n| `inductor_ferrite` | Ferrite-core inductor |\n| `variable_inductor` | Variable inductor |\n| `ferrite_bead` | EMI ferrite bead |\n| `crystal` | Quartz crystal oscillator (also: `xtal`) |\n| `transformer` | Coupled coils (also: `xfmr`) |\n\n```\ncircuit "Passive components gallery"\n# Row 1: resistor \u2192 capacitor \u2192 inductor\nR1: resistor right value="1k"\nwire right\nC1: capacitor right value="100n"\nwire right\nL1: inductor right value="10u"\n# Row 2: crystal and transformer, offset below\nat: R1.start\nwire down\nwire down\nX1: crystal right\nwire right\nwire right\nT1: transformer right\n```\n\n### 2.4 Sources and power\n\n| DSL type | Description |\n|---|---|\n| `voltage_source` | Circle + polarity (also: `vsource`) |\n| `current_source` | Circle + arrow (also: `isource`) |\n| `ac_source` | Circle + sine symbol (also: `acsource`) |\n| `battery` | Alternating long/short terminal lines |\n| `vcc` | Power rail arrow (pointing up) |\n| `ground` | Earth ground \u2014 3 decreasing lines (also: `gnd`) |\n| `gnd_signal` | Signal ground \u2014 solid triangle |\n| `gnd_chassis` | Chassis ground |\n| `gnd_digital` | Digital ground |\n\n```\ncircuit "Sources and power gallery"\n# voltage source with ground\nV1: voltage_source down value="5V"\nwire down\nground\nat: V1.start\nwire right\nwire right\n# battery\nB1: battery down value="9V"\nwire down\nground\nat: B1.start\nwire right\nwire right\n# ac source\nA1: ac_source down value="120V"\nwire down\nground\nat: A1.start\nwire right\nwire right\n# vcc rail\nvcc up\nwire down\ngnd_signal down\n```\n\n### 2.5 Semiconductors \u2014 diodes\n\n| DSL type | Description |\n|---|---|\n| `diode` | Triangle + cathode bar |\n| `zener` | Diode + bent cathode bar |\n| `schottky` | Diode + S-bar |\n| `led` | Diode + outward emission arrows |\n| `photodiode` | Diode + inward light arrows |\n| `varactor` | Diode + variable capacitor |\n| `tvs_diode` | Bidirectional TVS (two bent bars) |\n| `bridge_rectifier` | 4-diode bridge, 4-pin |\n\n```\ncircuit "Diode types gallery"\nD1: diode right\nwire right\nD2: zener right\nwire right\nD3: led right\nwire right\nD4: schottky right\nwire right\nD5: photodiode right\nwire right\nground\nat: D1.start\nwire left\nground\n```\n\n### 2.6 Semiconductors \u2014 transistors\n\n| DSL type | Description |\n|---|---|\n| `npn` | NPN BJT (also: `transistor`, `bjt_npn`) |\n| `pnp` | PNP BJT (also: `bjt_pnp`) |\n| `darlington_npn` | NPN Darlington pair |\n| `darlington_pnp` | PNP Darlington pair |\n| `nmos` | N-channel MOSFET enhancement (also: `mosfet_n`) |\n| `pmos` | P-channel MOSFET enhancement (also: `mosfet_p`) |\n| `nmos_depletion` | N-channel MOSFET depletion |\n| `jfet_n` | N-channel JFET |\n| `jfet_p` | P-channel JFET |\n| `igbt` | IGBT |\n| `scr` | SCR / thyristor |\n| `triac` | TRIAC |\n| `diac` | DIAC |\n| `phototransistor` | NPN with light arrows |\n| `optocoupler` | LED + phototransistor in isolation box |\n\n```\ncircuit "Transistor types gallery"\n# NPN BJT\nQ1: npn right\nwire right\nwire right\n# PNP BJT\nQ2: pnp right\nwire right\nwire right\n# N-channel MOSFET\nQ3: nmos right\nwire right\nwire right\n# P-channel MOSFET\nQ4: pmos right\n```\n\n### 2.7 Analog ICs and op-amps\n\n| DSL type | Description |\n|---|---|\n| `opamp` | Triangle: +/\u2212 inputs, output |\n| `comparator` | Same shape, open-collector output |\n| `schmitt_buffer` | Buffer + hysteresis symbol |\n| `tri_state_buffer` | Buffer + enable pin |\n| `instrumentation_amp` | Three-op-amp INA block |\n| `generic_ic` | Configurable rect with labeled pins (also: `ic`) |\n| `voltage_regulator` | 3-terminal block: IN/GND/OUT (also: `reg`) |\n| `dc_dc_converter` | 2-port block with DC/DC label |\n| `555_timer` | 8-pin 555 pinout block (also: `timer555`) |\n\n```\ncircuit "Analog IC gallery"\n# op-amp with input/output wires\nwire right\nU1: opamp right\nwire right\nwire right\nwire right\n# comparator\nU2: comparator right\nwire right\nwire right\nwire right\n# generic IC block\nU3: generic_ic right\n```\n\n### 2.8 Switches and relays\n\n| DSL type | Description |\n|---|---|\n| `switch_spst` | Single-pole single-throw |\n| `switch_spdt` | Single-pole double-throw |\n| `switch_dpdt` | Double-pole double-throw |\n| `push_no` | Push button normally-open |\n| `push_nc` | Push button normally-closed |\n| `relay_coil` | Relay coil (2-pin rect) |\n| `relay_no` | Relay contact normally-open |\n| `relay_nc` | Relay contact normally-closed |\n\n```\ncircuit "Switch and relay gallery"\n# SPST switch\nS1: switch_spst right\nwire right\nwire right\n# SPDT switch\nS2: switch_spdt right\nwire right\nwire right\n# normally-open push button\nS3: push_no right\nwire right\nwire right\n# relay coil + contact pair\nK1: relay_coil right\nwire right\nK2: relay_no right\n```\n\n### 2.9 Electromechanical and measurement\n\n| DSL type | Description |\n|---|---|\n| `motor` | Circle + M |\n| `speaker` | Cone + box |\n| `microphone` | Capsule symbol |\n| `buzzer` | Piezo buzzer |\n| `ammeter` | Circle + A |\n| `voltmeter` | Circle + V |\n| `wattmeter` | Circle + W |\n| `oscilloscope` | Circle + waveform |\n\n### 2.10 Connectors and annotations\n\n| DSL type | Description |\n|---|---|\n| `wire` | Plain wire segment |\n| `dot` | Junction dot (T-junction marker) |\n| `label` | Net label / flag |\n| `port` | Named port (hollow circle) |\n| `test_point` | TP marker |\n| `no_connect` | X \u2014 intentionally unconnected pin |\n| `antenna` | Antenna stub |\n\n```\ncircuit "Passive components"\nR1: resistor right value="1k" label="R1"\nwire right\nC1: capacitor down value="100n" label="C1"\nwire down\nground\nat: R1.start\nwire up\nbattery up label="9V"\n```\n\n---\n\n## 3. Wiring and branching\n\n### 3.1 Wire segments\n\n`wire direction [N]` draws a bare wire from the current cursor in the given direction. An optional number sets the length in pixels.\n\n```\nwire right\nwire down 40\nwire left 20\n```\n\n### 3.2 Jumping the cursor with `at:`\n\n`at: id.end` moves the cursor to a named anchor without drawing anything. Use it to branch from a previously placed component.\n\n```\nR1: resistor right value="10k"\nat: R1.end\nC1: capacitor down value="100n"\n```\n\nNamed anchor suffixes: `end`, `start`. Components retain their ID across the whole diagram, so you can jump back to any previously placed component.\n\n### 3.3 Junction dots\n\nPlace a `dot` (or use `net NAME: dot`) to mark a T-junction \u2014 a point where three or more wires meet. Without a dot, crossed wires are drawn as a crossover (no connection).\n\n```\nR1: resistor right\ndot\nwire right # continues from R1.end\nat: R1.end\nC1: capacitor down # branches down from the same point\n```\n\n### 3.4 Named nets\n\n`net NAME` declares a named net. `net NAME: dot` declares the net and places a junction dot at the current cursor, remembering that location. Later, `at: NAME` jumps back to that net\'s anchor.\n\n```\nnet VOUT: dot\nR2: resistor right value="10k"\nat: VOUT\nC1: capacitor down value="470n"\n```\n\n### 3.5 Net labels\n\n`label "text" direction?` places a text label at the current cursor position. Labels do not advance the cursor. They are useful for naming power rails or inter-sheet connections.\n\n```\nlabel "VCC" up\nlabel "GND" down\n```\n\n```\ncircuit "RC filter"\nV1: voltage_source down value="5V"\nwire right\nR1: resistor right value="1k" label="R1"\nnet OUT: dot\nwire right\nlabel "Vout" right\nat: OUT\nC1: capacitor down value="100n" label="C1"\nwire down\nground\n```\n\n---\n\n## 4. Netlist mode\n\nAdd `netlist` after the title on the header line to switch to SPICE-style netlist parsing. The auto-layout engine computes component positions from the net connectivity.\n\n```\ncircuit "Low-pass filter" netlist\n```\n\n### 4.1 Netlist line format\n\nEach line is: `ID net1 net2 [net3\u2026] [value] [key=value\u2026]`\n\n- **ID** \u2014 component identifier. The first letter determines the default type (SPICE prefix convention).\n- **net1, net2, \u2026** \u2014 net names the pins connect to. Net names matching `0`, `gnd`, `ground`, `earth`, `pe`, `agnd`, `dgnd`, `gnda`, `gndd`, `vss`, or `com` (case-insensitive, with optional `_<word>` or numeric suffix \u2014 e.g. `gnd_ref`, `AGND_DIG`, `EARTH1`) all canonicalize to the ground net.\n- **value** (optional bare token) \u2014 component value or model name.\n- **key=value** (optional) \u2014 `label=`, `value=`, `type=` overrides.\n\n### 4.2 SPICE prefix \u2192 component type\n\n| Prefix | Default type | Pin order |\n|---|---|---|\n| `R` | `resistor` | p1, p2 |\n| `C` | `capacitor` | p1, p2 |\n| `L` | `inductor` | p1, p2 |\n| `D` | `diode` | anode (start), cathode (end) |\n| `V` | `voltage_source` | plus, minus |\n| `I` | `current_source` | plus, minus |\n| `Q` | `npn` | c, b, e |\n| `M` | `nmos` | d, g, s |\n| `J` | `jfet_n` | d, g, s |\n| `S` | `switch_spst` | p1, p2 |\n| `F` | `fuse` | p1, p2 |\n| `B` | `battery` | plus, minus |\n| `K` | `relay_coil` | p1, p2 |\n| `U`, `X` | `generic_ic` | custom via `pins=` |\n| `W` | `wire` | start, end |\n| `T` | `terminal_block` | custom via `pins=` (also `type=junction_box`) |\n\n> **Scope:** schematex circuit covers **electrical schematics only** (IEEE 315 / IEC 60617). Hydraulic and pneumatic schematics (ISO 1219) use a fundamentally different visual grammar \u2014 directional valve envelopes, cylinder symbols, line styles for pressure/return/drain \u2014 and are not supported by this engine. Hydraulic prefixes such as `EV*` (electrovalve), `BOMBA*` (pump), `TANK*`, `DIPOSIT*` will be rejected with a "cannot infer type" error.\n\n### 4.3 Transistor model override\n\nFor `Q` lines, a trailing model name overrides the type:\n\n```\nQ1 c b e npn # NPN BJT\nQ2 c b e pnp # PNP BJT\nM1 d g s nmos # N-channel MOSFET\nM2 d g s pmos # P-channel MOSFET\n```\n\nFor `D` lines, similarly:\n\n```\nD1 anode cathode zener\nD2 anode cathode led\nD3 anode cathode schottky\nD4 anode cathode photodiode\n```\n\n### 4.4 Netlist example\n\n```\ncircuit "CE Amp (netlist)" netlist\nV1 vcc 0 9V\nRc vcc c 2.2k\nRb vcc b 100k\nQ1 c b e npn\nRe e 0 1k\n```\n\n---\n\n## 5. Attributes\n\nBoth positional and netlist modes accept these key=value attributes:\n\n| Attribute | Accepted by | Effect |\n|---|---|---|\n| `label="\u2026"` | all components | Display label (reference designator) |\n| `value="\u2026"` | all components | Value annotation (1k\u03A9, 100nF, 5V) |\n| `at=id.end` | positional components | Start this component at a named anchor |\n| `length=N` | `wire`, some passives | Length in pixels |\n\nIn positional mode, `at=` inside the component line is equivalent to a preceding `at:` line:\n\n```\nC1: capacitor down at=R1.end value="100n"\n```\n\n---\n\n## 6. Labels & comments\n\n- **Diagram title:** `circuit "RC Filter"` \u2014 first line only.\n- **Component label:** `label="R1"` attribute \u2014 reference designator shown beside the symbol.\n- **Value annotation:** `value="4.7k"` \u2014 shown beside or below the component.\n- **Net label:** `label "VOUT" right` \u2014 standalone net flag at the current cursor.\n- **Comments:** `#` at the start of a line (after leading whitespace).\n\n---\n\n## 7. Reserved words & escaping\n\n**Reserved at line start (positional):** `circuit` (header), `at:`, `net`, `wire`, `label`.\n\n**Reserved in netlist mode:** same header rules apply; all other lines are SPICE component lines.\n\n**Ground net aliases (netlist only):** `0`, `gnd`, `GND`, `Gnd`, `ground`, `Ground` \u2014 all treated as the same node.\n\n**Component IDs** must match `[a-zA-Z_][a-zA-Z0-9_]*`. Spaces in values must be quoted: `value="10 k\u03A9"`.\n\n---\n\n## 8. Common mistakes\n\n| You wrote | Parser says | Fix |\n|---|---|---|\n| `resistor right 1k` (bare value without `value=`) | `1k` is parsed as an unknown attribute flag and ignored | Use `value="1k"`: `resistor right value="1k"` |\n| `at: R1.center` | `center` is not a recognized anchor suffix \u2014 cursor stays at current position | Use `at: R1.end` or `at: R1.start` |\n| `wire 40` (no direction) | Direction defaults to `right`; length `40` is accepted | Explicit direction recommended: `wire right 40` |\n| `R1 vcc out 10k` in positional mode | Line matches the bare-type pattern; `R1` is read as a type name, fails lookup | In positional mode, use `R1: resistor right value="10k"` |\n| `Q1 c b e` (netlist, no model) | Type defaults to `npn` from `Q` prefix \u2014 correct | OK; add `npn` explicitly for clarity |\n| `net OUT` then `at: OUT` without `net OUT: dot` | `OUT` net exists but has no anchor; jump has no destination | Use `net OUT: dot` to register the cursor position |\n| `label VCC up` (unquoted label) | `VCC` is parsed as a direction token, then `up` \u2014 the label text is lost | Quote the text: `label "VCC" up` |\n\n---\n\n## 9. Grammar (EBNF)\n\n```text\ndocument = header statement*\n\n-- Positional mode --\nheader = "circuit" ( WS quoted-string )? NEWLINE\nstatement = blank | comment | component | wire | at | net-decl | label-stmt\n\ncomponent = ( id ":" WS )? type WS direction? attrs* NEWLINE\nwire = "wire" ( WS direction )? ( WS integer )? NEWLINE\nat = "at:" WS anchor NEWLINE\nanchor = id "." ( "start" | "end" )\n | id // net name anchor\n\nnet-decl = "net" WS id NEWLINE // declare net only\n | "net" WS id ":" WS "dot" NEWLINE // declare + place dot\n\nlabel-stmt = "label" WS quoted-string ( WS direction )? NEWLINE\n\ncomponent-attr = "value=" quoted-string\n | "label=" quoted-string\n | "at=" anchor\n | "length=" integer\n\ndirection = "right" | "left" | "up" | "down"\ntype = // any value from \xA72 component tables\n\n-- Netlist mode --\nnetlist-header = "circuit" ( WS quoted-string )? WS "netlist" NEWLINE\nnetlist-stmt = id WS net-ref+ ( WS kv-pair )* NEWLINE\n | comment\nnet-ref = id | "0" // net name or ground alias\nkv-pair = id "=" ( quoted-string | bare-value )\n\nid = [a-zA-Z_] [a-zA-Z0-9_]*\ninteger = [0-9]+\nquoted-string = \'"\' any-char-but-quote* \'"\'\ncomment = "#" any NEWLINE\n```\n\nAuthoritative source: `src/diagrams/circuit/parser.ts` and `src/diagrams/circuit/netlist.ts`. If this diverges from the parser, the parser wins \u2014 please open an issue.\n\n---'
|
|
2444
2595
|
},
|
|
2445
2596
|
"block": {
|
|
2446
2597
|
"title": "Block diagram",
|
|
@@ -2540,7 +2691,7 @@ var SYNTAX = {
|
|
|
2540
2691
|
},
|
|
2541
2692
|
"network": {
|
|
2542
2693
|
"title": "Network Topology",
|
|
2543
|
-
"content": '## 1. Your first diagram\n\
|
|
2694
|
+
"content": '## 1. Your first diagram\n\nA complete network diagram needs only two kinds of line: **device declarations** and **links**. Nothing else is required.\n\n```\nnetwork "Tiny LAN"\nrouter r1 "Edge Router"\nswitch sw1 "Core Switch"\npc pc1 "Workstation"\nr1 -- sw1\nsw1 -- pc1\n```\n\nThat\'s it \u2014 a valid, laid-out diagram. Just two rules:\n\n- `<kind> <id> ["label"]` \u2014 a typed device. The kind picks the icon.\n- `<a> -- <b>` \u2014 an undirected link between two declared devices.\n\n**Everything else is optional and additive \u2014 but not all of it is equal.** Two cheap, high-value structural hints are worth adding whenever hierarchy matters: `layout:` (tiered/tree/star/ring/bus/mesh/spine-leaf) and `tier:` (edge/core/distribution/access). They drive a readable top-down hierarchy at almost no syntax cost:\n\n```\nnetwork "Branch"\n layout: tiered\n router r1 "Edge Router" tier: edge\n l3switch core1 "Core SW" tier: core\n switch acc1 "Access SW" tier: access\n pc pc1 "Workstation"\n r1 -- core1\n core1 -- acc1\n acc1 -- pc1\n```\n\nBy contrast, the **per-link annotations** \u2014 link types (`fiber`/`wireless`/`poe`\u2026), speeds, `vlan:`, `port:`, `trunk`/`access`, and `subnet { }` boundaries \u2014 don\'t affect layout and are where generation most often breaks. Add them only when the request calls for them. Rule of thumb: keep the structural hints, drop the decorative annotations unless asked.\n\nDevices are **not** auto-declared from links \u2014 an undeclared id can\'t be safely typed, so a link to an unknown device is a readable error. Use `;` to put several statements on one line, and `a b c : kind` shorthand to declare several same-kind devices at once.\n\nOnce the skeleton works, you can layer on direction and annotations \u2014 `->` is a directed link, `==` is a LAG, and anything after `:` is the link spec:\n\n```\nnetwork "Home"\n layout: star\n router gw "Gateway"\n pc pc1\n laptop lt1\n gw -- pc1\n gw -- lt1 : wireless\n```\n\n---\n\n## 2. Device kinds\n\nPick the kind that matches the box; the icon follows the Cisco-convention silhouette.\n\n- **Infrastructure** \u2014 `router`, `switch`, `l3switch`, `firewall`, `loadbalancer`, `ap`, `wlc`, `gateway`, `modem`, `ids`, `proxy`, `vpngw`\n- **Endpoints** \u2014 `server`, `serverfarm` (`count: n`), `pc`, `laptop`, `mobile`, `ipphone`, `printer`, `storage`\n- **CCTV / security** \u2014 `camera` (with `type: fixed | bullet | dome | ptz | turret`), `nvr`, `dvr`, `poeswitch`, `encoder`, `monitor`\n- **Clouds** \u2014 `internet`, `wan`, `pstn`, `cloud`, plus `lan` (a bus bar)\n\nAliases are accepted: `multilayer`\u2192`l3switch`, `workstation`\u2192`pc`, `wifi`\u2192`ap`, `nas`/`san`\u2192`storage`, `voip`\u2192`ipphone`.\n\n```\ncamera cam1 type: dome ip: 192.168.20.11\nserverfarm farm "Server Farm" count: 4\nl3switch core1 tier: core model: "C9500"\n```\n\n---\n\n## 3. Links & annotations\n\nA link\'s appearance follows its type; everything after `:` is order-free.\n\n```\na -- b # copper / ethernet (default solid)\na -- b : fiber 10G # fiber \u2014 orange with slash ticks\na -- b : wireless # dashed\na -- b : serial # leased / WAN circuit\na -- b : poe # Power-over-Ethernet (green + tag)\na -- b : vpn "site-to-site" # dashed tunnel\na == b : lag 40G # aggregated / EtherChannel (double line)\na -- b : trunk vlan: 10,20 1G port: Gi0/1>Gi1/0/24\n```\n\n- `trunk` / `access` \u2014 port mode (a trunk should connect switch-class devices).\n- `vlan: 10` or `vlan: 10,20` \u2014 a single VLAN tints the link (skipping the reserved alarm-red).\n- `1G` / `10G` / `100M` / `40G` \u2014 speed, shown mid-link.\n- `port: near>far` \u2014 interface labels at each end.\n\n---\n\n## 4. Layout modes\n\n```\nlayout: tiered # default \u2014 band by tier: edge \u2192 core \u2192 distribution \u2192 access\nlayout: tree # hierarchical from the root\nlayout: star # hub at center, spokes on a ring\nlayout: ring # nodes on a circle\nlayout: bus # shared backbone\nlayout: mesh # full/partial mesh on a circle\nlayout: spine-leaf # two rows, every leaf auto-meshed to every spine\nlayout: manual # explicit at: x,y per device\ndirection: tb | lr # flow axis for tiered/tree\n```\n\nFor `tiered`, set `tier:` (`edge` / `core` / `distribution` / `access`) on infrastructure; untiered endpoints are placed below their switch. For `spine-leaf`, declare `spines:` and `leaves:` and the spine\u2194leaf links are generated for you.\n\n---\n\n## 5. Boundaries: sites, racks, subnets, VLANs\n\nA device can live inside nested boundary blocks. **Physical** containers (site/rack) draw a solid border; **logical** overlays (subnet/VLAN/zone/DMZ) draw a dashed tinted region.\n\n```\nnetwork "Branch"\n site hq "HQ Building" {\n rack mdf "MDF Rack" {\n firewall fw1 tier: edge\n l3switch core1 tier: core\n }\n }\n subnet lan "10.0.10.0/24" {\n switch a1 tier: access\n pc u1 "User PC" ip: 10.0.10.50\n }\n zone dmz "DMZ" {\n server web\n }\n fw1 -- core1 : 10G\n core1 -- a1 : trunk vlan: 10\n a1 -- u1\n```\n\nA device declared inside a `subnet` whose label is a CIDR has its `ip:` validated \u2014 an address outside the range is a readable error. A bare id on its own line inside a block adds an already-declared device to that group.\n\n---\n\n## 6. Validation & the no-drop guarantee\n\nThe engine guarantees every declared device and link renders \u2014 the dropped-device failure of generic tools is structurally impossible. It also checks:\n\n- **duplicate id** \u2192 error;\n- **unknown kind** \u2192 error with the nearest suggestion (`"swtich" \u2192 did you mean "switch"?`);\n- **link to an undeclared device** \u2192 error;\n- **VLAN id outside 1\u20134094** \u2192 warning (still renders);\n- **device IP outside its subnet CIDR** \u2192 error.\n\nThe SVG `<desc>` records device/link counts, the detected topology class (star / ring / bus / mesh / tree / hierarchical / spine-leaf), and any warnings.\n\n---\n\n## 7. Themes\n\n```\ntheme: default # house "network blue" Cisco-style bodies\ntheme: monochrome # clean line-art for print/audit (link meaning via line-style + tags)\ntheme: dark # Catppuccin Mocha\n```\n\nCJK labels and `\u300C\u2026\u300D` / `"\u2026"` quotes parse cleanly:\n\n```\nnetwork "\u529E\u516C\u5BA4"\n multilayer core1 \u300C\u6838\u5FC3\u4EA4\u6362\u673A\u300D\n poeswitch poe1\n camera cam1 type: dome\n core1 -- poe1 : trunk vlan: 10\n poe1 -- cam1 : poe\n```\n\n---'
|
|
2544
2695
|
}
|
|
2545
2696
|
};
|
|
2546
2697
|
|
|
@@ -2641,11 +2792,23 @@ var PROFILES = {
|
|
|
2641
2792
|
timing: {
|
|
2642
2793
|
type: "timing",
|
|
2643
2794
|
header: 'timing "Title"',
|
|
2644
|
-
mode: "WaveDrom-
|
|
2645
|
-
forms: [
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2795
|
+
mode: "WaveDrom signals, with clock/run-length shorthands",
|
|
2796
|
+
forms: [
|
|
2797
|
+
"CLK: clock 8 (clock generator, 8 periods \u2014 no char-counting)",
|
|
2798
|
+
"RST: rle 1*2 0*6 (run-length: two 1s then six 0s)",
|
|
2799
|
+
'DATA: x====x data: ["A","B"] (raw WaveDrom wave + bus labels)'
|
|
2800
|
+
],
|
|
2801
|
+
prefer: [
|
|
2802
|
+
"Use `clock N` for clocks instead of counting `p` characters.",
|
|
2803
|
+
"Use `rle <state>*<count> ...` for level/data signals instead of counting characters \u2014 it auto-aligns length.",
|
|
2804
|
+
"Drop to a raw wave string only for fine control; keep all signals the same total length so they align.",
|
|
2805
|
+
"Use `data:` labels for bus segments (`=` or digit states)."
|
|
2806
|
+
],
|
|
2807
|
+
avoid: ["Avoid hand-counting long runs of identical characters \u2014 that is the main source of misaligned waves."],
|
|
2808
|
+
repair: [
|
|
2809
|
+
"Wave-state errors name the offending character and list the valid states.",
|
|
2810
|
+
"If two signals don't line up, make their total cell counts equal (clock N and rle make this easy)."
|
|
2811
|
+
]
|
|
2649
2812
|
},
|
|
2650
2813
|
logic: {
|
|
2651
2814
|
type: "logic",
|
|
@@ -2659,11 +2822,23 @@ var PROFILES = {
|
|
|
2659
2822
|
circuit: {
|
|
2660
2823
|
type: "circuit",
|
|
2661
2824
|
header: 'circuit "Title" netlist',
|
|
2662
|
-
mode: "SPICE-style netlist",
|
|
2663
|
-
forms: [
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2825
|
+
mode: "SPICE-style netlist (recommended for generation)",
|
|
2826
|
+
forms: [
|
|
2827
|
+
"V1 in 0 5V (component-id node-A node-B value)",
|
|
2828
|
+
"R1 in out 1k",
|
|
2829
|
+
"C1 out 0 100n"
|
|
2830
|
+
],
|
|
2831
|
+
prefer: [
|
|
2832
|
+
"Always use netlist mode (`... netlist` header). Each line is one component; no spatial state to track.",
|
|
2833
|
+
"Two components that share a node name are wired together. `0`, `gnd`, or `GND` is the ground net.",
|
|
2834
|
+
"The component-id prefix sets the type (R=resistor, C=capacitor, L=inductor, V=source, D=diode, Q=BJT). Add explicit `type=` only when the prefix is ambiguous.",
|
|
2835
|
+
"Optional orientation hint `dir=` (right|left|up|down) nudges a single symbol's facing, e.g. `C1 out 0 100n dir=down` for a shunt cap. Connectivity is unaffected; omit it unless layout readability needs it."
|
|
2836
|
+
],
|
|
2837
|
+
avoid: [
|
|
2838
|
+
"Avoid positional cursor routing (`wire`, `at:`) \u2014 that mode is for hand-drawing, not generation.",
|
|
2839
|
+
"Do not invent coordinates; the layout engine places components from the net connectivity. `dir=` only rotates a symbol, it does not set position."
|
|
2840
|
+
],
|
|
2841
|
+
repair: ["If a component type or pin count is ambiguous, make the symbol type explicit with `type=`."]
|
|
2667
2842
|
},
|
|
2668
2843
|
blockdiagram: {
|
|
2669
2844
|
type: "blockdiagram",
|
|
@@ -2775,12 +2950,26 @@ var PROFILES = {
|
|
|
2775
2950
|
},
|
|
2776
2951
|
state: {
|
|
2777
2952
|
type: "state",
|
|
2778
|
-
header:
|
|
2779
|
-
mode: "
|
|
2780
|
-
forms: [
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2953
|
+
header: "stateDiagram-v2",
|
|
2954
|
+
mode: "Mermaid stateDiagram-v2 (recommended for generation)",
|
|
2955
|
+
forms: [
|
|
2956
|
+
"[*] --> Idle",
|
|
2957
|
+
"Idle --> Running : start",
|
|
2958
|
+
"Running --> Done : finish",
|
|
2959
|
+
"Done --> [*]"
|
|
2960
|
+
],
|
|
2961
|
+
prefer: [
|
|
2962
|
+
"Use Mermaid `stateDiagram-v2` syntax: `[*]` for the start/end pseudo-states, `-->` for transitions, `: label` for the event/guard.",
|
|
2963
|
+
'This matches the most common training data, so prefer it over the native `state "Title"` + `initial`/`final` form (which is also accepted).'
|
|
2964
|
+
],
|
|
2965
|
+
avoid: [
|
|
2966
|
+
"Avoid composite/concurrent-state syntax until the request needs it.",
|
|
2967
|
+
"Do not mix the two styles in one file (e.g. `[*]` together with `initial X`); pick `[*]`."
|
|
2968
|
+
],
|
|
2969
|
+
repair: [
|
|
2970
|
+
"Every transition uses `-->`; place at least one named state between a `[*]` start and a `[*]` end.",
|
|
2971
|
+
'If the header is rejected, use exactly `stateDiagram-v2` (or `state "Title"`).'
|
|
2972
|
+
]
|
|
2784
2973
|
},
|
|
2785
2974
|
pid: {
|
|
2786
2975
|
type: "pid",
|
|
@@ -2793,12 +2982,25 @@ var PROFILES = {
|
|
|
2793
2982
|
},
|
|
2794
2983
|
erd: {
|
|
2795
2984
|
type: "erd",
|
|
2796
|
-
header: "
|
|
2797
|
-
mode: "
|
|
2798
|
-
forms: [
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2985
|
+
header: "erDiagram",
|
|
2986
|
+
mode: "Mermaid erDiagram (recommended for generation)",
|
|
2987
|
+
forms: [
|
|
2988
|
+
"CUSTOMER ||--o{ ORDER : places",
|
|
2989
|
+
"ORDER {",
|
|
2990
|
+
" int id PK",
|
|
2991
|
+
" string customerId FK",
|
|
2992
|
+
"}"
|
|
2993
|
+
],
|
|
2994
|
+
prefer: [
|
|
2995
|
+
"Use Mermaid `erDiagram` syntax: relationships `A <card>--<card> B : label` with crow's-foot glyphs (`||` one, `o{` zero-or-many, `|{` one-or-many, `|o` zero-or-one); entity blocks `NAME { type name KEY }` with attributes **type-first** and KEY \u2208 PK/FK/UK.",
|
|
2996
|
+
"Entities are auto-created from relationships; you only need a `{ \u2026 }` block to list attributes.",
|
|
2997
|
+
"This matches the dominant training-data prior. The native `erd` header with `table NAME { name type PK }` + `ref \u2026 many-mandatory -- one-mandatory \u2026` is also accepted."
|
|
2998
|
+
],
|
|
2999
|
+
avoid: ["Do not mix the two header styles; under `erDiagram`, attributes are type-first (`int id PK`), not name-first."],
|
|
3000
|
+
repair: [
|
|
3001
|
+
"Crow's-foot glyph pairs must be valid (`||`, `|o`, `}o`, `}|` on the left; `||`, `o|`, `o{`, `|{` on the right).",
|
|
3002
|
+
"If the header is rejected, use exactly `erDiagram` (or native `erd`)."
|
|
3003
|
+
]
|
|
2802
3004
|
},
|
|
2803
3005
|
breadboard: {
|
|
2804
3006
|
type: "breadboard",
|
|
@@ -2865,12 +3067,25 @@ var PROFILES = {
|
|
|
2865
3067
|
},
|
|
2866
3068
|
sequence: {
|
|
2867
3069
|
type: "sequence",
|
|
2868
|
-
header:
|
|
2869
|
-
mode: "
|
|
2870
|
-
forms: [
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
3070
|
+
header: "sequenceDiagram",
|
|
3071
|
+
mode: "Mermaid sequenceDiagram (recommended for generation)",
|
|
3072
|
+
forms: [
|
|
3073
|
+
"participant Alice",
|
|
3074
|
+
"participant Bob",
|
|
3075
|
+
"Alice->>Bob: request",
|
|
3076
|
+
"Bob-->>Alice: response",
|
|
3077
|
+
"Note over Alice,Bob: handshake"
|
|
3078
|
+
],
|
|
3079
|
+
prefer: [
|
|
3080
|
+
"Use Mermaid `sequenceDiagram` syntax: `->>` is a sync call, `-->>` a reply/return, `-)` async; `participant`/`actor`, `Note over A,B:`, and `loop`/`alt`/`opt`/`par \u2026 end` all work.",
|
|
3081
|
+
'This matches the dominant training-data prior; the native `sequence "Title"` header (where `->>` means async) is also accepted.',
|
|
3082
|
+
"Add combined fragments only when control flow matters."
|
|
3083
|
+
],
|
|
3084
|
+
avoid: ["Do not mix the two header styles; pick `sequenceDiagram` and keep Mermaid arrow meanings throughout."],
|
|
3085
|
+
repair: [
|
|
3086
|
+
"Every fragment (`loop`/`alt`/`opt`/`par`/`break`/`critical`) needs a matching `end`; `else` only inside `alt`.",
|
|
3087
|
+
'If the header is rejected, use exactly `sequenceDiagram` (or `sequence "Title"`).'
|
|
3088
|
+
]
|
|
2874
3089
|
},
|
|
2875
3090
|
petri: {
|
|
2876
3091
|
type: "petri",
|
|
@@ -2900,29 +3115,29 @@ var PROFILES = {
|
|
|
2900
3115
|
network: {
|
|
2901
3116
|
type: "network",
|
|
2902
3117
|
header: 'network "Title"',
|
|
2903
|
-
mode: "
|
|
3118
|
+
mode: "device declarations + links (annotations are optional)",
|
|
2904
3119
|
forms: [
|
|
2905
|
-
"
|
|
2906
|
-
'
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
"
|
|
2910
|
-
"
|
|
2911
|
-
|
|
3120
|
+
'router r1 "Edge Router" (kind id "label")',
|
|
3121
|
+
'l3switch core1 "Core" tier: core (optional structural hint)',
|
|
3122
|
+
'switch acc1 "Access" tier: access',
|
|
3123
|
+
'pc pc1 "Workstation"',
|
|
3124
|
+
"r1 -- core1 (link: id -- id)",
|
|
3125
|
+
"core1 -- acc1",
|
|
3126
|
+
"acc1 -- pc1"
|
|
2912
3127
|
],
|
|
2913
3128
|
prefer: [
|
|
2914
|
-
"
|
|
2915
|
-
"
|
|
2916
|
-
"
|
|
2917
|
-
"
|
|
3129
|
+
'Start from the skeleton: `kind id "label"` device lines plus `a -- b` links. That alone renders a complete, valid diagram.',
|
|
3130
|
+
"Declare every device before any link references it.",
|
|
3131
|
+
"Keep the cheap structural hints `layout:` (tiered/tree/star/ring/bus/mesh/spine-leaf) and `tier:` (edge/core/distribution/access) \u2014 they cost little and drive a readable hierarchy. They are recommended, not noise.",
|
|
3132
|
+
"Common kinds: router, switch, l3switch, firewall, ap, server, pc, laptop, camera, nvr, poeswitch, internet, cloud."
|
|
2918
3133
|
],
|
|
2919
3134
|
avoid: [
|
|
2920
3135
|
"Avoid linking to an undeclared device id.",
|
|
2921
|
-
|
|
3136
|
+
'Add the verbose per-link annotations \u2014 `vlan:`, `port:`, speeds (1G/10G), `trunk`/`access` \u2014 and `subnet "cidr" { ... }` boundaries ONLY when the request explicitly needs them. These don\'t affect the layout and are where generation most often breaks.'
|
|
2922
3137
|
],
|
|
2923
3138
|
repair: [
|
|
2924
3139
|
"An 'undeclared device' error means a link references an id with no `kind id` declaration \u2014 declare it first.",
|
|
2925
|
-
"
|
|
3140
|
+
"If the layout looks flat/messy, add `layout: tiered` + `tier:` on infrastructure; if unsure about per-link annotations, drop them \u2014 the skeleton always renders."
|
|
2926
3141
|
]
|
|
2927
3142
|
}
|
|
2928
3143
|
};
|
|
@@ -3068,5 +3283,5 @@ function repairHint(type) {
|
|
|
3068
3283
|
}
|
|
3069
3284
|
|
|
3070
3285
|
export { DIAGRAM_REGISTRY, DIAGRAM_SINCE, getAllDiagramTypes, getDiagramMeta, getDiagramSince, getExamples, getSyntax, listDiagrams, renderDsl, resolveDiagramType, validateDsl };
|
|
3071
|
-
//# sourceMappingURL=chunk-
|
|
3072
|
-
//# sourceMappingURL=chunk-
|
|
3286
|
+
//# sourceMappingURL=chunk-ITUPR7G5.js.map
|
|
3287
|
+
//# sourceMappingURL=chunk-ITUPR7G5.js.map
|