bunto 1.0.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.
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