173
|
1 //===--- Markup.h -------------------------------------------*- C++-*------===//
|
|
2 //
|
|
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
4 // See https://llvm.org/LICENSE.txt for license information.
|
|
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
6 //
|
|
7 //===----------------------------------------------------------------------===//
|
|
8 //
|
|
9 // A model of formatted text that can be rendered to plaintext or markdown.
|
|
10 //
|
|
11 //===----------------------------------------------------------------------===//
|
|
12 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_MARKUP_H
|
|
13 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_MARKUP_H
|
|
14
|
|
15 #include "llvm/Support/raw_ostream.h"
|
|
16 #include <cstddef>
|
|
17 #include <memory>
|
|
18 #include <string>
|
|
19 #include <vector>
|
|
20
|
|
21 namespace clang {
|
|
22 namespace clangd {
|
|
23 namespace markup {
|
|
24
|
|
25 /// Holds text and knows how to lay it out. Multiple blocks can be grouped to
|
|
26 /// form a document. Blocks include their own trailing newlines, container
|
|
27 /// should trim them if need be.
|
|
28 class Block {
|
|
29 public:
|
|
30 virtual void renderMarkdown(llvm::raw_ostream &OS) const = 0;
|
|
31 virtual void renderPlainText(llvm::raw_ostream &OS) const = 0;
|
|
32 virtual std::unique_ptr<Block> clone() const = 0;
|
|
33 std::string asMarkdown() const;
|
|
34 std::string asPlainText() const;
|
|
35
|
|
36 virtual bool isRuler() const { return false; }
|
|
37 virtual ~Block() = default;
|
|
38 };
|
|
39
|
|
40 /// Represents parts of the markup that can contain strings, like inline code,
|
|
41 /// code block or plain text.
|
|
42 /// One must introduce different paragraphs to create separate blocks.
|
|
43 class Paragraph : public Block {
|
|
44 public:
|
|
45 void renderMarkdown(llvm::raw_ostream &OS) const override;
|
|
46 void renderPlainText(llvm::raw_ostream &OS) const override;
|
|
47 std::unique_ptr<Block> clone() const override;
|
|
48
|
|
49 /// Append plain text to the end of the string.
|
|
50 Paragraph &appendText(llvm::StringRef Text);
|
|
51
|
|
52 /// Append inline code, this translates to the ` block in markdown.
|
|
53 /// \p Preserve indicates the code span must be apparent even in plaintext.
|
|
54 Paragraph &appendCode(llvm::StringRef Code, bool Preserve = false);
|
|
55
|
|
56 /// Ensure there is space between the surrounding chunks.
|
|
57 /// Has no effect at the beginning or end of a paragraph.
|
|
58 Paragraph &appendSpace();
|
|
59
|
|
60 private:
|
|
61 struct Chunk {
|
|
62 enum {
|
|
63 PlainText,
|
|
64 InlineCode,
|
|
65 } Kind = PlainText;
|
|
66 // Preserve chunk markers in plaintext.
|
|
67 bool Preserve = false;
|
|
68 std::string Contents;
|
|
69 // Whether this chunk should be surrounded by whitespace.
|
|
70 // Consecutive SpaceAfter and SpaceBefore will be collapsed into one space.
|
|
71 // Code spans don't usually set this: their spaces belong "inside" the span.
|
|
72 bool SpaceBefore = false;
|
|
73 bool SpaceAfter = false;
|
|
74 };
|
|
75 std::vector<Chunk> Chunks;
|
|
76 };
|
|
77
|
|
78 /// Represents a sequence of one or more documents. Knows how to print them in a
|
|
79 /// list like format, e.g. by prepending with "- " and indentation.
|
|
80 class BulletList : public Block {
|
|
81 public:
|
236
|
82 BulletList();
|
|
83 ~BulletList();
|
|
84
|
173
|
85 void renderMarkdown(llvm::raw_ostream &OS) const override;
|
|
86 void renderPlainText(llvm::raw_ostream &OS) const override;
|
|
87 std::unique_ptr<Block> clone() const override;
|
|
88
|
|
89 class Document &addItem();
|
|
90
|
|
91 private:
|
|
92 std::vector<class Document> Items;
|
|
93 };
|
|
94
|
|
95 /// A format-agnostic representation for structured text. Allows rendering into
|
|
96 /// markdown and plaintext.
|
|
97 class Document {
|
|
98 public:
|
|
99 Document() = default;
|
|
100 Document(const Document &Other) { *this = Other; }
|
|
101 Document &operator=(const Document &);
|
|
102 Document(Document &&) = default;
|
|
103 Document &operator=(Document &&) = default;
|
|
104
|
|
105 void append(Document Other);
|
|
106
|
|
107 /// Adds a semantical block that will be separate from others.
|
|
108 Paragraph &addParagraph();
|
|
109 /// Inserts a horizontal separator to the document.
|
|
110 void addRuler();
|
|
111 /// Adds a block of code. This translates to a ``` block in markdown. In plain
|
|
112 /// text representation, the code block will be surrounded by newlines.
|
|
113 void addCodeBlock(std::string Code, std::string Language = "cpp");
|
|
114 /// Heading is a special type of paragraph that will be prepended with \p
|
|
115 /// Level many '#'s in markdown.
|
|
116 Paragraph &addHeading(size_t Level);
|
|
117
|
|
118 BulletList &addBulletList();
|
|
119
|
|
120 /// Doesn't contain any trailing newlines.
|
|
121 /// We try to make the markdown human-readable, e.g. avoid extra escaping.
|
|
122 /// At least one client (coc.nvim) displays the markdown verbatim!
|
|
123 std::string asMarkdown() const;
|
|
124 /// Doesn't contain any trailing newlines.
|
|
125 std::string asPlainText() const;
|
|
126
|
|
127 private:
|
|
128 std::vector<std::unique_ptr<Block>> Children;
|
|
129 };
|
|
130 } // namespace markup
|
|
131 } // namespace clangd
|
|
132 } // namespace clang
|
|
133
|
|
134 #endif
|