Neograph734 Neograph734 - 2 months ago 11
Sass (Sass) Question

Parse yaml file content to scss via ruby

I am trying to obtain the contents of a yaml (.yml) file in my scss. The aim is to make the contents of the yaml file available as an SCSS map, so the values can be read and iterated over.

So far I have this:

SCSS file:

$ranges: yaml_load('path/to/file');


Ruby file (a hacked version of this gem):

require 'yaml'

module Sass::Script::Functions
def yaml_load(file_name)
# Required because the filename is escaped: "\"path/to/file.yml\""
file_name = file_name.to_s[1..-2]
if (File.file?(file_name))
file_content = YAML::load_file(file_name)

if (file_content.is_a?(Hash))
p 'is indeed a hash'
return Sass::Script::Value::Map.new(file_content)
end

p 'Parse error'
else
p 'The requested file could not be found'
end
end
end


It was my understanding that
YAML::load_file
returns a hash, and that
Sass::Script::Value::Map
would take a hash as input. But I get the following error I do not understand:


C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/sass-3.5.1/lib/sass/script/value/map.rb:22:in
`block in options=': undefined method `options=' for
"
first.value.in.yaml.file
":String (NoMethodError)


Using a yaml file like this:

first.value.in.yaml.file:
name: MyName
color: red


What is this options method, and how should I be converting the yaml file's contents into a SASS map?

(And if you know how to properly use a filename without it getting escaped, please share :) )

Answer Source

All values in the map should be an instance of Sass::Script::Value::Base so that sass can use them. But Sass::Script::Value::Map.new method does not do the conversion for us according to sass source code: this and this.

So a conversion method is needed.

# @param [Hash]  value
# @return [Sass::Script::Value::Map or Sass::Script::Value::List] 
  def convert_to_base(value) # part of this function is copied from https://github.com/fabiofabbrucci/sass-yaml/blob/master/lib/sass-yaml.rb
    if value.is_a?(String) 
      return Sass::Script::Value::String.new(value.to_s)
    elsif value.is_a?(Array)
      value.each_with_index do |elem, i|
        value[i]= Sass::Script::Value::String.new(elem.to_s)
      end
      return Sass::Script::Value::List.new(value, ",")
    end
    result = Hash.new
    value.each {|the_key, the_value|
      result[convert_to_base(the_key)]=convert_to_base(the_value)
    }
    Sass::Script::Value::Map.new(result)
  end

Also changes return Sass::Script::Value::Map.new(file_content) to return convert_to_base(file_content)