Skip to content

Commit

Permalink
feat: cleaner reimplementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ronaldtse committed Nov 3, 2024
1 parent c739e45 commit d18cf97
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 33 deletions.
26 changes: 15 additions & 11 deletions lib/moxml/adapter/nokogiri.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,12 @@ def create_native_processing_instruction(target, content)
end

def create_native_declaration(version, encoding, standalone)
doc = ::Nokogiri::XML::Document.new
doc.create_internal_subset("xml", nil, nil)
declaration = ::Nokogiri::XML::ProcessingInstruction.new(doc, "xml", declaration_content(version, encoding, standalone))
declaration
end

def declaration_content(version, encoding, standalone)
content = "version=\"#{version}\""
content << " encoding=\"#{encoding}\"" if encoding
content << " standalone=\"#{standalone}\"" if standalone
content
decl = ::Nokogiri::XML::ProcessingInstruction.new(
::Nokogiri::XML::Document.new,
"xml",
build_declaration_attrs(version, encoding, standalone)
)
decl
end

def set_namespace(element, ns)
Expand Down Expand Up @@ -227,6 +222,15 @@ def serialize(node, options = {})
save_with: save_options,
)
end

private

def build_declaration_attrs(version, encoding, standalone)
attrs = { "version" => version }
attrs["encoding"] = encoding if encoding
attrs["standalone"] = standalone if standalone
attrs.map { |k, v| %{#{k}="#{v}"} }.join(" ")
end
end
end
end
Expand Down
9 changes: 3 additions & 6 deletions lib/moxml/adapter/oga.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,10 @@ def create_native_processing_instruction(target, content)
end

def create_native_declaration(version, encoding, standalone)
doc = ::Oga::XML::Document.new
doc.xml_declaration = ::Oga::XML::XmlDeclaration.new(
version: version,
encoding: encoding,
standalone: standalone,
::Oga::XML::ProcessingInstruction.new(
name: "xml",
text: build_declaration_attrs(version, encoding, standalone),
)
doc
end

def create_native_namespace(element, prefix, uri)
Expand Down
6 changes: 6 additions & 0 deletions lib/moxml/adapter/ox.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ def create_document
::Ox::Document.new
end

def create_native_declaration(version, encoding, standalone)
inst = ::Ox::Instruction.new("xml")
inst.value = build_declaration_attrs(version, encoding, standalone)
inst
end

def create_native_element(name)
element = ::Ox::Element.new(name)
element.instance_variable_set(:@attributes, {})
Expand Down
47 changes: 34 additions & 13 deletions lib/moxml/declaration.rb
Original file line number Diff line number Diff line change
@@ -1,28 +1,44 @@
# lib/moxml/declaration.rb
module Moxml
class Declaration < Node
ALLOWED_VERSIONS = ["1.0", "1.1"].freeze
ALLOWED_STANDALONE = ["yes", "no"].freeze

def version
extract_attribute("version")
end

def version=(new_version)
update_content("version", new_version)
unless ALLOWED_VERSIONS.include?(new_version)
raise ValidationError, "Invalid XML version: #{new_version}"
end
set_attribute("version", new_version)
end

def encoding
extract_attribute("encoding")
end

def encoding=(new_encoding)
update_content("encoding", new_encoding)
if new_encoding
begin
Encoding.find(new_encoding)
rescue ArgumentError
raise ValidationError, "Invalid encoding: #{new_encoding}"
end
end
set_attribute("encoding", new_encoding)
end

def standalone
extract_attribute("standalone")
end

def standalone=(new_standalone)
update_content("standalone", new_standalone)
unless new_standalone.nil? || ALLOWED_STANDALONE.include?(new_standalone)
raise ValidationError, "Invalid standalone value: #{new_standalone}"
end
set_attribute("standalone", new_standalone)
end

def declaration?
Expand All @@ -37,19 +53,24 @@ def extract_attribute(name)
match && match[1]
end

def update_content(name, value)
content = @native.content || ""
def set_attribute(name, value)
attrs = current_attributes
if value.nil?
content.gsub!(/\s*#{name}="[^"]*"/, "")
attrs.delete(name)
else
if content.include?("#{name}=\"")
content.gsub!(/#{name}="[^"]*"/, "#{name}=\"#{value}\"")
else
content << " #{name}=\"#{value}\""
end
attrs[name] = value
end
@native.content = content.strip
self
update_content(attrs)
end

def current_attributes
@native.content.to_s.scan(/(\w+)="([^"]*)"/).each_with_object({}) do |(name, value), hash|
hash[name] = value
end
end

def update_content(attrs)
@native.content = attrs.map { |k, v| %{#{k}="#{v}"} }.join(" ")
end
end
end
6 changes: 3 additions & 3 deletions spec/moxml/comment_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

describe "serialization" do
it "wraps content in comment markers" do
expect(comment.to_xml(pretty: false)).to eq("<!-- test comment -->")
expect(comment.to_xml(pretty: false)).to eq("<!--test comment-->")
end

it "escapes double hyphens" do
Expand All @@ -38,7 +38,7 @@

it "handles special characters" do
comment.content = "< > & \" '"
expect(comment.to_xml(pretty: false)).to eq("<!-- < > & \" ' -->")
expect(comment.to_xml(pretty: false)).to eq("<!--< > & \" '-->")
end
end

Expand All @@ -47,7 +47,7 @@

it "adds to element" do
element.add_child(comment)
expect(element.to_xml).to include("<!-- test comment -->")
expect(element.to_xml).to include("<!--test comment-->")
end

it "removes from element" do
Expand Down

0 comments on commit d18cf97

Please sign in to comment.