nanoc 2.0.4 → 2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/ChangeLog +31 -1
  2. data/LICENSE +1 -1
  3. data/README +63 -3
  4. data/Rakefile +59 -12
  5. data/bin/nanoc +7 -199
  6. data/lib/nanoc.rb +83 -12
  7. data/lib/nanoc/base/asset.rb +113 -0
  8. data/lib/nanoc/base/asset_defaults.rb +21 -0
  9. data/lib/nanoc/base/asset_rep.rb +277 -0
  10. data/lib/nanoc/base/binary_filter.rb +44 -0
  11. data/lib/nanoc/base/code.rb +41 -0
  12. data/lib/nanoc/base/compiler.rb +46 -34
  13. data/lib/nanoc/base/core_ext/hash.rb +51 -7
  14. data/lib/nanoc/base/core_ext/string.rb +8 -0
  15. data/lib/nanoc/base/data_source.rb +253 -20
  16. data/lib/nanoc/base/defaults.rb +30 -0
  17. data/lib/nanoc/base/enhancements.rb +9 -84
  18. data/lib/nanoc/base/filter.rb +109 -6
  19. data/lib/nanoc/base/layout.rb +91 -0
  20. data/lib/nanoc/base/notification_center.rb +66 -0
  21. data/lib/nanoc/base/page.rb +94 -126
  22. data/lib/nanoc/base/page_defaults.rb +20 -0
  23. data/lib/nanoc/base/page_rep.rb +318 -0
  24. data/lib/nanoc/base/plugin.rb +57 -9
  25. data/lib/nanoc/base/proxies/asset_proxy.rb +29 -0
  26. data/lib/nanoc/base/proxies/asset_rep_proxy.rb +26 -0
  27. data/lib/nanoc/base/proxies/layout_proxy.rb +25 -0
  28. data/lib/nanoc/base/proxies/page_proxy.rb +35 -0
  29. data/lib/nanoc/base/proxies/page_rep_proxy.rb +28 -0
  30. data/lib/nanoc/base/proxy.rb +37 -0
  31. data/lib/nanoc/base/router.rb +72 -0
  32. data/lib/nanoc/base/site.rb +219 -88
  33. data/lib/nanoc/base/template.rb +64 -0
  34. data/lib/nanoc/binary_filters/image_science_thumbnail.rb +28 -0
  35. data/lib/nanoc/cli.rb +1 -0
  36. data/lib/nanoc/cli/base.rb +219 -0
  37. data/lib/nanoc/cli/cli.rb +16 -0
  38. data/lib/nanoc/cli/command.rb +105 -0
  39. data/lib/nanoc/cli/commands/autocompile.rb +80 -0
  40. data/lib/nanoc/cli/commands/compile.rb +273 -0
  41. data/lib/nanoc/cli/commands/create_layout.rb +85 -0
  42. data/lib/nanoc/cli/commands/create_page.rb +85 -0
  43. data/lib/nanoc/cli/commands/create_site.rb +327 -0
  44. data/lib/nanoc/cli/commands/create_template.rb +76 -0
  45. data/lib/nanoc/cli/commands/help.rb +69 -0
  46. data/lib/nanoc/cli/commands/info.rb +114 -0
  47. data/lib/nanoc/cli/commands/switch.rb +141 -0
  48. data/lib/nanoc/cli/commands/update.rb +91 -0
  49. data/lib/nanoc/cli/ext.rb +37 -0
  50. data/lib/nanoc/cli/logger.rb +66 -0
  51. data/lib/nanoc/cli/option_parser.rb +168 -0
  52. data/lib/nanoc/data_sources/filesystem.rb +645 -224
  53. data/lib/nanoc/data_sources/filesystem_combined.rb +495 -0
  54. data/lib/nanoc/extra/auto_compiler.rb +265 -0
  55. data/lib/nanoc/extra/context.rb +22 -0
  56. data/lib/nanoc/extra/core_ext/hash.rb +54 -0
  57. data/lib/nanoc/extra/core_ext/time.rb +13 -0
  58. data/lib/nanoc/extra/file_proxy.rb +29 -0
  59. data/lib/nanoc/extra/vcs.rb +48 -0
  60. data/lib/nanoc/extra/vcses/bazaar.rb +21 -0
  61. data/lib/nanoc/extra/vcses/dummy.rb +20 -0
  62. data/lib/nanoc/extra/vcses/git.rb +21 -0
  63. data/lib/nanoc/extra/vcses/mercurial.rb +21 -0
  64. data/lib/nanoc/extra/vcses/subversion.rb +21 -0
  65. data/lib/nanoc/filters/bluecloth.rb +13 -0
  66. data/lib/nanoc/filters/erb.rb +6 -22
  67. data/lib/nanoc/filters/erubis.rb +14 -0
  68. data/lib/nanoc/filters/haml.rb +7 -23
  69. data/lib/nanoc/filters/markaby.rb +5 -5
  70. data/lib/nanoc/filters/maruku.rb +14 -0
  71. data/lib/nanoc/filters/old.rb +19 -0
  72. data/lib/nanoc/filters/rdiscount.rb +13 -0
  73. data/lib/nanoc/filters/rdoc.rb +5 -4
  74. data/lib/nanoc/filters/redcloth.rb +14 -0
  75. data/lib/nanoc/filters/rubypants.rb +14 -0
  76. data/lib/nanoc/filters/sass.rb +13 -0
  77. data/lib/nanoc/helpers/blogging.rb +170 -0
  78. data/lib/nanoc/helpers/capturing.rb +59 -0
  79. data/lib/nanoc/helpers/html_escape.rb +23 -0
  80. data/lib/nanoc/helpers/link_to.rb +69 -0
  81. data/lib/nanoc/helpers/render.rb +47 -0
  82. data/lib/nanoc/helpers/tagging.rb +52 -0
  83. data/lib/nanoc/helpers/xml_sitemap.rb +58 -0
  84. data/lib/nanoc/routers/default.rb +54 -0
  85. data/lib/nanoc/routers/no_dirs.rb +66 -0
  86. data/lib/nanoc/routers/versioned.rb +79 -0
  87. metadata +112 -22
  88. data/lib/nanoc/base/auto_compiler.rb +0 -132
  89. data/lib/nanoc/base/layout_processor.rb +0 -33
  90. data/lib/nanoc/base/page_proxy.rb +0 -31
  91. data/lib/nanoc/base/plugin_manager.rb +0 -33
  92. data/lib/nanoc/data_sources/database.rb +0 -259
  93. data/lib/nanoc/data_sources/trivial.rb +0 -145
  94. data/lib/nanoc/filters/markdown.rb +0 -13
  95. data/lib/nanoc/filters/smartypants.rb +0 -13
  96. data/lib/nanoc/filters/textile.rb +0 -13
  97. data/lib/nanoc/layout_processors/erb.rb +0 -35
  98. data/lib/nanoc/layout_processors/haml.rb +0 -38
  99. data/lib/nanoc/layout_processors/markaby.rb +0 -16
@@ -0,0 +1,76 @@
1
+ module Nanoc::CLI
2
+
3
+ class CreateTemplateCommand < Command # :nodoc:
4
+
5
+ def name
6
+ 'create_template'
7
+ end
8
+
9
+ def aliases
10
+ [ 'ct' ]
11
+ end
12
+
13
+ def short_desc
14
+ 'create a template'
15
+ end
16
+
17
+ def long_desc
18
+ 'Create a new template in the current site.'
19
+ end
20
+
21
+ def usage
22
+ "nanoc create_template [name]"
23
+ end
24
+
25
+ def option_definitions
26
+ [
27
+ # --vcs
28
+ {
29
+ :long => 'vcs', :short => 'c', :argument => :required,
30
+ :desc => 'select the VCS to use'
31
+ }
32
+ ]
33
+ end
34
+
35
+ def run(options, arguments)
36
+ # Check arguments
37
+ if arguments.length != 1
38
+ $stderr.puts "usage: #{usage}"
39
+ exit 1
40
+ end
41
+
42
+ # Extract arguments
43
+ name = arguments[0]
44
+
45
+ # Check template name
46
+ if name.include?('/')
47
+ $stderr.puts 'Template names cannot contain slashes; aborting.'
48
+ exit 1
49
+ end
50
+
51
+ # Make sure we are in a nanoc site directory
52
+ @base.require_site
53
+
54
+ # Set VCS if possible
55
+ @base.set_vcs(options[:vcs])
56
+
57
+ # Setup notifications
58
+ Nanoc::NotificationCenter.on(:file_created) do |file_path|
59
+ Nanoc::CLI::Logger.instance.file(:high, :create, file_path)
60
+ end
61
+
62
+ # Create template
63
+ template = Nanoc::Template.new(
64
+ "Hi, I'm a new template. Please edit me!",
65
+ { :title => "A Title" },
66
+ name
67
+ )
68
+ template.site = @base.site
69
+ template.save
70
+
71
+ puts "A template named '#{name}' has been created."
72
+ end
73
+
74
+ end
75
+
76
+ end
@@ -0,0 +1,69 @@
1
+ module Nanoc::CLI
2
+
3
+ class HelpCommand < Command # :nodoc:
4
+
5
+ def name
6
+ 'help'
7
+ end
8
+
9
+ def aliases
10
+ []
11
+ end
12
+
13
+ def short_desc
14
+ 'show help for a command'
15
+ end
16
+
17
+ def long_desc
18
+ 'Show help for the given command, or show general help. When no ' +
19
+ 'command is given, a list of available commands is displayed, as ' +
20
+ 'well as a list of global commandline options. When a command is ' +
21
+ 'given, a command description as well as command-specific ' +
22
+ 'commandline options are shown.'
23
+ end
24
+
25
+ def usage
26
+ "nanoc help [command]"
27
+ end
28
+
29
+ def run(options, arguments)
30
+ # Check arguments
31
+ if arguments.size > 1
32
+ $stderr.puts "usage: #{usage}"
33
+ exit 1
34
+ end
35
+
36
+ if arguments.length == 0
37
+ # Build help text
38
+ text = ''
39
+
40
+ # Add title
41
+ text << "nanoc, a static site compiler written in Ruby.\n"
42
+
43
+ # Add available commands
44
+ text << "\n"
45
+ text << "Available commands:\n"
46
+ text << "\n"
47
+ @base.commands.sort.each do |command|
48
+ text << sprintf(" %-20s %s\n", command.name, command.short_desc)
49
+ end
50
+
51
+ # Add global options
52
+ text << "\n"
53
+ text << "Global options:\n"
54
+ text << "\n"
55
+ @base.global_option_definitions.sort { |x,y| x[:long] <=> y[:long] }.each do |opt_def|
56
+ text << sprintf(" -%1s --%-15s %s\n", opt_def[:short], opt_def[:long], opt_def[:desc])
57
+ end
58
+
59
+ # Display text
60
+ puts text
61
+ elsif arguments.length == 1
62
+ command = @base.command_named(arguments[0])
63
+ puts command.help
64
+ end
65
+ end
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,114 @@
1
+ module Nanoc::CLI
2
+
3
+ class InfoCommand < Command # :nodoc:
4
+
5
+ def name
6
+ 'info'
7
+ end
8
+
9
+ def aliases
10
+ []
11
+ end
12
+
13
+ def short_desc
14
+ 'show info about available plugins'
15
+ end
16
+
17
+ def long_desc
18
+ 'Show a list of available plugins, including filters, data sources ' +
19
+ 'and routers. If the current directory contains a nanoc web site, ' +
20
+ 'the plugins defined in this site will be shown as well.'
21
+ end
22
+
23
+ def usage
24
+ "nanoc info"
25
+ end
26
+
27
+ def option_definitions
28
+ []
29
+ end
30
+
31
+ def run(options, arguments)
32
+ # Check arguments
33
+ if arguments.size != 0
34
+ $stderr.puts "usage: #{usage}"
35
+ exit 1
36
+ end
37
+
38
+ # Get list of plugins (before and after)
39
+ plugins_before = find_all_plugins
40
+ @base.site
41
+ plugins_after = find_all_plugins
42
+
43
+ # Get structured list of plugins
44
+ plugins = {}
45
+ plugin_classes.each do |klass|
46
+ plugins[klass] = {
47
+ :builtin => plugins_before[klass],
48
+ :custom => plugins_after[klass] - plugins_before[klass]
49
+ }
50
+ end
51
+
52
+ # Find longest name
53
+ max_length = plugins.values.map { |k| k.values }.flatten.map { |k| k.identifiers.join(', ').length }.max + 2
54
+
55
+ plugins.each_pair do |superclass, structured_plugins|
56
+ # Print kind
57
+ kind = name_for_plugin_class(superclass)
58
+ puts "#{kind}:"
59
+ puts
60
+
61
+ # Print plugins organised by subtype
62
+ [ :builtin, :custom ].each do |type|
63
+ # Find relevant plugins
64
+ subclasses = structured_plugins[type]
65
+
66
+ # Print type
67
+ puts " #{type}:"
68
+ if subclasses.empty?
69
+ puts " (none)"
70
+ next
71
+ end
72
+
73
+ # Print plugins
74
+ subclasses.sort_by { |k| k.identifier.to_s }.each do |klass|
75
+ # Get data
76
+ is_custom = !plugins_before[superclass].include?(klass)
77
+ klass_name = klass.to_s
78
+ klass_id = klass.identifiers.join(', ')
79
+
80
+ # Display
81
+ puts sprintf(" %-#{max_length}s (%s)", klass_id, klass_name)
82
+ end
83
+ end
84
+
85
+ puts
86
+ end
87
+ end
88
+
89
+ private
90
+
91
+ PLUGIN_CLASSES = {
92
+ Nanoc::Filter => 'Filters',
93
+ Nanoc::DataSource => 'Data Sources',
94
+ Nanoc::Router => 'Routers',
95
+ Nanoc::Extra::VCS => 'VCSes'
96
+ }
97
+
98
+ def find_all_plugins
99
+ plugin_classes.inject({}) do |memo, klass|
100
+ memo.merge(klass => Nanoc::Plugin::MAP[klass].values.uniq)
101
+ end
102
+ end
103
+
104
+ def plugin_classes
105
+ PLUGIN_CLASSES.keys
106
+ end
107
+
108
+ def name_for_plugin_class(klass)
109
+ PLUGIN_CLASSES[klass]
110
+ end
111
+
112
+ end
113
+
114
+ end
@@ -0,0 +1,141 @@
1
+ module Nanoc::CLI
2
+
3
+ class SwitchCommand < Command # :nodoc:
4
+
5
+ def name
6
+ 'switch'
7
+ end
8
+
9
+ def aliases
10
+ []
11
+ end
12
+
13
+ def short_desc
14
+ 'switch the site to a new data source'
15
+ end
16
+
17
+ def long_desc
18
+ 'Move the data stored in the site to a new, given data source.' +
19
+ "\n" +
20
+ 'The given new data source may need additional configuration ' +
21
+ 'parameters that cannot be specified on the commandline. These ' +
22
+ 'should be stored in the configuration file (config.yaml) BEFORE ' +
23
+ 'executing the switch command.' +
24
+ "\n" +
25
+ 'This command first loads all existing data into memory, destroys ' +
26
+ 'the on-disk data, changes the site\'s data source, and finally ' +
27
+ 'writes the data back to the disk using the new data source. Because ' +
28
+ 'of this action\'s destructive nature, THIS OPERATION SHOULD NOT BE ' +
29
+ 'INTERRUPTED as interruption could result in data loss.' +
30
+ "\n" +
31
+ 'This command will change data, and it is therefore recommended to ' +
32
+ 'make a backup in case something goes wrong.'
33
+ end
34
+
35
+ def usage
36
+ "nanoc switch [options]"
37
+ end
38
+
39
+ def option_definitions
40
+ [
41
+ # --vcs
42
+ {
43
+ :long => 'vcs', :short => 'c', :argument => :required,
44
+ :desc => 'select the VCS to use'
45
+ },
46
+ # --yes
47
+ {
48
+ :long => 'yes', :short => 'y', :argument => :forbidden,
49
+ :desc => 'switches the data source without warning'
50
+ },
51
+ # --datasource
52
+ {
53
+ :long => 'datasource', :short => 'd', :argument => :required,
54
+ :desc => 'specify the new data source for the site'
55
+ }
56
+ ]
57
+ end
58
+
59
+ def run(options, arguments)
60
+ # Check arguments
61
+ if arguments.size != 0
62
+ $stderr.puts "usage: #{usage}"
63
+ exit 1
64
+ end
65
+
66
+ # Check options
67
+ unless options.has_key?(:datasource)
68
+ $stderr.puts 'A new data source should be specified using the ' +
69
+ '-d/--datasource option.'
70
+ exit 1
71
+ end
72
+
73
+ # Find data source
74
+ data_source = Nanoc::DataSource.named(options[:datasource])
75
+ if data_source.nil?
76
+ $stderr.puts "Unrecognised data source: #{options[:datasource]}"
77
+ exit 1
78
+ end
79
+
80
+ # Make sure we are in a nanoc site directory
81
+ @base.require_site
82
+
83
+ # Set VCS if possible
84
+ @base.set_vcs(options[:vcs])
85
+
86
+ # Check for -y switch
87
+ unless options.has_key?(:yes)
88
+ $stderr.puts '*************'
89
+ $stderr.puts '** WARNING **'
90
+ $stderr.puts '*************'
91
+ $stderr.puts
92
+ $stderr.puts 'Are you absolutely sure you want to set up the data ' +
93
+ 'source for this site? Setting up the data source ' +
94
+ 'will remove existing data. This operation is ' +
95
+ 'destructive and cannot be reverted. Please do not ' +
96
+ 'interrupt this operation; doing so can result in ' +
97
+ 'data loss. As always, consider making a backup copy.'
98
+ $stderr.puts
99
+ $stderr.puts 'To continue, use the -y/--yes option, like "nanoc ' +
100
+ 'switch -y".'
101
+ exit 1
102
+ end
103
+
104
+ # Setup notifications
105
+ Nanoc::NotificationCenter.on(:file_created) do |file_path|
106
+ Nanoc::CLI::Logger.instance.file(:high, :create, file_path)
107
+ end
108
+ Nanoc::NotificationCenter.on(:file_updated) do |file_path|
109
+ Nanoc::CLI::Logger.instance.file(:high, :update, file_path)
110
+ end
111
+
112
+ # Load data
113
+ @base.site.load_data
114
+
115
+ # Destroy existing data
116
+ @base.site.data_source.destroy
117
+
118
+ # Update configuration
119
+ @base.site.config[:data_source] = options[:datasource]
120
+ @base.site.instance_eval { @data_source = data_source.new(self) }
121
+ File.open('config.yaml', 'w') { |io| io.write(YAML.dump(@base.site.config.stringify_keys)) }
122
+
123
+ # Set VCS on new data source if possible
124
+ @base.set_vcs(options[:vcs])
125
+
126
+ @base.site.data_source.loading do
127
+ # Create initial data source
128
+ @base.site.data_source.setup
129
+
130
+ # Store all data
131
+ @base.site.pages.each { |p| @base.site.data_source.save_page(p) }
132
+ @base.site.data_source.save_page_defaults(@base.site.page_defaults)
133
+ @base.site.layouts.each { |l| @base.site.data_source.save_layout(l) }
134
+ @base.site.templates.each { |t| @base.site.data_source.save_template(t) }
135
+ @base.site.data_source.save_code(@base.site.code)
136
+ end
137
+ end
138
+
139
+ end
140
+
141
+ end
@@ -0,0 +1,91 @@
1
+ module Nanoc::CLI
2
+
3
+ class UpdateCommand < Command # :nodoc:
4
+
5
+ def name
6
+ 'update'
7
+ end
8
+
9
+ def aliases
10
+ []
11
+ end
12
+
13
+ def short_desc
14
+ 'update the data stored by the data source to a newer version'
15
+ end
16
+
17
+ def long_desc
18
+ 'Update the data stored by the data source to a newer format. The ' +
19
+ 'format in which data is stored can change between releases, and ' +
20
+ 'even though backward compatibility is usually preserved, it is ' +
21
+ 'often a good idea to store the site data in a newer format so newer ' +
22
+ 'features can be taken advantage of.' +
23
+ "\n" +
24
+ 'This command will change data, and it is therefore recommended to ' +
25
+ 'make a backup in case something goes wrong.'
26
+ end
27
+
28
+ def usage
29
+ "nanoc update [options]"
30
+ end
31
+
32
+ def option_definitions
33
+ [
34
+ # --vcs
35
+ {
36
+ :long => 'vcs', :short => 'c', :argument => :required,
37
+ :desc => 'select the VCS to use'
38
+ },
39
+ # --yes
40
+ {
41
+ :long => 'yes', :short => 'y', :argument => :forbidden,
42
+ :desc => 'updates the data without warning'
43
+ }
44
+ ]
45
+ end
46
+
47
+ def run(options, arguments)
48
+ # Check arguments
49
+ if arguments.size != 0
50
+ $stderr.puts "usage: #{usage}"
51
+ exit 1
52
+ end
53
+
54
+ # Make sure we are in a nanoc site directory
55
+ @base.require_site
56
+
57
+ # Set VCS if possible
58
+ @base.set_vcs(options[:vcs])
59
+
60
+ # Check for -y switch
61
+ unless options.has_key?(:yes)
62
+ $stderr.puts '*************'
63
+ $stderr.puts '** WARNING **'
64
+ $stderr.puts '*************'
65
+ $stderr.puts
66
+ $stderr.puts 'Are you absolutely sure you want to update the ' +
67
+ 'content for this site? Updating the site content ' +
68
+ 'will change the structure of existing data. This ' +
69
+ 'operation is destructive and cannot be reverted. ' +
70
+ 'Please do not interrupt this operation; doing so can ' +
71
+ 'result in data loss. As always, consider making a ' +
72
+ 'backup copy.'
73
+ $stderr.puts
74
+ $stderr.puts 'If this nanoc site is versioned using a VCS ' +
75
+ 'supported by nanoc, consider using the --vcs option ' +
76
+ 'to have nanoc perform add/delete/move operations ' +
77
+ 'using the specified VCS. To get a list of VCSes ' +
78
+ 'supported by nanoc, issue the "info" command.'
79
+ $stderr.puts
80
+ $stderr.puts 'To continue, use the -y/--yes option, like "nanoc ' +
81
+ 'update -y".'
82
+ exit 1
83
+ end
84
+
85
+ # Update
86
+ @base.site.data_source.update
87
+ end
88
+
89
+ end
90
+
91
+ end