magneto 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|