Class: Jekyll::Converters::Scss

Inherits:
Converter
  • Object
show all
Defined in:
lib/jekyll/converters/scss.rb

Direct Known Subclasses

Sass

Constant Summary collapse

BYTE_ORDER_MARK =
%r!^\xEF\xBB\xBF!.freeze
EXTENSION_PATTERN =
%r!^\.scss$!i.freeze
SyntaxError =
Class.new(ArgumentError)
ALLOWED_STYLES =
%w(nested expanded compact compressed).freeze

Instance Method Summary collapse

Instance Method Details

#add_charset?Boolean

Returns:

  • (Boolean)


164
165
166
# File 'lib/jekyll/converters/scss.rb', line 164

def add_charset?
  !!jekyll_sass_configuration["add_charset"]
end

#allow_caching?Boolean

rubocop:enable Metrics/AbcSize

Returns:

  • (Boolean)


160
161
162
# File 'lib/jekyll/converters/scss.rb', line 160

def allow_caching?
  !safe?
end

#associate_page(page) ⇒ Object

Associate this Converter with the “page” object that manages input and output files for this converter.

Note: changing the associated sass_page during the live time of this Converter instance may result in inconsistent results.

Parameters:

  • page (Jekyll:Page)

    The sass_page for which this object acts as converter.



47
48
49
50
51
52
53
54
55
# File 'lib/jekyll/converters/scss.rb', line 47

def associate_page(page)
  if @sass_page
    Jekyll.logger.debug "Sass Converter:",
                        "sass_page re-assigned: #{@sass_page.name} to #{page.name}"
    dissociate_page(page)
    return
  end
  @sass_page = page
end

#convert(content) ⇒ Object



182
183
184
185
186
187
188
189
190
191
# File 'lib/jekyll/converters/scss.rb', line 182

def convert(content)
  config = sass_configs
  engine = SassC::Engine.new(content.dup, config)
  output = engine.render
  generate_source_map(engine) if sourcemap_required?
  replacement = add_charset? ? '@charset "UTF-8";' : ""
  output.sub(BYTE_ORDER_MARK, replacement)
rescue SassC::SyntaxError => e
  raise SyntaxError, e.to_s
end

#dissociate_page(page) ⇒ Object

Dissociate this Converter with the “page” object.

Parameters:

  • page (Jekyll:Page)

    The sass_page for which this object has acted as a converter.



60
61
62
63
64
65
66
67
68
69
# File 'lib/jekyll/converters/scss.rb', line 60

def dissociate_page(page)
  unless page.equal?(@sass_page)
    Jekyll.logger.debug "Sass Converter:",
                        "dissociating a page that was never associated #{page.name}"
  end

  @source_map_page = nil
  @sass_page = nil
  @site = nil
end

#jekyll_sass_configurationObject



83
84
85
86
87
88
89
90
91
# File 'lib/jekyll/converters/scss.rb', line 83

def jekyll_sass_configuration
  @jekyll_sass_configuration ||= begin
    options = @config["sass"] || {}
    unless options["style"].nil?
      options["style"] = options["style"].to_s.gsub(%r!\A:!, "").to_sym
    end
    options
  end
end

#matches(ext) ⇒ Object



71
72
73
# File 'lib/jekyll/converters/scss.rb', line 71

def matches(ext)
  ext =~ self.class::EXTENSION_PATTERN
end

#output_ext(_ext) ⇒ Object



75
76
77
# File 'lib/jekyll/converters/scss.rb', line 75

def output_ext(_ext)
  ".css"
end

#safe?Boolean

Returns:

  • (Boolean)


79
80
81
# File 'lib/jekyll/converters/scss.rb', line 79

def safe?
  !!@config["safe"]
end

#sass_build_configuration_options(overrides) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/jekyll/converters/scss.rb', line 93

def sass_build_configuration_options(overrides)
  if safe?
    overrides
  else
    Jekyll::Utils.symbolize_hash_keys(
      Jekyll::Utils.deep_merge_hashes(
        jekyll_sass_configuration,
        overrides
      )
    )
  end
end

#sass_configsObject



168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/jekyll/converters/scss.rb', line 168

def sass_configs
  sass_build_configuration_options(
    :style                => sass_style,
    :syntax               => syntax,
    :filename             => filename,
    :output_path          => output_path,
    :source_map_file      => source_map_file,
    :load_paths           => sass_load_paths,
    :omit_source_map_url  => !sourcemap_required?,
    :source_map_contents  => true,
    :line_comments_option => line_comments_option
  )
end

#sass_dirObject



110
111
112
113
114
# File 'lib/jekyll/converters/scss.rb', line 110

def sass_dir
  return "_sass" if jekyll_sass_configuration["sass_dir"].to_s.empty?

  jekyll_sass_configuration["sass_dir"]
end

#sass_dir_relative_to_site_sourceObject



125
126
127
128
129
# File 'lib/jekyll/converters/scss.rb', line 125

def sass_dir_relative_to_site_source
  @sass_dir_relative_to_site_source ||= begin
    Jekyll.sanitized_path(site_source, sass_dir).sub(site.source + "/", "")
  end
end

#sass_load_pathsObject

rubocop:disable Metrics/AbcSize



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/jekyll/converters/scss.rb', line 132

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.flat_map { |path| Dir.glob(path) }

    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.uniq!
  paths << site.theme.sass_path if site.theme&.sass_path
  paths.select { |path| File.directory?(path) }
end

#sass_styleObject



116
117
118
119
# File 'lib/jekyll/converters/scss.rb', line 116

def sass_style
  style = jekyll_sass_configuration.fetch("style", :compact)
  ALLOWED_STYLES.include?(style.to_s) ? style.to_sym : :compact
end

#syntaxObject



106
107
108
# File 'lib/jekyll/converters/scss.rb', line 106

def syntax
  :scss
end

#user_sass_load_pathsObject



121
122
123
# File 'lib/jekyll/converters/scss.rb', line 121

def user_sass_load_paths
  Array(jekyll_sass_configuration["load_paths"])
end