bryanlarsen-rubydoctest 1.0.2
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/History.txt +24 -0
- data/License.txt +19 -0
- data/Manifest.txt +38 -0
- data/PostInstall.txt +7 -0
- data/README.txt +100 -0
- data/Rakefile +4 -0
- data/bin/rubydoctest +82 -0
- data/config/hoe.rb +72 -0
- data/config/requirements.rb +15 -0
- data/lib/code_block.rb +68 -0
- data/lib/doctest_require.rb +3 -0
- data/lib/lines.rb +143 -0
- data/lib/result.rb +63 -0
- data/lib/rubydoctest.rb +29 -0
- data/lib/rubydoctest/version.rb +9 -0
- data/lib/runner.rb +414 -0
- data/lib/special_directive.rb +54 -0
- data/lib/statement.rb +81 -0
- data/lib/test.rb +29 -0
- data/rubydoctest.gemspec +72 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/rstakeout +92 -0
- data/script/txt2html +82 -0
- data/setup.rb +1585 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/doctests.rake +30 -0
- data/tasks/environment.rake +7 -0
- data/tasks/website.rake +17 -0
- data/textmate/DocTest (Markdown).textmate +7 -0
- data/textmate/DocTest (Ruby).textmate +65 -0
- data/textmate/DocTest (Text).textmate +66 -0
- data/website/index.html +94 -0
- data/website/index.txt +37 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +138 -0
- data/website/template.html.erb +48 -0
- metadata +106 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'lines'
|
5
|
+
|
6
|
+
module RubyDocTest
|
7
|
+
class SpecialDirective < Lines
|
8
|
+
NAMES = ["doctest:", "it:", "!!!", "doctest_require:"]
|
9
|
+
NAMES_FOR_RX = NAMES.map{ |n| Regexp.escape(n) }.join("|")
|
10
|
+
|
11
|
+
# === Test
|
12
|
+
#
|
13
|
+
# doctest: The name of the directive should be detected in the first line
|
14
|
+
# >> s = RubyDocTest::SpecialDirective.new(["doctest: Testing Stuff", "Other Stuff"])
|
15
|
+
# >> s.name
|
16
|
+
# => "doctest:"
|
17
|
+
#
|
18
|
+
# doctest: "it:" is a valid directive
|
19
|
+
# >> s = RubyDocTest::SpecialDirective.new(["it: should test stuff"])
|
20
|
+
# >> s.name
|
21
|
+
# => "it:"
|
22
|
+
def name
|
23
|
+
if m = lines.first.match(/^#{Regexp.escape(indentation)}(#{NAMES_FOR_RX})/)
|
24
|
+
m[1]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# === Test
|
29
|
+
#
|
30
|
+
# doctest: The value of the directive should be detected in the first line
|
31
|
+
# >> s = RubyDocTest::SpecialDirective.new(["doctest: Testing Stuff", "Other Stuff"])
|
32
|
+
# >> s.value
|
33
|
+
# => "Testing Stuff"
|
34
|
+
#
|
35
|
+
# >> s = RubyDocTest::SpecialDirective.new([" # doctest: Testing Stuff", " # Other Stuff"])
|
36
|
+
# >> s.value
|
37
|
+
# => "Testing Stuff"
|
38
|
+
#
|
39
|
+
# doctest: Multiple lines for the directive value should work as well
|
40
|
+
# >> s = RubyDocTest::SpecialDirective.new(["doctest: Testing Stuff", " On Two Lines"])
|
41
|
+
# >> s.value
|
42
|
+
# => "Testing Stuff\nOn Two Lines"
|
43
|
+
#
|
44
|
+
# doctest: "it" should also work as a directive
|
45
|
+
# >> s = RubyDocTest::SpecialDirective.new(["it: should do something"])
|
46
|
+
# >> s.value
|
47
|
+
# => "should do something"
|
48
|
+
def value
|
49
|
+
if m = lines.join("\n").match(/^#{Regexp.escape(indentation)}(#{NAMES_FOR_RX})(.*)/m)
|
50
|
+
m[2].strip
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/statement.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'rubydoctest'
|
5
|
+
require 'lines'
|
6
|
+
|
7
|
+
module RubyDocTest
|
8
|
+
class EvaluationError < Exception
|
9
|
+
attr_reader :statement, :original_exception
|
10
|
+
def initialize(statement, original_exception)
|
11
|
+
@statement, @original_exception = statement, original_exception
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Statement < Lines
|
16
|
+
|
17
|
+
attr_reader :actual_result
|
18
|
+
|
19
|
+
# === Tests
|
20
|
+
#
|
21
|
+
# doctest: The FILENAME ruby constant should be replaced by the name of the file
|
22
|
+
# >> __FILE__[/statement\.rb$/]
|
23
|
+
# => "statement.rb"
|
24
|
+
def initialize(doc_lines, line_index = 0, file_name = nil)
|
25
|
+
@file_name = file_name
|
26
|
+
super(doc_lines, line_index)
|
27
|
+
end
|
28
|
+
|
29
|
+
# === Tests
|
30
|
+
#
|
31
|
+
# doctest: A statement should parse out a '>>' irb prompt
|
32
|
+
# >> s = RubyDocTest::Statement.new([">> a = 1"])
|
33
|
+
# >> s.source_code
|
34
|
+
# => "a = 1"
|
35
|
+
#
|
36
|
+
# doctest: More than one line should get included, if indentation so indicates
|
37
|
+
# >> s = RubyDocTest::Statement.new([">> b = 1 +", " 1", "not part of the statement"])
|
38
|
+
# >> s.source_code
|
39
|
+
# => "b = 1 +\n1"
|
40
|
+
#
|
41
|
+
# doctest: Lines indented by ?> should have the ?> removed.
|
42
|
+
# >> s = RubyDocTest::Statement.new([">> b = 1 +", "?> 1"])
|
43
|
+
# >> s.source_code
|
44
|
+
# => "b = 1 +\n1"
|
45
|
+
def source_code
|
46
|
+
lines.first =~ /^#{Regexp.escape(indentation)}>>\s(.*)$/
|
47
|
+
first = [$1]
|
48
|
+
remaining = (lines[1..-1] || [])
|
49
|
+
(first + remaining).join("\n")
|
50
|
+
end
|
51
|
+
|
52
|
+
# === Test
|
53
|
+
#
|
54
|
+
# doctest: Evaluating a multi-line statement should be ok
|
55
|
+
# >> s = RubyDocTest::Statement.new([">> b = 1 +", " 1", "not part of the statement"])
|
56
|
+
# >> s.evaluate
|
57
|
+
# => 2
|
58
|
+
#
|
59
|
+
# doctest: Evaluating a syntax error should raise an EvaluationError
|
60
|
+
# >> s = RubyDocTest::Statement.new([">> b = 1 +"])
|
61
|
+
# >> begin s.evaluate; :fail; rescue RubyDocTest::EvaluationError; :ok end
|
62
|
+
# => :ok
|
63
|
+
def evaluate
|
64
|
+
sc = source_code.gsub("__FILE__", @file_name.inspect)
|
65
|
+
if RubyDocTest.verbose
|
66
|
+
puts "EVAL: #{sc}"
|
67
|
+
end
|
68
|
+
@actual_result = eval(sc, TOPLEVEL_BINDING, __FILE__, __LINE__)
|
69
|
+
if RubyDocTest.verbose
|
70
|
+
puts "RESULT: #{@actual_result}"
|
71
|
+
end
|
72
|
+
@actual_result
|
73
|
+
rescue Exception => e
|
74
|
+
if RubyDocTest.trace
|
75
|
+
raise e.class, e.to_s + "\n" + e.backtrace.first
|
76
|
+
else
|
77
|
+
raise EvaluationError.new(self, e)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/test.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module RubyDocTest
|
2
|
+
# This is the top-level 'test' container that holds an optional description and one
|
3
|
+
# or more CodeBlock objects.
|
4
|
+
class Test
|
5
|
+
attr_accessor :description
|
6
|
+
attr_reader :code_blocks, :passed
|
7
|
+
|
8
|
+
def initialize(description, code_blocks)
|
9
|
+
@description, @code_blocks = description, code_blocks
|
10
|
+
end
|
11
|
+
|
12
|
+
def pass?
|
13
|
+
@passed = @code_blocks.all?{ |c| c.pass? }
|
14
|
+
end
|
15
|
+
|
16
|
+
def first_failed
|
17
|
+
@code_blocks.detect{ |cb| !cb.pass? }
|
18
|
+
end
|
19
|
+
|
20
|
+
def actual_result
|
21
|
+
first_failed.actual_result.inspect
|
22
|
+
end
|
23
|
+
|
24
|
+
def expected_result
|
25
|
+
first_failed.expected_result
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/rubydoctest.gemspec
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "rubydoctest"
|
3
|
+
s.version = "1.0.2"
|
4
|
+
|
5
|
+
s.specification_version = 2 if s.respond_to? :specification_version=
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Duane Johnson", "Tom Locke", "Dr Nic Williams"]
|
9
|
+
s.date = "2008-12-06"
|
10
|
+
s.default_executable = "rubydoctest"
|
11
|
+
s.description = "Ruby version of Python's doctest tool, but a bit different."
|
12
|
+
s.email = ["duane.johnson@gmail.com"]
|
13
|
+
s.executables = ["rubydoctest"]
|
14
|
+
s.extra_rdoc_files = ["History.txt", "License.txt", "Manifest.txt", "PostInstall.txt", "README.txt", "website/index.txt"]
|
15
|
+
manifest = <<-MANIFEST
|
16
|
+
History.txt
|
17
|
+
License.txt
|
18
|
+
Manifest.txt
|
19
|
+
PostInstall.txt
|
20
|
+
README.txt
|
21
|
+
Rakefile
|
22
|
+
bin/rubydoctest
|
23
|
+
config/hoe.rb
|
24
|
+
config/requirements.rb
|
25
|
+
lib/code_block.rb
|
26
|
+
lib/doctest_require.rb
|
27
|
+
lib/lines.rb
|
28
|
+
lib/result.rb
|
29
|
+
lib/rubydoctest.rb
|
30
|
+
lib/rubydoctest/version.rb
|
31
|
+
lib/runner.rb
|
32
|
+
lib/special_directive.rb
|
33
|
+
lib/statement.rb
|
34
|
+
lib/test.rb
|
35
|
+
rubydoctest.gemspec
|
36
|
+
script/console
|
37
|
+
script/destroy
|
38
|
+
script/generate
|
39
|
+
script/rstakeout
|
40
|
+
script/txt2html
|
41
|
+
setup.rb
|
42
|
+
tasks/deployment.rake
|
43
|
+
tasks/doctests.rake
|
44
|
+
tasks/environment.rake
|
45
|
+
tasks/website.rake
|
46
|
+
textmate/DocTest (Markdown).textmate
|
47
|
+
textmate/DocTest (Ruby).textmate
|
48
|
+
textmate/DocTest (Text).textmate
|
49
|
+
website/index.html
|
50
|
+
website/index.txt
|
51
|
+
website/javascripts/rounded_corners_lite.inc.js
|
52
|
+
website/stylesheets/screen.css
|
53
|
+
website/template.html.erb
|
54
|
+
MANIFEST
|
55
|
+
s.files = manifest.strip.split("\n").map{|m| m.strip}
|
56
|
+
s.has_rdoc = true
|
57
|
+
s.homepage = %q{http://rubydoctest.rubyforge.org}
|
58
|
+
s.post_install_message = %q{
|
59
|
+
rubydoctest comes as an executable that takes a file or directory:
|
60
|
+
|
61
|
+
rubydoctest .
|
62
|
+
rubydoctest simple.doctest
|
63
|
+
|
64
|
+
|
65
|
+
}
|
66
|
+
s.rdoc_options = ["--main", "README.txt"]
|
67
|
+
s.require_paths = ["lib"]
|
68
|
+
s.rubyforge_project = %q{rubydoctest}
|
69
|
+
s.rubygems_version = %q{1.1.1}
|
70
|
+
s.summary = %q{Ruby version of Python's doctest tool, but a bit different.}
|
71
|
+
s.test_files = []
|
72
|
+
end
|
data/script/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: script/console
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
+
|
5
|
+
libs = " -r irb/completion"
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/rubydoctest.rb'}"
|
9
|
+
puts "Loading rubydoctest gem"
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
data/script/rstakeout
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
##
|
4
|
+
# Originally by Mike Clark.
|
5
|
+
#
|
6
|
+
# From http://www.pragmaticautomation.com/cgi-bin/pragauto.cgi/Monitor/StakingOutFileChanges.rdoc
|
7
|
+
#
|
8
|
+
# Runs a user-defined command when files are modified.
|
9
|
+
#
|
10
|
+
# Like autotest, but more customizable. This is useful when you want to do
|
11
|
+
# something other than run tests. For example, generate a PDF book, run
|
12
|
+
# a single test, or run a legacy Test::Unit suite in an app that also
|
13
|
+
# has an rSpec suite.
|
14
|
+
#
|
15
|
+
# Can use Ruby's Dir[] to get file glob. Quote your args to take advantage of this.
|
16
|
+
#
|
17
|
+
# rstakeout 'rake test:recent' **/*.rb
|
18
|
+
# => Only watches Ruby files one directory down (no quotes)
|
19
|
+
#
|
20
|
+
# rstakeout 'rake test:recent' '**/*.rb'
|
21
|
+
# => Watches all Ruby files in all directories and subdirectories
|
22
|
+
#
|
23
|
+
# Modified (with permission) by Geoffrey Grosenbach to call growlnotify for
|
24
|
+
# rspec and Test::Unit output.
|
25
|
+
#
|
26
|
+
# See the PeepCode screencast on rSpec or other blog articles for instructions on
|
27
|
+
# setting up growlnotify.
|
28
|
+
|
29
|
+
def growl(title, msg, img, pri=0, sticky="")
|
30
|
+
system "growlnotify -n autotest --image ~/.autotest_images/#{img} -p #{pri} -m #{msg.inspect} #{title} #{sticky}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.growl_fail(output)
|
34
|
+
growl "FAIL", "#{output}", "fail.png", 2
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.growl_pass(output)
|
38
|
+
growl "Pass", "#{output}", "pass.png"
|
39
|
+
end
|
40
|
+
|
41
|
+
command = ARGV.shift
|
42
|
+
files = {}
|
43
|
+
|
44
|
+
ARGV.each do |arg|
|
45
|
+
Dir[arg].each { |file|
|
46
|
+
files[file] = File.mtime(file)
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
puts "Watching #{files.keys.join(', ')}\n\nFiles: #{files.keys.length}"
|
51
|
+
|
52
|
+
trap('INT') do
|
53
|
+
puts "\nQuitting..."
|
54
|
+
exit
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
loop do
|
59
|
+
|
60
|
+
sleep 1
|
61
|
+
|
62
|
+
changed_file, last_changed = files.find { |file, last_changed|
|
63
|
+
File.mtime(file) > last_changed
|
64
|
+
}
|
65
|
+
|
66
|
+
if changed_file
|
67
|
+
files[changed_file] = File.mtime(changed_file)
|
68
|
+
puts "=> #{changed_file} changed, running #{command}"
|
69
|
+
args = ""
|
70
|
+
args += ARGV.last == '--pass-as-arg' ? changed_file : ""
|
71
|
+
args += ARGV.last == '--pass-as-env' ? "CHANGED=#{changed_file}" : ""
|
72
|
+
puts "Executing: #{command} #{args}"
|
73
|
+
results = `#{command} #{args}`
|
74
|
+
puts results
|
75
|
+
|
76
|
+
if results.include? 'tests'
|
77
|
+
output = results.slice(/(\d+)\s+tests?,\s*(\d+)\s+assertions?,\s*(\d+)\s+failures?(,\s*(\d+)\s+errors)?/)
|
78
|
+
if output
|
79
|
+
$~[3].to_i + $~[5].to_i > 0 ? growl_fail(output) : growl_pass(output)
|
80
|
+
end
|
81
|
+
else
|
82
|
+
output = results.slice(/(\d+)\s+examples?,\s*(\d+)\s+failures?(,\s*(\d+)\s+not implemented)?/)
|
83
|
+
if output
|
84
|
+
$~[2].to_i > 0 ? growl_fail(output) : growl_pass(output)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
# TODO Generic growl notification for other actions
|
88
|
+
|
89
|
+
puts "=> done"
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
data/script/txt2html
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
GEM_NAME = 'rubydoctest' # what ppl will type to install your gem
|
4
|
+
RUBYFORGE_PROJECT = 'rubydoctest'
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
begin
|
8
|
+
require 'newgem'
|
9
|
+
require 'rubyforge'
|
10
|
+
rescue LoadError
|
11
|
+
puts "\n\nGenerating the website requires the newgem RubyGem"
|
12
|
+
puts "Install: gem install newgem\n\n"
|
13
|
+
exit(1)
|
14
|
+
end
|
15
|
+
require 'redcloth'
|
16
|
+
require 'syntax/convertors/html'
|
17
|
+
require 'erb'
|
18
|
+
require File.dirname(__FILE__) + "/../lib/#{GEM_NAME}/version.rb"
|
19
|
+
|
20
|
+
version = Rubydoctest::VERSION::STRING
|
21
|
+
download = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
|
22
|
+
|
23
|
+
def rubyforge_project_id
|
24
|
+
RubyForge.new.autoconfig["group_ids"][RUBYFORGE_PROJECT]
|
25
|
+
end
|
26
|
+
|
27
|
+
class Fixnum
|
28
|
+
def ordinal
|
29
|
+
# teens
|
30
|
+
return 'th' if (10..19).include?(self % 100)
|
31
|
+
# others
|
32
|
+
case self % 10
|
33
|
+
when 1: return 'st'
|
34
|
+
when 2: return 'nd'
|
35
|
+
when 3: return 'rd'
|
36
|
+
else return 'th'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Time
|
42
|
+
def pretty
|
43
|
+
return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def convert_syntax(syntax, source)
|
48
|
+
return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
|
49
|
+
end
|
50
|
+
|
51
|
+
if ARGV.length >= 1
|
52
|
+
src, template = ARGV
|
53
|
+
template ||= File.join(File.dirname(__FILE__), '/../website/template.html.erb')
|
54
|
+
else
|
55
|
+
puts("Usage: #{File.split($0).last} source.txt [template.html.erb] > output.html")
|
56
|
+
exit!
|
57
|
+
end
|
58
|
+
|
59
|
+
template = ERB.new(File.open(template).read)
|
60
|
+
|
61
|
+
title = nil
|
62
|
+
body = nil
|
63
|
+
File.open(src) do |fsrc|
|
64
|
+
title_text = fsrc.readline
|
65
|
+
body_text_template = fsrc.read
|
66
|
+
body_text = ERB.new(body_text_template).result(binding)
|
67
|
+
syntax_items = []
|
68
|
+
body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
|
69
|
+
ident = syntax_items.length
|
70
|
+
element, syntax, source = $1, $2, $3
|
71
|
+
syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
|
72
|
+
"syntax-temp-#{ident}"
|
73
|
+
}
|
74
|
+
title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
|
75
|
+
body = RedCloth.new(body_text).to_html
|
76
|
+
body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
|
77
|
+
end
|
78
|
+
stat = File.stat(src)
|
79
|
+
created = stat.ctime
|
80
|
+
modified = stat.mtime
|
81
|
+
|
82
|
+
$stdout << template.result(binding)
|