From 105f1eee29e701b11a9ae1b2d0545b45b1450258 Mon Sep 17 00:00:00 2001 From: specCon18 Date: Sat, 1 Feb 2025 19:22:53 -0500 Subject: [PATCH] implemented md to html --- src/conversions.py | 88 +++++++++++++++++++++++++++++------------ src/main.py | 15 +++---- src/test_conversions.py | 25 ++++++++++-- 3 files changed, 90 insertions(+), 38 deletions(-) diff --git a/src/conversions.py b/src/conversions.py index 40911f6..9ced479 100644 --- a/src/conversions.py +++ b/src/conversions.py @@ -1,9 +1,28 @@ from textnode import TextType, TextNode -from htmlnode import LeafNode +from htmlnode import ParentNode, LeafNode import re # ====Markdown Parsing and Block Handling==== +def markdown_to_blocks(markdown): + lines = markdown.split('\n') + blocks = [] + current_block = [] + for line in lines: + stripped = line.strip() + if stripped == "": + if current_block == []: + continue + else: + blocks.append("\n".join(current_block).strip()) + current_block = [] + else: + current_block.append(line) + if current_block != []: + blocks.append("\n".join(current_block).strip()) + current_block = [] + return blocks + def block_to_block_type(markdown): markdown = markdown.strip() # Remove leading/trailing whitespace @@ -49,37 +68,56 @@ def block_to_block_type(markdown): else: return "paragraph" - -def markdown_to_blocks(markdown): - lines = markdown.split('\n') - blocks = [] - current_block = [] - for line in lines: - stripped = line.strip() - if stripped == "": - if current_block == []: - continue - else: - blocks.append("\n".join(current_block).strip()) - current_block = [] - else: - current_block.append(line) - if current_block != []: - blocks.append("\n".join(current_block).strip()) - current_block = [] - return blocks - - -# ====Markdown Node Conversion==== +def markdown_to_html_node(markdown): + blocks = markdown_to_blocks(markdown) + nodes = [] + for block in blocks: + block_type = block_to_block_type(block) + match block_type: + case "paragraph": + nodes.append(ParentNode("p",text_to_children(block))) + case "heading": + nodes.append(ParentNode(f"h{block.count("#")}",text_to_children(block.strip("#"*block.count("#")+" ")))) + case "quote": + nodes.append(ParentNode("blockquote",text_to_children(block.strip("> ")))) + case "code": + tnodes = text_to_textnodes(block.strip("```").strip("\n")) + hnodes = [] + for node in tnodes: + hnodes.append(text_node_to_html_node(node)) + nodes.append(ParentNode("pre",[ParentNode("code",hnodes)])) + case "ordered_list": + items = block.split("\n") + trimmed = [] + for item in items: + item = re.sub(r'^\d+\. ', '', item) + trimmed.append(ParentNode("li",text_to_children(item))) + nodes.append(ParentNode("ol",trimmed)) + case "unordered_list": + items = block.split("\n") + trimmed = [] + for item in items: + item = item.lstrip("* ") + item = item.lstrip("- ") + trimmed.append(ParentNode("li",text_to_children(item))) + nodes.append(ParentNode("ul",trimmed)) + return ParentNode("div",nodes) +# ====Markdown to HTML Helpers==== +def text_to_children(text): + text_nodes = text_to_textnodes(text) + html_nodes = [] + for node in text_nodes: + html_nodes.append(text_node_to_html_node(node)) + return html_nodes def text_node_to_html_node(text_node): match text_node.text_type: case TextType.NORMAL_TEXT: return LeafNode(value=text_node.text) case TextType.BOLD_TEXT: - return LeafNode(value=text_node.text, tag="b") + return LeafNode(value=text_node.text, tag="strong") case TextType.ITALIC_TEXT: - return LeafNode(value=text_node.text, tag="i") + return LeafNode(value=text_node.text, tag="em") case TextType.CODE_TEXT: return LeafNode(value=text_node.text, tag="code") case TextType.LINK_TEXT: diff --git a/src/main.py b/src/main.py index 983f032..c344dc5 100644 --- a/src/main.py +++ b/src/main.py @@ -1,15 +1,10 @@ from textnode import TextNode,TextType -from conversions import markdown_to_blocks +from conversions import markdown_to_html_node def main(): - md = """# This is a heading - - This is a paragraph of text. It has some **bold** and *italic* words inside of it. - - * This is the first list item in a list block - * This is a list item - * This is another list item - """ - print(markdown_to_blocks(md)) + test_input = "This is *italics* and **bold**" + result = markdown_to_html_node(test_input).to_html() + print(f"Expected:

This is italics and bold

") + print(f"Got: {result}") if __name__=="__main__": main() diff --git a/src/test_conversions.py b/src/test_conversions.py index 4fc299e..3a5fe09 100644 --- a/src/test_conversions.py +++ b/src/test_conversions.py @@ -1,6 +1,6 @@ import unittest from htmlnode import LeafNode -from conversions import text_node_to_html_node,split_nodes_delimiter,extract_markdown_images,extract_markdown_links,split_nodes_image,split_nodes_link,text_to_textnodes,markdown_to_blocks,block_to_block_type +from conversions import text_node_to_html_node,split_nodes_delimiter,extract_markdown_images,extract_markdown_links,split_nodes_image,split_nodes_link,text_to_textnodes,markdown_to_blocks,block_to_block_type,markdown_to_html_node from textnode import TextType,TextNode import re class TestConversions(unittest.TestCase): @@ -15,13 +15,13 @@ class TestConversions(unittest.TestCase): def test_bold_node_to_html_node(self): bold_node = TextNode("Hello, world!", TextType.BOLD_TEXT) html_node = text_node_to_html_node(bold_node) - assert html_node.tag == "b" + assert html_node.tag == "strong" assert html_node.value == "Hello, world!" def test_italic_node_to_html_node(self): italic_node = TextNode("Hello, world!", TextType.ITALIC_TEXT) html_node = text_node_to_html_node(italic_node) - assert html_node.tag == "i" + assert html_node.tag == "em" assert html_node.value == "Hello, world!" def test_code_node_to_html_node(self): @@ -287,6 +287,25 @@ class TestBlockToBlockType(unittest.TestCase): self.assertEqual(block_to_block_type("Random text without markdown"), "paragraph") self.assertEqual(block_to_block_type("Another paragraph"), "paragraph") +class TestMDToHTML(unittest.TestCase): + def test_markdown_to_html_node(self): + # Basic blocks + assert markdown_to_html_node("This is a paragraph").to_html() == "

This is a paragraph

" + assert markdown_to_html_node("# Header").to_html() == "

Header

" + assert markdown_to_html_node("## Header 2").to_html() == "

Header 2

" + + # Lists + assert markdown_to_html_node("- Item 1\n- Item 2").to_html() == "
" + assert markdown_to_html_node("1. First\n2. Second").to_html() == "
  1. First
  2. Second
" + + # Code blocks + assert markdown_to_html_node("```\ncode block\n```").to_html() == "
code block
" + + # Quotes + assert markdown_to_html_node("> Quote").to_html() == "
Quote
" + + # Mixed inline formatting + assert markdown_to_html_node("This is *italics* and **bold**").to_html() == "

This is italics and bold

" if __name__ == "__main__": unittest.main()