Megacorp Documentation v2.0-beta

Diagrams over the entity graph

A diagram directive's body is PlantUML source. In the plain .. plantuml::/.. uml:: spelling it reaches the compiler exactly as written; in the three spellings below it is first expanded as a Jinja template against the project's entity graph, so a picture can be derived from what the documents declare rather than restated beside them.

Because the graph spans documents, expansion happens after the whole project has been indexed — which is why diagram compilation belongs to the site rather than to any one library.

Drawing what a filter selects

filter() takes the same expression language an .. entity-table::'s :filter: is written in, and flow() turns an id into a clickable node. Clicking one lands on exactly the anchor a :ref: to that entity would.

PlantUML Diagram

Every requirement in the project

.. needuml:: is accepted as a second spelling of the same directive, so a migrating sphinx-needs project keeps its documents.

Reading one entity's fields

needs holds every entity by id and need(id) fetches one. Attributes, relations and derived back-links share the one namespace the directive's options do, so .. req::'s :owner: is read as need.owner.

PlantUML Diagram

One requirement and what it links to

@startuml
rectangle "The system shall boot within two seconds\n<size:10>req: REQ_001</size>" as REQ_001 [[requirements.html#entity-REQ_001]]
note right of REQ_001
  owner: platform
  status: in_progress
end note

rectangle "Boot sequence\n<size:10>spec: SPEC_001</size>" as SPEC_001 [[requirements.html#entity-SPEC_001]]
REQ_001 --> SPEC_001

rectangle "Staged boot loader\n<size:10>impl: IMPL_001</size>" as IMPL_001 [[requirements.html#entity-IMPL_001]]
REQ_001 --> IMPL_001

@enduml

:debug: shows the expanded PlantUML below the picture — the text that was actually compiled, which is what an author needs when a diagram comes out wrong.

Extra values

:extra: binds names into the template's context, as comma-separated name: value pairs.

PlantUML Diagram

An architecture diagram inside an entity

.. entity-arch:: — sphinx-needs spells it .. needarch:: — is written inside an entity and binds that entity as need. Writing one outside any entity is reported as uml.arch-outside-entity rather than drawn against a need bound to nothing.

Its `:key:` stores the template on the entity, so another diagram can import it. This is what makes architecture diagrams compositional: a component draws itself once, and every diagram that reaches it pulls that picture in rather than restating it.

RequirementThe bootloader shall verify the kernel signatureREQ_BOOT

PlantUML Diagram
Details
Statusopen
Ownerplatform

A diagram written inside a section still knows the entity it sits in, even though a section's body deliberately forgets the entity's type:

PlantUML Diagram

Importing another entity's diagram

uml(id, key) expands the diagram another entity wrote, with need rebound to that entity. imports(id, relation) does the same for everything an entity points at along a relation, skipping targets that drew nothing.

A diagram that reaches itself — directly, or around a cycle — is reported as uml.recursive-import with the route it took, rather than expanding until the build dies.

PlantUML Diagram

The bootloader's own picture, pulled in from where it was written

Named PlantUML preambles

:config: names a preamble declared under [uml_configs] in the site's rinx.toml — the preamble's text, never a path to a file holding it, so it survives a sandboxed build relocating files. The preamble is inserted directly after @startuml, which is the only place PlantUML reads a skinparam from. Naming one that is not declared is uml.unknown-config rather than a diagram quietly missing its styling.

PlantUML Diagram

The same graph, with the site's monochrome preamble applied

Flowcharts of the graph itself

.. entity-flow:: — sphinx-needs spells it .. needflow:: — draws the entities a filter selects and the relations between them, without a template. The picture is generated: there is no body to write, and the directive reports one rather than mistaking it for PlantUML source.

PlantUML Diagram

Every entity in the project, and every relation between them

Selecting a subgraph, and labelling its edges

:filter: is the same expression language an .. entity-table::'s is, and :relations: — sphinx-needs spells it :link_types: — says which relations become edges. An edge whose target the filter left out is not drawn, so a filtered picture stays a picture of what was asked for.

PlantUML Diagram

Requirements and the specifications they link to, laid out sideways

The :name: above registers as an ordinary cross-reference target, so requirement-flow links to the picture.

The generated source, and a preamble

:debug: shows the PlantUML that was compiled — worth more here than on a written diagram, since this text exists nowhere else — and :config: names a preamble from the site's [uml_configs], exactly as it does above.

PlantUML Diagram

The test cases, in monochrome

@startuml
skinparam monochrome true
rectangle "Boot timing regression test\n<size:10>test: TEST_001</size>" as TEST_001 [[requirements.html#entity-TEST_001]]
@enduml

A filter matching nothing is reported as entity-flow.empty-result rather than compiled: PlantUML rejects an empty diagram, so the build would otherwise fail with a syntax error naming a generated file nobody wrote.

Sequence diagrams of the graph

.. entity-sequence:: — sphinx-needs spells it .. needsequence:: — walks the graph instead of filtering it. From each :start: entity, a relation named in :relations: leads to a message, and the same relations lead on from the message to its receivers; every hop is an arrow labelled with the message's title, and every receiver not yet seen is walked in turn.

The components and messages below are ordinary entities, declared inside a dropdown the way the sphinx-needs demo corpus declares its own.

The coffee machine's components and messages

ComponentUser interfaceCOMP_UI

Details

ComponentHardware abstraction layerCOMP_HAL

Details

ComponentSafety monitorCOMP_SAFETY

Details

ComponentHeaterCOMP_HEATER

Details

Messageinit()MSG_INIT

Details

Messageinit_okMSG_INIT_OK

Details

Messagearm()MSG_ARM

Details

Messagepoll_sensors()MSG_POLL

Details

Messagetemp=22°CMSG_READING

Details

Messagestart()MSG_START_HEATER

Details

MessageheatingMSG_HEATER_UP

Details

MessagereadyMSG_READY

Details

Messageemergency_stopMSG_HALT

Details
PlantUML Diagram

Startup

The argument is the caption, as in sphinx-needs, and :name: registers the picture as a cross-reference target: startup-sequence.

:relations: is mandatory — sphinx-needs defaults it to links, but neither that nor "every relation" says which edges are messages. Several starts share one walk, so a component the first start already reached is not drawn twice:

PlantUML Diagram

Shutdown

Selecting receivers, and capping the picture

:filter: keeps only the receivers it selects — a receiver it rejects gets no arrow and is not walked on from. :max-items: draws only the first messages and says so beneath the picture; the build warns as well, as entity-sequence.truncated, which a deliberate cap silences.

PlantUML Diagram

Startup without the heater

PlantUML Diagram

The first three messages of the startup, in monochrome

@startuml
skinparam monochrome true
participant "User interface" as COMP_UI [[diagrams.html#entity-COMP_UI]]
participant "Hardware abstraction layer" as COMP_HAL [[diagrams.html#entity-COMP_HAL]]
participant "Safety monitor" as COMP_SAFETY [[diagrams.html#entity-COMP_SAFETY]]
COMP_UI -> COMP_HAL : init()
COMP_HAL -> COMP_UI : init_ok
COMP_HAL -> COMP_SAFETY : temp=22°C
@enduml

Showing the first 3 of 8 messages; raise :max-items: (0 for all) to draw more.