api

Finished
1// REFACTORING: Helper function to wrap text in HTML tags
12function wrap(text, tag) {
23 return `<${tag}>${text}</${tag}>`;
34}
45
6// REFACTORING: Helper function to check if text starts with a specific HTML tag
57function isTag(text, tag) {
68 return text.startsWith(`<${tag}>`);
79}
810
9function parser(markdown, delimiter, tag) {
11// REFACTORING: Generic parser for emphasis (bold/italic) - renamed from 'parser' for clarity
12function parseEmphasis(markdown, delimiter, tag) {
1013 const pattern = new RegExp(`${delimiter}(.+)${delimiter}`);
1114 const replacement = `<${tag}>$1</${tag}>`;
1215 return markdown.replace(pattern, replacement);
1316}
1417
15function parse__(markdown) {
16 return parser(markdown, '__', 'strong');
18// REFACTORING: Parse bold text (renamed from parse__ for clarity)
19function parseBold(markdown) {
20 return parseEmphasis(markdown, '__', 'strong');
1721}
1822
19function parse_(markdown) {
20 return parser(markdown, '_', 'em');
23// REFACTORING: Parse italic text (renamed from parse_ for clarity)
24function parseItalic(markdown) {
25 return parseEmphasis(markdown, '_', 'em');
2126}
2227
23function parseText(markdown, list) {
24 const parsedText = parse_(parse__(markdown));
25 if (list) {
28// REFACTORING: Parse text content with emphasis, handling list context
29function parseTextContent(markdown, isInsideList) {
30 const parsedText = parseItalic(parseBold(markdown));
31 if (isInsideList) {
2632 return parsedText;
2733 } else {
2834 return wrap(parsedText, 'p');
2935 }
3036}
3137
32function parseHeader(markdown, list) {
33 let count = 0;
38// REFACTORING: Parse header lines (1-6 levels) with better variable names and logic
39function parseHeader(markdown, isInsideList) {
40 let headerLevel = 0;
41
42 // Count consecutive # characters at the start
3443 for (let i = 0; i < markdown.length; i++) {
3544 if (markdown[i] === '#') {
36 count += 1;
45 headerLevel += 1;
3746 } else {
3847 break;
3948 }
4049 }
41 if (count === 0 || count > 6) {
42 return [null, list];
50
51 // Valid headers are 1-6 levels
52 if (headerLevel === 0 || headerLevel > 6) {
53 return [null, isInsideList];
4354 }
44 const headerTag = `h${count}`;
45 const headerHtml = wrap(markdown.substring(count + 1), headerTag);
46 if (list) {
55
56 const headerTag = `h${headerLevel}`;
57 const headerContent = markdown.substring(headerLevel + 1).trim();
58 const headerHtml = wrap(headerContent, headerTag);
59
60 // If we were inside a list, close it before the header
61 if (isInsideList) {
4762 return [`</ul>${headerHtml}`, false];
4863 } else {
4964 return [headerHtml, false];
5065 }
5166}
5267
53function parseLineItem(markdown, list) {
68// REFACTORING: Parse list items starting with * - improved clarity and variable names
69function parseListItem(markdown, isInsideList) {
5470 if (markdown.startsWith('*')) {
55 const innerHtml = wrap(parseText(markdown.substring(2), true), 'li');
56 if (list) {
57 return [innerHtml, true];
71 const itemContent = markdown.substring(2).trim();
72 const listItemHtml = wrap(parseTextContent(itemContent, true), 'li');
73
74 if (isInsideList) {
75 return [listItemHtml, true];
5876 } else {
59 return [`<ul>${innerHtml}`, true];
77 return [`<ul>${listItemHtml}`, true];
6078 }
6179 }
62 return [null, list];
80 return [null, isInsideList];
6381}
6482
65function parseParagraph(markdown, list) {
66 if (!list) {
67 return [parseText(markdown, false), false];
83// REFACTORING: Parse regular paragraphs - handles list context properly
84function parseParagraph(markdown, isInsideList) {
85 if (!isInsideList) {
86 return [parseTextContent(markdown, false), false];
6887 } else {
69 return [`</ul>${parseText(markdown, false)}`, false];
88 return [`</ul>${parseTextContent(markdown, false)}`, false];
7089 }
7190}
7291
73function parseLine(markdown, list) {
74 let [result, inListAfter] = parseHeader(markdown, list);
75 if (result === null) {
76 [result, inListAfter] = parseLineItem(markdown, list);
92// REFACTORING: Main line parsing logic - much clearer flow with early returns
93function parseLine(markdown, isInsideList) {
94 // Try to parse as header first
95 let [result, newInsideList] = parseHeader(markdown, isInsideList);
96 if (result !== null) {
97 return [result, newInsideList];
7798 }
78 if (result === null) {
79 [result, inListAfter] = parseParagraph(markdown, list);
99
100 // Try to parse as list item
101 [result, newInsideList] = parseListItem(markdown, isInsideList);
102 if (result !== null) {
103 return [result, newInsideList];
80104 }
81 if (result === null) {
82 throw new Error('Remove this line and implement the function');
105
106 // Default to paragraph
107 [result, newInsideList] = parseParagraph(markdown, isInsideList);
108 if (result !== null) {
109 return [result, newInsideList];
83110 }
84 return [result, inListAfter];
111
112 // This should never happen with valid markdown
113 throw new Error('Unable to parse markdown line');
85114}
86115
87116/**
88 * @param {string} markdown
89 * @returns {string}
117 * REFACTORING: Main markdown parser function - improved variable names and logic
118 * @param {string} markdown - The markdown string to parse
119 * @returns {string} - The resulting HTML
90120 */
91121export function parse(markdown) {
92122 const lines = markdown.split('\n');
93 let result = '';
94 let list = false;
123 let htmlResult = '';
124 let isInsideList = false;
125
126 // Process each line of markdown
95127 for (let i = 0; i < lines.length; i++) {
96 let [lineResult, newList] = parseLine(lines[i], list);
97 result += lineResult;
98 list = newList;
128 const [lineHtml, newInsideList] = parseLine(lines[i], isInsideList);
129 htmlResult += lineHtml;
130 isInsideList = newInsideList;
99131 }
100 if (list) {
101 return result + '</ul>';
132
133 // Close any unclosed list
134 if (isInsideList) {
135 return htmlResult + '</ul>';
102136 } else {
103 return result;
137 return htmlResult;
104138 }
105139}
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.