MovableTypeで「改行を変換する」オプションを選択すると、 <pre>
の間にある文章(ソースコード記述)まで“改行変換”されて表示がおかしくなる。
※ 「改行を変換する」オプションは標準設定値のため、特に明示しなければこのオプションで構築しているはず…
MovableTypeのデータベースファイルを直接開いて、一括して修正するスクリプトを作成した。(この修正後、MovableTypeの管理画面で“全て再構築”すれば、作業完了する)
■ MovableTypeでの記述例と表示サンプル
(1)改行だけの行が存在する場合
<div class="code">
#!/usr/bin/perl
use warnings;
use strict;
use DBI;
use HTML::Entities;
my $dbh = undef;
</div>
#!/usr/bin/perl
use warnings;
use strict;
use DBI;
use HTML::Entities;
my $dbh = undef;
</div>
このソースコードをMovableTypeで「改行を変換する」をONにして変換(構築)すると
<div class="code">
<p>#!/usr/bin/perl</p>
<p>use warnings;<br />
use strict;<br />
use DBI;<br />
use HTML::Entities;</p>
<p>my $dbh = undef;<br />
<p>#!/usr/bin/perl</p>
<p>use warnings;<br />
use strict;<br />
use DBI;<br />
use HTML::Entities;</p>
<p>my $dbh = undef;<br />
表示サンプル
(2)改行だけの行に1この空白文字を付加した場合
<div class="code">
#!/usr/bin/perl
use warnings;
use strict;
use DBI;
use HTML::Entities;
my $dbh = undef;
</div>
#!/usr/bin/perl
use warnings;
use strict;
use DBI;
use HTML::Entities;
my $dbh = undef;
</div>
このソースコードをMovableTypeで「改行を変換する」をONにして変換(構築)すると
<div class="code">
#!/usr/bin/perl
use warnings;
use strict;
use DBI;
use HTML::Entities;
my $dbh = undef;
#!/usr/bin/perl
use warnings;
use strict;
use DBI;
use HTML::Entities;
my $dbh = undef;
表示サンプル
■ MovableTypeの全エントリを一括修正するPerlスクリプト
MovableTypeのデータベースを直接開いて修正する。このサンプルスクリプトは、SQLite3のデータベースファイル mtdata.sqlite
の存在するディレクトリで実行すると仮定している。
・mt_fix_entry_code.plをダウンロードする(<div class="code"> 〜 </div> 版)
#!/usr/bin/perl
use warnings;
use strict;
use DBI;
use HTML::Entities;
my $dbh = undef;
my $sth = undef;
my $strQuery = "";
my $strTmp = "";
my $strDsn = 'DBI:SQLite:dbname=./mtdata.sqlite'; # DSN
my @arr_entry = (); # 修正すべきentry_id
eval{
# DBに接続
$dbh = DBI->connect($strDsn, "", "", {PrintError => 1, AutoCommit => 0});
if(!$dbh) { die();}
# データを読み込む
$strQuery = "select entry_id,entry_text,entry_text_more from mt_entry where entry_text like '%\"code\"%' or entry_text_more like '%\"code\"%'";
$sth = $dbh->prepare($strQuery);
if($sth){ $sth->execute();}
my $counter = 0;
while(my $arrData = $sth->fetchrow_arrayref()) {
my ($id, $text, $text_more) = @$arrData;
my @arr_textline = split(/\n/, $text."\n".$text_more);
my $flag_incode = 0;
foreach my $text_line (@arr_textline) {
chomp $text_line;
if($text_line =~ m/class\s*=\s*"code"/){ $flag_incode = 1; }
if($flag_incode && $text_line =~ m/<\/div>/){ $flag_incode = 0; }
if(length($text_line)<=0 && $flag_incode){
push(@arr_entry, $id);
$counter++;
last;
}
}
}
if($sth){ $sth->finish();}
print "found ".$counter."topics\n";
foreach my $id (@arr_entry) {
print $id." ...";
# 指定されたentry_idが複数ないか、データ件数を確認する
$strQuery = "select count(*) from mt_entry where entry_id = ?";
$sth = $dbh->prepare($strQuery);
$sth->bind_param(1, $id, DBI::SQL_INTEGER);
if($sth){ $sth->execute();}
my @arr = $sth->fetchrow_array();
if($sth){ $sth->finish();}
if($arr[0] != 1){
print "count(entry_id=".$id.") = ".$arr[0]." , is not only one row\n";
last;
}
# 指定されたentry_idの内容を読み込む
$strQuery = "select entry_id,entry_text,entry_text_more from mt_entry where entry_id = ?";
$sth = $dbh->prepare($strQuery);
$sth->bind_param(1, $id);
if($sth){$sth->execute();}
my $arrData = $sth->fetchrow_arrayref();
if($sth){ $sth->finish();}
my ($id, $text, $text_more) = @$arrData;
# entry_textとentry_text_moreを修正する
$text = fix_text($text);
$text_more = fix_text($text_more);
# 指定されたentry_idの内容を更新する
$strQuery = "update mt_entry set entry_text = ?, entry_text_more = ? where entry_id = ?";
$sth = $dbh->prepare($strQuery);
$sth->bind_param(1, $text, DBI::SQL_VARCHAR);
$sth->bind_param(2, $text_more, DBI::SQL_VARCHAR);
$sth->bind_param(3, $id, DBI::SQL_INTEGER);
if($sth){$sth->execute();}
if($sth){ $sth->finish();}
print "\n";
}
$dbh->commit();
# DBを閉じる
$dbh->disconnect();
};
if($@){
# evalによるDBエラートラップ:エラー時の処理
$dbh->disconnect();
print("DBI error : ".$@."\n");
}
exit(0);
#
# <div class="code"> 〜 </div> で囲まれた領域で改行のみの行に1文字分の空白を追加する
#
sub fix_text {
my $text = shift;
my @arr_textline = split(/\n/, $text);
$text = "";
my $flag_incode = 0;
foreach my $text_line (@arr_textline) {
chomp $text_line;
if($text_line =~ m/class\s*=\s*"code"/){ $flag_incode = 1; }
if($flag_incode && $text_line =~ m/<\/div>/){ $flag_incode = 0; }
if(length($text_line)<=0 && $flag_incode){ $text_line = " "; }
$text .= ($text_line . "\n");
}
return $text;
}
use warnings;
use strict;
use DBI;
use HTML::Entities;
my $dbh = undef;
my $sth = undef;
my $strQuery = "";
my $strTmp = "";
my $strDsn = 'DBI:SQLite:dbname=./mtdata.sqlite'; # DSN
my @arr_entry = (); # 修正すべきentry_id
eval{
# DBに接続
$dbh = DBI->connect($strDsn, "", "", {PrintError => 1, AutoCommit => 0});
if(!$dbh) { die();}
# データを読み込む
$strQuery = "select entry_id,entry_text,entry_text_more from mt_entry where entry_text like '%\"code\"%' or entry_text_more like '%\"code\"%'";
$sth = $dbh->prepare($strQuery);
if($sth){ $sth->execute();}
my $counter = 0;
while(my $arrData = $sth->fetchrow_arrayref()) {
my ($id, $text, $text_more) = @$arrData;
my @arr_textline = split(/\n/, $text."\n".$text_more);
my $flag_incode = 0;
foreach my $text_line (@arr_textline) {
chomp $text_line;
if($text_line =~ m/class\s*=\s*"code"/){ $flag_incode = 1; }
if($flag_incode && $text_line =~ m/<\/div>/){ $flag_incode = 0; }
if(length($text_line)<=0 && $flag_incode){
push(@arr_entry, $id);
$counter++;
last;
}
}
}
if($sth){ $sth->finish();}
print "found ".$counter."topics\n";
foreach my $id (@arr_entry) {
print $id." ...";
# 指定されたentry_idが複数ないか、データ件数を確認する
$strQuery = "select count(*) from mt_entry where entry_id = ?";
$sth = $dbh->prepare($strQuery);
$sth->bind_param(1, $id, DBI::SQL_INTEGER);
if($sth){ $sth->execute();}
my @arr = $sth->fetchrow_array();
if($sth){ $sth->finish();}
if($arr[0] != 1){
print "count(entry_id=".$id.") = ".$arr[0]." , is not only one row\n";
last;
}
# 指定されたentry_idの内容を読み込む
$strQuery = "select entry_id,entry_text,entry_text_more from mt_entry where entry_id = ?";
$sth = $dbh->prepare($strQuery);
$sth->bind_param(1, $id);
if($sth){$sth->execute();}
my $arrData = $sth->fetchrow_arrayref();
if($sth){ $sth->finish();}
my ($id, $text, $text_more) = @$arrData;
# entry_textとentry_text_moreを修正する
$text = fix_text($text);
$text_more = fix_text($text_more);
# 指定されたentry_idの内容を更新する
$strQuery = "update mt_entry set entry_text = ?, entry_text_more = ? where entry_id = ?";
$sth = $dbh->prepare($strQuery);
$sth->bind_param(1, $text, DBI::SQL_VARCHAR);
$sth->bind_param(2, $text_more, DBI::SQL_VARCHAR);
$sth->bind_param(3, $id, DBI::SQL_INTEGER);
if($sth){$sth->execute();}
if($sth){ $sth->finish();}
print "\n";
}
$dbh->commit();
# DBを閉じる
$dbh->disconnect();
};
if($@){
# evalによるDBエラートラップ:エラー時の処理
$dbh->disconnect();
print("DBI error : ".$@."\n");
}
exit(0);
#
# <div class="code"> 〜 </div> で囲まれた領域で改行のみの行に1文字分の空白を追加する
#
sub fix_text {
my $text = shift;
my @arr_textline = split(/\n/, $text);
$text = "";
my $flag_incode = 0;
foreach my $text_line (@arr_textline) {
chomp $text_line;
if($text_line =~ m/class\s*=\s*"code"/){ $flag_incode = 1; }
if($flag_incode && $text_line =~ m/<\/div>/){ $flag_incode = 0; }
if(length($text_line)<=0 && $flag_incode){ $text_line = " "; }
$text .= ($text_line . "\n");
}
return $text;
}
■ コード記述のある記事のみを抜き出してHTML化するスクリプト
・mt_export_entry_code.plをダウンロードする(<div class="code"> 〜 </div> 版)
・mt_export_entry_pre.plをダウンロードする(<pre> 〜 </pre> 版)
#!/usr/bin/perl
use warnings;
use strict; # 変数の宣言を強制する
use DBI; # DBI モジュールを利用する
use HTML::Entities;
my $dbh = undef;
my $sth = undef;
my $strQuery = "";
my $strTmp = "";
my $strDsn = 'DBI:SQLite:dbname=./mtdata.db'; # DSN
print "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n".
"<html>\n".
"<head>\n".
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n".
"<meta http-equiv=\"Content-Language\" content=\"ja\" />\n".
"<style type=\"text/css\">\n".
"<!--\n".
"table, td, tr { border:solid 1px maroon;font-size:10px;border-collapse: collapse; }\n".
"-->\n".
"</style>\n".
"<title></title>\n".
"</head>\n".
"<body>\n".
"<table>\n";
eval{
# DBに接続
$dbh = DBI->connect($strDsn, "", "", {PrintError => 1, AutoCommit => 0});
if(!$dbh) { die();}
# データを読み込む
$strQuery = "select entry_id,entry_text,entry_text_more from mt_entry where entry_text like '%\"code\"%' or entry_text_more like '%\"code\"%'";
$sth = $dbh->prepare($strQuery);
if($sth){ $sth->execute();}
my $counter = 0;
while(my $arrData = $sth->fetchrow_arrayref()) {
$counter++;
my ($id, $text, $text_more) = @$arrData;
my @arr_textline = split(/\n/, $text."\n".$text_more);
print "<tr><td>".$id."</td><td><pre>";
my $flag_incode = 0;
foreach my $text_line (@arr_textline) {
chomp $text_line;
if($text_line =~ m/class\s*=\s*"code"/){ $flag_incode = 1; }
if($flag_incode && $text_line =~ m/<\/div>/){ $flag_incode = 0; }
if(length($text_line)<=0 && $flag_incode){ print "<span style=\"background-color:red;\"> </span>"; }
if($flag_incode){ print "<span style=\"color:green;\">"; }
print encode_entities($text_line, '&<>\\\"\'');
if($flag_incode){ print "</span>"; }
print "\n";
}
print "</pre></td></tr>\n";
}
if($sth){ $sth->finish();}
# DBを閉じる
$dbh->disconnect();
print "</table>\n".
"<p>total count = ".$counter."</p>\n".
"</body>\n".
"</html>\n";
};
if($@){
# evalによるDBエラートラップ:エラー時の処理
$dbh->disconnect();
print("DBI error : ".$@."\n");
}
exit(0);
use warnings;
use strict; # 変数の宣言を強制する
use DBI; # DBI モジュールを利用する
use HTML::Entities;
my $dbh = undef;
my $sth = undef;
my $strQuery = "";
my $strTmp = "";
my $strDsn = 'DBI:SQLite:dbname=./mtdata.db'; # DSN
print "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n".
"<html>\n".
"<head>\n".
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n".
"<meta http-equiv=\"Content-Language\" content=\"ja\" />\n".
"<style type=\"text/css\">\n".
"<!--\n".
"table, td, tr { border:solid 1px maroon;font-size:10px;border-collapse: collapse; }\n".
"-->\n".
"</style>\n".
"<title></title>\n".
"</head>\n".
"<body>\n".
"<table>\n";
eval{
# DBに接続
$dbh = DBI->connect($strDsn, "", "", {PrintError => 1, AutoCommit => 0});
if(!$dbh) { die();}
# データを読み込む
$strQuery = "select entry_id,entry_text,entry_text_more from mt_entry where entry_text like '%\"code\"%' or entry_text_more like '%\"code\"%'";
$sth = $dbh->prepare($strQuery);
if($sth){ $sth->execute();}
my $counter = 0;
while(my $arrData = $sth->fetchrow_arrayref()) {
$counter++;
my ($id, $text, $text_more) = @$arrData;
my @arr_textline = split(/\n/, $text."\n".$text_more);
print "<tr><td>".$id."</td><td><pre>";
my $flag_incode = 0;
foreach my $text_line (@arr_textline) {
chomp $text_line;
if($text_line =~ m/class\s*=\s*"code"/){ $flag_incode = 1; }
if($flag_incode && $text_line =~ m/<\/div>/){ $flag_incode = 0; }
if(length($text_line)<=0 && $flag_incode){ print "<span style=\"background-color:red;\"> </span>"; }
if($flag_incode){ print "<span style=\"color:green;\">"; }
print encode_entities($text_line, '&<>\\\"\'');
if($flag_incode){ print "</span>"; }
print "\n";
}
print "</pre></td></tr>\n";
}
if($sth){ $sth->finish();}
# DBを閉じる
$dbh->disconnect();
print "</table>\n".
"<p>total count = ".$counter."</p>\n".
"</body>\n".
"</html>\n";
};
if($@){
# evalによるDBエラートラップ:エラー時の処理
$dbh->disconnect();
print("DBI error : ".$@."\n");
}
exit(0);