#!/usr/bin/perl -w
#-------------------------------------------------------------------#
# MovableType TextFormatingプラグイン mt-sukeroku-plus.pl ver.1.10b #
# Copyright(C)DonaDona(KITAO Masato) 2004 #
#-------------------------------------------------------------------#
package MT::Plugins::SukerokuPlus;
use vars qw($VERSION);
$VERSION = 1.10;
use strict;
use MT;
use MT::Blog;
use MT::Entry;
use MT::Template::Context;
use MT::Util qw(encode_html first_n_words);
use LWP::UserAgent;
use XML::Simple;
use Jcode;
##############################################################################
## ■■■■■■■■■■■■ 設定パラメータの記述 ■■■■■■■■■■■■ ##
## 【ここから】 ##
##############################################################################
my $sysParam = {
# ■見出しの先頭につける文字列(加工なく出力されます)
# ※出力をUTFにしている場合には実体参照でお願いします。
symbolHeading1 => '*', # ■…■
symbolHeading2 => '*', # ■…■
symbolHeading3 => '*', # ■…■
# ■見出しリンクアンカーの種類(typeHeadingAnchor)
# ・見出し文字列から生成………………… 1
# ・見出し番号(章・節・項)から生成… 0
typeHeadingAnchor => 1,
# ■リンク時に画像ファイルなら自動展開(linkAutoImage)
# ・画像展開する… 1, 画像展開しない… 0
linkAutoImage => 1,
# ■リンク時のtarget指定(linkAnchorTarget)
# ・同じウィンドウに展開する…… '_self'
# ・新しいウィンドウに展開する… '_blank'
# (※xhtml11modeが1のとき_self以外の場合、新規ウィンドウで開きます)
linkAnchorTarget => '_blank',
# ■リンク時のAmazonアソシエイトID(linkAmazonAssociate)
# ※契約されていない場合は空欄''にしておいてください。
linkAmazonAssociate => 'hsjjp-22',
# ■Amazonの書影画像が存在しない場合の代替画像のアドレス
linkAmazonNoImageImage=> 'http://hsj.jp/works/comingsoon.gif',
# ■AmazonWebServices利用時のデベロッパートークン
# ※契約されていない場合は空欄''にしておいてください。
linkAmazonAWSToken => '',
# ■脚注の先頭につける文字列(加工なく出力されます)
# ※出力をUTFにしている場合には実体参照でお願いします。
symbolFootnote1 => '*', # †…†
symbolFootnote2 => '*', # ‡…‡
symbolFootnote3 => '*', # *
# ■脚注表示に使うHTML要素と属性の指定
htmlTagFootnoteList => 'ul',
htmlAttrFootnoteList => 'class="footnote"',
htmlTagFootnoteItem => 'li',
htmlAttrFootnoteItem => 'class="footnote"',
htmlTagFootnoteRoot => 'span',
htmlAttrFootnoteRoot => 'class="footnote"',
# ■強調表示に使うHTML要素の指定
htmlTagEmphasisBold => 'strong',
htmlTagEmphasisItalic => 'em',
htmlTagDelete => 'del',
htmlTagInsert => 'ins',
# ■PukiWikiのコメント内逐語出力モードの利用
# ・逐語出力する… 1, 逐語出力しない… 0
pukiwikiVerbatimEnabled => 1,
pukiwikiHardVerbatimOpenRegexp => "^\/\/\/\/",
pukiwikiHardVerbatimCloseRegexp => "^\/\/\/\/",
pukiwikiSoftVerbatimOpenRegexp => "^\/\/\/",
pukiwikiSoftVerbatimCloseRegexp => "^\/\/\/",
# ■論理行末は強制的に
を挟む。
# ・対応する… 1, 対応しない… 0
convert_line_break => 0,
# ■はてなダイアリー風フォーマットの整形済みテキストのハードモード利用
# ※整形済みの入れ子でHTMLエスケープが自動的にされるかどうか。
# ・エスケープ展開する… 1, エスケープ展開しない… 0
hatenaPreHTMLEscape => 1,
# ■XHTML 1.1にできるだけ対応する(^^;;
# ・対応する… 1, 対応しない… 0
xhtml11mode => 1,
# ■PukiWiki風フォーマットでエントリの末尾に
{p}>"); # 大域変数の初期化 &initGlobalVariable($text, $ctx); # バーベイタムモード(0=なし、1=soft、2=hard) my $format_mode_verbatim = 0; # 正規表現 my $regexp_yukiwiki_italic = qq('''([^']+?)'''); #' my $regexp_yukiwiki_bold = qq(''([^']+?)''); #' my $regexp_yukiwiki_link = qq((mailto|http|https|ftp):([^\x00-\x20()<>\x7F-\xFF])*); my $regexp_yukiwiki_plugin = '\&(\w+)\(((([^()]*(\([^()]*\))?)*)*)\)'; #無名関数で実装 my $func_inline; my $func_inlineLinkAnother; $func_inline = sub { my ($localLine, $localInlineNestLv) = @_; $localLine = &escape($localLine) if($localInlineNestLv == 0); $localLine =~ s!$regexp_yukiwiki_italic !&buildTagString($sysParam->{htmlTagEmphasisItalic}, $htmlAttribute->{italic}, &$func_inline($1, $localInlineNestLv + 1))!gex; $localLine =~ s!$regexp_yukiwiki_bold !&buildTagString($sysParam->{htmlTagEmphasisBold}, $htmlAttribute->{bold}, &$func_inline($1, $localInlineNestLv + 1))!gex; $localLine =~ s!(($regexp_yukiwiki_link)|($regexp_yukiwiki_plugin)) !&$func_inlineLinkAnother($1)!gex; return $localLine; }; $func_inlineLinkAnother = sub { my ($localString) = @_; if($localString =~ /^$regexp_yukiwiki_link/i ){ $localString = &buildAnchorString($localString, ''); } elsif($localString =~ /^$regexp_yukiwiki_plugin/){ my $pluginName = lc($1); my @pluginParam = split(/,/,$2); # plugin 処理 $localString = ($pluginName eq 'ruby') ? &buildRubyString($pluginParam[0], $pluginParam[1]) : ($pluginName eq 'link') ? &buildAnchorString($pluginParam[1], $pluginParam[0]) : ($pluginName eq 'amazon') ? &buildAnchorString('asin:'.$pluginParam[1], $pluginParam[0]) : ($pluginName eq 'amazon_detail') ? &buildAnchorString('asin:'.$pluginParam[0]. ':detail', $pluginParam[0]) : ($pluginName eq 'color') ? qq($pluginParam[1]) : ($pluginName eq 'style') ? qq($pluginParam[1]) : ($pluginName eq 'verb') ? &unescape($pluginParam[0]) : $localString; } return $localString; }; # 一行ずつフォーマット処理をする foreach (@lines) { # 末尾の\nを除去 chomp; # バーベイタムモード if($format_mode_verbatim >= 1){ my $localVerbatimLevel = $format_mode_verbatim + 1; if(/^(-{$localVerbatimLevel})\)$/){ push(@result, splice(@saved)); $format_mode_verbatim = 0; } else{ ($format_mode_verbatim == 1) ? push(@result, $_) : push(@result, &escape($_)); } next; } # 見出し if (/^(\*{1,3})(.*)/) { push(@result, splice(@saved), &buildHeadingString(length($1), &$func_inline($2, 0), '')); } # バーベイタムモード elsif (/^(-{2,3})\($/) { $format_mode_verbatim = length($1) - 1; &back_push('pre', 1, \@saved, \@result, $htmlAttribute->{pre}); next; } # 水平線 elsif (/^----/) { push(@result, splice(@saved), qq(
{p}>)); } # 整形済みテキスト elsif (/^\s(.*)$/) { &back_push('pre', 1, \@saved, \@result, $htmlAttribute->{pre}); push(@result, &escape($1)); # Not &$func_inline, but &escape } # YukiWikiからまるごと引用。 # This part is taken from Mr. Ohzaki's Perl Memo and Makio Tsukamoto's WalWiki. elsif (/^\,(.*?)[\x0D\x0A]*$/) { &back_push('table', 1, \@saved, \@result, $htmlAttribute->{table}); my $tmp = "$1,"; my @value = map {/^"(.*)"$/ ? scalar($_ = $1, s/""/"/g, $_) : $_} ($tmp =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g); # " my @align = map {(s/^\s+//) ? ((s/\s+$//) ? ' align="center"' : ' align="right"') : ''} @value; my @colspan = map {($_ eq '==') ? 0 : 1} @value; for (my $i = 0; $i < @value; $i++) { if ($colspan[$i]) { while ($i + $colspan[$i] < @value and $value[$i + $colspan[$i]] eq '==') { $colspan[$i]++; } $colspan[$i] = ($colspan[$i] > 1) ? sprintf(' colspan="%d"', $colspan[$i]) : ''; $value[$i] = sprintf('
{p}>");
# 大域変数の初期化
&initGlobalVariable($text,$ctx);
## 正規表現
my $regexp_pukiwiki_italic = qq('''([^']+?)'''); #'
my $regexp_pukiwiki_bold = qq(''([^']+?)''); #'
my $regexp_pukiwiki_insert = qq(%%%([^%]+?)%%%); #
my $regexp_pukiwiki_delete = qq(%%([^%]+?)%%); #
my $regexp_pukiwiki_footnote = '';
$regexp_pukiwiki_footnote = qr/\(\(.*?(?:(?:{$regexp_pukiwiki_footnote}).*)*?\)\)/;
my $regexp_pukiwiki_plugin = '';
#$regexp_pukiwiki_plugin = qr/&(\w+)\([^)]*\)({(.*(?:(?:{$regexp_pukiwiki_plugin}).*)*)})?;/;
$regexp_pukiwiki_plugin = qr/&(\w+)\([^)]*\)({([^}]*(?:(?:{$regexp_pukiwiki_plugin}).*)*)})?;/;
#
# 無理やり再帰(^^;
#
my $func_inline;
my $func_inlineFunction;
my $func_inlineFootnoteFilter;
my $func_inlinePluginFilter;
my $func_inlineLink;
my $func_inlineRefParam;
$func_inline = sub {
my $localLine = '';
my $localInlineNestLv = 0;
($localLine, $localInlineNestLv) = @_;
if(!defined($localLine)){
$localLine = '';
}
if(!defined($localInlineNestLv) || $localInlineNestLv == 0){
$localLine = &escape($localLine);
}
$localLine =~ s|$regexp_pukiwiki_italic
|&buildTagString($sysParam->{htmlTagEmphasisItalic},
$htmlAttribute->{italic},
&$func_inline($1, $localInlineNestLv + 1))|gex; # # 'Italic'
$localLine =~ s|$regexp_pukiwiki_bold
|&buildTagString($sysParam->{htmlTagEmphasisBold},
$htmlAttribute->{bold},
&$func_inline($1, $localInlineNestLv + 1))|gex; # 'Bold'
$localLine =~ s|$regexp_pukiwiki_insert
|&buildTagString($sysParam->{htmlTagInsert},
$htmlAttribute->{ins},
&$func_inline($1, $localInlineNestLv + 1))|gex; # u
$localLine =~ s|$regexp_pukiwiki_delete
|&buildTagString($sysParam->{htmlTagDelete},
$htmlAttribute->{del},
&$func_inline($1, $localInlineNestLv + 1))|gex; # s
# インライン入れ子レベルが0のときだけリンクアンカー生成を行う
if(!defined($localInlineNestLv) || $localInlineNestLv == 0){
# google, keyword以外
$localLine =~ s!
\[\[
((.+?)(?::|\>))?
(
(mailto|http|https|ftp|ASIN|ISBN|asin|isbn|anchor):([^\x00-\x20()<>\x7F-\xFF])*
)
\]\]
!&buildAnchorString($3, $2)!gexi;
# googleとkeywordの場合
$localLine =~ s!
\[\[
((.+?)(?::|\>))?
(
(google|keyword|anchor):[^\]]+
)
\]\]!&buildAnchorString($3, $2)!gexi;
}
$localLine =~ s|~$|
|g;
$localLine =~ s|&br;|
|gi;
$localLine =~ s|($regexp_pukiwiki_plugin)
|&$func_inlinePluginFilter($1, $localInlineNestLv)|gex;
$localLine =~ s|&\#([0-9A-Fa-f]+);|&\#$1;|gi;
$localLine =~ s|&([A-z]+);|&\$1;|gi;
# インライン入れ子レベルが0のときだけリンクアンカー生成を行う
if(/$regexp_pukiwiki_footnote/ && !(defined($localInlineNestLv) && $localInlineNestLv != 0)){
$localLine =~ s|($regexp_pukiwiki_footnote)|&$func_inlineFootnoteFilter($1)|gex;
}
return $localLine;
};
$func_inlineFootnoteFilter = sub {
my $localFootnoteString = '';
($localFootnoteString) = @_;
if($localFootnoteString =~ /^\(\((.+)\)\)$/ ){
$localFootnoteString = &buildFootnoteString($1);
}
return $localFootnoteString;
};
$func_inlinePluginFilter = sub {
my $localPluginString = '';
my $localInlineNestLv = 0;
($localPluginString, $localInlineNestLv) = @_;
if($localPluginString =~ /^&(\w+)\((.+)\);$/ ){
return &$func_inlineFunction($1, $2,'', $localInlineNestLv + 1);
}
elsif($localPluginString =~ /^&(\w+)\(([^){}]+?)\){(.+)};$/ ){
return &$func_inlineFunction($1, $2, $3, $localInlineNestLv + 1);
}
else{
return $localPluginString;
}
};
$func_inlineFunction = sub{
my ($localFuncName, $localFuncParam, $localInlineText, $localInlineNestLv) = @_;
# Color
if($localFuncName =~ /color/){
my ($localForeColor, $localBackColor) = split(/\,/, $localFuncParam);
my $localSpanStyle = '';
$localSpanStyle = qq(color:${localForeColor};);
if(defined($localBackColor) && $localBackColor ne ''){
$localSpanStyle = $localSpanStyle . qq(background-color:${localBackColor};);
}
return &buildTagString("span", qq(style="${localSpanStyle}"),
&$func_inline($localInlineText, $localInlineNestLv + 1));
}
# Size
elsif($localFuncName =~ /size/){
return &buildTagString("span", qq(style="font-size:${localFuncParam}px"),
&$func_inline($localInlineText, $localInlineNestLv + 1));
}
# ref
elsif($localFuncName =~ /ref/){
# カンマ区切りがあれば
if($localFuncParam =~ /^([^,]+)(,.+)$/){
return &$func_inlineRefParam(&buildAnchorString($1, ''), $2);
}
else{
return &buildAnchorString($localFuncParam, '');
}
}
# ruby
elsif($localFuncName =~ /ruby/){
return &buildRubyString($localFuncParam, &$func_inline($localInlineText, $localInlineNestLv + 1));
}
# aname
elsif($localFuncName =~ /aname/){
$localFuncParam =~ s/(\W)/'%' . unpack('H2', $1)/eg;
my $localRenderAnchorId = qq(id="${localFuncParam}" );
if(!$sysParam->{xhtml11mode}){
$localRenderAnchorId = $localRenderAnchorId . qq(name="${localFuncParam}");
}
return qq() .
&$func_inline($localInlineText, $localInlineNestLv + 1) . qq();
}
# verb
elsif($localFuncName =~ /verb/){
return &unescape($localFuncParam);
}
# style
elsif($localFuncName =~ /style/){
return &buildTagString("span", qq(style="${localFuncParam}"),
&$func_inline($localInlineText, $localInlineNestLv + 1));
}
};
$func_inlineRefParam = sub {
my ($localAnchorString, $localRefParam) = @_;
if($localRefParam =~ /,(left|right|center),?/){
my $localAlign = $1;
if($localRefParam =~ /,around,?/){
if($localAlign eq 'center'){
$localAlign = 'left';
}
$localAnchorString = qq(
{p}>");
}
# 整形済みテキスト
elsif (/^\s(.*)$/) {
&back_push('pre', 1, \@saved, \@result, $htmlAttribute->{pre});
push(@result, &escape($1));
}
# 改行
elsif (/^\#br/) {
push(@result, splice(@saved), '
');
}
# 寄せクリア
elsif (/^\#clear/) {
push(@result, splice(@saved), '
{pre}>)); } $format_mode_pre += length($1); } else{ if($format_mode_pre != 1){ push(@result, splice(@saved)); push(@result, qq('); $format_mode_pre = 0; } } } # >|...>|の場合にフラグがONならばHTMLエスケープを実施する。 # 以降の処理はスキップする(最終行の取得は行う) elsif(defined($sysParam->{hatenaPreHTMLEscape}) #&& $sysParam->{hatenaPreHTMLEscape} == 1 && $format_mode_pre > 1){ push(@result, &escape($_)); $lastLine = $_; next; } # # アンカー付き見出し # elsif (/^(\*{1,3})([^\*]+)\*(.*)$/) { push(@result, splice(@saved), &buildHeadingString(length($1), &$func_inline($3), $2)); } # # 見出し # elsif (/^(\*{1,3})(.*)/) { push(@result, splice(@saved), &buildHeadingString(length($1), &$func_inline($2), '')); } # # リスト表示。 # elsif (/^(-+)(.*)$/) { &back_push('ul', length($1), \@saved, \@result, $htmlAttribute->{ul}); push(@result, qq({pre}>)); $format_mode_pre = length($1); } } } # # 整形済みテキスト(終了) # elsif (/^(\|{1,2})<$/) { if(defined($sysParam->{hatenaPreHTMLEscape}) && $sysParam->{hatenaPreHTMLEscape} == 1){ if($format_mode_pre == 1){ push(@result, splice(@saved)); push(@result, ''); } $format_mode_pre -= length($1); } else{ if($format_mode_pre == length($1)){ push(@result, splice(@saved)); push(@result, '
{blockquote}>)); } elsif (/^>>$/) { push(@result, splice(@saved)); push(@result, qq({blockquote}>)); } elsif (/^<<$/) { push(@result, splice(@saved)); push(@result, ''); } elsif (/^$/){ if($lastLine =~ /^$/){ push(@result, "
"); } } # # 下書きモードでなければ・・・ # elsif ($format_mode_draft == 0){ # スタックを吐き出す push(@result, splice(@saved)); # 空白文字ではじまり、整形テキスト出力でないなら付加 if (/^\s+/) { ($format_mode_paragraph == 1 && $format_mode_pre != 1) ? push(@result, "{p}>", $_, "
") : push(@result, ($_)); } else{ my $inlineText = $_; # 論理行頭・行末の><の判定 if (/^>(<.*>)<$/) { $format_mode_paragraph = 0; $inlineText = $1; } elsif (/^>(<.*)/) { $format_mode_paragraph = 0; $inlineText = $1; } elsif (/(.*>)<$/) { $inlineText = $1; } if($sysParam->{convert_line_break}){ $inlineText = $inlineText . "
"; } #付加実施判定後、インライン処理。 if($format_mode_paragraph == 1 && $format_mode_pre != 1){ $inlineText = qq(
{p}>$inlineText
); } push(@result, &$func_inline($inlineText)); # ><で終わっている場合は付加フラグを立てる。 if (/><$/) { $format_mode_paragraph = 1; } } } #最終処理行・状態の保存 $lastLine = $_; } # スタックをすべて押し出し、脚注を挟み、すべて改行文字を挟み込み出力。 push(@result, splice(@saved)); if($counter_footnote > 0){ push(@result, qq(<$sysParam->{htmlTagFootnoteList} $sysParam->{htmlAttrFootnoteList}>)); push(@result, $buffer_footnote); push(@result, qq($sysParam->{htmlTagFootnoteList}>)); } return join("\n", @result); } ############################################################### # 共通レンダリング部分 (0) インラインタグ # buildTagString($localTag, $localAttr, $localInline) ############################################################### sub buildTagString{ # 宣言部 my $localTag = ''; my $localAttr = ''; my $localInline = ''; ($localTag, $localAttr, $localInline) = @_; return qq(<${localTag} ${localAttr}>${localInline}${localTag}>); } ############################################################### # 共通レンダリング部分 (1) ルビ # buildRubyString($localBaseText, $localRubyText) ############################################################### sub buildRubyString{ my $localBaseText = ''; my $localRubyText = ''; ($localBaseText, $localRubyText) = @_; return qq(
${localBaseText} ); } ############################################################### # 共通レンダリング部分 (2) リンクアンカー # buildAnchorString($localAddress, $localAltText) ############################################################### sub buildAnchorString{ # 宣言部 my $localAddress = ''; my $localAltText = ''; my $localAnswer = ''; my $localTarget = ''; ($localAddress, $localAltText) = @_; # リンクのターゲットウィンドウの取得設定 # (XHTML 1.1モードの場合、JavaScriptに置き換える) $localTarget = ($sysParam->{linkAnchorTarget} ne '') ? $sysParam->{linkAnchorTarget} : '_self'; $localTarget = qq(target="${localTarget}"); if($sysParam->{xhtml11mode}){ if($localTarget ne qq(target="_self")){ $localTarget = qq(onclick="window.open(this.href); return false;"); } else{ $localTarget = ""; } } ## ## http, https, ftpプロトコルのURI ## if ($localAddress =~ /^(http|https|ftp):/) { if ($sysParam->{linkAutoImage} and $localAddress =~ /\.(gif|png|jpeg|jpg)$/) { if(!defined($localAltText)){ $localAltText = ''; } $localAnswer = qq(); } else { if(defined($localAltText)){ if($localAltText eq ''){ $localAltText = $localAddress; } } else{ $localAltText = $localAddress; } if ($sysParam->{linkAutoImage} and $localAltText =~ /\.(gif|png|jpeg|jpg)$/) { $localAltText = qq(); } $localAnswer = qq({a}>${localAltText}); } } ## ## ローカルアンカージャンプ ## elsif ($localAddress =~ /^(anchor|\#):(.+)/) { # 宣言 my $localAnchorString = $2; # 代替テキストの設定 if(defined($localAltText)){ if($localAltText eq ''){ $localAltText = $localAnchorString; } } else{ $localAltText = $localAnchorString; } # リンク生成 $localAnchorString =~ s/(\W)/'%' . unpack('H2', $1)/eg; $localAnswer = qq(${localAltText}); } ## ## ASIN,ISBNコード(detail) ## elsif ($localAddress =~ /^(ISBN|ASIN|isbn|asin):([0-9A-Z\-]+):detail/) { my $localASINCode = $2; my $aws_url = 'http://xml.amazon.co.jp/onca/xml3?'; my @query; my @res; my $localAmazonAssociateID = 'hsjjp-22'; my $localAmazonAWSDevToken = '0Q00TC89ZRCXRJ390YR2'; my $localAmazonNoImageUrl = ''; # AmazonアソシエイトIDの取得 if(defined($sysParam->{linkAmazonAssociate}) && $sysParam->{linkAmazonAssociate} ne '') { $localAmazonAssociateID = $sysParam->{linkAmazonAssociate}; } # AWSデベロッパートークンの取得 if(defined($sysParam->{linkAmazonAWSToken}) && $sysParam->{linkAmazonAWSToken} ne '') { $localAmazonAWSDevToken = $sysParam->{linkAmazonAWSToken}; } # 画像なしのときの代替措置 if(defined($sysParam->{linkAmazonNoImageImage}) && $sysParam->{linkAmazonNoImageImage} ne '') { $localAmazonNoImageUrl = $sysParam->{linkAmazonNoImageImage}; } push @query, "AsinSearch=$localASINCode"; push @query, "dev-t=$localAmazonAWSDevToken"; push @query, "t=$localAmazonAssociateID"; push @query, "f=xml"; push @query, "type=heavy"; push @query, "locale=jp"; $aws_url .= join("&", @query); my $ua = new LWP::UserAgent; $ua->agent("mt-sukeroku-plus"); my $http_request = new HTTP::Request('GET', $aws_url); my $http_response = $ua->request($http_request); my $content = $http_response->{'_content'}; my $aws_answer; $aws_answer = XMLin($content); if (!($aws_answer)) { $localAnswer = ''; } else{ my $d = $aws_answer->{Details}; push(@res, qq()); push(@res, qq({a}>)); push(@res, qq()); push(@res, qq()); $localAnswer = join("\n", @res); } } ## ## ASIN,ISBNコード ## elsif ($localAddress =~ /^(ISBN|ASIN|isbn|asin):([0-9A-Z\-]+)(:image(:(small|large))?)?/) { # 宣言 my $localASINCode = $2; my $localImageKeyword = $3; my $localAmazonAssociateID = ''; my $localAmazonNoImageUrl = ''; # ASINではISBNの-を削除する必要がある。 $localASINCode =~ s/-//g; # 代替テキストの設定 if(defined($localAltText)){ if($localAltText eq ''){ $localAltText = $localAddress; } } else{ $localAltText = $localAddress; } # Amazon書影表示オプション(:image) if(defined($localImageKeyword) && $localImageKeyword ne ''){ my $localImageAddress = ''; # 画像なしのときの代替措置 if(defined($sysParam->{linkAmazonNoImageImage}) && $sysParam->{linkAmazonNoImageImage} ne '') { $localAmazonNoImageUrl = $sysParam->{linkAmazonNoImageImage}; } # 標準サイズ表示, サムネイル表示, 拡大表示。該当しない場合は空文字列。 $localImageAddress = ($localImageKeyword =~ /^:image$/) ? "${localASINCode}.09.MZZZZZZZ.jpg" : ($localImageKeyword =~ /^:image:small$/) ? "${localASINCode}.09.THUMBZZZ.jpg" : ($localImageKeyword =~ /^:image:large$/) ? "${localASINCode}.09.LZZZZZZZ.jpg" : ""; # HTMLの置き換え(インラインテキストに置き換える) $localAltText = ($localImageAddress eq '') ? '' :qq(); } # AmazonアソシエイトIDの取得 if(defined($sysParam->{linkAmazonAssociate}) && $sysParam->{linkAmazonAssociate} ne '') { $localAmazonAssociateID = $sysParam->{linkAmazonAssociate}; } # Amazonへのリンク生成 $localAnswer = qq({a}>${localAltText}); } ## ## mailto(メールアドレス) ## elsif ($localAddress =~ /^(mailto\:)?(.+\@.+)/) { # mailto:がない場合は補てん $localAddress = ($1 eq '') ? 'mailto:' . $localAddress : $localAddress; $localAltText = ($localAltText eq '') ? $2 : $localAltText; $localAnswer = qq(${localAltText}); } ## ## Google 検索 (original by のもとさん) + はてなキーワードリンク ## http://t.nomoto.org/diary/archives/000002.html ## elsif ($localAddress =~ /^(google|keyword):(.+)/) { # 宣言 my $localScheme = lc($1); my $localWords = $2; # 代替テキストの設定 if(defined($localAltText)){ if($localAltText eq ''){ $localAltText = $localWords; } } else{ $localAltText = $localWords; } # 空白類を+に変換 $localWords =~ s/(\W)/'%' . unpack('H2', $1)/eg; $localWords =~ tr/ /+/; # Google/はてなへのリンク生成 my $localHref = ($localScheme eq 'google') ? qq(${google_SearchURILeft}${localWords}) : ($localScheme eq 'keyword')? qq(${hatena_KeywordURILeft}${localWords}) : ''; $localAnswer = qq({a}>${localAltText}); } ## ## それ以外の場合 ## else{ $localAnswer = qq({a}>${localAddress}); } return $localAnswer; } ############################################################### # 共通レンダリング部分 (3) 見出し # buildHeadingString($localHeadingLv, $localInline) ############################################################### sub buildHeadingString{ # 宣言部 my $localHeadingLv = 1; my $localInline = ''; my $localHTag = ''; my $localHeadingAnchor = ''; my $localHeadingSymbol = ''; my $localHeadingAttr = ''; my $localAnchorString = ''; ($localHeadingLv, $localInline, $localAnchorString) = @_; if($localHeadingLv <= 1){ $localHTag = 'h3'; $counter_heading1++; $counter_heading2 = 0; $counter_heading3 = 0; $localHeadingAnchor = qq(${counter_heading1}); $localHeadingSymbol = $sysParam->{symbolHeading1}; $localHeadingAttr = $htmlAttribute->{heading1}; } elsif($localHeadingLv == 2){ $localHTag = 'h4'; $counter_heading2++; $counter_heading3 = 0; $localHeadingAnchor = qq(${counter_heading1}_${counter_heading2}); $localHeadingSymbol = $sysParam->{symbolHeading2}; $localHeadingAttr = $htmlAttribute->{heading2}; } elsif($localHeadingLv >= 3){ $localHTag = 'h5'; $counter_heading3++; $localHeadingAnchor = qq(${counter_heading1}_${counter_heading2}_${counter_heading3}); $localHeadingSymbol = $sysParam->{symbolHeading3}; $localHeadingAttr = $htmlAttribute->{heading3}; } # 見出し文字列のアンカー if(defined($localAnchorString) && $localAnchorString ne ''){ $localHeadingAnchor = $localAnchorString; $localHeadingAnchor =~ s/<\w+[^>]*>//gx; $localHeadingAnchor =~ s/(\W)/unpack('H2', $1)/eg; } else{ if(defined($sysParam->{typeHeadingAnchor}) && $sysParam->{typeHeadingAnchor} != 0){ $localHeadingAnchor = $localInline; $localHeadingAnchor =~ s/<\w+[^>]*>//gx; $localHeadingAnchor =~ s/(\W)/unpack('H2', $1)/eg; } else{ $localHeadingAnchor = qq(${mt_TextPartInitChar}_p${localHeadingAnchor}); } } my $localRenderAnchorId = qq(id="${localHeadingAnchor}" ); if(!$sysParam->{xhtml11mode}){ $localRenderAnchorId = $localRenderAnchorId . qq(name="${localHeadingAnchor}"); } return &buildTagString($localHTag, $localHeadingAttr, qq(${localHeadingSymbol}${localInline})); } ############################################################### # 共通レンダリング部分 (4) 脚注文字列出力 # buildFootnoteString($footnote_text) ############################################################### sub buildFootnoteString{ my $func_collapse_tag = sub{ my $tag_text = ''; ($tag_text) = @_; $tag_text =~ s/<[^>]+>//g; return $tag_text; }; my $footnote_text = ''; my $footnote_symbol = ''; my $footnote_anchor = ''; my $footnote_title = ''; ($footnote_text) = @_; # 脚注番号の前にある記号を取得 $footnote_symbol = ($mt_TextPartInitChar eq 't') ? $sysParam->{symbolFootnote1} : ($mt_TextPartInitChar eq 'm') ? $sysParam->{symbolFootnote2} : $sysParam->{symbolFootnote3}; # 脚注番号のカウントアップ $counter_footnote++; # 脚注リンクアンカー $footnote_anchor = qq(footnote_${mt_EntryId}${mt_TextPartInitChar}${counter_footnote}); # 脚注タイトル $footnote_title = &$func_collapse_tag(${footnote_text}); # 脚注本文 my $localRenderAnchorId = qq(id="${footnote_anchor}" ); if(!$sysParam->{xhtml11mode}){ $localRenderAnchorId = $localRenderAnchorId . qq(name="${footnote_anchor}"); } $buffer_footnote = $buffer_footnote . &buildTagString($sysParam->{htmlTagFootnoteItem}, $sysParam->{htmlAttrFootnoteItem}, qq(${footnote_symbol}${counter_footnote}: ${footnote_text})); # 脚注記号 $localRenderAnchorId = qq(id="${footnote_anchor}_root" ); if(!$sysParam->{xhtml11mode}){ $localRenderAnchorId = $localRenderAnchorId . qq(name="${footnote_anchor}_root"); } return &buildTagString($sysParam->{htmlTagFootnoteRoot}, $sysParam->{htmlAttrFootnoteRoot}, qq(${footnote_symbol}${counter_footnote})); } ################################################################ ##ここからはYukiWiki(http://www.hyuki.com/yukiwiki/)から ## ##抜粋引用させていただいているコードです。 ## ##------------------------------------------------------------## ##original code from YukiWiki(http://www.hyuki.com/yukiwiki/) ## ################################################################ sub back_push { my ($tag, $level, $savedref, $resultref, $attr) = @_; while (@$savedref > $level) { push(@$resultref, shift(@$savedref)); #my $shiftItem = shift(@$savedref); #push(@$resultref, $shiftItem); #if($level > 1 && ($shiftItem eq '' || $shiftItem eq '')){ # push(@$resultref, ''); #} } if(scalar(@{$savedref}) > 0){ if ($savedref->[0] ne "${tag}>") { push(@{$resultref}, splice(@{$savedref})); } } while (@$savedref < $level) { unshift(@$savedref, "$tag>"); #if($level > 1 && ($tag eq 'ul' || $tag eq 'ol')){ # push(@$resultref, ')); if(($d->{Authors})){ push(@res, qq(
)); push(@res, qq(- )); push(@res, '作者: '); # 作者 my $tmpcnt = 0; if(ref($d->{Authors}->{Author} eq 'ARRAY')){ foreach my $author(@{$d->{Authors}->{Author}}){ if($tmpcnt++ != 0){ push(@res, ', '); } push(@res, $author); } } else{ push(@res, $d->{Authors}->{Author}); } push(@res, qq(
)); } push(@res, qq(- )); push(@res, '出版社・メーカー: '); # 出版社・メーカー push(@res, $d->{Manufacturer}); push(@res, qq(
)); push(@res, qq(- )); push(@res, '発売日: '); # 発売日 push(@res, $d->{ReleaseDate}); push(@res, qq(
)); if($d->{Media}){ push(@res, qq(- )); push(@res, 'メディア: '); # メディア push(@res, $d->{Media}); push(@res, qq(
)); } # 評価があれば if($d->{Reviews}){ push(@res, qq(- )); push(@res, '評価: '); # 評価 push(@res, $d->{Reviews}->{AvgCustomerRating}); push(@res, '(全' . $d->{Reviews}->{TotalCustomerReviews} . '件)'); push(@res, qq(
)); } push(@res, qq('); #} push(@$resultref, "<$tag $attr>"); } } sub escape { my $s = shift; $s =~ s|\r\n|\n|g; $s =~ s|\&|&|g; $s =~ s|<|<|g; $s =~ s|>|>|g; $s =~ s|\"|"|g; return $s; } sub unescape { my $s = shift; # $s =~ s|\n|\r\n|g; $s =~ s|\&|\&|g; $s =~ s|\<|\<|g; $s =~ s|\>|\>|g; $s =~ s|\"|\"|g; return $s; } 1;