monad 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CONTRIBUTING.md +68 -0
- data/Gemfile +2 -0
- data/LICENSE +21 -0
- data/README.md +88 -0
- data/Rakefile +136 -0
- data/bin/monad +102 -0
- data/cucumber.yml +3 -0
- data/features/create_sites.feature +112 -0
- data/features/data_sources.feature +76 -0
- data/features/drafts.feature +25 -0
- data/features/embed_filters.feature +60 -0
- data/features/markdown.feature +30 -0
- data/features/pagination.feature +54 -0
- data/features/permalinks.feature +65 -0
- data/features/post_data.feature +214 -0
- data/features/site_configuration.feature +206 -0
- data/features/site_data.feature +101 -0
- data/features/step_definitions/monad_steps.rb +175 -0
- data/features/support/env.rb +25 -0
- data/lib/monad.rb +90 -0
- data/lib/monad/command.rb +27 -0
- data/lib/monad/commands/build.rb +64 -0
- data/lib/monad/commands/doctor.rb +29 -0
- data/lib/monad/commands/new.rb +50 -0
- data/lib/monad/commands/serve.rb +33 -0
- data/lib/monad/configuration.rb +183 -0
- data/lib/monad/converter.rb +48 -0
- data/lib/monad/converters/identity.rb +21 -0
- data/lib/monad/converters/markdown.rb +43 -0
- data/lib/monad/converters/markdown/kramdown_parser.rb +44 -0
- data/lib/monad/converters/markdown/maruku_parser.rb +47 -0
- data/lib/monad/converters/markdown/rdiscount_parser.rb +35 -0
- data/lib/monad/converters/markdown/redcarpet_parser.rb +70 -0
- data/lib/monad/converters/textile.rb +50 -0
- data/lib/monad/convertible.rb +152 -0
- data/lib/monad/core_ext.rb +68 -0
- data/lib/monad/deprecator.rb +32 -0
- data/lib/monad/draft.rb +35 -0
- data/lib/monad/drivers/json_driver.rb +39 -0
- data/lib/monad/drivers/yaml_driver.rb +23 -0
- data/lib/monad/errors.rb +4 -0
- data/lib/monad/filters.rb +154 -0
- data/lib/monad/generator.rb +4 -0
- data/lib/monad/generators/pagination.rb +143 -0
- data/lib/monad/layout.rb +42 -0
- data/lib/monad/logger.rb +54 -0
- data/lib/monad/mime.types +85 -0
- data/lib/monad/page.rb +163 -0
- data/lib/monad/plugin.rb +75 -0
- data/lib/monad/post.rb +377 -0
- data/lib/monad/site.rb +455 -0
- data/lib/monad/static_file.rb +70 -0
- data/lib/monad/tags/gist.rb +30 -0
- data/lib/monad/tags/highlight.rb +85 -0
- data/lib/monad/tags/include.rb +37 -0
- data/lib/monad/tags/post_url.rb +61 -0
- data/lib/site_template/.gitignore +1 -0
- data/lib/site_template/_config.yml +2 -0
- data/lib/site_template/_layouts/default.html +46 -0
- data/lib/site_template/_layouts/post.html +9 -0
- data/lib/site_template/_posts/0000-00-00-welcome-to-monad.markdown.erb +24 -0
- data/lib/site_template/css/main.css +165 -0
- data/lib/site_template/css/syntax.css +60 -0
- data/lib/site_template/index.html +13 -0
- data/monad.gemspec +197 -0
- data/script/bootstrap +2 -0
- data/test/fixtures/broken_front_matter1.erb +5 -0
- data/test/fixtures/broken_front_matter2.erb +4 -0
- data/test/fixtures/broken_front_matter3.erb +7 -0
- data/test/fixtures/exploit_front_matter.erb +4 -0
- data/test/fixtures/front_matter.erb +4 -0
- data/test/fixtures/members.yaml +7 -0
- data/test/helper.rb +62 -0
- data/test/source/.htaccess +8 -0
- data/test/source/_includes/sig.markdown +3 -0
- data/test/source/_layouts/default.html +27 -0
- data/test/source/_layouts/simple.html +1 -0
- data/test/source/_plugins/dummy.rb +8 -0
- data/test/source/_posts/2008-02-02-not-published.textile +8 -0
- data/test/source/_posts/2008-02-02-published.textile +8 -0
- data/test/source/_posts/2008-10-18-foo-bar.textile +8 -0
- data/test/source/_posts/2008-11-21-complex.textile +8 -0
- data/test/source/_posts/2008-12-03-permalinked-post.textile +9 -0
- data/test/source/_posts/2008-12-13-include.markdown +8 -0
- data/test/source/_posts/2009-01-27-array-categories.textile +10 -0
- data/test/source/_posts/2009-01-27-categories.textile +7 -0
- data/test/source/_posts/2009-01-27-category.textile +7 -0
- data/test/source/_posts/2009-01-27-empty-categories.textile +7 -0
- data/test/source/_posts/2009-01-27-empty-category.textile +7 -0
- data/test/source/_posts/2009-03-12-hash-#1.markdown +6 -0
- data/test/source/_posts/2009-05-18-empty-tag.textile +6 -0
- data/test/source/_posts/2009-05-18-empty-tags.textile +6 -0
- data/test/source/_posts/2009-05-18-tag.textile +6 -0
- data/test/source/_posts/2009-05-18-tags.textile +9 -0
- data/test/source/_posts/2009-06-22-empty-yaml.textile +3 -0
- data/test/source/_posts/2009-06-22-no-yaml.textile +1 -0
- data/test/source/_posts/2010-01-08-triple-dash.markdown +5 -0
- data/test/source/_posts/2010-01-09-date-override.textile +7 -0
- data/test/source/_posts/2010-01-09-time-override.textile +7 -0
- data/test/source/_posts/2010-01-09-timezone-override.textile +7 -0
- data/test/source/_posts/2010-01-16-override-data.textile +4 -0
- data/test/source/_posts/2011-04-12-md-extension.md +7 -0
- data/test/source/_posts/2011-04-12-text-extension.text +0 -0
- data/test/source/_posts/2013-01-02-post-excerpt.markdown +14 -0
- data/test/source/_posts/2013-01-12-nil-layout.textile +6 -0
- data/test/source/_posts/2013-01-12-no-layout.textile +5 -0
- data/test/source/_posts/2013-03-19-not-a-post.markdown/.gitkeep +0 -0
- data/test/source/_posts/2013-04-11-custom-excerpt.markdown +10 -0
- data/test/source/_posts/2013-05-10-number-category.textile +7 -0
- data/test/source/_posts/es/2008-11-21-nested.textile +8 -0
- data/test/source/about.html +6 -0
- data/test/source/category/_posts/2008-9-23-categories.textile +6 -0
- data/test/source/contacts.html +5 -0
- data/test/source/contacts/bar.html +5 -0
- data/test/source/contacts/index.html +5 -0
- data/test/source/css/screen.css +76 -0
- data/test/source/deal.with.dots.html +7 -0
- data/test/source/foo/_posts/bar/2008-12-12-topical-post.textile +8 -0
- data/test/source/index.html +22 -0
- data/test/source/sitemap.xml +32 -0
- data/test/source/symlink-test/symlinked-file +22 -0
- data/test/source/win/_posts/2009-05-24-yaml-linebreak.markdown +7 -0
- data/test/source/z_category/_posts/2008-9-23-categories.textile +6 -0
- data/test/suite.rb +11 -0
- data/test/test_command.rb +39 -0
- data/test/test_configuration.rb +137 -0
- data/test/test_convertible.rb +51 -0
- data/test/test_core_ext.rb +88 -0
- data/test/test_filters.rb +102 -0
- data/test/test_generated_site.rb +83 -0
- data/test/test_json_driver.rb +63 -0
- data/test/test_kramdown.rb +35 -0
- data/test/test_new_command.rb +104 -0
- data/test/test_page.rb +193 -0
- data/test/test_pager.rb +115 -0
- data/test/test_post.rb +573 -0
- data/test/test_rdiscount.rb +22 -0
- data/test/test_redcarpet.rb +61 -0
- data/test/test_redcloth.rb +86 -0
- data/test/test_site.rb +374 -0
- data/test/test_tags.rb +310 -0
- data/test/test_yaml_driver.rb +35 -0
- metadata +554 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'rr'
|
|
3
|
+
require 'test/unit'
|
|
4
|
+
|
|
5
|
+
World do
|
|
6
|
+
include Test::Unit::Assertions
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
TEST_DIR = File.join('/', 'tmp', 'monad')
|
|
10
|
+
JEKYLL_PATH = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'monad')
|
|
11
|
+
|
|
12
|
+
def run_monad(opts = {})
|
|
13
|
+
command = JEKYLL_PATH.clone
|
|
14
|
+
command << " build"
|
|
15
|
+
command << " --drafts" if opts[:drafts]
|
|
16
|
+
command << " >> /dev/null 2>&1" if opts[:debug].nil?
|
|
17
|
+
system command
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def has_time_component?(date_string)
|
|
21
|
+
date_string.split(" ").size > 1
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# work around "invalid option: --format" cucumber bug (see #296)
|
|
25
|
+
Test::Unit.run = true if RUBY_VERSION < '1.9'
|
data/lib/monad.rb
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
$:.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 'fileutils'
|
|
20
|
+
require 'time'
|
|
21
|
+
require 'safe_yaml'
|
|
22
|
+
require 'English'
|
|
23
|
+
|
|
24
|
+
# 3rd party
|
|
25
|
+
require 'liquid'
|
|
26
|
+
require 'maruku'
|
|
27
|
+
require 'colorator'
|
|
28
|
+
|
|
29
|
+
# internal requires
|
|
30
|
+
require 'monad/core_ext'
|
|
31
|
+
require 'monad/logger'
|
|
32
|
+
require 'monad/deprecator'
|
|
33
|
+
require 'monad/configuration'
|
|
34
|
+
require 'monad/site'
|
|
35
|
+
require 'monad/convertible'
|
|
36
|
+
require 'monad/layout'
|
|
37
|
+
require 'monad/page'
|
|
38
|
+
require 'monad/post'
|
|
39
|
+
require 'monad/draft'
|
|
40
|
+
require 'monad/filters'
|
|
41
|
+
require 'monad/static_file'
|
|
42
|
+
require 'monad/errors'
|
|
43
|
+
|
|
44
|
+
# extensions
|
|
45
|
+
require 'monad/plugin'
|
|
46
|
+
require 'monad/converter'
|
|
47
|
+
require 'monad/generator'
|
|
48
|
+
require 'monad/command'
|
|
49
|
+
|
|
50
|
+
require_all 'monad/commands'
|
|
51
|
+
require_all 'monad/converters'
|
|
52
|
+
require_all 'monad/converters/markdown'
|
|
53
|
+
require_all 'monad/generators'
|
|
54
|
+
require_all 'monad/tags'
|
|
55
|
+
require_all 'monad/drivers'
|
|
56
|
+
|
|
57
|
+
SafeYAML::OPTIONS[:suppress_warnings] = true
|
|
58
|
+
|
|
59
|
+
module Monad
|
|
60
|
+
VERSION = '0.0.1'
|
|
61
|
+
|
|
62
|
+
# Public: Generate a Monad configuration Hash by merging the default
|
|
63
|
+
# options with anything in _config.yml, and adding the given options on top.
|
|
64
|
+
#
|
|
65
|
+
# override - A Hash of config directives that override any options in both
|
|
66
|
+
# the defaults and the config file. See Monad::Configuration::DEFAULTS for a
|
|
67
|
+
# list of option names and their defaults.
|
|
68
|
+
#
|
|
69
|
+
# Returns the final configuration Hash.
|
|
70
|
+
def self.configuration(override)
|
|
71
|
+
config = Configuration[Configuration::DEFAULTS]
|
|
72
|
+
override = Configuration[override].stringify_keys
|
|
73
|
+
config = config.read_config_files(config.config_files(override))
|
|
74
|
+
|
|
75
|
+
# Merge DEFAULTS < _config.yml < override
|
|
76
|
+
config = config.deep_merge(override).stringify_keys
|
|
77
|
+
set_timezone(config['timezone']) if config['timezone']
|
|
78
|
+
|
|
79
|
+
config
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Static: Set the TZ environment variable to use the timezone specified
|
|
83
|
+
#
|
|
84
|
+
# timezone - the IANA Time Zone
|
|
85
|
+
#
|
|
86
|
+
# Returns nothing
|
|
87
|
+
def self.set_timezone(timezone)
|
|
88
|
+
ENV['TZ'] = timezone
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Monad
|
|
2
|
+
class Command
|
|
3
|
+
def self.globs(source, destination)
|
|
4
|
+
Dir.chdir(source) do
|
|
5
|
+
dirs = Dir['*'].select { |x| File.directory?(x) }
|
|
6
|
+
dirs -= [destination, File.expand_path(destination), File.basename(destination)]
|
|
7
|
+
dirs = dirs.map { |x| "#{x}/**/*" }
|
|
8
|
+
dirs += ['*']
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Static: Run Site#process and catch errors
|
|
13
|
+
#
|
|
14
|
+
# site - the Monad::Site object
|
|
15
|
+
#
|
|
16
|
+
# Returns nothing
|
|
17
|
+
def self.process_site(site)
|
|
18
|
+
site.process
|
|
19
|
+
rescue Monad::FatalException => e
|
|
20
|
+
puts
|
|
21
|
+
Monad::Logger.error "ERROR:", "YOUR SITE COULD NOT BE BUILT:"
|
|
22
|
+
Monad::Logger.error "", "------------------------------------"
|
|
23
|
+
Monad::Logger.error "", e.message
|
|
24
|
+
exit(1)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module Monad
|
|
2
|
+
module Commands
|
|
3
|
+
class Build < Command
|
|
4
|
+
def self.process(options)
|
|
5
|
+
site = Monad::Site.new(options)
|
|
6
|
+
|
|
7
|
+
self.build(site, options)
|
|
8
|
+
self.watch(site, options) if options['watch']
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Private: Build the site from source into destination.
|
|
12
|
+
#
|
|
13
|
+
# site - A Monad::Site instance
|
|
14
|
+
# options - A Hash of options passed to the command
|
|
15
|
+
#
|
|
16
|
+
# Returns nothing.
|
|
17
|
+
def self.build(site, options)
|
|
18
|
+
source = options['source']
|
|
19
|
+
destination = options['destination']
|
|
20
|
+
Monad::Logger.info "Source:", source
|
|
21
|
+
Monad::Logger.info "Destination:", destination
|
|
22
|
+
print Monad::Logger.formatted_topic "Generating..."
|
|
23
|
+
self.process_site(site)
|
|
24
|
+
puts "done."
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Private: Watch for file changes and rebuild the site.
|
|
28
|
+
#
|
|
29
|
+
# site - A Monad::Site instance
|
|
30
|
+
# options - A Hash of options passed to the command
|
|
31
|
+
#
|
|
32
|
+
# Returns nothing.
|
|
33
|
+
def self.watch(site, options)
|
|
34
|
+
require 'directory_watcher'
|
|
35
|
+
|
|
36
|
+
source = options['source']
|
|
37
|
+
destination = options['destination']
|
|
38
|
+
|
|
39
|
+
Monad::Logger.info "Auto-regeneration:", "enabled"
|
|
40
|
+
|
|
41
|
+
dw = DirectoryWatcher.new(source, :glob => self.globs(source, destination), :pre_load => true)
|
|
42
|
+
dw.interval = 1
|
|
43
|
+
|
|
44
|
+
dw.add_observer do |*args|
|
|
45
|
+
t = Time.now.strftime("%Y-%m-%d %H:%M:%S")
|
|
46
|
+
print Monad::Logger.formatted_topic("Regenerating:") + "#{args.size} files at #{t} "
|
|
47
|
+
self.process_site(site)
|
|
48
|
+
puts "...done."
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
dw.start
|
|
52
|
+
|
|
53
|
+
unless options['serving']
|
|
54
|
+
trap("INT") do
|
|
55
|
+
puts " Halting auto-regeneration."
|
|
56
|
+
exit 0
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
loop { sleep 1000 }
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Monad
|
|
2
|
+
module Commands
|
|
3
|
+
class Doctor < Command
|
|
4
|
+
class << self
|
|
5
|
+
def process(options)
|
|
6
|
+
site = Monad::Site.new(options)
|
|
7
|
+
site.read
|
|
8
|
+
|
|
9
|
+
unless deprecated_relative_permalinks(site)
|
|
10
|
+
Monad::Logger.info "Your test results", "are in. Everything looks fine."
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def deprecated_relative_permalinks(site)
|
|
15
|
+
contains_deprecated_pages = false
|
|
16
|
+
site.pages.each do |page|
|
|
17
|
+
if page.uses_relative_permalinks
|
|
18
|
+
Monad::Logger.warn "Deprecation:", "'#{page.path}' uses relative" +
|
|
19
|
+
" permalinks which will be deprecated in" +
|
|
20
|
+
" Monad v1.1 and beyond."
|
|
21
|
+
contains_deprecated_pages = true
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
contains_deprecated_pages
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'erb'
|
|
2
|
+
|
|
3
|
+
module Monad
|
|
4
|
+
module Commands
|
|
5
|
+
class New < Command
|
|
6
|
+
def self.process(args)
|
|
7
|
+
raise ArgumentError.new('You must specify a path.') if args.empty?
|
|
8
|
+
|
|
9
|
+
new_blog_path = File.expand_path(args.join(" "), Dir.pwd)
|
|
10
|
+
FileUtils.mkdir_p new_blog_path
|
|
11
|
+
unless Dir["#{new_blog_path}/**/*"].empty?
|
|
12
|
+
Monad::Logger.error "Conflict:", "#{new_blog_path} exists and is not empty."
|
|
13
|
+
exit(1)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
create_sample_files new_blog_path
|
|
17
|
+
|
|
18
|
+
File.open(File.expand_path(self.initialized_post_name, new_blog_path), "w") do |f|
|
|
19
|
+
f.write(self.scaffold_post_content(site_template))
|
|
20
|
+
end
|
|
21
|
+
puts "New monad site installed in #{new_blog_path}."
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.scaffold_post_content(template_site)
|
|
25
|
+
ERB.new(File.read(File.expand_path(scaffold_path, site_template))).result
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Internal: Gets the filename of the sample post to be created
|
|
29
|
+
#
|
|
30
|
+
# Returns the filename of the sample post, as a String
|
|
31
|
+
def self.initialized_post_name
|
|
32
|
+
"_posts/#{Time.now.strftime('%Y-%m-%d')}-welcome-to-monad.markdown"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
def self.create_sample_files(path)
|
|
37
|
+
FileUtils.cp_r site_template + '/.', path
|
|
38
|
+
FileUtils.rm File.expand_path(scaffold_path, path)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.site_template
|
|
42
|
+
File.expand_path("../../site_template", File.dirname(__FILE__))
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.scaffold_path
|
|
46
|
+
"_posts/0000-00-00-welcome-to-monad.markdown.erb"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module Monad
|
|
3
|
+
module Commands
|
|
4
|
+
class Serve < Command
|
|
5
|
+
def self.process(options)
|
|
6
|
+
require 'webrick'
|
|
7
|
+
include WEBrick
|
|
8
|
+
|
|
9
|
+
destination = options['destination']
|
|
10
|
+
|
|
11
|
+
FileUtils.mkdir_p(destination)
|
|
12
|
+
|
|
13
|
+
mime_types_file = File.expand_path('../mime.types', File.dirname(__FILE__))
|
|
14
|
+
mime_types = WEBrick::HTTPUtils::load_mime_types(mime_types_file)
|
|
15
|
+
|
|
16
|
+
# recreate NondisclosureName under utf-8 circumstance
|
|
17
|
+
fh_option = WEBrick::Config::FileHandler
|
|
18
|
+
fh_option[:NondisclosureName] = ['.ht*','~*']
|
|
19
|
+
|
|
20
|
+
s = HTTPServer.new(
|
|
21
|
+
:Port => options['port'],
|
|
22
|
+
:BindAddress => options['host'],
|
|
23
|
+
:MimeTypes => mime_types
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
s.mount(options['baseurl'], HTTPServlet::FileHandler, destination, fh_option)
|
|
27
|
+
t = Thread.new { s.start }
|
|
28
|
+
trap("INT") { s.shutdown }
|
|
29
|
+
t.join()
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module Monad
|
|
4
|
+
class Configuration < Hash
|
|
5
|
+
|
|
6
|
+
# Default options. Overridden by values in _config.yml.
|
|
7
|
+
# Strings rather than symbols are used for compatibility with YAML.
|
|
8
|
+
DEFAULTS = {
|
|
9
|
+
'source' => Dir.pwd,
|
|
10
|
+
'destination' => File.join(Dir.pwd, '_site'),
|
|
11
|
+
'plugins' => '_plugins',
|
|
12
|
+
'layouts' => '_layouts',
|
|
13
|
+
'keep_files' => ['.git','.svn'],
|
|
14
|
+
|
|
15
|
+
'timezone' => nil, # use the local timezone
|
|
16
|
+
|
|
17
|
+
'safe' => false,
|
|
18
|
+
'show_drafts' => nil,
|
|
19
|
+
'limit_posts' => 0,
|
|
20
|
+
'lsi' => false,
|
|
21
|
+
'future' => true, # remove and make true just default
|
|
22
|
+
'pygments' => true,
|
|
23
|
+
|
|
24
|
+
'relative_permalinks' => true, # backwards-compatibility with < 1.0
|
|
25
|
+
# will be set to false once 1.1 hits
|
|
26
|
+
|
|
27
|
+
'markdown' => 'maruku',
|
|
28
|
+
'permalink' => 'date',
|
|
29
|
+
'baseurl' => '/',
|
|
30
|
+
'include' => ['.htaccess'],
|
|
31
|
+
'exclude' => [],
|
|
32
|
+
'paginate_path' => 'page:num',
|
|
33
|
+
|
|
34
|
+
'markdown_ext' => 'markdown,mkd,mkdn,md',
|
|
35
|
+
'textile_ext' => 'textile',
|
|
36
|
+
|
|
37
|
+
'port' => '4000',
|
|
38
|
+
'host' => '0.0.0.0',
|
|
39
|
+
|
|
40
|
+
'excerpt_separator' => "\n\n",
|
|
41
|
+
|
|
42
|
+
'maruku' => {
|
|
43
|
+
'use_tex' => false,
|
|
44
|
+
'use_divs' => false,
|
|
45
|
+
'png_engine' => 'blahtex',
|
|
46
|
+
'png_dir' => 'images/latex',
|
|
47
|
+
'png_url' => '/images/latex'
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
'rdiscount' => {
|
|
51
|
+
'extensions' => []
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
'redcarpet' => {
|
|
55
|
+
'extensions' => []
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
'kramdown' => {
|
|
59
|
+
'auto_ids' => true,
|
|
60
|
+
'footnote_nr' => 1,
|
|
61
|
+
'entity_output' => 'as_char',
|
|
62
|
+
'toc_levels' => '1..6',
|
|
63
|
+
'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo',
|
|
64
|
+
'use_coderay' => false,
|
|
65
|
+
|
|
66
|
+
'coderay' => {
|
|
67
|
+
'coderay_wrap' => 'div',
|
|
68
|
+
'coderay_line_numbers' => 'inline',
|
|
69
|
+
'coderay_line_number_start' => 1,
|
|
70
|
+
'coderay_tab_width' => 4,
|
|
71
|
+
'coderay_bold_every' => 10,
|
|
72
|
+
'coderay_css' => 'style'
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
'redcloth' => {
|
|
77
|
+
'hard_breaks' => true
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# Public: Turn all keys into string
|
|
82
|
+
#
|
|
83
|
+
# Return a copy of the hash where all its keys are strings
|
|
84
|
+
def stringify_keys
|
|
85
|
+
reduce({}) { |hsh,(k,v)| hsh.merge(k.to_s => v) }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Public: Directory of the Monad source folder
|
|
89
|
+
#
|
|
90
|
+
# override - the command-line options hash
|
|
91
|
+
#
|
|
92
|
+
# Returns the path to the Monad source directory
|
|
93
|
+
def source(override)
|
|
94
|
+
override['source'] || self['source'] || DEFAULTS['source']
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Public: Generate list of configuration files from the override
|
|
98
|
+
#
|
|
99
|
+
# override - the command-line options hash
|
|
100
|
+
#
|
|
101
|
+
# Returns an Array of config files
|
|
102
|
+
def config_files(override)
|
|
103
|
+
# Get configuration from <source>/_config.yml or <source>/<config_file>
|
|
104
|
+
config_files = override.delete('config')
|
|
105
|
+
config_files = File.join(source(override), "_config.yml") if config_files.to_s.empty?
|
|
106
|
+
config_files = [config_files] unless config_files.is_a? Array
|
|
107
|
+
config_files
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Public: Read configuration and return merged Hash
|
|
111
|
+
#
|
|
112
|
+
# file - the path to the YAML file to be read in
|
|
113
|
+
#
|
|
114
|
+
# Returns this configuration, overridden by the values in the file
|
|
115
|
+
def read_config_file(file)
|
|
116
|
+
next_config = YAML.safe_load_file(file)
|
|
117
|
+
raise "Configuration file: (INVALID) #{file}".yellow if !next_config.is_a?(Hash)
|
|
118
|
+
Monad::Logger.info "Configuration file:", file
|
|
119
|
+
next_config
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Public: Read in a list of configuration files and merge with this hash
|
|
123
|
+
#
|
|
124
|
+
# files - the list of configuration file paths
|
|
125
|
+
#
|
|
126
|
+
# Returns the full configuration, with the defaults overridden by the values in the
|
|
127
|
+
# configuration files
|
|
128
|
+
def read_config_files(files)
|
|
129
|
+
configuration = clone
|
|
130
|
+
|
|
131
|
+
begin
|
|
132
|
+
files.each do |config_file|
|
|
133
|
+
new_config = read_config_file(config_file)
|
|
134
|
+
configuration = configuration.deep_merge(new_config)
|
|
135
|
+
end
|
|
136
|
+
rescue SystemCallError
|
|
137
|
+
# Errno:ENOENT = file not found
|
|
138
|
+
Monad::Logger.warn "Configuration file:", "none"
|
|
139
|
+
rescue => err
|
|
140
|
+
Monad::Logger.warn "WARNING:", "Error reading configuration. " +
|
|
141
|
+
"Using defaults (and options)."
|
|
142
|
+
$stderr.puts "#{err}"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
configuration.backwards_compatibilize
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Public: Ensure the proper options are set in the configuration to allow for
|
|
149
|
+
# backwards-compatibility with Monad pre-1.0
|
|
150
|
+
#
|
|
151
|
+
# Returns the backwards-compatible configuration
|
|
152
|
+
def backwards_compatibilize
|
|
153
|
+
config = clone
|
|
154
|
+
# Provide backwards-compatibility
|
|
155
|
+
if config.has_key?('auto') || config.has_key?('watch')
|
|
156
|
+
Monad::Logger.warn "Deprecation:", "Auto-regeneration can no longer" +
|
|
157
|
+
" be set from your configuration file(s). Use the"+
|
|
158
|
+
" --watch/-w command-line option instead."
|
|
159
|
+
config.delete('auto')
|
|
160
|
+
config.delete('watch')
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
if config.has_key? 'server'
|
|
164
|
+
Monad::Logger.warn "Deprecation:", "The 'server' configuration option" +
|
|
165
|
+
" is no longer accepted. Use the 'monad serve'" +
|
|
166
|
+
" subcommand to serve your site with WEBrick."
|
|
167
|
+
config.delete('server')
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
if config.has_key? 'server_port'
|
|
171
|
+
Monad::Logger.warn "Deprecation:", "The 'server_port' configuration option" +
|
|
172
|
+
" has been renamed to 'port'. Please update your config" +
|
|
173
|
+
" file accordingly."
|
|
174
|
+
# copy but don't overwrite:
|
|
175
|
+
config['port'] = config['server_port'] unless config.has_key?('port')
|
|
176
|
+
config.delete('server_port')
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
config
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
end
|
|
183
|
+
end
|