blackboard 3.1.6 → 3.1.7

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 (108) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +132 -0
  3. data/exe/jekyll +55 -0
  4. data/lib/jekyll.rb +179 -0
  5. data/lib/jekyll/cleaner.rb +105 -0
  6. data/lib/jekyll/collection.rb +205 -0
  7. data/lib/jekyll/command.rb +65 -0
  8. data/lib/jekyll/commands/build.rb +77 -0
  9. data/lib/jekyll/commands/clean.rb +42 -0
  10. data/lib/jekyll/commands/doctor.rb +114 -0
  11. data/lib/jekyll/commands/help.rb +31 -0
  12. data/lib/jekyll/commands/new.rb +82 -0
  13. data/lib/jekyll/commands/serve.rb +205 -0
  14. data/lib/jekyll/commands/serve/servlet.rb +61 -0
  15. data/lib/jekyll/configuration.rb +348 -0
  16. data/lib/jekyll/converter.rb +48 -0
  17. data/lib/jekyll/converters/identity.rb +21 -0
  18. data/lib/jekyll/converters/markdown.rb +92 -0
  19. data/lib/jekyll/converters/markdown/kramdown_parser.rb +117 -0
  20. data/lib/jekyll/converters/markdown/rdiscount_parser.rb +33 -0
  21. data/lib/jekyll/converters/markdown/redcarpet_parser.rb +102 -0
  22. data/lib/jekyll/converters/smartypants.rb +34 -0
  23. data/lib/jekyll/convertible.rb +300 -0
  24. data/lib/jekyll/deprecator.rb +46 -0
  25. data/lib/jekyll/document.rb +447 -0
  26. data/lib/jekyll/drops/collection_drop.rb +22 -0
  27. data/lib/jekyll/drops/document_drop.rb +60 -0
  28. data/lib/jekyll/drops/drop.rb +200 -0
  29. data/lib/jekyll/drops/excerpt_drop.rb +15 -0
  30. data/lib/jekyll/drops/jekyll_drop.rb +33 -0
  31. data/lib/jekyll/drops/site_drop.rb +38 -0
  32. data/lib/jekyll/drops/unified_payload_drop.rb +25 -0
  33. data/lib/jekyll/drops/url_drop.rb +83 -0
  34. data/lib/jekyll/entry_filter.rb +72 -0
  35. data/lib/jekyll/errors.rb +10 -0
  36. data/lib/jekyll/excerpt.rb +124 -0
  37. data/lib/jekyll/external.rb +59 -0
  38. data/lib/jekyll/filters.rb +367 -0
  39. data/lib/jekyll/frontmatter_defaults.rb +188 -0
  40. data/lib/jekyll/generator.rb +3 -0
  41. data/lib/jekyll/hooks.rb +101 -0
  42. data/lib/jekyll/layout.rb +49 -0
  43. data/lib/jekyll/liquid_extensions.rb +22 -0
  44. data/lib/jekyll/liquid_renderer.rb +39 -0
  45. data/lib/jekyll/liquid_renderer/file.rb +50 -0
  46. data/lib/jekyll/liquid_renderer/table.rb +94 -0
  47. data/lib/jekyll/log_adapter.rb +115 -0
  48. data/lib/jekyll/mime.types +800 -0
  49. data/lib/jekyll/page.rb +180 -0
  50. data/lib/jekyll/plugin.rb +96 -0
  51. data/lib/jekyll/plugin_manager.rb +95 -0
  52. data/lib/jekyll/publisher.rb +21 -0
  53. data/lib/jekyll/reader.rb +126 -0
  54. data/lib/jekyll/readers/collection_reader.rb +20 -0
  55. data/lib/jekyll/readers/data_reader.rb +69 -0
  56. data/lib/jekyll/readers/layout_reader.rb +53 -0
  57. data/lib/jekyll/readers/page_reader.rb +21 -0
  58. data/lib/jekyll/readers/post_reader.rb +62 -0
  59. data/lib/jekyll/readers/static_file_reader.rb +21 -0
  60. data/lib/jekyll/regenerator.rb +175 -0
  61. data/lib/jekyll/related_posts.rb +56 -0
  62. data/lib/jekyll/renderer.rb +194 -0
  63. data/lib/jekyll/site.rb +392 -0
  64. data/lib/jekyll/static_file.rb +141 -0
  65. data/lib/jekyll/stevenson.rb +58 -0
  66. data/lib/jekyll/tags/highlight.rb +122 -0
  67. data/lib/jekyll/tags/include.rb +190 -0
  68. data/lib/jekyll/tags/post_url.rb +88 -0
  69. data/lib/jekyll/url.rb +136 -0
  70. data/lib/jekyll/utils.rb +300 -0
  71. data/lib/jekyll/utils/ansi.rb +59 -0
  72. data/lib/jekyll/utils/platforms.rb +30 -0
  73. data/lib/jekyll/version.rb +3 -0
  74. data/lib/site_template/.gitignore +3 -0
  75. data/lib/site_template/_config.yml +24 -0
  76. data/lib/site_template/_includes/footer.html +38 -0
  77. data/lib/site_template/_includes/head.html +12 -0
  78. data/lib/site_template/_includes/header.html +27 -0
  79. data/lib/site_template/_includes/icon-github.html +1 -0
  80. data/lib/site_template/_includes/icon-github.svg +1 -0
  81. data/lib/site_template/_includes/icon-twitter.html +1 -0
  82. data/lib/site_template/_includes/icon-twitter.svg +1 -0
  83. data/lib/site_template/_layouts/default.html +20 -0
  84. data/lib/site_template/_layouts/page.html +14 -0
  85. data/lib/site_template/_layouts/post.html +15 -0
  86. data/lib/site_template/_pages/about.md +15 -0
  87. data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.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/css/main.scss +53 -0
  92. data/lib/site_template/feed.xml +30 -0
  93. data/lib/site_template/index.html +23 -0
  94. data/lib/theme_template/CODE_OF_CONDUCT.md.erb +74 -0
  95. data/lib/theme_template/Gemfile +2 -0
  96. data/lib/theme_template/LICENSE.txt.erb +21 -0
  97. data/lib/theme_template/README.md.erb +46 -0
  98. data/lib/theme_template/Rakefile.erb +74 -0
  99. data/lib/theme_template/_layouts/default.html +1 -0
  100. data/lib/theme_template/_layouts/page.html +5 -0
  101. data/lib/theme_template/_layouts/post.html +5 -0
  102. data/lib/theme_template/example/_config.yml.erb +1 -0
  103. data/lib/theme_template/example/_post.md +12 -0
  104. data/lib/theme_template/example/index.html +14 -0
  105. data/lib/theme_template/example/style.scss +7 -0
  106. data/lib/theme_template/gitignore.erb +4 -0
  107. data/lib/theme_template/theme.gemspec.erb +22 -0
  108. metadata +109 -2
@@ -0,0 +1,31 @@
1
+ module Jekyll
2
+ module Commands
3
+ class Help < Command
4
+ class << self
5
+ def init_with_program(prog)
6
+ prog.command(:help) do |c|
7
+ c.syntax 'help [subcommand]'
8
+ c.description 'Show the help message, optionally for a given subcommand.'
9
+
10
+ c.action do |args, _|
11
+ cmd = (args.first || "").to_sym
12
+ if args.empty?
13
+ puts prog
14
+ elsif prog.has_command? cmd
15
+ puts prog.commands[cmd]
16
+ else
17
+ invalid_command(prog, cmd)
18
+ abort
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ def invalid_command(prog, cmd)
25
+ Jekyll.logger.error "Error:", "Hmm... we don't know what the '#{cmd}' command is."
26
+ Jekyll.logger.info "Valid commands:", prog.commands.keys.join(", ")
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,82 @@
1
+ require 'erb'
2
+
3
+ module Jekyll
4
+ module Commands
5
+ class New < Command
6
+ class << self
7
+ def init_with_program(prog)
8
+ prog.command(:new) do |c|
9
+ c.syntax 'new PATH'
10
+ c.description 'Creates a new Jekyll site scaffold in PATH'
11
+
12
+ c.option 'force', '--force', 'Force creation even if PATH already exists'
13
+ c.option 'blank', '--blank', 'Creates scaffolding but with empty files'
14
+
15
+ c.action do |args, options|
16
+ Jekyll::Commands::New.process(args, options)
17
+ end
18
+ end
19
+ end
20
+
21
+ def process(args, options = {})
22
+ raise ArgumentError.new('You must specify a path.') if args.empty?
23
+
24
+ new_blog_path = File.expand_path(args.join(" "), Dir.pwd)
25
+ FileUtils.mkdir_p new_blog_path
26
+ if preserve_source_location?(new_blog_path, options)
27
+ Jekyll.logger.abort_with "Conflict:", "#{new_blog_path} exists and is not empty."
28
+ end
29
+
30
+ if options["blank"]
31
+ create_blank_site new_blog_path
32
+ else
33
+ create_sample_files new_blog_path
34
+
35
+ File.open(File.expand_path(initialized_post_name, new_blog_path), "w") do |f|
36
+ f.write(scaffold_post_content)
37
+ end
38
+ end
39
+
40
+ Jekyll.logger.info "New jekyll site installed in #{new_blog_path}."
41
+ end
42
+
43
+ def create_blank_site(path)
44
+ Dir.chdir(path) do
45
+ FileUtils.mkdir(%w(_layouts _posts _drafts))
46
+ FileUtils.touch("index.html")
47
+ end
48
+ end
49
+
50
+ def scaffold_post_content
51
+ ERB.new(File.read(File.expand_path(scaffold_path, site_template))).result
52
+ end
53
+
54
+ # Internal: Gets the filename of the sample post to be created
55
+ #
56
+ # Returns the filename of the sample post, as a String
57
+ def initialized_post_name
58
+ "_posts/#{Time.now.strftime('%Y-%m-%d')}-welcome-to-jekyll.markdown"
59
+ end
60
+
61
+ private
62
+
63
+ def preserve_source_location?(path, options)
64
+ !options["force"] && !Dir["#{path}/**/*"].empty?
65
+ end
66
+
67
+ def create_sample_files(path)
68
+ FileUtils.cp_r site_template + '/.', path
69
+ FileUtils.rm File.expand_path(scaffold_path, path)
70
+ end
71
+
72
+ def site_template
73
+ File.expand_path("../../site_template", File.dirname(__FILE__))
74
+ end
75
+
76
+ def scaffold_path
77
+ "_posts/0000-00-00-welcome-to-jekyll.markdown.erb"
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,205 @@
1
+ module Jekyll
2
+ module Commands
3
+ class Serve < Command
4
+ class << self
5
+ COMMAND_OPTIONS = {
6
+ "ssl_cert" => ["--ssl-cert [CERT]", "X.509 (SSL) certificate."],
7
+ "host" => ["host", "-H", "--host [HOST]", "Host to bind to"],
8
+ "open_url" => ["-o", "--open-url", "Launch your browser with your site."],
9
+ "detach" => ["-B", "--detach", "Run the server in the background (detach)"],
10
+ "ssl_key" => ["--ssl-key [KEY]", "X.509 (SSL) Private Key."],
11
+ "port" => ["-P", "--port [PORT]", "Port to listen on"],
12
+ "baseurl" => ["-b", "--baseurl [URL]", "Base URL"],
13
+ "skip_initial_build" => ["skip_initial_build", "--skip-initial-build",
14
+ "Skips the initial site build which occurs before the server is started."]
15
+ }
16
+
17
+ #
18
+
19
+ def init_with_program(prog)
20
+ prog.command(:serve) do |cmd|
21
+ cmd.description "Serve your site locally"
22
+ cmd.syntax "serve [options]"
23
+ cmd.alias :server
24
+ cmd.alias :s
25
+
26
+ add_build_options(cmd)
27
+ COMMAND_OPTIONS.each do |key, val|
28
+ cmd.option key, *val
29
+ end
30
+
31
+ cmd.action do |_, opts|
32
+ opts["serving"] = true
33
+ opts["watch" ] = true unless opts.key?("watch")
34
+ Build.process(opts)
35
+ Serve.process(opts)
36
+ end
37
+ end
38
+ end
39
+
40
+ #
41
+
42
+ def process(opts)
43
+ opts = configuration_from_options(opts)
44
+ destination = opts["destination"]
45
+ setup(destination)
46
+
47
+ server = WEBrick::HTTPServer.new(webrick_opts(opts)).tap { |o| o.unmount("") }
48
+ server.mount(opts["baseurl"], Servlet, destination, file_handler_opts)
49
+ Jekyll.logger.info "Server address:", server_address(server, opts)
50
+ launch_browser server, opts if opts["open_url"]
51
+ boot_or_detach server, opts
52
+ end
53
+
54
+ # Do a base pre-setup of WEBRick so that everything is in place
55
+ # when we get ready to party, checking for an setting up an error page
56
+ # and making sure our destination exists.
57
+
58
+ private
59
+ def setup(destination)
60
+ require_relative "serve/servlet"
61
+
62
+ FileUtils.mkdir_p(destination)
63
+ if File.exist?(File.join(destination, "404.html"))
64
+ WEBrick::HTTPResponse.class_eval do
65
+ def create_error_page
66
+ @header["Content-Type"] = "text/html; charset=UTF-8"
67
+ @body = IO.read(File.join(@config[:DocumentRoot], "404.html"))
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ #
74
+
75
+ private
76
+ def webrick_opts(opts)
77
+ opts = {
78
+ :JekyllOptions => opts,
79
+ :DoNotReverseLookup => true,
80
+ :MimeTypes => mime_types,
81
+ :DocumentRoot => opts["destination"],
82
+ :StartCallback => start_callback(opts["detach"]),
83
+ :BindAddress => opts["host"],
84
+ :Port => opts["port"],
85
+ :DirectoryIndex => %W(
86
+ index.htm
87
+ index.html
88
+ index.rhtml
89
+ index.cgi
90
+ index.xml
91
+ )
92
+ }
93
+
94
+ enable_ssl(opts)
95
+ enable_logging(opts)
96
+ opts
97
+ end
98
+
99
+ # Recreate NondisclosureName under utf-8 circumstance
100
+
101
+ private
102
+ def file_handler_opts
103
+ WEBrick::Config::FileHandler.merge({
104
+ :FancyIndexing => true,
105
+ :NondisclosureName => [
106
+ '.ht*', '~*'
107
+ ]
108
+ })
109
+ end
110
+
111
+ #
112
+
113
+ private
114
+ def server_address(server, opts)
115
+ "%{prefix}://%{address}:%{port}%{baseurl}" % {
116
+ :prefix => server.config[:SSLEnable] ? "https" : "http",
117
+ :baseurl => opts["baseurl"] ? "#{opts["baseurl"]}/" : "",
118
+ :address => server.config[:BindAddress],
119
+ :port => server.config[:Port]
120
+ }
121
+ end
122
+
123
+ #
124
+
125
+ private
126
+ def launch_browser(server, opts)
127
+ command =
128
+ if Utils::Platforms.windows?
129
+ "start"
130
+ elsif Utils::Platforms.osx?
131
+ "open"
132
+ else
133
+ "xdg-open"
134
+ end
135
+ system command, server_address(server, opts)
136
+ end
137
+
138
+ # Keep in our area with a thread or detach the server as requested
139
+ # by the user. This method determines what we do based on what you
140
+ # ask us to do.
141
+
142
+ private
143
+ def boot_or_detach(server, opts)
144
+ if opts["detach"]
145
+ pid = Process.fork do
146
+ server.start
147
+ end
148
+
149
+ Process.detach(pid)
150
+ Jekyll.logger.info "Server detached with pid '#{pid}'.", \
151
+ "Run `pkill -f jekyll' or `kill -9 #{pid}' to stop the server."
152
+ else
153
+ t = Thread.new { server.start }
154
+ trap("INT") { server.shutdown }
155
+ t.join
156
+ end
157
+ end
158
+
159
+ # Make the stack verbose if the user requests it.
160
+
161
+ private
162
+ def enable_logging(opts)
163
+ opts[:AccessLog] = []
164
+ level = WEBrick::Log.const_get(opts[:JekyllOptions]["verbose"] ? :DEBUG : :WARN)
165
+ opts[:Logger] = WEBrick::Log.new($stdout, level)
166
+ end
167
+
168
+ # Add SSL to the stack if the user triggers --enable-ssl and they
169
+ # provide both types of certificates commonly needed. Raise if they
170
+ # forget to add one of the certificates.
171
+
172
+ private
173
+ def enable_ssl(opts)
174
+ return if !opts[:JekyllOptions]["ssl_cert"] && !opts[:JekyllOptions]["ssl_key"]
175
+ if !opts[:JekyllOptions]["ssl_cert"] || !opts[:JekyllOptions]["ssl_key"]
176
+ raise RuntimeError, "--ssl-cert or --ssl-key missing."
177
+ end
178
+
179
+ require "openssl"
180
+ require "webrick/https"
181
+ source_key = Jekyll.sanitized_path(opts[:JekyllOptions]["source"], opts[:JekyllOptions]["ssl_key" ])
182
+ source_certificate = Jekyll.sanitized_path(opts[:JekyllOptions]["source"], opts[:JekyllOptions]["ssl_cert"])
183
+ opts[:SSLCertificate] = OpenSSL::X509::Certificate.new(File.read(source_certificate))
184
+ opts[:SSLPrivateKey ] = OpenSSL::PKey::RSA.new(File.read(source_key))
185
+ opts[:SSLEnable] = true
186
+ end
187
+
188
+ private
189
+ def start_callback(detached)
190
+ unless detached
191
+ proc do
192
+ Jekyll.logger.info("Server running...", "press ctrl-c to stop.")
193
+ end
194
+ end
195
+ end
196
+
197
+ private
198
+ def mime_types
199
+ file = File.expand_path('../mime.types', File.dirname(__FILE__))
200
+ WEBrick::HTTPUtils.load_mime_types(file)
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,61 @@
1
+ require "webrick"
2
+
3
+ module Jekyll
4
+ module Commands
5
+ class Serve
6
+ class Servlet < WEBrick::HTTPServlet::FileHandler
7
+ DEFAULTS = {
8
+ "Cache-Control" => "private, max-age=0, proxy-revalidate, " \
9
+ "no-store, no-cache, must-revalidate"
10
+ }
11
+
12
+ def initialize(server, root, callbacks)
13
+ # So we can access them easily.
14
+ @jekyll_opts = server.config[:JekyllOptions]
15
+ set_defaults
16
+ super
17
+ end
18
+
19
+ # Add the ability to tap file.html the same way that Nginx does on our
20
+ # Docker images (or on GitHub Pages.) The difference is that we might end
21
+ # up with a different preference on which comes first.
22
+
23
+ def search_file(req, res, basename)
24
+ # /file.* > /file/index.html > /file.html
25
+ super || super(req, res, "#{basename}.html")
26
+ end
27
+
28
+ #
29
+
30
+ def do_GET(req, res)
31
+ rtn = super
32
+ validate_and_ensure_charset(req, res)
33
+ res.header.merge!(@headers)
34
+ rtn
35
+ end
36
+
37
+ #
38
+
39
+ private
40
+ def validate_and_ensure_charset(_req, res)
41
+ key = res.header.keys.grep(/content-type/i).first
42
+ typ = res.header[key]
43
+
44
+ unless typ =~ /;\s*charset=/
45
+ res.header[key] = "#{typ}; charset=#{@jekyll_opts["encoding"]}"
46
+ end
47
+ end
48
+
49
+ #
50
+
51
+ private
52
+ def set_defaults
53
+ hash_ = @jekyll_opts.fetch("webrick", {}).fetch("headers", {})
54
+ DEFAULTS.each_with_object(@headers = hash_) do |(key, val), hash|
55
+ hash[key] = val unless hash.key?(key)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,348 @@
1
+ # encoding: UTF-8
2
+
3
+ module Jekyll
4
+ class Configuration < Hash
5
+ # Default options. Overridden by values in _config.yml.
6
+ # Strings rather than symbols are used for compatibility with YAML.
7
+ DEFAULTS = Configuration[{
8
+ # Where things are
9
+ 'source' => Dir.pwd,
10
+ 'destination' => File.join(Dir.pwd, '_site'),
11
+ 'plugins_dir' => '_plugins',
12
+ 'layouts_dir' => '_layouts',
13
+ 'data_dir' => '_data',
14
+ 'includes_dir' => '_includes',
15
+ 'collections' => {},
16
+
17
+ # Handling Reading
18
+ 'safe' => false,
19
+ 'include' => ['.htaccess'],
20
+ 'exclude' => [],
21
+ 'keep_files' => ['.git', '.svn'],
22
+ 'encoding' => 'utf-8',
23
+ 'markdown_ext' => 'markdown,mkdown,mkdn,mkd,md',
24
+
25
+ # Filtering Content
26
+ 'show_drafts' => nil,
27
+ 'limit_posts' => 0,
28
+ 'future' => false,
29
+ 'unpublished' => false,
30
+
31
+ # Plugins
32
+ 'whitelist' => [],
33
+ 'gems' => [],
34
+
35
+ # Conversion
36
+ 'markdown' => 'kramdown',
37
+ 'highlighter' => 'rouge',
38
+ 'lsi' => false,
39
+ 'excerpt_separator' => "\n\n",
40
+ 'incremental' => false,
41
+
42
+ # Serving
43
+ 'detach' => false, # default to not detaching the server
44
+ 'port' => '4000',
45
+ 'host' => '127.0.0.1',
46
+ 'baseurl' => '',
47
+
48
+ # Output Configuration
49
+ 'permalink' => 'date',
50
+ 'paginate_path' => '/page:num',
51
+ 'timezone' => nil, # use the local timezone
52
+
53
+ 'quiet' => false,
54
+ 'verbose' => false,
55
+ 'defaults' => [],
56
+
57
+ 'rdiscount' => {
58
+ 'extensions' => []
59
+ },
60
+
61
+ 'redcarpet' => {
62
+ 'extensions' => []
63
+ },
64
+
65
+ 'kramdown' => {
66
+ 'auto_ids' => true,
67
+ 'toc_levels' => '1..6',
68
+ 'entity_output' => 'as_char',
69
+ 'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo',
70
+ 'input' => "GFM",
71
+ 'hard_wrap' => false,
72
+ 'footnote_nr' => 1
73
+ }
74
+ }.map { |k, v| [k, v.freeze] }].freeze
75
+
76
+ class << self
77
+ # Static: Produce a Configuration ready for use in a Site.
78
+ # It takes the input, fills in the defaults where values do not
79
+ # exist, and patches common issues including migrating options for
80
+ # backwards compatiblity. Except where a key or value is being fixed,
81
+ # the user configuration will override the defaults.
82
+ #
83
+ # user_config - a Hash or Configuration of overrides.
84
+ #
85
+ # Returns a Configuration filled with defaults and fixed for common
86
+ # problems and backwards-compatibility.
87
+ def from(user_config)
88
+ Utils.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys).
89
+ fix_common_issues.add_default_collections
90
+ end
91
+ end
92
+
93
+ # Public: Turn all keys into string
94
+ #
95
+ # Return a copy of the hash where all its keys are strings
96
+ def stringify_keys
97
+ reduce({}) { |hsh, (k, v)| hsh.merge(k.to_s => v) }
98
+ end
99
+
100
+ def get_config_value_with_override(config_key, override)
101
+ override[config_key] || self[config_key] || DEFAULTS[config_key]
102
+ end
103
+
104
+ # Public: Directory of the Jekyll source folder
105
+ #
106
+ # override - the command-line options hash
107
+ #
108
+ # Returns the path to the Jekyll source directory
109
+ def source(override)
110
+ get_config_value_with_override('source', override)
111
+ end
112
+
113
+ def quiet(override = {})
114
+ get_config_value_with_override('quiet', override)
115
+ end
116
+ alias_method :quiet?, :quiet
117
+
118
+ def verbose(override = {})
119
+ get_config_value_with_override('verbose', override)
120
+ end
121
+ alias_method :verbose?, :verbose
122
+
123
+ def safe_load_file(filename)
124
+ case File.extname(filename)
125
+ when /\.toml/i
126
+ Jekyll::External.require_with_graceful_fail('toml') unless defined?(TOML)
127
+ TOML.load_file(filename)
128
+ when /\.ya?ml/i
129
+ SafeYAML.load_file(filename) || {}
130
+ else
131
+ raise ArgumentError, "No parser for '#{filename}' is available. Use a .toml or .y(a)ml file instead."
132
+ end
133
+ end
134
+
135
+ # Public: Generate list of configuration files from the override
136
+ #
137
+ # override - the command-line options hash
138
+ #
139
+ # Returns an Array of config files
140
+ def config_files(override)
141
+ # Adjust verbosity quickly
142
+ Jekyll.logger.adjust_verbosity(:quiet => quiet?(override), :verbose => verbose?(override))
143
+
144
+ # Get configuration from <source>/_config.yml or <source>/<config_file>
145
+ config_files = override.delete('config')
146
+ if config_files.to_s.empty?
147
+ default = %w(yml yaml).find(-> { 'yml' }) do |ext|
148
+ File.exist?(Jekyll.sanitized_path(source(override), "_config.#{ext}"))
149
+ end
150
+ config_files = Jekyll.sanitized_path(source(override), "_config.#{default}")
151
+ @default_config_file = true
152
+ end
153
+ config_files = [config_files] unless config_files.is_a? Array
154
+ config_files
155
+ end
156
+
157
+ # Public: Read configuration and return merged Hash
158
+ #
159
+ # file - the path to the YAML file to be read in
160
+ #
161
+ # Returns this configuration, overridden by the values in the file
162
+ def read_config_file(file)
163
+ next_config = safe_load_file(file)
164
+ check_config_is_hash!(next_config, file)
165
+ Jekyll.logger.info "Configuration file:", file
166
+ next_config
167
+ rescue SystemCallError
168
+ if @default_config_file
169
+ Jekyll.logger.warn "Configuration file:", "none"
170
+ {}
171
+ else
172
+ Jekyll.logger.error "Fatal:", "The configuration file '#{file}' could not be found."
173
+ raise LoadError, "The Configuration file '#{file}' could not be found."
174
+ end
175
+ end
176
+
177
+ # Public: Read in a list of configuration files and merge with this hash
178
+ #
179
+ # files - the list of configuration file paths
180
+ #
181
+ # Returns the full configuration, with the defaults overridden by the values in the
182
+ # configuration files
183
+ def read_config_files(files)
184
+ configuration = clone
185
+
186
+ begin
187
+ files.each do |config_file|
188
+ next if config_file.nil? or config_file.empty?
189
+ new_config = read_config_file(config_file)
190
+ configuration = Utils.deep_merge_hashes(configuration, new_config)
191
+ end
192
+ rescue ArgumentError => err
193
+ Jekyll.logger.warn "WARNING:", "Error reading configuration. " \
194
+ "Using defaults (and options)."
195
+ $stderr.puts "#{err}"
196
+ end
197
+
198
+ configuration.fix_common_issues.backwards_compatibilize.add_default_collections
199
+ end
200
+
201
+ # Public: Split a CSV string into an array containing its values
202
+ #
203
+ # csv - the string of comma-separated values
204
+ #
205
+ # Returns an array of the values contained in the CSV
206
+ def csv_to_array(csv)
207
+ csv.split(",").map(&:strip)
208
+ end
209
+
210
+ # Public: Ensure the proper options are set in the configuration to allow for
211
+ # backwards-compatibility with Jekyll pre-1.0
212
+ #
213
+ # Returns the backwards-compatible configuration
214
+ def backwards_compatibilize
215
+ config = clone
216
+ # Provide backwards-compatibility
217
+ if config.key?('auto') || config.key?('watch')
218
+ Jekyll::Deprecator.deprecation_message "Auto-regeneration can no longer" \
219
+ " be set from your configuration file(s). Use the"\
220
+ " --[no-]watch/-w command-line option instead."
221
+ config.delete('auto')
222
+ config.delete('watch')
223
+ end
224
+
225
+ if config.key? 'server'
226
+ Jekyll::Deprecator.deprecation_message "The 'server' configuration option" \
227
+ " is no longer accepted. Use the 'jekyll serve'" \
228
+ " subcommand to serve your site with WEBrick."
229
+ config.delete('server')
230
+ end
231
+
232
+ renamed_key 'server_port', 'port', config
233
+ renamed_key 'plugins', 'plugins_dir', config
234
+ renamed_key 'layouts', 'layouts_dir', config
235
+ renamed_key 'data_source', 'data_dir', config
236
+
237
+ if config.key? 'pygments'
238
+ Jekyll::Deprecator.deprecation_message "The 'pygments' configuration option" \
239
+ " has been renamed to 'highlighter'. Please update your" \
240
+ " config file accordingly. The allowed values are 'rouge', " \
241
+ "'pygments' or null."
242
+
243
+ config['highlighter'] = 'pygments' if config['pygments']
244
+ config.delete('pygments')
245
+ end
246
+
247
+ %w(include exclude).each do |option|
248
+ if config[option].is_a?(String)
249
+ Jekyll::Deprecator.deprecation_message "The '#{option}' configuration option" \
250
+ " must now be specified as an array, but you specified" \
251
+ " a string. For now, we've treated the string you provided" \
252
+ " as a list of comma-separated values."
253
+ config[option] = csv_to_array(config[option])
254
+ end
255
+ config[option].map!(&:to_s) if config[option]
256
+ end
257
+
258
+ if (config['kramdown'] || {}).key?('use_coderay')
259
+ Jekyll::Deprecator.deprecation_message "Please change 'use_coderay'" \
260
+ " to 'enable_coderay' in your configuration file."
261
+ config['kramdown']['use_coderay'] = config['kramdown'].delete('enable_coderay')
262
+ end
263
+
264
+ if config.fetch('markdown', 'kramdown').to_s.downcase.eql?("maruku")
265
+ Jekyll.logger.abort_with "Error:", "You're using the 'maruku' " \
266
+ "Markdown processor, which has been removed as of 3.0.0. " \
267
+ "We recommend you switch to Kramdown. To do this, replace " \
268
+ "`markdown: maruku` with `markdown: kramdown` in your " \
269
+ "`_config.yml` file."
270
+ end
271
+
272
+ config
273
+ end
274
+
275
+ def fix_common_issues
276
+ config = clone
277
+
278
+ if config.key?('paginate') && (!config['paginate'].is_a?(Integer) || config['paginate'] < 1)
279
+ Jekyll.logger.warn "Config Warning:", "The `paginate` key must be a" \
280
+ " positive integer or nil. It's currently set to '#{config['paginate'].inspect}'."
281
+ config['paginate'] = nil
282
+ end
283
+
284
+ config
285
+ end
286
+
287
+ def add_default_collections
288
+ config = clone
289
+
290
+ # It defaults to `{}`, so this is only if someone sets it to null manually.
291
+ return config if config['collections'].nil?
292
+
293
+ # Ensure we have a hash.
294
+ if config['collections'].is_a?(Array)
295
+ config['collections'] = Hash[config['collections'].map { |c| [c, {}] }]
296
+ end
297
+
298
+ config['collections'] = Utils.deep_merge_hashes(
299
+ { 'posts' => {} }, config['collections']
300
+ ).tap do |collections|
301
+ collections['posts']['output'] = true
302
+ if config['permalink']
303
+ collections['posts']['permalink'] ||= style_to_permalink(config['permalink'])
304
+ end
305
+ end
306
+
307
+ config
308
+ end
309
+
310
+ def renamed_key(old, new, config, _ = nil)
311
+ if config.key?(old)
312
+ Jekyll::Deprecator.deprecation_message "The '#{old}' configuration" \
313
+ "option has been renamed to '#{new}'. Please update your config " \
314
+ "file accordingly."
315
+ config[new] = config.delete(old)
316
+ end
317
+ end
318
+
319
+ private
320
+
321
+ def style_to_permalink(permalink_style)
322
+ case permalink_style.to_sym
323
+ when :pretty
324
+ "/:categories/:year/:month/:day/:title/"
325
+ when :none
326
+ "/:categories/:title:output_ext"
327
+ when :date
328
+ "/:categories/:year/:month/:day/:title:output_ext"
329
+ when :ordinal
330
+ "/:categories/:year/:y_day/:title:output_ext"
331
+ else
332
+ permalink_style.to_s
333
+ end
334
+ end
335
+
336
+ # Private: Checks if a given config is a hash
337
+ #
338
+ # extracted_config - the value to check
339
+ # file - the file from which the config was extracted
340
+ #
341
+ # Raises an ArgumentError if given config is not a hash
342
+ def check_config_is_hash!(extracted_config, file)
343
+ unless extracted_config.is_a?(Hash)
344
+ raise ArgumentError.new("Configuration file: (INVALID) #{file}".yellow)
345
+ end
346
+ end
347
+ end
348
+ end