#!/usr/bin/perl -w #-------------------------------------------------------------------# # MovableType TextFormatingプラグイン mt-sukeroku-plus.pl ver.1.01b # # Copyright(C)DonaDona(KITAO Masato) 2004 # #-------------------------------------------------------------------# #[UPDATE] はてなの>||...||<(入力した内容がそのまま表示される整形済みテキストブロック)に対応。 #[UPDATE] onClickと出力していたものをonclickに変更(validにするため) # (via. bit-a) http://common.dialog.jp/movabletype/archives/2004/08/movabletypewiki.html #[UPDATE] 一行の中に二つのインラインを入れるとインラインの終わりを正しく判別できない障害を対策。 # (via. 世界の果てから) http://blog.positrail.org/archives/2004/08/pukiwiki_1.html #[懸案] http://eternal.ddo.jp/~mitsuhiko/diary/archives/2004/09/mtsukerokuplusp_2.html #[UPDATE] はてなダイアリー風記法 http://...:title=hogehogeに対応。 # http://d.hatena.ne.jp/hatenadiary/20040915#1095241004 package MT::Plugins::SukerokuPlus; use vars qw($VERSION); $VERSION = 1.01; use strict; use MT; use MT::Blog; use MT::Entry; use MT::Template::Context; use MT::Util qw(encode_html first_n_words); ############################################################################## ## ■■■■■■■■■■■■ 設定パラメータの記述 ■■■■■■■■■■■■ ## ## 【ここから】 ## ############################################################################## 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', # ■脚注の先頭につける文字列(加工なく出力されます) # ※出力を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風フォーマットでエントリの末尾に
# を出力する # ・出力する… 1, 出力しない… 0 pukiwikiBottomClearOutput => 1, }; # ■各種HTML要素に対する属性指定(CSSのクラス指定などを想定) my $htmlAttribute = { bold => '', # htmlTagEmphasisBoldに並行適用 italic => '', # htmlTagEmphasisItalicに並行適用 del => '', # htmlTagDeleteに並行適用 ins => '', # htmlTagInsertに並行適用 blockquote => '', pre => '', p => '', heading1 => '', # * 章に対応 heading2 => '', # ** 節に対応 heading3 => '', # *** 項に対応 a => '', ul => '', ul_li => '', ol => '', ol_li => '', dl => '', dl_dt => 'style="text-decoration:underline;"', dl_dd => '', hr => 'width="50%"', table => 'border="1"', }; ############################################################################## ## ■■■■■■■■■■■■ 設定パラメータの記述 ■■■■■■■■■■■■ ## ## 【ここまで】 ## ############################################################################## ############################################################################## ## ■ TextFilter・コンテナタグの追加 ## ############################################################################## MT->add_text_filter(sukerokuplus_hatena => { label => 'SukerokuPlus(HatenaLike)', docs => 'http://hsj.jp/works/archives/000324.html', on_format => \& sukeroku_plus_hatena_format, }); MT->add_text_filter(sukerokuplus_yukiwiki => { label => 'SukerokuPlus(YukiWikiLike)', docs => 'http://hsj.jp/works/archives/000318.html', on_format => \& sukeroku_plus_yukiwiki_format, }); MT->add_text_filter(sukerokuplus_pukiwiki => { label => 'SukerokuPlus(PukiWikiLike)', docs => 'http://hsj.jp/works/archives/000317.html', on_format => \& sukeroku_plus_pukiwiki_format, }); ############################################################################## ## ■ 大域定数の定義 ## ############################################################################## my $regexp_LinkPattern = '(?:(?:(?:http|https|ftp|mailto|google|anchor|keyword):)|(?:(?:ISBN|isbn|ASIN|asin):\w+(?::image(?::\w+)?)?)|[^:])+'; my $amazon_ImageURILeft = "http://images-jp.amazon.com/images/P/"; my $amazon_ItemURILeft = "http://www.amazon.co.jp/exec/obidos/ASIN/"; my $google_SearchURILeft = "http://www.google.com/search?lr=lang_ja\&q="; my $hatena_KeywordURILeft = "http://d.hatena.ne.jp/keyword/"; ############################################################################## ## ■ 大域変数の定義 ## ############################################################################## # エントリーのURI my $mt_EntryPermalink = ''; my $mt_EntryId = ''; # 対象テキストエリア判定 my $mt_EntryTextPart = ''; my $mt_TextPartInitChar = ''; # 見出しカウンタ my $counter_heading1 = 0; my $counter_heading2 = 0; my $counter_heading3 = 0; # ((と))で囲まれた部分は脚注扱いとする my $counter_footnote = 0; my $buffer_footnote = ''; # 大域変数の初期化 sub initGlobalVariable { # パラメータの取得(#1:text, #2:context)→テキストの各行を改行で分割 my ($text, $ctx) = @_; ## エントリーのPermalinkの取得 my $func_getMTEntryPermalink = sub{ my $localAnswer = ''; if ((defined($ctx)) && (ref($ctx) eq 'MT::Template::Context')) { my $entry = $ctx->stash('entry'); if ($entry && $entry->id) { $localAnswer = $entry->permalink; $mt_EntryId = $entry->id; } } return $localAnswer; }; # テキストのどのパート(本文・追記・概略)かを判定。 my $func_decideEntryTextPart = sub { if ((defined $ctx) && (ref($ctx) eq 'MT::Template::Context')) { my $entry = $ctx->stash('entry'); if ($entry && $entry->id) { if(!defined $text){ $text = ''; } $mt_EntryTextPart = ($text eq $entry->text) ? 'text' : ($text eq $entry->text_more) ? 'text_more' : ($text eq $entry->excerpt) ? 'excerpt' : ''; } } }; # blogサイトURL, エントリーの絶対パスの取得 $mt_EntryPermalink = ''; $mt_EntryPermalink = &$func_getMTEntryPermalink(); # 対象テキストエリア判定 $mt_EntryTextPart = ''; $mt_TextPartInitChar = ''; &$func_decideEntryTextPart(); $mt_TextPartInitChar = ($mt_EntryTextPart eq 'text') ? 't' : ($mt_EntryTextPart eq 'text_more') ? 'm' : ($mt_EntryTextPart eq 'excerpt') ? 'e' : 'x' ; # 見出しカウンタ $counter_heading1 = 0; $counter_heading2 = 0; $counter_heading3 = 0; # 脚注カウンタとバッファ $counter_footnote = 0; $buffer_footnote = ''; } ############################################################################## ## ■ YukiWiki風テキストフォーマット用サブルーチン ## ## http://hsj.jp/works/archives/000318.html ## ############################################################################## sub sukeroku_plus_yukiwiki_format { # パラメータの取得(#1:text, #2:context)→テキストの各行を改行で分割 my ($text, $ctx) = @_; my (@lines) = split(/\n/, $text); # tagのスタックを初期化 my (@saved, @result); unshift(@saved, "

"); push(@result, "

{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 '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(


{hr}/>)); } # リスト elsif (/^(-{1,3})(.*)/) { &back_push('ul', length($1), \@saved, \@result, $htmlAttribute->{ul}); push(@result, qq(
  • {ul_li}>) . &$func_inline($2, 0) . qq(
  • )); } # 定義リスト elsif (/^:([^:]+):(.*)/) { &back_push('dl', 1, \@saved, \@result, $htmlAttribute->{dl}); push(@result, qq(
    {dl_dt}>) . &$func_inline($1, 0) . qq(
    ), qq(
    {dl_dd}>) . &$func_inline($2, 0) . qq(
    )); } # 引用文 elsif (/^(>{1,3})(.*)/) { &back_push('blockquote', length($1), \@saved, \@result, $htmlAttribute->{blockquote}); push(@result, &$func_inline($2, 0)); if($sysParam->{convert_line_break}){ push(@result, "
    "); } } # 空行 elsif (/^$/) { push(@result, splice(@saved)); unshift(@saved, "

    "); push(@result, 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('%s', $align[$i], $colspan[$i], &$func_inline($value[$i], 0)); } else { $value[$i] = ''; } } push(@result, join('', '', @value, '')); } else { push(@result, &$func_inline($_, 0)); if($sysParam->{convert_line_break}){ push(@result, "
    "); } } } # スタックをすべて押し出し、すべて改行文字を挟み込み出力。 push(@result, splice(@saved)); return join("\n", @result); } ############################################################################## ## ■ PukiWiki風テキストフォーマット用サブルーチン ## ## http://hsj.jp/works/archives/000317.html ## ############################################################################## sub sukeroku_plus_pukiwiki_format { # パラメータの取得(#1:text, #2:context)→テキストの各行を改行で分割 my ($text, $ctx) = @_; my (@lines) = split(/\n/, $text); # バーベイタムモード(0=なし、1=あり) my $format_mode_verbatim = 0; my $regexp_pukiwiki_OpenHardVerbatim = ''; my $regexp_pukiwiki_CloseHardVerbatim = ''; my $regexp_pukiwiki_OpenSoftVerbatim = ''; my $regexp_pukiwiki_CloseSoftVerbatim = ''; if($sysParam->{pukiwikiVerbatimEnabled}){ $regexp_pukiwiki_OpenHardVerbatim = $sysParam->{pukiwikiHardVerbatimOpenRegexp}; $regexp_pukiwiki_CloseHardVerbatim = $sysParam->{pukiwikiHardVerbatimCloseRegexp}; $regexp_pukiwiki_OpenSoftVerbatim = $sysParam->{pukiwikiSoftVerbatimOpenRegexp}; $regexp_pukiwiki_CloseSoftVerbatim = $sysParam->{pukiwikiSoftVerbatimCloseRegexp}; } # tagのスタックを初期化 my (@saved, @result); unshift(@saved, "

    "); push(@result, "

    {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(

    ${localAnchorString}
    ); } else{ $localAnchorString = qq(
    ${localAnchorString}
    ); } } if($localRefParam =~ /,(wrap),?/){ $localAnchorString =~ s|(.+)|$1|gi; } if($localRefParam =~ /,([^,]+)$/){ my $localAltString = $1; if(grep($_ eq $localAltString, 'around','left','right','center','wrap','nowrap','nolink','noembed') == 0){ $localAnchorString =~ s|alt=\"[^\"]*\"|alt=\"${localAltString}\"|gi; } } if($localRefParam =~ /,(noembed),?/){ $localAnchorString =~ s!()!$2!gi; #" } return $localAnchorString; }; #----------------------------------------------------------------- # 一行ずつフォーマット処理をする #----------------------------------------------------------------- foreach (@lines) { # 末尾の\nを除去 chomp; # バーベイタムモード(Hardモードを優先検索します) if($sysParam->{pukiwikiVerbatimEnabled}){ if($format_mode_verbatim >= 1){ if(/$sysParam->{pukiwikiHardVerbatimCloseRegexp}/ && $format_mode_verbatim == 2){ $format_mode_verbatim = 0; } elsif(/$sysParam->{pukiwikiSoftVerbatimCloseRegexp}/ && $format_mode_verbatim == 1){ $format_mode_verbatim = 0; } else{ ($format_mode_verbatim == 1) ? push(@result, $_) : push(@result, &escape($_)); } next; } elsif(/$sysParam->{pukiwikiHardVerbatimOpenRegexp}/){ $format_mode_verbatim = 2; next; } elsif(/$sysParam->{pukiwikiSoftVerbatimOpenRegexp}/){ $format_mode_verbatim = 1; next; } } # 見出し if (/^(\*{1,3})(.*)/) { push(@result, splice(@saved), &buildHeadingString(length($1), &$func_inline($2, 0), '')); } # 水平線 elsif (/^----/) { push(@result, splice(@saved), qq(
    {hr} />)); } # リスト elsif (/^(-{1,3})(.*)/) { &back_push('ul', length($1), \@saved, \@result, $htmlAttribute->{ul}); push(@result, qq(
  • {ul_li}>) , &$func_inline($2, 0) , qq(
  • )); } # 番号リスト elsif (/^(\+{1,3})(.*)/) { &back_push('ol', length($1), \@saved, \@result, $htmlAttribute->{ol}); push(@result, qq(
  • {ol_li}>) , &$func_inline($2, 0) , qq(
  • )); } # 定義リスト elsif (/^(\:{1,3})([^\|]*)\|(.*)/) { &back_push('dl', length($1), \@saved, \@result, $htmlAttribute->{dl}); push(@result, qq(
    {dl_dt}>) . &$func_inline($2, 0) . qq(
    ), qq(
    {dl_dd}>) , &$func_inline($3, 0) , qq(
    )); } # 引用文 elsif (/^(>{1,3})=((.+?)(?::|\>))?((http|https):([^\x00-\x20()<>\x7F-\xFF])*)/){ &back_push('blockquote', length($1), \@saved, \@result, qq( title="$3" cite="$4" ) . $htmlAttribute->{blockquote}); } # 引用文 elsif (/^(>{1,3})(.*)/) { &back_push('blockquote', length($1), \@saved, \@result, $htmlAttribute->{blockquote}); push(@result, &$func_inline($2, 0)); if($sysParam->{convert_line_break}){ push(@result, "
    "); } } # 空行 elsif (/^$/) { push(@result, splice(@saved)); unshift(@saved, "

    "); push(@result, "

    {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), '

    '); } # 参照 elsif (/^\#ref\((.+)\)$/) { my $localRefParam = $1; # カンマ区切りがあれば if($localRefParam =~ /^([^,]+)(,.+)$/){ push(@result, splice(@saved), &$func_inlineRefParam(&buildAnchorString($1, ''), $2)); } else{ push(@result, splice(@saved), &buildAnchorString($localRefParam, '')); } } # 逐語出力 elsif (/^\#verb\((.+)\)$/) { push(@result, &unescape($1)); } #//ではじまる行はコメント elsif (/^\/\/.*/) { } # 表組み(CSV) ,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('%s', $align[$i], $colspan[$i], &$func_inline($value[$i], 0)); } else { $value[$i] = ''; } } push(@result, join('', '', @value, '')); } # 表組み # 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 = split(/\|/, $tmp); my @colspan = map {($_ eq '>') ? 0 : 1} @value; my @th = map {(s/^~//) ? 1 : 0} @value; my @style = map {''} @value; for (my $i = 0; $i < @value; $i++) { while($value[$i] =~ s/^((LEFT|CENTER|RIGHT)?((BG)?COLOR\(([^\)]+)\))?(SIZE\(([^\)]+)\))?:)//i){ my $localMatch = $1; if($localMatch =~ /^(LEFT|CENTER|RIGHT):$/i){ $style[$i] .= "text-align:" . lc($1) . ";"; } elsif($localMatch =~ /^((?:BG)?COLOR)\(([^\)]+)\):$/i){ $style[$i] .= (lc($1) eq 'color') ? "color:$2;" : "background-color:$2;"; } elsif($localMatch =~ /^(size)\(([^\)]+)\):$/i){ $style[$i] .= "font-size:$2px;"; } } } for (my $i = 0; $i < @value; $i++) { if ($colspan[$i] == 1) { while ($i - $colspan[$i] >= 0 and $value[$i - $colspan[$i]] eq '>') { $value[$i - $colspan[$i]] = ''; $colspan[$i]++; } $colspan[$i] = ($colspan[$i] > 1) ? sprintf(' colspan="%d"', $colspan[$i]) : ' nowrap="nowrap" '; my $thisCellTag = ($th[$i]) ? 'th' : 'td'; $value[$i] = sprintf('<%s%s style="%s">%s', $thisCellTag, $colspan[$i], $style[$i], &$func_inline($value[$i], 0), $thisCellTag); } } push(@result, join('', '', @value, '')); } # 右寄せ・中央寄せ・右寄せ elsif (/^(LEFT|CENTER|RIGHT)\:(.*)/i) { my $localTextAlign = lc($1); &back_push('div', 1, \@saved, \@result, qq( style="text-align:${localTextAlign};" )); push(@result, &$func_inline($2, 0)); if($sysParam->{convert_line_break}){ push(@result, "
    "); } } # 段落(行頭特殊文字エスケープ含む) elsif (/^(\~)?(.*)/) { my $thisLine = $2; my $lastResult = pop(@result); if($lastResult =~ /<\/(li|dd|blockquote)>/){ if($sysParam->{convert_line_break}){ push(@result, "
    "); } push(@result, &$func_inline($thisLine, 0), $lastResult); } else{ push(@result, $lastResult, &$func_inline($thisLine, 0)); if($sysParam->{convert_line_break}){ push(@result, "
    "); } } } } # スタックをすべて押し出し、脚注を挟み、すべて改行文字を挟み込み出力。 # ただしデフォルト要素しか存在しない場合は空行を返す。 push(@result, splice(@saved)); if($#result > 2){ if($sysParam->{pukiwikiBottomClearOutput}){ push(@result, '
    '); } if($counter_footnote > 0){ push(@result, qq(<$sysParam->{htmlTagFootnoteList} $sysParam->{htmlAttrFootnoteList}>)); push(@result, $buffer_footnote); push(@result, qq({htmlTagFootnoteList}>)); } return join("\n", @result); } else{ return ""; } } ############################################################################## ## ■ はてなダイアリー風テキストフォーマット用サブルーチン ## ## http://hsj.jp/works/archives/000324.html ## ############################################################################## sub sukeroku_plus_hatena_format { # パラメータの取得(#1:text, #2:context)→テキストの各行を改行で分割 my ($text, $ctx) = @_; my (@lines) = split(/\n/, $text); ## 脚注正規表現 my $regexp_footnote = ''; $regexp_footnote = qr/\(\(.*?(?:(?:{$regexp_footnote}).*)*?\)\)/; # 論理行頭が>|で開始し、論理行末が|<で終了するまで 整形済みテキストの扱いとする my $format_mode_pre = 0; # 論理行頭が>で開始し、論理行末が<で終了するまで

    の囲み処理を行う my $format_mode_paragraph = 1; # 論理行頭が><で終了するまで整形済みテキストの扱いとする my $format_mode_draft = 0; # 大域変数の初期化 &initGlobalVariable($text,$ctx); # tagのスタックを初期化 my (@saved, @result); # 処理上の最終行の状態と内容 my $lastLine = ''; # インライン処理 my $func_inline; my $func_inlineLink; # URL自動リンク関係 $func_inlineLink = sub { my ($localString) = @_; #[]URL[]…そのまま出力 if($localString =~ /^\[\](.+)\[\]$/ ){ $localString = $1; } #[[Words]]…キーワード扱い elsif($localString =~ /^\[\[(.+)\]\]$/ ){ $localString = &buildAnchorString('keyword:' . $1, ''); } #[URL]…URLを切り出し elsif($localString =~ /^\[(.+):title=(.+)\]$/ ){ $localString = &buildAnchorString($1, $2); } #[URL]…URLを切り出し elsif($localString =~ /^\[(.+)\]$/ ){ $localString = &buildAnchorString($1, ''); } #[URL]…amazonを有効化 elsif($localString =~ /^(src|href|cite)=[\'\"](.+)[\'\"]$/i ){ my $localAttr = $1; my $localUrl = $2; if($localUrl =~ /^(ISBN|isbn|ASIN|asin)/){ my $localTempAnswer = &buildAnchorString($localUrl, ''); $localTempAnswer =~ s|\x7F-\xFF])*\[\]) | # [URL] (\[(http|https|ftp|mailto|isbn|asin|ISBN|ASIN|anchor):([^\x00-\x20()<>\x7F-\xFF])*(:title=.*)?\]) | # [google:WORDs] (\[(google):[^\]]+\]) | # [keyword:WORDs] (\[(keyword):[^\]]+\]) | # [anchor:WORDs] (\[(anchor):[^\]]+\]) | # src="URL", href="url" ((src|href|cite)=[\'\"](http|https|ftp|mailto|isbn|asin|ISBN|ASIN|anchor):([^\x00-\x20()<>\x7F-\xFF])*[\'\"]) | # URL ((http|https|ftp|mailto|isbn|asin|ISBN|ASIN|anchor):([^\x00-\x20()<>\x7F-\xFF])*) )!&$func_inlineLink($1)!igex; } # ■ キーワードリンク if(/\[\[([^\]]+)\]\]/){ $inlineText =~ s!( (\[\[[^\]]+\]\]) )!&$func_inlineLink($1)!gex; } # ■ 脚注 if(/$regexp_footnote/ && (!defined($inlineNested) || !(defined($inlineNested) && $inlineNested))){ my $func_footnote_switch = sub{ my ($localString) = @_; if($localString =~ /^\(\(\(/ ){ $localString = $localString; } elsif($localString =~ /^\)(\(\(.+\)\))\($/ ){ $localString = $1; } elsif($localString =~ /^\(\((.+)\)\)$/ ){ $localString = &buildFootnoteString($1); } return $localString; }; # さまざまなパターンについて $inlineText =~ s!( (\($regexp_footnote\)) | (\)$regexp_footnote\() | ($regexp_footnote) )!&$func_footnote_switch($1)!gex; } return $inlineText; }; # 一行ずつフォーマット処理をする foreach (@lines) { # 末尾の\nを除去 chomp; # # 下書きテキスト # if (/^><$/) { if($format_mode_draft == 1){ $format_mode_draft = 0; } } # # 整形済みテキスト(開始) # elsif (/^>(\|{1,2})$/) { if(defined($sysParam->{hatenaPreHTMLEscape}) && $sysParam->{hatenaPreHTMLEscape} == 1){ if($format_mode_pre == 0){ push(@result, splice(@saved)); push(@result, qq(
    {pre}>));
            }
            $format_mode_pre += length($1);
          }
          else{
            if($format_mode_pre != 1){
              push(@result, splice(@saved));
              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, '
    '); $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(
  • {ul_li}>) . &$func_inline($2) . qq(
  • )); } elsif (/^(\++)(.*)$/) { &back_push('ol', length($1), \@saved, \@result, $htmlAttribute->{ol}); push(@result, qq(
  • {ol_li}>) . &$func_inline($2) . qq(
  • )); } # # 用語定義 # elsif(/^:($regexp_LinkPattern)?:(.*)/){ &back_push('dl', 1, \@saved, \@result, $htmlAttribute->{dl}); if(defined($1) && $1 ne ''){ push(@result, qq(
    {dl_dt}>) . &$func_inline($1) . '
    '); } push(@result, qq(
    {dl_dd}>) . &$func_inline($2) . '
    '); } # # 引用 # # 引用文 elsif (/^>>=((.+?)(?::|\>))?((http|https):([^\x00-\x20()<>\x7F-\xFF])*)$/) { push(@result, splice(@saved)); push(@result, qq(
    {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({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}); } ############################################################### # 共通レンダリング部分 (1) ルビ # buildRubyString($localBaseText, $localRubyText) ############################################################### sub buildRubyString{ my $localBaseText = ''; my $localRubyText = ''; ($localBaseText, $localRubyText) = @_; return qq(${localBaseText}\(${localRubyText}\)); } ############################################################### # 共通レンダリング部分 (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(${localAltText}); } else { if(defined($localAltText)){ if($localAltText eq ''){ $localAltText = $localAddress; } } else{ $localAltText = $localAddress; } if ($sysParam->{linkAutoImage} and $localAltText =~ /\.(gif|png|jpeg|jpg)$/) { $localAltText = qq(${localAltText}); } $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コード ## elsif ($localAddress =~ /^(ISBN|ASIN):([0-9A-Z\-]+)(:image(:(small|large))?)?/) { # 宣言 my $localASINCode = $2; my $localImageKeyword = $3; my $localAmazonAssociateID = ''; # 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 = ''; # 標準サイズ表示, サムネイル表示, 拡大表示。該当しない場合は空文字列。 $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(${localAltText}); } # 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 "") { push(@{$resultref}, splice(@{$savedref})); } } while (@$savedref < $level) { unshift(@$savedref, ""); #if($level > 1 && ($tag eq 'ul' || $tag eq 'ol')){ # push(@$resultref, '

  • '); #} 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;