Movable Type 備忘録

 カンタンに実体参照文字に変換する

XHTMLでは、「 & 」や「 " 」、「 < 」などの、ある特定の文字はそのまま使ってはいけません…とされています。
なので、「 & 」なら「 &amp; 」、「 " 」なら「 &quot; 」、「 < 」の場合は「 &lt; 」のように実体参照文字に変換してあげる必要があります。

とはいっても、XHTMLの記述に拘らない人にとってもどうでもいいことなのですけどね。

わたしはいつもテキストエディタで記事を書いてまして、その都度上記のように実体参照文字を手入力してるのですが、チョビッとの記述ならまだしも、サンプルコードなどの場合にはそうはいかず、かなりの手間がかかってしまいます。
つか、やってられません(。-ω-)

今回は、カンタンに実体参照文字に変換するカスタマイズをご紹介します。

EntityRefButton

実体参照文字の変換にはEntityRefButtonプラグインを使用します。
このプラグインをインストールすることで、右図にあるように、エントリ編集ページ中にボタンが追加されます。

使い方としては、たとえば、<head>~</head>などのように、普通にXHTMLなどを記述して、記事全体を選択してから追加されたボタンをクリックすると、一括して変換されます。
1つ、1つ変換する必要もなく、ましてや1つ、1つ記述する必要もないのでとっても楽できます。

EntityRefButtonプラグインはエムロジック放課後プロジェクトさんのところで配布されてます。

プラグインのインストール

  1. エムロジック放課後プロジェクトさんのところから、EntityRefButtonプラグインをダウンロードします。
    ダウンロードしたら適当なフォルダに展開します。

  2. entityrefbutton.plを修正します。
    このプラグインはそのままでは使えないようで、drry+@->さんのところで、Forked EntityRefButton plugin 0.0.3という記事で修正箇所について紹介されてました。

  3. 以下はdrryさんの記事を元に修正したプラグインのコードになります。

    - 2006.12.13 追記 -

    以下の修正はMovableType(ムーバブルタイプ) 3.3では行う必要ありません。 そのまま使えます。

    package MT::Plugin::EntityRefButton;
    use strict;
    use MT::Plugin;
    @MT::Plugin::EntityRefButton::ISA = qw( MT::Plugin );
    use vars qw( $VERSION $PLUGIN_NAME );
    $PLUGIN_NAME = 'EntityRefButton';
    $VERSION = '0.0.3';
    use MT;
    my $plugin = MT::Plugin::EntityRefButton->new({
    name => $PLUGIN_NAME,
    version => $VERSION,
    description => '<MT_TRANS phrase=\'This plugin adds a convert button to the entry body and the extended body fields on the edit entry screen, which converts special characters to character entity references.\'>',
    author_name => 'M-Logic, Inc.',
    author_link => 'http://labs.m-logic.jp/',
    doc_link => 'http://labs.m-logic.jp/plugins/entityrefbutton/docs/entityrefbutton.html',
    l10n_class => 'EntityRefButton::L10N',
    });
    MT->add_plugin($plugin);
    MT->add_callback('MT::App::CMS::AppTemplateSource.edit_entry', 9, $plugin, sub { transform('edit_entry', @_) });
    MT->add_callback('MT::App::CMS::AppTemplateSource.bm_entry', 9, $plugin, sub { transform('bm_entry', @_) });
    my %BUTTONS = (
    edit_entry => [
    # body
    {
    pattern => quotemeta(q{        write('<img title="<MT_TRANS phrase="Quote"}) .
    q{(?:\ escape="singlequotes")?} .
    quotemeta(q{>" onclick="return formatStr(document.entry_form.text, \'blockquote\')" src="<TMPL_VAR NAME=STATIC_URI>images/formatting-icons/quote.gif" alt="<MT_TRANS phrase="Quote"}) .
    q{(?:\ escape="singlequotes")?} .
    quotemeta(q{>" width="26" height="19" />');}),
    replacement => <<'REPLACEMENT_END'
    write('<img title="_BUTTON_LABEL_" onclick="return convertToCharEntityRef(document.entry_form.text)" src="<TMPL_VAR NAME=STATIC_URI>plugins/EntityRefButton/images/formatting-icons/ref.gif" alt="_BUTTON_LABEL_" width="26" height="19" />');
    REPLACEMENT_END
    ,
    },
    # extended body
    {
    pattern => quotemeta(q{        write('<img title="<MT_TRANS phrase="Quote"}) .
    q{(?:\ escape="singlequotes")?} .
    quotemeta(q{>" onclick="return formatStr(document.entry_form.text_more, \'blockquote\')" src="<TMPL_VAR NAME=STATIC_URI>images/formatting-icons/quote.gif" alt="<MT_TRANS phrase="Quote"}) .
    q{(?:\ escape="singlequotes")?} .
    quotemeta(q{>" width="26" height="19" />');}),
    replacement => <<'REPLACEMENT_END'
    write('<img title="_BUTTON_LABEL_" onclick="return convertToCharEntityRef(document.entry_form.text_more)" src="<TMPL_VAR NAME=STATIC_URI>plugins/EntityRefButton/images/formatting-icons/ref.gif" alt="_BUTTON_LABEL_" width="26" height="19" />');
    REPLACEMENT_END
    },
    ],
    bm_entry => [
    # body
    {
    pattern => quotemeta <<'PATTERN_END'
    write('<a title="<MT_TRANS phrase="Quote">" href="#" onclick="return formatStr(document.entry_form.text, \'blockquote\')"><img src="<TMPL_VAR NAME=STATIC_URI>images/html-quote.gif" alt="<MT_TRANS phrase="Quote">" width="22" height="16" /></a>');
    PATTERN_END
    ,
    replacement => <<'REPLACEMENT_END'
    write('<a title="_BUTTON_LABEL_" href="#" onclick="return convertToCharEntityRef(document.entry_form.text)"><img src="<TMPL_VAR NAME=STATIC_URI>plugins/EntityRefButton/images/html-ref.gif" alt="_BUTTON_LABEL_" width="22" height="16" /></a>');
    REPLACEMENT_END
    ,
    },
    # extended body
    {
    pattern => quotemeta <<'PATTERN_END'
    write('<a title="<MT_TRANS phrase="Quote">" href="#" onclick="return formatStr(document.entry_form.text_more, \'blockquote\')"><img src="<TMPL_VAR NAME=STATIC_URI>images/html-quote.gif" alt="<MT_TRANS phrase="Quote">" width="22" height="16" /></a>');
    PATTERN_END
    ,
    replacement => <<'REPLACEMENT_END'
    write('<a title="_BUTTON_LABEL_" href="#" onclick="return convertToCharEntityRef(document.entry_form.text_more)"><img src="<TMPL_VAR NAME=STATIC_URI>plugins/EntityRefButton/images/html-ref.gif" alt="_BUTTON_LABEL_" width="22" height="16" /></a>');
    REPLACEMENT_END
    ,
    },
    ],
    );
    sub instance { $plugin; }
    sub transform {
    my $template_name = shift;
    my ($eh, $app, $tmpl) = @_;
    add_script($template_name, $eh, $app, $tmpl);
    add_convert_button($template_name, $eh, $app, $tmpl);
    }
    sub add_script {
    my $template_name = shift;
    my ($eh, $app, $tmpl) = @_;
    # insert javascript
    my $script = <<'SCRIPT';
    function convertToCharEntityRef(e) {
    if(!canFormat) return;
    var str = getSelected(e);
    if(str) {
    str = str.replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;");
    setSelection(e, str);
    }
    return false;
    }
    SCRIPT
    $$tmpl =~ s!(?<=\n\n)(?=//-->\n</script>)!$script!is;
    }
    sub add_convert_button {
    my $template_name = shift;
    my ($eh, $app, $tmpl) = @_;
    # translate button's label
    my $alt_str = $plugin->translate('Convert to character entity reference');
    my $entries = $BUTTONS{$template_name};
    foreach my $item (@$entries) {
    my $pattern = $item->{pattern};
    my $replacement = $item->{replacement};
    $replacement =~ s!_BUTTON_LABEL_!$alt_str!isg;
    $$tmpl =~ s!$pattern!$&$replacement!is;
    }
    }
    1;
    __END__
    

    青い字の部分が修正したところになります。

  4. 修正したら保存して、mt-staticフォルダとpluginsフォルダをそのままサーバにアップロードします。
    アップロード先は、mt/ディレクトリの中にアップロードします。

以上でインストールは完了です。
エントリ編集画面を表示すると、図のようにボタンが追加されます。

後は、普通に記事を書いて変換したい部分を選択してからボタンをクリックすると、XHMLで都合の悪い、すべての文字を実体参照文字に変換してくれます。

わたしは面倒なので、書いた記事すべてを選択してからボタンクリックして変換しちゃってます。

 Trackback Pings(0)

No trackbacks found.

 Comments(3)

#1: Posted by drry @ December 12, 2006 [REPLY]
user-pic

あ、MT 3.3 でしたら、そのままで何も問題なく使うことができます。
ところで、最近さくらインターネットのサーバからトラックバックを受信するのですが、bzbell さんご利用の www854.sakura.ne.jp も bsb.spamlookup.net にブラックリスト入りしており、MT 標準プラグインの SpamLookup によって迷惑トラックバック扱いされていました。少し前にも同じことが起きて、迷惑トラックバック群から引っ張り出したのですけど、困りものです。さくらインターネットほぼ全滅かもしれないです。SpamLookup 標準設定でこれですので、この問題は根深い……

#2: Posted by oscar @ December 12, 2006 [REPLY]
user-pic

あれっ、bzbellさん、そのカスタマイズは、drry+@->さんの所のテンプレートがMT3.3の標準と違ってるから、直してるんじゃないでしょうか?
そのままで、プラグイン動作しますよ。

「スペース」を「改行禁止スペース文字」にしちゃうのを修正するのは、意味があるかもしれないけど、それもその人の捉え方だと思います。
大抵の実態参照のカスタマイズは「改行禁止スペース文字」にしちゃうのが、多かったですよ。

>改行禁止では意味が違ってしまいます
というのは、確かに納得できるのですが。

#3: Posted by bzbell @ December 13, 2006 [REPLY]
user-pic

>>1 drry さん

こんにちわ^^

> あ、MT 3.3 でしたら、そのままで何も問題なく使うことができます。

えぇーーーΣ( ̄Д ̄;)!!
そうなんですの!?
そのままアップロードして確認してみます。

> MT 標準プラグインの SpamLookup によって迷惑トラックバック扱いされていました。

前にどっかでさくらインターネットがブラックリスト入りされてる・・・なんての見たことありますが、やっぱりそうなんですの(つω-`。)
わたしのとこでもスパムじゃなさそうなのにスパム入りしてるトラバがありますが、その都度スパム解除してます。

> SpamLookup 標準設定でこれですので、この問題は根深い……

スパムに悩まされてたとき、たまたま正当なトラバが混じってるのを見つけて解除しましたけど、かなりのスパム件数だったのですべてを見ることができず、もしかしたら・・・と思ってたんです。

何でブラックリスト入りしちゃったんでしょうね。

>>2 oscar さん

こんにちわ^^

> そのままで、プラグイン動作しますよ。

はい。そのようですの(つω-`。)
drryさんにも言われたので、そのままプラグイン入れて動作確認したら動いてました。

でも、最初インストしたときボタンが表示されなかったので、「なるほど・・・」と思って、drryさんの記事を元に修正したはずだったんですけどね。

ありがとうございます。
記事修正します。

 Post a Comment

 

コメント用フィード