feat: attribute selection
parent
c923159d7a
commit
79d6a8f77d
34
css.lua
34
css.lua
|
@ -66,7 +66,8 @@ local function parse_compound_selector( tokeniser )
|
||||||
tag_name = nil,
|
tag_name = nil,
|
||||||
id = nil,
|
id = nil,
|
||||||
class = {},
|
class = {},
|
||||||
attributes = {},
|
attributes_values = {},
|
||||||
|
attributes_present = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
--local selectors = {}
|
--local selectors = {}
|
||||||
|
@ -106,6 +107,37 @@ local function parse_compound_selector( tokeniser )
|
||||||
end
|
end
|
||||||
--table.insert(selectors, {type = "id", value = name})
|
--table.insert(selectors, {type = "id", value = name})
|
||||||
selector.id = name
|
selector.id = name
|
||||||
|
elseif char == "[" then
|
||||||
|
tokeniser.next() -- consume leading [
|
||||||
|
|
||||||
|
local name = tokeniser.read_identifier()
|
||||||
|
|
||||||
|
if tokeniser.peek() == "=" then
|
||||||
|
tokeniser.next()
|
||||||
|
|
||||||
|
if tokeniser.peek() ~= "\"" then
|
||||||
|
error("Expected opening quote \" at pos " .. tokeniser.pos() )
|
||||||
|
end
|
||||||
|
tokeniser.next() -- consume leading "
|
||||||
|
|
||||||
|
local value = ""
|
||||||
|
while tokeniser.peek() ~= "\"" do
|
||||||
|
value = value .. tokeniser.peek()
|
||||||
|
tokeniser.next()
|
||||||
|
end
|
||||||
|
|
||||||
|
tokeniser.next() -- consume trailing "
|
||||||
|
|
||||||
|
selector.attributes_values[name] = value
|
||||||
|
else
|
||||||
|
table.insert( selector.attributes_present, name )
|
||||||
|
end
|
||||||
|
|
||||||
|
if tokeniser.peek() ~= "]" then
|
||||||
|
error("Expected closing bracket (']') at " .. tokeniser.pos())
|
||||||
|
end
|
||||||
|
|
||||||
|
tokeniser.next() -- consume trailing ]
|
||||||
else
|
else
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
76
html.lua
76
html.lua
|
@ -386,45 +386,59 @@ end
|
||||||
|
|
||||||
|
|
||||||
function M.check_simple_selector(element, selector)
|
function M.check_simple_selector(element, selector)
|
||||||
-- Skip text nodes
|
-- Skip text nodes
|
||||||
if element.tag_name == ":text" then
|
if element.tag_name == ":text" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check tag name if specified
|
||||||
|
if selector.tag_name and element.tag_name ~= selector.tag_name then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check ID if specified
|
||||||
|
if selector.id and element.attributes.id ~= selector.id then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check classes if specified
|
||||||
|
if selector.class and #selector.class > 0 then
|
||||||
|
local element_classes = element.attributes.class
|
||||||
|
if not element_classes then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check tag name if specified
|
for _, class in ipairs(selector.class) do
|
||||||
if selector.tag_name and element.tag_name ~= selector.tag_name then
|
local found = false
|
||||||
return false
|
for _, elem_class in ipairs(element_classes) do
|
||||||
end
|
if elem_class == class then
|
||||||
|
found = true
|
||||||
-- Check ID if specified
|
break
|
||||||
if selector.id and element.attributes.id ~= selector.id then
|
end
|
||||||
return false
|
end
|
||||||
end
|
if not found then
|
||||||
|
|
||||||
-- Check classes if specified
|
|
||||||
if selector.class and #selector.class > 0 then
|
|
||||||
local element_classes = element.attributes.class
|
|
||||||
if not element_classes then
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, class in ipairs(selector.class) do
|
|
||||||
local found = false
|
|
||||||
for _, elem_class in ipairs(element_classes) do
|
|
||||||
if elem_class == class then
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not found then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
for attr_name, attr_value in pairs(selector.attributes_values) do
|
||||||
|
local elem_attr_value = element.attributes[attr_name]
|
||||||
|
if elem_attr_value ~= attr_value then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check attribute presence selectors
|
||||||
|
for _, attr_name in ipairs(selector.attributes_present) do
|
||||||
|
if not element.attributes[attr_name] then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
function M.query_simple_selector(document, selector)
|
function M.query_simple_selector(document, selector)
|
||||||
local matches = {}
|
local matches = {}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue