mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-18 00:26:29 +00:00
chore(docs): widen docs-consistency test, archive stale concept docs
The TestDocsConsistency walk only iterated [".", "guides", "reference",
"analysis"] — concepts/ was silently invisible, which is why
amazon-music-oauth.md slipped into the tree without a SUMMARY entry.
Refactored to walk the entire docs/ tree, with a small dirsToSkip
allow-list (_includes, archive, diagrams, images) for asset trees.
New top-level narrative directories are picked up automatically;
only asset dirs need an explicit entry.
The wider walk surfaced six previously-hidden concepts/* files. Five
older planning artefacts ("Enhanced State Management System",
"Upstream Bose Service Simulation") moved into docs/archive/ where
the dirsToSkip already excludes them; concepts/README.md renamed to
upstream-service-simulation-overview.md since "README.md" inside
archive/ would be misleading. Spotify Overview and Amazon Music
OAuth are user-facing narrative docs and are now linked under
Concepts in SUMMARY.md.
Note: concepts/streborn-patterns.md is internal review notes (its
own opening line says so) and is currently unlinked from SUMMARY.md;
will be handled separately by the maintainer.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
56ace2f960
commit
1421ad5ce1
@@ -53,8 +53,10 @@
|
||||
|
||||
## Concepts
|
||||
* [Request Recording](REQUEST_RECORDING_CONCEPT.md)
|
||||
* [Spotify Overview](concepts/spotify-overview.md)
|
||||
* [Spotify Priming Strategy](concepts/spotify-priming-strategy.md)
|
||||
* [Spotify OAuth](concepts/spotify-oauth.md)
|
||||
* [Amazon Music OAuth](concepts/amazon-music-oauth.md)
|
||||
* [Encrypted Export](concepts/ENCRYPTED-EXPORT.md)
|
||||
* [Diagnostic Export (Maintainer Setup)](DIAGNOSTIC-EXPORT.md)
|
||||
* [soundtouch-web Roadmap](soundtouch-web-roadmap.md)
|
||||
|
||||
@@ -9,6 +9,27 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// dirsToSkip names docs/ subdirectories whose contents are not meant
|
||||
// to appear in SUMMARY.md. These are asset / partial / archive trees,
|
||||
// not narrative documentation:
|
||||
//
|
||||
// - _includes : HTML partials consumed by the docs site renderer
|
||||
// - archive : superseded plans / status reports kept for the
|
||||
// record but deliberately unlinked
|
||||
// - diagrams : Mermaid sources for embedded diagrams
|
||||
// - images : binary assets + a directory README that explains them
|
||||
//
|
||||
// Adding a new top-level dir under docs/ does NOT require touching
|
||||
// this list — only add the dir name here when its contents should
|
||||
// stay out of SUMMARY.md by design. Individual file exclusions live
|
||||
// in .docsignore instead.
|
||||
var dirsToSkip = map[string]bool{
|
||||
"_includes": true,
|
||||
"archive": true,
|
||||
"diagrams": true,
|
||||
"images": true,
|
||||
}
|
||||
|
||||
func TestDocsConsistency(t *testing.T) {
|
||||
// Root of the project relative to this test file
|
||||
// The test runs in the directory of the package
|
||||
@@ -22,61 +43,73 @@ func TestDocsConsistency(t *testing.T) {
|
||||
}
|
||||
|
||||
summaryText := string(summaryContent)
|
||||
|
||||
docsIgnore := readDocsIgnore(t, filepath.Join(projectRoot, ".docsignore"))
|
||||
|
||||
// List of directories to check
|
||||
dirsToCheck := []string{".", "guides", "reference", "analysis"}
|
||||
// Walk the entire docs tree. Directory-level exclusions live in
|
||||
// dirsToSkip above (asset / archive trees); file-level exclusions
|
||||
// live in .docsignore (individual narrative docs that are
|
||||
// intentionally unlinked). New subdirectories are picked up
|
||||
// automatically — this is the behaviour amazon-music-oauth.md
|
||||
// surprised us by lacking.
|
||||
err = filepath.WalkDir(docsDir, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, dir := range dirsToCheck {
|
||||
dirPath := filepath.Join(docsDir, dir)
|
||||
err := filepath.WalkDir(dirPath, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.IsDir() {
|
||||
// Don't recurse into subdirectories if we are checking the root,
|
||||
// as they are handled separately or ignored (like archive)
|
||||
if dir == "." && path != dirPath {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !strings.HasSuffix(d.Name(), ".md") {
|
||||
if d.IsDir() {
|
||||
if path == docsDir {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Skip SUMMARY.md itself
|
||||
if d.Name() == "SUMMARY.md" {
|
||||
return nil
|
||||
rel, relErr := filepath.Rel(docsDir, path)
|
||||
if relErr != nil {
|
||||
return relErr
|
||||
}
|
||||
|
||||
// Skip files listed in .docsignore at the project root
|
||||
for _, skip := range docsIgnore {
|
||||
if strings.HasSuffix(path, filepath.FromSlash(skip)) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get relative path from docs/
|
||||
relPath, err := filepath.Rel(docsDir, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if this file is linked in SUMMARY.md
|
||||
// We look for [Label](relPath)
|
||||
linkPattern := "(" + relPath + ")"
|
||||
if !strings.Contains(summaryText, linkPattern) {
|
||||
t.Errorf("Documentation file %s is not linked in docs/SUMMARY.md", relPath)
|
||||
// Skip only top-level asset / archive directories. Nested
|
||||
// directories inside narrative trees (e.g. docs/guides/foo/)
|
||||
// would still be walked.
|
||||
if !strings.ContainsRune(rel, filepath.Separator) && dirsToSkip[d.Name()] {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Error walking directory %s: %v", dir, err)
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(d.Name(), ".md") {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Skip SUMMARY.md itself
|
||||
if d.Name() == "SUMMARY.md" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Skip files listed in .docsignore at the project root
|
||||
for _, skip := range docsIgnore {
|
||||
if strings.HasSuffix(path, filepath.FromSlash(skip)) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get relative path from docs/
|
||||
relPath, err := filepath.Rel(docsDir, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if this file is linked in SUMMARY.md
|
||||
// We look for [Label](relPath)
|
||||
linkPattern := "(" + relPath + ")"
|
||||
if !strings.Contains(summaryText, linkPattern) {
|
||||
t.Errorf("Documentation file %s is not linked in docs/SUMMARY.md", relPath)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Error walking docs directory: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user