From d26bb8eb6f367f41cc8098e033e80bc3527a3f43 Mon Sep 17 00:00:00 2001 From: David de Hilster Date: Mon, 26 Oct 2026 17:43:13 -0400 Subject: [PATCH] Help: help-tree.json, the index the VSCode Help view is built from Help/markdown/vscode/help-tree.json lists the Help view's tree: labels, icons, pages, folders, and the folders filled from files (LLM prompts, helpful links, announcements, version notes). The NLP extension (4.3.17) reads it, so adding or reordering a help page is now an edit here and a visualtext-files release, with no extension update. It matches the tree the extension shows today, Large Files included. check-help-docs.ps1 gets a check 1c that fails when an entry's page does not exist, an entry has no label, a source is unknown, or the JSON does not parse. Co-Authored-By: Claude Opus 5.5 --- Help/check-help-docs.ps1 | 35 +++++++++++++++++++++--- Help/markdown/vscode/help-tree.json | 42 +++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 Help/markdown/vscode/help-tree.json diff --git a/Help/check-help-docs.ps1 b/Help/check-help-docs.ps1 index 6bf8469..7e9a220 100644 --- a/Help/check-help-docs.ps1 +++ b/Help/check-help-docs.ps1 @@ -10,6 +10,7 @@ Reports: 1. Broken links - any ](*.md) reference in the corpus that does not resolve. 1b. Broken images - any ![..](img) reference that does not resolve. + 1c. Help view tree - vscode/help-tree.json pages that do not exist. 2. Orphaned pages - *.md files not referenced from index.md (legacy candidates). 3. Table/index drift- pages linked from a Table_of_* but absent from index.md. 4. Engine coverage - (info) engine function/action names with no help page. @@ -75,6 +76,34 @@ foreach ($f in $allMd) { Write-Host "`n== 1b. Broken image links ($($brokenImg.Count)) ==" -ForegroundColor Cyan $brokenImg | Sort-Object | ForEach-Object { Write-Host " $_" } +# --- 1c. Help view tree (vscode/help-tree.json) -------------------------------- +# The VSCode extension builds its Help view from this file, so every page it +# names must exist and every source must be one the extension knows. +$treeErr = @() +$treePath = Join-Path $HelpDir 'vscode\help-tree.json' +if (Test-Path $treePath) { + try { + $tree = Get-Content $treePath -Raw | ConvertFrom-Json + $stack = New-Object System.Collections.Stack + foreach ($it in @($tree.items)) { $stack.Push($it) } + while ($stack.Count -gt 0) { + $it = $stack.Pop() + if (-not $it.label) { $treeErr += 'item with no label'; continue } + if ($it.page -and -not (Test-Path (Join-Path $HelpDir ($it.page + '.md')))) { + $treeErr += '{0} -> {1}.md' -f $it.label, $it.page + } + if ($it.source -and ($it.source -notin @('prompts','links','announcements','versions'))) { + $treeErr += '{0} -> unknown source "{1}"' -f $it.label, $it.source + } + foreach ($c in @($it.children)) { if ($c) { $stack.Push($c) } } + } + } catch { + $treeErr += "invalid JSON: $($_.Exception.Message)" + } +} +Write-Host "`n== 1c. Help view tree errors ($($treeErr.Count)) ==" -ForegroundColor Cyan +$treeErr | ForEach-Object { Write-Host " $_" } + # --- 2. Orphaned flat pages (not referenced from index.md) -------------------- $flat = $allMd | Where-Object { $_.DirectoryName -eq $HelpDir -and $_.Name -ne 'index.md' } $orphans = $flat | Where-Object { $indexTxt -notmatch [regex]::Escape('(' + $_.Name + ')') } | @@ -170,6 +199,6 @@ if ($Images) { } Write-Host "`n--- summary ---" -ForegroundColor Green -Write-Host ("broken links: {0} broken images: {1} orphaned pages: {2} table/index drift: {3}" -f $broken.Count, $brokenImg.Count, $orphans.Count, $tableDrift.Count) -# Exit non-zero on hard errors (broken .md links / broken images / table-index drift) so it can gate CI. -if (($broken.Count + $brokenImg.Count + $tableDrift.Count) -gt 0) { exit 1 } else { exit 0 } +Write-Host ("broken links: {0} broken images: {1} help tree: {2} orphaned pages: {3} table/index drift: {4}" -f $broken.Count, $brokenImg.Count, $treeErr.Count, $orphans.Count, $tableDrift.Count) +# Exit non-zero on hard errors (broken .md links / broken images / help tree / table-index drift) so it can gate CI. +if (($broken.Count + $brokenImg.Count + $treeErr.Count + $tableDrift.Count) -gt 0) { exit 1 } else { exit 0 } diff --git a/Help/markdown/vscode/help-tree.json b/Help/markdown/vscode/help-tree.json new file mode 100644 index 0000000..7016234 --- /dev/null +++ b/Help/markdown/vscode/help-tree.json @@ -0,0 +1,42 @@ +{ + "_comment": [ + "The VSCode Help view tree. The NLP extension reads this file, so adding or", + "reordering a help page needs only an edit here -- no extension release.", + "Each item: label (required), icon (a VSCode codicon name), and one of:", + " page - a markdown page under Help/markdown/, without .md", + " url - an external link opened in the browser", + " children - a list of items (a collapsible folder)", + " source - a folder filled from files on disk: prompts, links,", + " announcements, or versions", + "Optional: tooltip (hover text), expanded (folder starts open).", + "Help/check-help-docs.ps1 fails if a page here does not exist." + ], + "items": [ + { "label": "Home", "page": "vscode/home", "icon": "home" }, + { "label": "NLP++ Textbook", "page": "NLP++_Textbook", "icon": "book" }, + { "label": "Quick Start", "page": "vscode/quickstart", "icon": "rocket" }, + { "label": "LLM Prompts", "icon": "comment-discussion", "source": "prompts" }, + { "label": "Regression Testing", "page": "vscode/testing", "icon": "beaker" }, + { "label": "Compiling Analyzers", "page": "vscode/compiling", "icon": "gear" }, + { "label": "Lazy Loading", "page": "vscode/lazyload", "icon": "symbol-array" }, + { "label": "Large Files", "page": "vscode/largefiles", "icon": "file-binary" }, + { + "label": "NLP++", "icon": "symbol-namespace", + "children": [ + { "label": "About NLP++", "page": "NLP_PP_Stuff/About_NLP++", "icon": "book" }, + { "label": "Variables", "page": "NLP_PP_Stuff/About_NLP++_Variables", "icon": "symbol-variable" }, + { "label": "Tokens", "page": "NLP_PP_Stuff/Tokens", "icon": "symbol-key" }, + { "label": "String Functions", "page": "Table_of_String_Functions", "icon": "symbol-string" }, + { "label": "Node / Parse Tree Functions", "page": "Table_of_Parse_Tree_Functions", "icon": "list-tree" }, + { "label": "Knowledge Base Functions", "page": "Table_of_Knowledge_Base_Functions", "icon": "database" }, + { "label": "Math Functions", "page": "Table_of_Math_Functions", "icon": "symbol-operator" }, + { "label": "Array Functions", "page": "Table_of_Array_Functions", "icon": "symbol-array" }, + { "label": "Formatting & I/O Functions", "page": "Table_of_Formatting_and_I_O_Functions", "icon": "output" }, + { "label": "Special Functions", "page": "Table_of_Special_Functions", "icon": "symbol-misc" } + ] + }, + { "label": "Helpful Links", "icon": "link", "source": "links" }, + { "label": "Announcements", "icon": "megaphone", "source": "announcements", "expanded": true }, + { "label": "Version Notes", "icon": "history", "source": "versions", "expanded": true } + ] +}