From 24e7196158e4673c90aca5c6bff89319d3427282 Mon Sep 17 00:00:00 2001 From: Ben Wiederhake Date: Fri, 10 Sep 2021 21:36:29 +0200 Subject: LibMarkdown: Implement introspection of the document tree --- Userland/Libraries/LibMarkdown/Block.h | 3 + Userland/Libraries/LibMarkdown/BlockQuote.cpp | 10 +++ Userland/Libraries/LibMarkdown/BlockQuote.h | 1 + Userland/Libraries/LibMarkdown/CodeBlock.cpp | 17 +++++ Userland/Libraries/LibMarkdown/CodeBlock.h | 1 + Userland/Libraries/LibMarkdown/ContainerBlock.cpp | 16 +++++ Userland/Libraries/LibMarkdown/ContainerBlock.h | 1 + Userland/Libraries/LibMarkdown/Document.cpp | 10 +++ Userland/Libraries/LibMarkdown/Document.h | 11 ++++ Userland/Libraries/LibMarkdown/Forward.h | 26 ++++++++ Userland/Libraries/LibMarkdown/Heading.cpp | 10 +++ Userland/Libraries/LibMarkdown/Heading.h | 1 + Userland/Libraries/LibMarkdown/HorizontalRule.cpp | 10 +++ Userland/Libraries/LibMarkdown/HorizontalRule.h | 1 + Userland/Libraries/LibMarkdown/List.cpp | 16 +++++ Userland/Libraries/LibMarkdown/List.h | 1 + Userland/Libraries/LibMarkdown/Paragraph.cpp | 10 +++ Userland/Libraries/LibMarkdown/Paragraph.h | 1 + Userland/Libraries/LibMarkdown/Table.cpp | 35 +++++++++++ Userland/Libraries/LibMarkdown/Table.h | 3 + Userland/Libraries/LibMarkdown/Text.cpp | 75 +++++++++++++++++++++++ Userland/Libraries/LibMarkdown/Text.h | 10 +++ Userland/Libraries/LibMarkdown/Visitor.h | 50 +++++++++++++++ 23 files changed, 319 insertions(+) create mode 100644 Userland/Libraries/LibMarkdown/Forward.h create mode 100644 Userland/Libraries/LibMarkdown/Visitor.h (limited to 'Userland/Libraries') diff --git a/Userland/Libraries/LibMarkdown/Block.h b/Userland/Libraries/LibMarkdown/Block.h index bc5ec0e897..ed71c9933e 100644 --- a/Userland/Libraries/LibMarkdown/Block.h +++ b/Userland/Libraries/LibMarkdown/Block.h @@ -6,8 +6,10 @@ #pragma once +#include #include #include +#include namespace Markdown { @@ -17,6 +19,7 @@ public: virtual String render_to_html(bool tight = false) const = 0; virtual String render_for_terminal(size_t view_width = 0) const = 0; + virtual RecursionDecision walk(Visitor&) const = 0; }; } diff --git a/Userland/Libraries/LibMarkdown/BlockQuote.cpp b/Userland/Libraries/LibMarkdown/BlockQuote.cpp index a40a24dbc1..df879a3c05 100644 --- a/Userland/Libraries/LibMarkdown/BlockQuote.cpp +++ b/Userland/Libraries/LibMarkdown/BlockQuote.cpp @@ -6,6 +6,7 @@ #include #include +#include namespace Markdown { @@ -24,6 +25,15 @@ String BlockQuote::render_for_terminal(size_t view_width) const return m_contents->render_for_terminal(view_width); } +RecursionDecision BlockQuote::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + + return m_contents->walk(visitor); +} + OwnPtr
BlockQuote::parse(LineIterator& lines) { lines.push_context(LineIterator::Context::block_quote()); diff --git a/Userland/Libraries/LibMarkdown/BlockQuote.h b/Userland/Libraries/LibMarkdown/BlockQuote.h index 5c9abbbfab..a3eacdb0e7 100644 --- a/Userland/Libraries/LibMarkdown/BlockQuote.h +++ b/Userland/Libraries/LibMarkdown/BlockQuote.h @@ -22,6 +22,7 @@ public: virtual String render_to_html(bool tight = false) const override; virtual String render_for_terminal(size_t view_width = 0) const override; + virtual RecursionDecision walk(Visitor&) const override; static OwnPtr
parse(LineIterator& lines); diff --git a/Userland/Libraries/LibMarkdown/CodeBlock.cpp b/Userland/Libraries/LibMarkdown/CodeBlock.cpp index d433d3c61e..455045d9ad 100644 --- a/Userland/Libraries/LibMarkdown/CodeBlock.cpp +++ b/Userland/Libraries/LibMarkdown/CodeBlock.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include namespace Markdown { @@ -54,6 +55,22 @@ String CodeBlock::render_for_terminal(size_t) const return builder.build(); } +RecursionDecision CodeBlock::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + + rd = visitor.visit(m_code); + if (rd != RecursionDecision::Recurse) + return rd; + + // Don't recurse on m_language and m_style. + + // Normalize return value. + return RecursionDecision::Continue; +} + static Regex style_spec_re("\\s*([\\*_]*)\\s*([^\\*_\\s]*).*"); OwnPtr CodeBlock::parse(LineIterator& lines) diff --git a/Userland/Libraries/LibMarkdown/CodeBlock.h b/Userland/Libraries/LibMarkdown/CodeBlock.h index c4b7ff7885..aa6c7f099b 100644 --- a/Userland/Libraries/LibMarkdown/CodeBlock.h +++ b/Userland/Libraries/LibMarkdown/CodeBlock.h @@ -25,6 +25,7 @@ public: virtual String render_to_html(bool tight = false) const override; virtual String render_for_terminal(size_t view_width = 0) const override; + virtual RecursionDecision walk(Visitor&) const override; static OwnPtr parse(LineIterator& lines); private: diff --git a/Userland/Libraries/LibMarkdown/ContainerBlock.cpp b/Userland/Libraries/LibMarkdown/ContainerBlock.cpp index 8ae1213459..0682bc89b0 100644 --- a/Userland/Libraries/LibMarkdown/ContainerBlock.cpp +++ b/Userland/Libraries/LibMarkdown/ContainerBlock.cpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace Markdown { @@ -50,6 +51,21 @@ String ContainerBlock::render_for_terminal(size_t view_width) const return builder.build(); } +RecursionDecision ContainerBlock::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + + for (auto const& block : m_blocks) { + rd = block.walk(visitor); + if (rd == RecursionDecision::Break) + return rd; + } + + return RecursionDecision::Continue; +} + template static bool try_parse_block(LineIterator& lines, NonnullOwnPtrVector& blocks) { diff --git a/Userland/Libraries/LibMarkdown/ContainerBlock.h b/Userland/Libraries/LibMarkdown/ContainerBlock.h index c737a6fc0e..e1fe9a9b28 100644 --- a/Userland/Libraries/LibMarkdown/ContainerBlock.h +++ b/Userland/Libraries/LibMarkdown/ContainerBlock.h @@ -27,6 +27,7 @@ public: virtual String render_to_html(bool tight = false) const override; virtual String render_for_terminal(size_t view_width = 0) const override; + virtual RecursionDecision walk(Visitor&) const override; static OwnPtr parse(LineIterator& lines); diff --git a/Userland/Libraries/LibMarkdown/Document.cpp b/Userland/Libraries/LibMarkdown/Document.cpp index e1fd47cc9f..ee53bf9686 100644 --- a/Userland/Libraries/LibMarkdown/Document.cpp +++ b/Userland/Libraries/LibMarkdown/Document.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace Markdown { @@ -41,6 +42,15 @@ String Document::render_for_terminal(size_t view_width) const return m_container->render_for_terminal(view_width); } +RecursionDecision Document::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + + return m_container->walk(visitor); +} + OwnPtr Document::parse(const StringView& str) { const Vector lines_vec = str.lines(); diff --git a/Userland/Libraries/LibMarkdown/Document.h b/Userland/Libraries/LibMarkdown/Document.h index 796fdbda10..db3e0fc0d6 100644 --- a/Userland/Libraries/LibMarkdown/Document.h +++ b/Userland/Libraries/LibMarkdown/Document.h @@ -23,6 +23,17 @@ public: String render_to_inline_html() const; String render_for_terminal(size_t view_width = 0) const; + /* + * Walk recursively through the document tree. Returning `RecursionDecision::Recurse` from + * `Visitor::visit` proceeds with the next element of the pre-order walk, usually a child element. + * Returning `RecursionDecision::Continue` skips the subtree, and usually proceeds with the next + * sibling. Returning `RecursionDecision::Break` breaks the recursion, with no further calls to + * any of the `Visitor::visit` methods. + * + * Note that `walk()` will only return `RecursionDecision::Continue` or `RecursionDecision::Break`. + */ + RecursionDecision walk(Visitor&) const; + static OwnPtr parse(const StringView&); private: diff --git a/Userland/Libraries/LibMarkdown/Forward.h b/Userland/Libraries/LibMarkdown/Forward.h new file mode 100644 index 0000000000..4edf3ce6f2 --- /dev/null +++ b/Userland/Libraries/LibMarkdown/Forward.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021, Ben Wiederhake + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +namespace Markdown { + +class Block; +class Document; +class Text; + +class BlockQuote; +class CodeBlock; +class ContainerBlock; +class Heading; +class HoriziontalRule; +class List; +class Paragraph; +class Table; + +class Visitor; + +} diff --git a/Userland/Libraries/LibMarkdown/Heading.cpp b/Userland/Libraries/LibMarkdown/Heading.cpp index 66c8d4b02d..1dd321f8e5 100644 --- a/Userland/Libraries/LibMarkdown/Heading.cpp +++ b/Userland/Libraries/LibMarkdown/Heading.cpp @@ -6,6 +6,7 @@ #include #include +#include namespace Markdown { @@ -35,6 +36,15 @@ String Heading::render_for_terminal(size_t) const return builder.build(); } +RecursionDecision Heading::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + + return m_text.walk(visitor); +} + OwnPtr Heading::parse(LineIterator& lines) { if (lines.is_end()) diff --git a/Userland/Libraries/LibMarkdown/Heading.h b/Userland/Libraries/LibMarkdown/Heading.h index 4e7ffa1948..da8dc49102 100644 --- a/Userland/Libraries/LibMarkdown/Heading.h +++ b/Userland/Libraries/LibMarkdown/Heading.h @@ -27,6 +27,7 @@ public: virtual String render_to_html(bool tight = false) const override; virtual String render_for_terminal(size_t view_width = 0) const override; + virtual RecursionDecision walk(Visitor&) const override; static OwnPtr parse(LineIterator& lines); private: diff --git a/Userland/Libraries/LibMarkdown/HorizontalRule.cpp b/Userland/Libraries/LibMarkdown/HorizontalRule.cpp index 5d884df3db..2e696143ed 100644 --- a/Userland/Libraries/LibMarkdown/HorizontalRule.cpp +++ b/Userland/Libraries/LibMarkdown/HorizontalRule.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace Markdown { @@ -24,6 +25,15 @@ String HorizontalRule::render_for_terminal(size_t view_width) const return builder.to_string(); } +RecursionDecision HorizontalRule::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + // Normalize return value. + return RecursionDecision::Continue; +} + OwnPtr HorizontalRule::parse(LineIterator& lines) { if (lines.is_end()) diff --git a/Userland/Libraries/LibMarkdown/HorizontalRule.h b/Userland/Libraries/LibMarkdown/HorizontalRule.h index 034b2233ea..affa84842a 100644 --- a/Userland/Libraries/LibMarkdown/HorizontalRule.h +++ b/Userland/Libraries/LibMarkdown/HorizontalRule.h @@ -23,6 +23,7 @@ public: virtual String render_to_html(bool tight = false) const override; virtual String render_for_terminal(size_t view_width = 0) const override; + virtual RecursionDecision walk(Visitor&) const override; static OwnPtr parse(LineIterator& lines); }; diff --git a/Userland/Libraries/LibMarkdown/List.cpp b/Userland/Libraries/LibMarkdown/List.cpp index 3e2b63a4df..187a5e5c11 100644 --- a/Userland/Libraries/LibMarkdown/List.cpp +++ b/Userland/Libraries/LibMarkdown/List.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace Markdown { @@ -54,6 +55,21 @@ String List::render_for_terminal(size_t) const return builder.build(); } +RecursionDecision List::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + + for (auto const& block : m_items) { + rd = block->walk(visitor); + if (rd == RecursionDecision::Break) + return rd; + } + + return RecursionDecision::Continue; +} + OwnPtr List::parse(LineIterator& lines) { Vector> items; diff --git a/Userland/Libraries/LibMarkdown/List.h b/Userland/Libraries/LibMarkdown/List.h index 2881902200..5e62a78a6c 100644 --- a/Userland/Libraries/LibMarkdown/List.h +++ b/Userland/Libraries/LibMarkdown/List.h @@ -26,6 +26,7 @@ public: virtual String render_to_html(bool tight = false) const override; virtual String render_for_terminal(size_t view_width = 0) const override; + virtual RecursionDecision walk(Visitor&) const override; static OwnPtr parse(LineIterator& lines); diff --git a/Userland/Libraries/LibMarkdown/Paragraph.cpp b/Userland/Libraries/LibMarkdown/Paragraph.cpp index df0e3f2aea..ab30bdd0bb 100644 --- a/Userland/Libraries/LibMarkdown/Paragraph.cpp +++ b/Userland/Libraries/LibMarkdown/Paragraph.cpp @@ -6,6 +6,7 @@ #include #include +#include namespace Markdown { @@ -34,4 +35,13 @@ String Paragraph::render_for_terminal(size_t) const return builder.build(); } +RecursionDecision Paragraph::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + + return m_text.walk(visitor); +} + } diff --git a/Userland/Libraries/LibMarkdown/Paragraph.h b/Userland/Libraries/LibMarkdown/Paragraph.h index e9c8db692e..e2af98a717 100644 --- a/Userland/Libraries/LibMarkdown/Paragraph.h +++ b/Userland/Libraries/LibMarkdown/Paragraph.h @@ -24,6 +24,7 @@ public: virtual String render_to_html(bool tight = false) const override; virtual String render_for_terminal(size_t view_width = 0) const override; + virtual RecursionDecision walk(Visitor&) const override; private: Text m_text; diff --git a/Userland/Libraries/LibMarkdown/Table.cpp b/Userland/Libraries/LibMarkdown/Table.cpp index 37f3c1ad5a..995738f718 100644 --- a/Userland/Libraries/LibMarkdown/Table.cpp +++ b/Userland/Libraries/LibMarkdown/Table.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace Markdown { @@ -96,6 +97,21 @@ String Table::render_to_html(bool) const return builder.to_string(); } +RecursionDecision Table::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + + for (auto const& column : m_columns) { + rd = column.walk(visitor); + if (rd == RecursionDecision::Break) + return rd; + } + + return RecursionDecision::Continue; +} + OwnPtr Table::parse(LineIterator& lines) { auto peek_it = lines; @@ -207,4 +223,23 @@ OwnPtr
Table::parse(LineIterator& lines) return table; } +RecursionDecision Table::Column::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + + rd = header.walk(visitor); + if (rd != RecursionDecision::Recurse) + return rd; + + for (auto const& row : rows) { + rd = row.walk(visitor); + if (rd == RecursionDecision::Break) + return rd; + } + + return RecursionDecision::Continue; +} + } diff --git a/Userland/Libraries/LibMarkdown/Table.h b/Userland/Libraries/LibMarkdown/Table.h index a4f4d0e578..c0073a0ad9 100644 --- a/Userland/Libraries/LibMarkdown/Table.h +++ b/Userland/Libraries/LibMarkdown/Table.h @@ -27,6 +27,8 @@ public: Vector rows; Alignment alignment { Alignment::Left }; size_t relative_width { 0 }; + + RecursionDecision walk(Visitor&) const; }; Table() { } @@ -34,6 +36,7 @@ public: virtual String render_to_html(bool tight = false) const override; virtual String render_for_terminal(size_t view_width = 0) const override; + virtual RecursionDecision walk(Visitor&) const override; static OwnPtr
parse(LineIterator& lines); private: diff --git a/Userland/Libraries/LibMarkdown/Text.cpp b/Userland/Libraries/LibMarkdown/Text.cpp index 64a548fb1a..dfa72ab319 100644 --- a/Userland/Libraries/LibMarkdown/Text.cpp +++ b/Userland/Libraries/LibMarkdown/Text.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,15 @@ size_t Text::EmphasisNode::terminal_length() const return child->terminal_length(); } +RecursionDecision Text::EmphasisNode::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + + return child->walk(visitor); +} + void Text::CodeNode::render_to_html(StringBuilder& builder) const { builder.append(""); @@ -58,6 +68,15 @@ size_t Text::CodeNode::terminal_length() const return code->terminal_length(); } +RecursionDecision Text::CodeNode::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + + return code->walk(visitor); +} + void Text::BreakNode::render_to_html(StringBuilder& builder) const { builder.append("
"); @@ -72,6 +91,15 @@ size_t Text::BreakNode::terminal_length() const return 0; } +RecursionDecision Text::BreakNode::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + // Normalize return value + return RecursionDecision::Continue; +} + void Text::TextNode::render_to_html(StringBuilder& builder) const { builder.append(escape_html_entities(text)); @@ -95,6 +123,18 @@ size_t Text::TextNode::terminal_length() const return text.length(); } +RecursionDecision Text::TextNode::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + rd = visitor.visit(text); + if (rd != RecursionDecision::Recurse) + return rd; + // Normalize return value + return RecursionDecision::Continue; +} + void Text::LinkNode::render_to_html(StringBuilder& builder) const { if (is_image) { @@ -134,6 +174,17 @@ size_t Text::LinkNode::terminal_length() const return text->terminal_length(); } +RecursionDecision Text::LinkNode::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + + // Don't recurse on href. + + return text->walk(visitor); +} + void Text::MultiNode::render_to_html(StringBuilder& builder) const { for (auto& child : children) { @@ -157,6 +208,21 @@ size_t Text::MultiNode::terminal_length() const return length; } +RecursionDecision Text::MultiNode::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + + for (auto const& child : children) { + rd = child.walk(visitor); + if (rd == RecursionDecision::Break) + return rd; + } + + return RecursionDecision::Continue; +} + size_t Text::terminal_length() const { return m_node->terminal_length(); @@ -176,6 +242,15 @@ String Text::render_for_terminal() const return builder.build().trim(" \n\t"); } +RecursionDecision Text::walk(Visitor& visitor) const +{ + RecursionDecision rd = visitor.visit(*this); + if (rd != RecursionDecision::Recurse) + return rd; + + return m_node->walk(visitor); +} + Text Text::parse(StringView const& str) { Text text; diff --git a/Userland/Libraries/LibMarkdown/Text.h b/Userland/Libraries/LibMarkdown/Text.h index bacfedb0e2..7549fb94eb 100644 --- a/Userland/Libraries/LibMarkdown/Text.h +++ b/Userland/Libraries/LibMarkdown/Text.h @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include namespace Markdown { @@ -21,6 +23,7 @@ public: virtual void render_to_html(StringBuilder& builder) const = 0; virtual void render_for_terminal(StringBuilder& builder) const = 0; virtual size_t terminal_length() const = 0; + virtual RecursionDecision walk(Visitor&) const = 0; virtual ~Node() { } }; @@ -39,6 +42,7 @@ public: virtual void render_to_html(StringBuilder& builder) const override; virtual void render_for_terminal(StringBuilder& builder) const override; virtual size_t terminal_length() const override; + virtual RecursionDecision walk(Visitor&) const override; }; class CodeNode : public Node { @@ -53,6 +57,7 @@ public: virtual void render_to_html(StringBuilder& builder) const override; virtual void render_for_terminal(StringBuilder& builder) const override; virtual size_t terminal_length() const override; + virtual RecursionDecision walk(Visitor&) const override; }; class BreakNode : public Node { @@ -60,6 +65,7 @@ public: virtual void render_to_html(StringBuilder& builder) const override; virtual void render_for_terminal(StringBuilder& builder) const override; virtual size_t terminal_length() const override; + virtual RecursionDecision walk(Visitor&) const override; }; class TextNode : public Node { @@ -82,6 +88,7 @@ public: virtual void render_to_html(StringBuilder& builder) const override; virtual void render_for_terminal(StringBuilder& builder) const override; virtual size_t terminal_length() const override; + virtual RecursionDecision walk(Visitor&) const override; }; class LinkNode : public Node { @@ -100,6 +107,7 @@ public: virtual void render_to_html(StringBuilder& builder) const override; virtual void render_for_terminal(StringBuilder& builder) const override; virtual size_t terminal_length() const override; + virtual RecursionDecision walk(Visitor&) const override; }; class MultiNode : public Node { @@ -109,12 +117,14 @@ public: virtual void render_to_html(StringBuilder& builder) const override; virtual void render_for_terminal(StringBuilder& builder) const override; virtual size_t terminal_length() const override; + virtual RecursionDecision walk(Visitor&) const override; }; size_t terminal_length() const; String render_to_html() const; String render_for_terminal() const; + RecursionDecision walk(Visitor&) const; static Text parse(StringView const&); diff --git a/Userland/Libraries/LibMarkdown/Visitor.h b/Userland/Libraries/LibMarkdown/Visitor.h new file mode 100644 index 0000000000..d2035811a9 --- /dev/null +++ b/Userland/Libraries/LibMarkdown/Visitor.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021, Ben Wiederhake + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Markdown { + +class Visitor { +public: + Visitor() = default; + virtual ~Visitor() = default; + + virtual RecursionDecision visit(Document const&) { return RecursionDecision::Recurse; } + + virtual RecursionDecision visit(BlockQuote const&) { return RecursionDecision::Recurse; } + virtual RecursionDecision visit(CodeBlock const&) { return RecursionDecision::Recurse; } + virtual RecursionDecision visit(ContainerBlock const&) { return RecursionDecision::Recurse; } + virtual RecursionDecision visit(Heading const&) { return RecursionDecision::Recurse; } + virtual RecursionDecision visit(HorizontalRule const&) { return RecursionDecision::Recurse; } + virtual RecursionDecision visit(List const&) { return RecursionDecision::Recurse; } + virtual RecursionDecision visit(Paragraph const&) { return RecursionDecision::Recurse; } + + virtual RecursionDecision visit(Table const&) { return RecursionDecision::Recurse; } + virtual RecursionDecision visit(Table::Column const&) { return RecursionDecision::Recurse; } + + virtual RecursionDecision visit(Text const&) { return RecursionDecision::Recurse; } + virtual RecursionDecision visit(Text::BreakNode const&) { return RecursionDecision::Recurse; } + virtual RecursionDecision visit(Text::CodeNode const&) { return RecursionDecision::Recurse; } + virtual RecursionDecision visit(Text::EmphasisNode const&) { return RecursionDecision::Recurse; } + virtual RecursionDecision visit(Text::LinkNode const&) { return RecursionDecision::Recurse; } + virtual RecursionDecision visit(Text::MultiNode const&) { return RecursionDecision::Recurse; } + virtual RecursionDecision visit(Text::TextNode const&) { return RecursionDecision::Recurse; } + + virtual RecursionDecision visit(String const&) { return RecursionDecision::Recurse; } +}; + +} -- cgit v1.2.3