Files
leonwww/Scripts/main.gd

233 lines
6.5 KiB
GDScript3
Raw Normal View History

class_name Main
2025-07-20 13:45:07 +03:00
extends Control
@onready var website_container: Control = %WebsiteContainer
@onready var tab_container: TabManager = $VBoxContainer/TabContainer
const LOADER_CIRCLE = preload("res://Assets/Icons/loader-circle.svg")
const P = preload("res://Scenes/Tags/p.tscn")
const IMG = preload("res://Scenes/Tags/img.tscn")
const SEPARATOR = preload("res://Scenes/Tags/separator.tscn")
const PRE = preload("res://Scenes/Tags/pre.tscn")
const BR = preload("res://Scenes/Tags/br.tscn")
2025-07-22 21:15:57 +03:00
const SPAN = preload("res://Scenes/Tags/span.tscn")
2025-07-23 13:35:42 +03:00
const H1 = preload("res://Scenes/Tags/h1.tscn")
const H2 = preload("res://Scenes/Tags/h2.tscn")
const H3 = preload("res://Scenes/Tags/h3.tscn")
const H4 = preload("res://Scenes/Tags/h4.tscn")
const H5 = preload("res://Scenes/Tags/h5.tscn")
const H6 = preload("res://Scenes/Tags/h6.tscn")
2025-07-23 15:23:32 +03:00
const FORM = preload("res://Scenes/Tags/form.tscn")
const INPUT = preload("res://Scenes/Tags/input.tscn")
const BUTTON = preload("res://Scenes/Tags/button.tscn")
const MIN_SIZE = Vector2i(750, 200)
func _ready():
ProjectSettings.set_setting("display/window/size/min_width", MIN_SIZE.x)
ProjectSettings.set_setting("display/window/size/min_height", MIN_SIZE.y)
DisplayServer.window_set_min_size(MIN_SIZE)
2025-07-20 13:45:07 +03:00
func render():
# Clear existing content
for child in website_container.get_children():
child.queue_free()
2025-07-20 13:45:07 +03:00
var html_bytes = "<head>
<title>My cool web</title>
2025-07-22 21:15:57 +03:00
<icon src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Google_%22G%22_logo.svg/768px-Google_%22G%22_logo.svg.png\">
2025-07-20 13:45:07 +03:00
<meta name=\"theme-color\" content=\"#000000\">
<meta name=\"description\" content=\"My cool web\">
<style href=\"styles.css\">
<script src=\"script.lua\" />
</head>
<body>
2025-07-23 13:35:42 +03:00
<h1>Header 1</h1>
<h2>Header 2</h2>
<h3>Header 3</h3>
<h4>Header 4</h4>
<h5>Header 5</h5>
<h6>Header 6</h6>
<p>Hey there! this is a test</p>
<b>This is bold</b>
2025-07-22 21:15:57 +03:00
<i>This is italic <mark>actually, and it's pretty <u>cool</u></mark></i>
<u>This is underline</u>
<small>this is small</small>
<mark>this is marked</mark>
2025-07-22 21:15:57 +03:00
<code>this is code<span> THIS IS A SPAN AND SHOULDNT BE ANY DIFFERENT</span></code>
2025-07-22 22:14:37 +03:00
<p>
<a href=\"https://youtube.com\">Hello gang</a>
</p>
<pre>
Text in a pre element
is displayed in a fixed-width
font, and it preserves
both spaces and
line breaks
</pre>
2025-07-20 13:45:07 +03:00
<!-- action, method, and type=submit are for when we implement Lua -->
<form action=\"/submit\" method=\"POST\">
2025-07-23 15:23:32 +03:00
<span>Name:</span>
<input type=\"text\" placeholder=\"First name\" value=\"John\" maxlength=\"20\" minlength=\"3\" />
<span>Email regex:</span>
<input type=\"text\" placeholder=\"Last name\" value=\"Doe\" pattern=\"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$\" />
2025-07-23 15:23:32 +03:00
<span>Smart:</span>
<input type=\"checkbox\" />
<input type=\"checkbox\" value=\"true\" />
<p>favorite food</p>
<input type=\"radio\" group=\"food\" />
<span>Pizza</span>
<input type=\"radio\" group=\"food\" />
<span>Berry</span>
<input type=\"radio\" group=\"food\" />
<span>Gary</span>
2025-07-23 20:42:02 +03:00
<h2>Color</h2>
<input type=\"color\" value=\"#ff0000\" />
<input type=\"password\" placeholder=\"your password...\" />
<button type=\"submit\">Submit</button>
2025-07-23 15:23:32 +03:00
</form>
<separator direction=\"horizontal\" />
<img src=\"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQMNUPIKabszX0Js_c0kfa4cz_JQYKfGTuBUA&s\" />
<separator direction=\"vertical\" />
2025-07-20 13:45:07 +03:00
</body>".to_utf8_buffer()
# Create parser and parse
var parser: HTMLParser = HTMLParser.new(html_bytes)
2025-07-20 13:45:07 +03:00
var parse_result = parser.parse()
print("Total elements found: " + str(parse_result.all_elements.size()))
if parse_result.errors.size() > 0:
print("Parse errors: " + str(parse_result.errors))
# TODO: render the shit on the screen
var tab = tab_container.tabs[tab_container.active_tab]
var title = parser.get_title()
tab.set_title(title)
var icon = parser.get_icon()
2025-07-24 13:52:34 +03:00
tab.update_icon_from_url(icon)
var body = parser.find_first("body")
2025-07-22 21:15:57 +03:00
var i = 0
while i < body.children.size():
var element: HTMLParser.HTMLElement = body.children[i]
if element.is_inline_element():
# Collect consecutive inline elements and flatten nested ones
var inline_elements: Array[HTMLParser.HTMLElement] = []
2025-07-22 22:14:37 +03:00
var has_hyperlink = false
2025-07-22 21:15:57 +03:00
while i < body.children.size() and body.children[i].is_inline_element():
inline_elements.append(body.children[i])
2025-07-22 22:14:37 +03:00
if contains_hyperlink(body.children[i]):
has_hyperlink = true
2025-07-22 21:15:57 +03:00
i += 1
var inline_container = P.instantiate()
var temp_parent = HTMLParser.HTMLElement.new()
temp_parent.tag_name = "p"
temp_parent.children = inline_elements
inline_container.init(temp_parent)
2025-07-22 22:14:37 +03:00
2025-07-22 21:15:57 +03:00
website_container.add_child(inline_container)
2025-07-22 22:14:37 +03:00
if has_hyperlink:
inline_container.rich_text_label.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
2025-07-22 21:15:57 +03:00
continue
var element_node = create_element_node(element)
if element_node:
website_container.add_child(element_node)
# Handle hyperlinks for all elements
if contains_hyperlink(element) and element_node.has_method("get") and element_node.get("rich_text_label"):
element_node.rich_text_label.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
else:
print("Couldn't parse unsupported HTML tag \"%s\"" % element.tag_name)
2025-07-22 21:15:57 +03:00
i += 1
2025-07-22 22:14:37 +03:00
func contains_hyperlink(element: HTMLParser.HTMLElement) -> bool:
if element.tag_name == "a":
return true
for child in element.children:
if contains_hyperlink(child):
return true
return false
2025-07-23 15:23:32 +03:00
func create_element_node(element: HTMLParser.HTMLElement) -> Control:
var node: Control = null
2025-07-23 15:23:32 +03:00
match element.tag_name:
"p":
node = P.instantiate()
node.init(element)
"h1":
node = H1.instantiate()
node.init(element)
"h2":
node = H2.instantiate()
node.init(element)
"h3":
node = H3.instantiate()
node.init(element)
"h4":
node = H4.instantiate()
node.init(element)
"h5":
node = H5.instantiate()
node.init(element)
"h6":
node = H6.instantiate()
node.init(element)
"pre":
node = PRE.instantiate()
node.init(element)
"br":
node = BR.instantiate()
node.init(element)
"img":
node = IMG.instantiate()
node.init(element)
"separator":
node = SEPARATOR.instantiate()
node.init(element)
"form":
node = FORM.instantiate()
node.init(element)
for child_element in element.children:
var child_node = create_element_node(child_element)
if child_node:
node.add_child(child_node)
2025-07-23 15:23:32 +03:00
"input":
node = INPUT.instantiate()
node.init(element)
2025-07-23 15:23:32 +03:00
"button":
node = BUTTON.instantiate()
node.init(element)
2025-07-23 15:23:32 +03:00
"span":
node = SPAN.instantiate()
node.init(element)
2025-07-23 15:23:32 +03:00
_:
return null
return node