create-kerf-component 5.0.0-beta.9 → 6.0.0-beta.1

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.
@@ -0,0 +1,282 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raw.githubusercontent.com/brianwestphal/kerf/main/create-kerf-component/component-metadata.schema.json",
4
+ "title": "Kerf consumer component metadata source",
5
+ "type": "object",
6
+ "required": ["schemaVersion", "components"],
7
+ "properties": {
8
+ "$schema": { "type": "string" },
9
+ "schemaVersion": { "const": 1 },
10
+ "componentCatalog": {
11
+ "type": "string",
12
+ "minLength": 1,
13
+ "description": "Relative path to the package's component (selection) catalog, copied into the generated composition catalog's compatibility.componentCatalog; defaults to \"not-applicable\"."
14
+ },
15
+ "components": {
16
+ "type": "array",
17
+ "items": { "$ref": "#/$defs/component" }
18
+ }
19
+ },
20
+ "additionalProperties": false,
21
+ "$defs": {
22
+ "stateAttribute": {
23
+ "type": "object",
24
+ "required": ["name", "on", "helper", "meaning"],
25
+ "properties": {
26
+ "name": {
27
+ "type": "string",
28
+ "minLength": 1,
29
+ "pattern": "^data-[a-z0-9]+(-[a-z0-9]+)*$"
30
+ },
31
+ "on": {
32
+ "type": "string",
33
+ "minLength": 1,
34
+ "description": "The element that carries it: a public class, or the element passed to the helper."
35
+ },
36
+ "helper": {
37
+ "type": "string",
38
+ "minLength": 1,
39
+ "description": "The helper, one of wiring.helpers, that writes it."
40
+ },
41
+ "meaning": {
42
+ "type": "string",
43
+ "minLength": 1,
44
+ "description": "What its presence or value means."
45
+ }
46
+ },
47
+ "additionalProperties": false
48
+ },
49
+ "stringList": {
50
+ "type": "array",
51
+ "items": { "type": "string", "minLength": 1 },
52
+ "uniqueItems": true
53
+ },
54
+ "cardinality": {
55
+ "type": "object",
56
+ "required": ["min", "max"],
57
+ "properties": {
58
+ "min": { "type": "integer", "minimum": 0 },
59
+ "max": {
60
+ "anyOf": [
61
+ { "type": "integer", "minimum": 1 },
62
+ { "const": "unbounded" }
63
+ ]
64
+ }
65
+ },
66
+ "additionalProperties": false
67
+ },
68
+ "diagnostic": {
69
+ "type": "object",
70
+ "required": ["id", "severity", "when", "message"],
71
+ "properties": {
72
+ "id": { "type": "string", "pattern": "^KUI-C[0-9]{3}$" },
73
+ "severity": { "enum": ["error", "warning"] },
74
+ "when": { "type": "string", "minLength": 1 },
75
+ "message": { "type": "string", "minLength": 1 }
76
+ },
77
+ "additionalProperties": false
78
+ },
79
+ "component": {
80
+ "type": "object",
81
+ "required": [
82
+ "id",
83
+ "name",
84
+ "kind",
85
+ "purpose",
86
+ "source",
87
+ "publicExports",
88
+ "sourceLinks",
89
+ "composition",
90
+ "boundaries",
91
+ "accessibility",
92
+ "diagnostics",
93
+ "provenance"
94
+ ],
95
+ "properties": {
96
+ "id": { "type": "string", "minLength": 1 },
97
+ "name": { "type": "string", "minLength": 1 },
98
+ "kind": { "enum": ["component", "composition", "recipe"] },
99
+ "purpose": { "type": "string", "minLength": 1 },
100
+ "source": { "type": "string", "minLength": 1 },
101
+ "publicExports": {
102
+ "type": "array",
103
+ "minItems": 1,
104
+ "description": "Each export's name and package.json#exports subpath. A private application (package.json#private) may omit subpath; the name is then verified against the component's source file.",
105
+ "items": {
106
+ "type": "object",
107
+ "required": ["name"],
108
+ "properties": {
109
+ "name": { "type": "string", "minLength": 1 },
110
+ "subpath": { "type": "string", "pattern": "^\\." }
111
+ },
112
+ "additionalProperties": false
113
+ }
114
+ },
115
+ "sourceLinks": { "$ref": "#/$defs/stringList" },
116
+ "composition": { "$ref": "#/$defs/composition" },
117
+ "boundaries": {
118
+ "type": "object",
119
+ "required": ["rootClass", "publicClasses", "publicTokens"],
120
+ "properties": {
121
+ "rootClass": {
122
+ "oneOf": [
123
+ { "type": "string", "minLength": 1 },
124
+ { "type": "null" }
125
+ ]
126
+ },
127
+ "publicClasses": { "$ref": "#/$defs/stringList" },
128
+ "placeableClasses": {
129
+ "$ref": "#/$defs/stringList",
130
+ "description": "The subset of publicClasses an application may place on its own elements (a layout utility, item geometry on another carrier). Absent means none: every public class is the component's rendered anatomy, which eslint-plugin-kerfjs reports on an application-owned element as KUI-L103 with the component to render."
131
+ },
132
+ "rootElement": {
133
+ "type": "string",
134
+ "pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$",
135
+ "description": "The intrinsic element the component renders around its own placeableClasses. A placeable class on a plain element of this tag is the component recreated (KUI-L103); another carrier element keeps it. Requires placeableClasses."
136
+ },
137
+ "publicTokens": { "$ref": "#/$defs/stringList" }
138
+ },
139
+ "additionalProperties": false
140
+ },
141
+ "accessibility": {
142
+ "type": "object",
143
+ "required": ["obligations"],
144
+ "properties": { "obligations": { "$ref": "#/$defs/stringList" } },
145
+ "additionalProperties": false
146
+ },
147
+ "diagnostics": {
148
+ "type": "array",
149
+ "items": { "$ref": "#/$defs/diagnostic" }
150
+ },
151
+ "provenance": {
152
+ "type": "object",
153
+ "required": ["selection", "composition"],
154
+ "properties": {
155
+ "selection": { "type": "string", "minLength": 1 },
156
+ "composition": { "type": "string", "minLength": 1 }
157
+ },
158
+ "additionalProperties": false
159
+ }
160
+ },
161
+ "additionalProperties": false
162
+ },
163
+ "composition": {
164
+ "type": "object",
165
+ "required": [
166
+ "parents",
167
+ "contexts",
168
+ "zones",
169
+ "children",
170
+ "state",
171
+ "wiring",
172
+ "responsive",
173
+ "layout"
174
+ ],
175
+ "properties": {
176
+ "rendersAs": {
177
+ "description": "For a wrapper component: the cataloged roots it renders (package-qualified keys such as @kerfjs/ui:toolbar-control-group), any one of them or nothing. UI composition checks treat the wrapper as each declared root.",
178
+ "type": "array",
179
+ "minItems": 1,
180
+ "items": { "type": "string", "pattern": "^[^:]+:[^:]+$" },
181
+ "uniqueItems": true
182
+ },
183
+ "parents": {
184
+ "type": "object",
185
+ "required": ["mode", "entries"],
186
+ "properties": {
187
+ "mode": { "enum": ["any", "root", "listed"] },
188
+ "entries": { "$ref": "#/$defs/stringList" }
189
+ },
190
+ "additionalProperties": false
191
+ },
192
+ "contexts": { "$ref": "#/$defs/stringList" },
193
+ "zones": {
194
+ "type": "array",
195
+ "items": {
196
+ "type": "object",
197
+ "required": ["id", "accepts", "cardinality", "exclusiveWith"],
198
+ "properties": {
199
+ "id": { "type": "string", "minLength": 1 },
200
+ "accepts": { "$ref": "#/$defs/stringList" },
201
+ "cardinality": { "$ref": "#/$defs/cardinality" },
202
+ "exclusiveWith": { "$ref": "#/$defs/stringList" }
203
+ },
204
+ "additionalProperties": false
205
+ }
206
+ },
207
+ "children": {
208
+ "type": "object",
209
+ "required": ["mode", "concepts", "requiredConcepts"],
210
+ "properties": {
211
+ "mode": { "enum": ["any", "none", "listed"] },
212
+ "concepts": { "$ref": "#/$defs/stringList" },
213
+ "requiredConcepts": { "$ref": "#/$defs/stringList" }
214
+ },
215
+ "additionalProperties": false
216
+ },
217
+ "state": {
218
+ "type": "array",
219
+ "items": {
220
+ "type": "object",
221
+ "required": ["id", "owner", "required"],
222
+ "properties": {
223
+ "id": { "type": "string", "minLength": 1 },
224
+ "owner": { "enum": ["application", "controlled", "component"] },
225
+ "required": { "type": "boolean" }
226
+ },
227
+ "additionalProperties": false
228
+ }
229
+ },
230
+ "wiring": {
231
+ "type": "object",
232
+ "required": ["required", "helpers", "obligations"],
233
+ "properties": {
234
+ "required": { "type": "boolean" },
235
+ "helpers": { "$ref": "#/$defs/stringList" },
236
+ "obligations": { "$ref": "#/$defs/stringList" },
237
+ "stateAttributes": {
238
+ "description": "Optional wiring-owned state attributes: data-* attributes a wiring helper writes at runtime, which the application must not render, remove, or treat as its own state.",
239
+ "type": "array",
240
+ "items": { "$ref": "#/$defs/stateAttribute" }
241
+ }
242
+ },
243
+ "additionalProperties": false
244
+ },
245
+ "responsive": {
246
+ "type": "object",
247
+ "required": ["owner", "behaviors"],
248
+ "properties": {
249
+ "owner": {
250
+ "enum": ["application", "component", "shared", "not-applicable"]
251
+ },
252
+ "behaviors": { "$ref": "#/$defs/stringList" }
253
+ },
254
+ "additionalProperties": false
255
+ },
256
+ "layout": {
257
+ "type": "object",
258
+ "required": ["roles", "geometry"],
259
+ "properties": {
260
+ "roles": { "$ref": "#/$defs/stringList" },
261
+ "geometry": {
262
+ "type": "object",
263
+ "required": ["margin", "border", "padding"],
264
+ "properties": {
265
+ "margin": { "$ref": "#/$defs/geometryOwner" },
266
+ "border": { "$ref": "#/$defs/geometryOwner" },
267
+ "padding": { "$ref": "#/$defs/geometryOwner" },
268
+ "notes": { "$ref": "#/$defs/stringList" }
269
+ },
270
+ "additionalProperties": false
271
+ }
272
+ },
273
+ "additionalProperties": false
274
+ }
275
+ },
276
+ "additionalProperties": false
277
+ },
278
+ "geometryOwner": {
279
+ "enum": ["self", "parent", "child", "none", "conditional", "composed"]
280
+ }
281
+ }
282
+ }
package/index.js CHANGED
@@ -17,8 +17,18 @@
17
17
  // kerf-component` alone just works. No third-party dependencies — the
18
18
  // initializer is plain Node so `npm create` runs it with zero install latency.
19
19
 
20
- import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
20
+ import {
21
+ copyFileSync,
22
+ cpSync,
23
+ existsSync,
24
+ mkdirSync,
25
+ readdirSync,
26
+ readFileSync,
27
+ renameSync,
28
+ writeFileSync,
29
+ } from 'node:fs';
21
30
  import { basename, dirname, join, resolve } from 'node:path';
31
+ import process from 'node:process';
22
32
  import { createInterface } from 'node:readline/promises';
23
33
  import { fileURLToPath } from 'node:url';
24
34
 
@@ -41,7 +51,9 @@ const USAGE =
41
51
  async function promptForTarget() {
42
52
  const rl = createInterface({ input: process.stdin, output: process.stdout });
43
53
  try {
44
- const answer = await rl.question(`Directory (\`.\` for current) [${DEFAULT_NAME}]: `);
54
+ const answer = await rl.question(
55
+ `Directory (\`.\` for current) [${DEFAULT_NAME}]: `,
56
+ );
45
57
  return answer.trim() || DEFAULT_NAME;
46
58
  } finally {
47
59
  rl.close();
@@ -117,6 +129,19 @@ async function main(argv) {
117
129
  // verbatim (`_gitignore` → `.gitignore`).
118
130
  mkdirSync(targetDir, { recursive: true });
119
131
  cpSync(TEMPLATE_DIR, targetDir, { recursive: true });
132
+ mkdirSync(join(targetDir, 'scripts'), { recursive: true });
133
+ copyFileSync(
134
+ join(dirname(fileURLToPath(import.meta.url)), 'catalog.js'),
135
+ join(targetDir, 'scripts', 'kerf-component-catalog.mjs'),
136
+ );
137
+ for (const schema of [
138
+ 'component-metadata.schema.json',
139
+ 'component-composition.schema.json',
140
+ ])
141
+ copyFileSync(
142
+ join(dirname(fileURLToPath(import.meta.url)), schema),
143
+ join(targetDir, 'scripts', schema),
144
+ );
120
145
 
121
146
  for (const file of walk(targetDir)) {
122
147
  const text = readFileSync(file, 'utf8');
@@ -136,8 +161,10 @@ async function main(argv) {
136
161
  cdHint +
137
162
  ' npm install\n' +
138
163
  ' npm run build # tsup → ESM + .d.ts (kerfjs stays external)\n' +
164
+ ' npm run catalog:check # verify AI metadata and public exports\n' +
165
+ ' npm run check:styles # each component styles only itself (kerf-ui-analyze)\n' +
139
166
  ' npm run typecheck\n\n' +
140
- 'Edit src/counter.tsx, then publish with `npm publish --access public`.\n',
167
+ 'Edit src/counter.tsx, src/counter.css, and kerf.components.json, then publish with `npm publish --access public`.\n',
141
168
  );
142
169
  }
143
170
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-kerf-component",
3
- "version": "5.0.0-beta.9",
3
+ "version": "6.0.0-beta.1",
4
4
  "description": "Scaffold a publishable kerf component package that already follows kerf's hard packaging rules.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -26,15 +26,22 @@
26
26
  "node": ">=18.0.0"
27
27
  },
28
28
  "bin": {
29
- "create-kerf-component": "index.js"
29
+ "create-kerf-component": "index.js",
30
+ "kerf-component-catalog": "catalog.js"
30
31
  },
31
32
  "files": [
32
33
  "index.js",
34
+ "catalog.js",
35
+ "component-metadata.schema.json",
36
+ "component-composition.schema.json",
33
37
  "template",
34
38
  "README.md",
35
39
  "LICENSE"
36
40
  ],
37
41
  "scripts": {
38
42
  "test": "node --test tests/*.test.js"
43
+ },
44
+ "dependencies": {
45
+ "typescript": "^5.0.0 || ^6.0.0"
39
46
  }
40
47
  }
@@ -1,4 +1,4 @@
1
- # __PKG_NAME__
1
+ # **PKG_NAME**
2
2
 
3
3
  A reusable [kerf](https://github.com/brianwestphal/kerf) component package,
4
4
  scaffolded with `create-kerf-component`.
@@ -7,8 +7,10 @@ scaffolded with `create-kerf-component`.
7
7
 
8
8
  ```bash
9
9
  npm install
10
- npm run build # tsup → dist/ (ESM + .d.ts); kerfjs stays external
10
+ npm run build # tsup → dist/ (ESM + .d.ts); kerfjs stays external
11
11
  npm run typecheck
12
+ npm run catalog:check # verify component-composition.json is current
13
+ npm run check:styles # each component styles only itself (kerf-ui-analyze)
12
14
  ```
13
15
 
14
16
  ## Use it
@@ -17,13 +19,14 @@ A kerf app that already has `jsxImportSource: "kerfjs"` configured can import an
17
19
  render the component like any local function — there's no extra toolchain:
18
20
 
19
21
  ```tsx
20
- import { mount } from 'kerfjs';
21
- import { Counter, createCounter, wireCounter } from '__PKG_NAME__';
22
+ import { mount } from "kerfjs";
23
+ import { Counter, createCounter, wireCounter } from "__PKG_NAME__";
24
+ import "__PKG_NAME__/counter.css";
22
25
 
23
- const counter = createCounter(0); // per-instance state (a factory)
24
- const root = document.getElementById('app')!;
26
+ const counter = createCounter(0); // per-instance state (a factory)
27
+ const root = document.getElementById("app")!;
25
28
 
26
- mount(root, () => <Counter store={counter} label="Clicks" />);
29
+ mount(root, () => <Counter store={counter} label="Clicks" size="compact" />);
27
30
 
28
31
  const dispose = wireCounter(root, counter); // delegation disposer (call on teardown)
29
32
  ```
@@ -31,7 +34,7 @@ const dispose = wireCounter(root, counter); // delegation disposer (call on tear
31
34
  ## The rules this package follows
32
35
 
33
36
  These are kerf's hard packaging rules (see the kerf docs,
34
- *Building reusable component packages*). The scaffold encodes them so you don't
37
+ _Building reusable component packages_). The scaffold encodes them so you don't
35
38
  have to:
36
39
 
37
40
  - **`kerfjs` is a `peerDependency` and is `external` in the build — never
@@ -43,9 +46,17 @@ have to:
43
46
  - **No inline JSX event handlers.** Components are pure `(props) => SafeHtml`
44
47
  string-builders; emit `data-action` hooks and let the host wire events with
45
48
  `delegate()` (see `wireCounter`), which returns a disposer.
49
+ - **Each component owns its styles; configure, never override.** `counter.css`
50
+ styles only `.kerf-counter` and its own internals and writes only
51
+ `--_kerf-counter-*` private variables (context it provides is named after
52
+ Counter). Consumers configure it through props (`size`) and its public token
53
+ (`--kerf-counter-gap`); when it must adapt inside a parent, Counter does so
54
+ in its own stylesheet (`.kui-toolbar .kerf-counter`). A needed variation with
55
+ no prop is a gap to add here, not an override for consumers.
56
+ `npm run check:styles` enforces this with `kerf-ui-analyze`.
46
57
  - **Build emits ESM + `.d.ts`; `tsconfig` sets `jsxImportSource: "kerfjs"`.**
47
58
  - **Never import `kerfjs/dev`.** kerf's dev diagnostics install global hooks, so
48
- installing them is the consuming *app's* call, not a library's — the app
59
+ installing them is the consuming _app's_ call, not a library's — the app
49
60
  writes `if (import.meta.env.DEV) await import('kerfjs/dev')` in its own entry.
50
61
  To get the diagnostics while developing this package, add that line to your own
51
62
  test harness or demo page instead (it belongs to the harness, not to `src/`).
@@ -56,4 +67,36 @@ have to:
56
67
  npm publish --access public
57
68
  ```
58
69
 
59
- `prepublishOnly` runs the build first; `files` ships only `dist/` + docs.
70
+ `prepublishOnly` checks the catalog and runs the build; `files` ships `dist/`,
71
+ the metadata/catalog pair, the README, and the license.
72
+
73
+ ## AI component metadata
74
+
75
+ `kerf.components.json` is the author-owned source for the component's purpose,
76
+ public exports, composition rules, geometry ownership, tokens, accessibility,
77
+ and source links. `boundaries.rootClass` explicitly names the public class that
78
+ owns runtime geometry (or is `null` when none does); `publicClasses` order has no
79
+ semantic meaning. Every public class is the component's rendered anatomy unless
80
+ `boundaries.placeableClasses` lists it: once an app's `.kerf-ui-profile.json`
81
+ declares this package's catalog under `catalogs`, `eslint-plugin-kerfjs`
82
+ reports an app that writes `kerf-counter` onto its own `<div>` (`KUI-L103`) and
83
+ tells it to render `Counter` instead. List a class there only when apps may legitimately
84
+ place it themselves (a layout utility, item geometry on another carrier), and
85
+ add `rootElement` when the component itself renders those classes on that tag.
86
+ Keep decisions explicit: the generator deliberately does not
87
+ derive semantic or geometry ownership from rendered appearance. It validates
88
+ both this source and the generated catalog against the schema copies beside the
89
+ checker, including rejection of unknown fields. Named exports must exist in
90
+ the TypeScript/TSX syntax tree; JSX text, nested scopes, comments, and literals
91
+ are not exports. The checker uses this package's installed TypeScript compiler,
92
+ so run `npm install` before the first local catalog command.
93
+
94
+ ```bash
95
+ npm run catalog:generate # write component-composition.json
96
+ npm run catalog:check # no writes; fail when metadata, source, or output drift
97
+ ```
98
+
99
+ The generated catalog ships with the package. AI tools join each entry to
100
+ Kerf's catalog by its `package:id` key, search this package first for
101
+ application-specific concepts, and retain both packages' identities when
102
+ following cross-catalog composition references.
@@ -0,0 +1,144 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/brianwestphal/kerf/main/ui/ai/component-composition-extension.schema.json",
3
+ "schemaVersion": 1,
4
+ "package": "__PKG_NAME__",
5
+ "compatibility": {
6
+ "componentCatalog": "not-applicable",
7
+ "identity": "package:id"
8
+ },
9
+ "entries": [
10
+ {
11
+ "key": "__PKG_NAME__:counter",
12
+ "package": "__PKG_NAME__",
13
+ "id": "counter",
14
+ "name": "Counter",
15
+ "kind": "component",
16
+ "purpose": "Render a controlled counter with delegated increment and decrement actions.",
17
+ "publicExports": [
18
+ {
19
+ "name": "Counter",
20
+ "subpath": "."
21
+ },
22
+ {
23
+ "name": "CounterProps",
24
+ "subpath": "."
25
+ },
26
+ {
27
+ "name": "CounterState",
28
+ "subpath": "."
29
+ },
30
+ {
31
+ "name": "CounterStore",
32
+ "subpath": "."
33
+ },
34
+ {
35
+ "name": "createCounter",
36
+ "subpath": "."
37
+ },
38
+ {
39
+ "name": "wireCounter",
40
+ "subpath": "."
41
+ },
42
+ {
43
+ "name": "Counter",
44
+ "subpath": "./counter"
45
+ },
46
+ {
47
+ "name": "CounterProps",
48
+ "subpath": "./counter"
49
+ },
50
+ {
51
+ "name": "CounterState",
52
+ "subpath": "./counter"
53
+ },
54
+ {
55
+ "name": "CounterStore",
56
+ "subpath": "./counter"
57
+ },
58
+ {
59
+ "name": "createCounter",
60
+ "subpath": "./counter"
61
+ },
62
+ {
63
+ "name": "wireCounter",
64
+ "subpath": "./counter"
65
+ }
66
+ ],
67
+ "sourceLinks": [
68
+ "README.md#use-it",
69
+ "src/counter.tsx"
70
+ ],
71
+ "source": "src/counter.tsx",
72
+ "parents": {
73
+ "mode": "any",
74
+ "entries": []
75
+ },
76
+ "contexts": [
77
+ "controlled-counter"
78
+ ],
79
+ "zones": [],
80
+ "children": {
81
+ "mode": "listed",
82
+ "concepts": [
83
+ "decrement-control",
84
+ "value",
85
+ "increment-control"
86
+ ],
87
+ "requiredConcepts": [
88
+ "decrement-control",
89
+ "value",
90
+ "increment-control"
91
+ ]
92
+ },
93
+ "state": [
94
+ {
95
+ "id": "count",
96
+ "owner": "controlled",
97
+ "required": true
98
+ }
99
+ ],
100
+ "wiring": {
101
+ "required": true,
102
+ "helpers": [
103
+ "wireCounter"
104
+ ],
105
+ "obligations": [
106
+ "Retain and call the disposer returned by wireCounter."
107
+ ]
108
+ },
109
+ "responsive": {
110
+ "owner": "not-applicable",
111
+ "behaviors": []
112
+ },
113
+ "layout": {
114
+ "roles": [
115
+ "counter"
116
+ ],
117
+ "geometry": {
118
+ "margin": "none",
119
+ "border": "none",
120
+ "padding": "none"
121
+ }
122
+ },
123
+ "accessibility": {
124
+ "obligations": [
125
+ "Keep increment and decrement controls named and expose the current count as output."
126
+ ]
127
+ },
128
+ "boundaries": {
129
+ "rootClass": "kerf-counter",
130
+ "publicClasses": [
131
+ "kerf-counter"
132
+ ],
133
+ "publicTokens": [
134
+ "--kerf-counter-gap"
135
+ ]
136
+ },
137
+ "diagnostics": [],
138
+ "provenance": {
139
+ "selection": "README.md#use-it",
140
+ "composition": "README.md#the-rules-this-package-follows"
141
+ }
142
+ }
143
+ ]
144
+ }