@gitpagedocs/cli 0.0.10 → 0.0.11

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.
@@ -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,14 @@ 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
+ FocusMode: { tag: "LuBookOpen" },
47
+ QuickNavigation: { tag: "LuSearch" },
48
+ PdfDownload: { tag: "LuDownload" },
49
+ PdfOpenInNewTab: { tag: "LuExternalLink" },
50
+ DocumentPrevious: { tag: "LuChevronLeft" },
51
+ DocumentNext: { tag: "LuChevronRight" },
38
52
  },
39
53
  pdf: { enabled: true, previewEnabled: true, downloadEnabled: true, openInNewTabEnabled: true },
40
54
  },
@@ -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,15 @@
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";
4
7
 
5
8
  export const docsEn = {
6
9
  ...practicalEn,
7
10
  ...operationsEn,
11
+ ...overviewsEn,
12
+ contentBlocks: CONTENT_BLOCKS_DOCS.en,
8
13
  pdf: `# PDF documents
9
14
 
10
15
  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 +39,11 @@ Add this block inside \`site\` in \`gitpagedocs/config.json\`:
34
39
 
35
40
  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
41
 
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.
42
+ 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
43
 
39
44
  ## Route and menu example
40
45
 
41
- In \`gitpagedocs/docs/versions/0.0.10/config.json\`, keep route and menu arrays at the top level:
46
+ In \`gitpagedocs/docs/versions/0.0.11/config.json\`, keep route and menu arrays at the top level:
42
47
 
43
48
  \`\`\`json
44
49
  {
@@ -47,9 +52,9 @@ In \`gitpagedocs/docs/versions/0.0.10/config.json\`, keep route and menu arrays
47
52
  "title": { "en": "Project guide (English)", "pt": "Guia do projeto (inglês)", "es": "Guía del proyecto (inglés)" },
48
53
  "pdf": {
49
54
  "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"
55
+ "en": "gitpagedocs/docs/versions/0.0.11/en/gitpagedocs-project-guide.pdf",
56
+ "pt": "gitpagedocs/docs/versions/0.0.11/en/gitpagedocs-project-guide.pdf",
57
+ "es": "gitpagedocs/docs/versions/0.0.11/en/gitpagedocs-project-guide.pdf"
53
58
  },
54
59
  "previewEnabled": true,
55
60
  "downloadEnabled": true,
@@ -123,6 +128,7 @@ The runtime expects this structure:
123
128
  - **CLI reference**: installation, every command and compatibility flags.
124
129
  - **MCP server**: client setup, all 20 tools, 7 resources and provider configuration.
125
130
  - **Navigation and nested menus**: recursive trees, URLs and breadcrumb overrides.
131
+ - **Ordered content blocks**: repeat and reorder Markdown, HTML, video, audio and PDF in one page; independently position configured titles and descriptions.
126
132
  - **Focus mode**: copy/download Markdown and section/document navigation.
127
133
  - **Accessibility and narration**: browser voices, controls and media interaction.
128
134
  - **PDF documents**: native previews, download/new-tab controls and the included English guide.
@@ -435,35 +441,35 @@ In \`gitpagedocs/config.json\`, these \`site.icons\` entries configure the langu
435
441
  "site": {
436
442
  "icons": {
437
443
  "LanguageSelector": {
438
- "reactIcon": true, "tag": "FiGlobe", "size": "22px",
444
+ "reactIcon": true, "tag": "SiGoogletranslate", "size": "22px",
439
445
  "colorDark": "currentColor", "colorLight": "currentColor"
440
446
  },
441
447
  "ThemeSelector": {
442
- "reactIcon": true, "tag": "BsSunFill", "size": "22px",
448
+ "reactIcon": true, "tag": "LuPencil", "size": "22px",
443
449
  "colorDark": "currentColor", "colorLight": "currentColor"
444
450
  },
445
451
  "FocusMode": {
446
- "reactIcon": true, "tag": "MdFullscreen", "size": "22px",
452
+ "reactIcon": true, "tag": "LuBookOpen", "size": "22px",
447
453
  "colorDark": "currentColor", "colorLight": "currentColor"
448
454
  },
449
455
  "QuickNavigation": {
450
- "reactIcon": true, "tag": "FiSearch", "size": "22px",
456
+ "reactIcon": true, "tag": "LuSearch", "size": "22px",
451
457
  "colorDark": "currentColor", "colorLight": "currentColor"
452
458
  },
453
459
  "PdfDownload": {
454
- "reactIcon": true, "tag": "FiDownload", "size": "22px",
460
+ "reactIcon": true, "tag": "LuDownload", "size": "22px",
455
461
  "colorDark": "currentColor", "colorLight": "currentColor"
456
462
  },
457
463
  "PdfOpenInNewTab": {
458
- "reactIcon": true, "tag": "FiExternalLink", "size": "22px",
464
+ "reactIcon": true, "tag": "LuExternalLink", "size": "22px",
459
465
  "colorDark": "currentColor", "colorLight": "currentColor"
460
466
  },
461
467
  "DocumentPrevious": {
462
- "reactIcon": true, "tag": "FiChevronLeft", "size": "22px",
468
+ "reactIcon": true, "tag": "LuChevronLeft", "size": "22px",
463
469
  "colorDark": "currentColor", "colorLight": "currentColor"
464
470
  },
465
471
  "DocumentNext": {
466
- "reactIcon": true, "tag": "FiChevronRight", "size": "22px",
472
+ "reactIcon": true, "tag": "LuChevronRight", "size": "22px",
467
473
  "colorDark": "currentColor", "colorLight": "currentColor"
468
474
  }
469
475
  }
@@ -904,7 +910,7 @@ Routes define page content; menus define how readers reach it. Configure them in
904
910
 
905
911
  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
912
 
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.
913
+ 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
914
 
909
915
  \`\`\`json
910
916
  {
@@ -972,6 +978,14 @@ Groups without \`path-click\` organize children. For a Markdown destination, use
972
978
 
973
979
  ## Nesting behavior
974
980
 
981
+ 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.
982
+
983
+ 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:
984
+
985
+ \`\`\`json
986
+ ${PARENT_MENU_JSON}
987
+ \`\`\`
988
+
975
989
  \`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
990
 
977
991
  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 +1000,7 @@ The tree supplies sidebar navigation, search labels, parent expansion and breadc
986
1000
 
987
1001
  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
1002
 
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.
1003
+ 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
1004
 
991
1005
  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
1006
  `,
@@ -1025,6 +1039,8 @@ Each option defaults to \`true\`; setting one to \`false\` hides its correspondi
1025
1039
 
1026
1040
  ## Copy and download
1027
1041
 
1042
+ 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.
1043
+
1028
1044
  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
1045
 
1030
1046
  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.