Skip to content

Add first-class TOML support with YAML feature parity #104

Description

@DandyLyons

Summary

Add TOML as a first-class metadata serialization format using mattt/swift-toml (product: TOML). TOML should reach practical feature parity with YAML throughout md-utils, especially in the frontmatter / fm command group and every applicable --format option.

This includes both TOML frontmatter in Markdown documents and TOML as an input/output format. Existing YAML behavior and defaults must remain backward compatible.

Goals

  • Read and write standard +++-delimited TOML frontmatter in addition to ----delimited YAML frontmatter.
  • Preserve a document's frontmatter format when an fm or document transformation command mutates it.
  • Support toml anywhere an existing --format option supports yaml, when the command's data can be represented as TOML.
  • Give TOML-backed documents the same in-scope fm CRUD, array, query, validation, and batch-processing capabilities as YAML-backed documents.
  • Keep format-independent behavior in portable MarkdownUtilitiesCore where practical and retain supported Apple/Linux/Wasm builds.

Scope

Frontmatter parsing and writing

  • Detect YAML (---) and TOML (+++) frontmatter without changing body extraction semantics.
  • Represent parsed metadata through a format-neutral model or conversion layer rather than spreading TOML/YAML branches through every command.
  • Preserve the original delimiter and serialization format when updating existing frontmatter.
  • Provide an explicit way to select yaml or toml when a command creates a new frontmatter block; retain YAML as the default for backward compatibility.
  • Produce clear diagnostics for malformed TOML, mixed/mismatched delimiters, unsupported root values, and values that cannot be represented losslessly.
  • Frontmatter comments are not guaranteed to survive mutation in either TOML or YAML. Documentation should advise users not to add comments to mutable frontmatter.

md-utils fm parity

All existing operations except fm search should work against YAML- and TOML-backed frontmatter with equivalent semantics:

  • get, has, list, set, remove, rename, replace, remove-frontmatter / rmfm
  • dump, unique, sort-keys, and touch
  • array append, array prepend, array contains, and array remove
  • single files, explicit file lists, recursive directories, and supported wrapped frontmatter in non-Markdown text files
  • in-scope JMESPath consumers, missing-versus-present values, JSON Schema/rules checks, mdtype assessment/fixes, and other frontmatter consumers

TOML support for fm search, including TOML-backed input and --format toml output, is explicitly out of scope. The command should reject these cases clearly. fm search may be removed separately in the future.

fm replace --format toml should parse TOML input, and output-oriented fm commands that already accept --format yaml should also accept --format toml.

Other --format surfaces

Audit the CLI for every input/output format enum and add toml wherever YAML is currently supported, including type-definition workflows and shared serialization helpers. Update help text, examples, shell completion values, and error messages consistently.

When a command currently emits a top-level scalar or array that TOML cannot represent as a document root, define and document a stable TOML envelope rather than silently changing types. Unsupported YAML-only values (notably null, non-string mapping keys, and incompatible heterogeneous values) must fail with actionable errors instead of being coerced or dropped.

Dependency and architecture

  • Add https://github.com/mattt/swift-toml.git from 2.0.0 and use the TOML product.
  • Confirm dependency placement does not unnecessarily pull TOML into targets that do not need it.
  • Keep decoding limits appropriate for untrusted frontmatter and preserve deterministic/sorted output where current YAML output is deterministic.
  • Do not manually edit Package.resolved.

Acceptance criteria

  • Markdown with +++ TOML frontmatter can be parsed, queried, mutated, and serialized while preserving its body and TOML format.
  • Every existing fm subcommand other than the explicitly excluded fm search has TOML-backed coverage equivalent to its YAML-backed behavior.
  • Every applicable --format option that accepts yaml also accepts toml for input or output, excluding fm search as documented above.
  • New frontmatter can be explicitly created as TOML; omitted format selection continues to create YAML.
  • Mutations preserve the source frontmatter format and delimiter unless the user explicitly requests conversion.
  • YAML ↔ TOML conversion behavior and representability failures are documented and tested, with no silent data loss of representable values. Comments are explicitly non-preserving in both formats.
  • Rules, in-scope JMESPath consumers, schemas, mdtypes, document transformations, wrapped non-Markdown frontmatter, and collection/batch output work with TOML or report a documented format limitation.
  • Unit and CLI integration tests cover scalars, nested tables, arrays, arrays of tables, TOML date/time values, empty frontmatter, malformed input, unsupported values, and multi-file operations.
  • README, DocC command documentation, CLI help, common-use-case examples, the bundled Agent Skill, and the Project Brief are updated.
  • swift build, swift test, the native Linux Core smoke test, and the existing WebAssembly validation pass (or any upstream platform limitation is isolated and documented).

Notes

TOML and YAML do not have identical data models. “Feature parity” here means equivalent user workflows and explicit, lossless behavior—not pretending every YAML value has a direct TOML representation.

TOML config-file support is tracked separately in #105.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions