Tweeki
Tweeki という MediaWiki の Skin(外装)を導入したので、設定の備忘録。
詳しくは公式の解説を参照。
- mw:Skin:Tweeki(英語)
- Tweeki = Mediawiki + Twitter Bootstrap(公式ホームページ、英語)
経緯
以前使っていたカスタムSkin(公開されている外装を大幅改造したもの)が、MediaWiki 1.28 への更新に伴い使えなくなってしまったので、他のSkinを探していて見つけた。
Tweeki では Twitter Bootstrap を採用し、responsive design になっており、端末を選ばず見やすくなっている。
見た目にも、他の MediaWiki Skin にありがちな、過剰なナビメニューなどが大胆に省略されている。 一方、既定ではカテゴリなどの一般的に使われている要素や、移動や削除などの管理用メニューも表示されないなど、少々癖もある。Wikipediaでお馴染みの左上に大きく表示されるロゴも、Tweekiでは標準で非表示になっている(設定すれば表示できる)。
Wikipediaのような多数の一般編集者がいるサイトには向かないだろうが、個人や団体のサイトなど、編集者が特定少数で、多数の一般閲覧者には編集させないサイトで使うには良い選択肢になりそう。
導入
2.GitHub からダウンロードし、MediaWiki の skins ディレクトリ下に展開する。WebサーバにSSHログインできれば git clone(下記)が手軽。GitHub からリリース版 (zip, tar.gz) をダウンロードもできる。
% cd /path/to/mediawiki/skins % git clone https://github.com/thaider/Tweeki
3.LocalSettings.php に、下記を追加。
wfLoadSkin( 'Tweeki' );
$wgDefaultSkin = "Tweeki";
設定
LocalSettings.php
設定例。→公式の解説(英語)
# Tweeki settings
$wgTweekiSkinHideable = array('navbar', 'sidebar-right');
# 本文中に {{#tweekihide}} の記述があるページでのみ非表示にすることができる要素を指定
$wgTweekiSkinHideAnon = array('EDIT', 'EDIT-EXT', 'TOOLBOX', 'TOOLBOX-EXT', 'PERSONAL');
# ログインしていない人に見せない要素を指定
# (編集メニュー、ツールボックス、マイページへのリンクボタンを指定)
$wgTweekiSkinFooterIcons = true;
# フッタのアイコン (CreativeCommons, MediaWiki) を表示する
$wgTweekiSkinHideAll['footer-info'] = false;
# フッタの更新日等を表示する
Navigational Sectionsの図にあるように、上下左右の計5面に、表示したい要素を割り当ててゆく。
- MediaWiki:Tweeki-navbar-class - Bootstrap の Navbar
- MediaWiki:Tweeki-navbar-brand - 規定では {{SITENAME}} が入る。画像を貼ることもできる。
- MediaWiki:Tweeki-navbar-left - 規定では空
- MediaWiki:Tweeki-navbar-right - 規定では TOOLBOX,PERSONAL,SEARCH
- MediaWiki:Tweeki-subnav-class - Bootstrap .navに相当。標準で非表示になっているので、表示する場合は LocalSettings.php に設定の追加が必要
- MediaWiki:Tweeki-sidebar-left
- MediaWiki:Tweeki-sidebar-right
- MediaWiki:Tweeki-footer
- MediaWiki:Tweeki-footer-info - 最終更新日など。表示するには $wgTweekiSkinHideAll['footer-info'] = false; の設定が必要。
- MediaWiki:Tweeki-footer-places - Privacy policy, About, Disclaimers
- MediaWiki:Tweeki-footer-custom
- MediaWiki:Tweeki-footer-icons
内部リンクを設定する場合は、[[ ]] で括らず、ページ名|表示名 と記述する。 項目を階層化する場合は、先頭に見出しの文字列を記述し、続いて各子項目の先頭に * を付ける。 例:
このサイトについて,*About|会社概要,*News|ニュースリリース,*Privacy|プライバシーポリシー
編集関連メニューの割り振り
'EDIT' や 'TOOLBOX' が表示されないと編集者には不便なので、適宜使いやすい場所に割り当てておく必要がある。管理用には 'VIEWS' や 'ACTIONS'(履歴表示や移動、削除など)も必要になるだろう。
多数の編集者がいるサイトでTweekiを使う場合は、'PERSONAL' や 'TALK' も必要になるかもしれない。
各項目の詳細は 公式の解説(英語)を参照。
限られた編集者以外は閲覧専用のサイトや、匿名利用者の編集を認めないサイトであれば、ログインしていない場合は編集等のメニューを非表示にできる。 例:
$wgTweekiSkinHideAnon = array( 'EDIT' => true, 'TALK' => true, 'PERSONAL' => true, 'TOOLBOX' => true, 'ACTIONS' => true , 'VIEWS' => true );
または、Tweekiの編集関連メニューは非表示にして、特定の編集者のみ他のSkinを使う方法もある。
HTMLタグの埋め込み
外部リンクは Navigation Sections に直接指定できるようになったが、HTMLの埋め込みは直接指定できず、HTMLets のような拡張機能も使えない(本文に埋め込みたい場合はもちろん使える)。
Navigation Sections にHTMLタグを埋め込みたい場合は、LocalSettings.php 内で関数による定義が必要。このように生成した独自のタグ(下記例では 'MYTAG')を Navigation Sections 内に割り当てることで、HTMLを埋め込むことができる。[1] 例:
$wgTweekiSkinSpecialElements['MYTAG'] = 'tweekiMyTag';
# MYTAG タグが指定されたときに tweekiMyTag 関数を呼び出す
# 呼び出される関数
function tweekiMyTag( $skin, $context ) {
echo '<埋め込むHTMLタグ>';
}
スクリプトの埋め込み
上記から察しの通り、(本文以外の場所に)HTMLタグを埋め込むにはいちいち関数を追加する必要があって面倒だが、見方を変えれば任意のスクリプトを動かすことができる。
PHPを書ける人ならば、セキュリティホールを作らない程度に遊んでみるのも良さそう。
例:接続先(閲覧者)のIPアドレスバージョン(IPv4またはIPv6)を表示する
$wgTweekiSkinSpecialElements['IPV6READY'] = 'tweekiTagIpv6ready';
# [Skin:Tweeki] 接続先(閲覧者)のIPアドレスバージョンを表示する
function tweekiTagIpv6ready( $skin, $context ) {
$myipaddr = getenv('REMOTE_ADDR');
if(preg_match('/^\d+\.\d+\.\d+\.\d+$/', $myipaddr)) {
$myiptype = '4';
} elseif(preg_match('/^\[?[\dabcdef]*\:[\:\dabcdef]+\]?$/i', $myipaddr)) {
$myiptype = '6';
} else {
return;
}
echo "<div id='ipv6ready'><span id='ready'>IPv6 Ready</span> You connected via <span id='ip'>IPv$myiptype</span></div>";
}
※実際に使う場合は、別途スタイルシートで加工してあげましょう。例→MediaWiki:Common.css
記事本文中の記述
表や画像のレスポンシブ化
表に class="img-responsive" を追加すると、サイズの自動追従に対応する。[2]
画像の場合は下記のようにする。
[[File:Screenshot tweeki.png|class=img-responsive]]
- Bootstrapで使われる他のClassも使える(img-rounded, img-circle, img-thumbnail)
- Tweeki以外のSkinでは使えず、表示乱れ等の原因になることもあるので、複数のSkinを併用する場合は要注意。
How-to
目次の一覧表示
目次 (TOC, Table of contents) は規定で sidebar-right に表示される。
規定ではレベル2 <H2> のみが一覧表示されて、クリック/タップされるとレベル3 <H3> 以降が表示される。
見た目にはすっきりするが、一覧性が低く、どこに何が書いてあるか一見して判りづらい難がある。
MediaWiki:Common.css に下記の設定を追加すると、最初から全件が一覧表示されるようになる。
#tweekiTOC #toc ul > li > ul { display: block; }
一方、細かい見出しが出すぎると見づらくなる。細かい見出しを目次に表示したくない場合は、MediaWiki の機能を使い、LocalSettings.php に $wgMaxTocLevel を指定する。 例えば、レベル3 <H3> までを目次に表示したいときは、こうする。
$wgMaxTocLevel = 3;
見出しレベルとは
- ==レベル2== → <H2>
- ===レベル3== → <H3>
- ====レベル4=== → <H4>
- =====レベル5==== → <H5>
- ======レベル6===== → <H6>
見出しレベル1 <H1> は記事のタイトルなので、目次には表示されない。
sidebar-right をスクロールできるようにする
規定では sidebar-right にはスクロールバーが出ないが、ここに目次が表示されるので、全件表示にすると下の方が見切れてしまうことがある。
そこで、MediaWiki:Common.css に下記の設定を追加して、sidebar-right のスクロールを有効にしてやる。
#sidebar-right { overflow: scroll; }
目次を表示する場所を移動したいときは
Tweekiでは、規定では sidebar-right に目次が表示される。#Navigation Sections内のどこにでも移動できるが、TOCを複数表示することはできない。
全ての Navigation Sections にTOCを指定しなければ、MediaWikiの流儀に従い、本文中に表示される。この場合は __TOC__ などのマジックワードも使える。
ただし、規定ではCSSで非表示にされているので、本文中に目次を表示したい場合は、MediaWiki:Common.css に下記の設定を追加する必要がある。
#toc { display:block; }
カテゴリを表示する
既定ではカテゴリが非表示になっている。表示する場合は MediaWiki:Common.css※に下記の設定を追加。[3]
#catlinks { display: block; }
カテゴリの表示位置を上方に移動
Tweeki.skin.php を直接書き換え。これを実施する場合、Tweekiをアップデートする度に書き換えが必要。 書き換え例: Tweeki.skin.patch (1KB)
--- Tweeki.skin.php.orig 2017-04-13 04:30:51.000000000 +0900 +++ Tweeki.skin.php 2017-06-12 06:56:54.000000000 +0900 @@ -268,6 +268,11 @@ <?php if( !$skin->checkEmptiness( 'subnav' ) ) { $skin->renderSubnav( $mainclass ); } ?> <div class="row"> + + <?php if ( $this->data['catlinks'] ) { ?> + <?php $this->html( 'catlinks' ); ?> + <?php } ?> + <div class="<?php echo $mainclass ?>" role="main"> <?php $skin->renderContent(); ?> </div> @@ -834,9 +839,6 @@ <?php $this->html( 'printfooter' ); ?> </div> <?php } ?> - <?php if ( $this->data['catlinks'] ) { ?> - <?php $this->html( 'catlinks' ); ?> - <?php } ?> <?php if ( $this->data['dataAfterContent'] ) { ?> <?php $this->html( 'dataAfterContent' ); ?> <?php } ?>
特定のページでのみナビゲーション要素を隠したい
例えば、特定のページでは navbar と編集リンクとロゴを隠せるようにしたい、といった場合の設定例。
LocalSettings.php に下記設定を追加
# Tweeki settings
$wgTweekiSkinHideable = array('navbar', 'EDIT', 'LOGO');
指定した要素※を隠したいページの記事本文中に、下記記述を追加
{{#tweekihide:navbar|EDIT|LOGO}}
ただし、他のSkinを使うと {{#tweekihide:}} が認識されず、見えてしまうことがあるので、要注意。後々面倒なことにならないよう、トップページや管理用の記事で使う程度に留め、一般の記事では使わない方が良いかも。
フッタに任意の Powered by アイコンを追加する
LocalSettings.php に下記の設定をする
- Tweekiのフッタでアイコン表示を有効にする
$wgTweekiSkinFooterIcons = true;
- 表示したいアイコンの設定をする → mw:Manual:$wgFooterIcons
$wgFooterIcons['poweredby']['freebsd'] = array(
"src" => "/path/to/bannerimage.gif",
"url" => "http://www.freebsd.org/ja/",
"alt" => "Powered by FreeBSD",
"width" => "171",
"height" => "64"
);
広告を入れる
Google Adsense
→MediaWiki#広告を入れるを参照
Yahoo!ショッピング
電子機器類のページでは、ショッピングサイトへのリンクがあると良さそう。Amazonや楽天が定番だが、簡単で自由度が高い※Yahoo!ショッピングの商品検索APIを使ってみることにした。
TweekiのSkin領域内に埋め込んでみたが、驚くほど簡単。具体的には下記の準備が必要。
- バリューコマースに会員登録し、Yahoo!ショッピングと提携する
- Yahoo! JAPAN ID が無ければ取得し(無料会員でOK)、アプリケーションIDを発行する
- アプリケーションID発行完了画面に、同社の爆速JSONPフレームワークを使ったサンプルが表示されるので、そのHTMLコード(中身は JavaScript)をコピペすればそのまま使える
- ちょっと手を加えてやって、Tweekiに埋め込んで使う
ちょっと手を加えてTweekiに埋め込んだ即席スクリプトの例:
$wgTweekiSkinSpecialElements['YAHOOSHOPPING'] = 'tweekiTagYahooshopping';
function tweekiTagYahooshopping( $skin, $context ) {
$title = urlencode($skin->getSkin()->getTitle()->getBaseText());
$appid = '※';
$vcid = '※';
/* appid 無指定では動作しない */
if( empty($appid) ) {
return;
}
$ret = <<<'START_END_MARKER'
<div class="yahooshoppingitemsearch">
<script src="/file/bakusoku-jsonp-v1-min.js"
data-url="//shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch"
data-p-appid=
START_END_MARKER;
$ret .= "\"$appid\"";
if( !empty($vcid) ) {
$ret .= <<<'START_END_MARKER'
data-p-affiliate_type="vc"
data-p-affiliate_id=
START_END_MARKER;
$ret .= '"' . $vcid . '"';
}
$ret .= <<<'START_END_MARKER'
data-p-sort="-score"
data-p-query=
START_END_MARKER;
$ret .= "\"$title\"";
$ret .= <<<'START_END_MARKER'
>
{{#ResultSet.0.Result}}
{{#0}}
<a href="{{Url}}" target="_blank" rel="nofollow"><img src="{{Image.Medium}}" title="{{Name}}" /></a>
{{/0}}
{{#1}}
<a href="{{Url}}" target="_blank" rel="nofollow"><img src="{{Image.Medium}}" title="{{Name}}"></a>
{{/1}}
{{#2}}
<a href="{{Url}}" target="_blank" rel="nofollow"><img src="{{Image.Medium}}" title="{{Name}}"></a>
{{/2}}
{{/ResultSet.0.Result}}
</script>
</div>
START_END_MARKER;
echo $ret;
}
- $appid には、ここで発行したものを入れる
- $vcid に入れるアフィリエイトURLは、ここに書いてある要領で作成する
- 関連Extension
- Extension:YJShopping
楽天トラベル
鉄道路線ページに商品リンクがあってもあまり意味がなく、沿線の宿が表示されると良いと思ったので、それなりの量の宿情報を提供している楽天トラベルのキーワード検索APIを使ってみた。
これは良いサンプルが無かったので自作した。即席で書いた汚いコードだけれど、WebAPI的な物に触ったことがある人ならば見ればすぐに分かると思う。
$wgTweekiSkinSpecialElements['RAKUTEN-TRAVEL'] = 'tweekiTagRakutenTravel';
function tweekiTagRakutenTravel( $skin, $context ) {
$title = urlencode($skin->getSkin()->getTitle()->getBaseText());
$appid = '※';
$affiliateid = '※';
$count = 3;
$imgclass = 'tweeki-rakuten-travel-hotel img-responsive';
/* appid 無指定では動作しない */
if( empty($appid) ) {
return;
}
/* 呼び出すURLを生成 */
$apiurl = "https://app.rakuten.co.jp/services/api/Travel/KeywordHotelSearch/20170426?applicationId=$appid";
if( !empty($affiliateid) ) {
$apiurl .= "&affiliateId=$affiliateid";
}
$apiurl .= "&format=json&formatVersion=2&responseType=small&keyword=$title";
/* API 呼び出し */
$retapi = file_get_contents($apiurl);
if( !$retapi ) {
return;
}
/* JSON分解 */
$result = json_decode( mb_convert_encoding( $retapi, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'), true );
/* 読み出したデータが異常(失敗を含む)ならば何もせずに返す */
if( is_null($result) ) {
return;
}
/* 先頭から $count 数だけ表示 */
for( $i=0; $count > 0; $i++) {
if( empty($r = $result['hotels'][$i][0]['hotelBasicInfo'])
|| $i >= $result['pagingInfo']['recordCount'] ) {
break;
}
if( empty($r['hotelImageUrl']) ) {
continue;
}
echo '<a href="' . $r['hotelInformationUrl'] . '" target="_blank" rel="nofollow"><img src="' . $r['hotelImageUrl'] . '" title="' . htmlspecialchars($r['hotelName']);
if( !empty($imgclass) ) {
echo '" class="' . $imgclass;
}
echo '" /></a>';
$count--;
}
}
- $appid には、ここで発行したアプリIDを入れる(楽天IDが必要)
- $affiliateid には、ここで取得したアフィリエイトIDを入れる(楽天IDが必要)
楽天トラベルキーワード検索APIのように戻り値の階層が深い場合など、仕様書を眺めていてもピンとこなければ、まずは簡単なリクエストURLを作ってFirefoxなどで開いて見ると良い。
右図は「只見線」で検索した例。この場合は期待通りの結果が得られて満足。
ところが、例えば「会津鉄道会津線」などで検索しても、うまく出てこないのが課題。まあ普通は「会津鉄道」だけで通るからねぇ。 ソフトウェアで処理することも考えたけれども、「内陸線」だけで通っている所もあったりするし、記事の見出しを変えるか…悩ましい。
- 関連Extension
- Extension:Yado
Bugs
Safariブラウザで「応答を解析できません」
2021年5月頃、最新のiOS・iPadOSに更新したiPhone・iPadのSafariブラウザで開くと「応答を解析できません」というエラーになる不具合が起きていた。
筆者が普段使っているFirefoxやChromeではこの不具合が起きなかったので気づくのが遅れたが、このときは Tweeki をアップデートすることで解消した。
MediaWikiバージョンアップ等の際にはiPadでも表示確認しているので、以前は問題が無かったのだが、その後、Safari側の変更でこの不具合が発生するようになったと思われる。
時々他のブラウザでも開いてみるとともに、Tweekiは頻繁に更新されているので、時々更新すると良さそうだ。
SSH等でサーバにログインできれば、更新は簡単にできる。
% cd /path/to/mediawiki/skins % mv Tweeki Tweeki.old % git clone https://github.com/thaider/Tweeki % rm -r Tweeki.old
SSH等を使えないWebサーバを借りている場合は、リポジトリよりZipでダウンロードし、展開してからWebサーバにアップロードする。
Navigation に外部リンクを設定すると、なぜか INVALID-TITLE:[…] への余計なAタグが生成されてしまう。(下記例) → 修正されたっぽい
<a href="INVALID-TITLE:[http://mobile.twitter.com/kimagurenote/media twitter]"
id="n-.5Bhttp:.2F.2Fmobile.twitter.com.2Fkimagurenote.2Fmedia-twitter.5D" class="btn btn-primary btn-block">
<a rel="nofollow" class="external text" href="http://mobile.twitter.com/kimagurenote/media">twitter</a>
</a>
規定ではページの移動、削除といった管理メニューが表示されないので、Tweekiのみで運用する場合は、設定変更が必要(設定例を参照)。 または、編集担当者(ログインユーザ)は個人設定で他のSkinを選択しておくなど、他のSkinとの併用する方法もある。
Bootstrap 4
いつの頃からかわからないが(筆者は2021年6月に気づいた)、Tweeki公式が Bootstrap 4 に対応していた。
と言っても規定では従来の Bootstrap 3 が引き続き有効なので、Tweekiをアップデートしたらデザインが崩れてしまった、という心配は(今のところ)ない。
LocalSettings.php に下記を追加することで、Bootstrap 4 が有効になる[4]。
$wgTweekiSkinUseBootstrap4 = true;
Bootstrap 3→4 の変更で大きなもの:
- 規定のフォントサイズが、14px→16pxに変更。
- CSSで使用する主要な単位が、px→emに変更。
Tweeki固有の挙動の変更(不具合か仕様かは不明):
- 従来は縦長画面で表示すると sidebar-right が下に回るが、Bootstrap 4 にすると下に回らなくなる(ので本文が狭くなる)。
- 縦スクロールすると navbar が見えなくなる。
Bootstrap 3→4 に変更する際は、全体に見直しが必要になるかもしれないので、時間がある時にじっくり作業するのが良いと思う。
参考リンク
- mw:Skin:Tweeki(英語)
- Tweeki = Mediawiki + Twitter Bootstrap(公式ホームページ、英語)
- mw:Manual:Gallery_of_user_styles