Skip to main content

Module file_loader

Module file_loader 

Source
Expand description

File-based resource loading for templates and stylesheets.

Standout supports file-based configuration for templates and stylesheets, enabling a web-app-like development workflow for CLI applications.

§Problem

CLI applications need to manage templates and stylesheets. Developers want:

  • Separation of concerns - Keep templates and styles in files, not Rust code
  • Accessible to non-developers - Designers can edit YAML/Jinja without Rust
  • Rapid iteration - Changes visible immediately without recompilation
  • Single-binary distribution - Released apps should be self-contained

These requirements create tension: development wants external files for flexibility, while release wants everything embedded for distribution.

§Solution

The file loader provides a unified system that:

  • Development mode: Reads files from disk with hot reload on each access
  • Release mode: Embeds all files into the binary at compile time via proc macros

§Directory Structure

Organize resources in dedicated directories:

my-app/
├── templates/
│   ├── list.jinja
│   └── report/
│       └── summary.jinja
└── styles/
    ├── default.yaml
    └── themes/
        └── dark.yaml

§Name Resolution

Files are referenced by their relative path from the root, without extension:

File PathResolution Name
templates/list.jinja"list"
templates/report/summary.jinja"report/summary"
styles/themes/dark.yaml"themes/dark"

§Development Usage

Register directories and access resources by name:

use standout_render::file_loader::{FileRegistry, FileRegistryConfig};

let config = FileRegistryConfig {
    extensions: &[".yaml", ".yml"],
    transform: |content| Ok(content.to_string()),
};

let mut registry = FileRegistry::new(config);
registry.add_dir("./styles")?;

// Re-reads from disk each call - edits are immediately visible
let content = registry.get("themes/dark")?;

§Release Embedding

For release builds, use the embedding macros to bake files into the binary:

// At compile time, walks directory and embeds all files
let styles = standout_render::embed_styles!("./styles");

// Same API - resources accessed by name
let theme = styles.get("themes/dark")?;

The macros walk the directory at compile time, read each file, and generate code that registers all resources with their derived names.

See the standout_macros crate for detailed documentation on embed_templates! and embed_styles!.

§Extension Priority

Extensions are specified in priority order. When multiple files share the same base name, the extension appearing earlier wins for extensionless lookups:

// With extensions: [".yaml", ".yml"]
// If both default.yaml and default.yml exist:
registry.get("default")     // → default.yaml (higher priority)
registry.get("default.yml") // → default.yml (explicit)

§Collision Detection

Cross-directory collisions (same name from different directories) cause a panic with detailed diagnostics. This catches configuration mistakes early.

Same-directory, different-extension scenarios are resolved by priority (not errors).

§Supported Resource Types

ResourceExtensionsTransform
Templates.jinja, .jinja2, .j2, .txtIdentity
Stylesheets.yaml, .ymlYAML parsing
CustomUser-definedUser-defined

The registry is generic over content type T, enabling consistent behavior across all resource types with type-specific parsing via the transform function.

Structs§

FileRegistry
Generic registry for file-based resources.
FileRegistryConfig
Configuration for a file registry.
LoadedFile
A file discovered during directory walking.

Enums§

LoadError
Error type for file loading operations.
LoadedEntry
How a resource is stored—file path (dev) or content (release).

Functions§

build_embedded_registry
Builds a registry map from embedded entries with extension priority handling.
extension_priority
Returns the extension priority for a filename (lower = higher priority).
strip_extension
Strips a recognized extension from a filename.
walk_dir
Walks a directory recursively and collects files with recognized extensions.