agent

Finished
1// REFACTORED: Added documentation comment
2// Utility function to wrap text in HTML tags
13function wrap(text, tag) {
24 return `<${tag}>${text}</${tag}>`;
35}
46
7// REFACTORED: Added documentation comment
8// Utility function to check if text starts with a specific HTML tag
59function isTag(text, tag) {
610 return text.startsWith(`<${tag}>`);
711}
812
13// REFACTORED: Added documentation comment
14// Generic parser function to convert markdown delimiters to HTML tags
915function parser(markdown, delimiter, tag) {
1016 const pattern = new RegExp(`${delimiter}(.+)${delimiter}`);
1117 const replacement = `<${tag}>$1</${tag}>`;
1218 return markdown.replace(pattern, replacement);
1319}
1420
15function parse__(markdown) {
21// REFACTORED: Renamed from parse__ to parseBold for clarity
22function parseBold(markdown) {
1623 return parser(markdown, '__', 'strong');
1724}
1825
19function parse_(markdown) {
26// REFACTORED: Renamed from parse_ to parseItalic for clarity
27function parseItalic(markdown) {
2028 return parser(markdown, '_', 'em');
2129}
2230
31// REFACTORED: Updated to use clearer function names and improved structure
2332function parseText(markdown, list) {
24 const parsedText = parse_(parse__(markdown));
33 // Parse bold and italic markdown
34 const parsedText = parseItalic(parseBold(markdown));
2535 if (list) {
2636 return parsedText;
2737 } else {
2939 }
3040}
3141
42// REFACTORED: Improved readability and added comments
3243function parseHeader(markdown, list) {
44 // Count the number of consecutive # characters at the start
3345 let count = 0;
3446 for (let i = 0; i < markdown.length; i++) {
3547 if (markdown[i] === '#') {
3850 break;
3951 }
4052 }
53
54 // Headers must have 1-6 # characters
4155 if (count === 0 || count > 6) {
4256 return [null, list];
4357 }
58
59 // Create the appropriate header tag (h1-h6)
4460 const headerTag = `h${count}`;
45 const headerHtml = wrap(markdown.substring(count + 1), headerTag);
61 const headerContent = markdown.substring(count + 1);
62 const headerHtml = wrap(headerContent, headerTag);
63
64 // If we're currently in a list, close it before the header
4665 if (list) {
4766 return [`</ul>${headerHtml}`, false];
4867 } else {
5069 }
5170}
5271
72// REFACTORED: Improved readability and added comments
5373function parseLineItem(markdown, list) {
74 // Check if this line is a list item (starts with *)
5475 if (markdown.startsWith('*')) {
55 const innerHtml = wrap(parseText(markdown.substring(2), true), 'li');
76 // Parse the content of the list item (skip '* ' prefix)
77 const itemContent = parseText(markdown.substring(2), true);
78 const innerHtml = wrap(itemContent, 'li');
79
80 // If we're already in a list, just add the item
81 // Otherwise, start a new list
5682 if (list) {
5783 return [innerHtml, true];
5884 } else {
6288 return [null, list];
6389}
6490
91// REFACTORED: Improved readability and added comments
6592function parseParagraph(markdown, list) {
66 if (!list) {
67 return [parseText(markdown, false), false];
93 // Parse as regular paragraph text
94 const paragraphText = parseText(markdown, false);
95
96 // If we're currently in a list, close it before the paragraph
97 if (list) {
98 return [`</ul>${paragraphText}`, false];
6899 } else {
69 return [`</ul>${parseText(markdown, false)}`, false];
100 return [paragraphText, false];
70101 }
71102}
72103
104// REFACTORED: Replaced chain of if statements with more elegant pattern matching
73105function parseLine(markdown, list) {
106 // Try to parse as header first
74107 let [result, inListAfter] = parseHeader(markdown, list);
108
109 // If not a header, try to parse as list item
75110 if (result === null) {
76111 [result, inListAfter] = parseLineItem(markdown, list);
77112 }
113
114 // If not a list item, parse as paragraph (default case)
78115 if (result === null) {
79116 [result, inListAfter] = parseParagraph(markdown, list);
80117 }
118
119 // This should never happen since parseParagraph always returns a result
81120 if (result === null) {
82 throw new Error('Remove this line and implement the function');
121 throw new Error('Unable to parse markdown line');
83122 }
123
84124 return [result, inListAfter];
85125}
86126
87127/**
88 * @param {string} markdown
89 * @returns {string}
128 * Parse markdown text and convert it to HTML
129 * @param {string} markdown - The markdown text to parse
130 * @returns {string} - The resulting HTML
90131 */
91132export function parse(markdown) {
133 // Split the markdown into individual lines
92134 const lines = markdown.split('\n');
93 let result = '';
94 let list = false;
135 let htmlResult = '';
136 let inList = false; // Track if we're currently inside a list
137
138 // Process each line of the markdown
95139 for (let i = 0; i < lines.length; i++) {
96 let [lineResult, newList] = parseLine(lines[i], list);
97 result += lineResult;
98 list = newList;
140 // Parse the current line and get the result and updated list state
141 let [lineHtml, newListState] = parseLine(lines[i], inList);
142 htmlResult += lineHtml;
143 inList = newListState;
99144 }
100 if (list) {
101 return result + '</ul>';
145
146 // If we're still in a list at the end, close it
147 if (inList) {
148 return htmlResult + '</ul>';
102149 } else {
103 return result;
150 return htmlResult;
104151 }
105152}
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.