github iwe-org/iwe iwe-v0.9.0
v0.9.0

latest releases: iwec-v0.9.0, iwes-v0.9.0
7 hours ago

iwe

Added

  • --project / --add-fields accept block-addressed sources: { $content: PREDICATE } narrows a document's body to the selected blocks (rendered at their original depth), $blocks / { $blocks: PREDICATE } lists each selected block as type / path / text data, and { $matches: REGEX } greps matching lines with their section paths.
  • find markdown output renders $blocks and $matches entries one line each as key › section path › text, and switches to the fenced-block form with the narrowed body when a parameterized $content field is projected.
  • --project accepts a bare block predicate — --project '$header: {}' renders each document's body narrowed to the selected blocks (the headers-only form) under key and content fields, so --format json/yaml output keeps the document identity that the markdown fence already carries.
  • update gains a block-edit flag per operator — --replace, --replace-text, --insert-before, --insert-after, --append, --delete — each taking a { <selector>, payload } mapping and composing with --set / --unset into one atomic update. A validation failure (unmet expect, overlapping selections, incompatible target) prints the offending blocks and exits non-zero without writing. --replace-text accepts a from-less argument ({ $header: Goals, to: Aims }) that rewrites the block's entire own text — the clean way to rename a header or restate a line.
  • A block edit targeting a $header acts on the heading line alone: --delete '{ $header: Goals }' dissolves the section (contents re-attach to the parent and re-level) and --replace '{ $header: Goals, content: "## Aims" }' retitles it (contents kept), while --delete '{ $section: Goals }' removes the whole tree. --insert-after '{ $header: Goals, content: ... }' adds content at the top of the section, below the heading line.
  • update and delete gain --expect — a document-level guard asserting the number of matched documents (N or { min, max }); on a mismatch the command lists the matched documents as key › title and exits non-zero without writing. Both also gain --strict, which requires an expect guard on every mutating application (the document-level --expect and each block operator's expect) and aborts before writing if any is missing; --dry-run is exempt so counts can be learned.
  • find --blocks PRED adds a blocks field listing each block matching the predicate (lowers to addFields: { blocks: { $blocks: PRED } }), and find --matches PATTERN restricts results to documents whose content matches PATTERN and adds a matches grep field (lowers to a $content membership filter plus addFields: { matches: { $matches: PATTERN } }).
  • find --filter accepts the $content block-membership operator — --filter '$content: { $header: Status }' selects documents that contain at least one block satisfying the predicate.

Changed

  • update -k / --key is repeatable, matching find: one key lowers to $eq, two or more to $in (body-overwrite mode still takes exactly one). Previously it accepted a single key only.
  • update writes only documents whose rendered content actually changes and reports honestly — Updated N document(s) when every matched document changed, Matched N document(s), M changed otherwise (No documents matched when none) — so a no-op edit (e.g. expect: 0) leaves the file, and its mtime, untouched.

Fixed

  • --project / --add-fields now parse the argument as a YAML mapping whenever it contains a : or {, and report a parse error on malformed input instead of silently falling back to the comma list. Previously an unbraced multi-field mapping like --project 'a: { $content: ... }, b: { $content: ... }' failed the YAML parse, degraded to the comma list, and emitted a: null, b: null with no error. The comma list keeps the name, name=source, and bare $selector forms; write multi-field or block projections as a braced mapping.

iwec

Added

  • iwe_query tool runs an IWE query/block-selection operation document — operation is find / count / update / delete and document is the operation as a YAML string. It exposes the $content membership filter, the $content / $blocks / $matches projection sources, and the block update operators ($replace, $replaceText, $insertBefore, $insertAfter, $append, $delete). find and count read; update applies frontmatter and block edits; delete removes documents with reference cleanup. The tool is always strict: every mutating application must carry an expect guard or the operation is refused with the missing guards named. update / delete accept dry_run to preview without writing.

liwe

Added

  • query::block module with the BlockPredicate grammar for addressing blocks inside a document: text and regex predicates, $within / $contains axes, per-type operators ($section, $header, $paragraph, $item, $list, $quote, $code, $table, $ref, $hr), $references, and $and / $or / $nor composition.
  • Block-addressed projection sources: { $content: PREDICATE } renders the selected blocks, $blocks reports each selected block as type / path / text, and { $matches: REGEX } greps matching lines with their section paths — all evaluated through the new query::block_eval::BlockIndex.
  • IntoBlockPredicate trait accepting scalar shorthands wherever a block predicate is expected.
  • FindOp::add_fields sets an additive (addFields) projection; CountOp and DeleteOp implement From<FindOp>, reinterpreting a built find with its projection dropped.
  • project accepts a $-prefixed block predicate mapping (project: { $header: {} }), lowering it to a key field and a content field carrying the narrowed body.
  • Block update operators in the update document — $replace, $replaceText, $insertBefore, $insertAfter, $append, $delete — each pairing a block predicate selector with its payload and an optional expect guard, validated and applied atomically; represented by BlockUpdate, BlockUpdateOp, and Expect on Update::block_ops.
  • Unit block operators act on their target as selected: a $header node covers its heading line alone ($delete dissolves the section, a heading $replace retitles it) while a $section covers the whole tree.
  • UpdateOp and DeleteOp carry an optional expect guard asserting the number of matched documents; on violation nothing is written and the error lists each matched document.
  • $content filter operator (Filter::Content) matches documents holding at least one block satisfying a block predicate; it composes with every other filter clause.
  • query::strict_guard_violations names the mutating applications that lack an expect guard.

Changed

  • query::execute returns Result<Outcome, block_update::EvalError> (was Outcome) so a failed block update reports its validation error instead of writing; find, count, and delete always return Ok.
  • Update carries block_ops: Vec<BlockUpdate> alongside the frontmatter operators.
  • Projection carries a base: ProjectionBase (Empty / Frontmatter / Document) in place of mode: ProjectionMode, so FindOp::project is a plain Projection (was Option<Projection>); Projection::document_fields() replaces Projection::default_for_find().
  • ProjectionContext is constructed with ProjectionContext::new(graph, key) (was a public struct literal).

Fixed

  • A mis-typed project mapping now reports a parse error instead of being silently read as a comma list of frontmatter field names and yielding null.

Removed

  • query::prelude module (with its WithFilter trait) — the Rust builder functions moved into the test suite; construct Operation, FindOp, and Filter directly.
  • query::project::apply_projection_or_defaultapply_projection covers the no-projection case.

Don't miss a new iwe release

NewReleases is sending notifications on new releases.