feat: add docs landing page slug handling
- Add function to find first doc in sidebar - Pass found doc ID to process_page - Set slug: / for landing page in frontmatter
This commit is contained in:
@@ -6,11 +6,11 @@ import incubaid.herolib.web.site
|
||||
|
||||
pub struct Configuration {
|
||||
pub mut:
|
||||
main Main
|
||||
navbar Navbar
|
||||
footer Footer
|
||||
sidebar_json_txt string //will hold the sidebar.json content
|
||||
announcement AnnouncementBar
|
||||
main Main
|
||||
navbar Navbar
|
||||
footer Footer
|
||||
sidebar_json_txt string // will hold the sidebar.json content
|
||||
announcement AnnouncementBar
|
||||
}
|
||||
|
||||
pub struct Main {
|
||||
@@ -86,9 +86,7 @@ pub mut:
|
||||
is_closeable bool @[json: 'isCloseable']
|
||||
}
|
||||
|
||||
// ... (struct definitions remain the same) ...
|
||||
|
||||
// This function is now a pure transformer: site.SiteConfig -> docusaurus.Configuration
|
||||
// This function is a pure transformer: site.SiteConfig -> docusaurus.Configuration
|
||||
fn new_configuration(mysite site.Site) !Configuration {
|
||||
// Transform site.SiteConfig to docusaurus.Configuration
|
||||
mut site_cfg := mysite.siteconfig
|
||||
@@ -121,7 +119,7 @@ fn new_configuration(mysite site.Site) !Configuration {
|
||||
sidebar_json_txt := mysite.nav.sidebar_to_json()!
|
||||
|
||||
cfg := Configuration{
|
||||
main: Main{
|
||||
main: Main{
|
||||
title: site_cfg.title
|
||||
tagline: site_cfg.tagline
|
||||
favicon: site_cfg.favicon
|
||||
@@ -151,7 +149,7 @@ fn new_configuration(mysite site.Site) !Configuration {
|
||||
copyright: site_cfg.copyright
|
||||
name: site_cfg.name
|
||||
}
|
||||
navbar: Navbar{
|
||||
navbar: Navbar{
|
||||
title: site_cfg.menu.title
|
||||
logo: Logo{
|
||||
alt: site_cfg.menu.logo_alt
|
||||
@@ -160,11 +158,11 @@ fn new_configuration(mysite site.Site) !Configuration {
|
||||
}
|
||||
items: nav_items
|
||||
}
|
||||
footer: Footer{
|
||||
footer: Footer{
|
||||
style: site_cfg.footer.style
|
||||
links: footer_links
|
||||
}
|
||||
announcement: AnnouncementBar{
|
||||
announcement: AnnouncementBar{
|
||||
// id: site_cfg.announcement.id
|
||||
content: site_cfg.announcement.content
|
||||
background_color: site_cfg.announcement.background_color
|
||||
|
||||
@@ -11,6 +11,30 @@ import os
|
||||
// Doc Linking - Generate Docusaurus docs from Atlas collections
|
||||
// ============================================================================
|
||||
|
||||
// get_first_doc_from_sidebar recursively finds the first doc ID in the sidebar.
|
||||
// Used to determine which page should get slug: / in frontmatter when url_home ends with "/".
|
||||
fn get_first_doc_from_sidebar(items []site.NavItem) string {
|
||||
for item in items {
|
||||
match item {
|
||||
site.NavDoc {
|
||||
return site.extract_page_id(item.id)
|
||||
}
|
||||
site.NavCat {
|
||||
// Recursively search in category items
|
||||
doc := get_first_doc_from_sidebar(item.items)
|
||||
if doc.len > 0 {
|
||||
return doc
|
||||
}
|
||||
}
|
||||
site.NavLink {
|
||||
// Skip links, we want docs
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
// link_docs generates markdown files from site page definitions.
|
||||
// Pages are fetched from Atlas collections and written with frontmatter.
|
||||
pub fn (mut docsite DocSite) link_docs() ! {
|
||||
@@ -23,8 +47,15 @@ pub fn (mut docsite DocSite) link_docs() ! {
|
||||
mut client := atlas_client.new(export_dir: c.atlas_dir)!
|
||||
mut errors := []string{}
|
||||
|
||||
// Determine if we need to set a docs landing page (when url_home ends with "/")
|
||||
first_doc_page := if docsite.website.siteconfig.url_home.ends_with('/') {
|
||||
get_first_doc_from_sidebar(docsite.website.nav.my_sidebar)
|
||||
} else {
|
||||
''
|
||||
}
|
||||
|
||||
for _, page in docsite.website.pages {
|
||||
process_page(mut client, docs_path, page, mut errors)
|
||||
process_page(mut client, docs_path, page, first_doc_page, mut errors)
|
||||
}
|
||||
|
||||
if errors.len > 0 {
|
||||
@@ -51,7 +82,7 @@ fn report_errors(mut client atlas_client.AtlasClient, errors []string) ! {
|
||||
// Page Processing
|
||||
// ============================================================================
|
||||
|
||||
fn process_page(mut client atlas_client.AtlasClient, docs_path string, page site.Page, mut errors []string) {
|
||||
fn process_page(mut client atlas_client.AtlasClient, docs_path string, page site.Page, first_doc_page string, mut errors []string) {
|
||||
collection, page_name := parse_page_src(page.src) or {
|
||||
errors << err.msg()
|
||||
return
|
||||
@@ -62,7 +93,10 @@ fn process_page(mut client atlas_client.AtlasClient, docs_path string, page site
|
||||
return
|
||||
}
|
||||
|
||||
write_page(docs_path, page_name, page, content) or {
|
||||
// Check if this page is the docs landing page
|
||||
is_landing_page := first_doc_page.len > 0 && page_name == first_doc_page
|
||||
|
||||
write_page(docs_path, page_name, page, content, is_landing_page) or {
|
||||
errors << "Failed to write page '${page_name}': ${err.msg()}"
|
||||
return
|
||||
}
|
||||
@@ -79,8 +113,8 @@ fn parse_page_src(src string) !(string, string) {
|
||||
return parts[0], parts[1]
|
||||
}
|
||||
|
||||
fn write_page(docs_path string, page_name string, page site.Page, content string) ! {
|
||||
frontmatter := build_frontmatter(page, content)
|
||||
fn write_page(docs_path string, page_name string, page site.Page, content string, is_landing_page bool) ! {
|
||||
frontmatter := build_frontmatter(page, content, is_landing_page)
|
||||
final_content := frontmatter + '\n\n' + content
|
||||
|
||||
output_path := '${docs_path}/${page_name}.md'
|
||||
@@ -97,7 +131,7 @@ fn copy_page_assets(mut client atlas_client.AtlasClient, docs_path string, colle
|
||||
// Frontmatter Generation
|
||||
// ============================================================================
|
||||
|
||||
fn build_frontmatter(page site.Page, content string) string {
|
||||
fn build_frontmatter(page site.Page, content string, is_landing_page bool) string {
|
||||
title := get_title(page, content)
|
||||
description := get_description(page, title)
|
||||
|
||||
@@ -105,6 +139,11 @@ fn build_frontmatter(page site.Page, content string) string {
|
||||
lines << "title: '${escape_yaml(title)}'"
|
||||
lines << "description: '${escape_yaml(description)}'"
|
||||
|
||||
// Add slug: / for the docs landing page so /docs/ works directly
|
||||
if is_landing_page {
|
||||
lines << 'slug: /'
|
||||
}
|
||||
|
||||
if page.draft {
|
||||
lines << 'draft: true'
|
||||
}
|
||||
|
||||
82
lib/web/docusaurus/for_testing/README.md
Normal file
82
lib/web/docusaurus/for_testing/README.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Docusaurus Link Resolution Test
|
||||
|
||||
This directory contains a comprehensive test for the herolib documentation linking mechanism.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
for_testing/
|
||||
├── README.md # This file
|
||||
├── collections/
|
||||
│ └── test_collection/ # Markdown source files
|
||||
│ ├── .collection # Collection metadata
|
||||
│ ├── page1.md # Introduction
|
||||
│ ├── page2.md # Basic Concepts
|
||||
│ ├── page3.md # Configuration
|
||||
│ ├── page4.md # Advanced Features
|
||||
│ ├── page5.md # Troubleshooting
|
||||
│ ├── page6.md # Best Practices
|
||||
│ └── page7.md # Conclusion
|
||||
└── ebooks/
|
||||
└── test_site/ # Heroscript configuration
|
||||
├── heroscriptall # Master configuration (entry point)
|
||||
├── config.heroscript # Site configuration
|
||||
├── pages.heroscript # Page definitions
|
||||
└── docusaurus.heroscript # Docusaurus settings
|
||||
```
|
||||
|
||||
## What This Tests
|
||||
|
||||
1. **Link Resolution** - Each page contains links using the `[text](collection:page)` format
|
||||
2. **Navigation Chain** - Pages link sequentially: 1 → 2 → 3 → 4 → 5 → 6 → 7
|
||||
3. **Sidebar Generation** - All 7 pages should appear in the sidebar
|
||||
4. **Category Support** - Pages are organized into categories (root, basics, advanced, reference)
|
||||
|
||||
## Running the Test
|
||||
|
||||
From the herolib root directory:
|
||||
|
||||
```bash
|
||||
# Build herolib first
|
||||
./cli/compile.vsh
|
||||
|
||||
# Run the test site
|
||||
/Users/mahmoud/hero/bin/hero docs -d -p lib/web/docusaurus/for_testing/ebooks/test_site
|
||||
```
|
||||
|
||||
## Expected Results
|
||||
|
||||
When the test runs successfully:
|
||||
|
||||
1. ✅ All 7 pages are generated in `~/hero/var/docusaurus/build/docs/`
|
||||
2. ✅ Sidebar shows all pages organized by category
|
||||
3. ✅ Clicking navigation links works (page1 → page2 → ... → page7)
|
||||
4. ✅ No broken links or 404 errors
|
||||
5. ✅ Back-links also work (e.g., page7 → page1)
|
||||
|
||||
## Link Syntax Being Tested
|
||||
|
||||
```markdown
|
||||
[Next Page](test_collection:page2)
|
||||
```
|
||||
|
||||
This should resolve to a proper Docusaurus link when the site is built.
|
||||
|
||||
## Verification
|
||||
|
||||
After running the test:
|
||||
|
||||
1. Open http://localhost:3000/test/ in your browser
|
||||
2. Click through all navigation links from Page 1 to Page 7
|
||||
3. Verify the back-link on Page 7 returns to Page 1
|
||||
4. Check the sidebar displays all pages correctly
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If links don't resolve:
|
||||
|
||||
1. Check that the collection is registered in the atlas
|
||||
2. Verify page names match (no typos)
|
||||
3. Run with debug flag (`-d`) to see detailed output
|
||||
4. Check `~/hero/var/docusaurus/build/docs/` for generated files
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
name: test_collection
|
||||
description: Test collection for link resolution testing
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# Page 1: Introduction
|
||||
|
||||
Welcome to the documentation linking test. This page serves as the entry point for testing herolib's link resolution mechanism.
|
||||
|
||||
## Overview
|
||||
|
||||
This test suite consists of 7 interconnected pages that form a chain. Each page links to the next, demonstrating that the `collection:page_name` link syntax works correctly across multiple layers.
|
||||
|
||||
## What We're Testing
|
||||
|
||||
- Link resolution using `collection:page_name` format
|
||||
- Proper generation of Docusaurus-compatible links
|
||||
- Navigation chain integrity from page 1 through page 7
|
||||
- Sidebar generation with all pages
|
||||
|
||||
## Navigation
|
||||
|
||||
Continue to the next section to learn about the basic concepts.
|
||||
|
||||
**Next:** [Page 2: Basic Concepts](test_collection:page2)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# Page 2: Basic Concepts
|
||||
|
||||
This page covers the basic concepts of the documentation system.
|
||||
|
||||
## Link Syntax
|
||||
|
||||
In herolib, links between pages use the format:
|
||||
|
||||
```
|
||||
[Link Text](collection_name:page_name)
|
||||
```
|
||||
|
||||
For example, to link to `page3` in `test_collection`:
|
||||
|
||||
```markdown
|
||||
[Go to Page 3](test_collection:page3)
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
1. The parser identifies links with the `collection:page` format
|
||||
2. During site generation, these are resolved to actual file paths
|
||||
3. Docusaurus receives properly formatted relative links
|
||||
|
||||
## Navigation
|
||||
|
||||
**Previous:** [Page 1: Introduction](test_collection:page1)
|
||||
|
||||
**Next:** [Page 3: Configuration](test_collection:page3)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# Page 3: Configuration
|
||||
|
||||
This page explains configuration options for the documentation system.
|
||||
|
||||
## Site Configuration
|
||||
|
||||
The site is configured using heroscript files:
|
||||
|
||||
```heroscript
|
||||
!!site.config
|
||||
name:"test_site"
|
||||
title:"Test Documentation"
|
||||
base_url:"/test/"
|
||||
url_home:"docs/page1"
|
||||
```
|
||||
|
||||
## Page Definitions
|
||||
|
||||
Each page is defined using the `!!site.page` action:
|
||||
|
||||
```heroscript
|
||||
!!site.page src:"test_collection:page1"
|
||||
title:"Introduction"
|
||||
```
|
||||
|
||||
## Important Settings
|
||||
|
||||
| Setting | Description |
|
||||
|---------|-------------|
|
||||
| `name` | Unique page identifier |
|
||||
| `collection` | Source collection name |
|
||||
| `title` | Display title in sidebar |
|
||||
|
||||
## Navigation
|
||||
|
||||
**Previous:** [Page 2: Basic Concepts](test_collection:page2)
|
||||
|
||||
**Next:** [Page 4: Advanced Features](test_collection:page4)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# Page 4: Advanced Features
|
||||
|
||||
This page covers advanced features of the linking mechanism.
|
||||
|
||||
## Cross-Collection Links
|
||||
|
||||
You can link to pages in different collections:
|
||||
|
||||
```markdown
|
||||
[Link to other collection](other_collection:some_page)
|
||||
```
|
||||
|
||||
## Categories
|
||||
|
||||
Pages can be organized into categories:
|
||||
|
||||
```heroscript
|
||||
!!site.page_category name:'advanced' label:"Advanced Topics"
|
||||
|
||||
!!site.page name:'page4' collection:'test_collection'
|
||||
title:"Advanced Features"
|
||||
```
|
||||
|
||||
## Multiple Link Formats
|
||||
|
||||
The system supports various link formats:
|
||||
|
||||
1. **Collection links:** `[text](collection:page)`
|
||||
2. **Relative links:** `[text](./other_page.md)`
|
||||
3. **External links:** `[text](https://example.com)`
|
||||
|
||||
## Navigation
|
||||
|
||||
**Previous:** [Page 3: Configuration](test_collection:page3)
|
||||
|
||||
**Next:** [Page 5: Troubleshooting](test_collection:page5)
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
# Page 5: Troubleshooting
|
||||
|
||||
This page helps you troubleshoot common issues.
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Broken Links
|
||||
|
||||
If links appear broken, check:
|
||||
|
||||
1. The collection name is correct
|
||||
2. The page name matches the markdown filename (without `.md`)
|
||||
3. The collection is properly registered in the atlas
|
||||
|
||||
### Page Not Found
|
||||
|
||||
Ensure the page is defined in your heroscript:
|
||||
|
||||
```heroscript
|
||||
!!site.page name:'page5' collection:'test_collection'
|
||||
title:"Troubleshooting"
|
||||
```
|
||||
|
||||
## Debugging Tips
|
||||
|
||||
- Run with debug flag: `hero docs -d -p .`
|
||||
- Check the generated `sidebar.json`
|
||||
- Verify the docs output in `~/hero/var/docusaurus/build/docs/`
|
||||
|
||||
## Error Messages
|
||||
|
||||
| Error | Solution |
|
||||
|-------|----------|
|
||||
| "Page not found" | Check page name spelling |
|
||||
| "Collection not found" | Verify atlas configuration |
|
||||
| "Link resolution failed" | Check link syntax |
|
||||
|
||||
## Navigation
|
||||
|
||||
**Previous:** [Page 4: Advanced Features](test_collection:page4)
|
||||
|
||||
**Next:** [Page 6: Best Practices](test_collection:page6)
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# Page 6: Best Practices
|
||||
|
||||
This page outlines best practices for documentation.
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
- Use lowercase for page names: `page_name.md`
|
||||
- Use underscores for multi-word names: `my_long_page_name.md`
|
||||
- Keep names short but descriptive
|
||||
|
||||
## Link Organization
|
||||
|
||||
### Do This ✓
|
||||
|
||||
```markdown
|
||||
See the [configuration guide](test_collection:page3) for details.
|
||||
```
|
||||
|
||||
### Avoid This ✗
|
||||
|
||||
```markdown
|
||||
Click [here](test_collection:page3) for more.
|
||||
```
|
||||
|
||||
## Documentation Structure
|
||||
|
||||
A well-organized documentation site should:
|
||||
|
||||
1. **Start with an introduction** - Explain what the documentation covers
|
||||
2. **Progress logically** - Each page builds on the previous
|
||||
3. **End with reference material** - API docs, troubleshooting, etc.
|
||||
|
||||
## Content Guidelines
|
||||
|
||||
- Keep paragraphs short
|
||||
- Use code blocks for examples
|
||||
- Include navigation links at the bottom of each page
|
||||
|
||||
## Navigation
|
||||
|
||||
**Previous:** [Page 5: Troubleshooting](test_collection:page5)
|
||||
|
||||
**Next:** [Page 7: Conclusion](test_collection:page7)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# Page 7: Conclusion
|
||||
|
||||
Congratulations! You've reached the final page of the documentation linking test.
|
||||
|
||||
## Summary
|
||||
|
||||
This test suite demonstrated:
|
||||
|
||||
- ✅ Link resolution using `collection:page_name` format
|
||||
- ✅ Navigation chain across 7 pages
|
||||
- ✅ Proper sidebar generation
|
||||
- ✅ Docusaurus-compatible output
|
||||
|
||||
## Test Verification
|
||||
|
||||
If you've reached this page by clicking through all the navigation links, the linking mechanism is working correctly!
|
||||
|
||||
### Link Chain Verified
|
||||
|
||||
1. [Page 1: Introduction](test_collection:page1) → Entry point
|
||||
2. [Page 2: Basic Concepts](test_collection:page2) → Link syntax
|
||||
3. [Page 3: Configuration](test_collection:page3) → Site setup
|
||||
4. [Page 4: Advanced Features](test_collection:page4) → Cross-collection links
|
||||
5. [Page 5: Troubleshooting](test_collection:page5) → Common issues
|
||||
6. [Page 6: Best Practices](test_collection:page6) → Guidelines
|
||||
7. **Page 7: Conclusion** → You are here!
|
||||
|
||||
## What's Next
|
||||
|
||||
You can now use the herolib documentation system with confidence that links will resolve correctly across your entire documentation site.
|
||||
|
||||
## Navigation
|
||||
|
||||
**Previous:** [Page 6: Best Practices](test_collection:page6)
|
||||
|
||||
**Back to Start:** [Page 1: Introduction](test_collection:page1)
|
||||
|
||||
16
lib/web/docusaurus/for_testing/ebooks/test_site/config.hero
Normal file
16
lib/web/docusaurus/for_testing/ebooks/test_site/config.hero
Normal file
@@ -0,0 +1,16 @@
|
||||
!!site.config
|
||||
name:"test_site"
|
||||
title:"Link Resolution Test"
|
||||
tagline:"Testing herolib documentation linking mechanism"
|
||||
url:"http://localhost:3000"
|
||||
url_home:"docs/"
|
||||
base_url:"/test/"
|
||||
favicon:"img/favicon.png"
|
||||
copyright:"© 2024 Herolib Test"
|
||||
default_collection:"test_collection"
|
||||
|
||||
!!site.config_meta
|
||||
description:"Test suite for verifying herolib documentation link resolution across multiple pages"
|
||||
title:"Link Resolution Test - Herolib"
|
||||
keywords:"herolib, docusaurus, testing, links, documentation"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
!!docusaurus.define name:'test_site'
|
||||
|
||||
!!atlas.export include:true
|
||||
|
||||
33
lib/web/docusaurus/for_testing/ebooks/test_site/menus.hero
Normal file
33
lib/web/docusaurus/for_testing/ebooks/test_site/menus.hero
Normal file
@@ -0,0 +1,33 @@
|
||||
// Navbar configuration
|
||||
!!site.navbar
|
||||
title:"Link Test"
|
||||
|
||||
!!site.navbar_item
|
||||
label:"Documentation"
|
||||
to:"docs/"
|
||||
position:"left"
|
||||
|
||||
!!site.navbar_item
|
||||
label:"GitHub"
|
||||
href:"https://github.com/incubaid/herolib"
|
||||
position:"right"
|
||||
|
||||
// Footer configuration
|
||||
!!site.footer
|
||||
style:"dark"
|
||||
|
||||
!!site.footer_item
|
||||
title:"Docs"
|
||||
label:"Introduction"
|
||||
to:"docs/"
|
||||
|
||||
!!site.footer_item
|
||||
title:"Docs"
|
||||
label:"Configuration"
|
||||
to:"docs/page3"
|
||||
|
||||
!!site.footer_item
|
||||
title:"Community"
|
||||
label:"GitHub"
|
||||
href:"https://github.com/incubaid/herolib"
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// Page Definitions for Link Resolution Test
|
||||
// Each page maps to a markdown file in the test_collection
|
||||
|
||||
// Root pages (no category)
|
||||
!!site.page src:"test_collection:page1"
|
||||
title:"Introduction"
|
||||
|
||||
!!site.page src:"page2"
|
||||
title:"Basic Concepts"
|
||||
|
||||
// Basics category
|
||||
!!site.page_category name:'basics' label:"Getting Started"
|
||||
|
||||
!!site.page src:"page3"
|
||||
title:"Configuration"
|
||||
|
||||
!!site.page src:"page4"
|
||||
title:"Advanced Features"
|
||||
|
||||
// Advanced category
|
||||
!!site.page_category name:'advanced' label:"Advanced Topics"
|
||||
|
||||
!!site.page src:"page5"
|
||||
title:"Troubleshooting"
|
||||
|
||||
!!site.page src:"page6"
|
||||
title:"Best Practices"
|
||||
|
||||
// Reference category
|
||||
!!site.page_category name:'reference' label:"Reference"
|
||||
|
||||
!!site.page src:"page7"
|
||||
title:"Conclusion"
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
!!atlas.scan path:"../../collections/test_collection"
|
||||
|
||||
@@ -93,7 +93,9 @@ fn from_category(cat NavCat) SidebarItem {
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_page_id(id string) string {
|
||||
// extract_page_id extracts the page name from a "collection:page_name" format.
|
||||
// If the id doesn't contain a colon, returns the id as-is.
|
||||
pub fn extract_page_id(id string) string {
|
||||
parts := id.split(':')
|
||||
if parts.len == 2 {
|
||||
return parts[1]
|
||||
|
||||
Reference in New Issue
Block a user