Skip to main content

FindBlocks

Trait FindBlocks 

Source
pub trait FindBlocks<'a>: Sealed<'a> {
    // Provided methods
    fn descendant_blocks(&'a self) -> Descendants<'a>  { ... }
    fn find_blocks(&'a self, selector: &BlockSelector<'a>) -> FindBlocksIter<'a>  { ... }
    fn find_block_by_id(&'a self, id: &str) -> Option<&'a Block<'a>> { ... }
    fn traverse_blocks<F>(&'a self, control: F) -> TraverseBlocks<'a, F> 
       where F: FnMut(&Block<'a>) -> Descend { ... }
}
Expand description

A search over a Document or a Block for its descendant blocks.

This is the Rust-native counterpart to Asciidoctor’s block-finding API. Where Asciidoctor exposes find_by(selector = {}, &block_filter), this trait leans on Rust’s iterator patterns: descendant_blocks is a plain Iterator you compose with the standard combinators, find_blocks takes a declarative BlockSelector, and traverse_blocks gives per-block control over the walk (including subtree pruning) via the Descend enum.

The trait is implemented for Document and Block and is sealed (it cannot be implemented for other types); bring it into scope to call its methods. All of the returned iterators yield &Block in document order and never yield the receiver itself.

§Traversal model

The walk is depth-first and yields blocks in document order. It reaches every block reachable through the tree, including the children of Markdown-style blockquotes (whose children are not exposed through the 'src-bound IsBlock::nested_blocks because they borrow the block’s own owned source). AsciiDoc table cells are separate nested documents and are not entered by default; opt in with BlockSelector::traverse_documents (the analog of Asciidoctor’s traverse_documents selector key).

§Differences from Asciidoctor

  • The receiver is never yielded. These iterators visit descendants only. (Asciidoctor includes the receiver as a candidate.) A Document is not a Block, so “descendants only” is the one rule that reads the same on both receivers. To include a starting block, chain it yourself: std::iter::once(block).chain(block.descendant_blocks()).
  • traverse_documents is off by default (as in Asciidoctor).

§Examples

use asciidoc_parser::{
    Parser,
    blocks::{Block, BlockSelector, Descend, FindBlocks, IsBlock},
};

let doc =
    Parser::default().parse("= Title\n\n== First\n\n[source,rust]\n----\nfn main() {}\n----\n");

// The Rust-native core: a plain iterator you compose with std combinators.
let sections = doc
    .descendant_blocks()
    .filter(|b| matches!(b, Block::Section(_)))
    .count();
assert_eq!(sections, 1);

// A declarative selector, like `find_by(context: :listing, style: 'source')`.
let listings: Vec<_> = doc
    .find_blocks(&BlockSelector::new().context("listing").style("source"))
    .collect();
assert_eq!(listings.len(), 1);

// Per-block traversal control, like the Asciidoctor block filter. Collect
// only top-level sidebars: include each sidebar but do not descend into it,
// and reject everything else (so nested sidebars are not reported).
let top_sidebars: Vec<_> = doc
    .traverse_blocks(|b| {
        if b.resolved_context().as_ref() == "sidebar" {
            Descend::Prune
        } else {
            Descend::Reject
        }
    })
    .collect();
assert!(top_sidebars.is_empty());

Provided Methods§

Source

fn descendant_blocks(&'a self) -> Descendants<'a>

Returns a depth-first, document-order iterator over every descendant block.

This is the equivalent of Asciidoctor’s find_by with no arguments. Because it is an ordinary Iterator, the idiomatic way to search is to compose it with the standard combinators (filter, find, map, …).

AsciiDoc table cells are not entered; use find_blocks with BlockSelector::traverse_documents to include them.

Source

fn find_blocks(&'a self, selector: &BlockSelector<'a>) -> FindBlocksIter<'a>

Returns an iterator over the descendant blocks that match selector.

This mirrors Asciidoctor’s find_by(selector): a block is yielded when it matches every field the selector sets (see BlockSelector). Traversal still descends through non-matching blocks, so matches at any depth are found.

Source

fn find_block_by_id(&'a self, id: &str) -> Option<&'a Block<'a>>

Returns the first descendant block whose id equals id, if any.

Block ids are unique within a document, so at most one block can match. This is the equivalent of Asciidoctor’s find_by(id: '…').first.

Source

fn traverse_blocks<F>(&'a self, control: F) -> TraverseBlocks<'a, F>
where F: FnMut(&Block<'a>) -> Descend,

Returns an iterator that walks the descendant blocks under the control of control, which is called once per block, in document order, to decide whether the block is yielded and whether its children are visited.

This is the equivalent of Asciidoctor’s find_by block filter; the Descend return value plays the role of the filter’s :accept / :skip / :reject / :prune symbols and is the mechanism for pruning whole subtrees. AsciiDoc table cells are not entered.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§

Source§

impl<'a> FindBlocks<'a> for Block<'a>

Source§

impl<'a> FindBlocks<'a> for Document<'a>