PageTemplate 1.1.2 → 1.2.0

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 (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