Text.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
  3. * Copyright (c) 2021, Peter Elliott <pelliott@serenityos.org>
  4. * Copyright (c) 2022, the SerenityOS developers.
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #pragma once
  9. #include <AK/ByteString.h>
  10. #include <AK/Noncopyable.h>
  11. #include <AK/OwnPtr.h>
  12. #include <AK/RecursionDecision.h>
  13. #include <AK/Vector.h>
  14. #include <LibMarkdown/Forward.h>
  15. namespace Markdown {
  16. class Text final {
  17. public:
  18. class Node {
  19. public:
  20. virtual void render_to_html(StringBuilder& builder) const = 0;
  21. virtual void render_for_terminal(StringBuilder& builder) const = 0;
  22. virtual void render_for_raw_print(StringBuilder& builder) const = 0;
  23. virtual size_t terminal_length() const = 0;
  24. virtual RecursionDecision walk(Visitor&) const = 0;
  25. virtual ~Node() = default;
  26. };
  27. class EmphasisNode : public Node {
  28. public:
  29. bool strong;
  30. NonnullOwnPtr<Node> child;
  31. EmphasisNode(bool strong, NonnullOwnPtr<Node> child)
  32. : strong(strong)
  33. , child(move(child))
  34. {
  35. }
  36. virtual void render_to_html(StringBuilder& builder) const override;
  37. virtual void render_for_terminal(StringBuilder& builder) const override;
  38. virtual void render_for_raw_print(StringBuilder& builder) const override;
  39. virtual size_t terminal_length() const override;
  40. virtual RecursionDecision walk(Visitor&) const override;
  41. };
  42. class CodeNode : public Node {
  43. public:
  44. NonnullOwnPtr<Node> code;
  45. CodeNode(NonnullOwnPtr<Node> code)
  46. : code(move(code))
  47. {
  48. }
  49. virtual void render_to_html(StringBuilder& builder) const override;
  50. virtual void render_for_terminal(StringBuilder& builder) const override;
  51. virtual void render_for_raw_print(StringBuilder& builder) const override;
  52. virtual size_t terminal_length() const override;
  53. virtual RecursionDecision walk(Visitor&) const override;
  54. };
  55. class BreakNode : public Node {
  56. public:
  57. virtual void render_to_html(StringBuilder& builder) const override;
  58. virtual void render_for_terminal(StringBuilder& builder) const override;
  59. virtual void render_for_raw_print(StringBuilder& builder) const override;
  60. virtual size_t terminal_length() const override;
  61. virtual RecursionDecision walk(Visitor&) const override;
  62. };
  63. class TextNode : public Node {
  64. public:
  65. ByteString text;
  66. bool collapsible;
  67. TextNode(StringView text)
  68. : text(text)
  69. , collapsible(true)
  70. {
  71. }
  72. TextNode(StringView text, bool collapsible)
  73. : text(text)
  74. , collapsible(collapsible)
  75. {
  76. }
  77. virtual void render_to_html(StringBuilder& builder) const override;
  78. virtual void render_for_terminal(StringBuilder& builder) const override;
  79. virtual void render_for_raw_print(StringBuilder& builder) const override;
  80. virtual size_t terminal_length() const override;
  81. virtual RecursionDecision walk(Visitor&) const override;
  82. };
  83. class LinkNode : public Node {
  84. public:
  85. bool is_image;
  86. NonnullOwnPtr<Node> text;
  87. ByteString href;
  88. Optional<int> image_width;
  89. Optional<int> image_height;
  90. LinkNode(bool is_image, NonnullOwnPtr<Node> text, ByteString href, Optional<int> image_width, Optional<int> image_height)
  91. : is_image(is_image)
  92. , text(move(text))
  93. , href(move(href))
  94. , image_width(image_width)
  95. , image_height(image_height)
  96. {
  97. }
  98. bool has_image_dimensions() const
  99. {
  100. return image_width.has_value() || image_height.has_value();
  101. }
  102. virtual void render_to_html(StringBuilder& builder) const override;
  103. virtual void render_for_terminal(StringBuilder& builder) const override;
  104. virtual void render_for_raw_print(StringBuilder& builder) const override;
  105. virtual size_t terminal_length() const override;
  106. virtual RecursionDecision walk(Visitor&) const override;
  107. };
  108. class MultiNode : public Node {
  109. public:
  110. Vector<NonnullOwnPtr<Node>> children;
  111. virtual void render_to_html(StringBuilder& builder) const override;
  112. virtual void render_for_terminal(StringBuilder& builder) const override;
  113. virtual void render_for_raw_print(StringBuilder& builder) const override;
  114. virtual size_t terminal_length() const override;
  115. virtual RecursionDecision walk(Visitor&) const override;
  116. };
  117. class StrikeThroughNode : public Node {
  118. public:
  119. NonnullOwnPtr<Node> striked_text;
  120. StrikeThroughNode(NonnullOwnPtr<Node> striked_text)
  121. : striked_text(move(striked_text))
  122. {
  123. }
  124. virtual void render_to_html(StringBuilder& builder) const override;
  125. virtual void render_for_terminal(StringBuilder& builder) const override;
  126. virtual void render_for_raw_print(StringBuilder& builder) const override;
  127. virtual size_t terminal_length() const override;
  128. virtual RecursionDecision walk(Visitor&) const override;
  129. };
  130. size_t terminal_length() const;
  131. ByteString render_to_html() const;
  132. ByteString render_for_terminal() const;
  133. ByteString render_for_raw_print() const;
  134. RecursionDecision walk(Visitor&) const;
  135. static Text parse(StringView);
  136. private:
  137. struct Token {
  138. ByteString data;
  139. // Flanking basically means that a delimiter run has a non-whitespace,
  140. // non-punctuation character on the corresponding side. For a more exact
  141. // definition, see the CommonMark spec.
  142. bool left_flanking;
  143. bool right_flanking;
  144. bool punct_before;
  145. bool punct_after;
  146. // is_run indicates that this token is a 'delimiter run'. A delimiter
  147. // run occurs when several of the same syntactical character ('`', '_',
  148. // or '*') occur in a row.
  149. bool is_run;
  150. char run_char() const
  151. {
  152. VERIFY(is_run);
  153. return data[0];
  154. }
  155. char run_length() const
  156. {
  157. VERIFY(is_run);
  158. return data.length();
  159. }
  160. bool is_space() const
  161. {
  162. return data[0] == ' ';
  163. }
  164. bool operator==(StringView str) const { return str == data; }
  165. };
  166. static Vector<Token> tokenize(StringView);
  167. static bool can_open(Token const& opening);
  168. static bool can_close_for(Token const& opening, Token const& closing);
  169. static NonnullOwnPtr<MultiNode> parse_sequence(Vector<Token>::ConstIterator& tokens, bool in_link);
  170. static NonnullOwnPtr<Node> parse_break(Vector<Token>::ConstIterator& tokens);
  171. static NonnullOwnPtr<Node> parse_newline(Vector<Token>::ConstIterator& tokens);
  172. static NonnullOwnPtr<Node> parse_emph(Vector<Token>::ConstIterator& tokens, bool in_link);
  173. static NonnullOwnPtr<Node> parse_code(Vector<Token>::ConstIterator& tokens);
  174. static NonnullOwnPtr<Node> parse_link(Vector<Token>::ConstIterator& tokens);
  175. static NonnullOwnPtr<Node> parse_strike_through(Vector<Token>::ConstIterator& tokens);
  176. OwnPtr<Node> m_node;
  177. };
  178. }