Text.h 5.5 KB

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