nanoc3 3.1.8 → 3.1.9
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/NEWS.md +7 -1
- data/README.md +1 -0
- data/lib/nanoc3.rb +1 -1
- data/lib/nanoc3/filters/colorize_syntax.rb +12 -0
- data/lib/nanoc3/filters/less.rb +49 -6
- data/lib/nanoc3/filters/sass.rb +56 -62
- data/test/filters/test_colorize_syntax.rb +28 -0
- data/test/filters/test_less.rb +60 -1
- data/test/filters/test_sass.rb +66 -1
- metadata +2 -4
- data/lib/nanoc3/filters/sass.rb.orig +0 -75
- data/test/filters/test_sass.rb.orig +0 -103
data/NEWS.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
# nanoc news
|
2
2
|
|
3
|
-
## 3.1.
|
3
|
+
## 3.1.9 (2011-06-30)
|
4
|
+
|
5
|
+
* Really fixed dependency generation between Sass partials this time
|
6
|
+
* Updated Less filter to 2.0
|
7
|
+
* Made colorize_syntax filter throw an error if pygmentize is not available
|
8
|
+
|
9
|
+
## 3.1.8 (2011-06-25)
|
4
10
|
|
5
11
|
* Made link validator accept https: URLs
|
6
12
|
* Fixed erronous handling of layouts with names ending in index
|
data/README.md
CHANGED
data/lib/nanoc3.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require 'open3'
|
4
|
+
|
3
5
|
module Nanoc3::Filters
|
4
6
|
class ColorizeSyntax < Nanoc3::Filter
|
5
7
|
|
@@ -36,6 +38,9 @@ module Nanoc3::Filters
|
|
36
38
|
#
|
37
39
|
# @param [String] content The content to filter
|
38
40
|
#
|
41
|
+
# @option params [Symbol] :syntax (:html) The syntax to use, which can be
|
42
|
+
# `:html`, `:xml` or `:xhtml`, the latter two being the same.
|
43
|
+
#
|
39
44
|
# @option params [Hash] :colorizers (DEFAULT_COLORIZER) A hash containing
|
40
45
|
# a mapping of programming languages (symbols, not strings) onto
|
41
46
|
# colorizers (symbols).
|
@@ -90,6 +95,8 @@ module Nanoc3::Filters
|
|
90
95
|
end
|
91
96
|
|
92
97
|
def pygmentize(code, language, params={})
|
98
|
+
check_availability('pygmentize --V')
|
99
|
+
|
93
100
|
IO.popen("pygmentize -l #{language} -f html", "r+") do |io|
|
94
101
|
io.write(code)
|
95
102
|
io.close_write
|
@@ -100,5 +107,10 @@ module Nanoc3::Filters
|
|
100
107
|
end
|
101
108
|
end
|
102
109
|
|
110
|
+
def check_availability(cmd)
|
111
|
+
# Will raise on error
|
112
|
+
Open3.popen3('highlight --version') { |stdin, stdout, stderr| }
|
113
|
+
end
|
114
|
+
|
103
115
|
end
|
104
116
|
end
|
data/lib/nanoc3/filters/less.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require 'less'
|
4
|
+
|
3
5
|
module Nanoc3::Filters
|
4
6
|
class Less < Nanoc3::Filter
|
5
7
|
|
@@ -10,15 +12,56 @@ module Nanoc3::Filters
|
|
10
12
|
#
|
11
13
|
# @return [String] The filtered content
|
12
14
|
def run(content, params={})
|
13
|
-
|
15
|
+
# Find imports (hacky)
|
16
|
+
imports = []
|
17
|
+
imports.concat(content.scan(/^@import\s+(["'])([^\1]+?)\1;/))
|
18
|
+
imports.concat(content.scan(/^@import\s+url\((["']?)([^)]+?)\1\);/))
|
19
|
+
imported_filenames = imports.map do |i|
|
20
|
+
i[1].match(/\.(less|css)$/) ? i[1] : i[1] + '.less'
|
21
|
+
end
|
22
|
+
|
23
|
+
# Convert to items
|
24
|
+
imported_items = imported_filenames.map do |filename|
|
25
|
+
# Find directory for this item
|
26
|
+
current_dir_pathname = Pathname.new(@item[:content_filename]).dirname.realpath
|
27
|
+
|
28
|
+
# Find absolute pathname for imported item
|
29
|
+
imported_pathname = Pathname.new(filename)
|
30
|
+
if imported_pathname.relative?
|
31
|
+
imported_pathname = current_dir_pathname + imported_pathname
|
32
|
+
end
|
33
|
+
next if !imported_pathname.exist?
|
34
|
+
imported_filename = imported_pathname.realpath
|
35
|
+
|
36
|
+
# Find matching item
|
37
|
+
@items.find do |i|
|
38
|
+
next if i[:content_filename].nil?
|
39
|
+
Pathname.new(i[:content_filename]).realpath == imported_filename
|
40
|
+
end
|
41
|
+
end.compact
|
42
|
+
|
43
|
+
# Create dependencies
|
44
|
+
depend_on(imported_items)
|
14
45
|
|
15
46
|
# Add filename to load path
|
16
|
-
|
47
|
+
paths = [ File.dirname(@item[:content_filename]) ]
|
48
|
+
parser = ::Less::Parser.new(:paths => paths)
|
49
|
+
parser.parse(content).to_css
|
50
|
+
end
|
51
|
+
|
52
|
+
# @todo Remove me in nanoc 3.2.x
|
53
|
+
def depend_on(items)
|
54
|
+
# Notify
|
55
|
+
items.each do |item|
|
56
|
+
Nanoc3::NotificationCenter.post(:visit_started, item)
|
57
|
+
Nanoc3::NotificationCenter.post(:visit_ended, item)
|
58
|
+
end
|
17
59
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
60
|
+
# Raise unmet dependency error if necessary
|
61
|
+
items.each do |item|
|
62
|
+
rep = item.reps.find { |r| !r.compiled? }
|
63
|
+
raise Nanoc3::Errors::UnmetDependency.new(rep) if rep
|
64
|
+
end
|
22
65
|
end
|
23
66
|
|
24
67
|
end
|
data/lib/nanoc3/filters/sass.rb
CHANGED
@@ -1,8 +1,38 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require 'sass'
|
4
|
+
require 'set'
|
5
|
+
|
3
6
|
module Nanoc3::Filters
|
4
7
|
class Sass < Nanoc3::Filter
|
5
8
|
|
9
|
+
class << self
|
10
|
+
# The current filter. This is definitely going to bite me if I ever get
|
11
|
+
# to multithreading nanoc.
|
12
|
+
attr_accessor :current
|
13
|
+
end
|
14
|
+
|
15
|
+
# Essentially the {Sass::Importers::Filesystem} but registering each
|
16
|
+
# import file path.
|
17
|
+
class SassFilesystemImporter < ::Sass::Importers::Filesystem
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def _find(dir, name, options)
|
22
|
+
full_filename, syntax = find_real_file(dir, name)
|
23
|
+
return unless full_filename && File.readable?(full_filename)
|
24
|
+
|
25
|
+
filter = Nanoc3::Filters::Sass.current
|
26
|
+
item = filter.imported_filename_to_item(full_filename)
|
27
|
+
filter.depend_on([ item ]) unless item.nil?
|
28
|
+
|
29
|
+
options[:syntax] = syntax
|
30
|
+
options[:filename] = full_filename
|
31
|
+
options[:importer] = self
|
32
|
+
::Sass::Engine.new(File.read(full_filename), options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
6
36
|
# Runs the content through [Sass](http://sass-lang.com/).
|
7
37
|
# Parameters passed to this filter will be passed on to Sass.
|
8
38
|
#
|
@@ -10,77 +40,41 @@ module Nanoc3::Filters
|
|
10
40
|
#
|
11
41
|
# @return [String] The filtered content
|
12
42
|
def run(content, params={})
|
13
|
-
|
14
|
-
|
15
|
-
# Add imported_filename read accessor to ImportNode
|
16
|
-
# … but… but… nex3 said I could monkey patch it! :(
|
17
|
-
methods = ::Sass::Tree::ImportNode.instance_methods
|
18
|
-
if !methods.include?(:import_filename) && !methods.include?('import_filename')
|
19
|
-
::Sass::Tree::ImportNode.send(:attr_reader, :imported_filename)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Get options
|
43
|
+
# Build options
|
23
44
|
options = params.dup
|
24
|
-
sass_filename = options[:filename] ||
|
45
|
+
sass_filename = options[:filename] ||
|
46
|
+
(@item && @item[:content_filename])
|
25
47
|
options[:filename] ||= sass_filename
|
48
|
+
options[:filesystem_importer] ||=
|
49
|
+
Nanoc3::Filters::Sass::SassFilesystemImporter
|
26
50
|
|
27
|
-
#
|
51
|
+
# Render
|
28
52
|
engine = ::Sass::Engine.new(content, options)
|
53
|
+
self.class.current = self
|
54
|
+
engine.render
|
55
|
+
end
|
29
56
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
# Get an unprocessed node
|
36
|
-
node = unprocessed_nodes.each { |n| break n }
|
37
|
-
unprocessed_nodes.delete(node)
|
38
|
-
|
39
|
-
# Add to list of import nodes if necessary
|
40
|
-
imported_nodes << node if node.is_a?(::Sass::Tree::ImportNode)
|
41
|
-
|
42
|
-
# Mark children of this node for processing
|
43
|
-
node.children.each { |c| unprocessed_nodes << c }
|
57
|
+
def imported_filename_to_item(filename)
|
58
|
+
path = Pathname.new(filename).realpath
|
59
|
+
@items.find do |i|
|
60
|
+
next if i[:content_filename].nil?
|
61
|
+
Pathname.new(i[:content_filename]).realpath == path
|
44
62
|
end
|
63
|
+
end
|
45
64
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
imported_items = imported_filenames.map do |filename|
|
53
|
-
# Find directory for this item
|
54
|
-
current_dir_pathname = Pathname.new(@item[:content_filename]).dirname.realpath
|
55
|
-
|
56
|
-
# Find absolute pathname for imported item
|
57
|
-
imported_pathname = Pathname.new(filename)
|
58
|
-
if imported_pathname.relative?
|
59
|
-
imported_pathname = current_dir_pathname + imported_pathname
|
60
|
-
end
|
61
|
-
next if !imported_pathname.exist?
|
62
|
-
imported_filename = imported_pathname.realpath
|
63
|
-
|
64
|
-
# Find matching item
|
65
|
-
@items.find do |i|
|
66
|
-
next if i[:content_filename].nil?
|
67
|
-
Pathname.new(i[:content_filename]).realpath == imported_filename
|
68
|
-
end
|
69
|
-
end.compact
|
70
|
-
|
71
|
-
# Require compilation of each item
|
72
|
-
imported_items.each do |i|
|
73
|
-
# Notify
|
74
|
-
Nanoc3::NotificationCenter.post(:visit_started, i)
|
75
|
-
Nanoc3::NotificationCenter.post(:visit_ended, i)
|
76
|
-
|
77
|
-
# Raise unmet dependency error if item is not yet compiled
|
78
|
-
any_uncompiled_rep = i.reps.find { |r| !r.compiled? }
|
79
|
-
raise Nanoc3::Errors::UnmetDependency.new(any_uncompiled_rep) if any_uncompiled_rep
|
65
|
+
# @todo Remove me in nanoc 3.2.x
|
66
|
+
def depend_on(items)
|
67
|
+
# Notify
|
68
|
+
items.each do |item|
|
69
|
+
Nanoc3::NotificationCenter.post(:visit_started, item)
|
70
|
+
Nanoc3::NotificationCenter.post(:visit_ended, item)
|
80
71
|
end
|
81
72
|
|
82
|
-
#
|
83
|
-
|
73
|
+
# Raise unmet dependency error if necessary
|
74
|
+
items.each do |item|
|
75
|
+
rep = item.reps.find { |r| !r.compiled? }
|
76
|
+
raise Nanoc3::Errors::UnmetDependency.new(rep) if rep
|
77
|
+
end
|
84
78
|
end
|
85
79
|
|
86
80
|
end
|
@@ -53,4 +53,32 @@ class Nanoc3::Filters::ColorizeSyntaxTest < MiniTest::Unit::TestCase
|
|
53
53
|
assert_match(expected_output, actual_output)
|
54
54
|
end
|
55
55
|
|
56
|
+
def test_colorize_syntax_with_missing_executables
|
57
|
+
if_have 'nokogiri' do
|
58
|
+
begin
|
59
|
+
original_path = ENV['PATH']
|
60
|
+
ENV['PATH'] = './blooblooblah'
|
61
|
+
|
62
|
+
# Create filter
|
63
|
+
filter = ::Nanoc3::Filters::ColorizeSyntax.new
|
64
|
+
|
65
|
+
# Get input and expected output
|
66
|
+
input = '<pre><code class="language-ruby">puts "foo"</code></pre>'
|
67
|
+
|
68
|
+
# Run filter
|
69
|
+
begin
|
70
|
+
input = '<pre><code class="language-ruby">puts "foo"</code></pre>'
|
71
|
+
actual_output = filter.run(
|
72
|
+
input,
|
73
|
+
:colorizers => { :ruby => :pygmentize })
|
74
|
+
flunk "expected colorizer to raise if no executable is available"
|
75
|
+
rescue => e
|
76
|
+
assert_match /No such file or directory/, e.message
|
77
|
+
end
|
78
|
+
ensure
|
79
|
+
ENV['PATH'] = original_path
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
56
84
|
end
|
data/test/filters/test_less.rb
CHANGED
@@ -45,10 +45,11 @@ class Nanoc3::Filters::LessTest < MiniTest::Unit::TestCase
|
|
45
45
|
File.open('content/foo/bar/imported_file.less', 'w') { |io| io.write('p { color: red; }') }
|
46
46
|
|
47
47
|
# Create item
|
48
|
+
File.open('content/foo/bar.txt', 'w') { |io| io.write('meh') }
|
48
49
|
@item = Nanoc3::Item.new("blah", { :content_filename => 'content/foo/bar.txt' }, '/foo/bar/')
|
49
50
|
|
50
51
|
# Create filter
|
51
|
-
filter = ::Nanoc3::Filters::Less.new(:item => @item)
|
52
|
+
filter = ::Nanoc3::Filters::Less.new(:item => @item, :items => [ @item ])
|
52
53
|
|
53
54
|
# Run filter
|
54
55
|
result = filter.run('@import "bar/imported_file.less";')
|
@@ -56,4 +57,62 @@ class Nanoc3::Filters::LessTest < MiniTest::Unit::TestCase
|
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
60
|
+
def test_recompile_includes
|
61
|
+
if_have 'less' do
|
62
|
+
Nanoc3::CLI::Base.new.run([ 'create_site', 'bar' ])
|
63
|
+
FileUtils.cd('bar') do
|
64
|
+
# Create two less files
|
65
|
+
Dir['content/*'].each { |i| FileUtils.rm(i) }
|
66
|
+
File.open('content/a.less', 'w') do |io|
|
67
|
+
io.write('@import "b.less";')
|
68
|
+
end
|
69
|
+
File.open('content/b.less', 'w') do |io|
|
70
|
+
io.write("p { color: red; }")
|
71
|
+
end
|
72
|
+
|
73
|
+
# Update rules
|
74
|
+
File.open('Rules', 'w') do |io|
|
75
|
+
io.write "compile '*' do\n"
|
76
|
+
io.write " filter :less\n"
|
77
|
+
io.write "end\n"
|
78
|
+
io.write "\n"
|
79
|
+
io.write "route '/a/' do\n"
|
80
|
+
io.write " item.identifier.chop + '.css'\n"
|
81
|
+
io.write "end\n"
|
82
|
+
io.write "\n"
|
83
|
+
io.write "route '/b/' do\n"
|
84
|
+
io.write " nil\n"
|
85
|
+
io.write "end\n"
|
86
|
+
end
|
87
|
+
|
88
|
+
# Compile
|
89
|
+
site = Nanoc3::Site.new('.')
|
90
|
+
site.load_data
|
91
|
+
site.compiler.run
|
92
|
+
|
93
|
+
# Check
|
94
|
+
assert Dir['output/*'].size == 1
|
95
|
+
assert File.file?('output/a.css')
|
96
|
+
refute File.file?('output/b.css')
|
97
|
+
assert_match /^p\s*\{\s*color:\s*red;?\s*\}/, File.read('output/a.css')
|
98
|
+
|
99
|
+
# Update included file
|
100
|
+
File.open('content/b.less', 'w') do |io|
|
101
|
+
io.write("p { color: blue; }")
|
102
|
+
end
|
103
|
+
|
104
|
+
# Recompile
|
105
|
+
site = Nanoc3::Site.new('.')
|
106
|
+
site.load_data
|
107
|
+
site.compiler.run
|
108
|
+
|
109
|
+
# Recheck
|
110
|
+
assert Dir['output/*'].size == 1
|
111
|
+
assert File.file?('output/a.css')
|
112
|
+
refute File.file?('output/b.css')
|
113
|
+
assert_match /^p\s*\{\s*color:\s*blue;?\s*\}/, File.read('output/a.css')
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
59
118
|
end
|
data/test/filters/test_sass.rb
CHANGED
@@ -159,10 +159,75 @@ class Nanoc3::Filters::SassTest < MiniTest::Unit::TestCase
|
|
159
159
|
end
|
160
160
|
end
|
161
161
|
|
162
|
+
def test_recompile_includes_with_underscore_without_extension
|
163
|
+
if_have 'sass' do
|
164
|
+
# Create site
|
165
|
+
Nanoc3::CLI::Base.new.run([ 'create_site', 'bar' ])
|
166
|
+
FileUtils.cd('bar') do
|
167
|
+
# Create two Sass files
|
168
|
+
Dir['content/*'].each { |i| FileUtils.rm(i) }
|
169
|
+
File.open('content/a.sass', 'w') do |io|
|
170
|
+
io.write('@import b')
|
171
|
+
end
|
172
|
+
File.open('content/_b.sass', 'w') do |io|
|
173
|
+
io.write("p\n color: red")
|
174
|
+
end
|
175
|
+
|
176
|
+
# Update rules
|
177
|
+
File.open('Rules', 'w') do |io|
|
178
|
+
io.write "compile '*' do\n"
|
179
|
+
io.write " filter :sass\n"
|
180
|
+
io.write "end\n"
|
181
|
+
io.write "\n"
|
182
|
+
io.write "route '/a/' do\n"
|
183
|
+
io.write " item.identifier.chop + '.css'\n"
|
184
|
+
io.write "end\n"
|
185
|
+
io.write "\n"
|
186
|
+
io.write "route '/_b/' do\n"
|
187
|
+
io.write " nil\n"
|
188
|
+
io.write "end\n"
|
189
|
+
end
|
190
|
+
|
191
|
+
# Compile
|
192
|
+
site = Nanoc3::Site.new('.')
|
193
|
+
site.load_data
|
194
|
+
site.compiler.run
|
195
|
+
|
196
|
+
# Check
|
197
|
+
assert Dir['output/*'].size == 1
|
198
|
+
assert File.file?('output/a.css')
|
199
|
+
refute File.file?('output/b.css')
|
200
|
+
assert_match /^p\s*{\s*color:\s*red;?\s*}/, File.read('output/a.css')
|
201
|
+
|
202
|
+
# Update included file
|
203
|
+
File.open('content/_b.sass', 'w') do |io|
|
204
|
+
io.write("p\n color: blue")
|
205
|
+
end
|
206
|
+
|
207
|
+
# Recompile
|
208
|
+
site = Nanoc3::Site.new('.')
|
209
|
+
site.load_data
|
210
|
+
site.compiler.run
|
211
|
+
|
212
|
+
# Recheck
|
213
|
+
assert Dir['output/*'].size == 1
|
214
|
+
assert File.file?('output/a.css')
|
215
|
+
refute File.file?('output/b.css')
|
216
|
+
assert_match /^p\s*{\s*color:\s*blue;?\s*}/, File.read('output/a.css')
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
162
221
|
private
|
163
222
|
|
164
223
|
def create_filter(params={})
|
165
|
-
|
224
|
+
FileUtils.mkdir_p('content')
|
225
|
+
File.open('content/xyzzy.sass', 'w') { |io| io.write('p\n color: green')}
|
226
|
+
|
227
|
+
items = [ Nanoc3::Item.new(
|
228
|
+
'blah',
|
229
|
+
{ :content_filename => 'content/xyzzy.sass' },
|
230
|
+
'/blah/') ]
|
166
231
|
params = { :item => items[0], :items => items }.merge(params)
|
167
232
|
::Nanoc3::Filters::Sass.new(params)
|
168
233
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: nanoc3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 3.1.
|
5
|
+
version: 3.1.9
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Denis Defreyne
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-06-
|
13
|
+
date: 2011-06-30 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: cri
|
@@ -122,7 +122,6 @@ files:
|
|
122
122
|
- lib/nanoc3/filters/relativize_paths.rb
|
123
123
|
- lib/nanoc3/filters/rubypants.rb
|
124
124
|
- lib/nanoc3/filters/sass.rb
|
125
|
-
- lib/nanoc3/filters/sass.rb.orig
|
126
125
|
- lib/nanoc3/filters.rb
|
127
126
|
- lib/nanoc3/helpers/blogging.rb
|
128
127
|
- lib/nanoc3/helpers/breadcrumbs.rb
|
@@ -200,7 +199,6 @@ files:
|
|
200
199
|
- test/filters/test_relativize_paths.rb
|
201
200
|
- test/filters/test_rubypants.rb
|
202
201
|
- test/filters/test_sass.rb
|
203
|
-
- test/filters/test_sass.rb.orig
|
204
202
|
- test/gem_loader.rb
|
205
203
|
- test/helper.rb
|
206
204
|
- test/helpers/test_blogging.rb
|
@@ -1,75 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Nanoc3::Filters
|
4
|
-
class Sass < Nanoc3::Filter
|
5
|
-
|
6
|
-
# Runs the content through [Sass](http://sass-lang.com/).
|
7
|
-
# Parameters passed to this filter will be passed on to Sass.
|
8
|
-
#
|
9
|
-
# @param [String] content The content to filter
|
10
|
-
#
|
11
|
-
# @return [String] The filtered content
|
12
|
-
def run(content, params={})
|
13
|
-
require 'sass'
|
14
|
-
|
15
|
-
# Add imported_filename read accessor to ImportNode
|
16
|
-
# … but… but… nex3 said I could monkey patch it! :(
|
17
|
-
methods = ::Sass::Tree::ImportNode.instance_methods
|
18
|
-
if !methods.include?(:import_filename) && !methods.include?('import_filename')
|
19
|
-
::Sass::Tree::ImportNode.send(:attr_reader, :imported_filename)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Get options
|
23
|
-
options = params.dup
|
24
|
-
sass_filename = options[:filename] || (@item && @item[:content_filename])
|
25
|
-
options[:filename] ||= sass_filename
|
26
|
-
|
27
|
-
# Build engine
|
28
|
-
engine = ::Sass::Engine.new(content, options)
|
29
|
-
|
30
|
-
# Get import nodes
|
31
|
-
require 'set'
|
32
|
-
imported_nodes = []
|
33
|
-
unprocessed_nodes = Set.new([ engine.to_tree ])
|
34
|
-
until unprocessed_nodes.empty?
|
35
|
-
# Get an unprocessed node
|
36
|
-
node = unprocessed_nodes.each { |n| break n }
|
37
|
-
unprocessed_nodes.delete(node)
|
38
|
-
|
39
|
-
# Add to list of import nodes if necessary
|
40
|
-
imported_nodes << node if node.is_a?(::Sass::Tree::ImportNode)
|
41
|
-
|
42
|
-
# Mark children of this node for processing
|
43
|
-
node.children.each { |c| unprocessed_nodes << c }
|
44
|
-
end
|
45
|
-
|
46
|
-
# Get import paths
|
47
|
-
import_paths = (options[:load_paths] || []).dup
|
48
|
-
import_paths.unshift(File.dirname(sass_filename)) if sass_filename
|
49
|
-
imported_filenames = imported_nodes.map { |node| node.imported_filename }
|
50
|
-
|
51
|
-
# Convert to items
|
52
|
-
imported_items = imported_filenames.map do |filename|
|
53
|
-
pathname = Pathname.new(filename)
|
54
|
-
next unless pathname.file?
|
55
|
-
normalized_filename = pathname.realpath
|
56
|
-
@items.find { |i| i[:content_filename] && Pathname.new(i[:content_filename]).realpath == normalized_filename }
|
57
|
-
end.compact
|
58
|
-
|
59
|
-
# Require compilation of each item
|
60
|
-
imported_items.each do |item|
|
61
|
-
# Notify
|
62
|
-
Nanoc3::NotificationCenter.post(:visit_started, item)
|
63
|
-
Nanoc3::NotificationCenter.post(:visit_ended, item)
|
64
|
-
|
65
|
-
# Raise unmet dependency error if item is not yet compiled
|
66
|
-
any_uncompiled_rep = item.reps.find { |r| !r.compiled? }
|
67
|
-
raise Nanoc3::Errors::UnmetDependency.new(any_uncompiled_rep) if any_uncompiled_rep
|
68
|
-
end
|
69
|
-
|
70
|
-
# Done
|
71
|
-
engine.render
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
75
|
-
end
|
@@ -1,103 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'test/helper'
|
4
|
-
|
5
|
-
class Nanoc3::Filters::SassTest < MiniTest::Unit::TestCase
|
6
|
-
|
7
|
-
include Nanoc3::TestHelpers
|
8
|
-
|
9
|
-
def test_filter
|
10
|
-
if_have 'sass' do
|
11
|
-
# Get filter
|
12
|
-
filter = ::Nanoc3::Filters::Sass.new({ :foo => 'bar' })
|
13
|
-
|
14
|
-
# Run filter
|
15
|
-
result = filter.run(".foo #bar\n color: #f00")
|
16
|
-
assert_match(/.foo\s+#bar\s*\{\s*color:\s+(red|#f00);?\s*\}/, result)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_filter_with_params
|
21
|
-
if_have 'sass' do
|
22
|
-
# Create filter
|
23
|
-
filter = ::Nanoc3::Filters::Sass.new({ :foo => 'bar' })
|
24
|
-
|
25
|
-
# Check with compact
|
26
|
-
result = filter.run(".foo #bar\n color: #f00", :style => 'compact')
|
27
|
-
assert_match(/^\.foo #bar[\s\n]*\{[\s\n]*color:\s*(red|#f00);?[\s\n]*\}/m, result)
|
28
|
-
|
29
|
-
# Check with compressed
|
30
|
-
result = filter.run(".foo #bar\n color: #f00", :style => 'compressed')
|
31
|
-
assert_match(/^\.foo #bar[\s\n]*\{[\s\n]*color:\s*(red|#f00);?[\s\n]*\}/m, result)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_filter_error
|
36
|
-
if_have 'sass' do
|
37
|
-
# Create filter
|
38
|
-
filter = ::Nanoc3::Filters::Sass.new({ :foo => 'bar' })
|
39
|
-
|
40
|
-
# Run filter
|
41
|
-
raised = false
|
42
|
-
begin
|
43
|
-
filter.run('$*#&!@($')
|
44
|
-
rescue Sass::SyntaxError => e
|
45
|
-
assert_match ':1', e.backtrace[0]
|
46
|
-
raised = true
|
47
|
-
end
|
48
|
-
assert raised
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_filter_can_import_external_files
|
53
|
-
if_have 'sass' do
|
54
|
-
# Create filter
|
55
|
-
filter = ::Nanoc3::Filters::Sass.new(:items => [])
|
56
|
-
|
57
|
-
# Create sample file
|
58
|
-
File.open('moo.sass', 'w') { |io| io.write "body\n color: red" }
|
59
|
-
|
60
|
-
# Run filter
|
61
|
-
filter.run('@import moo')
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def test_filter_can_import_relative_files
|
66
|
-
if_have 'sass' do
|
67
|
-
# Create filter
|
68
|
-
filter = ::Nanoc3::Filters::Sass.new(:items => [])
|
69
|
-
|
70
|
-
# Create sample file
|
71
|
-
File.open('moo.sass', 'w') { |io| io.write %Q{@import subdir/relative} }
|
72
|
-
FileUtils.mkdir_p("subdir")
|
73
|
-
File.open('subdir/relative.sass', 'w') { |io| io.write "body\n color: red" }
|
74
|
-
|
75
|
-
# Run filter
|
76
|
-
filter.run('@import moo')
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def test_filter_will_skip_items_without_filename
|
81
|
-
if_have 'sass' do
|
82
|
-
# Create filter
|
83
|
-
filter = ::Nanoc3::Filters::Sass.new(:items => [ Nanoc3::Item.new('blah', {}, '/blah/') ])
|
84
|
-
|
85
|
-
# Create sample file
|
86
|
-
File.open('moo.sass', 'w') { |io| io.write "body\n color: red" }
|
87
|
-
|
88
|
-
# Run filter
|
89
|
-
filter.run('@import moo')
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def test_css_imports_work
|
94
|
-
if_have 'sass' do
|
95
|
-
# Create filter
|
96
|
-
filter = ::Nanoc3::Filters::Sass.new(:items => [ Nanoc3::Item.new('blah', {}, '/blah/') ])
|
97
|
-
|
98
|
-
# Run filter
|
99
|
-
filter.run('@import moo.css')
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
end
|