kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/cxx/doc/markup_handler.cc (about) 1 /* 2 * Copyright 2016 The Kythe Authors. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "kythe/cxx/doc/markup_handler.h" 18 19 #include <algorithm> 20 #include <cstddef> 21 #include <stack> 22 #include <string> 23 #include <utility> 24 #include <vector> 25 26 #include "kythe/proto/xref.pb.h" 27 28 namespace kythe { 29 30 void PrintableSpans::Merge(const PrintableSpans& o) { 31 spans_.insert(spans_.end(), o.spans_.begin(), o.spans_.end()); 32 spans_.erase( 33 std::remove_if(spans_.begin(), spans_.end(), 34 [](const PrintableSpan& s) { return !s.is_valid(); }), 35 spans_.end()); 36 std::sort(spans_.begin(), spans_.end()); 37 } 38 39 Printable::Printable(const proto::Printable& from) { 40 text_.reserve(from.raw_text().size() - from.link_size() * 2); 41 size_t current_link = 0; 42 std::stack<size_t> unclosed_links; 43 for (size_t i = 0; i < from.raw_text().size(); ++i) { 44 char c = from.raw_text()[i], next = (i + 1 == from.raw_text().size()) 45 ? '\0' 46 : from.raw_text()[i + 1]; 47 switch (c) { 48 case '\\': 49 text_.push_back(next); 50 ++i; 51 break; 52 case '[': 53 if (current_link < from.link_size()) { 54 unclosed_links.push(spans_.size()); 55 spans_.Emplace(text_.size(), text_.size(), from.link(current_link++)); 56 } 57 break; 58 case ']': 59 if (!unclosed_links.empty()) { 60 spans_.mutable_span(unclosed_links.top())->set_end(text_.size()); 61 unclosed_links.pop(); 62 } 63 break; 64 default: 65 text_.push_back(c); 66 break; 67 } 68 } 69 while (!unclosed_links.empty()) { 70 spans_.mutable_span(unclosed_links.top())->set_end(text_.size()); 71 unclosed_links.pop(); 72 } 73 } 74 75 Printable HandleMarkup(const std::vector<MarkupHandler>& handlers, 76 const Printable& printable) { 77 if (handlers.empty()) { 78 return printable; 79 } 80 PrintableSpans spans = printable.spans(); 81 for (const auto& handler : handlers) { 82 PrintableSpans next_spans; 83 handler(printable, spans, &next_spans); 84 spans.Merge(next_spans); 85 } 86 return Printable(printable.text(), std::move(spans)); 87 } 88 89 std::string PrintableSpans::Dump(const std::string& annotated_buffer) const { 90 std::string text_out; 91 text_out.reserve(annotated_buffer.size()); 92 std::stack<const PrintableSpan*> open_spans; 93 PrintableSpan default_span(0, annotated_buffer.size(), 94 PrintableSpan::Semantic::Raw); 95 open_spans.push(&default_span); 96 text_out.append("["); 97 size_t current_span = 0; 98 for (size_t i = 0; i <= annotated_buffer.size(); ++i) { 99 while (!open_spans.empty() && open_spans.top()->end() == i) { 100 text_out.append("]"); 101 open_spans.pop(); 102 } 103 if (open_spans.empty() || i == annotated_buffer.size()) { 104 // default_span is first to enter and last to leave; there also may 105 // be no empty spans. 106 break; 107 } 108 while (current_span < spans_.size() && spans_[current_span].begin() == i) { 109 open_spans.push(&spans_[current_span++]); 110 switch (open_spans.top()->semantic()) { 111 case PrintableSpan::Semantic::Uri: 112 text_out.append("[uri "); 113 break; 114 case PrintableSpan::Semantic::Escaped: 115 text_out.append("[esc "); 116 break; 117 case PrintableSpan::Semantic::Styled: { 118 text_out.append("[s"); 119 switch (open_spans.top()->style()) { 120 case PrintableSpan::Style::Bold: 121 text_out.append("B "); 122 break; 123 case PrintableSpan::Style::Italic: 124 text_out.append("I "); 125 break; 126 case PrintableSpan::Style::H1: 127 text_out.append("H1 "); 128 break; 129 case PrintableSpan::Style::H2: 130 text_out.append("H2 "); 131 break; 132 case PrintableSpan::Style::H3: 133 text_out.append("H3 "); 134 break; 135 case PrintableSpan::Style::H4: 136 text_out.append("H4 "); 137 break; 138 case PrintableSpan::Style::H5: 139 text_out.append("H5 "); 140 break; 141 case PrintableSpan::Style::H6: 142 text_out.append("H6 "); 143 break; 144 case PrintableSpan::Style::Big: 145 text_out.append("BIG "); 146 break; 147 case PrintableSpan::Style::Small: 148 text_out.append("SMALL "); 149 break; 150 case PrintableSpan::Style::Blockquote: 151 text_out.append("BQ "); 152 break; 153 case PrintableSpan::Style::Superscript: 154 text_out.append("SUP "); 155 break; 156 case PrintableSpan::Style::Subscript: 157 text_out.append("SUB "); 158 break; 159 case PrintableSpan::Style::Underline: 160 text_out.append("UL "); 161 break; 162 } 163 } break; 164 case PrintableSpan::Semantic::Link: 165 text_out.append("[link"); 166 break; 167 case PrintableSpan::Semantic::CodeRef: 168 text_out.append("[coderef "); 169 break; 170 case PrintableSpan::Semantic::Paragraph: 171 text_out.append("[p "); 172 break; 173 case PrintableSpan::Semantic::ListItem: 174 text_out.append("[li "); 175 break; 176 case PrintableSpan::Semantic::UnorderedList: 177 text_out.append("[ul "); 178 break; 179 case PrintableSpan::Semantic::Raw: 180 text_out.append("[raw "); 181 break; 182 case PrintableSpan::Semantic::Brief: 183 text_out.append("[brief "); 184 break; 185 case PrintableSpan::Semantic::Markup: 186 text_out.append("[^ "); 187 break; 188 case PrintableSpan::Semantic::CodeBlock: 189 text_out.append("[cb "); 190 break; 191 case PrintableSpan::Semantic::UriLink: 192 text_out.append("[uril "); 193 break; 194 case PrintableSpan::Semantic::TagBlock: { 195 text_out.append("[tb"); 196 switch (open_spans.top()->tag_block().first) { 197 case PrintableSpan::TagBlockId::Author: 198 text_out.append("Author"); 199 break; 200 case PrintableSpan::TagBlockId::Returns: 201 text_out.append("Returns"); 202 break; 203 case PrintableSpan::TagBlockId::Since: 204 text_out.append("Since"); 205 break; 206 case PrintableSpan::TagBlockId::Version: 207 text_out.append("Version"); 208 break; 209 case PrintableSpan::TagBlockId::Param: 210 text_out.append("Param"); 211 break; 212 case PrintableSpan::TagBlockId::Throws: 213 text_out.append("Throws"); 214 break; 215 case PrintableSpan::TagBlockId::See: 216 text_out.append("See"); 217 break; 218 } 219 text_out.append(std::to_string(open_spans.top()->tag_block().second)); 220 text_out.append(" "); 221 } break; 222 } 223 } 224 text_out.push_back(annotated_buffer[i]); 225 } 226 return text_out; 227 } 228 } // namespace kythe