...
This commit is contained in:
@@ -1,42 +0,0 @@
|
||||
#!/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.data.doctree
|
||||
|
||||
// Create a new docusaurus factory
|
||||
mut docs := docusaurus.new(
|
||||
build_path: '/tmp/docusaurus_build'
|
||||
)!
|
||||
|
||||
// Create a new docusaurus site
|
||||
mut site := docs.dev(
|
||||
url: 'https://git.ourworld.tf/despiegk/docs_kristof'
|
||||
)!
|
||||
|
||||
// FOR FUTURE TO ADD CONTENT FROM DOCTREE
|
||||
|
||||
// Create a doctree for content
|
||||
// mut tree := doctree.new(name: 'content')!
|
||||
|
||||
// // Add some content from a git repository
|
||||
// tree.scan(
|
||||
// git_url: 'https://github.com/yourusername/your-docs-repo'
|
||||
// git_pull: true
|
||||
// )!
|
||||
|
||||
// // Export the content to the docusaurus site
|
||||
// tree.export(
|
||||
// destination: '${site.path_build.path}/docs'
|
||||
// reset: true
|
||||
// keep_structure: true
|
||||
// exclude_errors: false
|
||||
// )!
|
||||
|
||||
// Build the docusaurus site
|
||||
// site.build()!
|
||||
|
||||
// Generate the static site
|
||||
// site.generate()!
|
||||
|
||||
// Optionally open the site in a browser
|
||||
// site.open()!
|
||||
17
examples/webtools/starllight_example.vsh
Executable file
17
examples/webtools/starllight_example.vsh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.web.starlight
|
||||
// import freeflowuniverse.herolib.data.doctree
|
||||
|
||||
// Create a new starlight factory
|
||||
mut docs := starlight.new(
|
||||
build_path: '/tmp/starlight_build'
|
||||
)!
|
||||
|
||||
// Create a new starlight site
|
||||
mut site := docs.get(
|
||||
url: 'https://git.ourworld.tf/tfgrid/docs_aibox'
|
||||
init:true //init means we put config files if not there
|
||||
)!
|
||||
|
||||
site.dev()!
|
||||
@@ -10,7 +10,7 @@ import os
|
||||
|
||||
// checks if a certain version or above is installed
|
||||
fn installed() !bool {
|
||||
res := os.execute('tailwind -h')
|
||||
res := os.execute('tailwindcss -h')
|
||||
if res.exit_code == 0 {
|
||||
r := res.output.split_into_lines().filter(it.contains('tailwindcss v'))
|
||||
if r.len != 1 {
|
||||
@@ -22,6 +22,9 @@ fn installed() !bool {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}else{
|
||||
println("error in executing tailwindcss")
|
||||
println(res)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -6,22 +6,18 @@ pub const version = '3.4.12'
|
||||
const singleton = false
|
||||
const default = true
|
||||
|
||||
// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
|
||||
@[heap]
|
||||
pub struct Tailwind {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
}
|
||||
|
||||
// your checking & initialization code if needed
|
||||
fn obj_init(mycfg_ Tailwind) !Tailwind {
|
||||
mut mycfg := mycfg_
|
||||
return mycfg
|
||||
}
|
||||
|
||||
// called before start if done
|
||||
fn configure() ! {
|
||||
// mut installer := get()!
|
||||
}
|
||||
|
||||
/////////////NORMALLY NO NEED TO TOUCH
|
||||
|
||||
13
lib/installers/web/tailwind4/.heroscript
Normal file
13
lib/installers/web/tailwind4/.heroscript
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
!!hero_code.generate_installer
|
||||
name:'tailwind4'
|
||||
classname:'Tailwind'
|
||||
singleton:0
|
||||
templates:0
|
||||
default:1
|
||||
title:''
|
||||
supported_platforms:''
|
||||
reset:0
|
||||
startupmanager:0
|
||||
hasconfig:0
|
||||
build:0
|
||||
36
lib/installers/web/tailwind4/readme.md
Normal file
36
lib/installers/web/tailwind4/readme.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# tailwind4
|
||||
|
||||
|
||||
|
||||
To get started
|
||||
|
||||
```vlang
|
||||
|
||||
|
||||
|
||||
import freeflowuniverse.herolib.installers.something. tailwind4
|
||||
|
||||
mut installer:= tailwind4.get()!
|
||||
|
||||
installer.start()!
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
## example heroscript
|
||||
|
||||
|
||||
```hero
|
||||
!!tailwind4.install
|
||||
homedir: '/home/user/tailwind4'
|
||||
username: 'admin'
|
||||
password: 'secretpassword'
|
||||
title: 'Some Title'
|
||||
host: 'localhost'
|
||||
port: 8888
|
||||
|
||||
```
|
||||
|
||||
|
||||
69
lib/installers/web/tailwind4/tailwind_actions.v
Normal file
69
lib/installers/web/tailwind4/tailwind_actions.v
Normal file
@@ -0,0 +1,69 @@
|
||||
module tailwind4
|
||||
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.core
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.installers.ulist
|
||||
import os
|
||||
//////////////////// following actions are not specific to instance of the object
|
||||
|
||||
// checks if a certain version or above is installed
|
||||
fn installed() !bool {
|
||||
res := os.execute('tailwindcss4 -h')
|
||||
if res.exit_code == 0 {
|
||||
r := res.output.split_into_lines().filter(it.contains('tailwindcss v'))
|
||||
if r.len != 1 {
|
||||
return error("couldn't parse tailwind4 version, expected 'tailwindcss v' on 1 row.\n${res.output}")
|
||||
}
|
||||
|
||||
v := texttools.version(r[0].all_after(' '))
|
||||
if v < texttools.version(version) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}else{
|
||||
println("error in executing tailwindcss")
|
||||
println(res)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// get the Upload List of the files
|
||||
fn ulist_get() !ulist.UList {
|
||||
// optionally build a UList which is all paths which are result of building, is then used e.g. in upload
|
||||
return ulist.UList{}
|
||||
}
|
||||
|
||||
fn upload() ! {
|
||||
}
|
||||
|
||||
fn install() ! {
|
||||
console.print_header('install tailwind4')
|
||||
|
||||
mut url := ''
|
||||
if core.is_linux_arm()! {
|
||||
url = 'https://github.com/tailwindlabs/tailwindcss/releases/download/v${version}/tailwindcss-linux-arm64'
|
||||
} else if core.is_linux_intel()! {
|
||||
url = 'https://github.com/tailwindlabs/tailwindcss/releases/download/v${version}/tailwindcss-linux-x64'
|
||||
} else if core.is_osx_arm()! {
|
||||
url = 'https://github.com/tailwindlabs/tailwindcss/releases/download/v${version}/tailwindcss-macos-arm64'
|
||||
} else if core.is_osx_intel()! {
|
||||
url = 'https://github.com/tailwindlabs/tailwindcss/releases/download/v${version}/tailwindcss-macos-x64'
|
||||
} else {
|
||||
return error('unsported platform')
|
||||
}
|
||||
|
||||
mut dest := osal.download(
|
||||
url: url
|
||||
minsize_kb: 40000
|
||||
// reset: true
|
||||
)!
|
||||
|
||||
osal.cmd_add(
|
||||
cmdname: 'tailwind4'
|
||||
source: dest.path
|
||||
)!
|
||||
}
|
||||
|
||||
fn destroy() ! {}
|
||||
109
lib/installers/web/tailwind4/tailwind_factory_.v
Normal file
109
lib/installers/web/tailwind4/tailwind_factory_.v
Normal file
@@ -0,0 +1,109 @@
|
||||
module tailwind4
|
||||
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.sysadmin.startupmanager
|
||||
import freeflowuniverse.herolib.osal.zinit
|
||||
|
||||
__global (
|
||||
tailwind_global map[string]&Tailwind
|
||||
tailwind_default string
|
||||
)
|
||||
|
||||
/////////FACTORY
|
||||
|
||||
@[params]
|
||||
pub struct ArgsGet {
|
||||
pub mut:
|
||||
name string
|
||||
}
|
||||
|
||||
pub fn get(args_ ArgsGet) !&Tailwind {
|
||||
return &Tailwind{}
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct PlayArgs {
|
||||
pub mut:
|
||||
heroscript string // if filled in then plbook will be made out of it
|
||||
plbook ?playbook.PlayBook
|
||||
reset bool
|
||||
}
|
||||
|
||||
pub fn play(args_ PlayArgs) ! {
|
||||
mut args := args_
|
||||
|
||||
mut plbook := args.plbook or { playbook.new(text: args.heroscript)! }
|
||||
|
||||
mut other_actions := plbook.find(filter: 'tailwind4.')!
|
||||
for other_action in other_actions {
|
||||
if other_action.name in ['destroy', 'install', 'build'] {
|
||||
mut p := other_action.params
|
||||
reset := p.get_default_false('reset')
|
||||
if other_action.name == 'destroy' || reset {
|
||||
console.print_debug('install action tailwind4.destroy')
|
||||
destroy()!
|
||||
}
|
||||
if other_action.name == 'install' {
|
||||
console.print_debug('install action tailwind4.install')
|
||||
install()!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS ///////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
fn startupmanager_get(cat zinit.StartupManagerType) !startupmanager.StartupManager {
|
||||
// unknown
|
||||
// screen
|
||||
// zinit
|
||||
// tmux
|
||||
// systemd
|
||||
match cat {
|
||||
.zinit {
|
||||
console.print_debug('startupmanager: zinit')
|
||||
return startupmanager.get(cat: .zinit)!
|
||||
}
|
||||
.systemd {
|
||||
console.print_debug('startupmanager: systemd')
|
||||
return startupmanager.get(cat: .systemd)!
|
||||
}
|
||||
else {
|
||||
console.print_debug('startupmanager: auto')
|
||||
return startupmanager.get()!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct InstallArgs {
|
||||
pub mut:
|
||||
reset bool
|
||||
}
|
||||
|
||||
pub fn (mut self Tailwind) install(args InstallArgs) ! {
|
||||
switch(self.name)
|
||||
if args.reset || (!installed()!) {
|
||||
install()!
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut self Tailwind) destroy() ! {
|
||||
switch(self.name)
|
||||
destroy()!
|
||||
}
|
||||
|
||||
// switch instance to be used for tailwind4
|
||||
pub fn switch(name string) {
|
||||
tailwind_default = name
|
||||
}
|
||||
|
||||
// helpers
|
||||
|
||||
@[params]
|
||||
pub struct DefaultConfigArgs {
|
||||
instance string = 'default'
|
||||
}
|
||||
37
lib/installers/web/tailwind4/tailwind_model.v
Normal file
37
lib/installers/web/tailwind4/tailwind_model.v
Normal file
@@ -0,0 +1,37 @@
|
||||
module tailwind4
|
||||
|
||||
import freeflowuniverse.herolib.data.encoderhero
|
||||
|
||||
|
||||
pub const version = '4.0.8'
|
||||
const singleton = false
|
||||
const default = true
|
||||
|
||||
// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
|
||||
@[heap]
|
||||
pub struct Tailwind {
|
||||
pub mut:
|
||||
name string = 'default'
|
||||
}
|
||||
|
||||
// your checking & initialization code if needed
|
||||
fn obj_init(mycfg_ Tailwind) !Tailwind {
|
||||
mut mycfg := mycfg_
|
||||
return mycfg
|
||||
}
|
||||
|
||||
// called before start if done
|
||||
fn configure() ! {
|
||||
// mut installer := get()!
|
||||
}
|
||||
|
||||
/////////////NORMALLY NO NEED TO TOUCH
|
||||
|
||||
pub fn heroscript_dumps(obj Tailwind) !string {
|
||||
return encoderhero.encode[Tailwind](obj)!
|
||||
}
|
||||
|
||||
pub fn heroscript_loads(heroscript string) !Tailwind {
|
||||
mut obj := encoderhero.decode[Tailwind](heroscript)!
|
||||
return obj
|
||||
}
|
||||
51
lib/web/starlight/clean.v
Normal file
51
lib/web/starlight/clean.v
Normal file
@@ -0,0 +1,51 @@
|
||||
module starlight
|
||||
|
||||
import os
|
||||
import strings
|
||||
|
||||
pub fn (mut site DocSite) clean(args ErrorArgs) ! {
|
||||
toclean := '
|
||||
/node_modules
|
||||
|
||||
babel.config.js
|
||||
|
||||
# Production
|
||||
/build
|
||||
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
bun.lockb
|
||||
bun.lock
|
||||
|
||||
yarn.lock
|
||||
|
||||
build.sh
|
||||
build_dev.sh
|
||||
build-dev.sh
|
||||
develop.sh
|
||||
install.sh
|
||||
|
||||
package.json
|
||||
package-lock.json
|
||||
pnpm-lock.yaml
|
||||
|
||||
sidebars.ts
|
||||
|
||||
tsconfig.json
|
||||
'
|
||||
|
||||
//TODO: need better way how to deal with this
|
||||
|
||||
}
|
||||
126
lib/web/starlight/config.v
Normal file
126
lib/web/starlight/config.v
Normal file
@@ -0,0 +1,126 @@
|
||||
module starlight
|
||||
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import json
|
||||
import os
|
||||
|
||||
// Footer config structures
|
||||
pub struct FooterItem {
|
||||
pub mut:
|
||||
label string
|
||||
to string
|
||||
href string
|
||||
}
|
||||
|
||||
pub struct FooterLink {
|
||||
pub mut:
|
||||
title string
|
||||
items []FooterItem
|
||||
}
|
||||
|
||||
pub struct Footer {
|
||||
pub mut:
|
||||
style string = 'dark'
|
||||
links []FooterLink
|
||||
}
|
||||
|
||||
pub struct Main {
|
||||
pub mut:
|
||||
name string
|
||||
title string = 'A Test Site'
|
||||
// tagline string
|
||||
url string = 'http://localhost/testsite'
|
||||
// url_home string
|
||||
// base_url string = '/' @[json: 'baseUrl']
|
||||
// image string = 'img/tf_graph.png' @[required]
|
||||
build_dest []string @[json: 'buildDest']
|
||||
build_dest_dev []string @[json: 'buildDestDev']
|
||||
content []ContentItem
|
||||
}
|
||||
|
||||
// Navbar config structures
|
||||
pub struct NavbarItem {
|
||||
pub mut:
|
||||
href string
|
||||
label string
|
||||
position string
|
||||
}
|
||||
|
||||
pub struct Navbar {
|
||||
pub mut:
|
||||
title string
|
||||
items []NavbarItem
|
||||
}
|
||||
|
||||
// Combined config structure
|
||||
pub struct Config {
|
||||
pub mut:
|
||||
footer Footer
|
||||
main Main
|
||||
navbar Navbar
|
||||
}
|
||||
|
||||
//pulled from e.g. git and linked to a destination in the astro build location
|
||||
pub struct ContentItem {
|
||||
pub mut:
|
||||
url string
|
||||
dest string
|
||||
replacer map[string]string //items we want to replace
|
||||
}
|
||||
|
||||
// load_config loads all configuration from the specified directory
|
||||
pub fn load_config(cfg_dir string) !Config {
|
||||
// Ensure the config directory exists
|
||||
if !os.exists(cfg_dir) {
|
||||
return error('Config directory ${cfg_dir} does not exist')
|
||||
}
|
||||
|
||||
// Load and parse footer config
|
||||
footer_content := os.read_file(os.join_path(cfg_dir, 'footer.json'))!
|
||||
footer := json.decode(Footer, footer_content)!
|
||||
|
||||
// Load and parse main config
|
||||
main_config_path := os.join_path(cfg_dir, 'main.json')
|
||||
main_content := os.read_file(main_config_path)!
|
||||
main := json.decode(Main, main_content) or {
|
||||
eprintln('main.json in ${cfg_dir} is not in the right format please fix.\nError: ${err}')
|
||||
println('
|
||||
|
||||
## EXAMPLE OF A GOOD ONE:
|
||||
|
||||
- note the list for buildDest and buildDestDev
|
||||
- note its the full path where the html is pushed too
|
||||
|
||||
{
|
||||
"title": "ThreeFold Web4",
|
||||
"tagline": "ThreeFold Web4",
|
||||
"url": "https://docs.threefold.io",
|
||||
"url_home": "docs/introduction",
|
||||
"image": "img/tf_graph.png",
|
||||
"buildDest":["root@info.ourworld.tf:/root/hero/www/info/tfgrid4"],
|
||||
"buildDestDev":["root@info.ourworld.tf:/root/hero/www/infodev/tfgrid4"]
|
||||
|
||||
}
|
||||
')
|
||||
exit(99)
|
||||
}
|
||||
|
||||
// Load and parse navbar config
|
||||
navbar_content := os.read_file(os.join_path(cfg_dir, 'navbar.json'))!
|
||||
navbar := json.decode(Navbar, navbar_content)!
|
||||
|
||||
return Config{
|
||||
footer: footer
|
||||
main: main
|
||||
navbar: navbar
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c Config) write(path string) ! {
|
||||
mut footer_file := pathlib.get_file(path: '${path}/footer.json', create: true)!
|
||||
footer_file.write(json.encode(c.footer))!
|
||||
mut main_file := pathlib.get_file(path: '${path}/main.json', create: true)!
|
||||
main_file.write(json.encode(c.main))!
|
||||
mut navbar_file := pathlib.get_file(path: '${path}/navbar.json', create: true)!
|
||||
navbar_file.write(json.encode(c.navbar))!
|
||||
}
|
||||
42
lib/web/starlight/factory.v
Normal file
42
lib/web/starlight/factory.v
Normal file
@@ -0,0 +1,42 @@
|
||||
module starlight
|
||||
|
||||
import os
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.develop.gittools
|
||||
|
||||
@[heap]
|
||||
pub struct StarlightFactory {
|
||||
pub mut:
|
||||
sites []&DocSite @[skip; str: skip]
|
||||
path_build pathlib.Path
|
||||
// path_publish pathlib.Path
|
||||
args StarlightArgs
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct StarlightArgs {
|
||||
pub mut:
|
||||
// publish_path string
|
||||
build_path string
|
||||
production bool
|
||||
update bool
|
||||
}
|
||||
|
||||
pub fn new(args_ StarlightArgs) !&StarlightFactory {
|
||||
mut args := args_
|
||||
if args.build_path == '' {
|
||||
args.build_path = '${os.home_dir()}/hero/var/starlight'
|
||||
}
|
||||
// if args.publish_path == ""{
|
||||
// args.publish_path = "${os.home_dir()}/hero/var/starlight/publish"
|
||||
// }
|
||||
mut ds := &StarlightFactory{
|
||||
args: args_
|
||||
path_build: pathlib.get_dir(path: args.build_path, create: true)!
|
||||
// path_publish: pathlib.get_dir(path: args_.publish_path, create: true)!
|
||||
}
|
||||
|
||||
ds.template_install(install:true,template_update:args.update,delete:true)!
|
||||
|
||||
return ds
|
||||
}
|
||||
24
lib/web/starlight/model.v
Normal file
24
lib/web/starlight/model.v
Normal file
@@ -0,0 +1,24 @@
|
||||
module starlight
|
||||
|
||||
pub struct SiteError {
|
||||
Error
|
||||
pub mut:
|
||||
path string
|
||||
msg string
|
||||
cat ErrorCat
|
||||
}
|
||||
|
||||
pub enum ErrorCat {
|
||||
unknown
|
||||
image_double
|
||||
file_double
|
||||
file_not_found
|
||||
image_not_found
|
||||
page_double
|
||||
page_not_found
|
||||
sidebar
|
||||
circular_import
|
||||
def
|
||||
summary
|
||||
include
|
||||
}
|
||||
214
lib/web/starlight/site.v
Normal file
214
lib/web/starlight/site.v
Normal file
@@ -0,0 +1,214 @@
|
||||
module starlight
|
||||
|
||||
import freeflowuniverse.herolib.osal.screen
|
||||
import os
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.core.base
|
||||
import freeflowuniverse.herolib.develop.gittools
|
||||
import json
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
@[heap]
|
||||
pub struct DocSite {
|
||||
pub mut:
|
||||
name string
|
||||
url string
|
||||
path_src pathlib.Path
|
||||
path_build pathlib.Path
|
||||
// path_publish pathlib.Path
|
||||
args SiteGetArgs
|
||||
errors []SiteError
|
||||
config Config
|
||||
factory &StarlightFactory @[skip; str: skip] // Reference to the parent
|
||||
}
|
||||
|
||||
|
||||
pub fn (mut s DocSite) build() ! {
|
||||
s.generate()!
|
||||
osal.exec(
|
||||
cmd: '
|
||||
cd ${s.path_build.path}
|
||||
bash build.sh
|
||||
'
|
||||
retry: 0
|
||||
)!
|
||||
}
|
||||
|
||||
pub fn (mut s DocSite) build_dev_publish() ! {
|
||||
s.generate()!
|
||||
osal.exec(
|
||||
cmd: '
|
||||
cd ${s.path_build.path}
|
||||
bash build_dev_publish.sh
|
||||
'
|
||||
retry: 0
|
||||
)!
|
||||
}
|
||||
|
||||
pub fn (mut s DocSite) build_publish()! {
|
||||
s.generate()!
|
||||
osal.exec(
|
||||
cmd: '
|
||||
cd ${s.path_build.path}
|
||||
bash build_publish.sh
|
||||
'
|
||||
retry: 0
|
||||
)!
|
||||
}
|
||||
|
||||
pub fn (mut s DocSite) dev()! {
|
||||
s.clean()!
|
||||
s.generate()!
|
||||
|
||||
// Create screen session for starlight development server
|
||||
mut screen_name := 'starlight'
|
||||
mut sf := screen.new()!
|
||||
|
||||
// Add and start a new screen session
|
||||
mut scr := sf.add(
|
||||
name: screen_name
|
||||
cmd: '/bin/bash'
|
||||
start: true
|
||||
attach: false
|
||||
reset: true
|
||||
)!
|
||||
|
||||
// Send commands to the screen session
|
||||
scr.cmd_send('cd ${s.path_build.path}')!
|
||||
scr.cmd_send('bash develop.sh')!
|
||||
|
||||
// Print instructions for user
|
||||
console.print_header(' Starlight Development Server')
|
||||
console.print_item('Development server is running in a screen session.')
|
||||
console.print_item('To view the server output:')
|
||||
console.print_item(' 1. Attach to screen: screen -r ${screen_name}')
|
||||
console.print_item(' 2. To detach from screen: Press Ctrl+A then D')
|
||||
console.print_item(' 3. To list all screens: screen -ls')
|
||||
console.print_item('The site content is on::')
|
||||
console.print_item(' 1. location of documents: ${s.path_src.path}/docs')
|
||||
if osal.cmd_exists('code') {
|
||||
console.print_item(' 2. We opened above dir in vscode.')
|
||||
osal.exec(cmd: 'code ${s.path_src.path}/docs')!
|
||||
}
|
||||
|
||||
// Start the watcher in a separate thread
|
||||
// mut tf:=spawn watch_docs(docs_path, s.path_src.path, s.path_build.path)
|
||||
// tf.wait()!
|
||||
println('\n')
|
||||
|
||||
if s.args.watch_changes {
|
||||
docs_path := '${s.path_src.path}/docs'
|
||||
watch_docs(docs_path, s.path_src.path, s.path_build.path)!
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@[params]
|
||||
pub struct ErrorArgs {
|
||||
pub mut:
|
||||
path string
|
||||
msg string
|
||||
cat ErrorCat
|
||||
}
|
||||
|
||||
pub fn (mut site DocSite) error(args ErrorArgs) {
|
||||
// path2 := pathlib.get(args.path)
|
||||
e := SiteError{
|
||||
path: args.path
|
||||
msg: args.msg
|
||||
cat: args.cat
|
||||
}
|
||||
site.errors << e
|
||||
console.print_stderr(args.msg)
|
||||
}
|
||||
|
||||
fn check_item(item string)!{
|
||||
item2:=item.trim_space().trim("/").trim_space().all_after_last("/")
|
||||
if ["internal","infodev","info","dev","friends","dd","web"].contains(item2){
|
||||
return error("destination path is wrong, cannot be: ${item}")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn (mut site DocSite) check() ! {
|
||||
for item in site.config.main.build_dest{
|
||||
check_item(item)!
|
||||
}
|
||||
for item in site.config.main.build_dest_dev{
|
||||
check_item(item)!
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut site DocSite) generate() ! {
|
||||
console.print_header(' site generate: ${site.name} on ${site.path_build.path}')
|
||||
console.print_header(' site source on ${site.path_src.path}')
|
||||
site.check()!
|
||||
site.template_install()!
|
||||
|
||||
// Now copy all directories that exist in src to build
|
||||
for item in ['src', 'static', 'cfg', 'public'] {
|
||||
if os.exists('${site.path_src.path}/${item}') {
|
||||
mut aa := site.path_src.dir_get(item)!
|
||||
aa.copy(dest: '${site.path_build.path}/${item}')!
|
||||
}
|
||||
}
|
||||
for item in ['docs'] {
|
||||
if os.exists('${site.path_src.path}/${item}') {
|
||||
mut aa := site.path_src.dir_get(item)!
|
||||
aa.copy(dest: '${site.path_build.path}/${item}', delete: true)!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut site DocSite) template_install() ! {
|
||||
mut gs := gittools.new()!
|
||||
|
||||
site.factory.template_install(template_update:false, install:false, delete:false)!
|
||||
|
||||
cfg := site.config
|
||||
|
||||
mut myhome:="\$\{HOME\}" //for usage in bash
|
||||
|
||||
profile_include := osal.profile_path_source()!.replace(os.home_dir(),myhome)
|
||||
|
||||
mydir:=site.path_build.path.replace(os.home_dir(),myhome)
|
||||
|
||||
for item in ['src', 'static'] {
|
||||
mut aa := site.path_src.dir_get(item) or {continue}
|
||||
aa.copy(dest: '${site.factory.path_build.path}/${item}', delete:false)!
|
||||
|
||||
}
|
||||
|
||||
|
||||
develop := $tmpl('templates/develop.sh')
|
||||
build := $tmpl('templates/build.sh')
|
||||
build_dev_publish := $tmpl('templates/build_dev_publish.sh')
|
||||
build_publish := $tmpl('templates/build_publish.sh')
|
||||
|
||||
mut develop_ := site.path_build.file_get_new('develop.sh')!
|
||||
develop_.template_write(develop, true)!
|
||||
develop_.chmod(0o700)!
|
||||
|
||||
mut build_ := site.path_build.file_get_new('build.sh')!
|
||||
build_.template_write(build, true)!
|
||||
build_.chmod(0o700)!
|
||||
|
||||
mut build_publish_ := site.path_build.file_get_new('build_publish.sh')!
|
||||
build_publish_.template_write(build_publish, true)!
|
||||
build_publish_.chmod(0o700)!
|
||||
|
||||
mut build_dev_publish_ := site.path_build.file_get_new('build_dev_publish.sh')!
|
||||
build_dev_publish_.template_write(build_dev_publish, true)!
|
||||
build_dev_publish_.chmod(0o700)!
|
||||
|
||||
mut develop2_ := site.path_src.file_get_new('develop.sh')!
|
||||
develop2_.template_write(develop, true)!
|
||||
develop2_.chmod(0o700)!
|
||||
|
||||
mut build2_ := site.path_src.file_get_new('build.sh')!
|
||||
build2_.template_write(build, true)!
|
||||
build2_.chmod(0o700)!
|
||||
|
||||
}
|
||||
109
lib/web/starlight/site_get.v
Normal file
109
lib/web/starlight/site_get.v
Normal file
@@ -0,0 +1,109 @@
|
||||
module starlight
|
||||
|
||||
import os
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.develop.gittools
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
@[params]
|
||||
pub struct SiteGetArgs {
|
||||
pub mut:
|
||||
name string
|
||||
nameshort string
|
||||
path string
|
||||
url string
|
||||
publish_path string
|
||||
build_path string
|
||||
production bool
|
||||
watch_changes bool = true
|
||||
update bool
|
||||
init bool //means create new one if needed
|
||||
deploykey string
|
||||
config ?Config
|
||||
}
|
||||
|
||||
pub fn (mut f StarlightFactory) get(args_ SiteGetArgs) !&DocSite {
|
||||
console.print_header(' Starlight: ${args_.name}')
|
||||
mut args := args_
|
||||
|
||||
if args.build_path.len == 0 {
|
||||
args.build_path = '${f.path_build.path}'
|
||||
}
|
||||
// if args.publish_path.len == 0 {
|
||||
// args.publish_path = '${f.path_publish.path}/${args.name}'
|
||||
|
||||
// coderoot:"${os.home_dir()}/hero/var/publishcode"
|
||||
mut gs := gittools.new(ssh_key_path: args.deploykey)!
|
||||
|
||||
if args.url.len > 0 {
|
||||
args.path = gs.get_path(url: args.url)!
|
||||
}
|
||||
|
||||
if args.path.trim_space() == "" {
|
||||
args.path = os.getwd()
|
||||
}
|
||||
args.path = args.path.replace('~', os.home_dir())
|
||||
|
||||
mut r := gs.get_repo(
|
||||
url: 'https://github.com/freeflowuniverse/starlight_template.git'
|
||||
)!
|
||||
mut template_path := r.patho()!
|
||||
|
||||
// First, check if the new site args provides a configuration that can be written instead of template cfg dir
|
||||
if cfg := args.config {
|
||||
cfg.write('${args.path}/cfg')!
|
||||
} else {
|
||||
// Then ensure cfg directory exists in src,
|
||||
if !os.exists('${args.path}/cfg') {
|
||||
if args.init{
|
||||
// else copy config from template
|
||||
mut template_cfg := template_path.dir_get('cfg')!
|
||||
template_cfg.copy(dest: '${args.path}/cfg')!
|
||||
}else{
|
||||
return error("Can't find cfg dir in chosen starlight location: ${args.path}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !os.exists('${args.path}/src') {
|
||||
if args.init{
|
||||
mut template_cfg := template_path.dir_get('src')!
|
||||
template_cfg.copy(dest: '${args.path}/src')!
|
||||
} else{
|
||||
return error("Can't find src dir in chosen starlight location: ${args.path}")
|
||||
}
|
||||
}
|
||||
|
||||
mut myconfig := load_config('${args.path}/cfg')!
|
||||
|
||||
if args.name == '' {
|
||||
args.name = myconfig.main.name
|
||||
}
|
||||
|
||||
if args.name.len==0{
|
||||
return error("name for a site cannot be empty")
|
||||
}
|
||||
|
||||
if args.nameshort.len == 0 {
|
||||
args.nameshort = args.name
|
||||
}
|
||||
args.nameshort = texttools.name_fix(args.nameshort)
|
||||
|
||||
mut ds := DocSite{
|
||||
name: args.name
|
||||
url: args.url
|
||||
path_src: pathlib.get_dir(path: args.path, create: false)!
|
||||
path_build: f.path_build
|
||||
// path_publish: pathlib.get_dir(path: args.publish_path, create: true)!
|
||||
args: args
|
||||
config: myconfig
|
||||
factory: &f
|
||||
}
|
||||
|
||||
ds.check()!
|
||||
|
||||
f.sites << &ds
|
||||
|
||||
return &ds
|
||||
}
|
||||
58
lib/web/starlight/template.v
Normal file
58
lib/web/starlight/template.v
Normal file
@@ -0,0 +1,58 @@
|
||||
module starlight
|
||||
|
||||
import freeflowuniverse.herolib.develop.gittools
|
||||
import freeflowuniverse.herolib.osal
|
||||
import freeflowuniverse.herolib.installers.web.bun
|
||||
import freeflowuniverse.herolib.installers.web.tailwind
|
||||
import os
|
||||
|
||||
@[params]
|
||||
struct TemplateInstallArgs{
|
||||
template_update bool = true
|
||||
install bool
|
||||
delete bool = true
|
||||
}
|
||||
|
||||
fn (mut self StarlightFactory) template_install(args TemplateInstallArgs) ! {
|
||||
mut gs := gittools.new()!
|
||||
|
||||
mut r := gs.get_repo(
|
||||
url: 'https://github.com/freeflowuniverse/starlight_template.git'
|
||||
pull: args.template_update
|
||||
)!
|
||||
mut template_path := r.patho()!
|
||||
|
||||
for item in ['public', 'src'] {
|
||||
mut aa := template_path.dir_get(item) or {continue} //skip if not exist
|
||||
aa.copy(dest: '${self.path_build.path}/${item}', delete: args.delete)!
|
||||
}
|
||||
|
||||
for item in ['package.json', 'tsconfig.json', 'astro.config.mjs'] {
|
||||
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}')
|
||||
}
|
||||
}
|
||||
|
||||
if args.install{
|
||||
// install bun
|
||||
mut installer := bun.get()!
|
||||
installer.install()!
|
||||
|
||||
mut installer2 := tailwind.get()!
|
||||
installer2.install()!
|
||||
|
||||
|
||||
|
||||
osal.exec(
|
||||
cmd: '
|
||||
${osal.profile_path_source_and()!}
|
||||
export PATH=/tmp/starlight_build/node_modules/.bin:${os.home_dir()}/.bun/bin/:??PATH
|
||||
cd ${self.path_build.path}
|
||||
bun install
|
||||
'
|
||||
)!
|
||||
}
|
||||
|
||||
}
|
||||
22
lib/web/starlight/templates/build.sh
Executable file
22
lib/web/starlight/templates/build.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
script_dir="???cd "???dirname "??{BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "??{script_dir}"
|
||||
|
||||
echo "Docs directory: ??script_dir"
|
||||
|
||||
cd "${mydir}"
|
||||
|
||||
export PATH=${site.path_build.path}/node_modules/.bin:??{HOME}/.bun/bin/:??PATH
|
||||
|
||||
rm -rf ${site.path_build.path}/build/
|
||||
|
||||
${profile_include}
|
||||
|
||||
bun run build
|
||||
|
||||
mkdir -p ${site.args.publish_path.trim_right("/")}
|
||||
echo SYNC TO ${site.args.publish_path.trim_right("/")}
|
||||
rsync -rv --delete ${site.path_build.path}/build/ ${site.args.publish_path.trim_right("/")}/
|
||||
23
lib/web/starlight/templates/build_dev_publish.sh
Executable file
23
lib/web/starlight/templates/build_dev_publish.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
script_dir="???cd "???dirname "??{BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "??{script_dir}"
|
||||
|
||||
|
||||
echo "Docs directory: ??script_dir"
|
||||
|
||||
cd "${mydir}"
|
||||
|
||||
export PATH=${site.path_build.path}/node_modules/.bin:??{HOME}/.bun/bin/:??PATH
|
||||
|
||||
rm -rf ${site.path_build.path}/build/
|
||||
|
||||
${profile_include}
|
||||
|
||||
bun run build
|
||||
|
||||
@for dest in cfg.main.build_dest_dev
|
||||
rsync -rv --delete ${site.path_build.path}/build/ ${dest.trim_right("/")}/
|
||||
@end
|
||||
22
lib/web/starlight/templates/build_publish.sh
Executable file
22
lib/web/starlight/templates/build_publish.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
script_dir="???cd "???dirname "??{BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "??{script_dir}"
|
||||
|
||||
echo "Docs directory: ??script_dir"
|
||||
|
||||
cd "${mydir}"
|
||||
|
||||
export PATH=${site.path_build.path}/node_modules/.bin:??{HOME}/.bun/bin/:??PATH
|
||||
|
||||
rm -rf ${site.path_build.path}/build/
|
||||
|
||||
${profile_include}
|
||||
|
||||
bun run build
|
||||
|
||||
@for dest in cfg.main.build_dest
|
||||
rsync -rv --delete ${site.path_build.path}/build/ ${dest.trim_right("/")}/
|
||||
@end
|
||||
16
lib/web/starlight/templates/develop.sh
Executable file
16
lib/web/starlight/templates/develop.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
script_dir="???cd "???dirname "??{BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "??{script_dir}"
|
||||
|
||||
echo "Docs directory: ??script_dir"
|
||||
|
||||
cd "${mydir}"
|
||||
|
||||
export PATH=${site.path_build.path}/node_modules/.bin:??{HOME}/.bun/bin/:??PATH
|
||||
|
||||
${profile_include}
|
||||
|
||||
bun dev
|
||||
96
lib/web/starlight/watcher.v
Normal file
96
lib/web/starlight/watcher.v
Normal file
@@ -0,0 +1,96 @@
|
||||
module starlight
|
||||
|
||||
import freeflowuniverse.herolib.osal.notifier
|
||||
import os
|
||||
|
||||
fn watch_docs(docs_path string, path_src string, path_build string) ! {
|
||||
mut n := notifier.new('docsite_watcher') or {
|
||||
eprintln('Failed to create watcher: ${err}')
|
||||
return
|
||||
}
|
||||
|
||||
n.args['path_src'] = path_src
|
||||
n.args['path_build'] = path_build
|
||||
|
||||
// Add watch with captured args
|
||||
n.add_watch(docs_path, fn (event notifier.NotifyEvent, path string, args map[string]string) {
|
||||
handle_file_change(event, path, args) or { eprintln('Error handling file change: ${err}') }
|
||||
})!
|
||||
|
||||
n.start()!
|
||||
}
|
||||
|
||||
// handle_file_change processes file system events
|
||||
fn handle_file_change(event notifier.NotifyEvent, path string, args map[string]string) ! {
|
||||
file_base := os.base(path)
|
||||
is_dir := os.is_dir(path)
|
||||
|
||||
// Skip files starting with #
|
||||
if file_base.starts_with('#') {
|
||||
return
|
||||
}
|
||||
|
||||
// For files (not directories), check extensions
|
||||
if !is_dir {
|
||||
ext := os.file_ext(path).to_lower()
|
||||
if ext !in ['.md', '.png', '.jpeg', '.jpg'] {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Get relative path from docs directory
|
||||
rel_path := path.replace('${args['path_src']}/docs/', '')
|
||||
dest_path := '${args['path_build']}/docs/${rel_path}'
|
||||
|
||||
match event {
|
||||
.create, .modify {
|
||||
if is_dir {
|
||||
// For directories, just ensure they exist
|
||||
os.mkdir_all(dest_path) or {
|
||||
return error('Failed to create directory ${dest_path}: ${err}')
|
||||
}
|
||||
println('Created directory: ${rel_path}')
|
||||
} else {
|
||||
// For files, ensure parent directory exists and copy
|
||||
os.mkdir_all(os.dir(dest_path)) or {
|
||||
return error('Failed to create directory ${os.dir(dest_path)}: ${err}')
|
||||
}
|
||||
os.cp(path, dest_path) or {
|
||||
return error('Failed to copy ${path} to ${dest_path}: ${err}')
|
||||
}
|
||||
println('Updated: ${rel_path}')
|
||||
}
|
||||
}
|
||||
.delete {
|
||||
if os.exists(dest_path) {
|
||||
if is_dir {
|
||||
os.rmdir_all(dest_path) or {
|
||||
return error('Failed to delete directory ${dest_path}: ${err}')
|
||||
}
|
||||
println('Deleted directory: ${rel_path}')
|
||||
} else {
|
||||
os.rm(dest_path) or { return error('Failed to delete ${dest_path}: ${err}') }
|
||||
println('Deleted: ${rel_path}')
|
||||
}
|
||||
}
|
||||
}
|
||||
.rename {
|
||||
// For rename events, fswatch provides the new path in the event
|
||||
// The old path is already removed, so we just need to handle the new path
|
||||
if is_dir {
|
||||
os.mkdir_all(dest_path) or {
|
||||
return error('Failed to create directory ${dest_path}: ${err}')
|
||||
}
|
||||
println('Renamed directory to: ${rel_path}')
|
||||
} else {
|
||||
os.mkdir_all(os.dir(dest_path)) or {
|
||||
return error('Failed to create directory ${os.dir(dest_path)}: ${err}')
|
||||
}
|
||||
os.cp(path, dest_path) or {
|
||||
return error('Failed to copy ${path} to ${dest_path}: ${err}')
|
||||
}
|
||||
println('Renamed to: ${rel_path}')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user