@canonical/anatomy-dsl 0.2.2 → 0.5.0
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.
- package/README.md +240 -23
- package/definitions/lift.fixture.json +216 -0
- package/definitions/ontology.ttl +206 -13
- package/definitions/registry.ttl +659 -0
- package/definitions/shapes.ttl +593 -8
- package/definitions/style-keys.yaml +391 -0
- package/package.json +15 -4
- package/dist/esm/index.js +0 -2
- package/dist/esm/parse.js +0 -72
- package/dist/esm/transform.js +0 -116
- package/dist/esm/types.js +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.js +0 -2
- package/dist/parse.d.ts +0 -2
- package/dist/parse.js +0 -72
- package/dist/transform.d.ts +0 -2
- package/dist/transform.js +0 -114
- package/dist/types/index.d.ts +0 -3
- package/dist/types/parse.d.ts +0 -2
- package/dist/types/transform.d.ts +0 -2
- package/dist/types/types.d.ts +0 -36
- package/dist/types.d.ts +0 -36
- package/dist/types.js +0 -1
package/definitions/shapes.ttl
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
@prefix anatomy: <
|
|
1
|
+
@prefix anatomy: <https://anatomy.canonical.com/> .
|
|
2
2
|
@prefix sh: <http://www.w3.org/ns/shacl#> .
|
|
3
3
|
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
4
4
|
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
5
5
|
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
|
|
6
|
+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
|
|
7
|
+
# The token graph. A consumed symbol is a dt: IRI, and SymbolListShape
|
|
8
|
+
# constrains every member of anatomy:consumes to one.
|
|
9
|
+
@prefix dt: <https://dt.canonical.com/> .
|
|
10
|
+
# The design system graph. Bound because ds:TokenBinding reuses
|
|
11
|
+
# anatomy:styleKey and anatomy:styleState, and a reader of these shapes needs
|
|
12
|
+
# the other end of that reuse in front of them.
|
|
13
|
+
@prefix ds: <https://ds.canonical.com/> .
|
|
6
14
|
|
|
7
15
|
# ═══════════════════════════════════════════════════════════════
|
|
8
|
-
# SHACL SHAPES FOR ANATOMY DSL 0.
|
|
16
|
+
# SHACL SHAPES FOR ANATOMY DSL 0.4.0
|
|
9
17
|
# ═══════════════════════════════════════════════════════════════
|
|
10
18
|
#
|
|
11
19
|
# Constraints, patterns, enumerations, and encoding conventions.
|
|
@@ -13,13 +21,21 @@
|
|
|
13
21
|
#
|
|
14
22
|
# Shapes:
|
|
15
23
|
# SpecificationShape — root document
|
|
16
|
-
# NamedNodeShape — uri required, encoding pattern
|
|
17
|
-
#
|
|
24
|
+
# NamedNodeShape — uri required, encoding pattern, props allowed,
|
|
25
|
+
# edges and styles well-formed
|
|
26
|
+
# AnonymousNodeShape — role required, props forbidden,
|
|
27
|
+
# edges and styles well-formed
|
|
18
28
|
# EdgeShape — edgeTarget XOR edgeSwitch
|
|
19
|
-
# RelationShape — cardinality pattern, optional slotName
|
|
29
|
+
# RelationShape — cardinality pattern, optional slotName,
|
|
30
|
+
# optional traversal projection (field required)
|
|
20
31
|
# SwitchShape — discriminator enum, minimum cases
|
|
21
32
|
# SwitchCaseShape — case node required
|
|
22
|
-
# StyleShape — reified key-value tuple (one key, one value
|
|
33
|
+
# StyleShape — reified key-value tuple (one key, one value,
|
|
34
|
+
# optional closed-vocabulary interaction state);
|
|
35
|
+
# targeted by PREDICATE, since style tuples carry
|
|
36
|
+
# no rdf:type — see the shape for why
|
|
37
|
+
# ProjectionShape — at least one of projectionType/projectionField
|
|
38
|
+
# PropShape — reified name-value tuple (one name, one value)
|
|
23
39
|
# ═══════════════════════════════════════════════════════════════
|
|
24
40
|
|
|
25
41
|
# ───────────────────────────────────────────────────────────────
|
|
@@ -70,6 +86,36 @@ anatomy:NamedNodeShape a sh:NodeShape ;
|
|
|
70
86
|
sh:path anatomy:role ;
|
|
71
87
|
sh:maxCount 0 ;
|
|
72
88
|
sh:message "NamedNode must not have a role (use AnonymousNode instead)." ;
|
|
89
|
+
] ;
|
|
90
|
+
|
|
91
|
+
sh:property [
|
|
92
|
+
sh:path anatomy:hasProjection ;
|
|
93
|
+
sh:maxCount 1 ;
|
|
94
|
+
sh:class anatomy:Projection ;
|
|
95
|
+
sh:message "NamedNode admits at most one projection." ;
|
|
96
|
+
] ;
|
|
97
|
+
|
|
98
|
+
sh:property [
|
|
99
|
+
sh:path anatomy:hasProp ;
|
|
100
|
+
sh:class anatomy:Prop ;
|
|
101
|
+
sh:message "hasProp must point at a Prop." ;
|
|
102
|
+
] ;
|
|
103
|
+
|
|
104
|
+
sh:property [
|
|
105
|
+
sh:path anatomy:hasEdge ;
|
|
106
|
+
sh:class anatomy:Edge ;
|
|
107
|
+
sh:message "hasEdge must point at an Edge." ;
|
|
108
|
+
] ;
|
|
109
|
+
|
|
110
|
+
sh:property [
|
|
111
|
+
sh:path anatomy:hasStyle ;
|
|
112
|
+
# Written as a negation rather than as sh:nodeKind
|
|
113
|
+
# sh:BlankNodeOrIRI, which is the same constraint: sem 0.1.0-alpha.2
|
|
114
|
+
# reports every blank-node style tuple as a violation of the nodeKind
|
|
115
|
+
# form, while rdf-validate-shacl accepts them. The negation is what
|
|
116
|
+
# the message says anyway, and both engines agree on it.
|
|
117
|
+
sh:not [ sh:nodeKind sh:Literal ] ;
|
|
118
|
+
sh:message "hasStyle must point at a style tuple, not a literal." ;
|
|
73
119
|
] .
|
|
74
120
|
|
|
75
121
|
# ───────────────────────────────────────────────────────────────
|
|
@@ -94,6 +140,36 @@ anatomy:AnonymousNodeShape a sh:NodeShape ;
|
|
|
94
140
|
sh:path anatomy:uri ;
|
|
95
141
|
sh:maxCount 0 ;
|
|
96
142
|
sh:message "AnonymousNode must not have a uri (use NamedNode instead)." ;
|
|
143
|
+
] ;
|
|
144
|
+
|
|
145
|
+
sh:property [
|
|
146
|
+
sh:path anatomy:hasProjection ;
|
|
147
|
+
sh:maxCount 1 ;
|
|
148
|
+
sh:class anatomy:Projection ;
|
|
149
|
+
sh:message "AnonymousNode admits at most one projection." ;
|
|
150
|
+
] ;
|
|
151
|
+
|
|
152
|
+
sh:property [
|
|
153
|
+
sh:path anatomy:hasProp ;
|
|
154
|
+
sh:maxCount 0 ;
|
|
155
|
+
sh:message "Props belong to components: anonymous nodes have no prop surface to pin — use a NamedNode." ;
|
|
156
|
+
] ;
|
|
157
|
+
|
|
158
|
+
sh:property [
|
|
159
|
+
sh:path anatomy:hasEdge ;
|
|
160
|
+
sh:class anatomy:Edge ;
|
|
161
|
+
sh:message "hasEdge must point at an Edge." ;
|
|
162
|
+
] ;
|
|
163
|
+
|
|
164
|
+
sh:property [
|
|
165
|
+
sh:path anatomy:hasStyle ;
|
|
166
|
+
# Written as a negation rather than as sh:nodeKind
|
|
167
|
+
# sh:BlankNodeOrIRI, which is the same constraint: sem 0.1.0-alpha.2
|
|
168
|
+
# reports every blank-node style tuple as a violation of the nodeKind
|
|
169
|
+
# form, while rdf-validate-shacl accepts them. The negation is what
|
|
170
|
+
# the message says anyway, and both engines agree on it.
|
|
171
|
+
sh:not [ sh:nodeKind sh:Literal ] ;
|
|
172
|
+
sh:message "hasStyle must point at a style tuple, not a literal." ;
|
|
97
173
|
] .
|
|
98
174
|
|
|
99
175
|
# ───────────────────────────────────────────────────────────────
|
|
@@ -161,6 +237,28 @@ anatomy:RelationShape a sh:NodeShape ;
|
|
|
161
237
|
sh:path anatomy:slotName ;
|
|
162
238
|
sh:maxCount 1 ;
|
|
163
239
|
sh:datatype xsd:string ;
|
|
240
|
+
] ;
|
|
241
|
+
|
|
242
|
+
# A relation projection is a traversal: the field is mandatory.
|
|
243
|
+
# Type narrowing belongs on the child node, never on the relation.
|
|
244
|
+
sh:property [
|
|
245
|
+
sh:path anatomy:hasProjection ;
|
|
246
|
+
sh:maxCount 1 ;
|
|
247
|
+
sh:class anatomy:Projection ;
|
|
248
|
+
sh:node [
|
|
249
|
+
a sh:NodeShape ;
|
|
250
|
+
sh:property [
|
|
251
|
+
sh:path anatomy:projectionField ;
|
|
252
|
+
sh:minCount 1 ;
|
|
253
|
+
sh:message "Relation projections must name the traversal field." ;
|
|
254
|
+
] ;
|
|
255
|
+
sh:property [
|
|
256
|
+
sh:path anatomy:projectionType ;
|
|
257
|
+
sh:maxCount 0 ;
|
|
258
|
+
sh:message "Type narrowing lives on the child node, not the relation." ;
|
|
259
|
+
] ;
|
|
260
|
+
] ;
|
|
261
|
+
sh:message "Relation admits at most one projection, and it must be a traversal (projectionField, no projectionType)." ;
|
|
164
262
|
] .
|
|
165
263
|
|
|
166
264
|
# ───────────────────────────────────────────────────────────────
|
|
@@ -209,24 +307,511 @@ anatomy:SwitchCaseShape a sh:NodeShape ;
|
|
|
209
307
|
# STYLE
|
|
210
308
|
# ───────────────────────────────────────────────────────────────
|
|
211
309
|
|
|
310
|
+
# Targeted by PREDICATE as well as by class, and the predicate target is the
|
|
311
|
+
# one that does the work. Prop and Projection tuples carry an explicit
|
|
312
|
+
# rdf:type (":hasProp [ a :Prop ; … ]"), so sh:targetClass reaches them;
|
|
313
|
+
# style tuples do not (":hasStyle [ :styleKey … ; :styleValue … ]"), so a
|
|
314
|
+
# class target alone matched NOTHING the transform emits and every
|
|
315
|
+
# constraint below was inert — the CTI key pattern and the styleState
|
|
316
|
+
# vocabulary included. sh:targetObjectsOf reaches them where they are.
|
|
317
|
+
#
|
|
318
|
+
# The alternative is to emit "a :Style" from the transform and rewrite the
|
|
319
|
+
# golden pairs. That is the more uniform data model and worth doing on its
|
|
320
|
+
# own terms; this shape is correct either way, since both targets stay.
|
|
212
321
|
anatomy:StyleShape a sh:NodeShape ;
|
|
213
322
|
sh:targetClass anatomy:Style ;
|
|
323
|
+
sh:targetObjectsOf anatomy:hasStyle ;
|
|
214
324
|
rdfs:label "Style Shape" ;
|
|
215
325
|
skos:definition "Reified key-value tuple: exactly one key and one value." ;
|
|
216
326
|
|
|
327
|
+
# The key vocabulary is CLOSED, as styleState already is: one
|
|
328
|
+
# anatomy:StyleKey individual per canonical key in registry.ttl, whose
|
|
329
|
+
# roster is style-keys.yaml — measured over the reference stylesheets,
|
|
330
|
+
# with its provenance stated there and in registry.ttl. The sh:in below
|
|
331
|
+
# is PROJECTED from that roster by `bun run generate:shapes` and diffed
|
|
332
|
+
# in CI — never hand-edited.
|
|
333
|
+
#
|
|
334
|
+
# The pattern is the Path production of §4.1, not the old all-lowercase
|
|
335
|
+
# CTI one: a Key and a Symbol are one shape and the registry tells them
|
|
336
|
+
# apart, so a key may carry a camelCase segment
|
|
337
|
+
# (typography.lineHeight) exactly as a symbol may (color.focusRing).
|
|
217
338
|
sh:property [
|
|
218
339
|
sh:path anatomy:styleKey ;
|
|
219
340
|
sh:minCount 1 ;
|
|
220
341
|
sh:maxCount 1 ;
|
|
221
342
|
sh:datatype xsd:string ;
|
|
222
|
-
sh:pattern "^[a-z]
|
|
223
|
-
sh:message "Style key must
|
|
343
|
+
sh:pattern "^[a-z]+(\\.[A-Za-z0-9]+)+$" ;
|
|
344
|
+
sh:message "Style key must be a dotted path: a lowercase namespace then one or more segments." ;
|
|
345
|
+
# BEGIN GENERATED styleKey sh:in — bun run generate:shapes
|
|
346
|
+
sh:in (
|
|
347
|
+
"appearance.background"
|
|
348
|
+
"appearance.background.image"
|
|
349
|
+
"appearance.background.position"
|
|
350
|
+
"appearance.background.repeat"
|
|
351
|
+
"appearance.background.size"
|
|
352
|
+
"appearance.border.block.start.color"
|
|
353
|
+
"appearance.border.bottom.color"
|
|
354
|
+
"appearance.border.color"
|
|
355
|
+
"appearance.border.inline.end.color"
|
|
356
|
+
"appearance.border.style"
|
|
357
|
+
"appearance.border.top.width"
|
|
358
|
+
"appearance.border.width"
|
|
359
|
+
"appearance.native"
|
|
360
|
+
"appearance.opacity"
|
|
361
|
+
"appearance.outline.color"
|
|
362
|
+
"appearance.outline.offset"
|
|
363
|
+
"appearance.outline.style"
|
|
364
|
+
"appearance.outline.width"
|
|
365
|
+
"appearance.radius"
|
|
366
|
+
"appearance.visibility"
|
|
367
|
+
"interaction.cursor"
|
|
368
|
+
"interaction.pointerEvents"
|
|
369
|
+
"interaction.resize"
|
|
370
|
+
"interaction.select"
|
|
371
|
+
"layout.align"
|
|
372
|
+
"layout.alignContent"
|
|
373
|
+
"layout.alignSelf"
|
|
374
|
+
"layout.boxSizing"
|
|
375
|
+
"layout.container"
|
|
376
|
+
"layout.direction"
|
|
377
|
+
"layout.flex.basis"
|
|
378
|
+
"layout.flex.grow"
|
|
379
|
+
"layout.flex.shrink"
|
|
380
|
+
"layout.grid.area"
|
|
381
|
+
"layout.grid.autoFlow"
|
|
382
|
+
"layout.grid.autoRows"
|
|
383
|
+
"layout.grid.column"
|
|
384
|
+
"layout.grid.columns"
|
|
385
|
+
"layout.grid.row"
|
|
386
|
+
"layout.grid.rows"
|
|
387
|
+
"layout.justify"
|
|
388
|
+
"layout.listStyle"
|
|
389
|
+
"layout.objectFit"
|
|
390
|
+
"layout.offset.block.end"
|
|
391
|
+
"layout.offset.block.start"
|
|
392
|
+
"layout.offset.bottom"
|
|
393
|
+
"layout.offset.inline.start"
|
|
394
|
+
"layout.offset.left"
|
|
395
|
+
"layout.offset.right"
|
|
396
|
+
"layout.offset.top"
|
|
397
|
+
"layout.order"
|
|
398
|
+
"layout.overflow"
|
|
399
|
+
"layout.overflow.block"
|
|
400
|
+
"layout.overflow.inline"
|
|
401
|
+
"layout.overscroll"
|
|
402
|
+
"layout.position"
|
|
403
|
+
"layout.stack"
|
|
404
|
+
"layout.table.collapse"
|
|
405
|
+
"layout.table.layout"
|
|
406
|
+
"layout.table.spacing"
|
|
407
|
+
"layout.type"
|
|
408
|
+
"layout.verticalAlign"
|
|
409
|
+
"layout.wrap"
|
|
410
|
+
"motion.duration"
|
|
411
|
+
"motion.easing"
|
|
412
|
+
"motion.property"
|
|
413
|
+
"size.block"
|
|
414
|
+
"size.height"
|
|
415
|
+
"size.inline"
|
|
416
|
+
"size.max.block"
|
|
417
|
+
"size.max.height"
|
|
418
|
+
"size.max.width"
|
|
419
|
+
"size.min.block"
|
|
420
|
+
"size.min.height"
|
|
421
|
+
"size.min.width"
|
|
422
|
+
"size.width"
|
|
423
|
+
"spacing.external.block.end"
|
|
424
|
+
"spacing.external.block.start"
|
|
425
|
+
"spacing.external.bottom"
|
|
426
|
+
"spacing.external.inline.end"
|
|
427
|
+
"spacing.external.inline.start"
|
|
428
|
+
"spacing.external.left"
|
|
429
|
+
"spacing.external.right"
|
|
430
|
+
"spacing.external.top"
|
|
431
|
+
"spacing.gap"
|
|
432
|
+
"spacing.gap.block"
|
|
433
|
+
"spacing.gap.inline"
|
|
434
|
+
"spacing.internal.block.end"
|
|
435
|
+
"spacing.internal.block.start"
|
|
436
|
+
"spacing.internal.bottom"
|
|
437
|
+
"spacing.internal.inline.end"
|
|
438
|
+
"spacing.internal.inline.start"
|
|
439
|
+
"spacing.internal.left"
|
|
440
|
+
"spacing.internal.top"
|
|
441
|
+
"typography.align"
|
|
442
|
+
"typography.color"
|
|
443
|
+
"typography.decoration"
|
|
444
|
+
"typography.decoration.offset"
|
|
445
|
+
"typography.decoration.thickness"
|
|
446
|
+
"typography.direction"
|
|
447
|
+
"typography.font"
|
|
448
|
+
"typography.fontFamily"
|
|
449
|
+
"typography.letterSpacing"
|
|
450
|
+
"typography.lineHeight"
|
|
451
|
+
"typography.overflow"
|
|
452
|
+
"typography.size"
|
|
453
|
+
"typography.variant.caps"
|
|
454
|
+
"typography.variant.numeric"
|
|
455
|
+
"typography.weight"
|
|
456
|
+
"typography.whiteSpace"
|
|
457
|
+
"typography.wrap"
|
|
458
|
+
) ;
|
|
459
|
+
# END GENERATED styleKey sh:in
|
|
224
460
|
] ;
|
|
225
461
|
|
|
462
|
+
# The authored spelling, verbatim, as the evidence of what the reference
|
|
463
|
+
# says: a scalar as written, a sequence in its flow form. The symbols are
|
|
464
|
+
# NOT re-derived from it — anatomy:consumes carries them — so the three
|
|
465
|
+
# constraints here are only that the retired notation cannot reach the
|
|
466
|
+
# graph through it.
|
|
226
467
|
sh:property [
|
|
227
468
|
sh:path anatomy:styleValue ;
|
|
228
469
|
sh:minCount 1 ;
|
|
229
470
|
sh:maxCount 1 ;
|
|
230
471
|
sh:datatype xsd:string ;
|
|
231
472
|
sh:message "Style requires exactly one value." ;
|
|
473
|
+
] ;
|
|
474
|
+
|
|
475
|
+
sh:property [
|
|
476
|
+
sh:path anatomy:styleValue ;
|
|
477
|
+
# The slash-delimited path is retired (AT.01). Anchored on the whole
|
|
478
|
+
# value, so a literal that merely holds a slash between spaces
|
|
479
|
+
# ("1 / -1", a grid line the reference writes 42 times) is untouched.
|
|
480
|
+
sh:not [ sh:pattern "^[A-Za-z0-9-]+(/[A-Za-z0-9-]+)+\\??$" ] ;
|
|
481
|
+
sh:message "The slash-delimited token path is retired: write the symbol's own dotted name." ;
|
|
482
|
+
] ;
|
|
483
|
+
|
|
484
|
+
sh:property [
|
|
485
|
+
sh:path anatomy:styleValue ;
|
|
486
|
+
# The trailing "?" marker is retired (AT.03). An element that
|
|
487
|
+
# resolves nowhere is a register row and a comment, not a sigil.
|
|
488
|
+
sh:not [ sh:pattern "\\?$" ] ;
|
|
489
|
+
sh:message "The trailing '?' optional marker is retired: an unresolved element is a register row and a comment." ;
|
|
490
|
+
] ;
|
|
491
|
+
|
|
492
|
+
sh:property [
|
|
493
|
+
sh:path anatomy:styleValue ;
|
|
494
|
+
sh:not [ sh:pattern "(^|[./])\\$?root([./]|$)" ] ;
|
|
495
|
+
sh:message "'root' and '$root' are not value segments." ;
|
|
496
|
+
] ;
|
|
497
|
+
|
|
498
|
+
# THE SEAM. An rdf:List of dt:TokenSymbol IRIs in fallback order, whose
|
|
499
|
+
# head is the primary symbol; the authored spelling stays in styleValue as
|
|
500
|
+
# evidence. Whether a key carries one is the registry's business, and the
|
|
501
|
+
# generated sh:or below is where that is said.
|
|
502
|
+
sh:property [
|
|
503
|
+
sh:path anatomy:consumes ;
|
|
504
|
+
sh:maxCount 1 ;
|
|
505
|
+
sh:node anatomy:SymbolListShape ;
|
|
506
|
+
sh:message "consumes must be one rdf:List of dt: token symbols, in fallback order." ;
|
|
507
|
+
] ;
|
|
508
|
+
|
|
509
|
+
# Closed v1 vocabulary, registry-governed. Additions go through the
|
|
510
|
+
# registry (checked, visited, dragged, pending, error, read-only are
|
|
511
|
+
# candidates), never through loosening this list ad hoc. There is no
|
|
512
|
+
# "default" state: an absent styleState IS the default.
|
|
513
|
+
#
|
|
514
|
+
# A state value that differs from its base state's is a LINT, not a
|
|
515
|
+
# constraint (AT.11): the reference does it — Button's :disabled reads a
|
|
516
|
+
# different symbol — so it is reported with its ranks and never rejected,
|
|
517
|
+
# and the report lives in design-system's validator, not here.
|
|
518
|
+
sh:property [
|
|
519
|
+
sh:path anatomy:styleState ;
|
|
520
|
+
sh:maxCount 1 ;
|
|
521
|
+
sh:datatype xsd:string ;
|
|
522
|
+
sh:in ( "hover" "active" "focus" "disabled" "selected" ) ;
|
|
523
|
+
sh:message "styleState must be one of: hover, active, focus, disabled, selected (absent = default state)." ;
|
|
524
|
+
] ;
|
|
525
|
+
|
|
526
|
+
# BEGIN GENERATED valueKind sh:or — bun run generate:shapes
|
|
527
|
+
sh:or (
|
|
528
|
+
[ # a primitive key: a literal, and nothing consumed
|
|
529
|
+
sh:property [
|
|
530
|
+
sh:path anatomy:styleKey ;
|
|
531
|
+
sh:in (
|
|
532
|
+
"appearance.background.image"
|
|
533
|
+
"appearance.background.position"
|
|
534
|
+
"appearance.background.repeat"
|
|
535
|
+
"appearance.background.size"
|
|
536
|
+
"appearance.border.style"
|
|
537
|
+
"appearance.native"
|
|
538
|
+
"appearance.opacity"
|
|
539
|
+
"appearance.outline.style"
|
|
540
|
+
"appearance.visibility"
|
|
541
|
+
"interaction.cursor"
|
|
542
|
+
"interaction.pointerEvents"
|
|
543
|
+
"interaction.resize"
|
|
544
|
+
"interaction.select"
|
|
545
|
+
"layout.align"
|
|
546
|
+
"layout.alignContent"
|
|
547
|
+
"layout.alignSelf"
|
|
548
|
+
"layout.boxSizing"
|
|
549
|
+
"layout.container"
|
|
550
|
+
"layout.direction"
|
|
551
|
+
"layout.flex.grow"
|
|
552
|
+
"layout.flex.shrink"
|
|
553
|
+
"layout.grid.area"
|
|
554
|
+
"layout.grid.autoFlow"
|
|
555
|
+
"layout.grid.autoRows"
|
|
556
|
+
"layout.grid.column"
|
|
557
|
+
"layout.grid.columns"
|
|
558
|
+
"layout.grid.row"
|
|
559
|
+
"layout.grid.rows"
|
|
560
|
+
"layout.justify"
|
|
561
|
+
"layout.listStyle"
|
|
562
|
+
"layout.objectFit"
|
|
563
|
+
"layout.order"
|
|
564
|
+
"layout.overflow"
|
|
565
|
+
"layout.overflow.block"
|
|
566
|
+
"layout.overflow.inline"
|
|
567
|
+
"layout.overscroll"
|
|
568
|
+
"layout.position"
|
|
569
|
+
"layout.stack"
|
|
570
|
+
"layout.table.collapse"
|
|
571
|
+
"layout.table.layout"
|
|
572
|
+
"layout.table.spacing"
|
|
573
|
+
"layout.type"
|
|
574
|
+
"layout.verticalAlign"
|
|
575
|
+
"layout.wrap"
|
|
576
|
+
"motion.property"
|
|
577
|
+
"typography.align"
|
|
578
|
+
"typography.decoration"
|
|
579
|
+
"typography.direction"
|
|
580
|
+
"typography.overflow"
|
|
581
|
+
"typography.variant.caps"
|
|
582
|
+
"typography.variant.numeric"
|
|
583
|
+
"typography.whiteSpace"
|
|
584
|
+
"typography.wrap"
|
|
585
|
+
) ;
|
|
586
|
+
] ;
|
|
587
|
+
sh:property [ sh:path anatomy:consumes ; sh:maxCount 0 ] ;
|
|
588
|
+
sh:property [
|
|
589
|
+
sh:path anatomy:styleValue ;
|
|
590
|
+
sh:not [ sh:pattern "^[a-z]+(\\.[A-Za-z0-9]+)+$" ] ;
|
|
591
|
+
] ;
|
|
592
|
+
]
|
|
593
|
+
[ # a token key: the symbols are consumed, always
|
|
594
|
+
sh:property [
|
|
595
|
+
sh:path anatomy:styleKey ;
|
|
596
|
+
sh:in (
|
|
597
|
+
"appearance.border.block.start.color"
|
|
598
|
+
"appearance.border.bottom.color"
|
|
599
|
+
"appearance.border.inline.end.color"
|
|
600
|
+
"layout.offset.block.end"
|
|
601
|
+
"layout.offset.block.start"
|
|
602
|
+
"layout.offset.inline.start"
|
|
603
|
+
"size.inline"
|
|
604
|
+
"size.max.block"
|
|
605
|
+
"size.min.block"
|
|
606
|
+
"size.min.height"
|
|
607
|
+
"spacing.gap.block"
|
|
608
|
+
"spacing.gap.inline"
|
|
609
|
+
"typography.decoration.offset"
|
|
610
|
+
) ;
|
|
611
|
+
] ;
|
|
612
|
+
sh:property [ sh:path anatomy:consumes ; sh:minCount 1 ] ;
|
|
613
|
+
]
|
|
614
|
+
[ # an either key, consuming symbols
|
|
615
|
+
sh:property [
|
|
616
|
+
sh:path anatomy:styleKey ;
|
|
617
|
+
sh:in (
|
|
618
|
+
"appearance.background"
|
|
619
|
+
"appearance.border.color"
|
|
620
|
+
"appearance.border.top.width"
|
|
621
|
+
"appearance.border.width"
|
|
622
|
+
"appearance.outline.color"
|
|
623
|
+
"appearance.outline.offset"
|
|
624
|
+
"appearance.outline.width"
|
|
625
|
+
"appearance.radius"
|
|
626
|
+
"layout.flex.basis"
|
|
627
|
+
"layout.offset.bottom"
|
|
628
|
+
"layout.offset.left"
|
|
629
|
+
"layout.offset.right"
|
|
630
|
+
"layout.offset.top"
|
|
631
|
+
"motion.duration"
|
|
632
|
+
"motion.easing"
|
|
633
|
+
"size.block"
|
|
634
|
+
"size.height"
|
|
635
|
+
"size.max.height"
|
|
636
|
+
"size.max.width"
|
|
637
|
+
"size.min.width"
|
|
638
|
+
"size.width"
|
|
639
|
+
"spacing.external.block.end"
|
|
640
|
+
"spacing.external.block.start"
|
|
641
|
+
"spacing.external.bottom"
|
|
642
|
+
"spacing.external.inline.end"
|
|
643
|
+
"spacing.external.inline.start"
|
|
644
|
+
"spacing.external.left"
|
|
645
|
+
"spacing.external.right"
|
|
646
|
+
"spacing.external.top"
|
|
647
|
+
"spacing.gap"
|
|
648
|
+
"spacing.internal.block.end"
|
|
649
|
+
"spacing.internal.block.start"
|
|
650
|
+
"spacing.internal.bottom"
|
|
651
|
+
"spacing.internal.inline.end"
|
|
652
|
+
"spacing.internal.inline.start"
|
|
653
|
+
"spacing.internal.left"
|
|
654
|
+
"spacing.internal.top"
|
|
655
|
+
"typography.color"
|
|
656
|
+
"typography.decoration.thickness"
|
|
657
|
+
"typography.font"
|
|
658
|
+
"typography.fontFamily"
|
|
659
|
+
"typography.letterSpacing"
|
|
660
|
+
"typography.lineHeight"
|
|
661
|
+
"typography.size"
|
|
662
|
+
"typography.weight"
|
|
663
|
+
) ;
|
|
664
|
+
] ;
|
|
665
|
+
sh:property [ sh:path anatomy:consumes ; sh:minCount 1 ] ;
|
|
666
|
+
]
|
|
667
|
+
[ # an either key, carrying a primitive
|
|
668
|
+
sh:property [
|
|
669
|
+
sh:path anatomy:styleKey ;
|
|
670
|
+
sh:in (
|
|
671
|
+
"appearance.background"
|
|
672
|
+
"appearance.border.color"
|
|
673
|
+
"appearance.border.top.width"
|
|
674
|
+
"appearance.border.width"
|
|
675
|
+
"appearance.outline.color"
|
|
676
|
+
"appearance.outline.offset"
|
|
677
|
+
"appearance.outline.width"
|
|
678
|
+
"appearance.radius"
|
|
679
|
+
"layout.flex.basis"
|
|
680
|
+
"layout.offset.bottom"
|
|
681
|
+
"layout.offset.left"
|
|
682
|
+
"layout.offset.right"
|
|
683
|
+
"layout.offset.top"
|
|
684
|
+
"motion.duration"
|
|
685
|
+
"motion.easing"
|
|
686
|
+
"size.block"
|
|
687
|
+
"size.height"
|
|
688
|
+
"size.max.height"
|
|
689
|
+
"size.max.width"
|
|
690
|
+
"size.min.width"
|
|
691
|
+
"size.width"
|
|
692
|
+
"spacing.external.block.end"
|
|
693
|
+
"spacing.external.block.start"
|
|
694
|
+
"spacing.external.bottom"
|
|
695
|
+
"spacing.external.inline.end"
|
|
696
|
+
"spacing.external.inline.start"
|
|
697
|
+
"spacing.external.left"
|
|
698
|
+
"spacing.external.right"
|
|
699
|
+
"spacing.external.top"
|
|
700
|
+
"spacing.gap"
|
|
701
|
+
"spacing.internal.block.end"
|
|
702
|
+
"spacing.internal.block.start"
|
|
703
|
+
"spacing.internal.bottom"
|
|
704
|
+
"spacing.internal.inline.end"
|
|
705
|
+
"spacing.internal.inline.start"
|
|
706
|
+
"spacing.internal.left"
|
|
707
|
+
"spacing.internal.top"
|
|
708
|
+
"typography.color"
|
|
709
|
+
"typography.decoration.thickness"
|
|
710
|
+
"typography.font"
|
|
711
|
+
"typography.fontFamily"
|
|
712
|
+
"typography.letterSpacing"
|
|
713
|
+
"typography.lineHeight"
|
|
714
|
+
"typography.size"
|
|
715
|
+
"typography.weight"
|
|
716
|
+
) ;
|
|
717
|
+
] ;
|
|
718
|
+
sh:property [ sh:path anatomy:consumes ; sh:maxCount 0 ] ;
|
|
719
|
+
sh:property [
|
|
720
|
+
sh:path anatomy:styleValue ;
|
|
721
|
+
sh:not [ sh:pattern "^[a-z]+(\\.[A-Za-z0-9]+)+$" ] ;
|
|
722
|
+
] ;
|
|
723
|
+
]
|
|
724
|
+
) ;
|
|
725
|
+
sh:message "A style tuple must match its key's valueKind: a token key consumes symbols, a primitive key carries a literal and consumes none, an either key does one or the other." ;
|
|
726
|
+
# END GENERATED valueKind sh:or
|
|
727
|
+
rdfs:comment "The valueKind disjunction above is generated from registry.ttl." .
|
|
728
|
+
|
|
729
|
+
# ───────────────────────────────────────────────────────────────
|
|
730
|
+
# SYMBOL LIST
|
|
731
|
+
# ───────────────────────────────────────────────────────────────
|
|
732
|
+
|
|
733
|
+
anatomy:SymbolListShape a sh:NodeShape ;
|
|
734
|
+
rdfs:label "Symbol List Shape" ;
|
|
735
|
+
skos:definition """The shape of anatomy:consumes: every member of the
|
|
736
|
+
rdf:List is an IRI in the token graph's namespace whose local name is a
|
|
737
|
+
dotted symbol. The list is the fallback order, so its head is the primary
|
|
738
|
+
symbol; a member that is a literal, a blank node or an IRI outside dt: is
|
|
739
|
+
a violation. Whether a member RESOLVES — whether the token graph declares
|
|
740
|
+
that symbol — is not asked here: a name no stratum declares is kept as
|
|
741
|
+
consumed with a register row (AT.09), and the check belongs to the
|
|
742
|
+
consumer holding the strata.""" ;
|
|
743
|
+
|
|
744
|
+
sh:property [
|
|
745
|
+
sh:path ( [ sh:zeroOrMorePath rdf:rest ] rdf:first ) ;
|
|
746
|
+
sh:minCount 1 ;
|
|
747
|
+
sh:nodeKind sh:IRI ;
|
|
748
|
+
sh:pattern "^https://dt\\.canonical\\.com/[a-z]+(\\.[A-Za-z0-9]+)+$" ;
|
|
749
|
+
sh:message "Every consumed element must be a dt: token symbol IRI with a dotted local name." ;
|
|
750
|
+
] .
|
|
751
|
+
|
|
752
|
+
# ───────────────────────────────────────────────────────────────
|
|
753
|
+
# PROJECTION
|
|
754
|
+
# ───────────────────────────────────────────────────────────────
|
|
755
|
+
|
|
756
|
+
anatomy:ProjectionShape a sh:NodeShape ;
|
|
757
|
+
sh:targetClass anatomy:Projection ;
|
|
758
|
+
rdfs:label "Projection Shape" ;
|
|
759
|
+
skos:definition "Fragment-style graph binding: a type condition, a field path, or both — never neither." ;
|
|
760
|
+
|
|
761
|
+
sh:property [
|
|
762
|
+
sh:path anatomy:projectionType ;
|
|
763
|
+
sh:maxCount 1 ;
|
|
764
|
+
sh:datatype xsd:string ;
|
|
765
|
+
sh:pattern "^[A-Z][A-Za-z0-9_]*$" ;
|
|
766
|
+
sh:message "Projection type must be a GraphQL type name (PascalCase)." ;
|
|
767
|
+
] ;
|
|
768
|
+
|
|
769
|
+
sh:property [
|
|
770
|
+
sh:path anatomy:projectionField ;
|
|
771
|
+
sh:maxCount 1 ;
|
|
772
|
+
sh:datatype xsd:string ;
|
|
773
|
+
sh:pattern "^[_A-Za-z][_A-Za-z0-9]*(\\.[_A-Za-z][_A-Za-z0-9]*)*$" ;
|
|
774
|
+
sh:message "Projection field must be a dot-delimited path of GraphQL field names." ;
|
|
775
|
+
] ;
|
|
776
|
+
|
|
777
|
+
sh:or (
|
|
778
|
+
[
|
|
779
|
+
sh:property [
|
|
780
|
+
sh:path anatomy:projectionType ;
|
|
781
|
+
sh:minCount 1 ;
|
|
782
|
+
] ;
|
|
783
|
+
]
|
|
784
|
+
[
|
|
785
|
+
sh:property [
|
|
786
|
+
sh:path anatomy:projectionField ;
|
|
787
|
+
sh:minCount 1 ;
|
|
788
|
+
] ;
|
|
789
|
+
]
|
|
790
|
+
) ;
|
|
791
|
+
sh:message "Projection requires at least one of projectionType or projectionField." .
|
|
792
|
+
|
|
793
|
+
# ───────────────────────────────────────────────────────────────
|
|
794
|
+
# PROP
|
|
795
|
+
# ───────────────────────────────────────────────────────────────
|
|
796
|
+
|
|
797
|
+
anatomy:PropShape a sh:NodeShape ;
|
|
798
|
+
sh:targetClass anatomy:Prop ;
|
|
799
|
+
rdfs:label "Prop Shape" ;
|
|
800
|
+
skos:definition "Reified pinned-prop tuple: exactly one name and one value. Whether the prop exists on the referenced component is validated by consumers holding the design system graph, not here." ;
|
|
801
|
+
|
|
802
|
+
sh:property [
|
|
803
|
+
sh:path anatomy:propName ;
|
|
804
|
+
sh:minCount 1 ;
|
|
805
|
+
sh:maxCount 1 ;
|
|
806
|
+
sh:datatype xsd:string ;
|
|
807
|
+
sh:pattern "^[a-z][a-zA-Z0-9]*$" ;
|
|
808
|
+
sh:message "Prop name must be a camelCase identifier as defined on the component." ;
|
|
809
|
+
] ;
|
|
810
|
+
|
|
811
|
+
sh:property [
|
|
812
|
+
sh:path anatomy:propValue ;
|
|
813
|
+
sh:minCount 1 ;
|
|
814
|
+
sh:maxCount 1 ;
|
|
815
|
+
sh:datatype xsd:string ;
|
|
816
|
+
sh:message "Prop requires exactly one value." ;
|
|
232
817
|
] .
|