This commit is contained in:
2025-08-04 08:01:26 +02:00
parent 07bd258e54
commit c853f3b0ce
9 changed files with 195 additions and 119 deletions

View File

@@ -12,15 +12,37 @@ This module allows you to build and manage Docusaurus websites using a generic c
### Example HeroScript
```heroscript
# 1. Define the Docusaurus build environment
!!docusaurus.define
path_build: "/tmp/docusaurus_build"
path_publish: "/tmp/docusaurus_publish"
reset: true
install: true
# 2. Configure the site using the generic 'site' module
# This part is handled by lib/web/site
// Define the Docusaurus build environment, is optional
!!docusaurus.define
path_build: "/tmp/docusaurus_build"
path_publish: "/tmp/docusaurus_publish"
reset: 1
install: 1
template_update: 1
!!docusaurus.add
sitename:"my_site"
path:"./path/to/my/site/source"
path_publish: "/tmp/docusaurus_publish" //optional
git_url:"https://git.threefold.info/tfgrid/docs_tfgrid4/src/branch/main/ebooks/tech" //or can use git to pull the site source, if we do like this then will
git_root:"/tmp/code"
git_reset:1
git_pull:1
// Run the development server
!!docusaurus.dev site:"my_site" open:true watch_changes:true
```
## see sites to define a site
the site needs to be defined following the generic site definition, see the `lib/web/site` module for more details.
```heroscript
//Configure the site using the generic 'site' module
!!site.config
name: "my_site"
title: "My Awesome Docs"
@@ -34,14 +56,8 @@ This module allows you to build and manage Docusaurus websites using a generic c
href: "https://example.com"
position: "right"
# ... add footer, pages, etc. using !!site.* actions ...
// ... add footer, pages, etc. using !!site.* actions ...
# 3. Add the generic site to the Docusaurus factory for building
# The 'path' points to your local source directory with static assets etc.
!!docusaurus.add site:"my_site" path:"./path/to/my/site/source"
# 4. Run the development server
!!docusaurus.dev site:"my_site" open:true watch_changes:true
```
### Heroscript Actions

View File

@@ -20,6 +20,7 @@ pub mut:
git_root string
git_pull bool
path_publish string
play bool = true
}
pub fn dsite_add(args_ AddArgs) !&DocSite {
@@ -85,6 +86,9 @@ pub fn dsite_add(args_ AddArgs) !&DocSite {
console.print_debug('Docusaurus site ${args.sitename} already exists, using existing site.')
mysite = site.get(name: args.sitename)!
} else {
if !args.play{
return error('Docusaurus site ${args.sitename} does not exist, please set play to true to create it.')
}
console.print_debug('Creating new Docusaurus site ${args.sitename}.')
mut plbook := playbook.new(path: "${args.path}/cfg")!
site.play(mut plbook)!

View File

@@ -12,11 +12,15 @@ import freeflowuniverse.herolib.core.texttools.regext
import freeflowuniverse.herolib.web.site as sitegen
pub fn (mut site DocSite) generate() ! {
console.print_header(' site generate: ${site.name} on ${site.factory.path_build.path}')
mut f:=factory_get()!
console.print_header(' site generate: ${site.name} on ${f.path_build.path}')
console.print_header(' site source on ${site.path_src.path}')
// lets make sure we remove the cfg dir so we rebuild
cfg_path := os.join_path(site.factory.path_build.path, 'cfg')
cfg_path := os.join_path(f.path_build.path, 'cfg')
osal.rm(cfg_path)!
mut gs := gittools.new()!
@@ -30,11 +34,11 @@ pub fn (mut site DocSite) generate() ! {
// we need to copy the template each time for these 2 items, otherwise there can be leftovers from other run
for item in ['src', 'static'] {
mut template_src_path := pathlib.get_dir(path: '${template_path}/${item}', create: true)!
template_src_path.copy(dest: '${site.factory.path_build.path}/${item}', delete: true)!
template_src_path.copy(dest: '${f.path_build.path}/${item}', delete: true)!
// now copy the info which can be overruled from source in relation to the template
if os.exists('${site.path_src.path}/${item}') {
mut src_path := pathlib.get_dir(path: '${site.path_src.path}/${item}', create: false)!
src_path.copy(dest: '${site.factory.path_build.path}/${item}', delete: false)!
src_path.copy(dest: '${f.path_build.path}/${item}', delete: false)!
}
}
@@ -47,11 +51,11 @@ pub fn (mut site DocSite) generate() ! {
mut footer_file := pathlib.get_file(path: '${cfg_path}/footer.json', create: true)!
footer_file.write(json.encode_pretty(site.config.footer))!
osal.rm('${site.factory.path_build.path}/docs')!
osal.rm('${f.path_build.path}/docs')!
if os.exists('${site.path_src.path}/docs') {
mut aa := site.path_src.dir_get('docs')!
aa.copy(dest: '${site.factory.path_build.path}/docs', delete: true)!
aa.copy(dest: '${f.path_build.path}/docs', delete: true)!
}
// now we need to process the pages, call the sitegen module, which will look for statements like
@@ -68,33 +72,35 @@ pub fn (mut site DocSite) generate() ! {
mut plbook := playbook.new(path: configpath)!
sitegen.play(mut plbook)!
site.process_imports()!
// site.process_imports()!
}
pub fn (mut site DocSite) process_imports() ! {
mut gs := gittools.new()!
for item in site.siteconfig.imports {
mypath := gs.get_path(
pull: false
reset: false
url: item.url
)!
mut mypatho := pathlib.get(mypath)
// pub fn (mut site DocSite) process_imports() ! {
// mut gs := gittools.new()!
// mut f:=factory_get()!
mypatho.copy(dest: '${site.factory.path_build.path}/docs/${item.dest}', delete: true)!
// for item in site.siteconfig.imports {
// mypath := gs.get_path(
// pull: false
// reset: false
// url: item.url
// )!
// mut mypatho := pathlib.get(mypath)
// println(item)
// replace: {'NAME': 'MyName', 'URGENCY': 'red'}
mut ri := regext.regex_instructions_new()
for key, val in item.replace {
ri.add_item('\{${key}\}', val)!
}
mypatho.copy(dest: '${site.factory.path_build.path}/docs/${item.dest}', delete: true)!
ri.replace_in_dir(
path: '${site.factory.path_build.path}/docs/${item.dest}'
extensions: [
'md',
]
)!
}
}
// mypatho.copy(dest: '${f.path_build.path}/docs/${item.dest}', delete: true)!
// // println(item)
// // replace: {'NAME': 'MyName', 'URGENCY': 'red'}
// mut ri := regext.regex_instructions_new()
// for key, val in item.replace {
// ri.add_item('\{${key}\}', val)!
// }
// mypatho.copy(dest: '${f.path_build.path}/docs/${item.dest}', delete: true)!
// ri.replace_in_dir(
// path: '${f.path_build.path}/docs/${item.dest}'
// extensions: [
// 'md',
// ]
// )!
// }
// }

View File

@@ -20,7 +20,7 @@ pub mut:
@[params]
pub struct DocSiteFactoryArgs {
pub:
pub mut:
path_build string
path_publish string
install bool
@@ -30,30 +30,37 @@ pub:
pub fn factory_get(args_ DocSiteFactoryArgs) !DocSiteFactory {
mut args:= args_
mut f:= docusaurus_factory or {
if args.path_build == '' {
args.path_build = '${os.home_dir()}/hero/var/docusaurus/build/${site_name}'
}
if args.path_publish == '' {
args.path_publish = '${os.home_dir()}/hero/var/docusaurus/publish/${site_name}'
}
mut factory := DocSiteFactory{
path_publish: pathlib.get_dir(args.path_publish)!
path_build: pathlib.get_dir(args.path_build)!
}
if !os.exists('${f.path_build.path}/node_modules') {
args.install = true
}
if args.install {
factory.install(args.reset, args.template_update)!
}
mut f:= docusaurus_factory or {
mut factory:=factory_set(args)!
factory
}
return f
}
pub fn factory_set(args_ DocSiteFactoryArgs) !DocSiteFactory {
mut args:= args_
if args.path_build == '' {
args.path_build = '${os.home_dir()}/hero/var/docusaurus/build'
}
if args.path_publish == '' {
args.path_publish = '${os.home_dir()}/hero/var/docusaurus/publish'
}
mut factory := DocSiteFactory{
path_publish: pathlib.get_dir(path:args.path_publish,create:true)!
path_build: pathlib.get_dir(path:args.path_build,create:true)!
}
if !os.exists('${args.path_build}/node_modules') {
args.install = true
}
if args.install {
factory.install(args.reset, args.template_update)!
}
return factory
}
pub fn dsite_get(name_ string) !&DocSite {
name := texttools.name_fix(name_)
return docusaurus_sites[name] or {

View File

@@ -1,4 +1,4 @@
module site
module docusaurus
import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.web.doctreeclient

View File

@@ -8,43 +8,70 @@ pub fn play(mut plbook PlayBook) ! {
// This populates the global `site.websites` map.
site.play(mut plbook)!
// 3. Process `docusaurus.add` actions to create sites.
for action in plbook.find(filter: 'docusaurus.add')! {
mut p := action.params
site_name := p.get('site') or { return error('In docusaurus.add, param "site" is required.') }
path := p.get('path') or { return error('In docusaurus.add, param "path" to the site source code is required.') }
mut generic_site := site.get(name: site_name)!
add(
site: generic_site
path_src: path
path_build: p.get_default('path_build', '')!
path_publish: p.get_default('path_publish', '')!
reset: p.get_default_false('reset')
template_update: p.get_default_false('template_update')
install: p.get_default_false('install')
)!
// check if docusaurus.define exists, if not, we create a default factory
mut f:=DocSiteFactory{}
if plbook.exists_once(filter: 'docusaurus.define'){
mut a:=plbook.get(filter: 'docusaurus.define') or {
panic('docusaurus.define action not found, this should not happen.')
}
mut p:=a.params
f=factory_set(
path_build: p.get_default('path_build', '')!
path_publish: p.get_default('path_publish', '')!
reset: p.get_default_false('reset')
template_update: p.get_default_false('template_update')
install: p.get_default_false('install')
)!
a.done = true
}else{
f=factory_get()!
}
// 4. Process actions like 'dev', 'build', etc.
for action in plbook.find(filter: 'docusaurus.dev')! {
// 3. Process `docusaurus.add` actions to create sites.
for mut action in plbook.find(filter: 'docusaurus.add')! {
mut p := action.params
site_name := p.get('sitename') or { return error('In docusaurus.add, param "sitename" is required.') }
dsite_add(
sitename: site_name
path: p.get('path')!
git_url: p.get('git_url')!
git_reset: p.get_default_false('git_reset')
git_root: p.get('git_root')!
git_pull: p.get_default_false('git_pull')
path_publish: p.get_default('path_publish', f.path_publish.path)!
play:false //need to make sure we don't play again
)!
action.done = true
}
mut actions_dev:=plbook.find(filter: 'docusaurus.dev')!
if actions_dev.len > 1 {
return error('Multiple "docusaurus.dev" actions found. Only one is allowed.')
}
for mut action in actions_dev {
mut p := action.params
site_name := p.get('site')!
mut dsite := get(site_name)!
mut dsite := dsite_get(site_name)!
dsite.dev(
host: p.get_default('host', 'localhost')!
port: p.get_int_default('port', 3000)!
open: p.get_default_false('open')
watch_changes: p.get_default_false('watch_changes')
)!
action.done = true
}
for action in plbook.find(filter: 'docusaurus.build')! {
mut actions_build:=plbook.find(filter: 'docusaurus.build')!
if actions_build.len > 1 {
return error('Multiple "docusaurus.build" actions found. Only one is allowed.')
}
for mut action in actions_build {
mut p := action.params
site_name := p.get('site')!
mut dsite := get(site_name)!
mut dsite := dsite_get(site_name)!
dsite.build()!
action.done = true
}
}

View File

@@ -6,15 +6,16 @@ import time
pub fn play(mut plbook PlayBook) ! {
// Handle multiple site configurations
config_actions := plbook.find(filter: 'site.config')!
mut config_actions := plbook.find(filter: 'site.config')!
if config_actions.len == 0 {
return error('No site.config actions found')
}
// Process each site configuration separately
for config_action in config_actions {
mut website := play_config_single(config_action)!
for mut config_action in config_actions {
mut website := play_config_single(mut config_action)!
mut config := &website.siteconfig
play_import(mut plbook, mut config)!
@@ -27,7 +28,7 @@ pub fn play(mut plbook PlayBook) ! {
}
}
fn play_config_single(action Action) !&Site {
fn play_config_single(mut action Action) !&Site {
mut p := action.params
name := p.get('name') or {
return error('need to specify name in site.config.\n${action}')
@@ -47,6 +48,8 @@ fn play_config_single(action Action) !&Site {
config.url_home = p.get_default('url_home', config.url_home)!
config.name = name
action.done = true // Mark the action as done
return website
}
@@ -84,14 +87,15 @@ fn play_config(mut plbook PlayBook) !&Site {
config.description = p_meta.get('description')!
}
action.done = true // Mark the action as done
return website
}
fn play_import(mut plbook PlayBook, mut config SiteConfig) ! {
import_actions := plbook.find(filter: 'site.import')!
mut import_actions := plbook.find(filter: 'site.import')!
// println('import_actions: ${import_actions}')
for action in import_actions {
for mut action in import_actions {
mut p := action.params
mut replace_map := map[string]string{}
if replace_str := p.get_default('replace', '') {
@@ -112,28 +116,32 @@ fn play_import(mut plbook PlayBook, mut config SiteConfig) ! {
visible: p.get_default_false('visible')
}
config.imports << import_
action.done = true // Mark the action as done
}
}
fn play_menu(mut plbook PlayBook, mut config SiteConfig) ! {
navbar_actions := plbook.find(filter: 'site.navbar')!
mut navbar_actions := plbook.find(filter: 'site.navbar')!
if navbar_actions.len > 0 {
for action in navbar_actions { // Should ideally be one, but loop for safety
for mut action in navbar_actions { // Should ideally be one, but loop for safety
mut p := action.params
config.menu.title = p.get_default('title', config.title)! // Use existing config.title as ultimate fallback
config.menu.logo_alt = p.get_default('logo_alt', '')!
config.menu.logo_src = p.get_default('logo_src', '')!
config.menu.logo_src_dark = p.get_default('logo_src_dark', '')!
action.done = true // Mark the action as done
}
} else {
// Fallback to site.menu for title if site.navbar is not found
menu_actions := plbook.find(filter: 'site.menu')!
for action in menu_actions {
mut menu_actions := plbook.find(filter: 'site.menu')!
for mut action in menu_actions {
mut p := action.params
config.menu.title = p.get_default('title', config.title)!
config.menu.logo_alt = p.get_default('logo_alt', '')!
config.menu.logo_src = p.get_default('logo_src', '')!
config.menu.logo_src_dark = p.get_default('logo_src_dark', '')!
action.done = true // Mark the action as done
}
}
@@ -143,7 +151,7 @@ fn play_menu(mut plbook PlayBook, mut config SiteConfig) ! {
menu_item_actions = plbook.find(filter: 'site.menu_item')!
}
for action in menu_item_actions {
for mut action in menu_item_actions {
mut p := action.params
mut item := MenuItem{
label: p.get_default('label', 'Documentation')!
@@ -152,20 +160,22 @@ fn play_menu(mut plbook PlayBook, mut config SiteConfig) ! {
position: p.get_default('position', 'right')!
}
config.menu.items << item
action.done = true // Mark the action as done
}
}
fn play_footer(mut plbook PlayBook, mut config SiteConfig) ! {
footer_actions := plbook.find(filter: 'site.footer')!
for action in footer_actions {
mut footer_actions := plbook.find(filter: 'site.footer')!
for mut action in footer_actions {
mut p := action.params
config.footer.style = p.get_default('style', 'dark')!
action.done = true // Mark the action as done
}
footer_item_actions := plbook.find(filter: 'site.footer_item')!
mut footer_item_actions := plbook.find(filter: 'site.footer_item')!
mut links_map := map[string][]FooterItem{}
for action in footer_item_actions {
for mut action in footer_item_actions {
mut p := action.params
title := p.get_default('title', 'Docs')!
mut item := FooterItem{
@@ -178,6 +188,7 @@ fn play_footer(mut plbook PlayBook, mut config SiteConfig) ! {
links_map[title] = []FooterItem{}
}
links_map[title] << item
action.done = true // Mark the action as done
}
// Convert map to footer links array
@@ -190,25 +201,27 @@ fn play_footer(mut plbook PlayBook, mut config SiteConfig) ! {
}
fn play_build_dest(mut plbook PlayBook, mut config SiteConfig) ! {
build_dest_actions := plbook.find(filter: 'site.build_dest')!
for action in build_dest_actions {
mut build_dest_actions := plbook.find(filter: 'site.build_dest')!
for mut action in build_dest_actions {
mut p := action.params
mut dest := BuildDest{
path: p.get('path')!
ssh_name: p.get_default('ssh_name', '')!
}
config.build_dest << dest
action.done = true // Mark the action as done
}
}
fn play_build_dest_dev(mut plbook PlayBook, mut config SiteConfig) ! {
build_dest_dev_actions := plbook.find(filter: 'site.build_dest_dev')!
for action in build_dest_dev_actions {
mut build_dest_dev_actions := plbook.find(filter: 'site.build_dest_dev')!
for mut action in build_dest_dev_actions {
mut p := action.params
mut dest_dev := BuildDest{
path: p.get('path')!
ssh_name: p.get_default('ssh_name', '')!
}
config.build_dest_dev << dest_dev
action.done = true // Mark the action as done
}
}