Skip to content

Commit 1e53fb0

Browse files
committed
Fix XPath syntax errors and hash validation false positives
1 parent 9b0d406 commit 1e53fb0

1 file changed

Lines changed: 17 additions & 6 deletions

File tree

lib/html_proofer/url_validator/internal.rb

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,12 @@ def run_internal_link_checker(links)
116116
return true if blank?(href_hash)
117117
return true unless @runner.options[:check_internal_hash]
118118

119-
# prevents searching files we didn't ask about
120-
return false unless url.known_extension?
121-
return false unless url.has_hash?
119+
# For hash links, we need to defer to file-based checking
120+
# (even if URL doesn't have extension, it may resolve to index.html)
121+
return nil unless url.has_hash?
122+
123+
# If URL has no known extension, defer to file-based checking
124+
return nil unless url.known_extension?
122125

123126
decoded_href_hash = Addressable::URI.unescape(href_hash)
124127
fragment_ids = [href_hash, decoded_href_hash]
@@ -134,10 +137,18 @@ def run_internal_link_checker(links)
134137

135138
private def find_fragments(fragment_ids, html)
136139
xpaths = fragment_ids.uniq.flat_map do |frag_id|
137-
escaped_frag_id = "'#{frag_id.split("'").join("', \"'\", '")}', ''"
140+
# Build XPath string argument, handling single quotes
141+
if frag_id.include?("'")
142+
# Use concat() to handle single quotes: concat('part1', "'", 'part2')
143+
escaped_frag_id = frag_id.split("'").map { |part| "'#{part}'" }.join(", \"'\", ")
144+
xpath_arg = "concat(#{escaped_frag_id})"
145+
else
146+
# No single quotes, just use quoted string
147+
xpath_arg = "'#{frag_id}'"
148+
end
138149
[
139-
"//*[case_sensitive_equals(@id, concat(#{escaped_frag_id}))]",
140-
"//*[case_sensitive_equals(@name, concat(#{escaped_frag_id}))]",
150+
"//*[case_sensitive_equals(@id, #{xpath_arg})]",
151+
"//*[case_sensitive_equals(@name, #{xpath_arg})]",
141152
]
142153
end
143154
xpaths << XpathFunctions.new

0 commit comments

Comments
 (0)