--- Build strict file-reference rules for HTML documents
-- @module formats.html.references

local html_references = {}

--- Return the strict prefix before one quoted HTML file target
-- @param name string lowercase attribute name
-- @return string prefix
local function file_attribute(name)
	-- Pattern breakdown: frontiers reject longer and hyphenated names, followed by optional spaces around '='
	return "%f[%w_:%-]" .. name .. "%f[^%w_:%-]%s*=%s*"
end

--- Return whether one HTML target can name a local file
-- @param reference table parsed file reference
-- @return boolean accepted
local function is_local_target(reference)
	local path = reference.path
	if path:sub(1, 1) == "#" or path:sub(1, 2) == "//" then
		return false
	end

	-- Keep Windows drive paths while rejecting URI schemes such as 'https:' and 'data:'
	return path:match("^%a:[/\\]") ~= nil or path:match("^%a[%w+%.%-]*:") == nil
end

--- Remove browser-only query or fragment text when looking for the local file
-- @param reference table parsed file reference
-- @return table candidates
local function file_candidates(reference)
	local filename = reference.path:match("^[^%?#]+")

	return filename and { filename } or {}
end

--- Return direct local-file attributes with normal HTML quote styles
-- @return table rules
function html_references.new()
	local rules = {}

	-- List attributes such as 'srcset' need separate parsing
	for _, attribute in ipairs({ "href", "src", "action", "formaction", "poster", "data" }) do
		local prefix = file_attribute(attribute)
		for _, quote in ipairs({ "\"", "'" }) do
			rules[#rules + 1] = {
				prefix = prefix,
				open = quote,
				close = quote,
				caseless = true,
				validate = is_local_target,
				candidates = file_candidates,
			}
		end
	end

	return rules
end

return html_references
