├── .coveralls.yml ├── .gitignore ├── Gemfile ├── test ├── fixtures │ ├── booleans │ │ ├── variables.json │ │ └── style.scss │ ├── lists │ │ ├── variables.json │ │ └── style.scss │ ├── sass │ │ ├── style.sass │ │ └── variables.json │ ├── strings │ │ ├── style.scss │ │ └── variables.json │ ├── nesting │ │ ├── strings.scss │ │ ├── numbers.scss │ │ ├── booleans.scss │ │ └── variables.json │ └── maps │ │ ├── variables.json │ │ └── style.scss ├── test_helper.rb ├── sass_test.rb ├── sass-json-vars_importer_test.rb └── sass-json-vars_test.rb ├── lib ├── sass-json-vars │ ├── version.rb │ ├── monkeypatch.rb │ └── importer.rb └── sass-json-vars.rb ├── .travis.yml ├── CHANGELOG.md ├── Rakefile ├── Gemfile.lock ├── sass-json-vars.gemspec ├── MIT-LICENSE └── README.md /.coveralls.yml: -------------------------------------------------------------------------------- 1 | service_name: travis-ci 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .sass-cache/* 2 | /coverage 3 | *.gem 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | gemspec 3 | 4 | gem 'rake' 5 | -------------------------------------------------------------------------------- /test/fixtures/booleans/variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "value": true 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/lists/variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : ["#c33", "#33c"] 3 | } 4 | -------------------------------------------------------------------------------- /lib/sass-json-vars/version.rb: -------------------------------------------------------------------------------- 1 | module SassJSONVars 2 | VERSION = "0.3.3" 3 | end 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | script: "bundle exec rake test" 3 | rvm: 4 | - 1.9.3 5 | - 2.0.0 -------------------------------------------------------------------------------- /test/fixtures/sass/style.sass: -------------------------------------------------------------------------------- 1 | @import "variables.json" 2 | 3 | body 4 | color: $color-red 5 | -------------------------------------------------------------------------------- /test/fixtures/strings/style.scss: -------------------------------------------------------------------------------- 1 | @import 'variables.json'; 2 | 3 | body { 4 | color: $color-red; 5 | } -------------------------------------------------------------------------------- /test/fixtures/lists/style.scss: -------------------------------------------------------------------------------- 1 | @import 'variables.json'; 2 | 3 | body { 4 | color: nth($colors, 1); 5 | } -------------------------------------------------------------------------------- /test/fixtures/sass/variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "color-red" : "#c33", 3 | "color-blue" : "#33c" 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/strings/variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "color-red" : "#c33", 3 | "color-blue" : "#33c" 4 | } 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.3.3 2 | 3 | - Fixed issue where non-string values nested within maps would throw a 4 | type error. 5 | -------------------------------------------------------------------------------- /test/fixtures/nesting/strings.scss: -------------------------------------------------------------------------------- 1 | @import 'variables.json'; 2 | 3 | body { 4 | color: map-get($string, red); 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/maps/variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors": { 3 | "red" : { 4 | "base": "#c33" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/booleans/style.scss: -------------------------------------------------------------------------------- 1 | @import 'variables.json'; 2 | 3 | body { 4 | @if $value { 5 | color: blue; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/maps/style.scss: -------------------------------------------------------------------------------- 1 | @import 'variables.json'; 2 | 3 | body { 4 | color: map-get(map-get($colors, red), base); 5 | } 6 | -------------------------------------------------------------------------------- /lib/sass-json-vars.rb: -------------------------------------------------------------------------------- 1 | require 'sass-json-vars/importer' 2 | require 'sass-json-vars/monkeypatch' 3 | 4 | module SassJSONVars 5 | end 6 | -------------------------------------------------------------------------------- /test/fixtures/nesting/numbers.scss: -------------------------------------------------------------------------------- 1 | @import 'variables.json'; 2 | 3 | body { 4 | padding: map-get($number, padding) + 0px; 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/nesting/booleans.scss: -------------------------------------------------------------------------------- 1 | @import 'variables.json'; 2 | 3 | body { 4 | @if map-get($bool, isRed) { 5 | color: red; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | require 'simplecov' 2 | require 'coveralls' 3 | 4 | SimpleCov.formatter = Coveralls::SimpleCov::Formatter 5 | SimpleCov.start 'rails' 6 | -------------------------------------------------------------------------------- /test/fixtures/nesting/variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "bool": { 3 | "isRed" : true 4 | }, 5 | "string": { 6 | "red": "red" 7 | }, 8 | "number": { 9 | "padding": 10 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | Bundler::GemHelper.install_tasks 3 | 4 | require 'rake/testtask' 5 | 6 | Rake::TestTask.new(:test) do |t| 7 | t.libs << 'lib' 8 | t.libs << 'test' 9 | t.pattern = 'test/**/*_test.rb' 10 | t.verbose = false 11 | end 12 | 13 | task :default => :test 14 | -------------------------------------------------------------------------------- /test/sass_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'test/unit' 3 | require 'sass' 4 | require 'sass-json-vars' 5 | 6 | class SassTest < Test::Unit::TestCase 7 | def test_sass_syntax 8 | scss = Sass.compile_file("test/fixtures/sass/style.sass") 9 | assert_equal "body {\n color: #cc3333; }\n", scss 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/sass-json-vars/monkeypatch.rb: -------------------------------------------------------------------------------- 1 | require 'sass-json-vars/importer' 2 | 3 | # Taken from https://github.com/chriseppstein/sass-css-importer/blob/master/lib/sass/css_importer/monkey_patches.rb 4 | # TODO: This feels wrong, surely there must be a better way to handle this 5 | 6 | class Sass::Engine 7 | alias initialize_without_json_importer initialize 8 | 9 | def initialize(template, options={}) 10 | initialize_without_json_importer(template, options) 11 | 12 | json_importer = self.options[:load_paths].find {|lp| lp.is_a?(SassJSONVars::Importer) } 13 | 14 | unless json_importer 15 | root = File.dirname(options[:filename] || ".") 16 | self.options[:load_paths] << SassJSONVars::Importer.new(root) 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | sass-json-vars (0.3.2) 5 | sass (>= 3.1) 6 | 7 | GEM 8 | remote: http://rubygems.org/ 9 | specs: 10 | coveralls (0.7.0) 11 | multi_json (~> 1.3) 12 | rest-client 13 | simplecov (>= 0.7) 14 | term-ansicolor 15 | thor 16 | mime-types (2.0) 17 | multi_json (1.10.1) 18 | rake (10.3.2) 19 | rest-client (1.6.7) 20 | mime-types (>= 1.16) 21 | sass (3.3.14) 22 | simplecov (0.7.1) 23 | multi_json (~> 1.0) 24 | simplecov-html (~> 0.7.1) 25 | simplecov-html (0.7.1) 26 | term-ansicolor (1.2.2) 27 | tins (~> 0.8) 28 | thor (0.19.1) 29 | tins (0.13.1) 30 | 31 | PLATFORMS 32 | ruby 33 | 34 | DEPENDENCIES 35 | coveralls 36 | rake 37 | sass-json-vars! 38 | simplecov (~> 0.7.1) 39 | 40 | BUNDLED WITH 41 | 1.10.4 42 | -------------------------------------------------------------------------------- /sass-json-vars.gemspec: -------------------------------------------------------------------------------- 1 | $:.push File.expand_path("../lib", __FILE__) 2 | 3 | # Maintain your gem's version: 4 | require "sass-json-vars/version" 5 | 6 | # Describe your gem and declare its dependencies 7 | Gem::Specification.new do |s| 8 | s.name = 'sass-json-vars' 9 | s.version = SassJSONVars::VERSION 10 | s.platform = Gem::Platform::RUBY 11 | s.authors = ["Nate Hunzaker"] 12 | s.email = ['nate.hunzaker@viget.com'] 13 | s.homepage = 'https://github.com/vigetlabs/sass-json-vars' 14 | s.summary = "Allows the use of JSON to declare variables with @import 'file.json'." 15 | s.description = "Allows the use of JSON to declare variables with @import 'file.json'." 16 | s.license = 'MIT' 17 | 18 | s.files = Dir['lib/**/*', 'Rakefile', 'readme.md'] 19 | s.test_files = Dir['test/**/*'] 20 | 21 | s.add_runtime_dependency 'sass', '>= 3.1' 22 | s.add_development_dependency 'simplecov', '~> 0.7.1' 23 | s.add_development_dependency 'coveralls' 24 | end 25 | -------------------------------------------------------------------------------- /test/sass-json-vars_importer_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'test/unit' 3 | require 'sass' 4 | require 'sass-json-vars' 5 | 6 | class SassJSONVarsImporterTest < Test::Unit::TestCase 7 | def test_unwatched_non_json_file 8 | unwatched_file = make_path(root, 'style.scss') 9 | assert_equal false, importer.watched_file?(unwatched_file) 10 | end 11 | 12 | def test_unwatched_non_root_file 13 | unwatched_file = make_path([File.dirname(__FILE__)], 'fixtures', 'maps', 'variables.json') 14 | assert_equal false, importer.watched_file?(unwatched_file) 15 | end 16 | 17 | def test_watched_file 18 | watched_file = make_path(root, 'variables.json') 19 | assert_equal true, importer.watched_file?(watched_file) 20 | end 21 | 22 | private 23 | 24 | def importer 25 | @importer ||= SassJSONVars::Importer.new(root) 26 | end 27 | 28 | def root 29 | make_path [File.dirname(__FILE__)], 'fixtures', 'strings' 30 | end 31 | 32 | def make_path(*path_components) 33 | path_components.join(File::SEPARATOR) 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 Viget 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /test/sass-json-vars_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'test/unit' 3 | require 'sass' 4 | require 'sass-json-vars' 5 | 6 | class SassJSONVarsTest < Test::Unit::TestCase 7 | def test_strings 8 | scss = Sass.compile_file("test/fixtures/strings/style.scss") 9 | assert_equal "body {\n color: #cc3333; }\n", scss 10 | end 11 | 12 | def test_lists 13 | scss = Sass.compile_file("test/fixtures/lists/style.scss") 14 | assert_equal "body {\n color: #cc3333; }\n", scss 15 | end 16 | 17 | def test_maps 18 | scss = Sass.compile_file("test/fixtures/maps/style.scss") 19 | assert_equal "body {\n color: #cc3333; }\n", scss 20 | end 21 | 22 | def test_booleans 23 | scss = Sass.compile_file("test/fixtures/booleans/style.scss") 24 | assert_equal "body {\n color: blue; }\n", scss 25 | end 26 | 27 | def test_nesting_booleans 28 | scss = Sass.compile_file("test/fixtures/nesting/booleans.scss") 29 | assert_equal "body {\n color: red; }\n", scss 30 | end 31 | 32 | def test_nesting_strings 33 | scss = Sass.compile_file("test/fixtures/nesting/strings.scss") 34 | assert_equal "body {\n color: red; }\n", scss 35 | end 36 | 37 | def test_nesting_numbers 38 | scss = Sass.compile_file("test/fixtures/nesting/numbers.scss") 39 | assert_equal "body {\n padding: 10px; }\n", scss 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/sass-json-vars/importer.rb: -------------------------------------------------------------------------------- 1 | require 'sass' 2 | require 'json' 3 | 4 | module SassJSONVars 5 | class Importer < Sass::Importers::Filesystem 6 | 7 | def watched_file?(uri) 8 | !!(uri =~ /\.json$/ && 9 | uri.start_with?(root + File::SEPARATOR)) 10 | end 11 | 12 | protected 13 | 14 | def extensions 15 | {'json' => :scss} 16 | end 17 | 18 | def json?(name) 19 | File.extname(name) == '.json' 20 | end 21 | 22 | private 23 | 24 | def _find(dir, name, options) 25 | return unless json? name 26 | 27 | full_filename, syntax = Sass::Util.destructure(find_real_file(dir, name, options)) 28 | return unless full_filename && File.readable?(full_filename) 29 | 30 | json = JSON.parse(IO.read(full_filename)) 31 | variables = json.map { |key, value| "$#{key}: #{_convert_to_sass(value)};" }.join("\n") 32 | 33 | Sass::Engine.new(variables, options.merge( 34 | :filename => full_filename, 35 | :importer => self, 36 | :syntax => :scss 37 | )) 38 | end 39 | 40 | def _convert_to_sass(item) 41 | if item.is_a? Array 42 | _make_list(item) 43 | elsif item.is_a? Hash 44 | _make_map(item) 45 | else 46 | item.to_s 47 | end 48 | end 49 | 50 | def _make_list(item) 51 | '(' + item.map { |i| _convert_to_sass(i) }.join(',') + ')' 52 | end 53 | 54 | def _make_map(item) 55 | '(' + item.map {|key, value| key.to_s + ':' + _convert_to_sass(value) }.join(',') + ')' 56 | end 57 | end 58 | 59 | end 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sass JSON Vars 2 | 3 | [![Build Status](https://travis-ci.org/vigetlabs/sass-json-vars.png?branch=master)](https://travis-ci.org/vigetlabs/sass-json-vars) 4 | [![Coverage Status](https://coveralls.io/repos/vigetlabs/sass-json-vars/badge.png)](https://coveralls.io/r/vigetlabs/sass-json-vars) 5 | [![Code Climate](https://codeclimate.com/github/vigetlabs/sass-json-vars.png)](https://codeclimate.com/github/vigetlabs/sass-json-vars) 6 | [![Gem Version](https://badge.fury.io/rb/sass-json-vars.png)](http://badge.fury.io/rb/sass-json-vars) 7 | 8 | `@import` json data into Sass `$variables`. 9 | 10 | 11 | **Important:** the latest version of [`sass-rails`](https://github.com/rails/sass-rails) is locked in to Sass 3.2. This means that [Sass maps](http://thesassway.com/news/sass-3-3-released#maps) are not available to `sass-json-vars` to parse nested objects. 12 | 13 | ### Usage 14 | 15 | ```shell 16 | gem install sass-json-vars 17 | ``` 18 | 19 | After that reload rails server if you are on rails. 20 | 21 | #### For projects using Sass >= 3.3 22 | 23 | 24 | Place variables in a JSON file: 25 | 26 | ```javascript 27 | // variables.json 28 | { 29 | "font-sans": "Helvetica, sans-serif", 30 | "colors": { 31 | "red": "#c33" 32 | } 33 | } 34 | ``` 35 | 36 | Import the file in Sass to expose variable names: 37 | 38 | ```scss 39 | @import "variables.json" 40 | 41 | body { 42 | color: map-get($colors, red); 43 | font: $font-sans; 44 | } 45 | ``` 46 | 47 | Require sass-json-vars when compiling 48 | 49 | ```shell 50 | sass style.scss -r sass-json-vars 51 | ``` 52 | 53 | #### For projects using Sass <= 3.2 54 | 55 | Place variables in a JSON file: 56 | 57 | ```javascript 58 | // variables.json 59 | { 60 | "font-sans": "Helvetica, sans-serif", 61 | "colors-red": "#c33" 62 | } 63 | ``` 64 | 65 | Import the file in Sass to expose variable names: 66 | 67 | ```scss 68 | @import "variables.json" 69 | 70 | body { 71 | color: $colors-red; 72 | font: $font-sans; 73 | } 74 | ``` 75 | 76 | 77 | Require sass-json-vars when compiling 78 | 79 | ```shell 80 | sass style.scss -r sass-json-vars 81 | ``` 82 | 83 | ### What about node-sass? 84 | 85 | Take a look at 86 | [node-sass-json-importer](https://github.com/Updater/node-sass-json-importer) 87 | for a libsass variant of this project: 88 | 89 | https://github.com/Updater/node-sass-json-importer 90 | --------------------------------------------------------------------------------