@preset.nz/facets 0.1.3 → 0.3.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/schema/v0.1.json CHANGED
@@ -4,10 +4,7 @@
4
4
  "title": "@preset.nz/facets PropertySchema, 0.1",
5
5
  "description": "An inspector panel as data: groups of rows of fields. Valid for every 0.1.x release; later 0.1 patches only add kinds and props. Playground: https://facets.preset.nz",
6
6
  "type": "object",
7
- "required": [
8
- "version",
9
- "groups"
10
- ],
7
+ "required": ["version", "groups"],
11
8
  "additionalProperties": false,
12
9
  "properties": {
13
10
  "$schema": {
@@ -18,6 +15,18 @@
18
15
  "type": "number",
19
16
  "description": "The host's own version of this schema. Bump it when the shape changes."
20
17
  },
18
+ "title": {
19
+ "type": "string",
20
+ "description": "What the scope is called, e.g. \"Filter\". Heads the card; the host can override it."
21
+ },
22
+ "pages": {
23
+ "type": "array",
24
+ "description": "Splits the inspector into tabs, in this order. Omit it for one page and no tab row. With pages, every group names one in `page`, and every page needs a group that isn't advanced.",
25
+ "minItems": 1,
26
+ "items": {
27
+ "$ref": "#/definitions/page"
28
+ }
29
+ },
21
30
  "groups": {
22
31
  "type": "array",
23
32
  "description": "Rendered top to bottom, with a rule between groups.",
@@ -29,10 +38,7 @@
29
38
  "definitions": {
30
39
  "group": {
31
40
  "type": "object",
32
- "required": [
33
- "id",
34
- "rows"
35
- ],
41
+ "required": ["id", "rows"],
36
42
  "additionalProperties": false,
37
43
  "properties": {
38
44
  "id": {
@@ -55,6 +61,14 @@
55
61
  "type": "boolean",
56
62
  "description": "Start folded."
57
63
  },
64
+ "page": {
65
+ "type": "string",
66
+ "description": "The id of the page this group sits on. Required when the schema declares pages, not allowed otherwise."
67
+ },
68
+ "advanced": {
69
+ "type": "boolean",
70
+ "description": "Sits behind the page's one closed Advanced row, at the foot of the page."
71
+ },
58
72
  "rows": {
59
73
  "type": "array",
60
74
  "description": "A field is a full-width row; an array of fields is one row laid out as a grid (usually two).",
@@ -74,12 +88,38 @@
74
88
  }
75
89
  }
76
90
  },
91
+ "page": {
92
+ "type": "object",
93
+ "description": "A tab in the inspector. Presentation only: no field path names a page.",
94
+ "required": ["id", "label"],
95
+ "additionalProperties": false,
96
+ "properties": {
97
+ "id": {
98
+ "type": "string",
99
+ "minLength": 1,
100
+ "description": "Unique among the pages. Groups name it in `page`."
101
+ },
102
+ "label": {
103
+ "type": "string",
104
+ "description": "The tab's text."
105
+ }
106
+ }
107
+ },
77
108
  "disabledWhen": {
109
+ "description": "Greys the field out depending on other fields' values: one condition, or a list that disables the field when any of them holds.",
110
+ "oneOf": [
111
+ { "$ref": "#/definitions/disabledWhenOne" },
112
+ {
113
+ "type": "array",
114
+ "minItems": 1,
115
+ "items": { "$ref": "#/definitions/disabledWhenOne" }
116
+ }
117
+ ]
118
+ },
119
+ "disabledWhenOne": {
78
120
  "type": "object",
79
- "description": "Greys the field out depending on another field's value. Set one operator; if several are set, the first of equals, notEquals, in, notIn wins.",
80
- "required": [
81
- "path"
82
- ],
121
+ "description": "One condition on another field's value. Set one operator; if several are set, the first of equals, notEquals, in, notIn wins.",
122
+ "required": ["path"],
83
123
  "additionalProperties": false,
84
124
  "properties": {
85
125
  "path": {
@@ -102,12 +142,17 @@
102
142
  }
103
143
  }
104
144
  },
145
+ "promote": {
146
+ "type": "array",
147
+ "description": "The views the field shows in besides the inspector, like a parm promoted to a Houdini asset's interface. \"card\": on the card. \"collapsed\": in a closed group's header and in a folded scope. Omit for inspector-only.",
148
+ "items": {
149
+ "enum": ["card", "collapsed"]
150
+ },
151
+ "uniqueItems": true
152
+ },
105
153
  "selectOption": {
106
154
  "type": "object",
107
- "required": [
108
- "value",
109
- "label"
110
- ],
155
+ "required": ["value", "label"],
111
156
  "additionalProperties": false,
112
157
  "properties": {
113
158
  "value": {
@@ -120,6 +165,24 @@
120
165
  }
121
166
  }
122
167
  },
168
+ "fileFilter": {
169
+ "type": "object",
170
+ "required": ["name", "extensions"],
171
+ "additionalProperties": false,
172
+ "properties": {
173
+ "name": {
174
+ "type": "string",
175
+ "description": "Shown in the Open dialog, e.g. \"Images\"."
176
+ },
177
+ "extensions": {
178
+ "type": "array",
179
+ "description": "Extensions without the dot, e.g. [\"png\", \"jpg\"].",
180
+ "items": {
181
+ "type": "string"
182
+ }
183
+ }
184
+ }
185
+ },
123
186
  "vectorComponent": {
124
187
  "type": "object",
125
188
  "additionalProperties": false,
@@ -149,10 +212,7 @@
149
212
  "field": {
150
213
  "type": "object",
151
214
  "description": "One field. kind picks the renderer: a built-in kind is checked strictly; any other kind is a custom kind registered by the host, which may carry extra props.",
152
- "required": [
153
- "kind",
154
- "id"
155
- ],
215
+ "required": ["kind", "id"],
156
216
  "properties": {
157
217
  "kind": {
158
218
  "type": "string",
@@ -179,9 +239,7 @@
179
239
  "allOf": [
180
240
  {
181
241
  "if": {
182
- "required": [
183
- "kind"
184
- ],
242
+ "required": ["kind"],
185
243
  "properties": {
186
244
  "kind": {
187
245
  "const": "text"
@@ -194,9 +252,7 @@
194
252
  },
195
253
  {
196
254
  "if": {
197
- "required": [
198
- "kind"
199
- ],
255
+ "required": ["kind"],
200
256
  "properties": {
201
257
  "kind": {
202
258
  "const": "textarea"
@@ -209,9 +265,7 @@
209
265
  },
210
266
  {
211
267
  "if": {
212
- "required": [
213
- "kind"
214
- ],
268
+ "required": ["kind"],
215
269
  "properties": {
216
270
  "kind": {
217
271
  "const": "number"
@@ -224,9 +278,7 @@
224
278
  },
225
279
  {
226
280
  "if": {
227
- "required": [
228
- "kind"
229
- ],
281
+ "required": ["kind"],
230
282
  "properties": {
231
283
  "kind": {
232
284
  "const": "slider"
@@ -239,9 +291,7 @@
239
291
  },
240
292
  {
241
293
  "if": {
242
- "required": [
243
- "kind"
244
- ],
294
+ "required": ["kind"],
245
295
  "properties": {
246
296
  "kind": {
247
297
  "const": "select"
@@ -254,9 +304,7 @@
254
304
  },
255
305
  {
256
306
  "if": {
257
- "required": [
258
- "kind"
259
- ],
307
+ "required": ["kind"],
260
308
  "properties": {
261
309
  "kind": {
262
310
  "const": "color"
@@ -269,9 +317,7 @@
269
317
  },
270
318
  {
271
319
  "if": {
272
- "required": [
273
- "kind"
274
- ],
320
+ "required": ["kind"],
275
321
  "properties": {
276
322
  "kind": {
277
323
  "const": "checkbox"
@@ -284,9 +330,7 @@
284
330
  },
285
331
  {
286
332
  "if": {
287
- "required": [
288
- "kind"
289
- ],
333
+ "required": ["kind"],
290
334
  "properties": {
291
335
  "kind": {
292
336
  "const": "file"
@@ -299,9 +343,7 @@
299
343
  },
300
344
  {
301
345
  "if": {
302
- "required": [
303
- "kind"
304
- ],
346
+ "required": ["kind"],
305
347
  "properties": {
306
348
  "kind": {
307
349
  "const": "vector"
@@ -314,9 +356,7 @@
314
356
  },
315
357
  {
316
358
  "if": {
317
- "required": [
318
- "kind"
319
- ],
359
+ "required": ["kind"],
320
360
  "properties": {
321
361
  "kind": {
322
362
  "const": "separator"
@@ -329,9 +369,7 @@
329
369
  },
330
370
  {
331
371
  "if": {
332
- "required": [
333
- "kind"
334
- ],
372
+ "required": ["kind"],
335
373
  "properties": {
336
374
  "kind": {
337
375
  "const": "label"
@@ -344,9 +382,7 @@
344
382
  },
345
383
  {
346
384
  "if": {
347
- "required": [
348
- "kind"
349
- ],
385
+ "required": ["kind"],
350
386
  "properties": {
351
387
  "kind": {
352
388
  "not": {
@@ -376,11 +412,7 @@
376
412
  "text": {
377
413
  "type": "object",
378
414
  "description": "A single line of text. Value: string.",
379
- "required": [
380
- "kind",
381
- "id",
382
- "path"
383
- ],
415
+ "required": ["kind", "id", "path"],
384
416
  "properties": {
385
417
  "kind": {
386
418
  "const": "text"
@@ -393,6 +425,10 @@
393
425
  "type": "string",
394
426
  "description": "Shown above the field. Defaults to id."
395
427
  },
428
+ "help": {
429
+ "type": "string",
430
+ "description": "One or two sentences on what the field does, drawn under the control in the inspector view. The card and collapsed views leave it out."
431
+ },
396
432
  "path": {
397
433
  "type": "string",
398
434
  "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
@@ -403,6 +439,9 @@
403
439
  "placeholder": {
404
440
  "type": "string",
405
441
  "description": "Shown while empty."
442
+ },
443
+ "promote": {
444
+ "$ref": "#/definitions/promote"
406
445
  }
407
446
  },
408
447
  "additionalProperties": false
@@ -410,11 +449,7 @@
410
449
  "textarea": {
411
450
  "type": "object",
412
451
  "description": "Several lines of text. Value: string.",
413
- "required": [
414
- "kind",
415
- "id",
416
- "path"
417
- ],
452
+ "required": ["kind", "id", "path"],
418
453
  "properties": {
419
454
  "kind": {
420
455
  "const": "textarea"
@@ -427,6 +462,10 @@
427
462
  "type": "string",
428
463
  "description": "Shown above the field. Defaults to id."
429
464
  },
465
+ "help": {
466
+ "type": "string",
467
+ "description": "One or two sentences on what the field does, drawn under the control in the inspector view. The card and collapsed views leave it out."
468
+ },
430
469
  "path": {
431
470
  "type": "string",
432
471
  "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
@@ -441,6 +480,9 @@
441
480
  "rows": {
442
481
  "type": "number",
443
482
  "description": "Visible lines. Default 3."
483
+ },
484
+ "promote": {
485
+ "$ref": "#/definitions/promote"
444
486
  }
445
487
  },
446
488
  "additionalProperties": false
@@ -448,11 +490,7 @@
448
490
  "number": {
449
491
  "type": "object",
450
492
  "description": "A number typed into a box. Value: number.",
451
- "required": [
452
- "kind",
453
- "id",
454
- "path"
455
- ],
493
+ "required": ["kind", "id", "path"],
456
494
  "properties": {
457
495
  "kind": {
458
496
  "const": "number"
@@ -465,6 +503,10 @@
465
503
  "type": "string",
466
504
  "description": "Shown above the field. Defaults to id."
467
505
  },
506
+ "help": {
507
+ "type": "string",
508
+ "description": "One or two sentences on what the field does, drawn under the control in the inspector view. The card and collapsed views leave it out."
509
+ },
468
510
  "path": {
469
511
  "type": "string",
470
512
  "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
@@ -483,6 +525,17 @@
483
525
  "step": {
484
526
  "type": "number",
485
527
  "description": "Increment. Default 1."
528
+ },
529
+ "integer": {
530
+ "type": "boolean",
531
+ "description": "Whole numbers only: no fractional display, and a fine-step modifier never goes finer than step."
532
+ },
533
+ "suffix": {
534
+ "type": "string",
535
+ "description": "Unit after the number, e.g. px or °. Shown when the panel sets labelLayout to column or stacked."
536
+ },
537
+ "promote": {
538
+ "$ref": "#/definitions/promote"
486
539
  }
487
540
  },
488
541
  "additionalProperties": false
@@ -490,11 +543,7 @@
490
543
  "slider": {
491
544
  "type": "object",
492
545
  "description": "A number dragged along a range. Value: number.",
493
- "required": [
494
- "kind",
495
- "id",
496
- "path"
497
- ],
546
+ "required": ["kind", "id", "path"],
498
547
  "properties": {
499
548
  "kind": {
500
549
  "const": "slider"
@@ -507,6 +556,10 @@
507
556
  "type": "string",
508
557
  "description": "Shown above the field. Defaults to id."
509
558
  },
559
+ "help": {
560
+ "type": "string",
561
+ "description": "One or two sentences on what the field does, drawn under the control in the inspector view. The card and collapsed views leave it out."
562
+ },
510
563
  "path": {
511
564
  "type": "string",
512
565
  "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
@@ -525,6 +578,9 @@
525
578
  "step": {
526
579
  "type": "number",
527
580
  "description": "Increment. Default 1."
581
+ },
582
+ "promote": {
583
+ "$ref": "#/definitions/promote"
528
584
  }
529
585
  },
530
586
  "additionalProperties": false
@@ -532,11 +588,7 @@
532
588
  "select": {
533
589
  "type": "object",
534
590
  "description": "One choice from a list. Value: the chosen option's value (string). Options can also come from optionsProvider(ctx), a function, which is set in code and has no JSON form.",
535
- "required": [
536
- "kind",
537
- "id",
538
- "path"
539
- ],
591
+ "required": ["kind", "id", "path"],
540
592
  "properties": {
541
593
  "kind": {
542
594
  "const": "select"
@@ -549,6 +601,10 @@
549
601
  "type": "string",
550
602
  "description": "Shown above the field. Defaults to id."
551
603
  },
604
+ "help": {
605
+ "type": "string",
606
+ "description": "One or two sentences on what the field does, drawn under the control in the inspector view. The card and collapsed views leave it out."
607
+ },
552
608
  "path": {
553
609
  "type": "string",
554
610
  "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
@@ -562,6 +618,9 @@
562
618
  "items": {
563
619
  "$ref": "#/definitions/selectOption"
564
620
  }
621
+ },
622
+ "promote": {
623
+ "$ref": "#/definitions/promote"
565
624
  }
566
625
  },
567
626
  "additionalProperties": false
@@ -569,11 +628,7 @@
569
628
  "color": {
570
629
  "type": "object",
571
630
  "description": "A colour as a hex string, e.g. \"#2b7c76\". Value: string.",
572
- "required": [
573
- "kind",
574
- "id",
575
- "path"
576
- ],
631
+ "required": ["kind", "id", "path"],
577
632
  "properties": {
578
633
  "kind": {
579
634
  "const": "color"
@@ -586,6 +641,10 @@
586
641
  "type": "string",
587
642
  "description": "Shown above the field. Defaults to id."
588
643
  },
644
+ "help": {
645
+ "type": "string",
646
+ "description": "One or two sentences on what the field does, drawn under the control in the inspector view. The card and collapsed views leave it out."
647
+ },
589
648
  "path": {
590
649
  "type": "string",
591
650
  "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
@@ -599,6 +658,9 @@
599
658
  "type": "string"
600
659
  },
601
660
  "description": "Hex strings. Declared in 0.1; the built-in renderer does not draw them."
661
+ },
662
+ "promote": {
663
+ "$ref": "#/definitions/promote"
602
664
  }
603
665
  },
604
666
  "additionalProperties": false
@@ -606,11 +668,7 @@
606
668
  "checkbox": {
607
669
  "type": "object",
608
670
  "description": "On or off. Value: boolean.",
609
- "required": [
610
- "kind",
611
- "id",
612
- "path"
613
- ],
671
+ "required": ["kind", "id", "path"],
614
672
  "properties": {
615
673
  "kind": {
616
674
  "const": "checkbox"
@@ -623,24 +681,27 @@
623
681
  "type": "string",
624
682
  "description": "Shown above the field. Defaults to id."
625
683
  },
684
+ "help": {
685
+ "type": "string",
686
+ "description": "One or two sentences on what the field does, drawn under the control in the inspector view. The card and collapsed views leave it out."
687
+ },
626
688
  "path": {
627
689
  "type": "string",
628
690
  "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
629
691
  },
630
692
  "disabledWhen": {
631
693
  "$ref": "#/definitions/disabledWhen"
694
+ },
695
+ "promote": {
696
+ "$ref": "#/definitions/promote"
632
697
  }
633
698
  },
634
699
  "additionalProperties": false
635
700
  },
636
701
  "file": {
637
702
  "type": "object",
638
- "description": "Shows a file's name; always read-only. Value: { \"name\": string }.",
639
- "required": [
640
- "kind",
641
- "id",
642
- "path"
643
- ],
703
+ "description": "A path to a file, edited on a path field with a recent list, browse icon and Missing check when the host registers file handlers. Value: the path string as written, or null.",
704
+ "required": ["kind", "id", "path"],
644
705
  "properties": {
645
706
  "kind": {
646
707
  "const": "file"
@@ -653,6 +714,10 @@
653
714
  "type": "string",
654
715
  "description": "Shown above the field. Defaults to id."
655
716
  },
717
+ "help": {
718
+ "type": "string",
719
+ "description": "One or two sentences on what the field does, drawn under the control in the inspector view. The card and collapsed views leave it out."
720
+ },
656
721
  "path": {
657
722
  "type": "string",
658
723
  "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
@@ -660,13 +725,35 @@
660
725
  "disabledWhen": {
661
726
  "$ref": "#/definitions/disabledWhen"
662
727
  },
728
+ "recentKey": {
729
+ "type": "string",
730
+ "description": "Keys the recent paths: fields with the same key share one list, across documents. Example: \"texture\"."
731
+ },
732
+ "filters": {
733
+ "type": "array",
734
+ "description": "File types in the Open dialog.",
735
+ "items": {
736
+ "$ref": "#/definitions/fileFilter"
737
+ }
738
+ },
739
+ "title": {
740
+ "type": "string",
741
+ "description": "The Open dialog's title."
742
+ },
743
+ "placeholder": {
744
+ "type": "string",
745
+ "description": "Shown while the field is empty."
746
+ },
663
747
  "accept": {
664
748
  "type": "string",
665
- "description": "File types, as on <input>. Declared in 0.1; the built-in renderer ignores it."
749
+ "description": "Deprecated: use filters. File types as on <input accept>; the extensions in it become one \"Files\" filter when filters is absent."
666
750
  },
667
751
  "helperText": {
668
752
  "type": "string",
669
- "description": "A hint. Declared in 0.1; the built-in renderer does not draw it."
753
+ "description": "Deprecated: use help, which every field has. Drawn as help when that's absent."
754
+ },
755
+ "promote": {
756
+ "$ref": "#/definitions/promote"
670
757
  }
671
758
  },
672
759
  "additionalProperties": false
@@ -674,12 +761,7 @@
674
761
  "vector": {
675
762
  "type": "object",
676
763
  "description": "Several numbers in one row: position, size, RGB, LCh. Value: number[], one per component.",
677
- "required": [
678
- "kind",
679
- "id",
680
- "path",
681
- "components"
682
- ],
764
+ "required": ["kind", "id", "path", "components"],
683
765
  "properties": {
684
766
  "kind": {
685
767
  "const": "vector"
@@ -692,6 +774,10 @@
692
774
  "type": "string",
693
775
  "description": "Shown above the field. Defaults to id."
694
776
  },
777
+ "help": {
778
+ "type": "string",
779
+ "description": "One or two sentences on what the field does, drawn under the control in the inspector view. The card and collapsed views leave it out."
780
+ },
695
781
  "path": {
696
782
  "type": "string",
697
783
  "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
@@ -713,6 +799,9 @@
713
799
  "precision": {
714
800
  "type": "number",
715
801
  "description": "Decimals shown when read-only."
802
+ },
803
+ "promote": {
804
+ "$ref": "#/definitions/promote"
716
805
  }
717
806
  },
718
807
  "additionalProperties": false
@@ -720,10 +809,7 @@
720
809
  "separator": {
721
810
  "type": "object",
722
811
  "description": "A horizontal rule between rows, with label as an optional caption. Holds no value, so it has no path.",
723
- "required": [
724
- "kind",
725
- "id"
726
- ],
812
+ "required": ["kind", "id"],
727
813
  "properties": {
728
814
  "kind": {
729
815
  "const": "separator"
@@ -738,6 +824,9 @@
738
824
  },
739
825
  "disabledWhen": {
740
826
  "$ref": "#/definitions/disabledWhen"
827
+ },
828
+ "promote": {
829
+ "$ref": "#/definitions/promote"
741
830
  }
742
831
  },
743
832
  "additionalProperties": false
@@ -745,11 +834,7 @@
745
834
  "label": {
746
835
  "type": "object",
747
836
  "description": "Static text: a hint, a note, a sub-heading. The text is label. Holds no value, so it has no path.",
748
- "required": [
749
- "kind",
750
- "id",
751
- "label"
752
- ],
837
+ "required": ["kind", "id", "label"],
753
838
  "properties": {
754
839
  "kind": {
755
840
  "const": "label"
@@ -764,6 +849,9 @@
764
849
  },
765
850
  "disabledWhen": {
766
851
  "$ref": "#/definitions/disabledWhen"
852
+ },
853
+ "promote": {
854
+ "$ref": "#/definitions/promote"
767
855
  }
768
856
  },
769
857
  "additionalProperties": false
@@ -771,11 +859,7 @@
771
859
  "custom": {
772
860
  "type": "object",
773
861
  "description": "A custom kind. The host's renderer decides which extra props it reads.",
774
- "required": [
775
- "kind",
776
- "id",
777
- "path"
778
- ],
862
+ "required": ["kind", "id"],
779
863
  "properties": {
780
864
  "kind": {
781
865
  "type": "string"
@@ -788,14 +872,62 @@
788
872
  "type": "string",
789
873
  "description": "Shown above the field. Defaults to id."
790
874
  },
875
+ "help": {
876
+ "type": "string",
877
+ "description": "One or two sentences on what the field does, drawn under the control in the inspector view. The card and collapsed views leave it out."
878
+ },
791
879
  "path": {
792
880
  "type": "string",
793
- "description": "A key into the record the scope's read() returns. A flat lookup, not a nested traversal: \"transform.x\" is one key."
881
+ "description": "A key into the record the scope's read() returns. Leave it out for a field that holds no value. A flat lookup, not a nested traversal: \"transform.x\" is one key."
794
882
  },
795
883
  "disabledWhen": {
796
884
  "$ref": "#/definitions/disabledWhen"
885
+ },
886
+ "promote": {
887
+ "$ref": "#/definitions/promote"
797
888
  }
798
889
  }
799
890
  }
800
- }
891
+ },
892
+ "allOf": [
893
+ {
894
+ "if": {
895
+ "properties": {
896
+ "pages": true
897
+ },
898
+ "required": ["pages"]
899
+ },
900
+ "then": {
901
+ "properties": {
902
+ "groups": {
903
+ "type": "array",
904
+ "items": {
905
+ "type": "object",
906
+ "properties": {
907
+ "page": true
908
+ },
909
+ "required": ["page"]
910
+ }
911
+ }
912
+ }
913
+ },
914
+ "else": {
915
+ "properties": {
916
+ "groups": {
917
+ "type": "array",
918
+ "items": {
919
+ "not": {
920
+ "type": "object",
921
+ "properties": {
922
+ "page": true
923
+ },
924
+ "required": ["page"]
925
+ }
926
+ }
927
+ }
928
+ }
929
+ },
930
+ "$comment": "With pages every group names one; without, none does. Which page, and whether it exists, is checked in code: schemaProblems()."
931
+ }
932
+ ]
801
933
  }