nanoc 1.4 → 1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,93 @@
1
+ def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
+
3
+ require 'fileutils'
4
+
5
+ def handle_exception(exception, text)
6
+ unless $quiet or exception.class == SystemExit
7
+ $stderr.puts "ERROR: Exception occured while #{text}:\n"
8
+ $stderr.puts exception
9
+ $stderr.puts exception.backtrace.join("\n")
10
+ end
11
+ exit
12
+ end
13
+
14
+ def deprecate(str)
15
+ $stderr.puts 'DEPRECATION WARNING: ' + str unless $quiet
16
+ end
17
+
18
+ class FileLogger
19
+ COLORS = {
20
+ :reset => "\e[0m",
21
+
22
+ :bold => "\e[1m",
23
+
24
+ :black => "\e[30m",
25
+ :red => "\e[31m",
26
+ :green => "\e[32m",
27
+ :yellow => "\e[33m",
28
+ :blue => "\e[34m",
29
+ :magenta => "\e[35m",
30
+ :cyan => "\e[36m",
31
+ :white => "\e[37m"
32
+ }
33
+
34
+ ACTION_COLORS = {
35
+ :create => COLORS[:bold] + COLORS[:green],
36
+ :update => COLORS[:bold] + COLORS[:yellow],
37
+ :move => COLORS[:bold] + COLORS[:blue],
38
+ :identical => COLORS[:bold]
39
+ }
40
+
41
+ attr_reader :out
42
+
43
+ def initialize(a_out = $stdout)
44
+ @out = a_out
45
+ end
46
+
47
+ def log(a_action, a_path)
48
+ @out.puts('%s%12s%s %s' % [ACTION_COLORS[a_action.to_sym], a_action, COLORS[:reset], a_path]) unless $quiet
49
+ end
50
+
51
+ private
52
+
53
+ def method_missing(a_method, *a_args)
54
+ log(a_method.to_s, a_args.first)
55
+ end
56
+ end
57
+
58
+ class FileManager
59
+ @@stack = []
60
+ @@logger = FileLogger.new
61
+
62
+ def self.create_dir(a_name)
63
+ @@stack.pushing(a_name) do
64
+ path = File.join(@@stack)
65
+ unless File.directory?(path)
66
+ FileUtils.mkdir_p(path)
67
+ @@logger.create(path)
68
+ end
69
+ yield if block_given?
70
+ end
71
+ end
72
+
73
+ def self.create_file(a_name)
74
+ path = File.join(@@stack + [ a_name ])
75
+ FileManager.create_dir(path.sub(/\/[^\/]+$/, '')) if @@stack.empty?
76
+ content = block_given? ? yield : nil
77
+ if File.exist?(path)
78
+ if block_given? and File.read(path) == content
79
+ @@logger.identical(path)
80
+ else
81
+ @@logger.update(path)
82
+ end
83
+ else
84
+ @@logger.create(path)
85
+ end
86
+ open(path, 'w') { |io| io.write(content) unless content.nil? }
87
+ end
88
+ end
89
+
90
+ def render(a_name, a_context={})
91
+ assigns = a_context.merge({ :page => @page, :pages => @pages })
92
+ File.read('layouts/' + a_name.to_s + '.erb').eruby(:assigns => assigns)
93
+ end
@@ -0,0 +1,7 @@
1
+ # Convenience function for registering filters
2
+ def register_filter(*names, &block)
3
+ names.each { |name| $nanoc_compiler.register_filter(name, &block) }
4
+ end
5
+
6
+ # Load all filters
7
+ Dir[File.join(File.dirname(__FILE__), 'filters', '*_filter.rb')].each { |f| require f }
@@ -0,0 +1,44 @@
1
+ def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
+
3
+ try_require 'rubygems'
4
+
5
+ require 'erb'
6
+ try_require 'erubis'
7
+
8
+ class ERBContext
9
+
10
+ def initialize(hash)
11
+ hash.each_pair do |key, value|
12
+ instance_variable_set('@' + key.to_s, value)
13
+ end
14
+ end
15
+
16
+ def get_binding
17
+ binding
18
+ end
19
+
20
+ end
21
+
22
+ class String
23
+
24
+ # Converts the string using eRuby
25
+ def eruby(params={})
26
+ params[:eruby_engine] == :erubis ? erubis(params) : erb(params)
27
+ end
28
+
29
+ # Converts the string using Erubis
30
+ def erubis(params={})
31
+ Erubis::Eruby.new(self).evaluate(params[:assigns] || {})
32
+ end
33
+
34
+ # Converts the string using ERB
35
+ def erb(params={})
36
+ ERB.new(self).result(ERBContext.new(params[:assigns] || {}).get_binding)
37
+ end
38
+
39
+ end
40
+
41
+ register_filter 'eruby' do |page, pages, config|
42
+ assigns = { :page => page, :pages => pages }
43
+ page.content.eruby(:assigns => assigns, :eruby_engine => config[:eruby_engine])
44
+ end
@@ -0,0 +1,24 @@
1
+ def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
+
3
+ try_require 'rubygems'
4
+
5
+ try_require 'haml'
6
+
7
+ class String
8
+
9
+ # Converts the string using Haml
10
+ def haml(params={})
11
+ options = (params[:haml_options] || {})
12
+ options[:locals] = params[:assigns] unless params[:assigns].nil?
13
+ Haml::Engine.new(self, options).to_html
14
+ rescue NameError
15
+ $stderr.puts 'ERROR: String#haml failed (Haml not installed?)' unless $quiet
16
+ exit
17
+ end
18
+
19
+ end
20
+
21
+ register_filter 'haml' do |page, pages, config|
22
+ assigns = { :page => page, :pages => pages }
23
+ page.content.haml(:assigns => assigns, :haml_options => page[:haml_options])
24
+ end
@@ -0,0 +1,51 @@
1
+ def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
+
3
+ try_require 'rubygems'
4
+
5
+ try_require 'liquid'
6
+
7
+ class String
8
+
9
+ # Converts the string using Liquid
10
+ def liquid(params={})
11
+ Liquid::Template.parse(self).render((params[:assigns] || {}).stringify_keys)
12
+ rescue NameError
13
+ $stderr.puts 'ERROR: String#liquid failed (Liquid not installed?)' unless $quiet
14
+ exit
15
+ end
16
+
17
+ end
18
+
19
+ begin
20
+ class Nanoc::LiquidRenderTag < ::Liquid::Tag
21
+ Syntax = /(['"])([^'"]+)\1/
22
+
23
+ def initialize(markup, tokens)
24
+ if markup =~ Syntax
25
+ @layout_name = $2
26
+ else
27
+ raise SyntaxError.new("Error in tag 'render' - Valid syntax: render '[layout]'")
28
+ end
29
+
30
+ super
31
+ end
32
+
33
+ def parse(tokens)
34
+ end
35
+
36
+ def render(context)
37
+ source = File.read('layouts/' + @layout_name + '.liquid')
38
+ partial = Liquid::Template.parse(source)
39
+
40
+ partial.render(context)
41
+ end
42
+ end
43
+
44
+ Liquid::Template.register_tag('render', Nanoc::LiquidRenderTag)
45
+ rescue NameError
46
+ end
47
+
48
+ register_filter 'liquid' do |page, pages, config|
49
+ assigns = { :page => page, :pages => pages }
50
+ page.content.liquid(:assigns => assigns)
51
+ end
@@ -0,0 +1,25 @@
1
+ def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
+
3
+ try_require 'rubygems'
4
+
5
+ require 'erb'
6
+
7
+ try_require 'markaby'
8
+
9
+ class String
10
+
11
+ # Converts the string using Markaby
12
+ # TODO perhaps add support for helpers
13
+ def markaby(params={})
14
+ Markaby::Builder.new((params[:assigns] || {})).instance_eval(self).to_s
15
+ rescue NameError
16
+ $stderr.puts 'ERROR: String#markaby failed (Markaby not installed?)' unless $quiet
17
+ exit
18
+ end
19
+
20
+ end
21
+
22
+ register_filter 'markaby' do |page, pages, config|
23
+ assigns = { :page => page, :pages => pages }
24
+ page.content.markaby(:assigns => assigns)
25
+ end
@@ -0,0 +1,21 @@
1
+ def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
+
3
+ try_require 'rubygems'
4
+
5
+ try_require 'bluecloth'
6
+
7
+ class String
8
+
9
+ # Converts the string to HTML using BlueCloth/Markdown.
10
+ def markdown
11
+ BlueCloth.new(self).to_html
12
+ rescue NameError
13
+ $stderr.puts 'ERROR: String#markdown failed: BlueCloth not installed' unless $quiet
14
+ exit
15
+ end
16
+
17
+ end
18
+
19
+ register_filter 'markdown', 'bluecloth' do |page, pages, config|
20
+ page.content.markdown
21
+ end
@@ -0,0 +1,19 @@
1
+ def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
+
3
+ try_require 'rubygems'
4
+
5
+ try_require 'rdoc/markup/simple_markup'
6
+ try_require 'rdoc/markup/simple_markup/to_html'
7
+
8
+ class String
9
+
10
+ # Converts the string using RDoc
11
+ def rdoc
12
+ SM::SimpleMarkup.new.convert(self, SM::ToHtml.new)
13
+ end
14
+
15
+ end
16
+
17
+ register_filter 'rdoc' do |page, pages, config|
18
+ page.content.rdoc
19
+ end
@@ -0,0 +1,18 @@
1
+ def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
+
3
+ try_require 'rubygems'
4
+
5
+ try_require 'haml'
6
+
7
+ class String
8
+
9
+ # Converts the string using Sass
10
+ def sass
11
+ Sass::Engine.new(self).render
12
+ end
13
+
14
+ end
15
+
16
+ register_filter 'sass' do |page, pages, config|
17
+ page.content.sass
18
+ end
@@ -0,0 +1,21 @@
1
+ def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
+
3
+ try_require 'rubygems'
4
+
5
+ try_require 'rubypants'
6
+
7
+ class String
8
+
9
+ # Converts the string using RubyPants/SmartyPants
10
+ def smartypants
11
+ RubyPants.new(self).to_html
12
+ rescue NameError
13
+ $stderr.puts 'ERROR: String#smartypants failed (RubyPants not installed?)' unless $quiet
14
+ exit
15
+ end
16
+
17
+ end
18
+
19
+ register_filter 'smartypants', 'rubypants' do |page, pages, config|
20
+ page.content.smartypants
21
+ end
@@ -0,0 +1,21 @@
1
+ def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
+
3
+ try_require 'rubygems'
4
+
5
+ try_require 'redcloth'
6
+
7
+ class String
8
+
9
+ # Converts the string using RedCloth/Textile
10
+ def textile
11
+ RedCloth.new(self).to_html
12
+ rescue NameError
13
+ $stderr.puts 'ERROR: String#textile failed (RedCloth not installed?)' unless $quiet
14
+ exit
15
+ end
16
+
17
+ end
18
+
19
+ register_filter 'textile', 'redcloth' do |page, pages, config|
20
+ page.content.textile
21
+ end
data/lib/nanoc/page.rb ADDED
@@ -0,0 +1,147 @@
1
+ def try_require(s) ; begin ; require s ; rescue LoadError ; end ; end
2
+
3
+ try_require 'rubygems'
4
+ try_require 'liquid'
5
+
6
+ module Nanoc
7
+
8
+ # Page drop
9
+
10
+ begin
11
+ class PageDrop < ::Liquid::Drop
12
+ def initialize(page)
13
+ @page = page
14
+ end
15
+
16
+ def before_method(name)
17
+ name == 'content' ? @page.content : @page.attributes[name.to_sym]
18
+ end
19
+ end
20
+ rescue NameError
21
+ class PageDrop
22
+ def initialize(*args)
23
+ $stderr.puts 'ERROR: Liquid not installed; cannot use Liquid in layouts.'
24
+ exit
25
+ end
26
+ end
27
+ end
28
+
29
+ # Page proxy
30
+
31
+ class PageProxy
32
+ def initialize(page, params={})
33
+ @page = page
34
+ @do_compile = (params[:compile] != false)
35
+ end
36
+
37
+ def [](key)
38
+ if key.to_sym == :content and @do_compile
39
+ @page.content
40
+ else
41
+ if key.to_s.starts_with?('_')
42
+ nil
43
+ elsif key.to_s.ends_with?('?')
44
+ @page.attributes[key.to_s[0..-2].to_sym]
45
+ else
46
+ @page.attributes[key]
47
+ end
48
+ end
49
+ end
50
+
51
+ def method_missing(method, *args)
52
+ self[method]
53
+ end
54
+ end
55
+
56
+ # Page
57
+
58
+ class Page
59
+
60
+ def initialize(hash={})
61
+ @attributes = hash
62
+ end
63
+
64
+ def attributes
65
+ @attributes
66
+ end
67
+
68
+ def content
69
+ compile
70
+ @attributes[:content]
71
+ end
72
+
73
+ # Proxy/Liquid support
74
+
75
+ def to_proxy(params={})
76
+ PageProxy.new(self, :compile => params[:compile])
77
+ end
78
+
79
+ def to_liquid
80
+ PageDrop.new(self)
81
+ end
82
+
83
+ # Compiling
84
+
85
+ def self.compile(pages)
86
+ @@compilation_stack = []
87
+ @@pages = pages
88
+
89
+ # Compile all pages
90
+ pages.each { |page| page.compile }
91
+ end
92
+
93
+ def compile
94
+ # Check for recursive call
95
+ if @@compilation_stack.include?(self)
96
+ # Print compilation stack
97
+ unless $quiet
98
+ $stderr.puts 'ERROR: Recursive call to page content.'
99
+ print_compilation_stack
100
+ end
101
+
102
+ exit
103
+ # Compile if not yet compiled
104
+ elsif @attributes[:content].nil?
105
+ @@compilation_stack.pushing(self) do
106
+ # Read page
107
+ content = File.read(@attributes[:_content_filename])
108
+
109
+ begin
110
+ # Get params
111
+ page = self.to_proxy(:compile => false)
112
+ pages = @@pages.map { |p| p.to_proxy }
113
+ config = $nanoc_compiler.config
114
+
115
+ # Filter page
116
+ @attributes[:content] = content
117
+ @attributes[:filters].each do |filter_name|
118
+ filter = $nanoc_compiler.filter_named(filter_name)
119
+ if filter.nil?
120
+ $stderr.puts 'WARNING: Unknown filter: ' + filter_name unless $quiet
121
+ else
122
+ @attributes[:content] = filter.call(page, pages, config)
123
+ end
124
+ end
125
+ rescue Exception => exception
126
+ handle_exception(exception, "compiling page '#{@attributes[:_content_filename]}'")
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ def print_compilation_stack
133
+ # Determine relevant part of compilation stack
134
+ stack_begin = @@compilation_stack.index(self)
135
+ stack_end = @@compilation_stack.size
136
+ relevant_stack_part = @@compilation_stack.last(stack_end - stack_begin)
137
+
138
+ # Print relevant part of compilation stack
139
+ $stderr.puts 'Page compilation stack:'
140
+ relevant_stack_part.each_with_index do |page, i|
141
+ $stderr.puts "#{i} #{page.attributes[:_content_filename]}"
142
+ end
143
+ end
144
+
145
+ end
146
+
147
+ end