asciidoc_parser/blocks/
is_block.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
use std::{fmt::Debug, slice::Iter};

use crate::{blocks::Block, strings::CowStr, HasSpan};

/// Block elements form the main structure of an AsciiDoc document, starting
/// with the document itself.
///
/// A block element (aka block) is a discrete, line-oriented chunk of content in
/// an AsciiDoc document. Once parsed, that chunk of content becomes a block
/// element in the parsed document model. Certain blocks may contain other
/// blocks, so we say that blocks can be nested. The converter visits each block
/// in turn, in document order, converting it to a corresponding chunk of
/// output.
///
/// This trait implements many of the same core methods as the
/// [Block](crate::blocks::Block) enum but provides a mechanism for third-party
/// code to extend the behavior of blocks.
pub trait IsBlock<'src>: HasSpan<'src> + Clone + Debug + Eq + PartialEq {
    /// Returns the [ContentModel] for this block.
    fn content_model(&self) -> ContentModel;

    /// Returns the context for this block.
    ///
    /// A block’s context is also sometimes referred to as a name, such as an
    /// example block, a sidebar block, an admonition block, or a section.
    ///
    /// Every block has a context. The context is often implied by the syntax,
    /// but can be declared explicitly in certain cases. The context is what
    /// distinguishes one kind of block from another. You can think of the
    /// context as the block’s type.
    ///
    /// For that reason, the context is not defined as an enumeration, but
    /// rather as a string type that is optimized for the case where predefined
    /// constants are viable.
    fn context(&self) -> CowStr<'src>;

    /// Returns an iterator over the nested blocks contained within
    /// this block.
    ///
    /// Many block types do not have nested blocks so the default implementation
    /// returns an empty iterator.
    fn nested_blocks(&'src self) -> Iter<'src, Block<'src>> {
        const NO_BLOCKS: &[Block<'static>] = &[];
        NO_BLOCKS.iter()
    }
}

/// The content model of a block determines what kind of content the block can
/// have (if any) and how that content is processed.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ContentModel {
    /// A block that may only contain other blocks (e.g., a section)
    Compound,

    /// A block that's treated as contiguous lines of paragraph text (and
    /// subject to normal substitutions) (e.g., a paragraph block)
    Simple,

    /// A block that holds verbatim text (displayed "`as is`") (and subject to
    /// verbatim substitutions) (e.g., a listing block)
    Verbatim,

    /// A block that holds unprocessed content passed directly through to the
    /// output with no substitutions applied (e.g., a passthrough block)
    Raw,

    /// Ablock that has no content (e.g., an image block)
    Empty,

    /// A special content model reserved for tables that enforces a fixed
    /// structure
    Table,
}