Liking cljdoc? Tell your friends :D

vaelii.impl.svg

The inline-SVG primitives the term page's concept graph is drawn with: a node, an edge, an arrowhead, and the arithmetic that lays out a row, a column or a ring.

No graph library. The browser ships two JavaScript files and this adds none — a layout that is a fold over a row of boxes is a dozen lines, and a dependency that drew it would be the largest thing the client loads. Nor a shell-out: a page that renders by starting a process is a page that cannot be served.

Everything here is pure — no KB, no access facade, no belief — so it is tested on hand-built maps. What a node means is the caller's: it supplies the term, the colour class, the link and the tooltip, and this decides only where the box goes and what shape it is.

Coordinates live in one flat user space and may be negative; scene crops the viewBox to the union of what was actually drawn, so a sparse graph is centred rather than adrift in a fixed canvas and a long snake_case label is never clipped. Every number reaching an attribute is a long: Clojure's / yields a ratio, and 1/2 in an SVG attribute is not a coordinate.

The inline-SVG primitives the term page's concept graph is drawn with: a node, an
edge, an arrowhead, and the arithmetic that lays out a row, a column or a ring.

**No graph library.**  The browser ships two JavaScript files and this adds none — a
layout that is a fold over a row of boxes is a dozen lines, and a dependency that drew
it would be the largest thing the client loads.  Nor a shell-out: a page that renders
by starting a process is a page that cannot be served.

Everything here is **pure** — no KB, no access facade, no belief — so it is tested on
hand-built maps.  What a node *means* is the caller's: it supplies the term, the
colour class, the link and the tooltip, and this decides only where the box goes and
what shape it is.

Coordinates live in one flat user space and may be negative; `scene` crops the
`viewBox` to the union of what was actually drawn, so a sparse graph is centred rather
than adrift in a fixed canvas and a long snake_case label is never clipped.  Every
number reaching an attribute is a **long**: Clojure's `/` yields a ratio, and `1/2` in
an SVG attribute is not a coordinate.
raw docstring

arcclj

(arc nodes cx cy r a)

Place measured nodes on a short arc of radius r centred on angle a around (cx, cy) — a cluster hanging off one direction rather than a full ring, which is what puts a neighbour's own neighbours out past it instead of somewhere else entirely.

The angular step is derived from the widest box exactly as ring's radius is: the arc between two of them is 1.1× the widest, so a cluster of long names spreads and a pair of short ones stays tight.

Place measured `nodes` on a short arc of radius `r` **centred on angle** `a` around
(`cx`, `cy`) — a cluster hanging off one direction rather than a full ring, which is
what puts a neighbour's own neighbours out past it instead of somewhere else entirely.

The angular step is derived from the widest box exactly as `ring`'s radius is: the arc
between two of them is 1.1× the widest, so a cluster of long names spreads and a pair of
short ones stays tight.
raw docstring

columnclj

(column nodes x-edge y gap side)

Place measured nodes in a vertical column beside the centre, stacked gap apart and centred on y. side is -1 for a column to the left of x-edge (its right edge there) and 1 for one to the right, so the two flanks mirror without the caller doing the arithmetic twice.

Place measured `nodes` in a vertical column beside the centre, stacked `gap` apart and
centred on `y`.  `side` is -1 for a column to the *left* of `x-edge` (its right edge
there) and 1 for one to the right, so the two flanks mirror without the caller doing
the arithmetic twice.
raw docstring

labelclj

(label term)

The text a node carries for term, cut to label-cap with an ellipsis.

The text a node carries for `term`, cut to `label-cap` with an ellipsis.
raw docstring

label-capclj

How many characters of a term's name a node label carries. Past this it is cut and the whole term goes in the node's title, so nothing is lost — only moved one hover away. Twenty-two holds physical_object and every predicate the shipped schema has, and is short enough that a row of eight still reads.

How many characters of a term's name a node label carries.  Past this it is cut and
the whole term goes in the node's `title`, so nothing is lost — only moved one hover
away.  Twenty-two holds `physical_object` and every predicate the shipped schema has,
and is short enough that a row of eight still reads.
raw docstring

measureclj

(measure node)

Give a node its label and its box — :label, :w, :h — leaving where it goes to the layout fns below. Idempotent, so a caller may measure once and place twice.

The text is :display when the caller supplied one, else the term itself: what a term is called on the page is the caller's business (a reified term reads as the expression it denotes), and :term stays the identity the layout dedups on.

The width is rounded up to an even number, and node-h is even for the same reason: a box's edge is then an integer wherever its centre is, so trim lands an arrowhead exactly on the boundary instead of half a pixel inside it.

Give a node its label and its box — `:label`, `:w`, `:h` — leaving *where* it goes to
the layout fns below.  Idempotent, so a caller may measure once and place twice.

The text is `:display` when the caller supplied one, else the term itself: what a term
is *called* on the page is the caller's business (a reified term reads as the
expression it denotes), and `:term` stays the identity the layout dedups on.

The width is rounded **up to an even number**, and `node-h` is even for the same reason:
a box's edge is then an integer wherever its centre is, so `trim` lands an arrowhead
exactly on the boundary instead of half a pixel inside it.
raw docstring

node-hclj

Every node is the same height. A row is then a straight line of pills and the eye reads the row rather than the boxes.

Every node is the same height.  A row is then a straight line of pills and the eye
reads the row rather than the boxes.
raw docstring

ringclj

(ring nodes cx cy min-r start)

Place measured nodes evenly around a circle centred at (cx, cy), starting at start radians and going clockwise.

The radius is computed, not given: min-r, or whatever radius spaces the arc between neighbours at 1.15× the widest box — so eight long names spread onto a wider ring instead of overlapping, and two short ones do not fly apart. That is the whole reason a ring is affordable without a force simulation.

Place measured `nodes` evenly around a circle centred at (`cx`, `cy`), starting at
`start` radians and going clockwise.

The radius is **computed, not given**: `min-r`, or whatever radius spaces the arc
between neighbours at 1.15× the widest box — so eight long names spread onto a wider
ring instead of overlapping, and two short ones do not fly apart.  That is the whole
reason a ring is affordable without a force simulation.
raw docstring

rowclj

(row nodes cx y gap)

Place measured nodes left to right in a row centred on cx at height y, gap apart.

Place measured `nodes` left to right in a row centred on `cx` at height `y`, `gap`
apart.
raw docstring

sceneclj

(scene {:keys [nodes edges aria-label]})

The whole picture as one <svg>, or nil when there is nothing to draw — a caller renders the nil and gets no empty frame.

aria-label is what a screen reader is told the image shows; it is role="img" because the prose above it, not the picture, is the accessible answer. The viewBox is the crop, and width=100% with preserveAspectRatio is what makes the drawing scale to the column instead of a fixed pixel canvas.

The whole picture as one `<svg>`, or **nil** when there is nothing to draw — a caller
renders the nil and gets no empty frame.

`aria-label` is what a screen reader is told the image shows; it is `role="img"`
because the prose above it, not the picture, is the accessible answer.  The `viewBox`
is the crop, and `width=100%` with `preserveAspectRatio` is what makes the drawing
scale to the column instead of a fixed pixel canvas.
raw docstring

trimclj

(trim a b)

The visible segment between two placed nodes: the line between their centres, clipped at each one's box, so an arrowhead lands on the boundary of the node it points at rather than under its label. Nil when the two centres coincide — there is no direction to draw.

The visible segment between two **placed** nodes: the line between their centres,
clipped at each one's box, so an arrowhead lands on the boundary of the node it points
at rather than under its label.  Nil when the two centres coincide — there is no
direction to draw.
raw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close