SiteConfig
Loads optional sigil.toml project config and merges it over the built-in defaults. Precedence (low -> high): defaults < sigil.toml < CLI flags. This module only seeds the defaults from the config file; CLI flag overriding happens afterwards in Ssg.parse_flags.
Schema (flat [section] tables, double-quoted string values): [site] title = "My Site" base_url = "https://example.com" [build] content_dir = "content" output_dir = "out" static_dir = "static"
Missing/unreadable file -> silently returns the unchanged defaults.
IMPLEMENTATION NOTE: this is a deliberately small line-based parser rather than the stdlib Toml module. Toml.parse produces a nested TomlValue whose compiled (Perceus) manipulation is currently miscompiled — every shape we tried failed natively: reading the value with Toml.get_in more than once aborts with an RC underflow (each getter consumes the value), a single hand-walk that binds TTable(inner)/TStr(val) comes back empty, and threading a multi-field accumulator drops trailing fields. A flat line scan that only threads Strings and binds plain tuples (the same shape as Page.decode / FrontMatter.split, which compile correctly) sidesteps all of those compiler bugs.
scan's accumulator is bundled into a SINGLE record (Acc), not threaded as separate String parameters: a self-recursive call whose argument list mixes a freshly-computed value (e.g. header_name(t), from String.slice_bytes) with one or more OTHER arguments merely forwarded unchanged crashes the compiled backend (bad-pointer read in march_incrc/march_string_eq — a double-free from a TIR drop inserted after the tail call, freeing an argument the call already consumed). Reproduces even with only 2 total scan params (one replaced, one forwarded) and with the forwarded value being a record instead of a String, so it isn't about String specifically or about argument count past some threshold — it's specifically "replaced + forwarded together". Passing exactly ONE argument that is always freshly reconstructed as a whole (copying forward whichever fields don't change) sidesteps it.