diff --git a/Gemfile.lock b/Gemfile.lock index f49d987..760dbc2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -21,6 +21,7 @@ PATH deface (~> 1.9) html_press (~> 0.8.2) nokogiri (~> 1.0) + nokogiri-html5-inference (~> 0.2) phlex (~> 1.6) phlex-rails (>= 0.9, < 2.0) syntax_tree (~> 6.0) @@ -180,6 +181,8 @@ GEM racc (~> 1.4) nokogiri (1.16.4-x86_64-linux) racc (~> 1.4) + nokogiri-html5-inference (0.2.0) + nokogiri (~> 1.14) parallel (1.22.1) parser (3.1.2.1) ast (~> 2.4.1) diff --git a/gem/Gemfile b/gem/Gemfile index 0fe4dc7..8117724 100644 --- a/gem/Gemfile +++ b/gem/Gemfile @@ -8,3 +8,6 @@ gem "maxitest", "~> 4.4" gem "minitest", "~> 5.0" gem "rake", "~> 13.0" gem "rubocop", require: false, github: "joeldrapper/rubocop", branch: "rubocop-user-agent" +# gem "nokogiri-html5-inference", github: "flavorjones/nokogiri-html5-inference", branch: "2-use-template-context-node" + +gem "nokogiri-html5-inference", github: "flavorjones/nokogiri-html5-inference", branch: "flavorjones-always-return-nodeset" diff --git a/gem/Gemfile.lock b/gem/Gemfile.lock index 77ed5ce..cbb27bb 100644 --- a/gem/Gemfile.lock +++ b/gem/Gemfile.lock @@ -1,3 +1,11 @@ +GIT + remote: https://github.com/flavorjones/nokogiri-html5-inference.git + revision: 7426a3601d30bf6cb9794d6b5c2e767151a0fa6f + branch: flavorjones-always-return-nodeset + specs: + nokogiri-html5-inference (0.2.0) + nokogiri (~> 1.14) + GIT remote: https://github.com/joeldrapper/rubocop.git revision: 8d3c1a7dd04a0dee701e26ee506b28af0ffe3b98 @@ -21,6 +29,7 @@ PATH deface (~> 1.9) html_press (~> 0.8.2) nokogiri (~> 1.0) + nokogiri-html5-inference (~> 0.2) phlex (~> 1.6) phlex-rails (>= 0.9, < 2.0) syntax_tree (~> 6.0) @@ -178,6 +187,7 @@ PLATFORMS DEPENDENCIES maxitest (~> 4.4) minitest (~> 5.0) + nokogiri-html5-inference! phlexing! rake (~> 13.0) rubocop! diff --git a/gem/lib/phlexing/name_suggestor.rb b/gem/lib/phlexing/name_suggestor.rb index 3003711..a2f4dd8 100644 --- a/gem/lib/phlexing/name_suggestor.rb +++ b/gem/lib/phlexing/name_suggestor.rb @@ -33,7 +33,7 @@ def self.wrap(name) def self.extract(document, method) return [] unless document - document.children.map { |element| send(method, element) }.compact + document.map { |element| send(method, element) }.compact end def self.extract_id_from_element(element) diff --git a/gem/lib/phlexing/parser.rb b/gem/lib/phlexing/parser.rb index 346223d..8cfca48 100644 --- a/gem/lib/phlexing/parser.rb +++ b/gem/lib/phlexing/parser.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "nokogiri" +require "nokogiri/html5/inference" module Phlexing class Parser @@ -8,25 +9,7 @@ def self.call(source) source = ERBTransformer.call(source) source = Minifier.call(source) - # Credit: - # https://github.com/spree/deface/blob/6bf18df76715ee3eb3d0cd1b6eda822817ace91c/lib/deface/parser.rb#L105-L111 - # - - html_tag = /)[\s\S])*>)|>)/i - head_tag = /)[\s\S])*>)|>)/i - body_tag = /)[\s\S])*>)|>)/i - - if source =~ html_tag - Nokogiri::HTML::Document.parse(source) - elsif source =~ head_tag && source =~ body_tag - Nokogiri::HTML::Document.parse(source).css("html").first - elsif source =~ head_tag - Nokogiri::HTML::Document.parse(source).css("head").first - elsif source =~ body_tag - Nokogiri::HTML::Document.parse(source).css("body").first - else - Nokogiri::HTML::DocumentFragment.parse(source) - end + Nokogiri::HTML5::Inference.parse(source) end end end diff --git a/gem/lib/phlexing/template_generator.rb b/gem/lib/phlexing/template_generator.rb index 5acc61d..974e1b5 100644 --- a/gem/lib/phlexing/template_generator.rb +++ b/gem/lib/phlexing/template_generator.rb @@ -231,6 +231,8 @@ def handle_node(node, level = 0) handle_document_node(node, level) in Nokogiri::XML::Comment handle_html_comment_node(node) + in Nokogiri::XML::NodeSet + node.each { |n| handle_node(n, level + 1) } end end end diff --git a/gem/phlexing.gemspec b/gem/phlexing.gemspec index 60cab99..3f32c69 100644 --- a/gem/phlexing.gemspec +++ b/gem/phlexing.gemspec @@ -32,6 +32,7 @@ Gem::Specification.new do |spec| spec.add_dependency "deface", "~> 1.9" spec.add_dependency "html_press", "~> 0.8.2" spec.add_dependency "nokogiri", "~> 1.0" + spec.add_dependency "nokogiri-html5-inference", "~> 0.2" spec.add_dependency "phlex", "~> 1.6" spec.add_dependency "phlex-rails", ">= 0.9", "< 2.0" spec.add_dependency "syntax_tree", "~> 6.0" diff --git a/gem/test/phlexing/converter/tags_test.rb b/gem/test/phlexing/converter/tags_test.rb index 6d4f7c3..ae5be4b 100644 --- a/gem/test/phlexing/converter/tags_test.rb +++ b/gem/test/phlexing/converter/tags_test.rb @@ -8,10 +8,15 @@ class Phlexing::Converter::TagsTest < Minitest::Spec assert_phlex_template "span", %() assert_phlex_template "p", %(

) assert_phlex_template "template_tag", %() - assert_phlex_template "html", %() - assert_phlex_template "head", %() + assert_phlex_template "head\n\nbody", %() assert_phlex_template "header", %(
) assert_phlex_template "body", %() + assert_phlex_template <<~PHLEX.strip, %() + html do + head + body + end + PHLEX end it "basic self closing tag" do @@ -133,11 +138,9 @@ class Phlexing::Converter::TagsTest < Minitest::Spec HTML expected = <<~PHLEX.strip - html do - head + head - body - end + body PHLEX assert_phlex_template expected, html @@ -150,11 +153,9 @@ class Phlexing::Converter::TagsTest < Minitest::Spec HTML expected = <<~PHLEX.strip - html do - head + head - body - end + body PHLEX assert_phlex_template expected, html @@ -167,6 +168,8 @@ class Phlexing::Converter::TagsTest < Minitest::Spec expected = <<~PHLEX.strip head + + body PHLEX assert_phlex_template expected, html @@ -179,6 +182,8 @@ class Phlexing::Converter::TagsTest < Minitest::Spec expected = <<~PHLEX.strip head(id: "123") + + body PHLEX assert_phlex_template expected, html diff --git a/gem/test/phlexing/converter/uppercase_tags_test.rb b/gem/test/phlexing/converter/uppercase_tags_test.rb index b6f706e..8472bb3 100644 --- a/gem/test/phlexing/converter/uppercase_tags_test.rb +++ b/gem/test/phlexing/converter/uppercase_tags_test.rb @@ -8,9 +8,14 @@ class Phlexing::Converter::UppercaseTagsTest < Minitest::Spec assert_phlex_template "span", %() assert_phlex_template "p", %(

) assert_phlex_template "template_tag", %() - assert_phlex_template "html", %() - assert_phlex_template "head", %() + assert_phlex_template "head\n\nbody", %() assert_phlex_template "body", %() + assert_phlex_template <<~PHLEX.strip, %() + html do + head + body + end + PHLEX end it "standlone uppercase body tag" do @@ -32,6 +37,8 @@ class Phlexing::Converter::UppercaseTagsTest < Minitest::Spec expected = <<~PHLEX.strip head + + body PHLEX assert_phlex_template expected, html @@ -43,7 +50,10 @@ class Phlexing::Converter::UppercaseTagsTest < Minitest::Spec HTML expected = <<~PHLEX.strip - html + html do + head + body + end PHLEX assert_phlex_template expected, html @@ -56,11 +66,8 @@ class Phlexing::Converter::UppercaseTagsTest < Minitest::Spec HTML expected = <<~PHLEX.strip - html do - head - - body - end + head + body PHLEX assert_phlex_template expected, html @@ -76,7 +83,6 @@ class Phlexing::Converter::UppercaseTagsTest < Minitest::Spec expected = <<~PHLEX.strip html do - whitespace head whitespace body diff --git a/gem/test/phlexing/parser_test.rb b/gem/test/phlexing/parser_test.rb index 59ff496..5025af6 100644 --- a/gem/test/phlexing/parser_test.rb +++ b/gem/test/phlexing/parser_test.rb @@ -2,10 +2,6 @@ require_relative "../test_helper" -def assert_dom_equal(expected, actual) - assert_equal expected, actual.gsub(%(), "").squish -end - module Phlexing class ParserTest < Minitest::Spec before(:each) do @@ -13,9 +9,13 @@ class ParserTest < Minitest::Spec end def extract_children(node) - @nodes << node.name + @nodes << node.name if node.respond_to?(:name) - if node&.children + if node.is_a?(Nokogiri::XML::NodeSet) + node.each do |n| + extract_children(n) + end + elsif node&.children node.children.each do |node| extract_children(node) end @@ -27,118 +27,106 @@ def extract_children(node) it "should handle nil" do parser = Parser.call(nil) - assert_equal "#document-fragment", extract_children(parser).join(",") - assert_dom_equal "", parser.to_xml - assert_equal "#document-fragment", parser.name - assert_equal Nokogiri::HTML4::DocumentFragment, parser.class + assert_equal "", extract_children(parser).join(",") + assert_equal "", parser.to_html + assert_equal Nokogiri::XML::NodeSet, parser.class end it "should handle empty string" do parser = Parser.call("") - assert_equal "#document-fragment", extract_children(parser).join(",") - assert_dom_equal "", parser.to_xml - assert_equal "#document-fragment", parser.name - assert_equal Nokogiri::HTML4::DocumentFragment, parser.class + assert_equal "", extract_children(parser).join(",") + assert_equal "", parser.to_html + assert_equal Nokogiri::XML::NodeSet, parser.class end it "should handle simple div" do parser = Parser.call("
") - assert_equal "#document-fragment,div", extract_children(parser).join(",") - assert_dom_equal %(
), parser.to_html - assert_equal "#document-fragment", parser.name - assert_equal Nokogiri::HTML4::DocumentFragment, parser.class + assert_equal "div", extract_children(parser).join(",") + assert_equal %(
), parser.to_html + assert_equal Nokogiri::XML::NodeSet, parser.class end it "should handle ERB" do parser = Parser.call("
<%= some_method %>
") - assert_equal "#document-fragment,div,erb,text", extract_children(parser).join(",") - assert_dom_equal %(
some_method
), parser.to_xml - assert_equal "#document-fragment", parser.name - assert_equal Nokogiri::HTML4::DocumentFragment, parser.class + assert_equal "div,erb,text", extract_children(parser).join(",") + assert_equal %(
some_method
), parser.to_html + assert_equal Nokogiri::XML::NodeSet, parser.class end it "should handle html" do parser = Parser.call("") - assert_equal "document,html,html", extract_children(parser).join(",") - assert_dom_equal %(), parser.to_xml + assert_equal "document,html,head,body", extract_children(parser).join(",") + assert_equal %(), parser.to_html assert_equal "document", parser.name - assert_equal Nokogiri::HTML4::Document, parser.class + assert_equal Nokogiri::HTML5::Document, parser.class end it "should handle html, head and body" do parser = Parser.call("Title

Hello

") - assert_equal "document,html,html,head,title,text,body,h1,text", extract_children(parser).join(",") - assert_dom_equal %( Title

Hello

), parser.to_xml - assert_equal "document", parser.name - assert_equal Nokogiri::HTML4::Document, parser.class + assert_equal "document,html,head,title,text,body,h1,text", extract_children(parser).join(",") + assert_equal %(Title

Hello

), parser.to_html + assert_equal Nokogiri::HTML5::Document, parser.class end it "should handle html and head" do parser = Parser.call("Title") - assert_equal "document,html,html,head,title,text", extract_children(parser).join(",") - assert_dom_equal %( Title ), parser.to_xml - assert_equal "document", parser.name - assert_equal Nokogiri::HTML4::Document, parser.class + assert_equal "document,html,head,title,text,body", extract_children(parser).join(",") + assert_equal %(Title), parser.to_html + assert_equal Nokogiri::HTML5::Document, parser.class end it "should handle html and body" do parser = Parser.call("

Hello

") - assert_equal "document,html,html,body,h1,text", extract_children(parser).join(",") - assert_dom_equal %(

Hello

), parser.to_xml - assert_equal "document", parser.name - assert_equal Nokogiri::HTML4::Document, parser.class + assert_equal "document,html,head,body,h1,text", extract_children(parser).join(",") + assert_equal %(

Hello

), parser.to_html + assert_equal Nokogiri::HTML5::Document, parser.class end it "should handle head and body" do parser = Parser.call("Title

Hello

") - assert_equal "html,head,title,text,body,h1,text", extract_children(parser).join(",") - assert_dom_equal %( Title

Hello

), parser.to_xml - assert_equal "html", parser.name - assert_equal Nokogiri::XML::Element, parser.class + assert_equal "head,title,text,body,h1,text", extract_children(parser).join(",") + assert_equal %(Title

Hello

), parser.to_html + assert_equal Nokogiri::XML::NodeSet, parser.class end it "should handle head with title" do parser = Parser.call("Title") - assert_equal "head,title,text", extract_children(parser).join(",") - assert_dom_equal %( Title ), parser.to_xml - assert_equal "head", parser.name - assert_equal Nokogiri::XML::Element, parser.class + assert_equal "head,title,text,body", extract_children(parser).join(",") + assert_equal %(Title), parser.to_html + assert_equal Nokogiri::XML::NodeSet, parser.class end it "should handle head" do parser = Parser.call("") - assert_equal "head", extract_children(parser).join(",") - assert_dom_equal %(), parser.to_html - assert_equal "head", parser.name - assert_equal Nokogiri::XML::Element, parser.class + assert_equal "head,body", extract_children(parser).join(",") + assert_equal %(), parser.to_html + assert_equal Nokogiri::XML::NodeSet, parser.class end it "should handle body with h1" do parser = Parser.call("

Hello

") assert_equal "body,h1,text", extract_children(parser).join(",") - assert_dom_equal %(

Hello

), parser.to_xml - assert_equal "body", parser.name - assert_equal Nokogiri::XML::Element, parser.class + assert_equal %(

Hello

), parser.to_html + assert_equal Nokogiri::XML::NodeSet, parser.class end it "should handle body" do parser = Parser.call("") assert_equal "body", extract_children(parser).join(",") - assert_dom_equal %(), parser.to_html - assert_equal "body", parser.name - assert_equal Nokogiri::XML::Element, parser.class + assert_equal %(), parser.to_html + assert_equal Nokogiri::XML::NodeSet, parser.class end end end