skip to Main Content

Shopify has recently decided to stop supporting SCSS in their themes. I’d like to change all the SCSS files to CSS, but this has become a nightmare due to the presence of liquid syntax contained in them. Here’s an example:

// Overlays
$color-overlay-title-text: {{ settings.color_image_overlay_text }};
$color-image-overlay: {{ settings.color_image_overlay }};
$opacity-image-overlay: {{ settings.image_overlay_opacity | divided_by: 100.00 }};

{%- comment -%}
  Based on the image overlay opacity, either lighten or darken the image on hover
{%- endcomment -%}
{% assign image_overlay_opacity = settings.image_overlay_opacity | divided_by: 100.00 %};

{% if image_overlay_opacity > 0.85 %}
  {% assign image_overlay_opacity_hover = image_overlay_opacity | minus: 0.3 %};
{% else %}
  {% assign image_overlay_opacity_hover = image_overlay_opacity | plus: 0.4 %};
{% endif %}
$hover-overlay-opacity: {{ image_overlay_opacity_hover | at_most: 1 }};

When I try to run this through through an scss compiler found online, it fails at the first {{, {%, or {%- since this isn’t valid scss syntax. The end result I’d like is a valid css file which retains liquid syntax.

My next thought was to precompile the file and wrap liquid syntax inside an unquote("") or a css comment to be removed later, then pass it to the ruby scss compiler forked from here. Something like this:

require 'tempfile'
require 'fileutils'

files = ARGV[0]
input_file, output_file = [files.split(":")[0], files.split(":")[1]]
puts "Converting file: #{input_file}"

path_to_compiler = "./lib/ruby-sass/bin/scss"
tmp_path = "./tmp"

# Replace liquid syntax with something SCSS can parse
temp_file = Tempfile.new('tmpscss')
begin
  File.open(input_file, 'r') do |file|
    file.each_line do |temp_line|
      line = temp_line

      # Trying to account for edge cases in liquid syntax
      if line[0..1] == "{{"
        line = line.gsub("{{", "/*lsc {{").gsub("}}", "}} lsc*/")
      else
        line = line.gsub("{{", "unquote("{{").gsub("}}", "}}")")
      end

      if line.include?("comment")
        line = line.gsub("{%- comment -%}", "/*lsc {%- comment -%}").gsub("{%- endcomment -%}", "{%- endcomment -%} lsc*/")
      else
        line = line.gsub("{%", "/*lsc {%").gsub("%}", "%} lsc*/")
      end
      temp_file.puts line
    end
  end
  temp_file.close
  FileUtils.mv(temp_file.path, tmp_path)

  puts "#{temp_file.path}:#{output_file}"

  # Pass to SCSS compiler
  system "ruby #{path_to_compiler} -C .#{temp_file.path}:#{output_file}"
ensure
  temp_file.close
  temp_file.unlink
end

puts "Output file to: #{Dir.pwd}/#{output_file}"

This is successful for a few lines, but there’s too many edge cases for the primitive logic I tried to parse it through, and the scss to css conversion will inevitably fail. There must be a better way to do this. Does anybody have any ideas? I wish Shopify would allow us to use their SCSS compiler.

2

Answers


  1. There is no program that can convert the scss.liquid as far I know. The scss.liquid usually have variable that link to settings_data.json in your shop that’s unique plus numerous mixin function. I don’t see any holistic way other than:

    1. Get an updated theme.

    2. grab the file from page source when it is rendered.

    3. Remove all the liquid from SCSS and convert.

    4. Recode the file with CSS and liquid. Instead of variable in sass, use var(). This is the most painful way.

       {% assign image_overlay_opacity = settings.image_overlay_opacity | divided_by: 100.00 %};
      
       {% if image_overlay_opacity > 0.85 %}
         {% assign image_overlay_opacity_hover = image_overlay_opacity | minus: 0.3 %};
       {% else %}
         {% assign image_overlay_opacity_hover = image_overlay_opacity | plus: 0.4 %};
       {% endif %}
      
       // Overlays
      
       :root {
           --color-overlay-title-text: {{ settings.color_image_overlay_text }};
           --color-image-overlay: {{ settings.color_image_overlay }};
           --opacity-image-overlay: {{ settings.image_overlay_opacity | divided_by: 100.00 }};
           --hover-overlay-opacity: {{ image_overlay_opacity_hover | at_most: 1 }};
       }
      
    Login or Signup to reply.
  2. Any luck with this? I too am looking to migrate a shopify theme from scss to css but liquid is getting in the way.

    I am successfully escaping ‘{{‘ using the following:

    $product-accordion-title-size: #{'"{{ settings.font_product_accordion_title_size }}"'}px;
    

    but am running into loads of other edge case issues. Namely getting the compiler to accept a commented out value when passing through a scss function:

          border-color: darken($color-button-bg,10%);
    

    which references:

    $color-button-bg: #{'"{{ settings.color_btn_bg }}"'};
    

    which ultimately breaks the compiler as it is expecting a value there.

    Currently am contemplating actually going through each case where there is a scss function in place, finding the corresponding value and manually inputing as I’ve had no luck with any of the npm packages that claim to convert json config files to scss.

    I realize this is a question on it’s own but hopefully the part about commenting will help you out and count as an answer ¯_(ツ)_/¯ . A writeup about commenting out some liquid.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search