Xml: Add #element_text method
This refactors verbose code in the `Sparkle` strategy where we access element text into a reusable `Xml#element_text` method, replacing chained calls like `item.elements["title"]&.text&.strip&.presence` with `Xml.element_text(item, "title")`. `#element_text` is only used to retrieve the text of a child element in the `Sparkle` strategy but it can also retrieve the text from the provided element if the `child_path` argument is omitted (i.e., `Xml.element_text(item)`). This will allow us to also avoid similar calls like `item.text.strip.presence` in the future.
This commit is contained in:
parent
5fa5f3b0aa
commit
9bfe423a5a
@ -95,16 +95,16 @@ module Homebrew
|
||||
os = enclosure["os"].presence
|
||||
end
|
||||
|
||||
title = item.elements["title"]&.text&.strip&.presence
|
||||
link = item.elements["link"]&.text&.strip&.presence
|
||||
title = Xml.element_text(item, "title")
|
||||
link = Xml.element_text(item, "link")
|
||||
url ||= link
|
||||
channel = item.elements["channel"]&.text&.strip&.presence
|
||||
release_notes_link = item.elements["releaseNotesLink"]&.text&.strip&.presence
|
||||
short_version ||= item.elements["shortVersionString"]&.text&.strip&.presence
|
||||
version ||= item.elements["version"]&.text&.strip&.presence
|
||||
channel = Xml.element_text(item, "channel")
|
||||
release_notes_link = Xml.element_text(item, "releaseNotesLink")
|
||||
short_version ||= Xml.element_text(item, "shortVersionString")
|
||||
version ||= Xml.element_text(item, "version")
|
||||
|
||||
minimum_system_version_text =
|
||||
item.elements["minimumSystemVersion"]&.text&.strip&.gsub(/\A\D+|\D+\z/, "")&.presence
|
||||
Xml.element_text(item, "minimumSystemVersion")&.gsub(/\A\D+|\D+\z/, "")
|
||||
if minimum_system_version_text.present?
|
||||
minimum_system_version = begin
|
||||
MacOSVersion.new(minimum_system_version_text)
|
||||
@ -113,7 +113,7 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
pub_date = item.elements["pubDate"]&.text&.strip&.presence&.then do |date_string|
|
||||
pub_date = Xml.element_text(item, "pubDate")&.then do |date_string|
|
||||
Time.parse(date_string)
|
||||
rescue ArgumentError
|
||||
# Omit unparsable strings (e.g. non-English dates)
|
||||
|
@ -72,6 +72,30 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
# Retrieves the stripped inner text of an `REXML` element. Returns
|
||||
# `nil` if the optional child element doesn't exist or the text is
|
||||
# blank.
|
||||
# @param element [REXML::Element] an `REXML` element to retrieve text
|
||||
# from, either directly or from a child element
|
||||
# @param child_path [String, nil] the XPath of a child element to
|
||||
# retrieve text from
|
||||
# @return [String, nil]
|
||||
sig {
|
||||
params(
|
||||
element: REXML::Element,
|
||||
child_path: T.nilable(String),
|
||||
).returns(T.nilable(String))
|
||||
}
|
||||
def self.element_text(element, child_path = nil)
|
||||
element = element.get_elements(child_path).first if child_path.present?
|
||||
return if element.nil?
|
||||
|
||||
text = element.text
|
||||
return if text.blank?
|
||||
|
||||
text.strip
|
||||
end
|
||||
|
||||
# Parses XML text and identifies versions using a `strategy` block.
|
||||
# If a regex is provided, it will be passed as the second argument to
|
||||
# the `strategy` block (after the parsed XML data).
|
||||
|
@ -79,6 +79,24 @@ describe Homebrew::Livecheck::Strategy::Xml do
|
||||
EOS
|
||||
end
|
||||
|
||||
let(:parent_child_text) { { parent: "1.2.3", child: "4.5.6" } }
|
||||
let(:content_parent_child) do
|
||||
# This XML deliberately includes unnecessary whitespace, to ensure that
|
||||
# Xml#element_text properly strips the retrieved text.
|
||||
<<~EOS
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<elements>
|
||||
<parent>
|
||||
#{parent_child_text[:parent]}
|
||||
<child> #{parent_child_text[:child]} </child>
|
||||
</parent>
|
||||
<blank-parent>
|
||||
<blank-child></blank-child>
|
||||
</blank-parent>
|
||||
</elements>
|
||||
EOS
|
||||
end
|
||||
|
||||
let(:content_matches) { ["1.1.2", "1.1.1", "1.1.0", "1.0.3", "1.0.2", "1.0.1", "1.0.0"] }
|
||||
let(:content_simple_matches) { ["1.2.3"] }
|
||||
|
||||
@ -123,6 +141,29 @@ describe Homebrew::Livecheck::Strategy::Xml do
|
||||
end
|
||||
end
|
||||
|
||||
describe "::element_text" do
|
||||
let(:parent_child_doc) { xml.parse_xml(content_parent_child) }
|
||||
let(:parent) { parent_child_doc.get_elements("/elements/parent").first }
|
||||
let(:blank_parent) { parent_child_doc.get_elements("/elements/blank-parent").first }
|
||||
|
||||
it "returns the element text if child_name is not provided" do
|
||||
expect(xml.element_text(parent)).to eq(parent_child_text[:parent])
|
||||
end
|
||||
|
||||
it "returns the child element text if child_name is provided" do
|
||||
expect(xml.element_text(parent, "child")).to eq(parent_child_text[:child])
|
||||
end
|
||||
|
||||
it "returns `nil` if the provided child element does not exist" do
|
||||
expect(xml.element_text(parent, "nonexistent")).to be_nil
|
||||
end
|
||||
|
||||
it "returns `nil` if the retrieved text is blank" do
|
||||
expect(xml.element_text(blank_parent)).to be_nil
|
||||
expect(xml.element_text(blank_parent, "blank-child")).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "::versions_from_content" do
|
||||
it "returns an empty array when given a block but content is blank" do
|
||||
expect(xml.versions_from_content("", regex) { "1.2.3" }).to eq([])
|
||||
|
Loading…
x
Reference in New Issue
Block a user