nanoc 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 +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:
|