From 701889076d1b34f6d9774be91b80816bd27b74e5 Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Sat, 14 Feb 2026 18:22:12 +0100 Subject: [PATCH] Refactor documentation structure, add SUMMARY.md sidebar, and automated consistency checks --- README.md | 8 +- docs/SUMMARY.md | 54 ++++++++++++++ docs/{ => analysis}/ANONYMIZATION-SUMMARY.md | 0 .../API-COVERAGE.md} | 0 .../{ => analysis}/DEVICE-REDIRECT-METHODS.md | 0 .../SUPPORTED-URLS.md} | 0 .../UPSTREAM-URLS.md} | 0 .../WIKI-COMPARISON.md} | 0 docs/{ => archive}/MERGE_PROJECTS.md | 0 docs/{ => archive}/PLAN.md | 0 docs/{ => archive}/STATUS.md | 0 .../{ => archive}/WIKI-IMPLEMENTATION-PLAN.md | 0 docs/{ => guides}/CLI-REFERENCE.md | 0 docs/{ => guides}/DEPLOYMENT.md | 0 docs/{ => guides}/DEVICE-INITIAL-SETUP.md | 0 docs/{ => guides}/GETTING-STARTED.md | 0 docs/{ => guides}/HTTPS-SETUP.md | 0 .../MIGRATION-SAFETY.md} | 5 +- docs/{ => guides}/SOUNDTOUCH-SERVICE.md | 0 .../SURVIVAL-GUIDE.md} | 8 +- docs/{ => guides}/TROUBLESHOOTING.md | 0 docs/{ => reference}/API-COOKBOOK.md | 0 .../API-ENDPOINTS.md} | 0 docs/{ => reference}/BASS-CONTROLS.md | 0 docs/{ => reference}/DISCOVERY.md | 0 .../FEATURE-MAPPING.md} | 0 docs/{ => reference}/KEY-CONTROLS.md | 0 docs/{ => reference}/PRESET-MANAGEMENT.md | 0 docs/{ => reference}/SOURCE-SELECTION.md | 0 .../SPEAKER-ENDPOINT.md} | 0 docs/{ => reference}/SYSTEM-ENDPOINTS.md | 0 docs/{ => reference}/VOLUME-CONTROLS.md | 0 .../WEBSOCKET-EVENTS.md} | 0 .../ZONE-MANAGEMENT.md} | 0 pkg/service/handlers/docs_consistency_test.go | 71 ++++++++++++++++++ pkg/service/handlers/handlers_docs.go | 74 +++++++++++++++++-- pkg/service/handlers/web/index.html | 13 +++- 37 files changed, 215 insertions(+), 18 deletions(-) create mode 100644 docs/SUMMARY.md rename docs/{ => analysis}/ANONYMIZATION-SUMMARY.md (100%) rename docs/{API-COVERAGE-ANALYSIS.md => analysis/API-COVERAGE.md} (100%) rename docs/{ => analysis}/DEVICE-REDIRECT-METHODS.md (100%) rename docs/{SUPPORTEDURLS-ANALYSIS.md => analysis/SUPPORTED-URLS.md} (100%) rename docs/{UPSTREAM-URLS-ANALYSIS.md => analysis/UPSTREAM-URLS.md} (100%) rename docs/{WIKI-API-COMPARISON.md => analysis/WIKI-COMPARISON.md} (100%) rename docs/{ => archive}/MERGE_PROJECTS.md (100%) rename docs/{ => archive}/PLAN.md (100%) rename docs/{ => archive}/STATUS.md (100%) rename docs/{ => archive}/WIKI-IMPLEMENTATION-PLAN.md (100%) rename docs/{ => guides}/CLI-REFERENCE.md (100%) rename docs/{ => guides}/DEPLOYMENT.md (100%) rename docs/{ => guides}/DEVICE-INITIAL-SETUP.md (100%) rename docs/{ => guides}/GETTING-STARTED.md (100%) rename docs/{ => guides}/HTTPS-SETUP.md (100%) rename docs/{MIGRATION-SAFETY-GUIDE.md => guides/MIGRATION-SAFETY.md} (89%) rename docs/{ => guides}/SOUNDTOUCH-SERVICE.md (100%) rename docs/{CLOUD-SHUTDOWN-GUIDE.md => guides/SURVIVAL-GUIDE.md} (93%) rename docs/{ => guides}/TROUBLESHOOTING.md (100%) rename docs/{ => reference}/API-COOKBOOK.md (100%) rename docs/{API-Endpoints-Overview.md => reference/API-ENDPOINTS.md} (100%) rename docs/{ => reference}/BASS-CONTROLS.md (100%) rename docs/{ => reference}/DISCOVERY.md (100%) rename docs/{FEATURE-MAPPING-GUIDE.md => reference/FEATURE-MAPPING.md} (100%) rename docs/{ => reference}/KEY-CONTROLS.md (100%) rename docs/{ => reference}/PRESET-MANAGEMENT.md (100%) rename docs/{ => reference}/SOURCE-SELECTION.md (100%) rename docs/{SPEAKER_ENDPOINT.md => reference/SPEAKER-ENDPOINT.md} (100%) rename docs/{ => reference}/SYSTEM-ENDPOINTS.md (100%) rename docs/{ => reference}/VOLUME-CONTROLS.md (100%) rename docs/{websocket-events.md => reference/WEBSOCKET-EVENTS.md} (100%) rename docs/{zone-management.md => reference/ZONE-MANAGEMENT.md} (100%) create mode 100644 pkg/service/handlers/docs_consistency_test.go diff --git a/README.md b/README.md index 8fefa91..cca4b3d 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ soundtouch-cli --host 192.168.1.100 volume set --level 50 soundtouch-cli --host 192.168.1.100 preset list ``` -For full CLI documentation, see [docs/CLI-REFERENCE.md](docs/CLI-REFERENCE.md). +For full CLI documentation, see [docs/guides/CLI-REFERENCE.md](docs/guides/CLI-REFERENCE.md). ### SoundTouch Service (Cloud Shutdown Protection) @@ -82,11 +82,11 @@ soundtouch-service ``` Open `http://localhost:8000` in your browser to manage your devices. Documentation is also available directly through the web interface. -For a comprehensive guide on transitioning your system, see the [Bose Cloud Shutdown: Survival Guide](docs/CLOUD-SHUTDOWN-GUIDE.md). +For a comprehensive guide on transitioning your system, see the [Bose Cloud Shutdown: Survival Guide](docs/guides/SURVIVAL-GUIDE.md). -Detailed service configuration and Docker instructions can be found in [docs/SOUNDTOUCH-SERVICE.md](docs/SOUNDTOUCH-SERVICE.md). +Detailed service configuration and Docker instructions can be found in [docs/guides/SOUNDTOUCH-SERVICE.md](docs/guides/SOUNDTOUCH-SERVICE.md). -For professional migration tips and safety measures, see the [Migration & Safety Guide](docs/MIGRATION-SAFETY-GUIDE.md). +For professional migration tips and safety measures, see the [Migration & Safety Guide](docs/guides/MIGRATION-SAFETY.md). ### Library Usage diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md new file mode 100644 index 0000000..5d7b16f --- /dev/null +++ b/docs/SUMMARY.md @@ -0,0 +1,54 @@ +# Table of Contents + +## User Guides +* [Cloud Shutdown Survival Guide](guides/SURVIVAL-GUIDE.md) +* [Migration & Safety Guide](guides/MIGRATION-SAFETY.md) +* [CLI Reference](guides/CLI-REFERENCE.md) +* [Getting Started](guides/GETTING-STARTED.md) +* [SoundTouch Service](guides/SOUNDTOUCH-SERVICE.md) +* [Initial Device Setup](guides/DEVICE-INITIAL-SETUP.md) +* [HTTPS Setup](guides/HTTPS-SETUP.md) +* [Deployment](guides/DEPLOYMENT.md) +* [Troubleshooting](guides/TROUBLESHOOTING.md) + +## Technical Reference +* [API Cookbook](reference/API-COOKBOOK.md) +* [API Endpoints](reference/API-ENDPOINTS.md) +* [System Endpoints](reference/SYSTEM-ENDPOINTS.md) +* [Speaker Endpoint](reference/SPEAKER-ENDPOINT.md) +* [WebSocket Events](reference/WEBSOCKET-EVENTS.md) +* [Discovery](reference/DISCOVERY.md) +* [Zone Management](reference/ZONE-MANAGEMENT.md) +* [Preset Management](reference/PRESET-MANAGEMENT.md) +* [Source Selection](reference/SOURCE-SELECTION.md) +* [Volume Controls](reference/VOLUME-CONTROLS.md) +* [Bass Controls](reference/BASS-CONTROLS.md) +* [Key Controls](reference/KEY-CONTROLS.md) +* [Feature Mapping](reference/FEATURE-MAPPING.md) + +## Analysis & Research +* [API Coverage Analysis](analysis/API-COVERAGE.md) +* [Supported URLs](analysis/SUPPORTED-URLS.md) +* [Upstream URLs](analysis/UPSTREAM-URLS.md) +* [Anonymization Summary](analysis/ANONYMIZATION-SUMMARY.md) +* [Device Redirect Methods](analysis/DEVICE-REDIRECT-METHODS.md) +* [Wiki API Comparison](analysis/WIKI-COMPARISON.md) + +## Appendix (Other Documents) +* [API Navigation Reference](API-NAVIGATION-REFERENCE.md) +* [Claude Instructions](CLAUDE.md) +* [Content Selection Implementation](CONTENT-SELECTION-IMPLEMENTATION.md) +* [Device Customization Setup](DEVICE-CUSTOMIZATION-SETUP.md) +* [Device Logging](DEVICE-LOGGING.md) +* [Feature History](FEATURE_HISTORY.md) +* [Host/Port Parsing](HOST-PORT-PARSING.md) +* [Manual Network Discovery](MANUAL-NETWORK-DISCOVERY.md) +* [Navigation Guide](NAVIGATION-GUIDE.md) +* [Official API Verification](OFFICIAL-API-VERIFICATION.md) +* [Preset Quickstart](PRESET-QUICKSTART.md) +* [Project Patterns](PROJECT-PATTERNS.md) +* [Service Availability Implementation](SERVICE-AVAILABILITY-IMPLEMENTATION.md) +* [SoundTouch Service Announcement](SOUNDTOUCH-SERVICE-ANNOUNCEMENT.md) +* [Undocumented Community Features](UNDOCUMENTED-COMMUNITY-FEATURES.md) +* [Unimplemented Endpoints](UNIMPLEMENTED-ENDPOINTS.md) +* [Preset Store](preset-store.md) diff --git a/docs/ANONYMIZATION-SUMMARY.md b/docs/analysis/ANONYMIZATION-SUMMARY.md similarity index 100% rename from docs/ANONYMIZATION-SUMMARY.md rename to docs/analysis/ANONYMIZATION-SUMMARY.md diff --git a/docs/API-COVERAGE-ANALYSIS.md b/docs/analysis/API-COVERAGE.md similarity index 100% rename from docs/API-COVERAGE-ANALYSIS.md rename to docs/analysis/API-COVERAGE.md diff --git a/docs/DEVICE-REDIRECT-METHODS.md b/docs/analysis/DEVICE-REDIRECT-METHODS.md similarity index 100% rename from docs/DEVICE-REDIRECT-METHODS.md rename to docs/analysis/DEVICE-REDIRECT-METHODS.md diff --git a/docs/SUPPORTEDURLS-ANALYSIS.md b/docs/analysis/SUPPORTED-URLS.md similarity index 100% rename from docs/SUPPORTEDURLS-ANALYSIS.md rename to docs/analysis/SUPPORTED-URLS.md diff --git a/docs/UPSTREAM-URLS-ANALYSIS.md b/docs/analysis/UPSTREAM-URLS.md similarity index 100% rename from docs/UPSTREAM-URLS-ANALYSIS.md rename to docs/analysis/UPSTREAM-URLS.md diff --git a/docs/WIKI-API-COMPARISON.md b/docs/analysis/WIKI-COMPARISON.md similarity index 100% rename from docs/WIKI-API-COMPARISON.md rename to docs/analysis/WIKI-COMPARISON.md diff --git a/docs/MERGE_PROJECTS.md b/docs/archive/MERGE_PROJECTS.md similarity index 100% rename from docs/MERGE_PROJECTS.md rename to docs/archive/MERGE_PROJECTS.md diff --git a/docs/PLAN.md b/docs/archive/PLAN.md similarity index 100% rename from docs/PLAN.md rename to docs/archive/PLAN.md diff --git a/docs/STATUS.md b/docs/archive/STATUS.md similarity index 100% rename from docs/STATUS.md rename to docs/archive/STATUS.md diff --git a/docs/WIKI-IMPLEMENTATION-PLAN.md b/docs/archive/WIKI-IMPLEMENTATION-PLAN.md similarity index 100% rename from docs/WIKI-IMPLEMENTATION-PLAN.md rename to docs/archive/WIKI-IMPLEMENTATION-PLAN.md diff --git a/docs/CLI-REFERENCE.md b/docs/guides/CLI-REFERENCE.md similarity index 100% rename from docs/CLI-REFERENCE.md rename to docs/guides/CLI-REFERENCE.md diff --git a/docs/DEPLOYMENT.md b/docs/guides/DEPLOYMENT.md similarity index 100% rename from docs/DEPLOYMENT.md rename to docs/guides/DEPLOYMENT.md diff --git a/docs/DEVICE-INITIAL-SETUP.md b/docs/guides/DEVICE-INITIAL-SETUP.md similarity index 100% rename from docs/DEVICE-INITIAL-SETUP.md rename to docs/guides/DEVICE-INITIAL-SETUP.md diff --git a/docs/GETTING-STARTED.md b/docs/guides/GETTING-STARTED.md similarity index 100% rename from docs/GETTING-STARTED.md rename to docs/guides/GETTING-STARTED.md diff --git a/docs/HTTPS-SETUP.md b/docs/guides/HTTPS-SETUP.md similarity index 100% rename from docs/HTTPS-SETUP.md rename to docs/guides/HTTPS-SETUP.md diff --git a/docs/MIGRATION-SAFETY-GUIDE.md b/docs/guides/MIGRATION-SAFETY.md similarity index 89% rename from docs/MIGRATION-SAFETY-GUIDE.md rename to docs/guides/MIGRATION-SAFETY.md index e58b92a..ceb8689 100644 --- a/docs/MIGRATION-SAFETY-GUIDE.md +++ b/docs/guides/MIGRATION-SAFETY.md @@ -19,11 +19,14 @@ Before you proceed with the actual migration, follow these steps: - Insert the USB stick into the SoundTouch speaker's **SERVICE** port. - Reboot the speaker (unplug and replug). - The speaker will now allow SSH connections as `root` with no password. + - **Verify**: Run `ssh -oHostKeyAlgorithms=+ssh-rsa root@` to confirm access. (Note: older devices may require enabling `ssh-rsa` support). 2. **Network Isolation (Optional but Recommended)**: Ensure the device is on a stable wired connection if possible, or a dedicated 2.4GHz SSID to avoid drops during SSH operations. 3. **Initial Discovery & Sync**: - Run `soundtouch-cli discover devices` to ensure connectivity. - Use the Web UI or CLI to "Sync" the device. This will automatically backup your presets and system configuration files to your local server. -4. **Validate SSH Access**: Confirm the device responds to SSH without a password (the service handles this, but a manual check with `ssh root@` is a good sanity check). +4. **Validate SSH Access**: Confirm the device responds to SSH without a password. + - In the Web UI **Migration** tab, select your speaker and verify that the "SSH Connection" status shows ✅ Success. + - This toolkit automatically handles the necessary SSH parameters (ciphers and key exchanges) required by older Bose firmware. 5. **Use XML Migration First**: The `XML` migration method is less invasive than the `Hosts` method. It only changes the application config and doesn't require modifying the system's DNS/CA trust store if you don't need full HTTPS interception initially. 6. **Monitor Logs**: Run the `soundtouch-service` with `DEBUG` or `INFO` logging to see the step-by-step progress of the migration. diff --git a/docs/SOUNDTOUCH-SERVICE.md b/docs/guides/SOUNDTOUCH-SERVICE.md similarity index 100% rename from docs/SOUNDTOUCH-SERVICE.md rename to docs/guides/SOUNDTOUCH-SERVICE.md diff --git a/docs/CLOUD-SHUTDOWN-GUIDE.md b/docs/guides/SURVIVAL-GUIDE.md similarity index 93% rename from docs/CLOUD-SHUTDOWN-GUIDE.md rename to docs/guides/SURVIVAL-GUIDE.md index 8a33120..f79ad63 100644 --- a/docs/CLOUD-SHUTDOWN-GUIDE.md +++ b/docs/guides/SURVIVAL-GUIDE.md @@ -40,11 +40,15 @@ Open your web browser and navigate to the service's web interface: To migrate your speakers, the service needs SSH access. You can enable it by: 1. Creating an empty file named `remote_services` on a USB stick. 2. Inserting the USB stick into the SoundTouch speaker's service port. -3. Rebooting the speaker. +3. Rebooting the speaker (unplug/replug). + +**Verify SSH Access:** +- Confirm the device responds to SSH without a password: `ssh -oHostKeyAlgorithms=+ssh-rsa root@` +- Or use the **Migration** tab in the Web UI to see if the device shows a "✅ Success" status for SSH. Once enabled, you can log in as `root` (no password). #### 4. Setup Through the Web UI -The web interface handles the entire process in a guided flow. Before proceeding, we strongly recommend reviewing the [Migration & Safety Guide](MIGRATION-SAFETY-GUIDE.md). +The web interface handles the entire process in a guided flow. Before proceeding, we strongly recommend reviewing the [Migration & Safety Guide](MIGRATION-SAFETY.md). * **Step 1: Settings**: Configure your server's IP or domain. This ensures the speakers know where to find the local services. * **Step 2: Devices**: The service automatically scans for SoundTouch devices on your network. If a device is not found, you can manually add its IP address. diff --git a/docs/TROUBLESHOOTING.md b/docs/guides/TROUBLESHOOTING.md similarity index 100% rename from docs/TROUBLESHOOTING.md rename to docs/guides/TROUBLESHOOTING.md diff --git a/docs/API-COOKBOOK.md b/docs/reference/API-COOKBOOK.md similarity index 100% rename from docs/API-COOKBOOK.md rename to docs/reference/API-COOKBOOK.md diff --git a/docs/API-Endpoints-Overview.md b/docs/reference/API-ENDPOINTS.md similarity index 100% rename from docs/API-Endpoints-Overview.md rename to docs/reference/API-ENDPOINTS.md diff --git a/docs/BASS-CONTROLS.md b/docs/reference/BASS-CONTROLS.md similarity index 100% rename from docs/BASS-CONTROLS.md rename to docs/reference/BASS-CONTROLS.md diff --git a/docs/DISCOVERY.md b/docs/reference/DISCOVERY.md similarity index 100% rename from docs/DISCOVERY.md rename to docs/reference/DISCOVERY.md diff --git a/docs/FEATURE-MAPPING-GUIDE.md b/docs/reference/FEATURE-MAPPING.md similarity index 100% rename from docs/FEATURE-MAPPING-GUIDE.md rename to docs/reference/FEATURE-MAPPING.md diff --git a/docs/KEY-CONTROLS.md b/docs/reference/KEY-CONTROLS.md similarity index 100% rename from docs/KEY-CONTROLS.md rename to docs/reference/KEY-CONTROLS.md diff --git a/docs/PRESET-MANAGEMENT.md b/docs/reference/PRESET-MANAGEMENT.md similarity index 100% rename from docs/PRESET-MANAGEMENT.md rename to docs/reference/PRESET-MANAGEMENT.md diff --git a/docs/SOURCE-SELECTION.md b/docs/reference/SOURCE-SELECTION.md similarity index 100% rename from docs/SOURCE-SELECTION.md rename to docs/reference/SOURCE-SELECTION.md diff --git a/docs/SPEAKER_ENDPOINT.md b/docs/reference/SPEAKER-ENDPOINT.md similarity index 100% rename from docs/SPEAKER_ENDPOINT.md rename to docs/reference/SPEAKER-ENDPOINT.md diff --git a/docs/SYSTEM-ENDPOINTS.md b/docs/reference/SYSTEM-ENDPOINTS.md similarity index 100% rename from docs/SYSTEM-ENDPOINTS.md rename to docs/reference/SYSTEM-ENDPOINTS.md diff --git a/docs/VOLUME-CONTROLS.md b/docs/reference/VOLUME-CONTROLS.md similarity index 100% rename from docs/VOLUME-CONTROLS.md rename to docs/reference/VOLUME-CONTROLS.md diff --git a/docs/websocket-events.md b/docs/reference/WEBSOCKET-EVENTS.md similarity index 100% rename from docs/websocket-events.md rename to docs/reference/WEBSOCKET-EVENTS.md diff --git a/docs/zone-management.md b/docs/reference/ZONE-MANAGEMENT.md similarity index 100% rename from docs/zone-management.md rename to docs/reference/ZONE-MANAGEMENT.md diff --git a/pkg/service/handlers/docs_consistency_test.go b/pkg/service/handlers/docs_consistency_test.go new file mode 100644 index 0000000..e45428d --- /dev/null +++ b/pkg/service/handlers/docs_consistency_test.go @@ -0,0 +1,71 @@ +package handlers + +import ( + "io/fs" + "os" + "path/filepath" + "strings" + "testing" +) + +func TestDocsConsistency(t *testing.T) { + // Root of the project relative to this test file + // The test runs in the directory of the package + projectRoot := "../../.." + docsDir := filepath.Join(projectRoot, "docs") + summaryPath := filepath.Join(docsDir, "SUMMARY.md") + + summaryContent, err := os.ReadFile(summaryPath) + if err != nil { + t.Fatalf("Failed to read SUMMARY.md: %v", err) + } + + summaryText := string(summaryContent) + + // List of directories to check + dirsToCheck := []string{".", "guides", "reference", "analysis"} + + 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") { + return nil + } + + // Skip SUMMARY.md itself + if d.Name() == "SUMMARY.md" { + 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 directory %s: %v", dir, err) + } + } +} diff --git a/pkg/service/handlers/handlers_docs.go b/pkg/service/handlers/handlers_docs.go index 900b7bc..87b722c 100644 --- a/pkg/service/handlers/handlers_docs.go +++ b/pkg/service/handlers/handlers_docs.go @@ -15,7 +15,7 @@ func (s *Server) HandleDocs(w http.ResponseWriter, r *http.Request) { path := strings.TrimPrefix(r.URL.Path, "/docs") path = strings.TrimPrefix(path, "/") if path == "" { - path = "CLOUD-SHUTDOWN-GUIDE.md" + path = "guides/SURVIVAL-GUIDE.md" } // Ensure we only serve files from the docs directory @@ -31,10 +31,26 @@ func (s *Server) HandleDocs(w http.ResponseWriter, r *http.Request) { return } + // Load sidebar (SUMMARY.md) + summaryContent, _ := os.ReadFile(filepath.Join("docs", "SUMMARY.md")) + sidebar := "" + if len(summaryContent) > 0 { + // Render summary to HTML + sidebar = string(blackfriday.Run(summaryContent)) + // Adjust links in sidebar to be relative to /docs/ + sidebar = strings.ReplaceAll(sidebar, "href=\"guides/", "href=\"/docs/guides/") + sidebar = strings.ReplaceAll(sidebar, "href=\"reference/", "href=\"/docs/reference/") + sidebar = strings.ReplaceAll(sidebar, "href=\"analysis/", "href=\"/docs/analysis/") + // Fix relative links that don't have a directory prefix (root docs) + // We look for href="filename.md" and replace with href="/docs/filename.md" + // This avoids manual listing of every file. + sidebar = s.fixSidebarLinks(sidebar) + } + // Render markdown to HTML output := blackfriday.Run(content) - // Wrap in a simple HTML template + // Wrap in a documentation template with sidebar w.Header().Set("Content-Type", "text/html") fmt.Fprintf(w, ` @@ -44,21 +60,65 @@ func (s *Server) HandleDocs(w http.ResponseWriter, r *http.Request) { - ← Back to Toolkit -
+ +
+
+ %s +
+
-`, path, output) +`, path, sidebar, output) +} + +// fixSidebarLinks ensures that relative links in the SUMMARY.md (sidebar) +// are correctly prefixed with /docs/ for the web UI. +func (s *Server) fixSidebarLinks(sidebar string) string { + // Root links like [Label](file.md) become href="file.md" + // We want href="/docs/file.md", but only if it doesn't already start with /docs/ + // and isn't an external link. + // Since blackfriday renders [Label](file.md) as + + // A simple but effective way is to use a regex or just check for common patterns. + // We already handled subdirectories. Now we handle files in the root of docs/ + + // We'll look for href="filename.md" where filename doesn't contain a slash + // and isn't already prefixed. + + // Since we know our doc files always end in .md, we can look for that. + lines := strings.Split(sidebar, "\n") + for i, line := range lines { + if strings.Contains(line, "href=\"") && !strings.Contains(line, "href=\"/docs/") && !strings.Contains(line, "://") { + // Extract filename + start := strings.Index(line, "href=\"") + 6 + end := strings.Index(line[start:], "\"") + start + filename := line[start:end] + + if strings.HasSuffix(filename, ".md") && !strings.Contains(filename, "/") { + lines[i] = strings.ReplaceAll(line, "href=\""+filename+"\"", "href=\"/docs/"+filename+"\"") + } + } + } + return strings.Join(lines, "\n") } diff --git a/pkg/service/handlers/web/index.html b/pkg/service/handlers/web/index.html index 0d39ab2..2cf31fd 100644 --- a/pkg/service/handlers/web/index.html +++ b/pkg/service/handlers/web/index.html @@ -27,10 +27,15 @@
🔌 Prerequisite: Enable SSH
Migration requires SSH access. To enable it: -
    +
    1. Create an empty file named remote_services on a USB stick.
    2. Insert it into the speaker's SERVICE port and reboot the speaker.
    + Verify connection: +
      +
    • Use the Migration tab to select your device and verify that SSH Connection shows ✅ Success.
    • +
    • Or manually: ssh -oHostKeyAlgorithms=+ssh-rsa root@<SPEAKER-IP> (no password).
    • +
  1. @@ -55,14 +60,14 @@
    ⚠️ Safety First: Before starting any migration, please read our - Professional Migration & Safety Guide. + Professional Migration & Safety Guide. The toolkit automatically creates backups, but understanding the process is key to a smooth transition.

    Useful Links