14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
# File 'lib/ace/compressor/atoms/markdown_parser.rb', line 14
def call(text)
body = strip_frontmatter(text.to_s)
return [] if body.strip.empty?
blocks = []
paragraph_lines = []
lines = body.lines
index = 0
while index < lines.length
stripped = lines[index].strip
if stripped.empty?
flush_paragraph(blocks, paragraph_lines)
index += 1
next
end
if layout_separator?(stripped)
flush_paragraph(blocks, paragraph_lines)
index += 1
next
end
if blockquote_marker?(stripped)
flush_paragraph(blocks, paragraph_lines)
index += 1
next
end
if stripped.match?(FENCE_START_RE)
flush_paragraph(blocks, paragraph_lines)
language = stripped.sub(FENCE_START_RE, "").strip
fence_lines = []
index += 1
while index < lines.length
candidate = lines[index]
break if candidate.strip.match?(FENCE_START_RE)
fence_lines << candidate
index += 1
end
index += 1 if index < lines.length && lines[index]&.strip&.match?(FENCE_START_RE)
blocks << {
type: :fenced_code,
language: language,
content: fence_lines.join
}
next
end
if image_only_line?(stripped)
flush_paragraph(blocks, paragraph_lines)
blocks << {
type: :unresolved,
text: stripped,
kind: "image-only"
}
index += 1
next
end
if table_start?(lines, index)
flush_paragraph(blocks, paragraph_lines)
table_rows = []
while index < lines.length
candidate = lines[index]
break if candidate.strip.empty?
break unless candidate.include?("|")
table_rows << candidate.strip
index += 1
end
blocks << {type: :table, rows: table_rows}
next
end
if list_start?(stripped)
flush_paragraph(blocks, paragraph_lines)
list_items = []
ordered = false
while index < lines.length
item_line = lines[index].strip
break unless list_start?(item_line)
ordered = true if ordered_list_line?(item_line)
list_items << strip_list_marker(item_line)
index += 1
end
blocks << {
type: :list,
ordered: ordered,
items: list_items
}
next
end
heading_match = stripped.match(HEADING_RE)
if heading_match && heading_match[1].length <= 6
flush_paragraph(blocks, paragraph_lines)
blocks << {
type: :heading,
level: heading_match[1].length,
text: heading_match[2].strip
}
else
paragraph_lines << stripped
end
index += 1
end
flush_paragraph(blocks, paragraph_lines)
blocks
end
|