0058. Lines without heads, free lines, sketched strokes and vertical text alignment
Status: accepted (lines-and-text-alignment change, 24 October 2026). Extends decisions 0003, 0007, 0012, 0013, 0018 and 0043. Pen strokes, which the sketch passes leave as drawn, are decision 0064. The text sizes and weights leave the free-only properties, and thirteen more families are bundled, in decision 0067.
Context
Section titled “Context”The owner asked for three things on 2026-10-23, and each had one cause in the language or the drawing.
- A relation could not be a plain line. The lexer made
->and-->arrows and-digita number, and any other run starting with-was an unknown token, soa -- bwassyntax.unexpected-character. The only line between two boxes was a named relation withstyle x { arrowhead none }, which is what the Mermaid and PlantUML importers wrote for every open link. - Nothing could be a line that joins no element: the free kinds were
box,text,icon,imageandgroup, every relation joins two elements and everyroutenames a relation, so a divider, a bracket or an underline on a slide had no statement. - Nothing looked hand-drawn, which whiteboard tools offer for early thinking, and the renderer had no dependency to draw it with.
- Text in a free box could move across (
textAlign, free-only by decision 0043) but not down: its vertical place was one point per shape.
Decision
Section titled “Decision”- Two line tokens.
--(a solid line) and---(a dashed line) join->,-->,<->and<-->: one dash more is dashed, and the lines drop the head glyph. The lexer takes the longest match (---,-->,--,->, then a number), so--->is---followed by an unexpected>, and the hint names the six tokens. Flow and free diagrams take the six; sequence diagrams take the four arrows (a message is a call or a reply) and C4 views->and-->(their relations come from the model), refusing the others withprop.invalid-valueon the token, as views refused<->already. - A
headsfact. A relation recordsheads,end,bothornone, from one table of the schema that also gives itsline;twoWaystays and isheads === "both", andarrowToken(line, heads)gives the token back to the importers, the edits and the C4 model. The heads are only defaults: the end head isarrowhead, else none for a line, else the theme’s, and the start head isarrowtail, else the end’s for a two-way relation, soa -- bwitharrowhead circlestill ends in a circle. The model JSON gainsheadsaftertwoWay; the version stays 0.1. - The importers write the tokens. Mermaid
---and===(withwidth 3) become--,-.-becomes---, architecture--edges become named--lines with their routes, and block-beta open links become lines; PlantUML headless arrows become--(---when dotted), a left UML head with no right head (*--) becomes--witharrowtail, and note links---. No sheet writesarrowhead nonefor a line any more, and relations that were named only for that style are anonymous. - A free
lineobject.line <id> ["Label"] from (x, y) to (x, y) [via [(x, y), ...]] [{ ... }]is a declaration of free diagrams. The label is the second argument, empty by default; the points are in the parent’s interior coordinates, asplaceis, so a line in a group moves with it. A line takes noplace,sizeorrotation, takes the styles of a relation (stroke, line, width, heads, routing, corners, and the pill’s colours and icon) and refuses those of a box;label <id> at …moves its pill, andrule line { }styles every line. The model JSON gives every elementlineaftershape, null but on lines. - Lines are drawn as connectors. The layout turns a line into a connector plan beside the
relations’: its written points,
polylineby default (and forauto, with no box to anchor to),orthogonalwith an elbow between points that differ on both axes,bezierthrough them,corners, headsnoneby default and cut as a relation’s, a label pill at 50 %. It takes no lanes, detours or gaps under titles. Its scene group has roleelementwith both atrackandbounds, so it is painted in source order like any object and every effect (flow, dash, pulse, trace) runs along it:planMotionanimates any group with atrackas a connector. Coinciding points draw a dot and reportlayout.degenerate-line(warning). - Lines on the canvas. The arrow button’s menu lists the six kinds and R cycles them. On a free
diagram the armed relation tool dragged on empty canvas draws a line: a ghost with the kind’s
dashes and heads, snapped, Shift for 45°, Escape cancels; the release writes the
lineinside the group under the press and the kind’s styles in one edit (line dashed, and the theme’sarrowheadtoken for the heads, so an editorial sheet getsopen). A press on an element keeps the two-click relation sequence. A selected line shows its outline, end, bend and midpoint handles; drags and nudges postsetLinePoints, which rewrites the tuples with minimal edits and inserts or removesvia. sketchis a theme token painted by the renderer.sketch none|light|rough; the built-in themes writenone, and two new built-in themes,sketch.lightandsketch.dark, are the technical pair withsketch lightandcorners rounded, eight in all;sketchis a reserved import name.renderSvgdraws every stroked rect, path and polyline of the element, relation, label, frame, lifeline and event groups, heads and pills included, as the fill alone plus two stroke-only passes: the outline (a rect turned into four sides with quarter arcs) sampled every 16 px (light) or 12 px (rough), each sample moved along the normal by at most 0.6 px or 1.4 px from a mulberry32 sequence seeded by a hash of the group’s id and the pass. Width, dash, dash offset, class, opacity and transform are copied to both passes. Text, images, icons, the mark, gradients and patterns are untouched, and the layout’s scene, tracks, bounds, hit tests and canvas overlays stay clean. The theme panel showssketchas a row of pictures.- Patrick Hand for the sketch text. The owner approved the download on 2026-10-24, and
@fontsource/patrick-hand5.3.0 (OFL-1.1) is the fourth bundled family: one weight (400) in the Latin, Latin Extended and Vietnamese subsets, measured, outlined and embedded like Cascadia Mono (no complete file). The sketch themes name"Patrick Hand", "Inter", …, so the characters it lacks (Greek, Cyrillic) are measured with Inter, outlined with it, and left to the viewer’s fallback when embedded, and no sketch picture carrieslayout.unmeasured-font. Every weight takes the one file; the embedded@font-facerule declaresfont-weight:400 700(EmbeddableFace.weightTo) so a browser draws a bold label with the same outlines as the layout measured and the outlined export draws, not a synthesized bold; a face that several weights ask for is embedded once, limited to the characters of them all. The licence inventory gains its row. verticalAlignwithin the shape’s text band.top,middle(default) orbottom, a free style property besidetextAlign, refused in flow diagrams as decision 0043 refuses the text properties. The text block keeps its height;topsearches the shape’s text band from its top edge pluspaddingfor the first row band whose inscribed span holds the block,bottomfrom the bottom edge, and the block moves back towards the middle when no band holds it. The band is each shape’s: the box, the inside of a curve, between a cylinder’s rims, above a document’s wave or a callout’s tail, an arrow’s shaft, away from a flag’s notch.layout.vertical-align-ignored(warning) reports it once per statement where it moves nothing: on the shapes whose text spot is fixed (triangle, pentagon, star, person, agent, icon), with a centred icon, and on texts, icons, images, groups and lines.- One alignment picker. The strip shows a 3 × 3 “Text alignment” grid after Shape for free boxes, three cells for free texts, the written pair pressed and the default greyed; a cell writes the properties that change in one step, and the Theme chip removes both.
Alternatives considered
Section titled “Alternatives considered”-alone,—or~~for a line.-is a number’s sign anda - breads as arithmetic;—is not ASCII (decision 0003 keeps the lexicon ASCII);~~is Mermaid’s invisible link.- Replacing
twoWaybyheads. Every consumer would change for no new behaviour. - A token that forbids heads, or
arrowhead nonewritten by the compiler. draw.io and Excalidraw let a line take an end decoration, the importers would still needarrowhead nonefor a line with a tail, and the strip could not tell an invented style from a written one. - Line tokens in sequence diagrams. Nothing in the profile draws a message without a head.
- A relation between point endpoints,
(x, y) -- (x, y). Statements start with a keyword or an id (decision 0003), routes need a named relation, and the placement would split between the relation and its route. - A
lineshape of a box.placeandsizegive a box, not two points: no bends, no heads, no effects, and a diagonal would be the box’s diagonal. - The label as
: "Label"after the points, orvia (x, y), (x, y)without brackets. A colon clause would be a parser change for one statement, and oneviagrammar is better than two. - A third scene role for lines, or a line registered as both element and relation. Every
consumer that switches on role would need the case, or one id would have two entries; an
element group with a
trackneeds one rule inplanMotion. - A Line tool of its own, or
arrowhead trianglewritten literally. A fourth gesture for what the arrow tool already means, and a theme switch would leave a stray triangle on an editorial sheet. rough.js. A download the owner has not approved, randomness not seeded by default, and the renderer’s first dependency.- A per-element
sketchstyle. draw.io has it diagram-wide, a mixed picture looks like a mistake, and a theme is where the family puts a look (decisions 0007 and 0013). - An SVG filter (
feTurbulence,feDisplacementMap). Not deterministic across renderers, dropped by some PDF and video captures, and it would wobble the text. - Sketching in the layout’s scene. Every consumer of the geometry would see jittered paths.
- Naming the hand font before it is bundled. Every sketch picture would carry
layout.unmeasured-fontand estimated widths, and the snapshots would move twice anyway. verticalAlignon flow nodes, or a pixel offset. Decision 0043 keeps the text properties free-only; an offset is precise but does not know the shape.- Two glyph rows or a select for the alignment. Six chips for what draw.io shows as one grid, or words where the strip shows pictures.
Consequences
Section titled “Consequences”-
The language stays 0.2: the tokens,
line,sketchandverticalAlignare additive. Every.model.jsonsnapshot gainsheadson each relation andlineon each element; the version stays 0.1. -
The sheets under
corpus/importlose theirarrowhead nonestyles and the names that only carried them. -
New diagnostics:
layout.vertical-align-ignoredandlayout.degenerate-line, both warnings. Thesyntax.unexpected-characterhint names six tokens, andlayout.unknown-themelists eight built-in themes. -
New public surface:
Relation.heads,RelationHeads,RELATION_ARROWS,arrowToken,Element.line,SKETCH_LEVELS,VERTICAL_ALIGNS,Theme.sketch,Scene.sketch,sketchItems, the protocol’sconnect.heads,ElementInfo.line,createLineandsetLinePoints. -
An anonymous relation’s key (
a->b#1) and a generated id change when statements are reordered, and the wobble of what they name changes with them; named targets keep theirs. -
Sketched pictures are larger, since each stroked item becomes up to three. Measured on 2026-10-24:
Picture Clean Sketched gallery/free/sketch(embedded fonts, the gallery’s SVG)136,282 bytes 67,756 bytes gallery/free/sketchwith--fonts system6,540 bytes 35,567 bytes corpus/acceptance/free/shapesandfree/sketch17,282 bytes 77,695 bytes The clean whiteboard is the same sheet rendered with
theme "technical.light"; the acceptance pair differs only in its theme, title and heading, and is rendered withsystemfonts. The fonts dominate an embedded export: Inter in four weights makes the clean file 136 KB, one weight of Patrick Hand makes the sketched file half of it, while the strokes alone grow about five times (thesystemrows). Nothing butrenderSvgreads the sketched paths, and the sketch themes are opt-in. -
The sketch pictures were regenerated when the hand font landed (the corpus and acceptance SVGs, the gallery sheet and the
free/sketchvisual reference).