This commit is contained in:
2025-05-04 06:53:12 +03:00
parent a066db6624
commit 3682ef2420
12 changed files with 873 additions and 41 deletions

View File

@@ -0,0 +1,10 @@
#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.web.docusaurus
// Create a new docusaurus factory
mut docs := docusaurus.new(
build_path: '/tmp/docusaurus_build'
)!

Binary file not shown.

View File

@@ -0,0 +1,239 @@
#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.web.docusaurus
import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.core.playbook
import os
fn main() {
println('Starting Docusaurus Example with HeroScript')
// Define the HeroScript that configures our Docusaurus site
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.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"
!!docusaurus.navbar
title:"My Project"
!!docusaurus.navbar_item
label:"Documentation"
href:"/docs"
position:"left"
!!docusaurus.navbar_item
label:"API"
href:"/api"
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:"Documentation"
label:"API Reference"
to:"/api"
!!docusaurus.footer_item
title:"Community"
label:"GitHub"
href:"https://github.com/example/repo"
!!docusaurus.footer_item
title:"Community"
label:"Discord"
href:"https://discord.gg/example"
!!docusaurus.footer_item
title:"More"
label:"Blog"
href:"https://blog.example.com"
!!docusaurus.import_source
url:"https://github.com/example/external-docs"
dest:"external"
replace:"PROJECT_NAME:My Project, VERSION:1.0.0"
'
mut docs := docusaurus.new(
build_path: os.join_path(os.home_dir(), 'hero/var/docusaurus_demo1')
update: true // Update the templates
heroscript: hero_script
) or {
eprintln('Error creating docusaurus factory with inline script: ${err}')
exit(1)
}
// Create a site directory if it doesn't exist
site_path := os.join_path(os.home_dir(), 'hero/var/docusaurus_demo_src')
os.mkdir_all(site_path) or {
eprintln('Error creating site directory: ${err}')
exit(1)
}
// Get or create a site using the factory
println('Creating site...')
mut site := docs.get(
name: 'my-documentation'
path: site_path
init: true // Create if it doesn't exist
// Note: The site will use the config from the previously processed HeroScript
) or {
eprintln('Error creating site: ${err}')
exit(1)
}
// Generate a sample markdown file for the docs
println('Creating sample markdown content...')
mut docs_dir := pathlib.get_dir(path: os.join_path(site_path, 'docs'), create: true) or {
eprintln('Error creating docs directory: ${err}')
exit(1)
}
// Create intro.md file
mut intro_file := docs_dir.file_get_new('intro.md') or {
eprintln('Error creating intro file: ${err}')
exit(1)
}
intro_content := '---
title: Introduction
slug: /
sidebar_position: 1
---
# Welcome to My Documentation
This is a sample documentation site created with Docusaurus and HeroLib V using HeroScript configuration.
## Features
- Easy to use
- Markdown support
- Customizable
- Search functionality
## Getting Started
Follow these steps to get started:
1. Installation
2. Configuration
3. Adding content
4. Deployment
'
intro_file.write(intro_content) or {
eprintln('Error writing to intro file: ${err}')
exit(1)
}
// Create quick-start.md file
mut quickstart_file := docs_dir.file_get_new('quick-start.md') or {
eprintln('Error creating quickstart file: ${err}')
exit(1)
}
quickstart_content := '---
title: Quick Start
sidebar_position: 2
---
# Quick Start Guide
This guide will help you get up and running quickly.
## Installation
```bash
$ npm install my-project
```
## Basic Usage
```javascript
import { myFunction } from "my-project";
// Use the function
const result = myFunction();
console.log(result);
```
'
quickstart_file.write(quickstart_content) or {
eprintln('Error writing to quickstart file: ${err}')
exit(1)
}
// Generate the site
println('Generating site...')
site.generate() or {
eprintln('Error generating site: ${err}')
exit(1)
}
println('Site generated successfully!')
// Choose which operation to perform:
// Option 1: Run in development mode
// This will start a development server in a screen session
println('Starting development server...')
site.dev() or {
eprintln('Error starting development server: ${err}')
exit(1)
}
// Option 2: Build for production (uncomment to use)
/*
println('Building site for production...')
site.build() or {
eprintln('Error building site: ${err}')
exit(1)
}
println('Site built successfully!')
*/
// Option 3: Build and publish to the remote server (uncomment to use)
/*
println('Building and publishing site...')
site.build_publish() or {
eprintln('Error publishing site: ${err}')
exit(1)
}
println('Site published successfully!')
*/
}

View File

@@ -3,7 +3,8 @@ module docusaurus
import os
import strings
pub fn (mut site DocSite) clean(args ErrorArgs) ! {
// clean removes temporary files and build artifacts from the site directory
pub fn (mut site DocSite) clean(args ...ErrorArgs) ! {
toclean := '
/node_modules

View File

@@ -0,0 +1,52 @@
# Docusaurus Library Code Review
This document outlines potential issues and suggested improvements for the Docusaurus library.
## Critical Issues
1. **Unexpected Program Termination**
- In `dsite.v` line 205, there's an `exit(0)` call in the `process_md` method.
- This will terminate the entire program unexpectedly when processing markdown files.
- **Recommendation**: Remove the `exit(0)` call and allow the function to complete normally.
2. **Function Signature Mismatch**
- In `clean.v` line 6, the `clean` method requires an `ErrorArgs` parameter: `pub fn (mut site DocSite) clean(args ErrorArgs) !`
- In `dsite.v` line 62, the function is called without arguments: `s.clean()!`
- **Recommendation**: Either make the parameter optional or update all calling code to provide the required argument.
## General Improvements
1. **Incomplete Example**
- The example file `docusaurus_example.vsh` is incomplete, only showing initialization.
- **Recommendation**: Complete the example with site creation, configuration, and building/development operations.
2. **Commented Code**
- There are several instances of commented-out code, such as in the `factory.v` file.
- **Recommendation**: Either complete the implementation of these features or remove the commented code for clarity.
3. **Debug Statements**
- The `process_md` method contains debug print statements (`println(myfm)` and `println(mymd.markdown()!)`)
- **Recommendation**: Replace with a proper logging system or remove if not needed for production.
4. **Error Handling**
- Some error handling could be improved with more descriptive error messages.
- **Recommendation**: Add more context to error messages, especially in file operations.
5. **Documentation**
- While the config structures have some documentation, many methods lack proper documentation.
- **Recommendation**: Add proper V-doc style comments to all public methods and structures.
## Architectural Suggestions
1. **Configuration Management**
- Consider providing a more fluent API for configuration, rather than requiring JSON file manipulation.
2. **Dependency Injection**
- The factory pattern is well-implemented, but consider making dependencies more explicit.
3. **Testing**
- No tests were found in the codebase.
- **Recommendation**: Add unit tests for critical functions.
4. **Logging**
- Replace direct console output with a proper logging system that can be configured based on environment.

View File

@@ -199,10 +199,10 @@ fn (mut site DocSite) process_md(mut path pathlib.Path, args MyImport) ! {
if !args.visible {
myfm.args['draft'] = 'true'
}
println(myfm)
println(mymd.markdown()!)
// println(myfm)
// println(mymd.markdown()!)
mydesto.write(mymd.markdown()!)!
exit(0)
// Note: exit(0) was removed to prevent unexpected program termination
}
fn (mut site DocSite) template_install() ! {

View File

@@ -50,9 +50,13 @@ pub fn (mut f DocusaurusFactory) get(args_ DSiteGetArgs) !&DocSite {
)!
mut template_path := r.patho()!
// First, check if the new site args provides a configuration that can be written instead of template cfg dir
// First, check if the new site args provides a configuration
if cfg := args.config {
// Use the provided config
cfg.write('${args.path}/cfg')!
} else if f.config.main.title != '' {
// Use the factory's config from heroscript if available
f.config.write('${args.path}/cfg')!
} else {
// Then ensure cfg directory exists in src,
if !os.exists('${args.path}/cfg') {
@@ -68,8 +72,23 @@ pub fn (mut f DocusaurusFactory) get(args_ DSiteGetArgs) !&DocSite {
if !os.exists('${args.path}/docs') {
if args.init {
mut template_cfg := template_path.dir_get('docs')!
template_cfg.copy(dest: '${args.path}/docs')!
// Create docs directory if it doesn't exist in template or site
os.mkdir_all('${args.path}/docs')!
// Create a default docs/intro.md file
intro_content := '---
title: Introduction
slug: /
sidebar_position: 1
---
# Introduction
Welcome to the documentation site.
This is a default page created by the Docusaurus site generator.
'
os.write_file('${args.path}/docs/intro.md', intro_content)!
} else {
return error("Can't find docs dir in chosen docusaurus location: ${args.path}")
}

View File

@@ -14,6 +14,7 @@ pub mut:
path_build pathlib.Path
// path_publish pathlib.Path
args DocusaurusArgs
config Config // Stores configuration from HeroScript if provided
}
@[params]
@@ -23,6 +24,8 @@ pub mut:
build_path string
production bool
update bool
heroscript string
heroscript_path string
}
pub fn new(args_ DocusaurusArgs) !&DocusaurusFactory {
@@ -32,13 +35,24 @@ pub fn new(args_ DocusaurusArgs) !&DocusaurusFactory {
}
// if args.publish_path == ""{
// args.publish_path = "${os.home_dir()}/hero/var/docusaurus/publish"
// }
// }
// Create the factory instance
mut ds := &DocusaurusFactory{
args: args_
path_build: pathlib.get_dir(path: args.build_path, create: true)!
// path_publish: pathlib.get_dir(path: args_.publish_path, create: true)!
}
// Process HeroScript if provided
if args.heroscript != '' || args.heroscript_path != '' {
// Use the play function to process the HeroScript
ds.config = play(
heroscript: args.heroscript
heroscript_path: args.heroscript_path
)!
}
ds.template_install(install: true, template_update: args.update, delete: true)!
return ds

View File

@@ -1,18 +1,41 @@
module docusaurus
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
plbook ?PlayBook
reset bool
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
}
// Process the heroscript and return a filled Config object
pub fn play(args_ PlayArgs) ! {
mut plbook := playbook.new(text: args_.heroscript)!
pub fn play(args_ PlayArgs) !Config {
mut heroscript_text := args_.heroscript
// 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 config := Config{}
play_config(mut plbook, mut config)!
@@ -22,20 +45,27 @@ pub fn play(args_ PlayArgs) ! {
play_build_dest(mut plbook, mut config)!
play_navbar(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')!
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{
title: p.get_default('title', 'Internet Geek')!
tagline: p.get_default('tagline', 'Internet Geek')!
favicon: p.get_default('favicon', 'img/favicon.png')!
url: p.get_default('url', 'https://friends.threefold.info')!
url_home: p.get_default('url_home', 'docs/')!
base_url: p.get_default('base_url', '/testsite/')!
image: p.get_default('image', 'img/tf_graph.png')!
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')!
}
}
}
@@ -45,9 +75,9 @@ fn play_config_meta(mut plbook PlayBook, mut config Config) ! {
for action in meta_actions {
mut p := action.params
config.main.metadata = MainMetadata{
description: p.get_default('description', 'ThreeFold is laying the foundation for a geo aware Web 4, the next generation of the Internet.')!
image: p.get_default('image', 'https://threefold.info/something/img/tf_graph.png')!
title: p.get_default('title', 'ThreeFold Technology Vision')!
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)!
}
}
}
@@ -108,15 +138,15 @@ 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', 'Chief Executive Geek')!
config.navbar.title = p.get_default('title', config.main.title)!
}
navbar_item_actions := plbook.find(filter: 'docusaurus.navbar_item')!
for action in navbar_item_actions {
mut p := action.params
mut item := NavbarItem{
label: p.get_default('label', 'ThreeFold Technology')!
href: p.get_default('href', 'https://threefold.info/tech')!
label: p.get_default('label', 'Documentation')!
href: p.get_default('href', '/docs')!
position: p.get_default('position', 'right')!
}
config.navbar.items << item

View File

@@ -0,0 +1,226 @@
# Docusaurus Library for V
A V language library for creating, configuring, and managing [Docusaurus](https://docusaurus.io/) documentation sites with minimal effort.
## Overview
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 structured JSON or 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
## Features
- **Simple API**: Create and manage Docusaurus sites with a few lines of V code
- **Flexible Configuration**: Configure sites using JSON files or programmatically
- **Development Mode**: Built-in development server with file watching
- **Remote Deployment**: Push to remote servers via SSH
- **Content Import**: Import content from Git repositories
- **Template Management**: Uses standard Docusaurus templates with custom configuration
## Installation
The library is part of the HeroLib package and can be imported as follows:
```v
import freeflowuniverse.herolib.web.docusaurus
```
## Usage
### Basic Example
```v
import freeflowuniverse.herolib.web.docusaurus
// Create a new docusaurus factory
mut docs := docusaurus.new(
build_path: '~/docusaurus_projects' // Optional, defaults to ~/hero/var/docusaurus
)!
// Get or create a site
mut site := docs.get(
name: 'my-docs',
path: '~/my-docs-source',
init: true // Create if doesn't exist
)!
// Run development server
site.dev()!
// Or build for production
// site.build()!
// Or build and publish
// site.build_publish()!
```
### Configuration
Configuration is done via JSON files in the `cfg` directory of your site:
- `main.json`: Main site configuration (title, URL, metadata, etc.)
- `navbar.json`: Navigation bar configuration
- `footer.json`: Footer configuration
Example `main.json`:
```json
{
"title": "My Documentation",
"tagline": "Documentation Made Easy",
"favicon": "img/favicon.png",
"url": "https://docs.example.com",
"url_home": "docs/",
"baseUrl": "/",
"image": "img/logo.png",
"metadata": {
"description": "Comprehensive documentation for my project",
"image": "https://docs.example.com/img/logo.png",
"title": "My Documentation"
},
"buildDest": ["user@server:/path/to/deployment"],
"buildDestDev": ["user@server:/path/to/dev-deployment"]
}
```
### Directory Structure
A typical Docusaurus site managed by this library has the following structure:
```
my-site/
├── cfg/
│ ├── main.json
│ ├── navbar.json
│ └── footer.json
├── docs/
│ ├── intro.md
│ └── ...
├── src/
│ └── ...
└── static/
└── img/
└── ...
```
### Development Workflow
1. Create a new site using `docs.get()`
2. Configure your site via JSON files or programmatically
3. Run `site.dev()` to start development server
4. Edit files in the `docs` directory
5. When ready, run `site.build()` or `site.build_publish()` to deploy
## 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. Configure the deployment destinations in `main.json`:
```json
"buildDest": ["user@server:/path/to/deployment"],
"buildDestDev": ["user@server:/path/to/dev-deployment"]
```
### Content Import
You can import content from Git repositories:
```json
"import": [
{
"url": "https://github.com/username/repo",
"dest": "external-docs",
"visible": true
}
]
```
## Advanced Usage with HeroScript
You can configure your Docusaurus site using HeroScript in multiple ways:
### Option 1: Provide HeroScript directly to the factory
```v
import freeflowuniverse.herolib.web.docusaurus
// Create a factory with inline HeroScript
mut docs := docusaurus.new(
build_path: '~/docusaurus_sites'
heroscript: '
!!docusaurus.config
name:"my-docs"
title:"My Documentation"
tagline:"Documentation Made Easy"
url:"https://docs.example.com"
base_url:"/"
!!docusaurus.navbar
title:"My Project"
!!docusaurus.navbar_item
label:"GitHub"
href:"https://github.com/username/repo"
position:"right"
'
)!
```
### Option 2: Load HeroScript from a file
```v
import freeflowuniverse.herolib.web.docusaurus
// Create a factory using HeroScript from a file
mut docs := docusaurus.new(
build_path: '~/docusaurus_sites'
heroscript_path: '~/my_docusaurus_config.hero'
)!
```
### Option 3: Process HeroScript separately
```v
import freeflowuniverse.herolib.web.docusaurus
mut script := '
!!docusaurus.config
title:"My Documentation"
tagline:"Documentation Made Easy"
url:"https://docs.example.com"
base_url:"/"
!!docusaurus.navbar
title:"My Project"
!!docusaurus.navbar_item
label:"GitHub"
href:"https://github.com/username/repo"
position:"right"
'
// Process the HeroScript to get a Config object
mut config := docusaurus.play(heroscript: script)!
// Use the config when creating a site
mut site := docs.get(
name: 'my-site',
path: '~/my-site-source',
config: config
)!
```
## License
This library is part of the HeroLib project and follows its licensing terms.

View File

@@ -3,7 +3,10 @@ module docusaurus
import freeflowuniverse.herolib.develop.gittools
import freeflowuniverse.herolib.osal
import freeflowuniverse.herolib.installers.web.bun
import freeflowuniverse.herolib.core.pathlib
import json
import os
import time
@[params]
struct TemplateInstallArgs {
@@ -21,24 +24,17 @@ fn (mut self DocusaurusFactory) template_install(args TemplateInstallArgs) ! {
)!
mut template_path := r.patho()!
for item in ['package.json', 'sidebars.ts', 'tsconfig.json'] {
mut aa := template_path.file_get(item)!
aa.copy(dest: '${self.path_build.path}/${item}')!
}
// always start from template first
// always start from template first for static assets and source files
for item in ['src', 'static'] {
mut aa := template_path.dir_get(item)!
aa.copy(dest: '${self.path_build.path}/${item}', delete: args.delete)!
}
for item in ['package.json', 'sidebars.ts', 'tsconfig.json', 'docusaurus.config.ts'] {
src_path := os.join_path(template_path.path, item)
dest_path := os.join_path(self.path_build.path, item)
os.cp(src_path, dest_path) or {
return error('Failed to copy ${item} to build path: ${err}')
}
}
// Generate config files dynamically from config
self.generate_package_json()!
self.generate_tsconfig_json()!
self.generate_sidebars_ts()!
self.generate_docusaurus_config_ts()!
if args.install {
// install bun
@@ -55,6 +51,251 @@ fn (mut self DocusaurusFactory) template_install(args TemplateInstallArgs) ! {
)!
}
mut aa := template_path.dir_get('docs') or { return }
aa.delete()!
// Only try to delete docs if it exists in the template
if os.exists(os.join_path(template_path.path, 'docs')) {
mut aa := template_path.dir_get('docs')!
aa.delete()!
}
}
// Generate package.json based on the configuration
fn (mut self DocusaurusFactory) generate_package_json() ! {
// Build package.json content as a structured JSON string
mut name := 'docusaurus-site'
if self.config.main.name != '' {
name = self.config.main.name
} else if self.config.navbar.title != '' {
name = self.config.navbar.title.to_lower().replace(' ', '-')
}
// Create the JSON structure manually
package_json := '{
"name": "${name}",
"version": "0.0.1",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"typecheck": "tsc"
},
"dependencies": {
"@docusaurus/core": "^3.1.0",
"@docusaurus/preset-classic": "^3.1.0",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.1.0",
"@docusaurus/tsconfig": "^3.1.0",
"@docusaurus/types": "^3.1.0",
"typescript": "^5.2.2"
},
"browserslist": {
"production": [">0.5%", "not dead", "not op_mini all"],
"development": ["last 1 chrome version", "last 1 firefox version", "last 1 safari version"]
},
"engines": {
"node": ">=18.0"
}
}'
// Write to file
mut package_file := pathlib.get_file(path: os.join_path(self.path_build.path, 'package.json'), create: true)!
package_file.write(package_json)!
}
// Generate tsconfig.json based on the configuration
fn (mut self DocusaurusFactory) generate_tsconfig_json() ! {
// Create tsconfig.json as a manual JSON string
tsconfig_json := '{
"extends": "@docusaurus/tsconfig",
"compilerOptions": {
"baseUrl": ".",
"resolveJsonModule": true
},
"include": ["src/**/*", "docusaurus.config.ts"]
}'
// Write to file
mut tsconfig_file := pathlib.get_file(path: os.join_path(self.path_build.path, 'tsconfig.json'), create: true)!
tsconfig_file.write(tsconfig_json)!
}
// Generate sidebars.ts based on the configuration
fn (mut self DocusaurusFactory) generate_sidebars_ts() ! {
// Simple default sidebar structure
sidebar_content := "import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';
/**
* Creating a sidebar enables you to:
- create an ordered group of docs
- render a sidebar for each doc of that group
- provide next/previous navigation
The sidebars can be generated from the filesystem, or explicitly defined here.
Create as many sidebars as you want.
*/
const sidebars: SidebarsConfig = {
// By default, Docusaurus generates a sidebar from the docs folder structure
tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
};
export default sidebars;
"
mut sidebars_file := pathlib.get_file(path: os.join_path(self.path_build.path, 'sidebars.ts'), create: true)!
sidebars_file.write(sidebar_content)!
}
// Generate docusaurus.config.ts based on the configuration
fn (mut self DocusaurusFactory) generate_docusaurus_config_ts() ! {
// Use config values with fallbacks
title := if self.config.main.title != '' { self.config.main.title } else { 'Docusaurus Site' }
tagline := if self.config.main.tagline != '' { self.config.main.tagline } else { 'Documentation Site' }
url := if self.config.main.url != '' { self.config.main.url } else { 'https://example.com' }
base_url := if self.config.main.base_url != '' { self.config.main.base_url } else { '/' }
favicon := if self.config.main.favicon != '' { self.config.main.favicon } else { 'img/favicon.png' }
// Format navbar items from config
mut navbar_items := []string{}
for item in self.config.navbar.items {
navbar_items << "{
label: '${item.label}',
href: '${item.href}',
position: '${item.position}'
}"
}
navbar_items_str := navbar_items.join(',\n ')
// Generate footer links if available
mut footer_links := []string{}
for link in self.config.footer.links {
mut items := []string{}
for item in link.items {
mut item_str := "{"
if item.label != '' {
item_str += "label: '${item.label}', "
}
// Ensure only one of 'to', 'href', or 'html' is used
// Priority: href > to > html
if item.href != '' {
item_str += "href: '${item.href}'"
} else if item.to != '' {
item_str += "to: '${item.to}'"
} else {
// Default to linking to docs if nothing specified
item_str += "to: '/docs'"
}
item_str += "}"
items << item_str
}
footer_links << "{
title: '${link.title}',
items: [
${items.join(',\n ')}
]
}"
}
footer_links_str := footer_links.join(',\n ')
// Year for copyright
year := time.now().year.str()
copyright := if self.config.main.copyright != '' {
self.config.main.copyright
} else {
"Copyright © ${year} ${title}"
}
// Construct the full config file content
config_content := "import {themes as prismThemes} from 'prism-react-renderer';
import type {Config} from '@docusaurus/types';
import type * as Preset from '@docusaurus/preset-classic';
const config: Config = {
title: '${title}',
tagline: '${tagline}',
favicon: '${favicon}',
// Set the production url of your site here
url: '${url}',
// Set the /<baseUrl>/ pathname under which your site is served
// For GitHub pages deployment, it is often '/<projectName>/'
baseUrl: '${base_url}',
// GitHub pages deployment config.
// If you aren't using GitHub pages, you don't need these.
organizationName: 'freeflowuniverse', // Usually your GitHub org/user name.
projectName: '${self.config.main.name}', // Usually your repo name.
onBrokenLinks: 'warn',
onBrokenMarkdownLinks: 'warn',
// Enable for i18n
// i18n: {
// defaultLocale: 'en',
// locales: ['en'],
// },
presets: [
[
'classic',
{
docs: {
sidebarPath: './sidebars.ts',
},
theme: {
customCss: './src/css/custom.css',
},
} satisfies Preset.Options,
],
],
themeConfig: {
// Replace with your project's social card
image: 'img/docusaurus-social-card.jpg',
navbar: {
title: '${self.config.navbar.title}',
logo: {
alt: 'Logo',
src: 'img/logo.svg',
},
items: [
${navbar_items_str}
],
},
footer: {
style: '${self.config.footer.style}',
links: [
${footer_links_str}
],
copyright: '${copyright}',
},
prism: {
theme: prismThemes.github,
darkTheme: prismThemes.dracula,
},
} satisfies Preset.ThemeConfig,
};
export default config;
"
mut config_file := pathlib.get_file(path: os.join_path(self.path_build.path, 'docusaurus.config.ts'), create: true)!
config_file.write(config_content)!
}