rote 0.2.4.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  # Standard Rakefile for custom Rote build
2
2
  #
3
3
  # Generated from:
4
- # $Id: Rakefile,v 1.1 2005/12/05 14:43:22 roscopeco Exp $
4
+ # $Id: Rakefile,v 1.2 2005/12/12 02:45:24 roscopeco Exp $
5
5
  #
6
6
  begin
7
7
  require 'rubygems'
@@ -11,6 +11,7 @@ end
11
11
  require 'rake'
12
12
  require 'rake/clean'
13
13
  require 'rote'
14
+ include Rote
14
15
 
15
16
  # Create a set of tasks with the prefix 'doc' to build the
16
17
  # documentation set. The directory layout is as for the
@@ -29,16 +30,36 @@ require 'rote'
29
30
  #
30
31
  # In addition to these tasks, you may also wish to define a 'doc_refresh' task
31
32
  # to be run whenever modified resources are processed in monitor mode.
32
- ws = Rote::DocTask.new(:doc) { |site|
33
+ ws = Rote::DocTask.new(:doc) do |site|
33
34
  site.output_dir = 'html'
34
35
  site.layout_dir = 'doc/layouts'
35
36
 
36
37
  site.pages.dir = 'doc/pages'
37
- site.pages.include('**/*')
38
-
38
+ site.pages.include('**/*')
39
+
39
40
  site.res.dir = 'doc/res'
40
41
  site.res.include('**/*')
41
- }
42
+
43
+ # TODO need to figure out what default mappings should be
44
+ site.ext_mapping(/(thtml)/, 'html') do |page|
45
+ page.extend Format::HTML
46
+ page.page_filter Filters::RedCloth.new(:textile)
47
+ end
48
+
49
+ site.ext_mapping(/mhtml/, 'html') do |page|
50
+ page.extend Format::HTML
51
+ page.page_filter Filters::RedCloth.new(:markdown)
52
+ end
53
+
54
+ site.ext_mapping(/rdoc/, 'html') do |page|
55
+ page.extend Format::HTML
56
+ page.page_filter Filters::RDoc.new
57
+ end
58
+
59
+ site.ext_mapping(/html/, 'html') do |page|
60
+ page.extend Format::HTML
61
+ end
62
+ end
42
63
 
43
64
  task :default => [:doc]
44
65
 
@@ -1,8 +1,10 @@
1
+ #--
1
2
  # Rake tasklib for Rote
2
3
  # (c)2005 Ross Bamford (and contributors)
3
4
  #
4
5
  # See 'rote.rb' or LICENSE for licence information.
5
- # $Id: rotetasks.rb,v 1.8 2005/12/05 14:44:32 roscopeco Exp $
6
+ # $Id: rotetasks.rb,v 1.9 2005/12/12 02:45:24 roscopeco Exp $
7
+ #++
6
8
  require 'rake'
7
9
  require 'rake/tasklib'
8
10
 
@@ -53,6 +55,54 @@ module Rote
53
55
  fl
54
56
  end
55
57
  end
58
+
59
+ # Special type of Hash that uses Regexp keys and maintains insertion order.
60
+ # When searching for a string, the first match (of either kind) is used.
61
+ # Allows backreferences from the key match to be used in the value with $1..$n
62
+ # notation in val str.
63
+ #
64
+ # Entries are kept in insertion order. Searches/insertion are slow, iteration
65
+ # is constant time. It's basically an unbucketed hash.
66
+ class ExtHash
67
+ class << self
68
+ alias :[] :new
69
+ end
70
+
71
+ # Create a new RxHash, copying the supplied
72
+ # map (in random order).
73
+ def initialize(map = nil)
74
+ @data = []
75
+ map.each { |k,v| self[k] = v } if map
76
+ end
77
+
78
+ # Insert the given regex key unless it already exists.
79
+ # You may use string representations for the keys, but
80
+ # they are converted as-is to regexps.
81
+ #
82
+ # Returns the value that was inserted, or nil.
83
+ def []=(key,value)
84
+ @data << [key,value] unless member?(key)
85
+ end
86
+
87
+ # Fetch the first matching data.
88
+ def [](key)
89
+ md = nil
90
+ if v = @data.detect { |it| md = /^#{it[0]}$/.match(key.to_s) }
91
+ v[1][0].gsub!(/\$(\d)/) { md[$1.to_i] }
92
+ v[1]
93
+ end
94
+ end
95
+
96
+ # Fetch a single entry based on key equality.
97
+ def fetch_entry(key)
98
+ @data.detect { |it| it[0] == key }
99
+ end
100
+
101
+ # Determine membership based on key equality.
102
+ def member?(key)
103
+ true if fetch_entry(key)
104
+ end
105
+ end
56
106
 
57
107
  #####
58
108
  ## Rake task library that provides a set of tasks to transform documentation
@@ -95,8 +145,25 @@ module Rote
95
145
  # +FileList+.
96
146
  attr_reader :res
97
147
 
148
+ # Ordered +ExtHash+ that supplies mappings between input and output
149
+ # file extensions. Keys are regexps that are matched in order
150
+ # against the search key.
151
+ #
152
+ # The values are [extension, ({ |page| ...})] . If a mapping has a
153
+ # block, it is executed when pages with a matching extension are,
154
+ # instantiated (before common and page code). It can be used to apply
155
+ # filters, for example, on a per-extension basis.
156
+ attr_reader :ext_mappings
157
+
158
+ # Define an extension mapping for the specified regex, which will
159
+ # be replaced with the specified extension. If a block is supplied
160
+ # it will be called with each matching +Page+ as it's created.
161
+ def ext_mapping(match, extension, &block)
162
+ @ext_mappings[match] = [extension,block]
163
+ end
164
+
98
165
  # If +show_page_tasks+ is +true+, then the file tasks created for each
99
- # source page will be shown in the Rake task listing from the command line.
166
+ # output file will be shown in the Rake task listing from the command line.
100
167
  attr_accessor :show_file_tasks
101
168
  alias :show_file_tasks? :show_file_tasks
102
169
  alias :show_file_tasks= :show_file_tasks=
@@ -111,16 +178,17 @@ module Rote
111
178
 
112
179
  # Create a new DocTask, using the supplied block for configuration,
113
180
  # and define tasks with the specified base-name within Rake.
114
- def initialize(name = :site) # :yield: self if block_given?
181
+ def initialize(name = :doc) # :yield: self if block_given?
115
182
  @name = name
116
183
  @output_dir = '.'
117
184
  @pages = FilePatterns.new('.')
118
185
  @res = FilePatterns.new('.')
119
186
  @monitor_interval = 1
120
- DEFAULT_SRC_EXCLUDES.each { |excl| @pages.exclude(excl) }
121
-
187
+ @ext_mappings = ExtHash.new
122
188
  @show_page_tasks = false
123
189
 
190
+ DEFAULT_SRC_EXCLUDES.each { |excl| @pages.exclude(excl) }
191
+
124
192
  yield self if block_given?
125
193
 
126
194
  define
@@ -135,16 +203,32 @@ module Rote
135
203
  nil
136
204
  end
137
205
 
206
+ # Get a target filename for a source filename. The dir_rx must
207
+ # match the portion of the directory that will be replaced
208
+ # with the target directory. The extension is mapped through
209
+ # ext_mappings. If a block is configured for this extension,
210
+ # it is returned too.
211
+ #
212
+ # Returns [target_fn, ({ |page| ...})]
213
+ def target_fn(dir_rx, fn)
214
+ tfn = fn.sub(dir_rx, output_dir)
215
+ ext = File.extname(tfn)
216
+ ext.sub!(/^\./,'') # strip leading dot
217
+ new_ext, blk = ext_mappings[ext] || [ext,nil]
218
+ [tfn.sub(/#{ext}$/,new_ext),blk]
219
+ end
220
+
138
221
  # define a task for each resource, and 'all resources' task
139
222
  def define_res_tasks
140
223
  res_fl = res.to_filelist
141
224
  tasks = res_fl.select { |fn| not File.directory?(fn) }.map do |fn|
142
- tfn = fn.sub(/^#{res.dir}/, output_dir)
143
- desc "#{fn} => #{tfn}" if show_file_tasks?
225
+ tfn, = target_fn(/^#{res.dir}/, fn)
226
+
227
+ desc "#{fn} => #{tfn}" #if show_file_tasks?
144
228
  file tfn => [fn] do
145
229
  dn = File.dirname(tfn)
146
230
  mkdir_p dn unless File.exists?(dn)
147
- cp fn, tfn
231
+ cp fn, tfn, :preserve => true
148
232
  end
149
233
  tfn
150
234
  end
@@ -156,22 +240,52 @@ module Rote
156
240
  # define a task for each page, and 'all pages' task
157
241
  def define_page_tasks
158
242
  pages_fl = pages.to_filelist
159
- tasks = pages_fl.select { |fn| not File.directory?(fn) }.map do |fn|
160
- tfn = fn.sub(/^#{pages.dir}/, output_dir)
161
- desc "#{fn} => #{tfn}" if show_file_tasks?
243
+
244
+ gen_files = pages_fl.select { |fn| not File.directory?(fn) }.map do |fn|
245
+ tfn, blk = target_fn(/^#{pages.dir}/, fn)
246
+
247
+ desc "#{fn} => #{tfn}" #if show_file_tasks?
162
248
  file tfn => [fn] do
163
249
  dn = File.dirname(tfn)
164
250
  mkdir_p dn unless File.exists?(dn)
165
- File.open(tfn, 'w+') do |f|
166
- puts "tr #{fn} => #{tfn}"
167
- f << Page.new(fn,layout_dir).render
168
- end
251
+ puts "tr #{fn} => #{tfn}"
252
+ begin
253
+ File.open(tfn, 'w+') do |f|
254
+ # new page, run extension block, render out, throw away
255
+ f << Page.new(fn,pages.dir,layout_dir,&blk).render
256
+ end
257
+ rescue => e
258
+ # Oops... Unlink file and dump backtrace
259
+ File.unlink(tfn)
260
+ bt = e.backtrace
261
+ end_idx = bt.each_with_index do |entry, idx|
262
+ break idx if entry =~ /^#{File.dirname(__FILE__)}/
263
+ end
264
+ puts bt[0...end_idx]
265
+ raise
266
+ end
267
+ end
268
+
269
+ # Each page depends properly on source and common - thx again
270
+ # Jonathan :)
271
+ src_rb = Page::page_ruby_filename(fn)
272
+ if File.exists?(src_rb)
273
+ file tfn => [src_rb]
169
274
  end
275
+
276
+ common_rbs = Page::resolve_common_rubys(File.dirname(fn))
277
+ file tfn => common_rbs unless common_rbs.empty?
278
+
170
279
  tfn
171
280
  end
172
281
 
173
282
  desc "Render new/changed documentation pages"
174
- task "#{name}_pages" => tasks
283
+ task "#{name}_pages" => gen_files
284
+ task "clobber_#{name}_pages" do
285
+ gen_files.each do |f|
286
+ rm_f f
287
+ end
288
+ end
175
289
  end
176
290
 
177
291
  def define_main_tasks
@@ -200,13 +314,12 @@ module Rote
200
314
 
201
315
  end
202
316
 
203
- end #class
204
-
317
+ end #class
205
318
  end #module
206
319
 
207
- ## The -run task requires a few mods to Rake to let us fire
320
+ ## The +monitor+ task requires a few mods to Rake to let us fire
208
321
  ## and reset task invocations in a loop.
209
- module Rake
322
+ module Rake # :nodoc: all
210
323
  class Task
211
324
  def reset
212
325
  @already_invoked = false
data/test/gem_tests.rb CHANGED
@@ -1,2 +1,4 @@
1
1
  TEST_FROM_GEM = true
2
- require File.join(File.dirname(__FILE__), 'test_page.rb')
2
+ $: << File.join(File.dirname(__FILE__),'../lib')
3
+ Dir[File.join(File.dirname(__FILE__), '**/test_*.rb')].each { |test| require test }
4
+
@@ -0,0 +1 @@
1
+ @layout_code_works = true
@@ -1,4 +1,8 @@
1
- <% format_opts << :markdown %>
1
+ <%
2
+ extend Format::HTML
3
+ format_opts << :markdown
4
+ %>
5
+
2
6
  *this* is a _test_
3
7
  ==================
4
8
 
data/test/pages/rdoc.txt CHANGED
@@ -1,3 +1,6 @@
1
- <% format_opts << :rdoc %>
1
+ <%
2
+ extend Format::HTML
3
+ format_opts << :rdoc
4
+ %>
2
5
  == RDoc
3
6
  === Markup
@@ -1 +1,3 @@
1
+ extend Format::HTML
2
+
1
3
  format_opts << :textile
@@ -0,0 +1,140 @@
1
+ begin
2
+ require 'rubygems'
3
+ rescue LoadError
4
+ nil
5
+ end
6
+
7
+ require 'test/unit'
8
+ require 'rote/page'
9
+ require 'rote/filters/redcloth'
10
+ require 'rote/filters/rdoc'
11
+ require 'rote/filters/proc'
12
+ require 'rote/filters/toc'
13
+ require 'rote/filters/syntax'
14
+
15
+ SYNTEST = <<-EOM
16
+ <p>Non-code</p>
17
+ #:code#ruby#
18
+ def amethod(arg)
19
+ puts arg
20
+ end
21
+ #:code#
22
+ <p>More non-code</p>
23
+ #:code#ruby#
24
+ def amethod_too(arg)
25
+ puts arg
26
+ end
27
+ #:code#
28
+
29
+ EOM
30
+
31
+ SYNEXPECT = <<-EOM
32
+ <p>Non-code</p>
33
+ <pre class='ruby'><code> <span class=\"keyword\">def </span><span class=\"method\">amethod</span><span class=\"punct\">(</span><span class=\"ident\">arg</span><span class=\"punct\">)</span>
34
+ <span class=\"ident\">puts</span> <span class=\"ident\">arg</span>
35
+ <span class=\"keyword\">end</span></code></pre>
36
+ <p>More non-code</p>
37
+ <pre class='ruby'><code> <span class=\"keyword\">def </span><span class=\"method\">amethod_too</span><span class=\"punct\">(</span><span class=\"ident\">arg</span><span class=\"punct\">)</span>
38
+ <span class=\"ident\">puts</span> <span class=\"ident\">arg</span>
39
+ <span class=\"keyword\">end</span></code></pre>
40
+ EOM
41
+
42
+ TOCTEST = <<-EOM
43
+ <h2>Section One</h2>
44
+ <p>This is section one</p>
45
+ <h3>Section Two</h3>
46
+ <p>This is section two</p>
47
+ EOM
48
+
49
+ TOCEXPECTH2 = <<-EOM
50
+ <a name='section_one'></a><h2>Section One</h2>
51
+ <p>This is section one</p>
52
+ <h3>Section Two</h3>
53
+ <p>This is section two</p>
54
+ EOM
55
+
56
+ TOCEXPECTALL = <<-EOM
57
+ <a name='section_one'></a><h2>Section One</h2>
58
+ <p>This is section one</p>
59
+ <a name='section_two'></a><h3>Section Two</h3>
60
+ <p>This is section two</p>
61
+ EOM
62
+
63
+ module Rote
64
+ class TestFormatting < Test::Unit::TestCase
65
+ ############## filters/redcloth #################
66
+ def test_render_default # textile
67
+ t = Filters::RedCloth.new.filter('*Textile* _Test_', nil)
68
+ assert_equal '<p><strong>Textile</strong> <em>Test</em></p>', t
69
+ end
70
+
71
+ def test_render_textile
72
+ t = Filters::RedCloth.new(:textile).filter('*Textile* _Test_', nil)
73
+ assert_equal '<p><strong>Textile</strong> <em>Test</em></p>', t
74
+ end
75
+
76
+ def test_render_markdown
77
+ t = Filters::RedCloth.new(:markdown).filter("*this* is a _test_\n==================", nil)
78
+ assert_equal '<h1>*this* is a _test_</h1>', t
79
+ end
80
+
81
+ ############## filters/rdoc #################
82
+ # FIXME Fails under Gem install, but passes when run normally (???)
83
+ unless defined?(TEST_FROM_GEM)
84
+ def test_render_rdoc
85
+ t = Filters::RDoc.new.filter("== RDoc\n=== Markup",nil)
86
+ assert_equal "<h2>RDoc</h2>\n<h3>Markup</h3>\n", t
87
+ end
88
+ end
89
+
90
+ ############## filters/proc #################
91
+ # FIXME Fails under Gem install, but passes when run normally (???)
92
+ def test_proc_no_block
93
+ begin
94
+ Filters::Proc.new
95
+ rescue ArgumentError => ex
96
+ assert_equal 'No block given', ex.message
97
+ end
98
+ end
99
+
100
+ def test_render_with_proc
101
+ f = Filters::Proc.new { |text, page| text + page }
102
+ assert_equal f.filter('some text ', 'fake page'), 'some text fake page'
103
+
104
+ # equivalent
105
+ f = Filters::Proc.with do |text, page|
106
+ text + page
107
+ end
108
+ assert_equal f.filter('some text ', 'fake page'), 'some text fake page'
109
+ end
110
+
111
+ # Toc filter is a non-output filter - it's used to get a list of links in
112
+ # the page, from layout code. It should output it's input directly, so
113
+ # that it doesn't matter where in the chain it is.
114
+ def test_toc_filter
115
+ # default RE
116
+ toc = Filters::TOC::new
117
+ assert_equal '<p>Has no sections</p>', toc.filter('<p>Has no sections</p>', nil)
118
+ assert toc.links.empty?
119
+
120
+ assert_equal TOCEXPECTALL, toc.filter(TOCTEST, nil)
121
+ assert_equal "<a href='#section_one'>Section One</a> - <a href='#section_two'>Section Two</a>", toc.links.join(' - ')
122
+
123
+ # custom RE
124
+ toc = Filters::TOC::new(/h2/)
125
+ assert_equal TOCEXPECTH2, toc.filter(TOCTEST, nil)
126
+ assert_equal "<a href='#section_one'>Section One</a>", toc.links.join(' - ')
127
+ end
128
+
129
+ def test_syntax_filter
130
+ # bad
131
+ assert_equal '', Filters::Syntax.new.filter('', nil)
132
+ assert_equal 'Has no source', Filters::Syntax.new.filter('Has no source', nil)
133
+
134
+ # good
135
+ assert_equal SYNEXPECT.chomp, Filters::Syntax.new.filter(SYNTEST, nil)
136
+ end
137
+ end
138
+
139
+ end
140
+