///|
pub(all) struct Folder[A] {
inline_ext_default : FoldFn[Inline, A]
block_ext_default : FoldFn[Block, A]
inline : FolderFn[Inline, A]
block : FolderFn[Block, A]
}
///|
pub(all) struct FoldFn[A, B]((Folder[B], B, A) -> B raise FolderError)
///|
pub(all) struct FolderFn[A, B]((Folder[B], B, A) -> FolderResult[B])
///|
/// The type for folder results.
/// `Default` means doing the default fold.
pub(all) enum FolderResult[A] {
Default
Fold(A)
} derive(Eq, Debug)
///|
#deprecated
#doc(hidden)
pub extend FolderResult with Eq::{not_equal, equal}
///|
#deprecated
#doc(hidden)
pub extend FolderResult with @debug.Debug::{to_repr}
///|
pub impl[A] Default for FolderResult[A] with fn default() {
Default
}
///|
#deprecated
#doc(hidden)
pub extend FolderResult with Default::{default}
///|
pub fn[A] Folder::ret(a : A) -> FolderResult[A] {
Fold(a)
}
///|
pub fn[A, B] Folder::none(self : Folder[A], _a : A, _b : B) -> FolderResult[A] {
let _ = self
Default
}
///|
pub fn[A] Folder::inline_ext_none(
self : Folder[A],
_a : A,
_b : Inline,
) -> A raise FolderError {
let _ = self
raise FolderError("unknown inline extension")
}
///|
pub fn[A] Folder::block_ext_none(
self : Folder[A],
_a : A,
_b : Block,
) -> A raise FolderError {
let _ = self
raise FolderError("unknown block extension")
}
///|
pub fn[A] Folder::new(
inline_ext_default~ : FoldFn[Inline, A] = Folder::inline_ext_none,
block_ext_default~ : FoldFn[Block, A] = Folder::block_ext_none,
inline~ : FolderFn[Inline, A] = Folder::none,
block~ : FolderFn[Block, A] = Folder::none,
) -> Folder[A] {
{ inline_ext_default, block_ext_default, inline, block, }
}
///|
pub fn[A] Folder::fold_inline(
self : Folder[A],
acc : A,
i : Inline,
) -> A raise FolderError {
if (self.inline)(self, acc, i) is Fold(acc) {
return acc
}
match i {
Autolink(_)
| Break(_)
| CodeSpan(_)
| RawHtml(_)
| Text(_)
| ExtMathSpan(_) => acc
Image({ v, .. }) | Link({ v, .. }) => self.fold_inline(acc, v.text)
Emphasis({ v, .. }) | StrongEmphasis({ v, .. }) =>
self.fold_inline(acc, v.inline)
Inlines({ v: is_, .. }) => {
let mut acc = acc
for x in is_ {
acc = self.fold_inline(acc, x)
}
acc
}
ExtStrikethrough({ v, .. }) => self.fold_inline(acc, v.0)
// ext => (self.inline_ext_default)!(self, acc, ext)
}
}
///|
pub fn[A] Folder::fold_block(
self : Folder[A],
acc : A,
b : Block,
) -> A raise FolderError {
if (self.block)(self, acc, b) is Fold(acc) {
return acc
}
match b {
BlankLine(_)
| CodeBlock(_)
| HtmlBlock(_)
| LinkRefDefinition(_)
| ThematicBreak(_)
| ExtMathBlock(_) => acc
Heading({ v, .. }) => self.fold_inline(acc, v.inline)
BlockQuote({ v, .. }) => self.fold_block(acc, v.block)
Blocks({ v, .. }) => {
let mut acc = acc
for x in v {
acc = self.fold_block(acc, x)
}
acc
}
List({ v, .. }) => {
let mut acc = acc
for x in v.items {
acc = self.fold_block(acc, x.v.block)
}
acc
}
Paragraph({ v, .. }) => self.fold_inline(acc, v.inline)
ExtTable({ v, .. }) => {
let mut acc = acc
for x in v.rows {
if x.0.v is (Header(is_) | Data(is_)) {
for y in is_ {
acc = self.fold_inline(acc, y.0)
}
}
}
acc
}
ExtFootnoteDefinition({ v, .. }) => self.fold_block(acc, v.block)
// ext => (self.block_ext_default)!(self, acc, ext)
}
}
///|
pub fn[A] Folder::fold_doc(
self : Folder[A],
acc : A,
doc : Doc,
) -> A raise FolderError {
self.fold_block(acc, doc.block)
}