PageTemplate 2.1.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
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