Files
news.gitea.happylizard.me/bin/gems/html-proofer-5.0.10/lib/html_proofer/element.rb
T
pizza2d1 4cee170d66
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 9s
Add bin and edit workflow
2026-09-16 13:11:16 -06:00

159 lines
3.8 KiB
Ruby

# frozen_string_literal: true
require "addressable/uri"
module HTMLProofer
# Represents the element currently being processed
class Element
include HTMLProofer::Utils
attr_reader :node, :url, :base_url, :line, :content
def initialize(runner, node, base_url: nil)
@runner = runner
@node = node
swap_attributes!
@base_url = base_url
@url = Attribute::Url.new(runner, link_attribute, base_url: base_url, source: @runner.current_source, filename: @runner.current_filename)
@line = node.line
@content = node.content
end
def link_attribute
meta_content || src || srcset || href
end
def meta_content
return unless meta_tag?
@node["content"]
end
def meta_tag?
@node.name == "meta"
end
def src
return if !img_tag? && !script_tag? && !source_tag?
@node["src"]
end
def img_tag?
@node.name == "img"
end
def script_tag?
@node.name == "script"
end
def srcset
return if !img_tag? && !source_tag?
@node["srcset"]
end
def source_tag?
@node.name == "source"
end
def href
return if !a_tag? && !link_tag?
@node["href"]
end
def a_tag?
@node.name == "a"
end
def link_tag?
@node.name == "link"
end
def aria_hidden?
@node.attributes["aria-hidden"]&.value == "true"
end
def multiple_srcsets?
!blank?(srcset) && srcset.split(",").size > 1
end
# From https://github.com/sindresorhus/srcset/blob/f7c48acd7facf18e94dec47e6b96e84e0f0e69dc/index.js#LL1-L16C71
# This regex represents a loose rule of an “image candidate string”; see https://html.spec.whatwg.org/multipage/images.html#srcset-attribute
# An “image candidate string” roughly consists of the following:
# 1. Zero or more whitespace characters.
# 2. A non-empty URL that does not start or end with `,`.
# 3. Zero or more whitespace characters.
# 4. An optional “descriptor” that starts with a whitespace character.
# 5. Zero or more whitespace characters.
# 6. Each image candidate string is separated by a `,`.
# We intentionally implement a loose rule here so that we can perform more aggressive error handling and reporting in the below code.
IMAGE_CANDIDATE_REGEX = /\s*([^,]\S*[^,](?:\s+[^,]+)?)\s*(?:,|$)/
def srcsets
return if blank?(srcset)
srcset.split(IMAGE_CANDIDATE_REGEX).select.with_index do |_part, idx|
idx.odd?
end.map(&:strip)
end
def multiple_sizes?
return false if blank?(srcsets)
srcsets.any? do |srcset|
!blank?(srcset) && srcset.split(" ").size > 1
end
end
def srcsets_wo_sizes
return if blank?(srcsets)
srcsets.map do |srcset|
srcset.split(" ").first
end
end
def ignore?
return true if @node.attributes["data-proofer-ignore"]
return true if ancestors_ignorable?
return true if url&.ignore?
false
end
private def attribute_swapped?
return false if blank?(@runner.options[:swap_attributes])
attrs = @runner.options[:swap_attributes][@node.name]
true unless blank?(attrs)
end
private def swap_attributes!
return unless attribute_swapped?
attr_swaps = @runner.options[:swap_attributes][@node.name]
attr_swaps.flatten.each_slice(2) do |(old_attr, new_attr)|
next if blank?(node[old_attr])
node[new_attr] = node[old_attr]
node.delete(old_attr)
end
end
private def ancestors_ignorable?
ancestors_attributes = @node.ancestors.map { |a| a.respond_to?(:attributes) && a.attributes }
ancestors_attributes.pop # remove document at the end
ancestors_attributes.any? { |a| !a["data-proofer-ignore"].nil? }
end
end
end