haml_to_star 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/haml_to_star.rb +292 -0
  2. metadata +45 -0
@@ -0,0 +1,292 @@
1
+ # HAML-TO-*
2
+
3
+ # MIT - Sebastien Drouyer
4
+
5
+ # Why an other haml converter (especially for JS) ?
6
+ # - others are using global variables, except if you prefix all your variables with this.
7
+ # - they don't support brackets in parameters : try {value: "test}"}
8
+ # - we are giving line number so that you can debug your code more easily
9
+ # - class can't be used on prefix and params on others
10
+ # - this one is intended to be used in various languages : you can easily use it for others languages as Ruby or C
11
+
12
+
13
+ require 'rubygems'
14
+ require 'json'
15
+ require 'cgi'
16
+
17
+ class CodeElement
18
+ attr_accessor :line
19
+ attr_accessor :children
20
+ attr_accessor :line_number
21
+
22
+ def initialize
23
+ @line = ''
24
+ @line_number = 0
25
+ @children = []
26
+ end
27
+ end
28
+
29
+ class HamlToStar
30
+ attr_accessor :variable_name
31
+ attr_accessor :variable_line_name
32
+ attr_accessor :self_closing
33
+ attr_accessor :doc_types
34
+ attr_accessor :line_number
35
+
36
+ def initialize
37
+ @variable_name = '_$output'
38
+ @variable_line_name = '_$line'
39
+ @self_closing = [
40
+ 'meta',
41
+ 'img',
42
+ 'link',
43
+ 'br',
44
+ 'hr',
45
+ 'input',
46
+ 'area',
47
+ 'base']
48
+
49
+ @doc_types = {
50
+ '5' => '<!DOCTYPE html>',
51
+ 'xml' => '<?xml version="1.0" encoding="utf-8" ?>',
52
+ 'default' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
53
+ 'strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
54
+ 'frameset' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
55
+ '1.1' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
56
+ 'basic' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
57
+ 'mobile' => '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">'
58
+ }
59
+ end
60
+
61
+
62
+ def convert_from_string(str)
63
+ nb_char_spacing = get_indentation_spacing_from_string(str)
64
+
65
+ @line_number = 0
66
+ code_tree = CodeElement.new
67
+ code_tree.children = get_code_children_from_string(str, nb_char_spacing, 0)
68
+ return convert_from_tree(code_tree)
69
+ end
70
+
71
+ def get_code_children_from_string(str, nb_char_spacing, nb_indentation_objective)
72
+ temp_str = ''
73
+ children = []
74
+ str.each_line do |line|
75
+ nb_indentations = get_nb_indentation_from_line(line, nb_char_spacing)
76
+ if (nb_indentations == nb_indentation_objective)
77
+ code_element = CodeElement.new
78
+ code_element.line = line[nb_indentation_objective * nb_char_spacing..line.size]
79
+ if code_element.line[code_element.line.size - 1] == "\n"
80
+ code_element.line = code_element.line[0..code_element.line.size - 2]
81
+ end
82
+ if (temp_str != '')
83
+ children.last.children = get_code_children_from_string(temp_str, nb_char_spacing, nb_indentation_objective + 1)
84
+ temp_str = ''
85
+ end
86
+ @line_number += 1
87
+ code_element.line_number = @line_number
88
+ children << code_element
89
+ else
90
+ temp_str += line
91
+ end
92
+ end
93
+ if (temp_str != '')
94
+ children.last.children = get_code_children_from_string(temp_str, nb_char_spacing, nb_indentation_objective + 1)
95
+ temp_str = ''
96
+ end
97
+ return children
98
+ end
99
+
100
+ def get_nb_indentation_from_line(line, nb_char_spacing)
101
+ nb_char = 0
102
+ line.each_char do |char|
103
+ if is_spacing_character(char)
104
+ nb_char += 1
105
+ else
106
+ break;
107
+ end
108
+ end
109
+ if (nb_char % nb_char_spacing != 0)
110
+ raise "Bad indentation"
111
+ end
112
+ return nb_char / nb_char_spacing
113
+ end
114
+
115
+ def get_indentation_spacing_from_string(str)
116
+ str.each_line do |line|
117
+ nb_char = 0
118
+ line.each_char do |char|
119
+ if is_spacing_character(char)
120
+ nb_char += 1
121
+ else
122
+ break
123
+ end
124
+ end
125
+ if (nb_char != 0)
126
+ return nb_char
127
+ end
128
+ end
129
+
130
+ return 1
131
+ end
132
+
133
+ def is_spacing_character(char)
134
+ return char == ' ' || char == "\t";
135
+ end
136
+
137
+ def convert_from_tree(code_tree, indentation = -1)
138
+ str = []
139
+
140
+ inside = []
141
+ code_tree.children.each do |child|
142
+ inside << convert_from_tree(child, indentation + 1)
143
+ end
144
+ if (indentation > -1)
145
+ line = code_tree.line
146
+ if (line[0] != '-')
147
+ process_code_number(str, code_tree.line_number)
148
+ end
149
+ if (line[0] == '%' || line[0] == '.' || line[0] == '#')
150
+ dom = convert_dom_element(line)
151
+ if (dom[:self_closing])
152
+ add_content(str, dom[:begin])
153
+ else
154
+ add_content(str, dom[:begin])
155
+ if (inside.size > 0)
156
+ str << inside.join("\n")
157
+ else
158
+ if (dom[:inside])
159
+ add_content(str, dom[:inside])
160
+ end
161
+ end
162
+ add_content(str, dom[:end])
163
+ end
164
+ elsif (line[0] == '=' || line[0] == '!')
165
+ process_inline_code(str, line)
166
+ elsif (line[0] == '-')
167
+ add_code(str, line, inside)
168
+ else
169
+ add_content(str, line.to_json)
170
+ end
171
+ else
172
+ initialize_content(str, inside)
173
+ end
174
+
175
+ return str.join("\n")
176
+ end
177
+
178
+ def convert_dom_element(line)
179
+ div_base_informations = line.gsub(%r{[^\{ =]*}).first
180
+ infos = div_base_informations.gsub(%r{[%.#][\w-]*})
181
+ params = {:tag => 'div'}
182
+ infos.each do |info|
183
+ if (info[0] == '%')
184
+ params[:tag] = info[1..info.size - 1]
185
+ elsif (info[0] == '#')
186
+ params[:id] = info[1..info.size - 1]
187
+ elsif (info[0] == '.')
188
+ unless params[:class]
189
+ params[:class] = ''
190
+ end
191
+ params[:class] += ' ' + info[1..info.size - 1]
192
+ end
193
+ end
194
+
195
+ rest_of_line = line[div_base_informations.size..line.size - 1]
196
+
197
+ num_brackets = 0
198
+ char_num = 0
199
+ start_brackets = 0
200
+ rest_of_line.each_char do |char|
201
+ if (char == '{')
202
+ if (num_brackets == 0)
203
+ start_brackets = char_num
204
+ end
205
+ num_brackets += 1
206
+ elsif (char == '}')
207
+ num_brackets -= 1
208
+ if (num_brackets == 0)
209
+ params[:additionnals] = process_additionnals(rest_of_line[start_brackets..char_num])
210
+ end
211
+ elsif (num_brackets == 0)
212
+ remaining = rest_of_line[char_num..rest_of_line.size - 1].strip
213
+ if (remaining.size > 0)
214
+ if (char == ' ')
215
+ params[:inside] = remaining
216
+ break
217
+ elsif (char == '=' || char == '!')
218
+ params[:inside_code] = evaluate(remaining)
219
+ break
220
+ end
221
+ end
222
+ end
223
+ char_num += 1
224
+ end
225
+
226
+ return construct_dom(params)
227
+ end
228
+
229
+ def construct_dom(params)
230
+ dom = {}
231
+ dom[:self_closing] = @self_closing.index(params[:tag])
232
+ dom[:begin] = '\'<' + params[:tag] + ' '
233
+ if (params[:additionnals])
234
+ extend = {}
235
+ if (params[:id])
236
+ extend[:id] = params[:id]
237
+ end
238
+ if (params[:class])
239
+ extend[:class] = params[:class]
240
+ end
241
+ dom[:begin] += '\' + attrs(' + params[:additionnals] + ', ' + extend.to_json + ') + \''
242
+ else
243
+ if (params[:id])
244
+ dom[:begin] += 'id="' + params[:id] + '" '
245
+ end
246
+ if (params[:class])
247
+ dom[:begin] += 'class="' + params[:class] + '" '
248
+ end
249
+ end
250
+ dom[:begin] += (dom[:self_closing] ? '/' : '') + '>\''
251
+ if (params[:inside])
252
+ dom[:inside] = CGI::escapeHTML(params[:inside])
253
+ elsif (params[:inside_code])
254
+ dom[:inside] = params[:inside_code]
255
+ end
256
+
257
+ dom[:end] = '\'</' + params[:tag] + '>\''
258
+ return dom
259
+ end
260
+
261
+ def process_additionnals(additionnals)
262
+ raise 'To be defined'
263
+ end
264
+
265
+ def process_code_line(line)
266
+ raise 'To be defined'
267
+ end
268
+
269
+ def initialize_content(str, content)
270
+ raise 'To be defined'
271
+ end
272
+
273
+ def add_content(str, content)
274
+ raise 'To be defined'
275
+ end
276
+
277
+ def add_code(str, line, inside)
278
+ raise 'To be defined'
279
+ end
280
+
281
+ def evaluate(line)
282
+ raise 'To be defined'
283
+ end
284
+
285
+ def process_code_number(str, code_number)
286
+ raise 'To be defined'
287
+ end
288
+
289
+ def process_inline_code(str, content)
290
+ raise 'To be defined'
291
+ end
292
+ end
metadata ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: haml_to_star
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sébastien Drouyer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-24 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: haml_to_star allows you to convert haml code into any language.
15
+ email: sdrdis@hotmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/haml_to_star.rb
21
+ homepage: http://rubygems.org/gems/haml_to_star
22
+ licenses: []
23
+ post_install_message:
24
+ rdoc_options: []
25
+ require_paths:
26
+ - lib
27
+ required_ruby_version: !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubyforge_project:
41
+ rubygems_version: 1.8.17
42
+ signing_key:
43
+ specification_version: 3
44
+ summary: convert haml code into an other language
45
+ test_files: []