pluginfactory 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/rake/manual.rb ADDED
@@ -0,0 +1,384 @@
1
+ #
2
+ # Manual-generation Rake tasks and classes
3
+ # $Id: manual.rb 10 2008-07-18 15:52:48Z deveiant $
4
+ #
5
+ # Author: Michael Granger <ged@FaerieMUD.org>
6
+ #
7
+ # This was born out of a frustration with other static HTML generation modules
8
+ # and systems. I've tried webby, webgen, rote, staticweb, staticmatic, and
9
+ # nanoc, but I didn't find any of them really suitable (except rote, which was
10
+ # excellent but apparently isn't maintained and has a fundamental
11
+ # incompatibilty with Rake because of some questionable monkeypatching.)
12
+ #
13
+ # So, since nothing seemed to scratch my itch, I'm going to scratch it myself.
14
+ #
15
+
16
+ require 'pathname'
17
+ require 'singleton'
18
+ require 'rake/tasklib'
19
+ require 'erb'
20
+
21
+
22
+ ### Namespace for Manual-generation classes
23
+ module Manual
24
+
25
+ ### Manual page-generation class
26
+ class Page
27
+
28
+ ### An abstract filter class for manual content transformation.
29
+ class Filter
30
+ include Singleton
31
+
32
+ # A list of inheriting classes, keyed by normalized name
33
+ @derivatives = {}
34
+ class << self; attr_reader :derivatives; end
35
+
36
+ ### Inheritance callback -- keep track of all inheriting classes for
37
+ ### later.
38
+ def self::inherited( subclass )
39
+ key = subclass.name.
40
+ sub( /^.*::/, '' ).
41
+ gsub( /[^[:alpha:]]+/, '_' ).
42
+ downcase.
43
+ sub( /filter$/, '' )
44
+
45
+ self.derivatives[ key ] = subclass
46
+ self.derivatives[ key.to_sym ] = subclass
47
+
48
+ super
49
+ end
50
+
51
+
52
+ ### Process the +page+'s source with the filter and return the altered content.
53
+ def process( source, page, metadata )
54
+ raise NotImplementedError,
55
+ "%s does not implement the #process method" % [ self.class.name ]
56
+ end
57
+ end
58
+
59
+
60
+ ### The default page configuration if none is specified.
61
+ DEFAULT_CONFIG = {
62
+ 'filters' => [ 'textile', 'erb' ],
63
+ 'layout' => 'default.page',
64
+ }.freeze
65
+
66
+ # Pattern to match a source page with a YAML header
67
+ PAGE_WITH_YAML_HEADER = /
68
+ \A---\s*$ # It should should start with three hyphens
69
+ (.*?) # ...have some YAML stuff
70
+ ^---\s*$ # then have another three-hyphen line,
71
+ (.*)\Z # then the rest of the document
72
+ /xm
73
+
74
+ # Options to pass to libtidy
75
+ TIDY_OPTIONS = {
76
+ :show_warnings => true,
77
+ :indent => false,
78
+ :indent_attributes => false,
79
+ :indent_spaces => 4,
80
+ :vertical_space => true,
81
+ :tab_size => 4,
82
+ :wrap_attributes => true,
83
+ :wrap => 100,
84
+ }
85
+
86
+
87
+ ### Create a new page-generator for the given +sourcefile+, which will use
88
+ ### ones of the templates in +layouts_dir+ as a wrapper.
89
+ def initialize( sourcefile, layouts_dir )
90
+ @sourcefile = Pathname.new( sourcefile )
91
+ @layouts_dir = Pathname.new( layouts_dir )
92
+
93
+ rawsource = @sourcefile.read
94
+ @config, @source = self.read_page_config( rawsource )
95
+ # $stderr.puts "Config is: %p" % [@config],
96
+ # "Source is: %p" % [ @source[0,100] ]
97
+ @filters = self.load_filters( @config['filters'] )
98
+
99
+ super()
100
+ end
101
+
102
+
103
+ ######
104
+ public
105
+ ######
106
+
107
+ # The Pathname object that specifys the page source file
108
+ attr_reader :sourcefile
109
+
110
+ # The configured layouts directory as a Pathname object.
111
+ attr_reader :layouts_dir
112
+
113
+ # The page configuration, as read from its YAML header
114
+ attr_reader :config
115
+
116
+ # The raw source of the page
117
+ attr_reader :source
118
+
119
+ # The filters the page will use to render itself
120
+ attr_reader :filters
121
+
122
+
123
+ ### Generate HTML output from the page and return it.
124
+ def generate( metadata )
125
+ content = self.generate_content( @source, metadata )
126
+
127
+ # :TODO: Read config from page for layout, filters, etc.
128
+ templatepath = @layouts_dir + 'default.page'
129
+ template = ERB.new( templatepath.read )
130
+ page = self
131
+
132
+ html = template.result( binding() )
133
+
134
+ # return self.cleanup( html )
135
+ return html
136
+ end
137
+
138
+
139
+ ### Run the various filters on the given input and return the transformed
140
+ ### content.
141
+ def generate_content( input, metadata )
142
+ return @filters.inject( input ) do |source, filter|
143
+ filter.process( source, self, metadata )
144
+ end
145
+ end
146
+
147
+
148
+ ### Trim the YAML header from the provided page +source+, convert it to
149
+ ### a Ruby object, and return it.
150
+ def read_page_config( source )
151
+ unless source =~ PAGE_WITH_YAML_HEADER
152
+ return DEFAULT_CONFIG.dup, source
153
+ end
154
+
155
+ pageconfig = YAML.load( $1 )
156
+ source = $2
157
+
158
+ return DEFAULT_CONFIG.merge( pageconfig ), source
159
+ end
160
+
161
+
162
+ ### Clean up and return the given HTML +source+.
163
+ def cleanup( source )
164
+ require 'tidy'
165
+
166
+ Tidy.path = '/usr/lib/libtidy.dylib'
167
+ Tidy.open( TIDY_OPTIONS ) do |tidy|
168
+ tidy.options.output_xhtml = true
169
+
170
+ xml = tidy.clean( source )
171
+ puts tidy.errors
172
+ puts tidy.diagnostics
173
+ return xml
174
+ end
175
+ rescue LoadError => err
176
+ trace "No cleanup: " + err.message
177
+ return source
178
+ end
179
+
180
+
181
+ ### Get (singleton) instances of the filters named in +filterlist+ and return them.
182
+ def load_filters( filterlist )
183
+ filterlist.flatten.collect do |key|
184
+ raise ArgumentError, "filter '#{key}' is not loaded" unless
185
+ Manual::Page::Filter.derivatives.key?( key )
186
+ Manual::Page::Filter.derivatives[ key ].instance
187
+ end
188
+ end
189
+
190
+ end
191
+
192
+
193
+ ### A Textile filter for the manual generation tasklib, implemented using RedCloth.
194
+ class TextileFilter < Manual::Page::Filter
195
+
196
+ ### Load RedCloth when the filter is first created
197
+ def initialize( *args )
198
+ require 'redcloth'
199
+ super
200
+ end
201
+
202
+
203
+ ### Process the given +source+ as Textile and return the resulting HTML
204
+ ### fragment.
205
+ def process( source, *ignored )
206
+ return RedCloth.new( source ).to_html
207
+ end
208
+
209
+ end
210
+
211
+
212
+ ### An ERB filter for the manual generation tasklib, implemented using Erubis.
213
+ class ErbFilter < Manual::Page::Filter
214
+
215
+ ### Process the given +source+ as ERB and return the resulting HTML
216
+ ### fragment.
217
+ def process( source, page, metadata )
218
+ template_name = page.sourcefile.basename
219
+ template = ERB.new( source )
220
+ return template.result( binding() )
221
+ end
222
+
223
+ end
224
+
225
+
226
+ ### Manual generation task library
227
+ class GenTask < Rake::TaskLib
228
+
229
+ # Default values for task config variables
230
+ DEFAULT_NAME = :manual
231
+ DEFAULT_BASE_DIR = Pathname.new( 'docs/manual' )
232
+ DEFAULT_SOURCE_DIR = 'source'
233
+ DEFAULT_LAYOUTS_DIR = 'layouts'
234
+ DEFAULT_OUTPUT_DIR = 'output'
235
+ DEFAULT_RESOURCE_DIR = 'resources'
236
+ DEFAULT_LIB_DIR = 'lib'
237
+ DEFAULT_METADATA = OpenStruct.new
238
+
239
+
240
+ ### Define a new manual-generation task with the given +name+.
241
+ def initialize( name=:manual )
242
+ @name = name
243
+
244
+ @source_dir = DEFAULT_SOURCE_DIR
245
+ @layouts_dir = DEFAULT_LAYOUTS_DIR
246
+ @output_dir = DEFAULT_OUTPUT_DIR
247
+ @resource_dir = DEFAULT_RESOURCE_DIR
248
+ @lib_dir = DEFAULT_LIB_DIR
249
+ @metadata = DEFAULT_METADATA
250
+
251
+ yield( self ) if block_given?
252
+
253
+ self.define
254
+ end
255
+
256
+
257
+ ######
258
+ public
259
+ ######
260
+
261
+ attr_accessor :base_dir,
262
+ :source_dir,
263
+ :layouts_dir,
264
+ :output_dir,
265
+ :resource_dir,
266
+ :lib_dir,
267
+ :metadata
268
+
269
+ attr_reader :name
270
+
271
+ ### Load the filter libraries provided in the given +libdir+
272
+ def load_filter_libraries( libdir )
273
+ Pathname.glob( libdir + '*.rb' ) do |filterlib|
274
+ trace " loading filter library #{filterlib}"
275
+ require( filterlib )
276
+ end
277
+ end
278
+
279
+
280
+ ### Set up the main HTML-generation task that will convert files in the given +sourcedir+ to
281
+ ### HTML in the +outputdir+
282
+ def setup_page_conversion_tasks( sourcedir, outputdir, layoutsdir )
283
+ source_glob = sourcedir + '**/*.page'
284
+ trace "Looking for sources that match: %s" % [ source_glob ]
285
+
286
+ # Find the list of source .page files
287
+ manual_sources = FileList[ source_glob ]
288
+ trace " found %d source files" % [ manual_sources.length ]
289
+
290
+ # Map .page files to their equivalent .html output
291
+ html_pathmap = "%%{%s,%s}X.html" % [ sourcedir, outputdir ]
292
+ manual_pages = manual_sources.pathmap( html_pathmap )
293
+ trace "Mapping sources like so: \n %p -> %p" %
294
+ [ manual_sources.first, manual_pages.first ]
295
+
296
+ # Output directory task
297
+ directory( outputdir.to_s )
298
+ file outputdir.to_s do
299
+ touch outputdir + '.buildtime'
300
+ end
301
+
302
+ # Rule to generate .html files from .page files
303
+ rule(
304
+ %r{#{outputdir}/.*\.html$} => [
305
+ proc {|name| name.sub(/\.[^.]+$/, '.page').sub( outputdir, sourcedir) },
306
+ outputdir.to_s
307
+ ]) do |task|
308
+
309
+ source = Pathname.new( task.source ).relative_path_from( Pathname.getwd )
310
+ target = Pathname.new( task.name ).relative_path_from( Pathname.getwd )
311
+ log " #{ source } -> #{ target }"
312
+
313
+ page = Manual::Page.new( source, layoutsdir )
314
+
315
+ target.dirname.mkpath
316
+ target.open( File::WRONLY|File::CREAT|File::TRUNC ) do |io|
317
+ io.write( page.generate(metadata) )
318
+ end
319
+ end
320
+
321
+ return manual_pages
322
+ end
323
+
324
+
325
+ ### Set up a rule for copying files from the resources directory to the output dir.
326
+ def setup_resource_copy_tasks( resourcedir, outputdir )
327
+
328
+ task :copy_resources => [ outputdir.to_s ] do
329
+ when_writing( "Copying resources" ) do
330
+ verbose do
331
+ files = FileList[ resourcedir + '*' ]
332
+ files.exclude( /\.svn/ )
333
+ unless files.empty?
334
+ trace " Copying resource files: #{files}"
335
+ cp_r files, outputdir, :verbose => true
336
+ end
337
+ end
338
+ end
339
+ end
340
+ end
341
+
342
+
343
+ ### Set up the tasks for building the manual
344
+ def define
345
+
346
+ # Set up a description if the caller hasn't already defined one
347
+ unless Rake.application.last_comment
348
+ desc "Generate the manual"
349
+ end
350
+
351
+ # Make Pathnames of the directories relative to the base_dir
352
+ basedir = Pathname.new( @base_dir )
353
+ sourcedir = basedir + @source_dir
354
+ layoutsdir = basedir + @layouts_dir
355
+ outputdir = basedir + @output_dir
356
+ resourcedir = basedir + @resource_dir
357
+ libdir = basedir + @lib_dir
358
+
359
+ load_filter_libraries( libdir )
360
+
361
+ # Declare the tasks outside the namespace that point in
362
+ task @name => "#@name:build"
363
+ task "clobber_#@name" => "#@name:clobber"
364
+
365
+ namespace( self.name ) do
366
+ setup_resource_copy_tasks( resourcedir, outputdir )
367
+ manual_pages = setup_page_conversion_tasks( sourcedir, outputdir, layoutsdir )
368
+
369
+ task :build => [ :copy_resources, *manual_pages ]
370
+
371
+ task :clobber do
372
+ RakeFileUtils.verbose( $verbose ) do
373
+ rm_f manual_pages.to_a
374
+ end
375
+ remove_dir( outputdir ) if ( outputdir + '.buildtime' ).exist?
376
+ end
377
+ task :rebuild => [ :clobber, :build ]
378
+ end
379
+
380
+ end # def define
381
+
382
+ end # class Manual::GenTask
383
+
384
+ end
data/rake/packaging.rb ADDED
@@ -0,0 +1,112 @@
1
+ #
2
+ # Packaging Rake Tasks
3
+ # $Id: packaging.rb 21 2008-08-07 23:45:52Z deveiant $
4
+ #
5
+
6
+ require 'rbconfig'
7
+ require 'rake/packagetask'
8
+ require 'rake/gempackagetask'
9
+
10
+ include Config
11
+
12
+ ### Task: gem
13
+ ### Task: package
14
+ Rake::PackageTask.new( PKG_NAME, PKG_VERSION ) do |task|
15
+ task.need_tar_gz = true
16
+ task.need_tar_bz2 = true
17
+ task.need_zip = true
18
+ task.package_dir = PKGDIR.to_s
19
+ task.package_files = RELEASE_FILES.
20
+ collect {|f| f.relative_path_from(BASEDIR).to_s }
21
+ end
22
+ task :package => [:gem]
23
+
24
+
25
+ ### Task: gem
26
+ gempath = PKGDIR + GEM_FILE_NAME
27
+
28
+ desc "Build a RubyGem package (#{GEM_FILE_NAME})"
29
+ task :gem => gempath.to_s
30
+ file gempath.to_s => [PKGDIR.to_s] + GEMSPEC.files do
31
+ when_writing( "Creating GEM" ) do
32
+ Gem::Builder.new( GEMSPEC ).build
33
+ verbose( true ) do
34
+ mv GEM_FILE_NAME, gempath
35
+ end
36
+ end
37
+ end
38
+
39
+ ### Task: install
40
+ desc "Install #{PKG_NAME} as a conventional library"
41
+ task :install do
42
+ log "Installing #{PKG_NAME} as a conventional library"
43
+ sitelib = Pathname.new( CONFIG['sitelibdir'] )
44
+ sitearch = Pathname.new( CONFIG['sitearchdir'] )
45
+ Dir.chdir( LIBDIR ) do
46
+ LIB_FILES.each do |libfile|
47
+ relpath = libfile.relative_path_from( LIBDIR )
48
+ target = sitelib + relpath
49
+ FileUtils.mkpath target.dirname,
50
+ :mode => 0755, :verbose => true, :noop => $dryrun unless target.dirname.directory?
51
+ FileUtils.install relpath, target,
52
+ :mode => 0644, :verbose => true, :noop => $dryrun
53
+ end
54
+ end
55
+ if EXTDIR.exist?
56
+ Dir.chdir( EXTDIR ) do
57
+ Pathname.glob( EXTDIR + Config::CONFIG['DLEXT'] ) do |dl|
58
+ target = sitearch + dl.basename
59
+ FileUtils.install dl, target,
60
+ :mode => 0755, :verbose => true, :noop => $dryrun
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+
67
+
68
+ ### Task: install_gem
69
+ desc "Install #{PKG_NAME} from a locally-built gem"
70
+ task :install_gem => [:package] do
71
+ $stderr.puts
72
+ installer = Gem::Installer.new( %{pkg/#{PKG_FILE_NAME}.gem} )
73
+ installer.install
74
+ end
75
+
76
+
77
+ ### Task: uninstall
78
+ desc "Uninstall #{PKG_NAME} if it's been installed as a conventional library"
79
+ task :uninstall do
80
+ log "Uninstalling conventionally-installed #{PKG_NAME} library files"
81
+ sitelib = Pathname.new( CONFIG['sitelibdir'] )
82
+ sitearch = Pathname.new( CONFIG['sitearchdir'] )
83
+
84
+ Dir.chdir( LIBDIR ) do
85
+ LIB_FILES.each do |libfile|
86
+ relpath = libfile.relative_path_from( LIBDIR )
87
+ target = sitelib + relpath
88
+ FileUtils.rm_f target, :verbose => true, :noop => $dryrun
89
+ FileUtils.rm_rf( target.dirname, :verbose => true, :noop => $dryrun ) if
90
+ target.dirname.entries.empty?
91
+ end
92
+ end
93
+ if EXTDIR.exist?
94
+ Dir.chdir( EXTDIR ) do
95
+ Pathname.glob( EXTDIR + Config::CONFIG['DLEXT'] ) do |dl|
96
+ target = sitearch + dl.basename
97
+ FileUtils.rm target, :verbose => true, :noop => $dryrun
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+
104
+ ### Task: uninstall_gem
105
+ desc "Install the #{PKG_NAME} gem"
106
+ task :uninstall_gem => [:clean] do
107
+ uninstaller = Gem::Uninstaller.new( PKG_FILE_NAME )
108
+ uninstaller.uninstall
109
+ end
110
+
111
+
112
+