コード書く用のTumblrカスタマイズ


##テーマ
Effectorをベースにする

##Tumblrデザイン設定
###組み込み変数
Tumblrであらかじめ定義されている変数。ブログタイトルや日付、投稿者アイコン等が取得できる。
block変数でHTMLを囲むことで、データが含まれていれば出力するといった制御が可能。

[カスタムHTMLテーマの作成](http://www.tumblr.com/docs/ja/custom_themes+)

###ローカライズ
Tumblrではあらかじめローカライズ文字列変数が定義されている。

[テーマのローカライズ](http://www.tumblr.com/docs/ja/localizing_themes)

###カスタム変数

Tumblrではメタタグで下記の変数を定義でき、HTMLの中で使用することが可能。
メタタグで定義された変数は、デザイン設定で値の設定が可能になる。

1. カラー変数(color:<varipableName>)
2. フォント変数(font:<variableName>)
3. 画像変数(image:<variableName>)
4. Boolean変数(if:<variableName>)
5. 外部サービスのユーザ名やIDなどを埋め込む(text:<variableName>)
	
※ 条件判定用にBlock:If変数も同時に定義される(変数名のスペースは削除される)。使い方は、組み込みのblock変数と同じ。

###変数の追加の仕方
HTMLにメタタグを追加し保存した後に、ブラウザタブを再起動すると、デザイン設定に項目が追加される

***追加変数***
- text:Google Custom Search ID: (query: cx)

***定義済みメタタグ抜粋***

```meta.html
	<meta name="color:Background" content="#e6ebea"/>
	<meta name="color:Colored Area Text" content="#fffadc"/>
[…]
	<meta name="color:Outside Link Hover" content="#131313"/>
	<meta name="color:Outside Text" content="#616566"/>
	<meta name="font:Inside Heading" content="Helvetica Neue, Arial, sans-serif"/>
	<meta name="font:Inside Text" content="Georgia, serif"/>
[…]
	<meta name="font:Outside Text" content="Helvetica Neue, Arial, sans-serif"/>
	<meta name="image:Background" content=""/>
	<meta name="image:Banner" content=""/>
[…]
	<meta name="image:Logo" content=""/>	
	<meta name="if:Align Top Menu Left" content="0"/>
	<meta name="if:Automatic Headings" content="0"/>
[…]
	<meta name="if:Top Menu With Labels" content="0"/>
	<meta name="text:Behance Username" content=""/>
	<meta name="text:Cargo URL" content=""/>
[…]
	<meta name="text:Google Analytics Web Property ID" content=""/>
	<meta name="text:Google URL" content=""/>
    <meta name="text:Google Custom Search ID" content="" />
[…]
	<meta name="text:github Username" content=""/>
```

##Tumblrコードハイライトと最新エントリ読み込み
コードハイライトライブラリ [Snippet::jQuery](http://www.steamdev.com/snippet/)

- TumblrのjQueryバージョンが古く、そのままだと使えないため、jQuery 1.7.1を先に読み込んで、jQueryを即時関数で束縛している
- デフォルトの言語以外に追加しているものあり
	- shjsというハイライトライブラリがベースになっているため、そこで定義されている言語を流用できる http://shjs.sourceforge.net/lang/

###スクリプトファイルの読み込み

```tumblr.html
<!-- line:205 -->
<!-- Load files -->
    <!-- Customize script, css -->
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <link rel="stylesheet" type="text/css" href="http://steamdev.com/snippet/css/jquery.snippet.min.css" />
    <script type="text/javascript" src="http://www.steamdev.com/snippet/js/jquery.snippet.min.js"></script>
    <script type="text/javascript" src="http://shjs.sourceforge.net/lang/sh_changelog.min.js"></script>
    <script type="text/javascript" src="http://shjs.sourceforge.net/lang/sh_diff.min.js"></script>
    <script type="text/javascript" src="http://shjs.sourceforge.net/lang/sh_glsl.min.js"></script>
    <script type="text/javascript" src="http://shjs.sourceforge.net/lang/sh_latex.min.js"></script>
    <script type="text/javascript" src="http://shjs.sourceforge.net/lang/sh_log.min.js"></script>
    <script type="text/javascript" src="http://shjs.sourceforge.net/lang/sh_m4.min.js"></script>
    <script type="text/javascript" src="http://shjs.sourceforge.net/lang/sh_makefile.min.js"></script>
    <script type="text/javascript" src="http://shjs.sourceforge.net/lang/sh_properties.min.js"></script>
    <script type="text/javascript" src="http://shjs.sourceforge.net/lang/sh_scala.min.js"></script>
    <script type="text/javascript" src="http://shjs.sourceforge.net/lang/sh_sh.min.js"></script>
    <script type="text/javascript" src="http://shjs.sourceforge.net/lang/sh_spec.min.js"></script>
```

###最新の投稿リスト作成とコードハイライト処理
- 前半が、投稿リストの作成処理
- 後半のDOM readyの部分が、コードハイライト処理
	- 投稿でコードハイライトを使う場合、preタグに各言語のクラス属性をつける
	- 付与するクラス属性は、各言語のファイル拡張子に従ったつもり

```js:Tumblr.js
<!-- line: 220 -->
    var tumblr = function() {};
    // HACK: Binding jQuery object in immidiate function for jquery.plugins.
    (function($) {	  // Binding jQuery v1.7.1 because of old version.(@see Footer Scripts).
        tumblr = function(resp) {
            var posts = resp.posts;
            $('#blog .loading').replaceWith('<ul/>');
            $ul = $('#blog ul');
            // Create recent entries and count tags.
            for (var i=0; i<posts.length; i++) {
                var p = posts[i];
				// post-type: regular, photo, quote, link, conversation, video, audio.
				// title property name: title(regular), text(link, etc.)
				var type = p.type;
				var title = p[type + '-title'] || p[type + '-text'] || p['slug'] || 'No title';
				$ul.append('<li><a href="'+p['url']+'">'+title+'</a></li>');
            }
        }

        $(document).ready(function() {
            var snippetOpts = {style: 'vim'};
            // Code syntax highlight(defaults).
            $("pre.c").snippet("c", snippetOpts);
            $("pre.cpp").snippet("cpp", snippetOpts);   // C++
            $("pre.cs").snippet("csharp", snippetOpts); // C#
            $("pre.css").snippet("css", snippetOpts);	// CSS
            $("pre.flex").snippet("flex", snippetOpts);	// Flex
            $("pre.html").snippet("html", snippetOpts);	// HTML
            $("pre.java").snippet("java", snippetOpts);	// Java
            $("pre.js").snippet("javascript", snippetOpts);	// Javascript
            $("pre.jsdom").snippet("javascript_dom", snippetOpts);  // Javascript With HTML, in <script>.
            $("pre.pl").snippet("perl", snippetOpts);
            $("pre.php").snippet("php", snippetOpts);
            $("pre.py").snippet("python", snippetOpts);
            $("pre.rb").snippet("ruby", snippetOpts);
            $("pre.sql").snippet("sql", snippetOpts);
            $("pre.xml").snippet("xml", snippetOpts);
            // Extend snippet's language support(require load <script>).
            $("pre.changelog").snippet("changelog", snippetOpts);
            $("pre.diff").snippet("diff", snippetOpts);
            $("pre.vert, pre.frag").snippet("glsl", snippetOpts);   // OpenGL
            $("pre.tex").snippet("latex", snippetOpts);
            $("pre.log").snippet("log", snippetOpts);
            $("pre.m4").snippet("m4", snippetOpts);
            $("pre.make, pre.makefile").snippet("makefile", snippetOpts);
            $("pre.properties").snippet("properties", snippetOpts);	// プロパティファイル
            $("pre.scala").snippet("scala", snippetOpts);
            $("pre.sh").snippet("sh", snippetOpts);   // Shell script.
            $("pre.spec").snippet("spec", snippetOpts);	// RPM spec.
        });
    }(jQuery));
```

##Google Analytics
- 最初からAnalyticsのコードが記述されているが、古いので新しいものを新たに取得して置き換える
- 最初からGoogle Analytics IDのTumblr変数が用意されているので、ハードコーディングされているID(UA-xxxxx)を変数に置き換える(変数は既に定義されているため、デザイン設定にIDを記述する)

```googleAnalytics.html
<!-- line: 273 -->
<!-- {block:…}と{text:…}はTumblrの変数 -->
    <!-- Google Analytics -->
    {block:IfGoogleAnalyticsWebPropertyID}
    <script type="text/javascript">
    	var _gaq = _gaq || [];
		_gaq.push(['_setAccount', '{text:Google Analytics Web Property ID}']);
		_gaq.push(['_trackPageview']);

		(function() {
			var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
			ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
			var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
		})();
    </script>
    {/block:IfGoogleAnalyticsWebPropertyID}
```

##Google Custom Search
- JS読み込み部分とレンダリング部分に分かれているので、読み込み部分をheadタグに、レンダリング部分を検索ボックスを表示する検索フォームのところにおく
	- 検索フォームはトップとサイドバーの2カ所ある
- 検索ID(cx値)のTumblr変数を定義し、デザイン設定で記述する
- ハードコーディングされている検索IDを変数に置き換える
- デザイン設定に検索IDが設定されているかどうかでデフォルトのTumblr検索フォームに切り替えるのに、block:Ifを使う

```googleCustomSearch.html
<!-- line: 287 -->
    <!-- Google Custom Search -->
    {block:IfGoogleCustomSearchID}
    <!-- Put the following javascript before the closing </head> tag. -->
    <script>
    (function() {
        var cx = '{text:Google Custom Search ID}';
        var gcse = document.createElement('script'); gcse.type = 'text/javascript'; gcse.async = true;
        gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
        '//www.google.com/cse/cse.js?cx=' + cx;
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(gcse, s);
    })();
    </script>
    {/block:IfGoogleCustomSearchID}
```

```searchbox_intop.html
<!-- line: 324 -->
			{block:IfNotSearchBoxInSidebar}
			<div id="search">
            <!-- Render Google Custom Search box -->
            {block:IfGoogleCustomSearchID}
            <!-- Place this tag where you want the search box to render -->
            <gcse:searchbox-only></gcse:searchbox-only>
            {/block:IfGoogleCustomSearchID}
            {block:IfNotGoogleCustomSearchID}
                <form id="search-form" method="get" action="/search">
					<span class="left"></span>
					<input type="text" name="q" value="{block:IfDefaultSearchText}{text:Default Search Text}{/block:IfDefaultSearchText}" />
					<span class="right"></span>
				</form>
            {/block:IfNotGoogleCustomSearchID}
			</div>
			{/block:IfNotSearchBoxInSidebar}
```

```searchInSidebar.html
<!-- line: 655 -->
			{block:IfSearchBoxInSidebar}
			<div id="search"><!-- 同じなので省略 [...]  -->
                        </div>
			{/block:IfSearchBoxInSidebar}
```

##テキスト投稿
- 投稿ユーザ名と画像を追加
- 日付を追加
- タイトルにリンクがないので追加

```post.html
<!-- line: 367 -->
			<!-- BEGIN POSTS -->
			{block:Posts}
				{block:Text}
				<div id="post-{postID}" class="post type-text{block:Tags} tag_{URLSafeTag}{/block:Tags}">
					<div class="post-panel">
						<div class="copy">
                            <div class="post-author">{lang:Contributors}<img class="post-avator" src="{PostAuthorPortraitURL-24}" /><span class="post-authorname">{PostAuthorName}</span></div>
                            {block:Date}
                            <h3 class="post-date"><a href="/day/{Year}/{MonthNumberWithZero}/{DayOfMonthWithZero}"><span class="post-date-txt">{Year}-{MonthNumberWithZero}-{DayOfMonthWithZero}</span></a></h3>
                            {/block:Date}
							{block:Title}
    						<h2 class="post-title"><a href="{Permalink}">{Title}</a></h2>
							{/block:Title}
							{Body}
						</div>
				{/block:Text}
```

##サイドバーに最新の投稿リストとタグを表示
- 最新の投稿は、Tumblrの /api/readを使えば取得可能(認証なし)
- タグ取得はライブラリを使う [Tumblr Tag Clouds](http://rive.rs/projects/tumblr-tag-clouds)

```HTML
<!-- line: 718 -->
<!-- Recent Entries and tags -->
            <!-- Recent Entries -->
            <div class="side-box ruled-top">
            <div id="blog">
            <h2>{lang:Newer}</h2>
            <span class="loading">Loading...</span>
            </div>
            </div>
            <script src="/api/read/json?callback=tumblr&amp;num=10" type="text/javascript"></script>
            <!-- Tag cloud -->
            <div class="side-box ruled-top">
            <div id="tagclouds">
            <h2>{lang:Tags}</h2>
            <!--Tumblr Tag Cloud [2012-09-01]-->
            <script type="text/javascript" src="http://rive.rs/javascripts/tumblr.min.js?css=default&minsize=120&maxsize=280&order=frequency&math=linear"></script>
            </div>
            </div>
```

##Custom CSS

気になるところを修正
- Google検索フォームがちょっとでかいので縮小
- 投稿タイトルが小さいの拡大
- 投稿でヘディングタグを使った場合のフォント調整
- 全体的に文字が小さめなのでちょっと拡大
- 追加した投稿日付の装飾
- Snippetコードハイライトのフォントがでかいので縮小

```custom.css
/* 検索ボックスの幅調整 */
#search { width: 230px; }
/* 投稿タイトルのフォント調整 */
.content-700 .copy .post-title { font-size: 28px; }
/* 投稿内でヘッダを使ったときのフォント調整 */
h2 { font-size: 24px; }
h3 { font-size: 20px; }
h4 { font-size: 16px; }
/* 全体的にフォントを大きく */
.post { font-size: 108%; }
/* 投稿日付の装飾 */
.post-date-txt {
  background-color: rgba(0, 0, 0, 0.75);
  color: white;
  padding: 5px 30px 5px 10px;
}
/* コードハイライトのフォント調整 */
.sh_sourceCode { font-size: 85%; }
/* <code> color */
code {
  padding: 2px 4px;
  color: #d14;
  background-color: #f7f7f9;
  border: 1px solid #e1e1e8;
  font-size: 85%;
}
/* 投稿者名と画像の調整 */
.copy .post-author {
  position: absolute;
  right: 30px;
}
.copy .post-avator {
  vertical-align: middle;
  margin: 0 0.5em;
}
```