Codebase list ruby-html2haml / 22e3c98
Merge tag 'upstream/2.0.0' Upstream version 2.0.0 Jérémy Bobbio 8 years ago
17 changed file(s) with 757 addition(s) and 375 deletion(s). Raw diff Collapse all Expand all
0 language: ruby
01 rvm:
1 - 1.8.7
2 - 2.1.0
3 - 2.0.0
24 - 1.9.3
3 - jruby-18mode
4 - rbx-18mode
5 - rbx-2
6 - jruby-19mode
57
68 gemfile:
79 - Gemfile
0 --markup markdown
00 # HTML2Haml Changelog
1
2 ## 2.0.0
3
4 * Switch to Nokogiri for XML parsing.
5 (thanks to [Stefan Natchev](https://github.com/snatchev) and [Norman
6 Clarke](https://github.com/norman))
7
8 * Add Ruby 2.0 support.
9 (thanks to [Yasuharu Ozaki](https://github.com/yasuoza))
10
11 * Add option to use Ruby 1.9-style attributes when possible.
12 (thanks to [Yoshinori Kawasaki](https://github.com/luvtechno) and
13 [Alexander Egorov](https://github.com/qatsi))
14
15 * Updated dependency versions.
16
17 * Removed some deprecated configuration flags.
18
19 * Move the internal HTML class from the Haml namespace into the Html2haml
20 namespace.
121
222 ## 1.0.1
323
0 Copyright (c) 2006-2013 Hampton Catlin, Nathan Weizenbaum and Norman Clarke
0 Copyright (c) 2006-2014 Hampton Catlin, Natalie Weizenbaum and Norman Clarke
11
22 Permission is hereby granted, free of charge, to any person obtaining a copy of
33 this software and associated documentation files (the "Software"), to deal in
00 # Html2haml
11
2 Converts HTML to Haml.
2 [![Build Status](https://travis-ci.org/haml/html2haml.svg?branch=master)](https://travis-ci.org/haml/html2haml)
3 [![Code Climate](https://codeclimate.com/github/haml/html2haml.svg)](https://codeclimate.com/github/haml/html2haml)
4 [![Gem Version](https://badge.fury.io/rb/html2haml.svg)](https://rubygems.org/gems/html2haml)
5
6 Html2haml, not surprisingly, converts HTML to Haml. It works on HTML with
7 embedded ERB tags as well as plain old HTML.
38
49 ## Installation
510
1722
1823 ## Usage
1924
25
26 ### To convert a project from .erb to .haml
27
28 If your system has `sed` and `xargs` available and none of your .erb file names
29 have whitespace in them, you can convert all your templates like so:
30
31 find . -name \*.erb -print | sed 'p;s/.erb$/.haml/' | xargs -n2 html2haml
32
33 If some of your file names have whitespace or you need finer-grained control
34 over the process, you can convert your files using `gsed` or multi-line script
35 techniques discussed [here](http://stackoverflow.com/questions/17576814/).
36
37
38 ### Documentation
39
40 #### About version 2.0
41
42 Html2haml 2.0 differs from 1.x primarily in that it uses Nokgiri as its HTML
43 parser rather than Hpricot. At the current time however, there are some
44 problems running Html2haml 2.0 on JRuby due to differences in the way the Java
45 version of Nokogiri parses HTML. If you are using JRuby you may wish to run
46 HTML2Haml on MRI or use a 1.x version until these problems have been resolved.
47
48 #### Options
49
50 Here are the options currently available to Html2haml:
51
2052 See `html2haml --help`:
2153
2254 Usage: html2haml [options] [INPUT] [OUTPUT]
2658 Options:
2759 -e, --erb Parse ERb tags.
2860 --no-erb Don't parse ERb tags.
29 -r, --rhtml Deprecated; same as --erb.
30 --no-rhtml Deprecated; same as --no-erb.
31 -x, --xhtml Parse the input using the more strict XHTML parser.
3261 --html-attributes Use HTML style attributes instead of Ruby hash style.
62 --ruby19-attributes Use Ruby 1.9-style attributes when possible.
3363 -E ex[:in] Specify the default external and internal character encodings.
3464 -s, --stdin Read input from standard input instead of an input file
3565 --trace Show a full traceback on error
3969
4070 ## License
4171
42 Copyright (c) 2006-2013 Hampton Catlin, Nathan Weizenbaum and Norman Clarke
72 Copyright (c) 2006-2014 Hampton Catlin, Natalie Weizenbaum and Norman Clarke
4373
4474 Permission is hereby granted, free of charge, to any person obtaining a copy of
4575 this software and associated documentation files (the "Software"), to deal in
77
88 Rake::TestTask.new do |t|
99 t.libs << 'lib' << 'test'
10 t.test_files = Dir["test/**/*_test.rb"]
10 if RUBY_PLATFORM == 'java'
11 t.test_files = FileList["test/**/*_test.rb"]
12 else
13 t.test_files = FileList["test/**/*_test.rb"].exclude(/jruby/)
14 end
1115 t.verbose = true
1216 end
1317
1519 ENV["COVERAGE"] = "true"
1620 end
1721
18 desc "Run Simplecov (only works on 1.9)"
22 desc "Run Simplecov"
1923 task :coverage => [:set_coverage_env, :test]
2024
2125 gemspec = File.expand_path("../html2haml.gemspec", __FILE__)
11 require File.expand_path('../lib/html2haml/version', __FILE__)
22
33 Gem::Specification.new do |gem|
4 gem.authors = ["Norman Clarke"]
5 gem.email = ["norman@njclarke.com"]
4 gem.authors = ["Norman Clarke", "Stefan Natchev"]
5 gem.email = ["norman@njclarke.com", "stefan.natchev@gmail.com"]
66 gem.description = %q{Converts HTML into Haml}
77 gem.summary = %q{Converts HTML into Haml}
88 gem.homepage = "http://haml.info"
1414 gem.require_paths = ["lib"]
1515 gem.version = Html2haml::VERSION
1616
17 gem.add_dependency 'hpricot', '~> 0.8.6'
17 gem.required_ruby_version = '>= 1.9.2'
18
19 gem.add_dependency 'nokogiri', '~> 1.6.0'
1820 gem.add_dependency 'erubis', '~> 2.7.0'
19 gem.add_dependency 'ruby_parser', '~> 3.1.1'
20 gem.add_dependency 'haml', '>= 4.0.0.rc.1'
21 gem.add_dependency 'ruby_parser', '~> 3.5'
22 gem.add_dependency 'haml', '~> 4.0.0'
2123 gem.add_development_dependency 'simplecov', '~> 0.7.1'
2224 gem.add_development_dependency 'minitest', '~> 4.4.0'
2325 gem.add_development_dependency 'rake'
22 require 'rbconfig'
33
44 module Html2haml
5 # This module handles the various Haml executables (`haml` and `haml-convert`).
5 # This module handles the Html2haml executable.
66 module Exec
7 # An abstract class that encapsulates the executable code for all three executables.
7 # An abstract class that encapsulates the executable code for the Html2haml executable.
8 # It's split into a base class and a subclass for historic reasons: this previously
9 # was used by all the executables in the Haml project, before Html2haml was moved
10 # into its own gem.
811 class Generic
912 # @param args [Array<String>] The command-line arguments
1013 def initialize(args)
207210 @options[:no_erb] = true
208211 end
209212
210 opts.on('-r', '--rhtml', 'Deprecated; same as --erb.') do
211 @module_opts[:erb] = true
212 end
213
214 opts.on('--no-rhtml', "Deprecated; same as --no-erb.") do
215 @options[:no_erb] = true
216 end
217
218 opts.on('-x', '--xhtml', 'Parse the input using the more strict XHTML parser.') do
219 @module_opts[:xhtml] = true
220 end
221
222213 opts.on("--html-attributes", "Use HTML style attributes instead of Ruby hash style.") do
223214 @module_opts[:html_style_attributes] = true
224215 end
225216
226 unless RUBY_VERSION < "1.9"
227 opts.on('-E ex[:in]', 'Specify the default external and internal character encodings.') do |encoding|
228 external, internal = encoding.split(':')
229 Encoding.default_external = external if external && !external.empty?
230 Encoding.default_internal = internal if internal && !internal.empty?
231 end
217 opts.on("--ruby19-attributes", "Use Ruby 1.9-style attributes when possible.") do
218 @module_opts[:ruby19_style_attributes] = true
219 end
220
221 opts.on('-E ex[:in]', 'Specify the default external and internal character encodings.') do |encoding|
222 external, internal = encoding.split(':')
223 Encoding.default_external = external if external && !external.empty?
224 Encoding.default_internal = internal if internal && !internal.empty?
232225 end
233226
234227 super
247240 @module_opts[:erb] ||= input.respond_to?(:path) && input.path =~ /\.(rhtml|erb)$/
248241 @module_opts[:erb] &&= @options[:no_erb] != false
249242
250 output.write(::Haml::HTML.new(input, @module_opts).render)
243 output.write(HTML.new(input, @module_opts).render)
251244 rescue ::Haml::Error => e
252245 raise "#{e.is_a?(::Haml::SyntaxError) ? "Syntax error" : "Error"} on line " +
253246 "#{get_line e}: #{e.message}"
11 require 'erubis'
22 require 'ruby_parser'
33
4 module Haml
4 module Html2haml
55 class HTML
66 # A class for converting ERB code into a format that's easier
7 # for the {Haml::HTML} Hpricot-based parser to understand.
7 # for the {Html2haml::HTML} Nokogiri-based parser to understand.
88 #
99 # Uses [Erubis](http://www.kuwata-lab.com/erubis)'s extensible parsing powers
1010 # to parse the ERB in a reliable way,
1212 # to figure out whether a given chunk of Ruby code starts a block or not.
1313 #
1414 # The ERB tags are converted to HTML tags in the following way.
15 # `<% ... %>` is converted into `<haml:silent> ... </haml:silent>`.
16 # `<%= ... %>` is converted into `<haml:loud> ... </haml:loud>`.
15 # `<% ... %>` is converted into `<haml_silent> ... </haml_silent>`.
16 # `<%= ... %>` is converted into `<haml_loud> ... </haml_loud>`.
17 # `<%== ... %>` is converted into `<haml_loud raw=raw> ... </haml_loud>`.
1718 # Finally, if either of these opens a Ruby block,
18 # `<haml:block> ... </haml:block>` will wrap the entire contents of the block -
19 # `<haml_block> ... </haml_block>` will wrap the entire contents of the block -
1920 # that is, everything that should be indented beneath the previous silent or loud tag.
2021 class ERB < Erubis::Basic::Engine
21 # Compiles an ERB template into a HTML document containing `haml:` tags.
22 # Compiles an ERB template into a HTML document containing `haml_*` tags.
2223 #
2324 # @param template [String] The ERB template
2425 # @return [String] The output document
25 # @see Haml::HTML::ERB
26 # @see Html2haml::HTML::ERB
2627 def self.compile(template)
2728 new(template).src
28 end
29
30 # `html2haml` doesn't support HTML-escaped expressions.
31 def escaped_expr(code)
32 raise Haml::Error.new("html2haml doesn't support escaped expressions.")
3329 end
3430
3531 # The ERB-to-Hamlized-HTML conversion has no preamble.
4743 end
4844
4945 # Concatenates a silent Ruby statement onto the source buffer.
50 # This uses the `<haml:silent>` tag,
51 # and may close and/or open a Ruby block with the `<haml:block>` tag.
46 # This uses the `<haml_silent>` tag,
47 # and may close and/or open a Ruby block with the `<haml_block>` tag.
5248 #
5349 # In particular, a block is closed if this statement is some form of `end`,
5450 # opened if it's a block opener like `do`, `if`, or `begin`,
5854 # @param src [String] The source buffer
5955 # @param code [String] The Ruby statement to add to the buffer
6056 def add_stmt(src, code)
61 src << '</haml:block>' if block_closer?(code) || mid_block?(code)
62 src << '<haml:silent>' << h(code) << '</haml:silent>' unless code.strip == "end"
63 src << '<haml:block>' if block_opener?(code) || mid_block?(code)
57 src << '</haml_block>' if block_closer?(code) || mid_block?(code)
58 src << '<haml_silent>' << h(code) << '</haml_silent>' unless code.strip == "end"
59 src << '<haml_block>' if block_opener?(code) || mid_block?(code)
6460 end
6561
6662 # Concatenates a Ruby expression that's printed to the document
7268 # @param src [String] The source buffer
7369 # @param code [String] The Ruby expression to add to the buffer
7470 def add_expr_literal(src, code)
75 src << '<haml:loud>' << h(code) << '</haml:loud>'
76 src << '<haml:block>' if block_opener?(code)
71 src << '<haml_loud>' << h(code) << '</haml_loud>'
72 src << '<haml_block>' if block_opener?(code)
73 end
74
75 def add_expr_escaped(src, code)
76 src << "<haml_loud raw=raw>" << h(code) << "</haml_loud>"
7777 end
7878
7979 # `html2haml` doesn't support debugging expressions.
108108 # @param code [String] Ruby code to check
109109 # @return [Boolean]
110110 def has_code?(code)
111 code != "\n"
111 return false if code == "\n"
112 return false if valid_ruby?(code) == nil
113 true
112114 end
113115
114116 # Checks if a string of Ruby code opens a block.
00 require 'cgi'
1 require 'hpricot'
1 require 'nokogiri'
22 require 'html2haml/html/erb'
33
4 # Haml monkeypatches various Hpricot classes
4 # Haml monkeypatches various Nokogiri classes
55 # to add methods for conversion to Haml.
66 # @private
7 module Hpricot
8 # @see Hpricot
9 module Node
10 # Whether this node has already been converted to Haml.
11 # Only used for text nodes and elements.
12 #
13 # @return [Boolean]
14 attr_accessor :converted_to_haml
15
16 # Returns the Haml representation of the given node.
17 #
18 # @param tabs [Fixnum] The indentation level of the resulting Haml.
19 # @option options (see Haml::HTML#initialize)
20 def to_haml(tabs, options)
21 return "" if converted_to_haml || to_s.strip.empty?
22 text = uninterp(self.to_s)
23 node = next_node
24 while node.is_a?(::Hpricot::Elem) && node.name == "haml:loud"
25 node.converted_to_haml = true
26 text << '#{' <<
27 CGI.unescapeHTML(node.inner_text).gsub(/\n\s*/, ' ').strip << '}'
28
29 if node.next_node.is_a?(::Hpricot::Text)
30 node = node.next_node
31 text << uninterp(node.to_s)
7 module Nokogiri
8
9 module XML
10 # @see Nokogiri
11 class Node
12 # Whether this node has already been converted to Haml.
13 # Only used for text nodes and elements.
14 #
15 # @return [Boolean]
16 attr_accessor :converted_to_haml
17
18 # Returns the Haml representation of the given node.
19 #
20 # @param tabs [Fixnum] The indentation level of the resulting Haml.
21 # @option options (see Html2haml::HTML#initialize)
22 def to_haml(tabs, options)
23 return "" if converted_to_haml || to_s.strip.empty?
24 text = uninterp(self.to_s)
25
26 #ending in a newline stops the inline nodes
27 if text.end_with?("\n")
28 parse_text_with_interpolation(text, tabs)
29 else
30 text << process_inline_nodes(next_sibling)
31 parse_text_with_interpolation(text, tabs)
32 end
33 end
34
35 private
36
37 def erb_to_interpolation(text, options)
38 return text unless options[:erb]
39 text = CGI.escapeHTML(uninterp(text))
40 %w[<haml_loud> </haml_loud>].each {|str| text.gsub!(CGI.escapeHTML(str), str)}
41 ::Nokogiri::XML.fragment(text).children.inject("") do |str, elem|
42 if elem.is_a?(::Nokogiri::XML::Text)
43 str + CGI.unescapeHTML(elem.to_s)
44 else # <haml_loud> element
45 str + '#{' + CGI.unescapeHTML(elem.inner_text.strip) + '}'
46 end
47 end
48 end
49
50 def tabulate(tabs)
51 ' ' * tabs
52 end
53
54 def uninterp(text)
55 text.gsub('#{', '\#{') #'
56 end
57
58 def attr_hash
59 Hash[attributes.map {|k, v| [k.to_s, v.to_s]}]
60 end
61
62 def parse_text(text, tabs)
63 parse_text_with_interpolation(uninterp(text), tabs)
64 end
65
66 def parse_text_with_interpolation(text, tabs)
67 text.strip!
68 return "" if text.empty?
69
70 text.split("\n").map do |line|
71 line.strip!
72 "#{tabulate(tabs)}#{'\\' if Haml::Parser::SPECIAL_CHARACTERS.include?(line[0])}#{line}\n"
73 end.join
74 end
75
76 def process_inline_nodes(node)
77 text = ""
78 while node.is_a?(::Nokogiri::XML::Element) && node.name == "haml_loud"
3279 node.converted_to_haml = true
33 end
34
35 node = node.next_node
36 end
37 return parse_text_with_interpolation(text, tabs)
38 end
39
40 private
41
42 def erb_to_interpolation(text, options)
43 return text unless options[:erb]
44 text = CGI.escapeHTML(uninterp(text))
45 %w[<haml:loud> </haml:loud>].each {|str| text.gsub!(CGI.escapeHTML(str), str)}
46 ::Hpricot::XML(text).children.inject("") do |str, elem|
47 if elem.is_a?(::Hpricot::Text)
48 str + CGI.unescapeHTML(elem.to_s)
49 else # <haml:loud> element
50 str + '#{' + CGI.unescapeHTML(elem.innerText.strip) + '}'
51 end
52 end
53 end
54
55 def tabulate(tabs)
56 ' ' * tabs
57 end
58
59 def uninterp(text)
60 text.gsub('#{', '\#{') #'
61 end
62
63 def attr_hash
64 attributes.to_hash
65 end
66
67 def parse_text(text, tabs)
68 parse_text_with_interpolation(uninterp(text), tabs)
69 end
70
71 def parse_text_with_interpolation(text, tabs)
72 text.strip!
73 return "" if text.empty?
74
75 text.split("\n").map do |line|
76 line.strip!
77 "#{tabulate(tabs)}#{'\\' if Haml::Parser::SPECIAL_CHARACTERS.include?(line[0])}#{line}\n"
78 end.join
80 text << '#{' <<
81 CGI.unescapeHTML(node.inner_text).gsub(/\n\s*/, ' ').strip << '}'
82
83 if node.next_sibling.is_a?(::Nokogiri::XML::Text)
84 node = node.next_sibling
85 text << uninterp(node.to_s)
86 node.converted_to_haml = true
87 end
88
89 node = node.next_sibling
90 end
91 text
92 end
7993 end
8094 end
8195 end
8296
8397 # @private
84 HAML_TAGS = %w[haml:block haml:loud haml:silent]
85
86 HAML_TAGS.each do |t|
87 Hpricot::ElementContent[t] = {}
88 Hpricot::ElementContent.keys.each do |key|
89 Hpricot::ElementContent[t][key.hash] = true
90 end
91 end
92
93 Hpricot::ElementContent.keys.each do |k|
94 HAML_TAGS.each do |el|
95 val = Hpricot::ElementContent[k]
96 val[el.hash] = true if val.is_a?(Hash)
97 end
98 end
99
100 module Haml
98 HAML_TAGS = %w[haml_block haml_loud haml_silent]
99 #
100 # HAML_TAGS.each do |t|
101 # Nokogiri::XML::ElementContent[t] = {}
102 # Nokogiri::XML::ElementContent.keys.each do |key|
103 # Nokogiri::XML::ElementContent[t][key.hash] = true
104 # end
105 # end
106 #
107 # Nokogiri::XML::ElementContent.keys.each do |k|
108 # HAML_TAGS.each do |el|
109 # val = Nokogiri::XML::ElementContent[k]
110 # val[el.hash] = true if val.is_a?(Hash)
111 # end
112 # end
113
114 module Html2haml
101115 # Converts HTML documents into Haml templates.
102 # Depends on [Hpricot](http://github.com/whymirror/hpricot) for HTML parsing.
103 # If ERB conversion is being used, also depends on
116 # Depends on [Nokogiri](http://nokogiri.org/) for HTML parsing.
117 # If ERB conversion is being used, also depends on
104118 # [Erubis](http://www.kuwata-lab.com/erubis) to parse the ERB
105119 # and [ruby_parser](http://parsetree.rubyforge.org/) to parse the Ruby code.
106120 #
107121 # Example usage:
108122 #
109 # Haml::HTML.new("<a href='http://google.com'>Blat</a>").render
123 # HTML.new("<a href='http://google.com'>Blat</a>").render
110124 # #=> "%a{:href => 'http://google.com'} Blat"
111125 class HTML
112 # @param template [String, Hpricot::Node] The HTML template to convert
126 # @param template [String, Nokogiri::Node] The HTML template to convert
113127 # @option options :erb [Boolean] (false) Whether or not to parse
114128 # ERB's `<%= %>` and `<% %>` into Haml's `=` and `-`
115129 # @option options :xhtml [Boolean] (false) Whether or not to parse
117131 def initialize(template, options = {})
118132 @options = options
119133
120 if template.is_a? Hpricot::Node
134 if template.is_a? Nokogiri::XML::Node
121135 @template = template
122136 else
123137 if template.is_a? IO
131145 template = ERB.compile(template)
132146 end
133147
134 method = @options[:xhtml] ? Hpricot.method(:XML) : method(:Hpricot)
135 @template = method.call(template.gsub('&', '&amp;'))
136 end
148 @template = detect_proper_parser(template)
149 end
150 end
151
152 def detect_proper_parser(template)
153 if template =~ /^\s*<!DOCTYPE|<html/i
154 return Nokogiri.HTML(template)
155 end
156
157 if template =~ /^\s*<head|<body/i
158 return Nokogiri.HTML(template).at('/html').children
159 end
160
161 parsed = Nokogiri::HTML::DocumentFragment.parse(template)
162
163 #detect missplaced head or body tag
164 #XML_HTML_STRUCURE_ERROR : 800
165 if parsed.errors.any? {|e| e.code == 800 }
166 return Nokogiri.HTML(template).at('/html').children
167 end
168
169 #in order to support CDATA in HTML (which is invalid) try using the XML parser
170 # we can detect this when libxml returns error code XML_ERR_NAME_REQUIRED : 68
171 if parsed.errors.any? {|e| e.code == 68 } || template =~ /CDATA/
172 return Nokogiri::XML.fragment(template)
173 end
174
175 parsed
137176 end
138177
139178 # Processes the document and returns the result as a string
145184
146185 TEXT_REGEXP = /^(\s*).*$/
147186
148 # @see Hpricot
187
188 # @see Nokogiri
149189 # @private
150 class ::Hpricot::Doc
151 # @see Haml::HTML::Node#to_haml
190 class ::Nokogiri::XML::Document
191 # @see Html2haml::HTML::Node#to_haml
152192 def to_haml(tabs, options)
153193 (children || []).inject('') {|s, c| s << c.to_haml(0, options)}
154194 end
155195 end
156196
157 # @see Hpricot
197 class ::Nokogiri::XML::DocumentFragment
198 # @see Html2haml::HTML::Node#to_haml
199 def to_haml(tabs, options)
200 (children || []).inject('') {|s, c| s << c.to_haml(0, options)}
201 end
202 end
203
204 class ::Nokogiri::XML::NodeSet
205 # @see Html2haml::HTML::Node#to_haml
206 def to_haml(tabs, options)
207 self.inject('') {|s, c| s << c.to_haml(tabs, options)}
208 end
209 end
210
211 # @see Nokogiri
158212 # @private
159 class ::Hpricot::XMLDecl
160 # @see Haml::HTML::Node#to_haml
213 class ::Nokogiri::XML::ProcessingInstruction
214 # @see Html2haml::HTML::Node#to_haml
161215 def to_haml(tabs, options)
162216 "#{tabulate(tabs)}!!! XML\n"
163217 end
164218 end
165219
166 # @see Hpricot
220 # @see Nokogiri
167221 # @private
168 class ::Hpricot::CData
169 # @see Haml::HTML::Node#to_haml
222 class ::Nokogiri::XML::CDATA
223 # @see Html2haml::HTML::Node#to_haml
170224 def to_haml(tabs, options)
171225 content = parse_text_with_interpolation(
172226 erb_to_interpolation(self.content, options), tabs + 1)
173227 "#{tabulate(tabs)}:cdata\n#{content}"
174228 end
175 end
176
177 # @see Hpricot
229
230 # removes the start and stop markers for cdata
231 def content_without_cdata_tokens
232 content.
233 gsub(/^\s*<!\[CDATA\[\n/,"").
234 gsub(/^\s*\]\]>\n/, "")
235 end
236 end
237
238 # @see Nokogiri
178239 # @private
179 class ::Hpricot::DocType
180 # @see Haml::HTML::Node#to_haml
181 def to_haml(tabs, options)
182 attrs = public_id.nil? ? ["", "", ""] :
183 public_id.scan(/DTD\s+([^\s]+)\s*([^\s]*)\s*([^\s]*)\s*\/\//)[0]
240 class ::Nokogiri::XML::DTD
241 # @see Html2haml::HTML::Node#to_haml
242 def to_haml(tabs, options)
243 attrs = external_id.nil? ? ["", "", ""] :
244 external_id.scan(/DTD\s+([^\s]+)\s*([^\s]*)\s*([^\s]*)\s*\/\//)[0]
184245 raise Haml::SyntaxError.new("Invalid doctype") if attrs == nil
185246
186247 type, version, strictness = attrs.map { |a| a.downcase }
204265 end
205266 end
206267
207 # @see Hpricot
268 # @see Nokogiri
208269 # @private
209 class ::Hpricot::Comment
210 # @see Haml::HTML::Node#to_haml
270 class ::Nokogiri::XML::Comment
271 # @see Html2haml::HTML::Node#to_haml
211272 def to_haml(tabs, options)
212273 content = self.content
213274 if content =~ /\A(\[[^\]]+\])>(.*)<!\[endif\]\z/m
223284 end
224285 end
225286
226 # @see Hpricot
287 # @see Nokogiri
227288 # @private
228 class ::Hpricot::Elem
229 # @see Haml::HTML::Node#to_haml
289 class ::Nokogiri::XML::Element
290 # @see Html2haml::HTML::Node#to_haml
230291 def to_haml(tabs, options)
231292 return "" if converted_to_haml
293
232294 if name == "script" &&
233 (attr_hash['type'].nil? || attr_hash['type'] == "text/javascript") &&
295 (attr_hash['type'].nil? || attr_hash['type'].to_s == "text/javascript") &&
234296 (attr_hash.keys - ['type']).empty?
235297 return to_haml_filter(:javascript, tabs, options)
236298 elsif name == "style" &&
237 (attr_hash['type'].nil? || attr_hash['type'] == "text/css") &&
299 (attr_hash['type'].nil? || attr_hash['type'].to_s == "text/css") &&
238300 (attr_hash.keys - ['type']).empty?
239301 return to_haml_filter(:css, tabs, options)
240302 end
241303
242304 output = tabulate(tabs)
243 if options[:erb] && name[0...5] == 'haml:'
244 case name[5..-1]
245 when "loud"
305 if options[:erb] && HAML_TAGS.include?(name)
306 case name
307 when "haml_loud"
246308 lines = CGI.unescapeHTML(inner_text).split("\n").
247309 map {|s| s.rstrip}.reject {|s| s.strip.empty?}
248 lines.first.gsub!(/^[ \t]*/, "= ")
310
311 if attribute("raw")
312 lines.first.gsub!(/^[ \t]*/, "!= ")
313 else
314 lines.first.gsub!(/^[ \t]*/, "= ")
315 end
249316
250317 if lines.size > 1 # Multiline script block
251318 # Normalize the indentation so that the last line is the base
260327 length = lines.map {|s| s.size}.max + 1
261328 lines.map! {|s| "%#{-length}s|" % s}
262329
263 if next_sibling && next_sibling.is_a?(Hpricot::Elem) && next_sibling.name == "haml:loud" &&
330 if next_sibling && next_sibling.is_a?(Nokogiri::XML::Element) && next_sibling.name == "haml_loud" &&
264331 next_sibling.inner_text.split("\n").reject {|s| s.strip.empty?}.size > 1
265332 lines << "-#"
266333 end
267334 end
268335 return lines.map {|s| output + s + "\n"}.join
269 when "silent"
336 when "haml_silent"
270337 return CGI.unescapeHTML(inner_text).split("\n").map do |line|
271338 next "" if line.strip.empty?
272339 "#{output}- #{line.strip}\n"
273340 end.join
274 when "block"
341 when "haml_block"
275342 return render_children("", tabs, options)
276343 end
277344 end
285352 output << "= succeed #{self.next.content.slice!(/\A[^\s]+/).dump} do\n"
286353 tabs += 1
287354 output << tabulate(tabs)
288 end
289 end
290
291 output << "%#{name}" unless name == 'div' &&
355 #empty the text node since it was inserted into the block
356 self.next.content = ""
357 end
358 end
359
360 output << "%#{name}" unless name.to_s == 'div' &&
292361 (static_id?(options) ||
293362 static_classname?(options) &&
294 attr_hash['class'].split(' ').any?(&method(:haml_css_attr?)))
363 attr_hash['class'].to_s.split(' ').any?(&method(:haml_css_attr?)))
295364
296365 if attr_hash
366
297367 if static_id?(options)
298 output << "##{attr_hash['id']}"
368 output << "##{attr_hash['id'].to_s}"
299369 remove_attribute('id')
300370 end
301371 if static_classname?(options)
302 leftover = attr_hash['class'].split(' ').reject do |c|
372 leftover = attr_hash['class'].to_s.split(' ').reject do |c|
303373 next unless haml_css_attr?(c)
304374 output << ".#{c}"
305375 end
310380 end
311381
312382 output << ">" if nuke_outer_whitespace
313 output << "/" if empty? && !etag
383 output << "/" if to_xhtml.end_with?("/>")
314384
315385 if children && children.size == 1
316386 child = children.first
317 if child.is_a?(::Hpricot::Text)
387 if child.is_a?(::Nokogiri::XML::Text)
318388 if !child.to_s.include?("\n")
319389 text = child.to_haml(tabs + 1, options)
320390 return output + " " + text.lstrip.gsub(/^\\/, '') unless text.chomp.include?("\n") || text.empty?
321391 return output + "\n" + text
322392 elsif ["pre", "textarea"].include?(name) ||
323 (name == "code" && parent.is_a?(::Hpricot::Elem) && parent.name == "pre")
393 (name == "code" && parent.is_a?(::Nokogiri::XML::Element) && parent.name == "pre")
324394 return output + "\n#{tabulate(tabs + 1)}:preserve\n" +
325 innerText.gsub(/^/, tabulate(tabs + 2))
395 inner_text.gsub(/^/, tabulate(tabs + 2))
326396 end
327 elsif child.is_a?(::Hpricot::Elem) && child.name == "haml:loud"
397 elsif child.is_a?(::Nokogiri::XML::Element) && child.name == "haml_loud"
328398 return output + child.to_haml(tabs + 1, options).lstrip
329399 end
330400 end
341411 end
342412
343413 def dynamic_attributes
344 @dynamic_attributes ||= begin
345 Hash[attr_hash.map do |name, value|
346 next if value.empty?
347 full_match = nil
348 ruby_value = value.gsub(%r{<haml:loud>\s*(.+?)\s*</haml:loud>}) do
349 full_match = $`.empty? && $'.empty?
350 CGI.unescapeHTML(full_match ? $1: "\#{#{$1}}")
414 #reject any attrs without <haml>
415 @dynamic_attributes = attr_hash.select {|name, value| value =~ %r{<haml.*</haml} }
416 @dynamic_attributes.each do |name, value|
417 fragment = Nokogiri::XML.fragment(CGI.unescapeHTML(value))
418
419 # unwrap interpolation if we can:
420 if fragment.children.size == 1 && fragment.child.name == 'haml_loud'
421 if attribute_value_can_be_bare_ruby?(fragment.text)
422 value.replace(fragment.text.strip)
423 next
351424 end
352 next if ruby_value == value
353 [name, full_match ? ruby_value : %("#{ruby_value}")]
354 end]
355 end
356 end
425 end
426
427 # turn erb into interpolations
428 fragment.css('haml_loud').each do |el|
429 inner_text = el.text.strip
430 next if inner_text == ""
431 el.replace('#{' + inner_text + '}')
432 end
433
434 # put the resulting text in a string
435 value.replace('"' + fragment.text.strip + '"')
436 end
437 end
438
439 def attribute_value_can_be_bare_ruby?(value)
440 begin
441 ruby = RubyParser.new.parse(value)
442 rescue Racc::ParseError, RubyParser::SyntaxError
443 return false
444 end
445
446 return false if ruby.nil?
447 return true if ruby.sexp_type == :str #regular string
448 return true if ruby.sexp_type == :dstr #string with interpolation
449 return true if ruby.sexp_type == :lit #symbol
450 return true if ruby.sexp_type == :call && ruby.mass == 1 #local var or method with no params
451
452 false
453 end
454
357455
358456 def to_haml_filter(filter, tabs, options)
359457 content =
360 if children.first.is_a?(::Hpricot::CData)
361 children.first.content
458 if children.first && children.first.cdata?
459 decode_entities(children.first.content_without_cdata_tokens)
362460 else
363 CGI.unescapeHTML(self.innerText)
461 decode_entities(self.inner_text)
364462 end
365463
366464 content = erb_to_interpolation(content, options)
381479 "#{tabulate(tabs)}:#{filter}\n#{content}"
382480 end
383481
482 # TODO: this method is utterly awful, find a better way to decode HTML entities.
483 def decode_entities(str)
484 str.gsub(/&[\S]+;/) do |entity|
485 begin
486 [Nokogiri::HTML::NamedCharacters[entity[1..-2]]].pack("C")
487 rescue TypeError
488 entity
489 end
490 end
491 end
492
384493 def static_attribute?(name, options)
385494 attr_hash[name] && !dynamic_attribute?(name, options)
386495 end
405514 # that's prettier than that produced by Hash#inspect
406515 def haml_attributes(options)
407516 attrs = attr_hash.sort.map do |name, value|
408 haml_attribute_pair(name, value, options)
517 haml_attribute_pair(name, value.to_s, options)
409518 end
410519 if options[:html_style_attributes]
411520 "(#{attrs.join(' ')})"
417526 # Returns the string representation of a single attribute key value pair
418527 def haml_attribute_pair(name, value, options)
419528 value = dynamic_attribute?(name, options) ? dynamic_attributes[name] : value.inspect
529
420530 if options[:html_style_attributes]
421 "#{name}=#{value}"
422 else
423 name = name.index(/\W/) ? name.inspect : ":#{name}"
424 "#{name} => #{value}"
425 end
531 return "#{name}=#{value}"
532 end
533
534 if name.index(/\W/)
535 return "#{name.inspect} => #{value}"
536 end
537
538 if options[:ruby19_style_attributes]
539 return "#{name}: #{value}"
540 end
541
542 ":#{name} => #{value}"
426543 end
427544 end
428545 end
00 module Html2haml
1 VERSION = "1.0.1"
1 VERSION = "2.0.0"
22 end
0 --- !ruby/object:Gem::Specification
0 --- !ruby/object:Gem::Specification
11 name: html2haml
2 version: !ruby/object:Gem::Version
3 prerelease: false
4 segments:
5 - 1
6 - 0
7 - 1
8 version: 1.0.1
2 version: !ruby/object:Gem::Version
3 version: 2.0.0
94 platform: ruby
10 authors:
5 authors:
116 - Norman Clarke
7 - Stefan Natchev
128 autorequire:
139 bindir: bin
1410 cert_chain: []
15
16 date: 2013-02-16 00:00:00 -03:00
17 default_executable:
18 dependencies:
19 - !ruby/object:Gem::Dependency
20 name: hpricot
11 date: 2015-01-19 00:00:00.000000000 Z
12 dependencies:
13 - !ruby/object:Gem::Dependency
14 name: nokogiri
15 requirement: !ruby/object:Gem::Requirement
16 requirements:
17 - - "~>"
18 - !ruby/object:Gem::Version
19 version: 1.6.0
20 type: :runtime
2121 prerelease: false
22 requirement: &id001 !ruby/object:Gem::Requirement
23 requirements:
24 - - ~>
25 - !ruby/object:Gem::Version
26 segments:
27 - 0
28 - 8
29 - 6
30 version: 0.8.6
31 type: :runtime
32 version_requirements: *id001
33 - !ruby/object:Gem::Dependency
22 version_requirements: !ruby/object:Gem::Requirement
23 requirements:
24 - - "~>"
25 - !ruby/object:Gem::Version
26 version: 1.6.0
27 - !ruby/object:Gem::Dependency
3428 name: erubis
35 prerelease: false
36 requirement: &id002 !ruby/object:Gem::Requirement
37 requirements:
38 - - ~>
39 - !ruby/object:Gem::Version
40 segments:
41 - 2
42 - 7
43 - 0
29 requirement: !ruby/object:Gem::Requirement
30 requirements:
31 - - "~>"
32 - !ruby/object:Gem::Version
4433 version: 2.7.0
4534 type: :runtime
46 version_requirements: *id002
47 - !ruby/object:Gem::Dependency
35 prerelease: false
36 version_requirements: !ruby/object:Gem::Requirement
37 requirements:
38 - - "~>"
39 - !ruby/object:Gem::Version
40 version: 2.7.0
41 - !ruby/object:Gem::Dependency
4842 name: ruby_parser
43 requirement: !ruby/object:Gem::Requirement
44 requirements:
45 - - "~>"
46 - !ruby/object:Gem::Version
47 version: '3.5'
48 type: :runtime
4949 prerelease: false
50 requirement: &id003 !ruby/object:Gem::Requirement
51 requirements:
52 - - ~>
53 - !ruby/object:Gem::Version
54 segments:
55 - 3
56 - 1
57 - 1
58 version: 3.1.1
50 version_requirements: !ruby/object:Gem::Requirement
51 requirements:
52 - - "~>"
53 - !ruby/object:Gem::Version
54 version: '3.5'
55 - !ruby/object:Gem::Dependency
56 name: haml
57 requirement: !ruby/object:Gem::Requirement
58 requirements:
59 - - "~>"
60 - !ruby/object:Gem::Version
61 version: 4.0.0
5962 type: :runtime
60 version_requirements: *id003
61 - !ruby/object:Gem::Dependency
62 name: haml
6363 prerelease: false
64 requirement: &id004 !ruby/object:Gem::Requirement
65 requirements:
66 - - ">="
67 - !ruby/object:Gem::Version
68 segments:
69 - 4
70 - 0
71 - 0
72 - rc
73 - 1
74 version: 4.0.0.rc.1
75 type: :runtime
76 version_requirements: *id004
77 - !ruby/object:Gem::Dependency
64 version_requirements: !ruby/object:Gem::Requirement
65 requirements:
66 - - "~>"
67 - !ruby/object:Gem::Version
68 version: 4.0.0
69 - !ruby/object:Gem::Dependency
7870 name: simplecov
79 prerelease: false
80 requirement: &id005 !ruby/object:Gem::Requirement
81 requirements:
82 - - ~>
83 - !ruby/object:Gem::Version
84 segments:
85 - 0
86 - 7
87 - 1
71 requirement: !ruby/object:Gem::Requirement
72 requirements:
73 - - "~>"
74 - !ruby/object:Gem::Version
8875 version: 0.7.1
8976 type: :development
90 version_requirements: *id005
91 - !ruby/object:Gem::Dependency
77 prerelease: false
78 version_requirements: !ruby/object:Gem::Requirement
79 requirements:
80 - - "~>"
81 - !ruby/object:Gem::Version
82 version: 0.7.1
83 - !ruby/object:Gem::Dependency
9284 name: minitest
93 prerelease: false
94 requirement: &id006 !ruby/object:Gem::Requirement
95 requirements:
96 - - ~>
97 - !ruby/object:Gem::Version
98 segments:
99 - 4
100 - 4
101 - 0
85 requirement: !ruby/object:Gem::Requirement
86 requirements:
87 - - "~>"
88 - !ruby/object:Gem::Version
10289 version: 4.4.0
10390 type: :development
104 version_requirements: *id006
105 - !ruby/object:Gem::Dependency
91 prerelease: false
92 version_requirements: !ruby/object:Gem::Requirement
93 requirements:
94 - - "~>"
95 - !ruby/object:Gem::Version
96 version: 4.4.0
97 - !ruby/object:Gem::Dependency
10698 name: rake
99 requirement: !ruby/object:Gem::Requirement
100 requirements:
101 - - ">="
102 - !ruby/object:Gem::Version
103 version: '0'
104 type: :development
107105 prerelease: false
108 requirement: &id007 !ruby/object:Gem::Requirement
109 requirements:
106 version_requirements: !ruby/object:Gem::Requirement
107 requirements:
110108 - - ">="
111 - !ruby/object:Gem::Version
112 segments:
113 - 0
114 version: "0"
115 type: :development
116 version_requirements: *id007
109 - !ruby/object:Gem::Version
110 version: '0'
117111 description: Converts HTML into Haml
118 email:
112 email:
119113 - norman@njclarke.com
120 executables:
114 - stefan.natchev@gmail.com
115 executables:
121116 - html2haml
122117 extensions: []
123
124118 extra_rdoc_files: []
125
126 files:
127 - .gitignore
128 - .travis.yml
119 files:
120 - ".gitignore"
121 - ".travis.yml"
122 - ".yardopts"
129123 - Changelog.markdown
130124 - Gemfile
131125 - MIT-LICENSE
140134 - lib/html2haml/version.rb
141135 - test/erb_test.rb
142136 - test/html2haml_test.rb
137 - test/jruby/erb_test.rb
138 - test/jruby/html2haml_test.rb
143139 - test/test_helper.rb
144 has_rdoc: true
145140 homepage: http://haml.info
146141 licenses: []
147
142 metadata: {}
148143 post_install_message:
149144 rdoc_options: []
150
151 require_paths:
145 require_paths:
152146 - lib
153 required_ruby_version: !ruby/object:Gem::Requirement
154 requirements:
147 required_ruby_version: !ruby/object:Gem::Requirement
148 requirements:
155149 - - ">="
156 - !ruby/object:Gem::Version
157 segments:
158 - 0
159 version: "0"
160 required_rubygems_version: !ruby/object:Gem::Requirement
161 requirements:
150 - !ruby/object:Gem::Version
151 version: 1.9.2
152 required_rubygems_version: !ruby/object:Gem::Requirement
153 requirements:
162154 - - ">="
163 - !ruby/object:Gem::Version
164 segments:
165 - 0
166 version: "0"
155 - !ruby/object:Gem::Version
156 version: '0'
167157 requirements: []
168
169158 rubyforge_project:
170 rubygems_version: 1.3.6
159 rubygems_version: 2.4.5
171160 signing_key:
172 specification_version: 3
161 specification_version: 4
173162 summary: Converts HTML into Haml
174 test_files:
163 test_files:
175164 - test/erb_test.rb
176165 - test/html2haml_test.rb
166 - test/jruby/erb_test.rb
167 - test/jruby/html2haml_test.rb
177168 - test/test_helper.rb
99
1010 def test_inline_erb
1111 assert_equal("%p= foo", render_erb("<p><%= foo %></p>"))
12 assert_equal(<<HAML.rstrip, render_erb(<<HTML))
13 %p
14 = foo
15 HAML
16 <p><%= foo %>
17 </p>
18 HTML
1219 end
1320
1421 def test_non_inline_erb
2633 HAML
2734 <p>
2835 <%= foo %></p>
29 HTML
30 assert_equal(<<HAML.rstrip, render_erb(<<HTML))
31 %p
32 = foo
33 HAML
34 <p><%= foo %>
35 </p>
3636 HTML
3737 end
3838
115115 def test_erb_in_html_escaped_attribute
116116 assert_equal '%div{:class => "foo"} Bang!',
117117 render_erb('<div class="<%= "foo" %>">Bang!</div>')
118 end
119
120 def test_erb_in_html_escaped_attribute_with_symbol
121 assert_equal '%div{:class => :foo} Bang!',
122 render_erb('<div class="<%= :foo %>">Bang!</div>')
123 end
124
125 def test_empty_erb_in_attribute
126 assert_equal '%div{:class => ""}',
127 render_erb('<div class="<%= %>"></div>')
118128 end
119129
120130 def test_erb_in_attribute_to_multiple_interpolations
198208 = foo + |
199209 bar.baz.bang + |
200210 baz |
201 -#
202211 = foo.bar do |
203212 bang |
204213 end |
459468 def test_can_parse_ruby_19_hashes_as_arguments
460469 erb = "<%= foobar 'foo', {bar: 'baz'} %>"
461470 begin
462 Haml::HTML::ERB.new(erb)
471 Html2haml::HTML::ERB.new(erb)
463472 rescue
464473 flunk "should not raise an error"
465474 end
466475 end
467476
468477 def test_should_wrap_in_silent
469 assert_equal(<<HTML.rstrip, Haml::HTML::ERB.new(<<ERB).src)
470 <haml:silent> some_variable_or_function \n</haml:silent>
478 assert_equal(<<HTML.rstrip, Html2haml::HTML::ERB.new(<<ERB).src)
479 <haml_silent> some_variable_or_function \n</haml_silent>
471480 HTML
472481 <% some_variable_or_function %>
473482 ERB
475484
476485 #comment content is removed by erubis
477486 def test_should_wrap_process_comments_as_empty_lines
478 assert_equal(<<HTML.rstrip, Haml::HTML::ERB.new(<<ERB).src)
479 <haml:silent>\n</haml:silent>
487 assert_equal(<<HTML.rstrip, Html2haml::HTML::ERB.new(<<ERB).src)
488 <haml_silent>\n</haml_silent>
480489 HTML
481490 <%# some_variable_or_function %>
482491 ERB
483492 end
484493
494 def test_conditional_structure_in_argument
495 assert_equal(<<HAML.rstrip, render_erb(<<HTML))
496 %span{:class => "\#{"active" if condition}"}
497 HAML
498 <span class="<%= "active" if condition %>"></span>
499 HTML
500 end
501
502 def test_method_call_without_brackets_in_argument
503 assert_equal(<<HAML.rstrip, render_erb(<<HTML))
504 %span{:class => "\#{call_me maybe}"}
505 HAML
506 <span class="<%= call_me maybe %>"></span>
507 HTML
508 end
509
510 def test_multiline_erb_comment
511 assert_equal(<<HAML.rstrip, render_erb(<<ERB))
512 - # comment
513 %p hi
514 HAML
515 <%
516 # comment
517 -%>
518 <p>hi</p>
519 ERB
520 end
521
522 ##
523 # <%== %> is supposed to be equal to <%= raw %>
524 def test_erb_with_double_equals
525 assert_equal(<<HAML.rstrip, render_erb(<<ERB))
526 != link_to "https://github.com/haml/html2haml/issues/44"
527 HAML
528 <%== link_to "https://github.com/haml/html2haml/issues/44" %>
529 ERB
530 end
531
532 #https://github.com/haml/html2haml/issues/43
533 def test_escaped_ruby_call_when_preceeded_by_text
534 assert_equal(<<HAML.rstrip, render_erb(<<ERB))
535 random text
536 = form_tag(url: sessions_path) do
537 = submit_tag "cdcd"
538 HAML
539 random text
540 <%= form_tag(url: sessions_path) do %>
541 <%= submit_tag "cdcd" %>
542 <% end %>
543 ERB
544 end
485545 end
0 # encoding: UTF-8
01 require 'test_helper'
12
23 class Html2HamlTest < MiniTest::Unit::TestCase
4445 render('<meta http-equiv="Content-Type" content="text/html" />', :html_style_attributes => true))
4546 end
4647
48 def test_should_have_ruby_19_hash_style_attributes
49 assert_equal('%input{name: "login", type: "text"}/',
50 render('<input type="text" name="login" />', :ruby19_style_attributes => true))
51 assert_equal('%meta{content: "text/html", "http-equiv" => "Content-Type"}/',
52 render('<meta http-equiv="Content-Type" content="text/html" />', :ruby19_style_attributes => true))
53 end
54
55 def test_should_have_attributes_without_values
56 assert_equal('%input{:disabled => "disabled"}/', render('<input disabled>'))
57 end
58
4759 def test_class_with_dot_and_hash
4860 assert_equal('%div{:class => "foo.bar"}', render("<div class='foo.bar'></div>"))
4961 assert_equal('%div{:class => "foo#bar"}', render("<div class='foo#bar'></div>"))
8092 end
8193
8294 def test_self_closing_tag
83 assert_equal("%foo/", render("<foo />"))
95 assert_equal("%img/", render("<img />"))
8496 end
8597
8698 def test_inline_text
135147 end
136148
137149 def test_script_tag
150 assert_equal(<<HAML.rstrip, render(<<HTML))
151 :javascript
152 function foo() {
153 return "12" & "13";
154 }
155 HAML
156 <script type="text/javascript">
157 function foo() {
158 return "12" & "13";
159 }
160 </script>
161 HTML
162 end
163
164 def test_script_tag_with_html_escaped_javascript
138165 assert_equal(<<HAML.rstrip, render(<<HTML))
139166 :javascript
140167 function foo() {
256283 HTML
257284 end
258285
286 def test_style_to_css_filter_with_no_content
287 assert_equal(<<HAML.rstrip, render(<<HTML))
288 :css
289 HAML
290 <style type="text/css"> </style>
291 HTML
292 assert_equal(<<HAML.rstrip, render(<<HTML))
293 :css
294 HAML
295 <style type="text/css"></style>
296 HTML
297 end
298
259299 def test_filter_with_inconsistent_indentation
260300 assert_equal(<<HAML.rstrip, render(<<HTML))
261301 :css
332372
333373 # Encodings
334374
335 unless RUBY_VERSION < "1.9"
336 def test_encoding_error
337 render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
338 assert(false, "Expected exception")
339 rescue Haml::Error => e
340 assert_equal(3, e.line)
341 assert_equal('Invalid UTF-8 character "\xFE"', e.message)
342 end
343
344 def test_ascii_incompatible_encoding_error
345 template = "foo\nbar\nb_z".encode("utf-16le")
346 template[9] = "\xFE".force_encoding("utf-16le")
347 render(template)
348 assert(false, "Expected exception")
349 rescue Haml::Error => e
350 assert_equal(3, e.line)
351 assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
352 end
375 def test_encoding_error
376 render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
377 assert(false, "Expected exception")
378 rescue Haml::Error => e
379 assert_equal(3, e.line)
380 assert_match(/Invalid UTF-8 character/, e.message)
381 end
382
383 def test_ascii_incompatible_encoding_error
384 template = "foo\nbar\nb_z".encode("utf-16le")
385 template[9] = "\xFE".force_encoding("utf-16le")
386 render(template)
387 assert(false, "Expected exception")
388 rescue Haml::Error => e
389 assert_equal(3, e.line)
390 assert_match(/Invalid UTF-16LE character/, e.message)
353391 end
354392
355393 # Regression Tests
360398 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
361399 HTML
362400 end
401
402 def test_html_document_without_doctype
403 assert_equal(<<HAML.rstrip, render(<<HTML))
404 !!!
405 %html
406 %head
407 %meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
408 %title Hello
409 %body
410 %p Hello
411 HAML
412 <html>
413 <head>
414 <title>Hello</title>
415 </head>
416 <body>
417 <p>Hello</p>
418 </body>
419 </html>
420 HTML
421 end
422
363423 end
0 #reopen classes that need to be modified for JRuby specific behavior
1 class ErbTest
2 def test_two_multiline_erb_loud_scripts
3 assert_equal(<<HAML.rstrip, render_erb(<<ERB))
4 .blah
5 = foo + |
6 bar.baz.bang + |
7 baz |
8 = foo.bar do |
9 bang |
10 end |
11 %p foo
12 HAML
13 <div class="blah">
14 <%=
15 foo +
16 bar.baz.bang +
17 baz
18 %>
19 <%= foo.bar do
20 bang
21 end %>
22 <p>foo</p>
23 </div>
24 ERB
25 end
26
27 end
0 class Html2HamlTest
1
2 def test_doctype
3 empty_body = "\n%html\n %head\n %body"
4 assert_equal '!!!' + empty_body, render("<!DOCTYPE html>")
5 assert_equal '!!! 1.1' + empty_body, render('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">')
6 assert_equal '!!! Strict' + empty_body, render('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">')
7 assert_equal '!!! Frameset' + empty_body, render('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">')
8 assert_equal '!!! Mobile 1.2' + empty_body, render('<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">')
9 assert_equal '!!! Basic 1.1' + empty_body, render('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">')
10 assert_equal '!!!' + empty_body, render('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">')
11 assert_equal '!!! Strict' + empty_body, render('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">')
12 assert_equal '!!! Frameset' + empty_body, render('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">')
13 assert_equal '!!!' + empty_body, render('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">')
14 end
15
16 def test_xhtml_strict_doctype
17 assert_equal(<<HAML.rstrip, render(<<HTML))
18 !!! Strict
19 %html
20 %head
21 %body
22 HAML
23 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
24 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
25 HTML
26 end
27
28 def test_html_document_without_doctype
29 assert_equal(<<HAML.rstrip, render(<<HTML))
30 %html
31 %head
32 %title Hello
33 %body
34 %p Hello
35 HAML
36 <html>
37 <head>
38 <title>Hello</title>
39 </head>
40 <body>
41 <p>Hello</p>
42 </body>
43 </html>
44 HTML
45 end
46
47 def test_should_have_attributes_without_values
48 assert_equal('%input{:disabled => ""}/', render('<input disabled>'))
49 end
50
51 def test_style_to_css_filter_with_following_content
52 assert_equal(<<HAML.rstrip, render(<<HTML))
53 %head
54 :css
55 foo {
56 bar: baz;
57 }
58 %body
59 Hello
60 HAML
61 <head>
62 <style type="text/css">
63 foo {
64 bar: baz;
65 }
66 </style>
67 </head>
68 <body>Hello</body>
69 HTML
70 end
71 end
1212 class MiniTest::Unit::TestCase
1313 protected
1414 def render(text, options = {})
15 Haml::HTML.new(text, options).render.rstrip
15 Html2haml::HTML.new(text, options).render.rstrip
1616 end
1717
1818 def render_erb(text)