...
This commit is contained in:
@@ -1,9 +1,12 @@
|
|||||||
#!/usr/bin/env hero
|
#!/usr/bin/env hero
|
||||||
|
|
||||||
!!atlas.scan
|
!!atlas.scan
|
||||||
git_url: 'https://git.ourworld.tf/tfgrid/docs_tfgrid4/src/branch/main/collections/mycelium_economics'
|
git_url: 'https://git.ourworld.tf/tfgrid/docs_tfgrid4/src/branch/main/collections/mycelium_economics'
|
||||||
|
|
||||||
!!atlas.scan
|
!!atlas.scan
|
||||||
git_url: 'https://git.ourworld.tf/tfgrid/docs_tfgrid4/src/branch/main/collections/authentic_web'
|
git_url: 'https://git.ourworld.tf/tfgrid/docs_tfgrid4/src/branch/main/collections/authentic_web'
|
||||||
|
|
||||||
|
// !!atlas.scan
|
||||||
|
// git_url: 'https://git.ourworld.tf/geomind/docs_geomind/src/branch/main/collections/usecases'
|
||||||
|
|
||||||
!!atlas.export destination: '/tmp/atlas_export'
|
!!atlas.export destination: '/tmp/atlas_export'
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ fn (mut self Atlas) add_collection(mut path pathlib.Path) !Collection {
|
|||||||
error_cache: map[string]bool{}
|
error_cache: map[string]bool{}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.init()!
|
c.init_pre()!
|
||||||
|
|
||||||
self.collections[name] = &c
|
self.collections[name] = &c
|
||||||
|
|
||||||
@@ -56,16 +56,9 @@ pub fn (a Atlas) get_collection(name string) !&Collection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate all links in all collections
|
// Validate all links in all collections
|
||||||
pub fn (mut a Atlas) validate_links() ! {
|
pub fn (mut a Atlas) init_post() ! {
|
||||||
for _, mut col in a.collections {
|
for _, mut col in a.collections {
|
||||||
col.validate_links()!
|
col.init_post()!
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix all links in all collections
|
|
||||||
pub fn (mut a Atlas) fix_links() ! {
|
|
||||||
for _, mut col in a.collections {
|
|
||||||
col.fix_links()!
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,12 +90,6 @@ pub fn (a Atlas) groups_get(session Session) []&Group {
|
|||||||
|
|
||||||
return matching
|
return matching
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut a Atlas) validate() ! {
|
|
||||||
a.validate_links()!
|
|
||||||
a.fix_links()!
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////SCAN
|
//////////////////SCAN
|
||||||
|
|
||||||
// Scan a path for collections
|
// Scan a path for collections
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
module atlas
|
module atlas
|
||||||
|
|
||||||
import incubaid.herolib.core.pathlib
|
import incubaid.herolib.core.pathlib
|
||||||
import incubaid.herolib.core.texttools
|
// import incubaid.herolib.core.texttools
|
||||||
import incubaid.herolib.develop.gittools
|
import incubaid.herolib.develop.gittools
|
||||||
import incubaid.herolib.data.paramsparser { Params }
|
import incubaid.herolib.data.paramsparser { Params }
|
||||||
import incubaid.herolib.ui.console
|
import incubaid.herolib.ui.console
|
||||||
@@ -34,12 +34,18 @@ pub fn (mut c Collection) path() !pathlib.Path {
|
|||||||
return pathlib.get_dir(path: c.path, create: false)!
|
return pathlib.get_dir(path: c.path, create: false)!
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Collection) init() ! {
|
fn (mut c Collection) init_pre() ! {
|
||||||
mut p := mut c.path()!
|
mut p := mut c.path()!
|
||||||
c.scan(mut p)!
|
c.scan(mut p)!
|
||||||
c.scan_acl()!
|
c.scan_acl()!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut c Collection) init_post() ! {
|
||||||
|
c.validate_links()!
|
||||||
|
c.init_git_info()!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Add a page to the collection
|
// Add a page to the collection
|
||||||
@@ -62,7 +68,7 @@ fn (mut c Collection) add_page(mut path pathlib.Path) ! {
|
|||||||
|
|
||||||
// Add an image to the collection
|
// Add an image to the collection
|
||||||
fn (mut c Collection) add_file(mut p pathlib.Path) ! {
|
fn (mut c Collection) add_file(mut p pathlib.Path) ! {
|
||||||
name := p.name_fix_no_ext()
|
name := p.name_fix_keepext()
|
||||||
if name in c.files {
|
if name in c.files {
|
||||||
return error('Page ${name} already exists in collection ${c.name}')
|
return error('Page ${name} already exists in collection ${c.name}')
|
||||||
}
|
}
|
||||||
@@ -115,6 +121,15 @@ pub fn (c Collection) file_get(name string) !&File {
|
|||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (c Collection) file_or_image_get(name string) !&File {
|
||||||
|
mut f := c.files[name] or { return FileNotFound{
|
||||||
|
collection: c.name
|
||||||
|
file: name
|
||||||
|
} }
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check if page exists
|
// Check if page exists
|
||||||
pub fn (c Collection) page_exists(name string) bool {
|
pub fn (c Collection) page_exists(name string) bool {
|
||||||
return name in c.pages
|
return name in c.pages
|
||||||
@@ -132,6 +147,14 @@ pub fn (c Collection) file_exists(name string) bool {
|
|||||||
return f.ftype == .file
|
return f.ftype == .file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (c Collection) file_or_image_exists(name string) bool {
|
||||||
|
f := c.files[name] or { return false }
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@[params]
|
@[params]
|
||||||
pub struct CollectionErrorArgs {
|
pub struct CollectionErrorArgs {
|
||||||
pub mut:
|
pub mut:
|
||||||
@@ -220,7 +243,7 @@ pub fn (c Collection) print_errors() {
|
|||||||
pub fn (mut c Collection) validate_links() ! {
|
pub fn (mut c Collection) validate_links() ! {
|
||||||
for _, mut page in c.pages {
|
for _, mut page in c.pages {
|
||||||
content := page.content(include: true)!
|
content := page.content(include: true)!
|
||||||
page.find_links(content)! // will walk over links see if errors and add errors
|
page.links=page.find_links(content)! // will walk over links see if errors and add errors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ pub enum CollectionErrorCategory {
|
|||||||
missing_include
|
missing_include
|
||||||
include_syntax_error
|
include_syntax_error
|
||||||
invalid_page_reference
|
invalid_page_reference
|
||||||
|
invalid_file_reference
|
||||||
file_not_found
|
file_not_found
|
||||||
invalid_collection
|
invalid_collection
|
||||||
general_error
|
general_error
|
||||||
@@ -26,13 +27,13 @@ pub mut:
|
|||||||
// Hash is based on category + page_key (or file if page_key is empty)
|
// Hash is based on category + page_key (or file if page_key is empty)
|
||||||
pub fn (e CollectionError) hash() string {
|
pub fn (e CollectionError) hash() string {
|
||||||
mut hash_input := '${e.category}'
|
mut hash_input := '${e.category}'
|
||||||
|
|
||||||
if e.page_key != '' {
|
if e.page_key != '' {
|
||||||
hash_input += ':${e.page_key}'
|
hash_input += ':${e.page_key}'
|
||||||
} else if e.file != '' {
|
} else if e.file != '' {
|
||||||
hash_input += ':${e.file}'
|
hash_input += ':${e.file}'
|
||||||
}
|
}
|
||||||
|
|
||||||
return md5.hexhash(hash_input)
|
return md5.hexhash(hash_input)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ pub fn (e CollectionError) str() string {
|
|||||||
} else if e.file != '' {
|
} else if e.file != '' {
|
||||||
location = ' [${e.file}]'
|
location = ' [${e.file}]'
|
||||||
}
|
}
|
||||||
|
|
||||||
return '[${e.category}]${location}: ${e.message}'
|
return '[${e.category}]${location}: ${e.message}'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,9 +56,10 @@ pub fn (e CollectionError) category_str() string {
|
|||||||
.missing_include { 'Missing Include' }
|
.missing_include { 'Missing Include' }
|
||||||
.include_syntax_error { 'Include Syntax Error' }
|
.include_syntax_error { 'Include Syntax Error' }
|
||||||
.invalid_page_reference { 'Invalid Page Reference' }
|
.invalid_page_reference { 'Invalid Page Reference' }
|
||||||
|
.invalid_file_reference { 'Invalid File Reference' }
|
||||||
.file_not_found { 'File Not Found' }
|
.file_not_found { 'File Not Found' }
|
||||||
.invalid_collection { 'Invalid Collection' }
|
.invalid_collection { 'Invalid Collection' }
|
||||||
.general_error { 'General Error' }
|
.general_error { 'General Error' }
|
||||||
.acl_denied { 'ACL Access Denied' }
|
.acl_denied { 'ACL Access Denied' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ pub fn (mut a Atlas) export(args ExportArgs) ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate links before export
|
// Validate links before export
|
||||||
a.validate_links()!
|
// a.validate_links()!
|
||||||
|
|
||||||
for _, mut col in a.collections {
|
for _, mut col in a.collections {
|
||||||
col.export(
|
col.export(
|
||||||
@@ -61,7 +61,7 @@ pub fn (mut c Collection) export(args CollectionExportArgs) ! {
|
|||||||
col_dir_meta.empty()!
|
col_dir_meta.empty()!
|
||||||
}
|
}
|
||||||
|
|
||||||
c.init_git_info()!
|
|
||||||
|
|
||||||
if c.has_errors() {
|
if c.has_errors() {
|
||||||
c.print_errors()
|
c.print_errors()
|
||||||
|
|||||||
@@ -33,6 +33,16 @@ pub fn (a Atlas) file_get(key string) !&File {
|
|||||||
return col.file_get(parts[1])!
|
return col.file_get(parts[1])!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get a file (can be image) from any collection using format "collection:file"
|
||||||
|
pub fn (a Atlas) file_or_image_get(key string) !&File {
|
||||||
|
parts := key.split(':')
|
||||||
|
if parts.len != 2 {
|
||||||
|
return error('Invalid file key format. Use "collection:file"')
|
||||||
|
}
|
||||||
|
col := a.get_collection(parts[0])!
|
||||||
|
return col.file_or_image_get(parts[1])!
|
||||||
|
}
|
||||||
|
|
||||||
// Check if page exists
|
// Check if page exists
|
||||||
pub fn (a Atlas) page_exists(key string) bool {
|
pub fn (a Atlas) page_exists(key string) bool {
|
||||||
parts := key.split(':')
|
parts := key.split(':')
|
||||||
@@ -66,6 +76,16 @@ pub fn (a Atlas) file_exists(key string) bool {
|
|||||||
return col.file_exists(parts[1])
|
return col.file_exists(parts[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (a Atlas) file_or_image_exists(key string) bool {
|
||||||
|
parts := key.split(':')
|
||||||
|
if parts.len != 2 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
col := a.get_collection(parts[0]) or { return false }
|
||||||
|
return col.file_or_image_exists(parts[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// List all pages in Atlas
|
// List all pages in Atlas
|
||||||
pub fn (a Atlas) list_pages() map[string][]string {
|
pub fn (a Atlas) list_pages() map[string][]string {
|
||||||
mut result := map[string][]string{}
|
mut result := map[string][]string{}
|
||||||
|
|||||||
@@ -11,24 +11,23 @@ pub mut:
|
|||||||
target string // Original link target (the source text)
|
target string // Original link target (the source text)
|
||||||
line int // Line number where link was found
|
line int // Line number where link was found
|
||||||
target_collection_name string
|
target_collection_name string
|
||||||
target_page_name string
|
target_item_name string
|
||||||
status LinkStatus
|
status LinkStatus
|
||||||
|
is_file_link bool // is the link pointing to a file
|
||||||
page &Page @[skip; str: skip] // Reference to page where this link is found
|
page &Page @[skip; str: skip] // Reference to page where this link is found
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum LinkStatus {
|
pub enum LinkStatus {
|
||||||
init
|
init
|
||||||
external
|
external
|
||||||
page_found
|
found
|
||||||
page_not_found
|
not_found
|
||||||
file_found
|
|
||||||
file_not_found
|
|
||||||
anchor
|
anchor
|
||||||
error
|
error
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut self Link) key() string {
|
fn (mut self Link) key() string {
|
||||||
return '${self.target_collection_name}:${self.target_page_name}'
|
return '${self.target_collection_name}:${self.target_item_name}'
|
||||||
}
|
}
|
||||||
|
|
||||||
// is the link in the same collection as the page containing the link
|
// is the link in the same collection as the page containing the link
|
||||||
@@ -57,6 +56,8 @@ fn (mut p Page) find_links(content string) ![]Link {
|
|||||||
for line_idx, line in lines {
|
for line_idx, line in lines {
|
||||||
mut pos := 0
|
mut pos := 0
|
||||||
for {
|
for {
|
||||||
|
mut image_open := line.index_after('!', pos) or { break }
|
||||||
|
|
||||||
// Find next [
|
// Find next [
|
||||||
open_bracket := line.index_after('[', pos) or { break }
|
open_bracket := line.index_after('[', pos) or { break }
|
||||||
|
|
||||||
@@ -69,6 +70,10 @@ fn (mut p Page) find_links(content string) ![]Link {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if image_open + 1 != open_bracket {
|
||||||
|
image_open = -1
|
||||||
|
}
|
||||||
|
|
||||||
// Find matching )
|
// Find matching )
|
||||||
open_paren := close_bracket + 1
|
open_paren := close_bracket + 1
|
||||||
close_paren := line.index_after(')', open_paren) or { break }
|
close_paren := line.index_after(')', open_paren) or { break }
|
||||||
@@ -77,12 +82,15 @@ fn (mut p Page) find_links(content string) ![]Link {
|
|||||||
text := line[open_bracket + 1..close_bracket]
|
text := line[open_bracket + 1..close_bracket]
|
||||||
target := line[open_paren + 1..close_paren]
|
target := line[open_paren + 1..close_paren]
|
||||||
|
|
||||||
|
islink_file_link := (image_open != -1)
|
||||||
|
|
||||||
mut link := Link{
|
mut link := Link{
|
||||||
src: line[open_bracket..close_paren + 1]
|
src: line[open_bracket..close_paren + 1]
|
||||||
text: text
|
text: text
|
||||||
target: target.trim_space()
|
target: target.trim_space()
|
||||||
line: line_idx + 1
|
line: line_idx + 1
|
||||||
page: &p
|
is_file_link: islink_file_link
|
||||||
|
page: &p
|
||||||
}
|
}
|
||||||
|
|
||||||
p.parse_link_target(mut link)
|
p.parse_link_target(mut link)
|
||||||
@@ -96,7 +104,7 @@ fn (mut p Page) find_links(content string) ![]Link {
|
|||||||
|
|
||||||
// Parse link target to extract collection and page
|
// Parse link target to extract collection and page
|
||||||
fn (mut p Page) parse_link_target(mut link Link) {
|
fn (mut p Page) parse_link_target(mut link Link) {
|
||||||
target := link.target
|
mut target := link.target
|
||||||
|
|
||||||
// Skip external links
|
// Skip external links
|
||||||
if target.starts_with('http://') || target.starts_with('https://')
|
if target.starts_with('http://') || target.starts_with('https://')
|
||||||
@@ -111,28 +119,43 @@ fn (mut p Page) parse_link_target(mut link Link) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if target.contains('/') {
|
||||||
|
parts9 := target.split('/')
|
||||||
|
if parts9.len >= 1 {
|
||||||
|
target = parts9[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Format: $collection:$pagename or $collection:$pagename.md
|
// Format: $collection:$pagename or $collection:$pagename.md
|
||||||
if target.contains(':') {
|
if target.contains(':') {
|
||||||
parts := target.split(':')
|
parts := target.split(':')
|
||||||
if parts.len >= 2 {
|
if parts.len >= 2 {
|
||||||
link.target_collection_name = texttools.name_fix(parts[0])
|
link.target_collection_name = texttools.name_fix(parts[0])
|
||||||
link.target_page_name = normalize_page_name(parts[1])
|
link.target_item_name = normalize_page_name(parts[1])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
link.target_page_name = normalize_page_name(target).trim_space()
|
link.target_item_name = normalize_page_name(target).trim_space()
|
||||||
link.target_collection_name = p.collection.name
|
link.target_collection_name = p.collection.name
|
||||||
}
|
}
|
||||||
|
|
||||||
if !p.collection.atlas.page_exists(link.key()) {
|
if link.is_file_link == false && !p.collection.atlas.page_exists(link.key()) {
|
||||||
p.collection.error(
|
p.collection.error(
|
||||||
category: .invalid_page_reference
|
category: .invalid_page_reference
|
||||||
page_key: p.key()
|
page_key: p.key()
|
||||||
message: 'Broken link to `${link.key()}` at line ${link.line}: `${link.src}`'
|
message: 'Broken link to `${link.key()}` at line ${link.line}: `${link.src}`'
|
||||||
show_console: false
|
show_console: true
|
||||||
)
|
)
|
||||||
link.status = .page_not_found
|
link.status = .not_found
|
||||||
|
} else if link.is_file_link && !p.collection.atlas.file_or_image_exists(link.key()) {
|
||||||
|
p.collection.error(
|
||||||
|
category: .invalid_file_reference
|
||||||
|
page_key: p.key()
|
||||||
|
message: 'Broken file link to `${link.key()}` at line ${link.line}: `${link.src}`'
|
||||||
|
show_console: true
|
||||||
|
)
|
||||||
|
link.status = .not_found
|
||||||
} else {
|
} else {
|
||||||
link.status = .page_found
|
link.status = .found
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +171,7 @@ fn (mut p Page) content_with_fixed_links() !string {
|
|||||||
// Process links in reverse order to maintain positions
|
// Process links in reverse order to maintain positions
|
||||||
for mut link in p.links.reverse() {
|
for mut link in p.links.reverse() {
|
||||||
// if page not existing no point in fixing
|
// if page not existing no point in fixing
|
||||||
if link.status != .page_found {
|
if link.status != .found {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// if not local then no point in fixing
|
// if not local then no point in fixing
|
||||||
@@ -183,7 +206,7 @@ fn (mut p Page) process_cross_collection_links(mut export_dir pathlib.Path) !str
|
|||||||
|
|
||||||
// Process links in reverse order to maintain string positions
|
// Process links in reverse order to maintain string positions
|
||||||
for mut link in links.reverse() {
|
for mut link in links.reverse() {
|
||||||
if link.status != .page_found {
|
if link.status != .found {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
mut target_page := link.target_page()!
|
mut target_page := link.target_page()!
|
||||||
@@ -206,11 +229,11 @@ fn (mut p Page) process_cross_collection_links(mut export_dir pathlib.Path) !str
|
|||||||
panic('need to do for files too')
|
panic('need to do for files too')
|
||||||
}
|
}
|
||||||
|
|
||||||
for mut link in links.reverse() {
|
// for mut link in links.reverse() {
|
||||||
if link.status != . {
|
// if link.status != . {
|
||||||
continue
|
// continue
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,13 @@ pub fn play(mut plbook PlayBook) ! {
|
|||||||
|
|
||||||
mut atlases := map[string]&Atlas{}
|
mut atlases := map[string]&Atlas{}
|
||||||
|
|
||||||
|
mut name := ""
|
||||||
|
|
||||||
// Process scan actions - scan directories for collections
|
// Process scan actions - scan directories for collections
|
||||||
mut scan_actions := plbook.find(filter: 'atlas.scan')!
|
mut scan_actions := plbook.find(filter: 'atlas.scan')!
|
||||||
for mut action in scan_actions {
|
for mut action in scan_actions {
|
||||||
mut p := action.params
|
mut p := action.params
|
||||||
name := p.get_default('name', 'main')!
|
name = p.get_default('name', 'main')!
|
||||||
ignore := p.get_list_default('ignore', [])!
|
ignore := p.get_list_default('ignore', [])!
|
||||||
console.print_item("Scanning Atlas '${name}' with ignore patterns: ${ignore}\n${p}")
|
console.print_item("Scanning Atlas '${name}' with ignore patterns: ${ignore}\n${p}")
|
||||||
// Get or create atlas
|
// Get or create atlas
|
||||||
@@ -48,13 +50,22 @@ pub fn play(mut plbook PlayBook) ! {
|
|||||||
set(atlas_instance)
|
set(atlas_instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mut atlas_instance_post := atlases[name] or {
|
||||||
|
return error("Atlas '${name}' not found. Use !!atlas.scan first.")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
atlas_instance_post.init_post()!
|
||||||
|
|
||||||
|
println(atlas_instance_post)
|
||||||
|
|
||||||
// Process export actions - export collections to destination
|
// Process export actions - export collections to destination
|
||||||
mut export_actions := plbook.find(filter: 'atlas.export')!
|
mut export_actions := plbook.find(filter: 'atlas.export')!
|
||||||
|
|
||||||
// Process explicit export actions
|
// Process explicit export actions
|
||||||
for mut action in export_actions {
|
for mut action in export_actions {
|
||||||
mut p := action.params
|
mut p := action.params
|
||||||
name := p.get_default('name', 'main')!
|
name = p.get_default('name', 'main')!
|
||||||
destination := p.get('destination')!
|
destination := p.get('destination')!
|
||||||
reset := p.get_default_true('reset')
|
reset := p.get_default_true('reset')
|
||||||
include := p.get_default_true('include')
|
include := p.get_default_true('include')
|
||||||
|
|||||||
Reference in New Issue
Block a user