add class selectors
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
gurted (verb)
|
||||
> “to do something smart, but also dangerous”
|
||||
|
||||
Sir facedev you should use the appropriate feature for this (issues) instead of using the readme, it's not professional.
|
||||
wayfinder (noun)
|
||||
> “a person helping others navigate”
|
||||
|
||||
In traditional web, you might be familiar with the term "browser." A **wayfinder** is that, but for the **GURT** protocol.
|
||||
|
||||
TODO:
|
||||
1. Write a new **selection system**. Godot's built-in `RichTextLabel` selection is limited by the node's boundaries. In normal web, holding click and dragging your mouse across the screen will select text across multiple nodes. Godot doesn't have a "set_selected_text" property, despite having one for "get_selected_text".
|
||||
|
||||
@@ -21,6 +21,8 @@ class CSSRule:
|
||||
|
||||
func calculate_specificity():
|
||||
specificity = 1
|
||||
if selector.begins_with("."):
|
||||
specificity += 10 # Class selectors have higher specificity than tag selectors
|
||||
if event_prefix.length() > 0:
|
||||
specificity += 10
|
||||
|
||||
@@ -30,13 +32,13 @@ class CSSStylesheet:
|
||||
func add_rule(rule: CSSRule):
|
||||
rules.append(rule)
|
||||
|
||||
func get_styles_for_element(tag_name: String, event: String = "") -> Dictionary:
|
||||
func get_styles_for_element(tag_name: String, event: String = "", class_names: Array[String] = []) -> Dictionary:
|
||||
var styles = {}
|
||||
|
||||
# Sort rules by specificity
|
||||
var applicable_rules: Array[CSSRule] = []
|
||||
for rule in rules:
|
||||
if selector_matches(rule, tag_name, event):
|
||||
if selector_matches(rule, tag_name, event, class_names):
|
||||
applicable_rules.append(rule)
|
||||
|
||||
applicable_rules.sort_custom(func(a, b): return a.specificity < b.specificity)
|
||||
@@ -48,9 +50,16 @@ class CSSStylesheet:
|
||||
|
||||
return styles
|
||||
|
||||
func selector_matches(rule: CSSRule, tag_name: String, event: String = "") -> bool:
|
||||
if rule.selector != tag_name:
|
||||
return false
|
||||
func selector_matches(rule: CSSRule, tag_name: String, event: String = "", cls_names: Array[String] = []) -> bool:
|
||||
# Handle class selectors
|
||||
if rule.selector.begins_with("."):
|
||||
var cls = rule.selector.substr(1) # Remove the "." prefix
|
||||
if not cls in cls_names:
|
||||
return false
|
||||
else:
|
||||
# Handle tag selectors
|
||||
if rule.selector != tag_name:
|
||||
return false
|
||||
|
||||
if rule.event_prefix.length() > 0:
|
||||
return rule.event_prefix == event
|
||||
@@ -556,6 +565,39 @@ static func parse_inline_style(style_string: String) -> Dictionary:
|
||||
|
||||
return rule.properties
|
||||
|
||||
# TODO: probably a better idea to precompile the patterns, though idk how much more efficient that would be, if at all
|
||||
static func is_utility_class(cls: String) -> bool:
|
||||
var utility_patterns = [
|
||||
"^text-(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl)$", # font sizes
|
||||
"^text-(left|center|right|justify)$", # text alignment
|
||||
"^text-\\[.*\\]$", # custom text colors
|
||||
"^text-(white|black|transparent|slate-\\d+|gray-\\d+|red-\\d+|green-\\d+|blue-\\d+|yellow-\\d+)$", # text colors
|
||||
"^bg-\\[.*\\]$", # custom bg colors
|
||||
"^bg-(white|black|transparent|slate-\\d+|gray-\\d+|red-\\d+|green-\\d+|blue-\\d+|yellow-\\d+)$", # bg colors
|
||||
"^(w|h|min-w|min-h|max-w|max-h)-", # sizing
|
||||
"^font-(bold|mono|italic)$", # font styles
|
||||
"^underline$",
|
||||
"^flex", # flex utilities
|
||||
"^items-", # align items
|
||||
"^justify-", # justify content
|
||||
"^content-", # align content
|
||||
"^self-", # align self
|
||||
"^order-", # order
|
||||
"^gap-", # gap
|
||||
"^(p|px|py|pt|pr|pb|pl)-", # padding
|
||||
"^rounded", # border radius
|
||||
"^basis-", # flex basis
|
||||
"^(hover|active):", # pseudo classes
|
||||
]
|
||||
|
||||
for pattern in utility_patterns:
|
||||
var regex = RegEx.new()
|
||||
regex.compile(pattern)
|
||||
if regex.search(cls):
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
static func get_color(color_name: String) -> Color:
|
||||
# Common colors
|
||||
match color_name:
|
||||
|
||||
@@ -132,8 +132,8 @@ func get_element_styles_with_inheritance(element: HTMLElement, event: String = "
|
||||
|
||||
var styles = {}
|
||||
|
||||
styles.merge(parse_result.css_parser.stylesheet.get_styles_for_element(element.tag_name, event))
|
||||
|
||||
var class_names = extract_class_names_from_style(element)
|
||||
styles.merge(parse_result.css_parser.stylesheet.get_styles_for_element(element.tag_name, event, class_names))
|
||||
# Apply inline styles (higher priority) - force override CSS rules
|
||||
var inline_style = element.get_attribute("style")
|
||||
if inline_style.length() > 0:
|
||||
@@ -159,7 +159,8 @@ func get_element_styles_internal(element: HTMLElement, event: String = "") -> Di
|
||||
|
||||
# Apply CSS rules
|
||||
if parse_result.css_parser:
|
||||
styles.merge(parse_result.css_parser.stylesheet.get_styles_for_element(element.tag_name, event))
|
||||
var class_names = extract_class_names_from_style(element)
|
||||
styles.merge(parse_result.css_parser.stylesheet.get_styles_for_element(element.tag_name, event, class_names))
|
||||
|
||||
# Apply inline styles (higher priority) - force override CSS rules
|
||||
var inline_style = element.get_attribute("style")
|
||||
@@ -198,6 +199,17 @@ func parse_inline_style_with_event(style_string: String, event: String = "") ->
|
||||
|
||||
return properties
|
||||
|
||||
func extract_class_names_from_style(element: HTMLElement) -> Array[String]:
|
||||
var class_names: Array[String] = []
|
||||
var style_attr = element.get_attribute("style")
|
||||
if style_attr.length() > 0:
|
||||
var style_tokens = style_attr.split(" ")
|
||||
for token in style_tokens:
|
||||
token = token.strip_edges()
|
||||
if token.length() > 0 and not CSSParser.is_utility_class(token):
|
||||
class_names.append(token)
|
||||
return class_names
|
||||
|
||||
# Creates element from CURRENT xml parser node
|
||||
func create_element() -> HTMLElement:
|
||||
var element = HTMLElement.new(xml_parser.get_node_name())
|
||||
@@ -230,7 +242,7 @@ func find_all_by_class(tag: String, the_class_name: String) -> Array[HTMLElement
|
||||
|
||||
var results: Array[HTMLElement] = []
|
||||
for element in parse_result.all_elements:
|
||||
if element.tag_name == tag and element.get_class() == the_class_name:
|
||||
if element.tag_name == tag and element.get_class_name() == the_class_name:
|
||||
results.append(element)
|
||||
|
||||
return results
|
||||
|
||||
@@ -35,7 +35,7 @@ var HTML_CONTENT = """<head>
|
||||
h2 { text-[#cbd5e1] text-xl }
|
||||
p { text-[#94a3b8] text-base }
|
||||
button { bg-[#4ade80] text-[#ffffff] hover:bg-[#22c55e] active:bg-[#15803d] }
|
||||
card { bg-[#1e293b] text-[#f8fafc] rounded-xl p-4 shadow-lg }
|
||||
.card { bg-[#1e293b] text-[#f8fafc] rounded-xl p-4 shadow-lg }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user