blob: 98d3c95be3b4561d1c18fb597dbd4ac5d23559bc [file] [log] [blame]
# encoding: utf-8
require 'sass'
require 'jekyll/utils'
module Jekyll
module Converters
class Scss < Converter
BYTE_ORDER_MARK = /^\xEF\xBB\xBF/
SyntaxError = Class.new(ArgumentError)
safe true
priority :low
ALLOWED_STYLES = %w(nested expanded compact compressed).freeze
def matches(ext)
ext =~ /^\.scss$/i
end
def output_ext(ext)
".css"
end
def safe?
!!@config["safe"]
end
def jekyll_sass_configuration
options = @config["sass"] || {}
unless options["style"].nil?
options["style"] = options["style"].to_s.gsub(/\A:/, '').to_sym
end
options
end
def sass_build_configuration_options(overrides)
if safe?
{
:load_paths => sass_load_paths,
:syntax => syntax,
:style => sass_style,
:cache => false
}
else
Jekyll::Utils.symbolize_hash_keys(
Jekyll::Utils.deep_merge_hashes(
jekyll_sass_configuration,
overrides
)
)
end
end
def syntax
:scss
end
def sass_dir
return "_sass" if jekyll_sass_configuration["sass_dir"].to_s.empty?
jekyll_sass_configuration["sass_dir"]
end
def sass_style
style = jekyll_sass_configuration.fetch("style", :compact)
ALLOWED_STYLES.include?(style.to_s) ? style.to_sym : :compact
end
def user_sass_load_paths
Array(jekyll_sass_configuration["load_paths"])
end
def sass_dir_relative_to_site_source
Jekyll.sanitized_path(site_source, sass_dir)
end
def sass_load_paths
paths = user_sass_load_paths + [sass_dir_relative_to_site_source]
if safe?
# Sanitize paths to prevent any attack vectors (.e.g. `/**/*`)
paths.map! { |path| Jekyll.sanitized_path(site_source, path) }
end
# Expand file globs (e.g. `node_modules/*/node_modules` )
Dir.chdir(site_source) do
paths = paths.map { |path| Dir.glob(path) }.flatten.uniq
paths.map! do |path|
if safe?
# Sanitize again in case globbing was able to do something crazy.
Jekyll.sanitized_path(site_source, path)
else
File.expand_path(path)
end
end
end
paths.select { |path| File.directory?(path) }
end
def allow_caching?
!safe?
end
def add_charset?
!!jekyll_sass_configuration["add_charset"]
end
def sass_configs
sass_build_configuration_options({
"syntax" => syntax,
"cache" => allow_caching?,
"load_paths" => sass_load_paths
})
end
def convert(content)
output = ::Sass.compile(content, sass_configs)
replacement = add_charset? ? '@charset "UTF-8";' : ''
output.sub(BYTE_ORDER_MARK, replacement)
rescue ::Sass::SyntaxError => e
raise SyntaxError.new("#{e.to_s} on line #{e.sass_line}")
end
private
def site_source
@site_source ||= File.expand_path(@config["source"]).freeze
end
end
end
end