PageTemplate 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/CVS/Entries +10 -0
  2. data/CVS/Repository +1 -0
  3. data/CVS/Root +1 -0
  4. data/Changes +13 -0
  5. data/Changes~ +7 -0
  6. data/InstalledFiles +7 -0
  7. data/README.txt +1 -1
  8. data/Rakefile +1 -1
  9. data/Rakefile~ +54 -0
  10. data/TC_PageTemplate.rb +137 -19
  11. data/TC_PageTemplate.rb~ +965 -0
  12. data/doc/classes/BlockCommand.html +1 -1
  13. data/doc/classes/BlockCommand.src/M000004.html +1 -1
  14. data/doc/classes/BlockCommand.src/M000005.html +1 -1
  15. data/doc/classes/BlockCommand.src/M000006.html +1 -1
  16. data/doc/classes/BlockCommand.src/M000007.html +1 -1
  17. data/doc/classes/BlockCommand.src/M000008.html +1 -1
  18. data/doc/classes/Command.html +10 -10
  19. data/doc/classes/Command.src/{M000029.html → M000032.html} +0 -0
  20. data/doc/classes/Command.src/{M000030.html → M000033.html} +0 -0
  21. data/doc/classes/CommentCommand.html +146 -0
  22. data/doc/classes/CommentCommand.src/M000009.html +18 -0
  23. data/doc/classes/IfCommand.html +15 -15
  24. data/doc/classes/IfCommand.src/{M000039.html → M000042.html} +1 -1
  25. data/doc/classes/IfCommand.src/{M000040.html → M000043.html} +1 -1
  26. data/doc/classes/IfCommand.src/{M000041.html → M000044.html} +1 -1
  27. data/doc/classes/IfElseCommand.html +15 -15
  28. data/doc/classes/IfElseCommand.src/M000025.html +5 -6
  29. data/doc/classes/IfElseCommand.src/{M000024.html → M000026.html} +1 -1
  30. data/doc/classes/IfElseCommand.src/M000027.html +20 -0
  31. data/doc/classes/IncludeCommand.html +16 -23
  32. data/doc/classes/IncludeCommand.src/M000019.html +12 -4
  33. data/doc/classes/IncludeCommand.src/{M000018.html → M000020.html} +10 -5
  34. data/doc/classes/IncludeCommand.src/M000021.html +18 -0
  35. data/doc/classes/IncludeCommandError.html +118 -0
  36. data/doc/classes/LoopCommand.src/M000001.html +1 -1
  37. data/doc/classes/LoopCommand.src/M000002.html +11 -2
  38. data/doc/classes/LoopCommand.src/M000003.html +1 -1
  39. data/doc/classes/LoopElseCommand.html +15 -15
  40. data/doc/classes/LoopElseCommand.src/M000022.html +5 -6
  41. data/doc/classes/LoopElseCommand.src/{M000021.html → M000023.html} +1 -1
  42. data/doc/classes/LoopElseCommand.src/M000024.html +20 -0
  43. data/doc/classes/Namespace.html +42 -42
  44. data/doc/classes/Namespace.src/M000034.html +5 -5
  45. data/doc/classes/Namespace.src/M000035.html +4 -22
  46. data/doc/classes/Namespace.src/M000036.html +4 -7
  47. data/doc/classes/Namespace.src/M000037.html +5 -4
  48. data/doc/classes/Namespace.src/M000038.html +22 -4
  49. data/doc/classes/Namespace.src/M000039.html +21 -0
  50. data/doc/classes/Namespace.src/M000040.html +18 -0
  51. data/doc/classes/Namespace.src/{M000031.html → M000041.html} +4 -5
  52. data/doc/classes/PageTemplate.html +72 -44
  53. data/doc/classes/PageTemplate.src/M000010.html +31 -11
  54. data/doc/classes/PageTemplate.src/M000011.html +4 -4
  55. data/doc/classes/PageTemplate.src/M000012.html +15 -4
  56. data/doc/classes/PageTemplate.src/M000013.html +4 -4
  57. data/doc/classes/PageTemplate.src/M000014.html +4 -4
  58. data/doc/classes/PageTemplate.src/M000015.html +4 -4
  59. data/doc/classes/PageTemplate.src/M000016.html +4 -5
  60. data/doc/classes/PageTemplate.src/M000017.html +18 -0
  61. data/doc/classes/PageTemplate.src/M000018.html +19 -0
  62. data/doc/classes/Syntax/CachedParser.html +10 -10
  63. data/doc/classes/Syntax/CachedParser.src/{M000045.html → M000048.html} +1 -1
  64. data/doc/classes/Syntax/CachedParser.src/{M000046.html → M000049.html} +2 -1
  65. data/doc/classes/Syntax/Glossary.html +16 -10
  66. data/doc/classes/Syntax/Glossary.src/{M000047.html → M000050.html} +1 -1
  67. data/doc/classes/Syntax/Glossary.src/{M000048.html → M000051.html} +1 -1
  68. data/doc/classes/Syntax/Parser.html +31 -31
  69. data/doc/classes/Syntax/Parser.src/M000052.html +6 -5
  70. data/doc/classes/Syntax/Parser.src/M000053.html +20 -37
  71. data/doc/classes/Syntax/Parser.src/M000054.html +4 -93
  72. data/doc/classes/Syntax/Parser.src/{M000049.html → M000055.html} +5 -6
  73. data/doc/classes/Syntax/Parser.src/M000056.html +53 -0
  74. data/doc/classes/Syntax/Parser.src/M000057.html +111 -0
  75. data/doc/classes/Syntax.html +1 -1
  76. data/doc/classes/TextCommand.html +15 -15
  77. data/doc/classes/TextCommand.src/{M000042.html → M000045.html} +1 -1
  78. data/doc/classes/TextCommand.src/{M000043.html → M000046.html} +1 -1
  79. data/doc/classes/TextCommand.src/{M000044.html → M000047.html} +1 -1
  80. data/doc/classes/UnlessCommand.html +151 -0
  81. data/doc/classes/UnlessCommand.src/M000028.html +20 -0
  82. data/doc/classes/ValueCommand.html +15 -15
  83. data/doc/classes/ValueCommand.src/{M000026.html → M000029.html} +1 -1
  84. data/doc/classes/ValueCommand.src/{M000027.html → M000030.html} +1 -1
  85. data/doc/classes/ValueCommand.src/{M000028.html → M000031.html} +1 -1
  86. data/doc/created.rid +1 -1
  87. data/doc/files/README_txt.html +2 -2
  88. data/doc/files/lib/PageTemplate_rb.html +1 -1
  89. data/doc/fr_class_index.html +3 -0
  90. data/doc/fr_method_index.html +52 -49
  91. data/lib/CVS/Entries +2 -0
  92. data/lib/CVS/Repository +1 -0
  93. data/lib/CVS/Root +1 -0
  94. data/lib/PageTemplate.rb +103 -26
  95. data/lib/PageTemplate.rb~ +1004 -0
  96. data/pkg/PageTemplate-1.2.0.gem +0 -0
  97. data/tdata/CVS/Entries +28 -0
  98. data/tdata/CVS/Repository +1 -0
  99. data/tdata/CVS/Root +1 -0
  100. data/tdata/cm.txt +3 -0
  101. data/tdata/include.4.nf.out.txt +2 -0
  102. data/tdata/metadata.1.txt +5 -0
  103. data/tdata/metadata.2.txt +5 -0
  104. data/tdata/metadata.3.txt +5 -0
  105. data/tdata/metadata.4.txt +5 -0
  106. data/tdata/p/CVS/Entries +5 -0
  107. data/tdata/p/CVS/Repository +1 -0
  108. data/tdata/p/CVS/Root +1 -0
  109. data/tdata/p/CVS/b2.txt,t +0 -0
  110. data/tdata/p/b2.txt +4 -0
  111. data/tdata/p/b2.txt~ +4 -0
  112. metadata +70 -32
  113. data/doc/classes/IfElseCommand.src/M000023.html +0 -19
  114. data/doc/classes/IncludeCommand.src/M000017.html +0 -21
  115. data/doc/classes/LoopElseCommand.src/M000020.html +0 -19
  116. data/doc/classes/Namespace.src/M000032.html +0 -18
  117. data/doc/classes/Namespace.src/M000033.html +0 -18
  118. data/doc/classes/PageTemplate.src/M000009.html +0 -46
  119. data/doc/classes/Syntax/Parser.src/M000050.html +0 -35
  120. data/doc/classes/Syntax/Parser.src/M000051.html +0 -18
  121. data/lib/MANIFEST +0 -2
  122. data/pkg/PageTemplate-1.1.2.gem +0 -0
@@ -20,60 +20,63 @@
20
20
  <div id="index">
21
21
  <h1 class="section-bar">Methods</h1>
22
22
  <div id="index-entries">
23
- <a href="classes/PageTemplate.html#M000014">[] (PageTemplate)</a><br />
24
- <a href="classes/Namespace.html#M000033">[] (Namespace)</a><br />
25
- <a href="classes/Namespace.html#M000032">[]= (Namespace)</a><br />
26
- <a href="classes/PageTemplate.html#M000013">[]= (PageTemplate)</a><br />
23
+ <a href="classes/Namespace.html#M000036">[] (Namespace)</a><br />
24
+ <a href="classes/PageTemplate.html#M000016">[] (PageTemplate)</a><br />
25
+ <a href="classes/Namespace.html#M000035">[]= (Namespace)</a><br />
26
+ <a href="classes/PageTemplate.html#M000015">[]= (PageTemplate)</a><br />
27
27
  <a href="classes/BlockCommand.html#M000007">add (BlockCommand)</a><br />
28
- <a href="classes/Syntax/Parser.html#M000050">build (Syntax::Parser)</a><br />
29
- <a href="classes/Syntax/CachedParser.html#M000046">build (Syntax::CachedParser)</a><br />
30
- <a href="classes/PageTemplate.html#M000016">clearFile (PageTemplate)</a><br />
31
- <a href="classes/Syntax/Parser.html#M000054">compile (Syntax::Parser)</a><br />
32
- <a href="classes/Namespace.html#M000035">get (Namespace)</a><br />
33
- <a href="classes/PageTemplate.html#M000012">getParameter (PageTemplate)</a><br />
28
+ <a href="classes/PageTemplate.html#M000011">add_path (PageTemplate)</a><br />
29
+ <a href="classes/Syntax/Parser.html#M000053">build (Syntax::Parser)</a><br />
30
+ <a href="classes/Syntax/CachedParser.html#M000049">build (Syntax::CachedParser)</a><br />
31
+ <a href="classes/PageTemplate.html#M000018">clearFile (PageTemplate)</a><br />
32
+ <a href="classes/Syntax/Parser.html#M000057">compile (Syntax::Parser)</a><br />
33
+ <a href="classes/Namespace.html#M000038">get (Namespace)</a><br />
34
+ <a href="classes/PageTemplate.html#M000014">getParameter (PageTemplate)</a><br />
34
35
  <a href="classes/BlockCommand.html#M000006">length (BlockCommand)</a><br />
35
- <a href="classes/PageTemplate.html#M000010">load (PageTemplate)</a><br />
36
- <a href="classes/Syntax/Glossary.html#M000048">lookup (Syntax::Glossary)</a><br />
37
- <a href="classes/TextCommand.html#M000042">new (TextCommand)</a><br />
38
- <a href="classes/PageTemplate.html#M000009">new (PageTemplate)</a><br />
39
- <a href="classes/IncludeCommand.html#M000017">new (IncludeCommand)</a><br />
40
- <a href="classes/Syntax/CachedParser.html#M000045">new (Syntax::CachedParser)</a><br />
41
- <a href="classes/IfCommand.html#M000039">new (IfCommand)</a><br />
42
- <a href="classes/LoopElseCommand.html#M000020">new (LoopElseCommand)</a><br />
43
- <a href="classes/Syntax/Glossary.html#M000047">new (Syntax::Glossary)</a><br />
44
- <a href="classes/BlockCommand.html#M000004">new (BlockCommand)</a><br />
45
- <a href="classes/IfElseCommand.html#M000023">new (IfElseCommand)</a><br />
46
- <a href="classes/Syntax/Parser.html#M000049">new (Syntax::Parser)</a><br />
47
- <a href="classes/Namespace.html#M000031">new (Namespace)</a><br />
48
- <a href="classes/ValueCommand.html#M000026">new (ValueCommand)</a><br />
36
+ <a href="classes/PageTemplate.html#M000012">load (PageTemplate)</a><br />
37
+ <a href="classes/Syntax/Glossary.html#M000051">lookup (Syntax::Glossary)</a><br />
38
+ <a href="classes/ValueCommand.html#M000029">new (ValueCommand)</a><br />
49
39
  <a href="classes/LoopCommand.html#M000001">new (LoopCommand)</a><br />
50
- <a href="classes/ValueCommand.html#M000027">output (ValueCommand)</a><br />
51
- <a href="classes/Command.html#M000029">output (Command)</a><br />
52
- <a href="classes/TextCommand.html#M000044">output (TextCommand)</a><br />
53
- <a href="classes/PageTemplate.html#M000015">output (PageTemplate)</a><br />
54
- <a href="classes/IfElseCommand.html#M000024">output (IfElseCommand)</a><br />
55
- <a href="classes/Syntax/Parser.html#M000051">output (Syntax::Parser)</a><br />
56
- <a href="classes/IncludeCommand.html#M000018">output (IncludeCommand)</a><br />
57
- <a href="classes/LoopElseCommand.html#M000021">output (LoopElseCommand)</a><br />
58
- <a href="classes/BlockCommand.html#M000008">output (BlockCommand)</a><br />
59
- <a href="classes/IfCommand.html#M000040">output (IfCommand)</a><br />
40
+ <a href="classes/PageTemplate.html#M000010">new (PageTemplate)</a><br />
41
+ <a href="classes/IncludeCommand.html#M000019">new (IncludeCommand)</a><br />
42
+ <a href="classes/TextCommand.html#M000045">new (TextCommand)</a><br />
43
+ <a href="classes/IfCommand.html#M000042">new (IfCommand)</a><br />
44
+ <a href="classes/LoopElseCommand.html#M000022">new (LoopElseCommand)</a><br />
45
+ <a href="classes/Namespace.html#M000034">new (Namespace)</a><br />
46
+ <a href="classes/Syntax/CachedParser.html#M000048">new (Syntax::CachedParser)</a><br />
47
+ <a href="classes/IfElseCommand.html#M000025">new (IfElseCommand)</a><br />
48
+ <a href="classes/BlockCommand.html#M000004">new (BlockCommand)</a><br />
49
+ <a href="classes/Syntax/Parser.html#M000052">new (Syntax::Parser)</a><br />
50
+ <a href="classes/Syntax/Glossary.html#M000050">new (Syntax::Glossary)</a><br />
51
+ <a href="classes/UnlessCommand.html#M000028">output (UnlessCommand)</a><br />
52
+ <a href="classes/ValueCommand.html#M000030">output (ValueCommand)</a><br />
53
+ <a href="classes/IfElseCommand.html#M000026">output (IfElseCommand)</a><br />
54
+ <a href="classes/Command.html#M000032">output (Command)</a><br />
60
55
  <a href="classes/LoopCommand.html#M000002">output (LoopCommand)</a><br />
61
- <a href="classes/Syntax/Parser.html#M000053">parse (Syntax::Parser)</a><br />
62
- <a href="classes/Namespace.html#M000038">pop (Namespace)</a><br />
63
- <a href="classes/Namespace.html#M000037">push (Namespace)</a><br />
64
- <a href="classes/Syntax/Parser.html#M000052">reset (Syntax::Parser)</a><br />
65
- <a href="classes/Namespace.html#M000034">set (Namespace)</a><br />
66
- <a href="classes/PageTemplate.html#M000011">setParameter (PageTemplate)</a><br />
67
- <a href="classes/IfCommand.html#M000041">to_s (IfCommand)</a><br />
68
- <a href="classes/TextCommand.html#M000043">to_s (TextCommand)</a><br />
69
- <a href="classes/IncludeCommand.html#M000019">to_s (IncludeCommand)</a><br />
70
- <a href="classes/BlockCommand.html#M000005">to_s (BlockCommand)</a><br />
56
+ <a href="classes/LoopElseCommand.html#M000023">output (LoopElseCommand)</a><br />
57
+ <a href="classes/CommentCommand.html#M000009">output (CommentCommand)</a><br />
58
+ <a href="classes/BlockCommand.html#M000008">output (BlockCommand)</a><br />
59
+ <a href="classes/Syntax/Parser.html#M000054">output (Syntax::Parser)</a><br />
60
+ <a href="classes/TextCommand.html#M000047">output (TextCommand)</a><br />
61
+ <a href="classes/IncludeCommand.html#M000020">output (IncludeCommand)</a><br />
62
+ <a href="classes/IfCommand.html#M000043">output (IfCommand)</a><br />
63
+ <a href="classes/PageTemplate.html#M000017">output (PageTemplate)</a><br />
64
+ <a href="classes/Syntax/Parser.html#M000056">parse (Syntax::Parser)</a><br />
65
+ <a href="classes/Namespace.html#M000041">pop (Namespace)</a><br />
66
+ <a href="classes/Namespace.html#M000040">push (Namespace)</a><br />
67
+ <a href="classes/Syntax/Parser.html#M000055">reset (Syntax::Parser)</a><br />
68
+ <a href="classes/Namespace.html#M000037">set (Namespace)</a><br />
69
+ <a href="classes/PageTemplate.html#M000013">setParameter (PageTemplate)</a><br />
70
+ <a href="classes/IfElseCommand.html#M000027">to_s (IfElseCommand)</a><br />
71
+ <a href="classes/ValueCommand.html#M000031">to_s (ValueCommand)</a><br />
72
+ <a href="classes/TextCommand.html#M000046">to_s (TextCommand)</a><br />
71
73
  <a href="classes/LoopCommand.html#M000003">to_s (LoopCommand)</a><br />
72
- <a href="classes/Command.html#M000030">to_s (Command)</a><br />
73
- <a href="classes/LoopElseCommand.html#M000022">to_s (LoopElseCommand)</a><br />
74
- <a href="classes/IfElseCommand.html#M000025">to_s (IfElseCommand)</a><br />
75
- <a href="classes/ValueCommand.html#M000028">to_s (ValueCommand)</a><br />
76
- <a href="classes/Namespace.html#M000036">true? (Namespace)</a><br />
74
+ <a href="classes/Command.html#M000033">to_s (Command)</a><br />
75
+ <a href="classes/IfCommand.html#M000044">to_s (IfCommand)</a><br />
76
+ <a href="classes/IncludeCommand.html#M000021">to_s (IncludeCommand)</a><br />
77
+ <a href="classes/BlockCommand.html#M000005">to_s (BlockCommand)</a><br />
78
+ <a href="classes/LoopElseCommand.html#M000024">to_s (LoopElseCommand)</a><br />
79
+ <a href="classes/Namespace.html#M000039">true? (Namespace)</a><br />
77
80
  </div>
78
81
  </div>
79
82
  </body>
data/lib/CVS/Entries ADDED
@@ -0,0 +1,2 @@
1
+ /PageTemplate.rb/1.14/Fri Mar 11 19:04:23 2005//
2
+ D
@@ -0,0 +1 @@
1
+ PageTemplate/lib
data/lib/CVS/Root ADDED
@@ -0,0 +1 @@
1
+ /home/wisti/CVS
data/lib/PageTemplate.rb CHANGED
@@ -55,11 +55,11 @@ class Namespace
55
55
 
56
56
  @nSpaces.reverse.each do |ns|
57
57
 
58
- if ns.class.method_defined?(":#{key}")
58
+ if ns.respond_to?(":#{key}")
59
59
  value = ns.send(":#{key}")
60
- elsif ns.class.method_defined?("#{key}")
60
+ elsif ns.respond_to?("#{key}")
61
61
  value = ns.send(key)
62
- elsif ns.class.method_defined?("[]")
62
+ elsif ns.respond_to?("[]")
63
63
  value = ns[key]
64
64
  end
65
65
 
@@ -117,6 +117,16 @@ class Command
117
117
  end
118
118
  end
119
119
 
120
+ # CommentCommand provides a mechanism for ignoring the contents
121
+ # of a block.
122
+ class CommentCommand < Command
123
+
124
+ def output(namespace = nil)
125
+ return nil
126
+ end
127
+
128
+ end
129
+
120
130
  # BlockCommand provides a single interface to multiple Command
121
131
  # objects.
122
132
  class BlockCommand < Command
@@ -237,6 +247,17 @@ class IfCommand < ValueCommand
237
247
  end
238
248
  end
239
249
 
250
+ # An UnlessCommand simplifies templates that need to use
251
+ # a Block only if a condition is false
252
+ class UnlessCommand < IfCommand
253
+ # If +namespace+ does not have a true value for this Command's flag, returns
254
+ # the output generated by the CommandBlock. Otherwise, returns nil.
255
+ def output(namespace)
256
+ unless namespace.true?(@value)
257
+ return @commands.output(namespace)
258
+ end
259
+ end
260
+ end
240
261
 
241
262
  # An IfCommand with an alternate BlockCommand to use if the
242
263
  # flag variable if false.
@@ -299,10 +320,19 @@ class LoopCommand < ValueCommand
299
320
 
300
321
  result = ""
301
322
 
302
- items.each do |item|
323
+ items.each_with_index do |item, index|
324
+ metavariables = Namespace.new()
325
+ metavariables['__FIRST__'] = true if index == 0
326
+ metavariables['__LAST__'] = true if index == items.length - 1
327
+ # Even-numbered index means an odd-numbered iteration.
328
+ # Gotta love zero-based indexes.
329
+ metavariables['__ODD__'] = true if index % 2 == 0
330
+
331
+ namespace.push(metavariables)
303
332
  namespace.push(item)
304
333
  result += @commands.output(namespace)
305
334
  namespace.pop()
335
+ namespace.pop()
306
336
  end
307
337
 
308
338
  return result
@@ -379,6 +409,8 @@ module Syntax
379
409
  # * ifopen
380
410
  # * ifclose
381
411
  # * ifbranch
412
+ # * unlessopen
413
+ # * unlessclose
382
414
  # * loopopen
383
415
  # * loopclose
384
416
  # * loopbranch
@@ -420,6 +452,7 @@ module Syntax
420
452
  def checkGlossary(glossary)
421
453
  %w[ value
422
454
  ifopen ifclose ifbranch
455
+ unlessopen unlessclose
423
456
  loopopen loopclose loopbranch
424
457
  ].each do |key|
425
458
  unless glossary.has_key?(key)
@@ -438,10 +471,13 @@ module Syntax
438
471
  # Here are the keys and patterns associated with Syntax::DEFAULT
439
472
 
440
473
  # * directive: /\[%(.+)%\]/
474
+ # * comment: /--.+?--/
441
475
  # * value: /var (\w+)/
442
476
  # * ifopen: /if (\w+)/
443
477
  # * ifclose: /endif/
444
478
  # * ifbranch: /else/
479
+ # * unlessopen: /unless (\w+)/
480
+ # * unlessclose: /endunless/
445
481
  # * loopopen: /in (\w+)/
446
482
  # * loopclose: /endin/
447
483
  # * loopbranch: /no/
@@ -456,9 +492,12 @@ module Syntax
456
492
 
457
493
  DEFAULT = Syntax::Glossary.new( /\[%(.+?)%\]/,
458
494
  'value' => /^\s*var (\w+)\s*$/,
495
+ 'comment' => /^\s*--.+?--\s*$/,
459
496
  'ifopen' => /^\s*if (\w+)\s*$/,
460
497
  'ifclose' => /^\s*endif\s*$/,
461
498
  'ifbranch' => /^\s*else\s*$/,
499
+ 'unlessopen' => /^\s*unless (\w+)\s*$/,
500
+ 'unlessclose'=> /^\s*endunless\s*$/,
462
501
  'loopopen' => /^\s*in (\w+)\s*$/,
463
502
  'loopclose' => /^\s*endin\s*$/,
464
503
  'loopbranch' => /^\s*no\s*$/,
@@ -483,6 +522,7 @@ module Syntax
483
522
 
484
523
  # Parse and compile a file containing PageTemplate directives.
485
524
  def build(filename)
525
+ filename.untaint
486
526
  if File.exists?(filename)
487
527
  file = File.new(filename)
488
528
  else
@@ -589,6 +629,8 @@ module Syntax
589
629
  command = ValueCommand.new(value)
590
630
  elsif directive == "include"
591
631
  command = IncludeCommand.new(value, @path)
632
+ elsif directive == "comment"
633
+ command = CommentCommand.new()
592
634
  elsif directive =~ /^(\w+?)open$/
593
635
  mainBlock = nil
594
636
  branchBlock = nil
@@ -613,7 +655,7 @@ module Syntax
613
655
  mainBlock = compile(mainLines)
614
656
  end
615
657
  else
616
- raise "#{@file}:#{line[0]} - " +
658
+ raise "#{filename}:#{line[0]} - " +
617
659
  "#{block} #{value} doesn't close"
618
660
  end
619
661
 
@@ -624,6 +666,8 @@ module Syntax
624
666
  elsif mainBlock
625
667
  command = IfCommand.new(value, mainBlock)
626
668
  end
669
+ elsif block == "unless"
670
+ command = UnlessCommand.new(value, mainBlock)
627
671
  elsif block == "loop"
628
672
  if mainBlock and branchBlock
629
673
  command = LoopElseCommand.new(value,
@@ -639,15 +683,15 @@ module Syntax
639
683
  # Skip to the line after the block closer.
640
684
  i = close
641
685
  elsif %Q[
642
- ifbranch ifclose loopbranch loopclose
686
+ ifbranch ifclose loopbranch loopclose unlessclose
643
687
  ].include?(directive)
644
- raise "#{@file}:#{line[0]} - #{directive}" +
688
+ raise "#{filename}:#{line[0]} - #{directive}" +
645
689
  " without corresponding opening directive"
646
690
  else
647
- raise "#{@file}:#{line[0]} - Unknown command #{directive}"
691
+ raise "#{filename}:#{line[0]} - Unknown command #{directive}"
648
692
  end
649
693
  else
650
- raise "#{@file}: Unknown instruction in line #{line}"
694
+ raise "#{filename}: Unknown instruction in line #{line}"
651
695
  end
652
696
 
653
697
  commands.add(command)
@@ -720,6 +764,7 @@ module Syntax
720
764
  saveCache = false
721
765
 
722
766
  # See if cache exists and is newer than source.
767
+ cacheFile.untaint
723
768
  if File.exists?(cacheFile)
724
769
  cacheStat = File.stat(cacheFile)
725
770
  if cacheStat.mtime > File.stat(filename).mtime
@@ -765,6 +810,7 @@ end
765
810
  # PageTemplate is the primary user Class for this package.
766
811
  class PageTemplate
767
812
  attr_reader :file, :syntax, :parser
813
+ attr_accessor :path
768
814
 
769
815
  # Creates a new PageTemplate object, using +args+ to provide
770
816
  # optional initialization.
@@ -772,7 +818,8 @@ class PageTemplate
772
818
  # ==== Possible Keys For Args
773
819
  #
774
820
  # [:include_path]
775
- # The directory that PageTemplate will look for template files in.
821
+ # Additional directories that PageTemplate will look for template files in.
822
+ # - May be a string or Array
776
823
  #
777
824
  # [:filename]
778
825
  # The name of a text file to use for a template.
@@ -798,10 +845,13 @@ class PageTemplate
798
845
  @syntax = Syntax::DEFAULT
799
846
  end
800
847
 
801
- if args['include_path']
802
- @path = args['include_path']
803
- else
804
- @path = Dir.getwd()
848
+ @path = [ Dir.getwd() ]
849
+ if pathInfo = args['include_path']
850
+ if pathInfo.class == Array
851
+ @path = @path + pathInfo
852
+ else
853
+ @path.push(pathInfo)
854
+ end
805
855
  end
806
856
 
807
857
  if args['use_cache']
@@ -818,6 +868,11 @@ class PageTemplate
818
868
  end
819
869
 
820
870
  end
871
+
872
+ # Add a path to the search path for loading includes.
873
+ def add_path(path)
874
+ @path.push(path)
875
+ end
821
876
 
822
877
  # Open +file+ and parse its contents so they will be ready
823
878
  # for template generation.
@@ -880,22 +935,36 @@ class PageTemplate
880
935
  end
881
936
 
882
937
  # IncludeCommand allows including text from external files.
938
+ class IncludeCommandError < RuntimeError
939
+ # Adding nothing, I just want the class name
940
+ end
941
+
883
942
  class IncludeCommand < Command
884
943
 
885
- def initialize(filename, path = Dir.getwd)
944
+ def initialize(filename, path = nil)
886
945
  super()
887
946
  @filename = filename
888
- @path = path
947
+ @path = [ Dir.getwd() ]
948
+
949
+ if path then
950
+ @path = @path + path
951
+ end
952
+
889
953
  @parser = Syntax::Parser.new(Syntax::DEFAULT, @path)
890
954
  end
891
955
 
892
956
  def output(ns=nil)
893
957
  # First check to see if the file exists in the current working directory
894
958
  # or as an absolute filename.
895
- file = determine_file(ns)
896
- text = File.open(file).read()
897
- @parser.build(file)
898
- @parser.output(ns)
959
+ text = ""
960
+ begin
961
+ file = determine_file(ns)
962
+ @parser.build(file)
963
+ text = @parser.output(ns)
964
+ rescue IncludeCommandError => error
965
+ text = error
966
+ end
967
+ return text
899
968
  end
900
969
 
901
970
  def to_s
@@ -904,17 +973,25 @@ class IncludeCommand < Command
904
973
 
905
974
  private
906
975
  def determine_file(ns)
907
- path = @path
976
+ file = nil
977
+
908
978
  if ns
909
979
  base = ns.get(@filename) || @filename
910
980
  else
911
981
  base = @filename
912
982
  end
913
- f = File.expand_path(File.join(path, base))
914
- if File.exists?(f)
915
- file = f
916
- else
917
- raise RuntimeError, "Cannot find #{base} in include path (#{path})"
983
+
984
+ @path.each do |p|
985
+ f = File.expand_path(File.join(p, base))
986
+ f.untaint
987
+ if File.exists?(f)
988
+ file = f
989
+ break
990
+ end
991
+ end
992
+
993
+ unless file
994
+ raise IncludeCommandError, "File #{base} not found."
918
995
  end
919
996
 
920
997
  return file