Title goes here #### <& .link, 'Edit Settings', '/widget/settings', %Context &> ... <%def .link> % my( $title, $page, %args ) = @_; <% $title |h %> #### Edit Settings #### <& .link, 'Edit Settings', '/widget/settings', %Context |w &> #### package LinkToMason; use strict; use CGI(); use URI::Escape(); sub escape_url { my( $class, $string ) = @_; # Escape using default except don't escape '{' nor '}': return URI::Escape::uri_escape( $string, "^A-Za-z0-9\\-_.!~*'(){}" ); } sub as_url { my( $class, $page, $rel, %args ) = @_; if( $page !~ m(^/) ) { require Carp; Carp::croak( "..." ) if ! $rel; $rel =~ s{/[^/]*$}{}; $page = "$rel/$page"; } return $page if ! %args; return "$page?" . join ';', map { join '=', map $class->escape_url($_), $_, $args{$_} } sort keys %args; } sub html_link { my( $class, $title, $page, $args, $attrs, $rel ) = @_; $args ||= { }; $attrs ||= { }; if( ref $title ) { $title = $$title; # \ 'Real HTML' } else { $title = CGI->escapeHTML( $title ); # Non-HTML string } my $url = $class->as_url( $page, $rel, %$args ); return CGI->a( { href => $url, %$attrs }, $title ); } 1; #### <%once> use LinkToMason; <%args> $acct_id <%shared> my %Context = ( acct => $acct_id, widget => $widget_id, ); ... <& .link, "Edit $widget_name Settings", 'settings', %Context &> ... <%def .link><%perl> my( $title, $page, %args ) = @_; my $link = LinkToMason->html_link( $title, $page, \%args, { }, '/widget/', ); <% $link |n %> #### <& .link, "Edit $widget_name Settings", 'settings', 'acct,widg' &> ...