benoit 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) hide show
  1. data/.gitignore +4 -0
  2. data/.gitmodules +3 -0
  3. data/.rspec +1 -0
  4. data/.rspec-turnip +1 -0
  5. data/.ruby-version +1 -0
  6. data/Assetfile +44 -0
  7. data/Gemfile +5 -0
  8. data/Gemfile.lock +110 -0
  9. data/Rakefile +9 -0
  10. data/benoit.gemspec +50 -0
  11. data/bin/benoit +121 -0
  12. data/bin/bundle-development +1 -0
  13. data/bin/bundle-sandbox +1 -0
  14. data/lib/benoit.rb +36 -0
  15. data/lib/benoit/cadenza.rb +11 -0
  16. data/lib/benoit/cadenza/output_filters.rb +21 -0
  17. data/lib/benoit/cleaner.rb +10 -0
  18. data/lib/benoit/compiler_error.rb +49 -0
  19. data/lib/benoit/configuration.rb +24 -0
  20. data/lib/benoit/current_site.rb +12 -0
  21. data/lib/benoit/file_wrapper_extensions.rb +13 -0
  22. data/lib/benoit/filters.rb +15 -0
  23. data/lib/benoit/filters/base_filter.rb +44 -0
  24. data/lib/benoit/filters/blacklist_filter.rb +18 -0
  25. data/lib/benoit/filters/cadenza_filter.rb +75 -0
  26. data/lib/benoit/filters/content_page_filter.rb +45 -0
  27. data/lib/benoit/filters/markdown_filter.rb +19 -0
  28. data/lib/benoit/filters/metadata_cleaner.rb +30 -0
  29. data/lib/benoit/filters/move_to_root_filter.rb +22 -0
  30. data/lib/benoit/filters/pagination_filter.rb +23 -0
  31. data/lib/benoit/filters/pass_thru_filter.rb +22 -0
  32. data/lib/benoit/filters/sass_filter.rb +74 -0
  33. data/lib/benoit/filters/set_metadata_filter.rb +15 -0
  34. data/lib/benoit/logger.rb +69 -0
  35. data/lib/benoit/page.rb +88 -0
  36. data/lib/benoit/page_metadata.rb +8 -0
  37. data/lib/benoit/page_metadata/container.rb +74 -0
  38. data/lib/benoit/page_metadata/json_converter.rb +28 -0
  39. data/lib/benoit/page_metadata/parser.rb +38 -0
  40. data/lib/benoit/page_metadata/store.rb +75 -0
  41. data/lib/benoit/pipeline.rb +1 -0
  42. data/lib/benoit/pipeline/dsl_extensions.rb +8 -0
  43. data/lib/benoit/pipeline/pagination_matcher.rb +53 -0
  44. data/lib/benoit/pipeline_project.rb +81 -0
  45. data/lib/benoit/site_context.rb +123 -0
  46. data/lib/benoit/utils/finds_layouts_for_template.rb +77 -0
  47. data/lib/benoit/utils/normalizes_path_to_template.rb +43 -0
  48. data/lib/benoit/utils/paginated_list.rb +102 -0
  49. data/lib/benoit/version.rb +3 -0
  50. data/lib/build_notifiers/file_built_notifier.rb +20 -0
  51. data/lib/build_notifiers/progress_notifier.rb +57 -0
  52. data/lib/cli.rb +39 -0
  53. data/spec/.rbenv-gemsets +1 -0
  54. data/spec/Gemfile +9 -0
  55. data/spec/Gemfile.lock +57 -0
  56. data/spec/bin/autospec +16 -0
  57. data/spec/bin/cucumber +16 -0
  58. data/spec/bin/htmldiff +16 -0
  59. data/spec/bin/ldiff +16 -0
  60. data/spec/bin/rspec +16 -0
  61. data/spec/features/build_command.feature +46 -0
  62. data/spec/features/frontmatter_metadata.feature +99 -0
  63. data/spec/features/javascript_files.feature +35 -0
  64. data/spec/features/output_filters.feature +20 -0
  65. data/spec/features/page_layouts.feature +72 -0
  66. data/spec/features/pagination.feature +58 -0
  67. data/spec/features/sass_files.feature +30 -0
  68. data/spec/features/version.feature +5 -0
  69. data/spec/lib/filters/base_filter_spec.rb +141 -0
  70. data/spec/lib/filters/markdown_filter_spec.rb +65 -0
  71. data/spec/lib/filters/sass_filter_spec.rb +73 -0
  72. data/spec/lib/metadata_json_converter_spec.rb +65 -0
  73. data/spec/lib/metadata_store_spec.rb +148 -0
  74. data/spec/lib/page_spec.rb +19 -0
  75. data/spec/lib/site_context_spec.rb +106 -0
  76. data/spec/spec_helper.rb +16 -0
  77. data/spec/steps/output_file_steps.rb +45 -0
  78. data/spec/steps/run_steps.rb +71 -0
  79. data/spec/steps/staticly_steps.rb +194 -0
  80. data/spec/support/aruba/rspec.rb +66 -0
  81. data/spec/support/files/img.png +0 -0
  82. data/spec/support/files/input.css.scss +7 -0
  83. data/spec/support/files/input.scss +7 -0
  84. data/spec/support/spec_helpers/file_helpers.rb +8 -0
  85. data/spec/support/spec_helpers/memory_file_wrapper.rb +43 -0
  86. data/spec/support/spec_helpers/memory_manifest.rb +19 -0
  87. data/spec/turnip_helper.rb +19 -0
  88. data/vendor/frontmatter/frontmatter.gemspec +24 -0
  89. data/vendor/frontmatter/lib/frontmatter.rb +92 -0
  90. data/vendor/frontmatter/lib/frontmatter/version.rb +3 -0
  91. data/vendor/rake-pipeline/.gitignore +18 -0
  92. data/vendor/rake-pipeline/.rspec +1 -0
  93. data/vendor/rake-pipeline/.travis.yml +12 -0
  94. data/vendor/rake-pipeline/.yardopts +2 -0
  95. data/vendor/rake-pipeline/GETTING_STARTED.md +268 -0
  96. data/vendor/rake-pipeline/Gemfile +14 -0
  97. data/vendor/rake-pipeline/LICENSE +20 -0
  98. data/vendor/rake-pipeline/README.markdown +11 -0
  99. data/vendor/rake-pipeline/README.yard +178 -0
  100. data/vendor/rake-pipeline/Rakefile +21 -0
  101. data/vendor/rake-pipeline/bin/rakep +4 -0
  102. data/vendor/rake-pipeline/examples/copying_files.md +12 -0
  103. data/vendor/rake-pipeline/examples/minifying_files.md +37 -0
  104. data/vendor/rake-pipeline/examples/modifying_pipelines.md +67 -0
  105. data/vendor/rake-pipeline/examples/multiple_pipelines.md +77 -0
  106. data/vendor/rake-pipeline/lib/generators/rake/pipeline/install/install_generator.rb +70 -0
  107. data/vendor/rake-pipeline/lib/rake-pipeline.rb +509 -0
  108. data/vendor/rake-pipeline/lib/rake-pipeline/cli.rb +57 -0
  109. data/vendor/rake-pipeline/lib/rake-pipeline/dsl.rb +9 -0
  110. data/vendor/rake-pipeline/lib/rake-pipeline/dsl/pipeline_dsl.rb +246 -0
  111. data/vendor/rake-pipeline/lib/rake-pipeline/dsl/project_dsl.rb +108 -0
  112. data/vendor/rake-pipeline/lib/rake-pipeline/dynamic_file_task.rb +194 -0
  113. data/vendor/rake-pipeline/lib/rake-pipeline/error.rb +17 -0
  114. data/vendor/rake-pipeline/lib/rake-pipeline/file_wrapper.rb +195 -0
  115. data/vendor/rake-pipeline/lib/rake-pipeline/filter.rb +267 -0
  116. data/vendor/rake-pipeline/lib/rake-pipeline/filters.rb +4 -0
  117. data/vendor/rake-pipeline/lib/rake-pipeline/filters/concat_filter.rb +63 -0
  118. data/vendor/rake-pipeline/lib/rake-pipeline/filters/gsub_filter.rb +56 -0
  119. data/vendor/rake-pipeline/lib/rake-pipeline/filters/ordering_concat_filter.rb +38 -0
  120. data/vendor/rake-pipeline/lib/rake-pipeline/filters/pipeline_finalizing_filter.rb +21 -0
  121. data/vendor/rake-pipeline/lib/rake-pipeline/graph.rb +178 -0
  122. data/vendor/rake-pipeline/lib/rake-pipeline/manifest.rb +82 -0
  123. data/vendor/rake-pipeline/lib/rake-pipeline/manifest_entry.rb +34 -0
  124. data/vendor/rake-pipeline/lib/rake-pipeline/matcher.rb +141 -0
  125. data/vendor/rake-pipeline/lib/rake-pipeline/middleware.rb +73 -0
  126. data/vendor/rake-pipeline/lib/rake-pipeline/precompile.rake +8 -0
  127. data/vendor/rake-pipeline/lib/rake-pipeline/project.rb +338 -0
  128. data/vendor/rake-pipeline/lib/rake-pipeline/rails_plugin.rb +10 -0
  129. data/vendor/rake-pipeline/lib/rake-pipeline/railtie.rb +34 -0
  130. data/vendor/rake-pipeline/lib/rake-pipeline/reject_matcher.rb +29 -0
  131. data/vendor/rake-pipeline/lib/rake-pipeline/server.rb +15 -0
  132. data/vendor/rake-pipeline/lib/rake-pipeline/sorted_pipeline.rb +19 -0
  133. data/vendor/rake-pipeline/lib/rake-pipeline/version.rb +6 -0
  134. data/vendor/rake-pipeline/rails/init.rb +2 -0
  135. data/vendor/rake-pipeline/rake-pipeline.gemspec +24 -0
  136. data/vendor/rake-pipeline/spec/cli_spec.rb +73 -0
  137. data/vendor/rake-pipeline/spec/concat_filter_spec.rb +37 -0
  138. data/vendor/rake-pipeline/spec/dsl/pipeline_dsl_spec.rb +165 -0
  139. data/vendor/rake-pipeline/spec/dsl/project_dsl_spec.rb +41 -0
  140. data/vendor/rake-pipeline/spec/dynamic_file_task_spec.rb +119 -0
  141. data/vendor/rake-pipeline/spec/encoding_spec.rb +106 -0
  142. data/vendor/rake-pipeline/spec/file_wrapper_spec.rb +132 -0
  143. data/vendor/rake-pipeline/spec/filter_spec.rb +367 -0
  144. data/vendor/rake-pipeline/spec/graph_spec.rb +56 -0
  145. data/vendor/rake-pipeline/spec/gsub_filter_spec.rb +87 -0
  146. data/vendor/rake-pipeline/spec/manifest_entry_spec.rb +46 -0
  147. data/vendor/rake-pipeline/spec/manifest_spec.rb +67 -0
  148. data/vendor/rake-pipeline/spec/matcher_spec.rb +141 -0
  149. data/vendor/rake-pipeline/spec/middleware_spec.rb +199 -0
  150. data/vendor/rake-pipeline/spec/ordering_concat_filter_spec.rb +42 -0
  151. data/vendor/rake-pipeline/spec/pipeline_spec.rb +232 -0
  152. data/vendor/rake-pipeline/spec/project_spec.rb +295 -0
  153. data/vendor/rake-pipeline/spec/rake_acceptance_spec.rb +720 -0
  154. data/vendor/rake-pipeline/spec/rake_tasks_spec.rb +21 -0
  155. data/vendor/rake-pipeline/spec/reject_matcher_spec.rb +31 -0
  156. data/vendor/rake-pipeline/spec/sorted_pipeline_spec.rb +27 -0
  157. data/vendor/rake-pipeline/spec/spec_helper.rb +38 -0
  158. data/vendor/rake-pipeline/spec/support/spec_helpers/file_utils.rb +35 -0
  159. data/vendor/rake-pipeline/spec/support/spec_helpers/filters.rb +37 -0
  160. data/vendor/rake-pipeline/spec/support/spec_helpers/input_helpers.rb +23 -0
  161. data/vendor/rake-pipeline/spec/support/spec_helpers/memory_file_wrapper.rb +35 -0
  162. data/vendor/rake-pipeline/spec/support/spec_helpers/memory_manifest.rb +19 -0
  163. data/vendor/rake-pipeline/tools/perfs +101 -0
  164. metadata +497 -0
@@ -0,0 +1,49 @@
1
+ #
2
+ # CompilerError.rb
3
+ # Benoit
4
+ #
5
+ # Created by Joseph Fiorini on 11/5/12.
6
+ # Copyright 2012 densitypop. All rights reserved.
7
+ #
8
+
9
+ class StandardError
10
+ def to_json
11
+ { message: "Benoit has encountered an internal error. Please contact @benoitapp on Twitter to resolve this problem.", type: "error" }.to_json
12
+ end
13
+ end
14
+
15
+ module Benoit
16
+ class CompilerError < StandardError
17
+ attr_accessor :line, :message
18
+ attr_reader :output, :env, :file_path, :original_error
19
+
20
+ def initialize(line, file_path, original_error)
21
+ @line = line
22
+ @file_path = file_path
23
+ @output = output
24
+ @env = env
25
+ @original_error = original_error
26
+ end
27
+
28
+ def to_json
29
+ { line_no: @line, message: @message, path: @file_path, original_error: @original_error, type: "error" }.to_json
30
+ end
31
+
32
+ end
33
+
34
+ class FileMissingError < CompilerError
35
+ attr_accessor :missing_file
36
+
37
+ def initialize(missing_file, line, file_path, original_error)
38
+ @missing_file = missing_file
39
+ super line, file_path, original_error
40
+ end
41
+
42
+ def message
43
+ <<-EOS
44
+ You included a file named #{missing_file.inspect} in #{file_path.inspect}. I could not find a file with that name. Maybe you forgot to specify a folder?
45
+ EOS
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,24 @@
1
+ module Benoit
2
+ module Configuration
3
+
4
+ class Config
5
+
6
+ attr_accessor :output_mode, :cache_path, :output_path, :site_path
7
+ attr_writer :clean_before_build
8
+
9
+ def clean_before_build?
10
+ @clean_before_build
11
+ end
12
+
13
+ end
14
+
15
+ def configure(&block)
16
+ block.call(config)
17
+ end
18
+
19
+ def config
20
+ @config ||= Config.new
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ require 'delegate'
2
+
3
+ module Benoit
4
+ class CurrentSite < SimpleDelegator
5
+ def self.load
6
+ context_hash = PageMetadata::SiteContextConverter.export
7
+ new(Benoit::SiteContext.from_hash(context_hash))
8
+ end
9
+ end
10
+ end
11
+
12
+
@@ -0,0 +1,13 @@
1
+ module Benoit
2
+ module FileWrapperExtensions
3
+
4
+ def final_output=(output)
5
+ @final_output = output
6
+ end
7
+
8
+ def final_output
9
+ @final_output
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ module Benoit
2
+ module Filters
3
+ require_relative './filters/base_filter'
4
+ require_relative './filters/sass_filter'
5
+ require_relative './filters/cadenza_filter'
6
+ require_relative './filters/pass_thru_filter'
7
+ require_relative './filters/blacklist_filter'
8
+ require_relative './filters/markdown_filter'
9
+ require_relative './filters/metadata_cleaner'
10
+ require_relative './filters/pagination_filter'
11
+ require_relative './filters/content_page_filter'
12
+ require_relative './filters/move_to_root_filter'
13
+ end
14
+ end
15
+
@@ -0,0 +1,44 @@
1
+ module Benoit
2
+ module Filters
3
+ class BaseFilter < Rake::Pipeline::Filter
4
+
5
+ class << self
6
+ attr_reader :builder, :output_name_generator
7
+
8
+ def build_output(&block)
9
+ @builder = block
10
+ end
11
+
12
+ def output_name(&block)
13
+ @output_name_generator = block
14
+ end
15
+ end
16
+
17
+ attr_accessor :current_site
18
+
19
+ def output_name_generator
20
+ self.class.output_name_generator ||
21
+ @output_name_generator
22
+ end
23
+
24
+ def builder
25
+ self.class.builder
26
+ end
27
+
28
+ def generate_output(inputs, output)
29
+ inputs.each do |input|
30
+ page = current_site[input.path]
31
+ content = build_output(page, input) if builder
32
+ output.write(content || page["content"])
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def build_output(page, input)
39
+ builder.(page, input)
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,18 @@
1
+ module Benoit::Filters
2
+ class BlacklistFilter < Rake::Pipeline::Filter
3
+ attr_accessor :whitelist
4
+
5
+ def initialize(options={}, &block)
6
+ @whitelist = options.delete(:allow)
7
+ super &block
8
+ end
9
+
10
+ def generate_rake_tasks
11
+ @rake_tasks = []
12
+ end
13
+
14
+ def output_files
15
+ []
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,75 @@
1
+ require 'cadenza'
2
+
3
+ class Benoit::Filters::CadenzaFilter < Rake::Pipeline::Filter
4
+ attr_reader :options
5
+ attr_accessor :current_site
6
+
7
+ include Benoit
8
+
9
+ def initialize
10
+ super
11
+ @page_layouts = {}
12
+ end
13
+
14
+ def generate_output(inputs, output)
15
+
16
+ site_context = current_site.to_context
17
+
18
+ inputs.each do |input|
19
+ load_paths = [input.root, Dir.pwd, "#{Dir.pwd}/_layouts"]
20
+
21
+ Benoit::Cadenza.load_output_filters!
22
+
23
+ load_paths.each do |load_path|
24
+ ::Cadenza::BaseContext.add_load_path load_path
25
+ end
26
+
27
+ page = current_site[input.path].to_hash
28
+
29
+ # Leave the original page for paginated pages blank
30
+ # otherwise we will get an "iteration reached an end" error
31
+ # from trying to iterate past the end of the enumerator
32
+ if input.path !~ /\d+.html/ && page.keys.any? { |key| key =~ /\w+_per_page/ }
33
+ output.write("")
34
+ next
35
+ end
36
+
37
+ context_hash = {
38
+ "site" => site_context,
39
+ "page" => page
40
+ }
41
+
42
+ begin
43
+ compiled = ::Cadenza.render_template input.path, context_hash
44
+ rescue ::Cadenza::TemplateNotFoundError => ex
45
+ error = Benoit::FileMissingError.new(ex.message, nil, input.path, ex)
46
+ raise error
47
+ rescue ::Cadenza::FilterNotDefinedError => ex
48
+ missing_filter = ex.message.scan(/undefined filter '([\w\-_]*)'/).flatten.first
49
+ error = Benoit::CompilerError.new(nil, input.path, ex)
50
+ error.message = "You used a filter named #{missing_filter.inspect}, but I could not find it. Maybe it's misspelled?"
51
+ raise error
52
+ rescue ::Cadenza::Error => ex
53
+ end
54
+
55
+ output.write compiled
56
+ end
57
+ end
58
+
59
+
60
+ def page_layouts_for_input(input)
61
+ @page_layouts[input.path] ||=
62
+ FindsLayoutsForTemplate(input.path, root: input.root, load_paths: ["_layouts"])
63
+ end
64
+
65
+ def additional_dependencies(input=nil)
66
+ if input
67
+ Dir["**/*.markdown"].map do |f|
68
+ f.gsub input.root, ""
69
+ end
70
+ else
71
+ []
72
+ end
73
+ end
74
+
75
+ end
@@ -0,0 +1,45 @@
1
+ module Benoit::Filters
2
+
3
+ class ContentPageFilter < Rake::Pipeline::Filter
4
+
5
+ attr_accessor :current_site
6
+
7
+ def initialize
8
+ super
9
+ @page_layouts = {}
10
+ end
11
+
12
+ def generate_output(inputs, output)
13
+ inputs.each do |input|
14
+
15
+ layout = page_layouts_for_input(input).first
16
+
17
+ template =
18
+ if layout
19
+ # TODO: Only use this for files that don't extend already but have specified a layout, if the file extends, then just replace the extends line with the normalized layout
20
+ "{% extends '#{layout}' %}\n\n"
21
+ end.to_s
22
+
23
+ template << input.read
24
+
25
+ output.write(template)
26
+
27
+ end
28
+ end
29
+
30
+ def page_layouts_for_input(input)
31
+ @page_layouts[input.path] ||=
32
+ FindsLayoutsForTemplate(input, root: input.root, load_paths: ["_layouts"])
33
+ end
34
+
35
+ def additional_dependencies(input=nil)
36
+ if input
37
+ output = current_site.paths_map[input.path]
38
+ page_layouts_for_input(input)
39
+ else
40
+ []
41
+ end
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,19 @@
1
+ require 'redcarpet'
2
+
3
+ module Benoit::Filters
4
+ class MarkdownFilter < BaseFilter
5
+
6
+ output_name do |path|
7
+ path.sub(/\.(md|mdown|mkdown|markdown)$/, '.html')
8
+ end
9
+
10
+ build_output do |page|
11
+
12
+ markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, fenced_code_blocks: true)
13
+ rendered = markdown.render(page["content"])
14
+
15
+ page["content"] = rendered
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ module Benoit::Filters
2
+ class MetadataCleaner < Rake::Pipeline::Filter
3
+
4
+ include Benoit
5
+
6
+ attr_accessor :current_site
7
+
8
+ def generate_output(inputs, output)
9
+ inputs.each do |input|
10
+ metadata = current_site[input.path]
11
+ if metadata and metadata.key?("content")
12
+ output.write metadata["content"]
13
+ else
14
+ output.write input.read
15
+ end
16
+ end
17
+ end
18
+
19
+
20
+ def super_pipeline(descendent=self.pipeline)
21
+ if descendent.respond_to? :pipeline
22
+ super_pipeline(descendent.pipeline)
23
+ else
24
+ descendent
25
+ end
26
+ end
27
+
28
+
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ class Benoit::Filters::MoveToRootFilter < Rake::Pipeline::Filter
2
+
3
+ def initialize
4
+ block = proc { |input|
5
+ components = input.split('/')
6
+ if components.length == 1 # Already at root
7
+ components.first
8
+ elsif components.first.start_with? '_'
9
+ components.shift
10
+ end
11
+ components.join('/')
12
+ }
13
+ super &block
14
+ end
15
+
16
+ def generate_output(inputs, output)
17
+ inputs.each do |input|
18
+ output.write input.read
19
+ end
20
+ end
21
+
22
+ end
@@ -0,0 +1,23 @@
1
+ class Pathname
2
+ def append_basename(str, suffix=nil)
3
+ ext = suffix || extname
4
+ dirname.join(basename(ext).to_s + str + ext.to_s)
5
+ end
6
+ end
7
+
8
+ module Benoit
9
+ module Filters
10
+ class PaginationFilter < MetadataCleaner
11
+
12
+ def initialize
13
+ @output_name_generator = ->(_,input){
14
+ pages_for_input = pipeline.per_page_counts[input]
15
+ (1..pages_for_input).to_a.map do |page|
16
+ Pathname.new(input.path).append_basename(page.to_s).to_path
17
+ end
18
+ }
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ #
2
+ # pass_thru_filter.rb
3
+ # Benoit
4
+ #
5
+ # Created by Joseph Fiorini on 10/3/12.
6
+ # Copyright 2012 densitypop. All rights reserved.
7
+ #
8
+
9
+
10
+ module Benoit::Filters
11
+ class PassThruFilter < Rake::Pipeline::Filter
12
+
13
+ processes_binary_files
14
+
15
+ def generate_output(inputs, output)
16
+ inputs.each do |input|
17
+ output.write input.read
18
+ end
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,74 @@
1
+ #
2
+ # sass_filter.rb
3
+ # Benoit
4
+ #
5
+ # Created by Joseph Fiorini on 10/6/12.
6
+ # Copyright 2012 densitypop. All rights reserved.
7
+ #
8
+
9
+ require 'compass'
10
+ require 'sass'
11
+
12
+ class Benoit::Filters::SassFilter < Rake::Pipeline::Filter
13
+ attr_reader :options, :additional_load_paths
14
+
15
+ def initialize(options={})
16
+ load_paths = options.delete(:additional_load_paths) || []
17
+
18
+ # TODO: Handle files that don't end in .scss
19
+ block ||= proc { |input| input.sub(/\.(?:css\.)?(scss|sass)$/, '.css') }
20
+ super(&block)
21
+ Compass.add_project_configuration
22
+ Compass.configuration.project_path ||= Dir.pwd
23
+ @additional_load_paths = Compass.configuration.sass_load_paths
24
+ @additional_load_paths += load_paths.map do |f|
25
+ File.expand_path(f)
26
+ end
27
+
28
+
29
+ @options = options
30
+ @options[:load_paths] ||= []
31
+ @options[:load_paths].concat(additional_load_paths)
32
+
33
+ end
34
+
35
+ def generate_output(inputs, output)
36
+ inputs.each do |input|
37
+ begin
38
+ sass_options = sass_options_for_file(input).merge(filename: input.path)
39
+ sass_engine = Sass::Engine.for_file(input.fullpath, sass_options)
40
+ output.write sass_engine.render
41
+ rescue Sass::SyntaxError => ex
42
+ path = ex.sass_filename.gsub(input.root + "/", "")
43
+ missing_files = ex.message.scan(/File to import not found or unreadable: ([\w\-]*)\./).flatten
44
+ if missing_files.empty?
45
+ error = Benoit::CompilerError.new(nil, path, ex)
46
+ error.line = ex.sass_line
47
+ else
48
+ error = Benoit::FileMissingError.new(missing_files.first, ex.sass_line, path, ex)
49
+ end
50
+ raise error
51
+ rescue StandardError => ex
52
+ raise Benoit::CompilerError.new(nil, path, ex)
53
+ end
54
+ end
55
+ end
56
+
57
+ def additional_dependencies(input=nil)
58
+ Dir.glob("**/*.scss")
59
+ end
60
+
61
+
62
+ private
63
+
64
+ def sass_options_for_file(file)
65
+ added_opts = {
66
+ :syntax => file.path.match(/\.sass$/) ? :sass : :scss,
67
+ :trace => true,
68
+ :cache => false,
69
+ :cache_location => nil
70
+ }
71
+
72
+ added_opts.merge(@options)
73
+ end
74
+ end