magneto 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +19 -0
- data/README.md +44 -0
- data/bin/magneto +7 -0
- data/lib/magneto.rb +30 -0
- data/lib/magneto/application.rb +153 -0
- data/lib/magneto/context.rb +21 -0
- data/lib/magneto/core_ext.rb +58 -0
- data/lib/magneto/filter.rb +21 -0
- data/lib/magneto/filters.rb +13 -0
- data/lib/magneto/filters/bluecloth.rb +22 -0
- data/lib/magneto/filters/coffeescript.rb +22 -0
- data/lib/magneto/filters/erb.rb +22 -0
- data/lib/magneto/filters/erubis.rb +28 -0
- data/lib/magneto/filters/haml.rb +26 -0
- data/lib/magneto/filters/kramdown.rb +22 -0
- data/lib/magneto/filters/less.rb +23 -0
- data/lib/magneto/filters/maruku.rb +22 -0
- data/lib/magneto/filters/rdiscount.rb +22 -0
- data/lib/magneto/filters/redcarpet.rb +29 -0
- data/lib/magneto/filters/redcloth.rb +24 -0
- data/lib/magneto/filters/rubypants.rb +22 -0
- data/lib/magneto/filters/sass.rb +22 -0
- data/lib/magneto/item.rb +118 -0
- data/lib/magneto/readable.rb +55 -0
- data/lib/magneto/render_context.rb +51 -0
- data/lib/magneto/script_context.rb +18 -0
- data/lib/magneto/site.rb +116 -0
- data/lib/magneto/template.rb +31 -0
- data/magneto.gemspec +17 -0
- metadata +75 -0
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2012 Don Melton
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# Magneto
|
2
|
+
|
3
|
+
Magneto is a static site generator.
|
4
|
+
|
5
|
+
## About
|
6
|
+
|
7
|
+
Hi, I'm Don Melton. I wrote Magneto to generate [my own website](http://donmelton.com/). Magneto was inspired by [nanoc](http://nanoc.stoneship.org/) and [Jekyll](http://jekyllrb.com/), but it's a much simpler tool with fewer features and less policy.
|
8
|
+
|
9
|
+
For example, Magneto is not "blog aware" like some other systems, but it allows you to write a site controller script and plugins which can easily generate blog posts, an index page and a RSS feed. This is how I use it. There may be more work up front compared to other tools, but Magneto gives you very precise control over its behavior and output.
|
10
|
+
|
11
|
+
Before using Magneto, realize that it does have limitations due to its simplicity and that its programming interface may change because it's still under development.
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
magneto [OPTION]...
|
16
|
+
|
17
|
+
Source file items, their templates and the site controller script are loaded from the `items` and `templates` directories and from the `script.rb` file, all within the current directory. These are watched for changes and reloaded when automatic regeneration is enabled.
|
18
|
+
|
19
|
+
Ruby library files are loaded from the `plugins` directory only once.
|
20
|
+
|
21
|
+
The generated site is written to the `output` directory.
|
22
|
+
|
23
|
+
Configuration is loaded from `config.yaml` but can be overriden using the following options:
|
24
|
+
|
25
|
+
-c, --config PATH use specific YAML configuration file
|
26
|
+
-s, --source PATH use specific source directory
|
27
|
+
-o, --output PATH use specific output directory
|
28
|
+
|
29
|
+
--[no-]hidden include [exclude] hidden source files
|
30
|
+
--[no-]remove remove [keep] obsolete output
|
31
|
+
--[no-]auto enable [disable] automatic regeneration
|
32
|
+
|
33
|
+
-h, --help display this help and exit
|
34
|
+
--version output version information and exit
|
35
|
+
|
36
|
+
## Dependencies
|
37
|
+
|
38
|
+
Magneto doesn't have any dependencies for basic operation.
|
39
|
+
|
40
|
+
Enabling automatic regeneration requires installation of the Directory Watcher gem:
|
41
|
+
|
42
|
+
sudo gem install directory_watcher
|
43
|
+
|
44
|
+
Using any of the built-in filters could require additional gem installations.
|
data/bin/magneto
ADDED
data/lib/magneto.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'optparse'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'set'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
require 'magneto/application'
|
9
|
+
require 'magneto/context'
|
10
|
+
require 'magneto/core_ext'
|
11
|
+
require 'magneto/filter'
|
12
|
+
require 'magneto/filters'
|
13
|
+
require 'magneto/item'
|
14
|
+
require 'magneto/readable'
|
15
|
+
require 'magneto/render_context'
|
16
|
+
require 'magneto/script_context'
|
17
|
+
require 'magneto/site'
|
18
|
+
require 'magneto/template'
|
19
|
+
|
20
|
+
module Magneto
|
21
|
+
|
22
|
+
VERSION = '0.1.0'
|
23
|
+
|
24
|
+
class << self
|
25
|
+
|
26
|
+
def application
|
27
|
+
@application ||= Application.new
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class Application
|
4
|
+
|
5
|
+
attr_reader :config, :filters, :site
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
super
|
9
|
+
@options = {}
|
10
|
+
@config_path = 'config.yaml'
|
11
|
+
@config = {
|
12
|
+
:source_path => '.',
|
13
|
+
:output_path => 'output',
|
14
|
+
:hidden_files => false,
|
15
|
+
:remove_obsolete => false,
|
16
|
+
:auto_regeneration => false
|
17
|
+
}
|
18
|
+
@filters = {}
|
19
|
+
@site = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def run
|
23
|
+
parse_options
|
24
|
+
load_configuration
|
25
|
+
|
26
|
+
@config.deep_merge! @options
|
27
|
+
|
28
|
+
[:source_path, :output_path].each do |path|
|
29
|
+
@config[path] = File.expand_path(@config[path])
|
30
|
+
@config[path].freeze
|
31
|
+
end
|
32
|
+
|
33
|
+
load_plugins
|
34
|
+
find_filters
|
35
|
+
|
36
|
+
@site = Site.new(@config, @filters)
|
37
|
+
|
38
|
+
if @config[:auto_regeneration]
|
39
|
+
puts 'Automatic regeneration enabled.'
|
40
|
+
|
41
|
+
require 'directory_watcher'
|
42
|
+
|
43
|
+
dw = DirectoryWatcher.new(@config[:source_path])
|
44
|
+
dw.glob = [@config[:hidden_files] ? 'items/**/{.[^.],}*' : 'items/**/*', 'templates/*.*', 'script.rb']
|
45
|
+
dw.interval = 1
|
46
|
+
dw.add_observer { |*args| @site.generate }
|
47
|
+
dw.start
|
48
|
+
gets
|
49
|
+
dw.stop
|
50
|
+
else
|
51
|
+
@site.generate
|
52
|
+
end
|
53
|
+
|
54
|
+
exit
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def parse_options
|
60
|
+
begin
|
61
|
+
OptionParser.new do |opts|
|
62
|
+
opts.banner = "Magneto is a static site generator."
|
63
|
+
opts.separator ""
|
64
|
+
opts.separator " Usage: #{File.basename($PROGRAM_NAME)} [OPTION]..."
|
65
|
+
opts.separator ""
|
66
|
+
opts.separator " Source file items, their templates and the site controller script"
|
67
|
+
opts.separator " are loaded from the 'items' and 'templates' directories and from the"
|
68
|
+
opts.separator " 'script.rb' file, all within the current directory. These are watched"
|
69
|
+
opts.separator " for changes and reloaded when automatic regeneration is enabled."
|
70
|
+
opts.separator ""
|
71
|
+
opts.separator " Ruby library files are loaded from the 'plugins' directory only once."
|
72
|
+
opts.separator ""
|
73
|
+
opts.separator " The generated site is written to the 'output' directory."
|
74
|
+
opts.separator ""
|
75
|
+
opts.separator " Configuration is loaded from 'config.yaml' but can be overriden"
|
76
|
+
opts.separator " using the following options:"
|
77
|
+
opts.separator ""
|
78
|
+
|
79
|
+
opts.on('-c', '--config PATH', 'use specific YAML configuration file') { |cp| @config_path = cp }
|
80
|
+
opts.on('-s', '--source PATH', 'use specific source directory') { |sp| @options[:source_path] = sp }
|
81
|
+
opts.on('-o', '--output PATH', 'use specific output directory') { |op| @options[:output_path] = op }
|
82
|
+
|
83
|
+
opts.separator ""
|
84
|
+
|
85
|
+
opts.on('--[no-]hidden', 'include [exclude] hidden source files') { |hf| @options[:hidden_files] = hf }
|
86
|
+
opts.on('--[no-]remove', 'remove [keep] obsolete output') { |ro| @options[:remove_obsolete] = ro }
|
87
|
+
opts.on('--[no-]auto', 'enable [disable] automatic regeneration') { |ar| @options[:auto_regeneration] = ar }
|
88
|
+
|
89
|
+
opts.separator ""
|
90
|
+
|
91
|
+
opts.on_tail('-h', '--help', 'display this help and exit') do
|
92
|
+
puts opts
|
93
|
+
exit
|
94
|
+
end
|
95
|
+
|
96
|
+
opts.on_tail '--version', 'output version information and exit' do
|
97
|
+
puts <<VERSION_HERE
|
98
|
+
#{File.basename($PROGRAM_NAME)} #{VERSION}
|
99
|
+
Copyright (c) 2012 Don Melton
|
100
|
+
This is free software; see the source for copying conditions. There is NO
|
101
|
+
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
102
|
+
VERSION_HERE
|
103
|
+
exit
|
104
|
+
end
|
105
|
+
end.parse!
|
106
|
+
rescue => ex
|
107
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
108
|
+
usage
|
109
|
+
end
|
110
|
+
|
111
|
+
if ARGV.size > 0
|
112
|
+
$stderr.print "#{File.basename($PROGRAM_NAME)}: unknown argument(s):"
|
113
|
+
ARGV.each { |a| $stderr.print " #{a}" }
|
114
|
+
$stderr.puts
|
115
|
+
usage
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def usage
|
120
|
+
$stderr.puts "Try '#{File.basename($PROGRAM_NAME)} --help' for more information."
|
121
|
+
exit false
|
122
|
+
end
|
123
|
+
|
124
|
+
def load_configuration
|
125
|
+
puts 'Loading configuration...'
|
126
|
+
|
127
|
+
begin
|
128
|
+
configuration = YAML.load_file(@config_path)
|
129
|
+
raise unless configuration.is_a? Hash
|
130
|
+
rescue => ex
|
131
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
132
|
+
$stderr.puts "WARNING: Couldn't load configuration. Using defaults (and options)."
|
133
|
+
configuration = {}
|
134
|
+
end
|
135
|
+
|
136
|
+
@config.deep_merge! configuration.symbolize_keys
|
137
|
+
end
|
138
|
+
|
139
|
+
def load_plugins
|
140
|
+
puts 'Loading plugins...'
|
141
|
+
Dir[@config[:source_path] + '/plugins/**/*.rb'].each { |plugin| require plugin unless File.directory? plugin }
|
142
|
+
end
|
143
|
+
|
144
|
+
def find_filters
|
145
|
+
puts 'Finding filters...'
|
146
|
+
|
147
|
+
Magneto::Filter.subclasses.each do |subclass|
|
148
|
+
filter = subclass.new(@config)
|
149
|
+
@filters[filter.name.to_sym] = filter
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
# Adapted from `nanoc/base/context.rb` with thanks to Denis Defreyne and
|
4
|
+
# contributors.
|
5
|
+
class Context
|
6
|
+
|
7
|
+
def initialize(ivars)
|
8
|
+
super()
|
9
|
+
eigenclass = class << self ; self ; end
|
10
|
+
|
11
|
+
ivars.each do |symbol, value|
|
12
|
+
instance_variable_set('@' + symbol.to_s, value)
|
13
|
+
eigenclass.send(:define_method, symbol) { value } unless eigenclass.send(:respond_to?, symbol)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_binding
|
18
|
+
binding
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class Hash
|
2
|
+
|
3
|
+
# Copied from `active_support/core_ext/hash/keys.rb` with thanks to David
|
4
|
+
# Heinemeier Hansson and contributors.
|
5
|
+
|
6
|
+
# Return a new hash with all keys converted to strings.
|
7
|
+
def stringify_keys
|
8
|
+
dup.stringify_keys!
|
9
|
+
end
|
10
|
+
|
11
|
+
# Destructively convert all keys to strings.
|
12
|
+
def stringify_keys!
|
13
|
+
keys.each do |key|
|
14
|
+
self[key.to_s] = delete(key)
|
15
|
+
end
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
# Return a new hash with all keys converted to symbols, as long as
|
20
|
+
# they respond to +to_sym+.
|
21
|
+
def symbolize_keys
|
22
|
+
dup.symbolize_keys!
|
23
|
+
end
|
24
|
+
|
25
|
+
# Destructively convert all keys to symbols, as long as they respond
|
26
|
+
# to +to_sym+.
|
27
|
+
def symbolize_keys!
|
28
|
+
keys.each do |key|
|
29
|
+
self[(key.to_sym rescue key) || key] = delete(key)
|
30
|
+
end
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
# Adapted from `jekyll/core_ext.rb` with thanks to Tom Preston-Werner.
|
35
|
+
|
36
|
+
# Merges self with another hash, recursively.
|
37
|
+
#
|
38
|
+
# This code was lovingly stolen (now adapted) from some random gem:
|
39
|
+
# http://gemjack.com/gems/tartan-0.1.1/classes/Hash.html
|
40
|
+
#
|
41
|
+
# Thanks to whoever made it.
|
42
|
+
def deep_merge(hash)
|
43
|
+
dup.deep_merge! hash
|
44
|
+
end
|
45
|
+
|
46
|
+
def deep_merge!(hash)
|
47
|
+
hash.keys.each do |key|
|
48
|
+
if hash[key].is_a? Hash and self[key].is_a? Hash
|
49
|
+
self[key] = self[key].deep_merge(hash[key])
|
50
|
+
next
|
51
|
+
end
|
52
|
+
|
53
|
+
self[key] = hash[key]
|
54
|
+
end
|
55
|
+
|
56
|
+
self
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
# Adapted from `jekyll/plugin.rb` with thanks to Tom Preston-Werner.
|
4
|
+
class Filter
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def inherited(subclass)
|
9
|
+
subclasses << subclass
|
10
|
+
end
|
11
|
+
|
12
|
+
def subclasses
|
13
|
+
@subclasses ||= []
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(config)
|
18
|
+
@config = config
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'magneto/filters/bluecloth'
|
2
|
+
require 'magneto/filters/coffeescript'
|
3
|
+
require 'magneto/filters/erb'
|
4
|
+
require 'magneto/filters/erubis'
|
5
|
+
require 'magneto/filters/haml'
|
6
|
+
require 'magneto/filters/kramdown'
|
7
|
+
require 'magneto/filters/less'
|
8
|
+
require 'magneto/filters/maruku'
|
9
|
+
require 'magneto/filters/rdiscount'
|
10
|
+
require 'magneto/filters/redcarpet'
|
11
|
+
require 'magneto/filters/redcloth'
|
12
|
+
require 'magneto/filters/rubypants'
|
13
|
+
require 'magneto/filters/sass'
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class BlueClothFilter < Filter
|
4
|
+
|
5
|
+
def name
|
6
|
+
'bluecloth'
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply(content, ivars)
|
10
|
+
begin
|
11
|
+
require 'bluecloth'
|
12
|
+
rescue LoadError => ex
|
13
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
14
|
+
$stderr.puts "You're missing a library required to use BlueCloth. Try running:"
|
15
|
+
$stderr.puts ' $ [sudo] gem install bluecloth'
|
16
|
+
raise 'Missing dependency: bluecloth'
|
17
|
+
end
|
18
|
+
|
19
|
+
BlueCloth.new(content, (ivars[:bluecloth].symbolize_keys rescue {})).to_html
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class CoffeeScriptFilter < Filter
|
4
|
+
|
5
|
+
def name
|
6
|
+
'coffeescript'
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply(content, ivars)
|
10
|
+
begin
|
11
|
+
require 'coffee-script'
|
12
|
+
rescue LoadError => ex
|
13
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
14
|
+
$stderr.puts "You're missing a library required to use CoffeeScript. Try running:"
|
15
|
+
$stderr.puts ' $ [sudo] gem install coffee-script'
|
16
|
+
raise 'Missing dependency: coffee-script'
|
17
|
+
end
|
18
|
+
|
19
|
+
CoffeeScript.compile(content, (ivars[:coffeescript].symbolize_keys rescue {}))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class ERBFilter < Filter
|
4
|
+
|
5
|
+
def name
|
6
|
+
'erb'
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply(content, ivars)
|
10
|
+
require 'erb'
|
11
|
+
|
12
|
+
# Adapted from `nanoc/filters/erb.rb` with thanks to Denis Defreyne and
|
13
|
+
# contributors.
|
14
|
+
context = RenderContext.new(ivars)
|
15
|
+
proc = ivars[:content] ? lambda { ivars[:content] } : lambda {}
|
16
|
+
b = context.get_binding(&proc)
|
17
|
+
|
18
|
+
args = ivars[:erb].symbolize_keys rescue {}
|
19
|
+
ERB.new(content, args[:safe_level], args[:trim_mode]).result b
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class ErubisFilter < Filter
|
4
|
+
|
5
|
+
def name
|
6
|
+
'erubis'
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply(content, ivars)
|
10
|
+
begin
|
11
|
+
require 'erubis'
|
12
|
+
require 'erubis/engine/enhanced'
|
13
|
+
rescue LoadError => ex
|
14
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
15
|
+
$stderr.puts "You're missing a library required to use Erubis. Try running:"
|
16
|
+
$stderr.puts ' $ [sudo] gem install erubis'
|
17
|
+
raise 'Missing dependency: erubis'
|
18
|
+
end
|
19
|
+
|
20
|
+
# Adapted from "nanoc/filters/erubis.rb" with thanks to Denis Defreyne and contributors.
|
21
|
+
context = RenderContext.new(ivars)
|
22
|
+
proc = ivars[:content] ? lambda { ivars[:content] } : lambda {}
|
23
|
+
b = context.get_binding(&proc)
|
24
|
+
|
25
|
+
Erubis::ErboutEruby.new(content, (ivars[:erubis].symbolize_keys rescue {})).result b
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class HamlFilter < Filter
|
4
|
+
|
5
|
+
def name
|
6
|
+
'haml'
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply(content, ivars)
|
10
|
+
begin
|
11
|
+
require 'haml'
|
12
|
+
rescue LoadError => ex
|
13
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
14
|
+
$stderr.puts "You're missing a library required to use Haml. Try running:"
|
15
|
+
$stderr.puts ' $ [sudo] gem install haml'
|
16
|
+
raise 'Missing dependency: haml'
|
17
|
+
end
|
18
|
+
|
19
|
+
# Adapted from "nanoc/filters/haml.rb" with thanks to Denis Defreyne and contributors.
|
20
|
+
context = RenderContext.new(ivars)
|
21
|
+
proc = ivars[:content] ? lambda { ivars[:content] } : lambda {}
|
22
|
+
|
23
|
+
Haml::Engine.new(content, (ivars[:haml].symbolize_keys rescue {})).render(context, ivars, &proc)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class KramdownFilter < Filter
|
4
|
+
|
5
|
+
def name
|
6
|
+
'kramdown'
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply(content, ivars)
|
10
|
+
begin
|
11
|
+
require 'kramdown'
|
12
|
+
rescue LoadError => ex
|
13
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
14
|
+
$stderr.puts "You're missing a library required to use kramdown. Try running:"
|
15
|
+
$stderr.puts ' $ [sudo] gem install kramdown'
|
16
|
+
raise 'Missing dependency: kramdown'
|
17
|
+
end
|
18
|
+
|
19
|
+
Kramdown::Document.new(content, (ivars[:kramdown].symbolize_keys rescue {})).to_html
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class LessFilter < Filter
|
4
|
+
|
5
|
+
def name
|
6
|
+
'less'
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply(content, ivars)
|
10
|
+
begin
|
11
|
+
require 'less'
|
12
|
+
rescue LoadError => ex
|
13
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
14
|
+
$stderr.puts "You're missing a library required to use Less. Try running:"
|
15
|
+
$stderr.puts ' $ [sudo] gem install less'
|
16
|
+
raise 'Missing dependency: less'
|
17
|
+
end
|
18
|
+
|
19
|
+
args = ivars[:less].symbolize_keys rescue {}
|
20
|
+
Less::Parser.new(args).parse(content).to_css(args)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class MarukuFilter < Filter
|
4
|
+
|
5
|
+
def name
|
6
|
+
'maruku'
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply(content, ivars)
|
10
|
+
begin
|
11
|
+
require 'maruku'
|
12
|
+
rescue LoadError => ex
|
13
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
14
|
+
$stderr.puts "You're missing a library required to use Maruku. Try running:"
|
15
|
+
$stderr.puts ' $ [sudo] gem install maruku'
|
16
|
+
raise 'Missing dependency: maruku'
|
17
|
+
end
|
18
|
+
|
19
|
+
Maruku.new(content, (ivars[:maruku].symbolize_keys rescue {})).to_html
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class RDiscountFilter < Filter
|
4
|
+
|
5
|
+
def name
|
6
|
+
'rdiscount'
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply(content, ivars)
|
10
|
+
begin
|
11
|
+
require 'rdiscount'
|
12
|
+
rescue LoadError => ex
|
13
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
14
|
+
$stderr.puts "You're missing a library required to use RDiscount. Try running:"
|
15
|
+
$stderr.puts ' $ [sudo] gem install rdiscount'
|
16
|
+
raise 'Missing dependency: rdiscount'
|
17
|
+
end
|
18
|
+
|
19
|
+
RDiscount.new(content, *((ivars[:rdiscount].symbolize_keys rescue {})[:extensions] || [])).to_html
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class RedcarpetFilter < Filter
|
4
|
+
|
5
|
+
def name
|
6
|
+
'redcarpet'
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply(content, ivars)
|
10
|
+
begin
|
11
|
+
require 'redcarpet'
|
12
|
+
rescue LoadError => ex
|
13
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
14
|
+
$stderr.puts "You're missing a library required to use Redcarpet. Try running:"
|
15
|
+
$stderr.puts ' $ [sudo] gem install redcarpet'
|
16
|
+
raise 'Missing dependency: redcarpet'
|
17
|
+
end
|
18
|
+
|
19
|
+
args = ivars[:redcarpet].symbolize_keys rescue {}
|
20
|
+
renderer_class = Kernel.const_get(args[:renderer_name]) rescue args[:renderer_class] || Redcarpet::Render::HTML
|
21
|
+
args.delete(:renderer_name)
|
22
|
+
args.delete(:renderer_class)
|
23
|
+
renderer_options = args[:renderer_options].symbolize_keys rescue {}
|
24
|
+
args.delete(:renderer_options)
|
25
|
+
|
26
|
+
Redcarpet::Markdown.new(renderer_class.new(renderer_options), args).render(content)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class RedClothFilter < Filter
|
4
|
+
|
5
|
+
def name
|
6
|
+
'redcloth'
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply(content, ivars)
|
10
|
+
begin
|
11
|
+
require 'redcloth'
|
12
|
+
rescue LoadError => ex
|
13
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
14
|
+
$stderr.puts "You're missing a library required to use RedCloth. Try running:"
|
15
|
+
$stderr.puts ' $ [sudo] gem install RedCloth'
|
16
|
+
raise 'Missing dependency: RedCloth'
|
17
|
+
end
|
18
|
+
|
19
|
+
textile_doc = RedCloth.new(content)
|
20
|
+
ivars[:redcloth].each { |rule, value| textile_doc.send((rule.to_s + '=').to_sym, value) }
|
21
|
+
textile_doc.to_html
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class RubyPantsFilter < Filter
|
4
|
+
|
5
|
+
def name
|
6
|
+
'rubypants'
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply(content, ivars)
|
10
|
+
begin
|
11
|
+
require 'rubypants'
|
12
|
+
rescue LoadError => ex
|
13
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
14
|
+
$stderr.puts "You're missing a library required to use RubyPants. Try running:"
|
15
|
+
$stderr.puts ' $ [sudo] gem install rubypants'
|
16
|
+
raise 'Missing dependency: rubypants'
|
17
|
+
end
|
18
|
+
|
19
|
+
RubyPants.new(content, *((ivars[:rubypants].symbolize_keys rescue {})[:options] || [])).to_html
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class SassFilter < Filter
|
4
|
+
|
5
|
+
def name
|
6
|
+
'sass'
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply(content, ivars)
|
10
|
+
begin
|
11
|
+
require 'sass'
|
12
|
+
rescue LoadError => ex
|
13
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
14
|
+
$stderr.puts "You're missing a library required to use Sass. Try running:"
|
15
|
+
$stderr.puts ' $ [sudo] gem install sass'
|
16
|
+
raise 'Missing dependency: sass'
|
17
|
+
end
|
18
|
+
|
19
|
+
Sass::Engine.new(content, (ivars[:sass].symbolize_keys rescue {})).render
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/magneto/item.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'magneto/readable'
|
2
|
+
|
3
|
+
module Magneto
|
4
|
+
|
5
|
+
class Item
|
6
|
+
include Readable
|
7
|
+
|
8
|
+
attr_reader :site, :origin
|
9
|
+
|
10
|
+
INVALID_LOCATION_MATCH_PATTERN = %r{(^[^/].*$|^.*/$)}
|
11
|
+
|
12
|
+
def initialize(site, origin = '')
|
13
|
+
super()
|
14
|
+
@site = site
|
15
|
+
@origin = origin.sub(INVALID_LOCATION_MATCH_PATTERN, '')
|
16
|
+
@destination = nil
|
17
|
+
@metadata = nil
|
18
|
+
@content = nil
|
19
|
+
@precomposed_content = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def relocated?
|
23
|
+
@origin == ''
|
24
|
+
end
|
25
|
+
|
26
|
+
def relocate
|
27
|
+
@origin = ''
|
28
|
+
end
|
29
|
+
|
30
|
+
def abandoned?
|
31
|
+
@destination == ''
|
32
|
+
end
|
33
|
+
|
34
|
+
def abandon
|
35
|
+
@destination = ''
|
36
|
+
end
|
37
|
+
|
38
|
+
def destination
|
39
|
+
@destination ||= @origin.dup
|
40
|
+
@destination
|
41
|
+
end
|
42
|
+
|
43
|
+
def destination=(destination)
|
44
|
+
@destination = (destination || '').sub(INVALID_LOCATION_MATCH_PATTERN, '')
|
45
|
+
end
|
46
|
+
|
47
|
+
def origin_path
|
48
|
+
@site.items_path + @origin
|
49
|
+
end
|
50
|
+
|
51
|
+
alias_method :path, :origin_path
|
52
|
+
|
53
|
+
def destination_path
|
54
|
+
@site.config[:output_path] + (@destination || @origin)
|
55
|
+
end
|
56
|
+
|
57
|
+
def import_metadata
|
58
|
+
self.destination = @metadata[:destination] unless @metadata.nil? || @metadata[:destination].nil?
|
59
|
+
end
|
60
|
+
|
61
|
+
def precomposed_content
|
62
|
+
read if @content.nil?
|
63
|
+
@precomposed_content || @content.dup
|
64
|
+
end
|
65
|
+
|
66
|
+
def apply_filter(filter_name, args = {})
|
67
|
+
filter = @site.filters[filter_name.to_sym]
|
68
|
+
|
69
|
+
if filter.nil?
|
70
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
71
|
+
raise "Couldn't find filter: '#{filter_name.to_s}'"
|
72
|
+
end
|
73
|
+
|
74
|
+
read if @content.nil?
|
75
|
+
|
76
|
+
@content = filter.apply(@content, @site.config.deep_merge(@metadata || {}).deep_merge({
|
77
|
+
:config => @site.config,
|
78
|
+
:site => @site,
|
79
|
+
:item => self
|
80
|
+
}).deep_merge(filter_name.to_sym => args))
|
81
|
+
end
|
82
|
+
|
83
|
+
def apply_template(template_name, args = {})
|
84
|
+
template = @site.templates[template_name.to_sym]
|
85
|
+
|
86
|
+
if template.nil?
|
87
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
88
|
+
raise "Couldn't find template: '#{template_name.to_s}'"
|
89
|
+
end
|
90
|
+
|
91
|
+
read if @content.nil?
|
92
|
+
@precomposed_content ||= @content.dup
|
93
|
+
|
94
|
+
@content = template.filter.apply(template.content, {
|
95
|
+
template.filter.name.to_sym => {}
|
96
|
+
}.deep_merge(@site.config).deep_merge(@metadata || {}).deep_merge(template.metadata || {}).deep_merge({
|
97
|
+
:config => @site.config,
|
98
|
+
:site => @site,
|
99
|
+
:item => self,
|
100
|
+
:content => @content
|
101
|
+
}).deep_merge(args.symbolize_keys))
|
102
|
+
end
|
103
|
+
|
104
|
+
def write
|
105
|
+
unless abandoned?
|
106
|
+
if content?
|
107
|
+
FileUtils.mkdir_p File.dirname(destination_path)
|
108
|
+
File.open(destination_path, 'w') { |f| f.write content }
|
109
|
+
else
|
110
|
+
unless relocated?
|
111
|
+
FileUtils.mkdir_p File.dirname(destination_path)
|
112
|
+
FileUtils.cp origin_path, destination_path
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
module Readable
|
4
|
+
|
5
|
+
def metadata?
|
6
|
+
not @metadata.nil? || @metadata.empty?
|
7
|
+
end
|
8
|
+
|
9
|
+
def metadata
|
10
|
+
read if @metadata.nil?
|
11
|
+
@metadata || {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def metadata=(metadata)
|
15
|
+
@metadata = metadata || {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def content?
|
19
|
+
not @content.nil? || @content.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
def content
|
23
|
+
read if @content.nil?
|
24
|
+
@content || ''
|
25
|
+
end
|
26
|
+
|
27
|
+
alias to_s content
|
28
|
+
|
29
|
+
def content=(content)
|
30
|
+
@content = content || ''
|
31
|
+
end
|
32
|
+
|
33
|
+
# Adapted from `jekyll/convertible.rb` with thanks to Tom Preston-Werner.
|
34
|
+
def read
|
35
|
+
@metadata = {}
|
36
|
+
@content = File.read(path)
|
37
|
+
|
38
|
+
if @content =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
|
39
|
+
@content = $POSTMATCH
|
40
|
+
|
41
|
+
begin
|
42
|
+
@metadata = YAML.load($1)
|
43
|
+
raise unless @metadata.is_a? Hash
|
44
|
+
rescue => ex
|
45
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
46
|
+
$stderr.puts "WARNING: Couldn't load metadata."
|
47
|
+
@metadata = {}
|
48
|
+
end
|
49
|
+
|
50
|
+
@metadata.symbolize_keys!
|
51
|
+
import_metadata
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
# Adapted from `nanoc/helpers/rendering.rb` and `nanoc/helpers/capturing.rb`
|
4
|
+
# with thanks to Denis Defreyne and contributors.
|
5
|
+
class RenderContext < Context
|
6
|
+
|
7
|
+
def render(template_name, args = {}, &block)
|
8
|
+
template = @site.templates[template_name.to_sym]
|
9
|
+
|
10
|
+
if template.nil?
|
11
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
12
|
+
raise "Couldn't find template: '#{template_name.to_s}'"
|
13
|
+
end
|
14
|
+
|
15
|
+
if block_given?
|
16
|
+
# Get templating system output instance.
|
17
|
+
erbout = eval('_erbout', block.binding)
|
18
|
+
|
19
|
+
# Save output length.
|
20
|
+
erbout_length = erbout.length
|
21
|
+
|
22
|
+
# Execute block (which may cause recursion).
|
23
|
+
block.call
|
24
|
+
|
25
|
+
# Use additional output from block execution as content.
|
26
|
+
current_content = erbout[erbout_length..-1]
|
27
|
+
|
28
|
+
# Remove addition from templating system output.
|
29
|
+
erbout[erbout_length..-1] = ''
|
30
|
+
else
|
31
|
+
current_content = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
ivars = {}
|
35
|
+
self.instance_variables.each { |ivar| ivars[ivar[1..-1].to_sym] = self.instance_variable_get(ivar) }
|
36
|
+
|
37
|
+
result = template.filter.apply(template.content, ivars.deep_merge({
|
38
|
+
:content => current_content
|
39
|
+
}).deep_merge(template.metadata || {}).deep_merge(args.symbolize_keys))
|
40
|
+
|
41
|
+
if block_given?
|
42
|
+
# Append filter result to templating system output and return empty
|
43
|
+
# string.
|
44
|
+
erbout << result
|
45
|
+
''
|
46
|
+
else
|
47
|
+
result
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class ScriptContext < Context
|
4
|
+
|
5
|
+
def initialize(ivars)
|
6
|
+
super
|
7
|
+
puts 'Evaluating script...'
|
8
|
+
|
9
|
+
begin
|
10
|
+
self.instance_eval File.read(@source_path + '/script.rb')
|
11
|
+
@site.write
|
12
|
+
rescue => ex
|
13
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
14
|
+
raise 'Script evaluation failed.'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/magneto/site.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class Site
|
4
|
+
|
5
|
+
attr_reader :config, :filters, :items_path, :items, :templates
|
6
|
+
|
7
|
+
def initialize(config, filters)
|
8
|
+
super()
|
9
|
+
@config = config
|
10
|
+
@filters = filters
|
11
|
+
@items_path = @config[:source_path] + '/items'
|
12
|
+
@items_path.freeze
|
13
|
+
reset
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate
|
17
|
+
find_items
|
18
|
+
find_templates
|
19
|
+
find_existing_output
|
20
|
+
|
21
|
+
ScriptContext.new(@config.deep_merge({
|
22
|
+
:config => @config,
|
23
|
+
:site => self
|
24
|
+
}))
|
25
|
+
|
26
|
+
reset
|
27
|
+
end
|
28
|
+
|
29
|
+
def write
|
30
|
+
return if @written
|
31
|
+
|
32
|
+
puts 'Writing output...'
|
33
|
+
@written = true
|
34
|
+
output = Set.new unless @existing_output.empty?
|
35
|
+
|
36
|
+
@items.each do |item|
|
37
|
+
item.write
|
38
|
+
|
39
|
+
unless @existing_output.empty?
|
40
|
+
next if item.abandoned?
|
41
|
+
path = item.destination_path
|
42
|
+
|
43
|
+
while path.start_with? @config[:output_path] do
|
44
|
+
output << path
|
45
|
+
path = File.dirname(path)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
unless @existing_output.empty?
|
51
|
+
obsolete_output = @existing_output - output
|
52
|
+
|
53
|
+
unless obsolete_output.empty?
|
54
|
+
if @config[:remove_obsolete]
|
55
|
+
puts 'Removing obsolete output...'
|
56
|
+
|
57
|
+
obsolete_output.to_a.sort.reverse.each do |path|
|
58
|
+
if File.directory? path
|
59
|
+
FileUtils.rmdir path
|
60
|
+
else
|
61
|
+
FileUtils.rm path
|
62
|
+
end
|
63
|
+
end
|
64
|
+
else
|
65
|
+
puts 'Listing obsolete output...'
|
66
|
+
puts obsolete_output.to_a.sort.reverse
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
puts 'Site generation succeeded.'
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def reset
|
77
|
+
@items = []
|
78
|
+
@templates = {}
|
79
|
+
@existing_output = Set.new
|
80
|
+
@written = false
|
81
|
+
end
|
82
|
+
|
83
|
+
def find_items
|
84
|
+
puts 'Finding items...'
|
85
|
+
|
86
|
+
if File.directory? @items_path
|
87
|
+
Dir.chdir @items_path do
|
88
|
+
Dir[@config[:hidden_files] ? '**/{.[^.],}*' : '**/*'].each do |path|
|
89
|
+
unless File.directory? path
|
90
|
+
@items << Item.new(self, '/' + path)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def find_templates
|
98
|
+
puts 'Finding templates...'
|
99
|
+
|
100
|
+
Dir[@config[:source_path] + '/templates/*.*'].each do |path|
|
101
|
+
unless File.directory? path
|
102
|
+
name = File.basename(path).split('.')[0..-2].join('.')
|
103
|
+
@templates[name.to_sym] = Template.new(self, path, name)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def find_existing_output
|
109
|
+
puts 'Finding existing output...'
|
110
|
+
|
111
|
+
Dir[@config[:output_path] + '/**/{.[^.],}*'].each do |path|
|
112
|
+
@existing_output << path
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Magneto
|
2
|
+
|
3
|
+
class Template
|
4
|
+
include Readable
|
5
|
+
|
6
|
+
attr_reader :site, :path, :name, :filter
|
7
|
+
|
8
|
+
def initialize(site, path, name)
|
9
|
+
super()
|
10
|
+
@site = site
|
11
|
+
@path = path
|
12
|
+
@name = name
|
13
|
+
@filter = nil
|
14
|
+
@metadata = nil
|
15
|
+
@content = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def use_filter(filter_name)
|
19
|
+
@filter = @site.filters[filter_name.to_sym]
|
20
|
+
|
21
|
+
if @filter.nil?
|
22
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{ex.to_s}"
|
23
|
+
raise "Couldn't find filter: '#{filter_name.to_s}'"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def import_metadata
|
28
|
+
@filter = use_filter(@metadata[:filter]) unless @metadata.nil? || @metadata[:filter].nil?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/magneto.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/lib')
|
2
|
+
|
3
|
+
require 'magneto'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'magneto'
|
7
|
+
s.version = Magneto::VERSION
|
8
|
+
s.summary = 'A static site generator.'
|
9
|
+
s.description = 'Magneto is a static site generator.'
|
10
|
+
s.authors = ['Don Melton']
|
11
|
+
s.email = 'don@blivet.com'
|
12
|
+
s.homepage = 'https://github.com/donmelton/magneto'
|
13
|
+
s.files = Dir['{bin,lib}/**/*'] + Dir['[A-Z]*'] + ['magneto.gemspec']
|
14
|
+
s.executables = ['magneto']
|
15
|
+
s.extra_rdoc_files = ['LICENSE']
|
16
|
+
s.require_paths = ['lib']
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: magneto
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Don Melton
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-17 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Magneto is a static site generator.
|
15
|
+
email: don@blivet.com
|
16
|
+
executables:
|
17
|
+
- magneto
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files:
|
20
|
+
- LICENSE
|
21
|
+
files:
|
22
|
+
- bin/magneto
|
23
|
+
- lib/magneto/application.rb
|
24
|
+
- lib/magneto/context.rb
|
25
|
+
- lib/magneto/core_ext.rb
|
26
|
+
- lib/magneto/filter.rb
|
27
|
+
- lib/magneto/filters/bluecloth.rb
|
28
|
+
- lib/magneto/filters/coffeescript.rb
|
29
|
+
- lib/magneto/filters/erb.rb
|
30
|
+
- lib/magneto/filters/erubis.rb
|
31
|
+
- lib/magneto/filters/haml.rb
|
32
|
+
- lib/magneto/filters/kramdown.rb
|
33
|
+
- lib/magneto/filters/less.rb
|
34
|
+
- lib/magneto/filters/maruku.rb
|
35
|
+
- lib/magneto/filters/rdiscount.rb
|
36
|
+
- lib/magneto/filters/redcarpet.rb
|
37
|
+
- lib/magneto/filters/redcloth.rb
|
38
|
+
- lib/magneto/filters/rubypants.rb
|
39
|
+
- lib/magneto/filters/sass.rb
|
40
|
+
- lib/magneto/filters.rb
|
41
|
+
- lib/magneto/item.rb
|
42
|
+
- lib/magneto/readable.rb
|
43
|
+
- lib/magneto/render_context.rb
|
44
|
+
- lib/magneto/script_context.rb
|
45
|
+
- lib/magneto/site.rb
|
46
|
+
- lib/magneto/template.rb
|
47
|
+
- lib/magneto.rb
|
48
|
+
- LICENSE
|
49
|
+
- README.md
|
50
|
+
- magneto.gemspec
|
51
|
+
homepage: https://github.com/donmelton/magneto
|
52
|
+
licenses: []
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 1.8.24
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: A static site generator.
|
75
|
+
test_files: []
|