wieldymarkup 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/bin/wieldymarkup +93 -0
  2. data/lib/wieldymarkup.rb +625 -0
  3. metadata +51 -0
data/bin/wieldymarkup ADDED
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'wieldymarkup'
4
+
5
+ # Creates an HTML file by running the WieldyMarkup compiler on the contents
6
+ # of the provided WML file.
7
+ #
8
+ # @param [String] filepath The path to the WML file
9
+ # @param [Hash] options The options for compiling the input text
10
+ # @option options [String] :strict
11
+ # Whether or not to raise an error for invalid filepaths
12
+ # @option options [String] :compress
13
+ # Whether to leave whitespace between HTML tags or not
14
+ def compile_file_from_path(filepath, options={})
15
+ defaults = {:strict => true, :compress => false}
16
+ options = defaults.merge options
17
+
18
+ ext = filepath.split('/')[-1].split('.')[-1]
19
+ if ext != 'wml'
20
+ puts ext
21
+ if options[:strict]
22
+ raise Exception, "Invalid extension for (#{filepath}). Must be .wml."
23
+ else
24
+ return
25
+ end
26
+ end
27
+
28
+ file = File.open(filepath, 'rb')
29
+ data = file.read
30
+
31
+ html = Compiler.new(:text => data, :compress => options[:compress]).output
32
+
33
+ temp = filepath.split('/')
34
+ temp.pop()
35
+ filename = temp.join('/') << '/' << filepath.split('/')[-1].split('.')[0] << '.html'
36
+ File.open(filename, 'wb') {|f| f.write(html) }
37
+ end
38
+
39
+
40
+ # Compiles WML files into HTML files based on command line options.
41
+ #
42
+ # @param [Array] args The command line arguments
43
+ def compile_from_command_line(args)
44
+ compress = false
45
+ if args.index("-c") != nil or args.index("--compress") != nil
46
+ compress = true
47
+ args = args.keep_if { |arg| ["-c", "--compress"].index(arg) == nil }
48
+ end
49
+
50
+ if args.index("-d") != nil
51
+ d_index = args.index("-d")
52
+ if args.length < d_index + 1
53
+ raise Exception, "The -d argument must be followed immediately by a directory path in which to compiler .wml files."
54
+ end
55
+
56
+ dir_path = args[d_index + 1]
57
+
58
+ if !File.directory? dir_path
59
+ raise Exception, "Invalid directory path following -d argument."
60
+ end
61
+
62
+ Dir.chdir dir_path
63
+ if args["-r"] != nil
64
+ Dir['**/*'].each { |f|
65
+ if File.directory? f and ['.', '..'][f] == nil
66
+ puts f
67
+ compile_file_from_path(f, :strict => false, :compress => compress)
68
+ end
69
+ }
70
+ else
71
+ Dir['*'].each { |f|
72
+ if File.directory? f and ['.', '..'][f] == nil
73
+ puts f
74
+ compile_file_from_path(f, :strict => false, :compress => compress)
75
+ end
76
+ }
77
+ end
78
+
79
+ else
80
+ strict = true
81
+ if args.index("-f") != nil or args.index("--force") != nil
82
+ strict = false
83
+ args = args.keep_if { |arg| ["-f", "--force"].index(arg) == nil }
84
+ end
85
+
86
+ args.each { |filepath|
87
+ compile_file_from_path(filepath, :strict => strict, :compress => compress)
88
+ }
89
+
90
+ end
91
+ end
92
+
93
+ compile_from_command_line ARGV
@@ -0,0 +1,625 @@
1
+ # Raises semantic errors in parsing markup.
2
+ class CompilerException < Exception; end
3
+
4
+ # Compiles WieldyMarkup HTML abstraction language into HTML, with each tag
5
+ # indented on its own line or without any whitespace between tags.
6
+ #
7
+ # @author Vail Gold
8
+ class Compiler
9
+
10
+ # Only available for unit tests.
11
+ attr_accessor :line_starts_with_tick,
12
+ :current_level, :tag, :indent_token, :inner_text, :open_tags,
13
+ :previous_level, :tag_id, :tag_classes, :tag_attributes, :self_closing
14
+ attr_reader :line_number
15
+
16
+ # @!attribute [rw] text
17
+ # @return [String] The text to parse and compile
18
+ attr_accessor :text
19
+
20
+ # @!attribute [rw] compress
21
+ # @return [Boolean] Whether or not the compiler should leave whitespace
22
+ # between output HTML tags
23
+ attr_accessor :compress
24
+
25
+ # @!attribute [rw] embedding_token
26
+ # @return [String] The character used to identify embedded HTML lines
27
+ attr_accessor :embedding_token
28
+
29
+ # @!attribute [r] output
30
+ # @return [String] The compiled HTML
31
+ attr_reader :output
32
+
33
+ class << self
34
+ # Removes all substrings surrounded by a grouping substring, including
35
+ # grouping substring on both sides.
36
+ #
37
+ # @param [String] text The string from which to remove grouped substrings
38
+ # @param [String] z The grouping substring
39
+ # @return [String] The string with substrings removed
40
+ def remove_grouped_text(text, z)
41
+ output = ""
42
+ text_copy = text * 1
43
+ status = true
44
+ while text_copy != '' do
45
+ grouper_index = text_copy.index z
46
+ if grouper_index == nil
47
+ if status
48
+ output << (text_copy * 1)
49
+ end
50
+ text_copy = ''
51
+
52
+ else
53
+ if status
54
+ output << text_copy[0..grouper_index-1]
55
+ end
56
+
57
+ if text_copy[grouper_index+1]
58
+ text_copy = text_copy[grouper_index+1..-1]
59
+ else
60
+ text_copy = ''
61
+ end
62
+ end
63
+
64
+ status = !status
65
+ end
66
+
67
+ output
68
+ end
69
+
70
+ # Gets the selector from the line of markup
71
+ #
72
+ # @param [String] line The string from which to get the selector
73
+ # @return [String] The substring from the beginning of the line until the
74
+ # first whitespace character
75
+ def get_selector_from_line(line)
76
+ first_whitespace_index = nil
77
+ line_copy = line.strip * 1
78
+ i = 0
79
+ while line_copy[i] != nil do
80
+ if " \t"[line_copy[i]] != nil
81
+ first_whitespace_index = i
82
+ break
83
+ end
84
+ i += 1
85
+ end
86
+
87
+ if first_whitespace_index == nil
88
+ return line
89
+ else
90
+ return line[0..first_whitespace_index-1]
91
+ end
92
+ end
93
+
94
+ # Determines the level of nesting in a string
95
+ #
96
+ # @param [String] text The string in which to determine the nest level
97
+ # @param [Hash] delimiters The delimiters for determining nest level
98
+ # @option delimiters [String] :open_string
99
+ # The substring that denotes an increase in nesting level.
100
+ # @option delimiters [String] :close_string
101
+ # The substring that denotes a decrase in nesting level.
102
+ # @return [String] The substring from the beginning of the line until the
103
+ # first whitespace character
104
+ def get_tag_nest_level(text, delimiters={})
105
+ defaults = {:open_string => '<', :close_string => '>'}
106
+ delimiters = defaults.merge delimiters
107
+ open_string = delimiters[:open_string] != nil ? delimiters[:open_string] : '<'
108
+ close_string = delimiters[:close_string] != nil ? delimiters[:close_string] : '>'
109
+
110
+ text = text * 1
111
+ nest_level = 0
112
+ while true do
113
+ open_string_index = text.index(open_string)
114
+ close_string_index = text.index(close_string)
115
+ open_string_first = false
116
+ close_string_first = false
117
+
118
+ # Only same if both nil
119
+ if open_string_index == close_string_index
120
+ break
121
+ elsif open_string_index != nil
122
+ open_string_first = true
123
+ elsif close_string_index != nil
124
+ close_string_first = true
125
+ else
126
+ if open_string_index < close_string_index
127
+ open_string_first = true
128
+ else
129
+ close_string_first = true
130
+ end
131
+ end
132
+
133
+ if open_string_first
134
+ nest_level += 1
135
+ if text.length == open_string_index + open_string.length
136
+ break
137
+ else
138
+ text = text[open_string_index + open_string.length..-1]
139
+ end
140
+ elsif close_string_first
141
+ nest_level -= 1
142
+ if text.length == close_string_index + close_string.length
143
+ break
144
+ else
145
+ text = text[close_string_index + close_string.length..-1]
146
+ end
147
+ end
148
+ end
149
+
150
+ nest_level
151
+ end
152
+
153
+ # Gets the string of leading spaces and tabs in some text.
154
+ #
155
+ # @param [String] text The string from which to get the leading whitespace
156
+ # @return [String] The leading whitespace in the string
157
+ def get_leading_whitespace_from_text(text)
158
+ leading_whitespace = ""
159
+ text_copy = text * 1
160
+ i = 0
161
+ while text_copy[i] != nil do
162
+ if " \t"[text_copy[i]] == nil
163
+ if i > 0
164
+ leading_whitespace = text[0..i-1]
165
+ end
166
+ break
167
+ end
168
+
169
+ i += 1
170
+ end
171
+
172
+ leading_whitespace
173
+ end
174
+
175
+ end
176
+
177
+ # Instantiate a new Compiler instance. Automatically compiles text if passed
178
+ # in via parameters.
179
+ #
180
+ # @param [Hash] options The options for compiling the input text
181
+ # @option options [String] :text
182
+ # The input text to compile
183
+ # @option options [String] :compress
184
+ # Whether to leave whitespace between HTML tags or not
185
+ def initialize(options={})
186
+ defaults = {:text => "", :compress => false}
187
+ options = defaults.merge options
188
+ @text = options[:text] != nil ? options[:text] : ''
189
+ @compress = options[:compress] != nil ? !!options[:compress] : false
190
+
191
+ @output = ""
192
+ @open_tags = []
193
+ @indent_token = ""
194
+ @current_level = 0
195
+ @previous_level = nil
196
+ @line_number = 0
197
+ @embedding_token = '`'
198
+
199
+ if @text != ""
200
+ self.compile
201
+ end
202
+ end
203
+
204
+ # Compiles input markup into HTML.
205
+ #
206
+ # @param [Hash] options The options for compiling the input text
207
+ # @option options [String] :text
208
+ # The input text to compile
209
+ # @option options [String] :compress
210
+ # Whether to leave whitespace between HTML tags or not
211
+ # @return [String] The compiled HTML
212
+ def compile(options={})
213
+ defaults = {:text => nil, :compress => nil}
214
+ options = defaults.merge options
215
+ @text = options[:text] if options[:text] != nil
216
+ @compress = !!options[:compress] if options[:compress] != nil
217
+
218
+ while @text != "" do
219
+ self.process_current_level
220
+ self.close_lower_level_tags
221
+ self.process_next_line
222
+ end
223
+
224
+ self.close_tag while @open_tags.length > 0
225
+
226
+ @output
227
+ end
228
+
229
+ # Determines current nesting level for HTML output.
230
+ #
231
+ # @return [Object] The reference to this instance object.
232
+ def process_current_level
233
+ @previous_level = @current_level * 1
234
+ leading_whitespace = self.class.get_leading_whitespace_from_text @text
235
+ if leading_whitespace == ""
236
+ @current_level = 0
237
+
238
+ # If there is leading whitespace but indent_token is still empty string
239
+ elsif @indent_token == ""
240
+ @indent_token = leading_whitespace
241
+ @current_level = 1
242
+
243
+ # Else, set current_level to number of repetitions of index_token in leading_whitespace
244
+ else
245
+ i = 0
246
+ while leading_whitespace.index(@indent_token) == 0 do
247
+ leading_whitespace = leading_whitespace[@indent_token.length..-1]
248
+ i += 1
249
+ end
250
+ @current_level = i
251
+ end
252
+
253
+ self
254
+ end
255
+
256
+ # Iterates through nesting levels that have been closed.
257
+ #
258
+ # @return [Object] The reference to this instance object.
259
+ def close_lower_level_tags
260
+ # If indentation level is less than or equal to previous level
261
+ if @current_level <= @previous_level
262
+ # Close all indentations greater than or equal to indentation level of this line
263
+ while @open_tags.length > 0 and @open_tags[@open_tags.length - 1][0] >= @current_level do
264
+ self.close_tag
265
+ end
266
+ end
267
+ self
268
+ end
269
+
270
+ # Adds closing HTML tags to output and removes entry from @open_tags.
271
+ #
272
+ # @return [Object] The reference to this instance object.
273
+ def close_tag
274
+ closing_tag_array = @open_tags.pop
275
+ if !@compress
276
+ @output << (@indent_token * closing_tag_array[0])
277
+ end
278
+ @output << "</" << closing_tag_array[1] << ">"
279
+ if !@compress
280
+ @output << "\n"
281
+ end
282
+ self
283
+ end
284
+
285
+ # Gets the next line of text, splits it into relevant pieces, and sends them
286
+ # to respective methods for parsing.
287
+ #
288
+ # @return [Object] The reference to this instance object.
289
+ def process_next_line
290
+ @line_starts_with_tick = false
291
+ @self_closing = false
292
+ @inner_text = nil
293
+
294
+ line = ""
295
+
296
+ if @text["\n"] != nil
297
+ line_break_index = @text.index "\n"
298
+ line = @text[0..line_break_index].strip
299
+ @text = @text[line_break_index+1..-1]
300
+ else
301
+ line = @text.strip()
302
+ @text = ""
303
+ end
304
+
305
+ @line_number += 1
306
+ if line.length == 0
307
+ return self
308
+ end
309
+
310
+ # Whole line embedded HTML, starting with back ticks:
311
+ if line[0] == @embedding_token
312
+ self.process_embedded_line line
313
+
314
+ else
315
+ # Support multiple tags on one line via "\-\" delimiter
316
+ while true do
317
+ line_split_list = line.split '\\-\\'
318
+ lines = [line_split_list[0]]
319
+
320
+ if line_split_list.length == 1
321
+ line = line_split_list[0].strip
322
+ break
323
+ else
324
+ lines << line_split_list[1..-1].join('\\-\\')
325
+ end
326
+
327
+ lines[0] = lines[0].strip
328
+ selector = self.class.get_selector_from_line lines[0]
329
+ self.process_selector((selector*1))
330
+ rest_of_line = lines[0][selector.length..-1].strip
331
+ rest_of_line = self.process_attributes rest_of_line
332
+ self.add_html_to_output
333
+
334
+ @tag = nil
335
+ @tag_id = nil
336
+ @tag_classes = []
337
+ @tag_attributes = []
338
+ @previous_level = @current_level * 1
339
+ @current_level += 1
340
+ line = lines[1..-1].join '\\-\\'
341
+ end
342
+
343
+ selector = self.class.get_selector_from_line line
344
+ self.process_selector((selector*1))
345
+ rest_of_line = line[selector.length..-1].strip
346
+ rest_of_line = self.process_attributes rest_of_line
347
+
348
+ if rest_of_line.index('<') == 0
349
+ @inner_text = rest_of_line
350
+ if self.class.get_tag_nest_level(@inner_text) < 0
351
+ raise CompilerException, "Too many '>' found on line #{@line_number}"
352
+ end
353
+
354
+ while self.class.get_tag_nest_level(@inner_text) > 0 do
355
+ if @text == ""
356
+ raise CompilerException, "Unmatched '<' found on line #{@line_number}"
357
+
358
+ elsif @text["\n"] != nil
359
+ line_break_index = @text.index "\n"
360
+ # Guarantee only one space between text between lines.
361
+ @inner_text << ' ' + @text[0..line_break_index].strip
362
+ if @text.length == line_break_index + 1
363
+ @text = ""
364
+ else
365
+ @text = @text[line_break_index+1..-1]
366
+ end
367
+
368
+ else
369
+ @inner_text << @text
370
+ @text = ""
371
+ end
372
+ end
373
+
374
+ @inner_text = @inner_text.strip()[1..-2]
375
+
376
+ elsif rest_of_line.index('/') == 0
377
+ if rest_of_line.length > 0 and rest_of_line[-1] == '/'
378
+ @self_closing = true
379
+ end
380
+ end
381
+
382
+ self.add_html_to_output
383
+ end
384
+
385
+ self
386
+ end
387
+
388
+ # Adds an embedded line to output, removing @embedding_token
389
+ # and not compiling.
390
+ #
391
+ # @param [String] line
392
+ # The line of text with @embedding_token
393
+ # @return [Object] The reference to this instance object.
394
+ def process_embedded_line(line)
395
+ @line_starts_with_tick = true
396
+ if !@compress
397
+ @output << (@indent_token * @current_level)
398
+ end
399
+ @output << line[1..-1]
400
+ if !@compress
401
+ @output << "\n"
402
+ end
403
+ self
404
+ end
405
+
406
+ # Parses a selector into tag, ID, and classes.
407
+ #
408
+ # @param [String] selector
409
+ # The unparsed selector string
410
+ # @return [Object] The reference to this instance object.
411
+ def process_selector(selector)
412
+ # Parse the first piece as a selector, defaulting to DIV tag if none is specified
413
+ if selector.length > 0 and ['#', '.'].count(selector[0]) > 0
414
+ @tag = 'div'
415
+ else
416
+ delimiter_index = nil
417
+ i = 0
418
+ for char in selector.split("") do
419
+ if ['#', '.'].count(char) > 0
420
+ delimiter_index = i
421
+ break
422
+ end
423
+ i += 1
424
+ end
425
+
426
+ if delimiter_index == nil
427
+ @tag = selector * 1
428
+ selector = ""
429
+ else
430
+ @tag = selector[0..delimiter_index-1]
431
+ selector = selector[@tag.length..-1]
432
+ end
433
+ end
434
+
435
+ @tag_id = nil
436
+ @tag_classes = []
437
+ while true do
438
+ next_delimiter_index = nil
439
+ if selector == ""
440
+ break
441
+
442
+ else
443
+ i = 0
444
+ for char in selector.split("") do
445
+ if i > 0 and ['#', '.'].count(char) > 0
446
+ next_delimiter_index = i
447
+ break
448
+ end
449
+ i += 1
450
+ end
451
+
452
+ if next_delimiter_index == nil
453
+ if selector[0] == '#'
454
+ @tag_id = selector[1..-1]
455
+ elsif selector[0] == "."
456
+ @tag_classes << selector[1..-1]
457
+ end
458
+
459
+ selector = ""
460
+
461
+ else
462
+ if selector[0] == '#'
463
+ @tag_id = selector[1..next_delimiter_index-1]
464
+ elsif selector[0] == "."
465
+ @tag_classes << selector[1..next_delimiter_index-1]
466
+ end
467
+
468
+ selector = selector[next_delimiter_index..-1]
469
+ end
470
+ end
471
+ end
472
+
473
+ self
474
+ end
475
+
476
+ # Parses attribute string off of the beginning of a line of text after
477
+ # the selector was removed, and returns everything after the attribute
478
+ # string.
479
+ #
480
+ # @param [String] rest_of_line
481
+ # The line of text after leading whitespace and selector have been removed
482
+ # @return [String] The input text after all attributes have been removed
483
+ def process_attributes(rest_of_line)
484
+ @tag_attributes = []
485
+ while rest_of_line != "" do
486
+ # If '=' doesn't exist, empty attribute string and break from loop
487
+ if rest_of_line.index('=') == nil
488
+ break
489
+ elsif rest_of_line.index('=') != nil and rest_of_line.index('<') != nil and rest_of_line.index('<') < rest_of_line.index('=')
490
+ break
491
+ end
492
+
493
+ first_equals_index = rest_of_line.index '='
494
+ embedded_attribute = false
495
+
496
+ if rest_of_line[first_equals_index+1..first_equals_index+2] == '{{'
497
+ embedded_attribute = true
498
+ close_index = rest_of_line.index '}}'
499
+ if close_index == nil
500
+ raise CompilerException, "Unmatched '{{' found in line #{@line_number}"
501
+ end
502
+ elsif rest_of_line[first_equals_index+1..first_equals_index+2] == '<%'
503
+ embedded_attribute = true
504
+ close_index = rest_of_line.index '%>'
505
+ if close_index == nil
506
+ raise CompilerException, "Unmatched '<%' found in line #{@line_number}"
507
+ end
508
+ end
509
+
510
+ if embedded_attribute
511
+ current_attribute = rest_of_line[0..close_index+1]
512
+ if rest_of_line.length == close_index + 2
513
+ rest_of_line = ""
514
+ else
515
+ rest_of_line = rest_of_line[close_index+2..-1]
516
+ end
517
+
518
+ elsif rest_of_line.length == first_equals_index
519
+ current_attribute = rest_of_line.strip
520
+ rest_of_line = ""
521
+
522
+ elsif rest_of_line[first_equals_index + 1..-1].index('=') == nil
523
+ open_inner_text_index = rest_of_line.index('<')
524
+ if open_inner_text_index != nil
525
+ current_attribute = rest_of_line[0..open_inner_text_index-1].strip
526
+ rest_of_line = rest_of_line[open_inner_text_index..-1]
527
+ else
528
+ current_attribute = rest_of_line * 1
529
+ rest_of_line = ""
530
+ end
531
+
532
+ else
533
+ second_equals_index = rest_of_line[first_equals_index + 1..-1].index '='
534
+ reversed_letters_between_equals = rest_of_line[first_equals_index+1..first_equals_index + 1 + second_equals_index - 1].split("").reverse
535
+
536
+ whitespace_index = nil
537
+ i = 0
538
+ for char in reversed_letters_between_equals do
539
+ if " \t".index(char) != nil
540
+ whitespace_index = first_equals_index + 1 + second_equals_index - i
541
+ break
542
+ end
543
+ i += 1
544
+ end
545
+
546
+ if whitespace_index == nil
547
+ # TODO: Do some error reporting here
548
+ break
549
+ end
550
+
551
+ current_attribute = rest_of_line[0..whitespace_index-1].strip
552
+ rest_of_line = rest_of_line[whitespace_index..-1]
553
+ end
554
+
555
+ if current_attribute != nil
556
+ equals_index = current_attribute.index '='
557
+ @tag_attributes << ' ' + current_attribute[0..equals_index-1] + '="' + current_attribute[equals_index+1..-1] + '"'
558
+ end
559
+ end
560
+
561
+ rest_of_line.strip
562
+ end
563
+
564
+ # Adds HTML to output for a given line.
565
+ #
566
+ # @return [Object] The reference to this instance object.
567
+ def add_html_to_output
568
+ if !@line_starts_with_tick
569
+ tag_html = "<" << @tag
570
+
571
+ if @tag_id != nil
572
+ tag_html << ' id="' << @tag_id << '"'
573
+ end
574
+
575
+ if @tag_classes.length > 0
576
+ tag_html << ' class="' << @tag_classes.join(' ') << '"'
577
+ end
578
+
579
+ if @tag_attributes.length > 0
580
+ tag_html << @tag_attributes.join('')
581
+ end
582
+
583
+ if @self_closing
584
+ tag_html << " />"
585
+ if !@compress
586
+ @output << (@indent_token * @current_level)
587
+ end
588
+ @output << tag_html
589
+ if !@compress
590
+ @output << "\n"
591
+ end
592
+
593
+ else
594
+ tag_html << ">"
595
+
596
+ if @inner_text != nil
597
+ tag_html << @inner_text
598
+ end
599
+
600
+ if !@compress
601
+ @output << (@indent_token * @current_level)
602
+ end
603
+
604
+ @output << tag_html
605
+
606
+ if @inner_text == nil
607
+ if !@compress
608
+ @output << "\n"
609
+ end
610
+ # Add tag data to open_tags list
611
+ @open_tags << [@current_level, @tag]
612
+
613
+ else
614
+ @output <<"</" << @tag << ">"
615
+ if !@compress
616
+ @output << "\n"
617
+ end
618
+ end
619
+ end
620
+ end
621
+
622
+ self
623
+ end
624
+
625
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wieldymarkup
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Vail Gold
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-11 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! " The WieldyMarkup compiler allows you to write more concise HTML
15
+ templates\n for your modern web applications. It works with other templating
16
+ engines\n as well, like Underscore, Mustache, et cetera.\n See http://www.github.com/vail130/wieldymarkup-ruby
17
+ for more information.\n"
18
+ email: vail@vailgold.com
19
+ executables:
20
+ - wieldymarkup
21
+ extensions: []
22
+ extra_rdoc_files: []
23
+ files:
24
+ - lib/wieldymarkup.rb
25
+ - bin/wieldymarkup
26
+ homepage: http://www.github.com/vail130/wieldymarkup-ruby
27
+ licenses: []
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubyforge_project:
46
+ rubygems_version: 1.8.23
47
+ signing_key:
48
+ specification_version: 3
49
+ summary: WieldyMarkup HTML Abstraction Markup Language Compiler
50
+ test_files: []
51
+ has_rdoc: