ouvrages-haml2erb 0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006-2011 Chris Goddard, Louis Sivillo
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,58 @@
1
+ = haml2erb Rails Plugin
2
+
3
+ haml2erb is a tool for converting {Haml markup}[http://haml-lang.com/] to Erb markup.
4
+
5
+ <b>Latest version:</b> 0.2.0
6
+
7
+ * API documentation (coming soon)
8
+ * {Source code} [http://github.com/cgoddard/haml2erb/]
9
+ * {Bug tracker} [http://github.com/cgoddard/haml2erb/issues]
10
+
11
+ Tested on Ruby 1.9.1 and Ruby 1.8.7
12
+
13
+ === Installing and loading haml2erb
14
+
15
+ haml2erb is currently distributed as a Rails plugin.
16
+
17
+ Simply move the main haml2erb directory into the vendor/plugins directory of your Rails application.
18
+
19
+ === Using haml2erb
20
+
21
+ From the Rails console or application, call the Haml2Erb.convert method to have haml
22
+ markup translated into erb.
23
+
24
+ ==== Example: Simple conversion
25
+ Haml2Erb.convert('.foo')
26
+ # => "<div class='foo'>\n</div>\n"
27
+
28
+ === Not supported yet
29
+
30
+ Parsing of tag internal string interpolations, such as:
31
+ #my_div{ class: "box #{extra_classes}" }
32
+
33
+ Coming soon though ...
34
+
35
+ == Licenses
36
+
37
+ ==== haml2erb code and documentation (MIT license)
38
+
39
+ Copyright (c) 2010 Chris Goddard
40
+
41
+ Permission is hereby granted, free of charge, to any person obtaining
42
+ a copy of this software and associated documentation files (the
43
+ "Software"), to deal in the Software without restriction, including
44
+ without limitation the rights to use, copy, modify, merge, publish,
45
+ distribute, sublicense, and/or sell copies of the Software, and to
46
+ permit persons to whom the Software is furnished to do so, subject to
47
+ the following conditions:
48
+
49
+ The above copyright notice and this permission notice shall be
50
+ included in all copies or substantial portions of the Software.
51
+
52
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
53
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
54
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
55
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
56
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
57
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
58
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,68 @@
1
+ module Haml2Erb
2
+ class ErbWriter
3
+
4
+ def initialize
5
+ @processed = ''
6
+ @tag_stack = [ ]
7
+ end
8
+
9
+ def <<(line_options)
10
+
11
+ else_block = (line_options[:content_type] == :ruby_run and (line_options[:contents] =~ /^\s*else\s*$/ or line_options[:contents] =~ /^\s*elsif\s/))
12
+ ruby_block = (line_options[:content_type] == :ruby_run and (line_options[:contents] =~ / do(\s*\|[\w\d_,\s]+\|)?$/ or line_options[:contents] =~ /^\s*if / or else_block))
13
+ close_tags(line_options[:indent], :incoming_else_block => else_block)
14
+ @tag_stack.push(line_options[:element_type]) if line_options[:element_type] and !line_options[:self_closing_tag]
15
+ @tag_stack.push(:ruby_block) if ruby_block
16
+
17
+ @processed << (" " * line_options[:indent]) if line_options[:indent]
18
+ @processed << "<#{line_options[:element_type].to_s}" if line_options[:element_type]
19
+ @processed << " id=\"#{line_options[:element_id].to_s}\"" if line_options[:element_id]
20
+ @processed << " class=\"#{[*line_options[:element_class]].join(' ')}\"" if line_options[:element_class]
21
+ line_options[:element_attributes] && line_options[:element_attributes].keys.each do |attribute_key|
22
+ @processed << " #{attribute_key}=\"#{line_options[:element_attributes][attribute_key]}\""
23
+ end
24
+ @processed << " /" if line_options[:self_closing_tag]
25
+ @processed << ">" if line_options[:element_type]
26
+
27
+ case(line_options[:content_type])
28
+ when :text
29
+ @processed << (line_options[:contents] || "")
30
+ when :ruby
31
+ @processed << ("<%= " + line_options[:contents] + " %>")
32
+ when :ruby_run
33
+ @processed << ("<% " + line_options[:contents] + " %>")
34
+ when :mixed
35
+ @processed << ('<%= "' + line_options[:contents] + '" %>')
36
+ end
37
+
38
+ close_tags(line_options[:indent], :separate_line => false) if line_options[:contents] and !line_options[:self_closing_tag] and !ruby_block
39
+ @processed << "\n"
40
+ end
41
+
42
+ def output_to_string
43
+ close_tags(0)
44
+ @processed
45
+ end
46
+
47
+ private
48
+
49
+ def close_tags(current_indent, options = {})
50
+ options = { :separate_line => true }.merge(options)
51
+ while(@tag_stack.size > current_indent)
52
+ indent = @tag_stack.size - 1
53
+ stack_item = @tag_stack.pop
54
+ if stack_item == :ruby_block
55
+ unless options[:incoming_else_block]
56
+ @processed << (" " * (indent)) if options[:separate_line] == true
57
+ @processed << "<% end %>"
58
+ @processed << "\n" if options[:separate_line] == true
59
+ end
60
+ else
61
+ @processed << (" " * (indent)) if options[:separate_line] == true
62
+ @processed << "</#{stack_item.to_s}>"
63
+ @processed << "\n" if options[:separate_line] == true
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,28 @@
1
+ require 'haml2erb/tokens'
2
+
3
+ module Haml2Erb
4
+ class HamlLexer
5
+
6
+ attr_reader :input
7
+
8
+ def load_input(text)
9
+ @input = text
10
+ end
11
+
12
+ def peek(klass)
13
+ #puts "peek #{klass} #{@input}"
14
+ klass.match(@input)
15
+ end
16
+
17
+ def pop(klass)
18
+ #puts "pop #{klass} #{@input}"
19
+ token = klass.match(@input)
20
+ @input.gsub!(/^#{Regexp.escape(token.matched)}/, '') # removed matched portion from the string
21
+ token
22
+ end
23
+
24
+ def end_input?
25
+ @input.strip.empty? ? true : false
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ module Haml2Erb
2
+ module Mixins
3
+ module CoMerging
4
+ def comerge
5
+ # NOT IMPLEMENTED YET
6
+ fail "comerge command not implemented yet"
7
+ end
8
+
9
+ # inclusive merge that combines results of two hashes when merging
10
+ def comerge! hash_b
11
+ hash_a = self
12
+ hash_b.respond_to?(:each_pair) && hash_b.each_pair do |k,v|
13
+ hash_a[k] = hash_a[k] ?
14
+ (hash_a[k].respond_to?(:push) ?
15
+ hash_a[k].push(v) :
16
+ [ hash_a[k], v ]) :
17
+ v
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,77 @@
1
+ require 'haml2erb/lexer'
2
+ require 'haml2erb/tokens'
3
+ require 'haml2erb/mixins/comerging'
4
+
5
+ module Haml2Erb
6
+ class HamlParser
7
+
8
+ ParsingError = Class.new(StandardError)
9
+
10
+ def initialize
11
+ @lexer = Haml2Erb::HamlLexer.new
12
+ end
13
+
14
+ def parse(unprocessed, writer)
15
+ @line_number = 0
16
+ # process incoming text one line at a time
17
+ unprocessed.each_line do |line|
18
+ @line_number += 1
19
+ next if line =~ /^\s*$/
20
+ options = { }
21
+ class << options
22
+ include Haml2Erb::Mixins::CoMerging
23
+ end
24
+ @lexer.load_input(line)
25
+
26
+ # handle indent
27
+ if(@lexer.peek(Haml2Erb::Tokens::Indent))
28
+ options.merge!(@lexer.pop(Haml2Erb::Tokens::Indent).options)
29
+ end
30
+ options.merge!(:indent => 0) unless options[:indent]
31
+
32
+ # handle initial tag attributes
33
+ while(@lexer.peek(Haml2Erb::Tokens::InitialAttribute))
34
+ options.comerge!(@lexer.pop(Haml2Erb::Tokens::InitialAttribute).options)
35
+ end
36
+ options[:element_type] = :div if((options[:element_id] || options[:element_class]) && !options[:element_type])
37
+
38
+ # handle interior element attributes
39
+ if(@lexer.peek(Haml2Erb::Tokens::AttributesStart))
40
+ @lexer.pop(Haml2Erb::Tokens::AttributesStart)
41
+ options[:element_attributes] = { }
42
+ while(!@lexer.peek(Haml2Erb::Tokens::AttributesEnd))
43
+ if(@lexer.peek(Haml2Erb::Tokens::InnerAttributeQuoted))
44
+ options[:element_attributes].merge!(@lexer.pop(Haml2Erb::Tokens::InnerAttributeQuoted).options[:element_attribute])
45
+ elsif(@lexer.peek(Haml2Erb::Tokens::InnerAttributeRuby))
46
+ options[:element_attributes].merge!(@lexer.pop(Haml2Erb::Tokens::InnerAttributeRuby).options[:element_attribute])
47
+ elsif(@lexer.peek(Haml2Erb::Tokens::InnerAttributeNumber))
48
+ options[:element_attributes].merge!(@lexer.pop(Haml2Erb::Tokens::InnerAttributeNumber).options[:element_attribute])
49
+ else
50
+ raise 'unrecognized inner attribute'
51
+ end
52
+ end
53
+ @lexer.pop(Haml2Erb::Tokens::AttributesEnd)
54
+ end
55
+
56
+ if(@lexer.peek(Haml2Erb::Tokens::SelfClosingTag))
57
+ @lexer.pop(Haml2Erb::Tokens::SelfClosingTag)
58
+ options[:self_closing_tag] = true
59
+ end
60
+
61
+ # handle element contents
62
+ if(@lexer.peek(Haml2Erb::Tokens::ContentsStart))
63
+ options.merge!(@lexer.pop(Haml2Erb::Tokens::ContentsStart).options)
64
+ end
65
+ options[:content_type] = :text unless options[:content_type]
66
+
67
+ if(@lexer.peek(Haml2Erb::Tokens::Contents))
68
+ options.merge!(:contents => @lexer.pop(Haml2Erb::Tokens::Contents).matched)
69
+ end
70
+
71
+ writer << options
72
+ end
73
+ rescue => error
74
+ raise ParsingError, "Haml2Erb had trouble parsing line #{@line_number} with input #{@lexer.input.inspect} remaining: #{error.to_s}", error.backtrace
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,7 @@
1
+ module Haml2Erb
2
+ class Railtie < Rails::Railtie
3
+ rake_tasks do
4
+ load File.join(File.dirname(__FILE__), '..', '..', 'tasks/haml2erb.rake')
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,148 @@
1
+ module Haml2Erb
2
+ module Tokens
3
+
4
+ class Token
5
+ attr_reader :options, :matched
6
+
7
+ def initialize(matched, options = {})
8
+ @matched = matched
9
+ @options = options
10
+ end
11
+
12
+ def self.match(text)
13
+ match_data = @regex.match(text)
14
+ match_data ? self.new(match_data.to_s) : nil
15
+ end
16
+ end
17
+
18
+ class Indent < Token
19
+ @regex = /^(\s\s)+/
20
+
21
+ def self.match(text)
22
+ match_data = @regex.match(text)
23
+ match_data ? self.new(match_data.to_s, :indent => (match_data.to_s.size / 2)) : nil
24
+ end
25
+ end
26
+
27
+ class AttributesStart < Token
28
+ @regex = /^\{\s*/
29
+ end
30
+
31
+ class AttributesEnd < Token
32
+ @regex = /^\s*\}/
33
+ end
34
+
35
+ class SelfClosingTag < Token
36
+ @regex = /^\//
37
+ end
38
+
39
+ class ContentsStart < Token
40
+ @regex = /^((\s+)|(==\s*)|(=\s*)|(-\s*))/
41
+
42
+ def self.match(text)
43
+ match_data = @regex.match(text)
44
+ if match_data
45
+ @return_token = case match_data[1][0,1]
46
+ when ' ' then self.new(match_data.to_s, :content_type => :text)
47
+ when '=', '-'
48
+ match_data[1][1,1] == '=' ? self.new(match_data.to_s, :content_type => :mixed) : self.new(match_data.to_s, :content_type => (match_data[1][0,1] == '-' ? :ruby_run : :ruby))
49
+ end
50
+ else
51
+ @return_token = nil
52
+ end
53
+ @return_token
54
+ end
55
+ end
56
+
57
+ class Contents < Token
58
+ @regex = /^.+$/
59
+
60
+ def self.match(text)
61
+ text.gsub!(/\\\-/, "-")
62
+ match_data = @regex.match(text)
63
+ match_data ? self.new(match_data.to_s) : nil
64
+ end
65
+ end
66
+
67
+ class InitialAttribute < Token
68
+ @regex = /^([%#\.])([-\w]+)/
69
+
70
+ def self.match(text)
71
+ match_data = @regex.match(text)
72
+ if match_data
73
+ @return_token = case match_data[1]
74
+ when '%' then self.new(match_data.to_s, :element_type => match_data[2])
75
+ when '#' then self.new(match_data.to_s, :element_id => match_data[2])
76
+ when '.' then self.new(match_data.to_s, :element_class => match_data[2])
77
+ end
78
+ else
79
+ @return_token = nil
80
+ end
81
+ @return_token
82
+ end
83
+ end
84
+
85
+ class InnerAttributeQuoted < Token
86
+ @regex = /^,?\s*:?['"]?([\w-]+)['"]?(:|(\s*=>))\s*['"]([^'"]+)['"]\s*/
87
+ def self.match(text)
88
+ match_data = @regex.match(text)
89
+ if(match_data)
90
+ value = match_data[4].gsub(/#\{([^\}]+?)\}/, '<%= \1 %>') # replace #{ value } with <%= value %>
91
+ self.new(match_data.to_s, :element_attribute => { match_data[1] => value })
92
+ else
93
+ nil
94
+ end
95
+ end
96
+ end
97
+
98
+ class InnerAttributeRuby < Token
99
+ @regex = /^,?\s*:?['"]?([\w-]+)['"]?(:|(\s*=>))\s*([^'"])/
100
+ def self.match(text)
101
+ match_data = @regex.match(text)
102
+ if match_data
103
+ ruby = match_data[4]
104
+ match = match_data.to_s
105
+ remaining = text[match.size..-1]
106
+ stack = []
107
+ remaining.split(//).each do |chr|
108
+ case chr
109
+ when /[\[\{\(]/
110
+ stack.push chr
111
+ ruby << chr
112
+ match << chr
113
+ when /[\]\}\)]/
114
+ if stack.empty?
115
+ break
116
+ else
117
+ stack.pop
118
+ ruby << chr
119
+ match << chr
120
+ end
121
+ when ','
122
+ if stack.empty?
123
+ break
124
+ else
125
+ ruby << chr
126
+ match << chr
127
+ end
128
+ else
129
+ ruby << chr
130
+ match << chr
131
+ end
132
+ end
133
+ self.new(match, :element_attribute => { match_data[1] => "<%= #{ruby} %>" })
134
+ else
135
+ nil
136
+ end
137
+ end
138
+ end
139
+
140
+ class InnerAttributeNumber < Token
141
+ @regex = /^,?\s*:?['"]?([\w-]+)['"]?(:|(\s*=>))\s*(\d+)\s*/
142
+ def self.match(text)
143
+ match_data = @regex.match(text)
144
+ match_data ? self.new(match_data.to_s, :element_attribute => { match_data[1] => match_data[4] }) : nil
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,3 @@
1
+ module Haml2Erb
2
+ VERSION = "0.3"
3
+ end
data/lib/haml2erb.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'haml2erb/railtie' if defined?(Rails::Railtie)
2
+ require 'haml2erb/erb_writer'
3
+ require 'haml2erb/parser'
4
+ require 'haml2erb/version'
5
+
6
+ module Haml2Erb
7
+
8
+ def self.convert(text)
9
+ parser = Haml2Erb::HamlParser.new
10
+ writer = Haml2Erb::ErbWriter.new
11
+ parser.parse(text, writer)
12
+ writer.output_to_string
13
+ end
14
+
15
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib/', __FILE__)
3
+ $:.unshift lib unless $:.include?(lib)
4
+
5
+ require 'haml2erb/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "ouvrages-haml2erb"
9
+ s.version = Haml2Erb::VERSION
10
+ s.platform = Gem::Platform::RUBY
11
+ s.authors = ['Ouvrages', 'Louis Sivillo']
12
+ s.email = ['contact@ouvrages-web.fr']
13
+
14
+ s.summary = 'Haml to ERB Converter'
15
+ s.description = 'Haml to ERB Converter'
16
+
17
+ s.required_rubygems_version = ">= 1.3.6"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.require_paths = ["lib"]
21
+ end
@@ -0,0 +1,7 @@
1
+ desc "This task will take the supplied .haml input file and convert it to .erb. It will remove the original .haml file and create a new .erb file"
2
+ task :haml2erb, :filename, :needs => :environment do |t, args|
3
+ output_file = args[:filename].gsub(/\.haml/, '.erb')
4
+ p output_file
5
+ File.open(output_file, 'w') { |f| f.write Haml2Erb.convert(File.open(args[:filename], 'r').read) }
6
+ FileUtils.rm_r args[:filename]
7
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ouvrages-haml2erb
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.3'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ouvrages
9
+ - Louis Sivillo
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-08-15 00:00:00.000000000 Z
14
+ dependencies: []
15
+ description: Haml to ERB Converter
16
+ email:
17
+ - contact@ouvrages-web.fr
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - LICENSE
23
+ - README.rdoc
24
+ - lib/haml2erb.rb
25
+ - lib/haml2erb/erb_writer.rb
26
+ - lib/haml2erb/lexer.rb
27
+ - lib/haml2erb/mixins/comerging.rb
28
+ - lib/haml2erb/parser.rb
29
+ - lib/haml2erb/railtie.rb
30
+ - lib/haml2erb/tokens.rb
31
+ - lib/haml2erb/version.rb
32
+ - ouvrages-haml2erb.gemspec
33
+ - tasks/haml2erb.rake
34
+ homepage:
35
+ licenses: []
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: 1.3.6
52
+ requirements: []
53
+ rubyforge_project:
54
+ rubygems_version: 1.8.11
55
+ signing_key:
56
+ specification_version: 3
57
+ summary: Haml to ERB Converter
58
+ test_files: []
59
+ has_rdoc: