nanoc 3.2.4 → 3.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.
- data/.gemtest +0 -0
- data/ChangeLog +3 -0
- data/Gemfile +32 -0
- data/LICENSE +19 -0
- data/NEWS.md +470 -0
- data/README.md +114 -0
- data/Rakefile +14 -0
- data/bin/nanoc +7 -27
- data/bin/nanoc3 +3 -0
- data/doc/yardoc_templates/default/layout/html/footer.erb +10 -0
- data/lib/nanoc.rb +41 -0
- data/lib/nanoc/base.rb +49 -0
- data/lib/nanoc/base/compilation/checksum_store.rb +57 -0
- data/lib/nanoc/base/compilation/compiled_content_cache.rb +62 -0
- data/lib/nanoc/base/compilation/compiler.rb +458 -0
- data/lib/nanoc/base/compilation/compiler_dsl.rb +214 -0
- data/lib/nanoc/base/compilation/dependency_tracker.rb +200 -0
- data/lib/nanoc/base/compilation/filter.rb +165 -0
- data/lib/nanoc/base/compilation/item_rep_proxy.rb +103 -0
- data/lib/nanoc/base/compilation/item_rep_recorder_proxy.rb +102 -0
- data/lib/nanoc/base/compilation/outdatedness_checker.rb +223 -0
- data/lib/nanoc/base/compilation/outdatedness_reasons.rb +46 -0
- data/lib/nanoc/base/compilation/rule.rb +73 -0
- data/lib/nanoc/base/compilation/rule_context.rb +84 -0
- data/lib/nanoc/base/compilation/rule_memory_calculator.rb +40 -0
- data/lib/nanoc/base/compilation/rule_memory_store.rb +53 -0
- data/lib/nanoc/base/compilation/rules_collection.rb +243 -0
- data/lib/nanoc/base/context.rb +47 -0
- data/lib/nanoc/base/core_ext.rb +6 -0
- data/lib/nanoc/base/core_ext/array.rb +62 -0
- data/lib/nanoc/base/core_ext/hash.rb +63 -0
- data/lib/nanoc/base/core_ext/pathname.rb +26 -0
- data/lib/nanoc/base/core_ext/string.rb +46 -0
- data/lib/nanoc/base/directed_graph.rb +275 -0
- data/lib/nanoc/base/errors.rb +211 -0
- data/lib/nanoc/base/memoization.rb +67 -0
- data/lib/nanoc/base/notification_center.rb +84 -0
- data/lib/nanoc/base/ordered_hash.rb +200 -0
- data/lib/nanoc/base/plugin_registry.rb +181 -0
- data/lib/nanoc/base/result_data/item_rep.rb +492 -0
- data/lib/nanoc/base/source_data/code_snippet.rb +58 -0
- data/lib/nanoc/base/source_data/configuration.rb +24 -0
- data/lib/nanoc/base/source_data/data_source.rb +234 -0
- data/lib/nanoc/base/source_data/item.rb +301 -0
- data/lib/nanoc/base/source_data/layout.rb +130 -0
- data/lib/nanoc/base/source_data/site.rb +361 -0
- data/lib/nanoc/base/store.rb +135 -0
- data/lib/nanoc/cli.rb +137 -0
- data/lib/nanoc/cli/command_runner.rb +104 -0
- data/lib/nanoc/cli/commands/autocompile.rb +58 -0
- data/lib/nanoc/cli/commands/compile.rb +297 -0
- data/lib/nanoc/cli/commands/create_item.rb +60 -0
- data/lib/nanoc/cli/commands/create_layout.rb +73 -0
- data/lib/nanoc/cli/commands/create_site.rb +411 -0
- data/lib/nanoc/cli/commands/debug.rb +117 -0
- data/lib/nanoc/cli/commands/deploy.rb +79 -0
- data/lib/nanoc/cli/commands/info.rb +98 -0
- data/lib/nanoc/cli/commands/nanoc.rb +38 -0
- data/lib/nanoc/cli/commands/prune.rb +50 -0
- data/lib/nanoc/cli/commands/update.rb +70 -0
- data/lib/nanoc/cli/commands/view.rb +82 -0
- data/lib/nanoc/cli/commands/watch.rb +124 -0
- data/lib/nanoc/cli/error_handler.rb +199 -0
- data/lib/nanoc/cli/logger.rb +92 -0
- data/lib/nanoc/data_sources.rb +29 -0
- data/lib/nanoc/data_sources/deprecated/delicious.rb +42 -0
- data/lib/nanoc/data_sources/deprecated/last_fm.rb +87 -0
- data/lib/nanoc/data_sources/deprecated/twitter.rb +38 -0
- data/lib/nanoc/data_sources/filesystem.rb +299 -0
- data/lib/nanoc/data_sources/filesystem_unified.rb +121 -0
- data/lib/nanoc/data_sources/filesystem_verbose.rb +91 -0
- data/lib/nanoc/extra.rb +24 -0
- data/lib/nanoc/extra/auto_compiler.rb +103 -0
- data/lib/nanoc/extra/chick.rb +125 -0
- data/lib/nanoc/extra/core_ext.rb +6 -0
- data/lib/nanoc/extra/core_ext/enumerable.rb +33 -0
- data/lib/nanoc/extra/core_ext/pathname.rb +30 -0
- data/lib/nanoc/extra/core_ext/time.rb +19 -0
- data/lib/nanoc/extra/deployer.rb +47 -0
- data/lib/nanoc/extra/deployers.rb +15 -0
- data/lib/nanoc/extra/deployers/fog.rb +98 -0
- data/lib/nanoc/extra/deployers/rsync.rb +70 -0
- data/lib/nanoc/extra/file_proxy.rb +40 -0
- data/lib/nanoc/extra/pruner.rb +86 -0
- data/lib/nanoc/extra/validators.rb +12 -0
- data/lib/nanoc/extra/validators/links.rb +268 -0
- data/lib/nanoc/extra/validators/w3c.rb +95 -0
- data/lib/nanoc/extra/vcs.rb +66 -0
- data/lib/nanoc/extra/vcses.rb +17 -0
- data/lib/nanoc/extra/vcses/bazaar.rb +25 -0
- data/lib/nanoc/extra/vcses/dummy.rb +24 -0
- data/lib/nanoc/extra/vcses/git.rb +25 -0
- data/lib/nanoc/extra/vcses/mercurial.rb +25 -0
- data/lib/nanoc/extra/vcses/subversion.rb +25 -0
- data/lib/nanoc/filters.rb +59 -0
- data/lib/nanoc/filters/asciidoc.rb +38 -0
- data/lib/nanoc/filters/bluecloth.rb +19 -0
- data/lib/nanoc/filters/coderay.rb +21 -0
- data/lib/nanoc/filters/coffeescript.rb +20 -0
- data/lib/nanoc/filters/colorize_syntax.rb +298 -0
- data/lib/nanoc/filters/erb.rb +38 -0
- data/lib/nanoc/filters/erubis.rb +34 -0
- data/lib/nanoc/filters/haml.rb +27 -0
- data/lib/nanoc/filters/kramdown.rb +20 -0
- data/lib/nanoc/filters/less.rb +53 -0
- data/lib/nanoc/filters/markaby.rb +20 -0
- data/lib/nanoc/filters/maruku.rb +20 -0
- data/lib/nanoc/filters/mustache.rb +24 -0
- data/lib/nanoc/filters/rainpress.rb +19 -0
- data/lib/nanoc/filters/rdiscount.rb +22 -0
- data/lib/nanoc/filters/rdoc.rb +33 -0
- data/lib/nanoc/filters/redcarpet.rb +62 -0
- data/lib/nanoc/filters/redcloth.rb +47 -0
- data/lib/nanoc/filters/relativize_paths.rb +94 -0
- data/lib/nanoc/filters/rubypants.rb +20 -0
- data/lib/nanoc/filters/sass.rb +74 -0
- data/lib/nanoc/filters/slim.rb +25 -0
- data/lib/nanoc/filters/typogruby.rb +23 -0
- data/lib/nanoc/filters/uglify_js.rb +42 -0
- data/lib/nanoc/filters/xsl.rb +46 -0
- data/lib/nanoc/filters/yui_compressor.rb +23 -0
- data/lib/nanoc/helpers.rb +16 -0
- data/lib/nanoc/helpers/blogging.rb +319 -0
- data/lib/nanoc/helpers/breadcrumbs.rb +40 -0
- data/lib/nanoc/helpers/capturing.rb +138 -0
- data/lib/nanoc/helpers/filtering.rb +50 -0
- data/lib/nanoc/helpers/html_escape.rb +55 -0
- data/lib/nanoc/helpers/link_to.rb +151 -0
- data/lib/nanoc/helpers/rendering.rb +140 -0
- data/lib/nanoc/helpers/tagging.rb +71 -0
- data/lib/nanoc/helpers/text.rb +44 -0
- data/lib/nanoc/helpers/xml_sitemap.rb +76 -0
- data/lib/nanoc/tasks.rb +10 -0
- data/lib/nanoc/tasks/clean.rake +16 -0
- data/lib/nanoc/tasks/clean.rb +29 -0
- data/lib/nanoc/tasks/deploy/rsync.rake +16 -0
- data/lib/nanoc/tasks/validate.rake +92 -0
- data/nanoc.gemspec +49 -0
- data/tasks/doc.rake +16 -0
- data/tasks/test.rake +46 -0
- data/test/base/core_ext/array_spec.rb +73 -0
- data/test/base/core_ext/hash_spec.rb +98 -0
- data/test/base/core_ext/pathname_spec.rb +27 -0
- data/test/base/core_ext/string_spec.rb +37 -0
- data/test/base/test_checksum_store.rb +35 -0
- data/test/base/test_code_snippet.rb +31 -0
- data/test/base/test_compiler.rb +403 -0
- data/test/base/test_compiler_dsl.rb +161 -0
- data/test/base/test_context.rb +31 -0
- data/test/base/test_data_source.rb +46 -0
- data/test/base/test_dependency_tracker.rb +262 -0
- data/test/base/test_directed_graph.rb +288 -0
- data/test/base/test_filter.rb +83 -0
- data/test/base/test_item.rb +179 -0
- data/test/base/test_item_rep.rb +579 -0
- data/test/base/test_layout.rb +59 -0
- data/test/base/test_memoization.rb +90 -0
- data/test/base/test_notification_center.rb +34 -0
- data/test/base/test_outdatedness_checker.rb +394 -0
- data/test/base/test_plugin.rb +30 -0
- data/test/base/test_rule.rb +19 -0
- data/test/base/test_rule_context.rb +65 -0
- data/test/base/test_site.rb +190 -0
- data/test/cli/commands/test_compile.rb +33 -0
- data/test/cli/commands/test_create_item.rb +14 -0
- data/test/cli/commands/test_create_layout.rb +28 -0
- data/test/cli/commands/test_create_site.rb +24 -0
- data/test/cli/commands/test_deploy.rb +74 -0
- data/test/cli/commands/test_help.rb +12 -0
- data/test/cli/commands/test_info.rb +11 -0
- data/test/cli/commands/test_prune.rb +98 -0
- data/test/cli/commands/test_update.rb +10 -0
- data/test/cli/test_cli.rb +102 -0
- data/test/cli/test_error_handler.rb +29 -0
- data/test/cli/test_logger.rb +10 -0
- data/test/data_sources/test_filesystem.rb +433 -0
- data/test/data_sources/test_filesystem_unified.rb +536 -0
- data/test/data_sources/test_filesystem_verbose.rb +357 -0
- data/test/extra/core_ext/test_enumerable.rb +30 -0
- data/test/extra/core_ext/test_pathname.rb +17 -0
- data/test/extra/core_ext/test_time.rb +15 -0
- data/test/extra/deployers/test_fog.rb +67 -0
- data/test/extra/deployers/test_rsync.rb +100 -0
- data/test/extra/test_auto_compiler.rb +417 -0
- data/test/extra/test_file_proxy.rb +19 -0
- data/test/extra/test_vcs.rb +22 -0
- data/test/extra/validators/test_links.rb +62 -0
- data/test/extra/validators/test_w3c.rb +47 -0
- data/test/filters/test_asciidoc.rb +22 -0
- data/test/filters/test_bluecloth.rb +18 -0
- data/test/filters/test_coderay.rb +44 -0
- data/test/filters/test_coffeescript.rb +18 -0
- data/test/filters/test_colorize_syntax.rb +379 -0
- data/test/filters/test_erb.rb +105 -0
- data/test/filters/test_erubis.rb +78 -0
- data/test/filters/test_haml.rb +96 -0
- data/test/filters/test_kramdown.rb +18 -0
- data/test/filters/test_less.rb +113 -0
- data/test/filters/test_markaby.rb +24 -0
- data/test/filters/test_maruku.rb +18 -0
- data/test/filters/test_mustache.rb +25 -0
- data/test/filters/test_rainpress.rb +29 -0
- data/test/filters/test_rdiscount.rb +31 -0
- data/test/filters/test_rdoc.rb +18 -0
- data/test/filters/test_redcarpet.rb +73 -0
- data/test/filters/test_redcloth.rb +33 -0
- data/test/filters/test_relativize_paths.rb +533 -0
- data/test/filters/test_rubypants.rb +18 -0
- data/test/filters/test_sass.rb +229 -0
- data/test/filters/test_slim.rb +35 -0
- data/test/filters/test_typogruby.rb +21 -0
- data/test/filters/test_uglify_js.rb +30 -0
- data/test/filters/test_xsl.rb +105 -0
- data/test/filters/test_yui_compressor.rb +44 -0
- data/test/gem_loader.rb +11 -0
- data/test/helper.rb +207 -0
- data/test/helpers/test_blogging.rb +754 -0
- data/test/helpers/test_breadcrumbs.rb +81 -0
- data/test/helpers/test_capturing.rb +41 -0
- data/test/helpers/test_filtering.rb +106 -0
- data/test/helpers/test_html_escape.rb +32 -0
- data/test/helpers/test_link_to.rb +249 -0
- data/test/helpers/test_rendering.rb +89 -0
- data/test/helpers/test_tagging.rb +87 -0
- data/test/helpers/test_text.rb +24 -0
- data/test/helpers/test_xml_sitemap.rb +103 -0
- data/test/tasks/test_clean.rb +67 -0
- metadata +327 -15
- data/bin/nanoc-select +0 -86
- data/lib/nanoc-select.rb +0 -11
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'rubypants'
|
|
4
|
+
|
|
5
|
+
module Nanoc::Filters
|
|
6
|
+
class RubyPants < Nanoc::Filter
|
|
7
|
+
|
|
8
|
+
# Runs the content through [RubyPants](http://chneukirchen.org/blog/static/projects/rubypants.html).
|
|
9
|
+
# This method takes no options.
|
|
10
|
+
#
|
|
11
|
+
# @param [String] content The content to filter
|
|
12
|
+
#
|
|
13
|
+
# @return [String] The filtered content
|
|
14
|
+
def run(content, params={})
|
|
15
|
+
# Get result
|
|
16
|
+
::RubyPants.new(content).to_html
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'sass'
|
|
4
|
+
require 'set'
|
|
5
|
+
|
|
6
|
+
module Nanoc::Filters
|
|
7
|
+
class Sass < Nanoc::Filter
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
# The current filter. This is definitely going to bite me if I ever get
|
|
11
|
+
# to multithreading nanoc.
|
|
12
|
+
attr_accessor :current
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Essentially the `Sass::Importers::Filesystem` but registering each
|
|
16
|
+
# import file path.
|
|
17
|
+
class SassFilesystemImporter < ::Sass::Importers::Filesystem
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def _find(dir, name, options)
|
|
22
|
+
full_filename, syntax = find_real_file(dir, name)
|
|
23
|
+
return unless full_filename && File.readable?(full_filename)
|
|
24
|
+
|
|
25
|
+
filter = Nanoc::Filters::Sass.current
|
|
26
|
+
item = filter.imported_filename_to_item(full_filename)
|
|
27
|
+
filter.depend_on([ item ]) unless item.nil?
|
|
28
|
+
|
|
29
|
+
options[:syntax] = syntax
|
|
30
|
+
options[:filename] = full_filename
|
|
31
|
+
options[:importer] = self
|
|
32
|
+
::Sass::Engine.new(File.read(full_filename), options)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Runs the content through [Sass](http://sass-lang.com/).
|
|
37
|
+
# Parameters passed to this filter will be passed on to Sass.
|
|
38
|
+
#
|
|
39
|
+
# @param [String] content The content to filter
|
|
40
|
+
#
|
|
41
|
+
# @return [String] The filtered content
|
|
42
|
+
def run(content, params={})
|
|
43
|
+
# Build options
|
|
44
|
+
options = params.dup
|
|
45
|
+
sass_filename = options[:filename] ||
|
|
46
|
+
(@item && @item[:content_filename])
|
|
47
|
+
options[:filename] ||= sass_filename
|
|
48
|
+
options[:filesystem_importer] ||=
|
|
49
|
+
Nanoc::Filters::Sass::SassFilesystemImporter
|
|
50
|
+
|
|
51
|
+
# Find items
|
|
52
|
+
item_dirglob = Pathname.new(sass_filename).dirname.realpath.to_s + '**'
|
|
53
|
+
clean_items = @items.reject { |i| i[:content_filename].nil? }
|
|
54
|
+
@scoped_items, @rest_items = clean_items.partition do |i|
|
|
55
|
+
i[:content_filename] &&
|
|
56
|
+
Pathname.new(i[:content_filename]).realpath.fnmatch(item_dirglob)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Render
|
|
60
|
+
engine = ::Sass::Engine.new(content, options)
|
|
61
|
+
self.class.current = self
|
|
62
|
+
engine.render
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def imported_filename_to_item(filename)
|
|
66
|
+
filematch = lambda do |i|
|
|
67
|
+
i[:content_filename] &&
|
|
68
|
+
Pathname.new(i[:content_filename]).realpath == Pathname.new(filename).realpath
|
|
69
|
+
end
|
|
70
|
+
@scoped_items.find(&filematch) || @rest_items.find(&filematch)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'slim'
|
|
4
|
+
|
|
5
|
+
module Nanoc::Filters
|
|
6
|
+
|
|
7
|
+
# @since 3.2.0
|
|
8
|
+
class Slim < Nanoc::Filter
|
|
9
|
+
|
|
10
|
+
# Runs the content through [Slim](http://slim-lang.com/)
|
|
11
|
+
# This method takes no options.
|
|
12
|
+
#
|
|
13
|
+
# @param [String] content The content to filter
|
|
14
|
+
#
|
|
15
|
+
# @return [String] The filtered content
|
|
16
|
+
def run(content, params={})
|
|
17
|
+
# Create context
|
|
18
|
+
context = ::Nanoc::Context.new(assigns)
|
|
19
|
+
|
|
20
|
+
::Slim::Template.new { content }.render(context) { assigns[:content] }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'typogruby'
|
|
4
|
+
|
|
5
|
+
module Nanoc::Filters
|
|
6
|
+
|
|
7
|
+
# @since 3.2.0
|
|
8
|
+
class Typogruby < Nanoc::Filter
|
|
9
|
+
|
|
10
|
+
# Runs the content through [Typogruby](http://avdgaag.github.com/typogruby/).
|
|
11
|
+
# This method takes no options.
|
|
12
|
+
#
|
|
13
|
+
# @param [String] content The content to filter
|
|
14
|
+
#
|
|
15
|
+
# @return [String] The filtered content
|
|
16
|
+
def run(content, params={})
|
|
17
|
+
# Get result
|
|
18
|
+
::Typogruby.improve(content)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'uglifier'
|
|
4
|
+
|
|
5
|
+
module Nanoc::Filters
|
|
6
|
+
class UglifyJS < Nanoc::Filter
|
|
7
|
+
|
|
8
|
+
# Runs the content through [UglifyJS](https://github.com/mishoo/UglifyJS/).
|
|
9
|
+
# This method optionally takes options to pass directly to Uglifier:
|
|
10
|
+
#
|
|
11
|
+
# {
|
|
12
|
+
# :mangle => true, # Mangle variables names
|
|
13
|
+
# :toplevel => false, # Mangle top-level variable names
|
|
14
|
+
# :except => [], # Variable names to be excluded from mangling
|
|
15
|
+
# :max_line_length => 32 * 1024, # Maximum line length
|
|
16
|
+
# :squeeze => true, # Squeeze code resulting in smaller, but less-readable code
|
|
17
|
+
# :seqs => true, # Reduce consecutive statements in blocks into single statement
|
|
18
|
+
# :dead_code => true, # Remove dead code (e.g. after return)
|
|
19
|
+
# :unsafe => false, # Optimizations known to be unsafe in some situations
|
|
20
|
+
# :copyright => true, # Show copyright message
|
|
21
|
+
# :beautify => false, # Ouput indented code
|
|
22
|
+
# :beautify_options => {
|
|
23
|
+
# :indent_level => 4,
|
|
24
|
+
# :indent_start => 0,
|
|
25
|
+
# :quote_keys => false,
|
|
26
|
+
# :space_colon => 0,
|
|
27
|
+
# :ascii_only => false
|
|
28
|
+
# }
|
|
29
|
+
# }
|
|
30
|
+
#
|
|
31
|
+
# @param [String] content The content to filter
|
|
32
|
+
#
|
|
33
|
+
# @option params [Array] :options ([]) A list of options to pass on to Uglifier
|
|
34
|
+
#
|
|
35
|
+
# @return [String] The filtered content
|
|
36
|
+
def run(content, params={})
|
|
37
|
+
# Add filename to load path
|
|
38
|
+
Uglifier.new(params).compile(content)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require 'nokogiri'
|
|
3
|
+
|
|
4
|
+
module Nanoc::Filters
|
|
5
|
+
|
|
6
|
+
# @since 3.3.0
|
|
7
|
+
class XSL < Nanoc::Filter
|
|
8
|
+
|
|
9
|
+
# Runs the item content through an [XSLT](http://www.w3.org/TR/xslt)
|
|
10
|
+
# stylesheet using [Nokogiri](http://nokogiri.org/).
|
|
11
|
+
#
|
|
12
|
+
# This filter can only be run for layouts, because it will need both the
|
|
13
|
+
# XML to convert (= the item content) as well as the XSLT stylesheet (=
|
|
14
|
+
# the layout content).
|
|
15
|
+
#
|
|
16
|
+
# Additional parameters can be passed to the layout call. These parameters
|
|
17
|
+
# will be turned into `xsl:param` elements.
|
|
18
|
+
#
|
|
19
|
+
# @example Invoking the filter as a layout
|
|
20
|
+
#
|
|
21
|
+
# compile '/reports/*/' do
|
|
22
|
+
# layout 'xsl-report'
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# layout 'xsl-report', :xsl, :awesome => 'definitely'
|
|
26
|
+
#
|
|
27
|
+
# @param [String] content The XML content to transform
|
|
28
|
+
#
|
|
29
|
+
# @param [Hash] params The parameters that will be stored in corresponding
|
|
30
|
+
# `xsl:param` elements.
|
|
31
|
+
#
|
|
32
|
+
# @return [String] The transformed content
|
|
33
|
+
def run(content, params={})
|
|
34
|
+
if assigns[:layout].nil?
|
|
35
|
+
raise "The XSL filter can only be run as a layout"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
xml = ::Nokogiri::XML(content)
|
|
39
|
+
xsl = ::Nokogiri::XSLT(assigns[:content])
|
|
40
|
+
|
|
41
|
+
xsl.transform(xml, ::Nokogiri::XSLT.quote_params(params)).to_s
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'yuicompressor'
|
|
2
|
+
|
|
3
|
+
module Nanoc::Filters
|
|
4
|
+
|
|
5
|
+
# @since 3.3.0
|
|
6
|
+
class YUICompressor < Nanoc::Filter
|
|
7
|
+
|
|
8
|
+
# Compress Javascript or CSS using [YUICompressor](http://rubydoc.info/gems/yuicompressor).
|
|
9
|
+
# This method optionally takes options to pass directly to the
|
|
10
|
+
# YUICompressor gem.
|
|
11
|
+
#
|
|
12
|
+
# @param [String] content JavaScript or CSS input
|
|
13
|
+
#
|
|
14
|
+
# @param [Hash] params Options passed to YUICompressor
|
|
15
|
+
#
|
|
16
|
+
# @return [String] Compressed but equivalent JavaScript or CSS
|
|
17
|
+
def run(content, params = {})
|
|
18
|
+
::YUICompressor.compress(content, params)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Nanoc::Helpers
|
|
4
|
+
|
|
5
|
+
autoload 'Blogging', 'nanoc/helpers/blogging'
|
|
6
|
+
autoload 'Breadcrumbs', 'nanoc/helpers/breadcrumbs'
|
|
7
|
+
autoload 'Capturing', 'nanoc/helpers/capturing'
|
|
8
|
+
autoload 'Filtering', 'nanoc/helpers/filtering'
|
|
9
|
+
autoload 'HTMLEscape', 'nanoc/helpers/html_escape'
|
|
10
|
+
autoload 'LinkTo', 'nanoc/helpers/link_to'
|
|
11
|
+
autoload 'Rendering', 'nanoc/helpers/rendering'
|
|
12
|
+
autoload 'Tagging', 'nanoc/helpers/tagging'
|
|
13
|
+
autoload 'Text', 'nanoc/helpers/text'
|
|
14
|
+
autoload 'XMLSitemap', 'nanoc/helpers/xml_sitemap'
|
|
15
|
+
|
|
16
|
+
end
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Nanoc::Helpers
|
|
4
|
+
|
|
5
|
+
# Provides functionality for building blogs, such as finding articles and
|
|
6
|
+
# constructing feeds.
|
|
7
|
+
#
|
|
8
|
+
# This helper has a few requirements. First, all blog articles should have
|
|
9
|
+
# the following attributes:
|
|
10
|
+
#
|
|
11
|
+
# * `kind` - Set to `"article"`
|
|
12
|
+
#
|
|
13
|
+
# * `created_at` - The article's publication timestamp
|
|
14
|
+
#
|
|
15
|
+
# Some functions in this blogging helper, such as the {#atom_feed} function,
|
|
16
|
+
# require additional attributes to be set; these attributes are described in
|
|
17
|
+
# the documentation for these functions.
|
|
18
|
+
#
|
|
19
|
+
# All "time" item attributes, site configuration attributes or method
|
|
20
|
+
# parameters can either be a `Time` instance or a string in any format
|
|
21
|
+
# parseable by `Time.parse`.
|
|
22
|
+
#
|
|
23
|
+
# The two main functions are {#sorted_articles} and {#atom_feed}.
|
|
24
|
+
module Blogging
|
|
25
|
+
|
|
26
|
+
# Returns an unsorted list of articles, i.e. items where the `kind`
|
|
27
|
+
# attribute is set to `"article"`.
|
|
28
|
+
#
|
|
29
|
+
# @return [Array] An array containing all articles
|
|
30
|
+
def articles
|
|
31
|
+
@items.select { |item| item[:kind] == 'article' }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Returns a sorted list of articles, i.e. items where the `kind`
|
|
35
|
+
# attribute is set to `"article"`. Articles are sorted by descending
|
|
36
|
+
# creation date, so newer articles appear before older articles.
|
|
37
|
+
#
|
|
38
|
+
# @return [Array] A sorted array containing all articles
|
|
39
|
+
def sorted_articles
|
|
40
|
+
articles.sort_by do |a|
|
|
41
|
+
attribute_to_time(a[:created_at])
|
|
42
|
+
end.reverse
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Returns a string representing the atom feed containing recent articles,
|
|
46
|
+
# sorted by descending creation date.
|
|
47
|
+
#
|
|
48
|
+
# The following attributes must be set on blog articles:
|
|
49
|
+
#
|
|
50
|
+
# * `title` - The title of the blog post
|
|
51
|
+
#
|
|
52
|
+
# * `kind` and `created_at` (described above)
|
|
53
|
+
#
|
|
54
|
+
# The following attributes can optionally be set on blog articles to
|
|
55
|
+
# change the behaviour of the Atom feed:
|
|
56
|
+
#
|
|
57
|
+
# * `excerpt` - An excerpt of the article, which is usually only a few
|
|
58
|
+
# lines long.
|
|
59
|
+
#
|
|
60
|
+
# * `custom_path_in_feed` - The path that will be used instead of the
|
|
61
|
+
# normal path in the feed. This can be useful when including
|
|
62
|
+
# non-outputted items in a feed; such items could have their custom feed
|
|
63
|
+
# path set to the blog path instead, for example.
|
|
64
|
+
#
|
|
65
|
+
# * `custom_url_in_feed` - The url that will be used instead of the
|
|
66
|
+
# normal url in the feed (generated from the site's base url + the item
|
|
67
|
+
# rep's path). This can be useful when building a link-blog where the
|
|
68
|
+
# URL of article is a remote location.
|
|
69
|
+
#
|
|
70
|
+
# * `updated_at` - The time when the article was last modified. If this
|
|
71
|
+
# attribute is not present, the `created_at` attribute will be used as
|
|
72
|
+
# the time when the article was last modified.
|
|
73
|
+
#
|
|
74
|
+
# The site configuration will need to have the following attributes:
|
|
75
|
+
#
|
|
76
|
+
# * `base_url` - The URL to the site, without trailing slash. For
|
|
77
|
+
# example, if the site is at "http://example.com/", the `base_url`
|
|
78
|
+
# would be "http://example.com".
|
|
79
|
+
#
|
|
80
|
+
# The feed item will need to know about the feed title, the feed author
|
|
81
|
+
# name, and the URI corresponding to the author. These can be specified
|
|
82
|
+
# using parameters, as attributes in the feed item, or in the site
|
|
83
|
+
# configuration.
|
|
84
|
+
#
|
|
85
|
+
# * `title` - The title of the feed, which is usually also the title of
|
|
86
|
+
# the blog.
|
|
87
|
+
#
|
|
88
|
+
# * `author_name` - The name of the item's author.
|
|
89
|
+
#
|
|
90
|
+
# * `author_uri` - The URI for the item's author, such as the author's
|
|
91
|
+
# web site URL.
|
|
92
|
+
#
|
|
93
|
+
# The feed item can have the following optional attributes:
|
|
94
|
+
#
|
|
95
|
+
# * `feed_url` - The custom URL of the feed. This can be useful when the
|
|
96
|
+
# private feed URL shouldn't be exposed; for example, when using
|
|
97
|
+
# FeedBurner this would be set to the public FeedBurner URL.
|
|
98
|
+
#
|
|
99
|
+
# To construct a feed, create a new item and make sure that it is
|
|
100
|
+
# filtered with `:erb` or `:erubis`; it should not be laid out. Ensure
|
|
101
|
+
# that it is routed to the proper path, e.g. `/blog.xml`. It may also be
|
|
102
|
+
# useful to set the `is_hidden` attribute to true, so that helpers such
|
|
103
|
+
# as the sitemap helper will ignore the item. The content of the feed
|
|
104
|
+
# item should be `<%= atom_feed %>`.
|
|
105
|
+
#
|
|
106
|
+
# @example Defining compilation and routing rules for a feed item
|
|
107
|
+
#
|
|
108
|
+
# compile '/blog/feed/' do
|
|
109
|
+
# filter :erb
|
|
110
|
+
# end
|
|
111
|
+
#
|
|
112
|
+
# route '/blog/feed/' do
|
|
113
|
+
# '/blog.xml'
|
|
114
|
+
# end
|
|
115
|
+
#
|
|
116
|
+
# @example Limiting the number of items in a feed
|
|
117
|
+
#
|
|
118
|
+
# <%= atom_feed :limit => 5 %>
|
|
119
|
+
#
|
|
120
|
+
# @option params [Number] :limit (5) The maximum number of articles to
|
|
121
|
+
# show
|
|
122
|
+
#
|
|
123
|
+
# @option params [Array] :articles (sorted_articles) A list of articles to
|
|
124
|
+
# include in the feed
|
|
125
|
+
#
|
|
126
|
+
# @option params [Proc] :content_proc (->{ |article|
|
|
127
|
+
# article.compiled_content(:snapshot => :pre) }) A proc that returns the
|
|
128
|
+
# content of the given article, which is passed as a parameter. This
|
|
129
|
+
# function may not return nil.
|
|
130
|
+
#
|
|
131
|
+
# @option params [proc] :excerpt_proc (->{ |article| article[:excerpt] })
|
|
132
|
+
# A proc that returns the excerpt of the given article, passed as a
|
|
133
|
+
# parameter. This function should return nil if there is no excerpt.
|
|
134
|
+
#
|
|
135
|
+
# @option params [String] :title The feed's title, if it is not given in
|
|
136
|
+
# the item attributes.
|
|
137
|
+
#
|
|
138
|
+
# @option params [String] :author_name The name of the feed's author, if
|
|
139
|
+
# it is not given in the item attributes.
|
|
140
|
+
#
|
|
141
|
+
# @option params [String] :author_uri The URI of the feed's author, if it
|
|
142
|
+
# is not given in the item attributes.
|
|
143
|
+
#
|
|
144
|
+
# @return [String] The generated feed content
|
|
145
|
+
def atom_feed(params={})
|
|
146
|
+
require 'builder'
|
|
147
|
+
|
|
148
|
+
# Extract parameters
|
|
149
|
+
limit = params[:limit] || 5
|
|
150
|
+
relevant_articles = params[:articles] || articles || []
|
|
151
|
+
content_proc = params[:content_proc] || lambda { |a| a.compiled_content(:snapshot => :pre) }
|
|
152
|
+
excerpt_proc = params[:excerpt_proc] || lambda { |a| a[:excerpt] }
|
|
153
|
+
|
|
154
|
+
# Check config attributes
|
|
155
|
+
if @site.config[:base_url].nil?
|
|
156
|
+
raise RuntimeError.new('Cannot build Atom feed: site configuration has no base_url')
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Check feed item attributes
|
|
160
|
+
title = params[:title] || @item[:title] || @site.config[:title]
|
|
161
|
+
if title.nil?
|
|
162
|
+
raise RuntimeError.new('Cannot build Atom feed: no title in params, item or site config')
|
|
163
|
+
end
|
|
164
|
+
author_name = params[:author_name] || @item[:author_name] || @site.config[:author_name]
|
|
165
|
+
if author_name.nil?
|
|
166
|
+
raise RuntimeError.new('Cannot build Atom feed: no author_name in params, item or site config')
|
|
167
|
+
end
|
|
168
|
+
author_uri = params[:author_uri] || @item[:author_uri] || @site.config[:author_uri]
|
|
169
|
+
if author_uri.nil?
|
|
170
|
+
raise RuntimeError.new('Cannot build Atom feed: no author_uri in params, item or site config')
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Check article attributes
|
|
174
|
+
if relevant_articles.empty?
|
|
175
|
+
raise RuntimeError.new('Cannot build Atom feed: no articles')
|
|
176
|
+
end
|
|
177
|
+
if relevant_articles.any? { |a| a[:created_at].nil? }
|
|
178
|
+
raise RuntimeError.new('Cannot build Atom feed: one or more articles lack created_at')
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Get sorted relevant articles
|
|
182
|
+
sorted_relevant_articles = relevant_articles.sort_by do |a|
|
|
183
|
+
attribute_to_time(a[:created_at])
|
|
184
|
+
end.reverse.first(limit)
|
|
185
|
+
|
|
186
|
+
# Get most recent article
|
|
187
|
+
last_article = sorted_relevant_articles.first
|
|
188
|
+
|
|
189
|
+
# Create builder
|
|
190
|
+
buffer = ''
|
|
191
|
+
xml = Builder::XmlMarkup.new(:target => buffer, :indent => 2)
|
|
192
|
+
|
|
193
|
+
# Build feed
|
|
194
|
+
xml.instruct!
|
|
195
|
+
xml.feed(:xmlns => 'http://www.w3.org/2005/Atom') do
|
|
196
|
+
root_url = @site.config[:base_url] + '/'
|
|
197
|
+
|
|
198
|
+
# Add primary attributes
|
|
199
|
+
xml.id root_url
|
|
200
|
+
xml.title title
|
|
201
|
+
|
|
202
|
+
# Add date
|
|
203
|
+
xml.updated(attribute_to_time(last_article[:created_at]).to_iso8601_time)
|
|
204
|
+
|
|
205
|
+
# Add links
|
|
206
|
+
xml.link(:rel => 'alternate', :href => root_url)
|
|
207
|
+
xml.link(:rel => 'self', :href => feed_url)
|
|
208
|
+
|
|
209
|
+
# Add author information
|
|
210
|
+
xml.author do
|
|
211
|
+
xml.name author_name
|
|
212
|
+
xml.uri author_uri
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Add articles
|
|
216
|
+
sorted_relevant_articles.each do |a|
|
|
217
|
+
# Get URL
|
|
218
|
+
url = url_for(a)
|
|
219
|
+
next if url.nil?
|
|
220
|
+
|
|
221
|
+
xml.entry do
|
|
222
|
+
# Add primary attributes
|
|
223
|
+
xml.id atom_tag_for(a)
|
|
224
|
+
xml.title a[:title], :type => 'html'
|
|
225
|
+
|
|
226
|
+
# Add dates
|
|
227
|
+
xml.published attribute_to_time(a[:created_at]).to_iso8601_time
|
|
228
|
+
xml.updated attribute_to_time(a[:updated_at] || a[:created_at]).to_iso8601_time
|
|
229
|
+
|
|
230
|
+
# Add specific author information
|
|
231
|
+
if a[:author_name] || a[:author_uri]
|
|
232
|
+
xml.author do
|
|
233
|
+
xml.name a[:author_name] || author_name
|
|
234
|
+
xml.uri a[:author_uri] || author_uri
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# Add link
|
|
239
|
+
xml.link(:rel => 'alternate', :href => url)
|
|
240
|
+
|
|
241
|
+
# Add content
|
|
242
|
+
summary = excerpt_proc.call(a)
|
|
243
|
+
xml.content content_proc.call(a), :type => 'html'
|
|
244
|
+
xml.summary summary, :type => 'html' unless summary.nil?
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
buffer
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# Returns the URL for the given item. It will return the URL containing
|
|
253
|
+
# the custom path in the feed if possible, otherwise the normal path.
|
|
254
|
+
#
|
|
255
|
+
# @param [Nanoc::Item] item The item for which to fetch the URL.
|
|
256
|
+
#
|
|
257
|
+
# @return [String] The URL of the given item
|
|
258
|
+
def url_for(item)
|
|
259
|
+
# Check attributes
|
|
260
|
+
if @site.config[:base_url].nil?
|
|
261
|
+
raise RuntimeError.new('Cannot build Atom feed: site configuration has no base_url')
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# Build URL
|
|
265
|
+
if item[:custom_url_in_feed]
|
|
266
|
+
item[:custom_url_in_feed]
|
|
267
|
+
elsif item[:custom_path_in_feed]
|
|
268
|
+
@site.config[:base_url] + item[:custom_path_in_feed]
|
|
269
|
+
elsif item.path
|
|
270
|
+
@site.config[:base_url] + item.path
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# Returns the URL of the feed. It will return the custom feed URL if set,
|
|
275
|
+
# or otherwise the normal feed URL.
|
|
276
|
+
#
|
|
277
|
+
# @return [String] The URL of the feed
|
|
278
|
+
def feed_url
|
|
279
|
+
# Check attributes
|
|
280
|
+
if @site.config[:base_url].nil?
|
|
281
|
+
raise RuntimeError.new('Cannot build Atom feed: site configuration has no base_url')
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
@item[:feed_url] || @site.config[:base_url] + @item.path
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# Returns an URI containing an unique ID for the given item. This will be
|
|
288
|
+
# used in the Atom feed to uniquely identify articles. These IDs are
|
|
289
|
+
# created using a procedure suggested by Mark Pilgrim and described in his
|
|
290
|
+
# ["How to make a good ID in Atom" blog post]
|
|
291
|
+
# (http://diveintomark.org/archives/2004/05/28/howto-atom-id).
|
|
292
|
+
#
|
|
293
|
+
# @param [Nanoc::Item] item The item for which to create an atom tag
|
|
294
|
+
#
|
|
295
|
+
# @return [String] The atom tag for the given item
|
|
296
|
+
def atom_tag_for(item)
|
|
297
|
+
hostname, base_dir = %r{^.+?://([^/]+)(.*)$}.match(@site.config[:base_url])[1..2]
|
|
298
|
+
|
|
299
|
+
formatted_date = attribute_to_time(item[:created_at]).to_iso8601_date
|
|
300
|
+
|
|
301
|
+
'tag:' + hostname + ',' + formatted_date + ':' + base_dir + (item.path || item.identifier)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# Converts the given attribute (which can be a string, a Time or a Date)
|
|
305
|
+
# into a Time.
|
|
306
|
+
#
|
|
307
|
+
# @param [String, Time, Date] time Something that contains time
|
|
308
|
+
# information but is not necessarily a Time instance yet
|
|
309
|
+
#
|
|
310
|
+
# @return [Time] The Time instance corresponding to the given input
|
|
311
|
+
def attribute_to_time(time)
|
|
312
|
+
time = Time.local(time.year, time.month, time.day) if time.is_a?(Date)
|
|
313
|
+
time = Time.parse(time) if time.is_a?(String)
|
|
314
|
+
time
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
end
|