140 lines
3.7 KiB
Ruby
140 lines
3.7 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
require_relative "error"
|
||
|
|
||
|
module SassC
|
||
|
class Engine
|
||
|
OUTPUT_STYLES = %i[
|
||
|
sass_style_nested
|
||
|
sass_style_expanded
|
||
|
sass_style_compact
|
||
|
sass_style_compressed
|
||
|
]
|
||
|
|
||
|
attr_reader :template, :options
|
||
|
|
||
|
def initialize(template, options = {})
|
||
|
@template = template
|
||
|
@options = options
|
||
|
end
|
||
|
|
||
|
def render
|
||
|
return @template.dup if @template.empty?
|
||
|
|
||
|
data_context = Native.make_data_context(@template)
|
||
|
context = Native.data_context_get_context(data_context)
|
||
|
native_options = Native.context_get_options(context)
|
||
|
|
||
|
Native.option_set_is_indented_syntax_src(native_options, true) if sass?
|
||
|
Native.option_set_input_path(native_options, filename) if filename
|
||
|
Native.option_set_precision(native_options, precision) if precision
|
||
|
Native.option_set_include_path(native_options, load_paths)
|
||
|
Native.option_set_output_style(native_options, output_style_enum)
|
||
|
Native.option_set_source_comments(native_options, true) if line_comments?
|
||
|
Native.option_set_source_map_file(native_options, source_map_file) if source_map_file
|
||
|
Native.option_set_source_map_embed(native_options, true) if source_map_embed?
|
||
|
Native.option_set_source_map_contents(native_options, true) if source_map_contents?
|
||
|
Native.option_set_omit_source_map_url(native_options, true) if omit_source_map_url?
|
||
|
|
||
|
import_handler.setup(native_options)
|
||
|
functions_handler.setup(native_options)
|
||
|
|
||
|
status = Native.compile_data_context(data_context)
|
||
|
|
||
|
if status != 0
|
||
|
message = Native.context_get_error_message(context)
|
||
|
filename = Native.context_get_error_file(context)
|
||
|
line = Native.context_get_error_line(context)
|
||
|
|
||
|
raise SyntaxError.new(message, filename: filename, line: line)
|
||
|
end
|
||
|
|
||
|
css = Native.context_get_output_string(context)
|
||
|
|
||
|
@dependencies = Native.context_get_included_files(context)
|
||
|
@source_map = Native.context_get_source_map_string(context)
|
||
|
|
||
|
Native.delete_data_context(data_context)
|
||
|
|
||
|
css.force_encoding(@template.encoding)
|
||
|
|
||
|
return css unless quiet?
|
||
|
end
|
||
|
|
||
|
def dependencies
|
||
|
raise NotRenderedError unless @dependencies
|
||
|
Dependency.from_filenames(@dependencies)
|
||
|
end
|
||
|
|
||
|
def source_map
|
||
|
raise NotRenderedError unless @source_map
|
||
|
@source_map
|
||
|
end
|
||
|
|
||
|
def filename
|
||
|
@options[:filename]
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def quiet?
|
||
|
@options[:quiet]
|
||
|
end
|
||
|
|
||
|
def precision
|
||
|
@options[:precision]
|
||
|
end
|
||
|
|
||
|
def sass?
|
||
|
@options[:syntax] && @options[:syntax].to_sym == :sass
|
||
|
end
|
||
|
|
||
|
def line_comments?
|
||
|
@options[:line_comments]
|
||
|
end
|
||
|
|
||
|
def source_map_embed?
|
||
|
@options[:source_map_embed]
|
||
|
end
|
||
|
|
||
|
def source_map_contents?
|
||
|
@options[:source_map_contents]
|
||
|
end
|
||
|
|
||
|
def omit_source_map_url?
|
||
|
@options[:omit_source_map_url]
|
||
|
end
|
||
|
|
||
|
def source_map_file
|
||
|
@options[:source_map_file]
|
||
|
end
|
||
|
|
||
|
def import_handler
|
||
|
@import_handler ||= ImportHandler.new(@options)
|
||
|
end
|
||
|
|
||
|
def functions_handler
|
||
|
@functions_handler = FunctionsHandler.new(@options)
|
||
|
end
|
||
|
|
||
|
def output_style_enum
|
||
|
@output_style_enum ||= Native::SassOutputStyle[output_style]
|
||
|
end
|
||
|
|
||
|
def output_style
|
||
|
@output_style ||= begin
|
||
|
style = @options.fetch(:style, :sass_style_nested).to_s
|
||
|
style = "sass_style_#{style}" unless style.include?("sass_style_")
|
||
|
style = style.to_sym
|
||
|
raise InvalidStyleError unless Native::SassOutputStyle.symbols.include?(style)
|
||
|
style
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def load_paths
|
||
|
paths = (@options[:load_paths] || []) + SassC.load_paths
|
||
|
paths.join(File::PATH_SEPARATOR) unless paths.empty?
|
||
|
end
|
||
|
end
|
||
|
end
|