ContainerBlock.cpp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /*
  2. * Copyright (c) 2021, Peter Elliott <pelliott@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibMarkdown/CodeBlock.h>
  7. #include <LibMarkdown/ContainerBlock.h>
  8. #include <LibMarkdown/Heading.h>
  9. #include <LibMarkdown/HorizontalRule.h>
  10. #include <LibMarkdown/List.h>
  11. #include <LibMarkdown/Paragraph.h>
  12. #include <LibMarkdown/Table.h>
  13. namespace Markdown {
  14. String ContainerBlock::render_to_html() const
  15. {
  16. StringBuilder builder;
  17. for (auto& block : m_blocks) {
  18. auto s = block.render_to_html();
  19. builder.append(s);
  20. }
  21. return builder.build();
  22. }
  23. String ContainerBlock::render_for_terminal(size_t view_width) const
  24. {
  25. StringBuilder builder;
  26. for (auto& block : m_blocks) {
  27. auto s = block.render_for_terminal(view_width);
  28. builder.append(s);
  29. }
  30. return builder.build();
  31. }
  32. template<typename BlockType>
  33. static bool try_parse_block(Vector<StringView>::ConstIterator& lines, NonnullOwnPtrVector<Block>& blocks)
  34. {
  35. OwnPtr<BlockType> block = BlockType::parse(lines);
  36. if (!block)
  37. return false;
  38. blocks.append(block.release_nonnull());
  39. return true;
  40. }
  41. OwnPtr<ContainerBlock> ContainerBlock::parse(Vector<StringView>::ConstIterator& lines)
  42. {
  43. NonnullOwnPtrVector<Block> blocks;
  44. StringBuilder paragraph_text;
  45. auto flush_paragraph = [&] {
  46. if (paragraph_text.is_empty())
  47. return;
  48. auto paragraph = make<Paragraph>(Text::parse(paragraph_text.build()));
  49. blocks.append(move(paragraph));
  50. paragraph_text.clear();
  51. };
  52. while (true) {
  53. if (lines.is_end())
  54. break;
  55. if ((*lines).is_empty()) {
  56. ++lines;
  57. flush_paragraph();
  58. continue;
  59. }
  60. bool any = try_parse_block<Table>(lines, blocks) || try_parse_block<List>(lines, blocks) || try_parse_block<CodeBlock>(lines, blocks)
  61. || try_parse_block<Heading>(lines, blocks) || try_parse_block<HorizontalRule>(lines, blocks);
  62. if (any) {
  63. if (!paragraph_text.is_empty()) {
  64. auto last_block = blocks.take_last();
  65. flush_paragraph();
  66. blocks.append(move(last_block));
  67. }
  68. continue;
  69. }
  70. if (!paragraph_text.is_empty())
  71. paragraph_text.append("\n");
  72. paragraph_text.append(*lines++);
  73. }
  74. flush_paragraph();
  75. return make<ContainerBlock>(move(blocks));
  76. }
  77. }