refactor: Rework playbook include and site import logic
- Replace manual script concatenation with playbook include handling - Preserve site configuration (imports, menu) during generation - Add support for copying static files from imported content - Handle static assets from sibling `ebooksall` directories - Fix import copy logic to not delete destination before copying
This commit is contained in:
@@ -11,15 +11,15 @@ playcmds.run(
|
|||||||
// install: 1
|
// install: 1
|
||||||
// template_update: 1
|
// template_update: 1
|
||||||
|
|
||||||
!!docusaurus.add sitename:"tfgrid_tech"
|
!!docusaurus.add sitename:"owh_intro"
|
||||||
git_url:"https://git.threefold.info/tfgrid/docs_tfgrid4/src/branch/main/ebooks/tech"
|
git_url:"https://git.ourworld.tf/ourworld_holding/docs_owh/src/branch/main/ebooks/owh_intro"
|
||||||
git_root:"/tmp/code"
|
git_root:"/tmp/code"
|
||||||
git_reset:1
|
git_reset:1
|
||||||
git_pull:1
|
git_pull:1
|
||||||
play:true
|
play:true
|
||||||
|
|
||||||
!!docusaurus.build
|
// !!docusaurus.build
|
||||||
|
|
||||||
// !!docusaurus.dev site:"tfgrid_tech" open:true
|
!!docusaurus.dev site:"owh_intro" open:true
|
||||||
'
|
'
|
||||||
)!
|
)!
|
||||||
|
|||||||
@@ -10,63 +10,54 @@ import freeflowuniverse.herolib.osal.core as osal
|
|||||||
import freeflowuniverse.herolib.core.playbook
|
import freeflowuniverse.herolib.core.playbook
|
||||||
// import freeflowuniverse.herolib.data.doctree
|
// import freeflowuniverse.herolib.data.doctree
|
||||||
|
|
||||||
// Recursively process heroscript files in a directory
|
// Process playbook includes - extracted from playcmds.play_core to avoid circular imports
|
||||||
fn process_heroscript_files_recursive(dir_path string) !string {
|
fn process_playbook_includes(mut plbook playbook.PlayBook) ! {
|
||||||
mut combined_heroscript := ''
|
// Track included paths to prevent infinite recursion
|
||||||
files := os.ls(dir_path) or { return combined_heroscript }
|
mut included_paths := map[string]bool{}
|
||||||
|
|
||||||
for file in files {
|
for action_ in plbook.find(filter: 'play.*')! {
|
||||||
file_path := os.join_path(dir_path, file)
|
if action_.name == 'include' {
|
||||||
|
mut action := *action_
|
||||||
|
mut playrunpath := action.params.get_default('path', '')!
|
||||||
|
if playrunpath.len == 0 {
|
||||||
|
action.name = 'pull'
|
||||||
|
playrunpath = gittools.get_repo_path(
|
||||||
|
path: action.params.get_default('path', '')!
|
||||||
|
git_url: action.params.get_default('git_url', '')!
|
||||||
|
git_reset: action.params.get_default_false('git_reset')
|
||||||
|
git_pull: action.params.get_default_false('git_pull')
|
||||||
|
)!
|
||||||
|
}
|
||||||
|
if playrunpath.len == 0 {
|
||||||
|
return error("can't run a heroscript didn't find url or path.")
|
||||||
|
}
|
||||||
|
|
||||||
if os.is_dir(file_path) {
|
// Check for cycle detection
|
||||||
// Recursively process subdirectories
|
if playrunpath in included_paths {
|
||||||
subdir_content := process_heroscript_files_recursive(file_path)!
|
continue
|
||||||
combined_heroscript += subdir_content
|
}
|
||||||
} else if file.ends_with('.heroscript') {
|
|
||||||
content := os.read_file(file_path) or { continue }
|
|
||||||
|
|
||||||
// Filter out only the play.include lines while keeping all other content
|
included_paths[playrunpath] = true
|
||||||
lines := content.split('\n')
|
plbook.add(path: playrunpath)!
|
||||||
mut filtered_lines := []string{}
|
|
||||||
for line in lines {
|
|
||||||
trimmed := line.trim_space()
|
|
||||||
if !trimmed.starts_with('!!play.include') {
|
|
||||||
filtered_lines << line
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
filtered_content := filtered_lines.join('\n')
|
|
||||||
|
|
||||||
// Only add if there's meaningful content after filtering
|
|
||||||
if filtered_content.trim_space().len > 0 {
|
|
||||||
combined_heroscript += filtered_content + '\n\n'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return combined_heroscript
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Central function to process site configuration from a path
|
// Central function to process site configuration from a path
|
||||||
// This is the single point of use for all site processing logic
|
// This is the single point of use for all site processing logic
|
||||||
// If sitename is empty, it will return the first available site
|
// If sitename is empty, it will return the first available site
|
||||||
pub fn process_site_from_path(path string, sitename string) !&site.Site {
|
pub fn process_site_from_path(path string, sitename string) !&site.Site {
|
||||||
console.print_debug('Processing site configuration from: ${path}')
|
// Create playbook from the config path and let it handle includes properly
|
||||||
|
// This way !!play.include statements will be processed and imports will be included
|
||||||
|
mut plbook := playbook.new(path: '${path}/cfg')!
|
||||||
|
|
||||||
// Process the site configuration recursively (excluding global includes)
|
// Process includes first - this is crucial for getting the imported site.import actions
|
||||||
combined_heroscript := process_heroscript_files_recursive('${path}/cfg')!
|
process_playbook_includes(mut plbook)!
|
||||||
console.print_debug('Combined heroscript length: ${combined_heroscript.len} characters')
|
|
||||||
|
|
||||||
if combined_heroscript.trim_space().len == 0 {
|
|
||||||
return error('No valid heroscript files found in ${path}/cfg')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create playbook and process site configuration
|
|
||||||
mut plbook := playbook.new(text: combined_heroscript)!
|
|
||||||
console.print_debug('Created playbook with ${plbook.actions.len} actions')
|
|
||||||
site.play(mut plbook)!
|
site.play(mut plbook)!
|
||||||
|
|
||||||
// Check what sites were created
|
// Check what sites were created
|
||||||
available_sites := site.list()
|
available_sites := site.list()
|
||||||
console.print_debug('Available sites after site.play(): ${available_sites}')
|
|
||||||
|
|
||||||
if available_sites.len == 0 {
|
if available_sites.len == 0 {
|
||||||
return error('No sites were created from the configuration')
|
return error('No sites were created from the configuration')
|
||||||
@@ -74,18 +65,14 @@ pub fn process_site_from_path(path string, sitename string) !&site.Site {
|
|||||||
|
|
||||||
// Determine which site to return
|
// Determine which site to return
|
||||||
target_sitename := if sitename.len == 0 {
|
target_sitename := if sitename.len == 0 {
|
||||||
console.print_debug('No specific site requested, using first available: ${available_sites[0]}')
|
|
||||||
available_sites[0] // Use the first (and likely only) site
|
available_sites[0] // Use the first (and likely only) site
|
||||||
} else {
|
} else {
|
||||||
console.print_debug('Looking for specific site: ${sitename}')
|
|
||||||
sitename
|
sitename
|
||||||
}
|
}
|
||||||
|
|
||||||
mysite := site.get(name: target_sitename) or {
|
mysite := site.get(name: target_sitename) or {
|
||||||
return error('Failed to get site after playing playbook: ${target_sitename}. Available sites: ${available_sites}')
|
return error('Failed to get site after playing playbook: ${target_sitename}. Available sites: ${available_sites}')
|
||||||
}
|
}
|
||||||
|
|
||||||
console.print_debug('Site processed successfully: ${mysite.siteconfig.name} with ${mysite.pages.len} pages')
|
|
||||||
return mysite
|
return mysite
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,6 +85,15 @@ pub fn (mut site DocSite) generate() ! {
|
|||||||
|
|
||||||
mut updated_site := best_site
|
mut updated_site := best_site
|
||||||
|
|
||||||
|
// IMPORTANT: Preserve the original site's imports and other configuration
|
||||||
|
// The sitegen.play() only processes pages, but we need to keep the original site config
|
||||||
|
// including imports, menu, footer, etc. that were processed in the hero command
|
||||||
|
updated_site.siteconfig.imports = site.website.siteconfig.imports
|
||||||
|
updated_site.siteconfig.menu = site.website.siteconfig.menu
|
||||||
|
updated_site.siteconfig.footer = site.website.siteconfig.footer
|
||||||
|
updated_site.siteconfig.build_dest = site.website.siteconfig.build_dest
|
||||||
|
updated_site.siteconfig.build_dest_dev = site.website.siteconfig.build_dest_dev
|
||||||
|
|
||||||
// Generate the configuration files using the processed site configuration
|
// Generate the configuration files using the processed site configuration
|
||||||
mut updated_config := new_configuration(updated_site.siteconfig)!
|
mut updated_config := new_configuration(updated_site.siteconfig)!
|
||||||
|
|
||||||
@@ -166,17 +175,15 @@ export default function Home() {
|
|||||||
site.process_imports()!
|
site.process_imports()!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub fn (mut site DocSite) process_imports() ! {
|
pub fn (mut site DocSite) process_imports() ! {
|
||||||
mut gs := gittools.new()!
|
mut gs := gittools.new()!
|
||||||
mut f := factory_get()!
|
mut f := factory_get()!
|
||||||
|
|
||||||
for item in site.website.siteconfig.imports {
|
if site.website.siteconfig.imports.len == 0 {
|
||||||
println(item)
|
return
|
||||||
if true{
|
|
||||||
panic("sdsd")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for item in site.website.siteconfig.imports {
|
||||||
mypath := gs.get_path(
|
mypath := gs.get_path(
|
||||||
pull: false
|
pull: false
|
||||||
reset: false
|
reset: false
|
||||||
@@ -184,20 +191,44 @@ pub fn (mut site DocSite) process_imports() ! {
|
|||||||
)!
|
)!
|
||||||
mut mypatho := pathlib.get(mypath)
|
mut mypatho := pathlib.get(mypath)
|
||||||
|
|
||||||
mypatho.copy(dest: '${f.path_build.path}/docs/${item.dest}', delete: true)!
|
dest_path := '${f.path_build.path}/docs/${item.dest}'
|
||||||
|
mypatho.copy(dest: dest_path, delete: false)!
|
||||||
|
|
||||||
// println(item)
|
// Also copy static files if they exist in the imported content
|
||||||
// replace: {'NAME': 'MyName', 'URGENCY': 'red'}
|
static_src_path := '${mypatho.path}/static'
|
||||||
|
if os.exists(static_src_path) && os.is_dir(static_src_path) {
|
||||||
|
static_dest_path := '${f.path_build.path}/static'
|
||||||
|
mut static_src := pathlib.get_dir(path: static_src_path, create: false)!
|
||||||
|
static_src.copy(dest: static_dest_path, delete: false)!
|
||||||
|
}
|
||||||
|
|
||||||
|
// SPECIAL CASE: For heroscriptall imports, also check for ebooksall/static in the same parent directory
|
||||||
|
// This handles the common pattern where heroscriptall contains config and ebooksall contains static assets
|
||||||
|
if mypatho.path.ends_with('heroscriptall') {
|
||||||
|
parent_dir := os.dir(mypatho.path)
|
||||||
|
ebooksall_static_path := '${parent_dir}/ebooksall/static'
|
||||||
|
if os.exists(ebooksall_static_path) && os.is_dir(ebooksall_static_path) {
|
||||||
|
static_dest_path := '${f.path_build.path}/static'
|
||||||
|
mut ebooksall_static_src := pathlib.get_dir(
|
||||||
|
path: ebooksall_static_path
|
||||||
|
create: false
|
||||||
|
)!
|
||||||
|
ebooksall_static_src.copy(dest: static_dest_path, delete: false)!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply replacements if any
|
||||||
|
if item.replace.len > 0 {
|
||||||
mut ri := regext.regex_instructions_new()
|
mut ri := regext.regex_instructions_new()
|
||||||
for key, val in item.replace {
|
for key, val in item.replace {
|
||||||
ri.add_item('\{${key}\}', val)!
|
ri.add_item('\{${key}\}', val)!
|
||||||
}
|
}
|
||||||
mypatho.copy(dest: '${f.path_build.path}/docs/${item.dest}', delete: true)!
|
|
||||||
ri.replace_in_dir(
|
ri.replace_in_dir(
|
||||||
path: '${f.path_build.path}/docs/${item.dest}'
|
path: dest_path
|
||||||
extensions: [
|
extensions: [
|
||||||
'md',
|
'md',
|
||||||
]
|
]
|
||||||
)!
|
)!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user