This commit is contained in:
2025-05-19 07:04:20 +04:00
parent 46898112f5
commit 49542b4bff
6 changed files with 90 additions and 379 deletions

View File

@@ -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"
```

View File

@@ -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

View File

@@ -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"

View 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:"..."

View File

@@ -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
View File