/* * Copyright (c) 2019-2020, Sergey Bugaev * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include #include namespace Markdown { String Document::render_to_html() const { StringBuilder builder; builder.append("\n"); builder.append("\n"); builder.append("\n"); builder.append("\n"); builder.append("\n"); builder.append("\n"); for (auto& block : m_blocks) { auto s = block.render_to_html(); builder.append(s); } builder.append("\n"); builder.append("\n"); return builder.build(); } String Document::render_for_terminal(size_t view_width) const { StringBuilder builder; for (auto& block : m_blocks) { auto s = block.render_for_terminal(view_width); builder.append(s); } return builder.build(); } template static bool helper(Vector::ConstIterator& lines, NonnullOwnPtrVector& blocks) { OwnPtr block = BlockType::parse(lines); if (!block) return false; blocks.append(block.release_nonnull()); return true; } OwnPtr Document::parse(const StringView& str) { const Vector lines_vec = str.lines(); auto lines = lines_vec.begin(); auto document = make(); auto& blocks = document->m_blocks; NonnullOwnPtrVector paragraph_lines; auto flush_paragraph = [&] { if (paragraph_lines.is_empty()) return; auto paragraph = make(move(paragraph_lines)); document->m_blocks.append(move(paragraph)); paragraph_lines.clear(); }; while (true) { if (lines.is_end()) break; if ((*lines).is_empty()) { ++lines; flush_paragraph(); continue; } bool any = helper(lines, blocks) || helper(lines, blocks) || helper(lines, blocks) || helper(lines, blocks) || helper(lines, blocks); if (any) { if (!paragraph_lines.is_empty()) { auto last_block = document->m_blocks.take_last(); flush_paragraph(); document->m_blocks.append(move(last_block)); } continue; } auto line = Paragraph::Line::parse(lines); if (!line) return {}; paragraph_lines.append(line.release_nonnull()); } if (!paragraph_lines.is_empty()) flush_paragraph(); return document; } }