From c077988dd60a179babdeb83e3eb2a7b895dc1edc Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 3 Apr 2014 22:44:00 +0200 Subject: [PATCH] Tree building of doctypes. --- lib/oga.rb | 1 + lib/oga/xml/doctype.rb | 29 ++++++++++++++++++ lib/oga/xml/document.rb | 6 +++- lib/oga/xml/tree_builder.rb | 17 +++++++++++ spec/oga/xml/doctype_spec.rb | 49 +++++++++++++++++++++++++++++++ spec/oga/xml/document_spec.rb | 16 ++++++++++ spec/oga/xml/tree_builder_spec.rb | 39 ++++++++++++++++++++++++ 7 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 lib/oga/xml/doctype.rb create mode 100644 spec/oga/xml/doctype_spec.rb diff --git a/lib/oga.rb b/lib/oga.rb index 03d0d34..d9876cb 100644 --- a/lib/oga.rb +++ b/lib/oga.rb @@ -11,6 +11,7 @@ require_relative 'oga/xml/text' require_relative 'oga/xml/comment' require_relative 'oga/xml/cdata' require_relative 'oga/xml/xml_declaration' +require_relative 'oga/xml/doctype' require_relative 'oga/xml/tree_builder' require_relative 'oga/html/parser' diff --git a/lib/oga/xml/doctype.rb b/lib/oga/xml/doctype.rb new file mode 100644 index 0000000..4fe8359 --- /dev/null +++ b/lib/oga/xml/doctype.rb @@ -0,0 +1,29 @@ +module Oga + module XML + ## + # Class description + # + class Doctype + attr_accessor :name, :type, :public_id, :system_id + + ## + # @param [Hash] options + # + def initialize(options = {}) + options.each do |key, value| + instance_variable_set("@#{key}", value) if respond_to?(key) + end + end + + def to_xml + segments = "' + end + end # Doctype + end # XML +end # Oga diff --git a/lib/oga/xml/document.rb b/lib/oga/xml/document.rb index db1f373..159c542 100644 --- a/lib/oga/xml/document.rb +++ b/lib/oga/xml/document.rb @@ -4,11 +4,15 @@ module Oga # Class description # class Document < Node - attr_accessor :xml_declaration + attr_accessor :doctype, :xml_declaration def to_xml xml = children.map(&:to_xml).join('') + if doctype + xml = doctype.to_xml + xml + end + if xml_declaration xml = xml_declaration.to_xml + xml end diff --git a/lib/oga/xml/tree_builder.rb b/lib/oga/xml/tree_builder.rb index 0805e39..6bf29ba 100644 --- a/lib/oga/xml/tree_builder.rb +++ b/lib/oga/xml/tree_builder.rb @@ -22,6 +22,10 @@ module Oga process_all(node).each do |child| if child.is_a?(XmlDeclaration) document.xml_declaration = child + + elsif child.is_a?(Doctype) + document.doctype = child + else document.children << child end @@ -44,6 +48,19 @@ module Oga return XmlDeclaration.new(attributes) end + ## + # @param [Oga::AST::Node] node + # @return [Oga::XML::Doctype] + # + def on_doctype(node) + return Doctype.new( + :name => node.children[0], + :type => node.children[1], + :public_id => node.children[2], + :system_id => node.children[3] + ) + end + ## # @param [Oga::AST::Node] node # @return [Oga::XML::Comment] diff --git a/spec/oga/xml/doctype_spec.rb b/spec/oga/xml/doctype_spec.rb new file mode 100644 index 0000000..adaf5a8 --- /dev/null +++ b/spec/oga/xml/doctype_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe Oga::XML::Doctype do + context 'setting attributes' do + example 'set the name via the constructor' do + described_class.new(:name => 'html').name.should == 'html' + end + + example 'set the name via a setter' do + instance = described_class.new + instance.name = 'html' + + instance.name.should == 'html' + end + end + + context '#to_xml' do + example 'generate a bare minimum representation' do + described_class.new(:name => 'html').to_xml.should == '' + end + + example 'include the type if present' do + instance = described_class.new(:name => 'html', :type => 'PUBLIC') + + instance.to_xml.should == '' + end + + example 'include the public ID if present' do + instance = described_class.new( + :name => 'html', + :type => 'PUBLIC', + :public_id => 'foo' + ) + + instance.to_xml.should == '' + end + + example 'include the system ID if present' do + instance = described_class.new( + :name => 'html', + :type => 'PUBLIC', + :public_id => 'foo', + :system_id => 'bar' + ) + + instance.to_xml.should == '' + end + end +end diff --git a/spec/oga/xml/document_spec.rb b/spec/oga/xml/document_spec.rb index 61220e4..274cea9 100644 --- a/spec/oga/xml/document_spec.rb +++ b/spec/oga/xml/document_spec.rb @@ -46,4 +46,20 @@ describe Oga::XML::Document do .should == '' end end + + context '#to_xml with doctypes' do + before do + doctype = Oga::XML::Doctype.new(:name => 'html', :type => 'PUBLIC') + children = [Oga::XML::Comment.new(:text => 'foo')] + + @document = described_class.new( + :doctype => doctype, + :children => children + ) + end + + example 'include the doctype' do + @document.to_xml.should == '' + end + end end diff --git a/spec/oga/xml/tree_builder_spec.rb b/spec/oga/xml/tree_builder_spec.rb index 0e6323c..f7b76d8 100644 --- a/spec/oga/xml/tree_builder_spec.rb +++ b/spec/oga/xml/tree_builder_spec.rb @@ -32,6 +32,18 @@ describe Oga::XML::TreeBuilder do end end + context '#on_document with doctypes' do + before do + doctype = s(:doctype, 'html', 'PUBLIC', 'foo', 'bar') + node = s(:document, doctype) + @tag = @builder.process(node) + end + + example 'set the doctype of the document' do + @tag.doctype.is_a?(Oga::XML::Doctype).should == true + end + end + context '#on_xml_decl' do before do node = s(:xml_decl, s(:attributes, s(:attribute, 'encoding', 'UTF-8'))) @@ -47,6 +59,33 @@ describe Oga::XML::TreeBuilder do end end + context '#on_doctype' do + before do + node = s(:doctype, 'html', 'PUBLIC', 'foo', 'bar') + @tag = @builder.process(node) + end + + example 'return a Doctype node' do + @tag.is_a?(Oga::XML::Doctype).should == true + end + + example 'include the doctype name' do + @tag.name.should == 'html' + end + + example 'include the doctype type' do + @tag.type.should == 'PUBLIC' + end + + example 'include the public ID' do + @tag.public_id.should == 'foo' + end + + example 'include the system ID' do + @tag.system_id.should == 'bar' + end + end + context '#on_comment' do before do node = s(:comment, 'foo')