...
This commit is contained in:
21
examples/data/atlas/heroscript_example.vsh
Normal file
21
examples/data/atlas/heroscript_example.vsh
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import incubaid.herolib.core.playbook
|
||||
import incubaid.herolib.data.atlas
|
||||
|
||||
heroscript := "
|
||||
!!atlas.scan
|
||||
path: '~/code/github/incubaid/herolib/lib/data/atlas/testdata'
|
||||
|
||||
!!atlas.validate
|
||||
|
||||
!!atlas.export
|
||||
destination: '/tmp/atlas_export_test'
|
||||
include: true
|
||||
redis: false
|
||||
"
|
||||
|
||||
mut plbook := playbook.new(text: heroscript)!
|
||||
atlas.play(mut plbook)!
|
||||
|
||||
println('✅ Atlas HeroScript processing complete!')
|
||||
@@ -88,6 +88,11 @@ pub fn (mut a Atlas) add_collection(args AddCollectionArgs) ! {
|
||||
pub fn (mut a Atlas) scan(args ScanArgs) ! {
|
||||
mut path := pathlib.get_dir(path: args.path)!
|
||||
a.scan_directory(mut path)!
|
||||
a.validate_links()!
|
||||
a.fix_links()!
|
||||
if args.save {
|
||||
a.save()!
|
||||
}
|
||||
}
|
||||
|
||||
// Get a collection by name
|
||||
|
||||
@@ -35,7 +35,7 @@ fn test_save_and_load_basic() {
|
||||
assert a.collections.len == 1
|
||||
|
||||
// Save all collections
|
||||
a.save_all()!
|
||||
a.save()!
|
||||
assert os.exists('${col_path}/.collection.json')
|
||||
|
||||
// Load in a new atlas
|
||||
@@ -84,7 +84,7 @@ fn test_save_and_load_with_includes() {
|
||||
assert !col.has_errors()
|
||||
|
||||
// Save
|
||||
a.save_all()!
|
||||
a.save()!
|
||||
|
||||
// Load
|
||||
mut a2 := new(name: 'loaded')!
|
||||
@@ -118,7 +118,7 @@ fn test_save_and_load_with_errors() {
|
||||
initial_error_count := col.errors.len
|
||||
|
||||
// Save with errors
|
||||
a.save_all()!
|
||||
a.save()!
|
||||
|
||||
// Load
|
||||
mut a2 := new(name: 'loaded')!
|
||||
@@ -156,7 +156,7 @@ fn test_save_and_load_multiple_collections() {
|
||||
|
||||
assert a.collections.len == 2
|
||||
|
||||
a.save_all()!
|
||||
a.save()!
|
||||
|
||||
// Load from directory
|
||||
mut a2 := new(name: 'loaded')!
|
||||
@@ -191,7 +191,7 @@ fn test_save_and_load_with_images() {
|
||||
assert col.image_exists('test')
|
||||
|
||||
// Save
|
||||
a.save_all()!
|
||||
a.save()!
|
||||
|
||||
// Load
|
||||
mut a2 := new(name: 'loaded')!
|
||||
|
||||
@@ -6,123 +6,123 @@ import os
|
||||
const test_base = '/tmp/atlas_test'
|
||||
|
||||
fn testsuite_begin() {
|
||||
os.rmdir_all(test_base) or {}
|
||||
os.mkdir_all(test_base)!
|
||||
os.rmdir_all(test_base) or {}
|
||||
os.mkdir_all(test_base)!
|
||||
}
|
||||
|
||||
fn testsuite_end() {
|
||||
os.rmdir_all(test_base) or {}
|
||||
os.rmdir_all(test_base) or {}
|
||||
}
|
||||
|
||||
fn test_create_atlas() {
|
||||
mut a := new(name: 'test_atlas')!
|
||||
assert a.name == 'test_atlas'
|
||||
assert a.collections.len == 0
|
||||
mut a := new(name: 'test_atlas')!
|
||||
assert a.name == 'test_atlas'
|
||||
assert a.collections.len == 0
|
||||
}
|
||||
|
||||
fn test_add_collection() {
|
||||
// Create test collection
|
||||
col_path := '${test_base}/col1'
|
||||
os.mkdir_all(col_path)!
|
||||
mut cfile := pathlib.get_file(path: '${col_path}/.collection', create: true)!
|
||||
cfile.write('name:col1')!
|
||||
// Create test collection
|
||||
col_path := '${test_base}/col1'
|
||||
os.mkdir_all(col_path)!
|
||||
mut cfile := pathlib.get_file(path: '${col_path}/.collection', create: true)!
|
||||
cfile.write('name:col1')!
|
||||
|
||||
mut page := pathlib.get_file(path: '${col_path}/page1.md', create: true)!
|
||||
page.write('# Page 1\n\nContent here.')!
|
||||
mut page := pathlib.get_file(path: '${col_path}/page1.md', create: true)!
|
||||
page.write('# Page 1\n\nContent here.')!
|
||||
|
||||
mut a := new(name: 'test')!
|
||||
a.add_collection(name: 'col1', path: col_path)!
|
||||
mut a := new(name: 'test')!
|
||||
a.add_collection(name: 'col1', path: col_path)!
|
||||
|
||||
assert a.collections.len == 1
|
||||
assert 'col1' in a.collections
|
||||
assert a.collections.len == 1
|
||||
assert 'col1' in a.collections
|
||||
}
|
||||
|
||||
fn test_scan() {
|
||||
// Create test structure
|
||||
os.mkdir_all('${test_base}/docs/guides')!
|
||||
mut cfile := pathlib.get_file(path: '${test_base}/docs/guides/.collection', create: true)!
|
||||
cfile.write('name:guides')!
|
||||
// Create test structure
|
||||
os.mkdir_all('${test_base}/docs/guides')!
|
||||
mut cfile := pathlib.get_file(path: '${test_base}/docs/guides/.collection', create: true)!
|
||||
cfile.write('name:guides')!
|
||||
|
||||
mut page := pathlib.get_file(path: '${test_base}/docs/guides/intro.md', create: true)!
|
||||
page.write('# Introduction')!
|
||||
mut page := pathlib.get_file(path: '${test_base}/docs/guides/intro.md', create: true)!
|
||||
page.write('# Introduction')!
|
||||
|
||||
mut a := new()!
|
||||
a.scan(path: '${test_base}/docs')!
|
||||
mut a := new()!
|
||||
a.scan(path: '${test_base}/docs')!
|
||||
|
||||
assert a.collections.len == 1
|
||||
col := a.get_collection('guides')!
|
||||
assert col.page_exists('intro')
|
||||
assert a.collections.len == 1
|
||||
col := a.get_collection('guides')!
|
||||
assert col.page_exists('intro')
|
||||
}
|
||||
|
||||
fn test_export() {
|
||||
// Setup
|
||||
col_path := '${test_base}/source/col1'
|
||||
export_path := '${test_base}/export'
|
||||
// Setup
|
||||
col_path := '${test_base}/source/col1'
|
||||
export_path := '${test_base}/export'
|
||||
|
||||
os.mkdir_all(col_path)!
|
||||
mut cfile := pathlib.get_file(path: '${col_path}/.collection', create: true)!
|
||||
cfile.write('name:col1')!
|
||||
os.mkdir_all(col_path)!
|
||||
mut cfile := pathlib.get_file(path: '${col_path}/.collection', create: true)!
|
||||
cfile.write('name:col1')!
|
||||
|
||||
mut page := pathlib.get_file(path: '${col_path}/test.md', create: true)!
|
||||
page.write('# Test Page')!
|
||||
mut page := pathlib.get_file(path: '${col_path}/test.md', create: true)!
|
||||
page.write('# Test Page')!
|
||||
|
||||
mut a := new()!
|
||||
a.add_collection(name: 'col1', path: col_path)!
|
||||
mut a := new()!
|
||||
a.add_collection(name: 'col1', path: col_path)!
|
||||
|
||||
a.export(destination: export_path, redis: false)!
|
||||
a.export(destination: export_path, redis: false)!
|
||||
|
||||
assert os.exists('${export_path}/col1/test.md')
|
||||
assert os.exists('${export_path}/col1/.collection')
|
||||
assert os.exists('${export_path}/col1/test.md')
|
||||
assert os.exists('${export_path}/col1/.collection')
|
||||
}
|
||||
|
||||
fn test_export_with_includes() {
|
||||
// Setup: Create pages with includes
|
||||
col_path := '${test_base}/include_test'
|
||||
os.mkdir_all(col_path)!
|
||||
// Setup: Create pages with includes
|
||||
col_path := '${test_base}/include_test'
|
||||
os.mkdir_all(col_path)!
|
||||
|
||||
mut cfile := pathlib.get_file(path: '${col_path}/.collection', create: true)!
|
||||
cfile.write('name:test_col')!
|
||||
mut cfile := pathlib.get_file(path: '${col_path}/.collection', create: true)!
|
||||
cfile.write('name:test_col')!
|
||||
|
||||
// Page 1: includes page 2
|
||||
mut page1 := pathlib.get_file(path: '${col_path}/page1.md', create: true)!
|
||||
page1.write('# Page 1\n\n!!include test_col:page2\n\nEnd of page 1')!
|
||||
// Page 1: includes page 2
|
||||
mut page1 := pathlib.get_file(path: '${col_path}/page1.md', create: true)!
|
||||
page1.write('# Page 1\n\n!!include test_col:page2\n\nEnd of page 1')!
|
||||
|
||||
// Page 2: standalone content
|
||||
mut page2 := pathlib.get_file(path: '${col_path}/page2.md', create: true)!
|
||||
page2.write('## Page 2 Content\n\nThis is included.')!
|
||||
// Page 2: standalone content
|
||||
mut page2 := pathlib.get_file(path: '${col_path}/page2.md', create: true)!
|
||||
page2.write('## Page 2 Content\n\nThis is included.')!
|
||||
|
||||
mut a := new()!
|
||||
a.add_collection(name: 'test_col', path: col_path)!
|
||||
mut a := new()!
|
||||
a.add_collection(name: 'test_col', path: col_path)!
|
||||
|
||||
export_path := '${test_base}/export_include'
|
||||
a.export(destination: export_path, include: true)!
|
||||
export_path := '${test_base}/export_include'
|
||||
a.export(destination: export_path, include: true)!
|
||||
|
||||
// Verify exported page1 has page2 content included
|
||||
exported := os.read_file('${export_path}/test_col/page1.md')!
|
||||
assert exported.contains('Page 2 Content')
|
||||
assert exported.contains('This is included')
|
||||
assert !exported.contains('!!include')
|
||||
// Verify exported page1 has page2 content included
|
||||
exported := os.read_file('${export_path}/test_col/page1.md')!
|
||||
assert exported.contains('Page 2 Content')
|
||||
assert exported.contains('This is included')
|
||||
assert !exported.contains('!!include')
|
||||
}
|
||||
|
||||
fn test_export_without_includes() {
|
||||
col_path := '${test_base}/no_include_test'
|
||||
os.mkdir_all(col_path)!
|
||||
col_path := '${test_base}/no_include_test'
|
||||
os.mkdir_all(col_path)!
|
||||
|
||||
mut cfile := pathlib.get_file(path: '${col_path}/.collection', create: true)!
|
||||
cfile.write('name:test_col2')!
|
||||
mut cfile := pathlib.get_file(path: '${col_path}/.collection', create: true)!
|
||||
cfile.write('name:test_col2')!
|
||||
|
||||
mut page1 := pathlib.get_file(path: '${col_path}/page1.md', create: true)!
|
||||
page1.write('# Page 1\n\n!!include test_col2:page2\n\nEnd')!
|
||||
mut page1 := pathlib.get_file(path: '${col_path}/page1.md', create: true)!
|
||||
page1.write('# Page 1\n\n!!include test_col2:page2\n\nEnd')!
|
||||
|
||||
mut a := new()!
|
||||
a.add_collection(name: 'test_col2', path: col_path)!
|
||||
mut a := new()!
|
||||
a.add_collection(name: 'test_col2', path: col_path)!
|
||||
|
||||
export_path := '${test_base}/export_no_include'
|
||||
a.export(destination: export_path, include: false)!
|
||||
export_path := '${test_base}/export_no_include'
|
||||
a.export(destination: export_path, include: false)!
|
||||
|
||||
// Verify exported page1 still has include action
|
||||
exported := os.read_file('${export_path}/test_col2/page1.md')!
|
||||
assert exported.contains('!!include')
|
||||
// Verify exported page1 still has include action
|
||||
exported := os.read_file('${export_path}/test_col2/page1.md')!
|
||||
assert exported.contains('!!include')
|
||||
}
|
||||
|
||||
fn test_error_deduplication() {
|
||||
@@ -300,8 +300,8 @@ fn test_link_formats() {
|
||||
assert local_links[1].page == 'page2'
|
||||
assert local_links[2].collection == 'guides'
|
||||
assert local_links[2].page == 'intro'
|
||||
assert local_links[3].page == 'page3' // Path ignored, only filename
|
||||
assert local_links[4].page == 'page4' // Path ignored, only filename
|
||||
assert local_links[3].page == 'page3' // Path ignored, only filename
|
||||
assert local_links[4].page == 'page4' // Path ignored, only filename
|
||||
}
|
||||
|
||||
fn test_cross_collection_links() {
|
||||
@@ -340,7 +340,7 @@ fn test_cross_collection_links() {
|
||||
a.fix_links()!
|
||||
|
||||
fixed := page1.read()!
|
||||
assert fixed.contains('[Link to col2](col2:page2)') // Unchanged
|
||||
assert fixed.contains('[Link to col2](col2:page2)') // Unchanged
|
||||
}
|
||||
|
||||
fn test_save_and_load() {
|
||||
@@ -357,7 +357,7 @@ fn test_save_and_load() {
|
||||
// Create and save
|
||||
mut a := new(name: 'test')!
|
||||
a.add_collection(name: 'test_col', path: col_path)!
|
||||
a.save_all()!
|
||||
a.save()!
|
||||
|
||||
assert os.exists('${col_path}/.collection.json')
|
||||
|
||||
@@ -437,7 +437,7 @@ fn test_load_from_directory() {
|
||||
mut a := new(name: 'test')!
|
||||
a.add_collection(name: 'col1', path: col1_path)!
|
||||
a.add_collection(name: 'col2', path: col2_path)!
|
||||
a.save_all()!
|
||||
a.save()!
|
||||
|
||||
// Load from directory
|
||||
mut a2 := new(name: 'loaded')!
|
||||
|
||||
56
lib/data/atlas/play.v
Normal file
56
lib/data/atlas/play.v
Normal file
@@ -0,0 +1,56 @@
|
||||
module atlas
|
||||
|
||||
import incubaid.herolib.core.playbook { PlayBook }
|
||||
|
||||
// Play function to process HeroScript actions for Atlas
|
||||
pub fn play(mut plbook PlayBook) ! {
|
||||
if !plbook.exists(filter: 'atlas.') {
|
||||
return
|
||||
}
|
||||
|
||||
mut atlases := map[string]&Atlas{}
|
||||
|
||||
// Process scan actions - scan directories for collections
|
||||
mut scan_actions := plbook.find(filter: 'atlas.scan')!
|
||||
for mut action in scan_actions {
|
||||
mut p := action.params
|
||||
name := p.get_default('name', 'main')!
|
||||
|
||||
// Get or create atlas
|
||||
mut atlas_instance := atlases[name] or {
|
||||
mut new_atlas := new(name: name)!
|
||||
atlases[name] = new_atlas
|
||||
new_atlas
|
||||
}
|
||||
|
||||
path := p.get('path')!
|
||||
atlas_instance.scan(path: path, save: true)!
|
||||
action.done = true
|
||||
atlas_set(atlas_instance)
|
||||
}
|
||||
|
||||
// Process export actions - export collections to destination
|
||||
mut export_actions := plbook.find(filter: 'atlas.export')!
|
||||
|
||||
// Process explicit export actions
|
||||
for mut action in export_actions {
|
||||
mut p := action.params
|
||||
name := p.get_default('name', 'main')!
|
||||
destination := p.get('destination')!
|
||||
reset := p.get_default_true('reset')
|
||||
include := p.get_default_true('include')
|
||||
redis := p.get_default_true('redis')
|
||||
|
||||
mut atlas_instance := atlases[name] or {
|
||||
return error("Atlas '${name}' not found. Use !!atlas.scan or !!atlas.load first.")
|
||||
}
|
||||
|
||||
atlas_instance.export(
|
||||
destination: destination
|
||||
reset: reset
|
||||
include: include
|
||||
redis: redis
|
||||
)!
|
||||
action.done = true
|
||||
}
|
||||
}
|
||||
@@ -81,7 +81,7 @@ a.add_collection(name: 'guides', path: './docs/guides')!
|
||||
```v
|
||||
// Get a page
|
||||
page := a.page_get('guides:introduction')!
|
||||
content := page.read_content()!
|
||||
content := page.content()!
|
||||
|
||||
// Check if page exists
|
||||
if a.page_exists('guides:setup') {
|
||||
@@ -207,13 +207,9 @@ mut page := a.page_get('col:mypage')!
|
||||
content := page.content(include: true)!
|
||||
|
||||
// Read raw content without processing includes
|
||||
content := page.read_content()!
|
||||
content := page.content()!
|
||||
```
|
||||
|
||||
#### Circular Include Detection
|
||||
|
||||
Atlas automatically detects circular includes and reports them as errors without causing infinite loops.
|
||||
|
||||
## Links
|
||||
|
||||
Atlas supports standard Markdown links with several formats for referencing pages within collections.
|
||||
@@ -471,7 +467,7 @@ print(f"Pages: {len(col.pages)}")
|
||||
# Access pages
|
||||
page = atlas.page_get('guides:intro')
|
||||
if page:
|
||||
content = page.read_content()
|
||||
content = page.content()
|
||||
print(content)
|
||||
|
||||
# Check for errors
|
||||
@@ -506,7 +502,7 @@ if atlas.has_errors():
|
||||
#### Page Class
|
||||
|
||||
- `page.key()` - Get page key in format 'collection:page'
|
||||
- `page.read_content()` - Read page content from file
|
||||
- `page.content()` - Read page content from file
|
||||
|
||||
#### File Class
|
||||
|
||||
@@ -572,7 +568,7 @@ atlas = Atlas.load_from_directory('/path/to/docs')
|
||||
# Access pages
|
||||
page = atlas.page_get('guides:intro')
|
||||
if page:
|
||||
content = page.read_content()
|
||||
content = page.content()
|
||||
print(content)
|
||||
|
||||
# Check errors
|
||||
@@ -630,3 +626,285 @@ if col.has_errors():
|
||||
```
|
||||
|
||||
|
||||
|
||||
## HeroScript Integration
|
||||
|
||||
Atlas integrates with HeroScript, allowing you to define Atlas operations in `.vsh` or playbook files.
|
||||
|
||||
### Available Actions
|
||||
|
||||
#### 1. `atlas.scan` - Scan Directory for Collections
|
||||
|
||||
Scan a directory tree to find and load collections marked with `.collection` files.
|
||||
|
||||
```heroscript
|
||||
!!atlas.scan
|
||||
name: 'main'
|
||||
path: './docs'
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `name` (optional, default: 'main') - Atlas instance name
|
||||
- `path` (required) - Directory path to scan
|
||||
|
||||
#### 2. `atlas.load` - Load from Saved Collections
|
||||
|
||||
Load collections from `.collection.json` files (previously saved with `atlas.save`).
|
||||
|
||||
```heroscript
|
||||
!!atlas.load
|
||||
name: 'main'
|
||||
path: './docs'
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `name` (optional, default: 'main') - Atlas instance name
|
||||
- `path` (required) - Directory path containing `.collection.json` files
|
||||
|
||||
#### 3. `atlas.validate` - Validate All Links
|
||||
|
||||
Validate all markdown links in all collections.
|
||||
|
||||
```heroscript
|
||||
!!atlas.validate
|
||||
name: 'main'
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `name` (optional, default: 'main') - Atlas instance name
|
||||
|
||||
#### 4. `atlas.fix_links` - Fix All Links
|
||||
|
||||
Automatically rewrite all local links with correct relative paths.
|
||||
|
||||
```heroscript
|
||||
!!atlas.fix_links
|
||||
name: 'main'
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `name` (optional, default: 'main') - Atlas instance name
|
||||
|
||||
#### 5. `atlas.save` - Save Collections
|
||||
|
||||
Save all collections to `.collection.json` files in their respective directories.
|
||||
|
||||
```heroscript
|
||||
!!atlas.save
|
||||
name: 'main'
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `name` (optional, default: 'main') - Atlas instance name
|
||||
|
||||
#### 6. `atlas.export` - Export Collections
|
||||
|
||||
Export collections to a destination directory.
|
||||
|
||||
```heroscript
|
||||
!!atlas.export
|
||||
name: 'main'
|
||||
destination: './output'
|
||||
reset: true
|
||||
include: true
|
||||
redis: true
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `name` (optional, default: 'main') - Atlas instance name
|
||||
- `destination` (required) - Export destination path
|
||||
- `reset` (optional, default: true) - Clear destination before export
|
||||
- `include` (optional, default: true) - Process `!!include` actions
|
||||
- `redis` (optional, default: true) - Store metadata in Redis
|
||||
|
||||
### Complete Workflow Examples
|
||||
|
||||
#### Example 1: Scan, Validate, and Export
|
||||
|
||||
```heroscript
|
||||
# Scan for collections
|
||||
!!atlas.scan
|
||||
path: '~/docs/myproject'
|
||||
|
||||
# Validate all links
|
||||
!!atlas.validate
|
||||
|
||||
# Export to output directory
|
||||
!!atlas.export
|
||||
destination: '~/docs/output'
|
||||
include: true
|
||||
```
|
||||
|
||||
#### Example 2: Load, Fix Links, and Export
|
||||
|
||||
```heroscript
|
||||
# Load from saved collections
|
||||
!!atlas.load
|
||||
path: '~/docs/myproject'
|
||||
|
||||
# Fix all broken links
|
||||
!!atlas.fix_links
|
||||
|
||||
# Save updated collections
|
||||
!!atlas.save
|
||||
|
||||
# Export
|
||||
!!atlas.export
|
||||
destination: '~/docs/output'
|
||||
```
|
||||
|
||||
#### Example 3: Multiple Atlas Instances
|
||||
|
||||
```heroscript
|
||||
# Main documentation
|
||||
!!atlas.scan
|
||||
name: 'docs'
|
||||
path: '~/docs'
|
||||
|
||||
# API reference
|
||||
!!atlas.scan
|
||||
name: 'api'
|
||||
path: '~/api-docs'
|
||||
|
||||
# Export docs
|
||||
!!atlas.export
|
||||
name: 'docs'
|
||||
destination: '~/output/docs'
|
||||
|
||||
# Export API
|
||||
!!atlas.export
|
||||
name: 'api'
|
||||
destination: '~/output/api'
|
||||
```
|
||||
|
||||
#### Example 4: Development Workflow
|
||||
|
||||
```heroscript
|
||||
# Scan collections
|
||||
!!atlas.scan
|
||||
path: './docs'
|
||||
|
||||
# Validate links (errors will be reported)
|
||||
!!atlas.validate
|
||||
|
||||
# Fix links automatically
|
||||
!!atlas.fix_links
|
||||
|
||||
# Save updated collections
|
||||
!!atlas.save
|
||||
|
||||
# Export final version
|
||||
!!atlas.export
|
||||
destination: './public'
|
||||
include: true
|
||||
redis: true
|
||||
```
|
||||
|
||||
### Using in V Scripts
|
||||
|
||||
Create a `.vsh` script to process Atlas operations:
|
||||
|
||||
```v
|
||||
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import incubaid.herolib.core.playbook
|
||||
import incubaid.herolib.data.atlas
|
||||
|
||||
// Define your HeroScript content
|
||||
heroscript := "
|
||||
!!atlas.scan
|
||||
path: './docs'
|
||||
|
||||
!!atlas.validate
|
||||
|
||||
!!atlas.export
|
||||
destination: './output'
|
||||
include: true
|
||||
"
|
||||
|
||||
// Create playbook from text
|
||||
mut plbook := playbook.new(text: heroscript)!
|
||||
|
||||
// Execute atlas actions
|
||||
atlas.play(mut plbook)!
|
||||
|
||||
println('Atlas processing complete!')
|
||||
```
|
||||
|
||||
### Using in Playbook Files
|
||||
|
||||
Create a `docs.play` file:
|
||||
|
||||
```heroscript
|
||||
!!atlas.scan
|
||||
name: 'main'
|
||||
path: '~/code/docs'
|
||||
|
||||
!!atlas.validate
|
||||
|
||||
!!atlas.fix_links
|
||||
|
||||
!!atlas.save
|
||||
|
||||
!!atlas.export
|
||||
destination: '~/code/output'
|
||||
reset: true
|
||||
include: true
|
||||
redis: true
|
||||
```
|
||||
|
||||
Execute it:
|
||||
|
||||
```bash
|
||||
vrun process_docs.vsh
|
||||
```
|
||||
|
||||
Where `process_docs.vsh` contains:
|
||||
|
||||
```v
|
||||
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import incubaid.herolib.core.playbook
|
||||
import incubaid.herolib.core.playcmds
|
||||
|
||||
// Load and execute playbook
|
||||
mut plbook := playbook.new(path: './docs.play')!
|
||||
playcmds.run(mut plbook)!
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
Errors are automatically collected and reported:
|
||||
|
||||
```heroscript
|
||||
!!atlas.scan
|
||||
path: './docs'
|
||||
|
||||
!!atlas.validate
|
||||
|
||||
# Errors will be printed during export
|
||||
!!atlas.export
|
||||
destination: './output'
|
||||
```
|
||||
|
||||
Errors are shown in the console:
|
||||
|
||||
```
|
||||
Collection guides - Errors (2)
|
||||
[invalid_page_reference] [guides:intro]: Broken link to `guides:setup` at line 5
|
||||
[missing_include] [guides:advanced]: Included page `guides:examples` not found
|
||||
```
|
||||
|
||||
### Auto-Export Behavior
|
||||
|
||||
If you use `!!atlas.scan` or `!!atlas.load` **without** an explicit `!!atlas.export`, Atlas will automatically export to the default location (current directory).
|
||||
|
||||
To disable auto-export, include an explicit (empty) export action or simply don't include any scan/load actions.
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Always validate before export**: Use `!!atlas.validate` to catch broken links early
|
||||
2. **Save after fixing**: Use `!!atlas.save` after `!!atlas.fix_links` to persist changes
|
||||
3. **Use named instances**: When working with multiple documentation sets, use the `name` parameter
|
||||
4. **Enable Redis for production**: Use `redis: true` for web deployments to enable fast lookups
|
||||
5. **Process includes during export**: Keep `include: true` to embed referenced content in exported files
|
||||
@@ -17,7 +17,7 @@ pub fn (c Collection) save() ! {
|
||||
}
|
||||
|
||||
// Save all collections in atlas to their respective directories
|
||||
pub fn (a Atlas) save_all() ! {
|
||||
pub fn (a Atlas) save() ! {
|
||||
for _, col in a.collections {
|
||||
col.save()!
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import os
|
||||
pub struct ScanArgs {
|
||||
pub mut:
|
||||
path string @[required]
|
||||
save bool = true // save atlas after scan
|
||||
}
|
||||
|
||||
// Scan a directory for collections
|
||||
|
||||
Reference in New Issue
Block a user