Skip to content

Commit

Permalink
Ruff
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinL10 committed Aug 26, 2023
1 parent 3ecb27b commit 4728956
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 43 deletions.
14 changes: 8 additions & 6 deletions browser/graphics.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from browser.parser import HTMLParser
from browser.parser import HTMLParser, style
from browser.request import request
from browser.constants import VSTEP, HEIGHT, WIDTH, SCROLL_STEP
from browser.layout import DocumentLayout
Expand All @@ -9,7 +9,9 @@
class Browser:
def __init__(self):
self.window = tkinter.Tk()
self.canvas = tkinter.Canvas(self.window, width=WIDTH, height=HEIGHT)
self.canvas = tkinter.Canvas(
self.window, width=WIDTH, height=HEIGHT, bg="white"
)
self.canvas.pack()
self.scroll = 0

Expand All @@ -30,7 +32,6 @@ def scrolldown(self, e):
self.scroll = min(self.scroll + SCROLL_STEP, max_y)
self.draw()


# Draws the to-be-displayed text; calculates the position
# of each character by subtracting the current scroll
# (i.e. how far the user is down the page)
Expand All @@ -44,12 +45,13 @@ def draw(self):

cmd.execute(self.scroll, self.canvas)


# Renders the contents of the url to the canvas
def load(self, url):
headers, body = request(url)
self.nodes = HTMLParser(body).parse()
self.document = DocumentLayout(self.nodes)
self.node = HTMLParser(body).parse()
style(self.node)

self.document = DocumentLayout(self.node)
self.document.layout()

# The display_list consists of commands like DrawText and DrawRect
Expand Down
18 changes: 13 additions & 5 deletions browser/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ def __init__(self, x1, y1, x2, y2, color):
# Draws rectangle to the given canvas
def execute(self, scroll, canvas: tkinter.Canvas):
canvas.create_rectangle(
self.left, self.top - scroll,
self.right, self.bottom - scroll,
width=0, # border width
self.left,
self.top - scroll,
self.right,
self.bottom - scroll,
width=0, # border width
fill=self.color,
)

Expand Down Expand Up @@ -106,14 +108,20 @@ def __init__(self, node: Element, parent: Element, previous: "BlockLayout"):
self.display_list = []

def paint(self, display_list):
if isinstance(self.node, Element) and self.node.tag == "pre":
bgcolor = self.node.style.get("background-color", "transparent")
if bgcolor != "transparent":
x2, y2 = self.x + self.width, self.y + self.height
display_list.append(DrawRect(self.x, self.y, x2, y2, "gray"))
display_list.append(DrawRect(self.x, self.y, x2, y2, bgcolor))

# if isinstance(self.node, Element) and self.node.tag == "pre":
# x2, y2 = self.x + self.width, self.y + self.height
# display_list.append(DrawRect(self.x, self.y, x2, y2, "gray"))

for child in self.children:
child.paint(display_list)

for x, y, word, font in self.display_list:
print(word)
display_list.append(DrawText(x, y, word, font))

"""
Expand Down
2 changes: 1 addition & 1 deletion browser/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
browser.load(sys.argv[1])
else:
browser.load("file:///home/vever/cs/browser/browser/tests/index.html")
browser.load("https://browser.engineering/layout.html")
# browser.load("https://browser.engineering/layout.html")

# browser.load("https://www.w3.org/Style/CSS/Test/CSS1/current/test5526c.htm")

Expand Down
114 changes: 90 additions & 24 deletions browser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ def __init__(self, text, parent):
def __repr__(self):
return self.text


class Element:
def __init__(self, tag, attributes, parent):
self.tag = tag
Expand Down Expand Up @@ -74,24 +73,26 @@ def parse(self):

return self.finish()

'''
"""
Returns the type of tag and key-value attributes
'''
"""

def get_attributes(self, text):
parts = text.split()
if len(parts) == 1:
return parts[0], {}

print(parts)
tag = parts[0]
attributes = {}
for part in parts[1:]:
if "=" in part:
key, value = part.split("=", 1)
if len(value) > 2 and value[0] in ["'", "\""]:
if len(value) > 2 and value[0] in ["'", '"']:
value = value[1:-1]
attributes[key.lower()] = value
else:
attributes[part.lower()] = ""

return tag, attributes

"""
Expand Down Expand Up @@ -146,27 +147,92 @@ def finish(self):

return self.unfinished.pop()


def print_tree(node, indent=0):
print(" " * indent, node)
print(" " * indent, node, node.style, getattr(node, "attributes", ""))
for child in node.children:
print_tree(child, indent + 2)


# k = HTMLParser(
# """<!DOCTYPE html>
# <html lang="en">
# <head>
# <meta charset="UTF-8">
# <meta http-equiv="X-UA-Compatible" content="IE=edge">
# <meta name="viewport" content="width=device-width, initial-scale=1.0">
# <title>Document</title>
# </head>
# <body>
# Hi! this is a test
# <b>bold text</b>
# </body>
# </html>"""
# )

# print_tree(k.parse())
# A parser class containing parsing functions to advance through the text
class CSSParser:
# Initialize the CSS parser with the text being parse and the position set to 0
def __init__(self, s):
self.s = s
self.i = 0

# Advance through the current whitespace characters
def whitespace(self):
while self.i < len(self.s) and self.s[self.i].isspace():
self.i += 1

# Advance through the current word
def word(self):
start = self.i
while self.i < len(self.s):
if self.s[self.i].isalnum() or self.s[self.i] in "#-.%":
self.i += 1
else:
break

if start == self.i:
raise Exception("Error when parsing word")

return self.s[start : self.i]

# Advance through the given literal
def literal(self, literal):
if not (self.i < len(self.s) and self.s[self.i] == literal):
raise Exception(f"Error when parsing literal {literal}")
self.i += 1

# Advance through the current property-value pair
def pair(self):
prop = self.word()
self.whitespace()
self.literal(":")
self.whitespace()
value = self.word()
return prop.lower(), value

# Advance the index unconditionally until you reach one of the chars
def ignore_until(self, chars):
while self.i < len(self.s):
if self.s[self.i] in chars:
return self.s[self.i]
else:
self.i += 1

# Advance through the current "style" attribute
def body(self):
pairs = {}
while self.i < len(self.s):
try:
prop, value = self.pair()
pairs[prop] = value
self.whitespace()
self.literal(";")
self.whitespace()
except Exception as e:
print("Error parsing body:", e) # DEBUG

# Skip to the next set of properties if encounter parsing error
why = self.ignore_until([";"])
if why == ";":
self.literal(";")
self.whitespace()
else:
break
return pairs

# Recursively add the style property-value attributes to the given node and its children
def style(node):
node.style = {}

if isinstance(node, Element) and "style" in node.attributes:
pairs = CSSParser(node.attributes["style"]).body()
for property, value in pairs.items():
node.style[property] = value


for child in node.children:
style(child)
9 changes: 2 additions & 7 deletions tests/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,9 @@ <h1> title</h1>
<b>bold text</b>

<i>italic text</i>
<p>
Some text in a paragraph
<p style="background-color:green">
GREEN TEXT
</p>
<div>
<b>some text in a div </b>
<b>more text in dev</b>
</div>

<p>
<big>this is a big text!</big>
</p>
Expand Down

0 comments on commit 4728956

Please sign in to comment.