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
Documentis not aBlock, 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_documentsis 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§
Sourcefn descendant_blocks(&'a self) -> Descendants<'a> ⓘ
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.
Sourcefn find_blocks(&'a self, selector: &BlockSelector<'a>) -> FindBlocksIter<'a> ⓘ
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.
Sourcefn find_block_by_id(&'a self, id: &str) -> Option<&'a Block<'a>>
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.
Sourcefn traverse_blocks<F>(&'a self, control: F) -> TraverseBlocks<'a, F> ⓘ
fn traverse_blocks<F>(&'a self, control: F) -> TraverseBlocks<'a, F> ⓘ
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".