nanoc3 3.1.8 → 3.1.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|