haml_to_star 0.1

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.
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: []