rote 0.1.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.
@@ -0,0 +1,66 @@
1
+ h2. Rote - A static website build tool for Ruby
2
+
3
+ *Rote is a simple page-based template system for your static website that was
4
+ written to make it easier to author and maintain non-dynamic websites and
5
+ offline documentation.* Rote provides a simple commandline or
6
+ "Rake":http://rake.rubyforge.org based build for your pages, with page
7
+ rendering (optionally supporting Textile and Markdown with
8
+ "RedCloth":http://redcloth.rubyforge.org/ and ruby code with
9
+ "ERB":http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html), layout,
10
+ and general documentation / website build tasks.
11
+
12
+ h3. Features
13
+
14
+ Rote offers the following major features:
15
+
16
+ * Simple set-up based on page templates and sections.
17
+ * ERB, Textile, and Markdown supported out of the box.
18
+ * Multiple configurable layouts apply boilerplate to your pages.
19
+ * 'Scoped' Ruby code support allows fine-grained control of data available across
20
+ all documentation, a subset, or individual pages.
21
+ * Can be used standalone (from the command-line) or from within "Rake":http://rake.rubyforge.org
22
+ as a custom task library.
23
+ * Supports any (text-based) format, while providing utilities and helpers for
24
+ common formats (HTML at present).
25
+
26
+ h3. So where is it?
27
+
28
+ The first release of Rote can be downloaded from "Our FRS on RubyForge":http://rubyforge.org/frs/?group_id=1120 .
29
+ It should be also available as a RubyGem (rote-0.1.0) in the usual way.
30
+ The "README":rdoc/files/README.html has the most comprehensive user guide at the moment. Obviously, this
31
+ site is still under construction too.
32
+
33
+ You can also grab the latest code from "CVS":http://rubyforge.org/cgi-bin/viewcvs.cgi/?cvsroot=rote.
34
+
35
+ Please note that Rote is still pretty new, and while this first release is fairly functional, it's
36
+ also still shiny and new, and liable to break down, destroy data, and run away with your spouse if
37
+ given half a chance. Check out the "Project page on Rubyforge":http://rubyforge.org/projects/rote
38
+ for everything you need to get going with the CVS version.
39
+
40
+ h3. Licence
41
+
42
+ <ul>
43
+ <pre>
44
+ <code>
45
+ Copyright (c) 2005 Ross Bamford (and contributors)
46
+
47
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
48
+ this software and associated documentation files (the "Software"), to deal in
49
+ the Software without restriction, including without limitation the rights to
50
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
51
+ of the Software, and to permit persons to whom the Software is furnished to do
52
+ so, subject to the following conditions:
53
+
54
+ The above copyright notice and this permission notice shall be included in all
55
+ copies or substantial portions of the Software.
56
+
57
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
58
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
59
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
60
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
61
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
62
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
63
+ SOFTWARE.
64
+ </code>
65
+ </pre>
66
+ </ul>
@@ -0,0 +1,4 @@
1
+ # the default
2
+ #layout 'page'
3
+
4
+ @page_title = 'Welcome!'
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,141 @@
1
+ /*
2
+ * (c)2005 Ross Bamford.
3
+ *
4
+ * rosco at roscopeco dot co dot uk
5
+ */
6
+ body {
7
+ background: #ffffff;
8
+ color: #000000;
9
+ font-family: arial, helvetica, sans-serif;
10
+ font-size: 10pt;
11
+ padding: 0px;
12
+ margin: 0px 0px 0px 0px;
13
+ }
14
+
15
+ a:link {
16
+ color: #cc3030;
17
+ text-decoration: none;
18
+ }
19
+
20
+ a:hover {
21
+ color: #df3b3b;
22
+ text-decoration: underline;
23
+ }
24
+
25
+ a:active {
26
+ color: #df3b3b;
27
+ text-decoration: underline;
28
+ }
29
+
30
+ a:visited {
31
+ color: #b02424;
32
+ text-decoration: none;
33
+ }
34
+
35
+ a#nav:link {
36
+ color: #cc3030;
37
+ text-decoration: none;
38
+ font-weight: bold;
39
+ background: auto;
40
+ }
41
+
42
+ a#nav:hover {
43
+ color: #df3b3b;
44
+ text-decoration: underline;
45
+ font-weight: bold;
46
+ background: #c3c3c3;
47
+ }
48
+
49
+ a#nav:active {
50
+ color: #df3b3b;
51
+ text-decoration: underline;
52
+ font-weight: bold;
53
+ background: #c3c3c3;
54
+ }
55
+
56
+ a#nav:visited {
57
+ color: #b02424;
58
+ text-decoration: none;
59
+ font-weight: bold;
60
+ background: auto;
61
+ }
62
+
63
+ /* outer div top bar on pages */
64
+ table.topbar {
65
+ background: #f5f5f5;
66
+ color: #000000;
67
+ width: 100%;
68
+ border: white thin none;
69
+ }
70
+
71
+ tr.topnav {
72
+ background: #ebebeb;
73
+ text-align: center;
74
+ padding: 5px;
75
+ }
76
+
77
+ td.toplogo {
78
+ text-align: left;
79
+ }
80
+
81
+ td.toprpotlogo {
82
+ text-align: right;
83
+ }
84
+
85
+ td.navicon {
86
+ width: 22px;
87
+ }
88
+
89
+ img.navicon {
90
+ border: white thin none;
91
+ width: 22px;
92
+ height: 22px;
93
+ }
94
+
95
+ /* ***************** */
96
+
97
+ div.frontcopyright {
98
+ /* Copyright bit on front page */
99
+ color: #909090;
100
+ position: absolute;
101
+ bottom: 2%;
102
+ right: 2%;
103
+ text-align: right;
104
+ font-size: 8pt;
105
+ }
106
+
107
+ div.copyright {
108
+ /* Copyright bit on pages */
109
+ color: #909090;
110
+ position: relative;
111
+ top: 5em;
112
+ right: 2%;
113
+ text-align: right;
114
+ font-size: 8pt;
115
+ }
116
+
117
+ div.main {
118
+ /* main div on front page */
119
+ width: 90%;
120
+ margin: 2% 2% 2% 2%;
121
+ }
122
+
123
+ img.smallrpotlogo {
124
+ width: 210px;
125
+ height: 47px;
126
+ }
127
+
128
+ img.biglogo {
129
+ width: 294px;
130
+ height: 135px;
131
+ }
132
+
133
+ img.medlogo {
134
+ width: 221px;
135
+ height: 101px;
136
+ }
137
+
138
+ img.smalllogo {
139
+ width: 147px;
140
+ height: 68px;
141
+ }
data/install.rb ADDED
@@ -0,0 +1,96 @@
1
+ puts <<-EOM
2
+ NOT YET SUPPORTED
3
+
4
+ Please copy 'bin' and 'lib' to a new directory, and set ROTE_HOME to
5
+ point there. Standard installation is not yet supported.
6
+ EOM
7
+
8
+ __END__
9
+ require 'rbconfig'
10
+ require 'find'
11
+ require 'ftools'
12
+
13
+ include Config
14
+
15
+ $ruby = CONFIG['ruby_install_name']
16
+
17
+ ##
18
+ # Install a binary file. We patch in on the way through to
19
+ # insert a #! line. If this is a Unix install, we name
20
+ # the command (for example) 'rake' and let the shebang line
21
+ # handle running it. Under windows, we add a '.rb' extension
22
+ # and let file associations to their stuff
23
+ #
24
+
25
+ def installBIN(from, opfile)
26
+
27
+ tmp_dir = nil
28
+ for t in [".", "/tmp", "c:/temp", $bindir]
29
+ stat = File.stat(t) rescue next
30
+ if stat.directory? and stat.writable?
31
+ tmp_dir = t
32
+ break
33
+ end
34
+ end
35
+
36
+ fail "Cannot find a temporary directory" unless tmp_dir
37
+ tmp_file = File.join(tmp_dir, "_tmp")
38
+
39
+ File.open(from) do |ip|
40
+ File.open(tmp_file, "w") do |op|
41
+ ruby = File.join($realbindir, $ruby)
42
+ op.puts "#!#{ruby} -w"
43
+ op.write ip.read
44
+ end
45
+ end
46
+
47
+ opfile += ".rb" if CONFIG["target_os"] =~ /mswin/i
48
+ File::install(tmp_file, File.join($bindir, opfile), 0755, true)
49
+ File::unlink(tmp_file)
50
+ end
51
+
52
+ $sitedir = CONFIG["sitelibdir"]
53
+ unless $sitedir
54
+ version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
55
+ $libdir = File.join(CONFIG["libdir"], "ruby", version)
56
+ $sitedir = $:.find {|x| x =~ /site_ruby/}
57
+ if !$sitedir
58
+ $sitedir = File.join($libdir, "site_ruby")
59
+ elsif $sitedir !~ Regexp.quote(version)
60
+ $sitedir = File.join($sitedir, version)
61
+ end
62
+ end
63
+
64
+ $bindir = CONFIG["bindir"]
65
+
66
+ $realbindir = $bindir
67
+
68
+ bindir = CONFIG["bindir"]
69
+ if (destdir = ENV['DESTDIR'])
70
+ $bindir = destdir + $bindir
71
+ $sitedir = destdir + $sitedir
72
+
73
+ File::makedirs($bindir)
74
+ File::makedirs($sitedir)
75
+ end
76
+
77
+ rote_dest = File.join($sitedir, "rote")
78
+ File::makedirs(rote_dest, true)
79
+ File::chmod(0755, rote_dest)
80
+
81
+ # The library files
82
+
83
+ files = Dir.chdir('lib') { Dir['**/*.rb'] }
84
+
85
+ for fn in files
86
+ fn_dir = File.dirname(fn)
87
+ target_dir = File.join($sitedir, fn_dir)
88
+ if ! File.exist?(target_dir)
89
+ File.makedirs(target_dir)
90
+ end
91
+ File::install(File.join('lib', fn), File.join($sitedir, fn), 0644, true)
92
+ end
93
+
94
+ # and the executable
95
+
96
+ installBIN("bin/rote", "rote")
data/lib/rote/app.rb ADDED
@@ -0,0 +1,112 @@
1
+ require 'getoptlong'
2
+
3
+ module Rote
4
+
5
+ # Command-line launcher for Rote.
6
+ class Application
7
+ attr_accessor :rote_bin
8
+ attr_accessor :rote_lib
9
+ attr_accessor :debug
10
+ attr_accessor :tasks
11
+ attr_accessor :trace
12
+ attr_accessor :usage
13
+ attr_accessor :version
14
+ attr_accessor :rake
15
+ attr_accessor :rakefile
16
+ attr_accessor :rakeopts
17
+
18
+ # Create a new Application instance, processing command-line arguments,
19
+ # optionally passing +self+ to the supplied block for further
20
+ # configuration.
21
+ def initialize(rote_bin, rote_lib) # :yield: self if block_given?
22
+ # init vars
23
+ @rote_bin = rote_bin
24
+ @rote_lib = rote_lib || rote_bin
25
+ @debug = false
26
+ @tasks = false
27
+ @trace = false
28
+ @usage = false
29
+ @version = false
30
+
31
+ @rakefile = File.exists?('Rakefile') ? 'Rakefile' : "#{rote_lib}/builtin.rf"
32
+ @rakeopts = ENV['RAKE_OPTS'] || ''
33
+ @rake = ENV['RAKE_CMD'] || 'rake'
34
+
35
+ process_args
36
+
37
+ yield self if block_given?
38
+ end
39
+
40
+ # Run the application with the current options.
41
+ def run
42
+ if @version
43
+ print "rote, version #{ROTEVERSION}\n"
44
+
45
+ elsif @tasks
46
+ print `#{rake} --rakefile=#{rakefile} --libdir=#{rote_lib} --tasks`.gsub(/^rake /,'rote ')
47
+
48
+ elsif @usage
49
+ show_usage()
50
+
51
+ else
52
+ if @trace
53
+ rakeopts << ' --trace'
54
+ elsif @debug
55
+ rakeopts << '--verbose'
56
+ end
57
+
58
+ exec("#{rake} --rakefile=#{rakefile} --libdir=#{rote_lib} #{rakeopts} #{$*.join(' ')}")
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ # Display help text
65
+ def show_usage
66
+ print <<-EOM
67
+ Usage: rote [options] [task1] .. [taskN]
68
+
69
+ Where [taskN] is a valid task or target name for the current project.
70
+ Rite generates targets for each page source, and also defines a number
71
+ of top-level tasks for various things. Use the '--tasks' option to get
72
+ a list of valid tasks.
73
+
74
+ Recognised options are:
75
+
76
+ --tasks -T Display a list of tasks in this project.
77
+ --debug -d Enable debugging information.
78
+ --trace -t Enables verbose debugging information.
79
+ --usage -u Display this help message and quit
80
+ --help -h Synonym for --usage
81
+ --version -v Display Rote's version and quit
82
+
83
+ The 'rote' command is implemented as a wrapper around Rake, and
84
+ requires the 'rake' command be in your path. You can circumvent this
85
+ by setting the RAKE_CMD environment variable appropriately.
86
+ Additional options can be passed to Rake via the RAKE_OPTS variable.
87
+
88
+ Depending on your environment, you may need to set ROTE_HOME to point
89
+ to the installation directory.
90
+ EOM
91
+ end
92
+
93
+ # Process commandline
94
+ def process_args
95
+ GetoptLong.new(
96
+ [ "--debug", "-d", GetoptLong::NO_ARGUMENT ],
97
+ [ "--tasks", "-T", GetoptLong::NO_ARGUMENT ],
98
+ [ "--trace", "-x", GetoptLong::NO_ARGUMENT ],
99
+ [ "--usage", "-u", GetoptLong::NO_ARGUMENT ],
100
+ [ "--help", "-h", GetoptLong::NO_ARGUMENT ],
101
+ [ "--version", "-v", GetoptLong::NO_ARGUMENT ]
102
+ ).each { |opt,arg|
103
+ @debug = true if opt == '--debug'
104
+ @trace = true if opt == '--trace'
105
+ @tasks = true if opt == '--tasks'
106
+ @usage = true if opt == '--usage' || opt == '--help'
107
+ @version = true if opt == '--version'
108
+ }
109
+ end
110
+
111
+ end # Application
112
+ end # Rote
@@ -0,0 +1,42 @@
1
+ module Rote
2
+
3
+ # An extension to the Rake +FileList+ class that allows a root
4
+ # directory to be specified.
5
+ class DirectoryFileList < FileList
6
+
7
+ # Create a +DirectoryFileList+ with optional root directory and
8
+ # patterns. You may also pass a block to perform additional
9
+ # configuration (e.g. if you have a lot of includes/excludes
10
+ # or just don't like arguments for whatever reason).
11
+ def initialize(basedir = '.', *patterns)
12
+ dir=(basedir)
13
+ super(*patterns)
14
+ end
15
+
16
+ # The root directory from which this filelist matches. All patterns
17
+ # are considered relative to this directory.
18
+ attr_accessor :dir
19
+ def dir=(newdir)
20
+ newdir = newdir.sub(/\/$/,'')
21
+ sub!(/^#{@dir}/,newdir)
22
+ @dir = newdir
23
+ end
24
+
25
+ # Adds the specified *shell glob* pattern(s) to the list of includes
26
+ # for this file list. The base directory is implied.
27
+ def include(*patterns)
28
+ super(*patterns.map { |it| "#{dir}/#{it}"})
29
+ end
30
+
31
+ # Adds the specified *regexp or shell glob* pattern(s) to the list of
32
+ # excludes for this file list. The base directory is implied on
33
+ # non-+Regexp+.arguments.
34
+ def exclude(*patterns)
35
+ # exclude takes regexps too, which we should leave alone.
36
+ super(*patterns.map { |it|
37
+ it.is_a?(String) ? "#{dir}/#{it}" : it
38
+ })
39
+ end
40
+ end
41
+
42
+ end
data/lib/rote/page.rb ADDED
@@ -0,0 +1,184 @@
1
+ require 'erb'
2
+ require 'rubygems'
3
+
4
+ require_gem('RedCloth')
5
+
6
+ module Rote
7
+
8
+ #####
9
+ ## A +Page+ object represents an individual page, taking input from a
10
+ ## template and (optionally) some ruby code, and producing rendered
11
+ ## ('merged') output as a +String+.
12
+ ## When a page is created, ruby source will be found alongside the
13
+ ## file, with same basename and an '.rb' extension. If found it will
14
+ ## run through +instance_eval+. That source can call methods
15
+ ## and set any instance variables, for use later in the template.
16
+ ##
17
+ ## Rendering happens only once for a given page object, when the
18
+ ## to_html method is first called. Once a page has been rendered
19
+ ## it is frozen.
20
+ class Page
21
+ # The text of the template to use for this page.
22
+ attr_reader :template_text
23
+
24
+ # The text of the layout to use for this page. This is read in
25
+ # when (if) the page source calls layout(basename).
26
+ attr_reader :layout_text
27
+
28
+ # Formatting options passed to RedCloth. This is an array of the
29
+ # option symbols defined by RedCloth.
30
+ # The most common are :textile and :markdown. See RedCloth
31
+ # documentation for full details of supported options.
32
+ #
33
+ # The default is [], which means 'No formatting'. This setting
34
+ # does not affect ERB rendering (which is always performed, before
35
+ # any formatting).
36
+ attr_accessor :format_opts
37
+ def format_opts=(opts)
38
+ if !opts.nil? && opts.respond_to?(:to_ary)
39
+ @format_opts = opts
40
+ else
41
+ @format_opts = [opts]
42
+ end
43
+ end
44
+
45
+ # Reads the template, and evaluates the global and page scripts, if
46
+ # available, using the current binding. You may define any instance
47
+ # variables or methods you like in that code for use in the template,
48
+ # as well as accessing the predefined @template and @template_text
49
+ # variables.
50
+ #
51
+ # If specified, the layout path will be used to find layouts referenced
52
+ # from templates.
53
+ #
54
+ # If a block is supplied, it is executed _after_ the global / page
55
+ # code, so you can locally override variables and so on.
56
+ def initialize(template_fn,
57
+ layout_path = File.dirname(template_fn),
58
+ default_layout_ext = File.extname(template_fn)) # :yield: self if block_given?
59
+ @template_text = nil
60
+ @layout_text = nil
61
+ @content_for_layout = nil
62
+ @result = nil
63
+ @format_opts = []
64
+ @layout_defext = default_layout_ext
65
+ @layout_path = layout_path
66
+ @fixme_dir = File.dirname(template_fn)
67
+
68
+ # read in the template. Layout _may_ get configured later in page code
69
+ read_template(template_fn)
70
+
71
+ # get script filenames, and eval them if found
72
+ src_rb = template_fn.sub(/\..*$/,'') + '.rb'
73
+ section_rb = @fixme_dir + '/COMMON.rb'
74
+ instance_eval(File.read(section_rb)) if File.exists?(section_rb)
75
+ instance_eval(File.read(src_rb)) if File.exists?(src_rb)
76
+
77
+ # Allow block to have the final say
78
+ yield self if block_given?
79
+ end
80
+
81
+ # Sets the layout from the specified file, or disables layout if
82
+ # +nil+ is passed in. The specified basename should be the name
83
+ # of the layout file relative to the +layout_dir+, with no extension.
84
+ #
85
+ # The layout is read by this method. An exception is
86
+ # thrown if the layout doesn't exist.
87
+ #
88
+ # This can only be called before the first call to +render+. After
89
+ # that the instance is frozen.
90
+ def layout(basename)
91
+ if basename
92
+ fn = layout_fn(basename)
93
+ raise "Layout #{fn} not found" unless File.exists?(fn)
94
+ @layout_text = File.read(fn)
95
+ else
96
+ @layout_text = nil
97
+ end
98
+ end
99
+
100
+ # Render this page's textile and ERB, and apply layout.
101
+ # This is only done once - after that, it's cached for next time. You can
102
+ # also circumvent rendering by setting @result yourself in your page's ruby.
103
+ def render
104
+ @result or do_render! # sets up result for next time...
105
+ end
106
+
107
+ alias to_s render
108
+
109
+ private
110
+
111
+ # Sets the template from the specified file, or clears the template if
112
+ # +nil+ is passed in. The specified basename should be the name
113
+ # of the layout file relative to the +layout_dir+, with no extension.
114
+ def read_template(fn)
115
+ if fn
116
+ raise "Template #{fn} not found" unless File.exists?(fn)
117
+ @template_text = File.read(fn)
118
+ else
119
+ @template_text = nil
120
+ end
121
+ end
122
+
123
+ # render, set up @result for next time. Return result too.
124
+ def do_render!
125
+ # Render the page content into the @content_for_layout
126
+ if !@template_text.nil?
127
+ ctl = ERB.new(@template_text).result(binding)
128
+
129
+ @content_for_layout =
130
+ if @format_opts && ((@format_opts.respond_to?(:to_ary) && (!@format_opts.empty?)) || @format_opts.is_a?(Symbol))
131
+ opts = @format_opts.respond_to?(:to_ary) ? @format_opts : [@format_opts]
132
+ RedCloth.new(ctl).to_html(*opts)
133
+ else
134
+ ctl
135
+ end
136
+ end
137
+
138
+ # render into the layout if supplied.
139
+ @result = if !@layout_text.nil?
140
+ ERB.new(@layout_text).result(binding)
141
+ else
142
+ @content_for_layout
143
+ end
144
+
145
+ freeze
146
+ @result
147
+ end
148
+
149
+ # Get a full layout filename from a basename. If the basename has no extension,
150
+ # the default extension is added.
151
+ def layout_fn(basename)
152
+ ext = File.extname(basename)
153
+ "#{@layout_path}/#{basename}#{@layout_defext if ext.empty?}"
154
+ end
155
+
156
+ # FIXME NASTY HACK: Allow templates to inherit COMMON.rb. This should be replaced
157
+ # with a proper search for inherited in Page.new. Call from your COMMON.rb to
158
+ # inherit the COMMON.rb immediately above this. If none exists there, this doesn't go
159
+ # looking beyond that - it just returns false
160
+ def inherit_common
161
+ inh = "#{@fixme_dir}/../COMMON.rb"
162
+ if File.exists?(inh)
163
+ instance_eval(File.read(inh))
164
+ true
165
+ else
166
+ false
167
+ end
168
+ end
169
+
170
+ # FIXME NASTY HACK II: relative links (doesn't work)
171
+ def link_rel(href)
172
+ thr = href
173
+ if thr.is_a?(String) && href[0,1] == '/'
174
+ thr = href[1..href.length]
175
+ count = @fixme_dir.split('/').length - 2
176
+ if count > 0 then count.times {
177
+ thr = '../' + thr
178
+ } end
179
+ end
180
+ thr
181
+ end
182
+
183
+ end #class
184
+ end #module