implemented md to html
This commit is contained in:
parent
590f8548b0
commit
105f1eee29
3 changed files with 90 additions and 38 deletions
|
|
@ -1,9 +1,28 @@
|
||||||
from textnode import TextType, TextNode
|
from textnode import TextType, TextNode
|
||||||
from htmlnode import LeafNode
|
from htmlnode import ParentNode, LeafNode
|
||||||
import re
|
import re
|
||||||
|
|
||||||
# ====Markdown Parsing and Block Handling====
|
# ====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):
|
def block_to_block_type(markdown):
|
||||||
markdown = markdown.strip() # Remove leading/trailing whitespace
|
markdown = markdown.strip() # Remove leading/trailing whitespace
|
||||||
|
|
||||||
|
|
@ -49,37 +68,56 @@ def block_to_block_type(markdown):
|
||||||
else:
|
else:
|
||||||
return "paragraph"
|
return "paragraph"
|
||||||
|
|
||||||
|
def markdown_to_html_node(markdown):
|
||||||
def markdown_to_blocks(markdown):
|
blocks = markdown_to_blocks(markdown)
|
||||||
lines = markdown.split('\n')
|
nodes = []
|
||||||
blocks = []
|
for block in blocks:
|
||||||
current_block = []
|
block_type = block_to_block_type(block)
|
||||||
for line in lines:
|
match block_type:
|
||||||
stripped = line.strip()
|
case "paragraph":
|
||||||
if stripped == "":
|
nodes.append(ParentNode("p",text_to_children(block)))
|
||||||
if current_block == []:
|
case "heading":
|
||||||
continue
|
nodes.append(ParentNode(f"h{block.count("#")}",text_to_children(block.strip("#"*block.count("#")+" "))))
|
||||||
else:
|
case "quote":
|
||||||
blocks.append("\n".join(current_block).strip())
|
nodes.append(ParentNode("blockquote",text_to_children(block.strip("> "))))
|
||||||
current_block = []
|
case "code":
|
||||||
else:
|
tnodes = text_to_textnodes(block.strip("```").strip("\n"))
|
||||||
current_block.append(line)
|
hnodes = []
|
||||||
if current_block != []:
|
for node in tnodes:
|
||||||
blocks.append("\n".join(current_block).strip())
|
hnodes.append(text_node_to_html_node(node))
|
||||||
current_block = []
|
nodes.append(ParentNode("pre",[ParentNode("code",hnodes)]))
|
||||||
return blocks
|
case "ordered_list":
|
||||||
|
items = block.split("\n")
|
||||||
|
trimmed = []
|
||||||
# ====Markdown Node Conversion====
|
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):
|
def text_node_to_html_node(text_node):
|
||||||
match text_node.text_type:
|
match text_node.text_type:
|
||||||
case TextType.NORMAL_TEXT:
|
case TextType.NORMAL_TEXT:
|
||||||
return LeafNode(value=text_node.text)
|
return LeafNode(value=text_node.text)
|
||||||
case TextType.BOLD_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:
|
case TextType.ITALIC_TEXT:
|
||||||
return LeafNode(value=text_node.text, tag="i")
|
return LeafNode(value=text_node.text, tag="em")
|
||||||
case TextType.CODE_TEXT:
|
case TextType.CODE_TEXT:
|
||||||
return LeafNode(value=text_node.text, tag="code")
|
return LeafNode(value=text_node.text, tag="code")
|
||||||
case TextType.LINK_TEXT:
|
case TextType.LINK_TEXT:
|
||||||
|
|
|
||||||
15
src/main.py
15
src/main.py
|
|
@ -1,15 +1,10 @@
|
||||||
from textnode import TextNode,TextType
|
from textnode import TextNode,TextType
|
||||||
from conversions import markdown_to_blocks
|
from conversions import markdown_to_html_node
|
||||||
def main():
|
def main():
|
||||||
md = """# This is a heading
|
test_input = "This is *italics* and **bold**"
|
||||||
|
result = markdown_to_html_node(test_input).to_html()
|
||||||
This is a paragraph of text. It has some **bold** and *italic* words inside of it.
|
print(f"Expected: <div><p>This is <em>italics</em> and <strong>bold</strong></p></div>")
|
||||||
|
print(f"Got: {result}")
|
||||||
* 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))
|
|
||||||
|
|
||||||
if __name__=="__main__":
|
if __name__=="__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import unittest
|
import unittest
|
||||||
from htmlnode import LeafNode
|
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
|
from textnode import TextType,TextNode
|
||||||
import re
|
import re
|
||||||
class TestConversions(unittest.TestCase):
|
class TestConversions(unittest.TestCase):
|
||||||
|
|
@ -15,13 +15,13 @@ class TestConversions(unittest.TestCase):
|
||||||
def test_bold_node_to_html_node(self):
|
def test_bold_node_to_html_node(self):
|
||||||
bold_node = TextNode("Hello, world!", TextType.BOLD_TEXT)
|
bold_node = TextNode("Hello, world!", TextType.BOLD_TEXT)
|
||||||
html_node = text_node_to_html_node(bold_node)
|
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!"
|
assert html_node.value == "Hello, world!"
|
||||||
|
|
||||||
def test_italic_node_to_html_node(self):
|
def test_italic_node_to_html_node(self):
|
||||||
italic_node = TextNode("Hello, world!", TextType.ITALIC_TEXT)
|
italic_node = TextNode("Hello, world!", TextType.ITALIC_TEXT)
|
||||||
html_node = text_node_to_html_node(italic_node)
|
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!"
|
assert html_node.value == "Hello, world!"
|
||||||
|
|
||||||
def test_code_node_to_html_node(self):
|
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("Random text without markdown"), "paragraph")
|
||||||
self.assertEqual(block_to_block_type("Another paragraph"), "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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue