浏览代码

LibMarkdown: Allow non-text items in Lists

Peter Elliott 3 年之前
父节点
当前提交
5bb87c630c
共有 2 个文件被更改,包括 30 次插入50 次删除
  1. 26 44
      Userland/Libraries/LibMarkdown/List.cpp
  2. 4 6
      Userland/Libraries/LibMarkdown/List.h

+ 26 - 44
Userland/Libraries/LibMarkdown/List.cpp

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
+ * Copyright (c) 2021, Peter Elliott <pelliott@serenityos.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
@@ -17,8 +18,8 @@ String List::render_to_html() const
     builder.appendff("<{}>\n", tag);
 
     for (auto& item : m_items) {
-        builder.append("<li>");
-        builder.append(item.render_to_html());
+        builder.append("<li>\n");
+        builder.append(item->render_to_html());
         builder.append("</li>\n");
     }
 
@@ -38,7 +39,7 @@ String List::render_for_terminal(size_t) const
             builder.appendff("{}. ", ++i);
         else
             builder.append("* ");
-        builder.append(item.render_for_terminal());
+        builder.append(item->render_for_terminal());
         builder.append("\n");
     }
     builder.append("\n");
@@ -48,26 +49,13 @@ String List::render_for_terminal(size_t) const
 
 OwnPtr<List> List::parse(LineIterator& lines)
 {
-    Vector<Text> items;
-    bool is_ordered = false;
+    Vector<OwnPtr<ContainerBlock>> items;
 
     bool first = true;
-    size_t offset = 0;
-    StringBuilder item_builder;
-    auto flush_item_if_needed = [&] {
-        if (first)
-            return true;
-
-        auto text = Text::parse(item_builder.string_view());
-        items.append(move(text));
-
-        item_builder.clear();
-        return true;
-    };
+    bool is_ordered = false;
+    while (!lines.is_end()) {
+        size_t offset = 0;
 
-    while (true) {
-        if (lines.is_end())
-            break;
         const StringView& line = *lines;
         if (line.is_empty())
             break;
@@ -76,7 +64,7 @@ OwnPtr<List> List::parse(LineIterator& lines)
         if (line.length() > 2) {
             if (line[1] == ' ' && (line[0] == '*' || line[0] == '-')) {
                 appears_unordered = true;
-                offset = 2;
+                offset = 1;
             }
         }
 
@@ -94,39 +82,33 @@ OwnPtr<List> List::parse(LineIterator& lines)
         }
 
         VERIFY(!(appears_unordered && appears_ordered));
-
-        if (appears_unordered || appears_ordered) {
+        if (!appears_unordered && !appears_ordered) {
             if (first)
-                is_ordered = appears_ordered;
-            else if (is_ordered != appears_ordered)
                 return {};
 
-            if (!flush_item_if_needed())
-                return {};
+            break;
+        }
 
-            while (offset + 1 < line.length() && line[offset + 1] == ' ')
-                offset++;
+        while (offset < line.length() && line[offset] == ' ')
+            offset++;
 
-        } else {
-            if (first)
-                return {};
-            for (size_t i = 0; i < offset; i++) {
-                if (line[i] != ' ')
-                    return {};
-            }
+        if (first) {
+            is_ordered = appears_ordered;
+        } else if (appears_ordered != is_ordered) {
+            break;
         }
 
+        size_t saved_indent = lines.indent();
+        lines.set_indent(saved_indent + offset);
+        lines.ignore_next_prefix();
+
+        items.append(ContainerBlock::parse(lines));
+
+        lines.set_indent(saved_indent);
+
         first = false;
-        if (!item_builder.is_empty())
-            item_builder.append(' ');
-        VERIFY(offset <= line.length());
-        item_builder.append(line.substring_view(offset, line.length() - offset));
-        ++lines;
-        offset = 0;
     }
 
-    if (!flush_item_if_needed() || first)
-        return {};
     return make<List>(move(items), is_ordered);
 }
 

+ 4 - 6
Userland/Libraries/LibMarkdown/List.h

@@ -7,17 +7,16 @@
 #pragma once
 
 #include <AK/OwnPtr.h>
-#include <AK/Vector.h>
 #include <LibMarkdown/Block.h>
+#include <LibMarkdown/ContainerBlock.h>
 #include <LibMarkdown/LineIterator.h>
-#include <LibMarkdown/Text.h>
 
 namespace Markdown {
 
 class List final : public Block {
 public:
-    List(Vector<Text>&& text, bool is_ordered)
-        : m_items(move(text))
+    List(Vector<OwnPtr<ContainerBlock>> items, bool is_ordered)
+        : m_items(move(items))
         , m_is_ordered(is_ordered)
     {
     }
@@ -29,8 +28,7 @@ public:
     static OwnPtr<List> parse(LineIterator& lines);
 
 private:
-    // TODO: List items should be considered blocks of their own kind.
-    Vector<Text> m_items;
+    Vector<OwnPtr<ContainerBlock>> m_items;
     bool m_is_ordered { false };
 };