From 7fd4839f7be0104b9f45a232b332e07ec7417489 Mon Sep 17 00:00:00 2001 From: Ronald Tse Date: Tue, 17 Dec 2024 17:39:06 +0800 Subject: [PATCH] chore: rubocop --- .rubocop.yml | 2 + .rubocop_todo.yml | 86 +++++++++++++++++++ Gemfile | 10 +-- lib/moxml.rb | 2 + lib/moxml/adapter.rb | 2 + lib/moxml/adapter/base.rb | 2 + .../adapter/customized_oga/xml_declaration.rb | 4 +- .../adapter/customized_oga/xml_generator.rb | 37 ++++---- lib/moxml/adapter/nokogiri.rb | 36 ++++---- lib/moxml/adapter/oga.rb | 35 ++++---- lib/moxml/adapter/ox.rb | 62 +++++++------ lib/moxml/attribute.rb | 5 +- lib/moxml/builder.rb | 2 + lib/moxml/cdata.rb | 3 +- lib/moxml/comment.rb | 3 +- lib/moxml/config.rb | 4 +- lib/moxml/context.rb | 4 +- lib/moxml/declaration.rb | 4 +- lib/moxml/doctype.rb | 2 + lib/moxml/document.rb | 4 +- lib/moxml/document_builder.rb | 10 ++- lib/moxml/element.rb | 12 +-- lib/moxml/error.rb | 2 + lib/moxml/namespace.rb | 6 +- lib/moxml/node.rb | 22 ++--- lib/moxml/node_set.rb | 3 + lib/moxml/processing_instruction.rb | 4 +- lib/moxml/text.rb | 3 +- lib/moxml/xml_utils.rb | 45 +++++----- lib/moxml/xml_utils/encoder.rb | 16 ++-- spec/moxml/adapter/nokogiri_spec.rb | 4 +- spec/moxml/adapter/oga_spec.rb | 4 +- spec/moxml/adapter/ox_spec.rb | 2 + spec/moxml/all_with_adapters_spec.rb | 42 ++++----- spec/moxml/config_spec.rb | 2 + spec/moxml/error_spec.rb | 14 +-- spec/moxml/examples/adapter_spec.rb | 5 +- spec/moxml_spec.rb | 2 + spec/spec_helper.rb | 4 +- spec/support/shared_examples/attribute.rb | 4 +- spec/support/shared_examples/builder.rb | 4 +- spec/support/shared_examples/cdata.rb | 4 +- spec/support/shared_examples/comment.rb | 4 +- spec/support/shared_examples/context.rb | 4 +- spec/support/shared_examples/declaration.rb | 4 +- spec/support/shared_examples/doctype.rb | 6 +- spec/support/shared_examples/document.rb | 4 +- .../shared_examples/document_builder.rb | 4 +- spec/support/shared_examples/edge_cases.rb | 18 ++-- spec/support/shared_examples/element.rb | 4 +- .../shared_examples/examples/attribute.rb | 2 + .../shared_examples/examples/basic_usage.rb | 2 + .../shared_examples/examples/memory.rb | 7 +- .../shared_examples/examples/namespace.rb | 2 + .../examples/readme_examples.rb | 12 +-- .../shared_examples/examples/thread_safety.rb | 2 + .../support/shared_examples/examples/xpath.rb | 6 +- spec/support/shared_examples/integration.rb | 6 +- spec/support/shared_examples/namespace.rb | 8 +- spec/support/shared_examples/node.rb | 10 ++- spec/support/shared_examples/node_set.rb | 14 +-- .../shared_examples/processing_instruction.rb | 4 +- spec/support/shared_examples/text.rb | 4 +- spec/support/shared_examples/xml_adapter.rb | 10 ++- spec/support/xml_matchers.rb | 4 +- 65 files changed, 436 insertions(+), 228 deletions(-) create mode 100644 .rubocop_todo.yml diff --git a/.rubocop.yml b/.rubocop.yml index 762eebb..640440a 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,3 +1,5 @@ +inherit_from: .rubocop_todo.yml + AllCops: TargetRubyVersion: 3.0 diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000..d400379 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,86 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2024-12-17 09:38:48 UTC using RuboCop version 1.69.2. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +Layout/ElseAlignment: + Exclude: + - 'lib/moxml/adapter/customized_oga/xml_generator.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyleAlignWith, Severity. +# SupportedStylesAlignWith: keyword, variable, start_of_line +Layout/EndAlignment: + Exclude: + - 'lib/moxml/adapter/customized_oga/xml_generator.rb' + +# Offense count: 2 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: Width, AllowedPatterns. +Layout/IndentationWidth: + Exclude: + - 'lib/moxml/adapter/customized_oga/xml_generator.rb' + +# Offense count: 1 +Lint/IneffectiveAccessModifier: + Exclude: + - 'lib/moxml/node.rb' + +# Offense count: 1 +# Configuration parameters: MaximumRangeSize. +Lint/MissingCopEnableDirective: + Exclude: + - 'lib/moxml/adapter/customized_oga/xml_generator.rb' + +# Offense count: 1 +# Configuration parameters: AllowedParentClasses. +Lint/MissingSuper: + Exclude: + - 'lib/moxml/adapter/customized_oga/xml_declaration.rb' + +# Offense count: 5 +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. +Metrics/AbcSize: + Max: 30 + +# Offense count: 46 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. +# AllowedMethods: refine +Metrics/BlockLength: + Max: 152 + +# Offense count: 3 +# Configuration parameters: CountComments, CountAsOne. +Metrics/ClassLength: + Max: 246 + +# Offense count: 3 +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/CyclomaticComplexity: + Max: 10 + +# Offense count: 9 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. +Metrics/MethodLength: + Max: 20 + +# Offense count: 4 +# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. +# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to +Naming/MethodParameterName: + Exclude: + - 'lib/moxml/adapter/customized_oga/xml_generator.rb' + - 'lib/moxml/adapter/nokogiri.rb' + - 'lib/moxml/adapter/ox.rb' + - 'lib/moxml/attribute.rb' + +# Offense count: 27 +# Configuration parameters: AllowedConstants. +Style/Documentation: + Enabled: false diff --git a/Gemfile b/Gemfile index 6cff383..2634084 100644 --- a/Gemfile +++ b/Gemfile @@ -5,12 +5,12 @@ source "https://rubygems.org" # Specify your gem's dependencies in moxml.gemspec gemspec +gem "byebug" +gem "get_process_mem", "~> 1.0.0" +gem "nokogiri", "~> 1.15" +gem "oga", "~> 3.4" +gem "ox", "~> 2.14" gem "rake", "~> 13" gem "rspec", "~> 3.0" gem "rubocop", "~> 1.21" -gem "nokogiri", "~> 1.15" -gem "ox", "~> 2.14" -gem "oga", "~> 3.4" -gem 'get_process_mem', "~> 1.0.0" gem "tempfile", "~> 0.3.1" -gem "byebug" diff --git a/lib/moxml.rb b/lib/moxml.rb index 42f6e4b..35d6595 100644 --- a/lib/moxml.rb +++ b/lib/moxml.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Moxml class << self def new(adapter = nil, &block) diff --git a/lib/moxml/adapter.rb b/lib/moxml/adapter.rb index 47917c7..e6d60e3 100644 --- a/lib/moxml/adapter.rb +++ b/lib/moxml/adapter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "adapter/base" module Moxml diff --git a/lib/moxml/adapter/base.rb b/lib/moxml/adapter/base.rb index 4f72f7c..a561190 100644 --- a/lib/moxml/adapter/base.rb +++ b/lib/moxml/adapter/base.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "../xml_utils" require_relative "../document_builder" diff --git a/lib/moxml/adapter/customized_oga/xml_declaration.rb b/lib/moxml/adapter/customized_oga/xml_declaration.rb index cd542c6..b46b628 100644 --- a/lib/moxml/adapter/customized_oga/xml_declaration.rb +++ b/lib/moxml/adapter/customized_oga/xml_declaration.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "oga" module Moxml @@ -5,7 +7,7 @@ module Adapter module CustomizedOga class XmlDeclaration < ::Oga::XML::XmlDeclaration def initialize(options = {}) - @version = options[:version] || '1.0' + @version = options[:version] || "1.0" # encoding is optional, but Oga sets it to UTF-8 by default @encoding = options[:encoding] @standalone = options[:standalone] diff --git a/lib/moxml/adapter/customized_oga/xml_generator.rb b/lib/moxml/adapter/customized_oga/xml_generator.rb index f551517..f7190d5 100644 --- a/lib/moxml/adapter/customized_oga/xml_generator.rb +++ b/lib/moxml/adapter/customized_oga/xml_generator.rb @@ -1,3 +1,5 @@ +# rubocop:disable Style/FrozenStringLiteralComment + require "oga" # monkey patch the Oga generator because it's not configurable @@ -14,24 +16,23 @@ def self_closing?(_element) def on_element(element, output) name = element.expanded_name - namespace_definitions = '' - element.namespaces.values.each do |ns| - namespace_definitions << ' ' + namespace_definitions = "" + element.namespaces.each_value do |ns| + namespace_definitions << " " on_namespace_definition(ns, namespace_definitions) end - attrs = '' + attrs = "" element.attributes.each do |attr| - attrs << ' ' + attrs << " " on_attribute(attr, attrs) end - closing_tag = - if self_closing?(element) - html_void_element?(element) ? '>' : ' />' - else - ">" - end + closing_tag = if self_closing?(element) + html_void_element?(element) ? ">" : " />" + else + ">" + end output << "<#{name}#{namespace_definitions}#{attrs}#{closing_tag}" end @@ -40,25 +41,23 @@ def on_namespace_definition(ns, output) name = "xmlns" name += ":#{ns.name}" unless ns.name.nil? - output << %Q(#{name}="#{ns.uri}") + output << %(#{name}="#{ns.uri}") end def on_attribute(attr, output) return super unless attr.value&.include?("'") - output << %Q(#{attr.expanded_name}="#{encode(attr.value)}") + output << %(#{attr.expanded_name}="#{encode(attr.value)}") end - + def on_cdata(node, output) # Escape the end sequence return super unless node.text.include?("]]>") chunks = node.text.split(/(\]\]>)/) - if chunks.size == 1 - chunks = ["]]", ">"] - end + chunks = ["]]", ">"] if chunks.size == 1 - while index = chunks.index("]]>") do + while (index = chunks.index("]]>")) # the end tag cannot be the first and the last at the same time if index.zero? @@ -92,7 +91,7 @@ def on_processing_instruction(node, output) def on_xml_declaration(node, output) super # remove the space before the closing tag - output.gsub!(/ \?\>$/, '?>') + output.gsub!(/ \?>$/, "?>") end protected diff --git a/lib/moxml/adapter/nokogiri.rb b/lib/moxml/adapter/nokogiri.rb index 544e29e..e8c6182 100644 --- a/lib/moxml/adapter/nokogiri.rb +++ b/lib/moxml/adapter/nokogiri.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "base" require "nokogiri" @@ -11,20 +13,20 @@ def set_root(doc, element) def parse(xml, options = {}) native_doc = begin - if options[:fragment] - ::Nokogiri::XML::DocumentFragment.parse(xml) do |config| - config.strict.nonet - config.recover unless options[:strict] - end - else - ::Nokogiri::XML(xml, nil, options[:encoding]) do |config| - config.strict.nonet - config.recover unless options[:strict] - end + if options[:fragment] + ::Nokogiri::XML::DocumentFragment.parse(xml) do |config| + config.strict.nonet + config.recover unless options[:strict] + end + else + ::Nokogiri::XML(xml, nil, options[:encoding]) do |config| + config.strict.nonet + config.recover unless options[:strict] end - rescue ::Nokogiri::XML::SyntaxError => e - raise Moxml::ParseError.new(e.message, line: e.line, column: e.column) end + rescue ::Nokogiri::XML::SyntaxError => e + raise Moxml::ParseError.new(e.message, line: e.line, column: e.column) + end DocumentBuilder.new(Context.new(:nokogiri)).build(native_doc) end @@ -32,7 +34,7 @@ def parse(xml, options = {}) def create_document ::Nokogiri::XML::Document.new end - + def create_fragment # document fragments are weird and should be used with caution: # https://github.com/sparklemotion/nokogiri/issues/572 @@ -93,7 +95,7 @@ def set_declaration_attribute(declaration, attr_name, value) end declaration.native_content = - attrs.map { |k, v| %{#{k}="#{v}"} }.join(" ") + attrs.map { |k, v| %(#{k}="#{v}") }.join(" ") end def set_namespace(element, ns) @@ -279,13 +281,13 @@ def serialize(node, options = {}) # Don't force expand empty elements if they're really empty save_options |= ::Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS if options[:expand_empty] - save_options |= ::Nokogiri::XML::Node::SaveOptions::FORMAT if options[:indent].to_i > 0 + save_options |= ::Nokogiri::XML::Node::SaveOptions::FORMAT if options[:indent].to_i.positive? save_options |= ::Nokogiri::XML::Node::SaveOptions::NO_DECLARATION if options[:no_declaration] node.to_xml( indent: options[:indent], encoding: options[:encoding], - save_with: save_options, + save_with: save_options ) end @@ -295,7 +297,7 @@ 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(" ") + attrs.map { |k, v| %(#{k}="#{v}") }.join(" ") end def current_declaration_attributes(declaration) diff --git a/lib/moxml/adapter/oga.rb b/lib/moxml/adapter/oga.rb index 965c517..e6f4a72 100644 --- a/lib/moxml/adapter/oga.rb +++ b/lib/moxml/adapter/oga.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "base" require_relative "customized_oga/xml_generator" require_relative "customized_oga/xml_declaration" @@ -8,16 +10,16 @@ module Adapter class Oga < Base class << self def set_root(doc, element) - doc.children.clear # Clear any existing children + doc.children.clear # Clear any existing children doc.children << element end def parse(xml, options = {}) native_doc = begin - ::Oga.parse_xml(xml, strict: options[:strict]) - rescue LL::ParserError => e - raise Moxml::ParseError.new(e.message) - end + ::Oga.parse_xml(xml, strict: options[:strict]) + rescue LL::ParserError => e + raise Moxml::ParseError, e.message + end DocumentBuilder.new(Context.new(:oga)).build(native_doc) end @@ -44,7 +46,7 @@ def create_native_comment(content) def create_native_doctype(name, external_id, system_id) ::Oga::XML::Doctype.new( - name: name, public_id: external_id, system_id: system_id, type: 'PUBLIC' + name: name, public_id: external_id, system_id: system_id, type: "PUBLIC" ) end @@ -122,14 +124,12 @@ def set_node_name(node, name) def children(node) all_children = [] - - if node.is_a?(::Oga::XML::Document) - all_children += [node.xml_declaration, node.doctype].compact - end + + all_children += [node.xml_declaration, node.doctype].compact if node.is_a?(::Oga::XML::Document) return all_children unless node.respond_to?(:children) - all_children += node.children.reject do |child| + all_children + node.children.reject do |child| child.is_a?(::Oga::XML::Text) && child.text.strip.empty? && !(child.previous.nil? && child.next.nil?) @@ -150,9 +150,7 @@ def previous_sibling(node) def document(node) current = node - while parent(current) - current = current.parent - end + current = current.parent while parent(current) current end @@ -171,9 +169,7 @@ def attributes(element) def set_attribute(element, name, value) namespace_name = nil - if name.to_s.include?(':') - namespace_name, name = name.to_s.split(':', 2) - end + namespace_name, name = name.to_s.split(":", 2) if name.to_s.include?(":") attr = ::Oga::XML::Attribute.new( name: name.to_s, @@ -275,16 +271,17 @@ def namespace_uri(namespace) def namespace_definitions(node) return [] unless node.respond_to?(:namespaces) + node.namespaces.values end - def xpath(node, expression, namespaces = {}) + def xpath(node, expression, _namespaces = {}) node.xpath(expression).to_a rescue ::LL::ParserError => e raise Moxml::XPathError, e.message end - def at_xpath(node, expression, namespaces = {}) + def at_xpath(node, expression, _namespaces = {}) node.at_xpath(expression) rescue ::Oga::XPath::Error => e raise Moxml::XPathError, e.message diff --git a/lib/moxml/adapter/ox.rb b/lib/moxml/adapter/ox.rb index 3dc9243..8a3d0ce 100644 --- a/lib/moxml/adapter/ox.rb +++ b/lib/moxml/adapter/ox.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "base" require "ox" @@ -9,21 +11,21 @@ def set_root(doc, element) replace_children(doc, [element]) end - def parse(xml, options = {}) + def parse(xml, _options = {}) native_doc = begin - result = ::Ox.parse(xml) - - # result can be either Document or Element - if result.is_a?(::Ox::Document) - result - else - doc = ::Ox::Document.new - doc << result - doc - end - rescue ::Ox::ParseError => e - raise Moxml::ParseError.new(e.message) + result = ::Ox.parse(xml) + + # result can be either Document or Element + if result.is_a?(::Ox::Document) + result + else + doc = ::Ox::Document.new + doc << result + doc end + rescue ::Ox::ParseError => e + raise Moxml::ParseError, e.message + end DocumentBuilder.new(Context.new(:ox)).build(native_doc) end @@ -87,8 +89,10 @@ def set_namespace(element, ns) def namespace(element) return nil unless element.attributes + xmlns_attr = element.attributes.find { |k, _| k.start_with?("xmlns:") || k == "xmlns" } return nil unless xmlns_attr + prefix = xmlns_attr[0] == "xmlns" ? nil : xmlns_attr[0].sub("xmlns:", "") [prefix, xmlns_attr[1]] end @@ -110,7 +114,9 @@ def node_type(node) end def node_name(node) - node.value rescue node.name + node.value + rescue StandardError + node.name end def set_node_name(node, name) @@ -120,6 +126,7 @@ def set_node_name(node, name) def children(node) return [] unless node.respond_to?(:nodes) + node.nodes || [] end @@ -128,7 +135,7 @@ def parent(node) end def next_sibling(node) - return unless parent = parent(node) + return unless (parent = parent(node)) siblings = parent.nodes idx = siblings.index(node) @@ -136,18 +143,16 @@ def next_sibling(node) end def previous_sibling(node) - return unless parent = parent(node) + return unless (parent = parent(node)) siblings = parent.nodes idx = siblings.index(node) - idx && idx > 0 ? siblings[idx - 1] : nil + idx&.positive? ? siblings[idx - 1] : nil end def document(node) current = node - while parent(current) - current = parent(current) - end + current = parent(current) while parent(current) current end @@ -157,6 +162,7 @@ def root(document) def attributes(element) return {} unless element.respond_to?(:attributes) && element.attributes + element.attributes.reject { |k, _| k.start_with?("xmlns") } end @@ -167,11 +173,13 @@ def set_attribute(element, name, value) def get_attribute(element, name) return nil unless element.respond_to?(:attributes) && element.attributes + element.attributes[name.to_s] end def remove_attribute(element, name) return unless element.respond_to?(:attributes) && element.attributes + element.attributes.delete(name.to_s) end @@ -252,8 +260,10 @@ def set_processing_instruction_content(node, content) def namespace_definitions(node) return [] unless node.respond_to?(:attributes) && node.attributes + node.attributes.each_with_object([]) do |(name, value), namespaces| next unless name.start_with?("xmlns") + prefix = name == "xmlns" ? nil : name.sub("xmlns:", "") namespaces << [prefix, value] end @@ -280,7 +290,7 @@ def serialize(node, options = {}) indent: options[:indent] || -1, with_xml: true, with_instructions: true, - encoding: options[:encoding], + encoding: options[:encoding] } ::Ox.dump(node, ox_options) end @@ -289,20 +299,22 @@ def serialize(node, options = {}) def traverse(node, &block) return unless node + yield node return unless node.respond_to?(:nodes) + node.nodes&.each { |child| traverse(child, &block) } end - def matches_xpath?(node, expression, namespaces = {}) + def matches_xpath?(node, expression, _namespaces = {}) case expression when %r{//(\w+)} - node.is_a?(::Ox::Element) && node.value == $1 + node.is_a?(::Ox::Element) && node.value == ::Regexp.last_match(1) when %r{//(\w+)\[@(\w+)='([^']+)'\]} node.is_a?(::Ox::Element) && - node.value == $1 && + node.value == ::Regexp.last_match(1) && node.attributes && - node.attributes[$2] == $3 + node.attributes[::Regexp.last_match(2)] == ::Regexp.last_match(3) else false end diff --git a/lib/moxml/attribute.rb b/lib/moxml/attribute.rb index 893719f..67a276e 100644 --- a/lib/moxml/attribute.rb +++ b/lib/moxml/attribute.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Moxml class Attribute < Node def name @@ -36,11 +38,12 @@ def remove def ==(other) return false unless other.is_a?(Attribute) + name == other.name && value == other.value && namespace == other.namespace end def to_s - if namespace && namespace.prefix + if namespace&.prefix "#{namespace.prefix}:#{name}=\"#{value}\"" else "#{name}=\"#{value}\"" diff --git a/lib/moxml/builder.rb b/lib/moxml/builder.rb index b629f47..b8ceabf 100644 --- a/lib/moxml/builder.rb +++ b/lib/moxml/builder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Moxml class Builder def initialize(context) diff --git a/lib/moxml/cdata.rb b/lib/moxml/cdata.rb index 6c858fd..9624fad 100644 --- a/lib/moxml/cdata.rb +++ b/lib/moxml/cdata.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Moxml class Cdata < Node def content @@ -6,7 +8,6 @@ def content def content=(text) adapter.set_cdata_content(@native, normalize_xml_value(text)) - self end def cdata? diff --git a/lib/moxml/comment.rb b/lib/moxml/comment.rb index b0f36ca..caac069 100644 --- a/lib/moxml/comment.rb +++ b/lib/moxml/comment.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Moxml class Comment < Node def content @@ -8,7 +10,6 @@ def content=(text) text = normalize_xml_value(text) adapter.validate_comment_content(text) adapter.set_comment_content(@native, text) - self end def comment? diff --git a/lib/moxml/config.rb b/lib/moxml/config.rb index 23fedf1..b896c77 100644 --- a/lib/moxml/config.rb +++ b/lib/moxml/config.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + module Moxml class Config - VALID_ADAPTERS = [:nokogiri, :oga, :ox].freeze + VALID_ADAPTERS = %i[nokogiri oga ox].freeze DEFAULT_ADAPTER = VALID_ADAPTERS.first class << self diff --git a/lib/moxml/context.rb b/lib/moxml/context.rb index 2aa422a..85d891b 100644 --- a/lib/moxml/context.rb +++ b/lib/moxml/context.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Moxml class Context attr_reader :config @@ -20,7 +22,7 @@ def default_options { encoding: config.default_encoding, strict: config.strict_parsing, - indent: config.default_indent, + indent: config.default_indent } end end diff --git a/lib/moxml/declaration.rb b/lib/moxml/declaration.rb index 9c73f9d..84f9bbd 100644 --- a/lib/moxml/declaration.rb +++ b/lib/moxml/declaration.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + module Moxml class Declaration < Node ALLOWED_VERSIONS = ["1.0", "1.1"].freeze - ALLOWED_STANDALONE = ["yes", "no"].freeze + ALLOWED_STANDALONE = %w[yes no].freeze ALLOWED_ATTRIBUTES = %w[version encoding standalone].freeze def version diff --git a/lib/moxml/doctype.rb b/lib/moxml/doctype.rb index c214890..a055577 100644 --- a/lib/moxml/doctype.rb +++ b/lib/moxml/doctype.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Moxml class Doctype < Node def doctype? diff --git a/lib/moxml/document.rb b/lib/moxml/document.rb index 60d7815..00116f3 100644 --- a/lib/moxml/document.rb +++ b/lib/moxml/document.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "node" require_relative "element" require_relative "text" @@ -77,7 +79,7 @@ def xpath(expression, namespaces = nil) end def at_xpath(expression, namespaces = nil) - if native_node = adapter.at_xpath(@native, expression, namespaces) + if (native_node = adapter.at_xpath(@native, expression, namespaces)) Node.wrap(native_node, context) end end diff --git a/lib/moxml/document_builder.rb b/lib/moxml/document_builder.rb index a83e8b0..e2497f6 100644 --- a/lib/moxml/document_builder.rb +++ b/lib/moxml/document_builder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Moxml class DocumentBuilder attr_reader :context @@ -16,11 +18,11 @@ def build(native_doc) private def visit_node(node) - node_name = node.respond_to?(:name) ? node.name : node + node.respond_to?(:name) ? node.name : node method_name = "visit_#{node_type(node)}" - if respond_to?(method_name, true) - send(method_name, node) - end + return unless respond_to?(method_name, true) + + send(method_name, node) end def visit_document(doc) diff --git a/lib/moxml/element.rb b/lib/moxml/element.rb index cd28721..7ab0ce8 100644 --- a/lib/moxml/element.rb +++ b/lib/moxml/element.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "attribute" require_relative "namespace" @@ -39,10 +41,10 @@ def add_namespace(prefix, uri) validate_uri(uri) adapter.create_native_namespace(@native, prefix, uri) self - rescue ValidationError => err - raise Moxml::NamespaceError, err.message + rescue ValidationError => e + raise Moxml::NamespaceError, e.message end - alias :add_namespace_definition :add_namespace + alias add_namespace_definition add_namespace # it's NOT the same as namespaces.first def namespace @@ -67,7 +69,7 @@ def namespaces Namespace.new(ns, context) end end - alias :namespace_definitions :namespaces + alias namespace_definitions namespaces def text adapter.text_content(@native) @@ -75,7 +77,6 @@ def text def text=(content) adapter.set_text_content(@native, normalize_xml_value(content)) - self end def inner_html @@ -85,7 +86,6 @@ def inner_html def inner_html=(html) doc = context.parse("#{html}") adapter.replace_children(@native, doc.root.children.map(&:native)) - self end # Fluent interface methods diff --git a/lib/moxml/error.rb b/lib/moxml/error.rb index 2021161..15ad6be 100644 --- a/lib/moxml/error.rb +++ b/lib/moxml/error.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Moxml class Error < StandardError; end diff --git a/lib/moxml/namespace.rb b/lib/moxml/namespace.rb index 8f7a0a4..f6dfd60 100644 --- a/lib/moxml/namespace.rb +++ b/lib/moxml/namespace.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Moxml class Namespace < Node def prefix @@ -14,9 +16,9 @@ def ==(other) def to_s if prefix - %{xmlns:#{prefix}="#{uri}"} + %(xmlns:#{prefix}="#{uri}") else - %{xmlns="#{uri}"} + %(xmlns="#{uri}") end end diff --git a/lib/moxml/node.rb b/lib/moxml/node.rb index c91011a..f1ecf75 100644 --- a/lib/moxml/node.rb +++ b/lib/moxml/node.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "xml_utils" require_relative "node_set" @@ -81,16 +83,16 @@ def self.wrap(node, context) return nil if node.nil? klass = case adapter(context).node_type(node) - when :element then Element - when :text then Text - when :cdata then Cdata - when :comment then Comment - when :processing_instruction then ProcessingInstruction - when :document then Document - when :declaration then Declaration - when :doctype then Doctype - else self - end + when :element then Element + when :text then Text + when :cdata then Cdata + when :comment then Comment + when :processing_instruction then ProcessingInstruction + when :document then Document + when :declaration then Declaration + when :doctype then Doctype + else self + end klass.new(node, context) end diff --git a/lib/moxml/node_set.rb b/lib/moxml/node_set.rb index b3c90c0..3b362e0 100644 --- a/lib/moxml/node_set.rb +++ b/lib/moxml/node_set.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Moxml class NodeSet include Enumerable @@ -11,6 +13,7 @@ def initialize(nodes, context) def each return to_enum(:each) unless block_given? + nodes.each { |node| yield Node.wrap(node, context) } self end diff --git a/lib/moxml/processing_instruction.rb b/lib/moxml/processing_instruction.rb index d27123e..e64a27b 100644 --- a/lib/moxml/processing_instruction.rb +++ b/lib/moxml/processing_instruction.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Moxml class ProcessingInstruction < Node def target @@ -6,7 +8,6 @@ def target def target=(new_target) adapter.set_node_name(@native, new_target.to_s) - self end def content @@ -15,7 +16,6 @@ def content def content=(new_content) adapter.set_processing_instruction_content(@native, new_content.to_s) - self end def processing_instruction? diff --git a/lib/moxml/text.rb b/lib/moxml/text.rb index 5376c48..503ebcd 100644 --- a/lib/moxml/text.rb +++ b/lib/moxml/text.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Moxml class Text < Node def content @@ -6,7 +8,6 @@ def content def content=(text) adapter.set_text_content(@native, normalize_xml_value(text)) - self end def text? diff --git a/lib/moxml/xml_utils.rb b/lib/moxml/xml_utils.rb index 3f08d06..b9f9488 100644 --- a/lib/moxml/xml_utils.rb +++ b/lib/moxml/xml_utils.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "xml_utils/encoder" # Ruby 3.3+ requires the URI module to be explicitly required @@ -10,13 +12,14 @@ def encode_entities(text, mode = nil) end def validate_declaration_version(version) - unless ::Moxml::Declaration::ALLOWED_VERSIONS.include?(version) - raise ValidationError, "Invalid XML version: #{version}" - end + return if ::Moxml::Declaration::ALLOWED_VERSIONS.include?(version) + + raise ValidationError, "Invalid XML version: #{version}" end def validate_declaration_encoding(encoding) return if encoding.nil? + begin Encoding.find(encoding) rescue ArgumentError @@ -26,9 +29,9 @@ def validate_declaration_encoding(encoding) def validate_declaration_standalone(standalone) return if standalone.nil? - unless ::Moxml::Declaration::ALLOWED_STANDALONE.include?(standalone) - raise ValidationError, "Invalid standalone value: #{standalone}" - end + return if ::Moxml::Declaration::ALLOWED_STANDALONE.include?(standalone) + + raise ValidationError, "Invalid standalone value: #{standalone}" end def validate_comment_content(text) @@ -36,33 +39,33 @@ def validate_comment_content(text) raise ValidationError, "XML comment cannot start or end with a hyphen" end - if text.include?("--") - raise ValidationError, "XML comment cannot contain double hyphens (--)" - end + return unless text.include?("--") + + raise ValidationError, "XML comment cannot contain double hyphens (--)" end def validate_element_name(name) - unless name.is_a?(String) && name.match?(/^[a-zA-Z_][\w\-\.:]*$/) - raise ValidationError, "Invalid XML name: #{name}" - end + return if name.is_a?(String) && name.match?(/^[a-zA-Z_][\w\-.:]*$/) + + raise ValidationError, "Invalid XML name: #{name}" end def validate_pi_target(target) - unless target.is_a?(String) && target.match?(/^[a-zA-Z_][\w\-\.]*$/) - raise ValidationError, "Invalid XML target: #{target}" - end + return if target.is_a?(String) && target.match?(/^[a-zA-Z_][\w\-.]*$/) + + raise ValidationError, "Invalid XML target: #{target}" end def validate_uri(uri) - unless uri.empty? || uri.match?(/\A#{::URI::DEFAULT_PARSER.make_regexp}\z/) - raise ValidationError, "Invalid URI: #{uri}" - end + return if uri.empty? || uri.match?(/\A#{::URI::DEFAULT_PARSER.make_regexp}\z/) + + raise ValidationError, "Invalid URI: #{uri}" end def validate_prefix(prefix) - unless prefix.match?(/\A[a-zA-Z_][\w\-]*\z/) - raise ValidationError, "Invalid namespace prefix: #{prefix}" - end + return if prefix.match?(/\A[a-zA-Z_][\w-]*\z/) + + raise ValidationError, "Invalid namespace prefix: #{prefix}" end def normalize_xml_value(value) diff --git a/lib/moxml/xml_utils/encoder.rb b/lib/moxml/xml_utils/encoder.rb index 18830e5..d74bc98 100644 --- a/lib/moxml/xml_utils/encoder.rb +++ b/lib/moxml/xml_utils/encoder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Moxml module XmlUtils class Encoder @@ -8,19 +10,19 @@ class Encoder basic: { "<" => "<", ">" => ">", - "&" => "&", + "&" => "&" }, quotes: { - "'" => "'", - '"' => """, + "'" => "'", + '"' => """ }, full: { "<" => "<", ">" => ">", - "'" => "'", - '"' => """, - "&" => "&", - }, + "'" => "'", + '"' => """, + "&" => "&" + } }.freeze MODES = MAPPINGS.keys.freeze diff --git a/spec/moxml/adapter/nokogiri_spec.rb b/spec/moxml/adapter/nokogiri_spec.rb index e6bbac4..06a7a99 100644 --- a/spec/moxml/adapter/nokogiri_spec.rb +++ b/spec/moxml/adapter/nokogiri_spec.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + require "nokogiri" require "moxml/adapter/nokogiri" RSpec.describe Moxml::Adapter::Nokogiri do around do |example| - Moxml.with_config(:nokogiri, true, "UTF-8") do + Moxml.with_config(:nokogiri, true, "UTF-8") do example.run end end diff --git a/spec/moxml/adapter/oga_spec.rb b/spec/moxml/adapter/oga_spec.rb index 3775fad..9239489 100644 --- a/spec/moxml/adapter/oga_spec.rb +++ b/spec/moxml/adapter/oga_spec.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + require "oga" require "moxml/adapter/oga" RSpec.describe Moxml::Adapter::Oga do around do |example| - Moxml.with_config(:oga, true, "UTF-8") do + Moxml.with_config(:oga, true, "UTF-8") do example.run end end diff --git a/spec/moxml/adapter/ox_spec.rb b/spec/moxml/adapter/ox_spec.rb index fe9ce7d..a1c984a 100644 --- a/spec/moxml/adapter/ox_spec.rb +++ b/spec/moxml/adapter/ox_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "ox" require "moxml/adapter/ox" diff --git a/spec/moxml/all_with_adapters_spec.rb b/spec/moxml/all_with_adapters_spec.rb index 1e195f9..a48b783 100644 --- a/spec/moxml/all_with_adapters_spec.rb +++ b/spec/moxml/all_with_adapters_spec.rb @@ -1,34 +1,36 @@ +# frozen_string_literal: true + RSpec.describe "Test all shared examples" do all_shared_examples = [ - 'Moxml::Node', - 'Moxml::Namespace', - 'Moxml::Attribute', - 'Moxml::NodeSet', - 'Moxml::Element', - 'Moxml::Cdata', - 'Moxml::Comment', - 'Moxml::Text', - 'Moxml::ProcessingInstruction', - 'Moxml::Declaration', - 'Moxml::Doctype', - 'Moxml::Document', - 'Moxml::Context', - 'Moxml::Builder', - 'Moxml::DocumentBuilder', - 'Moxml Integration', - 'Moxml Edge Cases', + "Moxml::Node", + "Moxml::Namespace", + "Moxml::Attribute", + "Moxml::NodeSet", + "Moxml::Element", + "Moxml::Cdata", + "Moxml::Comment", + "Moxml::Text", + "Moxml::ProcessingInstruction", + "Moxml::Declaration", + "Moxml::Doctype", + "Moxml::Document", + "Moxml::Context", + "Moxml::Builder", + "Moxml::DocumentBuilder", + "Moxml Integration", + "Moxml Edge Cases", "Attribute Examples", "Basic Usage Examples", "Namespace Examples", "README Examples", "XPath Examples", "Memory Usage Examples", - "Thread Safety Examples", + "Thread Safety Examples" ] Moxml::Adapter::AVALIABLE_ADAPTERS.each do |adapter_name| - # [:nokogiri].each do |adapter_name| - # [:oga].each do |adapter_name| + # [:nokogiri].each do |adapter_name| + # [:oga].each do |adapter_name| context "with #{adapter_name}" do around do |example| Moxml.with_config(adapter_name) do diff --git a/spec/moxml/config_spec.rb b/spec/moxml/config_spec.rb index e940b98..0c97b1f 100644 --- a/spec/moxml/config_spec.rb +++ b/spec/moxml/config_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # spec/moxml/config_spec.rb RSpec.describe Moxml::Config do subject(:config) { described_class.new } diff --git a/spec/moxml/error_spec.rb b/spec/moxml/error_spec.rb index 6c0477e..cc81e08 100644 --- a/spec/moxml/error_spec.rb +++ b/spec/moxml/error_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # spec/moxml/errors_spec.rb RSpec.describe "Moxml errors" do describe Moxml::Error do @@ -46,24 +48,24 @@ let(:context) { Moxml.new } it "raises ParseError for invalid XML" do - expect { + expect do context.parse("") - }.to raise_error(Moxml::ParseError) + end.to raise_error(Moxml::ParseError) end it "raises XPathError for invalid XPath" do doc = context.parse("") - expect { + expect do doc.xpath("///") - }.to raise_error(Moxml::XPathError) + end.to raise_error(Moxml::XPathError) end it "raises NamespaceError for invalid namespace" do doc = context.parse("") - expect { + expect do doc.root.add_namespace("xml", "http//invalid.com") - }.to raise_error(Moxml::NamespaceError, "Invalid URI: http//invalid.com") + end.to raise_error(Moxml::NamespaceError, "Invalid URI: http//invalid.com") end end end diff --git a/spec/moxml/examples/adapter_spec.rb b/spec/moxml/examples/adapter_spec.rb index 8c74c0e..05cf3ad 100644 --- a/spec/moxml/examples/adapter_spec.rb +++ b/spec/moxml/examples/adapter_spec.rb @@ -1,8 +1,11 @@ +# frozen_string_literal: true + RSpec.describe "Adapter Examples" do let(:xml) { "text" } describe "Serialization consistency" do - it "produces equivalent XML across adapters", skip: "No easy way to exclude the declaration from Nokogiri documents" do + it "produces equivalent XML across adapters", + skip: "No easy way to exclude the declaration from Nokogiri documents" do docs = Moxml::Adapter::AVALIABLE_ADAPTERS.map do |adapter| Moxml.new(adapter).parse(xml, fragment: true) end diff --git a/spec/moxml_spec.rb b/spec/moxml_spec.rb index 5ab9dbb..47ef9d3 100644 --- a/spec/moxml_spec.rb +++ b/spec/moxml_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # spec/moxml_spec.rb RSpec.describe Moxml do it "has a version number" do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1275f96..31595a9 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + require "moxml" require "nokogiri" require "byebug" -Dir[File.expand_path("../support/**/*.rb", __FILE__)].each { |f| require f } +Dir[File.expand_path("support/**/*.rb", __dir__)].each { |f| require f } RSpec.configure do |config| config.expect_with :rspec do |expectations| diff --git a/spec/support/shared_examples/attribute.rb b/spec/support/shared_examples/attribute.rb index b14b77c..8478da2 100644 --- a/spec/support/shared_examples/attribute.rb +++ b/spec/support/shared_examples/attribute.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml::Attribute' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::Attribute" do describe Moxml::Attribute do let(:context) { Moxml.new } let(:doc) { context.create_document } diff --git a/spec/support/shared_examples/builder.rb b/spec/support/shared_examples/builder.rb index dae3487..30a73fb 100644 --- a/spec/support/shared_examples/builder.rb +++ b/spec/support/shared_examples/builder.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml::Builder' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::Builder" do let(:context) { Moxml.new } let(:builder) { Moxml::Builder.new(context) } diff --git a/spec/support/shared_examples/cdata.rb b/spec/support/shared_examples/cdata.rb index b0989aa..090245a 100644 --- a/spec/support/shared_examples/cdata.rb +++ b/spec/support/shared_examples/cdata.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml::Cdata' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::Cdata" do let(:context) { Moxml.new } let(:doc) { context.create_document } let(:cdata) { doc.create_cdata("") } diff --git a/spec/support/shared_examples/comment.rb b/spec/support/shared_examples/comment.rb index 96f660a..cc43065 100644 --- a/spec/support/shared_examples/comment.rb +++ b/spec/support/shared_examples/comment.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml::Comment' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::Comment" do let(:context) { Moxml.new } let(:doc) { context.create_document } let(:comment) { doc.create_comment("test comment") } diff --git a/spec/support/shared_examples/context.rb b/spec/support/shared_examples/context.rb index d38596f..79e4283 100644 --- a/spec/support/shared_examples/context.rb +++ b/spec/support/shared_examples/context.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml::Context' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::Context" do let(:context) { Moxml::Context.new } describe "#parse" do diff --git a/spec/support/shared_examples/declaration.rb b/spec/support/shared_examples/declaration.rb index 1721687..c48d937 100644 --- a/spec/support/shared_examples/declaration.rb +++ b/spec/support/shared_examples/declaration.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml::Declaration' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::Declaration" do let(:context) { Moxml.new } let(:doc) { context.create_document } let(:declaration) { doc.create_declaration("1.0", "UTF-8", "yes") } diff --git a/spec/support/shared_examples/doctype.rb b/spec/support/shared_examples/doctype.rb index aa065b1..48e58ec 100644 --- a/spec/support/shared_examples/doctype.rb +++ b/spec/support/shared_examples/doctype.rb @@ -1,9 +1,11 @@ -RSpec.shared_examples 'Moxml::Doctype' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::Doctype" do let(:context) { Moxml.new } let(:doc) { context.create_document } let(:doctype) do doc.create_doctype( - 'html', + "html", "-//W3C//DTD HTML 4.01 Transitional//EN", "http://www.w3.org/TR/html4/loose.dtd" ) diff --git a/spec/support/shared_examples/document.rb b/spec/support/shared_examples/document.rb index 09f5f72..454abab 100644 --- a/spec/support/shared_examples/document.rb +++ b/spec/support/shared_examples/document.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml::Document' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::Document" do let(:context) { Moxml.new } let(:xml) do <<~XML diff --git a/spec/support/shared_examples/document_builder.rb b/spec/support/shared_examples/document_builder.rb index b0d9acf..8cdc5fe 100644 --- a/spec/support/shared_examples/document_builder.rb +++ b/spec/support/shared_examples/document_builder.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml::DocumentBuilder' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::DocumentBuilder" do let(:context) { Moxml.new } let(:builder) { Moxml::DocumentBuilder.new(context) } diff --git a/spec/support/shared_examples/edge_cases.rb b/spec/support/shared_examples/edge_cases.rb index 19071c6..ded70cb 100644 --- a/spec/support/shared_examples/edge_cases.rb +++ b/spec/support/shared_examples/edge_cases.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml Edge Cases' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml Edge Cases" do let(:context) { Moxml.new } describe "special characters handling" do @@ -46,23 +48,23 @@ it "rejects comments with double hyphens" do doc = context.create_document - expect { + expect do doc.create_comment("-- test -- comment --") - }.to raise_error(Moxml::ValidationError, "XML comment cannot start or end with a hyphen") + end.to raise_error(Moxml::ValidationError, "XML comment cannot start or end with a hyphen") end it "rejects comments starting with hyphen" do doc = context.create_document - expect { + expect do doc.create_comment("-starting with hyphen") - }.to raise_error(Moxml::ValidationError, "XML comment cannot start or end with a hyphen") + end.to raise_error(Moxml::ValidationError, "XML comment cannot start or end with a hyphen") end it "rejects comments ending with hyphen" do doc = context.create_document - expect { + expect do doc.create_comment("ending with hyphen-") - }.to raise_error(Moxml::ValidationError, "XML comment cannot start or end with a hyphen") + end.to raise_error(Moxml::ValidationError, "XML comment cannot start or end with a hyphen") end it "accepts valid comments" do @@ -125,7 +127,7 @@ "space" => " ", "tabs_newlines" => "\t\n", "unicode" => "⚡", - "entities" => "<&>'\"", + "entities" => "<&>'\"" } special_values.each do |name, value| diff --git a/spec/support/shared_examples/element.rb b/spec/support/shared_examples/element.rb index f3b8457..8a6b49c 100644 --- a/spec/support/shared_examples/element.rb +++ b/spec/support/shared_examples/element.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml::Element' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::Element" do describe Moxml::Element do let(:context) { Moxml.new } let(:doc) { context.create_document } diff --git a/spec/support/shared_examples/examples/attribute.rb b/spec/support/shared_examples/examples/attribute.rb index 3206fa5..eb2b687 100644 --- a/spec/support/shared_examples/examples/attribute.rb +++ b/spec/support/shared_examples/examples/attribute.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + RSpec.shared_examples "Attribute Examples" do let(:context) { Moxml.new } let(:doc) { context.create_document } diff --git a/spec/support/shared_examples/examples/basic_usage.rb b/spec/support/shared_examples/examples/basic_usage.rb index 90230f5..e548032 100644 --- a/spec/support/shared_examples/examples/basic_usage.rb +++ b/spec/support/shared_examples/examples/basic_usage.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + RSpec.shared_examples "Basic Usage Examples" do let(:context) { Moxml.new } diff --git a/spec/support/shared_examples/examples/memory.rb b/spec/support/shared_examples/examples/memory.rb index a1199cd..b1a3d8f 100644 --- a/spec/support/shared_examples/examples/memory.rb +++ b/spec/support/shared_examples/examples/memory.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "get_process_mem" require "tempfile" @@ -19,10 +21,7 @@ # Process and remove nodes memory_before = GetProcessMem.new.bytes - doc.xpath("//large-node").each do |node| - node.remove - node = nil - end + doc.xpath("//large-node").each(&:remove) GC.start memory_after = GetProcessMem.new.bytes diff --git a/spec/support/shared_examples/examples/namespace.rb b/spec/support/shared_examples/examples/namespace.rb index 2d01a4f..e93e668 100644 --- a/spec/support/shared_examples/examples/namespace.rb +++ b/spec/support/shared_examples/examples/namespace.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + RSpec.shared_examples "Namespace Examples" do let(:context) { Moxml.new } diff --git a/spec/support/shared_examples/examples/readme_examples.rb b/spec/support/shared_examples/examples/readme_examples.rb index 75a64bf..cb14d53 100644 --- a/spec/support/shared_examples/examples/readme_examples.rb +++ b/spec/support/shared_examples/examples/readme_examples.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + RSpec.shared_examples "README Examples" do describe "Quick Start example" do it "builds document as shown in README" do @@ -34,7 +36,7 @@ doc.add_child(root) # Add books - ["Ruby", "XML"].each do |title| + %w[Ruby XML].each do |title| book = doc.create_element("book") # Add metadata @@ -64,14 +66,14 @@ it "handles errors as shown in README" do context = Moxml.new - expect { + expect do context.parse("") - }.to raise_error(Moxml::ParseError) + end.to raise_error(Moxml::ParseError) doc = context.parse("") - expect { + expect do doc.xpath("///") - }.to raise_error(Moxml::XPathError) + end.to raise_error(Moxml::XPathError) end end diff --git a/spec/support/shared_examples/examples/thread_safety.rb b/spec/support/shared_examples/examples/thread_safety.rb index 320c19a..87d96d1 100644 --- a/spec/support/shared_examples/examples/thread_safety.rb +++ b/spec/support/shared_examples/examples/thread_safety.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + RSpec.shared_examples "Thread Safety Examples" do describe "Thread-safe processing" do let(:processor_class) do diff --git a/spec/support/shared_examples/examples/xpath.rb b/spec/support/shared_examples/examples/xpath.rb index 58687e3..71394c7 100644 --- a/spec/support/shared_examples/examples/xpath.rb +++ b/spec/support/shared_examples/examples/xpath.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + RSpec.shared_examples "XPath Examples" do let(:context) { Moxml.new } @@ -18,13 +20,13 @@ it "finds nodes by XPath" do books = doc.xpath("//book") expect(books.size).to eq(2) - expect(books.map { |b| b["id"] }).to eq(["1", "2"]) + expect(books.map { |b| b["id"] }).to eq(%w[1 2]) end it "finds nodes with namespaces" do titles = doc.xpath("//dc:title", "dc" => "http://purl.org/dc/elements/1.1/") - expect(titles.map(&:text)).to eq(["First", "Second"]) + expect(titles.map(&:text)).to eq(%w[First Second]) end it "finds nodes by attributes" do diff --git a/spec/support/shared_examples/integration.rb b/spec/support/shared_examples/integration.rb index a00b53c..1481a86 100644 --- a/spec/support/shared_examples/integration.rb +++ b/spec/support/shared_examples/integration.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml Integration' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml Integration" do let(:context) { Moxml.new } describe "complete document workflow" do @@ -118,7 +120,7 @@ b_node.add_child(doc.create_comment(" comment ")) b_node.add_child(doc.create_cdata("")) - expect(doc.root.children.map(&:name)).to eq(["a", "b", "c"]) + expect(doc.root.children.map(&:name)).to eq(%w[a b c]) expect(doc.to_xml).to include( '', "2]]>" diff --git a/spec/support/shared_examples/namespace.rb b/spec/support/shared_examples/namespace.rb index a383b4e..f4234a7 100644 --- a/spec/support/shared_examples/namespace.rb +++ b/spec/support/shared_examples/namespace.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml::Namespace' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::Namespace" do describe Moxml::Namespace do let(:context) { Moxml.new } let(:doc) { context.create_document } @@ -23,9 +25,9 @@ end it "validates URI" do - expect { + expect do element.add_namespace("xs", "invalid uri") - }.to raise_error(Moxml::NamespaceError, "Invalid URI: invalid uri") + end.to raise_error(Moxml::NamespaceError, "Invalid URI: invalid uri") end end diff --git a/spec/support/shared_examples/node.rb b/spec/support/shared_examples/node.rb index d14efea..6082cb6 100644 --- a/spec/support/shared_examples/node.rb +++ b/spec/support/shared_examples/node.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml::Node' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::Node" do describe Moxml::Node do let(:context) { Moxml.new } let(:doc) { context.parse("text") } @@ -77,14 +79,14 @@ it "uses native serialization" do expect(context.config.adapter).to receive(:serialize) - .with(doc.native, hash_including(indent: 2)) + .with(doc.native, hash_including(indent: 2)) doc.to_xml(indent: 2) end it "passes through serialization options" do expect(context.config.adapter).to receive(:serialize) - .with(doc.native, hash_including(encoding: "UTF-8", indent: 4)) + .with(doc.native, hash_including(encoding: "UTF-8", indent: 4)) doc.to_xml(encoding: "UTF-8", indent: 4) end @@ -96,7 +98,7 @@ it "finds nodes by xpath" do nodes = doc.xpath("//b") expect(nodes.size).to eq(2) - expect(nodes.map(&:text)).to eq(["1", "2"]) + expect(nodes.map(&:text)).to eq(%w[1 2]) end it "finds first node by xpath" do diff --git a/spec/support/shared_examples/node_set.rb b/spec/support/shared_examples/node_set.rb index 6379b5b..8711b33 100644 --- a/spec/support/shared_examples/node_set.rb +++ b/spec/support/shared_examples/node_set.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml::NodeSet' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::NodeSet" do describe Moxml::NodeSet do let(:context) { Moxml.new } let(:xml) do @@ -25,18 +27,18 @@ it "iterates over nodes" do texts = [] nodes.each { |node| texts << node.text } - expect(texts).to eq(["First", "Second", "Third"]) + expect(texts).to eq(%w[First Second Third]) end it "maps nodes" do texts = nodes.map(&:text) - expect(texts).to eq(["First", "Second", "Third"]) + expect(texts).to eq(%w[First Second Third]) end it "selects nodes" do selected = nodes.select { |node| node.text.include?("i") } expect(selected.size).to eq(2) - expect(selected.map(&:text)).to eq(["First", "Third"]) + expect(selected.map(&:text)).to eq(%w[First Third]) end end @@ -51,7 +53,7 @@ subset = nodes[0..1] expect(subset).to be_a(described_class) expect(subset.size).to eq(2) - expect(subset.map(&:text)).to eq(["First", "Second"]) + expect(subset.map(&:text)).to eq(%w[First Second]) end it "provides first and last" do @@ -81,7 +83,7 @@ expect(combined).to be_a(described_class) expect(combined.size).to eq(4) - expect(combined.map(&:text)).to eq(["First", "Second", "Third", "Fourth"]) + expect(combined.map(&:text)).to eq(%w[First Second Third Fourth]) end end end diff --git a/spec/support/shared_examples/processing_instruction.rb b/spec/support/shared_examples/processing_instruction.rb index 7ebb1fa..7b14be6 100644 --- a/spec/support/shared_examples/processing_instruction.rb +++ b/spec/support/shared_examples/processing_instruction.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml::ProcessingInstruction' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::ProcessingInstruction" do let(:context) { Moxml.new } let(:doc) { context.create_document } let(:pi) { doc.create_processing_instruction("xml-stylesheet", 'href="style.xsl" type="text/xsl"') } diff --git a/spec/support/shared_examples/text.rb b/spec/support/shared_examples/text.rb index 721f04f..cf268a9 100644 --- a/spec/support/shared_examples/text.rb +++ b/spec/support/shared_examples/text.rb @@ -1,4 +1,6 @@ -RSpec.shared_examples 'Moxml::Text' do +# frozen_string_literal: true + +RSpec.shared_examples "Moxml::Text" do let(:context) { Moxml.new } let(:doc) { context.create_document } let(:text) { doc.create_text("content") } diff --git a/spec/support/shared_examples/xml_adapter.rb b/spec/support/shared_examples/xml_adapter.rb index 68867cb..f9ff524 100644 --- a/spec/support/shared_examples/xml_adapter.rb +++ b/spec/support/shared_examples/xml_adapter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + RSpec.shared_examples "xml adapter" do let(:xml) do <<~XML @@ -24,13 +26,13 @@ it "handles malformed XML according to strict setting" do malformed = "" - expect { + expect do described_class.parse(malformed, strict: true) - }.to raise_error(Moxml::ParseError) + end.to raise_error(Moxml::ParseError) - expect { + expect do described_class.parse(malformed, strict: false) - }.not_to raise_error + end.not_to raise_error end end diff --git a/spec/support/xml_matchers.rb b/spec/support/xml_matchers.rb index 77010aa..86f3454 100644 --- a/spec/support/xml_matchers.rb +++ b/spec/support/xml_matchers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # spec/support/xml_matchers.rb # RSpec::Matchers.define :be_equivalent_to do |expected| # match do |actual| @@ -19,7 +21,7 @@ text.nil? ? !nodes.empty? : nodes.any? { |node| node.text == text } end - failure_message do |xml_node| + failure_message do |_xml_node| "expected to find xpath #{xpath} #{text ? "with text '#{text}'" : ""}" end end