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