Skip to content

Commit 87e45ac

Browse files
AAmbujhoe-jo
authored andcommitted
docs: add linker README with architecture and usage instructions
1 parent 008ebd2 commit 87e45ac

1 file changed

Lines changed: 257 additions & 0 deletions

File tree

plantuml/linker/README.md

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,260 @@
1010
1111
SPDX-License-Identifier: Apache-2.0
1212
----------------------------------------------------------------------------- -->
13+
14+
# PlantUML Linker
15+
16+
The **linker** reads FlatBuffers `.fbs.bin` files produced by the PlantUML parser and generates a `plantuml_links.json` file consumed by the [`clickable_plantuml`](../sphinx/clickable_plantuml/) Sphinx extension to make diagrams interactive.
17+
18+
## How It Works
19+
20+
```
21+
.puml files
22+
23+
24+
┌──────────┐ ┌────────────┐ ┌──────────────────────┐ ┌──────────────────┐
25+
│ Parser │ ──▶ │ .fbs.bin │ ──▶ │ Linker │ ──▶ │ plantuml_links │
26+
│ (puml_cli)│ │ (FlatBuf) │ │ (cross-diagram match)│ │ .json │
27+
└──────────┘ └────────────┘ └──────────────────────┘ └──────────────────┘
28+
29+
30+
┌──────────────────┐
31+
│ clickable_plantuml│
32+
│ (Sphinx extension)│
33+
└──────────────────┘
34+
```
35+
36+
### Supported Diagram Types
37+
38+
| Diagram Type | File ID | What Is Extracted |
39+
|---|---|---|
40+
| **Component** (`COMP`) | Alias, name, FQN (`id`), parent hierarchy, and relation targets |
41+
| **Class** (`CLSD`) | Entity name, FQN (`id`), diagram name, and relationship sources/targets |
42+
| **Sequence** (`SEQD`) | Unique participants (callers and callees from interactions) |
43+
44+
### Link Generation Algorithm
45+
46+
1. **Parse** each `.fbs.bin` file, detecting the diagram type by its 4-byte file identifier at bytes 4–7.
47+
2. **Build an index** of top-level aliases — components/entities with no parent — mapped to their source `.puml` file. Both the PlantUML alias and the FQN (`id`) are registered as index keys, along with any distinct `name`.
48+
3. **Register diagram names** (from `@startuml <name>`) as virtual top-level aliases, enabling cross-diagram linking by title.
49+
4. **Extract relationship targets**: relation targets from component diagrams and relationship sources/targets from class diagrams are added as linkable elements.
50+
5. **Match**: for each element alias in diagram A, if a top-level entry with the same name exists in diagram B, emit a link `A → B`.
51+
6. **Deduplicate** and keep one target per alias (PlantUML supports only one `url of` per alias).
52+
53+
### Output Format
54+
55+
```json
56+
{
57+
"links": [
58+
{
59+
"source_file": "overview.puml",
60+
"source_id": "MyComponent",
61+
"target_file": "my_component_detail.puml"
62+
}
63+
]
64+
}
65+
```
66+
67+
## Usage
68+
69+
```bash
70+
bazel run //plantuml/linker -- \
71+
--fbs-files path/to/*.fbs.bin \
72+
--output plantuml_links.json \
73+
--log-level info
74+
```
75+
76+
### Arguments
77+
78+
| Argument | Default | Description |
79+
|---|---|---|
80+
| `--fbs-files` | *(required)* | One or more `.fbs.bin` FlatBuffer files to process |
81+
| `--output` | `plantuml_links.json` | Output JSON file path |
82+
| `--log-level` | `warn` | Log verbosity: `error`, `warn`, `info`, `debug`, `trace` |
83+
84+
## Build & Test
85+
86+
```bash
87+
# Build
88+
bazel build //plantuml/linker
89+
90+
# Build with Clippy lint
91+
bazel build //plantuml/linker --config=clippy
92+
93+
# Run tests
94+
bazel test //plantuml/linker:linker_test
95+
```
96+
97+
## Linking Examples
98+
99+
### Component ↔ Component (alias match)
100+
101+
A top-level component in one diagram links to its detailed view in another:
102+
103+
```plantuml
104+
' overview.puml
105+
@startuml
106+
[AuthService] --> [UserDB]
107+
@enduml
108+
```
109+
110+
```plantuml
111+
' auth_detail.puml
112+
@startuml
113+
package AuthService {
114+
[TokenManager]
115+
[SessionStore]
116+
}
117+
@enduml
118+
```
119+
120+
**Result:** `AuthService` in `overview.puml` becomes clickable → navigates to `auth_detail.puml`.
121+
122+
### Component ↔ Sequence (participant match)
123+
124+
Sequence diagram participants link back to component diagrams that define them:
125+
126+
```plantuml
127+
' login_flow.puml
128+
@startuml
129+
AuthService -> TokenManager : validate()
130+
TokenManager -> SessionStore : getSession()
131+
@enduml
132+
```
133+
134+
**Result:** `AuthService`, `TokenManager`, and `SessionStore` in `login_flow.puml` become clickable → navigate to `auth_detail.puml` (where they are top-level components).
135+
136+
### Class ↔ Class (relationship target)
137+
138+
Relationship targets in class diagrams link to the diagram where the target class is defined:
139+
140+
```plantuml
141+
' models.puml
142+
@startuml
143+
class User {
144+
+name: String
145+
}
146+
class Order {
147+
+items: List
148+
}
149+
User --> Order : places
150+
@enduml
151+
```
152+
153+
```plantuml
154+
' order_detail.puml
155+
@startuml
156+
class Order {
157+
+items: List
158+
+total: float
159+
}
160+
class Payment {
161+
+amount: float
162+
}
163+
Order --> Payment
164+
@enduml
165+
```
166+
167+
**Result:** `Order` in `models.puml` becomes clickable → navigates to `order_detail.puml`. `Payment` extracted from the relationship also becomes linkable.
168+
169+
### FQN / ID match
170+
171+
When a component's fully qualified `id` (e.g. `auth.TokenManager`) is indexed, diagrams referencing that FQN can match even when the PlantUML alias differs:
172+
173+
```plantuml
174+
' system.puml — component with id "auth.TokenManager", alias "TokenManager"
175+
```
176+
177+
Other diagrams with a top-level element named `auth.TokenManager` will link to `system.puml`.
178+
179+
### Diagram name match
180+
181+
A diagram's `@startuml <name>` title acts as a virtual alias:
182+
183+
```plantuml
184+
' auth_detail.puml
185+
@startuml auth_detail
186+
package AuthService { ... }
187+
@enduml
188+
```
189+
190+
Any component with alias `auth_detail` in another diagram links to `auth_detail.puml`.
191+
192+
### Component name + alias (both registered)
193+
194+
When a component has both an `alias` and a distinct `name`, both are registered as linkable elements:
195+
196+
```plantuml
197+
' services.puml
198+
@startuml
199+
[Authentication Service] as AuthSvc
200+
@enduml
201+
```
202+
203+
**Result:** Both `AuthSvc` (alias) and `Authentication Service` (name) are indexed. A component named `Authentication Service` in another diagram will link here.
204+
205+
### Component relation targets
206+
207+
Dependency arrows extract their targets as linkable elements, even when the target isn't explicitly declared as a separate component:
208+
209+
```plantuml
210+
' gateway.puml
211+
@startuml
212+
[APIGateway] --> [AuthService] : authenticates
213+
[APIGateway] --> [RateLimiter] : throttles
214+
@enduml
215+
```
216+
217+
**Result:** `AuthService` and `RateLimiter` are extracted from relation targets. If either is a top-level component in another diagram, the arrow target becomes clickable.
218+
219+
### Class ↔ Component (cross-type linking)
220+
221+
Class entity names are matched against component aliases across diagram types:
222+
223+
```plantuml
224+
' class_model.puml
225+
@startuml
226+
class AuthService {
227+
+login(user: String): Token
228+
}
229+
@enduml
230+
```
231+
232+
```plantuml
233+
' system_overview.puml (component diagram)
234+
@startuml
235+
[AuthService] --> [UserDB]
236+
@enduml
237+
```
238+
239+
**Result:** `AuthService` in `system_overview.puml` becomes clickable → navigates to `class_model.puml` (where it is defined as a class entity).
240+
241+
### Sequence ↔ Class (cross-type linking)
242+
243+
Sequence diagram participants match class entity names from class diagrams:
244+
245+
```plantuml
246+
' login_flow.puml
247+
@startuml
248+
AuthService -> TokenManager : validate()
249+
@enduml
250+
```
251+
252+
```plantuml
253+
' token_classes.puml
254+
@startuml
255+
class TokenManager {
256+
+validate(): bool
257+
}
258+
@enduml
259+
```
260+
261+
**Result:** `TokenManager` in `login_flow.puml` becomes clickable → navigates to `token_classes.puml`.
262+
263+
## Related Changes
264+
265+
The linker works in concert with two other modified components:
266+
267+
- **`puml_serializer` ([class_serializer.rs](../parser/puml_serializer/src/serialize/class_serializer.rs))**: Prepends the actual source filename to the serialized `source_files` vector so the linker can correlate class diagrams with their `.puml` file.
268+
269+
- **`clickable_plantuml` ([clickable_plantuml.py](../sphinx/clickable_plantuml/clickable_plantuml.py))**: Extended alias formatting to accept hyphens and dots in element identifiers (e.g., `my-component`, `pkg.Class`), enabling `url of` directives for FQN-style names.

0 commit comments

Comments
 (0)