@canonical/pragma-cli 0.36.0 → 0.38.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 +3 -2
- package/bundled-skills/adoption-a1-styles/SKILL.md +24 -0
- package/bundled-skills/adoption-a2-components/SKILL.md +22 -6
- package/bundled-skills/anatomy-author/ANATOMY_DSL_SPEC.md +1397 -327
- package/bundled-skills/anatomy-author/SKILL.md +840 -137
- package/bundled-skills/design-auditor/SKILL.md +133 -9
- package/bundled-skills/implement-component/SKILL.md +192 -23
- package/bundled-skills/specify-component/SKILL.md +124 -12
- package/bundled-skills/specify-pattern/SKILL.md +47 -8
- package/dist/package.json +23 -20
- package/dist/pragma.conf.js +963 -40
- package/dist/pragma.conf.js.map +1 -1
- package/dist/src/capabilities/capabilities/catalog.js +14 -5
- package/dist/src/capabilities/capabilities/catalog.js.map +1 -1
- package/dist/src/capabilities/capabilities/hints.js +33 -5
- package/dist/src/capabilities/capabilities/hints.js.map +1 -1
- package/dist/src/capabilities/config/show.render.js +30 -2
- package/dist/src/capabilities/config/show.render.js.map +1 -1
- package/dist/src/capabilities/create/create.verb.js +2 -1
- package/dist/src/capabilities/create/create.verb.js.map +1 -1
- package/dist/src/capabilities/create/createSurface.generated.js +23 -1
- package/dist/src/capabilities/create/createSurface.generated.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/checkNodeVersion.js +11 -6
- package/dist/src/capabilities/doctor/checks/checkNodeVersion.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/harnessInventory.js +1 -1
- package/dist/src/capabilities/doctor/checks/harnessInventory.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/isSupportedNodeVersion.js +38 -0
- package/dist/src/capabilities/doctor/checks/isSupportedNodeVersion.js.map +1 -0
- package/dist/src/capabilities/doctor/checks/targetHealth.js +104 -14
- package/dist/src/capabilities/doctor/checks/targetHealth.js.map +1 -1
- package/dist/src/capabilities/graph/connect.render.js +101 -0
- package/dist/src/capabilities/graph/connect.render.js.map +1 -0
- package/dist/src/capabilities/graph/connect.types.js +21 -0
- package/dist/src/capabilities/graph/connect.types.js.map +1 -0
- package/dist/src/capabilities/graph/connect.verb.js +147 -0
- package/dist/src/capabilities/graph/connect.verb.js.map +1 -0
- package/dist/src/capabilities/graph/index.js +5 -3
- package/dist/src/capabilities/graph/index.js.map +1 -1
- package/dist/src/capabilities/graph/queryText.js +206 -0
- package/dist/src/capabilities/graph/queryText.js.map +1 -0
- package/dist/src/capabilities/graph/relationIndex.js +302 -0
- package/dist/src/capabilities/graph/relationIndex.js.map +1 -0
- package/dist/src/capabilities/graph/runConnect.js +456 -0
- package/dist/src/capabilities/graph/runConnect.js.map +1 -0
- package/dist/src/capabilities/graph/runQuery.js +21 -4
- package/dist/src/capabilities/graph/runQuery.js.map +1 -1
- package/dist/src/capabilities/setup/buildPlan.js +6 -2
- package/dist/src/capabilities/setup/buildPlan.js.map +1 -1
- package/dist/src/capabilities/setup/operations/index.js +7 -2
- package/dist/src/capabilities/setup/operations/index.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupCompletions.js +6 -2
- package/dist/src/capabilities/setup/operations/setupCompletions.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupConfig.js +4 -2
- package/dist/src/capabilities/setup/operations/setupConfig.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupGenerator.js +72 -14
- package/dist/src/capabilities/setup/operations/setupGenerator.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupLsp.js +372 -62
- package/dist/src/capabilities/setup/operations/setupLsp.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupMcp.js +150 -5
- package/dist/src/capabilities/setup/operations/setupMcp.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupSkills.js +4 -2
- package/dist/src/capabilities/setup/operations/setupSkills.js.map +1 -1
- package/dist/src/capabilities/setup/operations/writability.js +114 -0
- package/dist/src/capabilities/setup/operations/writability.js.map +1 -0
- package/dist/src/capabilities/setup/plan.js.map +1 -1
- package/dist/src/capabilities/setup/setup.verb.js +80 -31
- package/dist/src/capabilities/setup/setup.verb.js.map +1 -1
- package/dist/src/capabilities/setup/targets.js +124 -42
- package/dist/src/capabilities/setup/targets.js.map +1 -1
- package/dist/src/capabilities/shared/index.js +1 -1
- package/dist/src/capabilities/shared/index.js.map +1 -1
- package/dist/src/constants.js +7 -1
- package/dist/src/constants.js.map +1 -1
- package/dist/src/kernel/error/renderError.js +3 -2
- package/dist/src/kernel/error/renderError.js.map +1 -1
- package/dist/src/kernel/error/validOptions.js +41 -0
- package/dist/src/kernel/error/validOptions.js.map +1 -0
- package/dist/src/kernel/packs/compile.js +90 -6
- package/dist/src/kernel/packs/compile.js.map +1 -1
- package/dist/src/kernel/packs/cursor.js +135 -0
- package/dist/src/kernel/packs/cursor.js.map +1 -0
- package/dist/src/kernel/packs/graphql/buildLookupDocument.js +9 -2
- package/dist/src/kernel/packs/graphql/buildLookupDocument.js.map +1 -1
- package/dist/src/kernel/packs/paging.js +108 -0
- package/dist/src/kernel/packs/paging.js.map +1 -0
- package/dist/src/kernel/packs/renderPack.js +154 -5
- package/dist/src/kernel/packs/renderPack.js.map +1 -1
- package/dist/src/kernel/packs/resolveEntity.js +118 -19
- package/dist/src/kernel/packs/resolveEntity.js.map +1 -1
- package/dist/src/kernel/packs/runBodies.js +156 -18
- package/dist/src/kernel/packs/runBodies.js.map +1 -1
- package/dist/src/kernel/packs/schema.js +160 -12
- package/dist/src/kernel/packs/schema.js.map +1 -1
- package/dist/src/kernel/packs/sparql/authorQuery.js +227 -0
- package/dist/src/kernel/packs/sparql/authorQuery.js.map +1 -0
- package/dist/src/kernel/packs/sparql/buildListQuery.js +251 -0
- package/dist/src/kernel/packs/sparql/buildListQuery.js.map +1 -0
- package/dist/src/kernel/packs/sparql/buildLookupQuery.js +125 -22
- package/dist/src/kernel/packs/sparql/buildLookupQuery.js.map +1 -1
- package/dist/src/kernel/packs/sparql/filterValues.js +145 -0
- package/dist/src/kernel/packs/sparql/filterValues.js.map +1 -0
- package/dist/src/kernel/packs/sparql/index.js +24 -14
- package/dist/src/kernel/packs/sparql/index.js.map +1 -1
- package/dist/src/kernel/packs/sparql/runSelect.js +10 -4
- package/dist/src/kernel/packs/sparql/runSelect.js.map +1 -1
- package/dist/src/kernel/packs/sparql/searchTerm.js +25 -0
- package/dist/src/kernel/packs/sparql/searchTerm.js.map +1 -0
- package/dist/src/kernel/packs/storyRules.js +151 -0
- package/dist/src/kernel/packs/storyRules.js.map +1 -0
- package/dist/src/kernel/packs/tierScope.js +310 -0
- package/dist/src/kernel/packs/tierScope.js.map +1 -0
- package/dist/src/kernel/packs/types.js +80 -0
- package/dist/src/kernel/packs/types.js.map +1 -1
- package/dist/src/kernel/project/cli/buildProgram.js +10 -1
- package/dist/src/kernel/project/cli/buildProgram.js.map +1 -1
- package/dist/src/kernel/project/cli/dispatch.js +104 -3
- package/dist/src/kernel/project/cli/dispatch.js.map +1 -1
- package/dist/src/kernel/project/cli/rootHelp.js +8 -5
- package/dist/src/kernel/project/cli/rootHelp.js.map +1 -1
- package/dist/src/kernel/project/cli/suggestNames.js +31 -7
- package/dist/src/kernel/project/cli/suggestNames.js.map +1 -1
- package/dist/src/kernel/project/mcp/registerVerb.js +5 -1
- package/dist/src/kernel/project/mcp/registerVerb.js.map +1 -1
- package/dist/src/kernel/render/renderers.js +34 -2
- package/dist/src/kernel/render/renderers.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js +2 -3
- package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.js +4 -0
- package/dist/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/embedded.js +13 -6
- package/dist/src/kernel/runtime/graphpack/embedded.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/read.js +17 -10
- package/dist/src/kernel/runtime/graphpack/read.js.map +1 -1
- package/dist/src/kernel/runtime/loadSession.js +3 -1
- package/dist/src/kernel/runtime/loadSession.js.map +1 -1
- package/dist/src/kernel/runtime/probe.js +1 -1
- package/dist/src/kernel/runtime/probe.js.map +1 -1
- package/dist/src/kernel/runtime/readEntity.js +19 -4
- package/dist/src/kernel/runtime/readEntity.js.map +1 -1
- package/dist/src/kernel/runtime/refs/parseRef.js +17 -1
- package/dist/src/kernel/runtime/refs/parseRef.js.map +1 -1
- package/dist/src/kernel/runtime/refs/resolve.js +38 -5
- package/dist/src/kernel/runtime/refs/resolve.js.map +1 -1
- package/dist/src/kernel/spec/emitReference.js +1 -1
- package/dist/src/kernel/spec/emitReference.js.map +1 -1
- package/package.json +23 -20
- package/pragma.conf.ts +983 -40
- package/src/capabilities/block.parity.test.ts +207 -27
- package/src/capabilities/block.shipped.exec.test.ts +156 -14
- package/src/capabilities/block.tierRank.exec.test.ts +46 -9
- package/src/capabilities/capabilities/catalog.ts +14 -5
- package/src/capabilities/capabilities/hints.ts +40 -5
- package/src/capabilities/config/collectConfigShow.test.ts +1 -0
- package/src/capabilities/config/set.test.ts +24 -25
- package/src/capabilities/config/show.render.test.ts +9 -4
- package/src/capabilities/config/show.render.ts +30 -2
- package/src/capabilities/create/byteEquality.test.ts +28 -1
- package/src/capabilities/create/create.test.ts +1 -0
- package/src/capabilities/create/create.verb.ts +2 -1
- package/src/capabilities/create/createGrammar.test.ts +4 -1
- package/src/capabilities/create/createSurface.generated.ts +23 -1
- package/src/capabilities/create/crossCli.subprocess.test.ts +10 -3
- package/src/capabilities/distribution.parity.test.ts +12 -11
- package/src/capabilities/distribution.test.ts +77 -7
- package/src/capabilities/doctor/checks/checkNodeVersion.test.ts +49 -0
- package/src/capabilities/doctor/checks/checkNodeVersion.ts +11 -7
- package/src/capabilities/doctor/checks/harnessInventory.test.ts +13 -6
- package/src/capabilities/doctor/checks/harnessInventory.ts +8 -4
- package/src/capabilities/doctor/checks/isSupportedNodeVersion.test.ts +111 -0
- package/src/capabilities/doctor/checks/isSupportedNodeVersion.ts +34 -0
- package/src/capabilities/doctor/checks/mcpCommand.test.ts +7 -1
- package/src/capabilities/doctor/checks/targetHealth.ts +114 -13
- package/src/capabilities/doctor/doctor.test.ts +327 -36
- package/src/capabilities/emptyRecovery.test.ts +84 -28
- package/src/capabilities/graph/connect.render.ts +141 -0
- package/src/capabilities/graph/connect.shipped.exec.test.ts +370 -0
- package/src/capabilities/graph/connect.test.ts +361 -0
- package/src/capabilities/graph/connect.types.ts +136 -0
- package/src/capabilities/graph/connect.verb.ts +165 -0
- package/src/capabilities/graph/index.ts +5 -3
- package/src/capabilities/graph/query.shipped.exec.test.ts +66 -0
- package/src/capabilities/graph/query.test.ts +17 -0
- package/src/capabilities/graph/queryText.test.ts +121 -0
- package/src/capabilities/graph/queryText.ts +240 -0
- package/src/capabilities/graph/relationIndex.ts +372 -0
- package/src/capabilities/graph/runConnect.ts +577 -0
- package/src/capabilities/graph/runQuery.ts +21 -6
- package/src/capabilities/lazy.test.ts +32 -2
- package/src/capabilities/listBudget.shipped.exec.test.ts +239 -0
- package/src/capabilities/listLookup.shipped.exec.test.ts +387 -0
- package/src/capabilities/listQuery.shipped.exec.test.ts +400 -0
- package/src/capabilities/resources/resources.test.ts +38 -2
- package/src/capabilities/setup/buildPlan.ts +7 -1
- package/src/capabilities/setup/operations/index.ts +14 -0
- package/src/capabilities/setup/operations/setupCompletions.ts +9 -2
- package/src/capabilities/setup/operations/setupConfig.ts +7 -2
- package/src/capabilities/setup/operations/setupGenerator.ts +93 -15
- package/src/capabilities/setup/operations/setupLsp.ts +544 -85
- package/src/capabilities/setup/operations/setupMcp.ts +212 -4
- package/src/capabilities/setup/operations/setupSkills.ts +7 -2
- package/src/capabilities/setup/operations/writability.test.ts +151 -0
- package/src/capabilities/setup/operations/writability.ts +135 -0
- package/src/capabilities/setup/plan.ts +11 -0
- package/src/capabilities/setup/setup.test.ts +992 -16
- package/src/capabilities/setup/setup.verb.ts +84 -36
- package/src/capabilities/setup/targets.ts +152 -48
- package/src/capabilities/setup/types.ts +41 -5
- package/src/capabilities/shared/index.ts +1 -0
- package/src/capabilities/sources/sources.test.ts +55 -0
- package/src/capabilities/surface.test.ts +59 -11
- package/src/capabilities/tier.parity.test.ts +2 -2
- package/src/capabilities/token.parity.test.ts +784 -0
- package/src/capabilities/tokenGraph.cli.test.ts +279 -0
- package/src/capabilities/tokenGraph.shipped.exec.test.ts +653 -0
- package/src/capabilities/variable.parity.test.ts +448 -0
- package/src/constants.ts +8 -0
- package/src/kernel/completion/shellDrive.test.ts +32 -30
- package/src/kernel/config/defaults.test.ts +21 -2
- package/src/kernel/config/readConfig.test.ts +1 -1
- package/src/kernel/error/renderError.ts +3 -2
- package/src/kernel/error/validOptions.test.ts +57 -0
- package/src/kernel/error/validOptions.ts +45 -0
- package/src/kernel/packs/collect.test.ts +2 -0
- package/src/kernel/packs/compile.test.ts +188 -15
- package/src/kernel/packs/compile.ts +109 -14
- package/src/kernel/packs/cursor.ts +135 -0
- package/src/kernel/packs/filteredEmpty.test.ts +213 -0
- package/src/kernel/packs/graphql/buildLookupDocument.ts +16 -9
- package/src/kernel/packs/graphqlSource.test.ts +152 -0
- package/src/kernel/packs/listNotice.test.ts +156 -0
- package/src/kernel/packs/paging.ts +110 -0
- package/src/kernel/packs/renderPack.ts +186 -13
- package/src/kernel/packs/resolveEntity.test.ts +62 -3
- package/src/kernel/packs/resolveEntity.ts +186 -26
- package/src/kernel/packs/runBodies.ts +196 -26
- package/src/kernel/packs/schema.ts +180 -13
- package/src/kernel/packs/sparql/authorQuery.test.ts +179 -0
- package/src/kernel/packs/sparql/authorQuery.ts +257 -0
- package/src/kernel/packs/sparql/buildListQuery.test.ts +344 -0
- package/src/kernel/packs/sparql/buildListQuery.ts +344 -0
- package/src/kernel/packs/sparql/buildLookupQuery.test.ts +138 -0
- package/src/kernel/packs/sparql/buildLookupQuery.ts +140 -20
- package/src/kernel/packs/sparql/filterValues.test.ts +86 -0
- package/src/kernel/packs/sparql/filterValues.ts +182 -0
- package/src/kernel/packs/sparql/index.ts +30 -14
- package/src/kernel/packs/sparql/runSelect.test.ts +63 -0
- package/src/kernel/packs/sparql/runSelect.ts +42 -2
- package/src/kernel/packs/sparql/searchTerm.ts +29 -0
- package/src/kernel/packs/storyRules.ts +180 -0
- package/src/kernel/packs/tierScope.test.ts +487 -0
- package/src/kernel/packs/tierScope.ts +409 -0
- package/src/kernel/packs/toolDescription.test.ts +13 -10
- package/src/kernel/packs/types.ts +311 -9
- package/src/kernel/project/cli/buildProgram.ts +17 -1
- package/src/kernel/project/cli/dispatch.test.ts +87 -0
- package/src/kernel/project/cli/dispatch.ts +114 -4
- package/src/kernel/project/cli/rootHelp.ts +8 -5
- package/src/kernel/project/cli/suggest.test.ts +35 -0
- package/src/kernel/project/cli/suggestNames.ts +34 -7
- package/src/kernel/project/mcp/registerVerb.ts +5 -1
- package/src/kernel/render/contracts.ts +2 -0
- package/src/kernel/render/prefixes.test.ts +2 -0
- package/src/kernel/render/renderers.test.ts +43 -0
- package/src/kernel/render/renderers.ts +34 -1
- package/src/kernel/runtime/graphpack/embedded/pack.generated.ts +2 -3
- package/src/kernel/runtime/graphpack/embedded/pack.index.generated.ts +1 -1
- package/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.ts +3 -0
- package/src/kernel/runtime/graphpack/embedded.ts +14 -6
- package/src/kernel/runtime/graphpack/graphpack.test.ts +31 -5
- package/src/kernel/runtime/graphpack/read.ts +17 -13
- package/src/kernel/runtime/loadSession.ts +3 -1
- package/src/kernel/runtime/probe.ts +1 -1
- package/src/kernel/runtime/readEntity.ts +19 -4
- package/src/kernel/runtime/refs/parseRef.test.ts +49 -1
- package/src/kernel/runtime/refs/parseRef.ts +25 -1
- package/src/kernel/runtime/refs/resolve.ts +39 -5
- package/src/kernel/runtime/types.ts +30 -0
- package/src/kernel/spec/emitReference.ts +1 -1
- package/src/kernel/spec/surfaceConformance.test.ts +2 -2
- package/src/kernel/spec/types.ts +17 -0
- package/src/testing/PARITY_GAPS.ts +4 -4
- package/src/testing/behavioral/agentSession.mcp.test.ts +43 -39
- package/src/testing/behavioral/completion.test.ts +7 -6
- package/src/testing/behavioral/disclosure.test.ts +39 -37
- package/src/testing/behavioral/errorMatrix.mcp.test.ts +82 -64
- package/src/testing/behavioral/errorMatrix.storeless.test.ts +11 -10
- package/src/testing/behavioral/journeys.cli.test.ts +71 -32
- package/src/testing/behavioral/journeys.defaultPack.test.ts +6 -4
- package/src/testing/behavioral/journeys.firstInstall.test.ts +70 -5
- package/src/testing/behavioral/journeys.mcpLifecycle.mcp.test.ts +4 -3
- package/src/testing/behavioral/journeys.packageStories.test.ts +2 -1
- package/src/testing/behavioral/mcpSurface.test.ts +28 -25
- package/src/testing/behavioral/parity.test.ts +25 -23
- package/src/testing/eval/__snapshots__/eval.test.ts.snap +20 -0
- package/src/testing/eval/cases/effectful.ts +7 -1
- package/src/testing/eval/cases/readNouns.ts +100 -11
- package/src/testing/fixtures/blockGraph.ts +89 -5
- package/src/testing/fixtures/connectGraph.ts +159 -0
- package/src/testing/fixtures/graph/canonical.ts +128 -32
- package/src/testing/helpers/fsProbe.ts +88 -0
- package/src/testing/helpers/runCli.test.ts +44 -0
- package/src/testing/helpers/runCli.ts +27 -3
- package/src/testing/perf/budgets.test.ts +3 -1
- package/src/testing/perf/budgets.ts +138 -54
- package/dist/src/kernel/packs/sparql/applyFilters.js +0 -167
- package/dist/src/kernel/packs/sparql/applyFilters.js.map +0 -1
- package/dist/src/kernel/packs/sparql/applySearch.js +0 -25
- package/dist/src/kernel/packs/sparql/applySearch.js.map +0 -1
- package/src/kernel/packs/sparql/applyFilters.ts +0 -203
- package/src/kernel/packs/sparql/applySearch.ts +0 -33
package/pragma.conf.ts
CHANGED
|
@@ -55,8 +55,10 @@ over GraphQL or raw SPARQL.
|
|
|
55
55
|
## How it fits together
|
|
56
56
|
|
|
57
57
|
- **Tiers** are a hierarchy (\`global\` > \`apps\` > \`apps/lxd\`): a lower tier
|
|
58
|
-
inherits and overrides the blocks of its ancestors, so scoping a
|
|
59
|
-
tier walks that chain.
|
|
58
|
+
inherits and overrides the blocks of its ancestors, so scoping a read to a
|
|
59
|
+
tier walks that chain. Reads of a tiered entity ARE scoped — a list answers
|
|
60
|
+
from the top-level tiers, \`--tier apps_lxd\` from that tier and its
|
|
61
|
+
ancestors, \`--tier all\` from every tier.
|
|
60
62
|
- **Channels** (\`normal\`, \`experimental\`, \`prerelease\`) gate visibility, so an
|
|
61
63
|
in-progress block never leaks into a stable answer.
|
|
62
64
|
|
|
@@ -72,7 +74,15 @@ exactly the domain that was published.`;
|
|
|
72
74
|
|
|
73
75
|
/**
|
|
74
76
|
* The read stories the design-system pack supplies — `block`, `token`,
|
|
75
|
-
* `modifier` and `tier` as declared data rather than code.
|
|
77
|
+
* `variable`, `modifier` and `tier` as declared data rather than code.
|
|
78
|
+
*
|
|
79
|
+
* `token` and `variable` read the TOKEN-ONTOLOGY pack's four strata rather than
|
|
80
|
+
* this one's graph, and they are declared here anyway, deliberately: `token
|
|
81
|
+
* consumers` joins a symbol to the design-system records that consume it, so
|
|
82
|
+
* the pair spans both packs and there is no single pack whose `stories/*.json`
|
|
83
|
+
* could carry them. The day the strata are addressable without the design
|
|
84
|
+
* system — or the day either pack ships its own stories — is the day to split
|
|
85
|
+
* them out, and the note below about deletion applies to whichever half moves.
|
|
76
86
|
*
|
|
77
87
|
* The association with the pack is the point: when `@canonical/design-system`
|
|
78
88
|
* starts shipping its own `stories/*.json`, this block is deleted and the
|
|
@@ -82,11 +92,16 @@ exactly the domain that was published.`;
|
|
|
82
92
|
* layer does not know the pack grammar (`parsePackDefinition` does).
|
|
83
93
|
*/
|
|
84
94
|
const designSystemStories: readonly PackDefinition[] = [
|
|
85
|
-
// `block list` is declared content
|
|
86
|
-
//
|
|
87
|
-
// included, for everyone
|
|
88
|
-
//
|
|
89
|
-
//
|
|
95
|
+
// `block list` is declared content: one SELECT over the four UIBlock
|
|
96
|
+
// classes, listing every block the TIER SCOPE admits — experimental and
|
|
97
|
+
// alpha ones included, for everyone, since no read filters by channel.
|
|
98
|
+
//
|
|
99
|
+
// Tier filtering did come back in declared form, and in the form the story
|
|
100
|
+
// declares rather than the form the query text does: `tierScope` below names
|
|
101
|
+
// the hierarchy, and the kernel compiles the scope into this query as a
|
|
102
|
+
// constraint on `?uri` (`--tier all` for the unscoped list this used to be).
|
|
103
|
+
// The retired `--all-tiers` escape is not back — `--tier all` answers the
|
|
104
|
+
// same question with the argument a caller already holds. Display parity
|
|
90
105
|
// lives IN the query: `VALUES ?class` closes the type set, so the BINDs
|
|
91
106
|
// that derive `name` (declared name, else the IRI's local name), `type`
|
|
92
107
|
// (lowercased class local name), and `tier` (tier IRI's local name) operate
|
|
@@ -135,6 +150,30 @@ const designSystemStories: readonly PackDefinition[] = [
|
|
|
135
150
|
toolDescription:
|
|
136
151
|
"List all design system blocks with their type, tier, and modifier families. Use when browsing which blocks exist. Example: block_list {}.",
|
|
137
152
|
colophon: DESIGN_SYSTEM_COLOPHON,
|
|
153
|
+
// Blocks are TIERED, so every read of them is SCOPED: `block list` answers
|
|
154
|
+
// from the top-level tiers, `--tier apps_lxd` from that tier and its
|
|
155
|
+
// ancestors, `--tier all` from every tier (kernel/packs/tierScope.ts states
|
|
156
|
+
// the rule once, for every noun that declares this).
|
|
157
|
+
//
|
|
158
|
+
// The four terms are the ones the graph already carries, and three of them
|
|
159
|
+
// this story already declared for its RANKING (`scopeWeight` below): the
|
|
160
|
+
// hierarchy is the `/` in a tier's own `ds:name`, because the shipped graph
|
|
161
|
+
// asserts no parent edge to read instead — `ds:apps_lxd` is a `ds:Tier`
|
|
162
|
+
// with a name and nothing else. Reading the hierarchy from one place is
|
|
163
|
+
// what keeps the scope and the lookup ranking from disagreeing about which
|
|
164
|
+
// tier is above which.
|
|
165
|
+
//
|
|
166
|
+
// `base` is the editorial half, declared here for the reason `weights` is:
|
|
167
|
+
// nothing in the graph says `global` is the tier the others build on — the
|
|
168
|
+
// colophon above says it, and the 119 global blocks every product screen
|
|
169
|
+
// is assembled from say it. Without `base`, `--tier apps_lxd` would answer
|
|
170
|
+
// with LXD's nine blocks and hide the Buttons and Inputs they sit in.
|
|
171
|
+
tierScope: {
|
|
172
|
+
type: "ds:Tier",
|
|
173
|
+
via: "ds:tier",
|
|
174
|
+
by: "ds:name",
|
|
175
|
+
base: "ds:global",
|
|
176
|
+
},
|
|
138
177
|
list: {
|
|
139
178
|
query: [
|
|
140
179
|
"SELECT ?uri ?name ?type ?tier",
|
|
@@ -268,6 +307,10 @@ const designSystemStories: readonly PackDefinition[] = [
|
|
|
268
307
|
label: "Anatomy (DSL)",
|
|
269
308
|
kind: "code",
|
|
270
309
|
level: "detailed",
|
|
310
|
+
// The one piece of the notation that cannot be guessed from reading
|
|
311
|
+
// it: a bracketed value looks like a set of alternatives with no
|
|
312
|
+
// stated order of preference, and it is an ORDERED chain.
|
|
313
|
+
note: "A list value is the fallback chain the implementation reads, first wins.",
|
|
271
314
|
},
|
|
272
315
|
{
|
|
273
316
|
name: "anatomyClassic",
|
|
@@ -314,6 +357,69 @@ const designSystemStories: readonly PackDefinition[] = [
|
|
|
314
357
|
{ name: "uri", property: "ds:name", graphqlField: "uri" },
|
|
315
358
|
],
|
|
316
359
|
},
|
|
360
|
+
// Which symbols this block consumes, at which style key and rank — the
|
|
361
|
+
// mirror of `token consumers`, read from the block's end. It was
|
|
362
|
+
// DELIBERATELY ABSENT while none of the terms existed: the record the
|
|
363
|
+
// whole tuple hangs off is the design system's to mint, and until it
|
|
364
|
+
// did, `ds:hasTokenBinding`, `ds:consumesSymbol`, `ds:rank`,
|
|
365
|
+
// `ds:viaBlock` and `ds:node` were not declared properties at all. All
|
|
366
|
+
// five are now, with domains and ranges, and `ds:TokenBinding` is a
|
|
367
|
+
// class — so the declaration lands as the note then predicted, all six
|
|
368
|
+
// identity columns of it.
|
|
369
|
+
//
|
|
370
|
+
// SPARQL lane, and NOT this lookup's own GraphQL one, which is the only
|
|
371
|
+
// part of that prediction that had to change. Two of the six columns
|
|
372
|
+
// are unreachable through a generated document: `anatomy:styleKey` and
|
|
373
|
+
// `anatomy:styleState` carry no `rdfs:domain` — they are the anatomy
|
|
374
|
+
// vocabulary's, shared by every styled thing — so ke-graphql generates
|
|
375
|
+
// no field for them on `TokenBinding`, and a derived name the schema
|
|
376
|
+
// does not carry drops out of the document in silence. Measured on the
|
|
377
|
+
// shipped pack: Button rendered 24 rows with no key and no state, two
|
|
378
|
+
// of which (`spacing.internal.inline.start` and `…end`) were then
|
|
379
|
+
// byte-identical. A table whose rows a reader cannot tell apart is the
|
|
380
|
+
// defect this story refuses elsewhere, so the expand takes the lane
|
|
381
|
+
// that can read every term instead. The modifier families above cannot
|
|
382
|
+
// follow it — their nested `values` is a second hop only a document can
|
|
383
|
+
// make — which is why the lane is per-expand.
|
|
384
|
+
{
|
|
385
|
+
name: "tokens",
|
|
386
|
+
heading: "Tokens",
|
|
387
|
+
kind: "table",
|
|
388
|
+
relation: "ds:hasTokenBinding",
|
|
389
|
+
source: "sparql",
|
|
390
|
+
level: "detailed",
|
|
391
|
+
// Ordered by the READING order of the thing described: a node's
|
|
392
|
+
// styles, one key at a time, each key's fallback chain in the order
|
|
393
|
+
// the implementation walks it. The store's own scan order is
|
|
394
|
+
// undefined and put a node's two spacing keys either side of an
|
|
395
|
+
// unrelated one.
|
|
396
|
+
orderBy: ["node", "key", "rank"],
|
|
397
|
+
// The same sentence `Anatomy (DSL)` carries, because it is the same
|
|
398
|
+
// notation read from the other side: the anatomy's bracketed list is
|
|
399
|
+
// the chain, and `rank` is the position in it. A reader who has the
|
|
400
|
+
// rank column but not that sentence has no way to know that rank 2 is
|
|
401
|
+
// reached only when rank 1 does not resolve.
|
|
402
|
+
note: "A list value in the anatomy is the fallback chain the implementation reads, first wins; rank is the position in that chain.",
|
|
403
|
+
select: [
|
|
404
|
+
// The dotted name, not the symbol's IRI: it is the address
|
|
405
|
+
// `token lookup` and `token consumers --symbol` both take, so a row
|
|
406
|
+
// here is a query a reader can run.
|
|
407
|
+
{ name: "symbol", property: "ds:consumesSymbol/rdfs:label" },
|
|
408
|
+
{ name: "key", property: "anatomy:styleKey" },
|
|
409
|
+
{ name: "state", property: "anatomy:styleState" },
|
|
410
|
+
{ name: "rank", property: "ds:rank" },
|
|
411
|
+
// Blank on the block's OWN tree. `ds:viaBlock` is present on every
|
|
412
|
+
// record and its own definition says it equals the block in the
|
|
413
|
+
// own-tree case, so printing it raw put "Button" in all 24 of
|
|
414
|
+
// Button's rows — a cell that is only ever news when it differs.
|
|
415
|
+
{
|
|
416
|
+
name: "via",
|
|
417
|
+
property: "ds:viaBlock/ds:name",
|
|
418
|
+
blankWhenSelf: true,
|
|
419
|
+
},
|
|
420
|
+
{ name: "node", property: "ds:node" },
|
|
421
|
+
],
|
|
422
|
+
},
|
|
317
423
|
],
|
|
318
424
|
disclosure: {
|
|
319
425
|
levels: ["summary", "standard", "detailed"],
|
|
@@ -327,59 +433,845 @@ const designSystemStories: readonly PackDefinition[] = [
|
|
|
327
433
|
},
|
|
328
434
|
},
|
|
329
435
|
|
|
330
|
-
//
|
|
331
|
-
//
|
|
332
|
-
//
|
|
333
|
-
//
|
|
334
|
-
//
|
|
335
|
-
//
|
|
436
|
+
// The design-token SYMBOLS — S1 of the four token strata, keyed on the name
|
|
437
|
+
// literal the binding programme publishes.
|
|
438
|
+
//
|
|
439
|
+
// REPOINTED from `ds:Token`, a class no graph asserts. The shipped pack
|
|
440
|
+
// carries 0 instances of it and 745 `dt:TokenSymbol`, so every `token list`
|
|
441
|
+
// on every install answered an empty table while the population sat one
|
|
442
|
+
// namespace over — the same silent shape as reading a retired `ds:whenToUse`,
|
|
443
|
+
// and caught the same way (`listBudget.shipped.exec.test.ts` measured this
|
|
444
|
+
// story at 0 rows / 2 bytes). `ds:valueLight`/`ds:valueDark` go with it: a
|
|
445
|
+
// symbol's value is not a pair of theme columns but one row per POSITION in
|
|
446
|
+
// the coordinate space, which is what `token values` answers.
|
|
447
|
+
//
|
|
448
|
+
// NO `nameFallback`, deliberately. The kernel's IRI derivation publishes a
|
|
449
|
+
// dotted local name with SLASHES (`dt:color.text` → `color/text`), which
|
|
450
|
+
// contradicts the dotted notation ruled for symbol names and would make this
|
|
451
|
+
// answer disagree with the anatomy's spelling of the same symbol. The
|
|
452
|
+
// consequence is visible rather than hidden: until the pack ships
|
|
453
|
+
// `rdfs:label` on the symbols, `token list` publishes no rows and
|
|
454
|
+
// `token lookup` resolves no name. An empty answer that says so beats a
|
|
455
|
+
// populated one whose names nothing else recognises — and it is why `token`
|
|
456
|
+
// is still in `EMPTY_CORPUS_TODAY`.
|
|
336
457
|
{
|
|
337
458
|
noun: "token",
|
|
338
|
-
description: "List
|
|
459
|
+
description: "List the design-token symbols.",
|
|
339
460
|
toolDescription:
|
|
340
|
-
|
|
461
|
+
'List the design-token SYMBOLS — logical dotted names (`color.text`), with the type and description from the symbol\'s OWN definition, and the symbol a channel provisions. The CSS custom-property names a stylesheet declares are variable_list. Example: token_list { type: "color" }.',
|
|
341
462
|
list: {
|
|
463
|
+
// Type and description are DEFINITION-level facts, and 393 of the 745
|
|
464
|
+
// symbols have more than one definition (`color.text` has 20). The one
|
|
465
|
+
// that speaks FOR the symbol is its own, and the graph already carries a
|
|
466
|
+
// path to it: every symbol the resolver reached has a BASE
|
|
467
|
+
// `dt:ResolvedValue` — the one with no `dt:coordinate` — and the HEAD of
|
|
468
|
+
// that value's `dt:resolutionChain` is the definition the value was
|
|
469
|
+
// authored in at the all-defaults position. Its `dt:tokenType` and its
|
|
470
|
+
// `w3c-tokens:description` are this row's two cells.
|
|
471
|
+
//
|
|
472
|
+
// The base restriction is SPELLED OUT rather than left to `DISTINCT`.
|
|
473
|
+
// 354 of the 519 values at a coordinate carry a chain too, and their
|
|
474
|
+
// heads are the definitions authored for those positions — a different
|
|
475
|
+
// definition, correctly so, and not this column's. Over the shipped
|
|
476
|
+
// corpus those heads happen to agree with the base head on both fields,
|
|
477
|
+
// so the unrestricted walk answers the same 745 rows; `FILTER NOT EXISTS`
|
|
478
|
+
// says WHICH value is meant instead of resting on that coincidence.
|
|
479
|
+
//
|
|
480
|
+
// Measured over the 745 symbols: 718 publish both fields, 27 blank both.
|
|
481
|
+
// The 27 are the 25 minted channels, which have no definition anywhere,
|
|
482
|
+
// plus `typography.heading.display` and its `.bold` twin, which have
|
|
483
|
+
// definitions but no resolved value to authorise one of them. Nothing
|
|
484
|
+
// publishes one field and blanks the other — a chain head carries both,
|
|
485
|
+
// or the symbol has no chain head.
|
|
486
|
+
//
|
|
487
|
+
// This REPLACED an agreement rule (publish what every definition agrees
|
|
488
|
+
// on, blank it when they disagree), and the two never disagree where the
|
|
489
|
+
// old one spoke: 0 of the 745 symbols have two definitions naming
|
|
490
|
+
// different types, and the 40 whose descriptions "disagreed" disagree
|
|
491
|
+
// only with a `semantic/modifier/**` definition — one position's wording,
|
|
492
|
+
// which the old rule let outvote the symbol's own. Those 40 now read
|
|
493
|
+
// their own description instead of a blank. What went with the old rule
|
|
494
|
+
// is its cost: a `COUNT(DISTINCT ...)` sub-select over 1,311 definitions
|
|
495
|
+
// made this the slowest body in the distribution. The paged walk that
|
|
496
|
+
// `listQuery.shipped.exec.test.ts` runs over it took 190 s, past its own
|
|
497
|
+
// 60-second timeout; over this query it takes 1.8 s, and the whole
|
|
498
|
+
// population comes back in 71 ms rather than 1.1 s a page.
|
|
342
499
|
query: [
|
|
343
|
-
"SELECT ?uri ?name ?
|
|
344
|
-
"
|
|
345
|
-
"
|
|
500
|
+
"SELECT DISTINCT ?uri ?name ?type ?description ?channelOf",
|
|
501
|
+
"WHERE {",
|
|
502
|
+
" ?uri a dt:TokenSymbol ;",
|
|
503
|
+
" rdfs:label ?name .",
|
|
504
|
+
// A channel IS a symbol after the binding programme, so the relation to
|
|
505
|
+
// the symbol it provisions is a column on this population rather than a
|
|
506
|
+
// noun of its own. Bound to the base symbol's LABEL, not its IRI: the
|
|
507
|
+
// filter column and the displayed column are one column, and an
|
|
508
|
+
// unbound IRI cell renders as a full IRI.
|
|
509
|
+
" OPTIONAL { ?uri dt:channelOf/rdfs:label ?channelOf }",
|
|
346
510
|
" OPTIONAL {",
|
|
347
|
-
" ?
|
|
348
|
-
"
|
|
511
|
+
" ?resolved dt:forSymbol ?uri ;",
|
|
512
|
+
" dt:resolutionChain/rdf:first ?definition .",
|
|
513
|
+
" FILTER NOT EXISTS { ?resolved dt:coordinate ?coordinate }",
|
|
514
|
+
" OPTIONAL { ?definition dt:tokenType/rdfs:label ?type }",
|
|
515
|
+
" OPTIONAL { ?definition w3c-tokens:description ?description }",
|
|
349
516
|
" }",
|
|
350
517
|
"}",
|
|
351
518
|
"ORDER BY ?name",
|
|
352
519
|
].join("\n"),
|
|
353
520
|
columns: [
|
|
521
|
+
{ field: "name", label: "Name" },
|
|
522
|
+
{ field: "type", label: "Type" },
|
|
523
|
+
{ field: "channelOf", label: "Channel of" },
|
|
524
|
+
{ field: "description", label: "Description" },
|
|
354
525
|
{ field: "uri", label: "IRI" },
|
|
526
|
+
],
|
|
527
|
+
filters: [
|
|
528
|
+
{
|
|
529
|
+
param: "type",
|
|
530
|
+
variable: "type",
|
|
531
|
+
// The seven typed members of the definition's type class, which is
|
|
532
|
+
// the same term the `type` column reads off the symbol's own
|
|
533
|
+
// definition. A type the ontology declares that no symbol is filed
|
|
534
|
+
// under is a calm empty list, not a bad argument.
|
|
535
|
+
vocabulary: {
|
|
536
|
+
query: [
|
|
537
|
+
"SELECT DISTINCT ?type WHERE {",
|
|
538
|
+
" ?kind a w3c-tokens:TokenType ;",
|
|
539
|
+
" rdfs:label ?type .",
|
|
540
|
+
"}",
|
|
541
|
+
].join("\n"),
|
|
542
|
+
},
|
|
543
|
+
description: "Filter by type.",
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
param: "channelOf",
|
|
547
|
+
variable: "channelOf",
|
|
548
|
+
// The dimension is "which SYMBOL", so the roster is EVERY symbol —
|
|
549
|
+
// not the far smaller set that happens to have a channel today.
|
|
550
|
+
// Asking for a symbol nothing provisions is the documented calm empty
|
|
551
|
+
// list, which is the whole reason a vocabulary is read from the graph
|
|
552
|
+
// rather than from the rows a page returned.
|
|
553
|
+
//
|
|
554
|
+
// Keyed on `rdfs:label`, the same term the column binds and the same
|
|
555
|
+
// term the lookup resolves by. All three move together or not at all.
|
|
556
|
+
vocabulary: {
|
|
557
|
+
query: [
|
|
558
|
+
"SELECT DISTINCT ?channelOf WHERE {",
|
|
559
|
+
" ?symbol a dt:TokenSymbol ;",
|
|
560
|
+
" rdfs:label ?channelOf .",
|
|
561
|
+
"}",
|
|
562
|
+
].join("\n"),
|
|
563
|
+
},
|
|
564
|
+
description: "Filter to one symbol's channels.",
|
|
565
|
+
},
|
|
566
|
+
],
|
|
567
|
+
search: {
|
|
568
|
+
variables: ["name", "description"],
|
|
569
|
+
description: "Search name and description.",
|
|
570
|
+
},
|
|
571
|
+
// No `emptyRecovery`: this list is empty only on an install whose store
|
|
572
|
+
// holds no token pack at all, and the kernel's generic hint already names
|
|
573
|
+
// both fixes for that (broaden the filter, or build the store). Anything a
|
|
574
|
+
// story added here would be a sentence about an empty store printed to
|
|
575
|
+
// readers who have 745 symbols and only missed with a filter.
|
|
576
|
+
},
|
|
577
|
+
verbs: [
|
|
578
|
+
{
|
|
579
|
+
verb: "values",
|
|
580
|
+
description:
|
|
581
|
+
"List the value each symbol resolves to at each position, with its chain or its derivation.",
|
|
582
|
+
toolDescription:
|
|
583
|
+
'List the resolved token VALUES — one row per (symbol, position) the graph materialises, with the value and either its resolution chain or the symbol it derives from. Only MATERIALISED positions appear, not the permutation space: a position with no row falls through to the base symbol. A derived row carries a derivation and no value cell. Example: token_values { symbol: "color.text" }.',
|
|
584
|
+
// The resolved-value shape admits exactly one of a chain or a
|
|
585
|
+
// derivation, so BOTH are selected wherever a value is projected. A
|
|
586
|
+
// surface that selected only the chain would show a blank row for every
|
|
587
|
+
// one of the 165 channel routings — and channel values are precisely
|
|
588
|
+
// what the anatomy validator and the editor's completion ask about.
|
|
589
|
+
//
|
|
590
|
+
// Both are rdf:LISTs, not literals: `dt:resolutionChain` is a list of
|
|
591
|
+
// definition IRIs, so it needs `/rdf:rest*/rdf:first` and an aggregate
|
|
592
|
+
// to become one cell. The chain items are trimmed to the path inside
|
|
593
|
+
// the token files, which is the form the resolution chain is quoted in.
|
|
594
|
+
//
|
|
595
|
+
// The cell is a SET, and its order is NOT the list's. `GROUP_CONCAT`
|
|
596
|
+
// has no defined order in SPARQL and takes no `ORDER BY`, so the links
|
|
597
|
+
// of a multi-link chain may come back either way round — which a test
|
|
598
|
+
// pinning one spelling of a two-link chain found by flaking. Reading
|
|
599
|
+
// the cell as "which definitions this value passed through" is
|
|
600
|
+
// therefore right and reading it as "in what order" is not. The
|
|
601
|
+
// ORDERED anchor a caller usually wants is the chain's HEAD, the
|
|
602
|
+
// definition the value was authored in, and that is what the lookup's
|
|
603
|
+
// `values` expand projects with `rdf:first`.
|
|
604
|
+
query: [
|
|
605
|
+
"SELECT ?symbol ?position ?value ?derivedFrom",
|
|
606
|
+
' (GROUP_CONCAT(DISTINCT ?chainItem; SEPARATOR=" ") AS ?chain)',
|
|
607
|
+
"WHERE {",
|
|
608
|
+
" ?resolved a dt:ResolvedValue ;",
|
|
609
|
+
" dt:forSymbol ?symbolUri .",
|
|
610
|
+
" ?symbolUri rdfs:label ?symbol .",
|
|
611
|
+
" OPTIONAL { ?resolved dt:coordinate ?coordinate }",
|
|
612
|
+
" OPTIONAL { ?resolved dt:resolvesTo ?value }",
|
|
613
|
+
" OPTIONAL { ?resolved dt:derivedFrom/rdfs:label ?derivedFrom }",
|
|
614
|
+
" OPTIONAL {",
|
|
615
|
+
" ?resolved dt:resolutionChain/rdf:rest*/rdf:first ?chainUri .",
|
|
616
|
+
' BIND(REPLACE(STR(?chainUri), "^.*/file/", "") AS ?chainItem)',
|
|
617
|
+
" }",
|
|
618
|
+
// The coordinate's own dotted name, with the class prefix its IRI
|
|
619
|
+
// carries dropped: `dt:coordinate.mode.dark` displays and filters as
|
|
620
|
+
// `mode.dark`, which is how a position is written everywhere else.
|
|
621
|
+
// A value at the DEFAULT position carries no coordinate at all, and
|
|
622
|
+
// its cell is empty rather than a full IRI.
|
|
623
|
+
' BIND(REPLACE(REPLACE(STR(?coordinate), "^.*[/#]", ""), "^coordinate[.]", "") AS ?position)',
|
|
624
|
+
"}",
|
|
625
|
+
"GROUP BY ?resolved ?symbol ?position ?value ?derivedFrom",
|
|
626
|
+
"ORDER BY ?symbol ?position",
|
|
627
|
+
].join("\n"),
|
|
628
|
+
columns: [
|
|
629
|
+
{ field: "symbol", label: "Symbol" },
|
|
630
|
+
{ field: "position", label: "Position" },
|
|
631
|
+
{ field: "value", label: "Value" },
|
|
632
|
+
{ field: "chain", label: "Chain" },
|
|
633
|
+
{ field: "derivedFrom", label: "Derived from" },
|
|
634
|
+
],
|
|
635
|
+
filters: [
|
|
636
|
+
{
|
|
637
|
+
param: "symbol",
|
|
638
|
+
variable: "symbol",
|
|
639
|
+
vocabulary: {
|
|
640
|
+
query: [
|
|
641
|
+
"SELECT DISTINCT ?symbol WHERE {",
|
|
642
|
+
" ?s a dt:TokenSymbol ;",
|
|
643
|
+
" rdfs:label ?symbol .",
|
|
644
|
+
"}",
|
|
645
|
+
].join("\n"),
|
|
646
|
+
},
|
|
647
|
+
description: "Filter to one symbol.",
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
param: "position",
|
|
651
|
+
variable: "position",
|
|
652
|
+
// `set`, because ONE row can sit at several positions at once: a
|
|
653
|
+
// value asserted `dt:alsoAt` a second coordinate is one row
|
|
654
|
+
// belonging to both, and a filter comparing only the whole cell
|
|
655
|
+
// would answer such a row for neither.
|
|
656
|
+
match: "set",
|
|
657
|
+
vocabulary: {
|
|
658
|
+
query: [
|
|
659
|
+
"SELECT DISTINCT ?position WHERE {",
|
|
660
|
+
" ?c a dt:Coordinate .",
|
|
661
|
+
' BIND(REPLACE(REPLACE(STR(?c), "^.*[/#]", ""), "^coordinate[.]", "") AS ?position)',
|
|
662
|
+
"}",
|
|
663
|
+
].join("\n"),
|
|
664
|
+
},
|
|
665
|
+
description: "Filter to one position.",
|
|
666
|
+
},
|
|
667
|
+
],
|
|
668
|
+
search: {
|
|
669
|
+
variables: ["symbol", "value", "derivedFrom"],
|
|
670
|
+
description: "Search symbol, value, derivation.",
|
|
671
|
+
},
|
|
672
|
+
emptyRecovery: {
|
|
673
|
+
message:
|
|
674
|
+
"Resolved token values come from the @canonical/token-ontology pack, and a value is only addressable by symbol once that pack publishes its name literals — a store built without that pack carries none.",
|
|
675
|
+
cli: "sources update",
|
|
676
|
+
},
|
|
677
|
+
},
|
|
678
|
+
{
|
|
679
|
+
verb: "consumers",
|
|
680
|
+
description:
|
|
681
|
+
"List which blocks consume which token symbol, at which style key, state and rank.",
|
|
682
|
+
toolDescription:
|
|
683
|
+
'List the token BINDINGS the design system records — which block consumes which symbol, at which style key, state, rank and node. Every column is identity: two bindings differing only in state are different facts. The block is the CONSUMING block; via names the block whose anatomy the binding was authored in, and is blank when that is the consuming block itself. Name the symbol by its dotted name (symbol) or by a CSS variable standing for it (variable). Answers empty until the packs record bindings. Example: token_consumers { variable: "color-text" }.',
|
|
684
|
+
// Seven identity columns, and not one of them is decoration: a binding
|
|
685
|
+
// is identified by the whole tuple, so dropping `rank` or `node` would
|
|
686
|
+
// publish rows a caller cannot tell apart — which is worse than a wide
|
|
687
|
+
// table, because a deduplicating consumer would silently lose facts.
|
|
688
|
+
//
|
|
689
|
+
// `ds:hasTokenBinding` and its four siblings are DEFINED BY the
|
|
690
|
+
// design-system ontology only from the binding programme's records
|
|
691
|
+
// onward; today the shipped ontology defines none of them, and the `ds:`
|
|
692
|
+
// prefix IS bound, so this answers a calm empty list with the recovery
|
|
693
|
+
// below rather than failing. It starts answering with no code change.
|
|
694
|
+
//
|
|
695
|
+
// `?block` is the CONSUMING block and `?via` the block whose anatomy
|
|
696
|
+
// the binding was authored in, and the two are separate columns because
|
|
697
|
+
// they are separate facts. They were one: `?block` used to COALESCE the
|
|
698
|
+
// via name over the consuming block's, so a record Accordion carries
|
|
699
|
+
// because its anatomy embeds `Accordion.Item` printed as
|
|
700
|
+
// `Accordion.Item` — byte-identical to Accordion.Item's OWN record.
|
|
701
|
+
// `--symbol color.text` answered six rows reading `Button`, one per
|
|
702
|
+
// block that embeds a Button, and no reader could tell which component
|
|
703
|
+
// would change if the symbol did. Which component consumes the symbol
|
|
704
|
+
// is the fact this verb exists for, so it is the column the row leads
|
|
705
|
+
// with; the via is BLANK on a record sitting on the block's own tree —
|
|
706
|
+
// where the data asserts `ds:viaBlock` equal to the block itself —
|
|
707
|
+
// because "Button via Button" is not news and 24 of Button's rows
|
|
708
|
+
// would say it.
|
|
709
|
+
query: [
|
|
710
|
+
"SELECT ?block ?via ?symbol ?key ?state ?rank ?node ?uri",
|
|
711
|
+
' (GROUP_CONCAT(DISTINCT ?variableName; SEPARATOR=" ") AS ?variable)',
|
|
712
|
+
"WHERE {",
|
|
713
|
+
" ?blockUri ds:hasTokenBinding ?uri .",
|
|
714
|
+
" ?uri ds:consumesSymbol ?symbolUri .",
|
|
715
|
+
" ?symbolUri rdfs:label ?symbol .",
|
|
716
|
+
" OPTIONAL { ?uri anatomy:styleKey ?key }",
|
|
717
|
+
" OPTIONAL { ?uri anatomy:styleState ?state }",
|
|
718
|
+
" OPTIONAL { ?uri ds:rank ?rank }",
|
|
719
|
+
" OPTIONAL { ?uri ds:node ?node }",
|
|
720
|
+
" OPTIONAL { ?uri ds:viaBlock ?viaUri . OPTIONAL { ?viaUri ds:name ?viaName } }",
|
|
721
|
+
" OPTIONAL { ?blockUri ds:name ?blockName }",
|
|
722
|
+
// Every platform spelling of the consumed symbol, as a SET rather
|
|
723
|
+
// than a join that multiplies the row: 204 symbols carry both a
|
|
724
|
+
// kebab and a camelCase variable, and binding one row per variable
|
|
725
|
+
// would publish each binding twice under names a caller cannot tell
|
|
726
|
+
// apart. Aggregated, both spellings land in one cell and `--variable`
|
|
727
|
+
// set-matches either — which is also why the two spellings of one
|
|
728
|
+
// symbol return the SAME set rather than partitioning it.
|
|
729
|
+
" OPTIONAL {",
|
|
730
|
+
" ?variableUri dt:ofSymbol ?symbolUri ;",
|
|
731
|
+
" rdfs:label ?variableName .",
|
|
732
|
+
" }",
|
|
733
|
+
' BIND(COALESCE(?blockName, REPLACE(STR(?blockUri), "^.*[/#]", "")) AS ?block)',
|
|
734
|
+
// `IF` and not `COALESCE`: the blank says something a MISSING value
|
|
735
|
+
// cannot, because the via is present on every record and equals the
|
|
736
|
+
// block on its own tree. SPARQL evaluates only the taken arm of an
|
|
737
|
+
// `IF`, so the local-name fallback is never asked to name an unbound
|
|
738
|
+
// via.
|
|
739
|
+
" BIND(IF(BOUND(?viaUri) && ?viaUri != ?blockUri,",
|
|
740
|
+
' COALESCE(?viaName, REPLACE(STR(?viaUri), "^.*[/#]", "")),',
|
|
741
|
+
' "") AS ?via)',
|
|
742
|
+
"}",
|
|
743
|
+
"GROUP BY ?block ?via ?symbol ?key ?state ?rank ?node ?uri",
|
|
744
|
+
// `?via` second, so a block's OWN bindings (blank via, which sorts
|
|
745
|
+
// first) come before the ones it inherits, and the inherited ones
|
|
746
|
+
// stay grouped by the block they come from.
|
|
747
|
+
"ORDER BY ?block ?via ?symbol ?key ?state ?rank ?node",
|
|
748
|
+
].join("\n"),
|
|
749
|
+
// No `uri` COLUMN, though the record's IRI is still SELECTed: it is the
|
|
750
|
+
// row's subject and what keeps two bindings differing only in state
|
|
751
|
+
// apart, so `--format json` carries it exactly as before. What it is
|
|
752
|
+
// not is a cell worth a reader's eye. A binding record is a BLANK NODE,
|
|
753
|
+
// so it is not addressable — `graph inspect _:dda768d3…` answers
|
|
754
|
+
// INVALID_INPUT — and a blank node's label is re-minted on every store
|
|
755
|
+
// load, so the same row printed a different id on every run. And the
|
|
756
|
+
// `llm` renderer hoists a `uri` column to the HEAD of the line, ahead
|
|
757
|
+
// of every other cell, which is the slot the consuming block belongs
|
|
758
|
+
// in; a story cannot reorder that, so the column goes rather than the
|
|
759
|
+
// block staying second to an unusable id.
|
|
760
|
+
columns: [
|
|
761
|
+
{ field: "block", label: "Block" },
|
|
762
|
+
{ field: "via", label: "Via" },
|
|
763
|
+
{ field: "symbol", label: "Symbol" },
|
|
764
|
+
{ field: "variable", label: "Variables" },
|
|
765
|
+
{ field: "key", label: "Style key" },
|
|
766
|
+
{ field: "state", label: "State" },
|
|
767
|
+
{ field: "rank", label: "Rank" },
|
|
768
|
+
{ field: "node", label: "Node" },
|
|
769
|
+
],
|
|
770
|
+
filters: [
|
|
771
|
+
{
|
|
772
|
+
param: "symbol",
|
|
773
|
+
variable: "symbol",
|
|
774
|
+
vocabulary: {
|
|
775
|
+
query: [
|
|
776
|
+
"SELECT DISTINCT ?symbol WHERE {",
|
|
777
|
+
" ?s a dt:TokenSymbol ;",
|
|
778
|
+
" rdfs:label ?symbol .",
|
|
779
|
+
"}",
|
|
780
|
+
].join("\n"),
|
|
781
|
+
},
|
|
782
|
+
description: "Filter to one symbol.",
|
|
783
|
+
},
|
|
784
|
+
{
|
|
785
|
+
param: "variable",
|
|
786
|
+
variable: "variable",
|
|
787
|
+
// The SAME constraint as `--symbol`, named by the other spelling.
|
|
788
|
+
// A web implementer holds a CSS custom-property name, not a dotted
|
|
789
|
+
// symbol, so answering "what breaks if I change --color-text" used
|
|
790
|
+
// to take two calls and a spelling the caller did not start with.
|
|
791
|
+
// The join is in the query instead.
|
|
792
|
+
//
|
|
793
|
+
// `set`, because the cell is every platform spelling of the
|
|
794
|
+
// consumed symbol and one row legitimately belongs to all of them.
|
|
795
|
+
match: "set",
|
|
796
|
+
// The variable labels, the same source `variable lookup` resolves
|
|
797
|
+
// against — so a name that works there works here.
|
|
798
|
+
vocabulary: {
|
|
799
|
+
query: [
|
|
800
|
+
"SELECT DISTINCT ?variable WHERE {",
|
|
801
|
+
" ?v a dt:Variable ;",
|
|
802
|
+
" rdfs:label ?variable .",
|
|
803
|
+
"}",
|
|
804
|
+
].join("\n"),
|
|
805
|
+
},
|
|
806
|
+
// Two things a caller will otherwise assume, both wrong.
|
|
807
|
+
//
|
|
808
|
+
// A CHANNEL variable and its semantic sibling are DIFFERENT
|
|
809
|
+
// constraints: `--variable modifier-color-text` finds the blocks
|
|
810
|
+
// that bind the channel, `--variable color-text` those that bind
|
|
811
|
+
// the symbol, and neither includes the other. Whether a block's
|
|
812
|
+
// resolution eventually reaches the other through a fallback is a
|
|
813
|
+
// question about the consumed list, not about this single-symbol
|
|
814
|
+
// join, and blurring them here would answer a question nobody
|
|
815
|
+
// asked with rows nobody can check.
|
|
816
|
+
//
|
|
817
|
+
// And a variable standing for NO symbol has no answer down this
|
|
818
|
+
// path at all — 236 of them do — which is an empty answer for a
|
|
819
|
+
// reason the recovery below names, not evidence that nothing
|
|
820
|
+
// consumes it.
|
|
821
|
+
description:
|
|
822
|
+
"A CSS variable name for the consumed symbol — the other spelling of the symbol parameter. A channel variable and its semantic sibling differ.",
|
|
823
|
+
},
|
|
824
|
+
{
|
|
825
|
+
param: "key",
|
|
826
|
+
variable: "key",
|
|
827
|
+
// The style-key REGISTRY, which the anatomy pack publishes as 111
|
|
828
|
+
// `anatomy:StyleKey` individuals. Their identity is the IRI and
|
|
829
|
+
// they carry no key literal, so the admissible spelling is the
|
|
830
|
+
// IRI's local name with the class prefix its minting adds dropped:
|
|
831
|
+
// `anatomy:key.appearance.background` is the key
|
|
832
|
+
// `appearance.background`, which is how the vocabulary's own
|
|
833
|
+
// examples write it.
|
|
834
|
+
//
|
|
835
|
+
// Read from the REGISTRY rather than from the records, and that is
|
|
836
|
+
// the point: no block has a binding record yet, so a roster read
|
|
837
|
+
// from records would be empty and would refuse every key a caller
|
|
838
|
+
// could legitimately ask about. The registry is the graph's
|
|
839
|
+
// statement of what a key may be; the records are the population.
|
|
840
|
+
vocabulary: {
|
|
841
|
+
query: [
|
|
842
|
+
"SELECT DISTINCT ?key WHERE {",
|
|
843
|
+
" ?styleKey a anatomy:StyleKey .",
|
|
844
|
+
' BIND(REPLACE(REPLACE(STR(?styleKey), "^.*[/#]", ""), "^key[.]", "") AS ?key)',
|
|
845
|
+
"}",
|
|
846
|
+
].join("\n"),
|
|
847
|
+
},
|
|
848
|
+
description: "Filter to one style key.",
|
|
849
|
+
},
|
|
850
|
+
{
|
|
851
|
+
param: "state",
|
|
852
|
+
variable: "state",
|
|
853
|
+
// The closed interaction-state vocabulary, read from the shape that
|
|
854
|
+
// closes it rather than transcribed here: the anatomy pack's shapes
|
|
855
|
+
// constrain `anatomy:styleState` with an `sh:in` list, so the five
|
|
856
|
+
// admissible states are a query over that list. Hard-coding them
|
|
857
|
+
// would be the "don't hard-code the slugs" defect with an extra
|
|
858
|
+
// step — the graph already says it.
|
|
859
|
+
vocabulary: {
|
|
860
|
+
query: [
|
|
861
|
+
"SELECT DISTINCT ?state WHERE {",
|
|
862
|
+
" ?shape sh:path anatomy:styleState ;",
|
|
863
|
+
" sh:in/rdf:rest*/rdf:first ?state .",
|
|
864
|
+
"}",
|
|
865
|
+
].join("\n"),
|
|
866
|
+
},
|
|
867
|
+
description: "Filter to one interaction state.",
|
|
868
|
+
},
|
|
869
|
+
],
|
|
870
|
+
search: {
|
|
871
|
+
variables: ["block", "via", "symbol", "key", "state", "node"],
|
|
872
|
+
description: "Search block, via, symbol, key, state and node.",
|
|
873
|
+
},
|
|
874
|
+
// Deliberately `sources update`: unlike `standard list`, this story's
|
|
875
|
+
// data does NOT ride the embedded snapshot — the binding records are
|
|
876
|
+
// written by the design-system packs, so an empty answer here can be a
|
|
877
|
+
// store that predates them.
|
|
878
|
+
//
|
|
879
|
+
// CAN be, not is — which is why the message opens on the two cases
|
|
880
|
+
// rather than asserting one. This text prints under a filtered miss too
|
|
881
|
+
// (`--symbol color.text`), where "nothing is recorded at all" would be a
|
|
882
|
+
// claim the answer cannot support, so it names both readings and hands
|
|
883
|
+
// the reader the one command that separates them.
|
|
884
|
+
emptyRecovery: {
|
|
885
|
+
message:
|
|
886
|
+
"Either no component uses this token, or no component is recorded as using any token yet — which components use which tokens comes from the component anatomies in the design-system document, and a copy of the graph built before any anatomy named its tokens is empty for every token. Run the same command without `--symbol` to tell the two apart: an empty unfiltered answer means the graph predates the anatomies and fills in once they are written and the graph is rebuilt. If you asked about a CSS variable rather than a token: some variables are computed from others (the `--hover--…` and `--disabled--…` ones, for example) and stand for no token, so nothing is ever recorded as using them; `pragma variable chain --variable <name>` shows what such a variable ends up as.",
|
|
887
|
+
cli: "sources update",
|
|
888
|
+
},
|
|
889
|
+
},
|
|
890
|
+
],
|
|
891
|
+
lookup: {
|
|
892
|
+
source: "sparql",
|
|
893
|
+
// `rdfs:label`, matching the `name` the list publishes — the two-step
|
|
894
|
+
// grammar is that a row's `name` goes VERBATIM to lookup. Both halves
|
|
895
|
+
// REQUIRE the literal, so both are empty together rather than one
|
|
896
|
+
// publishing names the other cannot resolve.
|
|
897
|
+
by: "rdfs:label",
|
|
898
|
+
type: "dt:TokenSymbol",
|
|
899
|
+
description:
|
|
900
|
+
"Look up one or more token symbols by dotted name, IRI, or glob.",
|
|
901
|
+
toolDescription:
|
|
902
|
+
'Get one design-token symbol in full: its own type and description, every definition behind it with that definition\'s own type and description, the modifier families that may rebind it, and the value it resolves to at each position. Address it by the dotted name token_list publishes (`color.text`), by prefixed name, by IRI, or by a glob. Example: token_lookup { name: ["color.text"] }.',
|
|
903
|
+
fields: [
|
|
904
|
+
// Single-valued: a channel provisions exactly one symbol.
|
|
905
|
+
{
|
|
906
|
+
name: "channelOf",
|
|
907
|
+
property: "dt:channelOf/rdfs:label",
|
|
908
|
+
label: "Channel of",
|
|
909
|
+
},
|
|
910
|
+
// The same pair `token list` publishes, reached the same way: the head
|
|
911
|
+
// of a resolved value's chain is the definition that value was authored
|
|
912
|
+
// in, so these two read the symbol's OWN definition rather than
|
|
913
|
+
// sampling one of the twenty behind `color.text`.
|
|
914
|
+
//
|
|
915
|
+
// A lookup field is a property PATH, so it cannot spell the
|
|
916
|
+
// `FILTER NOT EXISTS` that restricts the list's walk to the BASE value,
|
|
917
|
+
// and here it does not have to. 354 symbols have more than one chain
|
|
918
|
+
// head — one per materialised position — and over the shipped corpus no
|
|
919
|
+
// symbol's heads name two types or two descriptions, so the path is
|
|
920
|
+
// multi-valued with one value repeated and `firstRowPerEntity` keeping
|
|
921
|
+
// the first is a choice between identical answers. Were a position's
|
|
922
|
+
// head ever to differ, the `definitions` expand is where the difference
|
|
923
|
+
// is readable, because it shows every definition APART.
|
|
924
|
+
{
|
|
925
|
+
name: "type",
|
|
926
|
+
property:
|
|
927
|
+
"^dt:forSymbol/dt:resolutionChain/rdf:first/dt:tokenType/rdfs:label",
|
|
928
|
+
label: "Type",
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
name: "description",
|
|
932
|
+
property:
|
|
933
|
+
"^dt:forSymbol/dt:resolutionChain/rdf:first/w3c-tokens:description",
|
|
934
|
+
label: "Description",
|
|
935
|
+
},
|
|
936
|
+
],
|
|
937
|
+
expand: [
|
|
938
|
+
{
|
|
939
|
+
name: "definitions",
|
|
940
|
+
heading: "Definitions",
|
|
941
|
+
kind: "table",
|
|
942
|
+
// The inverse edge: definitions point AT the symbol
|
|
943
|
+
// (`?definition dt:symbol ?uri`), so the relation from the symbol is
|
|
944
|
+
// `^dt:symbol`. 1,311 definitions stand behind 745 symbols.
|
|
945
|
+
relation: "^dt:symbol",
|
|
946
|
+
select: [
|
|
947
|
+
{ name: "file", property: "w3c-tokens:inFile/w3c-tokens:path" },
|
|
948
|
+
{ name: "type", property: "dt:tokenType/rdfs:label" },
|
|
949
|
+
{ name: "description", property: "w3c-tokens:description" },
|
|
950
|
+
],
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
name: "coverage",
|
|
954
|
+
heading: "Covered by",
|
|
955
|
+
// Coverage hangs on the FAMILY, not on the symbol
|
|
956
|
+
// (`?family dt:covers ?symbol`), so this is the inverse too. The
|
|
957
|
+
// family is a `ds:` entity, so its name comes from the
|
|
958
|
+
// design-system pack rather than the token ontology.
|
|
959
|
+
relation: "^dt:covers",
|
|
960
|
+
select: [{ name: "family", property: "ds:name" }],
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
name: "values",
|
|
964
|
+
heading: "Values",
|
|
965
|
+
kind: "table",
|
|
966
|
+
relation: "^dt:forSymbol",
|
|
967
|
+
// BOTH the chain and the derivation, for the reason `token values`
|
|
968
|
+
// states: the shape admits exactly one of them, and selecting only
|
|
969
|
+
// the chain would blank every channel routing.
|
|
970
|
+
//
|
|
971
|
+
// `rdf:first` and NOT `/rdf:rest*/rdf:first`, which is the walk
|
|
972
|
+
// `token values` uses. An expand's child field is a plain triple with
|
|
973
|
+
// no aggregate available, so a multi-hop chain multiplies the CHILD:
|
|
974
|
+
// 204 of the 1,072 values carry a chain of 2 or 3 links, and
|
|
975
|
+
// `color.background.container` rendered four "Values" rows for its
|
|
976
|
+
// two positions, each repeating the same value beside a different
|
|
977
|
+
// link. A caller counting positions would have read that as four.
|
|
978
|
+
// The head of the list is the definition the value was AUTHORED in
|
|
979
|
+
// (the tail is what it aliased through to a primitive), so one link
|
|
980
|
+
// per row is both correct and the most useful one; the full walk is
|
|
981
|
+
// `token values`, which can GROUP_CONCAT it into a single cell.
|
|
982
|
+
select: [
|
|
983
|
+
{ name: "position", property: "dt:coordinate" },
|
|
984
|
+
{ name: "value", property: "dt:resolvesTo" },
|
|
985
|
+
{ name: "chain", property: "dt:resolutionChain/rdf:first" },
|
|
986
|
+
{ name: "derivedFrom", property: "dt:derivedFrom/rdfs:label" },
|
|
987
|
+
],
|
|
988
|
+
},
|
|
989
|
+
],
|
|
990
|
+
sample: {
|
|
991
|
+
fixedCount: true,
|
|
992
|
+
toolDescription:
|
|
993
|
+
"Return random complete design-token symbols — definitions, coverage and resolved values — as exemplars. Use BEFORE writing queries to see real data shapes. Example: token_sample {}.",
|
|
994
|
+
},
|
|
995
|
+
},
|
|
996
|
+
},
|
|
997
|
+
|
|
998
|
+
// The platform VARIABLES — S4, the stylesheet's own names for the values.
|
|
999
|
+
//
|
|
1000
|
+
// A SECOND noun rather than a flag on `token`, and one measurement settles
|
|
1001
|
+
// it: 236 of the 1,156 variables stand for NO symbol at all — legacy twins
|
|
1002
|
+
// the ontology itself names, plus the computed states and resets.
|
|
1003
|
+
// `--disabled--color-text` and `--modifier-color-text` are nobody's symbol, so
|
|
1004
|
+
// a surface keyed on symbols cannot address them. The cut is by STRATUM ROLE,
|
|
1005
|
+
// not by platform: the platform is read out of the IRI base as an ordinary
|
|
1006
|
+
// filter, so a second platform's catalogue arrives as one more value of
|
|
1007
|
+
// `--platform` and not as a noun of its own.
|
|
1008
|
+
//
|
|
1009
|
+
// The published name is the label with its leading `--` STRIPPED, and that is
|
|
1010
|
+
// what makes the noun usable at all: `--color-text` cannot be typed as a
|
|
1011
|
+
// positional argument — the parser answers `unknown option '--color-text'`
|
|
1012
|
+
// and a glob is no escape. Upstream publishes the stripped form as
|
|
1013
|
+
// `rdfs:label`, and the stripping is measurably safe: over the 1,156
|
|
1014
|
+
// variables it produces 1,156 distinct names and collides with no symbol
|
|
1015
|
+
// name. `variable.parity.test.ts` pins both halves.
|
|
1016
|
+
{
|
|
1017
|
+
noun: "variable",
|
|
1018
|
+
description:
|
|
1019
|
+
"List the platform variables the design tokens are emitted as.",
|
|
1020
|
+
toolDescription:
|
|
1021
|
+
'List the platform VARIABLES a stylesheet declares as CSS custom properties, with the symbol each stands for, its tier, visibility and the coordinates it is selected at. 236 stand for no symbol, so token_list cannot reach them. Address one WITHOUT its leading dashes (`color-text`). Example: variable_list { symbol: "color.text" }.',
|
|
1022
|
+
list: {
|
|
1023
|
+
query: [
|
|
1024
|
+
"SELECT ?uri ?name ?platform ?symbol ?tier ?visibility",
|
|
1025
|
+
' (GROUP_CONCAT(DISTINCT ?coordinateName; SEPARATOR=" ") AS ?coordinate)',
|
|
1026
|
+
"WHERE {",
|
|
1027
|
+
" ?uri a dt:Variable ;",
|
|
1028
|
+
" rdfs:label ?name .",
|
|
1029
|
+
" OPTIONAL { ?uri dt:ofSymbol/rdfs:label ?symbol }",
|
|
1030
|
+
" OPTIONAL { ?uri dt:tier ?tierUri }",
|
|
1031
|
+
" OPTIONAL { ?uri dt:visibility ?visibilityUri }",
|
|
1032
|
+
// A variable is selected at a coordinate two ways, and both count: the
|
|
1033
|
+
// CONDITION its declaration sits under selects one
|
|
1034
|
+
// (`.success` → `criticality.success`), and a declaration may assert a
|
|
1035
|
+
// second directly (`dt:alsoAt`, which is `mode.dark` for all 261 of
|
|
1036
|
+
// them). 305 of the 1,156 variables reach at least one coordinate.
|
|
1037
|
+
" OPTIONAL {",
|
|
1038
|
+
" { ?uri dt:declaredAt/dt:under/dt:selectsCoordinate ?coordinateUri }",
|
|
1039
|
+
" UNION",
|
|
1040
|
+
" { ?uri dt:declaredAt/dt:alsoAt ?coordinateUri }",
|
|
1041
|
+
' BIND(REPLACE(REPLACE(STR(?coordinateUri), "^.*[/#]", ""), "^coordinate[.]", "") AS ?coordinateName)',
|
|
1042
|
+
" }",
|
|
1043
|
+
// The platform, read out of the IRI base rather than asserted: every
|
|
1044
|
+
// variable is minted under `…/s4/<platform>/`. STRAFTER/STRBEFORE
|
|
1045
|
+
// rather than a regex so a variable whose IRI carries no such segment
|
|
1046
|
+
// answers an EMPTY cell instead of its own full IRI, which is what a
|
|
1047
|
+
// failed REPLACE returns.
|
|
1048
|
+
' BIND(STRBEFORE(STRAFTER(STR(?uri), "/s4/"), "/") AS ?platform)',
|
|
1049
|
+
' BIND(REPLACE(REPLACE(STR(?tierUri), "^.*[/#]", ""), "^tier[.]", "") AS ?tier)',
|
|
1050
|
+
' BIND(REPLACE(REPLACE(STR(?visibilityUri), "^.*[/#]", ""), "^visibility[.]", "") AS ?visibility)',
|
|
1051
|
+
"}",
|
|
1052
|
+
"GROUP BY ?uri ?name ?platform ?symbol ?tier ?visibility",
|
|
1053
|
+
"ORDER BY ?name",
|
|
1054
|
+
].join("\n"),
|
|
1055
|
+
columns: [
|
|
355
1056
|
{ field: "name", label: "Name" },
|
|
356
|
-
{ field: "
|
|
1057
|
+
{ field: "symbol", label: "Symbol" },
|
|
1058
|
+
{ field: "tier", label: "Tier" },
|
|
1059
|
+
{ field: "visibility", label: "Visibility" },
|
|
1060
|
+
{ field: "platform", label: "Platform" },
|
|
1061
|
+
{ field: "coordinate", label: "Coordinates" },
|
|
1062
|
+
{ field: "uri", label: "IRI" },
|
|
1063
|
+
],
|
|
1064
|
+
filters: [
|
|
1065
|
+
{
|
|
1066
|
+
param: "platform",
|
|
1067
|
+
variable: "platform",
|
|
1068
|
+
// The vocabulary is a query over the IRI base, exactly as the column
|
|
1069
|
+
// is — the platform is not asserted anywhere, so the file identity
|
|
1070
|
+
// in the IRI is the only thing that states it. One value today
|
|
1071
|
+
// (`web`); a second platform's catalogue adds itself here with no
|
|
1072
|
+
// edit.
|
|
1073
|
+
vocabulary: {
|
|
1074
|
+
query: [
|
|
1075
|
+
"SELECT DISTINCT ?platform WHERE {",
|
|
1076
|
+
" ?v a dt:Variable .",
|
|
1077
|
+
' BIND(STRBEFORE(STRAFTER(STR(?v), "/s4/"), "/") AS ?platform)',
|
|
1078
|
+
"}",
|
|
1079
|
+
].join("\n"),
|
|
1080
|
+
},
|
|
1081
|
+
description: "Filter by platform.",
|
|
1082
|
+
},
|
|
1083
|
+
{
|
|
1084
|
+
param: "symbol",
|
|
1085
|
+
variable: "symbol",
|
|
1086
|
+
// The symbol roster, read the same way `token list`'s `channelOf`
|
|
1087
|
+
// filter reads it: every symbol, keyed on `rdfs:label`.
|
|
1088
|
+
vocabulary: {
|
|
1089
|
+
query: [
|
|
1090
|
+
"SELECT DISTINCT ?symbol WHERE {",
|
|
1091
|
+
" ?s a dt:TokenSymbol ;",
|
|
1092
|
+
" rdfs:label ?symbol .",
|
|
1093
|
+
"}",
|
|
1094
|
+
].join("\n"),
|
|
1095
|
+
},
|
|
1096
|
+
description: "Filter to one symbol.",
|
|
1097
|
+
},
|
|
1098
|
+
{
|
|
1099
|
+
param: "tier",
|
|
1100
|
+
variable: "tier",
|
|
1101
|
+
vocabulary: {
|
|
1102
|
+
query: [
|
|
1103
|
+
"SELECT DISTINCT ?tier WHERE {",
|
|
1104
|
+
" ?t a dt:Tier .",
|
|
1105
|
+
' BIND(REPLACE(REPLACE(STR(?t), "^.*[/#]", ""), "^tier[.]", "") AS ?tier)',
|
|
1106
|
+
"}",
|
|
1107
|
+
].join("\n"),
|
|
1108
|
+
},
|
|
1109
|
+
description: "Filter by tier.",
|
|
1110
|
+
},
|
|
1111
|
+
{
|
|
1112
|
+
param: "visibility",
|
|
1113
|
+
variable: "visibility",
|
|
1114
|
+
vocabulary: {
|
|
1115
|
+
query: [
|
|
1116
|
+
"SELECT DISTINCT ?visibility WHERE {",
|
|
1117
|
+
" ?v a dt:Visibility .",
|
|
1118
|
+
' BIND(REPLACE(REPLACE(STR(?v), "^.*[/#]", ""), "^visibility[.]", "") AS ?visibility)',
|
|
1119
|
+
"}",
|
|
1120
|
+
].join("\n"),
|
|
1121
|
+
},
|
|
1122
|
+
description: "Filter by visibility.",
|
|
1123
|
+
},
|
|
1124
|
+
{
|
|
1125
|
+
param: "coordinate",
|
|
1126
|
+
variable: "coordinate",
|
|
1127
|
+
// `set`, and it has to be: `--modifier-color-text` is selected at 17
|
|
1128
|
+
// coordinates at once, so its cell is the whole set its declarations
|
|
1129
|
+
// reach and a filter comparing the whole cell would answer for none
|
|
1130
|
+
// of them. The cell is a `GROUP_CONCAT`, so this predicate can only
|
|
1131
|
+
// run after aggregation — which is why the page wraps the query.
|
|
1132
|
+
match: "set",
|
|
1133
|
+
vocabulary: {
|
|
1134
|
+
query: [
|
|
1135
|
+
"SELECT DISTINCT ?coordinate WHERE {",
|
|
1136
|
+
" ?c a dt:Coordinate .",
|
|
1137
|
+
' BIND(REPLACE(REPLACE(STR(?c), "^.*[/#]", ""), "^coordinate[.]", "") AS ?coordinate)',
|
|
1138
|
+
"}",
|
|
1139
|
+
].join("\n"),
|
|
1140
|
+
},
|
|
1141
|
+
description: "Filter to one coordinate.",
|
|
1142
|
+
},
|
|
357
1143
|
],
|
|
1144
|
+
search: {
|
|
1145
|
+
variables: ["name", "symbol"],
|
|
1146
|
+
description: "Search name and symbol.",
|
|
1147
|
+
},
|
|
358
1148
|
emptyRecovery: {
|
|
359
1149
|
message:
|
|
360
|
-
"
|
|
1150
|
+
"Platform variables come from the @canonical/token-ontology pack, and a variable is only addressable once that pack publishes its name literals — a store built without that pack carries none.",
|
|
361
1151
|
cli: "sources update",
|
|
362
1152
|
},
|
|
363
1153
|
},
|
|
1154
|
+
verbs: [
|
|
1155
|
+
{
|
|
1156
|
+
verb: "chain",
|
|
1157
|
+
description:
|
|
1158
|
+
"List the walk from a variable to every symbol it reaches, through every variable in between.",
|
|
1159
|
+
toolDescription:
|
|
1160
|
+
'List the resolution WALK: every (variable, symbol) pair a variable reaches through what its declarations reference, transitively — what a variable finally means. The closure runs over every declaration of every hop, so one variable can reach dozens of pairs. Example: variable_chain { variable: "modifier-color-text" }.',
|
|
1161
|
+
// ONE property path carries the whole walk, which is why this is a
|
|
1162
|
+
// query and not a traversal in code. `dt:references` is an rdf:List of
|
|
1163
|
+
// the variables a declaration's value reads, so each hop is
|
|
1164
|
+
// `dt:declaredAt/dt:references/rdf:rest*/rdf:first`, and the `+` makes
|
|
1165
|
+
// the whole thing transitive. The terminal is a variable that stands
|
|
1166
|
+
// for a symbol, which is what `dt:ofSymbol` reads.
|
|
1167
|
+
query: [
|
|
1168
|
+
"SELECT ?variable ?reaches ?symbol",
|
|
1169
|
+
"WHERE {",
|
|
1170
|
+
" ?uri a dt:Variable ;",
|
|
1171
|
+
" rdfs:label ?variable .",
|
|
1172
|
+
" ?uri (dt:declaredAt/dt:references/rdf:rest*/rdf:first)+ ?reachedUri .",
|
|
1173
|
+
" ?reachedUri dt:ofSymbol ?symbolUri ;",
|
|
1174
|
+
" rdfs:label ?reaches .",
|
|
1175
|
+
" ?symbolUri rdfs:label ?symbol .",
|
|
1176
|
+
"}",
|
|
1177
|
+
"ORDER BY ?variable ?reaches ?symbol",
|
|
1178
|
+
].join("\n"),
|
|
1179
|
+
columns: [
|
|
1180
|
+
{ field: "variable", label: "Variable" },
|
|
1181
|
+
{ field: "reaches", label: "Reaches" },
|
|
1182
|
+
{ field: "symbol", label: "Symbol" },
|
|
1183
|
+
],
|
|
1184
|
+
filters: [
|
|
1185
|
+
{
|
|
1186
|
+
param: "variable",
|
|
1187
|
+
variable: "variable",
|
|
1188
|
+
// The variable roster, keyed on the same `rdfs:label` the column
|
|
1189
|
+
// binds and the lookup resolves by — the CSS name with its leading
|
|
1190
|
+
// `--` already stripped, which is the only form typable as a
|
|
1191
|
+
// positional. `variable.parity.test.ts` pins that the stripping is
|
|
1192
|
+
// injective and collides with no symbol name.
|
|
1193
|
+
vocabulary: {
|
|
1194
|
+
query: [
|
|
1195
|
+
"SELECT DISTINCT ?variable WHERE {",
|
|
1196
|
+
" ?v a dt:Variable ;",
|
|
1197
|
+
" rdfs:label ?variable .",
|
|
1198
|
+
"}",
|
|
1199
|
+
].join("\n"),
|
|
1200
|
+
},
|
|
1201
|
+
description: "Filter to one variable.",
|
|
1202
|
+
},
|
|
1203
|
+
{
|
|
1204
|
+
param: "symbol",
|
|
1205
|
+
variable: "symbol",
|
|
1206
|
+
vocabulary: {
|
|
1207
|
+
query: [
|
|
1208
|
+
"SELECT DISTINCT ?symbol WHERE {",
|
|
1209
|
+
" ?s a dt:TokenSymbol ;",
|
|
1210
|
+
" rdfs:label ?symbol .",
|
|
1211
|
+
"}",
|
|
1212
|
+
].join("\n"),
|
|
1213
|
+
},
|
|
1214
|
+
description: "Filter to one symbol.",
|
|
1215
|
+
},
|
|
1216
|
+
],
|
|
1217
|
+
emptyRecovery: {
|
|
1218
|
+
message:
|
|
1219
|
+
"A resolution walk follows the declarations the @canonical/token-ontology pack provides, and the walk is only addressable by name once that pack publishes its name literals — a store built without that pack carries none.",
|
|
1220
|
+
cli: "sources update",
|
|
1221
|
+
},
|
|
1222
|
+
},
|
|
1223
|
+
],
|
|
364
1224
|
lookup: {
|
|
365
1225
|
source: "sparql",
|
|
366
|
-
|
|
367
|
-
|
|
1226
|
+
// `rdfs:label`, matching the `name` the list publishes, and with NO
|
|
1227
|
+
// `nameFallback` for the same reason `token` has none: the kernel's IRI
|
|
1228
|
+
// derivation would publish `--color-text` with its dashes intact and its
|
|
1229
|
+
// dots as slashes, and a `--`-prefixed positional cannot be typed at all.
|
|
1230
|
+
by: "rdfs:label",
|
|
1231
|
+
type: "dt:Variable",
|
|
1232
|
+
description:
|
|
1233
|
+
"Look up one or more platform variables by name (without the leading dashes), IRI, or glob.",
|
|
368
1234
|
toolDescription:
|
|
369
|
-
'Get
|
|
1235
|
+
'Get one platform variable in full: its symbol, tier, visibility, and EVERY place it is declared — the selector and at-rule stack, the emitted value, the source location, the coordinate it also applies at, and the derivation. Address it by the CSS name WITHOUT its leading dashes (`color-text`). Example: variable_lookup { name: ["color-text"] }.',
|
|
370
1236
|
fields: [
|
|
1237
|
+
{ name: "symbol", property: "dt:ofSymbol/rdfs:label", label: "Symbol" },
|
|
1238
|
+
{ name: "tier", property: "dt:tier", label: "Tier" },
|
|
1239
|
+
{ name: "visibility", property: "dt:visibility", label: "Visibility" },
|
|
1240
|
+
],
|
|
1241
|
+
expand: [
|
|
371
1242
|
{
|
|
372
|
-
name: "
|
|
373
|
-
|
|
374
|
-
|
|
1243
|
+
name: "declarations",
|
|
1244
|
+
heading: "Declarations",
|
|
1245
|
+
kind: "table",
|
|
1246
|
+
relation: "dt:declaredAt",
|
|
1247
|
+
// 927 variables are declared once; the rest up to 17 times, which is
|
|
1248
|
+
// why this is an expand and not a set of fields.
|
|
1249
|
+
select: [
|
|
1250
|
+
{ name: "under", property: "dt:under" },
|
|
1251
|
+
{ name: "selector", property: "dt:under/dt-web:selector" },
|
|
1252
|
+
// The at-rule STACK, not one at-rule: `dt-web:inAtRule` is an
|
|
1253
|
+
// rdf:List, so the walk is `/rdf:rest*/rdf:first`. One condition of
|
|
1254
|
+
// the 31 nests two levels deep and so contributes two rows for one
|
|
1255
|
+
// declaration — that is the stack, read outermost-in, rather than a
|
|
1256
|
+
// duplicate.
|
|
1257
|
+
{
|
|
1258
|
+
name: "inAtRule",
|
|
1259
|
+
property: "dt:under/dt-web:inAtRule/rdf:rest*/rdf:first",
|
|
1260
|
+
},
|
|
1261
|
+
{ name: "emits", property: "dt:emits" },
|
|
1262
|
+
// `dt:at` is the SOURCE LOCATION (`modifiers.theme.css:322`), not a
|
|
1263
|
+
// coordinate; `dt:alsoAt` is the coordinate. The two read alike and
|
|
1264
|
+
// mean different things, which is why both are labelled.
|
|
1265
|
+
{ name: "at", property: "dt:at", label: "source" },
|
|
1266
|
+
{ name: "alsoAt", property: "dt:alsoAt", label: "alsoAt" },
|
|
1267
|
+
{ name: "derives", property: "dt:derives" },
|
|
1268
|
+
],
|
|
375
1269
|
},
|
|
376
|
-
{ name: "valueLight", property: "ds:valueLight", label: "Light value" },
|
|
377
|
-
{ name: "valueDark", property: "ds:valueDark", label: "Dark value" },
|
|
378
1270
|
],
|
|
379
1271
|
sample: {
|
|
380
1272
|
fixedCount: true,
|
|
381
1273
|
toolDescription:
|
|
382
|
-
"Return
|
|
1274
|
+
"Return random complete platform variables — symbol, tier, visibility and every declaration — as exemplars. Use BEFORE writing queries to see real data shapes. Example: variable_sample {}.",
|
|
383
1275
|
},
|
|
384
1276
|
},
|
|
385
1277
|
},
|
|
@@ -394,6 +1286,16 @@ const designSystemStories: readonly PackDefinition[] = [
|
|
|
394
1286
|
description: "List all modifier families.",
|
|
395
1287
|
toolDescription:
|
|
396
1288
|
"List all modifier families with their values. Use when browsing which modifier families exist and the values each allows. Example: modifier_list {}.",
|
|
1289
|
+
// Tiered like blocks — 11 of the modifier families carry a `ds:tier` — so
|
|
1290
|
+
// the same scope, declared with the same four terms. The scope is per NOUN
|
|
1291
|
+
// because being tiered is a fact about the entities, and the design
|
|
1292
|
+
// system's token symbols and code standards carry nothing of the kind.
|
|
1293
|
+
tierScope: {
|
|
1294
|
+
type: "ds:Tier",
|
|
1295
|
+
via: "ds:tier",
|
|
1296
|
+
by: "ds:name",
|
|
1297
|
+
base: "ds:global",
|
|
1298
|
+
},
|
|
397
1299
|
list: {
|
|
398
1300
|
query: [
|
|
399
1301
|
"SELECT ?uri ?name",
|
|
@@ -454,7 +1356,7 @@ const designSystemStories: readonly PackDefinition[] = [
|
|
|
454
1356
|
noun: "tier",
|
|
455
1357
|
description: "List all tiers in the design system ontology.",
|
|
456
1358
|
toolDescription:
|
|
457
|
-
"List all tiers in the design-system ontology. Use when
|
|
1359
|
+
"List all tiers in the design-system ontology. Use when picking the tier to read with: the `tier` parameter scopes a read to one tier plus its ancestors, and this list is never scoped itself. Example: tier_list {}.",
|
|
458
1360
|
list: {
|
|
459
1361
|
query: [
|
|
460
1362
|
"SELECT ?uri ?name WHERE {",
|
|
@@ -498,6 +1400,16 @@ const conceptStory: PackDefinition = {
|
|
|
498
1400
|
description: "List design-system concepts.",
|
|
499
1401
|
toolDescription:
|
|
500
1402
|
'List design-system concepts — long-form foundations, how-to guides, and decision guides not bound to a single UI block. Optionally filter by type or search. Example: concept_list { type: "Explanation" }.',
|
|
1403
|
+
// Concepts carry a `ds:tier` too (4 of them do), so they are scoped on the
|
|
1404
|
+
// same terms as blocks and modifier families. Its `list` publishes no tier
|
|
1405
|
+
// COLUMN and does not need to: the scope constrains the entity through
|
|
1406
|
+
// `ds:tier`, not a projected cell.
|
|
1407
|
+
tierScope: {
|
|
1408
|
+
type: "ds:Tier",
|
|
1409
|
+
via: "ds:tier",
|
|
1410
|
+
by: "ds:name",
|
|
1411
|
+
base: "ds:global",
|
|
1412
|
+
},
|
|
501
1413
|
list: {
|
|
502
1414
|
query: [
|
|
503
1415
|
"SELECT ?uri ?name ?type ?summary",
|
|
@@ -542,7 +1454,7 @@ const conceptStory: PackDefinition = {
|
|
|
542
1454
|
},
|
|
543
1455
|
emptyRecovery: {
|
|
544
1456
|
message:
|
|
545
|
-
"
|
|
1457
|
+
"Concepts come from the @canonical/design-system pack, and a local store built without it carries none — refresh it.",
|
|
546
1458
|
cli: "sources update",
|
|
547
1459
|
},
|
|
548
1460
|
},
|
|
@@ -671,7 +1583,7 @@ const implementationStory: PackDefinition = {
|
|
|
671
1583
|
},
|
|
672
1584
|
emptyRecovery: {
|
|
673
1585
|
message:
|
|
674
|
-
"
|
|
1586
|
+
"Implementations come from the @canonical/ds-implementations pack, and a local store built without it carries none — refresh it.",
|
|
675
1587
|
cli: "sources update",
|
|
676
1588
|
},
|
|
677
1589
|
},
|
|
@@ -871,10 +1783,23 @@ const codeStandardsStories: readonly PackDefinition[] = [
|
|
|
871
1783
|
// because a pack is data — a future release that drops a label should
|
|
872
1784
|
// degrade to the IRI-derived name, not become unaddressable.
|
|
873
1785
|
//
|
|
874
|
-
// Deliberately NOT declared on `
|
|
875
|
-
// those lists REQUIRES its `by` property, so an entity without
|
|
876
|
-
// row they never publish, and making it addressable (or
|
|
877
|
-
// would be the mirror of the defect this repairs.
|
|
1786
|
+
// Deliberately NOT declared on `token`/`modifier`/`tier`/`concept`:
|
|
1787
|
+
// each of those lists REQUIRES its `by` property, so an entity without
|
|
1788
|
+
// one is a row they never publish, and making it addressable (or
|
|
1789
|
+
// sampleable) here would be the mirror of the defect this repairs.
|
|
1790
|
+
//
|
|
1791
|
+
// `block` is NOT in that set, though an earlier version of this comment
|
|
1792
|
+
// claimed it was: its list COALESCEs an OPTIONAL `ds:name` with an
|
|
1793
|
+
// IRI-derived fallback, so a block without a `ds:name` WOULD be
|
|
1794
|
+
// published under a name its lookup cannot resolve. Every shipped block
|
|
1795
|
+
// carries `ds:name` today, so the divergence is latent — and pinned:
|
|
1796
|
+
// `listLookup.shipped.exec.test.ts` runs the whole corpus through both
|
|
1797
|
+
// halves on every test run, and goes red the moment upstream ships an
|
|
1798
|
+
// unnamed block. Fix it THEN, by choosing deliberately between requiring
|
|
1799
|
+
// the name in the list and declaring a fallback pair whose derivations
|
|
1800
|
+
// actually agree (the list keeps the IRI's dots; the shared
|
|
1801
|
+
// `nameFallback` derivation converts them to slashes — declaring the
|
|
1802
|
+
// fallback alone would trade one mismatch for another).
|
|
878
1803
|
nameFallback: "iri",
|
|
879
1804
|
type: "cs:CodeStandard",
|
|
880
1805
|
description:
|
|
@@ -982,7 +1907,20 @@ Made by the Canonical Webteam — https://canonical.com.`,
|
|
|
982
1907
|
name: "@canonical/anatomy-dsl",
|
|
983
1908
|
source: "git+https://github.com/canonical/anatomy-dsl.git#main",
|
|
984
1909
|
},
|
|
985
|
-
//
|
|
1910
|
+
// The design-token semantic model: the authored `dt:` / `w3c-tokens:`
|
|
1911
|
+
// ontology in `definitions/` plus the generated strata in `data/`.
|
|
1912
|
+
//
|
|
1913
|
+
// The only source here carrying a SUBDIRECTORY, and it needs one: this
|
|
1914
|
+
// package lives inside a monorepo, at `packages/token-ontology`, while a
|
|
1915
|
+
// git source names a repository. `readTtlSources` scans
|
|
1916
|
+
// `<root>/definitions` and `<root>/data`, which the design-tokens repo
|
|
1917
|
+
// root does not have — so without the subdirectory this would clone
|
|
1918
|
+
// cleanly and contribute nothing.
|
|
1919
|
+
{
|
|
1920
|
+
name: "@canonical/token-ontology",
|
|
1921
|
+
source:
|
|
1922
|
+
"git+https://github.com/canonical/design-tokens.git#main:packages/token-ontology",
|
|
1923
|
+
},
|
|
986
1924
|
// pack an agent is most likely to quote back at a human as policy, so which
|
|
987
1925
|
// revision answered a query has to be recoverable — a floating ref makes
|
|
988
1926
|
// "the CLI told me this was the rule" unfalsifiable. The other three still
|
|
@@ -1023,6 +1961,11 @@ Made by the Canonical Webteam — https://canonical.com.`,
|
|
|
1023
1961
|
// `cs:` is listed even though nothing rebinds it upstream.
|
|
1024
1962
|
prefixes: {
|
|
1025
1963
|
ds: "https://ds.canonical.com/",
|
|
1964
|
+
dt: "https://dt.canonical.com/",
|
|
1965
|
+
// Nested UNDER `dt:`, and both must be bound: `compactUri` takes the
|
|
1966
|
+
// longest match, so binding only the parent would render every term of
|
|
1967
|
+
// this vocabulary as `dt:w3c-tokens/…`.
|
|
1968
|
+
"w3c-tokens": "https://dt.canonical.com/w3c-tokens/",
|
|
1026
1969
|
cs: "http://pragma.canonical.com/codestandards#",
|
|
1027
1970
|
},
|
|
1028
1971
|
channel: "normal",
|