...
This commit is contained in:
436
lib/data/atlas/client/client.v
Normal file
436
lib/data/atlas/client/client.v
Normal file
@@ -0,0 +1,436 @@
|
||||
module client
|
||||
|
||||
import incubaid.herolib.core.pathlib
|
||||
import incubaid.herolib.core.texttools
|
||||
import os
|
||||
import json
|
||||
|
||||
// List of recognized image file extensions
|
||||
const image_extensions = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.bmp', '.tiff', '.ico']
|
||||
|
||||
// CollectionMetadata represents the metadata stored in meta/{collection}.json
|
||||
pub struct CollectionMetadata {
|
||||
pub mut:
|
||||
name string
|
||||
path string
|
||||
pages map[string]PageMetadata
|
||||
files map[string]FileMetadata
|
||||
errors []ErrorMetadata
|
||||
}
|
||||
|
||||
pub struct PageMetadata {
|
||||
pub mut:
|
||||
name string
|
||||
path string
|
||||
collection_name string
|
||||
links []LinkMetadata
|
||||
}
|
||||
|
||||
pub struct FileMetadata {
|
||||
pub mut:
|
||||
name string
|
||||
path string
|
||||
}
|
||||
|
||||
pub struct LinkMetadata {
|
||||
pub mut:
|
||||
src string
|
||||
text string
|
||||
target string
|
||||
line int
|
||||
target_collection_name string
|
||||
target_item_name string
|
||||
status string
|
||||
is_file_link bool
|
||||
is_image_link bool
|
||||
}
|
||||
|
||||
pub struct ErrorMetadata {
|
||||
pub mut:
|
||||
category string
|
||||
page_key string
|
||||
message string
|
||||
line int
|
||||
}
|
||||
|
||||
// get_page_path returns the path for a page in a collection
|
||||
// Pages are stored in {export_dir}/content/{collection}/{page}.md
|
||||
pub fn (mut c AtlasClient) get_page_path(collection_name string, page_name string) !string {
|
||||
// Apply name normalization
|
||||
fixed_collection_name := texttools.name_fix(collection_name)
|
||||
fixed_page_name := texttools.name_fix(page_name)
|
||||
|
||||
// Check if export directory exists
|
||||
if !os.exists(c.export_dir) {
|
||||
return c.error_export_dir_not_found(export_dir: c.export_dir)
|
||||
}
|
||||
|
||||
// Construct the page path
|
||||
page_path := os.join_path(c.export_dir, 'content', fixed_collection_name, '${fixed_page_name}.md')
|
||||
|
||||
// Check if the page file exists
|
||||
if !os.exists(page_path) {
|
||||
return c.error_page_not_found(
|
||||
collection_name: collection_name
|
||||
page_name: page_name
|
||||
)
|
||||
}
|
||||
|
||||
return page_path
|
||||
}
|
||||
|
||||
// get_file_path returns the path for a file in a collection
|
||||
// Files are stored in {export_dir}/content/{collection}/{filename}
|
||||
pub fn (mut c AtlasClient) get_file_path(collection_name string, file_name string) !string {
|
||||
// Apply name normalization
|
||||
fixed_collection_name := texttools.name_fix(collection_name)
|
||||
// Files keep their original names with extensions
|
||||
fixed_file_name := texttools.name_fix_keepext(file_name)
|
||||
|
||||
// Check if export directory exists
|
||||
if !os.exists(c.export_dir) {
|
||||
return c.error_export_dir_not_found(export_dir: c.export_dir)
|
||||
}
|
||||
|
||||
// Construct the file path
|
||||
file_path := os.join_path(c.export_dir, 'content', 'files', fixed_collection_name,
|
||||
fixed_file_name)
|
||||
|
||||
// Check if the file exists
|
||||
if !os.exists(file_path) {
|
||||
return c.error_file_not_found(
|
||||
collection_name: collection_name
|
||||
file_name: file_name
|
||||
)
|
||||
}
|
||||
|
||||
return file_path
|
||||
}
|
||||
|
||||
// get_image_path returns the path for an image in a collection
|
||||
// Images are stored in {export_dir}/content/{collection}/{imagename}
|
||||
pub fn (mut c AtlasClient) get_image_path(collection_name string, image_name string) !string {
|
||||
// Apply name normalization
|
||||
fixed_collection_name := texttools.name_fix_no_underscore_no_ext(collection_name)
|
||||
// Images keep their original names with extensions
|
||||
fixed_image_name := texttools.name_fix_keepext(image_name)
|
||||
|
||||
// Check if export directory exists
|
||||
if !os.exists(c.export_dir) {
|
||||
return c.error_export_dir_not_found(export_dir: c.export_dir)
|
||||
}
|
||||
|
||||
// Construct the image path
|
||||
image_path := os.join_path(c.export_dir, 'content', 'img', fixed_collection_name,
|
||||
fixed_image_name)
|
||||
|
||||
// Check if the image exists
|
||||
if !os.exists(image_path) {
|
||||
return c.error_image_not_found(
|
||||
collection_name: collection_name
|
||||
image_name: image_name
|
||||
)
|
||||
}
|
||||
|
||||
return image_path
|
||||
}
|
||||
|
||||
// page_exists checks if a page exists in a collection
|
||||
pub fn (mut c AtlasClient) page_exists(collection_name string, page_name string) bool {
|
||||
// Try to get the page path - if it succeeds, the page exists
|
||||
_ := c.get_page_path(collection_name, page_name) or { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
// file_exists checks if a file exists in a collection
|
||||
pub fn (mut c AtlasClient) file_exists(collection_name string, file_name string) bool {
|
||||
// Try to get the file path - if it succeeds, the file exists
|
||||
_ := c.get_file_path(collection_name, file_name) or { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
// image_exists checks if an image exists in a collection
|
||||
pub fn (mut c AtlasClient) image_exists(collection_name string, image_name string) bool {
|
||||
// Try to get the image path - if it succeeds, the image exists
|
||||
_ := c.get_image_path(collection_name, image_name) or { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
// get_page_content returns the content of a page in a collection
|
||||
pub fn (mut c AtlasClient) get_page_content(collection_name string, page_name string) !string {
|
||||
// Get the path for the page
|
||||
page_path := c.get_page_path(collection_name, page_name)!
|
||||
|
||||
// Use pathlib to read the file content
|
||||
mut path := pathlib.get_file(path: page_path)!
|
||||
|
||||
// Check if the file exists
|
||||
if !path.exists() {
|
||||
return c.error_page_file_not_exists(page_path: page_path)
|
||||
}
|
||||
|
||||
// Read and return the file content
|
||||
return path.read()!
|
||||
}
|
||||
|
||||
// list_collections returns a list of all collection names
|
||||
// Collections are directories in {export_dir}/content/
|
||||
pub fn (mut c AtlasClient) list_collections() ![]string {
|
||||
content_dir := os.join_path(c.export_dir, 'content')
|
||||
|
||||
// Check if content directory exists
|
||||
if !os.exists(content_dir) {
|
||||
return c.error_invalid_export_structure(content_dir: content_dir)
|
||||
}
|
||||
|
||||
// Get all subdirectories in content/
|
||||
mut collections := []string{}
|
||||
entries := os.ls(content_dir)!
|
||||
|
||||
for entry in entries {
|
||||
entry_path := os.join_path(content_dir, entry)
|
||||
if os.is_dir(entry_path) {
|
||||
collections << entry
|
||||
}
|
||||
}
|
||||
|
||||
return collections
|
||||
}
|
||||
|
||||
// list_pages returns a list of all page names in a collection
|
||||
// Uses metadata to get the authoritative list of pages that belong to this collection
|
||||
pub fn (mut c AtlasClient) list_pages(collection_name string) ![]string {
|
||||
// Get metadata which contains the authoritative list of pages
|
||||
metadata := c.get_collection_metadata(collection_name)!
|
||||
|
||||
// Extract page names from metadata
|
||||
mut page_names := []string{}
|
||||
for page_name, _ in metadata.pages {
|
||||
page_names << page_name
|
||||
}
|
||||
|
||||
return page_names
|
||||
}
|
||||
|
||||
// list_files returns a list of all file names in a collection (excluding pages and images)
|
||||
pub fn (mut c AtlasClient) list_files(collection_name string) ![]string {
|
||||
// Apply name normalization
|
||||
fixed_collection_name := texttools.name_fix(collection_name)
|
||||
|
||||
collection_dir := os.join_path(c.export_dir, 'content', fixed_collection_name)
|
||||
|
||||
// Check if collection directory exists
|
||||
if !os.exists(collection_dir) {
|
||||
return c.error_collection_not_found(collection_name: collection_name)
|
||||
}
|
||||
|
||||
// Get all files that are not .md and not images
|
||||
mut file_names := []string{}
|
||||
entries := os.ls(collection_dir)!
|
||||
|
||||
for entry in entries {
|
||||
entry_path := os.join_path(collection_dir, entry)
|
||||
|
||||
// Skip directories
|
||||
if os.is_dir(entry_path) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Skip .md files (pages)
|
||||
if entry.ends_with('.md') {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if it's an image
|
||||
mut is_image := false
|
||||
for ext in image_extensions {
|
||||
if entry.ends_with(ext) {
|
||||
is_image = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Add to file_names if it's not an image
|
||||
if !is_image {
|
||||
file_names << entry
|
||||
}
|
||||
}
|
||||
|
||||
return file_names
|
||||
}
|
||||
|
||||
// list_images returns a list of all image names in a collection
|
||||
pub fn (mut c AtlasClient) list_images(collection_name string) ![]string {
|
||||
// Apply name normalization
|
||||
fixed_collection_name := texttools.name_fix(collection_name)
|
||||
|
||||
collection_dir := os.join_path(c.export_dir, 'content', fixed_collection_name)
|
||||
|
||||
// Check if collection directory exists
|
||||
if !os.exists(collection_dir) {
|
||||
return c.error_collection_not_found(collection_name: collection_name)
|
||||
}
|
||||
|
||||
// Get all image files
|
||||
mut image_names := []string{}
|
||||
entries := os.ls(collection_dir)!
|
||||
|
||||
for entry in entries {
|
||||
entry_path := os.join_path(collection_dir, entry)
|
||||
|
||||
// Skip directories
|
||||
if os.is_dir(entry_path) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if it's an image
|
||||
for ext in image_extensions {
|
||||
if entry.ends_with(ext) {
|
||||
image_names << entry
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return image_names
|
||||
}
|
||||
|
||||
// list_pages_map returns a map of collection names to a list of page names within that collection.
|
||||
// The structure is map[collectionname][]pagename.
|
||||
pub fn (mut c AtlasClient) list_pages_map() !map[string][]string {
|
||||
mut result := map[string][]string{}
|
||||
collections := c.list_collections()!
|
||||
|
||||
for col_name in collections {
|
||||
mut page_names := c.list_pages(col_name)!
|
||||
page_names.sort()
|
||||
result[col_name] = page_names
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// list_markdown returns the collections and their pages in markdown format.
|
||||
pub fn (mut c AtlasClient) list_markdown() !string {
|
||||
mut markdown_output := ''
|
||||
pages_map := c.list_pages_map()!
|
||||
|
||||
if pages_map.len == 0 {
|
||||
return 'No collections or pages found in this atlas export.'
|
||||
}
|
||||
|
||||
mut sorted_collections := pages_map.keys()
|
||||
sorted_collections.sort()
|
||||
|
||||
for col_name in sorted_collections {
|
||||
page_names := pages_map[col_name]
|
||||
markdown_output += '## ${col_name}\n'
|
||||
if page_names.len == 0 {
|
||||
markdown_output += ' * No pages in this collection.\n'
|
||||
} else {
|
||||
for page_name in page_names {
|
||||
markdown_output += ' * ${page_name}\n'
|
||||
}
|
||||
}
|
||||
markdown_output += '\n' // Add a newline for spacing between collections
|
||||
}
|
||||
return markdown_output
|
||||
}
|
||||
|
||||
// get_collection_metadata reads and parses the metadata JSON file for a collection
|
||||
// Metadata is stored in {export_dir}/meta/{collection}.json
|
||||
pub fn (mut c AtlasClient) get_collection_metadata(collection_name string) !CollectionMetadata {
|
||||
// Apply name normalization
|
||||
fixed_collection_name := texttools.name_fix_no_underscore_no_ext(collection_name)
|
||||
|
||||
meta_path := os.join_path(c.export_dir, 'meta', '${fixed_collection_name}.json')
|
||||
|
||||
// Check if metadata file exists
|
||||
if !os.exists(meta_path) {
|
||||
return c.error_collection_not_found_at(
|
||||
collection_name: collection_name
|
||||
path: meta_path
|
||||
)
|
||||
}
|
||||
|
||||
// Read and parse the JSON file
|
||||
content := os.read_file(meta_path)!
|
||||
metadata := json.decode(CollectionMetadata, content)!
|
||||
|
||||
return metadata
|
||||
}
|
||||
|
||||
// get_page_links returns the links found in a page by reading the metadata
|
||||
pub fn (mut c AtlasClient) get_page_links(collection_name string, page_name string) ![]LinkMetadata {
|
||||
// Get collection metadata
|
||||
metadata := c.get_collection_metadata(collection_name)!
|
||||
|
||||
// Apply name normalization to page name
|
||||
fixed_page_name := texttools.name_fix_no_underscore_no_ext(page_name)
|
||||
|
||||
// Find the page in metadata
|
||||
if fixed_page_name in metadata.pages {
|
||||
return metadata.pages[fixed_page_name].links
|
||||
}
|
||||
|
||||
return c.error_page_not_found_in_metadata(
|
||||
collection_name: collection_name
|
||||
page_name: page_name
|
||||
)
|
||||
}
|
||||
|
||||
// get_collection_errors returns the errors for a collection from metadata
|
||||
pub fn (mut c AtlasClient) get_collection_errors(collection_name string) ![]ErrorMetadata {
|
||||
metadata := c.get_collection_metadata(collection_name)!
|
||||
return metadata.errors
|
||||
}
|
||||
|
||||
// has_errors checks if a collection has any errors
|
||||
pub fn (mut c AtlasClient) has_errors(collection_name string) bool {
|
||||
errors := c.get_collection_errors(collection_name) or { return false }
|
||||
return errors.len > 0
|
||||
}
|
||||
|
||||
// get_page_paths returns the path of a page and the paths of its linked images.
|
||||
// Returns (page_path, image_paths)
|
||||
// This is compatible with the doctreeclient API
|
||||
// pub fn (mut c AtlasClient) get_page_paths(collection_name string, page_name string) !(string, []string) {
|
||||
// // Get the page path
|
||||
// page_path := c.get_page_path(collection_name, page_name)!
|
||||
// page_content := c.get_page_content(collection_name, page_name)!
|
||||
|
||||
// // Extract image names from the page content
|
||||
// image_names := extract_image_links(page_content, true)!
|
||||
|
||||
// mut image_paths := []string{}
|
||||
// for image_name in image_names {
|
||||
// // Get the path for each image
|
||||
// image_path := c.get_image_path(collection_name, image_name) or {
|
||||
// // If an image is not found, log a warning and continue, don't fail the whole operation
|
||||
// return error('Error: Linked image "${image_name}" not found in collection "${collection_name}". Skipping.')
|
||||
// }
|
||||
// image_paths << image_path
|
||||
// }
|
||||
|
||||
// return page_path, image_paths
|
||||
// }
|
||||
|
||||
// copy_images copies all images linked in a page to a destination directory
|
||||
// This is compatible with the doctreeclient API
|
||||
// pub fn (mut c AtlasClient) copy_images(collection_name string, page_name string, destination_path string) ! {
|
||||
// // Get the page path and linked image paths
|
||||
// _, image_paths := c.get_page_paths(collection_name, page_name)!
|
||||
|
||||
// // Ensure the destination directory exists
|
||||
// os.mkdir_all(destination_path)!
|
||||
|
||||
// // Create an 'img' subdirectory within the destination
|
||||
// images_dest_path := os.join_path(destination_path, 'img')
|
||||
// os.mkdir_all(images_dest_path)!
|
||||
|
||||
// // Copy each linked image
|
||||
// for image_path in image_paths {
|
||||
// image_file_name := os.base(image_path)
|
||||
// dest_image_path := os.join_path(images_dest_path, image_file_name)
|
||||
// os.cp(image_path, dest_image_path)!
|
||||
// }
|
||||
// }
|
||||
Reference in New Issue
Block a user