Shazburg-webby 0.9.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.
- data/History.txt +176 -0
- data/Manifest.txt +171 -0
- data/README.txt +92 -0
- data/Rakefile +54 -0
- data/bin/webby +8 -0
- data/bin/webby-gen +8 -0
- data/examples/blog/Sitefile +7 -0
- data/examples/blog/tasks/blog.rake +72 -0
- data/examples/blog/templates/atom_feed.erb +40 -0
- data/examples/blog/templates/blog/month.erb +22 -0
- data/examples/blog/templates/blog/post.erb +16 -0
- data/examples/blog/templates/blog/year.erb +22 -0
- data/examples/presentation/Sitefile +10 -0
- data/examples/presentation/content/css/uv/twilight.css +137 -0
- data/examples/presentation/content/presentation/_sample_code.txt +10 -0
- data/examples/presentation/content/presentation/index.txt +63 -0
- data/examples/presentation/content/presentation/s5/blank.gif +0 -0
- data/examples/presentation/content/presentation/s5/bodybg.gif +0 -0
- data/examples/presentation/content/presentation/s5/framing.css +23 -0
- data/examples/presentation/content/presentation/s5/iepngfix.htc +42 -0
- data/examples/presentation/content/presentation/s5/opera.css +7 -0
- data/examples/presentation/content/presentation/s5/outline.css +15 -0
- data/examples/presentation/content/presentation/s5/pretty.css +86 -0
- data/examples/presentation/content/presentation/s5/print.css +1 -0
- data/examples/presentation/content/presentation/s5/s5-core.css +9 -0
- data/examples/presentation/content/presentation/s5/slides.css +3 -0
- data/examples/presentation/content/presentation/s5/slides.js +553 -0
- data/examples/presentation/layouts/presentation.txt +43 -0
- data/examples/presentation/templates/_code_partial.erb +13 -0
- data/examples/presentation/templates/presentation.erb +40 -0
- data/examples/tumblog/Sitefile +9 -0
- data/examples/tumblog/content/css/tumblog.css +308 -0
- data/examples/tumblog/content/images/tumblog/permalink.gif +0 -0
- data/examples/tumblog/content/images/tumblog/rss.gif +0 -0
- data/examples/tumblog/content/tumblog/200806/the-noble-chicken/index.txt +12 -0
- data/examples/tumblog/content/tumblog/200807/historical-perspectives-on-the-classic-chicken-joke/index.txt +12 -0
- data/examples/tumblog/content/tumblog/200807/mad-city-chickens/index.txt +10 -0
- data/examples/tumblog/content/tumblog/200807/the-wisdom-of-the-dutch/index.txt +11 -0
- data/examples/tumblog/content/tumblog/200807/up-a-tree/index.txt +13 -0
- data/examples/tumblog/content/tumblog/index.txt +37 -0
- data/examples/tumblog/content/tumblog/rss.txt +37 -0
- data/examples/tumblog/layouts/tumblog/default.txt +44 -0
- data/examples/tumblog/layouts/tumblog/post.txt +15 -0
- data/examples/tumblog/lib/tumblog_helper.rb +32 -0
- data/examples/tumblog/tasks/tumblog.rake +30 -0
- data/examples/tumblog/templates/atom_feed.erb +40 -0
- data/examples/tumblog/templates/tumblog/conversation.erb +12 -0
- data/examples/tumblog/templates/tumblog/link.erb +10 -0
- data/examples/tumblog/templates/tumblog/photo.erb +13 -0
- data/examples/tumblog/templates/tumblog/post.erb +12 -0
- data/examples/tumblog/templates/tumblog/quote.erb +11 -0
- data/examples/webby/Sitefile +19 -0
- data/examples/webby/content/css/background.gif +0 -0
- data/examples/webby/content/css/blueprint/print.css +76 -0
- data/examples/webby/content/css/blueprint/screen.css +696 -0
- data/examples/webby/content/css/coderay.css +96 -0
- data/examples/webby/content/css/site.css +184 -0
- data/examples/webby/content/css/uv/twilight.css +137 -0
- data/examples/webby/content/index.txt +37 -0
- data/examples/webby/content/manual/index.txt +430 -0
- data/examples/webby/content/reference/index.txt +202 -0
- data/examples/webby/content/release-notes/rel-0-9-0/index.txt +73 -0
- data/examples/webby/content/robots.txt +6 -0
- data/examples/webby/content/script/jquery.corner.js +152 -0
- data/examples/webby/content/script/jquery.js +31 -0
- data/examples/webby/content/sitemap.txt +31 -0
- data/examples/webby/content/tips_and_tricks/index.txt +96 -0
- data/examples/webby/content/tutorial/index.txt +131 -0
- data/examples/webby/layouts/default.txt +55 -0
- data/examples/webby/templates/page.erb +10 -0
- data/examples/website/Sitefile +7 -0
- data/examples/website/content/css/blueprint/License.txt +21 -0
- data/examples/website/content/css/blueprint/Readme.txt +100 -0
- data/examples/website/content/css/blueprint/compressed/print.css +76 -0
- data/examples/website/content/css/blueprint/compressed/screen.css +696 -0
- data/examples/website/content/css/blueprint/lib/forms.css +45 -0
- data/examples/website/content/css/blueprint/lib/grid.css +193 -0
- data/examples/website/content/css/blueprint/lib/grid.png +0 -0
- data/examples/website/content/css/blueprint/lib/ie.css +30 -0
- data/examples/website/content/css/blueprint/lib/reset.css +39 -0
- data/examples/website/content/css/blueprint/lib/typography.css +116 -0
- data/examples/website/content/css/blueprint/plugins/buttons/Readme +31 -0
- data/examples/website/content/css/blueprint/plugins/buttons/buttons.css +97 -0
- data/examples/website/content/css/blueprint/plugins/buttons/icons/cross.png +0 -0
- data/examples/website/content/css/blueprint/plugins/buttons/icons/key.png +0 -0
- data/examples/website/content/css/blueprint/plugins/buttons/icons/tick.png +0 -0
- data/examples/website/content/css/blueprint/plugins/css-classes/Readme +14 -0
- data/examples/website/content/css/blueprint/plugins/css-classes/css-classes.css +24 -0
- data/examples/website/content/css/blueprint/plugins/fancy-type/Readme +22 -0
- data/examples/website/content/css/blueprint/plugins/fancy-type/fancy-type-compressed.css +5 -0
- data/examples/website/content/css/blueprint/plugins/fancy-type/fancy-type.css +74 -0
- data/examples/website/content/css/blueprint/print.css +68 -0
- data/examples/website/content/css/blueprint/screen.css +22 -0
- data/examples/website/content/css/coderay.css +111 -0
- data/examples/website/content/css/site.css +67 -0
- data/examples/website/content/index.txt +19 -0
- data/examples/website/layouts/default.txt +58 -0
- data/examples/website/lib/breadcrumbs.rb +28 -0
- data/examples/website/templates/_partial.erb +10 -0
- data/examples/website/templates/page.erb +18 -0
- data/examples/website/templates/presentation.erb +40 -0
- data/lib/webby.rb +227 -0
- data/lib/webby/apps.rb +12 -0
- data/lib/webby/apps/generator.rb +283 -0
- data/lib/webby/apps/main.rb +221 -0
- data/lib/webby/auto_builder.rb +83 -0
- data/lib/webby/builder.rb +183 -0
- data/lib/webby/core_ext/enumerable.rb +11 -0
- data/lib/webby/core_ext/hash.rb +28 -0
- data/lib/webby/core_ext/kernel.rb +21 -0
- data/lib/webby/core_ext/string.rb +163 -0
- data/lib/webby/core_ext/time.rb +9 -0
- data/lib/webby/filters.rb +91 -0
- data/lib/webby/filters/basepath.rb +97 -0
- data/lib/webby/filters/erb.rb +9 -0
- data/lib/webby/filters/haml.rb +18 -0
- data/lib/webby/filters/markdown.rb +16 -0
- data/lib/webby/filters/outline.rb +308 -0
- data/lib/webby/filters/sass.rb +17 -0
- data/lib/webby/filters/slides.rb +56 -0
- data/lib/webby/filters/textile.rb +16 -0
- data/lib/webby/filters/tidy.rb +76 -0
- data/lib/webby/helpers.rb +30 -0
- data/lib/webby/helpers/capture_helper.rb +141 -0
- data/lib/webby/helpers/coderay_helper.rb +69 -0
- data/lib/webby/helpers/graphviz_helper.rb +136 -0
- data/lib/webby/helpers/tag_helper.rb +65 -0
- data/lib/webby/helpers/tex_img_helper.rb +133 -0
- data/lib/webby/helpers/ultraviolet_helper.rb +63 -0
- data/lib/webby/helpers/url_helper.rb +235 -0
- data/lib/webby/link_validator.rb +152 -0
- data/lib/webby/renderer.rb +379 -0
- data/lib/webby/resources.rb +96 -0
- data/lib/webby/resources/db.rb +251 -0
- data/lib/webby/resources/file.rb +221 -0
- data/lib/webby/resources/layout.rb +63 -0
- data/lib/webby/resources/page.rb +118 -0
- data/lib/webby/resources/partial.rb +79 -0
- data/lib/webby/resources/resource.rb +160 -0
- data/lib/webby/resources/static.rb +52 -0
- data/lib/webby/stelan/mktemp.rb +135 -0
- data/lib/webby/stelan/paginator.rb +150 -0
- data/lib/webby/stelan/spawner.rb +339 -0
- data/lib/webby/tasks/build.rake +27 -0
- data/lib/webby/tasks/create.rake +22 -0
- data/lib/webby/tasks/deploy.rake +22 -0
- data/lib/webby/tasks/growl.rake +15 -0
- data/lib/webby/tasks/heel.rake +28 -0
- data/lib/webby/tasks/validate.rake +19 -0
- data/spec/core_ext/hash_spec.rb +47 -0
- data/spec/core_ext/string_spec.rb +110 -0
- data/spec/core_ext/time_spec.rb +19 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/webby/apps/generator_spec.rb +111 -0
- data/spec/webby/apps/main_spec.rb +75 -0
- data/spec/webby/helpers/capture_helper_spec.rb +56 -0
- data/spec/webby/resources/file_spec.rb +104 -0
- data/spec/webby/resources_spec.rb +17 -0
- data/tasks/ann.rake +81 -0
- data/tasks/bones.rake +21 -0
- data/tasks/gem.rake +126 -0
- data/tasks/git.rake +41 -0
- data/tasks/manifest.rake +49 -0
- data/tasks/notes.rake +28 -0
- data/tasks/post_load.rake +39 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +57 -0
- data/tasks/setup.rb +268 -0
- data/tasks/spec.rake +55 -0
- data/tasks/website.rake +38 -0
- metadata +287 -0
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'hpricot'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module Webby
|
5
|
+
|
6
|
+
# The Webby LinkValidator class is used to validate the hyperlinks of all
|
7
|
+
# the HTML files in the output directory. By default, only links to other
|
8
|
+
# pages in the output directory are checked. However, setting the
|
9
|
+
# :external flag to +true+ will cause hyperlinks to external web sites to
|
10
|
+
# be validated as well.
|
11
|
+
#
|
12
|
+
class LinkValidator
|
13
|
+
|
14
|
+
# A lazy man's method that will instantiate a new link validator and run
|
15
|
+
# the validations.
|
16
|
+
#
|
17
|
+
def self.validate( opts = {} )
|
18
|
+
new(opts).validate
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_accessor :validate_externals
|
22
|
+
|
23
|
+
# call-seq:
|
24
|
+
# LinkValidator.new( opts = {} )
|
25
|
+
#
|
26
|
+
# Creates a new LinkValidator object. The only supported option is the
|
27
|
+
# :external flag. When set to +true+, the link validator will also check
|
28
|
+
# out links to external websites. This is done by opening a connection to
|
29
|
+
# the remote site and pulling down the page specified in the hyperlink.
|
30
|
+
# Use with caution.
|
31
|
+
#
|
32
|
+
def initialize( opts = {} )
|
33
|
+
@log = Logging::Logger[self]
|
34
|
+
|
35
|
+
glob = ::File.join(::Webby.site.output_dir, '**', '*.html')
|
36
|
+
@files = Dir.glob(glob).sort
|
37
|
+
@attr_rgxp = %r/\[@(\w+)\]$/o
|
38
|
+
|
39
|
+
@validate_externals = opts.getopt(:external, false)
|
40
|
+
@valid_uris = ::Webby.site.valid_uris.flatten
|
41
|
+
@invalid_uris = []
|
42
|
+
end
|
43
|
+
|
44
|
+
# Iterate over all the HTML files in the output directory and validate the
|
45
|
+
# hyperlinks.
|
46
|
+
#
|
47
|
+
def validate
|
48
|
+
@files.each {|fn| check_file fn}
|
49
|
+
end
|
50
|
+
|
51
|
+
# Check the given file (identified by its filename {fn for short here}) by
|
52
|
+
# iterating through all the configured xpaths and validating that those
|
53
|
+
# hyperlinks ae valid.
|
54
|
+
#
|
55
|
+
def check_file( fn )
|
56
|
+
@log.info "validating #{fn}"
|
57
|
+
|
58
|
+
dir = ::File.dirname(fn)
|
59
|
+
@doc = Hpricot(::File.read(fn))
|
60
|
+
|
61
|
+
::Webby.site.xpaths.each do |xpath|
|
62
|
+
@attr_name = nil
|
63
|
+
|
64
|
+
@doc.search(xpath).each do |element|
|
65
|
+
@attr_name ||= @attr_rgxp.match(xpath)[1]
|
66
|
+
uri = URI.parse(element.get_attribute(@attr_name))
|
67
|
+
validate_uri(uri, dir)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
@doc = @attr_name = nil
|
71
|
+
end
|
72
|
+
|
73
|
+
# Validate the the page the _uri_ refers to actually exists. The directory
|
74
|
+
# of the current page being processed is needed in order to resolve
|
75
|
+
# relative paths.
|
76
|
+
#
|
77
|
+
# If the _uri_ is a relative path, then the output directory is searched
|
78
|
+
# for the appropriate page. If the _uri_ is an absolute path, then the
|
79
|
+
# remote server is contacted and the page requested from the server. This
|
80
|
+
# will only take place if the LinkValidator was created with the :external
|
81
|
+
# flag set to true.
|
82
|
+
#
|
83
|
+
def validate_uri( uri, dir )
|
84
|
+
# for relative URIs, we can see if the file exists in the output folder
|
85
|
+
if uri.relative?
|
86
|
+
return validate_anchor(uri, @doc) if uri.path.empty?
|
87
|
+
|
88
|
+
path = if uri.path =~ %r/^\//
|
89
|
+
::File.join(::Webby.site.output_dir, uri.path)
|
90
|
+
else
|
91
|
+
::File.join(dir, uri.path)
|
92
|
+
end
|
93
|
+
path = ::File.join(path, 'index.html') if ::File.extname(path).empty?
|
94
|
+
|
95
|
+
uri_str = path.dup
|
96
|
+
(uri_str << '#' << uri.fragment) if uri.fragment
|
97
|
+
return if @valid_uris.include? uri_str
|
98
|
+
|
99
|
+
if test ?f, path
|
100
|
+
valid = if uri.fragment
|
101
|
+
validate_anchor(uri, Hpricot(::File.read(path)))
|
102
|
+
else true end
|
103
|
+
@valid_uris << uri_str if valid
|
104
|
+
else
|
105
|
+
@log.error "invalid URI '#{uri.to_s}'"
|
106
|
+
end
|
107
|
+
|
108
|
+
# if the URI responds to the open mehod, then try to access the URI
|
109
|
+
elsif uri.respond_to? :open
|
110
|
+
return unless @validate_externals
|
111
|
+
return if @valid_uris.include? uri.to_s
|
112
|
+
|
113
|
+
if @invalid_uris.include? uri.to_s
|
114
|
+
@log.error "could not open URI '#{uri.to_s}'"
|
115
|
+
return
|
116
|
+
end
|
117
|
+
|
118
|
+
begin
|
119
|
+
uri.open {|_| nil}
|
120
|
+
@valid_uris << uri.to_s
|
121
|
+
rescue Exception
|
122
|
+
@log.error "could not open URI '#{uri.to_s}'"
|
123
|
+
@invalid_uris << uri.to_s
|
124
|
+
end
|
125
|
+
|
126
|
+
# otherwise, post a warning that the URI could not be validated
|
127
|
+
else
|
128
|
+
return if @valid_uris.include? uri.to_s
|
129
|
+
@log.warn "could not validate URI '#{uri.to_s}'"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Validate that the anchor fragment of the URI exists in the given
|
134
|
+
# document. The document is an Hpricot document object.
|
135
|
+
#
|
136
|
+
# Returns +true+ if the anchor exists in the document and +false+ if it
|
137
|
+
# does not.
|
138
|
+
#
|
139
|
+
def validate_anchor( uri, doc )
|
140
|
+
return false if uri.fragment.nil?
|
141
|
+
|
142
|
+
anchor = '#' + uri.fragment
|
143
|
+
if doc.at(anchor).nil?
|
144
|
+
@log.error "invalid URI '#{uri.to_s}'"
|
145
|
+
false
|
146
|
+
else true end
|
147
|
+
end
|
148
|
+
|
149
|
+
end # class LinkValidator
|
150
|
+
end # module Webby
|
151
|
+
|
152
|
+
# EOF
|
@@ -0,0 +1,379 @@
|
|
1
|
+
# Equivalent to a header guard in C/C++
|
2
|
+
# Used to prevent the spec helper from being loaded more than once
|
3
|
+
unless defined? ::Webby::Renderer
|
4
|
+
|
5
|
+
require 'erb'
|
6
|
+
|
7
|
+
module Webby
|
8
|
+
|
9
|
+
# The Webby::Renderer is used to _filter_ and _layout_ the text found in the
|
10
|
+
# resource page files in the content directory.
|
11
|
+
#
|
12
|
+
# A page is filtered based on the settings of the 'filter' option in the
|
13
|
+
# page's meta-data information. For example, if 'textile' is specified as
|
14
|
+
# a filter, then the page will be run through the RedCloth markup filter.
|
15
|
+
# More than one filter can be used on a page; they will be run in the
|
16
|
+
# order specified in the meta-data.
|
17
|
+
#
|
18
|
+
# A page is rendered into a layout specified by the 'layout' option in the
|
19
|
+
# page's meta-data information.
|
20
|
+
#
|
21
|
+
class Renderer
|
22
|
+
include ERB::Util
|
23
|
+
|
24
|
+
# :stopdoc:
|
25
|
+
@@stack = []
|
26
|
+
# :startdoc:
|
27
|
+
|
28
|
+
# call-seq:
|
29
|
+
# Renderer.write( page )
|
30
|
+
#
|
31
|
+
# Render the given _page_ and write the resulting output to the page's
|
32
|
+
# destination. If the _page_ uses pagination, then multiple destination
|
33
|
+
# files will be created -- one for each paginated data set in the page.
|
34
|
+
#
|
35
|
+
def self.write( page )
|
36
|
+
renderer = self.new(page)
|
37
|
+
|
38
|
+
loop {
|
39
|
+
::File.open(page.destination, 'w') do |fd|
|
40
|
+
fd.write(renderer._layout_page)
|
41
|
+
end
|
42
|
+
break unless renderer._next_page
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
# call-seq:
|
47
|
+
# Renderer.new( page )
|
48
|
+
#
|
49
|
+
# Create a new renderer for the given _page_. The renderer will apply the
|
50
|
+
# desired filters to the _page_ (from the page's meta-data) and then
|
51
|
+
# render the filtered page into the desired layout.
|
52
|
+
#
|
53
|
+
def initialize( page )
|
54
|
+
unless page.instance_of? Resources::Page
|
55
|
+
raise ArgumentError,
|
56
|
+
"only page resources can be rendered '#{page.path}'"
|
57
|
+
end
|
58
|
+
|
59
|
+
@page = page
|
60
|
+
@pages = Resources.pages
|
61
|
+
@partials = Resources.partials
|
62
|
+
@content = nil
|
63
|
+
@config = ::Webby.site
|
64
|
+
|
65
|
+
@_bindings = []
|
66
|
+
@_content_for = {}
|
67
|
+
@log = Logging::Logger[self]
|
68
|
+
end
|
69
|
+
|
70
|
+
# call-seq:
|
71
|
+
# render( resource = nil, opts = {} ) => string
|
72
|
+
#
|
73
|
+
# Render the given resource (a page or a partial) and return the results
|
74
|
+
# as a string. If a resource is not given, then the options hash should
|
75
|
+
# contain the name of a partial to render (:partial => 'name').
|
76
|
+
#
|
77
|
+
# When a partial name is given, the partial is found by looking in the
|
78
|
+
# directory of the current page being rendered. Otherwise, the full path
|
79
|
+
# to the partial can be given.
|
80
|
+
#
|
81
|
+
# If a :guard option is given as true, then the resulting string will be
|
82
|
+
# protected from processing by subsequent filters. Currently this only
|
83
|
+
# protects against the textile filter.
|
84
|
+
#
|
85
|
+
# When rendering partials, local variables can be passed to the partial by
|
86
|
+
# setting them in hash passed as the :locals option.
|
87
|
+
#
|
88
|
+
# ==== Options
|
89
|
+
# :partial<String>::
|
90
|
+
# The partial to render
|
91
|
+
# :locals<Hash>::
|
92
|
+
# Locals values to define when rendering a partial
|
93
|
+
# :guard<Boolean>::
|
94
|
+
# Prevents the resulting string from being processed by subsequent
|
95
|
+
# filters (only textile for now)
|
96
|
+
#
|
97
|
+
# ==== Returns
|
98
|
+
# A string that is the rendered page or partial.
|
99
|
+
#
|
100
|
+
# ==== Examples
|
101
|
+
# # render the partial "foo" using the given local variables
|
102
|
+
# render( :partial => "foo", :locals => {:bar => "value for bar"} )
|
103
|
+
#
|
104
|
+
# # find another page and render it into this page and protect the
|
105
|
+
# # resulting contents from further filters
|
106
|
+
# page = @pages.find( :title => "Chicken Coop" )
|
107
|
+
# render( page, :guard => true )
|
108
|
+
#
|
109
|
+
# # find a partial and render it using the given local variables
|
110
|
+
# partial = @partials.find( :filename => "foo", :in_directory => "/path" )
|
111
|
+
# render( partial, :locals => {:baz => "baztastic"} )
|
112
|
+
#
|
113
|
+
def render( *args )
|
114
|
+
opts = Hash === args.last ? args.pop : {}
|
115
|
+
resource = args.first
|
116
|
+
resource = _find_partial(opts[:partial]) if resource.nil?
|
117
|
+
|
118
|
+
str = case resource
|
119
|
+
when Resources::Page
|
120
|
+
::Webby::Renderer.new(resource)._render_page
|
121
|
+
when Resources::Partial
|
122
|
+
_render_partial(resource, opts)
|
123
|
+
else
|
124
|
+
raise ::Webby::Error, "expecting a page or a partial but got '#{resource.class.name}'"
|
125
|
+
end
|
126
|
+
|
127
|
+
str = _guard(str) if opts[:guard]
|
128
|
+
str
|
129
|
+
end
|
130
|
+
|
131
|
+
# call-seq:
|
132
|
+
# render_page => string
|
133
|
+
#
|
134
|
+
# This method is being deprecated. It is being made internal to the
|
135
|
+
# framework and really shouldn't be used anymore.
|
136
|
+
#
|
137
|
+
def render_page
|
138
|
+
Webby.deprecated "render_page", "this method is being made internal to the framework"
|
139
|
+
_render_page
|
140
|
+
end
|
141
|
+
|
142
|
+
# call-seq:
|
143
|
+
# render_partial( partial, :locals => {} ) => string
|
144
|
+
#
|
145
|
+
# This method is being deprecated. Please use the +render+ method instead.
|
146
|
+
#
|
147
|
+
def render_partial( part, opts = {} )
|
148
|
+
Webby.deprecated "render_partial", "it is being replaced by the Renderer#render() method"
|
149
|
+
opts[:partial] = part
|
150
|
+
render opts
|
151
|
+
end
|
152
|
+
|
153
|
+
# call-seq:
|
154
|
+
# paginate( items, per_page ) {|item| block}
|
155
|
+
#
|
156
|
+
# Iterate the given _block_ for each item selected from the _items_ array
|
157
|
+
# using the given number of items _per_page_. The first time the page is
|
158
|
+
# rendered, the items passed to the block are selected using the range
|
159
|
+
# (0...per_page). The next rendering selects (per_page...2*per_page). This
|
160
|
+
# continues until all _items_ have been paginated.
|
161
|
+
#
|
162
|
+
# Calling this method creates a <code>@pager</code> object that can be
|
163
|
+
# accessed from the page. The <code>@pager</code> contains information
|
164
|
+
# about the next page, the current page number, the previous page, and the
|
165
|
+
# number of items in the current page.
|
166
|
+
#
|
167
|
+
def paginate( items, count, &block )
|
168
|
+
@pager ||= Paginator.new(items.length, count, @page) do |offset, per_page|
|
169
|
+
items[offset,per_page]
|
170
|
+
end.first
|
171
|
+
|
172
|
+
@pager.each(&block)
|
173
|
+
end
|
174
|
+
|
175
|
+
# call-seq:
|
176
|
+
# get_binding => binding
|
177
|
+
#
|
178
|
+
# Returns the current binding for the renderer.
|
179
|
+
#
|
180
|
+
def get_binding
|
181
|
+
@_bindings.last
|
182
|
+
end
|
183
|
+
|
184
|
+
# call-seq:
|
185
|
+
# _render_page => string
|
186
|
+
#
|
187
|
+
# Apply the desired filters to the page. The filters to apply are
|
188
|
+
# determined from the page's meta-data.
|
189
|
+
#
|
190
|
+
def _render_page
|
191
|
+
_track_rendering(@page.path) {
|
192
|
+
Filters.process(self, @page, ::Webby::Resources::File.read(@page.path))
|
193
|
+
}
|
194
|
+
end
|
195
|
+
|
196
|
+
# call-seq:
|
197
|
+
# _render_partial( partial, :locals => {} ) => string
|
198
|
+
#
|
199
|
+
# Render the given _partial_ into the current page. The :locals are a hash
|
200
|
+
# of key / value pairs that will be set as local variables in the scope of
|
201
|
+
# the partial when it is rendered.
|
202
|
+
#
|
203
|
+
def _render_partial( part, opts = {} )
|
204
|
+
_track_rendering(part.path) {
|
205
|
+
_configure_locals(opts[:locals])
|
206
|
+
Filters.process(self, part, ::Webby::Resources::File.read(part.path))
|
207
|
+
}
|
208
|
+
end
|
209
|
+
|
210
|
+
# call-seq:
|
211
|
+
# _layout_page => string
|
212
|
+
#
|
213
|
+
# Apply the desired filters to the page and then render the filtered page
|
214
|
+
# into the desired layout. The filters to apply to the page are determined
|
215
|
+
# from the page's meta-data. The layout to use is also determined from the
|
216
|
+
# page's meta-data.
|
217
|
+
#
|
218
|
+
def _layout_page
|
219
|
+
@content = _render_page
|
220
|
+
|
221
|
+
_track_rendering(@page.path) {
|
222
|
+
_render_layout_for(@page)
|
223
|
+
}
|
224
|
+
raise ::Webby::Error, "rendering stack corrupted" unless @@stack.empty?
|
225
|
+
|
226
|
+
@content
|
227
|
+
rescue ::Webby::Error => err
|
228
|
+
@log.error "while rendering page '#{@page.path}'"
|
229
|
+
@log.error err.message
|
230
|
+
rescue => err
|
231
|
+
@log.error "while rendering page '#{@page.path}'"
|
232
|
+
@log.fatal err
|
233
|
+
exit 1
|
234
|
+
ensure
|
235
|
+
@content = nil
|
236
|
+
@@stack.clear
|
237
|
+
end
|
238
|
+
|
239
|
+
# call-seq:
|
240
|
+
# _render_layout_for( resource )
|
241
|
+
#
|
242
|
+
# Render the layout for the given resource. If the resource does not have
|
243
|
+
# a layout, then this method returns immediately.
|
244
|
+
#
|
245
|
+
def _render_layout_for( res )
|
246
|
+
return unless res.layout
|
247
|
+
lyt = Resources.find_layout(res.layout)
|
248
|
+
return if lyt.nil?
|
249
|
+
|
250
|
+
_track_rendering(lyt.path) {
|
251
|
+
@content = Filters.process(
|
252
|
+
self, lyt, ::Webby::Resources::File.read(lyt.path))
|
253
|
+
_render_layout_for(lyt)
|
254
|
+
}
|
255
|
+
end
|
256
|
+
|
257
|
+
# call-seq:
|
258
|
+
# _next_page => true or false
|
259
|
+
#
|
260
|
+
# Returns +true+ if there is a next page to render. Returns +false+ if
|
261
|
+
# there is no next page or if pagination has not been configured for the
|
262
|
+
# current page.
|
263
|
+
#
|
264
|
+
def _next_page
|
265
|
+
return false unless defined? @pager and @pager
|
266
|
+
|
267
|
+
# go to the next page; break out if there is no next page
|
268
|
+
if @pager.next?
|
269
|
+
@pager = @pager.next
|
270
|
+
@_content_for.clear
|
271
|
+
@_bindings.clear
|
272
|
+
else
|
273
|
+
@page.number = nil
|
274
|
+
return false
|
275
|
+
end
|
276
|
+
|
277
|
+
true
|
278
|
+
end
|
279
|
+
|
280
|
+
# call-seq:
|
281
|
+
# _track_rendering( path ) {block}
|
282
|
+
#
|
283
|
+
# Keep track of the page rendering for the given _path_. The _block_ is
|
284
|
+
# where the the page will be rendered.
|
285
|
+
#
|
286
|
+
# This method keeps a stack of the current pages being rendeered. It looks
|
287
|
+
# for duplicates in the stack -- an indication of a rendering loop. When a
|
288
|
+
# rendering loop is detected, an error is raised.
|
289
|
+
#
|
290
|
+
# This method returns whatever is returned from the _block_.
|
291
|
+
#
|
292
|
+
def _track_rendering( path )
|
293
|
+
loop_error = @@stack.include? path
|
294
|
+
@@stack << path
|
295
|
+
@_bindings << _binding
|
296
|
+
|
297
|
+
if loop_error
|
298
|
+
msg = "rendering loop detected for '#{path}'\n"
|
299
|
+
msg << " current rendering stack\n\t"
|
300
|
+
msg << @@stack.join("\n\t")
|
301
|
+
raise ::Webby::Error, msg
|
302
|
+
end
|
303
|
+
|
304
|
+
yield
|
305
|
+
ensure
|
306
|
+
@@stack.pop if path == @@stack.last
|
307
|
+
@_bindings.pop
|
308
|
+
end
|
309
|
+
|
310
|
+
# call-seq:
|
311
|
+
# _configure_locals( locals )
|
312
|
+
#
|
313
|
+
# Configure local variables in the scope of the current binding returned
|
314
|
+
# by the +get_binding+ method. The _locals_ should be given as a hash of
|
315
|
+
# name / value pairs.
|
316
|
+
#
|
317
|
+
def _configure_locals( locals )
|
318
|
+
return if locals.nil?
|
319
|
+
|
320
|
+
locals.each do |k,v|
|
321
|
+
Thread.current[:value] = v
|
322
|
+
definition = "#{k} = Thread.current[:value]"
|
323
|
+
eval(definition, get_binding)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
# Attempts to locate a partial by name. If only the partial name is given,
|
328
|
+
# then the current directory of the page being rendered is searched for
|
329
|
+
# the partial. If a full path is given, then the partial is searched for
|
330
|
+
# in that directory.
|
331
|
+
#
|
332
|
+
# Raies a Webby::Error if the partial could not be found.
|
333
|
+
#
|
334
|
+
def _find_partial( part )
|
335
|
+
case part
|
336
|
+
when String
|
337
|
+
part_dir = ::File.dirname(part)
|
338
|
+
part_dir = @page.dir if part_dir == '.'
|
339
|
+
|
340
|
+
part_fn = ::File.basename(part)
|
341
|
+
part_fn = '_' + part_fn unless part_fn =~ %r/^_/
|
342
|
+
|
343
|
+
p = Resources.partials.find(
|
344
|
+
:filename => part_fn, :in_directory => part_dir ) rescue nil
|
345
|
+
raise ::Webby::Error, "could not find partial '#{part}'" if p.nil?
|
346
|
+
p
|
347
|
+
when ::Webby::Resources::Partial
|
348
|
+
part
|
349
|
+
else raise ::Webby::Error, "expecting a partial or a partial name" end
|
350
|
+
end
|
351
|
+
|
352
|
+
# This method will put filter guards around the given input string. This
|
353
|
+
# will protect the string from being processed by any remaining filters
|
354
|
+
# (specifically the textile filter).
|
355
|
+
#
|
356
|
+
# The string is returned unchanged if there are no remaining filters to
|
357
|
+
# guard against.
|
358
|
+
#
|
359
|
+
def _guard( str )
|
360
|
+
return str unless @_cursor
|
361
|
+
|
362
|
+
if @_cursor.remaining_filters.include? 'textile'
|
363
|
+
str = "<notextile>\n%s\n</notextile>" % str
|
364
|
+
end
|
365
|
+
str
|
366
|
+
end
|
367
|
+
|
368
|
+
# Returns the binding in the scope of this Renderer object.
|
369
|
+
#
|
370
|
+
def _binding() binding end
|
371
|
+
|
372
|
+
end # class Renderer
|
373
|
+
end # module Webby
|
374
|
+
|
375
|
+
Webby.require_all_libs_relative_to(__FILE__, 'stelan')
|
376
|
+
|
377
|
+
end # unless defined?
|
378
|
+
|
379
|
+
# EOF
|