@umami/shiso 0.55.0 → 0.61.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.
Files changed (99) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +9 -49
  3. package/bin/shiso.mjs +132 -0
  4. package/docs.schema.json +835 -0
  5. package/mdx.config.ts +143 -0
  6. package/package.json +73 -83
  7. package/scripts/check-package.mjs +18 -0
  8. package/scripts/generate-icon-registry.mjs +196 -0
  9. package/scripts/generate-last-modified.mjs +128 -0
  10. package/scripts/generate-search-index.mjs +252 -0
  11. package/scripts/load-docs-config.mjs +244 -0
  12. package/scripts/prerender.mjs +187 -0
  13. package/scripts/validate-config.mjs +104 -0
  14. package/scripts/vite-docs-config.mjs +60 -0
  15. package/src/App.tsx +39 -0
  16. package/src/components/Banner.tsx +69 -0
  17. package/src/components/CodeBlock.tsx +46 -0
  18. package/src/components/ConfiguredIcon.tsx +15 -0
  19. package/src/components/ContextualMenu.tsx +93 -0
  20. package/src/components/DocContent.tsx +100 -0
  21. package/src/components/Docs.tsx +126 -0
  22. package/src/components/Footer.tsx +84 -0
  23. package/src/components/Header.tsx +72 -0
  24. package/src/components/Layout.tsx +16 -0
  25. package/src/components/PageLinks.tsx +71 -0
  26. package/src/components/Search.tsx +208 -0
  27. package/src/components/SideNav.tsx +347 -0
  28. package/src/components/SocialIcon.tsx +88 -0
  29. package/src/components/ThemeToggle.tsx +34 -0
  30. package/src/components/TopNav.tsx +127 -0
  31. package/src/components/docs/Accordion.tsx +68 -0
  32. package/src/components/docs/Badge.tsx +171 -0
  33. package/src/components/docs/Callout.tsx +73 -0
  34. package/src/components/docs/Card.tsx +158 -0
  35. package/src/components/docs/CodeGroup.tsx +73 -0
  36. package/src/components/docs/Columns.tsx +20 -0
  37. package/src/components/docs/Expandable.tsx +28 -0
  38. package/src/components/docs/Frame.tsx +56 -0
  39. package/src/components/docs/Icon.tsx +30 -0
  40. package/src/components/docs/ParamField.tsx +45 -0
  41. package/src/components/docs/PropertiesTable.tsx +84 -0
  42. package/src/components/docs/ResponseField.tsx +36 -0
  43. package/src/components/docs/Steps.tsx +47 -0
  44. package/src/components/docs/Tabs.tsx +116 -0
  45. package/src/components/docs/Tooltip.tsx +21 -0
  46. package/src/components/docs/index.ts +15 -0
  47. package/src/components/docs/styles.ts +82 -0
  48. package/src/components/docs/utils.ts +118 -0
  49. package/src/components/icons/index.ts +17 -0
  50. package/src/components/ui/accordion.tsx +69 -0
  51. package/src/components/ui/alert.tsx +69 -0
  52. package/src/components/ui/badge.tsx +49 -0
  53. package/src/components/ui/button.tsx +58 -0
  54. package/src/components/ui/card.tsx +88 -0
  55. package/src/components/ui/collapsible.tsx +15 -0
  56. package/src/components/ui/command.tsx +173 -0
  57. package/src/components/ui/dialog.tsx +137 -0
  58. package/src/components/ui/dropdown-menu.tsx +257 -0
  59. package/src/components/ui/scroll-area.tsx +71 -0
  60. package/src/components/ui/sheet.tsx +124 -0
  61. package/src/components/ui/tabs.tsx +73 -0
  62. package/src/components/ui/tooltip.tsx +52 -0
  63. package/src/declarations.d.ts +9 -0
  64. package/src/entry-client.tsx +17 -0
  65. package/src/entry-server.tsx +77 -0
  66. package/src/generated/last-modified.ts +2 -0
  67. package/src/lib/content.ts +44 -0
  68. package/src/lib/docs-config.ts +682 -0
  69. package/src/lib/head.ts +220 -0
  70. package/src/lib/icon-registry.generated.ts +4 -0
  71. package/src/lib/icons.ts +29 -0
  72. package/src/lib/inline-markdown.tsx +86 -0
  73. package/src/lib/mdast.ts +56 -0
  74. package/src/lib/paths.ts +86 -0
  75. package/src/lib/remark-toc.ts +71 -0
  76. package/src/lib/search/config.ts +43 -0
  77. package/src/lib/search/provider.ts +80 -0
  78. package/src/lib/search/providers/local.ts +15 -0
  79. package/src/lib/search-index.generated.ts +4 -0
  80. package/src/lib/search.ts +100 -0
  81. package/src/lib/site-config.ts +104 -0
  82. package/src/lib/site-model.ts +221 -0
  83. package/src/lib/slug.ts +38 -0
  84. package/src/lib/types.ts +478 -0
  85. package/src/lib/utils.ts +6 -0
  86. package/src/pages/DocPage.tsx +33 -0
  87. package/src/styles/global.css +268 -0
  88. package/src/styles/tokens.css +114 -0
  89. package/types/client.d.ts +3 -0
  90. package/types/search.d.ts +17 -0
  91. package/vite.config.ts +342 -0
  92. package/LICENSE +0 -21
  93. package/dist/index.css +0 -189
  94. package/dist/index.d.ts +0 -57
  95. package/dist/index.js +0 -464
  96. package/dist/index.mjs +0 -437
  97. package/server/index.d.ts +0 -30
  98. package/server/index.js +0 -189
  99. package/styles.css +0 -4766
@@ -0,0 +1,835 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "docs.schema.json",
4
+ "title": "Shiso docs.json",
5
+ "description": "Configuration for a Shiso docs site. Documented settings are strictly validated and unknown keys are rejected.",
6
+ "type": "object",
7
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["navigation"] }],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "$ref": {
11
+ "allOf": [{ "$ref": "#/definitions/configRef" }]
12
+ },
13
+ "$schema": {
14
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
15
+ "description": "Path or URL to this schema, for editor autocomplete."
16
+ },
17
+ "$shiso": {
18
+ "type": "object",
19
+ "description": "Shiso-only options. Namespaced so the rest of the file stays portable.",
20
+ "additionalProperties": false,
21
+ "properties": {
22
+ "$ref": { "$ref": "#/definitions/configRef" },
23
+ "docsPrefix": {
24
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
25
+ "description": "Route prefix for docs pages. Defaults to \"/docs\"; use \"\" to serve docs at the site root.",
26
+ "default": "/docs"
27
+ },
28
+ "contentDir": {
29
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
30
+ "description": "Content directory relative to the project root.",
31
+ "default": "content/docs"
32
+ },
33
+ "siteUrl": {
34
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
35
+ "description": "Absolute site origin (e.g. \"https://docs.example.com\"). Required for canonical, og:url, and structured data."
36
+ },
37
+ "locale": {
38
+ "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }],
39
+ "description": "Locale used for dates and theme-provided interface copy. Defaults to en-US."
40
+ }
41
+ }
42
+ },
43
+ "name": {
44
+ "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }],
45
+ "description": "Site name, shown in the header and the page title."
46
+ },
47
+ "description": {
48
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
49
+ "description": "Default meta description for pages without one."
50
+ },
51
+ "colors": {
52
+ "type": "object",
53
+ "additionalProperties": false,
54
+ "properties": {
55
+ "$ref": { "$ref": "#/definitions/configRef" },
56
+ "primary": {
57
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
58
+ "description": "Primary accent color (any CSS color)."
59
+ },
60
+ "light": {
61
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
62
+ "description": "Accent color used in dark mode."
63
+ },
64
+ "dark": {
65
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
66
+ "description": "Fallback accent color when primary is omitted."
67
+ }
68
+ }
69
+ },
70
+ "logo": {
71
+ "oneOf": [
72
+ {
73
+ "type": "string",
74
+ "description": "Path to the logo image, relative to the public directory."
75
+ },
76
+ {
77
+ "type": "object",
78
+ "anyOf": [
79
+ { "required": ["$ref"] },
80
+ { "required": ["light"] },
81
+ { "required": ["dark"] }
82
+ ],
83
+ "additionalProperties": false,
84
+ "properties": {
85
+ "$ref": { "$ref": "#/definitions/configRef" },
86
+ "light": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Logo shown in light mode." },
87
+ "dark": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Logo shown in dark mode." },
88
+ "href": {
89
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
90
+ "description": "URL the logo links to. Defaults to the docs root."
91
+ },
92
+ "target": {
93
+ "allOf": [{ "$ref": "#/definitions/targetValue" }],
94
+ "description": "Browsing context for the logo link. Defaults from href."
95
+ }
96
+ }
97
+ }
98
+ ]
99
+ },
100
+ "favicon": {
101
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
102
+ "description": "Path to the favicon, relative to the public directory."
103
+ },
104
+ "navigation": {
105
+ "type": "object",
106
+ "description": "Site navigation. Define exactly one of: tabs, dropdowns, versions, languages, or top-level groups/pages.",
107
+ "additionalProperties": false,
108
+ "properties": {
109
+ "$ref": { "$ref": "#/definitions/configRef" },
110
+ "tabs": { "$ref": "#/definitions/tabList" },
111
+ "dropdowns": { "$ref": "#/definitions/dropdownList" },
112
+ "anchors": { "$ref": "#/definitions/anchorList" },
113
+ "versions": { "$ref": "#/definitions/versionList" },
114
+ "languages": { "$ref": "#/definitions/languageList" },
115
+ "groups": { "$ref": "#/definitions/groupList" },
116
+ "pages": { "$ref": "#/definitions/pageItemList" }
117
+ }
118
+ },
119
+
120
+ "theme": {
121
+ "anyOf": [
122
+ { "type": "string", "enum": ["shiso"] },
123
+ { "$ref": "#/definitions/configRefValue" }
124
+ ],
125
+ "default": "shiso",
126
+ "description": "Layout theme name. Only \"shiso\" is implemented."
127
+ },
128
+ "styling": {
129
+ "type": "object",
130
+ "description": "Visual styling configuration.",
131
+ "additionalProperties": false,
132
+ "properties": {
133
+ "$ref": { "$ref": "#/definitions/configRef" },
134
+ "eyebrows": {
135
+ "anyOf": [
136
+ { "enum": ["section", "breadcrumbs"] },
137
+ { "$ref": "#/definitions/configRefValue" }
138
+ ],
139
+ "description": "Page eyebrow style: the section name (default) or the full navigation path.",
140
+ "default": "section"
141
+ }
142
+ }
143
+ },
144
+ "fonts": {
145
+ "type": "object",
146
+ "description": "Custom fonts. Google Fonts families load automatically; use source/format for self-hosted files.",
147
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["family"] }],
148
+ "additionalProperties": false,
149
+ "properties": {
150
+ "$ref": { "$ref": "#/definitions/configRef" },
151
+ "family": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Font family name, e.g. \"Open Sans\"." },
152
+ "weight": { "allOf": [{ "$ref": "#/definitions/numberValue" }], "description": "Font weight, e.g. 400 or 700." },
153
+ "source": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "URL or path to a hosted font file." },
154
+ "format": {
155
+ "anyOf": [
156
+ { "enum": ["woff", "woff2"] },
157
+ { "$ref": "#/definitions/configRefValue" }
158
+ ],
159
+ "description": "Font file format, for `source`."
160
+ },
161
+ "heading": { "allOf": [{ "$ref": "#/definitions/fontSpec" }], "description": "Override for headings." },
162
+ "body": { "allOf": [{ "$ref": "#/definitions/fontSpec" }], "description": "Override for body text." }
163
+ }
164
+ },
165
+ "appearance": {
166
+ "type": "object",
167
+ "description": "Light/dark mode defaults.",
168
+ "additionalProperties": false,
169
+ "properties": {
170
+ "$ref": { "$ref": "#/definitions/configRef" },
171
+ "default": {
172
+ "anyOf": [
173
+ { "enum": ["system", "light", "dark"] },
174
+ { "$ref": "#/definitions/configRefValue" }
175
+ ],
176
+ "description": "Initial theme mode. \"system\" follows the OS preference.",
177
+ "default": "system"
178
+ },
179
+ "strict": {
180
+ "allOf": [{ "$ref": "#/definitions/booleanValue" }],
181
+ "description": "Hide the light/dark toggle and ignore stored preferences.",
182
+ "default": false
183
+ }
184
+ }
185
+ },
186
+ "background": {
187
+ "type": "object",
188
+ "description": "Background color and image settings.",
189
+ "additionalProperties": false,
190
+ "properties": {
191
+ "$ref": { "$ref": "#/definitions/configRef" },
192
+ "image": {
193
+ "description": "Background image, a single path or per-mode paths.",
194
+ "oneOf": [
195
+ { "type": "string" },
196
+ {
197
+ "type": "object",
198
+ "anyOf": [
199
+ { "required": ["$ref"] },
200
+ { "required": ["light"] },
201
+ { "required": ["dark"] }
202
+ ],
203
+ "additionalProperties": false,
204
+ "properties": {
205
+ "$ref": { "$ref": "#/definitions/configRef" },
206
+ "light": { "$ref": "#/definitions/stringValue" },
207
+ "dark": { "$ref": "#/definitions/stringValue" }
208
+ }
209
+ }
210
+ ]
211
+ },
212
+ "color": {
213
+ "type": "object",
214
+ "additionalProperties": false,
215
+ "properties": {
216
+ "$ref": { "$ref": "#/definitions/configRef" },
217
+ "light": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Background color for light mode." },
218
+ "dark": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Background color for dark mode." }
219
+ }
220
+ }
221
+ }
222
+ },
223
+ "interaction": {
224
+ "type": "object",
225
+ "description": "Navigation interaction settings.",
226
+ "additionalProperties": false,
227
+ "properties": {
228
+ "$ref": { "$ref": "#/definitions/configRef" },
229
+ "drilldown": {
230
+ "allOf": [{ "$ref": "#/definitions/booleanValue" }],
231
+ "description": "Collapsible-group click behavior: true navigates to the group's first page on expand, false only expands/collapses. Unset uses the default (headers with a root page navigate, others toggle)."
232
+ }
233
+ }
234
+ },
235
+ "search": {
236
+ "description": "Search settings. Set to false to disable search.",
237
+ "oneOf": [
238
+ { "const": false },
239
+ {
240
+ "type": "object",
241
+ "additionalProperties": false,
242
+ "properties": {
243
+ "$ref": { "$ref": "#/definitions/configRef" },
244
+ "prompt": {
245
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
246
+ "description": "Placeholder text for the search input."
247
+ },
248
+ "provider": {
249
+ "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }],
250
+ "description": "Registered search provider id. Defaults to local."
251
+ },
252
+ "options": {
253
+ "type": "object",
254
+ "description": "Provider-specific configuration."
255
+ },
256
+ "shortcut": {
257
+ "description": "Single Cmd/Ctrl shortcut key, or false to disable it.",
258
+ "oneOf": [
259
+ { "type": "string", "minLength": 1, "maxLength": 1 },
260
+ { "const": false },
261
+ { "$ref": "#/definitions/configRefValue" }
262
+ ]
263
+ },
264
+ "shortcutLabel": {
265
+ "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }],
266
+ "description": "Text displayed for the configured search shortcut."
267
+ }
268
+ }
269
+ }
270
+ ]
271
+ },
272
+ "contextual": {
273
+ "type": "object",
274
+ "description": "Contextual menu shown beside the page title.",
275
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["options"] }],
276
+ "additionalProperties": false,
277
+ "properties": {
278
+ "$ref": { "$ref": "#/definitions/configRef" },
279
+ "options": {
280
+ "anyOf": [
281
+ {
282
+ "type": "array",
283
+ "items": {
284
+ "oneOf": [
285
+ {
286
+ "enum": [
287
+ "copy",
288
+ "view",
289
+ "chatgpt",
290
+ "claude",
291
+ "perplexity"
292
+ ]
293
+ },
294
+ {
295
+ "type": "object",
296
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["title", "href"] }],
297
+ "additionalProperties": false,
298
+ "properties": {
299
+ "$ref": { "$ref": "#/definitions/configRef" },
300
+ "title": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Menu entry title." },
301
+ "description": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Menu entry description." },
302
+ "icon": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Icon name rendered with the action." },
303
+ "target": {
304
+ "allOf": [{ "$ref": "#/definitions/targetValue" }],
305
+ "description": "Browsing context for the action. Defaults from the destination URL."
306
+ },
307
+ "href": {
308
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
309
+ "description": "Destination URL. \"$path\" expands to the page path, \"$page\" to the page's markdown URL."
310
+ }
311
+ }
312
+ }
313
+ ]
314
+ }
315
+ },
316
+ { "$ref": "#/definitions/configRefValue" }
317
+ ],
318
+ "description": "Menu entries, in order; the first is the primary button."
319
+ }
320
+ }
321
+ },
322
+ "navbar": {
323
+ "type": "object",
324
+ "description": "Links and primary button in the top navigation bar.",
325
+ "additionalProperties": false,
326
+ "properties": {
327
+ "$ref": { "$ref": "#/definitions/configRef" },
328
+ "links": {
329
+ "type": ["array", "object"],
330
+ "if": { "type": "object" },
331
+ "then": { "$ref": "#/definitions/configRefValue" },
332
+ "items": {
333
+ "type": "object",
334
+ "anyOf": [
335
+ { "required": ["$ref"] },
336
+ {
337
+ "required": ["href"],
338
+ "anyOf": [{ "required": ["label"] }, { "required": ["icon"] }]
339
+ }
340
+ ],
341
+ "additionalProperties": false,
342
+ "properties": {
343
+ "$ref": { "$ref": "#/definitions/configRef" },
344
+ "label": {
345
+ "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }],
346
+ "description": "Visible link text. Omit for an icon-only link."
347
+ },
348
+ "href": { "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }], "description": "Destination URL." },
349
+ "ariaLabel": {
350
+ "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }],
351
+ "description": "Accessible text for an icon-only link."
352
+ },
353
+ "icon": {
354
+ "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }],
355
+ "description": "Icon name. Rendered alone when label is omitted."
356
+ },
357
+ "target": {
358
+ "allOf": [{ "$ref": "#/definitions/targetValue" }],
359
+ "description": "Browsing context. Defaults to _self for local links and _blank for external links."
360
+ }
361
+ }
362
+ }
363
+ },
364
+ "primary": {
365
+ "type": "object",
366
+ "anyOf": [
367
+ { "required": ["$ref"] },
368
+ {
369
+ "required": ["href"],
370
+ "anyOf": [{ "required": ["label"] }, { "required": ["icon"] }]
371
+ }
372
+ ],
373
+ "additionalProperties": false,
374
+ "properties": {
375
+ "$ref": { "$ref": "#/definitions/configRef" },
376
+ "label": { "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }], "description": "Visible button text. Omit for icon-only." },
377
+ "href": { "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }], "description": "Button destination URL." },
378
+ "icon": { "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }], "description": "Icon name." },
379
+ "ariaLabel": { "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }], "description": "Accessible text for icon-only buttons." },
380
+ "target": {
381
+ "allOf": [{ "$ref": "#/definitions/targetValue" }],
382
+ "description": "Browsing context. Defaults from the destination URL."
383
+ }
384
+ }
385
+ }
386
+ }
387
+ },
388
+ "metadata": {
389
+ "type": "object",
390
+ "description": "Page metadata settings.",
391
+ "additionalProperties": false,
392
+ "properties": {
393
+ "$ref": { "$ref": "#/definitions/configRef" },
394
+ "timestamp": {
395
+ "allOf": [{ "$ref": "#/definitions/booleanValue" }],
396
+ "description": "Show the last-modified date (from git history) on all pages. Override per page with the `timestamp` frontmatter field.",
397
+ "default": false
398
+ }
399
+ }
400
+ },
401
+ "footer": {
402
+ "type": "object",
403
+ "description": "Footer content: social links and link columns.",
404
+ "additionalProperties": false,
405
+ "properties": {
406
+ "$ref": { "$ref": "#/definitions/configRef" },
407
+ "socials": {
408
+ "type": ["array", "object"],
409
+ "if": { "type": "object" },
410
+ "then": { "$ref": "#/definitions/configRefValue" },
411
+ "description": "Social links displayed in the footer.",
412
+ "items": {
413
+ "type": "object",
414
+ "anyOf": [
415
+ { "required": ["$ref"] },
416
+ {
417
+ "required": ["href"],
418
+ "anyOf": [{ "required": ["label"] }, { "required": ["icon"] }]
419
+ }
420
+ ],
421
+ "additionalProperties": false,
422
+ "properties": {
423
+ "$ref": { "$ref": "#/definitions/configRef" },
424
+ "href": { "$ref": "#/definitions/stringValue" },
425
+ "label": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Visible link text." },
426
+ "icon": { "$ref": "#/definitions/stringValue" },
427
+ "ariaLabel": { "$ref": "#/definitions/stringValue" },
428
+ "target": { "$ref": "#/definitions/targetValue" }
429
+ }
430
+ }
431
+ },
432
+ "links": {
433
+ "type": ["array", "object"],
434
+ "if": { "type": "object" },
435
+ "then": { "$ref": "#/definitions/configRefValue" },
436
+ "description": "Link columns displayed above the footer bottom row.",
437
+ "items": {
438
+ "type": "object",
439
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["items"] }],
440
+ "additionalProperties": false,
441
+ "properties": {
442
+ "$ref": { "$ref": "#/definitions/configRef" },
443
+ "header": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Column heading." },
444
+ "items": {
445
+ "type": ["array", "object"],
446
+ "if": { "type": "object" },
447
+ "then": { "$ref": "#/definitions/configRefValue" },
448
+ "items": {
449
+ "type": "object",
450
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["label", "href"] }],
451
+ "additionalProperties": false,
452
+ "properties": {
453
+ "$ref": { "$ref": "#/definitions/configRef" },
454
+ "label": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Link text." },
455
+ "href": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Link destination URL." },
456
+ "target": { "$ref": "#/definitions/targetValue" }
457
+ }
458
+ }
459
+ }
460
+ }
461
+ }
462
+ },
463
+ "attribution": {
464
+ "allOf": [{ "$ref": "#/definitions/booleanValue" }],
465
+ "description": "Show the Shiso attribution in the footer. Defaults to true.",
466
+ "default": true
467
+ }
468
+ }
469
+ },
470
+ "banner": {
471
+ "type": "object",
472
+ "description": "Site-wide banner displayed above the header.",
473
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["content"] }],
474
+ "additionalProperties": false,
475
+ "properties": {
476
+ "$ref": { "$ref": "#/definitions/configRef" },
477
+ "content": {
478
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
479
+ "description": "Banner text. Supports basic markdown: links, bold, italic, and inline code."
480
+ },
481
+ "dismissible": {
482
+ "allOf": [{ "$ref": "#/definitions/booleanValue" }],
483
+ "description": "Show a dismiss button. Dismissal persists until the content changes.",
484
+ "default": false
485
+ }
486
+ }
487
+ },
488
+ "redirects": {
489
+ "type": ["array", "object"],
490
+ "if": { "type": "object" },
491
+ "then": { "$ref": "#/definitions/configRefValue" },
492
+ "description": "Redirects for moved, renamed, or deleted pages. Sources are matched exactly.",
493
+ "items": {
494
+ "type": "object",
495
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["source", "destination"] }],
496
+ "additionalProperties": false,
497
+ "properties": {
498
+ "$ref": { "$ref": "#/definitions/configRef" },
499
+ "source": { "allOf": [{ "$ref": "#/definitions/redirectSourceValue" }], "description": "Exact path to redirect from, e.g. \"/docs/old-page\"." },
500
+ "destination": {
501
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
502
+ "description": "Path or URL to redirect to, e.g. \"/new-page\"."
503
+ }
504
+ }
505
+ }
506
+ },
507
+ "seo": {
508
+ "type": "object",
509
+ "description": "SEO indexing configuration.",
510
+ "additionalProperties": false,
511
+ "properties": {
512
+ "$ref": { "$ref": "#/definitions/configRef" },
513
+ "metatags": {
514
+ "type": "object",
515
+ "description": "Meta tags added to every page, e.g. { \"og:image\": \"/social.png\" }.",
516
+ "additionalProperties": { "$ref": "#/definitions/stringValue" }
517
+ },
518
+ "indexing": {
519
+ "anyOf": [
520
+ { "enum": ["navigable", "all"] },
521
+ { "$ref": "#/definitions/configRefValue" }
522
+ ],
523
+ "description": "\"navigable\" (default) marks hidden pages noindex and keeps them out of the sitemap; \"all\" indexes every page.",
524
+ "default": "navigable"
525
+ }
526
+ }
527
+ },
528
+ "errors": {
529
+ "type": "object",
530
+ "description": "Error handling settings.",
531
+ "additionalProperties": false,
532
+ "properties": {
533
+ "$ref": { "$ref": "#/definitions/configRef" },
534
+ "404": {
535
+ "type": "object",
536
+ "description": "\"Page not found\" behavior.",
537
+ "additionalProperties": false,
538
+ "properties": {
539
+ "$ref": { "$ref": "#/definitions/configRef" },
540
+ "redirect": {
541
+ "allOf": [{ "$ref": "#/definitions/booleanValue" }],
542
+ "description": "Navigate to the docs home when a page is not found. Defaults to true.",
543
+ "default": true
544
+ },
545
+ "title": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Custom title for the 404 page." },
546
+ "description": {
547
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
548
+ "description": "Custom description. Supports basic markdown: links, bold, italic, and inline code."
549
+ }
550
+ }
551
+ }
552
+ }
553
+ }
554
+ },
555
+ "definitions": {
556
+ "configRef": {
557
+ "type": "string",
558
+ "pattern": "^(?![A-Za-z][A-Za-z0-9+.-]*:)(?![/\\\\]).+\\.json$",
559
+ "description": "Relative path to another JSON configuration file. Resolved relative to the file containing this reference."
560
+ },
561
+ "configRefValue": {
562
+ "type": "object",
563
+ "description": "Reference to a JSON file used in place of this configuration value.",
564
+ "required": ["$ref"],
565
+ "additionalProperties": true,
566
+ "properties": {
567
+ "$ref": { "$ref": "#/definitions/configRef" }
568
+ }
569
+ },
570
+ "stringValue": {
571
+ "anyOf": [
572
+ { "type": "string" },
573
+ { "$ref": "#/definitions/configRefValue" }
574
+ ]
575
+ },
576
+ "nonEmptyStringValue": {
577
+ "anyOf": [
578
+ { "type": "string", "minLength": 1 },
579
+ { "$ref": "#/definitions/configRefValue" }
580
+ ]
581
+ },
582
+ "booleanValue": {
583
+ "anyOf": [
584
+ { "type": "boolean" },
585
+ { "$ref": "#/definitions/configRefValue" }
586
+ ]
587
+ },
588
+ "numberValue": {
589
+ "anyOf": [
590
+ { "type": "number" },
591
+ { "$ref": "#/definitions/configRefValue" }
592
+ ]
593
+ },
594
+ "targetValue": {
595
+ "anyOf": [
596
+ { "enum": ["_self", "_blank"] },
597
+ { "$ref": "#/definitions/configRefValue" }
598
+ ]
599
+ },
600
+ "redirectSourceValue": {
601
+ "anyOf": [
602
+ { "type": "string", "pattern": "^/[^*]*$" },
603
+ { "$ref": "#/definitions/configRefValue" }
604
+ ]
605
+ },
606
+ "pageItemList": {
607
+ "anyOf": [
608
+ { "type": "array", "items": { "$ref": "#/definitions/pageItem" } },
609
+ { "$ref": "#/definitions/configRefValue" }
610
+ ]
611
+ },
612
+ "groupList": {
613
+ "anyOf": [
614
+ { "type": "array", "items": { "$ref": "#/definitions/group" } },
615
+ { "$ref": "#/definitions/configRefValue" }
616
+ ]
617
+ },
618
+ "dropdownList": {
619
+ "anyOf": [
620
+ { "type": "array", "items": { "$ref": "#/definitions/dropdown" } },
621
+ { "$ref": "#/definitions/configRefValue" }
622
+ ]
623
+ },
624
+ "tabList": {
625
+ "anyOf": [
626
+ { "type": "array", "items": { "$ref": "#/definitions/tab" } },
627
+ { "$ref": "#/definitions/configRefValue" }
628
+ ]
629
+ },
630
+ "anchorList": {
631
+ "anyOf": [
632
+ { "type": "array", "items": { "$ref": "#/definitions/anchor" } },
633
+ { "$ref": "#/definitions/configRefValue" }
634
+ ]
635
+ },
636
+ "versionList": {
637
+ "anyOf": [
638
+ { "type": "array", "items": { "$ref": "#/definitions/version" } },
639
+ { "$ref": "#/definitions/configRefValue" }
640
+ ]
641
+ },
642
+ "languageList": {
643
+ "anyOf": [
644
+ { "type": "array", "items": { "$ref": "#/definitions/language" } },
645
+ { "$ref": "#/definitions/configRefValue" }
646
+ ]
647
+ },
648
+ "fontSpec": {
649
+ "type": "object",
650
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["family"] }],
651
+ "additionalProperties": false,
652
+ "properties": {
653
+ "$ref": { "$ref": "#/definitions/configRef" },
654
+ "family": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Font family name, e.g. \"Open Sans\"." },
655
+ "weight": { "allOf": [{ "$ref": "#/definitions/numberValue" }], "description": "Font weight, e.g. 400 or 700." },
656
+ "source": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "URL or path to a hosted font file." },
657
+ "format": {
658
+ "anyOf": [
659
+ { "enum": ["woff", "woff2"] },
660
+ { "$ref": "#/definitions/configRefValue" }
661
+ ],
662
+ "description": "Font file format, for `source`."
663
+ }
664
+ }
665
+ },
666
+ "pageItem": {
667
+ "anyOf": [
668
+ {
669
+ "type": "string",
670
+ "description": "Page reference relative to the content directory, without extension (e.g. \"components/tabs\")."
671
+ },
672
+ { "$ref": "#/definitions/pageObject" },
673
+ { "$ref": "#/definitions/linkItem" },
674
+ { "$ref": "#/definitions/group" }
675
+ ]
676
+ },
677
+ "pageObject": {
678
+ "type": "object",
679
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["page"] }],
680
+ "additionalProperties": false,
681
+ "properties": {
682
+ "$ref": { "$ref": "#/definitions/configRef" },
683
+ "page": {
684
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
685
+ "description": "Page reference relative to the content directory, without extension."
686
+ },
687
+ "title": {
688
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
689
+ "description": "Custom sidebar label. Overrides the label derived from the file name."
690
+ },
691
+ "label": {
692
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
693
+ "description": "Custom sidebar label. Takes precedence over title."
694
+ },
695
+ "icon": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Icon name shown beside the label." },
696
+ "tag": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Short label shown after the page name." },
697
+ "hidden": {
698
+ "allOf": [{ "$ref": "#/definitions/booleanValue" }],
699
+ "description": "Hide from the sidebar and search. The page is still built and reachable by URL."
700
+ }
701
+ }
702
+ },
703
+ "linkItem": {
704
+ "type": "object",
705
+ "description": "An external link in the navigation tree.",
706
+ "anyOf": [
707
+ { "required": ["$ref"] },
708
+ {
709
+ "required": ["href"],
710
+ "anyOf": [{ "required": ["label"] }, { "required": ["anchor"] }]
711
+ }
712
+ ],
713
+ "additionalProperties": false,
714
+ "properties": {
715
+ "$ref": { "$ref": "#/definitions/configRef" },
716
+ "href": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Destination URL." },
717
+ "label": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Link text." },
718
+ "anchor": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Alias for label." },
719
+ "icon": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Icon name shown beside the label." },
720
+ "hidden": { "allOf": [{ "$ref": "#/definitions/booleanValue" }], "description": "Hide from the sidebar." },
721
+ "target": { "$ref": "#/definitions/targetValue" }
722
+ }
723
+ },
724
+ "anchor": {
725
+ "type": "object",
726
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["anchor"] }],
727
+ "additionalProperties": false,
728
+ "properties": {
729
+ "$ref": { "$ref": "#/definitions/configRef" },
730
+ "anchor": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Anchor label." },
731
+ "href": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Destination URL." },
732
+ "icon": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Icon name shown beside the label." },
733
+ "hidden": { "allOf": [{ "$ref": "#/definitions/booleanValue" }], "description": "Hide the anchor." },
734
+ "target": { "$ref": "#/definitions/targetValue" }
735
+ }
736
+ },
737
+ "group": {
738
+ "type": "object",
739
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["group", "pages"] }],
740
+ "additionalProperties": false,
741
+ "properties": {
742
+ "$ref": { "$ref": "#/definitions/configRef" },
743
+ "group": { "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }], "description": "Group heading shown in the sidebar." },
744
+ "root": {
745
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
746
+ "description": "Optional landing page for the group. When set, the group title links to this page (chevron still expands/collapses)."
747
+ },
748
+ "pages": { "$ref": "#/definitions/pageItemList" },
749
+ "icon": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Icon name shown beside the heading." },
750
+ "expanded": {
751
+ "allOf": [{ "$ref": "#/definitions/booleanValue" }],
752
+ "description": "When true, nested groups start expanded. Top-level groups start expanded by default. Groups that contain the current page always expand."
753
+ },
754
+ "collapsible": {
755
+ "allOf": [{ "$ref": "#/definitions/booleanValue" }],
756
+ "description": "When false, the group stays expanded and its heading does not show a collapse control."
757
+ },
758
+ "hidden": {
759
+ "allOf": [{ "$ref": "#/definitions/booleanValue" }],
760
+ "description": "Hide the group and its pages from the sidebar."
761
+ }
762
+ }
763
+ },
764
+ "dropdown": {
765
+ "type": "object",
766
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["dropdown"] }],
767
+ "additionalProperties": false,
768
+ "properties": {
769
+ "$ref": { "$ref": "#/definitions/configRef" },
770
+ "dropdown": {
771
+ "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }],
772
+ "description": "Dropdown label rendered by the selected theme."
773
+ },
774
+ "groups": { "$ref": "#/definitions/groupList" },
775
+ "pages": { "$ref": "#/definitions/pageItemList" },
776
+ "icon": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Icon name shown beside the label." },
777
+ "hidden": { "allOf": [{ "$ref": "#/definitions/booleanValue" }], "description": "Hide the dropdown." }
778
+ }
779
+ },
780
+ "tab": {
781
+ "type": "object",
782
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["tab"] }],
783
+ "additionalProperties": false,
784
+ "properties": {
785
+ "$ref": { "$ref": "#/definitions/configRef" },
786
+ "tab": { "allOf": [{ "$ref": "#/definitions/nonEmptyStringValue" }], "description": "Tab label shown in the top navigation." },
787
+ "groups": { "$ref": "#/definitions/groupList" },
788
+ "pages": { "$ref": "#/definitions/pageItemList" },
789
+ "dropdowns": { "$ref": "#/definitions/dropdownList" },
790
+ "icon": { "allOf": [{ "$ref": "#/definitions/stringValue" }], "description": "Icon name shown beside the tab label." },
791
+ "hidden": { "allOf": [{ "$ref": "#/definitions/booleanValue" }], "description": "Hide the tab from the top navigation." }
792
+ }
793
+ },
794
+ "version": {
795
+ "type": "object",
796
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["version"] }],
797
+ "additionalProperties": false,
798
+ "properties": {
799
+ "$ref": { "$ref": "#/definitions/configRef" },
800
+ "version": {
801
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
802
+ "description": "Version label. Only the default (or first) version is rendered."
803
+ },
804
+ "default": { "allOf": [{ "$ref": "#/definitions/booleanValue" }], "description": "Marks this version as the one to render." },
805
+ "hidden": { "allOf": [{ "$ref": "#/definitions/booleanValue" }], "description": "Hide this version." },
806
+ "tabs": { "$ref": "#/definitions/tabList" },
807
+ "dropdowns": { "$ref": "#/definitions/dropdownList" },
808
+ "groups": { "$ref": "#/definitions/groupList" },
809
+ "pages": { "$ref": "#/definitions/pageItemList" }
810
+ }
811
+ },
812
+ "language": {
813
+ "type": "object",
814
+ "anyOf": [{ "required": ["$ref"] }, { "required": ["language"] }],
815
+ "additionalProperties": false,
816
+ "properties": {
817
+ "$ref": { "$ref": "#/definitions/configRef" },
818
+ "language": {
819
+ "allOf": [{ "$ref": "#/definitions/stringValue" }],
820
+ "description": "Language code or label. Only the default (or first) language is rendered."
821
+ },
822
+ "default": {
823
+ "allOf": [{ "$ref": "#/definitions/booleanValue" }],
824
+ "description": "Marks this language as the one to render."
825
+ },
826
+ "hidden": { "allOf": [{ "$ref": "#/definitions/booleanValue" }], "description": "Hide this language." },
827
+ "versions": { "$ref": "#/definitions/versionList" },
828
+ "tabs": { "$ref": "#/definitions/tabList" },
829
+ "dropdowns": { "$ref": "#/definitions/dropdownList" },
830
+ "groups": { "$ref": "#/definitions/groupList" },
831
+ "pages": { "$ref": "#/definitions/pageItemList" }
832
+ }
833
+ }
834
+ }
835
+ }