implemented md to html

This commit is contained in:
specCon18 2025-02-01 19:22:53 -05:00
parent 590f8548b0
commit 105f1eee29
3 changed files with 90 additions and 38 deletions

View file

@ -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:

View file

@ -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: <div><p>This is <em>italics</em> and <strong>bold</strong></p></div>")
print(f"Got: {result}")
if __name__=="__main__":
main()

View file

@ -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() == "<div><p>This is a paragraph</p></div>"
assert markdown_to_html_node("# Header").to_html() == "<div><h1>Header</h1></div>"
assert markdown_to_html_node("## Header 2").to_html() == "<div><h2>Header 2</h2></div>"
# Lists
assert markdown_to_html_node("- Item 1\n- Item 2").to_html() == "<div><ul><li>Item 1</li><li>Item 2</li></ul></div>"
assert markdown_to_html_node("1. First\n2. Second").to_html() == "<div><ol><li>First</li><li>Second</li></ol></div>"
# Code blocks
assert markdown_to_html_node("```\ncode block\n```").to_html() == "<div><pre><code>code block</code></pre></div>"
# Quotes
assert markdown_to_html_node("> Quote").to_html() == "<div><blockquote>Quote</blockquote></div>"
# Mixed inline formatting
assert markdown_to_html_node("This is *italics* and **bold**").to_html() == "<div><p>This is <em>italics</em> and <strong>bold</strong></p></div>"
if __name__ == "__main__":
unittest.main()