dataverse
Find a file
JMARyA 263b8a8e1d
Some checks failed
moira/container moira/container — failed
moira/test moira/test — failed
feat: extract markdown structure (title, todos, sections) when inspecting .md files
Plain markdown files without frontmatter now parse into a structured
object instead of a bare content string. Reuses the existing
extract_tasks/extract_inline_tags helpers from record.rs; adds
parse_markdown_structure as a new pub fn there to avoid duplication.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 16:29:15 +02:00
.hooks split into workspace for core, bin, and gui components 2026-03-01 11:37:05 +01:00
.moira test: add integration tests and improve CI pipeline 2026-05-22 12:02:18 +02:00
docs feat: add jsaw render command with Tera templating 2026-05-22 11:10:11 +02:00
jsaw-bin fix: replace from_provider panic with graceful error exit 2026-05-23 16:10:05 +02:00
jsaw-core feat: extract markdown structure (title, todos, sections) when inspecting .md files 2026-05-23 16:29:15 +02:00
tests/data feat: add jsaw render command with Tera templating 2026-05-22 11:10:11 +02:00
.gitignore chore: nix pkg output 2025-11-10 13:49:59 +01:00
Cargo.lock test: add integration tests and improve CI pipeline 2026-05-22 12:02:18 +02:00
Cargo.toml chore: remove jsaw-gui, add clipboard yank, simplify README 2026-05-12 12:38:16 +02:00
cog.toml chore: add cog 2025-11-27 23:34:46 +01:00
flake.lock fix: recent dioxus 2025-11-26 18:01:44 +01:00
flake.nix chore: remove jsaw-gui, add clipboard yank, simplify README 2026-05-12 12:38:16 +02:00
justfile chore: remove jsaw-gui, add clipboard yank, simplify README 2026-05-12 12:38:16 +02:00
README.md feat: add jsaw render command with Tera templating 2026-05-22 11:10:11 +02:00
renovate.json chore: add renovate.json 2025-11-12 20:00:56 +00:00
zensical.toml feat: add jsaw render command with Tera templating 2026-05-22 11:10:11 +02:00

jsaw

A universal runtime for structured data.

JSON, TOML, YAML, Markdown frontmatter, CSV — one tool to inspect, query, validate, convert, and browse them all. Unix-friendly by default; a rich TUI when you want to think.


Install

# Nix (recommended)
nix run github:yourusername/jsaw

# From source
cargo install --path jsaw-bin

CLI

Composable, pipeable, scriptable. Every command reads from a file or - for stdin.

jsaw inspect <file|->               # type tree: keys, depths, value types
jsaw validate <path> [--schema <f>] # JSON Schema validation; auto-detects $schema
              [--recursive]         # walk a whole directory
              [--skip-unparseable]  # silently skip unreadable files
              [--quiet]             # only print failures
jsaw query <file|-> <expr>          # jq-style filter via jaq
              [--raw]               # raw string output, no JSON quoting
jsaw convert <file> --to <fmt>      # json | toml | yaml
              [--out <file>]        # write to file instead of stdout
jsaw fmt <file> [--in-place]        # pretty-print in original format
jsaw db <dir> [-c col] [-f filter]  # directory as queryable table → TUI or CSV
              [-s field] [-r]       # sort, reverse
              [--offset N] [-l N]   # pagination
              [--json]              # output as JSON instead
jsaw render <file|-> <template>     # render a Tera template with data as context

Piping examples:

cat secrets.yaml | jsaw query - '.tokens[]'
jsaw db ./posts -c "title" -c "date" -f '.published == true' -s date -r
jsaw validate ./schemas/ --recursive --skip-unparseable --quiet

# Render all open todos across a markdown vault
jsaw db ./vault -c "file.name" -c "md.tasks" -c "md.tasks_open" --json \
  | jsaw render - todos.j2

TUI

jsaw inspect <file> and jsaw db <dir> launch a TUI automatically when stdout is a terminal. This is the primary interactive surface of jsaw — the place where you think with your data, not just read it.

Column browser (jsaw inspect)

A ranger/twig-style multi-column file browser for JSON data:

  • Side-by-side columns — each nesting level is its own column (not an indented tree).
  • / or h/l — navigate between columns.
  • / or j/k — move selection. g/G — first/last.
  • Inspector pane on the right shows key, value, semantic type, path, and pretty preview.
  • View modes: Browse (columns), Table, List, Grouped — switch with Tab.
  • / — open jq filter bar to narrow the view.
  • Semantic coloring — every value is classified and color-coded by inferred type.

Table view (jsaw db)

  • j/k ↑/— move row;g/G— first/last;PgUp/PgDn` — page.
  • s/S — cycle sort column / reverse.
  • / — open jq filter bar (applied instantly on Enter).
  • Enter — open detail view for selected row.
  • ? — help overlay; q/Esc — quit.

Semantic rendering

Every value is classified and colored by jsaw-core::semantic:

Semantic type Display
URL cyan + underline
Email cyan
DateTime yellow
Date yellow
Boolean green ✓ / red ✗
Integer / Float magenta
UUID blue
Color (#rrggbb) rendered in its own RGB foreground color
SemVer green
File path yellow
IP address blue
Base64 dim, truncated to preview
Markdown first line only +
GeoJSON geometry green badge with shape name
JSON Schema cyan badge
Null dim

The inference engine is value-first (URL scheme, ISO-8601, UUID format, GeoJSON shape check, base64 alphabet, markdown signals) with key-name heuristics as fallback.


Templating (jsaw render)

jsaw render takes any structured data source and a Tera template, then prints the rendered output to stdout. Tera uses Jinja2-style syntax.

The data is available as data in the template context.

jsaw render <file|-> <template.j2>

Example — open todos across a markdown vault:

jsaw db ./vault -c "file.name" -c "md.tasks" -c "md.tasks_open" --json \
  | jsaw render - todos.j2

todos.j2:

{% for file in data %}{% if file["md.tasks_open"] and file["md.tasks_open"] > 0 %}
## {{ file["file.name"] }}
{% for t in file["md.tasks"] %}{% if not t.done %}  [ ] {{ t.text }}
{% endif %}{% endfor %}{% endif %}{% endfor %}

Output:

## personal
  [ ] Call dentist
  [ ] Read chapter 4

## project-alpha
  [ ] Write design doc
  [ ] Review with team
  [ ] Set up CI pipeline

Any jsaw command that produces JSON can be piped into jsaw render. Use - as the data argument to read from stdin, or pass a file path directly.


Roadmap

Now — solid foundation

  • Semantic type inference (value-first + key-name heuristics)
  • Column browser TUI (jsaw inspect)
  • Table view, list view, grouped view (jsaw db)
  • Clipboard yank (y to copy selected value)
  • Comprehensive test coverage for core inference and parsing
  • Edge case polish, reliability, perf

Next — power user features

  • Column picker — toggle visible columns interactively
  • Fuzzy search — cross-column fuzzy match
  • Export — write filtered/sorted view as JSON or CSV
  • Watch mode — --watch flag, auto-reload on file change
  • Clipboard yank for table cells

Later — edit & schema integration

  • Inline value editing in tree view
  • Schema-constrained editing (enum pickers, required fields)
  • Multi-file / cross-file linking
  • Schema overlay — field descriptions, required markers, enum hints

Future exploration

  • JSON-LD integration — linked data contexts, @id resolution, graph navigation
  • HTTP source — jsaw inspect https://… fetches and renders live
  • Graph view — force-directed node graph in the terminal
  • Diff mode — side-by-side TUI diff for jsaw diff

Architecture

jsaw/
├── jsaw-core/     # shared logic: data loading, filtering, records, schema
└── jsaw-bin/      # CLI binary (clap); TUI lives here (ratatui + crossterm)

jsaw-core has no UI dependencies. The TUI in jsaw-bin is the primary interactive surface — fast, keyboard-driven, scriptable context around it.


Development

# CLI only
cargo run -p jsaw-bin -- db ./some-dir

# TUI dev loop
cargo run -p jsaw-bin -- db ./testdata

# Run tests
cargo test -p jsaw-core -p jsaw-bin

Philosophy

  • Schema-first, not schema-required — schemas unlock contextual rendering, validation, and intelligent editing. jsaw degrades gracefully when none exists.
  • The UI is a lens, never the owner — files stay files. TOMLs stay TOMLs. jsaw never holds your data hostage.
  • Inference over annotation — a field named url with a URI value doesn't need to be tagged as a link. It already is one.
  • Unix-friendly — every command pipes in, pipes out. The TUI is opt-in, not mandatory.
  • TUI first — the terminal is the right home for a developer data tool. Fast to open, keyboard-driven, scriptable context around it.