File: engine.rb

package info (click to toggle)
ruby-sassc 2.4.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 368 kB
  • sloc: ruby: 2,277; makefile: 3
file content (141 lines) | stat: -rw-r--r-- 3,941 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# 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
      @functions = options.fetch(:functions, Script::Functions)
    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, functions: @functions)

      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)

      css.force_encoding(@template.encoding)
      @source_map.force_encoding(@template.encoding) if @source_map.is_a?(String)

      return css unless quiet?
    ensure
      Native.delete_data_context(data_context) if data_context
    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