monad 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
Contribute
|
2
|
+
==========
|
3
|
+
|
4
|
+
So you've got an awesome idea to throw into Jekyll. Great! Please keep the
|
5
|
+
following in mind:
|
6
|
+
|
7
|
+
* **Contributions will not be accepted without tests.**
|
8
|
+
* If you're creating a small fix or patch to an existing feature, just a simple
|
9
|
+
test will do. Please stay in the confines of the current test suite and use
|
10
|
+
[Shoulda](http://github.com/thoughtbot/shoulda/tree/master) and
|
11
|
+
[RR](http://github.com/btakita/rr/tree/master).
|
12
|
+
* If it's a brand new feature, make sure to create a new
|
13
|
+
[Cucumber](https://github.com/cucumber/cucumber/) feature and reuse steps
|
14
|
+
where appropriate. Also, whipping up some documentation in your fork's wiki
|
15
|
+
would be appreciated, and once merged it will be transferred over to the main
|
16
|
+
wiki.
|
17
|
+
* If your contribution changes any Jekyll behavior, make sure to update the
|
18
|
+
documentation. It lives in `site/_posts`. If the docs are missing information,
|
19
|
+
please feel free to add it in. Great docs make a great project!
|
20
|
+
* Please follow the [GitHub Ruby Styleguide](https://github.com/styleguide/ruby)
|
21
|
+
when modifying Ruby code.
|
22
|
+
|
23
|
+
Test Dependencies
|
24
|
+
-----------------
|
25
|
+
|
26
|
+
To run the test suite and build the gem you'll need to install Jekyll's
|
27
|
+
dependencies. Jekyll uses Bundler, so a quick run of the bundle command and
|
28
|
+
you're all set!
|
29
|
+
|
30
|
+
$ bundle
|
31
|
+
|
32
|
+
Before you start, run the tests and make sure that they pass (to confirm your
|
33
|
+
environment is configured properly):
|
34
|
+
|
35
|
+
$ rake test
|
36
|
+
$ rake features
|
37
|
+
|
38
|
+
Workflow
|
39
|
+
--------
|
40
|
+
|
41
|
+
Here's the most direct way to get your work merged into the project:
|
42
|
+
|
43
|
+
* Fork the project.
|
44
|
+
* Clone down your fork ( `git clone git@github.com:<username>/jekyll.git` ).
|
45
|
+
* Create a topic branch to contain your change ( `git checkout -b my_awesome_feature` ).
|
46
|
+
* Hack away, add tests. Not necessarily in that order.
|
47
|
+
* Make sure everything still passes by running `rake`.
|
48
|
+
* If necessary, rebase your commits into logical chunks, without errors.
|
49
|
+
* Push the branch up ( `git push origin my_awesome_feature` ).
|
50
|
+
* Create a pull request against mojombo/jekyll and describe what your change
|
51
|
+
does and the why you think it should be merged.
|
52
|
+
|
53
|
+
Gotchas
|
54
|
+
-------
|
55
|
+
|
56
|
+
* If you want to bump the gem version, please put that in a separate commit.
|
57
|
+
This way, the maintainers can control when the gem gets released.
|
58
|
+
* Try to keep your patch(es) based from the latest commit on mojombo/jekyll.
|
59
|
+
The easier it is to apply your work, the less work the maintainers have to do,
|
60
|
+
which is always a good thing.
|
61
|
+
* Please don't tag your GitHub issue with [fix], [feature], etc. The maintainers
|
62
|
+
actively read the issues and will label it once they come across it.
|
63
|
+
|
64
|
+
Finally...
|
65
|
+
----------
|
66
|
+
|
67
|
+
Thanks! Hacking on Jekyll should be fun. If you find any of this hard to figure
|
68
|
+
out, let us know so we can improve our process or documentation!
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2008 Tom Preston-Werner
|
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.md
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
## Monad
|
2
|
+
|
3
|
+
Monad is a simple, blog aware, static site generator based on and 100% compatible with [Jekyll](https://github.com/mojombo/jekyll).
|
4
|
+
|
5
|
+
The main feature it adds is as follows:
|
6
|
+
|
7
|
+
- Support data sources
|
8
|
+
- Support virtual posts from external sources(TBD)
|
9
|
+
|
10
|
+
## Data Sources
|
11
|
+
|
12
|
+
Data Source enables you to load data from external sources, such as web, file system,
|
13
|
+
databases and then use them inside views.
|
14
|
+
|
15
|
+
Jekyll supports two built-in data sources:
|
16
|
+
|
17
|
+
- `YAML` from local file system
|
18
|
+
- `JSON` from web
|
19
|
+
|
20
|
+
And it's easy to roll your own data source driver.
|
21
|
+
|
22
|
+
### JSON
|
23
|
+
|
24
|
+
In ordre to use json from web in your site, set following in `_config.yml` file:
|
25
|
+
|
26
|
+
``` yaml
|
27
|
+
data_sources:
|
28
|
+
- name: albums # will be used as site.albums to access data, no spaces allowed
|
29
|
+
type: json
|
30
|
+
url: http://www.example.com/albums.json # must be http or https
|
31
|
+
```
|
32
|
+
|
33
|
+
Then, inside html you can access the data as following:
|
34
|
+
|
35
|
+
{% for album in site.albums %}
|
36
|
+
...
|
37
|
+
{% endfor %}
|
38
|
+
|
39
|
+
### YAML
|
40
|
+
|
41
|
+
To define a yaml data source, set following in `_config.yml` file:
|
42
|
+
|
43
|
+
``` yaml
|
44
|
+
data_sources:
|
45
|
+
- name: products # will be used as site.products to access data, no spaces allowed
|
46
|
+
type: yaml
|
47
|
+
path: _data/products.yml # must be on local file system
|
48
|
+
```
|
49
|
+
|
50
|
+
Then, inside html you can access the data as following:
|
51
|
+
|
52
|
+
{% for product in site.products %}
|
53
|
+
...
|
54
|
+
{% endfor %}
|
55
|
+
|
56
|
+
### Custom drivers
|
57
|
+
|
58
|
+
The skeleton of your driver should be as follows:
|
59
|
+
|
60
|
+
``` ruby
|
61
|
+
module Monad
|
62
|
+
module Drivers
|
63
|
+
class XxxDriver
|
64
|
+
# source options are passed in as an Hash
|
65
|
+
def initialize(options)
|
66
|
+
end
|
67
|
+
|
68
|
+
# return the loaded data as Array or Hash or a nested structure of Array and Hash
|
69
|
+
def load
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
After you've implemented the code, put the source file inside `_plugins` directory.
|
77
|
+
|
78
|
+
Then in `_config.yml`, you can use the driver as follows:
|
79
|
+
|
80
|
+
``` yaml
|
81
|
+
data_sources:
|
82
|
+
- name: students
|
83
|
+
type: xxx
|
84
|
+
```
|
85
|
+
|
86
|
+
If the type is `xxx`, Jekyll assumes the corresponding driver is `Monad::Drivers::XxxDriver`. If the type is `xxx_yyy`, the driver should be `Monad::Drivers::XxxYyyDriver`, and so on.
|
87
|
+
|
88
|
+
Beside the obligatory `name` and `type` options, you can define any more options to be used inside the driver.
|
data/Rakefile
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rdoc'
|
4
|
+
require 'date'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), *%w[lib]))
|
7
|
+
|
8
|
+
#############################################################################
|
9
|
+
#
|
10
|
+
# Helper functions
|
11
|
+
#
|
12
|
+
#############################################################################
|
13
|
+
|
14
|
+
def name
|
15
|
+
@name ||= Dir['*.gemspec'].first.split('.').first
|
16
|
+
end
|
17
|
+
|
18
|
+
def version
|
19
|
+
line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
|
20
|
+
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
|
21
|
+
end
|
22
|
+
|
23
|
+
def date
|
24
|
+
Date.today.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def rubyforge_project
|
28
|
+
name
|
29
|
+
end
|
30
|
+
|
31
|
+
def gemspec_file
|
32
|
+
"#{name}.gemspec"
|
33
|
+
end
|
34
|
+
|
35
|
+
def gem_file
|
36
|
+
"#{name}-#{version}.gem"
|
37
|
+
end
|
38
|
+
|
39
|
+
def replace_header(head, header_name)
|
40
|
+
head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
|
41
|
+
end
|
42
|
+
|
43
|
+
#############################################################################
|
44
|
+
#
|
45
|
+
# Standard tasks
|
46
|
+
#
|
47
|
+
#############################################################################
|
48
|
+
|
49
|
+
task :default => [:test, :features]
|
50
|
+
|
51
|
+
require 'rake/testtask'
|
52
|
+
Rake::TestTask.new(:test) do |test|
|
53
|
+
test.libs << 'lib' << 'test'
|
54
|
+
test.pattern = 'test/**/test_*.rb'
|
55
|
+
test.verbose = true
|
56
|
+
end
|
57
|
+
|
58
|
+
require 'rdoc/task'
|
59
|
+
Rake::RDocTask.new do |rdoc|
|
60
|
+
rdoc.rdoc_dir = 'rdoc'
|
61
|
+
rdoc.title = "#{name} #{version}"
|
62
|
+
rdoc.rdoc_files.include('README*')
|
63
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
64
|
+
end
|
65
|
+
|
66
|
+
begin
|
67
|
+
require 'cucumber/rake/task'
|
68
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
69
|
+
t.profile = "travis"
|
70
|
+
end
|
71
|
+
Cucumber::Rake::Task.new(:"features:html", "Run Cucumber features and produce HTML output") do |t|
|
72
|
+
t.profile = "html_report"
|
73
|
+
end
|
74
|
+
rescue LoadError
|
75
|
+
desc 'Cucumber rake task not available'
|
76
|
+
task :features do
|
77
|
+
abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
desc "Open an irb session preloaded with this library"
|
82
|
+
task :console do
|
83
|
+
sh "irb -rubygems -r ./lib/#{name}.rb"
|
84
|
+
end
|
85
|
+
|
86
|
+
#############################################################################
|
87
|
+
#
|
88
|
+
# Packaging tasks
|
89
|
+
#
|
90
|
+
#############################################################################
|
91
|
+
|
92
|
+
task :release => :build do
|
93
|
+
unless `git branch` =~ /^\* master$/
|
94
|
+
puts "You must be on the master branch to release!"
|
95
|
+
exit!
|
96
|
+
end
|
97
|
+
sh "git commit --allow-empty -m 'Release #{version}'"
|
98
|
+
sh "git tag v#{version}"
|
99
|
+
sh "git push origin master"
|
100
|
+
sh "git push origin v#{version}"
|
101
|
+
sh "gem push pkg/#{name}-#{version}.gem"
|
102
|
+
end
|
103
|
+
|
104
|
+
task :build => :gemspec do
|
105
|
+
sh "mkdir -p pkg"
|
106
|
+
sh "gem build #{gemspec_file}"
|
107
|
+
sh "mv #{gem_file} pkg"
|
108
|
+
end
|
109
|
+
|
110
|
+
task :gemspec do
|
111
|
+
# read spec file and split out manifest section
|
112
|
+
spec = File.read(gemspec_file)
|
113
|
+
head, manifest, tail = spec.split(" # = MANIFEST =\n")
|
114
|
+
|
115
|
+
# replace name version and date
|
116
|
+
replace_header(head, :name)
|
117
|
+
replace_header(head, :version)
|
118
|
+
replace_header(head, :date)
|
119
|
+
#comment this out if your rubyforge_project has a different name
|
120
|
+
replace_header(head, :rubyforge_project)
|
121
|
+
|
122
|
+
# determine file list from git ls-files
|
123
|
+
files = `git ls-files`.
|
124
|
+
split("\n").
|
125
|
+
sort.
|
126
|
+
reject { |file| file =~ /^\./ }.
|
127
|
+
reject { |file| file =~ /^(rdoc|pkg|coverage)/ }.
|
128
|
+
map { |file| " #{file}" }.
|
129
|
+
join("\n")
|
130
|
+
|
131
|
+
# piece file back together and write
|
132
|
+
manifest = " s.files = %w[\n#{files}\n ]\n"
|
133
|
+
spec = [head, manifest, tail].join(" # = MANIFEST =\n")
|
134
|
+
File.open(gemspec_file, 'w') { |io| io.write(spec) }
|
135
|
+
puts "Updated #{gemspec_file}"
|
136
|
+
end
|
data/bin/monad
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
STDOUT.sync = true
|
3
|
+
|
4
|
+
$:.unshift File.join(File.dirname(__FILE__), *%w{ .. lib })
|
5
|
+
|
6
|
+
require 'commander/import'
|
7
|
+
require 'monad'
|
8
|
+
|
9
|
+
Monad::Deprecator.process(ARGV)
|
10
|
+
|
11
|
+
program :name, 'monad'
|
12
|
+
program :version, Monad::VERSION
|
13
|
+
program :description, 'Monad is a blog-aware, static site generator in Ruby based on jekyll'
|
14
|
+
|
15
|
+
default_command :help
|
16
|
+
|
17
|
+
global_option '-s', '--source [DIR]', 'Source directory (defaults to ./)'
|
18
|
+
global_option '-d', '--destination [DIR]', 'Destination directory (defaults to ./_site)'
|
19
|
+
global_option '--safe', 'Safe mode (defaults to false)'
|
20
|
+
global_option '--plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]', Array, 'Plugins directory (defaults to ./_plugins)'
|
21
|
+
global_option '--layouts', 'Layouts directory (defaults to ./_layouts)'
|
22
|
+
|
23
|
+
# Option names don't always directly match the configuration value we'd like.
|
24
|
+
# This method will rename options to match what Monad configuration expects.
|
25
|
+
#
|
26
|
+
# options - The Hash of options from Commander.
|
27
|
+
#
|
28
|
+
# Returns the normalized Hash.
|
29
|
+
def normalize_options(options)
|
30
|
+
if drafts_state = options.delete(:drafts)
|
31
|
+
options[:show_drafts] = drafts_state
|
32
|
+
end
|
33
|
+
options
|
34
|
+
end
|
35
|
+
|
36
|
+
command :new do |c|
|
37
|
+
c.syntax = 'monad new PATH'
|
38
|
+
c.description = 'Creates a new Monad site scaffold in PATH'
|
39
|
+
|
40
|
+
c.action do |args, options|
|
41
|
+
Monad::Commands::New.process(args)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
command :build do |c|
|
46
|
+
c.syntax = 'monad build [options]'
|
47
|
+
c.description = 'Build your site'
|
48
|
+
|
49
|
+
c.option '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
|
50
|
+
c.option '--future', 'Publishes posts with a future date'
|
51
|
+
c.option '--limit_posts MAX_POSTS', Integer, 'Limits the number of posts to parse and publish'
|
52
|
+
c.option '-w', '--watch', 'Watch for changes and rebuild'
|
53
|
+
c.option '--lsi', 'Use LSI for improved related posts'
|
54
|
+
c.option '--drafts', 'Render posts in the _drafts folder'
|
55
|
+
|
56
|
+
c.action do |args, options|
|
57
|
+
options = normalize_options(options.__hash__)
|
58
|
+
options = Monad.configuration(options)
|
59
|
+
Monad::Commands::Build.process(options)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
command :serve do |c|
|
64
|
+
c.syntax = 'monad serve [options]'
|
65
|
+
c.description = 'Serve your site locally'
|
66
|
+
|
67
|
+
c.option '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
|
68
|
+
c.option '--future', 'Publishes posts with a future date'
|
69
|
+
c.option '--limit_posts MAX_POSTS', Integer, 'Limits the number of posts to parse and publish'
|
70
|
+
c.option '-w', '--watch', 'Watch for changes and rebuild'
|
71
|
+
c.option '--lsi', 'Use LSI for improved related posts'
|
72
|
+
c.option '--drafts', 'Render posts in the _drafts folder'
|
73
|
+
|
74
|
+
c.option '-p', '--port [PORT]', 'Port to listen on'
|
75
|
+
c.option '-h', '--host [HOST]', 'Host to bind to'
|
76
|
+
c.option '-b', '--baseurl [URL]', 'Base URL'
|
77
|
+
|
78
|
+
c.action do |args, options|
|
79
|
+
options.default :serving => true
|
80
|
+
|
81
|
+
options = normalize_options(options.__hash__)
|
82
|
+
options = Monad.configuration(options)
|
83
|
+
Monad::Commands::Build.process(options)
|
84
|
+
Monad::Commands::Serve.process(options)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
alias_command :server, :serve
|
88
|
+
|
89
|
+
command :doctor do |c|
|
90
|
+
c.syntax = 'monad doctor'
|
91
|
+
c.description = 'Search site and print specific deprecation warnings'
|
92
|
+
|
93
|
+
c.option '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
|
94
|
+
|
95
|
+
c.action do |args, options|
|
96
|
+
options = normalize_options(options.__hash__)
|
97
|
+
options = Monad.configuration(options)
|
98
|
+
Monad::Commands::Doctor.process(options)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
alias_command :hyde, :doctor
|
102
|
+
|
data/cucumber.yml
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
Feature: Create sites
|
2
|
+
As a hacker who likes to blog
|
3
|
+
I want to be able to make a static site
|
4
|
+
In order to share my awesome ideas with the interwebs
|
5
|
+
|
6
|
+
Scenario: Basic site
|
7
|
+
Given I have an "index.html" file that contains "Basic Site"
|
8
|
+
When I run monad
|
9
|
+
Then the _site directory should exist
|
10
|
+
And I should see "Basic Site" in "_site/index.html"
|
11
|
+
|
12
|
+
Scenario: Basic site with a post
|
13
|
+
Given I have a _posts directory
|
14
|
+
And I have the following post:
|
15
|
+
| title | date | content |
|
16
|
+
| Hackers | 3/27/2009 | My First Exploit |
|
17
|
+
When I run monad
|
18
|
+
Then the _site directory should exist
|
19
|
+
And I should see "My First Exploit" in "_site/2009/03/27/hackers.html"
|
20
|
+
|
21
|
+
Scenario: Basic site with layout and a page
|
22
|
+
Given I have a _layouts directory
|
23
|
+
And I have an "index.html" page with layout "default" that contains "Basic Site with Layout"
|
24
|
+
And I have a default layout that contains "Page Layout: {{ content }}"
|
25
|
+
When I run monad
|
26
|
+
Then the _site directory should exist
|
27
|
+
And I should see "Page Layout: Basic Site with Layout" in "_site/index.html"
|
28
|
+
|
29
|
+
Scenario: Basic site with layout and a post
|
30
|
+
Given I have a _layouts directory
|
31
|
+
And I have a _posts directory
|
32
|
+
And I have the following posts:
|
33
|
+
| title | date | layout | content |
|
34
|
+
| Wargames | 3/27/2009 | default | The only winning move is not to play. |
|
35
|
+
And I have a default layout that contains "Post Layout: {{ content }}"
|
36
|
+
When I run monad
|
37
|
+
Then the _site directory should exist
|
38
|
+
And I should see "Post Layout: <p>The only winning move is not to play.</p>" in "_site/2009/03/27/wargames.html"
|
39
|
+
|
40
|
+
Scenario: Basic site with layouts, pages, posts and files
|
41
|
+
Given I have a _layouts directory
|
42
|
+
And I have a page layout that contains "Page {{ page.title }}: {{ content }}"
|
43
|
+
And I have a post layout that contains "Post {{ page.title }}: {{ content }}"
|
44
|
+
And I have an "index.html" page with layout "page" that contains "Site contains {{ site.pages.size }} pages and {{ site.posts.size }} posts"
|
45
|
+
And I have a blog directory
|
46
|
+
And I have a "blog/index.html" page with layout "page" that contains "blog category index page"
|
47
|
+
And I have an "about.html" file that contains "No replacement {{ site.posts.size }}"
|
48
|
+
And I have an "another_file" file that contains ""
|
49
|
+
And I have a _posts directory
|
50
|
+
And I have the following posts:
|
51
|
+
| title | date | layout | content |
|
52
|
+
| entry1 | 3/27/2009 | post | content for entry1. |
|
53
|
+
| entry2 | 4/27/2009 | post | content for entry2. |
|
54
|
+
And I have a category/_posts directory
|
55
|
+
And I have the following posts in "category":
|
56
|
+
| title | date | layout | content |
|
57
|
+
| entry3 | 5/27/2009 | post | content for entry3. |
|
58
|
+
| entry4 | 6/27/2009 | post | content for entry4. |
|
59
|
+
When I run monad
|
60
|
+
Then the _site directory should exist
|
61
|
+
And I should see "Page : Site contains 2 pages and 4 posts" in "_site/index.html"
|
62
|
+
And I should see "No replacement \{\{ site.posts.size \}\}" in "_site/about.html"
|
63
|
+
And I should see "" in "_site/another_file"
|
64
|
+
And I should see "Page : blog category index page" in "_site/blog/index.html"
|
65
|
+
And I should see "Post entry1: <p>content for entry1.</p>" in "_site/2009/03/27/entry1.html"
|
66
|
+
And I should see "Post entry2: <p>content for entry2.</p>" in "_site/2009/04/27/entry2.html"
|
67
|
+
And I should see "Post entry3: <p>content for entry3.</p>" in "_site/category/2009/05/27/entry3.html"
|
68
|
+
And I should see "Post entry4: <p>content for entry4.</p>" in "_site/category/2009/06/27/entry4.html"
|
69
|
+
|
70
|
+
Scenario: Basic site with include tag
|
71
|
+
Given I have a _includes directory
|
72
|
+
And I have an "index.html" page that contains "Basic Site with include tag: {% include about.textile %}"
|
73
|
+
And I have an "_includes/about.textile" file that contains "Generated by Monad"
|
74
|
+
When I run monad
|
75
|
+
Then the _site directory should exist
|
76
|
+
And I should see "Basic Site with include tag: Generated by Monad" in "_site/index.html"
|
77
|
+
|
78
|
+
Scenario: Basic site with subdir include tag
|
79
|
+
Given I have a _includes directory
|
80
|
+
And I have an "_includes/about.textile" file that contains "Generated by Monad"
|
81
|
+
And I have an info directory
|
82
|
+
And I have an "info/index.html" page that contains "Basic Site with subdir include tag: {% include about.textile %}"
|
83
|
+
When I run monad
|
84
|
+
Then the _site directory should exist
|
85
|
+
And I should see "Basic Site with subdir include tag: Generated by Monad" in "_site/info/index.html"
|
86
|
+
|
87
|
+
Scenario: Basic site with nested include tag
|
88
|
+
Given I have a _includes directory
|
89
|
+
And I have an "_includes/about.textile" file that contains "Generated by {% include monad.textile %}"
|
90
|
+
And I have an "_includes/monad.textile" file that contains "Monad"
|
91
|
+
And I have an "index.html" page that contains "Basic Site with include tag: {% include about.textile %}"
|
92
|
+
When I run monad
|
93
|
+
Then the _site directory should exist
|
94
|
+
And I should see "Basic Site with include tag: Generated by Monad" in "_site/index.html"
|
95
|
+
|
96
|
+
Scenario: Basic site with internal post linking
|
97
|
+
Given I have an "index.html" page that contains "URL: {% post_url 2020-01-31-entry2 %}"
|
98
|
+
And I have a configuration file with "permalink" set to "pretty"
|
99
|
+
And I have a _posts directory
|
100
|
+
And I have the following posts:
|
101
|
+
| title | date | layout | content |
|
102
|
+
| entry1 | 12/31/2007 | post | content for entry1. |
|
103
|
+
| entry2 | 01/31/2020 | post | content for entry2. |
|
104
|
+
When I run monad
|
105
|
+
Then the _site directory should exist
|
106
|
+
And I should see "URL: /2020/01/31/entry2/" in "_site/index.html"
|
107
|
+
|
108
|
+
Scenario: Basic site with whitelisted dotfile
|
109
|
+
Given I have an ".htaccess" file that contains "SomeDirective"
|
110
|
+
When I run monad
|
111
|
+
Then the _site directory should exist
|
112
|
+
And I should see "SomeDirective" in "_site/.htaccess"
|