@canonical/anatomy-dsl 0.3.0 → 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 +63 -28
- package/definitions/lift.fixture.json +216 -0
- package/definitions/ontology.ttl +110 -11
- package/definitions/registry.ttl +659 -0
- package/definitions/shapes.ttl +461 -7
- package/definitions/style-keys.yaml +391 -0
- package/package.json +14 -4
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,15 +21,19 @@
|
|
|
13
21
|
#
|
|
14
22
|
# Shapes:
|
|
15
23
|
# SpecificationShape — root document
|
|
16
|
-
# NamedNodeShape — uri required, encoding pattern, props allowed
|
|
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
29
|
# RelationShape — cardinality pattern, optional slotName,
|
|
20
30
|
# optional traversal projection (field required)
|
|
21
31
|
# SwitchShape — discriminator enum, minimum cases
|
|
22
32
|
# SwitchCaseShape — case node required
|
|
23
33
|
# StyleShape — reified key-value tuple (one key, one value,
|
|
24
|
-
# optional closed-vocabulary interaction state)
|
|
34
|
+
# optional closed-vocabulary interaction state);
|
|
35
|
+
# targeted by PREDICATE, since style tuples carry
|
|
36
|
+
# no rdf:type — see the shape for why
|
|
25
37
|
# ProjectionShape — at least one of projectionType/projectionField
|
|
26
38
|
# PropShape — reified name-value tuple (one name, one value)
|
|
27
39
|
# ═══════════════════════════════════════════════════════════════
|
|
@@ -87,6 +99,23 @@ anatomy:NamedNodeShape a sh:NodeShape ;
|
|
|
87
99
|
sh:path anatomy:hasProp ;
|
|
88
100
|
sh:class anatomy:Prop ;
|
|
89
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." ;
|
|
90
119
|
] .
|
|
91
120
|
|
|
92
121
|
# ───────────────────────────────────────────────────────────────
|
|
@@ -124,6 +153,23 @@ anatomy:AnonymousNodeShape a sh:NodeShape ;
|
|
|
124
153
|
sh:path anatomy:hasProp ;
|
|
125
154
|
sh:maxCount 0 ;
|
|
126
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." ;
|
|
127
173
|
] .
|
|
128
174
|
|
|
129
175
|
# ───────────────────────────────────────────────────────────────
|
|
@@ -261,20 +307,163 @@ anatomy:SwitchCaseShape a sh:NodeShape ;
|
|
|
261
307
|
# STYLE
|
|
262
308
|
# ───────────────────────────────────────────────────────────────
|
|
263
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.
|
|
264
321
|
anatomy:StyleShape a sh:NodeShape ;
|
|
265
322
|
sh:targetClass anatomy:Style ;
|
|
323
|
+
sh:targetObjectsOf anatomy:hasStyle ;
|
|
266
324
|
rdfs:label "Style Shape" ;
|
|
267
325
|
skos:definition "Reified key-value tuple: exactly one key and one value." ;
|
|
268
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).
|
|
269
338
|
sh:property [
|
|
270
339
|
sh:path anatomy:styleKey ;
|
|
271
340
|
sh:minCount 1 ;
|
|
272
341
|
sh:maxCount 1 ;
|
|
273
342
|
sh:datatype xsd:string ;
|
|
274
|
-
sh:pattern "^[a-z]
|
|
275
|
-
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
|
|
276
460
|
] ;
|
|
277
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.
|
|
278
467
|
sh:property [
|
|
279
468
|
sh:path anatomy:styleValue ;
|
|
280
469
|
sh:minCount 1 ;
|
|
@@ -283,16 +472,281 @@ anatomy:StyleShape a sh:NodeShape ;
|
|
|
283
472
|
sh:message "Style requires exactly one value." ;
|
|
284
473
|
] ;
|
|
285
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
|
+
|
|
286
509
|
# Closed v1 vocabulary, registry-governed. Additions go through the
|
|
287
510
|
# registry (checked, visited, dragged, pending, error, read-only are
|
|
288
511
|
# candidates), never through loosening this list ad hoc. There is no
|
|
289
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.
|
|
290
518
|
sh:property [
|
|
291
519
|
sh:path anatomy:styleState ;
|
|
292
520
|
sh:maxCount 1 ;
|
|
293
521
|
sh:datatype xsd:string ;
|
|
294
522
|
sh:in ( "hover" "active" "focus" "disabled" "selected" ) ;
|
|
295
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." ;
|
|
296
750
|
] .
|
|
297
751
|
|
|
298
752
|
# ───────────────────────────────────────────────────────────────
|