なんとなく…改め、Vue.jsでCSSスタイルガイド作成に挑戦
一体型VRヘッドセット『Oculus Go』がそろそろ発売されるのではないかと、ドキドキしながら待っている kouraku です。おはこんばんちわ。199$という低価格にも関わらず、スペックがそれなりにあるらしい・・・ので、ここから一気にVRユーザーが増えてくれるのではないか、と期待をしています。
さてさて、前回は Vue.js を使ってみたら、もしかしたらCSSのスタイルガイドが作れちゃうんじゃないの!?・・・ということで、marked.js と highlight.js を導入して見た目を整えたり、サンプルコードの下にサンプル表示を追加してみました。
これだけでもスタイルガイドの形に近づいて気がしますが、更にスタイルガイドとして機能させるために、色々と追加していこうと思います。
表示仕様を変更してみる
前回までの表示は、読み込んだ style.css のテキストデータに対して加工を施し配列に加え、そのまま表示しただけでした。よって、クラスの定義と定義の間に「,」といった不要な表示がされたりして、スタイルガイドとしてはあまりにも不十分すぎる状態です。
ということで、まずはこの表示の仕様に手を加えてみたいとおもいます。やりたいことは・・・
- 各定義の説明を styles[n]['html'] に格納。
- v-for を使用して、styles[n]['html'] を表示。
といった感じです。
では、まずJSから変更を加えていきます。基本的な流れは同じですが・・・ちょこちょこ変数を変えてます。。。
[guide.js]
:
axios.get('./style.css')
.then(function (response) {
var res = response.data.match(/\/\*docs[\s\S]*?\*\//gm); // <- 直接 data ではなく、res に格納
var data = []; // <- data を配列として定義
res.forEach(function(v,i,a) {
// コメント開始・終了削除
a[i] = a[i].replace(/\/\*docs[\s\S]/, '').replace(/[\s\S]\*\//, '');
// sample表示用HTML取得
var sample = a[i].match(/\`\`\`html[\s\S]*?\`\`\`/gm);
// Markdown形式に変換
a[i] = marked(a[i]);
// sample表示用HTMLが存在する場合、サンプル枠を追加
if (sample !== null) {
sample = sample[0].replace(/\`\`\`html[\s\S]/, '').replace(/[\s\S]\`\`\`/, '');
a[i] = a[i] + '<div class="sample">' + sample + '</div>';
}
// dataにsample表示用HTML追加
data[i] = {
html: a[i]
};
});
app.set(data);
})
.catch(function (error) {
console.log(error);
});
:
前回のものに追加した内容は、「dataにsample表示用HTML追加」の処理の部分が主です。
そして、HTMLは v-for を使って以下のように書き換えます。
[index.html]
:
<div id="app">
<div v-for="style in styles">
<div v-html="style.html"></div>
</div>
</div>
:
すると、結果は・・・
あまり見た目は変わっていませんが、まず各定義間の「,」はなくなり、また開発者ツールで生成されたHTMLを確認すると、各定義が div で囲まれていることが分かります。
パラメータを追加してみる
スタイルガイドっぽくなるように、更に手を加えたいと思います。次に追加するのは、title, name, category といったパラメータです。
- title: 定義の見出しとして使用。
- name: 並び順などで使用。(ゆくゆくはページ内リンク用のidとして使用したい)
- category: btn, text, link といったカテゴリとして使用。
ということで、まずは style.css を以下の様に準備します。
[style.css]
* {
box-sizing: border-box;
}
/* text */
/*docs
---
title: .text-red
name: text-red
category: text
---
テキストカラー:<span class="text-red">赤■</span>
```html
<span class="text-red">.text-red</span>
```
*/
.text-red {
color: #f66;
}
/*docs
---
title: .text-blue
name: text-blue
category: text
---
テキストカラー:<span class="text-blue">青■</span>
```html
<span class="text-blue">.text-blue</span>
```
*/
.text-blue {
color: #66f;
}
/*docs
---
title: .text-green
name: text-green
category: text
---
テキストカラー:<span class="text-green">緑■</span>
```html
<span class="text-green">.text-green</span>
```
*/
.text-green {
color: #6A6;
}
/* button */
/*docs
---
title: .btn-1
name: btn-1
category: btn
---
ボタン1
```html
<p><a href="DUMMY" class="btn-1">ボタン1</a></p>
<button class="btn-1">ボタン1</button>
```
*/
button.btn-1 {
-webkit-appearance: none;
-moz-appearance: none;
}
.btn-1 {
display: inline-block;
min-width: 140px;
padding: 5px 10px;
border: 1px solid #aaa;
border-radius: 3px;
background: #fff;
outline: none;
color: #333;
font-size: 14px;
text-align: center;
text-decoration: none;
transition: background .2s ease-in-out;
cursor: pointer;
}
.btn-1:hover {
background: #eaeaea;
}
パラメータの設定は、「---」で区切られた範囲で行うようにします。
では、設定されたパラメータを各定義毎に格納するよう、guide.js に処理を書き足します。
[guide.js]
:
axios.get('./style.css')
.then(function (response) {
var res = response.data.match(/\/\*docs[\s\S]*?\*\//gm);
var data = [];
res.forEach(function(v,i,a) {
var info, html, sample;
var title = '';
var name = '';
var category = '';
html = a[i];
// 情報取得
info = html.match(/\-\-\-[\s\S]*?\-\-\-/gm); // <- パラメータの箇所を抜き出す
if (info !== null) { // <- パラメータが存在した場合
if (info[0].match(/title: ?(.*)[\s\S]/) !== null) { // <- title取得
title = info[0].match(/title: ?(.*)[\s\S]/)[1];
}
if (info[0].match(/name: ?(.*)[\s\S]/) !== null) { // <- name取得
name = info[0].match(/name: ?(.*)[\s\S]/)[1];
}
if (info[0].match(/category: ?(.*)[\s\S]/) !== null) { // <- category取得
category = info[0].match(/category: ?(.*)[\s\S]/)[1];
}
}
// sample表示用HTML取得
sample = html.match(/\`\`\`html[\s\S]*?\`\`\`/gm);
// 不要情報削除
html = html.replace(/\/\*docs[\s\S]/, '')
.replace(/[\s\S]\*\//, '')
.replace(/\-\-\-[\s\S]*?\-\-\-/gm, '');
// Markdown形式に変換
html = marked(html);
// sample表示用HTMLが存在する場合、サンプル枠を追加
if (sample !== null) {
sample = sample[0].replace(/\`\`\`html[\s\S]/, '').replace(/[\s\S]\`\`\`/, '');
html = html + '<div class="sample">' + sample + '</div>';
}
// dataにsample表示用HTML追加
data[i] = {
title: title, // <- title格納
name: name, // <- name格納
category: category, <- category格納
html: html
};
});
app.set(data);
})
.catch(function (error) {
console.log(error);
});
:
次に、method の set で、Vue.set の際に name でソートした内容を受け渡すようにします。
[guide.js]
:
methods: {
set: function(data) {
Vue.set(app, 'styles', data.sort(function(a, b) {
return (a["name"] > b["name"]) ? 1 : -1;
}));
}
}
:
体裁を整えるために、index.html と guide.css にも手を加えました・・・が、ここはどうでも良いので省きます。
結果・・・こんな感じになりました。
おぉ・・・大分イメージしているスタイルガイドに近づいてきました!
しめ
妄想で始めたものが、徐々に完成に近づいている・・・そう思えるようになった今回ですが、次回はパラメータとして用意している category を使って、絞込表示やホーム画面などを作りたいと思います。これができたら、ほぼ完成ですよね。
そうそう、『Oculus Go』の話ですが、こいつは確かにコスパの面ではこれまでにないほどのものだとは思うのですが・・・人間はホント次から次へと欲が出てしまうものですね。この記事を書いている間にも、やはり『Oculus Go』より、ちゃんと位置トラッキング機能を実装している『Santa Cruz』の発売を待ったほうが良いのでは・・・なんて思い始めた今日このごろでした。