# Copyright 2013-2014 Stefan Goebel. # # This file is part of Newcomen. # # Newcomen is free software: you can redistribute it and/or modify it under the terms of the GNU # General Public License as published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # Newcomen is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even # the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along with Newcomen. If not, see # . package Newcomen::Formatter::RelativePaths; our $VERSION = 2014052501; use namespace::autoclean; use Moose '-meta_name' => '_moose_meta'; use MooseX::StrictConstructor; use Newcomen::Util::Hash qw( merge ); extends 'Newcomen::Formatter::Backend'; with 'Newcomen::Role::Attribute::Core'; with 'Newcomen::Role::Attribute::Config'; with 'Newcomen::Role::Attribute::URL'; sub BUILD { shift -> _config () -> add_default ( { 'formatter' => { 'relativepaths' => { 'open' => '{rel{', 'close' => '}}', 'separator' => ',', 'use_cache' => 1, }, }, } ); } override '_do_unique_id' => sub { my $self = shift; my $text = shift; my $options = shift; my $content = shift; my $page = shift; my $index = shift; my $config = $self -> _config () -> get (['formatter', 'relativepaths']) // {}; $config = merge ($config, $options -> data ()); return undef if exists $config -> {'use_cache'} and not $config -> {'use_cache'}; delete $config -> {'use_cache'}; return Newcomen::Util::data_sha1 ({ 'c' => $config, 'p' => $page -> dir (), }); }; override '_do_format' => sub { my $self = shift; my $text = shift; my $options = shift; my $content = shift; my $page = shift; my $index = shift; my $config = $self -> _config () -> get (['formatter', 'relativepaths']) // {}; $config = merge ($config, $options -> data ()); my $start = $config -> {'open' } // '{rel{'; my $stop = $config -> {'close' } // '}}'; my $separator = $config -> {'separator'} // ','; my @links = $text =~ /\Q$start\E(.+?)\Q$stop\E/g; my %links = (); for my $link (@links) { next if $links {$link}; my @parts = split ($separator, $link, -1); my $url = $self -> _url () -> get ([@parts]); if (defined $url and ref $url eq '' and $url ne '') { $url = $page -> rel ($url); $text =~ s/\Q$start$link$stop\E/$url/g; } else { $text =~ s/\Q$start$link$stop\E//g; } $links {$link} = 1; } return $text; }; __PACKAGE__ -> _moose_meta () -> make_immutable (); 1; __END__ #################################################################################################### =head1 NAME Newcomen::Formatter::RelativePaths - Reference other pages using relative paths. =head1 DESCRIPTION Formatter backends are usually not called directly. See L for the frontend documentation. This formatter backend uses the global URL map (see L) to allow other pages to be referenced inside a piece of content by their relative paths. The format to be used in the source text can be configured freely, see below. =head1 OPTIONS { 'formatter' => { 'relativepaths' => { 'open' => '{rel{', 'close' => '}}', 'separator' => ',', 'use_cache' => 1, }, }, } These are the default options set by this plugin. They may be overridden by user configuration. I and I specify the opening and closing "tags" for the relative link. The string between these two will be split on the separator character (or string) specified by I, and the resulting list will be passed to L's I method to retrieve the URL registered for the specified key. The URL (if any) will then be passed to the page's L method to convert it to a path relative to the current page. The whole string (including start and stop marker) will then be replaced by this relative path. For example, the string C<'{rel{Static,static/styles/style.css}}'> will result in this look-up in the URL map (if the default settings are used): $path = $url -> get (['Static', 'static/styles/style.css']); The resulting absolute C<$path> will then be converted to the relative path. This example would actually work for a page with the source path F (relative to the project root) created by the L plugin. The keys in the URL map are defined by the plugins creating a page, see the appropriate plugin documentation for details. If no URL can be found for a specific key, the whole string will be replaced by an empty string (i.e. the whole string will be deleted from the text). Note that there is no special treatment of whitespace or empty elements, i.e. both whitespace and empty elements will be preserved for the URL look-up, which is usually not what you want. I may be set to enable or disable the caching of the formatter results. It is enabled by default. See L for details. =head1 CACHING Results of this backend may be cached by the L. The formatting depends on the backend L, as well as on the page target. For effective caching the same options should be used for all pages. Since the formatting also depends on the page target, this formatter should be included in the formatter chain after formatters whose behaviour is only determined by their options. Note that the caching for this backend is still as effective as possible, by treating all pages with a target at the same directory level equally (e.g. relative paths will be the same for the two targets C<'some/path/file_1.html'> C<'some/path/file_2.html'>, so if the same content is included on these two pages, the formatted text will be cached and reused). Caching may be disabled for this backend (see L), it may also be disabled globally (see L). =head1 CLASS AND INSTANCE METHODS See L. =head1 SEE ALSO L, L, L, L, L =head1 VERSION This is version C<2014052501>. =head1 AUTHOR Stefan Goebel - newcomen {at} subtype {dot} de =head1 COPYRIGHT AND LICENSE Copyright 2013-2014 Stefan Goebel. This file is part of Newcomen. Newcomen is free software: you can redistribute it and/or modify it under the terms of the L as published by the L, either version 3 of the license, or (at your option) any later version. Newcomen is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the L for more details. You should have received a copy of the L along with Newcomen. If not, see >. =cut #################################################################################################### # :indentSize=3:tabSize=3:noTabs=true:mode=perl:maxLineLen=100: