@gitpagedocs/cli 0.0.10 → 0.0.12

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 CHANGED
@@ -28,7 +28,8 @@ npx @gitpagedocs/cli
28
28
  | `gitpagedocs provider [id]` · `models [provider]` | List AI providers / catalog models |
29
29
  | `gitpagedocs document[:repo\|:file\|:folder]` | Generate documentation with AI in the gitpagedocs pattern |
30
30
  | `gitpagedocs password` | Set a documentation access password (writes the public key to `config.json`, prints the private key) |
31
- | `gitpagedocs deploy` / `pages [actions\|deploy]` | Configure GitHub Pages via Actions + push |
31
+ | `gitpagedocs deploy` / `pages deploy` | Configure GitHub Pages via Actions, generate, commit and push |
32
+ | `gitpagedocs pages actions` | Switch the repository's Pages source to GitHub Actions; no generation or push |
32
33
  | `gitpagedocs docs` | Refresh managed regions of README/CONTRIBUTING/SECURITY |
33
34
  | `gitpagedocs config clear` | Delete the stored `.gitpagedocsconfig` **and** the encrypted key vault `.gitpagedocsvault` (wipes saved AI credentials) |
34
35
  | `gitpagedocs doctor` · `version` · `update` | Diagnostics / version / registry update check |
@@ -36,6 +37,24 @@ npx @gitpagedocs/cli
36
37
 
37
38
  The AI-CLI implementation lives in `cli/ai/` (relocated from the frontend so the published package is self-contained).
38
39
 
40
+ ## Generated documentation and themes
41
+
42
+ Version 0.0.12 registers documentation versions 0.0.12, 0.0.11 and 0.0.10 with English, Portuguese and Spanish pages. Existing older folders are preserved. Source content lives in `content/`; defaults and UI labels live in `data/`; edit these sources before regeneration. The published package includes the English PDF guide and the local HTML integration for the externally hosted DOOM player.
43
+
44
+ The scaffold demonstrates parent Markdown destinations with recursive submenus and navigable breadcrumbs, PDF routes/actions, and a page with ordered, repeated Markdown/HTML/video/audio/PDF blocks. Route titles and descriptions have independent placement settings. Focus mode provides source actions and eight document/section navigation controls; browser narration is configured separately. See the generated configuration, content-blocks, focus, accessibility and HTML/PDF guides for complete examples.
45
+
46
+ `gitpagedocs --layoutconfig` ships all 124 themes: 64 original themes, 20 standalone animated presets and 20 additional dark/light parallax pairs. New presets originate in `gitpagelayouts/v2/` and are compiled into package-local data by `pnpm run layouts:sync`; a standalone CLI installation does not need the source repository to emit them. Customize backgrounds through `site.backgroundEffects`, including global/per-theme settings, colors, density, speed and parallax. The master switch disables backgrounds; `overrides.accessibility.showPauseButton: false` hides only the pause control.
47
+
48
+ `site.icons.VersionSelector` and `BackgroundAnimationPause`/`BackgroundAnimationResume` use the same `reactIcon`, `tag`, `size`, `colorDark` and `colorLight` contract as other controls. Pause/resume appears in the navigation menu beside its lock; a manual pause persists across theme and menu changes. `reactIcon: false` selects localized text independently for each control.
49
+
50
+ The [MCP reference](../mcp/README.md) documents installation, client configuration, all 20 tools and seven resources. MCP runs over stdio and reads provider credentials from its environment; it does not automatically unlock the CLI vault.
51
+
52
+ ## Packaging and release
53
+
54
+ Root and frontend workspaces are private. The public packages are `@gitpagedocs/tools`, `@gitpagedocs/mcp` and `@gitpagedocs/cli`; their versions, internal ranges and lockfile must agree. The npm workflow checks a new CLI version, installs with a frozen lockfile, runs typecheck and contract self-tests, then publishes the workspaces. GitHub Pages builds the viewer in its separate workflow. Neither workflow creates GitHub release notes or tags automatically.
55
+
56
+ The package allowlist includes its source, templates, data and assets. `prebuilt/` is optional and is not created by the npm workflow. The config-only command generates repository data without starting a server. Run the full project checks and inspect package contents before publication; verify the published package and deployed site afterward.
57
+
39
58
  # CLI Architecture (Clean Architecture + SOLID)
40
59
 
41
60
  ## Layer Overview
@@ -141,7 +160,7 @@ npx @gitpagedocs/cli ai
141
160
 
142
161
  ### What it does
143
162
 
144
- - asks provider (`openai`, `claude`, `gemini`, `ollama`)
163
+ - asks for a provider from the shared catalog (14 providers, including OpenAI, Anthropic, Gemini and Ollama)
145
164
  - asks API key or Ollama URL
146
165
  - asks paths to scan (supports one or many paths, including other repositories)
147
166
  - generates documentation in `pt`, `en`, `es` **in the gitpagedocs pattern**
@@ -169,21 +188,22 @@ permissions on POSIX systems:
169
188
  - Linux: `$XDG_CONFIG_HOME/gitpagedocs/.gitpagedocsconfig` (or `~/.config/gitpagedocs/.gitpagedocsconfig`)
170
189
 
171
190
  Set `GITPAGEDOCS_CONFIG_DIR` to override the directory; delete the stored file,
172
- the vault and their credentials with `gitpagedocs config clear`. You can create/edit
173
- this file manually and then run `npx @gitpagedocs/cli ai`:
191
+ the vault and their credentials with `gitpagedocs config clear`. This example describes
192
+ a saved configuration whose key already exists in the encrypted vault. Edit its non-secret
193
+ settings and then run `npx @gitpagedocs/cli ai`. For a new installation, run the interactive
194
+ setup first; if no key exists, decline reuse of the configuration and enter the credentials.
174
195
 
175
196
  ```json
176
197
  {
177
198
  "version": 1,
178
199
  "ai": {
179
200
  "provider": "openai",
180
- "model": "gpt-4o-mini",
181
201
  "apiKeyEncrypted": true,
182
202
  "paths": ["src", "cli", "../another-repo/src"],
183
203
  "languages": ["pt", "en", "es"],
184
204
  "outputDir": "gitpagedocs/docs",
185
205
  "filePrefix": "ai-generated",
186
- "contextPrompt": "Você é um redator técnico sênior..."
206
+ "contextPrompt": "Write clear technical documentation for this project."
187
207
  }
188
208
  }
189
209
  ```
@@ -200,7 +220,7 @@ derived from your password with PBKDF2-HMAC-SHA-256, 210k iterations) and the co
200
220
  - `GITPAGEDOCS_VAULT_PASSWORD` supplies the password without a prompt (CI, pipes, no TTY);
201
221
  on a first run it initializes the vault, otherwise it must match the existing one.
202
222
  - A plaintext `"apiKey"` written by 0.0.1 is sealed into the vault and removed from the file
203
- the next time the config is read.
223
+ when `ai` or `chat` reuses that configuration and unlocks it with the vault password.
204
224
  - If you hand-write the file, leave the key out: enter it in the `gitpagedocs ai` prompt (it is
205
225
  sealed on save). `gitpagedocs chat` can also read the provider's environment variable
206
226
  (`gitpagedocs provider <id>` lists it) when no key is stored.
@@ -14,7 +14,7 @@ import { GITPAGEDOCS_DOC_SYSTEM_PROMPT } from "../config";
14
14
  import { parseAiPages, type AiDocPage } from "./docs-pattern";
15
15
  import { writeVersionDocs } from "../infrastructure/version-docs-writer";
16
16
  // @ts-expect-error .mjs runtime module is type-less in this package.
17
- import { DOC_VERSIONS } from "../../contracts/doc-versions.mjs";
17
+ import { PACKAGE_VERSION } from "../../contracts/doc-versions.mjs";
18
18
 
19
19
  const LANGUAGE_TO_LABEL: Record<string, string> = {
20
20
  pt: "Portuguese",
@@ -122,7 +122,7 @@ export async function executeAiRunPlan(
122
122
  }
123
123
 
124
124
  // Wire the AI pages into the latest documentation version (gitpagedocs pattern).
125
- const versionId = DOC_VERSIONS[DOC_VERSIONS.length - 1] as string;
125
+ const versionId = PACKAGE_VERSION as string;
126
126
  const result = await writeVersionDocs({ cwd, versionId, pagesByLang });
127
127
 
128
128
  return {
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { PACKAGE_VERSION } from "../contracts/doc-versions.mjs";
4
4
  import { THEME_COLORS } from "../data/theme-colors.mjs";
5
+ import { ANIMATED_BACKGROUNDS } from "../data/animated-layouts.mjs";
5
6
 
6
7
  /** `#RRGGBB` (or `#RGB`) to `rgba(r, g, b, alpha)` for palette-derived glows and borders. */
7
8
  function rgba(hex, alpha) {
@@ -14,6 +15,7 @@ function rgba(hex, alpha) {
14
15
  export function createThemeTemplate(layout, themeColors = THEME_COLORS) {
15
16
  const colors = themeColors[layout.id] ?? themeColors.default;
16
17
  const dark = layout.mode === "dark";
18
+ const background = ANIMATED_BACKGROUNDS[layout.id];
17
19
  return {
18
20
  id: layout.id,
19
21
  name: layout.name,
@@ -82,5 +84,6 @@ export function createThemeTemplate(layout, themeColors = THEME_COLORS) {
82
84
  enableGlow: dark,
83
85
  transitionDuration: "0.22s",
84
86
  },
87
+ ...(background ? { backgroundEffects: structuredClone(background) } : {}),
85
88
  };
86
89
  }
@@ -31,6 +31,7 @@ import { buildAudioRoute, buildMdRoute, buildPdfRoute, buildSourceViewerRoute, b
31
31
  import { resolveSourceViewerPath } from "./project-links.mjs";
32
32
  import { MARKDOWN_MENU_SECTIONS } from "../data/menu-sections.mjs";
33
33
  import { SUPPORTED_LANGUAGES } from "../contracts/languages.mjs";
34
+ import { COMPOSED_PAGES } from "../data/composed-pages.mjs";
34
35
 
35
36
  /** Demo route protections showcasing the "Authorized Routes" feature. They are
36
37
  * applied only to the official (non-parameterized) scaffold — user sites
@@ -158,12 +159,16 @@ function buildMarkdownMenus(entries, base) {
158
159
  es: { title: ROUTE_METAS[entry].titles.es, "path-click": `${base}/es/${ROUTE_PATHS[entry].es}` },
159
160
  };
160
161
  }
162
+ const parentPaths = ROUTE_PATHS[entry.routeId];
163
+ const parentLabels = Object.fromEntries(SUPPORTED_LANGUAGES.map((language) => [language, {
164
+ title: entry.titles[language],
165
+ ...(parentPaths ? { "path-click": `${base}/${language}/${parentPaths[language]}` } : {}),
166
+ ...(entry.pathClick ? { "path-click": entry.pathClick } : {}),
167
+ }]));
161
168
  return {
162
169
  id: entry.id,
163
- pt: { title: entry.titles.pt },
164
- en: { title: entry.titles.en },
165
- es: { title: entry.titles.es },
166
- submenus: buildMarkdownMenus(entry.submenus, base),
170
+ ...parentLabels,
171
+ ...(entry.submenus ? { submenus: buildMarkdownMenus(entry.submenus, base) } : {}),
167
172
  };
168
173
  });
169
174
  }
@@ -260,6 +265,7 @@ export function buildVersionConfig(versionId, options = {}) {
260
265
  "routes-video": buildVersionVideoRoutes(versionId, includeDemoAuthorization),
261
266
  "routes-audio": buildVersionAudioRoutes(versionId),
262
267
  "routes-pdf": [buildPdfRoute(PDF_GUIDE_META, `gitpagedocs/docs/versions/${versionId}/en/${PDF_GUIDE_FILENAME}`)],
268
+ pages: structuredClone(COMPOSED_PAGES),
263
269
  "menus-header-md": menus.md,
264
270
  "menus-header-source-viewer": menus.sourceViewer,
265
271
  "menus-header-html": menus.html,
@@ -3,6 +3,20 @@ import { PACKAGE_VERSION } from "../contracts/doc-versions.mjs";
3
3
  const docsDirectory = `gitpagedocs/docs/versions/${PACKAGE_VERSION}`;
4
4
  const localizedPath = (file) => Object.fromEntries(["en", "pt", "es"].map((language) => [language, `${docsDirectory}/${language}/${file}`]));
5
5
 
6
+ const menuLabels = (titles, file) => Object.fromEntries(["en", "pt", "es"].map((language) => [language, {
7
+ title: titles[language], "path-click": `${docsDirectory}/${language}/${file}`,
8
+ }]));
9
+
10
+ export const PARENT_MENU_JSON = JSON.stringify({
11
+ id: 1000,
12
+ ...menuLabels({ en: "Guides", pt: "Guias", es: "Guías" }, "guides.md"),
13
+ submenus: [{
14
+ id: 1001,
15
+ ...menuLabels({ en: "Configure your site", pt: "Configure seu site", es: "Configura tu sitio" }, "configure-your-site.md"),
16
+ submenus: [{ id: 13, ...menuLabels({ en: "Configuration", pt: "Configuração", es: "Configuración" }, "configuration.md") }],
17
+ }],
18
+ }, null, 2);
19
+
6
20
  export const HTML_ROUTE_JSON = JSON.stringify({
7
21
  id: 29,
8
22
  title: { en: "DOOM: HTML example", pt: "DOOM: exemplo HTML", es: "DOOM: ejemplo HTML" },
@@ -27,14 +41,15 @@ export const RECIPE_ROOT_JSON = JSON.stringify({
27
41
  focusMode: { copyEnabled: true, downloadEnabled: true, sectionNavigationEnabled: true, documentNavigationEnabled: true },
28
42
  icons: {
29
43
  defaults: { reactIcon: true, size: "22px", colorDark: "currentColor", colorLight: "currentColor" },
30
- LanguageSelector: { tag: "FiGlobe" },
31
- ThemeSelector: { tag: "BsSunFill" },
32
- FocusMode: { tag: "MdFullscreen" },
33
- QuickNavigation: { tag: "FiSearch" },
34
- PdfDownload: { tag: "FiDownload" },
35
- PdfOpenInNewTab: { tag: "FiExternalLink" },
36
- DocumentPrevious: { tag: "FiChevronLeft" },
37
- DocumentNext: { tag: "FiChevronRight" },
44
+ LanguageSelector: { tag: "SiGoogletranslate" },
45
+ ThemeSelector: { tag: "LuPencil" },
46
+ VersionSelector: { tag: "LuGitBranch" },
47
+ FocusMode: { tag: "LuBookOpen" },
48
+ QuickNavigation: { tag: "LuSearch" },
49
+ PdfDownload: { tag: "LuDownload" },
50
+ PdfOpenInNewTab: { tag: "LuExternalLink" },
51
+ DocumentPrevious: { tag: "LuChevronLeft" },
52
+ DocumentNext: { tag: "LuChevronRight" },
38
53
  },
39
54
  pdf: { enabled: true, previewEnabled: true, downloadEnabled: true, openInNewTabEnabled: true },
40
55
  },
@@ -0,0 +1,142 @@
1
+ import { COMPOSED_PAGES } from "../data/composed-pages.mjs";
2
+
3
+ const blocksExample = JSON.stringify({ pages: COMPOSED_PAGES }, null, 2);
4
+ const layoutExample = JSON.stringify({
5
+ id: 23,
6
+ layout: {
7
+ title: { placement: "outside", position: "before" },
8
+ description: { placement: "inside", position: "after" },
9
+ },
10
+ }, null, 2);
11
+
12
+ export const CONTENT_BLOCKS_DOCS = {
13
+ en: `# Ordered content blocks
14
+
15
+ A page can contain several Markdown documents, HTML players, videos, audio tracks and PDFs in any order. Add a top-level \`pages\` array to the version configuration. Each block references a route already defined in the corresponding \`routes-md\`, \`routes-html\`, \`routes-video\`, \`routes-audio\` or \`routes-pdf\` list. The page has one URL; blocks do not create separate navigation destinations.
16
+
17
+ ## Complete repeated-block example
18
+
19
+ The scaffold's page 39 combines three Markdown blocks, two HTML blocks, two videos, two audio tracks and three PDFs. It references the included routes 1, 2, 30, 29, 11, 12 and 23. Merge the following object into \`gitpagedocs/docs/versions/0.0.10/config.json\` or the current version's config; retain those route definitions and their files. The same example is included in the new scaffold.
20
+
21
+ \`\`\`json
22
+ ${blocksExample}
23
+ \`\`\`
24
+
25
+ Add a menu destination with \`"path-click": "page:39"\` in each language. The bundled entry is under Guides → Read and explore → Multiple content blocks. Its label is independent of the labels of the individual blocks.
26
+
27
+ ## Ordering, repetition and individual settings
28
+
29
+ - \`pages[].id\` is an integer page identity. Use a new ID that does not collide with an existing route ID.
30
+ - \`blocks[].id\` is a nonempty string, unique within its page. Two instances may use the same \`routeId\`, but need different block IDs.
31
+ - \`type\` is exactly \`md\`, \`html\`, \`video\`, \`audio\` or \`pdf\`; \`routeId\` selects a route from that type's list.
32
+ - Array order is display order. Move a block object to reorder it, remove it to hide that instance, or copy it with a new block ID to repeat it. \`hierarchyPage\` still applies to legacy pages and does not reorder this array.
33
+
34
+ Each reference uses its route's source, translation, visibility, sizing, PDF actions, media controls and authorization. To give two occurrences of the same file different options, define two routes with distinct IDs and the same source path, then reference those IDs. Do not put a second copy of route parameters inside a block.
35
+
36
+ A Markdown block renders only that Markdown document; inline legacy audio attached to its route does not become an extra block. Refer to an audio route explicitly when it belongs in the sequence. Blocks select fixed routes and do not share a \`browseAll\` index. Media exclusivity and browser restrictions still apply; repeating a player does not start playback automatically.
37
+
38
+ Focus mode and narration read the authorized Markdown blocks available in the selected language, in array order, including repetitions. Focus copy/download joins their original sources with two newline characters and uses \`page-39.md\` for this example. Each visible Markdown container keeps its individual copy/download actions and original filename. Rendered heading IDs are namespaced per block to avoid duplicate anchors; the downloaded source is unchanged. Denied pages or blocks are excluded from rendering, copy, focus and narration. This client-side gate does not protect public assets or prevent the document loader from reading their sources.
39
+
40
+ ## Position titles and descriptions
41
+
42
+ Every content route accepts \`layout.title\` and \`layout.description\` independently. \`placement\` is \`outside\` or \`inside\` the content container; \`position\` is \`before\` or \`after\` the content. Merge this presentation fragment into an existing route, preserving its content fields:
43
+
44
+ \`\`\`json
45
+ ${layoutExample}
46
+ \`\`\`
47
+
48
+ For Markdown, configured title and description always remain outside the rendered document; before/after positioning is honored. Headings authored inside the Markdown remain part of that document. HTML, video, audio and PDF accept both placements. These fields change presentation, not the source file or media contents. Existing \`titleIsVisible\`, \`descriptionIsVisible\`, alignment and styling options continue to apply. Omit \`layout\` to preserve the existing presentation. Shared values may live in \`routeDefaults\`; an explicit route-level \`layout\` replaces that defaults object.
49
+
50
+ ## Compatibility and access
51
+
52
+ Configs without \`pages\` keep their existing single-container or mixed-route behavior. A version-level \`pages\` array overrides the root array; \`[]\` clears it. Invalid definitions or unresolved references are ignored without preventing other pages from loading. Duplicate page or block identities keep the first valid entry, and a page ID colliding with a route is ignored so the existing route remains available. Review these mistakes in your configuration rather than relying on omission.
53
+
54
+ Page-level \`authorization\` protects the composed destination, and each referenced route retains its own access requirements. Hiding a block does not protect publicly hosted files. Markdown and PDF do not invent a translation when their selected-language file is absent; other types retain their existing route fallback behavior, including English fallback for video/audio and external HTML URLs. Test every block and language, direct page navigation, restricted routes, repeated media, download errors and browser resource limits before publishing. Large numbers of active embeds or PDFs consume memory and network bandwidth; include only what readers need.
55
+ `,
56
+ pt: `# Blocos de conteúdo ordenados
57
+
58
+ Uma página pode conter vários documentos Markdown, players HTML, vídeos, faixas de áudio e PDFs em qualquer ordem. Adicione um array \`pages\` no nível principal do config da versão. Cada bloco referencia uma rota já definida em \`routes-md\`, \`routes-html\`, \`routes-video\`, \`routes-audio\` ou \`routes-pdf\`. A página possui uma única URL; os blocos não criam destinos de navegação separados.
59
+
60
+ ## Exemplo completo com repetições
61
+
62
+ A página 39 do scaffold reúne três blocos Markdown, dois HTML, dois vídeos, dois áudios e três PDFs. Ela referencia as rotas incluídas 1, 2, 30, 29, 11, 12 e 23. Combine o objeto abaixo com \`gitpagedocs/docs/versions/0.0.10/config.json\` ou com o config da versão atual; preserve as definições dessas rotas e seus arquivos. O mesmo exemplo acompanha o novo scaffold.
63
+
64
+ \`\`\`json
65
+ ${blocksExample}
66
+ \`\`\`
67
+
68
+ Adicione um destino de menu com \`"path-click": "page:39"\` em cada idioma. A entrada incluída fica em Guias → Leia e explore → Múltiplos blocos de conteúdo. Seu rótulo é independente dos rótulos de cada bloco.
69
+
70
+ ## Ordem, repetição e opções individuais
71
+
72
+ - \`pages[].id\` é um identificador inteiro da página. Use um ID novo que não coincida com um ID de rota existente.
73
+ - \`blocks[].id\` é uma string não vazia, única dentro da página. Duas instâncias podem usar o mesmo \`routeId\`, mas precisam de IDs de bloco diferentes.
74
+ - \`type\` aceita exatamente \`md\`, \`html\`, \`video\`, \`audio\` ou \`pdf\`; \`routeId\` seleciona uma rota da lista desse tipo.
75
+ - A ordem do array é a ordem de exibição. Mova um objeto para reordená-lo, remova-o para ocultar aquela instância ou copie-o com um ID novo para repetir. \`hierarchyPage\` continua valendo para páginas legadas e não reordena esse array.
76
+
77
+ Cada referência usa a origem, tradução, visibilidade, dimensões, ações PDF, controles de mídia e autorização da sua rota. Para dar opções diferentes a duas ocorrências do mesmo arquivo, defina duas rotas com IDs distintos e o mesmo caminho de origem; depois referencie esses IDs. Não duplique parâmetros de rota dentro do bloco.
78
+
79
+ Um bloco Markdown renderiza apenas seu documento; um áudio inline legado da rota não se transforma em bloco extra. Referencie uma rota de áudio explicitamente quando ela fizer parte da sequência. Os blocos selecionam rotas fixas e não compartilham um índice de \`browseAll\`. A exclusividade de mídia e as restrições do navegador continuam valendo; repetir um player não inicia reprodução automaticamente.
80
+
81
+ Modo foco e narração leem os blocos Markdown autorizados e disponíveis no idioma selecionado, na ordem do array, incluindo repetições. Copiar/baixar no foco reúne as fontes originais com duas quebras de linha e usa \`page-39.md\` neste exemplo. Cada container Markdown visível mantém suas ações individuais de cópia/download e o nome original do arquivo. IDs de títulos renderizados recebem um prefixo por bloco para evitar âncoras duplicadas; a fonte baixada não muda. Páginas ou blocos negados são excluídos da renderização, cópia, foco e narração. Esse controle no cliente não protege arquivos públicos nem impede o carregador de documentos de ler suas fontes.
82
+
83
+ ## Posicionar títulos e descrições
84
+
85
+ Toda rota de conteúdo aceita \`layout.title\` e \`layout.description\` independentemente. \`placement\` vale \`outside\` ou \`inside\` do container; \`position\` vale \`before\` ou \`after\` do conteúdo. Combine este fragmento de apresentação com uma rota existente, preservando os campos do conteúdo:
86
+
87
+ \`\`\`json
88
+ ${layoutExample}
89
+ \`\`\`
90
+
91
+ No Markdown, título e descrição configurados sempre ficam fora do documento renderizado; a posição antes/depois é respeitada. Títulos escritos dentro do Markdown continuam pertencendo ao documento. HTML, vídeo, áudio e PDF aceitam as duas posições de container. Esses campos mudam a apresentação, não o arquivo de origem nem o conteúdo da mídia. \`titleIsVisible\`, \`descriptionIsVisible\`, alinhamento e estilos existentes continuam valendo. Omita \`layout\` para manter a apresentação atual. Valores compartilhados podem ficar em \`routeDefaults\`; um \`layout\` explícito da rota substitui esse objeto dos defaults.
92
+
93
+ ## Compatibilidade e acesso
94
+
95
+ Configs sem \`pages\` mantêm o comportamento existente de containers únicos ou rotas mistas. O array \`pages\` da versão sobrescreve o array raiz; \`[]\` limpa a lista. Definições inválidas ou referências inexistentes são ignoradas sem impedir o carregamento das outras páginas. IDs duplicados de página ou bloco preservam a primeira entrada válida; um ID de página que coincide com uma rota é ignorado para preservar a rota existente. Corrija esses erros na configuração em vez de depender da omissão.
96
+
97
+ O campo \`authorization\` da página protege o destino composto, e cada rota referenciada mantém suas próprias exigências de acesso. Ocultar um bloco não protege arquivos públicos. Markdown e PDF não inventam uma tradução quando falta o arquivo do idioma selecionado; os outros tipos preservam o fallback existente da rota, incluindo inglês para vídeo/áudio e URLs HTML externas. Teste todos os blocos e idiomas, navegação direta, rotas protegidas, mídias repetidas, erros de download e limites do navegador antes de publicar. Muitos embeds ou PDFs ativos consomem memória e rede; inclua apenas o que o leitor precisa.
98
+ `,
99
+ es: `# Bloques de contenido ordenados
100
+
101
+ Una página puede contener varios documentos Markdown, reproductores HTML, vídeos, pistas de audio y PDFs en cualquier orden. Añade un array \`pages\` en el nivel principal del config de la versión. Cada bloque referencia una ruta ya definida en \`routes-md\`, \`routes-html\`, \`routes-video\`, \`routes-audio\` o \`routes-pdf\`. La página tiene una sola URL; los bloques no crean destinos de navegación separados.
102
+
103
+ ## Ejemplo completo con repeticiones
104
+
105
+ La página 39 del scaffold combina tres bloques Markdown, dos HTML, dos vídeos, dos audios y tres PDFs. Referencia las rutas incluidas 1, 2, 30, 29, 11, 12 y 23. Combina el siguiente objeto con \`gitpagedocs/docs/versions/0.0.10/config.json\` o con el config de la versión actual; conserva las definiciones de esas rutas y sus archivos. El mismo ejemplo se incluye en el nuevo scaffold.
106
+
107
+ \`\`\`json
108
+ ${blocksExample}
109
+ \`\`\`
110
+
111
+ Añade un destino de menú con \`"path-click": "page:39"\` en cada idioma. La entrada incluida está en Guías → Lee y explora → Múltiples bloques de contenido. Su etiqueta es independiente de las etiquetas de cada bloque.
112
+
113
+ ## Orden, repetición y opciones individuales
114
+
115
+ - \`pages[].id\` es un identificador entero de página. Usa un ID nuevo que no coincida con una ruta existente.
116
+ - \`blocks[].id\` es una cadena no vacía, única dentro de su página. Dos instancias pueden usar el mismo \`routeId\`, pero necesitan IDs de bloque distintos.
117
+ - \`type\` acepta exactamente \`md\`, \`html\`, \`video\`, \`audio\` o \`pdf\`; \`routeId\` selecciona una ruta de la lista correspondiente.
118
+ - El orden del array determina el orden de presentación. Mueve un objeto para reordenarlo, elimínalo para ocultar esa instancia o cópialo con un ID nuevo para repetirlo. \`hierarchyPage\` sigue aplicándose a las páginas anteriores y no reordena este array.
119
+
120
+ Cada referencia utiliza el origen, traducción, visibilidad, dimensiones, acciones PDF, controles multimedia y autorización de su ruta. Para asignar opciones diferentes a dos apariciones del mismo archivo, define dos rutas con IDs distintos y la misma ruta de origen; después referencia esos IDs. No dupliques parámetros de ruta dentro del bloque.
121
+
122
+ Un bloque Markdown renderiza solo su documento; el audio inline antiguo de su ruta no se convierte en un bloque adicional. Referencia explícitamente una ruta de audio cuando forme parte de la secuencia. Los bloques seleccionan rutas fijas y no comparten un índice de \`browseAll\`. La exclusividad multimedia y las restricciones del navegador siguen aplicándose; repetir un reproductor no inicia la reproducción automáticamente.
123
+
124
+ El modo foco y la narración leen los bloques Markdown autorizados y disponibles en el idioma seleccionado, en el orden del array, incluidas las repeticiones. Copiar/descargar desde foco une sus fuentes originales con dos saltos de línea y utiliza \`page-39.md\` en este ejemplo. Cada contenedor Markdown visible conserva sus acciones individuales de copia/descarga y el nombre original. Los IDs de encabezados renderizados reciben un prefijo por bloque para evitar anclas duplicadas; la fuente descargada no cambia. Las páginas o bloques denegados se excluyen de renderización, copia, foco y narración. Este control del cliente no protege archivos públicos ni impide que el cargador de documentos lea sus fuentes.
125
+
126
+ ## Posicionar títulos y descripciones
127
+
128
+ Cada ruta de contenido acepta \`layout.title\` y \`layout.description\` independientemente. \`placement\` admite \`outside\` o \`inside\` del contenedor; \`position\` admite \`before\` o \`after\` del contenido. Combina este fragmento de presentación con una ruta existente, conservando sus campos de contenido:
129
+
130
+ \`\`\`json
131
+ ${layoutExample}
132
+ \`\`\`
133
+
134
+ En Markdown, el título y la descripción configurados siempre permanecen fuera del documento renderizado; se respeta su posición anterior/posterior. Los encabezados escritos en Markdown siguen perteneciendo al documento. HTML, vídeo, audio y PDF admiten ambas ubicaciones. Estos campos cambian la presentación, no el archivo de origen ni el contenido multimedia. \`titleIsVisible\`, \`descriptionIsVisible\`, alineación y estilos existentes siguen aplicándose. Omite \`layout\` para conservar la presentación actual. Los valores compartidos pueden estar en \`routeDefaults\`; un \`layout\` explícito de la ruta sustituye ese objeto de defaults.
135
+
136
+ ## Compatibilidad y acceso
137
+
138
+ Los configs sin \`pages\` mantienen su comportamiento de contenedor único o rutas mixtas. El array \`pages\` de la versión sustituye al array raíz; \`[]\` lo vacía. Las definiciones inválidas o referencias inexistentes se ignoran sin impedir que carguen las otras páginas. Las identidades duplicadas de página o bloque conservan la primera entrada válida; un ID de página que coincide con una ruta se ignora para conservar la ruta existente. Corrige esos errores en la configuración en lugar de depender de su omisión.
139
+
140
+ El campo \`authorization\` de la página protege el destino compuesto, y cada ruta referenciada mantiene sus propios requisitos de acceso. Ocultar un bloque no protege archivos públicos. Markdown y PDF no inventan traducciones cuando falta el archivo del idioma seleccionado; los demás tipos conservan el fallback de la ruta, incluido inglés para vídeo/audio y URLs HTML externas. Prueba todos los bloques e idiomas, navegación directa, rutas protegidas, medios repetidos, errores de descarga y límites del navegador antes de publicar. Muchos embeds o PDFs activos consumen memoria y red; incluye solo lo que necesita el lector.
141
+ `,
142
+ };
@@ -1,10 +1,16 @@
1
1
  import { PACKAGE_VERSION } from "../contracts/doc-versions.mjs";
2
2
  import { practicalEn } from "./practical-en.mjs";
3
3
  import { operationsEn } from "./operations-en.mjs";
4
+ import { overviewsEn } from "./overviews-en.mjs";
5
+ import { CONTENT_BLOCKS_DOCS } from "./content-blocks.mjs";
6
+ import { PARENT_MENU_JSON } from "./configuration-examples.mjs";
7
+ import { THEME_BACKGROUND_DOCS } from "./theme-backgrounds.mjs";
4
8
 
5
9
  export const docsEn = {
6
10
  ...practicalEn,
7
11
  ...operationsEn,
12
+ ...overviewsEn,
13
+ contentBlocks: CONTENT_BLOCKS_DOCS.en,
8
14
  pdf: `# PDF documents
9
15
 
10
16
  PDF is a first-class content type alongside Markdown, HTML, source code, video and audio. The viewer uses the browser's native PDF preview. Download and open-in-new-tab actions remain independently configurable.
@@ -34,11 +40,11 @@ Add this block inside \`site\` in \`gitpagedocs/config.json\`:
34
40
 
35
41
  Action precedence is \`route.pdf.<flag>\` > \`site.pdf.<flag>\` > \`true\`. An explicit route \`true\` enables that action even when its site default is \`false\`; \`site.pdf.enabled: false\` still disables PDF content everywhere. A missing path for the selected language makes the PDF unavailable; there is no automatic language fallback.
36
42
 
37
- PDF actions use icons by default. Configure \`site.icons.PdfDownload\` (\`FiDownload\`) and \`site.icons.PdfOpenInNewTab\` (\`FiExternalLink\`) independently with \`reactIcon\`, \`tag\`, \`size\`, \`colorDark\` and \`colorLight\`. For example, \`"PdfDownload": { "reactIcon": false }\` shows download text while the new-tab action remains an icon. Changing appearance does not change the action flags above.
43
+ PDF actions use icons by default. Configure \`site.icons.PdfDownload\` (\`LuDownload\`) and \`site.icons.PdfOpenInNewTab\` (\`LuExternalLink\`) independently with \`reactIcon\`, \`tag\`, \`size\`, \`colorDark\` and \`colorLight\`. For example, \`"PdfDownload": { "reactIcon": false }\` shows download text while the new-tab action remains an icon. Changing appearance does not change the action flags above.
38
44
 
39
45
  ## Route and menu example
40
46
 
41
- In \`gitpagedocs/docs/versions/0.0.10/config.json\`, keep route and menu arrays at the top level:
47
+ In \`gitpagedocs/docs/versions/0.0.12/config.json\`, keep route and menu arrays at the top level:
42
48
 
43
49
  \`\`\`json
44
50
  {
@@ -47,9 +53,9 @@ In \`gitpagedocs/docs/versions/0.0.10/config.json\`, keep route and menu arrays
47
53
  "title": { "en": "Project guide (English)", "pt": "Guia do projeto (inglês)", "es": "Guía del proyecto (inglés)" },
48
54
  "pdf": {
49
55
  "pathPdf": {
50
- "en": "gitpagedocs/docs/versions/0.0.10/en/gitpagedocs-project-guide.pdf",
51
- "pt": "gitpagedocs/docs/versions/0.0.10/en/gitpagedocs-project-guide.pdf",
52
- "es": "gitpagedocs/docs/versions/0.0.10/en/gitpagedocs-project-guide.pdf"
56
+ "en": "gitpagedocs/docs/versions/0.0.12/en/gitpagedocs-project-guide.pdf",
57
+ "pt": "gitpagedocs/docs/versions/0.0.12/en/gitpagedocs-project-guide.pdf",
58
+ "es": "gitpagedocs/docs/versions/0.0.12/en/gitpagedocs-project-guide.pdf"
53
59
  },
54
60
  "previewEnabled": true,
55
61
  "downloadEnabled": true,
@@ -123,6 +129,7 @@ The runtime expects this structure:
123
129
  - **CLI reference**: installation, every command and compatibility flags.
124
130
  - **MCP server**: client setup, all 20 tools, 7 resources and provider configuration.
125
131
  - **Navigation and nested menus**: recursive trees, URLs and breadcrumb overrides.
132
+ - **Ordered content blocks**: repeat and reorder Markdown, HTML, video, audio and PDF in one page; independently position configured titles and descriptions.
126
133
  - **Focus mode**: copy/download Markdown and section/document navigation.
127
134
  - **Accessibility and narration**: browser voices, controls and media interaction.
128
135
  - **PDF documents**: native previews, download/new-tab controls and the included English guide.
@@ -428,42 +435,46 @@ Behavior:
428
435
 
429
436
  ## Language, theme, focus, quick navigation, PDF and document controls
430
437
 
431
- In \`gitpagedocs/config.json\`, these \`site.icons\` entries configure the language selector, theme selector, focus, Ctrl+K navigation, PDF actions and document-footer navigation. All eight controls use React Icons by default:
438
+ In \`gitpagedocs/config.json\`, these \`site.icons\` entries configure the language selector, theme selector, focus, Ctrl+K navigation, PDF actions and document-footer navigation. All nine controls use React Icons by default:
432
439
 
433
440
  \`\`\`json
434
441
  {
435
442
  "site": {
436
443
  "icons": {
437
444
  "LanguageSelector": {
438
- "reactIcon": true, "tag": "FiGlobe", "size": "22px",
445
+ "reactIcon": true, "tag": "SiGoogletranslate", "size": "22px",
439
446
  "colorDark": "currentColor", "colorLight": "currentColor"
440
447
  },
441
448
  "ThemeSelector": {
442
- "reactIcon": true, "tag": "BsSunFill", "size": "22px",
449
+ "reactIcon": true, "tag": "LuPencil", "size": "22px",
450
+ "colorDark": "currentColor", "colorLight": "currentColor"
451
+ },
452
+ "VersionSelector": {
453
+ "reactIcon": true, "tag": "LuGitBranch", "size": "22px",
443
454
  "colorDark": "currentColor", "colorLight": "currentColor"
444
455
  },
445
456
  "FocusMode": {
446
- "reactIcon": true, "tag": "MdFullscreen", "size": "22px",
457
+ "reactIcon": true, "tag": "LuBookOpen", "size": "22px",
447
458
  "colorDark": "currentColor", "colorLight": "currentColor"
448
459
  },
449
460
  "QuickNavigation": {
450
- "reactIcon": true, "tag": "FiSearch", "size": "22px",
461
+ "reactIcon": true, "tag": "LuSearch", "size": "22px",
451
462
  "colorDark": "currentColor", "colorLight": "currentColor"
452
463
  },
453
464
  "PdfDownload": {
454
- "reactIcon": true, "tag": "FiDownload", "size": "22px",
465
+ "reactIcon": true, "tag": "LuDownload", "size": "22px",
455
466
  "colorDark": "currentColor", "colorLight": "currentColor"
456
467
  },
457
468
  "PdfOpenInNewTab": {
458
- "reactIcon": true, "tag": "FiExternalLink", "size": "22px",
469
+ "reactIcon": true, "tag": "LuExternalLink", "size": "22px",
459
470
  "colorDark": "currentColor", "colorLight": "currentColor"
460
471
  },
461
472
  "DocumentPrevious": {
462
- "reactIcon": true, "tag": "FiChevronLeft", "size": "22px",
473
+ "reactIcon": true, "tag": "LuChevronLeft", "size": "22px",
463
474
  "colorDark": "currentColor", "colorLight": "currentColor"
464
475
  },
465
476
  "DocumentNext": {
466
- "reactIcon": true, "tag": "FiChevronRight", "size": "22px",
477
+ "reactIcon": true, "tag": "LuChevronRight", "size": "22px",
467
478
  "colorDark": "currentColor", "colorLight": "currentColor"
468
479
  }
469
480
  }
@@ -477,6 +488,8 @@ Compact configs may move shared values into \`site.icons.defaults\`; omitted fie
477
488
 
478
489
  ## \`VersionControl\` section
479
490
 
491
+ \`site.icons.VersionSelector\` uses \`LuGitBranch\` by default. Set \`reactIcon: false\` to display the selected version as text; \`true\` displays its icon. Customize the same \`tag\`, \`size\`, \`colorDark\` and \`colorLight\` fields. The selector appears only when more than one documentation version is available, retains the localized accessible name of the selector and shows the selected version in its tooltip.
492
+
480
493
  \`VersionControl.versions\` defines:
481
494
 
482
495
  - \`id\`
@@ -693,6 +706,8 @@ Select an installed theme through the theme selector or configure \`site.ThemeDe
693
706
  For your own repository, run the CLI with \`--layoutconfig\`, then edit the generated template and keep its ID consistent with \`layoutsConfig.json\`. A route's content and \`site.icons\` remain independent of the theme catalog. Use \`currentColor\` for icons that should inherit the active text color, or configure separate dark/light colors with sufficient contrast.
694
707
 
695
708
  When contributing to Git Page Docs itself, the authoring source is \`gitpagelayouts/v2/base.json\` plus \`gitpagelayouts/v2/layouts/<id>.json\`. Run \`pnpm layouts:sync\` to regenerate templates and documentation. Direct edits to generated templates can be overwritten by that synchronization.
709
+
710
+ ${THEME_BACKGROUND_DOCS.en}
696
711
  `,
697
712
  mcp: `# MCP server
698
713
 
@@ -753,7 +768,7 @@ Select a provider using \`configure_ai_provider\` or \`.gitpagedocs-mcp.json\` a
753
768
  | \`fireworks\` | \`FIREWORKS_API_KEY\` |
754
769
  | \`perplexity\` | \`PERPLEXITY_API_KEY\` |
755
770
 
756
- With no valid selection, the default provider is OpenAI. Ollama does not require an API key; its local service and chosen model must be available. \`OLLAMA_BASE_URL\` is optional. Azure's base URL is the complete chat-operation URL, including deployment and API-version query when required. Model listings are the bundled catalog, not a live availability check.
771
+ When the saved selection is absent, unreadable or invalid JSON, the default provider is OpenAI. An unknown provider ID in readable JSON produces an explicit error instead of selecting another provider. Ollama does not require an API key; its local service and chosen model must be available. \`OLLAMA_BASE_URL\` is optional. Azure's base URL is the complete chat-operation URL, including deployment and API-version query when required. Model listings are the bundled catalog, not a live availability check.
757
772
 
758
773
  ## Tool reference
759
774
 
@@ -809,7 +824,7 @@ The generation step sends selected project content to the configured provider.
809
824
 
810
825
  - File reads: up to 512,000 bytes. Listing: up to 2,000 entries; gathered project trees: 400 entries.
811
826
  - Search: up to 5,000 entries, 200 matches, 240 characters per matching line.
812
- - Documentation gathering: first 40 Markdown files among up to 2,000 entries; files over 40,000 bytes are skipped. Provider context is capped at 24,000 characters.
827
+ - Documentation gathering: first 40 Markdown files among up to 2,000 entries; files over 40,000 bytes are skipped. Gathered file and Markdown context is limited to 24,000 characters. This is not a global prompt limit: tree/package context, an existing document and a caller-supplied question can add content according to the selected tool.
813
828
  - Listing skips build/dependency directories such as \`node_modules\`, \`.git\`, \`.next\`, \`out\`, \`dist\`, \`prebuilt\`, \`.turbo\` and \`coverage\`. It does not interpret \`.gitignore\`; files such as \`.env\` are not automatically excluded. Run only in a trusted project and select the content to expose.
814
829
  - Path checks use lexical containment; do not treat the process as an operating-system sandbox or assume symlink/junction isolation. Loading \`project://config\` can import JavaScript/TypeScript configuration.
815
830
  - Tool failures include \`isError: true\`. Missing resources return \`Unavailable: ...\`. Check the client's stderr log for startup errors; stdout is reserved for JSON-RPC.
@@ -904,7 +919,7 @@ Routes define page content; menus define how readers reach it. Configure them in
904
919
 
905
920
  Each \`menus-header-md\` entry has an \`id\` and localized \`pt\`, \`en\`, \`es\` objects with \`title\` and optional \`path-click\`. Add \`submenus\` containing more entries to nest the tree. A language object may also contain localized \`submenus\` with the same title/path structure. Use one form consistently to avoid listing the same child twice.
906
921
 
907
- Groups without \`path-click\` organize children. For a Markdown destination, use its actual localized path from \`routes-md[].path\`. The \`page:<id>\` alias is registered by source-viewer, video, audio and PDF routes; do not use it for a Markdown-only page. The example below uses version \`0.0.8\`: replace that segment with the version you are editing and create the three chapter files.
922
+ Groups without \`path-click\` organize children. For a Markdown route destination, use its actual localized path from \`routes-md[].path\`. Source-viewer, video, audio, PDF and explicitly composed \`pages\` register \`page:<id>\`; a plain Markdown route uses its file path. The example below uses version \`0.0.8\`: replace that segment with the version you are editing and create the three chapter files.
908
923
 
909
924
  \`\`\`json
910
925
  {
@@ -972,6 +987,14 @@ Groups without \`path-click\` organize children. For a Markdown destination, use
972
987
 
973
988
  ## Nesting behavior
974
989
 
990
+ A parent can be both a document and a group. Keep its localized \`path-click\` together with \`submenus\`: the title opens its Markdown page, while the separate arrow expands or collapses children. The scaffold includes useful overviews for all eight parent groups. Breadcrumb ancestors link to those documents; the current destination remains the current breadcrumb. A group without a path can still organize children, but has no destination to open.
991
+
992
+ The following excerpt uses the scaffold's existing Markdown routes 31, 32 and 13. Merge it into \`menus-header-md\` and retain the matching \`routes-md\` definitions and files:
993
+
994
+ \`\`\`json
995
+ ${PARENT_MENU_JSON}
996
+ \`\`\`
997
+
975
998
  \`site.nestedMenusEnabled: true\` renders expandable recursive menus. You may add another \`submenus\` array at any node: there is no fixed application depth limit. The configuration must remain finite and practical for browser memory and usability. Setting it to \`false\` displays destinations as a flat list; it does not remove nested pages.
976
999
 
977
1000
  The tree supplies sidebar navigation, search labels, parent expansion and breadcrumb trails. Keep IDs stable and unambiguous; nodes pointing at a protected page follow its authorization rules. Apply the same structure to \`menus-header-source-viewer\`, \`menus-header-html\`, \`menus-header-video\` , \`menus-header-audio\` and \`menus-header-pdf\`. \`hierarchyMenu\` orders the type sections; \`hierarchyPage\` orders content containers that share a page ID.
@@ -986,7 +1009,7 @@ The tree supplies sidebar navigation, search labels, parent expansion and breadc
986
1009
 
987
1010
  Versioned URLs use \`/v/<version>/\`; \`?lang=pt\` selects a language and \`?id=101\` selects a page ID. \`?name=chapter\` selects the document slug. Keep \`VersionControl.versions[].path\` pointing at the matching version config. \`site.ActiveNavigation\` enables quick navigation and its Ctrl+K shortcut. Footer previous/next controls follow available menu destinations; focus-mode document navigation has its own option. See Focus mode for its section and document controls.
988
1011
 
989
- Footer previous/next buttons use \`site.icons.DocumentPrevious\` (\`FiChevronLeft\`) and \`site.icons.DocumentNext\` (\`FiChevronRight\`) by default. Set \`reactIcon: false\` on either entry to show its translated text; each entry also accepts \`tag\`, \`size\`, \`colorDark\` and \`colorLight\`. Appearance does not change navigation: the footer appears when more than one menu destination is available, and the unavailable direction stays disabled at the ends.
1012
+ Footer previous/next buttons use \`site.icons.DocumentPrevious\` (\`LuChevronLeft\`) and \`site.icons.DocumentNext\` (\`LuChevronRight\`) by default. Set \`reactIcon: false\` on either entry to show its translated text; each entry also accepts \`tag\`, \`size\`, \`colorDark\` and \`colorLight\`. Appearance does not change navigation: the footer appears when more than one menu destination is available, and the unavailable direction stays disabled at the ends.
990
1013
 
991
1014
  Test a new menu from the sidebar, by direct URL and in each enabled language; verify the destination exists and is allowed for the current reader.
992
1015
  `,
@@ -1025,6 +1048,8 @@ Each option defaults to \`true\`; setting one to \`false\` hides its correspondi
1025
1048
 
1026
1049
  ## Copy and download
1027
1050
 
1051
+ On a composed page, focus reads the authorized Markdown blocks in order, including repetitions. Its copy/download actions join those sources and use \`page-<id>.md\`; individual block actions retain their original filenames. See Ordered content blocks for the full contract.
1052
+
1028
1053
  Copy and download use the **entire original Markdown document in the selected language**, including sections not currently visible. They do not export the rendered HTML or only the current reading section.
1029
1054
 
1030
1055
  The download keeps the Markdown basename from the route's localized \`path\`; if unavailable, the filename is \`document.md\`. Clipboard access follows the browser's permission and secure-context rules. If copying fails, use download instead and check the displayed error.
@@ -1126,7 +1151,7 @@ Because GitHub Pages build mode enables repository-search home and static-export
1126
1151
 
1127
1152
  ## Why does an icon still show text?
1128
1153
 
1129
- Set \`site.icons.<Control>.reactIcon\` to the boolean \`true\`, with an exact React Icons export name in \`tag\`. LanguageSelector, ThemeSelector, FocusMode, QuickNavigation, PdfDownload, PdfOpenInNewTab, DocumentPrevious and DocumentNext use icons by default; set any entry to \`false\` for text. Flat \`Icon*ReactIcones\` fields take precedence if both formats are present. Check whether the feature itself is disabled, such as \`HideThemeSelector\`, \`FocusMode\` or the PDF action flags.
1154
+ Set \`site.icons.<Control>.reactIcon\` to the boolean \`true\`, with an exact React Icons export name in \`tag\`. LanguageSelector, ThemeSelector, VersionSelector, FocusMode, QuickNavigation, PdfDownload, PdfOpenInNewTab, DocumentPrevious and DocumentNext use icons by default; set any entry to \`false\` for text. Flat \`Icon*ReactIcones\` fields take precedence if both formats are present. Check whether the feature itself is disabled, such as \`HideThemeSelector\`, \`FocusMode\` or the PDF action flags.
1130
1155
 
1131
1156
  ## Why do menu children or breadcrumbs differ?
1132
1157