Skip to content

Instantly share code, notes, and snippets.

@kazu69
Last active May 18, 2016 13:28
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kazu69/18930760cb6c5af323be to your computer and use it in GitHub Desktop.
Save kazu69/18930760cb6c5af323be to your computer and use it in GitHub Desktop.
JSONを使ってSassとJavaScriptで設定値を共有する方法

JSONを使ってSassとJavaScriptで設定値を共有する方法を調べてみた

cssのプロパティをJavaScriptでも扱う必要があり、方法を検討してみた。 管理するデータを一つにして、JavaScriptからも参照できると、便利そう。 ということで、データをJSON形式でデータを持たせて、 データをSassのMap型にコンバートして扱うことができれば、実現可能そうなので、 変換するmoduleなどを調べてみた。

例えば以下のようなjsonがあった場合でそれぞれのパターンを試してみた。

# variables.json
{
    "themes": {
    	"chrome": {
            "user-agent": "chrome",
    		"font-color": "red",
    		"background-color": "blue"
    	},
    	"firefox": {
            "user-agent": "firefox",
    		"font-color": "blue",
    		"background-color": "white"
    	}
    }
}

Compass を使っているプロジェクトの場合

compass extentionとして提供されている、SassyJSON を使う。 rubygems.orgよりもGitHubから取得したほうが最新っぽいので、注意したほうが良さそう。

# 適当なproject作成
bundle exec compass create sample

# 以下のような構成
├── Gemfile
├── Gemfile.lock
└──sample
    ├── config.rb
    ├── sass
    │   ├── ie.scss
    │   ├── print.scss
    │   ├── screen.scss
    │   ├── style.scss
    │   └── variables.json
    └── stylesheets
        ├── SassyJSON
        ├── ie.css
        ├── print.css
        ├── screen.css
        └── style.css

# コンパイル
bundle exec compass compile sample

sassは以下のようになり

@import 'SassyJSON';
// パラメーターに指定した変数名にjson値が格納されている
@import 'variables.json?themes';

@each $key, $theme  in $themes {
	@each $browser, $config in $theme {
			body.#{$browser} {
				content: "#{$browser}";
				color: map-get($config, font-color);
				background-color: map-get($config, background-color);
			}
	}
}

コンパイルすると、

/* line 6, ../sass/style.scss */
body.chrome {
  content: "chrome";
  color: red;
  background-color: blue;
}

/* line 6, ../sass/style.scss */
body.firefox {
  content: "firefox";
  color: blue;
  background-color: white;
}

json_encodeメソッドもあるので、contentプロパティ値にJSONの値を持たせることもで、 view側にもstyleとして出力もできそう。

.output {
	content: json_encode($variables);
	}

Ruby プロジェクトの場合

sass-json-varsが良さそう。 JSONのネスト構造もmapに変換してくれて、jsonをそのままsass変数に変換してくれそうなので、 直感的で使いやすそう。

# requireオプションでsass-json-varsを指定してコンパイル
bundle exec  sass style.scss style.css -r sass-json-vars

sassは以下のようになり

@import 'variables.json';

@each $browser, $config in $themes {
	body.#{$browser} {
			content: "#{$browser}";
			color: map-get($config, font-color);
			background-color: map-get($config, background-color);
	}
}

そのほか

ビルドツールを使って、コンパイルする。 この場合は、gulp plugin gulp-json-sass がある。

JSONをsass変数に変換するだけなので、sassファイルの結合とコンパイルには別のプラグインが必要。 今回は次のような感じでつかってみた。

# package.json
{
  "name": "gulp-json-sass-sample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "gulp": "^3.8.10"
  },
  "devDependencies": {
    "gulp": "^3.8.10",
    "gulp-json-sass": "^0.0.2",
    "gulp-sass": "^1.3.1",
    "gulp-concat": "^2.4.3"
  }
}
# gulpfile.js
var gulp = require('gulp'),
	jsonSass = require('gulp-json-sass'),
	concat = require('gulp-concat'),
    sass = require('gulp-sass');

gulp.task('default', function() {
  return gulp
    .src(['variables.json', 'style.scss'])
    .pipe(jsonSass({
    	delim: '-',
     	sass: false,
     	ignoreJsonErrors: true,
     	escapeIllegalCharacters: true,
     	prefixFirstNumericCharacter: true,
     	firstCharacter: '_'
    }))
    .pipe(concat('style.scss'))
//    .pipe(sass())
    .pipe(gulp.dest('./stylesheets'));
});

gulp-json-sassでJSONをsass変数にconvertできるが、 map形式にはならないのでJSONの構造を考量しておく必要がありそう。

デフォルトのままだと、次のようにconvertされる

$themes-chrome-user-agent: chrome;
$themes-chrome-font-color: red;
$themes-chrome-background-color: blue;
$themes-firefox-user-agent: firefox;
$themes-firefox-font-color: blue;
$themes-firefox-background-color: white;

ということなので、以下のsassファイルとgulp-concatで結合させて

%theme-chrome {
	content: "#{$themes-chrome-user-agent}";
	color: "#{$themes-chrome-font-color}";
	background-color: "#{$themes-chrome-background-color}";
}

%theme-firefox {
	content: "#{$themes-firefox-user-agent}";
	color: "#{$themes-firefox-font-color}";
	background-color: "#{$themes-firefox-background-color}";
}

@mixin set-theme($ua) {
	@extend %theme-#{$ua};
}

$ua: 'chrome' 'firefox';
@each $val in $ua {
	body.#{$val} {
		@include set-theme($val);
	}
}

gulp-sassでコンパイルする

body.chrome {
  content: "chrome";
  color: "red";
  background-color: "blue"; }

body.firefox {
  content: "firefox";
  color: "blue";
  background-color: "white"; }

他にもあるかもしれないけど、現状こんな感じでしょうか。

var gulp = require('gulp'),
jsonSass = require('gulp-json-sass'),
concat = require('gulp-concat'),
sass = require('gulp-sass');
gulp.task('default', function() {
return gulp
.src(['variables.json', 'style.scss'])
.pipe(jsonSass({
delim: '-',
sass: false,
ignoreJsonErrors: true,
escapeIllegalCharacters: true,
prefixFirstNumericCharacter: true,
firstCharacter: '_'
}))
.pipe(concat('style.scss'))
.pipe(sass())
.pipe(gulp.dest('./stylesheets'));
});
.output {
content: json_encode($variables);
}
/* line 6, ../sass/style.scss */
body.chrome {
content: "chrome";
color: red;
background-color: blue;
}
/* line 6, ../sass/style.scss */
body.firefox {
content: "firefox";
color: blue;
background-color: white;
}
@import 'SassyJSON';
// パラメーターに指定した変数名にjson値が格納されている
@import 'variables.json?themes';
@each $key, $theme in $themes {
@each $browser, $config in $theme {
body.#{$browser} {
content: "#{$browser}";
color: map-get($config, font-color);
background-color: map-get($config, background-color);
}
}
}
# 適当なproject作成
bundle exec compass create sample
# 以下のような構成
├── Gemfile
├── Gemfile.lock
└──sample
   ├── config.rb
   ├── sass
   │   ├── ie.scss
   │   ├── print.scss
   │   ├── screen.scss
   │   ├── style.scss
   │   └── variables.json
   └── stylesheets
   ├── SassyJSON
   ├── ie.css
   ├── print.css
   ├── screen.css
   └── style.css
# コンパイル
bundle exec compass compile sample
body.chrome {
content: "chrome";
color: "red";
background-color: "blue"; }
body.firefox {
content: "firefox";
color: "blue";
background-color: "white"; }
%theme-chrome {
content: "#{$themes-chrome-user-agent}";
color: "#{$themes-chrome-font-color}";
background-color: "#{$themes-chrome-background-color}";
}
%theme-firefox {
content: "#{$themes-firefox-user-agent}";
color: "#{$themes-firefox-font-color}";
background-color: "#{$themes-firefox-background-color}";
}
@mixin set-theme($ua) {
@extend %theme-#{$ua};
}
$ua: 'chrome' 'firefox';
@each $val in $ua {
body.#{$val} {
@include set-theme($val);
}
}
$themes-chrome-user-agent: chrome;
$themes-chrome-font-color: red;
$themes-chrome-background-color: blue;
$themes-firefox-user-agent: firefox;
$themes-firefox-font-color: blue;
$themes-firefox-background-color: white;
# package.json
{
"name": "gulp-json-sass-sample",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"gulp": "^3.8.10"
},
"devDependencies": {
"gulp": "^3.8.10",
"gulp-json-sass": "^0.0.2",
"gulp-sass": "^1.3.1",
"gulp-concat": "^2.4.3"
}
}
@import 'variables.json';
@each $browser, $config in $themes {
body.#{$browser} {
content: "#{$browser}";
color: map-get($config, font-color);
background-color: map-get($config, background-color);
}
}
# requireオプションでsass-json-varsを指定してコンパイル
bundle exec sass style.scss style.css -r sass-json-vars
{
"themes": {
"chrome": {
"user-agent": "chrome",
"font-color": "red",
"background-color": "blue"
},
"firefox": {
"user-agent": "firefox",
"font-color": "blue",
"background-color": "white"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment