This commit is contained in:
2025-07-30 18:51:29 +02:00
parent 1cb6c486df
commit 14d8d5af8d
14 changed files with 203 additions and 241 deletions

View File

@@ -0,0 +1,44 @@
## how to remember clients, installers as a global
the following is a good pragmatic way to remember clients, installers as a global, use it as best practice.
```vmodule docsite
module docsite
import freeflowuniverse.herolib.core.texttools
__global (
siteconfigs map[string]&SiteConfig
)
@[params]
pub struct FactoryArgs {
pub mut:
name string = "default"
}
pub fn new(args FactoryArgs) !&SiteConfig {
name := texttools.name_fix(args.name)
siteconfigs[name] = &SiteConfig{
name: name
}
return get(name:name)!
}
pub fn get(args FactoryArgs) !&SiteConfig {
name := texttools.name_fix(args.name)
mut sc := siteconfigs[name] or {
return error('siteconfig with name "${name}" does not exist')
}
return sc
}
pub fn default() !&SiteConfig {
if siteconfigs.len == 0 {
return new(name:'default')!
}
return get()!
}
```

38
lib/web/site/factory.v Normal file
View File

@@ -0,0 +1,38 @@
module site
import freeflowuniverse.herolib.core.texttools
__global (
websites map[string]&Site
)
@[params]
pub struct FactoryArgs {
pub mut:
name string = "default"
}
pub fn new(args FactoryArgs) !&Site {
name := texttools.name_fix(args.name)
websites[name] = &Site{
siteconfig: SiteConfig{
name: name
}
}
return get(name:name)!
}
pub fn get(args FactoryArgs) !&Site {
name := texttools.name_fix(args.name)
mut sc := websites[name] or {
return error('siteconfig with name "${name}" does not exist')
}
return sc
}
pub fn default() !&Site {
if websites.len == 0 {
return new(name:'default')!
}
return get()!
}

View File

@@ -1,32 +1,48 @@
module sitegen
module site
import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.web.doctreeclient
import freeflowuniverse.herolib.data.markdown.tools as markdowntools
import freeflowuniverse.herolib.ui.console
// import freeflowuniverse.herolib.ui.console
import os
pub struct Site {
pub struct SiteGenerator {
pub mut:
name string
siteconfig_name string
path pathlib.Path
client &doctreeclient.DocTreeClient
flat bool // if flat then won't use sitenames as subdir's
}
@[params]
pub struct Page {
pub struct SiteGeneratorArgs {
pub mut:
title string
description string
draft bool
position int
hide_title bool
src string @[required]
path string @[required]
title_nr int
slug string
path string
flat bool // if flat then won't use sitenames as subdir's
}
pub fn (mut site Site) page_add(args_ Page) ! {
// new creates a new siteconfig and stores it in redis, or gets an existing one
pub fn (siteconfig SiteConfig)generate(args SiteGeneratorArgs) ! {
mut path := args.path
if path == '' {
path = '${os.home_dir()}/hero/var/sitegen'
}
mut factory := SiteGenerator{
path: pathlib.get_dir(path: path, create: true)!
client: doctreeclient.new()!
flat: args.flat
}
for section in siteconfig.sections {
factory.section_generate(section)!
}
for page in siteconfig.pages {
factory.page_generate(page)!
}
}
fn (mut site SiteGenerator) page_generate(args_ Page) ! {
mut args := args_
mut content := ['---']
@@ -113,15 +129,7 @@ pub fn (mut site Site) page_add(args_ Page) ! {
}
}
@[params]
pub struct Section {
pub mut:
position int
path string
label string
}
pub fn (mut site Site) section_add(args_ Section) ! {
fn (mut site SiteGenerator) section_generate(args_ Section) ! {
mut args := args_
mut c := '{

View File

@@ -1,4 +1,4 @@
module sitegen
module site
import os
import freeflowuniverse.herolib.core.pathlib

32
lib/web/site/model_site.v Normal file
View File

@@ -0,0 +1,32 @@
module site
import os
@[heap]
pub struct Site {
pub mut:
pages []Page
sections []Section
siteconfig SiteConfig
}
pub struct Page {
pub mut:
title string
description string
draft bool
position int
hide_title bool
src string @[required]
path string @[required]
title_nr int
slug string
}
pub struct Section {
pub mut:
position int
path string
label string
}

View File

@@ -1,6 +1,7 @@
module siteconfig
module site
import os
// Combined config structure
@[heap]
pub struct SiteConfig {
pub mut:
name string
@@ -13,7 +14,6 @@ pub mut:
footer Footer
menu Menu
imports []ImportItem
// pages []Page
// New fields for Docusaurus compatibility
url string // The main URL of the site (from !!site.config url:)
@@ -27,19 +27,6 @@ pub mut:
build_dest_dev []BuildDest // Development build destinations (from !!site.build_dest_dev)
}
// pub struct Page {
// pub mut:
// name string
// content string
// title string
// description string
// draft bool
// folder string
// prio int
// src string
// collection string
// }
// Footer config structures
pub struct FooterItem {
pub mut:

View File

@@ -1,82 +1,35 @@
module siteconfig
module site
import freeflowuniverse.herolib.core.playbook { PlayBook }
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.core.base
import time
import json
@[params]
pub struct PlayArgs {
pub mut:
heroscript string
heroscript_path string
plbook ?PlayBook
reset bool
}
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 p := action.params
mut dest := BuildDest{
path: p.get('path')!
ssh_name: p.get_default('ssh_name', '')!
}
config.build_dest << dest
}
}
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 p := action.params
mut dest_dev := BuildDest{
path: p.get('path')!
ssh_name: p.get_default('ssh_name', '')!
}
config.build_dest_dev << dest_dev
}
}
pub fn play(mut plbook PlayBook)! {
mut context := base.context()!
mut redis := context.redis()!
mut website := play_config(mut plbook)!
mut config := &website.siteconfig
mut config := SiteConfig{}
play_import(mut plbook,mut config)!
play_menu(mut plbook,mut config)!
play_footer(mut plbook,mut config)!
play_build_dest(mut plbook,mut config)!
play_build_dest_dev(mut plbook,mut config)!
play_config(mut plbook, mut config)!
play_import(mut plbook, mut config)!
play_menu(mut plbook, mut config)!
play_footer(mut plbook, mut config)!
// play_pages(mut plbook, mut config)!
play_build_dest(mut plbook, mut config)!
play_build_dest_dev(mut plbook, mut config)!
json_config := json.encode(config)
redis.hset('siteconfigs', config.name, json_config)!
redis.set('siteconfigs:current', config.name)!
play_pages(mut plbook,mut website)!
}
fn play_config(mut plbook PlayBook, mut config SiteConfig) ! {
fn play_config(mut plbook PlayBook) !&Site {
mut action := plbook.get(filter: 'site.config')!
mut p:= action.params
name := p.get('name') or {return error("need to specify name in site.config")}
mut context := base.context()!
mut session := context.session_latest()!
mut website := new(name: name)!
mut config:= &website.siteconfig
sitename:=session.env_get('SITENAME') or {""}
mut p := action.params
config.name = p.get_default('name', sitename)!
if config.name == '' {
return error('site name is not set, please set it in the heroscript')
}
config.name = texttools.name_fix(config.name)
config.name = texttools.name_fix(name)
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')!
@@ -96,13 +49,16 @@ fn play_config(mut plbook PlayBook, mut config SiteConfig) ! {
config.meta_title = p_meta.get_default('title', config.title)!
// If 'image' is present in site.config_meta, it overrides. Otherwise, meta_image remains empty or uses site.config.image logic.
config.meta_image = p_meta.get_default('image', config.image)!
// 'description' from site.config_meta can also be parsed here if a separate meta_description field is added to SiteConfig
// 'description' from site.config_meta can also be parsed here if a separate meta_description field is added to
// For now, config.description (from site.config) is used as the primary source or fallback.
return website
}
fn play_import(mut plbook PlayBook, mut config SiteConfig) ! {
import_actions := plbook.find(filter: 'site.import')!
// println('import_actions: ${import_actions}')
for action in import_actions {
mut p := action.params
mut replace_map := map[string]string{}
@@ -167,7 +123,7 @@ fn play_menu(mut plbook PlayBook, mut config SiteConfig) ! {
}
}
fn play_footer(mut plbook PlayBook, mut config SiteConfig) ! {
fn play_footer(mut plbook PlayBook , mut config SiteConfig) ! {
footer_actions := plbook.find(filter: 'site.footer')!
for action in footer_actions {
mut p := action.params
@@ -201,23 +157,27 @@ fn play_footer(mut plbook PlayBook, mut config SiteConfig) ! {
}
}
// fn play_pages(mut plbook PlayBook, mut config SiteConfig) ! {
// page_actions := plbook.find(filter: 'site.page')!
// // println('page_actions: ${page_actions}')
// for action in page_actions {
// mut p := action.params
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 p := action.params
mut dest := BuildDest{
path: p.get('path')!
ssh_name: p.get_default('ssh_name', '')!
}
config.build_dest << dest
}
}
// mut page := Page{
// name: p.get('name')!
// title: p.get_default('title', '')!
// description: p.get_default('description', '')!
// content: p.get_default('content', '')!
// src: p.get_default('src', '')!
// draft: p.get_default_false('draft')
// folder: p.get_default('folder', '')!
// prio: p.get_int_default('prio', 0)!
// }
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 p := action.params
mut dest_dev := BuildDest{
path: p.get('path')!
ssh_name: p.get_default('ssh_name', '')!
}
config.build_dest_dev << dest_dev
}
}
// config.pages << page
// }
// }

View File

@@ -1,14 +1,11 @@
module sitegen
module site
import freeflowuniverse.herolib.core.playbook { PlayBook }
import freeflowuniverse.herolib.ui.console
import os
//plays the sections & pages
fn play_pages(mut plbook PlayBook, mut site Site) ! {
pub fn play(mut plbook PlayBook) ! {
defaultdest := '${os.home_dir()}/hero/var/sitegen'
// mut siteconfig := &site.siteconfig
//if only 1 doctree is specified, then we use that as the default doctree name
mut doctreename := 'main'
@@ -22,21 +19,12 @@ pub fn play(mut plbook PlayBook) ! {
}
}
// !!site.page name:"atest" path:"crazy/sub" position:1
// src:"marketplace_specs:tft_tfp_marketplace"
// title:"Just a Page"
// description:"A description not filled in"
// draft:1 hide_title:1
mut factory := new(path: defaultdest, flat: true)!
// LETS FIRST DO THE CATEGORIES
category_actions := plbook.find(filter: 'site.page_category')!
mut section := Section{}
for action in category_actions {
// println(action)
mut p := action.params
sitename := p.get_default('sitename', '')!
section.position = p.get_int_default('position', 20)!
section.label = p.get('label') or {
return error('need to specify label in site.page_category')
@@ -44,8 +32,7 @@ pub fn play(mut plbook PlayBook) ! {
section.path = p.get('path') or {
return error('need to specify path in site.page_category')
}
mut site := factory.site_get(sitename)!
site.section_add(section)!
site.sections << section
}
page_actions := plbook.find(filter: 'site.page')!
@@ -59,7 +46,6 @@ pub fn play(mut plbook PlayBook) ! {
for action in page_actions {
// println(action)
mut p := action.params
sitename := p.get_default('sitename', '')!
pathnew := p.get_default('path', '')!
if pathnew != '' {
mypage.path = path
@@ -95,7 +81,7 @@ pub fn play(mut plbook PlayBook) ! {
mypage.draft = p.get_default_false('draft')
mypage.hide_title = p.get_default_false('hide_title')
mypage.title_nr = p.get_int_default('title_nr', 0)!
mut site := factory.site_get(sitename)!
site.page_add(mypage)!
site.pages << mypage
}
}

View File

@@ -1,11 +1,5 @@
# Site Module
The `lib/web/site/` directory contains the Vlang code responsible for generating and managing a documentation website all the config elements are specified in heroscript
The result is in redis on the DB as used in the context on
- hset: siteconfigs:$name as json
- set: siteconfigs:current is the name of the last one we processed
## config heroscript
@@ -102,11 +96,11 @@ The result is in redis on the DB as used in the context on
```
## how to use easy
## factory
```v
import freeflowuniverse.herolib.web.site
siteconfig := site.new("/tmp/mypath")!
mut mysite := site.new()!
```

View File

@@ -1,4 +1,4 @@
module siteconfig
module site
import os

View File

@@ -1,37 +0,0 @@
module siteconfig
import freeflowuniverse.herolib.core.playbook
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.core.base
import json
// new creates a new siteconfig and stores it in redis, or gets an existing one
pub fn new(path string) !&SiteConfig {
mut context := base.context()!
mut redis := context.redis()!
if path == '' {
return error('path is empty')
}
mut plbook := playbook.new(path: path)!
play(mut plbook)! // Pass the config by mutable reference
current_config_name := redis.get('siteconfigs:current')!
if current_config_name == '' {
return error('no current siteconfig found in redis')
}
mut sc := get(current_config_name)!
return sc
}
// get gets siteconfig from redis
pub fn get(name_ string) !&SiteConfig {
name := texttools.name_fix(name_)
mut context := base.context()!
mut redis := context.redis()!
json_config := redis.hget('siteconfigs', name)!
if json_config == '' {
return error('SiteConfig ${name} not found in redis')
}
mut sc := json.decode(SiteConfig, json_config)!
return &sc
}

View File

@@ -1,50 +0,0 @@
module sitegen
import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.web.doctreeclient
import os
pub struct SiteFactory {
pub mut:
sites map[string]&Site
path pathlib.Path
client &doctreeclient.DocTreeClient
flat bool // if flat then won't use sitenames as subdir's
}
@[params]
pub struct SiteFactoryArgs {
pub mut:
path string
flat bool // if flat then won't use sitenames as subdir's
}
// new creates a new siteconfig and stores it in redis, or gets an existing one
pub fn new(args SiteFactoryArgs) !SiteFactory {
mut path := args.path
if path == '' {
path = '${os.home_dir()}/hero/var/sitegen'
}
mut factory := SiteFactory{
path: pathlib.get_dir(path: path, create: true)!
client: doctreeclient.new()!
flat: args.flat
}
return factory
}
pub fn (mut f SiteFactory) site_get(name string) !&Site {
mut s := f.sites[name] or {
mut mypath := f.path
if !f.flat {
mypath = f.path.dir_get_new(name)!
}
mut mysite := &Site{
path: mypath
name: name
client: f.client
}
mysite
}
return s
}