border styles
This commit is contained in:
@@ -18,6 +18,7 @@ TODO:
|
||||
9. Installer should register **gurt://** as a valid protocol thru the registry.
|
||||
10. < input type=**datetime** />, essentially a type "date" but with a vertical separator, then `mm | ss | FORMAT` layout for time.
|
||||
11. **< table >** component. [🔗 Related Godot proposal](https://github.com/godotengine/godot-proposals/issues/97)
|
||||
12. **< canvas >** component should be theoretically impossible by exposing Godot `_draw()` APIs to Lua.
|
||||
|
||||
Issues:
|
||||
1. **< br />** counts as 1 element in **WebsiteContainer**, therefore despite being (0,0) in size, it counts as double in spacing
|
||||
|
||||
@@ -508,6 +508,86 @@ static func parse_utility_class_internal(rule: CSSRule, utility_name: String) ->
|
||||
rule.properties["my-auto"] = true
|
||||
return
|
||||
|
||||
# Apply border properties
|
||||
var apply_border = func(side: String, width: String = "", color = null, style: String = "solid"):
|
||||
var prefix = "border" + ("-" + side if side != "" else "")
|
||||
if width != "":
|
||||
rule.properties[prefix + "-width"] = width
|
||||
if color != null:
|
||||
rule.properties[prefix + "-color"] = color
|
||||
if style != "":
|
||||
rule.properties[prefix + "-style"] = style
|
||||
|
||||
# Handle border utilities
|
||||
if utility_name == "border":
|
||||
apply_border.call("", "1px", Color.BLACK)
|
||||
return
|
||||
|
||||
if utility_name == "border-none":
|
||||
rule.properties["border-style"] = "none"
|
||||
return
|
||||
|
||||
# Individual border sides - pattern: border-{side}-{value}
|
||||
var border_sides = ["t", "r", "b", "l"]
|
||||
var side_map = {"t": "top", "r": "right", "b": "bottom", "l": "left"}
|
||||
|
||||
for side in border_sides:
|
||||
var short_side = side
|
||||
var full_side = side_map[side]
|
||||
|
||||
# Basic side border (e.g., border-t)
|
||||
if utility_name == "border-" + short_side:
|
||||
apply_border.call(full_side, "1px")
|
||||
return
|
||||
|
||||
# Side with value (e.g., border-t-2, border-t-red-500)
|
||||
if utility_name.begins_with("border-" + short_side + "-"):
|
||||
var val = utility_name.substr(9) # after "border-X-"
|
||||
|
||||
# Check for bracket notation first
|
||||
if utility_name.begins_with("border-" + short_side + "-[") and utility_name.ends_with("]"):
|
||||
var value = SizeUtils.extract_bracket_content(utility_name, 9)
|
||||
if value.begins_with("#") or ColorUtils.parse_color(value) != null:
|
||||
apply_border.call(full_side, "", ColorUtils.parse_color(value))
|
||||
else:
|
||||
apply_border.call(full_side, value)
|
||||
return
|
||||
|
||||
# Check if it's a numeric width
|
||||
if val.is_valid_int():
|
||||
apply_border.call(full_side, str(int(val)) + "px")
|
||||
return
|
||||
|
||||
# Check if it's a color
|
||||
var color = ColorUtils.get_color(val)
|
||||
if color != null:
|
||||
apply_border.call(full_side, "", color)
|
||||
return
|
||||
|
||||
# General border width (e.g., border-2)
|
||||
if utility_name.begins_with("border-"):
|
||||
var val = utility_name.substr(7)
|
||||
|
||||
# Custom border width like border-[2px]
|
||||
if utility_name.begins_with("border-[") and utility_name.ends_with("]"):
|
||||
var value = SizeUtils.extract_bracket_content(utility_name, 7)
|
||||
if value.begins_with("#"):
|
||||
apply_border.call("", "", ColorUtils.parse_color(value))
|
||||
else:
|
||||
apply_border.call("", value)
|
||||
return
|
||||
|
||||
# Numeric width
|
||||
if val.is_valid_int():
|
||||
apply_border.call("", str(int(val)) + "px")
|
||||
return
|
||||
|
||||
# Color name
|
||||
var color = ColorUtils.get_color(val)
|
||||
if color != null:
|
||||
apply_border.call("", "", color)
|
||||
return
|
||||
|
||||
# Handle more utility classes as needed
|
||||
# Add more cases here for other utilities
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ pre { text-xl font-mono }
|
||||
button { bg-[#1b1b1b] rounded-md text-white hover:bg-[#2a2a2a] active:bg-[#101010] }
|
||||
"""
|
||||
|
||||
var HTML_CONTENT = """<head>
|
||||
var HTML_CONTENT2 = """<head>
|
||||
<title>My Custom Dashboard</title>
|
||||
<icon src="https://cdn-icons-png.flaticon.com/512/1828/1828774.png">
|
||||
<meta name="theme-color" content="#1a202c">
|
||||
@@ -99,7 +99,7 @@ var HTML_CONTENT = """<head>
|
||||
|
||||
</body>
|
||||
""".to_utf8_buffer()
|
||||
var HTML_CONTENT2 = """<head>
|
||||
var HTML_CONTENT = """<head>
|
||||
<title>My cool web</title>
|
||||
<icon src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Google_%22G%22_logo.svg/768px-Google_%22G%22_logo.svg.png\">
|
||||
|
||||
@@ -141,7 +141,7 @@ var HTML_CONTENT2 = """<head>
|
||||
<code>this is code<span> THIS IS A SPAN AND SHOULDNT BE ANY DIFFERENT</span></code>
|
||||
|
||||
<p>
|
||||
<a href=\"https://youtube.com\">Hello gang</a>
|
||||
<a href="https://youtube.com">Hello gang</a>
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -152,9 +152,36 @@ both spaces and
|
||||
line breaks
|
||||
</pre>
|
||||
|
||||
<p style=\"text-center w-32 h-32\">
|
||||
So
|
||||
</p>
|
||||
<p style="text-center w-32 h-32">
|
||||
So
|
||||
</p>
|
||||
|
||||
<!-- Border examples -->
|
||||
<div style="border p-2 mb-2">border</div>
|
||||
<div style="border-2 p-2 mb-2">border-2</div>
|
||||
<div style="border-4 p-2 mb-2">border-4</div>
|
||||
<div style="border-2 border-red-500 p-2 mb-2">border-2 border-red-500</div>
|
||||
<div style="border p-2 mb-2">border-solid</div>
|
||||
<div style="border border-dashed p-2 mb-2">border-dashed</div>
|
||||
<div style="border border-dotted p-2 mb-2">border-dotted</div>
|
||||
<div style="border-none p-2 mb-2">border-none</div>
|
||||
<div style="border-t p-2 mb-2">border-t</div>
|
||||
<div style="border-r p-2 mb-2">border-r</div>
|
||||
<div style="border-b p-2 mb-2">border-b</div>
|
||||
<div style="border-l p-2 mb-2">border-l</div>
|
||||
<div style="border-t-4 p-2 mb-2">border-t-4</div>
|
||||
<div style="border-b-2 p-2 mb-2">border-b-2</div>
|
||||
<div style="border-l-6 p-2 mb-2">border-l-6</div>
|
||||
<div style="border-t-3 border-green-500 p-2 mb-2">border-t-3 border-green-500</div>
|
||||
<div style="border border-white p-2 mb-2">border-white</div>
|
||||
<div style="border border-black p-2 mb-2">border-black</div>
|
||||
<div style="border border-transparent p-2 mb-2">border-transparent</div>
|
||||
<div style="border border-gray-400 p-2 mb-2">border-gray-400</div>
|
||||
<div style="border border-slate-700 p-2 mb-2">border-slate-700</div>
|
||||
<div style="border border-red-500 p-2 mb-2">border-red-500</div>
|
||||
<div style="border border-green-600 p-2 mb-2">border-green-600</div>
|
||||
<div style="border border-blue-400 p-2 mb-2">border-blue-400</div>
|
||||
<div style="border border-yellow-300 p-2 mb-2">border-yellow-300</div>
|
||||
|
||||
<select style=\"text-center max-w-5 max-h-32\">
|
||||
<option value=\"test1\">Test 1</option>
|
||||
|
||||
@@ -84,14 +84,30 @@ static func apply_element_styles(node: Control, element: HTMLParser.HTMLElement,
|
||||
if label and label != node:
|
||||
label.anchors_preset = Control.PRESET_FULL_RECT
|
||||
|
||||
# Apply background color and border radius
|
||||
if styles.has("background-color") or styles.has("border-radius"):
|
||||
# Apply background color, border radius, borders
|
||||
var needs_styling = styles.has("background-color") or styles.has("border-radius") or styles.has("border-width") or styles.has("border-top-width") or styles.has("border-right-width") or styles.has("border-bottom-width") or styles.has("border-left-width") or styles.has("border-color")
|
||||
|
||||
if needs_styling:
|
||||
var target_node_for_bg = node if node is FlexContainer else label
|
||||
if target_node_for_bg:
|
||||
if styles.has("background-color"):
|
||||
target_node_for_bg.set_meta("custom_css_background_color", styles["background-color"])
|
||||
if styles.has("border-radius"):
|
||||
target_node_for_bg.set_meta("custom_css_border_radius", styles["border-radius"])
|
||||
|
||||
# Border properties
|
||||
if styles.has("border-width"):
|
||||
target_node_for_bg.set_meta("custom_css_border_width", styles["border-width"])
|
||||
if styles.has("border-color"):
|
||||
target_node_for_bg.set_meta("custom_css_border_color", styles["border-color"])
|
||||
|
||||
# Individual border sides
|
||||
var border_sides = ["top", "right", "bottom", "left"]
|
||||
for side in border_sides:
|
||||
var width_key = "border-" + side + "-width"
|
||||
if styles.has(width_key):
|
||||
target_node_for_bg.set_meta("custom_css_" + width_key.replace("-", "_"), styles[width_key])
|
||||
|
||||
if target_node_for_bg.has_method("add_background_rect"):
|
||||
target_node_for_bg.call_deferred("add_background_rect")
|
||||
|
||||
|
||||
@@ -30,6 +30,60 @@ static func create_stylebox_from_styles(styles: Dictionary = {}, container: Cont
|
||||
style_box.corner_radius_bottom_left = radius
|
||||
style_box.corner_radius_bottom_right = radius
|
||||
|
||||
# Border properties
|
||||
var has_border = false
|
||||
|
||||
style_box.border_width_top = 0
|
||||
style_box.border_width_right = 0
|
||||
style_box.border_width_bottom = 0
|
||||
style_box.border_width_left = 0
|
||||
|
||||
var general_border_width = null
|
||||
if styles.has("border-width"):
|
||||
general_border_width = styles["border-width"]
|
||||
elif container and container.has_meta("custom_css_border_width"):
|
||||
general_border_width = container.get_meta("custom_css_border_width")
|
||||
|
||||
if general_border_width:
|
||||
has_border = true
|
||||
var parsed_width = StyleManager.parse_size(general_border_width)
|
||||
style_box.border_width_top = parsed_width
|
||||
style_box.border_width_right = parsed_width
|
||||
style_box.border_width_bottom = parsed_width
|
||||
style_box.border_width_left = parsed_width
|
||||
|
||||
var individual_border_keys = [
|
||||
["border-top-width", "border_width_top"],
|
||||
["border-right-width", "border_width_right"],
|
||||
["border-bottom-width", "border_width_bottom"],
|
||||
["border-left-width", "border_width_left"]
|
||||
]
|
||||
|
||||
for pair in individual_border_keys:
|
||||
var style_key = pair[0]
|
||||
var property_name = pair[1]
|
||||
var width = null
|
||||
var meta_key = "custom_css_" + style_key.replace("-", "_")
|
||||
|
||||
if styles.has(style_key):
|
||||
width = styles[style_key]
|
||||
elif container and container.has_meta(meta_key):
|
||||
width = container.get_meta(meta_key)
|
||||
|
||||
if width:
|
||||
has_border = true
|
||||
var parsed_width = StyleManager.parse_size(width)
|
||||
style_box.set(property_name, parsed_width)
|
||||
|
||||
var border_color = Color.BLACK
|
||||
if styles.has("border-color"):
|
||||
border_color = styles["border-color"]
|
||||
elif container and container.has_meta("custom_css_border_color"):
|
||||
border_color = container.get_meta("custom_css_border_color")
|
||||
|
||||
if has_border:
|
||||
style_box.border_color = border_color
|
||||
|
||||
# Padding as content margins
|
||||
var has_padding = false
|
||||
if styles.size() > 0:
|
||||
@@ -114,4 +168,4 @@ static func create_panel_container_with_background(styles: Dictionary) -> PanelC
|
||||
return panel_container
|
||||
|
||||
static func needs_background_wrapper(styles: Dictionary) -> bool:
|
||||
return styles.has("background-color") or styles.has("border-radius") or styles.has("padding") or styles.has("padding-top") or styles.has("padding-right") or styles.has("padding-bottom") or styles.has("padding-left")
|
||||
return styles.has("background-color") or styles.has("border-radius") or styles.has("padding") or styles.has("padding-top") or styles.has("padding-right") or styles.has("padding-bottom") or styles.has("padding-left") or styles.has("border-width") or styles.has("border-top-width") or styles.has("border-right-width") or styles.has("border-bottom-width") or styles.has("border-left-width") or styles.has("border-color") or styles.has("border-style") or styles.has("border-top-color") or styles.has("border-right-color") or styles.has("border-bottom-color") or styles.has("border-left-color")
|
||||
|
||||
@@ -3,6 +3,7 @@ extends RefCounted
|
||||
|
||||
static var compiled_patterns: Array = []
|
||||
|
||||
# TODO: hardcoded colors gotta be swapped with Tailwind colors. stuff like "text-red-500" is considered a selector class
|
||||
static func init_patterns():
|
||||
if compiled_patterns.size() == 0:
|
||||
var utility_patterns = [
|
||||
@@ -28,6 +29,15 @@ static func init_patterns():
|
||||
"^rounded", # border radius
|
||||
"^basis-", # flex basis
|
||||
"^(mx|my|m)-auto$", # margin auto for centering
|
||||
"^border$", # general border
|
||||
"^border-\\d+$", # border width (e.g., border-2)
|
||||
"^border-\\[.*\\]$", # custom border width/color (e.g., border-[2px], border-[#ff0000])
|
||||
"^border-none$", # border styles
|
||||
"^border-(t|r|b|l)$", # individual border sides (e.g., border-t)
|
||||
"^border-(t|r|b|l)-\\d+$", # individual border side widths (e.g., border-t-2)
|
||||
"^border-(t|r|b|l)-\\[.*\\]$", # custom individual border sides (e.g., border-t-[2px])
|
||||
"^border-(t|r|b|l)-(white|black|transparent|slate-\\d+|gray-\\d+|red-\\d+|green-\\d+|blue-\\d+|yellow-\\d+)$", # individual border side colors
|
||||
"^border-(white|black|transparent|slate-\\d+|gray-\\d+|red-\\d+|green-\\d+|blue-\\d+|yellow-\\d+)$", # border colors
|
||||
"^(hover|active):", # pseudo classes
|
||||
]
|
||||
for pattern in utility_patterns:
|
||||
|
||||
@@ -132,6 +132,13 @@ func contains_hyperlink(element: HTMLParser.HTMLElement) -> bool:
|
||||
|
||||
return false
|
||||
|
||||
func is_text_only_element(element: HTMLParser.HTMLElement) -> bool:
|
||||
if element.children.size() == 0:
|
||||
var text = element.get_collapsed_text()
|
||||
return not text.is_empty()
|
||||
|
||||
return false
|
||||
|
||||
func create_element_node(element: HTMLParser.HTMLElement, parser: HTMLParser) -> Control:
|
||||
var styles = parser.get_element_styles_with_inheritance(element, "", [])
|
||||
var is_flex_container = styles.has("display") and ("flex" in styles["display"])
|
||||
@@ -269,7 +276,7 @@ func create_element_node_internal(element: HTMLParser.HTMLElement, parser: HTMLP
|
||||
node.init(element, parser)
|
||||
"span", "b", "i", "u", "small", "mark", "code", "a":
|
||||
node = SPAN.instantiate()
|
||||
node.init(element)
|
||||
node.init(element, parser)
|
||||
"ul":
|
||||
node = UL.instantiate()
|
||||
website_container.add_child(node)
|
||||
@@ -282,24 +289,37 @@ func create_element_node_internal(element: HTMLParser.HTMLElement, parser: HTMLP
|
||||
return node
|
||||
"li":
|
||||
node = LI.instantiate()
|
||||
node.init(element)
|
||||
node.init(element, parser)
|
||||
"select":
|
||||
node = SELECT.instantiate()
|
||||
node.init(element)
|
||||
"option":
|
||||
node = OPTION.instantiate()
|
||||
node.init(element)
|
||||
node.init(element, parser)
|
||||
"textarea":
|
||||
node = TEXTAREA.instantiate()
|
||||
node.init(element)
|
||||
"div":
|
||||
var styles = parser.get_element_styles_with_inheritance(element, "", [])
|
||||
|
||||
|
||||
# Create div container
|
||||
if BackgroundUtils.needs_background_wrapper(styles):
|
||||
node = BackgroundUtils.create_panel_container_with_background(styles)
|
||||
else:
|
||||
node = VBoxContainer.new()
|
||||
node.name = "Div"
|
||||
node = DIV.instantiate()
|
||||
node.init(element)
|
||||
|
||||
var has_only_text = is_text_only_element(element)
|
||||
|
||||
if has_only_text:
|
||||
var p_node = P.instantiate()
|
||||
p_node.init(element)
|
||||
|
||||
var container_for_children = node
|
||||
if node is PanelContainer and node.get_child_count() > 0:
|
||||
container_for_children = node.get_child(0) # The VBoxContainer inside
|
||||
|
||||
safe_add_child(container_for_children, p_node)
|
||||
_:
|
||||
return null
|
||||
|
||||
|
||||
Reference in New Issue
Block a user