bunto 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.markdown +59 -0
  4. data/bin/bunto +51 -0
  5. data/lib/bunto.rb +179 -0
  6. data/lib/bunto/cleaner.rb +105 -0
  7. data/lib/bunto/collection.rb +205 -0
  8. data/lib/bunto/command.rb +65 -0
  9. data/lib/bunto/commands/build.rb +77 -0
  10. data/lib/bunto/commands/clean.rb +42 -0
  11. data/lib/bunto/commands/doctor.rb +114 -0
  12. data/lib/bunto/commands/help.rb +31 -0
  13. data/lib/bunto/commands/new.rb +82 -0
  14. data/lib/bunto/commands/serve.rb +204 -0
  15. data/lib/bunto/commands/serve/servlet.rb +61 -0
  16. data/lib/bunto/configuration.rb +323 -0
  17. data/lib/bunto/converter.rb +48 -0
  18. data/lib/bunto/converters/identity.rb +21 -0
  19. data/lib/bunto/converters/markdown.rb +92 -0
  20. data/lib/bunto/converters/markdown/kramdown_parser.rb +117 -0
  21. data/lib/bunto/converters/markdown/rdiscount_parser.rb +33 -0
  22. data/lib/bunto/converters/markdown/redcarpet_parser.rb +102 -0
  23. data/lib/bunto/converters/smartypants.rb +34 -0
  24. data/lib/bunto/convertible.rb +297 -0
  25. data/lib/bunto/deprecator.rb +46 -0
  26. data/lib/bunto/document.rb +444 -0
  27. data/lib/bunto/drops/bunto_drop.rb +21 -0
  28. data/lib/bunto/drops/collection_drop.rb +22 -0
  29. data/lib/bunto/drops/document_drop.rb +27 -0
  30. data/lib/bunto/drops/drop.rb +176 -0
  31. data/lib/bunto/drops/site_drop.rb +38 -0
  32. data/lib/bunto/drops/unified_payload_drop.rb +25 -0
  33. data/lib/bunto/drops/url_drop.rb +83 -0
  34. data/lib/bunto/entry_filter.rb +72 -0
  35. data/lib/bunto/errors.rb +10 -0
  36. data/lib/bunto/excerpt.rb +127 -0
  37. data/lib/bunto/external.rb +59 -0
  38. data/lib/bunto/filters.rb +367 -0
  39. data/lib/bunto/frontmatter_defaults.rb +188 -0
  40. data/lib/bunto/generator.rb +3 -0
  41. data/lib/bunto/hooks.rb +101 -0
  42. data/lib/bunto/layout.rb +49 -0
  43. data/lib/bunto/liquid_extensions.rb +22 -0
  44. data/lib/bunto/liquid_renderer.rb +39 -0
  45. data/lib/bunto/liquid_renderer/file.rb +50 -0
  46. data/lib/bunto/liquid_renderer/table.rb +94 -0
  47. data/lib/bunto/log_adapter.rb +115 -0
  48. data/lib/bunto/mime.types +800 -0
  49. data/lib/bunto/page.rb +180 -0
  50. data/lib/bunto/plugin.rb +96 -0
  51. data/lib/bunto/plugin_manager.rb +95 -0
  52. data/lib/bunto/post.rb +329 -0
  53. data/lib/bunto/publisher.rb +21 -0
  54. data/lib/bunto/reader.rb +126 -0
  55. data/lib/bunto/readers/collection_reader.rb +20 -0
  56. data/lib/bunto/readers/data_reader.rb +69 -0
  57. data/lib/bunto/readers/layout_reader.rb +53 -0
  58. data/lib/bunto/readers/page_reader.rb +21 -0
  59. data/lib/bunto/readers/post_reader.rb +62 -0
  60. data/lib/bunto/readers/static_file_reader.rb +21 -0
  61. data/lib/bunto/regenerator.rb +175 -0
  62. data/lib/bunto/related_posts.rb +56 -0
  63. data/lib/bunto/renderer.rb +191 -0
  64. data/lib/bunto/site.rb +391 -0
  65. data/lib/bunto/static_file.rb +141 -0
  66. data/lib/bunto/stevenson.rb +58 -0
  67. data/lib/bunto/tags/highlight.rb +122 -0
  68. data/lib/bunto/tags/include.rb +190 -0
  69. data/lib/bunto/tags/post_url.rb +88 -0
  70. data/lib/bunto/url.rb +136 -0
  71. data/lib/bunto/utils.rb +287 -0
  72. data/lib/bunto/utils/ansi.rb +59 -0
  73. data/lib/bunto/utils/platforms.rb +30 -0
  74. data/lib/bunto/version.rb +3 -0
  75. data/lib/site_template/.gitignore +3 -0
  76. data/lib/site_template/_config.yml +21 -0
  77. data/lib/site_template/_includes/footer.html +38 -0
  78. data/lib/site_template/_includes/head.html +12 -0
  79. data/lib/site_template/_includes/header.html +27 -0
  80. data/lib/site_template/_includes/icon-github.html +1 -0
  81. data/lib/site_template/_includes/icon-github.svg +1 -0
  82. data/lib/site_template/_includes/icon-twitter.html +1 -0
  83. data/lib/site_template/_includes/icon-twitter.svg +1 -0
  84. data/lib/site_template/_layouts/default.html +20 -0
  85. data/lib/site_template/_layouts/page.html +14 -0
  86. data/lib/site_template/_layouts/post.html +15 -0
  87. data/lib/site_template/_posts/0000-00-00-welcome-to-bunto.markdown.erb +25 -0
  88. data/lib/site_template/_sass/_base.scss +206 -0
  89. data/lib/site_template/_sass/_layout.scss +242 -0
  90. data/lib/site_template/_sass/_syntax-highlighting.scss +71 -0
  91. data/lib/site_template/about.md +15 -0
  92. data/lib/site_template/css/main.scss +53 -0
  93. data/lib/site_template/feed.xml +30 -0
  94. data/lib/site_template/index.html +23 -0
  95. metadata +252 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: db4d93530a7eb0e73c615ce0699607440a4dfc3c
4
+ data.tar.gz: 3817cf82a033d008dad8a0438ddcf303a6d71c16
5
+ SHA512:
6
+ metadata.gz: b19c626c0e74905faddc592b4c6b832d77c2a65d14dafab7ebd81af6ae77763abf1790555c049685b25df402efb2ab7ab26e83c214755c960ff8395776ae7d57
7
+ data.tar.gz: aae78e9d6637ac07b5b12f5fa7bc508bf79ef4cc59ec24266b2de8b0cbb5295da8664c0e4dfee1475a2437b77fe73e4f9da0c5ae317310f32cca158ef7fbc6dd
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014-present Suriyaa Kudo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,59 @@
1
+ # ![Bunto](https://cloud.githubusercontent.com/assets/5073946/9288138/f4335fee-4337-11e5-9a28-068900097035.png)
2
+
3
+
4
+ > **Bunto** is a Web Application Framework which can be used as a simple, static site generator for personal, project, or organization sites.
5
+
6
+ [![Gem Version](https://img.shields.io/gem/v/bunto.svg)][ruby-gems]
7
+ [![Build Status](https://travis-ci.org/bunto/bunto.svg?branch=ruby)][travis]
8
+ <!--
9
+ [![Test Coverage](https://codeclimate.com/github/bunto/bunto/badges/coverage.svg)][coverage]
10
+ [![Code Climate](https://codeclimate.com/github/bunto/bunto/badges/gpa.svg)][codeclimate]
11
+ [![Dependency Status](https://gemnasium.com/bunto/bunto.svg)][gemnasium]
12
+ [![Security](https://hakiri.io/github/bunto/bunto/ruby.svg)][hakiri]
13
+ -->
14
+
15
+ [ruby-gems]: https://rubygems.org/gems/bunto
16
+ <!--
17
+ [gemnasium]: https://gemnasium.com/bunto/bunto
18
+ [codeclimate]: https://codeclimate.com/github/bunto/bunto
19
+ [coverage]: https://codeclimate.com/github/bunto/bunto/coverage
20
+ [hakiri]: https://hakiri.io/github/bunto/bunto/ruby
21
+ -->
22
+ [travis]: https://travis-ci.org/bunto/bunto
23
+
24
+ By Suriyaa Kudo, Tom Preston-Werner and many [awesome contributors](https://github.com/bunto/bunto/graphs/contributors)!
25
+
26
+ Bunto is a Web Application Framework and can be used as a static site generator perfect for personal, project, or organization sites. Think of it like a file-based CMS, without all the complexity. Bunto takes your content, renders HTML and CSS templates, and spits out a complete, static website ready to be served by Apache, hostSE, Nginx or another web server. Bunto is the engine behind [GitHub Pages](http://pages.github.com), which you can use to host sites right from your GitHub repositories.
27
+
28
+ ## Getting Started
29
+
30
+ * [Install](https://bunto.github.io/bunto/docs/installation/) the gem
31
+ * Read up about its [Usage](https://bunto.github.io/docs/usage/) and [Configuration](https://bunto.github.io/docs/configuration/)
32
+ * Take a gander at some existing [Sites](https://wiki.github.com/bunto/bunto/sites)
33
+ * Fork and [Contribute](https://bunto.github.io/docs/contributing/) your own modifications
34
+ * Have questions? Check out our official forum community [Bunto Talk](https://bunto.github.io/talk/) or [`#bunto` on irc.freenode.net](https://botbot.me/freenode/bunto/)
35
+
36
+ ## Code of Conduct
37
+
38
+ In order to have a more open and welcoming community, Bunto adheres to a
39
+ [code of conduct](CONDUCT.md) adapted from the Ruby on Rails code of
40
+ conduct.
41
+
42
+ Please adhere to this code of conduct in any interactions you have in the
43
+ Bunto community. It is strictly enforced on all official Bunto
44
+ repositories, websites, and resources. If you encounter someone violating
45
+ these terms, please let a maintainer (@SuriyaaKudoIsc) know
46
+ and we will address it as soon as possible.
47
+
48
+ ## Diving In
49
+
50
+ * [Migrate](http://bunto.github.io/import/docs/home/) from your previous system
51
+ * Learn how the [YAML Front Matter](https://bunto.github.io/docs/frontmatter/) works
52
+ * Put information on your site with [Variables](https://bunto.github.io/docs/variables/)
53
+ * Customize the [Permalinks](https://bunto.github.io/docs/permalinks/) your posts are generated with
54
+ * Use the built-in [Liquid Extensions](https://bunto.github.io/docs/templates/) to make your life easier
55
+ * Use custom [Plugins](https://bunto.github.io/docs/plugins/) to generate content specific to your site
56
+
57
+ ## License
58
+
59
+ See [LICENSE](https://github.com/bunto/bunto/blob/master/LICENSE).
data/bin/bunto ADDED
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+ STDOUT.sync = true
3
+
4
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w( .. lib ))
5
+
6
+ require 'bunto'
7
+ require 'mercenary'
8
+
9
+ Bunto::PluginManager.require_from_bundler
10
+
11
+ Bunto::Deprecator.process(ARGV)
12
+
13
+ Mercenary.program(:bunto) do |p|
14
+ p.version Bunto::VERSION
15
+ p.description 'Bunto is a static site generator in Ruby'
16
+ p.syntax 'bunto <subcommand> [options]'
17
+
18
+ p.option 'source', '-s', '--source [DIR]', 'Source directory (defaults to ./)'
19
+ p.option 'destination', '-d', '--destination [DIR]', 'Destination directory (defaults to ./_site)'
20
+ p.option 'safe', '--safe', 'Safe mode (defaults to false)'
21
+ p.option 'plugins_dir', '-p', '--plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]', Array, 'Plugins directory (defaults to ./_plugins)'
22
+ p.option 'layouts_dir', '--layouts DIR', String, 'Layouts directory (defaults to ./_layouts)'
23
+ p.option 'profile', '--profile', 'Generate a Liquid rendering profile'
24
+
25
+ Bunto::External.require_if_present(Bunto::External.blessed_gems) do |g|
26
+ cmd = g.split('-').last
27
+ p.command(cmd.to_sym) do |c|
28
+ c.syntax cmd
29
+ c.action do
30
+ Bunto.logger.abort_with "You must install the '#{g}' gem to use the 'bunto #{cmd}' command."
31
+ end
32
+ end
33
+ end
34
+
35
+ Bunto::Command.subclasses.each { |c| c.init_with_program(p) }
36
+
37
+ p.action do |args, _|
38
+ if args.empty?
39
+ Bunto.logger.error "A subcommand is required."
40
+ puts p
41
+ abort
42
+ else
43
+ subcommand = args.first
44
+ unless p.has_command? subcommand
45
+ Bunto.logger.abort_with "fatal: 'bunto #{args.first}' could not" \
46
+ " be found. You may need to install the bunto-#{args.first} gem" \
47
+ " or a related gem to be able to use this subcommand."
48
+ end
49
+ end
50
+ end
51
+ end
data/lib/bunto.rb ADDED
@@ -0,0 +1,179 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
2
+
3
+ # Require all of the Ruby files in the given directory.
4
+ #
5
+ # path - The String relative path from here to the directory.
6
+ #
7
+ # Returns nothing.
8
+ def require_all(path)
9
+ glob = File.join(File.dirname(__FILE__), path, '*.rb')
10
+ Dir[glob].each do |f|
11
+ require f
12
+ end
13
+ end
14
+
15
+ # rubygems
16
+ require 'rubygems'
17
+
18
+ # stdlib
19
+ require 'forwardable'
20
+ require 'fileutils'
21
+ require 'time'
22
+ require 'English'
23
+ require 'pathname'
24
+ require 'logger'
25
+ require 'set'
26
+
27
+ # 3rd party
28
+ require 'safe_yaml/load'
29
+ require 'liquid'
30
+ require 'kramdown'
31
+ require 'colorator'
32
+
33
+ SafeYAML::OPTIONS[:suppress_warnings] = true
34
+
35
+ module Bunto
36
+ # internal requires
37
+ autoload :Cleaner, 'bunto/cleaner'
38
+ autoload :Collection, 'bunto/collection'
39
+ autoload :Configuration, 'bunto/configuration'
40
+ autoload :Convertible, 'bunto/convertible'
41
+ autoload :Deprecator, 'bunto/deprecator'
42
+ autoload :Document, 'bunto/document'
43
+ autoload :Draft, 'bunto/draft'
44
+ autoload :EntryFilter, 'bunto/entry_filter'
45
+ autoload :Errors, 'bunto/errors'
46
+ autoload :Excerpt, 'bunto/excerpt'
47
+ autoload :External, 'bunto/external'
48
+ autoload :Filters, 'bunto/filters'
49
+ autoload :FrontmatterDefaults, 'bunto/frontmatter_defaults'
50
+ autoload :Hooks, 'bunto/hooks'
51
+ autoload :Layout, 'bunto/layout'
52
+ autoload :CollectionReader, 'bunto/readers/collection_reader'
53
+ autoload :DataReader, 'bunto/readers/data_reader'
54
+ autoload :LayoutReader, 'bunto/readers/layout_reader'
55
+ autoload :PostReader, 'bunto/readers/post_reader'
56
+ autoload :PageReader, 'bunto/readers/page_reader'
57
+ autoload :StaticFileReader, 'bunto/readers/static_file_reader'
58
+ autoload :LogAdapter, 'bunto/log_adapter'
59
+ autoload :Page, 'bunto/page'
60
+ autoload :PluginManager, 'bunto/plugin_manager'
61
+ autoload :Publisher, 'bunto/publisher'
62
+ autoload :Reader, 'bunto/reader'
63
+ autoload :Regenerator, 'bunto/regenerator'
64
+ autoload :RelatedPosts, 'bunto/related_posts'
65
+ autoload :Renderer, 'bunto/renderer'
66
+ autoload :LiquidRenderer, 'bunto/liquid_renderer'
67
+ autoload :Site, 'bunto/site'
68
+ autoload :StaticFile, 'bunto/static_file'
69
+ autoload :Stevenson, 'bunto/stevenson'
70
+ autoload :URL, 'bunto/url'
71
+ autoload :Utils, 'bunto/utils'
72
+ autoload :VERSION, 'bunto/version'
73
+
74
+ # extensions
75
+ require 'bunto/plugin'
76
+ require 'bunto/converter'
77
+ require 'bunto/generator'
78
+ require 'bunto/command'
79
+ require 'bunto/liquid_extensions'
80
+
81
+ class << self
82
+ # Public: Tells you which Bunto environment you are building in so you can skip tasks
83
+ # if you need to. This is useful when doing expensive compression tasks on css and
84
+ # images and allows you to skip that when working in development.
85
+
86
+ def env
87
+ ENV["BUNTO_ENV"] || "development"
88
+ end
89
+
90
+ # Public: Generate a Bunto configuration Hash by merging the default
91
+ # options with anything in _config.yml, and adding the given options on top.
92
+ #
93
+ # override - A Hash of config directives that override any options in both
94
+ # the defaults and the config file. See Bunto::Configuration::DEFAULTS for a
95
+ # list of option names and their defaults.
96
+ #
97
+ # Returns the final configuration Hash.
98
+ def configuration(override = {})
99
+ config = Configuration[Configuration::DEFAULTS]
100
+ override = Configuration[override].stringify_keys
101
+ unless override.delete('skip_config_files')
102
+ config = config.read_config_files(config.config_files(override))
103
+ end
104
+
105
+ # Merge DEFAULTS < _config.yml < override
106
+ config = Utils.deep_merge_hashes(config, override).stringify_keys
107
+ set_timezone(config['timezone']) if config['timezone']
108
+
109
+ config
110
+ end
111
+
112
+ # Public: Set the TZ environment variable to use the timezone specified
113
+ #
114
+ # timezone - the IANA Time Zone
115
+ #
116
+ # Returns nothing
117
+ def set_timezone(timezone)
118
+ ENV['TZ'] = timezone
119
+ end
120
+
121
+ # Public: Fetch the logger instance for this Bunto process.
122
+ #
123
+ # Returns the LogAdapter instance.
124
+ def logger
125
+ @logger ||= LogAdapter.new(Stevenson.new, (ENV["BUNTO_LOG_LEVEL"] || :info).to_sym)
126
+ end
127
+
128
+ # Public: Set the log writer.
129
+ # New log writer must respond to the same methods
130
+ # as Ruby's interal Logger.
131
+ #
132
+ # writer - the new Logger-compatible log transport
133
+ #
134
+ # Returns the new logger.
135
+ def logger=(writer)
136
+ @logger = LogAdapter.new(writer, (ENV["BUNTO_LOG_LEVEL"] || :info).to_sym)
137
+ end
138
+
139
+ # Public: An array of sites
140
+ #
141
+ # Returns the Bunto sites created.
142
+ def sites
143
+ @sites ||= []
144
+ end
145
+
146
+ # Public: Ensures the questionable path is prefixed with the base directory
147
+ # and prepends the questionable path with the base directory if false.
148
+ #
149
+ # base_directory - the directory with which to prefix the questionable path
150
+ # questionable_path - the path we're unsure about, and want prefixed
151
+ #
152
+ # Returns the sanitized path.
153
+ def sanitized_path(base_directory, questionable_path)
154
+ return base_directory if base_directory.eql?(questionable_path)
155
+
156
+ clean_path = File.expand_path(questionable_path, "/")
157
+ clean_path = clean_path.sub(/\A\w\:\//, '/')
158
+
159
+ if clean_path.start_with?(base_directory.sub(/\A\w\:\//, '/'))
160
+ clean_path
161
+ else
162
+ File.join(base_directory, clean_path)
163
+ end
164
+ end
165
+
166
+ # Conditional optimizations
167
+ Bunto::External.require_if_present('liquid-c')
168
+ end
169
+ end
170
+
171
+ require "bunto/drops/drop"
172
+ require_all 'bunto/commands'
173
+ require_all 'bunto/converters'
174
+ require_all 'bunto/converters/markdown'
175
+ require_all 'bunto/drops'
176
+ require_all 'bunto/generators'
177
+ require_all 'bunto/tags'
178
+
179
+ require 'bunto-sass-converter'
@@ -0,0 +1,105 @@
1
+ require 'set'
2
+
3
+ module Bunto
4
+ # Handles the cleanup of a site's destination before it is built.
5
+ class Cleaner
6
+ HIDDEN_FILE_REGEX = /\/\.{1,2}$/
7
+ attr_reader :site
8
+
9
+ def initialize(site)
10
+ @site = site
11
+ end
12
+
13
+ # Cleans up the site's destination directory
14
+ def cleanup!
15
+ FileUtils.rm_rf(obsolete_files)
16
+ FileUtils.rm_rf(metadata_file) unless @site.incremental?
17
+ end
18
+
19
+ private
20
+
21
+ # Private: The list of files and directories to be deleted during cleanup process
22
+ #
23
+ # Returns an Array of the file and directory paths
24
+ def obsolete_files
25
+ (existing_files - new_files - new_dirs + replaced_files).to_a
26
+ end
27
+
28
+ # Private: The metadata file storing dependency tree and build history
29
+ #
30
+ # Returns an Array with the metdata file as the only item
31
+ def metadata_file
32
+ [site.regenerator.metadata_file]
33
+ end
34
+
35
+ # Private: The list of existing files, apart from those included in keep_files and hidden files.
36
+ #
37
+ # Returns a Set with the file paths
38
+ def existing_files
39
+ files = Set.new
40
+ regex = keep_file_regex
41
+ dirs = keep_dirs
42
+
43
+ Utils.safe_glob(site.in_dest_dir, ["**", "*"], File::FNM_DOTMATCH).each do |file|
44
+ next if file =~ HIDDEN_FILE_REGEX || file =~ regex || dirs.include?(file)
45
+ files << file
46
+ end
47
+
48
+ files
49
+ end
50
+
51
+ # Private: The list of files to be created when site is built.
52
+ #
53
+ # Returns a Set with the file paths
54
+ def new_files
55
+ files = Set.new
56
+ site.each_site_file { |item| files << item.destination(site.dest) }
57
+ files
58
+ end
59
+
60
+ # Private: The list of directories to be created when site is built.
61
+ # These are the parent directories of the files in #new_files.
62
+ #
63
+ # Returns a Set with the directory paths
64
+ def new_dirs
65
+ new_files.map { |file| parent_dirs(file) }.flatten.to_set
66
+ end
67
+
68
+ # Private: The list of parent directories of a given file
69
+ #
70
+ # Returns an Array with the directory paths
71
+ def parent_dirs(file)
72
+ parent_dir = File.dirname(file)
73
+ if parent_dir == site.dest
74
+ []
75
+ else
76
+ [parent_dir] + parent_dirs(parent_dir)
77
+ end
78
+ end
79
+
80
+ # Private: The list of existing files that will be replaced by a directory during build
81
+ #
82
+ # Returns a Set with the file paths
83
+ def replaced_files
84
+ new_dirs.select { |dir| File.file?(dir) }.to_set
85
+ end
86
+
87
+ # Private: The list of directories that need to be kept because they are parent directories
88
+ # of files specified in keep_files
89
+ #
90
+ # Returns a Set with the directory paths
91
+ def keep_dirs
92
+ site.keep_files.map { |file| parent_dirs(site.in_dest_dir(file)) }.flatten.to_set
93
+ end
94
+
95
+ # Private: Creates a regular expression from the config's keep_files array
96
+ #
97
+ # Examples
98
+ # ['.git','.svn'] creates the following regex: /\/(\.git|\/.svn)/
99
+ #
100
+ # Returns the regular expression
101
+ def keep_file_regex
102
+ Regexp.union(site.keep_files)
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,205 @@
1
+ module Bunto
2
+ class Collection
3
+ attr_reader :site, :label, :metadata
4
+ attr_writer :docs
5
+
6
+ # Create a new Collection.
7
+ #
8
+ # site - the site to which this collection belongs.
9
+ # label - the name of the collection
10
+ #
11
+ # Returns nothing.
12
+ def initialize(site, label)
13
+ @site = site
14
+ @label = sanitize_label(label)
15
+ @metadata = extract_metadata
16
+ end
17
+
18
+ # Fetch the Documents in this collection.
19
+ # Defaults to an empty array if no documents have been read in.
20
+ #
21
+ # Returns an array of Bunto::Document objects.
22
+ def docs
23
+ @docs ||= []
24
+ end
25
+
26
+ # Override of normal respond_to? to match method_missing's logic for
27
+ # looking in @data.
28
+ def respond_to?(method, include_private = false)
29
+ docs.respond_to?(method.to_sym, include_private) || super
30
+ end
31
+
32
+ # Override of method_missing to check in @data for the key.
33
+ def method_missing(method, *args, &blck)
34
+ if docs.respond_to?(method.to_sym)
35
+ Bunto.logger.warn "Deprecation:", "#{label}.#{method} should be changed to #{label}.docs.#{method}."
36
+ Bunto.logger.warn "", "Called by #{caller.first}."
37
+ docs.public_send(method.to_sym, *args, &blck)
38
+ else
39
+ super
40
+ end
41
+ end
42
+
43
+ # Fetch the static files in this collection.
44
+ # Defaults to an empty array if no static files have been read in.
45
+ #
46
+ # Returns an array of Bunto::StaticFile objects.
47
+ def files
48
+ @files ||= []
49
+ end
50
+
51
+ # Read the allowed documents into the collection's array of docs.
52
+ #
53
+ # Returns the sorted array of docs.
54
+ def read
55
+ filtered_entries.each do |file_path|
56
+ full_path = collection_dir(file_path)
57
+ next if File.directory?(full_path)
58
+ if Utils.has_yaml_header? full_path
59
+ doc = Bunto::Document.new(full_path, { :site => site, :collection => self })
60
+ doc.read
61
+ if site.publisher.publish?(doc) || !write?
62
+ docs << doc
63
+ else
64
+ Bunto.logger.debug "Skipped From Publishing:", doc.relative_path
65
+ end
66
+ else
67
+ relative_dir = Bunto.sanitized_path(relative_directory, File.dirname(file_path)).chomp("/.")
68
+ files << StaticFile.new(site, site.source, relative_dir, File.basename(full_path), self)
69
+ end
70
+ end
71
+ docs.sort!
72
+ end
73
+
74
+ # All the entries in this collection.
75
+ #
76
+ # Returns an Array of file paths to the documents in this collection
77
+ # relative to the collection's directory
78
+ def entries
79
+ return [] unless exists?
80
+ @entries ||=
81
+ Utils.safe_glob(collection_dir, ["**", "*.*"]).map do |entry|
82
+ entry["#{collection_dir}/"] = ''
83
+ entry
84
+ end
85
+ end
86
+
87
+ # Filtered version of the entries in this collection.
88
+ # See `Bunto::EntryFilter#filter` for more information.
89
+ #
90
+ # Returns a list of filtered entry paths.
91
+ def filtered_entries
92
+ return [] unless exists?
93
+ @filtered_entries ||=
94
+ Dir.chdir(directory) do
95
+ entry_filter.filter(entries).reject do |f|
96
+ path = collection_dir(f)
97
+ File.directory?(path) || (File.symlink?(f) && site.safe)
98
+ end
99
+ end
100
+ end
101
+
102
+ # The directory for this Collection, relative to the site source.
103
+ #
104
+ # Returns a String containing the directory name where the collection
105
+ # is stored on the filesystem.
106
+ def relative_directory
107
+ @relative_directory ||= "_#{label}"
108
+ end
109
+
110
+ # The full path to the directory containing the collection.
111
+ #
112
+ # Returns a String containing th directory name where the collection
113
+ # is stored on the filesystem.
114
+ def directory
115
+ @directory ||= site.in_source_dir(relative_directory)
116
+ end
117
+
118
+ # The full path to the directory containing the collection, with
119
+ # optional subpaths.
120
+ #
121
+ # *files - (optional) any other path pieces relative to the
122
+ # directory to append to the path
123
+ #
124
+ # Returns a String containing th directory name where the collection
125
+ # is stored on the filesystem.
126
+ def collection_dir(*files)
127
+ return directory if files.empty?
128
+ site.in_source_dir(relative_directory, *files)
129
+ end
130
+
131
+ # Checks whether the directory "exists" for this collection.
132
+ # The directory must exist on the filesystem and must not be a symlink
133
+ # if in safe mode.
134
+ #
135
+ # Returns false if the directory doesn't exist or if it's a symlink
136
+ # and we're in safe mode.
137
+ def exists?
138
+ File.directory?(directory) && !(File.symlink?(directory) && site.safe)
139
+ end
140
+
141
+ # The entry filter for this collection.
142
+ # Creates an instance of Bunto::EntryFilter.
143
+ #
144
+ # Returns the instance of Bunto::EntryFilter for this collection.
145
+ def entry_filter
146
+ @entry_filter ||= Bunto::EntryFilter.new(site, relative_directory)
147
+ end
148
+
149
+ # An inspect string.
150
+ #
151
+ # Returns the inspect string
152
+ def inspect
153
+ "#<Bunto::Collection @label=#{label} docs=#{docs}>"
154
+ end
155
+
156
+ # Produce a sanitized label name
157
+ # Label names may not contain anything but alphanumeric characters,
158
+ # underscores, and hyphens.
159
+ #
160
+ # label - the possibly-unsafe label
161
+ #
162
+ # Returns a sanitized version of the label.
163
+ def sanitize_label(label)
164
+ label.gsub(/[^a-z0-9_\-\.]/i, '')
165
+ end
166
+
167
+ # Produce a representation of this Collection for use in Liquid.
168
+ # Exposes two attributes:
169
+ # - label
170
+ # - docs
171
+ #
172
+ # Returns a representation of this collection for use in Liquid.
173
+ def to_liquid
174
+ Drops::CollectionDrop.new self
175
+ end
176
+
177
+ # Whether the collection's documents ought to be written as individual
178
+ # files in the output.
179
+ #
180
+ # Returns true if the 'write' metadata is true, false otherwise.
181
+ def write?
182
+ !!metadata.fetch('output', false)
183
+ end
184
+
185
+ # The URL template to render collection's documents at.
186
+ #
187
+ # Returns the URL template to render collection's documents at.
188
+ def url_template
189
+ @url_template ||= metadata.fetch('permalink') do
190
+ Utils.add_permalink_suffix("/:collection/:path", site.permalink_style)
191
+ end
192
+ end
193
+
194
+ # Extract options for this collection from the site configuration.
195
+ #
196
+ # Returns the metadata for this collection
197
+ def extract_metadata
198
+ if site.config['collections'].is_a?(Hash)
199
+ site.config['collections'][label] || {}
200
+ else
201
+ {}
202
+ end
203
+ end
204
+ end
205
+ end