Building customized bootstrap theme

なんかタイトルの英語が間違ってたらごめんなさい。
備忘録です。

今職場でAccess + SQLServer2005 で作られている業務用のデスクストップアプリケーションをウェブシステム化する仕事を、本来の業務と並行で行っているのですが、僕が一番苦手なUIデザイン、モバイル携帯向けの含めて、どうしようか・・・と考えたとき、やっぱりネットでの情報が比較的多いbootstrapで・・・となりますよね💦

そこで問題になるのはやっぱりブートストラップ臭が・・・ということでしょうか。。。僕は古いタイプの人間なんで愚直に一個一個CSS、セレクタ、プロパティをガシガシ上書きしてました。これが実に苦痛で。。。

そこで、bootstrap4に移行するついでにSASSでカスタマイズするフローを学ぼう、というわけです(^▽^)/

bootstrap4のテーマの変更(Themingって日本語でなんていうんだ?)の仕方って、ググればググるほど、一体何が正解なんだ?という気になります。僕はGulpとか、gruntとか、webpack とか・・・ググらないと分からない・・・というレベルのオッサンでなんで、今時のトレンデーな、マックブック片手にバリバリ仕事をこなしている、最先端イってるイケてる人たちから見ると、アホかいな?というレベルの備忘録ですので、あらかじめご了承のほど。

余談です。フロントエンド開発が何を意味しているのか僕は正直わかんないです。最近は特についてけないです。Gulpとかgruntとかwebpackとか無縁の職場で、ナニソレ、おいしいの? いや普通に bootstrapの色を変えたり、角丸なくしたり、したいだけなんですぅ。未だに git じゃなくて svn だしぃ。

さて、まずはともかく、本家本元の手順に従いましょう。
ビルドツールのインストールです。https://getbootstrap.com/docs/4.3/getting-started/build-tools/
僕は Windowsユーザーなので、WSL(ubuntu16.04)を使用します。

(1) Node.js のインストール・・・これは適当に入れる。僕は以下の手順でいれます。
一旦aptでインストールし、nパッケージを入れ最新のものに入れ替えた後、apt removeします。

$ sudo apt install -y nodejs npm
$ sudo npm cache clean
$ sudo npm install n -g
$ sudo n stable
$ sudo ln -sf /usr/local/bin/node /usr/bin/node

$ sudo apt purge -v nodejs npm

(2) 上記サイトでは ruby のインストールも書かれていますが、テーマの変更だけしたい場合には必要ないと思います。まぁ、今時の開発者なら ruby は初めからインストールしているでしょうし・・・割愛(^^;

(3) 本家からbootstrapのソースをダウンロードし、適当なディレクトリに展開し、そのディレクトリで npm install で依存しているパッケージをインストールし、npm run css とすると、dist ディレクトリに css がコンパイル、ミニファイされたcssができあがります。

さて・・・ここからが本題です。

本家サイトのTheming(https://getbootstrap.com/docs/4.3/getting-started/theming/)を見るとカスタマイズ方法が書かれていますが・・・おそらくNode.jsに詳しくない、あるいは初めて触る人にとっては、そのページは何の参考にもなりません。。。custom.scssを作って・・・とか書いてますが・・・それで?って感じです。
scssファイルからcssをコンパイルおよびミニファイする具体的な手順とかほとんど書かれていません。

このあたりをググってみても、上記のgulpだの、gruntだの webpackだの、の手順とかがヒットして、オッサンが一番知りたい事の情報がでてきません。単に探し方が悪いのかも。。。
そこで自分なりに調べた結果、以下の手順でカスタマイズするフローに辿り着きました。

以下のフローでは、オリジナルのbootstrapには一切手を付けません。バージョンが上がるといろいろ困りますからね。
具体的なテーマをカスタマイズする方法は、本家サイトの Theming ページを参考にしてもらい、ここでは自分が用意したカスタマイズ用の.scssファイルを、どのように配置して、どのようにビルドするのかを書き留めておきます。

(0) 前準備として・・・

git がインストールされていなければインストールしときます。bootstrapのソースは git clone で取るようにしますんで。

(1) 作業用に適当なディレクトリを作り・・・

以下のようにディレクトリ・ファイルを配置します。。。各ファイル(a,b,c1~3)については後述します。

$ tree -n
.
├── babel.config.js  (a)
├── bootstrap (bootstrapのソースを置くディレクトリ)
├── dist (コンパイルされた css/js の置き場)
│   ├── css
│   └── js
├── package.json (b)
└── scss
    ├── custom-bootstrap-grid.scss (c1)
    ├── custom-bootstrap-reboot.scss (c2)
    └── custom-bootstrap.scss (c3)

(a) babel.config.js

bootstrapのソースにある、.babelrc.js をコピーしてこの名前にリネームします。JSファイルをコンパイルする際に単純にコピーして配置しただけだとエラーになってしまいました。理屈は知りません。すみません。npm-babelのサイトを斜め読みしたら、このファイル名に行きつきました💦

(b) package.json

これもbootstrapのソースにある、package.json をそのままコピーし、カスタマイズ用に修正しました。僕にとっては要らない機能もあるので逐一調べて不要なものを削除しまくり、以下のコードに行きつきました。内容については・・・よく分かりません。調べてください。すみません。

package.jsonは、npm(node package manager)が管理するファイルで、scriptsっていうキーにコマンド名、値に実行するコマンドラインを記述していくみたいです。
npm run コマンド名 で、そのコマンド名の値のコマンドラインが実行される、みたいな。makeみたいなもんか?

長くなりましたが、コピーした package.jsonファイル内のパス指定されている部分を修正したり、単体テストとかlintとか、サーバー機能、ドキュメントの構築などのビルドツールは基本必要ないので、片っ端から削除しました。テーマのカスタマイズ用にcss/jsのビルドさえできればいいという事にフォーカスしています。

通常はファイルを修正したら即反映されるような監視タスクを入れるのが開発のセオリーみたいなのですが・・・あれもこれもとやってると、結局、開発環境構築オタクになってしまうんで、やめときます。開発環境を作りたいんじゃなくて・・・コードを書くのが目的!

{
  "name": "custom-bootstrap",
  "description": "custom bootstrap4",
  "scripts": {
    "clone-bootstrap": "git clone https://github.com/twbs/bootstrap.git -b v4.3.1 --depth 1 bootstrap",
    "css": "npm-run-all css-compile css-prefix css-minify",
    "css-main": "npm-run-all css-compile-main css-prefix-main css-minify-main css-copy",
    "css-compile": "npm-run-all --parallel css-compile-*",
    "css-compile-main": "node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/custom-bootstrap.scss dist/css/bootstrap.css && node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/custom-bootstrap-grid.scss dist/css/bootstrap-grid.css && node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/custom-bootstrap-reboot.scss dist/css/bootstrap-reboot.css",
    "css-minify": "npm-run-all --parallel css-minify-*",
    "css-minify-main": "cleancss --level 1 --format breaksWith=lf --source-map --source-map-inline-sources --output dist/css/bootstrap.min.css dist/css/bootstrap.css && cleancss --level 1 --format breaksWith=lf --source-map --source-map-inline-sources --output dist/css/bootstrap-grid.min.css dist/css/bootstrap-grid.css && cleancss --level 1 --format breaksWith=lf --source-map --source-map-inline-sources --output dist/css/bootstrap-reboot.min.css dist/css/bootstrap-reboot.css",
    "css-prefix": "npm-run-all --parallel css-prefix-*",
    "css-prefix-main": "postcss --config bootstrap/build/postcss.config.js --replace \"dist/css/*.css\" \"!dist/css/*.min.css\"",
    "js": "npm-run-all js-compile js-minify js-move",
    "js-main": "npm-run-all js-lint js-compile js-minify-main",
    "js-compile": "npm-run-all --parallel js-compile-*",
    "js-compile-standalone": "rollup --environment BUNDLE:false --config bootstrap/build/rollup.config.js --sourcemap",
    "js-compile-bundle": "rollup --environment BUNDLE:true --config bootstrap/build/rollup.config.js --sourcemap",
    "js-compile-plugins": "node bootstrap/build/build-plugins.js",
    "js-minify": "npm-run-all --parallel js-minify-main",
    "js-minify-main": "npm-run-all js-minify-standalone js-minify-bundle",
    "js-minify-standalone": "uglifyjs --compress typeofs=false --mangle --comments \"/^!/\" --source-map \"content=bootstrap/dist/js/bootstrap.js.map,includeSources,url=bootstrap.min.js.map\" --output bootstrap/dist/js/bootstrap.min.js bootstrap/dist/js/bootstrap.js",
    "js-minify-bundle": "uglifyjs --compress typeofs=false --mangle --comments \"/^!/\" --source-map \"content=bootstrap/dist/js/bootstrap.bundle.js.map,includeSources,url=bootstrap.bundle.min.js.map\" --output bootstrap/dist/js/bootstrap.bundle.min.js bootstrap/dist/js/bootstrap.bundle.js",
    "js-move": "cross-env-shell shx mkdir -p dist/js && cross-env-shell shx cp -r bootstrap/dist/js dist/",
    "dist": "npm-run-all --parallel css js",
    "dist-clean": "cross-env-shell shx rm -f dist/{js,css}/*"
  },
  "devDependencies": {
    "@babel/cli": "^7.2.3",
    "@babel/core": "^7.2.2",
    "@babel/plugin-proposal-object-rest-spread": "^7.3.2",
    "@babel/preset-env": "^7.3.1",
    "autoprefixer": "^9.4.7",
    "babel-eslint": "^10.0.1",
    "babel-plugin-istanbul": "^5.1.0",
    "bundlesize": "0.15.3",
    "clean-css-cli": "^4.2.1",
    "cross-env": "^5.2.0",
    "find-unused-sass-variables": "^0.3.2",
    "glob": "^7.1.3",
    "node-sass": "^4.11.0",
    "npm-run-all": "^4.1.5",
    "postcss-cli": "^6.1.1",
    "rollup": "^1.1.2",
    "rollup-plugin-babel": "^4.3.2",
    "rollup-plugin-commonjs": "^9.2.0",
    "rollup-plugin-node-resolve": "^4.0.0",
    "shelljs": "^0.8.3",
    "shx": "^0.3.2",
    "uglify-js": "^3.4.9"
  },
  "engines": {
    "node": ">=6"
  }
}

上記 scripts を見てもらえれば、だいたい何をやってるのか分かると思います。
devDependencyは・・・必要なnodeプログラムの一覧?で、npm install すると、これらのプログラムが node_modules ディレクトリにインスコされるみたいですぅ。知らんけど。知らんけど。

(c1 ~ c3)bootstrapの下記ファイルをそれぞれインポートしてカスタマイズするファイルです。

  • bootstrap/scss/bootstrap.scss
  • bootstrap/scss/bootstrap-grid.scss
  • bootstrap/scss/bootstrap-reboot.scss

これは Theming でも説明されています。各ファイルの内容は・・・

/*******************************************************************************
 ファイル名: ./scss/custum-bootstrap.scss
ここに bootstrap本体の変数SASS を記述(上書き)していく。
その方法は、Theming を参照のこと。
*******************************************************************************/
$primary:  orange; 
.
.
.

/* ソース本体をインポート */
@import "../bootstrap/scss/bootstrap";

./scss/custom-bootstrap-grid.scss、./scss/custom-bootstrap-reboot.scss も同様です。

これらの./scss/custum-bootstrap*.scssを自分用にカスタマイズを施したあと、最後はビルドします。
カスタマイズは、主にbootstrap/scss/_variables.scss の中で定義されている変数を変更したりするのがカスタマイズの中心になってくると思います。もちろん、独自のスタイルを定義したければ、ここに書きます。

(2) コンパイル処理

./scss/custom-bootstrap*.scss の編集が終わったら、ビルドします。
順番としては、bootstrapソースを取得してから、npm run dist します。
distは、js,cssを一緒にやる感じです。

# まず、bootstrapのソースをbootstrapディレクトリに取得し、格納します。
# package.json を見ればわかりますが、git clone しているだけです。
$ npm run clone-bootstrap

# もし css/js すべてをビルドしたい場合は、dist
$ npm run dist

# css だけ欲しかったら css
$ npm run css

bootstrapをcloneするとき、v4.3.1のブランチを取得していますが、最新のものが必要であれば、”-b v4.3.1″の部分を消す。また”–depth 1″を消すと過去の履歴全部取得するので異常に時間がかかりますので消さない方がいいと思います。

なお、自分でソースをダウンロードする場合は、clone-bootstrapは実行する必要ありません。

lintとかテストとか一切省いているのでエラーが出たら・・・自力で何とかする!

gvim(+kaoriya) + WSL Part2

:prev
この前のつづきです。

シェルをWSL(ubuntu bash)にすることで、:terminalの他、外部コマンド実行(“!” から始まるやつ)をWSL内で完結することができました。
が、ただ一点、:terminal {command} にする場合、:terminal bash -c '{command}' としないとエラーになってしまうので、これが不満。

そこで、Wslterm というユーザー定義のコマンドを _gvimrc に追加することで、ラクしよう、と、こういうわけです(^^;
ヘルプを斜め読みしてとりあえず関数とコマンドの定義の仕方を最低限覚えて、以下の記述に辿り着く。
ほんとはもっとスマートなやり方があるんだと思いますが・・・素人の思いつきです。。。

" terminal の WSLラッパー コマンド (かなり修正:2018/7/13 0:02)
" ・・・なんかトンチカンなことをやってる気がしてきた・・・
" append to ~/_gvimrc 
set shellslash
set shell=C:/WINDOWS/system32/bash.exe
set shellcmdflag=-c
set shellquote=\"
set shellxescape=
set shellxquote=

function! Wslterms(c,f,l,...)
  let cmdline = []
  let option = []
  let i = 0
  while i < a:0
    if stridx(a:000[i],'++') == 0
      call add(l:option,a:000[i])
    else
      call add(l:cmdline,a:000[i])
    endif
    let i += 1
  endwhile
  let l:options = len(l:option) ? join(l:option," ")." " : ""
  let l:cmd = "terminal " . l:options

  if len(l:cmdline) > 0
    let l:cmd = printf("%s%s %s %s",l:cmd,&shell,&shellcmdflag,shellescape(join(l:cmdline," ")))
  endif

  if a:c 
    let l:cmd = join([a:f,a:l],",") . l:cmd
  endif

  execute(l:cmd)
endfunction
command! -nargs=+ -complete=file -range=0 Wslterm call Wslterms(<count>,<line1>,<line2>,<f-args>) 

これで、:Wslterm perl %とか、’<,'>Wslterm hogehoge とかやると、bash -c をつけて簡易的に :terminalの真似ができました(^^;; おまけで、gvimのterminalの中で、WSL(ubuntu)内のvimでファイルを編集(左)とかできちゃう!w

ただ、vim自体操作は慣れてきたとはいえ、まだよく分かっていないのでこういうアプローチでいいのか、よく分かんないです。またvimスクリプトの本でも買って勉強しよ。

■補足 2018/09/24
guioptions に “!” を追加すると :shell コマンド時、コンソールウィンドウが立ち上がるのではく、gVimのウィンドウを使用するみたい。知らんかった・・・・。

:set guioptions+=!

_gvimrcに書いとくと、かなりイケてる感が味わえるかも(^^;
ちなみに僕の guioptions は・・・

"snip
guioptions=egmrL!
"snip

となっております。。。

:continue
つづきは part3で

なんやかんやでエディタ宗旨変え

いろいろあって転職を思案中。持病持ち・身障者オッサンの転職は正直厳しく難しい。後片付けしながら就活するか、雇用保険もらいながらダラダラとやるか・・・。年度内で一区切りしようと思っているけど、どっちにしろメンドっちーなー。

そんなことはともかく。。。

10数年以上、テキストエディタはxyzzyを使っていました。
なんの不満もなく、僕的には最強のエディタだと、自分に言い聞かせ(^^;使っていました。ここ最近は Linuxなどの非WindowsなOSをいじることが多くなって、そういう時は操作感が非常に似通っているEmacsを、と使い分けていたのですが・・・Emacsを使えないサーバーが多々あり、やむなく 端末上で vim を使う練習・・・というか修行をここ1年ほどしてました。

最近・・・xyzzy で CTRL-N,CTRL-P,CTRL-B,CTRL-F でカーソル移動するところを・・・気付けば J,K,H,L と、打ち間違うことが多発 トホホ(笑)

で!、なんの気なしに『Windows版のGUIなvim ってあるのかな・・・?』と探している自分が居まして・・・、Kaoriya版のWindows向けvimをインストールして、まずはシェルスクリプトを編集するときだけ、gvim を極たまに使っておりました。
この頃はまだ、xyzzy 最強ー、と思ってました。vimってやっぱ、使いにくい!!! なんだ、あの、ノーマルモードやら挿入モードやらコマンドモードやらを行ったり来たりめんどくせーーーー、って。

でも、amazonで買ったkindle版の解説本で紹介されていた、vim-surroundというプラグインを知り、このプラグイン、すげー、カッコやら引用符やら、波カッコの挿入、変更、削除が一発でできるやん!!!ってことにコロッと一目ぼれして、気づけば、ソースコードファイルの拡張子をレジストリいじって gvim に関連付けしてた(ーー;

僕的に↓良書。
思考のスピードで編集しよう! (アスキー書籍)

でもWindows版 だと外部コマンド実行の時、コンソールウィンドウが開いてダサーーってなる。
んー、まぁ、このダサさもWindowsの味なんで・・・(^^;

あと、エディタで使うフォントでしっくりくるものが未だに見つからない。

それに英語配列以外のキーボードだと激しく使いづらい。。。まぁこれは慣れの問題だけども。

それと、vim使ってない時の他のアプリでテキスト入力するとき時で、入力が終わった後なんでもかんでもCTRL-[ をタイプしてしまうという謎の癖がついてしまった・・・orz

xkeymacs + Windows10

2018年4月8日 追記
ようやく設定プロパティダイアログの修正が入ったものがリリースされた模様。待ってました!ってなわけでここに置いてあるのは削除しました。


そろそろプロパティダイアログの修正入っているのかなぁ・・・と思って久しぶりにxkeymacsのページを覗いたけど、現状で安定しているのかsnapshotが6年前で止まってた。まぁ、Windows10でもちゃんと動いているんだし(^^;
snapshotのリリースは止まっていたけど、ソース自体は更新されていたので、最新のソースをダウンロードしてVisual Studio 2015 Community でビルドした。
ビルドする前に設定ダイアログのサイズをちょっと伸ばしてプロパティシートが切れないのようにちょっとだけ伸ばす。これは↓と同じ(^^;

Windows8.1用にxkeymacsをビルド

スクリーンテキストのサイズは100%でしか使わないのでOK。
プロパティの部分だけ(GUIの部分だけ)C# .Net Frameworkとかで書けば多分解決するんでしょうけど、いかんせん、MFCのソースは僕には皆目読めません。。。読む気ありません。。。ただでさえC++忘れかけてるのに・・・。C++ TR1ぐらいがギリついてけるが、C++11規格とかもうサッパリ・・・。Cに至ってはもうC90ぐらいでも今となってはついていけるかも怪しい。。。

ってなわけで、どこからでもダウンロードできるように、リンク貼っておこう。
Rev.8799a18のものをVisual Studio 2015 Community Editionでビルドしたやつ

Windows8.1用にxkeymacsをビルド

追記 2015/8/14
たぶん、画面のサイズを125%とか150%にするとまたボタンが隠れてしまいます。根本的な解決にはならないのでご注意ください。


Surface3にxkeymacsをセットアップして立ち上げたけど、プロパティダイアログで、ボタンが隠れる問題に直面(^^;

xkeymacs-8.1

ダイアログリソースをいじればいいや、と思いxkeymacs-snap-110830のソースをダウンロードしてVisual C++ 2010 Express Edition + WDKでビルドしたんですが、以下のエラーでストップ。

Utils.cpp(461): error C2039: 'GetString' : 'CString' のメンバーではありません。

ふむふむ、GetStringがないんだったら、強引にキャストしてまえ!ってことで、

//修正前
memcpy(pMem, text.GetString(), nLength);

//修正後
memcpy(pMem, (LPCSTR)text, nLength);

で切り抜け。

xkeymacs.rcだけVisual Studio Communityで適当にサイズ修正。
プロパティーシートで使用されるフォントがメイリオになってしまうのが原因?
ソース追えるほどMFCに精通していないため、ダイアログリソースだけ場当たり的に修正してビルド。

今度はちゃんとボタンが表示されました。

xkeymacs-8.1-2

めでたし!

ファイルの置き場に置いてます (xkeymacs-only-win8.1) 無保証

最後にリリースされてから4年と久しくバージョンアップされていないようですが、
Windows10も出ることですし、ダイアログ関連のメンテナンスリリースしてほしい<m(__)m>