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