rote 0.2.4.1 → 0.3.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.
@@ -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
+