@rse/specbook 1.2.4 → 1.2.6

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.
@@ -74,6 +74,7 @@ type SchemaObject = {
74
74
  refs?: string
75
75
  optional?: boolean
76
76
  referenced?: string[]
77
+ coverage?: string[]
77
78
  automaton?: SchemaAutomaton
78
79
  diagram?: SchemaDiagram
79
80
  format?: SchemaFormat
@@ -100,6 +101,7 @@ type SchemaDiagramCenterEdges = {
100
101
  outbound?: string
101
102
  both?: string
102
103
  labeled?: string
104
+ via?: string
103
105
  }
104
106
  type SchemaDiagram = {
105
107
  type?: "graph" | "hub" | "grid"
@@ -123,6 +125,7 @@ type SchemaDiagram = {
123
125
  type SchemaFormat = {
124
126
  type?: "auto" | "complex" | "concise"
125
127
  maxTableColumns?: number
128
+ maxCellHeight?: number
126
129
  withUnusedProps?: boolean
127
130
  }
128
131
  type SchemaProperty = {
@@ -234,6 +237,13 @@ type SchemaGradiaConfig = Partial<{
234
237
  at least once, where a lapse is reported as a warning only,
235
238
  BECAUSE a term nobody uses or a requirement no use case exercises is dead weight
236
239
 
240
+ - `SchemaObject.coverage?: string[]`:
241
+ wildcard references (e.g. `[[SCENARIO:*]]` for the use case scenarios)
242
+ matching the objects whose reference coverage every object of this kind
243
+ reports: the share of them referenced -- themselves or through their
244
+ descendants -- from the object or its descendants (see below),
245
+ BECAUSE a test artifact has to state how much of the specification it verifies
246
+
237
247
  - `SchemaObject.automaton?: SchemaAutomaton`:
238
248
  finite state machine the child objects of every object of this kind form,
239
249
  BECAUSE a lifecycle is only trustworthy when its dead-ends and
@@ -318,9 +328,11 @@ type SchemaGradiaConfig = Partial<{
318
328
  objects whose `inbound` value maps onto a node-to-center edge, whose
319
329
  `outbound` value onto a center-to-node edge, and whose `both` value
320
330
  onto both edges (the second placement rendered as a "ghost" node),
321
- each optionally named by the value of the `labeled` property,
322
- BECAUSE the nodes carry no `[[xxx]]` reference to a synthetic center,
323
- so their relation to it lives in a direction property instead
331
+ each optionally named by the value of the `labeled` property and/or
332
+ by the mediating object referenced by the `via` property (as `via
333
+ <name>`), BECAUSE the nodes carry no `[[xxx]]` reference to a
334
+ synthetic center, so their relation to it lives in a direction
335
+ property instead
324
336
 
325
337
  - `SchemaDiagram.links?: "props" | "all"`:
326
338
  edge source: property values (`props`) or also texts (`all`),
@@ -350,7 +362,7 @@ type SchemaGradiaConfig = Partial<{
350
362
 
351
363
  - `SchemaDiagram.deep?: boolean`:
352
364
  whether the references of the descendants of a node count as its own,
353
- lifted to their nearest node and counted as the arity (default: `false`),
365
+ counted as the arity (default: `false`),
354
366
  BECAUSE the relations between coarse objects live in their fine parts
355
367
 
356
368
  - `SchemaDiagram.onlyConnected?: boolean`:
@@ -365,6 +377,40 @@ type SchemaGradiaConfig = Partial<{
365
377
  whether every node is labeled with its kind (default: `false`),
366
378
  BECAUSE names alone are ambiguous across multiple object kinds
367
379
 
380
+ - `SchemaDiagram.ordered?: boolean`:
381
+ whether the nodes are placed in document order instead of by the
382
+ layered layout, the top-level ones stacked top-down and the members
383
+ of a container lined up left-to-right (default: `false`),
384
+ BECAUSE in a coarse-to-fine specification the references then all
385
+ point backward, i.e. upward
386
+
387
+ - `SchemaDiagram.nest?: SchemaDiagramNest`:
388
+ nesting of the nodes into container nodes,
389
+ BECAUSE a containment drawn as a box beats one drawn as an edge
390
+
391
+ - `SchemaDiagramNest.properties?: string[]`:
392
+ properties whose single referenced object is the container of a node,
393
+ BECAUSE a `PART-OF` or `TIER` reference is a containment, not a relation
394
+
395
+ - `SchemaDiagramNest.parent?: boolean`:
396
+ whether the parent object is the container of a node (default: `false`),
397
+ BECAUSE the nesting of the objects is a containment, too
398
+
399
+ - `SchemaDiagramNest.kind?: boolean`:
400
+ whether a synthetic container per object kind holds the nodes
401
+ (default: `false`),
402
+ BECAUSE a kind is a grouping no object models
403
+
404
+ - `SchemaDiagramNest.layout?: "graph" | "hub" | "grid"`:
405
+ shape the members of every container are laid out with
406
+ (default: the diagram type),
407
+ BECAUSE the inside of a container may tell a different story than the whole
408
+
409
+ - `SchemaDiagramNest.crossing?: "nodes" | "target" | "both"`:
410
+ ends of a boundary-crossing edge lifted onto the containers
411
+ (default: `nodes`, i.e. none),
412
+ BECAUSE a bundle of references into a container reads as one edge onto it
413
+
368
414
  - `SchemaDiagram.properties?: string[]`:
369
415
  property names attached to the nodes as key/value annotations,
370
416
  BECAUSE the node name alone rarely makes the nodes comparable
@@ -385,6 +431,10 @@ type SchemaGradiaConfig = Partial<{
385
431
  maximum column count of the table of the kind (default: `4`),
386
432
  BECAUSE the fixed print/PDF page width bounds the table width
387
433
 
434
+ - `SchemaFormat.maxCellHeight?: number`:
435
+ percent a table cell may tower over its row before it folds (default: `40`),
436
+ BECAUSE a cell of rich prose otherwise dwarfs the whole table
437
+
388
438
  - `SchemaFormat.withUnusedProps?: boolean`:
389
439
  whether unused properties still render (default: `false`),
390
440
  BECAUSE empty entries are noise, unless the gap is the message
@@ -474,9 +524,10 @@ type SchemaGradiaConfig = Partial<{
474
524
 
475
525
  The edges are derived from the `[[xxx]]` references of the node objects
476
526
  -- from their property values only, or, with `links: all`, from their
477
- descriptions as well. With `deep: true` the references of all
478
- descendants of a node object count as its own, every referenced object
479
- is lifted to its nearest ancestor-or-self within the node set, and the
527
+ descriptions as well. Every referenced object is lifted to its nearest
528
+ ancestor-or-self within the node set, so a reference onto the scenario
529
+ of a use case yields an edge onto the use case. With `deep: true` the
530
+ references of all descendants of a node object count as its own and the
480
531
  number of references behind an edge becomes its arity, so a diagram of
481
532
  coarse objects (like the artifacts of a whole specification) shows the
482
533
  relations living in their fine-grained parts. With `labeled: true` an
@@ -527,6 +578,52 @@ nodes as key/value annotations (with every `[[xxx]]` reference stripped
527
578
  to its target object name), and `config` passes arbitrary Gradia
528
579
  rendering options (e.g. `grid-columns-max: 5`) through to the diagram.
529
580
 
581
+ `ordered` replaces the layered layout of a `graph` by the document
582
+ order of the objects: the top-level nodes stack top-down in that order
583
+ (a synthetic container at the position of its first member), while the
584
+ members of a container line up left-to-right in it, wrapped by the
585
+ Gradia option `graph-columns-max`, so the references of a coarse-to-fine
586
+ specification all point backward, i.e. upward or leftward.
587
+
588
+ `nest` nests the nodes into *container* nodes, drawn as boxes around
589
+ their members with the edges crossing the box borders: the first of its
590
+ `properties` carrying exactly one resolvable reference names the
591
+ container of a node (a container outside the node set is added to it,
592
+ labeled and linked like a node, and nested on its own in turn, so a
593
+ `NODE` sits in its `TIER` and the tier in the tier it is `PART-OF`),
594
+ else with `parent: true` the parent object is the container when part
595
+ of the node set, else with `kind: true` a synthetic container per object
596
+ kind is. An edge between a container and one of its own members is
597
+ dropped, as the nesting already shows it, `layout` selects the shape
598
+ the members of every container are laid out with (default: the diagram
599
+ type), a `hub` carries no containers, as every container would need a
600
+ primary node of its own, and a node nested into itself or into a cycle
601
+ is reported. With `crossing: target` an edge crossing a container
602
+ boundary ends at the outermost container of its target not enclosing
603
+ its source, too, and with `crossing: both` it also starts at the
604
+ corresponding container of its source, where the edges coinciding
605
+ afterwards merge into one with their arities summed, so the edges
606
+ inside a container stay node-to-node while the bundles of references
607
+ into a container become single edges onto it.
608
+
609
+ ### Coverage
610
+
611
+ An object kind can carry a `coverage` field, a list of `[[xxx]]`
612
+ reference patterns, which makes every object of that kind report how
613
+ much of the objects matching each pattern it references: the *coverage*
614
+ is the share of the matching objects (those below the reporting object
615
+ itself excluded) which are referenced from the reporting object or one
616
+ of its descendants, where a matching object also counts as referenced
617
+ through one of its descendants, so a use case is covered as soon as one
618
+ of its scenarios is. While the `referenced` field demands the coverage
619
+ of an object kind and warns about every lapse, the `coverage` field
620
+ merely measures it: the HTML/PDF export renders a coverage table below
621
+ the description of the reporting object (one row per pattern, labeled
622
+ by the kinds of the matching objects, with the covered and total counts
623
+ and the ratio as a bar), the AST exports attach the counts as the
624
+ `coverage` field of the object, and the verbose output of `lint` and
625
+ `export` names the unreferenced objects.
626
+
530
627
  ### Format
531
628
 
532
629
  An object kind can furthermore carry a `format` field, which controls
@@ -542,7 +639,10 @@ Inside a `concise` table, unconfigured child kinds implicitly stay
542
639
  an explicitly configured `type` is always honored, even a `complex`
543
640
  rendering pressed into a cell. `maxTableColumns` (default: `4`) bounds
544
641
  the columns of the compact table of the kind (a wider group chunks
545
- its properties into embedded per-object tables), and `withUnusedProps`
642
+ its properties into embedded per-object tables), `maxCellHeight`
643
+ (default: `40`) is the percentage a table cell of the kind may exceed
644
+ the height of every other non-empty cell of its row before the HTML
645
+ export folds its remaining text away, and `withUnusedProps`
546
646
  (default: `false`) unconditionally renders the defined but unused
547
647
  properties of that kind, as property table lines or table columns. In
548
648
  the HTML/PDF export, a property absent from an object shows an "empty
@@ -837,7 +937,7 @@ In all formats, the `<name/>` may carry trailing decorations, in any
837
937
  order:
838
938
 
839
939
  - `{{<id/>}}`: the explicit Wiki-style anchor, setting the object id
840
- (e.g. `## ENTITY: Attendee Browser {{attendee}}`).
940
+ (e.g. `## ENTITY: Attendee {{attendee}}`).
841
941
 
842
942
  - `(<token/>)`: a parenthesized token with three possible roles: on
843
943
  level 1 it becomes the artifact id (e.g. `# DATA: Data Model (DM)`);
@@ -896,7 +996,7 @@ exports. A reference is a `.`-separated path of segments, where each
896
996
  segment matches a single object as:
897
997
 
898
998
  - `<id/>`: the object id or explicit anchor (e.g. `[[attendee]]`)
899
- - `<name/>`: the object name (e.g. `[[Attendee Browser]]`)
999
+ - `<name/>`: the object name (e.g. `[[Attendee]]`)
900
1000
  - `<kind/>:<name-or-id/>`: kind-qualified (e.g. `[[ENTITY:Event]]`)
901
1001
  - `<kind/>:*` or `*`: wildcards (for match sets, see below)
902
1002