w2tags 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/COPYING +340 -0
  2. data/LICENSE +6 -0
  3. data/MIT-LICENSE +18 -0
  4. data/Manifest.txt +95 -0
  5. data/README.rdoc +264 -0
  6. data/Rakefile +23 -0
  7. data/VERSION +1 -0
  8. data/bin/w2tags +143 -0
  9. data/doc/ERB.HOT.rdoc +82 -0
  10. data/doc/FAQ.rdoc +81 -0
  11. data/doc/HAML.rdoc +310 -0
  12. data/doc/HOT.rdoc +137 -0
  13. data/doc/History.rdoc +757 -0
  14. data/doc/W2TAGS.rdoc +150 -0
  15. data/example/common.hot +11 -0
  16. data/example/from_readme.erb +78 -0
  17. data/example/from_readme.w2erb +64 -0
  18. data/example/from_w2tags.erb +32 -0
  19. data/example/from_w2tags.w2erb +32 -0
  20. data/example/rails_basic.hot +10 -0
  21. data/hot/erb.hot +156 -0
  22. data/hot/erb_form.hot +42 -0
  23. data/hot/erb_head.hot +15 -0
  24. data/hot/erb_jquery.hot +8 -0
  25. data/hot/erb_merb.hot +12 -0
  26. data/hot/erb_table.hot +43 -0
  27. data/hot/html.hot +31 -0
  28. data/hot/jquery.hot +88 -0
  29. data/hot/nvelocity.hot +23 -0
  30. data/hot/rails/sc_zebra.hot +10 -0
  31. data/hot/rails/scaffold.hot +15 -0
  32. data/hot/vm.hot +9 -0
  33. data/hot/vm2.hot +34 -0
  34. data/hot/vm_crud.hot +34 -0
  35. data/hot/vm_popup.hot +74 -0
  36. data/hot/xul.hot +114 -0
  37. data/lib/w2tags/block/plain_text.rb +57 -0
  38. data/lib/w2tags/block/remark.rb +37 -0
  39. data/lib/w2tags/block/sass.rb +66 -0
  40. data/lib/w2tags/merb_hook.rb +15 -0
  41. data/lib/w2tags/parser.rb +975 -0
  42. data/lib/w2tags/rails_hook.rb +15 -0
  43. data/lib/w2tags/sinatra_hook.rb +50 -0
  44. data/lib/w2tags.rb +100 -0
  45. data/plugins//w2tags//README +2 -0
  46. data/plugins//w2tags//generators//w2scaffold//USAGE +29 -0
  47. data/plugins//w2tags//generators//w2scaffold//templates//controller.rb +85 -0
  48. data/plugins//w2tags//generators//w2scaffold//templates//functional_test.rb +45 -0
  49. data/plugins//w2tags//generators//w2scaffold//templates//helper.rb +2 -0
  50. data/plugins//w2tags//generators//w2scaffold//templates//helper_test.rb +4 -0
  51. data/plugins//w2tags//generators//w2scaffold//templates//layout.html.erb +17 -0
  52. data/plugins//w2tags//generators//w2scaffold//templates//style.css +54 -0
  53. data/plugins//w2tags//generators//w2scaffold//templates//view_edit.html.erb +18 -0
  54. data/plugins//w2tags//generators//w2scaffold//templates//view_edit.html.w2erb +17 -0
  55. data/plugins//w2tags//generators//w2scaffold//templates//view_index.html.erb +24 -0
  56. data/plugins//w2tags//generators//w2scaffold//templates//view_index.html.w2erb +14 -0
  57. data/plugins//w2tags//generators//w2scaffold//templates//view_new.html.erb +17 -0
  58. data/plugins//w2tags//generators//w2scaffold//templates//view_new.html.w2erb +16 -0
  59. data/plugins//w2tags//generators//w2scaffold//templates//view_show.html.erb +10 -0
  60. data/plugins//w2tags//generators//w2scaffold//templates//view_show.html.w2erb +9 -0
  61. data/plugins//w2tags//generators//w2scaffold//w2scaffold_generator.rb +106 -0
  62. data/plugins//w2tags//install.rb +1 -0
  63. data/spec/spec_helper.rb +17 -0
  64. data/spec/w2tags_spec.rb +8 -0
  65. data/tasks/ann.rake +81 -0
  66. data/tasks/bones.rake +21 -0
  67. data/tasks/gem.rake +126 -0
  68. data/tasks/git.rake +41 -0
  69. data/tasks/manifest.rake +49 -0
  70. data/tasks/notes.rake +28 -0
  71. data/tasks/post_load.rake +39 -0
  72. data/tasks/rdoc.rake +51 -0
  73. data/tasks/rubyforge.rake +57 -0
  74. data/tasks/setup.rb +268 -0
  75. data/tasks/spec.rake +55 -0
  76. data/tasks/svn.rake +48 -0
  77. data/tasks/test.rake +38 -0
  78. data/test/enlightning.hot +3 -0
  79. data/test/feature.hot +28 -0
  80. data/test/parser_test.rb +203 -0
  81. data/test/tricky.hot +8 -0
  82. data/test/vars.hot +30 -0
  83. data/test/w2tags_basic_usability.rb +187 -0
  84. data/test/w2tags_enlightning.rb +42 -0
  85. data/test/w2tags_form.rb +32 -0
  86. data/test/w2tags_hot.rb +85 -0
  87. data/test/w2tags_hot_var.rb +115 -0
  88. data/test/w2tags_no_parsing.rb +37 -0
  89. metadata +163 -0
@@ -0,0 +1,975 @@
1
+ module W2Tags
2
+ # Copyright (c) 2008 - 2009 Widi Harsojo
3
+ class Parser
4
+ attr_accessor :silent
5
+ #change debuging ex: obj.dbg[:parse] = true
6
+ attr_accessor :dbg
7
+ #set extention for ext auto loading HOT files
8
+ attr_accessor :ext
9
+ attr_reader :spc
10
+
11
+ block= ::W2Tags::Block.constants
12
+ include *(block.collect{|m|eval("::W2Tags::Block::#{m.to_s}")})
13
+ #initiall create instance object, default if no arguments will be
14
+ #target for html
15
+ def initialize(ext = 'html')
16
+ @dbg={
17
+ :hot =>nil,
18
+ :stack =>nil,
19
+ :parse =>nil,
20
+ :constanta=>nil
21
+ }
22
+
23
+ #regex for w2tags
24
+ @rg_tag = [
25
+ /^[ \t]*(%)([!]?[\w\-&\/:#.]+\{.*\}[=]*)!([^\n]*)\n/,
26
+ /^[ \t]*(%)([!]?[\w\-&\/:#.=]+)!([^\n]*)([\n])/]
27
+
28
+ #regex for function tags
29
+ @rg_hot = [
30
+ /(%)([!]?[ \t\$\w\-&\/:#.%=]+\{.*\}[=]*)~([^\n]*)\n/,
31
+ /(%)([!]?[ \t\$\w\-&\/:#.%=]+)~([^\n]*)\n/ ]
32
+ @rgx = nil #current regular expression
33
+ @ext = ext #target extension
34
+ @hot = 'hot' #source of file hot
35
+ @w2x = 'w2x' #source file to include
36
+ @src_path= '' #path for source file
37
+ @silent = false #for test
38
+
39
+ @spc = '' #current begining space of current source line
40
+ @ind = ' ' #indentation size
41
+ @row = 'row' #current source line
42
+ @key = 'key' #key extracted from regex function
43
+
44
+ @mem_hot= nil #@tg_nex will be use (for "%") if this var == nil
45
+ @mem_tag= {'^'=>"%div$*!"} #get memorize of w2tag
46
+ @mem_var= {'$me'=>"wharsojo"}
47
+ @mem_var['$basepath'] = File.basename(File.expand_path('.'))
48
+
49
+ @tg_hot = {} #{'div'=>[proc{|this|"%div$*!"},nil]} #collection of tag_hot after reading from source hot
50
+ @tg_nex = {} #tag next activate on shortcut tag "%"
51
+ @tg_end = [] #momorize tag end from regex function
52
+ @doc_src= []
53
+ @doc_out= []
54
+
55
+ @tg_nex['html' ]= [0,proc { @mem_tag["^"] = "%head $*\n"}]
56
+ @tg_nex['head' ]= [0,proc { @mem_tag["^"] = "%body $*\n"}]
57
+ @tg_nex['ol' ]= [0,proc { @mem_tag["^"] = "%li $0\n" }]
58
+ @tg_nex['ul' ]= [0,proc { @mem_tag["^"] = "%li $0\n" }]
59
+ @tg_nex['dl' ]= [0,proc { @mem_tag["^"] = "%dt $0\n" }]
60
+ @tg_nex['dd' ]= [0,proc { @mem_tag["^"] = "%dt $0\n" }]
61
+ @tg_nex['form' ]= [0,proc { @mem_tag["^"] = "%input $0\n"}]
62
+ @tg_nex['select']= [0,proc { @mem_tag["^"] = "%option $0\n"}]
63
+ @tg_nex['table' ]= [0,proc { @tg_nex['tr'][0]= 0 }]
64
+ @tg_nex['tr' ]= [0,proc {
65
+ @tg_nex['tr' ][0]+= 1
66
+ if @tg_nex['tr'][0]== 1
67
+ @mem_tag["^"] = "%th $0\n"
68
+ else
69
+ @mem_tag["^"] = "%td $0\n"
70
+ end
71
+ }]
72
+
73
+ @tagr = proc do |this|
74
+ @key.strip!
75
+ tags_created = "<#{@key}"
76
+ tags_created << " #{@mem_var["*all*"].strip}" if @mem_var["*all*"]!=''
77
+ #tags_created << " #{@att}" if @att!=''
78
+ if @txt=='/'
79
+ tags_created << "/>\n"
80
+ else
81
+ tags_created << '>'
82
+ @ln_end = " "
83
+ if @txt==''
84
+ @tg_end.push "#{@spc}</#{@key}>#{@ln_end}"
85
+ p "Stack: #{@tg_end}" if @dbg[:stack]
86
+ else
87
+ if @txt.gsub!(/\<$/,'')
88
+ @tg_end.push "#{@spc}</#{@key}>#{@ln_end}"
89
+ else
90
+ @ln_end = "</#{@key}>#{@ln_end}"
91
+ end
92
+ if @mem_var["*code*"] && @mem_var["*code*"]!=''
93
+ tags_created << @mem_var["*code*"].gsub('$*',@txt)
94
+ else
95
+ tags_created << @txt.gsub(/^ +/,'') #remove gsub if don't want auto trim left
96
+ end
97
+ end
98
+ end
99
+ tags_created
100
+ end
101
+ @skiper= []
102
+ public_methods.each do |f|
103
+ send(f) if /_initialize$/ =~ (meth= f.to_s)
104
+ @skiper << [$1,'_skip'].join.to_sym if /(.*)_skip$/ =~ meth
105
+ end
106
+ end
107
+
108
+ #parsing from fullpath source to the fullpath target/result
109
+ #with the option of auto add 'initialize' and 'finalize'
110
+ #for source file in w2tags only fill with LF it will not
111
+ #translate, since behaviour for "\n\n\n".split("\n")
112
+ #will result in empty array
113
+ #if hot available it will add w2tags in:
114
+ #firstline with @initialize()
115
+ #lastline with @finalize()
116
+ #to not add, supply this function with init_start=false
117
+ #ex: parsing("t.w2tst","t.tst",false)
118
+ def parsing(src,tgt,init_start=true)
119
+ puts ">>#{src}"
120
+ puts ">>#{tgt}"
121
+ parse_init
122
+ @src_path= File.dirname(src)
123
+ @doc_src = IO.read(src).delete("\r").split("\n")
124
+ @doc_src<< "%finallize" if @tg_hot['finallize' ]
125
+
126
+ while (@row = @doc_src.shift) do #;p "row:#{@row}"
127
+ if init_start && !(/!hot!/ =~ @row)
128
+ @doc_src,@row = [[@row]+@doc_src,"%initialize"] if @tg_hot['initialize']
129
+ p "HEAD:#{init_start}"
130
+ init_start = false
131
+ end
132
+ parse_row
133
+ end
134
+ if @dbg[:constanta]
135
+ p "const_ "
136
+ @mem_var.keys.sort.each {|k|p "#{k.ljust 10} : #{@mem_var[k]}"}
137
+ end
138
+
139
+ if @dbg[:hot]
140
+ @tg_hot.keys.sort.each_with_index do |v,i|
141
+ puts "hot keys: #{i}. #{v}"
142
+ end
143
+ end
144
+
145
+ open(tgt,'w') do |f|
146
+ @doc_out.each do |row|
147
+ f << row
148
+ end
149
+ end
150
+
151
+ end
152
+
153
+ #it use to clean all the definition and reloading the hot file
154
+ def parse_init
155
+ @tg_end = [] #momorize tag end from regex function
156
+ @doc_src = []
157
+ @doc_out = []
158
+ @tg_hot = {}
159
+ merge_tags
160
+ end
161
+
162
+ #to test parsing on source line and return will be the result,
163
+ #everytime it execude, it clean up and reloading the HOT files.
164
+ def parse_line row,init=true
165
+ parse_init if init
166
+ dbg[:parse]= false
167
+ @doc_src = row.delete("\r").split("\n") << ",/"
168
+ while (@row= @doc_src.shift) do #;p "row:#{@row}"
169
+ parse_row
170
+ end
171
+ @doc_out
172
+ end
173
+
174
+ #the actual parsing on row, but it use for parsing the files not to
175
+ #test the source line, since some of the row have a command that
176
+ #has effect on source, result and the row will be empty, please use
177
+ #parse_line if you want to test interactively on IRB.
178
+ def parse_row row=nil
179
+ @row = row if row
180
+ @row<<"\n" #;p "row:#{@row}"
181
+ p "_____> #{@row}" if @dbg[:parse] && @plt == 99 && @rmk == 99
182
+
183
+ parse_spc
184
+
185
+ @ln_end = "" #imediate ends tag
186
+ @row.gsub!(/\\\\/,'') #esc char \\
187
+ @row.gsub!('\}','') #esc char \)
188
+ @row.gsub!('\;','') #esc char \;
189
+ while (parse_all) do; end
190
+ @row.gsub!('','\\')
191
+ @row.gsub!('','}')
192
+ @row.gsub!('',';')
193
+ if @ln_end!=""
194
+ @row.gsub!(/([\n\t ]*$)/,'')
195
+ @row << "#{@ln_end.strip}\n"
196
+ end
197
+ if @row.strip!=""
198
+ p "#####> #{@row}" if @dbg[:parse]
199
+ @doc_out << @row.rstrip+"\n"
200
+ end
201
+ @row
202
+ end
203
+
204
+ #parse one w2tags, result will be name of the target file created
205
+ def parse_file(src,init_start=true,chk_date=false)
206
+ tgt,@ext = [src[/(.+\.)w2(\w+)$/,1]<<$2,$2]
207
+
208
+ return nil if !File.exist?(src) #p "src: #{src} not found..."
209
+ if chk_date && File.exist?(tgt)
210
+ return nil if File.mtime(src) <= File.mtime(tgt)
211
+ end
212
+
213
+ puts "\nParsing W2Tags File:#{src}"
214
+ parsing(src,tgt,init_start)
215
+ tgt
216
+ end
217
+
218
+ #parse multiple w2tags files, result will be array of target file created
219
+ def parse_files(srcs,init_start=true)
220
+ srcs.collect do |src|
221
+ src.gsub!(/\n/,'')
222
+ parse_file(src,init_start)
223
+ end.compact
224
+ end
225
+
226
+ def end_tags(arr)
227
+ @tg_end = @tg_end + arr
228
+ end
229
+
230
+ #call from proc hot before it render hots line
231
+ #see in source code "w2tags.rb::read_filehot"
232
+ #default behaviour for tag_nex will not execute
233
+ #since @mem_hot will assigned w/o nil
234
+ #assigned nil using "%!" in w2tags
235
+ def chg_mem_hot(nxt)
236
+ @mem_hot = nxt
237
+ @mem_tag["^"] = nxt if nxt
238
+ end
239
+
240
+ #pop up end tags from the stack
241
+ #result will be string contains end tags from stack
242
+ #who's space inside each end tags > current space
243
+ def multi_end(ttls)
244
+ rpls = ''
245
+ ttl = @tg_end.size-1
246
+ ttl = ttls-1 if ttls
247
+ ttl.downto(0) do |i|
248
+ sz = @tg_end[i][/^ +/].to_s.size
249
+ if ttls || @spc.size <= sz
250
+ send = @tg_end.pop.to_s
251
+ if send.strip[0,5]=="!run!"
252
+ scrpt = send.gsub("\n","\n#{@spc}").split("\n")
253
+ @doc_src = scrpt[1,99]+@doc_src
254
+ else
255
+ spc = send[/(^[ \t]*)/,1].to_s
256
+ rpls << send.gsub(/\n/,"\n#{spc}") + "\n"
257
+ end
258
+ end
259
+ end
260
+ p "End..: #{rpls.strip}" if @dbg[:parse] && rpls!= ''
261
+ rpls
262
+ end
263
+
264
+ private
265
+
266
+ # try to shift empty line create document and add current
267
+ # row to source. but it means re parsing current row.
268
+ def swap_last_empt_src_with_end_tg(end_tg)
269
+ last = []
270
+ while @doc_out[-1] && @doc_out[-1].to_s.strip == ''
271
+ last << @doc_out.pop
272
+ end
273
+ end_tg.shift if end_tg[0].strip==''
274
+ @doc_src = end_tg + @doc_src
275
+ #p "Swp..: #{@doc_src[-1]}" if @dbg[:parse]
276
+ end
277
+
278
+ #merging file hot based on the target extension, and target
279
+ #extension it self based on source extension, example:
280
+ #suppose you have source of w2tags 'index.html.w2erb'
281
+ #it just like autoloading:
282
+ # !hot!erb
283
+ #it will search HOT files in current folder, if it not found
284
+ #it will search in gem/hot and merging the HOT
285
+ def merge_tags
286
+ hot1 = "#{@src_path}/#{@ext}.#{@hot}"
287
+ hot2 = "#{W2Tags::Dir}/../hot/#{@ext}.#{@hot}"
288
+ filehot = hot1 if File.exist?(hot1)
289
+ filehot = hot2 if File.exist?(hot2)
290
+ if filehot
291
+ puts '=>'+File.expand_path(filehot) if !@silent
292
+ @tg_hot.merge!(W2Tags.read_filehot(filehot))
293
+ end
294
+ @tg_hot
295
+ end
296
+
297
+ #define variable ( &var! or @var! )tobe use by parser in hot for
298
+ #the next line parsing, example on w2tags:
299
+ # &myvar=hello\n
300
+ # ^{.myclass &myvar!}
301
+ #
302
+ #it will translate on the fly to:
303
+ # ^{.myclass hello}
304
+ #
305
+ #for @var! is uniq value split by ";", example on w2tags:
306
+ # @myvar=hello;world\n
307
+ # @myvar=world;tags\n
308
+ # ^{.myclass @myvar!}
309
+ #
310
+ #it will translate on the fly to:
311
+ # ^{.myclass hello;world;tags}
312
+ def parse_set_var
313
+ if @row.gsub!( /^[ \t]*(&[\w]+)=([^\n]+)([\n])/,'')
314
+ @mem_var[$1+"!"] = $2.strip
315
+ elsif @row.gsub!(/^[ \t]*(@[\w]+)=([^\n]+)([\n])/,'')
316
+ k,v = [$1+"!",$2.strip] #;p v
317
+ #v << ';'+@mem_var[k].to_s if v[0,1]!=';' && @mem_var[k]
318
+ v = (@mem_var[k].to_s + ';' + v) if v[0,1]!=';' && @mem_var[k]
319
+ @mem_var[k] = v.split(';').uniq.select{|x|x!=''}.join(';')
320
+ p "uniq var> #{v}" if @dbg[:parse] #&& @plt == 99 && @rmk == 99
321
+ end
322
+ end
323
+
324
+ #when parsing and found tag
325
+ # !hot!filehot1;filehotN
326
+ #it will search HOT files in current folder, if it not found it will search
327
+ #in gem/hot and merging the HOT, this command can have multiple
328
+ #file HOT separate with ";"
329
+ def merge_hot
330
+ if(/!hot!([\w;]+)([`\n])/ =~ @row;@rgx = $~)
331
+ hots= @rgx[1].split(';').collect {|x|x+'.'+@hot}
332
+ rpl = ['']
333
+ hots.each do |hot|
334
+ fls = File.exist?(hot) ? hot :
335
+ File.exist?(@src_path+'/'+hot) ? @src_path+'/'+hot :
336
+ File.exist?(W2Tags::Dir+'/../hot/'+hot) ? W2Tags::Dir+'/../hot/'+hot : ''
337
+ if fls==''
338
+ rpl << "<!--"+hot+", Not Found-->\n"
339
+ else
340
+ puts '=>'+File.expand_path(fls) if !@silent
341
+ @tg_hot.merge!(W2Tags.read_filehot(fls))
342
+ end
343
+ end
344
+ @row.gsub!(@rgx.to_s,rpl.join)
345
+ end
346
+ end
347
+
348
+ #when parsing and found tag
349
+ # !inc!fileinc
350
+ #it will include / replace current row from file inside .w2x, and after
351
+ #parser will try to get current row after merging to be evaluate
352
+ def merge_w2x
353
+ if(/!inc![ ]?([\/\w._]+)([`\n])/ =~ @row;@rgx = $~)
354
+ mac = @src_path+'/'+$1+'.'+@w2x
355
+ src = $~.to_s #;p mac
356
+ if File.exist?(mac)
357
+ pop = $~.captures.pop
358
+ new = IO.read(mac).delete("\r").gsub("\n","\n"+@spc) + ( pop=='`' ? "\n"+@spc : '' )
359
+ @doc_src= @row.gsub(src,new).split("\n")+@doc_src
360
+ @row= @doc_src.shift+"\n"
361
+ parse_spc
362
+ else
363
+ @row.gsub!(src,"<!--"+mac+", Not Found-->\n")
364
+ nil
365
+ end
366
+ end
367
+ end
368
+
369
+ #get space (tab and spaces) on the left of the code and save it to instance
370
+ #it will be use if row replace with more than one row and replacement row
371
+ #must continue with current column (indent).
372
+ def parse_spc
373
+ @spc = @row[/(^[ \t]+)/,1].to_s #sometime result is nil
374
+ end
375
+
376
+ #do the translation from the params inside function like:
377
+ # %a par1;par2;par3
378
+ #it do following job:
379
+ # * replace constanta (&var!) inside params of the function
380
+ # * replace constanta (&var!) inside new line of source code
381
+ # (inside instance var @new)
382
+ # * replace var $0 - $9 inside var @new from params if function have
383
+ # 3 params so 3 var $ will be replace from the params and if var @new
384
+ # have var # more than what function params suply, it will replace with
385
+ # an empty string
386
+ # * if in var @new define only 1 var $ and function params got more than
387
+ # 1, it will multiply the @new line with total number of lparams
388
+ # to get the illustrate I'll show you with an example:
389
+ # inside hot file :
390
+ # >>td
391
+ # <td>$0</td>
392
+ # --------------------
393
+ # function call: @td(col1;col2) # will result in
394
+ # --------------------
395
+ # <td>col1</td>
396
+ # <td>col2</td>
397
+ # * some of the replacement behaviour for var $ are :
398
+ # 1. optional meaning that var $ inside [ xxx $ xxxx ] sequare bracket are
399
+ # optional if not suply from params it will an emppty replacement
400
+ # 2. default value meaning that var $ inside [ xxx $ left sequare bracket
401
+ # are a default if not suply from params but if it suply from params it
402
+ # will empty the default and relace var $ from the params
403
+ # 3. execute String.method if var $ in the left got ":", example
404
+ # inside hot file:
405
+ # >>td
406
+ # <td>:capitalize$0</td>
407
+ # --------------------
408
+ # function call: @td(col1;col2) # will result in
409
+ # --------------------
410
+ # <td>Col1</td>
411
+ # <td>Col2</td>
412
+ def get_dollar(prms,ends=nil) #prms='@0;@1;@2' from hot
413
+ @mem_var.each do |k,v| #;p "#{k}, #{v}"
414
+ prms.gsub!(k,v)
415
+ if k[0,1]=='*' and Regexp.new("~([^~]+)~#{k}".gsub('*','\\*')) =~ @new
416
+ @new.gsub!($~.to_s,(v!='' ? v : $1))
417
+ else
418
+ @new.gsub!(k,v)
419
+ end
420
+ end
421
+ prms = prms.split(';') #W2Tags::splitter(prms)
422
+ new_prms = @new.scan(/\$[0-9]/).uniq
423
+ new_alls = @new.scan(/\$\*/) #;p 'rpl:',new_alls,new_prms,prms
424
+ @new.gsub!($1,"<%= \"#{$2}\" %>") if /(==(\$[0-9]))/ =~ @new
425
+ @new.gsub!($1,"<%= #{$2} %>") if /(=(\$[0-9]))/ =~ @new
426
+ if /^@[0-9]$/ =~ prms[0]
427
+ rpl = prms.shift.gsub('@','$')
428
+ repeat = @new
429
+ repeat.gsub!('$0',prms.shift) #repeat.gsub!('$*',rpl)
430
+ @new = ''
431
+ prms.each_with_index do |x,i| #;p "$0 #{x} => #{repeat}"
432
+ @new += repeat.gsub(rpl,x)
433
+ if i+1<prms.size
434
+ @new += "\n"+@spc+ends.join("\n") if ends
435
+ @new += "\n"+@spc
436
+ end
437
+ end
438
+ elsif new_alls==[] && new_prms.size==1 && prms.size>1
439
+ tmp = ""
440
+ rpt = @rgx.to_s.gsub(@rgx[3]+"\n","")
441
+ prms.each_with_index do |x,i|
442
+ tmp<< rpt+x #tmp<< @new.gsub(new_prms[0],x)
443
+ tmp<< "\n#{@spc}" if i+1<prms.size
444
+ end
445
+ @new = tmp
446
+ else
447
+ i = new_prms.size - 1
448
+ new_prms.sort.reverse.each do |x|
449
+ opt_v = Regexp.new('~([^$|\n]*)\\'+x+'([^\|\n]*)~')
450
+ def_v = Regexp.new('~([^~]+)~\\'+x)
451
+ eva_v = Regexp.new('\\'+x+'.([^~$]+)~') #$1.upcase~
452
+ if opt_v =~ @new #;p $1
453
+ rpl = ''
454
+ rpl = "#{$1.to_s}#{prms[i]}#{$2.to_s}" if prms[i] && prms[i].strip!=""
455
+ @new.gsub!(opt_v,rpl)
456
+ #p "options: #{rpl} >> #{@new}"
457
+ elsif def_v =~ @new #;p $1
458
+ src = $~.to_s
459
+ rpl = (prms[i] && prms[i].strip!="" ? prms[i] : $1)
460
+ @new.gsub!(src,rpl)
461
+ #p "default: #{@new}"
462
+ end
463
+ while eva_v=~ "\n#{@new}" do
464
+ src = "#{x}.#{$1}~" ; #p "\n#{@new} => #{src}"
465
+ evl = "\"#{prms[i]}\".#{$1}"; #p "====> #{evl} <=="
466
+ rpl = prms[i] ? eval(evl).to_s : ""
467
+ @new.gsub!(src,rpl)
468
+ end
469
+ #p "rest: #{x} => #{prms[i].to_s}"
470
+ @new.gsub!(x,prms[i].to_s)
471
+ i = i -1
472
+ end
473
+ @new.gsub!(/\$\*/,prms[new_prms.size,99].to_a.join(';') )
474
+ @new.gsub!(/\n\t+$/,'') #remove line if only tabs
475
+ end
476
+ end
477
+
478
+ #pop up end tags from the stack
479
+ def multi_end2(ttls)
480
+ rpls = ''
481
+ ttl = @tg_end.size-1
482
+ ttl = ttls-1 if ttls
483
+ ttl.downto(0) do |i|
484
+ sz = @tg_end[i][/^ +/].to_s.size
485
+ if ttls || @spc.size <= sz
486
+ send = @tg_end.pop
487
+ if send.strip[0,5]=="!run!"
488
+ scrpt = send.gsub("\n","\n#{@spc}").split("\n")
489
+ @doc_src = scrpt[1,99]+@doc_src
490
+ else
491
+ spc = send[/(^[ \t]*)/,1].to_s
492
+ rpls << send.gsub(/\n/,"\n#{spc}") + "\n"
493
+ end
494
+ end
495
+ end
496
+ p "End2 : #{rpls.strip}" if @dbg[:parse] && rpls!= ''
497
+ rpls
498
+ end
499
+
500
+ #command execution "-key", internally parsed to "%_key~", so both command
501
+ #are the same except that command "-key" need to translate to "%_key~" and
502
+ #it goes to Hot files key definition to lookup to. some of these definition
503
+ # built in (for erb: %_if , %_elsif , %_else , %_end , ... etc)
504
+ # -if => %_if
505
+ # -li => %_li
506
+ def shortcut_exec(regex)
507
+ if(regex =~ @row;@rgx = $~)
508
+ srcs = @rgx.to_s
509
+ rplc = "#{@rgx[1]}%!_#{@rgx[2]}~ #{@rgx[3]}\n"
510
+ @row.gsub!(srcs,rplc)
511
+ p "reExe_ #{@row}" if @dbg[:parse]
512
+ end
513
+ end
514
+
515
+ #command execution "=", internally parsed to "%=~", so both command
516
+ #are the same except that command "=" need to translate to "%=~" and
517
+ #it goes to Hot files key definition to lookup to. you can redefine it.
518
+ def shortcut_equal(regex)
519
+ if(regex =~ @row;@rgx = $~)
520
+ srcs = @rgx.to_s
521
+ rplc = "#{@rgx[1]}%!=~#{@rgx[3]}\n"
522
+ @row.gsub!(srcs,rplc)
523
+ p "reEqu_ #{rplc}" if @dbg[:parse]
524
+ end
525
+ end
526
+
527
+ #this command is the selector from command
528
+ # %..key.. params1;paramsN \n
529
+ #ex:
530
+ # %div<space>params\n or %div<\n>.
531
+ #if key div fine in hot, it will translate to HOT tags, but if not
532
+ #it become w2tags
533
+ def get_hot_simple(regex)
534
+ if regex =~ @row ;@rgx = $~
535
+ chk1= @rgx[2][-1,1] + @rgx[3][0,2].to_s
536
+ chk2= @rgx[2][/"\}!/]
537
+ chk3= @rgx[2][/"\}~/]
538
+ # already become w2tags, ignore!!!
539
+ if (/[=\}][!~][ ]?/ !~ chk1 && chk2 == nil && chk3 == nil)
540
+ keys = @rgx[2].strip
541
+ opts = @rgx[3]
542
+ #p chk1
543
+ # FIX for:
544
+ # %form#dodol{action="<%= #{aaa} %>"} <%= #{bbb} %>
545
+ # <form id="dodol" action="<%= #{aaa} %>"><%= #{bbb}%></form>
546
+ # when wrong splitting, fix the splitting...
547
+ # assume last attribute don't have spaceses!!! ==>{opt="blah"}<==
548
+ fixd = keys.split('"} ')
549
+ if fixd.length>1
550
+ keys = fixd[0]+'"}'
551
+ opts = fixd[1]+opts
552
+ end
553
+
554
+ srcs = @rgx.captures.join
555
+ opts = $1 << opts if keys.gsub!(/(\/)$/,'')
556
+ hots = keys.gsub(/\{.*\}$/,'').gsub(/[:#.][\w\-#.=]*$/,'')
557
+ rplc = @tg_hot[hots]!=nil ?
558
+ "%!#{keys}~ #{opts}" :
559
+ "%!#{keys}! #{opts}"
560
+ @row.gsub!(srcs,rplc)
561
+ p "reHot> #{@row} << -H-O-T-" if @dbg[:parse]
562
+ end
563
+ end
564
+ end
565
+
566
+ #translation for tags with shortcut of name, id, or class and put in constants
567
+ # ex: %div:name#id.class{attribute}=
568
+ #will result in some of this var:
569
+ # @mem_var['$$' ] => :name#id.class{attribute}==
570
+ # @mem_var['$:' ] => :name
571
+ # @mem_var['$#' ] => #id
572
+ # @mem_var['$.' ] => .class
573
+ # @mem_var['$@' ] => {attribute}
574
+ # @mem_var['*:' ] => name
575
+ # @mem_var['*#' ] => id
576
+ # @mem_var['*.' ] => class
577
+ # @mem_var['*@' ] => attribute
578
+ # @mem_var['*all*' ] => name="name" id="id" class="class"
579
+ # @mem_var['*name*' ] => name="name"
580
+ # @mem_var['*id*' ] => id="id"
581
+ # @mem_var['*class*'] => class="class"
582
+ # this var will be use in parsing w2tags/hot command
583
+ def nameidclass_var()
584
+ #@key = keys = @rgx[2].strip.gsub(/(\{(.*)\})/,'') #greedy :)
585
+ @key = keys = @key.strip.gsub(/(\{(.*)\})/,'') #greedy :)
586
+ @att = $2.to_s.strip
587
+ @mem_var['$$' ]= ''
588
+ @mem_var['$&' ]= ''
589
+ @mem_var['$:' ]= ''
590
+ @mem_var['$#' ]= ''
591
+ @mem_var['$.' ]= ''
592
+ @mem_var['$@' ]= $1.to_s
593
+ @mem_var['*&' ]= ''
594
+ @mem_var['*:' ]= ''
595
+ @mem_var['*#' ]= ''
596
+ @mem_var['*.' ]= ''
597
+ @mem_var['*@' ]= @att=='' ? '' : @att+' '
598
+ @mem_var['*all*' ]= ''
599
+ @mem_var['*name*' ]= ''
600
+ @mem_var['*id*' ]= ''
601
+ @mem_var['*class*']= ''
602
+ @mem_var['*code*' ]= ''
603
+ #p keys
604
+ if @key.gsub!(/([&:#.=])([\/\t\w\-#.= ]*$)/,'')
605
+ keys = $1+$2
606
+ if keys.gsub!(/^&([\/\w\-.]*)/,'')
607
+ if $1!=''
608
+ @mem_var['$&' ] = "&#{$1}"
609
+ @mem_var['*&' ] = $1
610
+ @mem_var['$$' ]<< "&#{$1}"
611
+ end
612
+ end
613
+ if keys.gsub!(/^:([\w\-.]*)/,'')
614
+ if $1!=''
615
+ @mem_var['$:' ] = ":#{$1}"
616
+ @mem_var['*:' ] = $1
617
+ @mem_var['*name*' ] = "name=\"#{$1}\" "
618
+ @mem_var['*all*' ]<< "name=\"#{$1}\" "
619
+ @mem_var['$$' ]<< ":#{$1}"
620
+ end
621
+ end
622
+ if keys.gsub!(/^#([\w\-]*)/,'')
623
+ if $1!=''
624
+ @mem_var['$#' ] = "##{$1}"
625
+ @mem_var['*#' ] = $1
626
+ @mem_var['*id*' ] = "id=\"#{$1}\" "
627
+ @mem_var['*all*' ]<< "id=\"#{$1}\" "
628
+ @mem_var['$$' ]<< "##{$1}"
629
+ end
630
+ end
631
+ if keys.gsub!(/^\.([\w\-\.]*)/,'')
632
+ if $1!=''
633
+ cl = $1
634
+ cx = cl.split('.').collect {|x|x.strip}.join(' ')
635
+ @mem_var['$.' ] = ".#{cl}"
636
+ @mem_var['*.' ] = cl
637
+ @mem_var['*class*'] = "class=\"#{cx}\" "
638
+ @mem_var['*all*' ]<< "class=\"#{cx}\" "
639
+ @mem_var['$$' ]<< ".#{cl}"
640
+ end
641
+ end
642
+ @key << keys
643
+ end
644
+ @mem_var['$$' ] << @mem_var['$@']
645
+ @mem_var['*all*'] << @mem_var['*@']
646
+ @mem_var['*att*'] = @mem_var['*@']
647
+ if @key[0,1]!='='
648
+ if @key.gsub!(/==$/,'')
649
+ @mem_var['*code*'] = '<%= "$*" %>'
650
+ @mem_var['$$' ]<< "=="
651
+ elsif @key.gsub!(/=$/,'')
652
+ @mem_var['*code*'] = "<%= $* %>"
653
+ @mem_var['$$' ]<< "="
654
+ end
655
+ end
656
+ end
657
+
658
+ #these not really visible for end user, since user usualy see the command as
659
+ #a HAML like command and translate to this HOT files. the translation usually
660
+ #came from method in:
661
+ # shortcut_exec
662
+ # get_hot_simple
663
+ #format for this command is
664
+ # %...key...~..params1;paramsN..\n
665
+ def parse_hot
666
+ eva = ''
667
+ col = @row.split('%')
668
+ return false if col.size==1
669
+ (col.size-1).downto(0) do |c|
670
+ eva = "%#{col[c]}" << eva
671
+ @rg_hot.each do |ht|
672
+ if(ht =~ eva;@rgx = $~)
673
+ @key = @rgx[2]
674
+ prms = @rgx[3].to_s.strip
675
+ if /^\!/ =~ @key
676
+ @new = (multi_end2(nil)+@spc+@rgx.to_s.gsub('%!','%')).split("\n")
677
+ swap_last_empt_src_with_end_tg(@new)
678
+ @row = ''
679
+ else
680
+ nameidclass_var()
681
+ # Auto closing, see in "erb.hot": _elsif _else:
682
+ # when last doc out is <% end %> and hot command is %_elsif or %_else
683
+ # then remove the last doc out <% end %>
684
+ if @doc_out[-1] and @doc_out[-1].strip=='<% end %>'
685
+ @doc_out.pop if %w[else elsif].include? prms.split(' ')[0]
686
+ end
687
+ while prms[-1,1]=='\\' do #concenation line if params end with \
688
+ prms.gsub!(/\\$/,'') << @doc_src.shift.strip
689
+ end
690
+ @mem_var["$tag"] = @key
691
+ if @tg_hot[@key]
692
+ hots = @tg_hot[@key]
693
+ hots[1]='' if !hots[1] #remark if not error!
694
+ @new = hots[0].call(self).clone
695
+ if @new.strip=="" #&& @tg_end[-1]
696
+ @tg_end << "#{@spc}#{hots[1][0]}"
697
+ empt = @row.gsub!(@rgx.to_s,"").strip
698
+ @row = empt if empt == "" #remove if empty (only \t,\n)
699
+ else
700
+ @tg_end << "#{@spc}#{hots[1][0]}" if hots[1]
701
+ @new.gsub!(/( *~\^.*[^\n]+)/,"^~^~^")
702
+ setvar = $1 # don't parse SetMem ~^
703
+ @new.gsub!(/\n/,"\n#{@spc}")
704
+ get_dollar(prms,hots[1])
705
+ @new.gsub!(/\^~\^~\^/,setvar) if setvar #restore SetMem
706
+ srcs = @rgx.to_s
707
+ @doc_src = @row.gsub(srcs,@new).split("\n")+@doc_src
708
+ @row = @doc_src.shift+"\n"
709
+ parse_spc
710
+ end
711
+ p "Func>> #{@new}" if @dbg[:parse]
712
+ else
713
+ @row.gsub!(@rgx.to_s,"<!-- no hot for:#{@key} -->")
714
+ end
715
+ end
716
+ break
717
+ end
718
+ end
719
+ break if @rgx
720
+ end
721
+ @rgx!=nil
722
+ end
723
+
724
+ #internal use call from
725
+ # get_div
726
+ # get_input
727
+ def get_shortcut(regex,tag)
728
+ if(regex =~ @row;@rgx = $~)
729
+ src = @rgx.captures.join
730
+ keys= @rgx[1,2].join.strip
731
+ opts= @rgx[3].to_s
732
+ opts= $1 << opts if keys.gsub!(/(\/)$/,'')
733
+ #tgt = "%!#{tag}#{keys}!#{opts}"
734
+ tgt = "%#{tag}#{keys} #{opts}"
735
+ @row.gsub!(src,tgt)
736
+ p "to#{tag.capitalize[0,3]}: #{tgt}" if @dbg[:parse]
737
+ end
738
+ @rgx!=nil
739
+ end
740
+
741
+ #shortcut for
742
+ # "%...div...!params",
743
+ #and user no need to write
744
+ # "%div"
745
+ #if user supply the command with ID or CLASS.
746
+ # %div#key my key features
747
+ #same as:
748
+ # #key my key features
749
+ #
750
+ # %div.okey my key features
751
+ #same as:
752
+ # .okey my key features
753
+ def get_div( regex)
754
+ get_shortcut(regex,'div')
755
+ end
756
+
757
+ #shortcut for
758
+ # "%...input...!params",
759
+ #and user no need to write
760
+ # "%input"
761
+ #if user supply the command with NAME
762
+ # %input:wharsojo my key features
763
+ #same as:
764
+ # :wharsojo my key features
765
+ def get_input(regex)
766
+ get_shortcut(regex,'input')
767
+ end
768
+
769
+ #popup the closing tags when indentation are less than the previous.
770
+ def auto_close
771
+ if @tg_end.size>1
772
+ sz = @tg_end[-1][/^ +/].to_s.size
773
+ if @spc.size <= sz
774
+ ed = multi_end(nil).rstrip
775
+ p "AutE:#{ed}#{@row}" if @dbg[:parse]
776
+ @doc_out += [ed,@row]
777
+ @row = ''
778
+ true
779
+ end
780
+ end
781
+ end
782
+
783
+ #all regex for line will be parse in this methods return value of not nill
784
+ #will try to parse the line (@row) again, if finish parsing (return nil)
785
+ #it try to check the indentation to auto_close the line.
786
+ def parse_all
787
+ #check for skipping the block using add on module...
788
+ if @skiper.select{|f|send(f)}.length>0
789
+ p "skip > #{@row}" if @dbg[:parse]
790
+ else
791
+ @plt_opt= ''
792
+ #rtn= true if @selector.select{|f|send(f)}.length>0
793
+ rtn = true if shortcut_exec( /(^[\t ]*)\-([\w\-&\/:#.%]*\{.*\}[=]?) *([^\n]*)\n/)
794
+ rtn = true if shortcut_exec( /(^[\t ]*)\-([\w\-&\/:#.%=]*) *([^\n]*)\n/)
795
+ rtn = true if shortcut_equal( /(^[\t ]*)=([\w\-&\/:#.%=]*) *([^\n]*)\n/)
796
+
797
+ rtn = true if get_hot_simple(/^[\t ]*(%)([\$\w\-&\/:#.]+\{.*\}[= ]*)([^\n]*)\n/)
798
+ rtn = true if get_hot_simple(/^[\t ]*(%)([\$\w\-&\/:#.]+\{.*\}[= ]*)()\n/)
799
+ rtn = true if get_hot_simple(/^[\t ]*(%)([\$\w\-&\/:#.%=]+ )([^\n]*)\n/)
800
+ rtn = true if get_hot_simple(/^[\t ]*(%)([\$\w\-&\/:#.%=]+)()\n/)
801
+
802
+ rtn = true if get_div(/^[\t ]*([#.])([\w\-&\/.]*\{.*\}[= ]*)([^\n]*)\n/)
803
+ rtn = true if get_div(/^[\t ]*([#.])([\w\-&\/.]*\{.*\}[= ]*)()\n/)
804
+ rtn = true if get_div(/^[\t ]*([#.])([\w\-&\/.=]* )([^\n]*)\n/)
805
+ rtn = true if get_div(/^[\t ]*([#.])([\w\-&\/.=]*)()\n/)
806
+ rtn = true if get_input( /^[\t ]*(:)([\w\-&\/#.]*\{.*\}[= ]*)([^\n]*)\n/)
807
+ rtn = true if get_input( /^[\t ]*(:)([\w\-&\/#.]*\{.*\}[= ]*)()\n/)
808
+ rtn = true if get_input( /^[\t ]*(:)([\w\-&\/#.=]* )([^\n]*)\n/)
809
+ rtn = true if get_input( /^[\t ]*(:)([\w\-&\/#.=]*)()\n/)
810
+ rtn = true if parse_hot
811
+ rtn = true if merge_hot
812
+ rtn = true if merge_w2x
813
+ rtn = true if parse_set_var
814
+ rtn = true if parse_set_mem
815
+ rtn = true if parse_get_mem
816
+ rtn = true if inline_tag
817
+ rtn = true if parse_end
818
+ if parse_tags
819
+ rtn = nil
820
+ elsif !rtn
821
+ auto_close
822
+ end
823
+ end
824
+ rtn
825
+ end
826
+
827
+ #remember command "^", not really use but if you want less typing you can
828
+ #define this command inside HOT file for the next command to be execute like:
829
+ # HOT file:
830
+ # >>_tr
831
+ # ~^%td
832
+ #
833
+ # Source file:
834
+ # -tr
835
+ # ^ inside td
836
+ #I think its Ok.
837
+ def parse_set_mem
838
+ if @row.gsub!(/([ \t]*~\^)([^\n]+)(\n)/,'')
839
+ p "setMem ^ => #{$2+"\n"}" if @dbg[:parse]
840
+ @mem_tag["^"]= $2+"\n"
841
+ end
842
+ end
843
+
844
+ #call from parse_get_mem
845
+ def get_mem(regex)
846
+ if(regex =~ @row;@rgx = $~)
847
+ keys,tmp,prms,opt,ends= @rgx.captures
848
+ if opt=='!'
849
+ opt=''
850
+ @mem_hot=nil
851
+ end
852
+
853
+ @new = @mem_tag[keys].split(' ')
854
+ @new[0] << tmp
855
+ @new = @new.join(" ") << "\n"
856
+ get_dollar(prms)
857
+ rpl = @new #+opt.to_s+ends.to_s
858
+ p "stMem> #{rpl}" if @dbg[:parse]
859
+ @row.gsub!(@rgx.to_s,rpl)
860
+ rows = @row.split("\n")
861
+ if rows.size>1
862
+ @doc_src = rows+@doc_src
863
+ @row = @doc_src.shift+"\n"
864
+ end
865
+ end
866
+ @rgx!=nil
867
+ end
868
+
869
+ #remember command "^", not really use but if you want less typing you can
870
+ #define this command inside HOT file for the next command to be execute like:
871
+ # HOT file:
872
+ # >>_tr
873
+ # ~^%td
874
+ #
875
+ # Source file:
876
+ # -tr
877
+ # ^ inside td
878
+ #I think its Ok.
879
+ def parse_get_mem
880
+ get_mem(/([\^])([^ ]*) ([^\n]*)(\n)/)
881
+ end
882
+
883
+ #it call from parse_end
884
+ def get_end(regex)
885
+ if(regex =~ @row;@rgx = $~)
886
+ if @rgx[1]=='~'
887
+ @new = ''
888
+ @new = multi_end(1) if @tg_end.size>0
889
+ else
890
+ case @rgx[1]
891
+ when '!';@new = multi_end(nil)
892
+ when ',';@new = multi_end(@tg_end.size)
893
+ else ;@new = multi_end(@rgx[1].size)
894
+ end
895
+ end
896
+ @doc_src = @row.gsub(@rgx.to_s,@new).split("\n")+@doc_src
897
+ @row = ''
898
+ end
899
+ end
900
+
901
+ #user can popup the end tags using these folowing command:
902
+ # ,/ all end tags will be popup
903
+ # ~/ one or multi end tags will be popup (depend on how many ~ you write)
904
+ # !/ popup until the same indentation of "!/"
905
+ def parse_end
906
+ (get_end(/^(,)\/(\n)/) ? true : \
907
+ (get_end(/^[ \t]*(~+)\/(\n)/) ? true : \
908
+ get_end(/^[ \t]*(!)\/(\n)/)))
909
+ end
910
+
911
+ #parsing w2tags commands
912
+ def parse_tags
913
+ @rgx = nil
914
+ par = []
915
+ rgs = @rg_tag.collect {|r|par << (r =~ @row);$~}
916
+ if(max = par.compact.sort.pop) #have any to parse?
917
+ @rgx = rgs[par.index(max)]
918
+ @key = @rgx[2]
919
+ @txt = @rgx[3].strip
920
+
921
+ # when wrong splitting, fix the splitting...
922
+ # assume last attribute don't have spaceses!!! ==>{opt="blah"}<==
923
+ fixd = @key.split('"} ')
924
+ if fixd.length>1
925
+ @key = fixd[0]+'"}'
926
+ @txt = fixd[1]+@txt
927
+ end
928
+
929
+ if /^\!/ =~ @key
930
+ @new = (multi_end(nil)+@rgx.to_s.gsub('%!','%')).split("\n")
931
+ swap_last_empt_src_with_end_tg(@new)
932
+ @row = ''
933
+ p "W2Tag: try closing tag by indentation..." if @dbg[:parse]
934
+ return true
935
+ else
936
+ @mem_var["$tag"] = @key
937
+ nameidclass_var()
938
+ srcs = @rgx.to_s.gsub!(/^[ \t]*/,'')
939
+ tag_next = @tg_nex[@key] #;p "%mem_hot:#{@mem_hot}:#{@key}"
940
+ tag_next[1].call if tag_next && @mem_hot==nil
941
+ rplc = @tagr.call(self);
942
+ @mem_var.each do |k,v|
943
+ rplc.gsub!(k,v)
944
+ end
945
+ @row.gsub!(srcs,rplc)
946
+ end
947
+ p "W2Tag: #{@row}" if @dbg[:parse]
948
+ end
949
+ @rgx!=nil
950
+ end
951
+
952
+ #inline parsing
953
+ #I Like (%strong.bold{banana="boys"} (%i.italic cake%)%)!
954
+ #I Like <strong class="bold" banana="boys"><i class="italic">cake</i></strong>!
955
+ def inline_tag()
956
+ if(/\(%(.*?)%\)/ =~ @row;@rgx = $~)
957
+ src = $1.split(/\(%/)
958
+ txt = src.length>1 ? src.pop : src[0]
959
+ tmp = txt.lstrip.split(' ')
960
+ @key= tmp.shift
961
+ @txt= tmp.join(" ")
962
+ nameidclass_var()
963
+ @key.strip!
964
+ html= @mem_var["*code*"]
965
+ html= html=='' ? @txt : html.gsub("$*",@txt)
966
+ tags_created = "<#{@key}"
967
+ tags_created << " #{@mem_var["*all*"].strip}" if @mem_var["*all*"]!=''
968
+ tags_created << ">#{html}</#{@key}>"
969
+ @row.gsub!("(%#{txt}%)",tags_created)
970
+ p "InLin: #{@row}" if @dbg[:parse]
971
+ end
972
+ @rgx
973
+ end
974
+ end
975
+ end