...
This commit is contained in:
@@ -25,10 +25,10 @@ The recommended structure for an ebook follows this pattern:
|
||||
|
||||
```
|
||||
my_ebook/
|
||||
├── scan.hero # Atlas collection scanning
|
||||
├── scan.hero # DocTree collection scanning
|
||||
├── config.hero # Site configuration
|
||||
├── menus.hero # Navbar and footer configuration
|
||||
├── include.hero # Docusaurus define and atlas export
|
||||
├── include.hero # Docusaurus define and doctree export
|
||||
├── 1_intro.heroscript # Page definitions (numbered for ordering)
|
||||
├── 2_concepts.heroscript # More page definitions
|
||||
└── 3_advanced.heroscript # Additional pages
|
||||
@@ -42,10 +42,10 @@ Defines which collections to scan for content:
|
||||
|
||||
```heroscript
|
||||
// Scan local collections
|
||||
!!atlas.scan path:"../../collections/my_collection"
|
||||
!!doctree.scan path:"../../collections/my_collection"
|
||||
|
||||
// Scan remote collections from git
|
||||
!!atlas.scan git_url:"https://git.example.com/org/repo/src/branch/main/collections/docs"
|
||||
!!doctree.scan git_url:"https://git.example.com/org/repo/src/branch/main/collections/docs"
|
||||
```
|
||||
|
||||
#### `config.hero` - Site Configuration
|
||||
@@ -113,7 +113,7 @@ Links to shared configuration or defines docusaurus directly:
|
||||
// Option 2: Define directly
|
||||
!!docusaurus.define name:'my_ebook'
|
||||
|
||||
!!atlas.export include:true
|
||||
!!doctree.export include:true
|
||||
```
|
||||
|
||||
#### Page Definition Files (`*.heroscript`)
|
||||
@@ -145,7 +145,7 @@ Define pages and categories:
|
||||
|
||||
## Collections
|
||||
|
||||
Collections are directories containing markdown files. They're scanned by Atlas and referenced in page definitions.
|
||||
Collections are directories containing markdown files. They're scanned by DocTree and referenced in page definitions.
|
||||
|
||||
```
|
||||
collections/
|
||||
@@ -189,16 +189,16 @@ The older approach using `!!docusaurus.add` is still supported but not recommend
|
||||
|
||||
## HeroScript Actions Reference
|
||||
|
||||
### `!!atlas.scan`
|
||||
### `!!doctree.scan`
|
||||
|
||||
Scans a directory for markdown collections:
|
||||
|
||||
- `path` (string): Local path to scan
|
||||
- `git_url` (string): Git URL to clone and scan
|
||||
- `name` (string): Atlas instance name (default: `main`)
|
||||
- `name` (string): DocTree instance name (default: `main`)
|
||||
- `ignore` (list): Directory names to skip
|
||||
|
||||
### `!!atlas.export`
|
||||
### `!!doctree.export`
|
||||
|
||||
Exports scanned collections:
|
||||
|
||||
@@ -215,7 +215,7 @@ Configures the Docusaurus build environment:
|
||||
- `reset` (bool): Clean build directory before starting
|
||||
- `template_update` (bool): Update Docusaurus template
|
||||
- `install` (bool): Run `bun install`
|
||||
- `atlas_dir` (string): Atlas export directory
|
||||
- `doctree_dir` (string): DocTree export directory
|
||||
|
||||
### `!!site.config`
|
||||
|
||||
@@ -254,4 +254,4 @@ Defines a sidebar category:
|
||||
## See Also
|
||||
|
||||
- `lib/web/site` - Generic site configuration module
|
||||
- `lib/data/atlas` - Atlas collection management
|
||||
- `lib/data/doctree` - DocTree collection management
|
||||
|
||||
@@ -17,7 +17,7 @@ pub mut:
|
||||
reset bool
|
||||
template_update bool
|
||||
coderoot string
|
||||
atlas_dir string
|
||||
doctree_dir string
|
||||
}
|
||||
|
||||
@[params]
|
||||
@@ -29,7 +29,7 @@ pub mut:
|
||||
reset bool
|
||||
template_update bool
|
||||
coderoot string
|
||||
atlas_dir string
|
||||
doctree_dir string
|
||||
}
|
||||
|
||||
// return the last know config
|
||||
@@ -38,8 +38,8 @@ pub fn config() !DocusaurusConfig {
|
||||
docusaurus_config << DocusaurusConfigParams{}
|
||||
}
|
||||
mut args := docusaurus_config[0] or { panic('bug in docusaurus config') }
|
||||
if args.atlas_dir == '' {
|
||||
return error('atlas_dir is not set')
|
||||
if args.doctree_dir == '' {
|
||||
return error('doctree_dir is not set')
|
||||
}
|
||||
if args.path_build == '' {
|
||||
args.path_build = '${os.home_dir()}/hero/var/docusaurus/build'
|
||||
@@ -58,7 +58,7 @@ pub fn config() !DocusaurusConfig {
|
||||
install: args.install
|
||||
reset: args.reset
|
||||
template_update: args.template_update
|
||||
atlas_dir: args.atlas_dir
|
||||
doctree_dir: args.doctree_dir
|
||||
}
|
||||
if c.install {
|
||||
install(c)!
|
||||
|
||||
@@ -73,7 +73,7 @@ pub mut:
|
||||
port int = 3000
|
||||
open bool = true // whether to open the browser automatically
|
||||
watch_changes bool // whether to watch for changes in docs and rebuild automatically
|
||||
skip_generate bool // whether to skip generation (useful when docs are pre-generated, e.g., from atlas)
|
||||
skip_generate bool // whether to skip generation (useful when docs are pre-generated, e.g., from doctree)
|
||||
}
|
||||
|
||||
pub fn (mut s DocSite) open(args DevArgs) ! {
|
||||
|
||||
@@ -37,7 +37,7 @@ pub fn (mut docsite DocSite) generate() ! {
|
||||
mut sidebar_file := pathlib.get_file(path: '${cfg_path}/sidebar.json', create: true)!
|
||||
sidebar_file.write(docsite.config.sidebar_json_txt)!
|
||||
|
||||
docsite.link_docs()!
|
||||
docsite.generate_docs()!
|
||||
|
||||
docsite.import()!
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
module docusaurus
|
||||
|
||||
import incubaid.herolib.core.pathlib
|
||||
import incubaid.herolib.data.atlas.client as atlas_client
|
||||
import incubaid.herolib.data.doctree.client as doctree_client
|
||||
import incubaid.herolib.data.markdown.tools as markdowntools
|
||||
import incubaid.herolib.ui.console
|
||||
import incubaid.herolib.web.site
|
||||
import os
|
||||
|
||||
// ============================================================================
|
||||
// Doc Linking - Generate Docusaurus docs from Atlas collections
|
||||
// Doc Linking - Generate Docusaurus docs from DocTree collections
|
||||
// ============================================================================
|
||||
|
||||
// get_first_doc_from_sidebar recursively finds the first doc ID in the sidebar.
|
||||
@@ -35,16 +35,16 @@ fn get_first_doc_from_sidebar(items []site.NavItem) string {
|
||||
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() ! {
|
||||
// generate_docs generates markdown files from site page definitions.
|
||||
// Pages are fetched from DocTree collections and written with frontmatter.
|
||||
pub fn (mut docsite DocSite) generate_docs() ! {
|
||||
c := config()!
|
||||
docs_path := '${c.path_build.path}/docs'
|
||||
|
||||
reset_docs_dir(docs_path)!
|
||||
console.print_header('Linking docs to ${docs_path}')
|
||||
console.print_header('Write doc: ${docs_path}')
|
||||
|
||||
mut client := atlas_client.new(export_dir: c.atlas_dir)!
|
||||
mut client := doctree_client.new(export_dir: c.doctree_dir)!
|
||||
mut errors := []string{}
|
||||
|
||||
// Determine if we need to set a docs landing page (when url_home ends with "/")
|
||||
@@ -72,7 +72,7 @@ fn reset_docs_dir(docs_path string) ! {
|
||||
os.mkdir_all(docs_path)!
|
||||
}
|
||||
|
||||
fn report_errors(mut client atlas_client.AtlasClient, errors []string) ! {
|
||||
fn report_errors(mut client doctree_client.AtlasClient, errors []string) ! {
|
||||
available := client.list_markdown() or { 'Could not list available pages' }
|
||||
console.print_stderr('Available pages:\n${available}')
|
||||
return error('Errors during doc generation:\n${errors.join('\n\n')}')
|
||||
@@ -82,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, first_doc_page string, mut errors []string) {
|
||||
fn process_page(mut client doctree_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
|
||||
@@ -122,7 +122,7 @@ fn write_page(docs_path string, page_name string, page site.Page, content string
|
||||
file.write(final_content)!
|
||||
}
|
||||
|
||||
fn copy_page_assets(mut client atlas_client.AtlasClient, docs_path string, collection string, page_name string) {
|
||||
fn copy_page_assets(mut client doctree_client.AtlasClient, docs_path string, collection string, page_name string) {
|
||||
client.copy_images(collection, page_name, docs_path) or {}
|
||||
client.copy_files(collection, page_name, docs_path) or {}
|
||||
}
|
||||
@@ -132,12 +132,21 @@ fn copy_page_assets(mut client atlas_client.AtlasClient, docs_path string, colle
|
||||
// ============================================================================
|
||||
|
||||
fn build_frontmatter(page site.Page, content string, is_landing_page bool) string {
|
||||
|
||||
title := get_title(page, content)
|
||||
|
||||
description := get_description(page, title)
|
||||
|
||||
mut lines := ['---']
|
||||
lines << "title: '${escape_yaml(title)}'"
|
||||
lines << "description: '${escape_yaml(description)}'"
|
||||
lines << "title: '${title}'"
|
||||
lines << "description: '${description}'"
|
||||
|
||||
// if page.id.contains('tfhowto_tools'){
|
||||
// println('extracted title: ${title}')
|
||||
// println('page.src: ${lines}')
|
||||
// $dbg;
|
||||
// }
|
||||
|
||||
|
||||
// Add slug: / for the docs landing page so /docs/ works directly
|
||||
if is_landing_page {
|
||||
@@ -154,25 +163,3 @@ fn build_frontmatter(page site.Page, content string, is_landing_page bool) strin
|
||||
lines << '---'
|
||||
return lines.join('\n')
|
||||
}
|
||||
|
||||
fn get_title(page site.Page, content string) string {
|
||||
if page.title.len > 0 {
|
||||
return page.title
|
||||
}
|
||||
extracted := markdowntools.extract_title(content)
|
||||
if extracted.len > 0 {
|
||||
return extracted
|
||||
}
|
||||
return page.src.split(':').last()
|
||||
}
|
||||
|
||||
fn get_description(page site.Page, title string) string {
|
||||
if page.description.len > 0 {
|
||||
return page.description
|
||||
}
|
||||
return title
|
||||
}
|
||||
|
||||
fn escape_yaml(s string) string {
|
||||
return s.replace("'", "''")
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
module docusaurus
|
||||
|
||||
import incubaid.herolib.core.pathlib
|
||||
// import incubaid.herolib.data.atlas.client as atlas_client
|
||||
// import incubaid.herolib.data.doctree.client as doctree_client
|
||||
// import incubaid.herolib.web.site { Page, Section, Site }
|
||||
// import incubaid.herolib.data.markdown.tools as markdowntools
|
||||
// import incubaid.herolib.ui.console
|
||||
@@ -24,7 +24,7 @@ import incubaid.herolib.core.pathlib
|
||||
// docs_path := '${c.path_build.path}/docs'
|
||||
|
||||
// // Create the appropriate client based on configuration
|
||||
// mut client_instance := atlas_client.new(export_dir: c.atlas_dir)!
|
||||
// mut client_instance := doctree_client.new(export_dir: c.doctree_dir)!
|
||||
// mut client := IDocClient(client_instance)
|
||||
|
||||
// mut gen := SiteGenerator{
|
||||
@@ -378,8 +378,8 @@ import incubaid.herolib.core.pathlib
|
||||
// }
|
||||
// }
|
||||
|
||||
// // STEP 5: Fix bare page references (from atlas self-contained exports)
|
||||
// // Atlas exports convert cross-collection links to simple relative links like "token_system2.md"
|
||||
// // STEP 5: Fix bare page references (from doctree self-contained exports)
|
||||
// // DocTree exports convert cross-collection links to simple relative links like "token_system2.md"
|
||||
// // We need to transform these to proper relative paths based on Docusaurus structure
|
||||
// for page_name, target_dir in page_to_path {
|
||||
// // Match links in the format ](page_name) or ](page_name.md)
|
||||
|
||||
60
lib/web/docusaurus/dsite_to_sidebar_json.v
Normal file
60
lib/web/docusaurus/dsite_to_sidebar_json.v
Normal file
@@ -0,0 +1,60 @@
|
||||
module doc
|
||||
import incubaid.herolib.web.site
|
||||
|
||||
//this is the logic to create docusaurus sidebar.json from site.NavItems
|
||||
|
||||
struct SidebarItem {
|
||||
typ string @[json: 'type']
|
||||
id string @[omitempty]
|
||||
label string
|
||||
href string @[omitempty]
|
||||
description string @[omitempty]
|
||||
collapsible bool @[json: 'collapsible'; omitempty]
|
||||
collapsed bool @[json: 'collapsed'; omitempty]
|
||||
items []SidebarItem @[omitempty]
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// JSON Serialization
|
||||
// ============================================================================
|
||||
|
||||
pub fn sidebar_to_json(sb site.SideBar) !string {
|
||||
items := sb.my_sidebar.map(to_sidebar_item(it))
|
||||
return json.encode_pretty(items)
|
||||
}
|
||||
|
||||
fn to_sidebar_item(item site.NavItem) SidebarItem {
|
||||
return match item {
|
||||
NavDoc { from_doc(item) }
|
||||
NavLink { from_link(item) }
|
||||
NavCat { from_category(item) }
|
||||
}
|
||||
}
|
||||
|
||||
fn from_doc(doc site.NavDoc) SidebarItem {
|
||||
return SidebarItem{
|
||||
typ: 'doc'
|
||||
id: doc.id
|
||||
label: doc.label
|
||||
}
|
||||
}
|
||||
|
||||
fn from_link(link site.NavLink) SidebarItem {
|
||||
return SidebarItem{
|
||||
typ: 'link'
|
||||
label: link.label
|
||||
href: link.href
|
||||
description: link.description
|
||||
}
|
||||
}
|
||||
|
||||
fn from_category(cat site.NavCat) SidebarItem {
|
||||
return SidebarItem{
|
||||
typ: 'category'
|
||||
label: cat.label
|
||||
collapsible: cat.collapsible
|
||||
collapsed: cat.collapsed
|
||||
items: cat.items.map(to_sidebar_item(it))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ After running the test:
|
||||
|
||||
If links don't resolve:
|
||||
|
||||
1. Check that the collection is registered in the atlas
|
||||
1. Check that the collection is registered in the doctree
|
||||
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
|
||||
|
||||
@@ -10,7 +10,7 @@ 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
|
||||
3. The collection is properly registered in the doctree
|
||||
|
||||
### Page Not Found
|
||||
|
||||
@@ -29,11 +29,11 @@ Ensure the page is defined in your heroscript:
|
||||
|
||||
## Error Messages
|
||||
|
||||
| Error | Solution |
|
||||
|-------|----------|
|
||||
| "Page not found" | Check page name spelling |
|
||||
| "Collection not found" | Verify atlas configuration |
|
||||
| "Link resolution failed" | Check link syntax |
|
||||
| Error | Solution |
|
||||
| ------------------------ | ---------------------------- |
|
||||
| "Page not found" | Check page name spelling |
|
||||
| "Collection not found" | Verify doctree configuration |
|
||||
| "Link resolution failed" | Check link syntax |
|
||||
|
||||
## Navigation
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
!!docusaurus.define name:'test_site'
|
||||
|
||||
!!atlas.export include:true
|
||||
!!doctree.export include:true
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
!!atlas.scan path:"../../collections/test_collection"
|
||||
!!doctree.scan path:"../../collections/test_collection"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module docusaurus
|
||||
|
||||
import incubaid.herolib.core.playbook { PlayBook }
|
||||
import incubaid.herolib.data.atlas
|
||||
import incubaid.herolib.data.doctree
|
||||
import incubaid.herolib.ui.console
|
||||
import os
|
||||
|
||||
@@ -24,7 +24,7 @@ fn process_define(mut plbook PlayBook) !&DocSite {
|
||||
mut action := plbook.ensure_once(filter: 'docusaurus.define')!
|
||||
p := action.params
|
||||
|
||||
atlas_dir := p.get_default('atlas_dir', '${os.home_dir()}/hero/var/atlas_export')!
|
||||
doctree_dir := p.get_default('doctree_dir', '${os.home_dir()}/hero/var/doctree_export')!
|
||||
|
||||
config_set(
|
||||
path_build: p.get_default('path_build', '')!
|
||||
@@ -32,13 +32,13 @@ fn process_define(mut plbook PlayBook) !&DocSite {
|
||||
reset: p.get_default_false('reset')
|
||||
template_update: p.get_default_false('template_update')
|
||||
install: p.get_default_false('install')
|
||||
atlas_dir: atlas_dir
|
||||
doctree_dir: doctree_dir
|
||||
)!
|
||||
|
||||
site_name := p.get('name') or { return error('docusaurus.define: "name" is required') }
|
||||
atlas_name := p.get_default('atlas', 'main')!
|
||||
doctree_name := p.get_default('doctree', 'main')!
|
||||
|
||||
export_atlas(atlas_name, atlas_dir)!
|
||||
export_doctree(doctree_name, doctree_dir)!
|
||||
dsite_define(site_name)!
|
||||
action.done = true
|
||||
|
||||
@@ -77,11 +77,11 @@ fn process_dev(mut plbook PlayBook, mut dsite DocSite) ! {
|
||||
action.done = true
|
||||
}
|
||||
|
||||
fn export_atlas(name string, dir string) ! {
|
||||
if !atlas.exists(name) {
|
||||
fn export_doctree(name string, dir string) ! {
|
||||
if !doctree.exists(name) {
|
||||
return
|
||||
}
|
||||
console.print_debug('Auto-exporting Atlas "${name}" to ${dir}')
|
||||
mut a := atlas.get(name)!
|
||||
console.print_debug('Auto-exporting DocTree "${name}" to ${dir}')
|
||||
mut a := doctree.get(name)!
|
||||
a.export(destination: dir, reset: true, include: true, redis: false)!
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user