diff --git a/content.odin b/content.odin index d0d9518..a6bcb14 100644 --- a/content.odin +++ b/content.odin @@ -217,25 +217,40 @@ strip_extension :: proc(name: string) -> string { return name[:dot] } -// copy_static_assets copies non-content files from the content root to the output directory. -copy_static_assets :: proc(content_path: string, output_dir: string) { - entries, err := os.read_all_directory_by_path(content_path, context.allocator) +// copy_static_dir recursively copies all files from static_dir to output_dir. +// Silently skips if static_dir doesn't exist. +copy_static_dir :: proc(static_dir: string, output_dir: string) { + if !os.exists(static_dir) { + return + } + copy_static_recursive(static_dir, "", output_dir) +} + +copy_static_recursive :: proc(current: string, rel_prefix: string, output_dir: string) { + entries, err := os.read_all_directory_by_path(current, context.allocator) if err != nil { + log.warnf("thor: cannot read %s: %v", current, err) return } defer os.file_info_slice_delete(entries, context.allocator) for entry in entries { - if entry.type != .Regular { - continue - } - if is_content_file(entry.name) { - continue - } - - dest := fmt.tprintf("%s/%s", output_dir, entry.name) - if err := os.copy_file(dest, entry.fullpath); err != nil { - log.warnf("thor: cannot copy %s: %v", entry.name, err) + rel := rel_prefix == "" ? entry.name : fmt.tprintf("%s/%s", rel_prefix, entry.name) + switch entry.type { + case .Regular: + dest := fmt.tprintf("%s/%s", output_dir, rel) + if idx := strings.last_index(dest, "/"); idx >= 0 { + if err := os.make_directory_all(dest[:idx]); err != nil && err != .Exist { + log.warnf("thor: cannot create %s: %v", dest[:idx], err) + continue + } + } + if err := os.copy_file(dest, entry.fullpath); err != nil { + log.warnf("thor: cannot copy %s: %v", entry.fullpath, err) + } + case .Directory: + copy_static_recursive(entry.fullpath, rel, output_dir) + case .Undetermined, .Symlink, .Named_Pipe, .Socket, .Block_Device, .Character_Device: } } } diff --git a/render.odin b/render.odin index d8fb34c..e9d0fc7 100644 --- a/render.odin +++ b/render.odin @@ -125,8 +125,8 @@ render_site :: proc(pages: []Page, config: Site) { sitemap := generate_sitemap(pages, config.base_url) write_file(fmt.tprintf("%s/sitemap.xml", config.output_dir), sitemap) - // Copy static assets (avatar, favicon, etc.) - copy_static_assets(config.content_dir, config.output_dir) + // Copy static directory (favicon, CSS, images, etc.) + copy_static_dir(config.static_dir, config.output_dir) // Generate robots.txt robots := fmt.aprintf("User-agent: *\nAllow: /\nSitemap: %s/sitemap.xml\n", config.base_url) diff --git a/site.odin b/site.odin index 0aedefc..fe76c79 100644 --- a/site.odin +++ b/site.odin @@ -15,6 +15,7 @@ Site :: struct { description: string, base_url: string `args:"name=base-url"`, content_dir: string `args:"name=content"`, + static_dir: string `args:"name=static"`, output_dir: string `args:"name=output"`, layouts_dir: string, author: string, @@ -53,6 +54,9 @@ init_site :: proc(site: ^Site, args: []string) { if site.content_dir == "" { site.content_dir = fmt.tprintf("%s/content", config_dir) } + if site.static_dir == "" { + site.static_dir = fmt.tprintf("%s/static", config_dir) + } if site.output_dir == "" { site.output_dir = fmt.tprintf("%s/public", config_dir) } @@ -93,6 +97,9 @@ site_merge :: proc(config: ^Site, flags: Site) { if flags.content_dir != "" { config.content_dir = flags.content_dir } + if flags.static_dir != "" { + config.static_dir = flags.static_dir + } if flags.output_dir != "" { config.output_dir = flags.output_dir }