@meltemi/diagrams-assist 1.9.0 → 1.10.0
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/guide.js +3 -3
- package/dist/guide.js.map +1 -1
- package/package.json +4 -4
package/dist/guide.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// Generated by `pnpm assist:guide` from skills/meltemi-diagrams/reference; do not edit.
|
|
2
2
|
/** The language references of the agent skill, by page. */
|
|
3
3
|
export const GUIDE_PAGES = {
|
|
4
|
-
language: "# The Meltemi language (0.2), flow profile\n\nA `.meltemi` file is UTF-8 text with LF or CRLF line breaks. Statements end at a line break or\n`;`; `//` and `/* */` are comments and are preserved by every tool. Identifiers match\n`[A-Za-z_][A-Za-z0-9_]*`; strings are double-quoted with `\\\"`, `\\\\`, `\\n` and `\\t` escapes;\nnumbers may carry a unit (`1200ms`, `2s`, `50%`).\n\n## File structure\n\n```text\nlanguage \"0.2\" // optional header, must come first\n\nimport \"../themes/company.meltemi\" as company // imports go before the blocks\nimport corporate from \"../themes/company.meltemi\"\n\ntheme <id> { <token> <value> ... } // optional, see themes.md\n\ndiagram <id>: flow { ... } // one or more diagrams\n```\n\n## Projects and imports\n\nA folder with `project.json` (`{ \"name\": \"...\", \"language\": \"0.2\" }`) is a project; files in it\nimport each other with relative paths (`./`, `../`, ending in `.meltemi`, never URLs).\n`import \"<path>\" as <ns>` makes `<ns>.<id>` available; `import <id> [as <alias>] from \"<path>\"`\nbinds ids directly. Use imported themes by name: `theme \"corporate\"`, `theme \"company.base\"`,\n`extends \"company.base\"`. Import cycles are errors (`module.cycle`). Validate a whole project with\n`pnpm mdg validate <project folder>`; the full rules are in the repository's\n`docs/language/projects.md`.\n\nEvery block compiles: `flow`, `free`, `sequence` and `c4` diagrams render, `story` blocks play\n([stories.md](stories.md)) and `export` profiles write deliveries (below); free compositions are described in [free.md](free.md), sequence\ndiagrams in [sequence.md](sequence.md), and models with C4 views in [c4.md](c4.md). Any element block may hold `link <diagram>.<element>`, which ties\nit to an element of another diagram.\n\n## Inside `diagram <id>: flow { }`\n\n| Statement | Meaning |\n| ------------------------------------------------------------ | --------------------------------------------------------------------------------------------- |\n| `title \"...\"`, `description \"...\"` | SVG `<title>` and `<desc>`; the title also appears in the brand frame |\n| `layout auto`, `layout assisted`, `layout manual` | ELK arranges everything, the unplaced boxes only, or nothing (layout.md) |\n| `routing orthogonal` | connector shape: `auto` (default), `orthogonal`, `polyline`, `bezier` |\n| `theme \"<name>\"` | built-in or file theme; default the project theme or `technical.light` |\n| `preset document`, `preset slide`, `canvas (w, h)` | canvas size and limits (see themes.md) |\n| `class id { ... }`, `rule kind { ... }` | reusable styles and styles for every element of a kind (themes.md) |\n| `direction LR` | flow of the automatic layout (`LR`, `RL`, `TB`, `BT`) |\n| `layers back, main, front`; `layer back` in a block | paint order, back to front; `main` always exists; elements, groups and relations take `layer` |\n| `id[\"Label\"]` | node (rounded box) |\n| `id[(\"Label\")]` | data store (cylinder) |\n| `node id \"Label\"`, `decision id \"Label?\"`, `data id \"Label\"` | typed declarations; label defaults to the id |\n| `group id \"Label\" { ... }` | band holding declarations, relations and nested groups |\n| `group id \"\" { ... }` | a plain container: no title band, padding 16 px all round (free.md) |\n| `note id \"Line one\\nLine two\"` | free text, left-aligned, no border |\n| `tag id \"PKCE\"` | small pill with mono text |\n| `a -> b`, `a --> b`, `a <-> b`, `a <--> b` | solid or dashed relation, one way or two-way; undeclared ids become nodes |\n| `a -> b: \"Label\" as id` | relation with label and id |\n| `{ description \"...\" }` after an element or relation | second text line of a box; description of a relation |\n| `{ assumption \"why\" }` after a relation | an inferred relation, drawn dashed and muted until someone confirms it |\n| `{ class a, b }` after an element, group or relation | apply classes |\n| `{ port in west 30% }` after an element | a named port on a side, at a percentage along it (50 % by default) |\n| `placement { ... }` | positions, sizes, routes, label anchors (below) |\n| `style <t>[, <t>...] { ... }` | visual properties for elements or named relations |\n| `animate <t>[, <t>...] { ... }` | motion effects: flow particles, a moving dash, a pulse, a trace (below) |\n\nElements and relations share one namespace per diagram. Anonymous relations get the key\n`<from>-><to>#<n>` in tools and JSON; name a relation (`as id`) before routing or styling it.\n\n## Placement\n\n```text\nplacement {\n place api at (360, 180) // centre of the box\n size api (200, 56) // width, height\n route create from api.east to orders.west via [(520, 180)]\n label create at 50% offset (0, -16) // position of the relation label\n row api, orders // constraints: align, row, column,\n distance orders, db 80 // order and distance\n}\n```\n\nPorts: `north`, `south`, `east`, `west`, `auto` (`from api` means `api.auto`) and the ports an\nelement declares with `port`; an undeclared name is `placement.unknown-port`. A route's endpoints\nmust be the relation's source and target, in that order. Each element has at most one `place` and\none `size`; each relation at most one `route` and one `label`. Several `placement` blocks may\nexist; order does not matter.\n\n## Styles\n\n```text\nstyle api, db { fill \"#ebe5fd\"; stroke \"#6a4fd0\"; color \"#33247a\" }\nstyle obo, ciba, proxy { line dashed }\nstyle r1, r2 { fill \"#0B1830\"; color \"#FFFFFF\" } // dark label pills\nstyle legendBox { fill \"none\" }\n```\n\n| Property | Element | Relation |\n| --------------- | ------------------------------------------------------------------------------ | ------------------------------------------ |\n| `fill` | background (`\"none\"` for no fill) | label pill background |\n| `stroke` | outline colour | connector and arrowhead colour |\n| `color` | label and description text | label pill text |\n| `line` | `solid`, `dashed` or `dotted` outline | overrides the arrow style |\n| `width` | outline width (0 to 16) | connector width |\n| `radius` | corner radius (0 to 64) of boxes, groups | not allowed |\n| `shape` | `node` only: `hexagon`, `icon`… (free.md) | not allowed |\n| `pattern` | `hatch`, `dots`, `cross` or `none` | not allowed |\n| `arrowhead` | not allowed | head at the target (below) |\n| `arrowtail` | not allowed | head at the source (below) |\n| `routing` | not allowed | `auto`, `orthogonal`, `polyline`, `bezier` |\n| `corners` | not allowed | `sharp` or `rounded` bends |\n| `class` | apply classes | apply classes |\n| `icon` | `\"pack:name\"`, placed by `iconPosition` | inside the label pill |\n| `iconColor` | colour of a monochrome icon | same |\n| `iconPosition` | `left`, `right`, `top`, `bottom`, `center` | not allowed |\n| `labelPosition` | label edge of a centred icon or `shape icon`: `top`, `bottom`, `left`, `right` | not allowed |\n| `iconSize` | `auto` or 8 to 128: the icon's side | not allowed |\n\nColours are quoted (`\"#6a4fd0\"`) or colour token names that follow the theme (`danger`, `accent`,\n`muted`, `success`, `warning`, `info`, …).\n\nHeads (`arrowhead` at the target, `arrowtail` at the source): `triangle`, `open`, `none`,\n`triangleOutline` (UML generalisation), `diamond` and `diamondOutline` (composition and\naggregation), `circle`, `circleOutline`, `bar`, `cross`, and the ER crow's feet `many`,\n`oneOrMany`, `onlyOne`, `zeroOrOne`, `zeroOrMany`. A relation has no start head unless it is\nwritten `<->`/`<-->` (the end's head at both ends) or has `arrowtail`:\n\n```text\ncustomer -> order as places\nstyle places { arrowtail onlyOne; arrowhead zeroOrMany } // one customer places zero or more orders\napi <-> cache // two-way\nstyle slow { line dotted; corners rounded } // dotted, rounded bends\n```\n\nSetting the same property twice for a target across statements is `prop.duplicate`; different\nproperties in different statements are fine.\n\n## Animate\n\n```text\nanimate r1, r2 { effect flow; particles 2 } // particles along named relations\nanimate save { effect dash; direction reverse } // a dash moving along a line or outline\nanimate db { effect pulse; duration 1500ms; repeat 3; delay 300ms; color accent }\nanimate r1 { effect trace } // a highlight that fills the relation, then restarts\n```\n\n`effect` is required. `duration` 100 ms to 60 s (the theme's `flowDuration`, `dashDuration`,\n`pulseDuration` or `traceDuration`, else 1200 ms for flow, 1500 ms for trace and 1 s otherwise),\n`repeat` `forever` (default) or 1 to 1000, `delay`, `direction forward|reverse` (flow, dash and\ntrace), `particles 1..8` (flow), `color` (flow, pulse and trace; a trace defaults to `accent`).\nFlow and trace run on relations only; dash on relations and boxes with an outline; pulse on\nelements, relations, notes and fragments. One effect of each\nkind per target (`animate.conflict`). Exports are static unless you ask:\n`pnpm mdg export sheet.meltemi --motion animated` writes an animated SVG (CSS keyframes, static\nfallback), `--at 1.5s` the frame at that time. Use the static export for documents and slides.\n\n## Stories\n\n`story <id> for <diagram> { scene ... }` walks through a diagram: `reveal`, `hide`, `highlight`,\n`focus`, `camera`, `trace` and `hold` on one clock, `parallel` blocks, and `view` with a\n`transition` to change diagram. `pnpm mdg export sheet.meltemi --story <id> --at 2s` writes a\nframe. See [stories.md](stories.md).\n\n## Export profiles and links\n\n```text\nexport slide for checkout {\n format png // svg, png, pdf, html (player), mp4, webm, gif\n scale 2 // png pixels per unit\n size (1920, 1080) // png, pdf, video: fitted and centred\n background transparent // or a quoted colour or a token\n file \"slides/checkout.png\"\n}\n```\n\nPlugins installed in `project.json` may declare diagram types (`diagram s: erd { entity a \"A\" }`):\ntheir kinds are boxes with the type's style and properties; `pnpm mdg plugins <project>` lists them.\n`pnpm mdg convert <file> --to json` writes the file's model JSON for other tools.\n`pnpm mdg init <folder> --template flow|c4|sequence|free|purchase` starts a project;\n`pnpm mdg preview <project>` serves its catalog and reloads it as files change;\n`pnpm mdg review <project> --base main` lists what changed by id (renames included).\n`pnpm mdg build catalog <project>` writes one offline HTML catalog of the project (settings in\n`project.json` `catalog`; comments and source stay out unless `--source`). In the catalog and in\n`--format html` pages, a double click (or the plus sign) on a system opens its container view, on\na container its component view, on an element with `link` the diagram it names: write those\nviews (`level` + `scope`) and links so readers can drill down; descriptions show on hover.\n`pnpm mdg export sheet.meltemi --profiles` writes every profile; `--profile slide` one.\n`--format mp4|webm|gif` records a story (`--story`) or effects (`--duration` when they repeat\nforever) with the installed browser and FFmpeg: 1080p at 30 fps, GIF 960 × 540 at 15 fps. Options\nof another format are `export.invalid-option`; a video of effects that repeat forever needs\n`duration` (`export.missing-duration`). Elements, groups and model entities take\n`url \"https://…\"`: SVG, PDF and HTML exports keep the link.\n`pnpm mdg login`, `push`, `pull`, `publish` and `projects` keep a project in step with its copy in\nthe optional cloud service, which `project.json` records in `cloud`, and\n`pnpm mdg review <project> --base cloud` compares with it; run them only when asked (see SKILL.md).\n\n## Diagnostics and fixes\n\n| Code | Cause and fix |\n| ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |\n| `syntax.expected-token`, `syntax.unexpected-token` | malformed statement; check quotes, `->`, parentheses, one statement per line |\n| `syntax.unterminated-string` | a string reached the end of the line; close it, use `\\n` for line breaks |\n| `syntax.unexpected-character` | characters such as `=>` or `#` outside strings; arrows are `->`, `-->`, `<->`, `<-->` |\n| `ref.duplicate-id` | the id is already an element, relation or top-level block; rename one |\n| `ref.unknown-element` | target of `place`, `size`, `style` or a qualified endpoint does not exist; declare it |\n| `ref.unknown-relation` | `route`/`label` on an unnamed relation; add `as <id>` |\n| `placement.route-mismatch` | `route` endpoints are reversed or wrong; use the relation's source then target |\n| `placement.duplicate` | second `place`/`size` for an element or `route`/`label` for a relation; delete one |\n| `placement.unknown-port` | the route names a port the element does not declare; the hint lists its ports |\n| `prop.unknown` | unknown word; the hint lists what the block accepts |\n| `prop.invalid-value` | wrong value shape; the message names the expected form; `shape` only on `node` and `box` |\n| `prop.duplicate` | property set twice for the same target; keep one |\n| `layout.missing-placement` | manual layout and an element without `place`, or a group with only one of `place`/`size` |\n| `layout.mode-unsupported` | a host without a layout engine met unplaced boxes; the command line always has ELK |\n| `layout.placement-ignored` | `place` or waypoints in `layout auto`; write `layout assisted` or `manual` |\n| `layout.constraint-conflict` | placed boxes break a constraint; move a `place` or change the constraint |\n| `layout.overlap` | two boxes overlap, or a box crosses a group edge; move it or add `distance`; a stack goes outer first |\n| `layout.label-under-connector` | a label sits on another arrow; move it with `label r at <n>% offset (dx, dy)` |\n| `layout.container-margin` | a box touches the edge or title band of its sized group; enlarge the group or move it |\n| `layout.connector-overlap` | two arrows run along each other; use other ports, a waypoint or `routing bezier` |\n| `layout.connector-crossing` | an arrow runs through a box it does not join; move the box or add a waypoint |\n| `layout.unknown-theme` | theme name is neither built in nor in the file; warning, renders with the default |\n| `theme.unknown-base`, `theme.cycle` | `extends` names a missing theme or loops; point it at a built-in theme |\n| `theme.unknown-class` | a class is not in the diagram, its theme or the built-in ones; declare it or fix the name |\n| `asset.unknown-icon`, `asset.unknown-pack` | the icon name or pack does not exist; search with `pnpm mdg assets icons <words>` |\n| `layout.too-large` | the sheet exceeds its `preset` or `canvas`; split it into views instead of shrinking |\n| `layout.text-overflow` | an explicit `size` is too narrow for its text; use the width in the hint |\n| `layout.icon-missing` | `shape icon` without an `icon`: a dashed placeholder is drawn; add the icon or change the shape |\n| `layout.label-position-ignored` | `labelPosition` without `iconPosition center` or `shape icon`; add one of them or remove it |\n| `animate.missing-effect`, `animate.invalid-target` | write `effect`; flow and trace on named relations, dash on lines and boxes, pulse anywhere |\n| `animate.conflict` | one effect of each kind per target; merge the two statements |\n| `story.*` | stories; see [stories.md](stories.md) |\n| `export.*` | export profiles: a known target, a `format`, options of that format, a video `duration` |\n| `ref.unknown-link` | a `link` names a diagram or element that does not exist; fix it or remove the link |\n| `ref.unknown-layer`, `asset.*-image`, `layout.image-unavailable` | free compositions; see [free.md](free.md) |\n| `export.no-diagram` | no flow or free diagram in the file |\n",
|
|
4
|
+
language: "# The Meltemi language (0.2), flow profile\n\nA `.meltemi` file is UTF-8 text with LF or CRLF line breaks. Statements end at a line break or\n`;`; `//` and `/* */` are comments and are preserved by every tool. Identifiers match\n`[A-Za-z_][A-Za-z0-9_]*`; strings are double-quoted with `\\\"`, `\\\\`, `\\n` and `\\t` escapes;\nnumbers may carry a unit (`1200ms`, `2s`, `50%`).\n\n## File structure\n\n```text\nlanguage \"0.2\" // optional header, must come first\n\nimport \"../themes/company.meltemi\" as company // imports go before the blocks\nimport corporate from \"../themes/company.meltemi\"\n\ntheme <id> { <token> <value> ... } // optional, see themes.md\n\ndiagram <id>: flow { ... } // one or more diagrams\n```\n\n## Projects and imports\n\nA folder with `project.json` (`{ \"name\": \"...\", \"language\": \"0.2\" }`) is a project; files in it\nimport each other with relative paths (`./`, `../`, ending in `.meltemi`, never URLs).\n`import \"<path>\" as <ns>` makes `<ns>.<id>` available; `import <id> [as <alias>] from \"<path>\"`\nbinds ids directly. Use imported themes by name: `theme \"corporate\"`, `theme \"company.base\"`,\n`extends \"company.base\"`. Import cycles are errors (`module.cycle`). Validate a whole project with\n`pnpm mdg validate <project folder>`; the full rules are in the repository's\n`docs/language/projects.md`.\n\nEvery block compiles: `flow`, `free`, `sequence` and `c4` diagrams render, `story` blocks play\n([stories.md](stories.md)) and `export` profiles write deliveries (below); free compositions are described in [free.md](free.md), sequence\ndiagrams in [sequence.md](sequence.md), and models with C4 views in [c4.md](c4.md). Any element block may hold `link <diagram>.<element>`, which ties\nit to an element of another diagram.\n\n## Inside `diagram <id>: flow { }`\n\n| Statement | Meaning |\n| ------------------------------------------------------------ | --------------------------------------------------------------------------------------------- |\n| `title \"...\"`, `description \"...\"` | SVG `<title>` and `<desc>`; the title also appears in the brand frame |\n| `layout auto`, `layout assisted`, `layout manual` | ELK arranges everything, the unplaced boxes only, or nothing (layout.md) |\n| `routing orthogonal` | connector shape: `auto` (default), `orthogonal`, `polyline`, `bezier` |\n| `theme \"<name>\"` | built-in or file theme; default the project theme or `technical.light` |\n| `preset document`, `preset slide`, `canvas (w, h)` | canvas size and limits (see themes.md) |\n| `class id { ... }`, `rule kind { ... }` | reusable styles and styles for every element of a kind (themes.md) |\n| `direction LR` | flow of the automatic layout (`LR`, `RL`, `TB`, `BT`) |\n| `layers back, main, front`; `layer back` in a block | paint order, back to front; `main` always exists; elements, groups and relations take `layer` |\n| `id[\"Label\"]` | node (rounded box) |\n| `id[(\"Label\")]` | data store (cylinder) |\n| `node id \"Label\"`, `decision id \"Label?\"`, `data id \"Label\"` | typed declarations; label defaults to the id |\n| `group id \"Label\" { ... }` | band holding declarations, relations and nested groups |\n| `group id \"\" { ... }` | a plain container: no title band, padding 16 px all round (free.md) |\n| `note id \"Line one\\nLine two\" [on element]` | free text, left-aligned, no border; `on` attaches it to an element with a dotted leader |\n| `tag id \"PKCE\"` | small pill with mono text |\n| `a -> b`, `a --> b`, `a <-> b`, `a <--> b` | solid or dashed relation, one way or two-way; undeclared ids become nodes |\n| `a -- b`, `a --- b` | a solid or dashed line without heads between two elements |\n| `a -> b: \"Label\" as id` | relation with label and id |\n| `{ description \"...\" }` after an element or relation | second text line of a box; description of a relation |\n| `{ assumption \"why\" }` after a relation | an inferred relation, drawn dashed and muted until someone confirms it |\n| `{ class a, b }` after an element, group or relation | apply classes |\n| `{ port in west 30% }` after an element | a named port on a side, at a percentage along it (50 % by default) |\n| `placement { ... }` | positions, sizes, routes, label anchors (below) |\n| `style <t>[, <t>...] { ... }` | visual properties for elements or named relations |\n| `animate <t>[, <t>...] { ... }` | motion effects: flow particles, a moving dash, a pulse, a trace (below) |\n\nElements and relations share one namespace per diagram. Anonymous relations get the key\n`<from>-><to>#<n>` in tools and JSON; name a relation (`as id`) before routing or styling it.\n\n## Placement\n\n```text\nplacement {\n place api at (360, 180) // centre of the box\n size api (200, 56) // width, height\n route create from api.east to orders.west via [(520, 180)]\n label create at 50% offset (0, -16) // position of the relation label\n row api, orders // constraints: align, row, column,\n distance orders, db 80 // order and distance\n}\n```\n\nPorts: `north`, `south`, `east`, `west`, `auto` (`from api` means `api.auto`) and the ports an\nelement declares with `port`; an undeclared name is `placement.unknown-port`. A route's endpoints\nmust be the relation's source and target, in that order. Each element has at most one `place` and\none `size`; each relation at most one `route` and one `label`. Several `placement` blocks may\nexist; order does not matter.\n\n## Styles\n\n```text\nstyle api, db { fill \"#ebe5fd\"; stroke \"#6a4fd0\"; color \"#33247a\" }\nstyle obo, ciba, proxy { line dashed }\nstyle r1, r2 { fill \"#0B1830\"; color \"#FFFFFF\" } // dark label pills\nstyle legendBox { fill \"none\" }\n```\n\n| Property | Element | Relation |\n| --------------- | ------------------------------------------------------------------------------ | ------------------------------------------ |\n| `fill` | background (`\"none\"` for no fill) | label pill background |\n| `stroke` | outline colour | connector and arrowhead colour |\n| `color` | label and description text | label pill text |\n| `line` | `solid`, `dashed` or `dotted` outline | overrides the arrow style |\n| `width` | outline width (0 to 16) | connector width |\n| `radius` | corner radius (0 to 64) of boxes, groups | not allowed |\n| `shape` | `node` only: `hexagon`, `icon`… (free.md) | not allowed |\n| `pattern` | `hatch`, `dots`, `cross` or `none` | not allowed |\n| `arrowhead` | not allowed | head at the target (below) |\n| `arrowtail` | not allowed | head at the source (below) |\n| `routing` | not allowed | `auto`, `orthogonal`, `polyline`, `bezier` |\n| `corners` | not allowed | `sharp` or `rounded` bends |\n| `class` | apply classes | apply classes |\n| `icon` | `\"pack:name\"`, placed by `iconPosition` | inside the label pill |\n| `iconColor` | colour of a monochrome icon | same |\n| `iconPosition` | `left`, `right`, `top`, `bottom`, `center` | not allowed |\n| `labelPosition` | label edge of a centred icon or `shape icon`: `top`, `bottom`, `left`, `right` | not allowed |\n| `iconSize` | `auto` or 8 to 128: the icon's side | not allowed |\n\nColours are quoted (`\"#6a4fd0\"`) or colour token names that follow the theme (`danger`, `accent`,\n`muted`, `success`, `warning`, `info`, …).\n\nHeads (`arrowhead` at the target, `arrowtail` at the source): `triangle`, `open`, `none`,\n`triangleOutline` (UML generalisation), `diamond` and `diamondOutline` (composition and\naggregation), `circle`, `circleOutline`, `bar`, `cross`, and the ER crow's feet `many`,\n`oneOrMany`, `onlyOne`, `zeroOrOne`, `zeroOrMany`. A relation has no start head unless it is\nwritten `<->`/`<-->` (the end's head at both ends) or has `arrowtail`. A line `--` (dashed `---`)\nhas no head at either end unless `arrowhead` or `arrowtail` is written; write it for an\nassociation, a link to a note or a plain connection, instead of `arrowhead none`:\n\n```text\ncustomer -> order as places\nstyle places { arrowtail onlyOne; arrowhead zeroOrMany } // one customer places zero or more orders\napi <-> cache // two-way\napi -- db // a line, no heads\nnote1 --- api // a dashed line, no heads\nstyle slow { line dotted; corners rounded } // dotted, rounded bends\n```\n\nThe six tokens are `->`, `-->`, `--`, `---`, `<->`, `<-->`; `--->` is a syntax error. Sequence\ndiagrams take the four arrows and C4 views `->` and `-->`: another token is `prop.invalid-value`.\n\nSetting the same property twice for a target across statements is `prop.duplicate`; different\nproperties in different statements are fine.\n\n## Animate\n\n```text\nanimate r1, r2 { effect flow; particles 2 } // particles along named relations\nanimate save { effect dash; direction reverse } // a dash moving along a line or outline\nanimate db { effect pulse; duration 1500ms; repeat 3; delay 300ms; color accent }\nanimate r1 { effect trace } // a highlight that fills the relation, then restarts\n```\n\n`effect` is required. `duration` 100 ms to 60 s (the theme's `flowDuration`, `dashDuration`,\n`pulseDuration` or `traceDuration`, else 1200 ms for flow, 1500 ms for trace and 1 s otherwise),\n`repeat` `forever` (default) or 1 to 1000, `delay`, `direction forward|reverse` (flow, dash and\ntrace), `particles 1..8` (flow), `color` (flow, pulse and trace; a trace defaults to `accent`).\nFlow and trace run on relations (and free lines) only; dash on relations, free lines, boxes with\nan outline and notes or texts that style an outline (`fill`, `stroke` or `pattern`); pulse on\nelements, relations, notes and fragments. One effect of each\nkind per target (`animate.conflict`). Exports are static unless you ask:\n`pnpm mdg export sheet.meltemi --motion animated` writes an animated SVG (CSS keyframes, static\nfallback), `--at 1.5s` the frame at that time. Use the static export for documents and slides.\n\n## Stories\n\n`story <id> for <diagram> { scene ... }` walks through a diagram: `reveal`, `hide`, `highlight`,\n`focus`, `camera`, `trace` and `hold` on one clock, `parallel` blocks, and `view` with a\n`transition` to change diagram. `pnpm mdg export sheet.meltemi --story <id> --at 2s` writes a\nframe. See [stories.md](stories.md).\n\n## Export profiles and links\n\n```text\nexport slide for checkout {\n format png // svg, png, pdf, html (player), mp4, webm, gif\n scale 2 // png pixels per unit\n size (1920, 1080) // png, pdf, video: fitted and centred\n background transparent // or a quoted colour or a token\n file \"slides/checkout.png\"\n}\n```\n\nPlugins installed in `project.json` may declare diagram types (`diagram s: erd { entity a \"A\" }`):\ntheir kinds are boxes with the type's style and properties; `pnpm mdg plugins <project>` lists them.\n`pnpm mdg convert <file> --to json` writes the file's model JSON for other tools.\n`pnpm mdg init <folder> --template flow|c4|sequence|free|purchase` starts a project;\n`pnpm mdg preview <project>` serves its catalog and reloads it as files change;\n`pnpm mdg review <project> --base main` lists what changed by id (renames included).\n`pnpm mdg build catalog <project>` writes one offline HTML catalog of the project (settings in\n`project.json` `catalog`; comments and source stay out unless `--source`). In the catalog and in\n`--format html` pages, a double click (or the plus sign) on a system opens its container view, on\na container its component view, on an element with `link` the diagram it names: write those\nviews (`level` + `scope`) and links so readers can drill down; descriptions show on hover.\n`pnpm mdg export sheet.meltemi --profiles` writes every profile; `--profile slide` one.\n`--format mp4|webm|gif` records a story (`--story`) or effects with the installed browser and\nFFmpeg: 1080p at 30 fps, GIF 960 × 540 at 15 fps. Effects that repeat forever last one loop of their\ncycles (6 s with the defaults) unless `--duration` or a profile's `duration` says otherwise, and the\nexport notes the length it chose; a transparent MP4 takes the theme's background. Options of\nanother format are `export.invalid-option`. Elements, groups and model entities take\n`url \"https://…\"`: SVG, PDF and HTML exports keep the link.\n`pnpm mdg login`, `push`, `pull`, `publish` and `projects` keep a project in step with its copy in\nthe optional cloud service, which `project.json` records in `cloud`, and\n`pnpm mdg review <project> --base cloud` compares with it; run them only when asked (see SKILL.md).\n\n## Diagnostics and fixes\n\n| Code | Cause and fix |\n| ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `syntax.expected-token`, `syntax.unexpected-token` | malformed statement; check quotes, `->`, parentheses, one statement per line |\n| `syntax.unterminated-string` | a string reached the end of the line; close it, use `\\n` for line breaks |\n| `syntax.unexpected-character` | characters such as `=>`, `--->` or `#` outside strings; the relation tokens are `->`, `-->`, `--`, `---`, `<->`, `<-->` |\n| `ref.duplicate-id` | the id is already an element, relation or top-level block; rename one |\n| `ref.unknown-element` | target of `place`, `size`, `style` or a qualified endpoint does not exist; declare it |\n| `ref.unknown-relation` | `route`/`label` on an unnamed relation; add `as <id>` |\n| `placement.route-mismatch` | `route` endpoints are reversed or wrong; use the relation's source then target |\n| `placement.duplicate` | second `place`/`size` for an element or `route`/`label` for a relation; delete one |\n| `placement.unknown-port` | the route names a port the element does not declare; the hint lists its ports |\n| `prop.unknown` | unknown word; the hint lists what the block accepts |\n| `prop.invalid-value` | wrong value shape; the message names the expected form; `shape` only on `node` and `box`; a relation token the profile refuses (`--` in a sequence) |\n| `prop.duplicate` | property set twice for the same target; keep one |\n| `layout.missing-placement` | manual layout and an element without `place`, or a group with only one of `place`/`size` |\n| `layout.mode-unsupported` | a host without a layout engine met unplaced boxes; the command line always has ELK |\n| `layout.placement-ignored` | `place` or waypoints in `layout auto`; write `layout assisted` or `manual` |\n| `layout.constraint-conflict` | placed boxes break a constraint; move a `place` or change the constraint |\n| `layout.overlap` | two boxes overlap, or a box crosses a group edge; move it or add `distance`; a stack goes outer first |\n| `layout.label-under-connector` | a label sits on another arrow; move it with `label r at <n>% offset (dx, dy)` |\n| `layout.container-margin` | a box touches the edge or title band of its sized group; enlarge the group or move it |\n| `layout.connector-overlap` | two arrows run along each other; use other ports, a waypoint or `routing bezier` |\n| `layout.connector-crossing` | an arrow runs through a box it does not join; move the box or add a waypoint |\n| `layout.unknown-theme` | theme name is neither built in nor in the file; warning, renders with the default |\n| `theme.unknown-base`, `theme.cycle` | `extends` names a missing theme or loops; point it at a built-in theme |\n| `theme.unknown-class` | a class is not in the diagram, its theme or the built-in ones; declare it or fix the name |\n| `asset.unknown-icon`, `asset.unknown-pack` | the icon name or pack does not exist; search with `pnpm mdg assets icons <words>` |\n| `layout.too-large` | the sheet exceeds its `preset` or `canvas`; split it into views instead of shrinking |\n| `layout.text-overflow` | an explicit `size` is too narrow for its text; use the width in the hint |\n| `layout.icon-missing` | `shape icon` without an `icon`: a dashed placeholder is drawn; add the icon or change the shape |\n| `layout.label-position-ignored` | `labelPosition` without `iconPosition center` or `shape icon`; add one of them or remove it |\n| `animate.missing-effect`, `animate.invalid-target` | write `effect`; flow and trace on named relations and free lines, dash on lines and boxes, pulse anywhere |\n| `animate.conflict` | one effect of each kind per target; merge the two statements |\n| `story.*` | stories; see [stories.md](stories.md) |\n| `export.*` | export profiles: a known target, a `format`, options of that format, a video `duration` |\n| `ref.unknown-link` | a `link` names a diagram or element that does not exist; fix it or remove the link |\n| `ref.unknown-layer`, `asset.*-image`, `layout.image-unavailable` | free compositions; see [free.md](free.md) |\n| `export.no-diagram` | no flow or free diagram in the file |\n",
|
|
5
5
|
sequence: "# Sequence diagrams\n\nUse `diagram <id>: sequence { }` for interactions over time: who calls whom, in what order, with\nwhich alternatives. Participants stand left to right in source order and events go top to bottom\nin source order. Never write `place`, `size` or `route` here; the layout is computed.\n\n## Participants\n\n`participant`, `actor`, `boundary`, `control`, `entity`, `database`, `collections` and `queue`,\neach `<kind> <id> \"Label\"`. `id[\"Label\"]` is a participant and `id[(\"Label\")]` a database. A\nmessage end that is never declared becomes a participant labelled with its id, placed at its first\nmention. `group backend \"Backend\" { participant api \"API\" }` draws a box around participants.\n\n## Messages and events\n\n```text\ncustomer -> api: \"Pay\" as pay // call: solid, filled arrowhead\napi --> customer: \"Receipt\" // reply: dashed, open arrowhead\napi -> events: \"Paid\" as paid { kind async } // async: solid, open arrowhead\napi <-> cache: \"Sync\" // two-way: a head at both ends\napi -> api: \"Validate\" // self-call\nactivate api // bar from the message before; deactivate ends it\ncreate order // the head appears at this row\ndestroy order // the lifeline ends with a cross\nnote over api, bank \"Timeout 3 s\" // also: note left of api \"…\", note right of api \"…\"\ndivider \"Fulfilment\"\ndelay \"Two days later\"\nautonumber // numbers every message from 1 (autonumber 10: from 10)\n```\n\n## Fragments\n\n```text\nalt result \"Approved\" {\n bank --> api: \"OK\"\n} else \"Declined\" {\n bank --> api: \"Declined\"\n}\nopt coupon \"Coupon applied\" { … }\nloop polling \"Until shipped\" { … }\npar { … } and \"Notify\" { … }\nbreak \"Fraud\" { … }\ncritical \"Shipment\" { … } option \"Carrier down\" { … }\nregion \"Audit\" { … }\n```\n\nWrite `else`, `and` and `option` on the line of the closing `}`. Give a fragment an id (`alt\nresult …`) when a scenario or `space` must name it. Fragments hold events only: declare every\nparticipant at the diagram level first.\n\n## Scenarios\n\n```text\nscenario approved \"Payment approved\" {\n choose result \"Approved\" // or: choose result 1\n repeat polling 3 // 1 to 100 passes\n skip coupon // opt or break not taken; take coupon keeps it (the default)\n}\n```\n\n`pnpm mdg export sheet.meltemi --scenario approved` writes `sheet.approved.svg` with only that\npath; without `--scenario` every branch is drawn.\n\n## Spacing and styles\n\n```text\nplacement {\n space authorize 28 // more room above a named message, note or fragment\n gap bank 40 // more room left of a participant\n label pay at 50% offset (0, -4)\n}\nstyle result { stroke accent } // notes and fragments with ids take styles\nrule fragment { stroke muted }\n```\n\n## Diagnostics\n\n| Code | Fix |\n| --------------------- | ---------------------------------------------------------------------------- |\n| `sequence.activation` | `deactivate p` without an open `activate p`: add the `activate` or remove it |\n| `sequence.lifecycle` | an event after `destroy`, `create` after the participant appeared, or twice |\n| `sequence.scenario` | the scenario names an unknown fragment, branch or loop count |\n| `ref.unknown-element` | declare the participant (`participant x \"X\"`); groups are not participants |\n| `prop.unknown` | a flow or free kind (`node`, `box`) or a declaration inside a fragment |\n\nBranches of `alt`, `par` and `critical` are checked separately, each from the state before the\nfragment; the first branch's state continues after it. Activations open at the end are fine.\n\n## Converting\n\nImport Mermaid and PlantUML sequences with `pnpm mdg import`, which maps them one to one: `participant`/`actor` (and the\nPlantUML kinds), `->>` and `->` to `->`, `-->>` and `-->` to `-->`, `-)` to `-> … { kind async }`,\n`+`/`-` suffixes to `activate`/`deactivate`, `Note over A,B: text` to `note over a, b \"text\"`,\n`rect`/`group` to `region`, `box` to `group`, `== x ==` to `divider \"x\"`, `...` to `delay`.\n",
|
|
6
|
-
c4: "# Models and C4 views\n\nUse a `model` block for the architecture (who uses what, which containers a system has) and C4\nviews to draw it at one level each. Declare entities once in the model; views only list them.\n\n## Model\n\n```text\nmodel commerce {\n person customer \"Cliente\" { description \"Compra en línea\" }\n system shop \"Commerce\" {\n container web \"Web\" { technology \"React\" }\n container api \"API\" {\n technology \"Kotlin\"\n component orders \"Pedidos\"\n }\n datastore db \"Pedidos\" { technology \"PostgreSQL\" }\n api -> db: \"SQL\" as persist // inside shop: api is shop.api\n }\n system bank \"Banco\" { external }\n\n customer -> shop.web: \"Compra\" as visit\n shop.web -> shop.api: \"HTTPS\" as request { technology \"JSON/HTTPS\" }\n shop.api.orders -> bank: \"Autoriza\" as authorize\n}\n```\n\n- Persons and systems at the root; containers and datastores in systems; components in containers\n (`model.invalid-nesting` otherwise).\n- Entities are named by path: `shop.api.orders`. Relations use `->` only and name paths.\n- `external` marks persons and systems outside the organisation (drawn grey and dashed).\n\n## Views\n\n```text\ndiagram containers: c4 using commerce {\n level container // context | container | component\n scope shop // a system; a container for component views\n include customer, shop.web, shop.api, shop.db\n label shop.api \"API de pedidos\" // local text, the model keeps \"API\"\n direction LR\n layout assisted\n placement { place shop.api at (420, 120) }\n style shop.db { fill accent }\n}\n```\n\n- Without `include`, a view draws its default set: everything at the context level, otherwise\n the scope's children and the entities related to them. `exclude` removes entities.\n- A container view draws the scope's containers and datastores (inside a dashed boundary),\n persons and other systems; a component view the scope's components, the other containers of the\n system, persons and other systems. Anything else is `c4.out-of-level`.\n- Relations come from the model; ends inside hidden entities are lifted to the drawn ancestor\n (at the context level `customer -> shop.web` becomes `customer -> shop`). Two relations to the\n same pair stay two arrows; to draw one, write a combination in the view:\n `customer -> shop: \"Usa\" as uses`. A combination with no model relation behind it is\n `c4.unsupported-relation`.\n- Placement, styles and routes take paths: `route request from shop.web.east to shop.api.west`.\n\n## Files\n\nKeep the model in `models/` and the views in `diagrams/` of a project, and import the model:\n\n```text\nimport commerce from \"../models/commerce.meltemi\"\ndiagram context: c4 using commerce { level context }\n```\n\nSequence and free objects link to entities with `link commerce.shop.api`; a participant without its\nown label shows the entity's.\n\n## Diagnostics\n\n| Code | Fix |\n| ------------------------- | ------------------------------------------------------------------------ |\n| `c4.invalid-level` | add `level context`, `level container` or `level component` |\n| `c4.scope-required` | add `scope <system>` (container view) or `scope <container>` (component) |\n| `c4.invalid-scope` | scope a system or a container; datastores have no components |\n| `c4.out-of-level` | remove the entity from `include`, or change the level |\n| `c4.unsupported-relation` | add the relation to the model, or remove the combination |\n| `ref.unknown-entity` | use the full path from the model's root (`shop.api`, not `api`) |\n| `ref.unknown-model` | declare or import the model named after `using` |\n| `model.invalid-nesting` | move the entity into the right parent |\n| `model.invalid-relation` | relate separate entities, not an entity and its parent |\n",
|
|
7
|
-
free: "# Free compositions\n\nUse `diagram <id>: free { }` for a slide, an executive picture or an explanation that does not fit\na flow notation. Objects are placed by hand (`layout manual` is the default); relations,\n`placement`, constraints, `style`, `class`, `rule`, `animate`, themes, `preset` and `canvas` work\nas in flow diagrams.\n\n## Objects\n\n| Declaration | Object | Default size |\n| ----------------------------- | ----------------------------------------------------------------------- | ------------------------------------- |\n| `box <id> \"Label\"`, `id[\"L\"]` | a shape with a label and an optional `description` | its shape's size, widened to its text |\n| `id[(\"Label\")]` | a box with the `cylinder` shape | 160 × 64 |\n| `text <id> \"Text\\nmore\"` | measured text without a frame | its extent |\n| `icon <id> \"tabler:server\"` | an icon of the packs; find names with `pnpm mdg assets icons <w>` | 48 × 48 |\n| `image <id> \"img/logo.png\"` | a PNG, JPEG, GIF, WebP or SVG file of the project, relative to the file | its pixel size, at most 640 wide |\n| `group <id> \"Label\" { ... }` | a band holding objects and relations; `group <id> \"\" { }` is plain | written, or fitted to children |\n\n`node`, `decision`, `data`, `note` and `tag` are flow kinds and are refused here.\n\n## Shapes and corners\n\n`style a { shape hexagon }` draws a box (or a flow `node`) as one of twenty-four shapes. Each has a\ndefault size (technical themes; it scales with the label size), keeps its text inside its outline\nand grows until the text fits, and connectors end on its outline:\n\n| Size | Shapes |\n| --------- | ------------------------------------------------------------------------------------ |\n| 160 × 56 | `rounded` (default), `rectangle`, `pill`, `parallelogram`, `arrow`, `framed`, `flag` |\n| 160 × 64 | `cylinder`, `trapezoid`, `hexagon` |\n| 160 × 72 | `ellipse`, `octagon`, `document`, `callout` |\n| 160 × 80 | `diamond` |\n| 160 × 96 | `triangle`, `pentagon` |\n| 160 × 104 | `person` |\n| 160 × 120 | `agent` |\n| 120 × 120 | `square`, `circle`, `star` |\n| 180 × 100 | `cloud` |\n| 64 × 64 | `icon` (or its `iconSize`), the label outside (below) |\n\n- `square` and `circle` are a rectangle and an ellipse with a square default size; `arrow` points\n right; `framed` has two inner lines (a subroutine); `callout` has a tail at the bottom left.\n- `person` is a round head over a body; `agent` is an AI agent, a robot head (eyes, mouth and an\n antenna) over a body. Both keep the text in the body; an end on the north side meets the head.\n- `\\n` breaks a box's or a node's label into lines, as in a `text`.\n- A `size` too narrow for the text inside a shape is `layout.text-overflow`; use the hint's width.\n- A pinned end (`route r from a.east to d.north 30%`) is drawn where the side's normal meets the\n outline, so arrows touch diamonds, ellipses and stars.\n- `radius 0..64` sets the corner radius of boxes, nodes, notes and groups (`radius 0` squares\n them); `rectangle`, `square` and `framed` are always square, the other shapes ignore it. The\n theme's `radius` (8) and `groupRadius` (14) are the defaults.\n- Decisions, data stores, notes, tags, groups, texts, icons and images refuse `shape`, in `style`\n statements as in rules: their kind is their drawing. Only `rule box` and `rule node` may set it.\n\nFree-only text properties (refused in flow diagrams):\n\n- `fontSize 6..160`, `fontWeight 400|500|600|700`, `textAlign left|center|right` on boxes and\n text (text defaults to 1.6 × the label size, left aligned);\n- a text, icon or image with `fill`, `stroke` or `pattern` gets a frame.\n\n## Icons in boxes and as shapes\n\nFlow diagrams take these too. The `icon` of a node, decision, data store or box goes beside the\ntext (`iconPosition left`, the default, or `right`), above or below it (`top`, `bottom`), or at the\ncentre as the picture of the box (`center`), with the label in a band at the `labelPosition` edge\ninside (`bottom` by default). `shape icon` draws the element as its icon alone, with the label\noutside at `labelPosition`, as provider icons are drawn in architecture diagrams:\n\n```text\nbox gateway \"API Gateway\"\nbox fn \"Checkout\"\nbox orders \"Orders\"\nbox tile \"Orders DB\"\ngateway -> fn\nfn -> orders\n\nstyle gateway { icon \"aws:api-gateway\"; shape icon } // label below the icon\nstyle fn { icon \"aws:lambda\"; shape icon; labelPosition top } // label above\nstyle orders { icon \"aws:dynamodb\"; shape icon; fill surface; stroke line } // framed\nstyle tile { icon \"tabler:database\"; iconPosition center } // 120 × 120 tile\n```\n\n- `iconSize` is the icon's side: 8 to 128 (px or unitless) or `auto`. Beside the text the theme's\n 18 px is the default; a number grows a box without `size`, and is clamped (never cut) in a box\n with a written `size`, where `auto` fills the room. A centred icon is as large as fits; a\n written `size` without room for an 8 px icon beside the label band is `layout.text-overflow`.\n- An icon shape is a 64 × 64 square (or `iconSize`; a written `size` wins, the icon fitted\n inside), with nothing behind the icon unless `fill`, `stroke` or `pattern` frames it; a frame\n adds half the padding on each side (an 80 × 80 square around a 64 px icon). Arrows, ports and\n anchors end on the square (`to fn.south` is the icon's bottom edge); groups and the canvas\n count the label too, and a box over the label is `layout.overlap`, so leave room for it. A\n connector on the label's side is drawn from beyond the label; other routes go around it.\n- `labelPosition` does nothing unless the icon is the centre piece: `layout.label-position-ignored`.\n `shape icon` without an `icon` is `layout.icon-missing` and draws a dashed placeholder.\n- A free `icon <id> \"pack:name\"` object is an icon without text; for a labelled icon use a box\n with `shape icon`.\n\n## Coordinates\n\n- `place` is the centre, as in flow diagrams.\n- **Inside a group, `place` is relative to the group's interior**: its top-left corner plus\n `groupPadding` (16) across and the header down: `groupHeader` (40) in the technical themes, or\n `groupPadding` (16) for an untitled group (`\"\"`, no description, no icon). A child at\n `(w/2, h/2)` touches the interior's top-left corner. Moving the group moves its children.\n- Every group needs a `place`. Without `size` it fits its children: padding + rightmost child edge\n - padding wide, header + lowest child edge + padding tall.\n- Route waypoints are always diagram coordinates.\n\n## Containers, stacks and bands\n\nThese are the pictures of a visual editor's containers and backdrops; flow diagrams take them too.\n\n```text\ngroup outer \"\" { // nested plain rectangles: untitled groups\n group inner \"\" {\n box core \"Core\"\n }\n}\nbox plate \"\" // a stack: the outer box first, empty label\nbox card \"Card\"\ngroup band \"\" { layer back } // a band behind arranged boxes (layers back, main)\n\nstyle outer { fill \"#dae8fc\"; stroke \"#6c8ebf\"; radius 0 }\nstyle inner { fill \"#fff2cc\"; stroke \"#d6b656\"; radius 0 }\nstyle band { fill \"#f5f5f5\"; radius 0 }\n```\n\n- **Untitled groups** draw only their outline, have no title band and cut no gap in connectors;\n children keep half the padding (8 px) from every edge (`layout.container-margin`).\n- **Stacks**: a box lying strictly inside a box declared before it on the same layer is not\n `layout.overlap`; a partial overlap still is, so are two boxes that coincide, and so is a stack\n declared inner first (its hint says to declare the outer box first). A\n container's own label may lie over its children, but two labels at the same point are\n `layout.label-overlap`: leave the outer labels empty.\n- **Bands**: a group with `place` and `size` is neither arranged by the engine nor an obstacle, so\n on a back layer it stays behind the boxes `layout assisted` arranges (pin one box with `place`\n so the others arrange around it). Boxes and groups on different layers are not checked against\n each other, and connectors cross them straight. In `layout auto` a group's `place` is ignored:\n make the band a group holding its boxes.\n\n## Layers, order and links\n\n- `layers back, main, front` lists layers back to front; `main` is the default and comes last\n when unlisted. Put `layer front` in an object's or relation's block.\n- Within a layer, groups paint first, then objects in source order, then relations: declare what\n must be on top later.\n- `link checkout.api` in a block records that the object stands for element `api` of `diagram\ncheckout` (same file), `link co.api` through `import checkout as co from \"...\"`, or `link\nviews.checkout.api` through `import \"...\" as views`. Identity only; nothing is kept in step.\n\n## From a flow diagram\n\n`pnpm mdg convert sheet.meltemi --to free [--diagram <id>] [--id <new>]` adds a free copy of the\nflow diagram as drawn: every box with `place` and `size`, children inside their copied groups,\nlayers, routes, labels, styles and animations, a `link` from each object to its source, and\nclasses `from_decision`, `from_data`, `from_note`, `from_tag` for the drawing of the flow kinds.\nEdit the copy freely; the flow diagram is unchanged.\n\n## Diagnostics\n\n| Code | Fix |\n| ------------------------------- | -------------------------------------------------------------------------------------------- |\n| `ref.unknown-layer` | add the layer to `layers` (the hint gives the statement) or fix its name |\n| `ref.unknown-link` | the diagram or element does not exist; fix the name or remove the `link` |\n| `asset.outside-project` | image paths are relative, use `/`, no URLs, and stay inside the project |\n| `asset.unknown-image` | the file does not exist next to the path written |\n| `asset.unsupported-image` | not a PNG, JPEG, GIF, WebP or SVG image, broken, or over 8 MB |\n| `layout.image-unavailable` | the host could not read the image; a placeholder is drawn |\n| `layout.missing-placement` | an object or a group has no `place` |\n| `layout.overlap` | boxes overlap partly, or a stack is declared inner first: declare the outer box first |\n| `layout.icon-missing` | `shape icon` without an `icon` style: add `icon \"pack:name\"` or choose another shape |\n| `layout.label-position-ignored` | `labelPosition` only moves the label of `iconPosition center` and `shape icon` elements |\n| `prop.invalid-value` | `fontSize`, `fontWeight` and `textAlign` are free-only; `shape` is for `node` and `box` only |\n",
|
|
6
|
+
c4: "# Models and C4 views\n\nUse a `model` block for the architecture (who uses what, which containers a system has) and C4\nviews to draw it at one level each. Declare entities once in the model; views only list them.\n\n## Model\n\n```text\nmodel commerce {\n person customer \"Cliente\" { description \"Compra en línea\" }\n system shop \"Commerce\" {\n container web \"Web\" { technology \"React\" }\n container api \"API\" {\n technology \"Kotlin\"\n component orders \"Pedidos\"\n }\n datastore db \"Pedidos\" { technology \"PostgreSQL\" }\n api -> db: \"SQL\" as persist // inside shop: api is shop.api\n }\n system bank \"Banco\" { external }\n\n customer -> shop.web: \"Compra\" as visit\n shop.web -> shop.api: \"HTTPS\" as request { technology \"JSON/HTTPS\" }\n shop.api.orders -> bank: \"Autoriza\" as authorize\n}\n```\n\n- Persons and systems at the root; containers and datastores in systems; components in containers\n (`model.invalid-nesting` otherwise).\n- Entities are named by path: `shop.api.orders`. Relations use `->` only and name paths.\n- `external` marks persons and systems outside the organisation (drawn grey and dashed).\n\n## Views\n\n```text\ndiagram containers: c4 using commerce {\n level container // context | container | component\n scope shop // a system; a container for component views\n include customer, shop.web, shop.api, shop.db\n label shop.api \"API de pedidos\" // local text, the model keeps \"API\"\n direction LR\n layout assisted\n placement { place shop.api at (420, 120) }\n style shop.db { fill accent }\n}\n```\n\n- Without `include`, a view draws its default set: everything at the context level, otherwise\n the scope's children and the entities related to them. `exclude` removes entities.\n- A container view draws the scope's containers and datastores (inside a dashed boundary),\n persons and other systems; a component view the scope's components, the other containers of the\n system, persons and other systems. Anything else is `c4.out-of-level`.\n- Relations come from the model; ends inside hidden entities are lifted to the drawn ancestor\n (at the context level `customer -> shop.web` becomes `customer -> shop`). Two relations to the\n same pair stay two arrows; to draw one, write a combination in the view:\n `customer -> shop: \"Usa\" as uses`. A combination with no model relation behind it is\n `c4.unsupported-relation`.\n- Placement, styles and routes take paths: `route request from shop.web.east to shop.api.west`.\n\n## Notes in views\n\nA view accepts `note <id> \"Text\" [on <entity path>]` beside its lists: an annotation of the view,\nnever of the model and never an entity (`include`, `exclude`, `label` and relations cannot name it).\n`note cache \"Cached 5 min\" on shop.api` draws a note with a dotted leader to `shop.api`, which the\nview must draw (else `ref.unknown-element`). It takes `class` and `url`, the view's `style`, `class`,\n`rule` and `animate`, and a `place` in the view's `placement`.\n\n## Files\n\nKeep the model in `models/` and the views in `diagrams/` of a project, and import the model:\n\n```text\nimport commerce from \"../models/commerce.meltemi\"\ndiagram context: c4 using commerce { level context }\n```\n\nSequence and free objects link to entities with `link commerce.shop.api`; a participant without its\nown label shows the entity's.\n\n## Diagnostics\n\n| Code | Fix |\n| ------------------------- | ------------------------------------------------------------------------ |\n| `c4.invalid-level` | add `level context`, `level container` or `level component` |\n| `c4.scope-required` | add `scope <system>` (container view) or `scope <container>` (component) |\n| `c4.invalid-scope` | scope a system or a container; datastores have no components |\n| `c4.out-of-level` | remove the entity from `include`, or change the level |\n| `c4.unsupported-relation` | add the relation to the model, or remove the combination |\n| `ref.unknown-entity` | use the full path from the model's root (`shop.api`, not `api`) |\n| `ref.unknown-model` | declare or import the model named after `using` |\n| `model.invalid-nesting` | move the entity into the right parent |\n| `model.invalid-relation` | relate separate entities, not an entity and its parent |\n",
|
|
7
|
+
free: "# Free compositions\n\nUse `diagram <id>: free { }` for a slide, an executive picture or an explanation that does not fit\na flow notation. Objects are placed by hand (`layout manual` is the default); relations,\n`placement`, constraints, `style`, `class`, `rule`, `animate`, themes, `preset` and `canvas` work\nas in flow diagrams.\n\n## Objects\n\n| Declaration | Object | Default size |\n| --------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------- |\n| `box <id> \"Label\"`, `id[\"L\"]` | a shape with a label and an optional `description` | its shape's size, widened to its text |\n| `id[(\"Label\")]` | a box with the `cylinder` shape | 160 × 64 |\n| `text <id> \"Text\\nmore\"` | measured text without a frame | its extent |\n| `icon <id> \"tabler:server\"` | an icon of the packs; find names with `pnpm mdg assets icons <w>` | 48 × 48 |\n| `image <id> \"img/logo.png\"` | a PNG, JPEG, GIF, WebP or SVG file of the project, relative to the file | its pixel size, at most 640 wide |\n| `note <id> \"Text\" [on <element>]` | an annotation: text with no frame until styled, and a dotted leader to the element it is attached to (below) | its text's extent |\n| `group <id> \"Label\" { ... }` | a band holding objects and relations; `group <id> \"\" { }` is plain | written, or fitted to children |\n| `line <id> from (x, y) to (x, y)` | a line that joins no element: a divider, a bracket, an underline (below) | the bounding box of its points |\n\n`node`, `decision`, `data` and `tag` are flow kinds and are refused here; `note` is a free kind.\nRelations take the lines without heads `a -- b` and `a --- b` too.\n\n## Notes\n\n`note remark \"Checked at the gateway\" on gateway { layer front }` is text at the theme's note size in\nthe muted colour, left-aligned and without a frame. `style remark { fill \"#fff7d6\"; stroke warning;\nline dashed }` gives it an outline (any of `fill`, `stroke` or `pattern` does); `fontSize`,\n`fontWeight`, `textAlign`, `radius`, `color`, `icon` and `rotation` apply, `shape` does not. The\nblock takes `description`, `class`, `layer`, `link` and `url`. `on <element>` attaches the note to\nany other element of the diagram: a dotted leader joins them, `layout auto` keeps them near each\nother, renaming the element rewrites the clause, and deleting the element leaves the note. An\nunknown target is `ref.unknown-element`; a note on itself, `prop.invalid-value`. A note with an\noutline can take `animate remark { effect dash }`; without one, only a pulse.\n\n## Shapes and corners\n\n`style a { shape hexagon }` draws a box (or a flow `node`) as one of twenty-four shapes. Each has a\ndefault size (technical themes; it scales with the label size), keeps its text inside its outline\nand grows until the text fits, and connectors end on its outline:\n\n| Size | Shapes |\n| --------- | ------------------------------------------------------------------------------------ |\n| 160 × 56 | `rounded` (default), `rectangle`, `pill`, `parallelogram`, `arrow`, `framed`, `flag` |\n| 160 × 64 | `cylinder`, `trapezoid`, `hexagon` |\n| 160 × 72 | `ellipse`, `octagon`, `document`, `callout` |\n| 160 × 80 | `diamond` |\n| 160 × 96 | `triangle`, `pentagon` |\n| 160 × 104 | `person` |\n| 160 × 120 | `agent` |\n| 120 × 120 | `square`, `circle`, `star` |\n| 180 × 100 | `cloud` |\n| 64 × 64 | `icon` (or its `iconSize`), the label outside (below) |\n\n- `square` and `circle` are a rectangle and an ellipse with a square default size; `arrow` points\n right; `framed` has two inner lines (a subroutine); `callout` has a tail at the bottom left.\n- `person` is a round head over a body; `agent` is an AI agent, a robot head (eyes, mouth and an\n antenna) over a body. Both keep the text in the body; an end on the north side meets the head.\n- `\\n` breaks a box's or a node's label into lines, as in a `text`.\n- A `size` too narrow for the text inside a shape is `layout.text-overflow`; use the hint's width.\n- A pinned end (`route r from a.east to d.north 30%`) is drawn where the side's normal meets the\n outline, so arrows touch diamonds, ellipses and stars.\n- `radius 0..64` sets the corner radius of boxes, nodes, notes and groups (`radius 0` squares\n them); `rectangle`, `square` and `framed` are always square, the other shapes ignore it. The\n theme's `radius` (8) and `groupRadius` (14) are the defaults.\n- Decisions, data stores, notes, tags, groups, texts, icons and images refuse `shape`, in `style`\n statements as in rules: their kind is their drawing. Only `rule box` and `rule node` may set it.\n\nFree-only text properties (refused in flow diagrams):\n\n- `fontSize 6..160`, `fontWeight 400|500|600|700`, `textAlign left|center|right` on boxes and\n text (text defaults to 1.6 × the label size, left aligned);\n- `verticalAlign top|middle|bottom` on boxes (`middle` by default) moves the label, description\n and icon to the top or bottom of the shape's text band, the theme's padding from its edge:\n `style card { shape rectangle; textAlign left; verticalAlign top }` is draw.io's top-left text.\n Ellipses and other narrowing shapes move a wide block back towards the middle until it fits;\n cylinders keep it between the rims, documents above the wave, callouts above the tail. On\n `triangle`, `pentagon`, `star`, `person`, `agent` and `icon` shapes, with `iconPosition center`,\n and on texts, icons, images, groups and lines it moves nothing (`layout.vertical-align-ignored`);\n- a text, icon or image with `fill`, `stroke` or `pattern` gets a frame.\n\n## Lines\n\n```text\nline divider \"Phase 2\" from (40, 160) to (520, 160) // a labelled divider\nline bracket from (40, 220) to (520, 280) via [(280, 220)] // bends in a via list\ngroup notes \"Notes\" {\n text remark \"Read first\"\n line underline from (0, 22) to (120, 22) // in the group's interior\n}\nstyle divider { line dashed; stroke muted }\nstyle bracket { routing orthogonal; corners rounded; arrowhead triangle }\n```\n\n- A `line` joins nothing: use it for dividers, brackets, underlines and strokes; between two\n boxes write a relation (`a -- b`) so it follows them.\n- Its points are written in the statement, in the parent group's interior like `place`; it takes\n no `place`, `size` or `rotation` (`prop.invalid-value`).\n- It takes a relation's styles: `stroke`, `width`, `line`, `arrowhead` and `arrowtail` (none by\n default), `routing` (`polyline` by default, `orthogonal`, `bezier`), `corners`, and `color`,\n `fill`, `icon` for its label pill; a box's properties (`shape`, `radius`, the text properties)\n are `prop.invalid-value`. `rule line { }` styles every line.\n- The label is the optional second argument, on a pill at 50 %;\n `label divider at 20% offset (0, -14)` in `placement` moves it. `flow`, `dash`, `pulse` and\n `trace` run along a line.\n- A line whose points coincide is drawn as a dot: `layout.degenerate-line`. Flow, sequence and C4\n diagrams refuse `line` (`prop.unknown`).\n\n## Icons in boxes and as shapes\n\nFlow diagrams take these too. The `icon` of a node, decision, data store or box goes beside the\ntext (`iconPosition left`, the default, or `right`), above or below it (`top`, `bottom`), or at the\ncentre as the picture of the box (`center`), with the label in a band at the `labelPosition` edge\ninside (`bottom` by default). `shape icon` draws the element as its icon alone, with the label\noutside at `labelPosition`, as provider icons are drawn in architecture diagrams:\n\n```text\nbox gateway \"API Gateway\"\nbox fn \"Checkout\"\nbox orders \"Orders\"\nbox tile \"Orders DB\"\ngateway -> fn\nfn -> orders\n\nstyle gateway { icon \"aws:api-gateway\"; shape icon } // label below the icon\nstyle fn { icon \"aws:lambda\"; shape icon; labelPosition top } // label above\nstyle orders { icon \"aws:dynamodb\"; shape icon; fill surface; stroke line } // framed\nstyle tile { icon \"tabler:database\"; iconPosition center } // 120 × 120 tile\n```\n\n- `iconSize` is the icon's side: 8 to 128 (px or unitless) or `auto`. Beside the text the theme's\n 18 px is the default; a number grows a box without `size`, and is clamped (never cut) in a box\n with a written `size`, where `auto` fills the room. A centred icon is as large as fits; a\n written `size` without room for an 8 px icon beside the label band is `layout.text-overflow`.\n- An icon shape is a 64 × 64 square (or `iconSize`; a written `size` wins, the icon fitted\n inside), with nothing behind the icon unless `fill`, `stroke` or `pattern` frames it; a frame\n adds half the padding on each side (an 80 × 80 square around a 64 px icon). Arrows, ports and\n anchors end on the square (`to fn.south` is the icon's bottom edge); groups and the canvas\n count the label too, and a box over the label is `layout.overlap`, so leave room for it. A\n connector on the label's side is drawn from beyond the label; other routes go around it.\n- `labelPosition` does nothing unless the icon is the centre piece: `layout.label-position-ignored`.\n `shape icon` without an `icon` is `layout.icon-missing` and draws a dashed placeholder.\n- A free `icon <id> \"pack:name\"` object is an icon without text; for a labelled icon use a box\n with `shape icon`.\n\n## Coordinates\n\n- `place` is the centre, as in flow diagrams.\n- **Inside a group, `place` is relative to the group's interior**: its top-left corner plus\n `groupPadding` (16) across and the header down: `groupHeader` (40) in the technical themes, or\n `groupPadding` (16) for an untitled group (`\"\"`, no description, no icon). A child at\n `(w/2, h/2)` touches the interior's top-left corner. Moving the group moves its children.\n- Every group needs a `place`. Without `size` it fits its children: padding + rightmost child edge\n - padding wide, header + lowest child edge + padding tall.\n- Route waypoints are always diagram coordinates.\n\n## Containers, stacks and bands\n\nThese are the pictures of a visual editor's containers and backdrops; flow diagrams take them too.\n\n```text\ngroup outer \"\" { // nested plain rectangles: untitled groups\n group inner \"\" {\n box core \"Core\"\n }\n}\nbox plate \"\" // a stack: the outer box first, empty label\nbox card \"Card\"\ngroup band \"\" { layer back } // a band behind arranged boxes (layers back, main)\n\nstyle outer { fill \"#dae8fc\"; stroke \"#6c8ebf\"; radius 0 }\nstyle inner { fill \"#fff2cc\"; stroke \"#d6b656\"; radius 0 }\nstyle band { fill \"#f5f5f5\"; radius 0 }\n```\n\n- **Untitled groups** draw only their outline, have no title band and cut no gap in connectors;\n children keep half the padding (8 px) from every edge (`layout.container-margin`).\n- **Stacks**: a box lying strictly inside a box declared before it on the same layer is not\n `layout.overlap`; a partial overlap still is, so are two boxes that coincide, and so is a stack\n declared inner first (its hint says to declare the outer box first). A\n container's own label may lie over its children, but two labels at the same point are\n `layout.label-overlap`: leave the outer labels empty.\n- **Bands**: a group with `place` and `size` is neither arranged by the engine nor an obstacle, so\n on a back layer it stays behind the boxes `layout assisted` arranges (pin one box with `place`\n so the others arrange around it). Boxes and groups on different layers are not checked against\n each other, and connectors cross them straight. In `layout auto` a group's `place` is ignored:\n make the band a group holding its boxes.\n\n## Layers, order and links\n\n- `layers back, main, front` lists layers back to front; `main` is the default and comes last\n when unlisted. Put `layer front` in an object's or relation's block.\n- Within a layer, groups paint first, then objects (lines included) in source order, then\n relations: declare what must be on top later.\n- `link checkout.api` in a block records that the object stands for element `api` of `diagram\ncheckout` (same file), `link co.api` through `import checkout as co from \"...\"`, or `link\nviews.checkout.api` through `import \"...\" as views`. Identity only; nothing is kept in step.\n\n## From a flow diagram\n\n`pnpm mdg convert sheet.meltemi --to free [--diagram <id>] [--id <new>]` adds a free copy of the\nflow diagram as drawn: every box with `place` and `size`, children inside their copied groups,\nlayers, routes, labels, styles and animations, a `link` from each object to its source, and\nclasses `from_decision`, `from_data`, `from_tag` for the drawing of the flow kinds; notes stay notes,\nwith their `on` clause.\nEdit the copy freely; the flow diagram is unchanged.\n\n## Diagnostics\n\n| Code | Fix |\n| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `ref.unknown-layer` | add the layer to `layers` (the hint gives the statement) or fix its name |\n| `ref.unknown-link` | the diagram or element does not exist; fix the name or remove the `link` |\n| `asset.outside-project` | image paths are relative, use `/`, no URLs, and stay inside the project |\n| `asset.unknown-image` | the file does not exist next to the path written |\n| `asset.unsupported-image` | not a PNG, JPEG, GIF, WebP or SVG image, broken, or over 8 MB |\n| `layout.image-unavailable` | the host could not read the image; a placeholder is drawn |\n| `layout.missing-placement` | an object or a group has no `place` |\n| `layout.overlap` | boxes overlap partly, or a stack is declared inner first: declare the outer box first |\n| `layout.icon-missing` | `shape icon` without an `icon` style: add `icon \"pack:name\"` or choose another shape |\n| `layout.label-position-ignored` | `labelPosition` only moves the label of `iconPosition center` and `shape icon` elements |\n| `layout.vertical-align-ignored` | `verticalAlign` moves nothing on this shape or kind: choose a shape with a text band (`rectangle`, `ellipse`, `cylinder`), set `labelPosition` with a centred icon, or remove it |\n| `layout.degenerate-line` | a line's points coincide: move an end or add a bend with `via` |\n| `prop.invalid-value` | `fontSize`, `fontWeight`, `textAlign` and `verticalAlign` are free-only; `shape` is for `node` and `box` only; a line takes no `place` or `size` |\n",
|
|
8
8
|
stories: "# Stories\n\nA `story` tells a diagram step by step for a walkthrough, a talk or a recorded demo. It never\nchanges the diagram: scenes reveal, hide, highlight, focus, frame and trace parts of it on one\ndeterministic clock, and may switch to another view of the same system. Write the diagram first,\nthen the story below it (or in another file that imports the diagram).\n\n```text\nstory purchase for checkout {\n title \"A purchase\"\n\n scene overview {\n reveal client, api, orders, db over 800ms\n hold 1s\n }\n\n scene processing {\n trace request over 1200ms\n parallel {\n trace save over 1200ms\n highlight db over 1200ms\n }\n hold 2s\n }\n}\n```\n\n## Vocabulary\n\n| Statement | Default | Meaning |\n| ------------------------------------------- | ------- | --------------------------------------------------------------------------------- |\n| `scene <id> [\"Title\"] { ... }` | | a step; scenes run one after the other |\n| `view <diagram>` | | first in a scene: the diagram it shows from now on |\n| `transition cut\\|fade\\|morph [over <time>]` | 800 ms | needed when the view changes; `morph` moves boxes with the same id, `cut` takes 0 |\n| `reveal a, b [over <time>]` | 600 ms | fades in; targets first revealed start hidden |\n| `hide a, b [over <time>]` | 600 ms | fades out |\n| `highlight a [over <time>]` | 1 s | accent outline for the action's time |\n| `focus a, b` / `focus all` | 600 ms | dims the rest to 25 % until the end of the scene; `all` clears it |\n| `camera a, b` / `camera all` | 800 ms | frames the targets plus 40 px; `all` frames the whole view |\n| `trace r [over <time>]` | 1.2 s | draws one named relation from source to target in the accent colour |\n| `hold <time>` | | waits |\n| `parallel { ... }` | | actions that start together; lasts as long as the longest |\n\nTargets are ids of the scene's view: elements, named relations (`as <id>`), named notes and\nfragments; entity paths (`shop.api`) in C4 views. Times are `800ms` or `1.5s`, up to `600s`.\n\n## Rules that save iterations\n\n- Name every relation you want to trace: `api -> db: \"SQL\" as save`.\n- Reveal everything that should appear; anything never revealed is visible from the start. An\n arrow appears with its two ends, so reveal the boxes, not the relations.\n- Two actions on the same target and channel must not overlap (`story.conflict`): put a `reveal`\n and a `hide` of the same box in sequence, not in one `parallel`.\n- A change of `view` needs a `transition` (`story.missing-transition`); use `morph` between views\n that share ids (two C4 views of one model), `fade` otherwise.\n- Keep scenes short (a few seconds) and end the story with a `hold` so the last state stays.\n\n## Diagnostics\n\n| Code | Fix |\n| -------------------------- | --------------------------------------------------------------------- |\n| `story.unknown-diagram` | the diagram after `for` or `view` is not in the file or imported |\n| `ref.unknown-element` | the target is not an id of the scene's view; use the suggested id |\n| `story.invalid-target` | `trace` needs a named relation |\n| `story.missing-transition` | add `transition cut`, `fade` or `morph` after `view` |\n| `story.conflict` | two overlapping actions on one target and channel; sequence them |\n| `story.empty-scene` | warning: give the scene an action or remove it |\n| `prop.invalid-value` | a time without `ms` or `s`, beyond 600 s, or a statement out of place |\n\n## Checking a story\n\n```bash\npnpm mdg validate path/to/sheet.meltemi\n```\n\n```bash\npnpm mdg export path/to/sheet.meltemi --story purchase --at 2.4s\n```\n\n`--story` writes `<stem>.<story>.svg`: the end of the story, or the frame at `--at`. Export a few\ninstants (the start of each scene, the middle of a trace) and look at them; the canvas in VS Code\nplays the story with a timeline.\n\nTo share the story, write its HTML player, an offline page with pause, progress, scenes, reduced\nmotion, a static view, a text summary, zoom, hover cards and a detail panel (`--embed` writes a\nfragment for an existing page):\n\n```bash\npnpm mdg export path/to/sheet.meltemi --story purchase --format html\n```\n",
|
|
9
9
|
};
|
|
10
10
|
//# sourceMappingURL=guide.js.map
|
package/dist/guide.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guide.js","sourceRoot":"","sources":["../src/guide.ts"],"names":[],"mappings":"AAAA,wFAAwF;AAExF,2DAA2D;AAC3D,MAAM,CAAC,MAAM,WAAW,GAAqC;IAC3D,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"guide.js","sourceRoot":"","sources":["../src/guide.ts"],"names":[],"mappings":"AAAA,wFAAwF;AAExF,2DAA2D;AAC3D,MAAM,CAAC,MAAM,WAAW,GAAqC;IAC3D,QAAQ,EAAE,m+vBAAm+vB;IAC7+vB,QAAQ,EAAE,0vIAA0vI;IACpwI,EAAE,EAAE,+gJAA+gJ;IACnhJ,IAAI,EAAE,4jiBAA4jiB;IAClkiB,OAAO,EAAE,ghKAAghK;CAC1hK,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meltemi/diagrams-assist",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Optional AI assistance for Meltemi sources: model adapters, reviewable proposals against a known revision, partial acceptance.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
"dist"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@meltemi/diagrams-i18n": "1.
|
|
30
|
-
"@meltemi/diagrams-model": "1.
|
|
31
|
-
"@meltemi/diagrams-language": "1.
|
|
29
|
+
"@meltemi/diagrams-i18n": "1.10.0",
|
|
30
|
+
"@meltemi/diagrams-model": "1.10.0",
|
|
31
|
+
"@meltemi/diagrams-language": "1.10.0"
|
|
32
32
|
},
|
|
33
33
|
"publishConfig": {
|
|
34
34
|
"access": "public"
|