nanoc 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 +37 -0
- data/Rakefile +59 -0
- data/bin/nanoc +97 -0
- data/lib/compiler.rb +95 -0
- data/lib/creator.rb +149 -0
- data/lib/enhancements.rb +123 -0
- data/lib/nanoc.rb +31 -0
- data/test/test_compile.rb +26 -0
- data/test/test_create.rb +71 -0
- data/test/test_enhancements.rb +114 -0
- metadata +64 -0
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2007 Denis Defreyne
|
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
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
== Overview
|
2
|
+
|
3
|
+
nanoc is a simple but very flexible content management system written in Ruby.
|
4
|
+
It operates on local files, and therefore does not run on the server. nanoc
|
5
|
+
"compiles" the local source files into HTML (usually), by evaluating eRuby,
|
6
|
+
Markdown, etc.
|
7
|
+
|
8
|
+
== Documentation
|
9
|
+
|
10
|
+
nanoc has a web site at <http://stoneship.org/software/nanoc/>, which contains
|
11
|
+
a "Getting Started" guide as well as a reference for nanoc.
|
12
|
+
|
13
|
+
== Contact
|
14
|
+
|
15
|
+
You can reach me at <denis.defreyne@stoneship.org>.
|
16
|
+
|
17
|
+
== Copyright
|
18
|
+
|
19
|
+
Copyright (c) 2007 Denis Defreyne
|
20
|
+
|
21
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
22
|
+
of this software and associated documentation files (the "Software"), to deal
|
23
|
+
in the Software without restriction, including without limitation the rights
|
24
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
25
|
+
copies of the Software, and to permit persons to whom the Software is
|
26
|
+
furnished to do so, subject to the following conditions:
|
27
|
+
|
28
|
+
The above copyright notice and this permission notice shall be included in all
|
29
|
+
copies or substantial portions of the Software.
|
30
|
+
|
31
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
32
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
33
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
34
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
35
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
36
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
37
|
+
SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'rake/testtask'
|
6
|
+
|
7
|
+
#####
|
8
|
+
|
9
|
+
NAME = 'nanoc'
|
10
|
+
VERS = '1.0'
|
11
|
+
SUMMARY = 'a CMS that doesn\'t even run on your server'
|
12
|
+
|
13
|
+
HOMEPAGE = 'http://stoneship.org/software/nanoc'
|
14
|
+
EMAIL = 'denis.defreyne@stoneship.org'
|
15
|
+
|
16
|
+
#####
|
17
|
+
|
18
|
+
CLEAN.include [ '*.gem', 'pkg', 'tmp' ]
|
19
|
+
|
20
|
+
spec = Gem::Specification.new do |s|
|
21
|
+
s.name = NAME
|
22
|
+
s.version = VERS
|
23
|
+
s.platform = Gem::Platform::RUBY
|
24
|
+
s.summary = SUMMARY
|
25
|
+
s.description = s.summary
|
26
|
+
s.homepage = HOMEPAGE
|
27
|
+
s.email = EMAIL
|
28
|
+
|
29
|
+
s.add_dependency('erubis')
|
30
|
+
s.required_ruby_version = '>= 1.8.2'
|
31
|
+
|
32
|
+
s.has_rdoc = false
|
33
|
+
s.files = %w( README LICENSE Rakefile ) + Dir.glob('{bin,lib,test}/**/*')
|
34
|
+
s.executables = [ 'nanoc' ]
|
35
|
+
s.require_path = 'lib'
|
36
|
+
s.bindir = 'bin'
|
37
|
+
end
|
38
|
+
|
39
|
+
Rake::GemPackageTask.new(spec) do |task|
|
40
|
+
task.need_tar = true
|
41
|
+
task.gem_spec = spec
|
42
|
+
end
|
43
|
+
|
44
|
+
Rake::TestTask.new(:test) do |test|
|
45
|
+
test.test_files = Dir.glob('test/test_*.rb')
|
46
|
+
end
|
47
|
+
|
48
|
+
#####
|
49
|
+
|
50
|
+
task :default => [ :test ]
|
51
|
+
|
52
|
+
task :install_gem do
|
53
|
+
sh %{rake package}
|
54
|
+
sh %{sudo gem install pkg/#{NAME}-#{VERS}}
|
55
|
+
end
|
56
|
+
|
57
|
+
task :uninstall_gem do
|
58
|
+
sh %{sudo gem uninstall #{NAME}}
|
59
|
+
end
|
data/bin/nanoc
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Available options:
|
4
|
+
#
|
5
|
+
# -h, --help:
|
6
|
+
# prints the help
|
7
|
+
#
|
8
|
+
# -t <template>, --template <template>
|
9
|
+
# Uses the specified template when creating a page
|
10
|
+
#
|
11
|
+
# -v, --version:
|
12
|
+
# prints the version information
|
13
|
+
|
14
|
+
require 'rubygems' rescue nil
|
15
|
+
require 'getoptlong'
|
16
|
+
|
17
|
+
require File.dirname(__FILE__) + '/../lib/nanoc.rb'
|
18
|
+
|
19
|
+
# Define some texts
|
20
|
+
version_text = 'nanoc 0.1 (c) 2007 Denis Defreyne.'
|
21
|
+
help_text = <<EOT
|
22
|
+
usage: nanoc [-hv]
|
23
|
+
nanoc create_site <name>
|
24
|
+
nanoc create_page <name> [-t template]
|
25
|
+
nanoc create_template <name>
|
26
|
+
nanoc compile
|
27
|
+
EOT
|
28
|
+
|
29
|
+
# Parse options
|
30
|
+
opts = GetoptLong.new(
|
31
|
+
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
32
|
+
[ '--template', '-t', GetoptLong::REQUIRED_ARGUMENT ],
|
33
|
+
[ '--version', '-v', GetoptLong::NO_ARGUMENT ]
|
34
|
+
)
|
35
|
+
uncompileed_opts = {}
|
36
|
+
begin
|
37
|
+
opts.each do |opt, arg|
|
38
|
+
case opt
|
39
|
+
when '--help'
|
40
|
+
$stderr.puts help_text
|
41
|
+
exit
|
42
|
+
when '--version'
|
43
|
+
puts version_text
|
44
|
+
exit
|
45
|
+
else
|
46
|
+
uncompileed_opts[opt] = arg
|
47
|
+
end
|
48
|
+
end
|
49
|
+
rescue GetoptLong::InvalidOption
|
50
|
+
$stderr.puts help_text
|
51
|
+
exit
|
52
|
+
end
|
53
|
+
|
54
|
+
# Make sure we have at least one argument
|
55
|
+
if ARGV.size == 0
|
56
|
+
$stderr.puts help_text
|
57
|
+
exit
|
58
|
+
end
|
59
|
+
|
60
|
+
# Handle command
|
61
|
+
command = ARGV[0]
|
62
|
+
case command
|
63
|
+
# Create site
|
64
|
+
when 'create_site', 'cs'
|
65
|
+
if ARGV.size != 2
|
66
|
+
$stderr.puts 'Usage: nanoc create_site [site_name]'
|
67
|
+
exit
|
68
|
+
end
|
69
|
+
Nanoc::Creator.create_site(ARGV[1])
|
70
|
+
|
71
|
+
# Create page
|
72
|
+
when 'create_page', 'cp'
|
73
|
+
if ARGV.size != 2
|
74
|
+
$stderr.puts 'Usage: nanoc create_page [page_name]'
|
75
|
+
exit
|
76
|
+
end
|
77
|
+
Nanoc::Creator.create_page(ARGV[1], :template => uncompileed_opts['--template'])
|
78
|
+
|
79
|
+
# Create template
|
80
|
+
when 'create_template', 'ct'
|
81
|
+
if ARGV.size != 2
|
82
|
+
$stderr.puts 'Usage: nanoc create_template [template_name]'
|
83
|
+
exit
|
84
|
+
end
|
85
|
+
Nanoc::Creator.create_template(ARGV[1])
|
86
|
+
|
87
|
+
# Process site and generate output
|
88
|
+
when 'compile', 'compile_site', 'co'
|
89
|
+
if ARGV.size != 1
|
90
|
+
$stderr.puts 'Usage: nanoc compile'
|
91
|
+
exit
|
92
|
+
end
|
93
|
+
Nanoc::Compiler.new.run
|
94
|
+
|
95
|
+
else
|
96
|
+
puts 'Unrecognised command \'' + command + '\''
|
97
|
+
end
|
data/lib/compiler.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
module Nanoc
|
2
|
+
|
3
|
+
class Compiler
|
4
|
+
|
5
|
+
DEFAULT_CONFIG = {
|
6
|
+
:output_dir => 'output'
|
7
|
+
}
|
8
|
+
|
9
|
+
DEFAULT_PAGE = {
|
10
|
+
:layout => '<%= @content %>',
|
11
|
+
:filters => [],
|
12
|
+
:order => 0,
|
13
|
+
:extension => 'html'
|
14
|
+
}
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
Nanoc.ensure_in_site
|
18
|
+
|
19
|
+
@config = DEFAULT_CONFIG.merge(File.read_clean_yaml('config.yaml'))
|
20
|
+
@global_page = DEFAULT_PAGE.merge(File.read_clean_yaml('meta.yaml'))
|
21
|
+
@default_layout = File.read_file('layouts/' + @global_page[:layout] + '.erb')
|
22
|
+
end
|
23
|
+
|
24
|
+
def run
|
25
|
+
Nanoc.ensure_in_site
|
26
|
+
|
27
|
+
# Require files in lib/
|
28
|
+
Dir.glob('lib/*.rb').each { |f| require f }
|
29
|
+
|
30
|
+
# Compile pages
|
31
|
+
pages = compile_pages(uncompiled_pages)
|
32
|
+
|
33
|
+
# Put pages in their layout
|
34
|
+
pages.each do |page|
|
35
|
+
content_with_layout = layout_for_page(page).eruby(page.merge({ :pages => pages }))
|
36
|
+
FileManager.create_file(path_for_page(page)) { content_with_layout }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def uncompiled_pages
|
43
|
+
# Get all meta file names
|
44
|
+
meta_filenames = Dir.glob('content/**/meta.yaml')
|
45
|
+
|
46
|
+
# Read all meta files
|
47
|
+
pages = meta_filenames.collect do |filename|
|
48
|
+
# Get meta file
|
49
|
+
page = @global_page.merge(File.read_clean_yaml(filename)).merge({:path => filename.sub(/^content/, '').sub('meta.yaml', '')})
|
50
|
+
|
51
|
+
# Get index filename
|
52
|
+
index_filenames = Dir.glob(File.dirname(filename) + '/index.*')
|
53
|
+
index_filenames.ensure_single('index files', File.dirname(filename))
|
54
|
+
page[:_index_filename] = index_filenames[0]
|
55
|
+
|
56
|
+
page
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def path_for_page(a_page)
|
61
|
+
if a_page[:custom_path].nil?
|
62
|
+
@config[:output_dir] + a_page[:path] + 'index.' + a_page[:extension]
|
63
|
+
else
|
64
|
+
@config[:output_dir] + a_page[:custom_path]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def layout_for_page(a_page)
|
69
|
+
if a_page[:layout] == 'none'
|
70
|
+
'<%= @content %>'
|
71
|
+
elsif @global_page[:layout] != a_page[:layout]
|
72
|
+
File.read_file('layouts/' + a_page[:layout] + '.erb')
|
73
|
+
else
|
74
|
+
@default_layout
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def compile_pages(a_pages)
|
79
|
+
pages = []
|
80
|
+
|
81
|
+
a_pages.each do |page|
|
82
|
+
# Read and filter page
|
83
|
+
content = File.read_file(page[:_index_filename])
|
84
|
+
content.filter!(page[:filters], :eruby_context => { :pages => pages }) unless page[:filters].nil?
|
85
|
+
|
86
|
+
# Store page
|
87
|
+
pages << page.merge( { :content => content })
|
88
|
+
end
|
89
|
+
|
90
|
+
pages
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
data/lib/creator.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
module Nanoc
|
2
|
+
|
3
|
+
class Creator
|
4
|
+
|
5
|
+
def self.create_site(a_sitename)
|
6
|
+
FileManager.create_dir a_sitename do
|
7
|
+
FileManager.create_dir 'output'
|
8
|
+
|
9
|
+
FileManager.create_file 'config.yaml' do
|
10
|
+
"output_dir: output\n"
|
11
|
+
end
|
12
|
+
|
13
|
+
FileManager.create_file 'meta.yaml' do
|
14
|
+
"# This file contains the default values for all metafiles.\n" +
|
15
|
+
"# Other metafiles can override the contents of this one.\n" +
|
16
|
+
"\n" +
|
17
|
+
"# Built-in\n" +
|
18
|
+
"layout: default\n" +
|
19
|
+
"order: 0\n" +
|
20
|
+
"filters: []\n" +
|
21
|
+
"\n" +
|
22
|
+
"# Custom\n"
|
23
|
+
end
|
24
|
+
|
25
|
+
FileManager.create_file 'Rakefile' do
|
26
|
+
"Dir['tasks/**/*.rake'].sort.each { |rakefile| load rakefile }\n" +
|
27
|
+
"\n" +
|
28
|
+
"task :default do\n" +
|
29
|
+
" puts 'This is an example rake task.'\n" +
|
30
|
+
"end\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
FileManager.create_dir 'layouts' do
|
34
|
+
FileManager.create_file 'default.erb' do
|
35
|
+
"<html>\n" +
|
36
|
+
" <head>\n" +
|
37
|
+
" <title><%= @title %></title>\n" +
|
38
|
+
" </head>\n" +
|
39
|
+
" <body>\n" +
|
40
|
+
"<%= @content %>\n" +
|
41
|
+
" </body>\n" +
|
42
|
+
"</html>\n"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
FileManager.create_dir 'lib' do
|
47
|
+
FileManager.create_file 'default.rb' do
|
48
|
+
"\# All files in the 'lib' directory will be loaded\n" +
|
49
|
+
"\# before nanoc starts compiling.\n" +
|
50
|
+
"\n" +
|
51
|
+
"def html_escape(a_string)\n" +
|
52
|
+
" a_string.gsub('&', '&').gsub('<', '<').gsub('>', '>').gsub('\\'', ''').gsub('\"', '"')\n" +
|
53
|
+
"end\n" +
|
54
|
+
"alias h html_escape\n"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
FileManager.create_dir 'tasks' do
|
59
|
+
FileManager.create_file 'default.rake' do
|
60
|
+
"task :example do\n" +
|
61
|
+
" puts 'This is an example rake task in tasks/default.rake.'\n" +
|
62
|
+
"end\n"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
FileManager.create_dir 'templates' do
|
67
|
+
FileManager.create_dir 'default' do
|
68
|
+
FileManager.create_file 'index.txt' do
|
69
|
+
"This is a new page. Please edit me!\n"
|
70
|
+
end
|
71
|
+
FileManager.create_file 'meta.yaml' do
|
72
|
+
"# Built-in\n" +
|
73
|
+
"\n" +
|
74
|
+
"# Custom\n" +
|
75
|
+
"title: A New Page\n"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
FileManager.create_dir 'content' do
|
81
|
+
FileManager.create_file 'index.txt' do
|
82
|
+
"This is a sample root page. Please edit me!\n"
|
83
|
+
end
|
84
|
+
FileManager.create_file 'meta.yaml' do
|
85
|
+
"# Built-in\n" +
|
86
|
+
"\n" +
|
87
|
+
"# Custom\n" +
|
88
|
+
"title: My New Homepage\n"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.create_page(a_pagename, a_params={})
|
95
|
+
Nanoc.ensure_in_site
|
96
|
+
|
97
|
+
# Sanitize page name
|
98
|
+
if a_pagename =~ /^[\/\.]+/
|
99
|
+
$stderr.puts 'ERROR: page name starts with dots and/or slashes, aborting'
|
100
|
+
return
|
101
|
+
end
|
102
|
+
|
103
|
+
# Read template
|
104
|
+
template_index = nil
|
105
|
+
template_meta = nil
|
106
|
+
begin
|
107
|
+
template = a_params[:template] || 'default'
|
108
|
+
template_meta = File.read_file('templates/' + template + '/meta.yaml').eruby
|
109
|
+
template_index_filename = Dir.glob('templates/' + template + '/index.*')[0]
|
110
|
+
template_index = File.read_file(template_index_filename).eruby
|
111
|
+
rescue
|
112
|
+
$stderr.puts 'ERROR: no such template'
|
113
|
+
exit
|
114
|
+
end
|
115
|
+
|
116
|
+
# Create index and yaml file
|
117
|
+
FileManager.create_dir 'content' do
|
118
|
+
FileManager.create_dir a_pagename do
|
119
|
+
FileManager.create_file 'index.txt' do
|
120
|
+
template_index
|
121
|
+
end
|
122
|
+
FileManager.create_file 'meta.yaml' do
|
123
|
+
template_meta
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.create_template(a_templatename)
|
130
|
+
Nanoc.ensure_in_site
|
131
|
+
|
132
|
+
FileManager.create_dir 'templates' do
|
133
|
+
FileManager.create_dir a_templatename do
|
134
|
+
FileManager.create_file 'index.txt' do
|
135
|
+
"This is a new page. Please edit me!\n"
|
136
|
+
end
|
137
|
+
FileManager.create_file 'meta.yaml' do
|
138
|
+
"# Built-in\n" +
|
139
|
+
"\n" +
|
140
|
+
"# Custom\n" +
|
141
|
+
"title: A New Page\n"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
data/lib/enhancements.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
|
2
|
+
|
3
|
+
try_require 'rubygems'
|
4
|
+
try_require 'bluecloth'
|
5
|
+
try_require 'rubypants'
|
6
|
+
|
7
|
+
require 'erubis'
|
8
|
+
require 'fileutils'
|
9
|
+
require 'yaml'
|
10
|
+
|
11
|
+
class Array
|
12
|
+
# Ensures that the array contains only one element
|
13
|
+
def ensure_single(a_noun, a_context)
|
14
|
+
raise "ERROR: expected 1 #{a_noun}, found #{self.size} (#{a_context})" if self.size != 1
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class File
|
19
|
+
# Reads the contents of the entire file
|
20
|
+
def self.read_file(a_filename)
|
21
|
+
content = ''
|
22
|
+
File.open(a_filename) { |io| content = io.read }
|
23
|
+
content
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns the contents of an entire file interpreted as YAML
|
27
|
+
def self.read_yaml(a_filename)
|
28
|
+
YAML::load(self.read_file(a_filename)) || {}
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the contents of an entire file interpreted as YAML and cleaned
|
32
|
+
def self.read_clean_yaml(a_filename)
|
33
|
+
self.read_yaml(a_filename).clean
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Hash
|
38
|
+
# Converts all keys to symbols, and converts *_at and *_on
|
39
|
+
# keys to Times and Dates, respectively
|
40
|
+
def clean
|
41
|
+
hash = {}
|
42
|
+
|
43
|
+
self.each_pair do |key, value|
|
44
|
+
if key =~ /_on$/
|
45
|
+
hash[key.to_sym] = Date.parse(value)
|
46
|
+
elsif key =~ /_at$/
|
47
|
+
hash[key.to_sym] = Time.parse(value)
|
48
|
+
elsif value == 'true'
|
49
|
+
hash[key.to_sym] = true
|
50
|
+
elsif value == 'false'
|
51
|
+
hash[key.to_sym] = false
|
52
|
+
else
|
53
|
+
hash[key.to_sym] = value
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
hash
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class String
|
62
|
+
# Runs the string through the filters as given by the array of
|
63
|
+
# filter names. Available filters include 'markdown', 'smartypants' and 'eruby'.
|
64
|
+
def filter!(a_filters, a_params={})
|
65
|
+
a_filters.each do |filter|
|
66
|
+
case filter
|
67
|
+
when 'markdown'
|
68
|
+
self.replace(self.markdown)
|
69
|
+
when 'smartypants'
|
70
|
+
self.replace(self.smartypants)
|
71
|
+
when 'eruby'
|
72
|
+
self.replace(self.eruby(a_params[:eruby_context]))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Converts the string to HTML using Markdown.
|
78
|
+
def markdown
|
79
|
+
BlueCloth::new(self).to_html
|
80
|
+
rescue NameError
|
81
|
+
$stderr.puts 'ERROR: String#markdown failed: BlueCloth not installed'
|
82
|
+
exit
|
83
|
+
end
|
84
|
+
|
85
|
+
# Styles the string as HTML by converting quotes, dashes, ... using RubyPants
|
86
|
+
def smartypants
|
87
|
+
RubyPants::new(self).to_html
|
88
|
+
rescue NameError
|
89
|
+
$stderr.puts 'ERROR: String#smartypants failed: RubyPants not installed'
|
90
|
+
exit
|
91
|
+
end
|
92
|
+
|
93
|
+
# Converts the string using eRuby.
|
94
|
+
def eruby(a_context={})
|
95
|
+
Erubis::Eruby.new(self).evaluate(a_context)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class FileManager
|
100
|
+
@@stack = []
|
101
|
+
|
102
|
+
def self.create_dir(a_name)
|
103
|
+
@@stack.push(a_name)
|
104
|
+
unless File.directory?(File.join(@@stack))
|
105
|
+
puts ' create ' + @@stack.join('/')
|
106
|
+
FileUtils.mkdir_p(@@stack.join('/'))
|
107
|
+
end
|
108
|
+
yield if block_given?
|
109
|
+
@@stack.pop
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.create_file(a_name)
|
113
|
+
path = @@stack.empty? ? a_name : @@stack.join('/') + '/' + a_name
|
114
|
+
FileManager.create_dir(path.sub(/\/[^\/]+$/, '')) if @@stack.empty?
|
115
|
+
puts " #{File.exist?(a_name) ? 'update' : 'create'} " + path
|
116
|
+
if block_given?
|
117
|
+
open(path, 'w') { |io| io.write(yield) }
|
118
|
+
else
|
119
|
+
open(path, 'w') { |io| }
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
data/lib/nanoc.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Nanoc
|
2
|
+
VERSION = '1.0'
|
3
|
+
|
4
|
+
def self.ensure_in_site
|
5
|
+
unless in_site?
|
6
|
+
$stderr.puts 'ERROR: The current working directory does not seem to be a valid/complete nanoc site directory; aborting.'
|
7
|
+
exit
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def self.in_site?
|
14
|
+
return false unless File.directory?('content')
|
15
|
+
return false unless File.directory?('layouts')
|
16
|
+
return false unless File.directory?('lib')
|
17
|
+
return false unless File.directory?('output')
|
18
|
+
return false unless File.directory?('tasks')
|
19
|
+
return false unless File.directory?('templates')
|
20
|
+
|
21
|
+
return false unless File.exist?('config.yaml')
|
22
|
+
return false unless File.exist?('meta.yaml')
|
23
|
+
return false unless File.exist?('Rakefile')
|
24
|
+
|
25
|
+
true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
require File.dirname(__FILE__) + '/creator.rb'
|
30
|
+
require File.dirname(__FILE__) + '/compiler.rb'
|
31
|
+
require File.dirname(__FILE__) + '/enhancements.rb'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../lib/nanoc.rb'
|
4
|
+
|
5
|
+
class CompileTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
FileManager.create_dir 'tmp'
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
FileUtils.rm_rf 'tmp'
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_compile
|
15
|
+
FileUtils.cd('tmp')
|
16
|
+
Nanoc::Creator.create_site('site')
|
17
|
+
FileUtils.cd('site')
|
18
|
+
Nanoc::Creator.create_page('moo')
|
19
|
+
Nanoc::Compiler.new.run
|
20
|
+
FileUtils.cd('..')
|
21
|
+
FileUtils.cd('..')
|
22
|
+
|
23
|
+
assert File.file?('tmp/site/output/index.html')
|
24
|
+
assert File.file?('tmp/site/output/moo/index.html')
|
25
|
+
end
|
26
|
+
end
|
data/test/test_create.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../lib/nanoc.rb'
|
4
|
+
|
5
|
+
class CreateTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
FileManager.create_dir 'tmp'
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
FileUtils.rm_rf 'tmp'
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_create_site
|
15
|
+
FileUtils.cd('tmp')
|
16
|
+
Nanoc::Creator.create_site('site')
|
17
|
+
FileUtils.cd('..')
|
18
|
+
|
19
|
+
assert File.directory?('tmp/site/')
|
20
|
+
|
21
|
+
assert File.file?('tmp/site/config.yaml')
|
22
|
+
assert File.file?('tmp/site/meta.yaml')
|
23
|
+
assert File.file?('tmp/site/Rakefile')
|
24
|
+
|
25
|
+
assert File.directory?('tmp/site/content/')
|
26
|
+
assert File.file?('tmp/site/content/index.txt')
|
27
|
+
assert File.file?('tmp/site/content/meta.yaml')
|
28
|
+
|
29
|
+
assert File.directory?('tmp/site/layouts/')
|
30
|
+
assert File.file?('tmp/site/layouts/default.erb')
|
31
|
+
|
32
|
+
assert File.directory?('tmp/site/lib/')
|
33
|
+
assert File.file?('tmp/site/lib/default.rb')
|
34
|
+
|
35
|
+
assert File.directory?('tmp/site/output/')
|
36
|
+
|
37
|
+
assert File.directory?('tmp/site/templates/')
|
38
|
+
assert File.directory?('tmp/site/templates/default/')
|
39
|
+
assert File.file?('tmp/site/templates/default/index.txt')
|
40
|
+
assert File.file?('tmp/site/templates/default/meta.yaml')
|
41
|
+
|
42
|
+
assert File.directory?('tmp/site/tasks/')
|
43
|
+
assert File.file?('tmp/site/tasks/default.rake')
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_create_page
|
47
|
+
FileUtils.cd('tmp')
|
48
|
+
Nanoc::Creator.create_site('site')
|
49
|
+
FileUtils.cd('site')
|
50
|
+
Nanoc::Creator.create_page('moo')
|
51
|
+
FileUtils.cd('..')
|
52
|
+
FileUtils.cd('..')
|
53
|
+
|
54
|
+
assert File.directory?('tmp/site/content/moo/')
|
55
|
+
assert File.file?('tmp/site/content/moo/index.txt')
|
56
|
+
assert File.file?('tmp/site/content/moo/meta.yaml')
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_create_template
|
60
|
+
FileUtils.cd('tmp')
|
61
|
+
Nanoc::Creator.create_site('site')
|
62
|
+
FileUtils.cd('site')
|
63
|
+
Nanoc::Creator.create_template('moo')
|
64
|
+
FileUtils.cd('..')
|
65
|
+
FileUtils.cd('..')
|
66
|
+
|
67
|
+
assert File.directory?('tmp/site/templates/moo/')
|
68
|
+
assert File.file?('tmp/site/templates/moo/index.txt')
|
69
|
+
assert File.file?('tmp/site/templates/moo/meta.yaml')
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
require File.dirname(__FILE__) + '/../lib/nanoc.rb'
|
6
|
+
|
7
|
+
class EnhancementsTest < Test::Unit::TestCase
|
8
|
+
def setup
|
9
|
+
open('test.yaml', 'w') do |io|
|
10
|
+
io.write('created_at: 12/07/04')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def teardown
|
15
|
+
FileUtils.rm('test.yaml')
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_array_ensure_single
|
19
|
+
assert_raise RuntimeError do
|
20
|
+
[ ].ensure_single('moofs', 'blargh')
|
21
|
+
end
|
22
|
+
assert_raise RuntimeError do
|
23
|
+
[ 1, 2 ].ensure_single('moofs', 'blargh')
|
24
|
+
end
|
25
|
+
assert_nothing_raised do
|
26
|
+
[ 1 ].ensure_single('moofs', 'blargh')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_file_read_file
|
31
|
+
assert_equal 'created_at: 12/07/04', File.read_file('test.yaml')
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_file_read_yaml
|
35
|
+
assert_equal({ 'created_at' => '12/07/04' }, File.read_yaml('test.yaml'))
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_file_read_clean_yaml
|
39
|
+
assert_equal({ :created_at => Time.parse('12/07/04') }, File.read_clean_yaml('test.yaml'))
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_hash_clean
|
43
|
+
hash1 = { 'foo' => 'bar' }
|
44
|
+
hash1_cleaned = { :foo => 'bar' }
|
45
|
+
|
46
|
+
hash2 = { 'created_at' => '12/07/2004' }
|
47
|
+
hash2_cleaned = { :created_at => Time.parse('12/07/2004') }
|
48
|
+
|
49
|
+
assert_equal hash1_cleaned, hash1.clean
|
50
|
+
assert_equal hash2_cleaned, hash2.clean
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_string_filter!
|
54
|
+
text = '<%= @foo %>'
|
55
|
+
context = { :foo => 'Te\'st' }
|
56
|
+
|
57
|
+
text.filter!([ 'eruby' ], :eruby_context => context)
|
58
|
+
assert_equal 'Te\'st', text
|
59
|
+
|
60
|
+
begin
|
61
|
+
text.filter!([ 'markdown', 'smartypants' ])
|
62
|
+
assert_equal '<p>Te’st</p>', text
|
63
|
+
rescue NameError
|
64
|
+
$stderr.puts 'WARNING: Unable to test String#filter! (BlueCloth or RubyPants not installed)'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_string_markdown
|
69
|
+
begin
|
70
|
+
assert_equal 'Hello!'.markdown, '<p>Hello!</p>'
|
71
|
+
rescue NameError
|
72
|
+
$stderr.puts 'WARNING: Unable to test String#markdown (BlueCloth not installed)'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_string_smartypants
|
77
|
+
begin
|
78
|
+
assert_equal 'Te\'st'.smartypants, 'Te’st'
|
79
|
+
rescue NameError
|
80
|
+
$stderr.puts 'WARNING: Unable to test String#smartypants (RubyPants not installed)'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_string_eruby
|
85
|
+
assert_equal '<%= "moo" %>'.eruby, 'moo'
|
86
|
+
assert_equal '<%= @foo %>'.eruby(:foo => 'bar'), 'bar'
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_filemanager_create_dir
|
90
|
+
FileManager.create_dir 'tmp' do
|
91
|
+
FileManager.create_dir 'foo'
|
92
|
+
end
|
93
|
+
|
94
|
+
assert File.exist?('tmp')
|
95
|
+
assert File.directory?('tmp')
|
96
|
+
|
97
|
+
assert File.exist?('tmp/foo')
|
98
|
+
assert File.directory?('tmp/foo')
|
99
|
+
|
100
|
+
assert !File.exist?('foo')
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_filemanager_create_file
|
104
|
+
FileManager.create_dir 'tmp' do
|
105
|
+
FileManager.create_file 'bar' do
|
106
|
+
"asdf"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
assert File.exist?('tmp/bar')
|
111
|
+
assert File.file?('tmp/bar')
|
112
|
+
assert_equal 'asdf', File.read_file('tmp/bar')
|
113
|
+
end
|
114
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.2
|
3
|
+
specification_version: 1
|
4
|
+
name: nanoc
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: "1.0"
|
7
|
+
date: 2007-05-03 00:00:00 +02:00
|
8
|
+
summary: a CMS that doesn't even run on your server
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: denis.defreyne@stoneship.org
|
12
|
+
homepage: http://stoneship.org/software/nanoc
|
13
|
+
rubyforge_project:
|
14
|
+
description: a CMS that doesn't even run on your server
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.8.2
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors: []
|
30
|
+
|
31
|
+
files:
|
32
|
+
- README
|
33
|
+
- LICENSE
|
34
|
+
- Rakefile
|
35
|
+
- bin/nanoc
|
36
|
+
- lib/compiler.rb
|
37
|
+
- lib/creator.rb
|
38
|
+
- lib/enhancements.rb
|
39
|
+
- lib/nanoc.rb
|
40
|
+
- test/test_compile.rb
|
41
|
+
- test/test_create.rb
|
42
|
+
- test/test_enhancements.rb
|
43
|
+
test_files: []
|
44
|
+
|
45
|
+
rdoc_options: []
|
46
|
+
|
47
|
+
extra_rdoc_files: []
|
48
|
+
|
49
|
+
executables:
|
50
|
+
- nanoc
|
51
|
+
extensions: []
|
52
|
+
|
53
|
+
requirements: []
|
54
|
+
|
55
|
+
dependencies:
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: erubis
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 0.0.0
|
64
|
+
version:
|