| Tripletail documentation | Contained in the Tripletail distribution. |
Tripletail::Filter::SEO - SEO出力フィルタ
$TL->setContentFilter('Tripletail::Filter::HTML');
$TL->setContentFilter(['Tripletail::Filter::SEO', 1001]);
$TL->print($TL->readTextFile('foo.html'));
このフィルタはリンクの QUERY_STRING を次のように PATH_INFO に変換する。
<a href="foo.cgi?Command=Foo&mode=1&SEO=1"> ↓ <a href="foo/Command/Foo/mode/1">
クエリの中にキーワードSEO=1を含んでいるもののみを対象とし、 リンク変換後にはSEO=1は消去する。
また、head要素内にbase要素を追加する。head要素が存在しない場合は body要素開始直前にhead要素が挿入されるが、body要素も存在しなければ 何も挿入されない。元々base要素が存在した場合はそのhref属性が置き換えられる。
REQUEST_URI: http://foo.com/bar/baz.cgi 挿入される要素: <base href="http://foo.com/bar/">
注意:
このフィルタは Tripletail::Filter::HTML や Tripletail::Filter::MobileHTML よりも後に実行されるように設定しなければならない。
また、リンクを書き換えた場合、そのリクエストは Tripletail::InputFilter::SEO を使用しなければ正常に受け取れない。
出力は Shift_JIS,EUC-JP,UTF-8 のいずれかでなければならない。 JIS コードの場合は正常に動作しない。
$TL->getContentFilter(1001)->setOrder(qw(ID Name));
SEO変換時に、出力するキーの順序を指定します。 指定されていないキーは、setOrder で指定されたキーの後に文字列順にソートされて出力されます。
$TL->getContentFilter(1001)->toLink($TL->newForm(KEY => 'VALUE'));
フォームオブジェクトを、SEO変換と同様の形でリンクに変換します。
$TL->setContentFilter(['Tripletail::Filter::SEO', 1001], hide_extension => 0);
リンク変換の際、拡張子を削除するかどうか。省略可能。デフォルトは1。
Copyright 2006 YMIRLINK Inc.
This framework is free software; you can redistribute it and/or modify it under the same terms as Perl itself
このフレームワークはフリーソフトウェアです。あなたは Perl と同じライセンスの 元で再配布及び変更を行うことが出来ます。
Address bug reports and comments to: tl@tripletail.jp
HP : http://tripletail.jp/
| Tripletail documentation | Contained in the Tripletail distribution. |
# ----------------------------------------------------------------------------- # Tripletail::Filter::SEO - SEOåºåãã£ã«ã¿ # ----------------------------------------------------------------------------- package Tripletail::Filter::SEO; use strict; use warnings; use Tripletail; require Tripletail::Filter; our @ISA = qw(Tripletail::Filter); # ãã®ãã£ã«ã¿ã¯ãªã³ã¯ã®QUERY_STRINGãæ¬¡ã®ããã«PATH_INFOã«å¤æããã # # <a href="foo.cgi?Command=Foo&mode=1&SEO=1"> # ããããããããâ # <a href="foo/Command/Foo/mode/1"> # # ã¯ã¨ãªã®ä¸ã«ãã¼ã¯ã¼ãSEO=1ãå«ãã§ãããã®ã®ã¿ã対象ã¨ãã # ãªã³ã¯å¤æå¾ã«ã¯SEO=1ã¯æ¶å»ããã # # # ã¾ããheadè¦ç´ å ã«baseè¦ç´ ã追å ããã # headè¦ç´ ãåå¨ããªãå ´åã¯bodyè¦ç´ éå§ç´åã«headè¦ç´ ãæ¿å ¥ããããã # bodyè¦ç´ ãåå¨ããªããã°ä½ãæ¿å ¥ãããªãã # å ã baseè¦ç´ ãåå¨ããå ´åã¯ãã®href屿§ãç½®ãæããããã # # REQUEST_URI: http://foo.com/bar/baz.cgi # æ¿å ¥ãããè¦ç´ : <base href="http://foo.com/bar/"> # ãªãã·ã§ã³ä¸è¦§: # * hide_extension => ãªã³ã¯å¤æã®éãæ¡å¼µåãåé¤ãããã©ãããããã©ã«ã1ã # 注æ: # * ãã®ãã£ã«ã¿ã¯Tripletail::Filter::HTMLãTripletail::Filter::MobileHTMLããã # å¾ã«å®è¡ãããããã«è¨å®ããªããã°ãªããªãã # * Tripletail::Filter::HTML, Tripletail::Filter::MobileHTML ãã¿ã°ã®éä¸ã§åºåã£ã¦ # åºåãè¡ããªãæ§è³ªã«ä¾åãã¦ããã # ãã以å¤ã®ã«ã¹ã¿ã ãã£ã«ã¿ã¨å ¼ç¨ããå ´åã¯ãã®ç¹ã注æãã # å¿ è¦ãããã # * JISã³ã¼ãã§ã®åºåæã¯æ£å¸¸ã«åä½ããªãã # * charsetã«ã¯Tripletail::Filter::HTMLã¾ãã¯Tripletail::Filter::MobileHTML㨠# åãæåã³ã¼ããæå®ããªããã°ãªããªãã 1; sub _new { my $class = shift; my $this = $class->SUPER::_new(@_); my $defaults = [ [charset => 'Shift_JIS'], [hide_extension => 1], ]; $this->_fill_option_defaults($defaults); my $check = { charset => [qw(defined no_empty scalar)], hide_extension => [qw(scalar)], }; $this->_check_options($check); $this->reset; $this; } sub print { my $this = shift; my $str = shift; if(ref($str)) { die __PACKAGE__."#print: arg[1] is a reference. [$str] (第1弿°ããªãã¡ã¬ã³ã¹ã§ã)\n"; } $this->_filter($str); } sub flush { my $this = shift; ''; } sub setOrder { my $this = shift; my @order = @_; my $count = 0; foreach my $data (@order) { $count++; if(ref($data)) { die __PACKAGE__."#setOrder: arg[$count] is a reference. [$data] (第${count}弿°ããªãã¡ã¬ã³ã¹ã§ã)\n"; } } $this->{order} = \@order; $this; } sub toLink { my $this = shift; my $form = shift; my $base = shift; if(!defined($form)) { die __PACKAGE__."#toLink: arg[1] is not defined. (第1弿°ãæå®ããã¦ãã¾ãã)\n"; } elsif(ref($form) ne 'Tripletail::Form') { die __PACKAGE__."#toLink: arg[1] is not an instance of Tripletail::Form. [$form]. (第1弿°ãFormãªãã¸ã§ã¯ãã§ã¯ããã¾ãã)\n"; } if(ref($base)) { die __PACKAGE__."#toLink: arg[2] is a reference. (第2弿°ããªãã¡ã¬ã³ã¹ã§ã)\n"; } $form = $form->clone->delete('SEO'); my $link = $form->toLink($base); my $query = $TL->newForm($TL->unescapeTag($link)); $this->__makeLink($link, $query); } sub reset { my $this = shift; $this->SUPER::reset(); $this->{header_skipped} = undef; # HTTPãããé¨ãééããå¾ã§ããã°1 $this->{rebased} = undef; # baseè¦ç´ ãæ¸æããè¥ããã¯è¿½å ããå¾ã§ããã°1 $this->{order} = []; # åºåé ã®æå® $this; } sub _filter { my $this = shift; my $str = shift; my $header = ''; if(!$this->{header_skipped}) { # HTTPãããé¨ãééããã¾ã§ä½ãããªãã while($str =~ s/^(.+?\r?\n)//) { $header .= $1; if($1 !~ m/\S/) { # ãããçµäº $this->{header_skipped} = 1; last; } } } if(length($str)) { $str = $this->_rebase($str); $str = $this->_relink($str); } $header . $str; } sub _rebase { my $this = shift; my $html = shift; if($this->{rebased}) { return $html; } my $filter = $TL->newHtmlFilter( interest => [qw[/head base body]], ); $filter->set($html); my $baseurl = $ENV{REQUEST_URI} || ''; $baseurl =~ s![^/]+$!!; if(!length($baseurl)) { # REQUEST_URIãä¸ãããã¦ããªãã®ã§ä½ãåºæ¥ãªãã return $html; } $baseurl = sprintf( '%s://%s%s', ($ENV{HTTPS} and $ENV{HTTPS} eq 'on') ? 'https' : 'http', $ENV{SERVER_NAME}, $baseurl, ); while(my ($context, $elem) = $filter->next) { if($this->{rebased}) { next; } if($elem->name eq 'base') { my $target = $elem->attr('target'); if(!defined($target) || $target eq '_self') { $elem->attr(href => $baseurl); $this->{rebased} = 1; #$TL->log( # __PACKAGE__, # sprintf( # 'Modified existent base element: [%s] => [%s]', # $elem->attr('href'), $baseurl) #); } } elsif($elem->name eq '/head') { # ç´åã«æ¿å ¥ã my $base = $context->newElement('base'); $base->attr(href => $baseurl); $context->delete; $context->add($base); $context->add($elem); $this->{rebased} = 1; #$TL->log( # __PACKAGE__, # sprintf( # 'Inserted base element before the end of head element: [%s]', # $baseurl) #); } elsif($elem->name eq 'body') { # ç´åã«headãæ¿å ¥ã $context->delete; $context->add($context->newElement('head')); my $base = $context->newElement('base'); $base->attr(href => $baseurl); $context->add($base); $context->add($context->newElement('/head')); $this->{rebased} = 1; #$TL->log( # __PACKAGE__, # sprintf( # 'Inserted head and base elements before the beginning of body element: [%s]', # $baseurl) #); } } $filter->toStr; } sub _relink { my $this = shift; my $html = shift; my $filter = $TL->newHtmlFilter( interest => ['a', 'form'], ); $filter->set($html); while(my ($context, $elem) = $filter->next) { if($elem->name eq 'a') { my $link = $elem->attr('href'); defined $link or next; my $query = $TL->newForm($TL->unescapeTag($link)); if($query->get('SEO')) { # 対象ã«ãªã£ã¦ãã $query->delete('SEO'); my $new_url = $this->__makeLink($link, $query); $elem->attr(href => $new_url) } } elsif($elem->name eq 'form') { $elem->attr(EXT => undef); } } $filter->toStr; } sub __makeLink { my $this = shift; my $link = shift; my $query = shift; local($_); my @params; foreach my $key (@{$this->{order}}) { if($query->exists($key)) { foreach my $value (sort $query->getValues($key)) { push(@params, $key, $value); } $query->delete($key); } } foreach my $key (sort $query->getKeys) { next if($key eq 'INT'); foreach my $value (sort $query->getValues($key)) { push(@params, $key, $value); } } my $path_info = join( '/', map { $TL->encodeURL($_); } @params); if(defined($_ = $query->getFragment)) { $path_info .= '#' . $TL->encodeURL($_); } (my $file = $link) =~ s/\?.*$//; if($this->{option}{hide_extension}) { $file =~ s/\..+$//; # æ¡å¼µåãæ¶ã } my $new_url = $file . ($path_info ? "/$path_info" : ''); #$TL->log(__PACKAGE__, sprintf ('Relinked: [%s] => [%s]', $elem->attr('href'), $new_url)); $new_url; } __END__