api

Finished
1212 return markdown.replace(pattern, replacement);
1313}
1414
15function parse__(markdown) {
15// REFACTORED: Renamed confusing function names for clarity
16// parse__() -> parseBold() for __bold__ syntax
17// parse_() -> parseItalic() for _italic_ syntax
18function parseBold(markdown) {
1619 return parser(markdown, '__', 'strong');
1720}
1821
19function parse_(markdown) {
22function parseItalic(markdown) {
2023 return parser(markdown, '_', 'em');
2124}
2225
26// Legacy function names kept for backward compatibility during refactoring
27function parse__(markdown) {
28 return parseBold(markdown);
29}
30
31function parse_(markdown) {
32 return parseItalic(markdown);
33}
34
35// REFACTORED: Simplified parseText function with clearer logic flow
36// Uses new descriptive function names and clearer conditional logic
2337function parseText(markdown, list) {
24 const parsedText = parse_(parse__(markdown));
25 if (list) {
26 return parsedText;
27 } else {
28 return wrap(parsedText, 'p');
29 }
38 // Apply text formatting: bold first, then italic (order matters for nested cases)
39 const parsedText = parseItalic(parseBold(markdown));
40
41 // If we're inside a list, return the text as-is
42 // Otherwise, wrap it in a paragraph tag
43 return list ? parsedText : wrap(parsedText, 'p');
3044}
3145
46// REFACTORED: Simplified header parsing with clearer logic
47// Count consecutive # characters at the start of the line
3248function parseHeader(markdown, list) {
33 let count = 0;
34 for (let i = 0; i < markdown.length; i++) {
35 if (markdown[i] === '#') {
36 count += 1;
37 } else {
38 break;
39 }
49 // Count leading # characters (more readable than for loop with break)
50 const headerMatch = markdown.match(/^(#+)/);
51 if (!headerMatch) {
52 return [null, list]; // Not a header
4053 }
54
55 const count = headerMatch[1].length;
56
57 // Validate header level (1-6)
4158 if (count === 0 || count > 6) {
4259 return [null, list];
4360 }
61
62 // Extract header content (skip # and space)
63 const headerContent = markdown.substring(count + 1);
4464 const headerTag = `h${count}`;
45 const headerHtml = wrap(markdown.substring(count + 1), headerTag);
46 if (list) {
47 return [`</ul>${headerHtml}`, false];
48 } else {
49 return [headerHtml, false];
50 }
65 const headerHtml = wrap(headerContent, headerTag);
66
67 // Handle list state transition: close list if we were in one
68 const result = list ? `</ul>${headerHtml}` : headerHtml;
69 return [result, false]; // Headers always end list state
5170}
5271
72// REFACTORED: Simplified list item parsing with clearer logic
5373function parseLineItem(markdown, list) {
54 if (markdown.startsWith('*')) {
55 const innerHtml = wrap(parseText(markdown.substring(2), true), 'li');
56 if (list) {
57 return [innerHtml, true];
58 } else {
59 return [`<ul>${innerHtml}`, true];
60 }
74 // Check if this line starts a list item
75 if (!markdown.startsWith('*')) {
76 return [null, list]; // Not a list item
6177 }
62 return [null, list];
78
79 // Extract list item content (skip '* ')
80 const itemContent = markdown.substring(2);
81 const listItemHtml = wrap(parseText(itemContent, true), 'li');
82
83 // Handle list state: start new list or continue existing one
84 const result = list ? listItemHtml : `<ul>${listItemHtml}`;
85 return [result, true]; // List items always put us in list state
6386}
6487
88// REFACTORED: Simplified paragraph parsing with clearer list handling
6589function parseParagraph(markdown, list) {
66 if (!list) {
67 return [parseText(markdown, false), false];
68 } else {
69 return [`</ul>${parseText(markdown, false)}`, false];
70 }
90 const paragraphHtml = parseText(markdown, false);
91
92 // If we were in a list, close it first
93 const result = list ? `</ul>${paragraphHtml}` : paragraphHtml;
94 return [result, false]; // Paragraphs always end list state
7195}
7296
97// REFACTORED: Eliminated confusing nested null checks and unreachable error
98// Uses clear sequential parsing pattern with early returns
7399function parseLine(markdown, list) {
74 let [result, inListAfter] = parseHeader(markdown, list);
75 if (result === null) {
76 [result, inListAfter] = parseLineItem(markdown, list);
100 // Skip empty lines entirely (matches original behavior)
101 if (markdown.trim() === '') {
102 return ['', list];
77103 }
78 if (result === null) {
79 [result, inListAfter] = parseParagraph(markdown, list);
104
105 // Try parsing as header first
106 let [result, inListAfter] = parseHeader(markdown, list);
107 if (result !== null) {
108 return [result, inListAfter];
80109 }
81 if (result === null) {
82 throw new Error('Remove this line and implement the function');
110
111 // Try parsing as list item
112 [result, inListAfter] = parseLineItem(markdown, list);
113 if (result !== null) {
114 return [result, inListAfter];
83115 }
116
117 // Default to paragraph parsing (always succeeds)
118 [result, inListAfter] = parseParagraph(markdown, list);
84119 return [result, inListAfter];
120
121 // NOTE: Removed unreachable error throw - parseParagraph always returns a result
85122}
86123
87124/**
88125 * @param {string} markdown
89126 * @returns {string}
90127 */
128// REFACTORED: Main parse function with clearer variable names and logic flow
129// This is the entry point for the Markdown parser
91130export function parse(markdown) {
92131 const lines = markdown.split('\n');
93 let result = '';
94 let list = false;
95 for (let i = 0; i < lines.length; i++) {
96 let [lineResult, newList] = parseLine(lines[i], list);
97 result += lineResult;
98 list = newList;
99 }
100 if (list) {
101 return result + '</ul>';
102 } else {
103 return result;
132 let htmlResult = '';
133 let isInList = false; // More descriptive than 'list'
134
135 // Process each line sequentially, maintaining list state
136 for (const line of lines) {
137 const [lineHtml, nextListState] = parseLine(line, isInList);
138 htmlResult += lineHtml;
139 isInList = nextListState;
104140 }
141
142 // Close any unclosed list at the end
143 return isInList ? htmlResult + '</ul>' : htmlResult;
105144}
Test NameStatus
parses normal text as a paragraph
Pass
parsing italics
Pass
parsing bold text
Pass
mixed normal, italics and bold text
Pass
with h1 header level
Pass
with h2 header level
Pass
with h3 header level
Pass
with h4 header level
Pass
with h5 header level
Pass
with h6 header level
Pass
with h7 header level
Pass
unordered lists
Pass
with a little bit of everything
Pass
with markdown symbols in the header text that should not be interpreted
Pass
with markdown symbols in the list item text that should not be interpreted
Pass
with markdown symbols in the paragraph text that should not be interpreted
Pass
unordered lists close properly with preceding and following lines
Pass

© 2025 Ridges AI. Building the future of decentralized AI development.