PageTemplate 2.1.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Changes CHANGED
@@ -1,3 +1,15 @@
1
+ CVS:
2
+ Bugfixes:
3
+ 'else' no longer crashes with CaseCommand. Patch by Jeremy Apthorp
4
+ Wrong regexp for modifier in parser.rb fixed. Report by anonymous.
5
+ modifiers are correctly reset when coming out of StackableCommands.
6
+ (report by Jeremy Apthorp)
7
+ Parser:
8
+ Added: Caching capability. If a Source returns a Command, it is used
9
+ instead of trying to compile it. After every compile,
10
+ Source#cache(filename,cmds) is called.
11
+ FileSource has caching, now.
12
+
1
13
  2.1
2
14
  Commands:
3
15
  Changed: IfCommand now accepts elseif, elsif, else if.
data/Rakefile CHANGED
@@ -54,7 +54,7 @@ end
54
54
 
55
55
  spec = Gem::Specification.new do |s|
56
56
  s.name = "PageTemplate"
57
- s.version = "2.1.0"
57
+ s.version = "2.1.1"
58
58
  s.author = "Brian Wisti"
59
59
  s.email = "brianwisti@rubyforge.org"
60
60
  s.homepage = "http://coolnamehere.com/products/pagetemplate"
@@ -67,7 +67,7 @@ class PageTemplate
67
67
  DefaultGlossary.define(/^case (\w+(?:\.\w+)*)$/) { |match,parser|
68
68
  CaseCommand.new(match[1])
69
69
  }
70
- if PageTemplate.constants.include? 'HTGlossary'
70
+ if PageTemplate.constants.include?('HTGlossary')
71
71
  HTGlossary.define(/^tmpl_case (?:NAME=)?(\w+(?:\.\w+\?)*)$/) { |m,parser|
72
72
  CaseCommand.new(m[1])
73
73
  }
@@ -485,15 +485,20 @@ class PageTemplate
485
485
  # We don't use parser.compile because we need to know when something
486
486
  # doesn't exist.
487
487
  parser = namespace.parser
488
- body = parser.source.get(@value)
488
+ fn = @value
489
+ body = parser.source.get(fn)
489
490
  unless body
490
491
  fn = namespace.get(@value)
491
492
  body = parser.source.get(fn) if fn
492
493
  end
493
- if body
494
- parser.parse(body).output(namespace)
494
+ if body.is_a?(Command)
495
+ body.output(namespace)
496
+ elsif body
497
+ cmds = parser.parse(body)
498
+ parser.source.cache(fn,cmds)
499
+ cmds.output(namespace)
495
500
  else
496
- "[ Template '#{fn || @value}' not found ]"
501
+ "[ Template '#{fn}' not found ]"
497
502
  end
498
503
  end
499
504
  end
@@ -170,22 +170,34 @@ class PageTemplate
170
170
  @paths = @args['include_paths']
171
171
  @paths ||= [@args['include_path']].compact
172
172
  @paths = [Dir.getwd,'/'] if @paths.empty?
173
+ @cache = Hash.new(nil)
174
+ @mtime = Hash.new(0)
173
175
  end
174
176
 
175
177
  # Return the contents of the file +name+, which must be within the
176
178
  # include_paths.
177
179
  def get(name)
180
+ fn = get_filename(name)
178
181
  begin
179
- fn = get_filename(name)
180
- if fn
181
- return IO.read(fn)
182
+ case
183
+ when fn.nil?
184
+ nil
185
+ when @cache.has_key?(fn) && (@mtime[fn] > File.mtime(fn).to_i)
186
+ cmds = @cache[fn]
187
+ cmds.clear_cache
188
+ cmds
182
189
  else
183
- return nil
190
+ IO.read(fn)
184
191
  end
185
192
  rescue Exception => er
186
- return "[ Unable to open file #{fn} ]"
193
+ return "[ Unable to open file #{fn} because of #{er.message} ]"
187
194
  end
188
195
  end
196
+ def cache(name,cmds)
197
+ fn = get_filename(name)
198
+ @cache[fn] = cmds.dup
199
+ @mtime[fn] = Time.now.to_i
200
+ end
189
201
  def get_filename(file)
190
202
  file = file.gsub(/\.\.\//,'')
191
203
  file.untaint
@@ -301,7 +313,7 @@ class PageTemplate
301
313
  # Command#else's expect only to be called
302
314
  modifier(:else) { |cmd,command|
303
315
  case command
304
- when /^else|no|empty$/i
316
+ when /^(else|no|empty)$/i
305
317
  cmd.else
306
318
  true
307
319
  else
@@ -341,7 +353,7 @@ class PageTemplate
341
353
  cmd.when($1)
342
354
  true
343
355
  when /^else$/i
344
- cmd.else($1)
356
+ cmd.else
345
357
  true
346
358
  else
347
359
  false
@@ -353,34 +365,41 @@ class PageTemplate
353
365
  # A preprocessor is used to process or otherwise prepare output for
354
366
  # printing by Valuecommand
355
367
  #
356
- # Preprocessors must be singletons, and take a string to convert in
357
- # some form.
368
+ # Preprocessors must be objects, that take a string to convert in
369
+ # some form. Typically singletons.
358
370
  class Preprocessor
359
371
  end
360
372
 
361
- # DefaultPreprocessor is a preprocessor with simple processors.
362
- class DefaultPreprocessor < Preprocessor
363
- # Just the string itself.
364
- def DefaultPreprocessor.process(str)
365
- str
366
- end
367
- # Reverse the string. (Just to demonstrate preprocessor)
368
- def DefaultPreprocessor.reverse(str)
369
- str.reverse
370
- end
371
- # HTML's escapeURI
372
- def DefaultPreprocessor.escapeURI(string)
373
- string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do
373
+ class DefaultPreprocessor
374
+ class << self
375
+ # Default, unescaped string.
376
+ def unescaped(str)
377
+ str
378
+ end
379
+ # :process, for backwards compatability.
380
+ alias_method :process, :unescaped
381
+ # Reverse the string. Don't see any use for this :D.
382
+ def reverse(str)
383
+ str.reverse
384
+ end
385
+ # escape URIs into %20-style escapes.
386
+ def escapeURI(string)
387
+ string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do
374
388
  '%' + $1.unpack('H2' * $1.size).join('%').upcase
375
- end.tr(' ','+')
376
- end
377
- # escape HTML.
378
- def DefaultPreprocessor.escapeHTML(string)
379
- str = string.gsub(/&/n, '&amp;')
380
- str.gsub!(/\"/n, '&quot;')
381
- str.gsub!(/>/n, '&gt;')
382
- str.gsub!(/</n, '&lt;')
383
- str
389
+ end.tr(' ', '+')
390
+ end
391
+ # Escape all HTML
392
+ def escapeHTML(string)
393
+ str = string.gsub(/&/n, '&amp;')
394
+ str.gsub!(/\"/n, '&quot;')
395
+ str.gsub!(/>/n, '&gt;')
396
+ str.gsub!(/</n, '&lt;')
397
+ str
398
+ end
399
+ # Escape HTML, but also turn newlines into <br />s
400
+ def simple(str)
401
+ escapeHTML(str).gsub(/\r\n|\n/,"<br />\n")
402
+ end
384
403
  end
385
404
  end
386
405
 
@@ -431,7 +450,7 @@ class PageTemplate
431
450
  @parent = args['namespace'] || nil
432
451
  @glossary = args['glossary'] || DefaultGlossary
433
452
  @preprocessor = args['preprocessor'] || DefaultPreprocessor
434
- @default_processor = args['default_processor'] || :process
453
+ @default_processor = args['default_processor'] || :unescaped
435
454
  @source = (args['source'] || FileSource).new(@args)
436
455
  @commands = nil
437
456
  end
@@ -443,10 +462,17 @@ class PageTemplate
443
462
  # Load +name+ from a template, but do not save it.
444
463
  def compile(name)
445
464
  body = @source.get(name)
446
- if body
447
- parse(body)
465
+ case
466
+ when body.is_a?(Command)
467
+ body
468
+ when body
469
+ cmds = parse(body)
470
+ @source.cache(name,cmds) if @source.respond_to?(:cache)
471
+ cmds
448
472
  else
449
- TextCommand.new("[ Template '#{name}' not found ]")
473
+ cmds = Template.new(self)
474
+ cmds.add TextCommand.new("[ Template '#{name}' not found ]")
475
+ cmds
450
476
  end
451
477
  end
452
478
  # Compile a Template (BlockCommand) from a string. Does not save
@@ -478,6 +504,8 @@ class PageTemplate
478
504
  cmd = stack.pop
479
505
  last = stack.last
480
506
  last.add(cmd)
507
+ modifier = last.class.modifier
508
+ closer = last.class.closer
481
509
  next
482
510
  end
483
511
 
data/lib/PageTemplate.rb CHANGED
@@ -21,6 +21,7 @@
21
21
  ############################################################
22
22
 
23
23
  require 'PageTemplate/parser'
24
+ require 'PageTemplate/preprocessor'
24
25
  require 'PageTemplate/commands'
25
26
 
26
27
  # PageTemplate is just the namespace for all of its real code, so as
data/test.rb CHANGED
@@ -508,6 +508,20 @@ module TestPageTemplate
508
508
  assert_equal(true, @@ns.true?("dude"),
509
509
  "If a flag is set to pretty much anything but false, then Namespace#true? returns true.")
510
510
  end
511
+ class Foo
512
+ def initialize(str)
513
+ @str = str
514
+ end
515
+ def bar
516
+ @str
517
+ end
518
+ end
519
+ def test_deep_true_eh
520
+ @@ns['foo'] = Foo.new('fizbit')
521
+ assert(@@ns.true?('foo.bar'),"foo.bar must be true")
522
+ assert(@@ns.true?('foo.bar.reverse'))
523
+ assert_equal(@@ns.get('foo.bar.reverse'),'tibzif')
524
+ end
511
525
  end
512
526
 
513
527
  class TestParser < Test::Unit::TestCase
@@ -536,7 +550,7 @@ module TestPageTemplate
536
550
  end
537
551
 
538
552
  def test_default_processor
539
- assert_equal(:process, @@p.default_processor)
553
+ assert_equal(:unescaped, @@p.default_processor)
540
554
  end
541
555
 
542
556
  def test_load
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.8
2
+ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: PageTemplate
5
5
  version: !ruby/object:Gem::Version
6
- version: 2.1.0
7
- date: 2005-05-01
6
+ version: 2.1.1
7
+ date: 2005-07-30 00:00:00 -07:00
8
8
  summary: A simple templating system for Web sites.
9
9
  require_paths:
10
10
  - lib
@@ -24,25 +24,27 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
24
24
  version: 0.0.0
25
25
  version:
26
26
  platform: ruby
27
+ signing_key:
28
+ cert_chain:
27
29
  authors:
28
30
  - Brian Wisti
29
31
  files:
30
- - README.txt
31
- - setup.rb
32
- - MANIFEST
33
- - lib
34
- - Changes
35
- - setup-usage.txt
36
32
  - test-install.rb
33
+ - test.rb
34
+ - setup-usage.txt
35
+ - Changes
36
+ - MANIFEST
37
+ - setup.rb
38
+ - README.txt
37
39
  - Rakefile
40
+ - lib
38
41
  - tdata
39
- - test.rb
40
- - lib/PageTemplate.rb
41
42
  - lib/PageTemplate
42
- - lib/PageTemplate/parser.rb
43
+ - lib/PageTemplate.rb
43
44
  - lib/PageTemplate/case.rb
44
45
  - lib/PageTemplate/commands.rb
45
46
  - lib/PageTemplate/htglossary.rb
47
+ - lib/PageTemplate/parser.rb
46
48
  - tdata/dummy.txt
47
49
  test_files:
48
50
  - test.rb