...
This commit is contained in:
@@ -1,245 +0,0 @@
|
||||
# Docusaurus Library for V
|
||||
|
||||
This library provides a convenient wrapper around Docusaurus, a powerful static website generator maintained by Meta. It allows you to:
|
||||
|
||||
- Create and manage multiple documentation sites
|
||||
- Configure sites through HeroScript
|
||||
- Build sites for production
|
||||
- Set up development environments with hot reloading
|
||||
- Handle file watching for automatic rebuilding
|
||||
- Deploy sites to remote servers
|
||||
- Import content from Git repositories
|
||||
|
||||
## Usage
|
||||
|
||||
```v
|
||||
import freeflowuniverse.herolib.web.docusaurus
|
||||
import os
|
||||
|
||||
// Define your HeroScript configuration
|
||||
hero_script := '
|
||||
!!docusaurus.config
|
||||
name:"my-documentation"
|
||||
title:"My Documentation Site"
|
||||
tagline:"Documentation made simple with V and Docusaurus"
|
||||
url:"https://docs.example.com"
|
||||
url_home:"docs/"
|
||||
base_url:"/"
|
||||
favicon:"img/favicon.png"
|
||||
image:"img/hero.png"
|
||||
copyright:"© 2025 Example Organization"
|
||||
|
||||
!!docusaurus.config_meta
|
||||
description:"Comprehensive documentation for our amazing project"
|
||||
image:"https://docs.example.com/img/social-card.png"
|
||||
title:"My Documentation | Official Docs"
|
||||
|
||||
!!docusaurus.navbar
|
||||
title:"My Project"
|
||||
|
||||
!!docusaurus.navbar_item
|
||||
label:"Documentation"
|
||||
href:"/docs"
|
||||
position:"left"
|
||||
|
||||
!!docusaurus.navbar_item
|
||||
label:"GitHub"
|
||||
href:"https://github.com/example/repo"
|
||||
position:"right"
|
||||
|
||||
!!docusaurus.footer
|
||||
style:"dark"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
title:"Documentation"
|
||||
label:"Introduction"
|
||||
to:"/docs"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
title:"Community"
|
||||
label:"GitHub"
|
||||
href:"https://github.com/example/repo"
|
||||
'
|
||||
|
||||
// Create a factory with the HeroScript configuration
|
||||
mut docs := docusaurus.new(
|
||||
build_path: os.join_path(os.home_dir(), 'hero/var/docusaurus_demo')
|
||||
heroscript: hero_script
|
||||
)!
|
||||
|
||||
// Create a site directory
|
||||
site_path := os.join_path(os.home_dir(), 'hero/var/docusaurus_source')
|
||||
os.mkdir_all(site_path)!
|
||||
|
||||
// Get or create a site using the factory
|
||||
mut site := docs.get(
|
||||
name: 'my-documentation'
|
||||
path: site_path
|
||||
init: true
|
||||
)!
|
||||
|
||||
// Generate a site
|
||||
site.generate()!
|
||||
|
||||
// Start development server
|
||||
site.dev()!
|
||||
|
||||
// Or build for production
|
||||
// site.build()!
|
||||
|
||||
// Or build and publish
|
||||
// site.build_publish()!
|
||||
```
|
||||
|
||||
### Directory Structure
|
||||
|
||||
A typical Docusaurus site managed by this library has the following structure:
|
||||
|
||||
```
|
||||
my-site/
|
||||
├── docs/
|
||||
│ ├── intro.md
|
||||
│ └── ...
|
||||
├── src/
|
||||
│ └── ...
|
||||
└── static/
|
||||
└── img/
|
||||
└── ...
|
||||
```
|
||||
|
||||
### Development Workflow
|
||||
|
||||
1. Define your site configuration using HeroScript
|
||||
2. Create a factory with the HeroScript configuration
|
||||
3. Get or create a site using the factory
|
||||
4. Run `site.dev()` to start development server
|
||||
5. Edit files in the `docs` directory
|
||||
6. When ready, run `site.build()` or `site.build_publish()` to deploy
|
||||
|
||||
## HeroScript Configuration Options
|
||||
|
||||
### Main Site Configuration
|
||||
|
||||
```
|
||||
!!docusaurus.config
|
||||
name:"my-documentation" # Site name (used for directories, etc.)
|
||||
title:"My Documentation" # Main title displayed in browser
|
||||
tagline:"Documentation Made Easy"
|
||||
url:"https://docs.example.com"
|
||||
url_home:"docs/"
|
||||
base_url:"/"
|
||||
favicon:"img/favicon.png"
|
||||
image:"img/hero.png"
|
||||
copyright:"© 2025 My Organization"
|
||||
```
|
||||
|
||||
### Metadata
|
||||
|
||||
```
|
||||
!!docusaurus.config_meta
|
||||
description:"Comprehensive documentation for my project"
|
||||
image:"https://docs.example.com/img/social-card.png"
|
||||
title:"My Documentation | Official Docs"
|
||||
```
|
||||
|
||||
### Navigation Bar
|
||||
|
||||
```
|
||||
!!docusaurus.navbar
|
||||
title:"My Project"
|
||||
|
||||
!!docusaurus.navbar_item
|
||||
label:"Documentation"
|
||||
href:"/docs"
|
||||
position:"left"
|
||||
|
||||
!!docusaurus.navbar_item
|
||||
label:"GitHub"
|
||||
href:"https://github.com/example/repo"
|
||||
position:"right"
|
||||
```
|
||||
|
||||
### Footer
|
||||
|
||||
```
|
||||
!!docusaurus.footer
|
||||
style:"dark"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
title:"Documentation"
|
||||
label:"Introduction"
|
||||
to:"/docs"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
title:"Community"
|
||||
label:"GitHub"
|
||||
href:"https://github.com/example/repo"
|
||||
```
|
||||
|
||||
### Remote Deployment
|
||||
|
||||
```
|
||||
!!docusaurus.ssh_connection
|
||||
name:"production"
|
||||
host:"example.com"
|
||||
login:"deploy"
|
||||
port:22
|
||||
key_path:"~/.ssh/id_rsa"
|
||||
|
||||
!!docusaurus.build_dest
|
||||
ssh_name:"production"
|
||||
path:"/var/www/docs"
|
||||
```
|
||||
|
||||
### Content Import
|
||||
|
||||
```
|
||||
!!docusaurus.import_source
|
||||
url:"https://github.com/example/external-docs"
|
||||
dest:"external"
|
||||
replace:"PROJECT_NAME:My Project, VERSION:1.0.0"
|
||||
```
|
||||
|
||||
## Multiple Ways to Use HeroScript
|
||||
|
||||
### Option 1: Provide HeroScript directly to the factory
|
||||
|
||||
```v
|
||||
mut docs := docusaurus.new(
|
||||
build_path: '~/docusaurus_sites'
|
||||
heroscript: hero_script
|
||||
)!
|
||||
```
|
||||
|
||||
### Option 2: Load HeroScript from a file
|
||||
|
||||
```v
|
||||
mut docs := docusaurus.new(
|
||||
build_path: '~/docusaurus_sites'
|
||||
heroscript_path: '~/my_docusaurus_config.hero'
|
||||
)!
|
||||
```
|
||||
|
||||
## Features in Detail
|
||||
|
||||
### File Watching
|
||||
|
||||
The library includes a file watcher that automatically updates the build directory when files change in the source directory. This enables a smooth development experience with hot reloading.
|
||||
|
||||
### Remote Deployment
|
||||
|
||||
Sites can be deployed to remote servers via SSH by configuring the deployment destinations in your HeroScript:
|
||||
|
||||
```
|
||||
!!docusaurus.ssh_connection
|
||||
name:"production"
|
||||
host:"example.com"
|
||||
login:"deploy"
|
||||
port:22
|
||||
key_path:"~/.ssh/id_rsa"
|
||||
|
||||
!!docusaurus.build_dest
|
||||
ssh_name:"production"
|
||||
path:"/var/www/docs"
|
||||
```
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
module docusaurus
|
||||
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import json
|
||||
import os
|
||||
module site
|
||||
|
||||
// Combined config structure
|
||||
pub struct Config {
|
||||
@@ -14,11 +10,21 @@ pub mut:
|
||||
favicon string = 'img/favicon.png'
|
||||
image string = 'img/tf_graph.png'
|
||||
copyright string = 'someone'
|
||||
footer Footer
|
||||
navbar Navbar
|
||||
import_sources []ImportSource
|
||||
footer Footer
|
||||
menu Menu
|
||||
import_collections []CollectionsImport
|
||||
pages []Page
|
||||
}
|
||||
|
||||
pub struct Page {
|
||||
pub mut:
|
||||
collection string
|
||||
name string
|
||||
content string
|
||||
title string
|
||||
description string
|
||||
draft bool
|
||||
}
|
||||
|
||||
// Footer config structures
|
||||
pub struct FooterItem {
|
||||
@@ -41,21 +47,21 @@ pub mut:
|
||||
}
|
||||
|
||||
|
||||
// Navbar config structures
|
||||
pub struct NavbarItem {
|
||||
// menu config structures
|
||||
pub struct MenuItem {
|
||||
pub mut:
|
||||
href string
|
||||
label string
|
||||
position string
|
||||
}
|
||||
|
||||
pub struct Navbar {
|
||||
pub struct Menu {
|
||||
pub mut:
|
||||
title string
|
||||
items []NavbarItem
|
||||
items []MenuItem
|
||||
}
|
||||
|
||||
pub struct ImportSource {
|
||||
pub struct CollectionsImport {
|
||||
pub mut:
|
||||
url string // http git url can be to specific path
|
||||
path string
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
!!docusaurus.config
|
||||
!!site.config
|
||||
name:"ThreeFold DePIN Tech"
|
||||
description:"ThreeFold is laying the foundation for a geo aware Web 4, the next generation of the Internet."
|
||||
tagline:"Geo Aware Internet Platform"
|
||||
@@ -6,95 +6,95 @@
|
||||
image:"img/tf_graph.png"
|
||||
copyright:"ThreeFold"
|
||||
|
||||
!!docusaurus.navbar
|
||||
!!site.menu
|
||||
title:"ThreeFold DePIN Tech"
|
||||
logo_alt:"ThreeFold Logo"
|
||||
logo_src:"img/logo.svg"
|
||||
logo_src_dark:"img/new_logo_tft.png"
|
||||
|
||||
!!docusaurus.navbar_item
|
||||
!!site.menu_item
|
||||
label:"ThreeFold.io"
|
||||
href:"https://threefold.io"
|
||||
position:"right"
|
||||
|
||||
!!docusaurus.navbar_item
|
||||
!!site.menu_item
|
||||
label:"Mycelium Network"
|
||||
href:"https://mycelium.threefold.io/"
|
||||
position:"right"
|
||||
|
||||
!!docusaurus.navbar_item
|
||||
!!site.menu_item
|
||||
label:"AI Box"
|
||||
href:"https://aibox.threefold.io/"
|
||||
position:"right"
|
||||
|
||||
!!docusaurus.footer
|
||||
!!site.footer
|
||||
style:"dark"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
!!site.footer_item
|
||||
title:"Docs"
|
||||
label:"Introduction"
|
||||
href:"https://docs.threefold.io/docs/introduction"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
!!site.footer_item
|
||||
title:"Docs"
|
||||
label:"Litepaper"
|
||||
href:"https://docs.threefold.io/docs/litepaper/"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
!!site.footer_item
|
||||
title:"Docs"
|
||||
label:"Roadmap"
|
||||
href:"https://docs.threefold.io/docs/roadmap"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
!!site.footer_item
|
||||
title:"Docs"
|
||||
label:"Manual"
|
||||
href:"https://manual.grid.tf/"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
!!site.footer_item
|
||||
title:"Features"
|
||||
label:"Become a Farmer"
|
||||
href:"https://docs.threefold.io/docs/category/become-a-farmer"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
!!site.footer_item
|
||||
title:"Features"
|
||||
label:"Components"
|
||||
href:"https://docs.threefold.io/docs/category/components"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
!!site.footer_item
|
||||
title:"Features"
|
||||
label:"Technology"
|
||||
href:"https://threefold.info/tech/"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
!!site.footer_item
|
||||
title:"Features"
|
||||
label:"Tokenomics"
|
||||
href:"https://docs.threefold.io/docs/tokens/tokenomics"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
!!site.footer_item
|
||||
title:"Web"
|
||||
label:"ThreeFold.io"
|
||||
href:"https://threefold.io"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
!!site.footer_item
|
||||
title:"Web"
|
||||
label:"Dashboard"
|
||||
href:"https://dashboard.grid.tf"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
!!site.footer_item
|
||||
title:"Web"
|
||||
label:"GitHub"
|
||||
href:"https://github.com/threefoldtech/home"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
!!site.footer_item
|
||||
title:"Web"
|
||||
label:"Mycelium Network"
|
||||
href:"https://mycelium.threefold.io/"
|
||||
|
||||
!!docusaurus.footer_item
|
||||
!!site.footer_item
|
||||
title:"Web"
|
||||
label:"AI Box"
|
||||
href:"https://www2.aibox.threefold.io/"
|
||||
|
||||
!!docusaurus.collections
|
||||
!!site.collections
|
||||
url:"https://github.com/example/external-docs"
|
||||
replace:"PROJECT_NAME:My Project, VERSION:1.0.0"
|
||||
18
lib/web/site/example/site.heroscript
Normal file
18
lib/web/site/example/site.heroscript
Normal file
@@ -0,0 +1,18 @@
|
||||
!!site.page name:intro
|
||||
description:"ThreeFold is laying the foundation for a geo aware Web 4, the next generation of the Internet."
|
||||
|
||||
//next is example where we use all properties, folder is where the page is located, prio is the order of the page, if not used the filled in from order in which we parse this config file
|
||||
!!site.page name:mycelium draft:true folder:"/specs/components" prio:4
|
||||
content:"the page content itself, only for small pages"
|
||||
title:"Mycelium as Title"
|
||||
description:"..."
|
||||
|
||||
!!site.page name:fungistor folder:"/specs/components" prio:1
|
||||
src:"mycollection:mycelium.md"
|
||||
title:"fungistor as Title"
|
||||
description:"...."
|
||||
|
||||
!!site.page name:fungistor folder:"/specs/components" prio:1
|
||||
src:"mycollection:mycelium" //can be without .md
|
||||
title:"fungistor as Title"
|
||||
description:"..."
|
||||
@@ -1,106 +1,49 @@
|
||||
module docusaurus
|
||||
module site
|
||||
|
||||
import freeflowuniverse.herolib.core.playbook { PlayBook }
|
||||
import time
|
||||
import os
|
||||
|
||||
|
||||
@[params]
|
||||
pub struct PlayArgs {
|
||||
pub mut:
|
||||
heroscript string // if filled in then playbook will be made out of it
|
||||
heroscript_path string // path to a file containing heroscript
|
||||
plbook ?PlayBook
|
||||
reset bool
|
||||
heroscript string // if filled in then plbook will be made out of it
|
||||
plbook ?playbook.PlayBook
|
||||
reset bool
|
||||
}
|
||||
|
||||
// Process the heroscript and return a filled Config object
|
||||
pub fn play(args_ PlayArgs) !Config {
|
||||
mut heroscript_text := args_.heroscript
|
||||
pub fn play(args_ PlayArgs) ! {
|
||||
|
||||
// If heroscript_path is provided, read the script from the file
|
||||
if args_.heroscript_path != '' && heroscript_text == '' {
|
||||
heroscript_text = os.read_file(args_.heroscript_path) or {
|
||||
return error('Failed to read heroscript from ${args_.heroscript_path}: ${err}')
|
||||
}
|
||||
}
|
||||
|
||||
// If no heroscript is provided, return an empty config
|
||||
if heroscript_text == '' && args_.plbook == none {
|
||||
return Config{}
|
||||
}
|
||||
|
||||
// Create playbook from the heroscript text
|
||||
mut plbook := if pb := args_.plbook {
|
||||
pb
|
||||
} else {
|
||||
playbook.new(text: heroscript_text)!
|
||||
}
|
||||
mut args := args_
|
||||
mut plbook := args.plbook or { playbook.new(text: args.heroscript)! }
|
||||
|
||||
mut config := Config{}
|
||||
|
||||
play_config(mut plbook, mut config)!
|
||||
play_config_meta(mut plbook, mut config)!
|
||||
play_ssh_connection(mut plbook, mut config)!
|
||||
play_import_source(mut plbook, mut config)!
|
||||
play_build_dest(mut plbook, mut config)!
|
||||
play_navbar(mut plbook, mut config)!
|
||||
play_collections(mut plbook, mut config)!
|
||||
play_menu(mut plbook, mut config)!
|
||||
play_footer(mut plbook, mut config)!
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
fn play_config(mut plbook PlayBook, mut config Config) ! {
|
||||
config_actions := plbook.find(filter: 'docusaurus.config')!
|
||||
config_actions := plbook.find(filter: 'site.config')!
|
||||
for action in config_actions {
|
||||
mut p := action.params
|
||||
// Get optional name parameter or use base_url as fallback
|
||||
name := p.get_default('name', 'docusaurus-site')!
|
||||
|
||||
config.main = Main{
|
||||
name: name
|
||||
title: p.get_default('title', 'Documentation Site')!
|
||||
tagline: p.get_default('tagline', 'Your awesome documentation')!
|
||||
favicon: p.get_default('favicon', 'img/favicon.png')!
|
||||
url: p.get_default('url', 'https://docs.example.com')!
|
||||
url_home: p.get_default('url_home', 'docs/')!
|
||||
base_url: p.get_default('base_url', '/')!
|
||||
image: p.get_default('image', 'img/hero.png')!
|
||||
copyright: p.get_default('copyright', '© ' + time.now().year.str() +
|
||||
' Example Organization')!
|
||||
}
|
||||
config.name = p.get_default('name', 'site')!
|
||||
config.title = p.get_default('title', 'Documentation Site')!
|
||||
config.description = p.get_default('description', 'Comprehensive documentation built with Docusaurus.')!
|
||||
config.tagline = p.get_default('tagline', 'Your awesome documentation')!
|
||||
config.favicon = p.get_default('favicon', 'img/favicon.png')!
|
||||
config.image = p.get_default('image', 'img/tf_graph.png')!
|
||||
config.copyright = p.get_default('copyright', '© ' + time.now().year.str() + ' Example Organization')!
|
||||
}
|
||||
}
|
||||
|
||||
fn play_config_meta(mut plbook PlayBook, mut config Config) ! {
|
||||
meta_actions := plbook.find(filter: 'docusaurus.config_meta')!
|
||||
for action in meta_actions {
|
||||
mut p := action.params
|
||||
config.main.metadata = MainMetadata{
|
||||
description: p.get_default('description', 'Comprehensive documentation built with Docusaurus.')!
|
||||
image: p.get_default('image', 'https://docs.example.com/img/social-card.png')!
|
||||
title: p.get_default('title', 'Documentation | ' + config.main.title)!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn play_ssh_connection(mut plbook PlayBook, mut config Config) ! {
|
||||
ssh_actions := plbook.find(filter: 'docusaurus.ssh_connection')!
|
||||
for action in ssh_actions {
|
||||
mut p := action.params
|
||||
mut ssh := SSHConnection{
|
||||
name: p.get_default('name', 'main')!
|
||||
host: p.get_default('host', 'info.ourworld.tf')!
|
||||
port: p.get_int_default('port', 21)!
|
||||
login: p.get_default('login', 'root')!
|
||||
key_path: p.get_default('key_path', '')!
|
||||
key: p.get_default('key', '')!
|
||||
}
|
||||
config.ssh_connections << ssh
|
||||
}
|
||||
}
|
||||
|
||||
fn play_import_source(mut plbook PlayBook, mut config Config) ! {
|
||||
import_actions := plbook.find(filter: 'docusaurus.import_source')!
|
||||
fn play_collections(mut plbook PlayBook, mut config Config) ! {
|
||||
import_actions := plbook.find(filter: 'site.collections')!
|
||||
for action in import_actions {
|
||||
mut p := action.params
|
||||
mut replace_map := map[string]string{}
|
||||
@@ -113,55 +56,44 @@ fn play_import_source(mut plbook PlayBook, mut config Config) ! {
|
||||
}
|
||||
}
|
||||
}
|
||||
mut import_ := ImportSource{
|
||||
mut import_ := CollectionsImport{
|
||||
url: p.get('url')!
|
||||
path: p.get_default('path', '')!
|
||||
dest: p.get_default('dest', '')!
|
||||
replace: replace_map
|
||||
visible: p.get_default_false('visible')
|
||||
}
|
||||
config.import_sources << import_
|
||||
config.import_collections << import_
|
||||
}
|
||||
}
|
||||
|
||||
fn play_build_dest(mut plbook PlayBook, mut config Config) ! {
|
||||
build_actions := plbook.find(filter: 'docusaurus.build_dest')!
|
||||
for action in build_actions {
|
||||
fn play_menu(mut plbook PlayBook, mut config Config) ! {
|
||||
menu_actions := plbook.find(filter: 'site.menu')!
|
||||
for action in menu_actions {
|
||||
mut p := action.params
|
||||
mut build := BuildDest{
|
||||
ssh_name: p.get_default('ssh_name', 'main')!
|
||||
path: p.get_default('path', '')!
|
||||
}
|
||||
config.build_destinations << build
|
||||
}
|
||||
}
|
||||
|
||||
fn play_navbar(mut plbook PlayBook, mut config Config) ! {
|
||||
navbar_actions := plbook.find(filter: 'docusaurus.navbar')!
|
||||
for action in navbar_actions {
|
||||
mut p := action.params
|
||||
config.navbar.title = p.get_default('title', config.main.title)!
|
||||
config.menu.title = p.get_default('title', config.title)!
|
||||
}
|
||||
|
||||
navbar_item_actions := plbook.find(filter: 'docusaurus.navbar_item')!
|
||||
for action in navbar_item_actions {
|
||||
menu_item_actions := plbook.find(filter: 'site.menu_item')!
|
||||
for action in menu_item_actions {
|
||||
mut p := action.params
|
||||
mut item := NavbarItem{
|
||||
mut item := MenuItem{
|
||||
label: p.get_default('label', 'Documentation')!
|
||||
href: p.get_default('href', '/docs')!
|
||||
position: p.get_default('position', 'right')!
|
||||
}
|
||||
config.navbar.items << item
|
||||
config.menu.items << item
|
||||
}
|
||||
}
|
||||
|
||||
fn play_footer(mut plbook PlayBook, mut config Config) ! {
|
||||
footer_actions := plbook.find(filter: 'docusaurus.footer')!
|
||||
footer_actions := plbook.find(filter: 'site.footer')!
|
||||
for action in footer_actions {
|
||||
mut p := action.params
|
||||
config.footer.style = p.get_default('style', 'dark')!
|
||||
}
|
||||
|
||||
footer_item_actions := plbook.find(filter: 'docusaurus.footer_item')!
|
||||
footer_item_actions := plbook.find(filter: 'site.footer_item')!
|
||||
mut links_map := map[string][]FooterItem{}
|
||||
|
||||
for action in footer_item_actions {
|
||||
|
||||
0
lib/web/site/readme.md
Normal file
0
lib/web/site/readme.md
Normal file
Reference in New Issue
Block a user