JSONを使ってSassとJavaScriptで設定値を共有する方法
{
"themes": {
"chrome": {
"user-agent": "chrome",
"font-color": "red",
"background-color": "blue"
},
"firefox": {
"user-agent": "firefox",
"font-color": "blue",
"background-color": "white"
}
}
}
# requireオプションでsass-json-varsを指定してコンパイル
bundle exec sass style.scss style.css -r sass-json-vars
@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);
}
}
# 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"
}
}
$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;
%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);
}
}
body.chrome {
content: "chrome";
color: "red";
background-color: "blue"; }
body.firefox {
content: "firefox";
color: "blue";
background-color: "white"; }
# 適当な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
@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;
}
.output {
content: json_encode($variables);
}
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'));
});
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 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);
}
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"; }
他にもあるかもしれないけど、現状こんな感じでしょうか。