MovableTypeでcanonical属性以外をルート相対パスに変換する

Movable Type

MovableTypeが出力するURLは、原則として http(s):// から始まる絶対パスです。

これらのURLをスラッシュで始まるルート相対パスに変換する方法は、以前からいろいろなサイトで紹介されています。

mt:Ulnless や mt:For でテンプレート全体を括り一括置換する方法はとても便利で簡単なのですが、できれば絶対URLで指定しておきたい canonical 属性や、本文中にテキスト表示したい絶対URLまで変換されてしまうデメリットがあります。

というわけで、プラグインを使用せずにできるルート相対パスの一括変換を考えてみました。

検証環境はMT7ですが、たぶん5.2以降なら使えるのではないかと思います。

コード

テンプレートモジュールに以下のコードを登録します。((他のツールなどと被らないよう、このブログのタイトル impov を prefix に使用しています。適宜変更してください。))

システムワイドで利用したい場合は、システム>グローバルテンプレート>テンプレートモジュールに登録すると便利です。

テンプレート名:impovRootPath

<mt:SetVars>
  impov_siteURL_regex=/(?!\s*?<link[^>]+?rel="canonical")(.*?<[^>]+?(href|src|content)=")<mt:WebsiteURL>/mig
  impov_siteURL_replace=$1<mt:WebsiteRelativeURL>
</mt:SetVars>

インデックステンプレートや、アーカイブテンプレートなどで以下のように利用します。

<mt:Include module="impovRootPath">
<mt:Unless regex_replace="$impov_siteURL_regex","$impov_siteURL_replace">

テンプレートの本体

</mt:Unless>

挙動

タグの、href 属性、src 属性、content 属性の URL にウェブサイトURLが含まれている場合、そのURLの MTWebsiteURL の値の部分を MTWebsiteRelativeURL の値に書き換えします。

置換前
<link rel="stylesheet" href="https://impov.hatenablog.com/styles.css">
<script src="https://impov.hatenablog.com/mt/mt-static/support/theme_static/eiger/js/html5shiv.js"></script>
<img alt="" src="https://impov.hatenablog.com/mt/mt-static/support/theme_static/eiger/images/mainimage-sample.png">
<a href="https://impov.hatenablog.com/">https://impov.hatenablog.com/</a>
<link rel="canonical" href="https://impov.hatenablog.com/" />
<form action="https://impov.hatenablog.com/mt/mt-search.cgi">

      ↓

置換後
<link rel="stylesheet" href="/styles.css">
<script src="/mt/mt-static/support/theme_static/eiger/js/html5shiv.js"></script>
<img alt="" src="/mt/mt-static/support/theme_static/eiger/images/mainimage-sample.png">
<a href="/">https://impov.hatenablog.com/</a>(タグの外は置換しない)
<link rel="canonical" href="https://impov.hatenablog.com/" />(canonical属性は置換しない)
<form action="https://impov.hatenablog.com/mt/mt-search.cgi">(actionは指定属性でないので置換しない)

タグの属性の指定

タグの内側にある置換対象となる属性の変更は、テンプレートモジュールに登録したコードの2行目の中程にある部分をいじります。

action属性も追加したいのであれば、

(href|src|content)

の部分を、

(href|src|content|action)

に変更します。

説明

mt:Unless に、正規表現による置換を行う regex_replace を設定して、条件に合致する部分のみ置換しています。

正規表現はかなり久しぶりに書いたので、少々不安です。もし、より効果的な書き方やエラーを発見した方がいらっしゃいましたら是非コメントください。

改造する方のために、正規表現の部分を分解して説明しておきます。

/(?!\s*?<link[^>]+?rel="canonical")(.*?<[^>]+?(href|src|content)=")<mt:WebsiteURL>/mig

  (?!\s*?<link[^>]+rel="canonical") # 否定先読みの条件
    # ?! : 否定先読
    # \s*? : タブやスペースなどの空白文字が0以上連続して最短で次のテキストにマッチ
    # <link[^>]+?rel="canonical") : <link に続き > 以外の任意の文字が1個以上あり、rel="canonical"に最短でマッチ

  (.*?<[^>]+?(href|src|content)=("|')) # 変数$1に代入される先頭一致の条件
    # .*?< : 任意の文字が0個以上あり、< に最短でマッチ
    # [^>]+?(href|src|content)=" : > 以外の任意の文字が1個以上あり、(href または src または content)="に最短でマッチ

  <mt:WebsiteURL>  # 置換したい部分は変数$1の範囲から外す(カッコの外に置く)
  mig # オプション、順に、複数行、大文字小文字区別無し、繰り返しマッチ

置換先の文字列に、$1<mt:WebsiteRelativeURL> としておけば、マッチした文字列のうち変数$1に格納された部分とルート相対パスが結合されて設定されます。

免責

うまく動かなかったら外してください。

なお、canonical属性のタグがある行に複数の置換対象がある場合は、試してないですが期待通りには動かないと思います。テンプレートを構成する際、canonical属性は1行で出力するように設定してください。

データベースの中身自体を変更することはないので、復旧不能な状態になることはまず無いとはおもいますが、当然のことながら動作保証はしませんので自己責任でお試しください。

コメント