Skip to content

Commit 92071e9

Browse files
committed
optimize
1 parent ae7c172 commit 92071e9

File tree

1 file changed

+46
-40
lines changed

1 file changed

+46
-40
lines changed

xtra_markdown.v

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ fn markdown_to_blocks(source string, style MarkdownStyle) []MarkdownBlock {
4444

4545
for i < lines.len {
4646
line := lines[i]
47+
trimmed := line.trim_space()
4748

4849
// Handle code blocks
4950
if line.starts_with('```') {
@@ -87,7 +88,7 @@ fn markdown_to_blocks(source string, style MarkdownStyle) []MarkdownBlock {
8788
}
8889

8990
// Horizontal rule
90-
if line.trim_space() in ['---', '***', '___'] {
91+
if trimmed in ['---', '***', '___'] {
9192
// Flush current runs first
9293
if block := flush_runs(mut runs) {
9394
blocks << block
@@ -101,7 +102,7 @@ fn markdown_to_blocks(source string, style MarkdownStyle) []MarkdownBlock {
101102
}
102103

103104
// Blank line = paragraph break
104-
if line.trim_space() == '' {
105+
if trimmed == '' {
105106
if runs.len > 0 {
106107
runs << rich_br()
107108
}
@@ -116,13 +117,13 @@ fn markdown_to_blocks(source string, style MarkdownStyle) []MarkdownBlock {
116117
}
117118

118119
// Table recognition: lines starting with | or separator rows
119-
if line.trim_space().starts_with('|') || is_table_separator(line) {
120+
if trimmed.starts_with('|') || is_table_separator(trimmed) {
120121
// Flush current runs
121122
if block := flush_runs(mut runs) {
122123
blocks << block
123124
}
124125
// Collect consecutive table lines
125-
mut table_lines := []string{}
126+
mut table_lines := []string{cap: 10}
126127
for i < lines.len {
127128
tl := lines[i].trim_space()
128129
if tl.starts_with('|') || is_table_separator(tl) || tl.contains('|') {
@@ -152,8 +153,7 @@ fn markdown_to_blocks(source string, style MarkdownStyle) []MarkdownBlock {
152153
}
153154

154155
// Definition list: line starting with : (treat as paragraph for now)
155-
if line.trim_space().starts_with(':') && line.trim_space().len > 1
156-
&& line.trim_space()[1] == ` ` {
156+
if trimmed.len > 1 && trimmed[0] == `:` && trimmed[1] == ` ` {
157157
// Treat as regular paragraph
158158
parse_inline(line, style.text, style, mut runs)
159159
runs << rich_br()
@@ -190,7 +190,7 @@ fn markdown_to_blocks(source string, style MarkdownStyle) []MarkdownBlock {
190190
}
191191
// Count initial depth and collect consecutive blockquote lines
192192
mut max_depth := count_blockquote_depth(line)
193-
mut quote_lines := []string{}
193+
mut quote_lines := []string{cap: 10}
194194
for i < lines.len {
195195
q := lines[i]
196196
if q.starts_with('>') {
@@ -206,7 +206,7 @@ fn markdown_to_blocks(source string, style MarkdownStyle) []MarkdownBlock {
206206
break
207207
}
208208
}
209-
mut quote_runs := []RichTextRun{}
209+
mut quote_runs := []RichTextRun{cap: 20}
210210
for qi, ql in quote_lines {
211211
// Skip blank lines but keep them as line breaks
212212
if ql.trim_space() == '' {
@@ -271,16 +271,16 @@ fn markdown_to_blocks(source string, style MarkdownStyle) []MarkdownBlock {
271271
}
272272

273273
// List items
274-
trimmed := line.trim_left(' \t')
274+
left_trimmed := line.trim_left(' \t')
275275
indent := get_indent_level(line)
276276

277277
// Task list (checked or unchecked)
278-
if task_prefix := get_task_prefix(trimmed) {
278+
if task_prefix := get_task_prefix(left_trimmed) {
279279
if block := flush_runs(mut runs) {
280280
blocks << block
281281
}
282-
content, consumed := collect_list_item_content(trimmed[6..], lines, i + 1)
283-
mut item_runs := []RichTextRun{}
282+
content, consumed := collect_list_item_content(left_trimmed[6..], lines, i + 1)
283+
mut item_runs := []RichTextRun{cap: 10}
284284
parse_inline(content, style.text, style, mut item_runs)
285285
blocks << MarkdownBlock{
286286
is_list: true
@@ -295,13 +295,14 @@ fn markdown_to_blocks(source string, style MarkdownStyle) []MarkdownBlock {
295295
}
296296

297297
// Unordered list (with nesting support)
298-
if trimmed.starts_with('- ') || trimmed.starts_with('* ') || trimmed.starts_with('+ ') {
298+
if left_trimmed.starts_with('- ') || left_trimmed.starts_with('* ')
299+
|| left_trimmed.starts_with('+ ') {
299300
// Flush any pending runs before list item
300301
if block := flush_runs(mut runs) {
301302
blocks << block
302303
}
303-
content, consumed := collect_list_item_content(trimmed[2..], lines, i + 1)
304-
mut item_runs := []RichTextRun{}
304+
content, consumed := collect_list_item_content(left_trimmed[2..], lines, i + 1)
305+
mut item_runs := []RichTextRun{cap: 10}
305306
parse_inline(content, style.text, style, mut item_runs)
306307
blocks << MarkdownBlock{
307308
is_list: true
@@ -316,16 +317,16 @@ fn markdown_to_blocks(source string, style MarkdownStyle) []MarkdownBlock {
316317
}
317318

318319
// Ordered list (with nesting support)
319-
if is_ordered_list(trimmed) {
320+
if is_ordered_list(left_trimmed) {
320321
// Flush any pending runs before list item
321322
if block := flush_runs(mut runs) {
322323
blocks << block
323324
}
324-
dot_pos := trimmed.index('.') or { 0 }
325-
num := trimmed[..dot_pos]
326-
rest := trimmed[dot_pos + 1..].trim_left(' ')
325+
dot_pos := left_trimmed.index('.') or { 0 }
326+
num := left_trimmed[..dot_pos]
327+
rest := left_trimmed[dot_pos + 1..].trim_left(' ')
327328
content, consumed := collect_list_item_content(rest, lines, i + 1)
328-
mut item_runs := []RichTextRun{}
329+
mut item_runs := []RichTextRun{cap: 10}
329330
parse_inline(content, style.text, style, mut item_runs)
330331
blocks << MarkdownBlock{
331332
is_list: true
@@ -778,33 +779,38 @@ fn get_indent_level(line string) int {
778779
// collect_list_item_content collects the full content of a list item including continuation lines.
779780
// Returns the combined content and the number of lines consumed (excluding the first).
780781
fn collect_list_item_content(first_content string, lines []string, start_idx int) (string, int) {
781-
mut content := first_content
782782
mut consumed := 0
783783
mut idx := start_idx
784784

785+
// Check if any continuation lines exist
785786
for idx < lines.len {
786787
next := lines[idx]
787-
next_trimmed := next.trim_space()
788-
789-
// Blank line ends the item
790-
if next_trimmed == '' {
788+
if next.len == 0 || (next[0] != ` ` && next[0] != `\t`) {
791789
break
792790
}
793-
// New block element ends the item
794-
if is_block_start(next) {
795-
break
796-
}
797-
// Continuation line - must be indented
798-
if next.len > 0 && (next[0] == ` ` || next[0] == `\t`) {
799-
content += ' ' + next_trimmed
800-
consumed++
801-
idx++
802-
} else {
791+
next_trimmed := next.trim_space()
792+
if next_trimmed == '' || is_block_start(next) {
803793
break
804794
}
795+
consumed++
796+
idx++
797+
}
798+
799+
// Fast path: no continuation lines
800+
if consumed == 0 {
801+
return first_content, 0
805802
}
806803

807-
return content, consumed
804+
// Build combined content with buffer
805+
mut buf := []u8{cap: first_content.len + consumed * 40}
806+
buf << first_content.bytes()
807+
idx = start_idx
808+
for _ in 0 .. consumed {
809+
buf << ` `
810+
buf << lines[idx].trim_space().bytes()
811+
idx++
812+
}
813+
return buf.bytestr(), consumed
808814
}
809815

810816
// is_block_start checks if a line starts a new block element.
@@ -884,15 +890,15 @@ fn strip_blockquote_prefix(line string) string {
884890
}
885891

886892
// is_table_separator checks if a line is a markdown table separator (e.g., |---|---|).
887-
fn is_table_separator(line string) bool {
888-
trimmed := line.trim_space()
889-
if trimmed.len < 3 {
893+
// Expects pre-trimmed input.
894+
fn is_table_separator(s string) bool {
895+
if s.len < 3 {
890896
return false
891897
}
892898
// Must contain at least --- or | and -
893899
mut has_dash := false
894900
mut has_pipe := false
895-
for c in trimmed {
901+
for c in s {
896902
if c == `-` {
897903
has_dash = true
898904
} else if c == `|` {

0 commit comments

Comments
 (0)