9 #include "clang/Basic/CharInfo.h" 10 #include "llvm/ADT/StringRef.h" 11 #include "llvm/Support/ErrorHandling.h" 12 #include "llvm/Support/FormatVariadic.h" 22 static std::string renderText(llvm::StringRef Input) {
25 R
"txt(!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~)txt"; 28 for (
size_t From = 0; From < Input.size();) {
29 size_t Next = Input.find_first_of(Punctuation, From);
30 R += Input.substr(From, Next - From);
31 if (Next == llvm::StringRef::npos)
43 static std::string renderInlineBlock(llvm::StringRef Input) {
46 for (
size_t From = 0; From < Input.size();) {
47 size_t Next = Input.find(
"`", From);
48 R += Input.substr(From, Next - From);
49 if (Next == llvm::StringRef::npos)
57 if (llvm::StringRef(R).startswith(
"`") || llvm::StringRef(R).endswith(
"`"))
58 return "` " + std::move(R) +
" `";
62 if (llvm::StringRef(R).startswith(
" ") && llvm::StringRef(R).endswith(
" "))
63 return "` " + std::move(R) +
" `";
64 return "`" + std::move(R) +
"`";
69 static std::string renderCodeBlock(llvm::StringRef Input,
70 llvm::StringRef Language) {
73 unsigned MaxBackticks = 0;
74 unsigned Backticks = 0;
75 for (
char C : Input) {
80 MaxBackticks = std::max(MaxBackticks, Backticks);
83 MaxBackticks = std::max(Backticks, MaxBackticks);
85 std::string BlockMarker(std::max(3u, MaxBackticks + 1),
'`');
86 return BlockMarker + Language.str() +
"\n" + Input.str() +
"\n" + BlockMarker;
93 C.Kind = ChunkKind::PlainText;
100 C.Kind = ChunkKind::CodeBlock;
101 C.Contents = std::move(Code);
102 C.Language = std::move(Language);
103 Chunks.push_back(std::move(C));
108 C.Kind = ChunkKind::InlineCodeBlock;
109 C.Contents = std::move(Code);
110 Chunks.push_back(std::move(C));
115 for (
const auto &C : Chunks) {
117 case ChunkKind::PlainText:
118 R += renderText(C.Contents);
120 case ChunkKind::InlineCodeBlock:
122 if (llvm::StringRef(R).endswith(
"`"))
124 R += renderInlineBlock(C.Contents);
126 case ChunkKind::CodeBlock:
127 if (!R.empty() && !llvm::StringRef(R).endswith(
"\n"))
129 R += renderCodeBlock(C.Contents, C.Language);
133 llvm_unreachable(
"unhanlded ChunkKind");
140 auto EnsureWhitespace = [&]() {
141 if (R.empty() || isWhitespace(R.back()))
145 Optional<bool> LastWasBlock;
146 for (
const auto &C : Chunks) {
147 bool IsBlock = C.Kind == ChunkKind::CodeBlock;
148 if (LastWasBlock.hasValue() && (IsBlock || *LastWasBlock))
150 LastWasBlock = IsBlock;
153 case ChunkKind::PlainText:
157 case ChunkKind::InlineCodeBlock:
161 case ChunkKind::CodeBlock:
166 while (!R.empty() && isWhitespace(R.back()))
174 for (
const auto &C : Chunks) {
176 case ChunkKind::PlainText:
177 R +=
"text[" + C.Contents +
"]";
179 case ChunkKind::InlineCodeBlock:
180 R +=
"code[" + C.Contents +
"]";
182 case ChunkKind::CodeBlock:
185 R += llvm::formatv(
"codeblock({0}) [\n{1}\n]\n", C.Language, C.Contents);
189 while (!R.empty() && isWhitespace(R.back()))
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//