Manual:How to make a MediaWiki skin/Migrating SkinTemplate based skins to SkinMustache/ja

From mediawiki.org

2020年の MediaWiki 1.35 リリースの一部として、SkinMustache クラスが MediaWiki コアに追加されました。 この開発により、Mustache テンプレートを使用して外装を作成できるようになりました。 PHP を使用したくない、または PHP への依存度を下げたいと考えている外装開発者には魅力的なはずです。 このチュートリアルは、PHP ベースの SkinTemplate 外装を SkinMustache に変換するために必要と思われる手順を示すことを目的としています。

ステップ 1: 外装登録の使用

以前は、外装は SkinTemplate を継承する Skin PHP クラスを宣言する必要がありました。 外装の内部キーと関連する PHP テンプレートを定義するために使用されるいくつかのプロパティを定義する必要があります。

MediaWiki 1.35 以降、この情報は外装登録時に定義できます。

外装の登録方法が新しくなり、より強力になりました。
File SkinTemplate - 従来の登録方法 SkinTemplate - 新しい登録方法
skin.json
{
    "ValidSkinNames": {
        "monobook": "MonoBook"
    }
}
{
    "ValidSkinNames": {
        "monobook": {
			"class": "SkinMonoBook",
			"args": [
				{
					"scripts": [
					    "skins.monobook.scripts"
					],
					"styles": [
					    "skins.monobook.styles"
					],
					"name": "monobook",
					"template": "MonoBookTemplate"
				}
			]
        }
    }
}
SkinMonobook.php
class SkinMonoBook extends SkinTemplate {
	/** Using MonoBook. */
	public $skinname = 'monobook';
	public $stylename = 'MonoBook';
	public $template = 'MonoBookTemplate';

	public function initPage( OutputPage $out ) {
	    parent::initPage( $out );
	    $out->addModules( 'skins.monobook.scripts' );
		$out->addModuleStyles( 'skins.monobook.styles' );
	}
}
class SkinMonoBook extends SkinTemplate {
}

これまで、外装を作成するには、2 つの PHP クラスを作成する必要がありました。 新しい登録方法では、最大で 1 つの PHP クラスが必要です。

外装を宣言する際、class の値として「SkinTemplate」を設定することで、既定のコア インターフェイスを使用できる可能性があります:

{
    "ValidSkinNames": {
        "monobook": {
			"class": "SkinTemplate",
			"args": [
				{
					"name": "monobook",
					"template": "MonoBookTemplate"
				}
			]
        }
    }
}

定義した Skin にフックが含まれている場合は、別のファイルに抜き出すことをお勧めします。

モノブックの場合の例を以下に示します: gerrit:701142

ステップ 2: テンプレート化の威力を発揮

この次のステップに進むには、Mustache テンプレート言語の知識が少し身に付いていることが前提になります。 最低限、下記の例で説明されている以下の Mustache の基本を知っている必要があります:

{{ str }} <!-- renders escaped string -->
{{{ html-str }}} <!-- renders RAW HTML -->

<!-- accesses data inside an associative array of the form { 'key' => 'hello' } -->
{{#array-data}} 
{{ key }} <!-- renders hello -->
{{/array-data}}

<!-- for boolean values -->
{{#is-talk-page}}
<!-- conditional rendering if is-talk-page is true -->
{{/is-talk-page}}

Hello World

Create a Mustache file with the relative path templates/skin.mustache

<div>
    <h1>My first Mustache skin</h1>
    <p><strong>Hello world!</strong></p>
</div>

To use the SkinMustache class, declare the class property as SkinMustache.

{
    "ValidSkinNames": {
        "monobook": {
			"class": "SkinMustache",
			"args": [
				{
					"name": "monobook"
				}
			]
        }
    }
}

ブラウザーで外装を読み込むと、Mustache ファイルの内容が表示されるはずです。

MediaWiki 1.37 未満のバージョンでは、templateDirectorytemplate も定義する必要があります:
{
    "ValidSkinNames": {
        "monobook": {
			"class": "SkinMustache",
			"args": [
				{
					"name": "monobook",
					"templateDirectory": "skins/Monobook/templates/",
                    "template": "skin"
				}
			]
        }
    }
}

カスタム クラスの使用

移行を支援するために、少なくとも暫定的なステップとして、SkinMustache を継承した独自のカスタム クラスを使用し、外装テンプレートからテンプレートへコードをリダイレクト (移行) するところから開始するのをお勧めします。

SkinMustache を継承した新しい外装クラスを作成します。例えば、MonoBook 外装の場合、このクラスは SkinMonoBook という名前になります。

PHP ベースのテンプレート (例: MonoBookTemplate) を使用する場合、外装の開発者が HTML を出力する execute 関数を実装することが期待されます。

<?php
class MonoBookTemplate extends BaseTemplate {
    public function execute() {
        $html = $this->get( 'headelement' );
        $html .= $this->get( 'bodytext' );
        $html .= $this->getTrail();
		$html .= Html::closeElement( 'body' );
		$html .= Html::closeElement( 'html' );
        echo $html;
    }
}

In SkinMustache, the approach is different. Mustache テンプレートに渡されるテンプレートデータの連想配列を提供します。

この後の例では、Mustache テンプレートに渡す新しいデータを設定します

<?php
class SkinMonoBook extends SkinMustache {
    public function getTemplateData() {
        $data = parent::getTemplateData();
        $data['html-hello'] = '<strong>HELLO WORLD</strong>';
        return $data;
    }
}

この変更により、データを出力するためのテンプレートを以下のように変更できます。

テンプレートデータを使用しないテンプレート 新たに追加されたテンプレートデータを使用するテンプレート
<div>
    <h1>My first Mustache skin</h1>
    <p><strong>Hello world!</strong></p>
</div>
<div>
    <h1>My first Mustache skin</h1>
    <p>{{{ html-hello }}}</p>
</div>

Using this technique we can bridge our old skin with SkinMustache.

First we may need to refactor our execute method to separate out a function that returns a string which represents the body of the skin. It's important to note in SkinMustache, you are restricted to templating the content of the body tag.

Original BaseTemplate BaseTemplate for usage in SkinMustache
<?php
class MonoBookTemplate extends BaseTemplate {
    public function execute() {
        $html = $this->get( 'headelement' );
        $html .= $this->get( 'bodytext' );
        $html .= $this->getTrail();
		$html .= Html::closeElement( 'body' );
		$html .= Html::closeElement( 'html' );
        echo $html;
    }
}
<?php
class MonoBookTemplate extends BaseTemplate {
    public function getHTML() {
        return $this->get( 'bodytext' );
    }
    public function execute() {
       /* This function needs to be present to implement BaseTemplate
         but is unused since we are using SkinMustache.
         The getTrail, headelement and closing body tags
         will be handled by SkinMustache.
       */
    }
}

In SkinMustache with this refactor done, we can extend the data we pass to a template as demonstrated with the html-hello example above. We can add a new template variable html-quick-template-migration which can be rendered inside our skin.mustache as raw HTML.

<?php
class SkinMonoBook extends SkinMustache {
    public function getTemplateData() {
        $data = parent::getTemplateData();
        $tpl = $this->prepareQuickTemplate();
		return $data + [ 'html-quick-template-migration' => $tpl->getHTML() ];
    }
}

Step 3: Embrace data

At this point you should have a skin implementing SkinMustache which is leveraging BaseTemplate to generate HTML. The PHP inside your PHP template that implements BaseTemplate should be possible with Mustache.

SkinMustache skins are data driven, which we believe gives better flexibility in how you want to render the data. The data is informed by skins in the wild. This data is documented elsewhere at Manual:SkinMustache.php#Template data.

There is little guidance on this step, other than explore how you can generate HTML code identical to your code in BaseTemplate using only the data and templates. Challenges you face while doing this should be raised on the talk page to help others.

Step 4: Fill out the missing data

During step 3 you may find HTML you are trying to generate cannot be rendered using the data inside SkinMustache. Hopefully from step 2 however you've realized you are not limited to the data you pass to your template.

However, it's useful for us to know about data that was missing, as it's likely your skin is doing something unique that may benefit other skins.

Simply by your code existing, you've communicated bits of data that would be helpful but you are invited to explicitly file Phabricator ticket requesting the data you need.