Wiki-Toolkit-Formatter-UseMod-0.24/0002755000175000017500000000000012011755446015247 5ustar domdomWiki-Toolkit-Formatter-UseMod-0.24/Changes0000644000175000017500000000705212011755100016527 0ustar domdom0.24 12 August 2012 Add new "external_link_class" option to ->new, for people who prefer to style their external links with CSS. 0.23 1 February 2009 Fix POD errors and add POD test (#46) 0.22 18 April 2008 Add missing prerequisite of Wiki::Toolkit to aid automated testing. Clean up test sqlite databases correctly 0.21 12 April 2008 Made Test::MockObject optional. Skip tests broken by Text::WikiFormat bug (see http://www.wiki-toolkit.org/ticket/12) 0.20 6 June 2006 Update copyright notice. Fix bug with badly-formed internal links. 0.19 27 April 2006 Rename to Wiki::Toolkit::Formatter::UseMod 0.18 30 November 2004 Skip CGI::Wiki-requiring tests if CGI::Wiki not installed (thanks to CPAN tester "nothingmuch" for failure report). 0.17 26 November 2004 Removed debugging info accidentally left in last release. 0.16 20 September 2004 Added the "pass_wiki_to_macros" flag to let you write more powerful macros - see perldoc for details. Exposed the ->format_link method - see perldoc for details. 0.15 7 August 2004 Added very simple table support: || foo || bar || || bax || quux || Tables are added with a class of "user_table" so you can manipulate them in your stylesheet without affecting any other tables on your site. 0.14 9 July 2004 Allow subclassing to alter hyperlink appearance - see SUBCLASSING in perldoc CGI::Wiki::Formatter::UseMod. 0.13 4 June 2004 Leading ':' (which creates a definition list for an indent effect) now has better HTML, plus adds a leading   to allow blank lines in the indented text. 0.12 2 June 2004 Indentation now causes
, as per the UseMod spec.

0.11    20 November 2003
        Added (experimental, advanced) "munge_node_name" parameter.

0.10    20 October 2003
        Fixed bug - ordered lists shouldn't require indent.

0.09    22 September 2003
        Changed the way we call Text::WikiFormat, to avoid 
new in order for this to happen. **** RELATED NOTE FOR PEOPLE WITH OPENGUIDES INSTALLS **** Do *not* install this version of CGI::Wiki::Formatter::UseMod unless you are using OpenGuides version 0.21 or later. 0.04 14 May 2003 ->node_name_to_node_param method now takes notice of the force_ucfirst_nodes attribute. 0.03 28 April 2003 Subs in macros are now called with up to nine arguments. I know this is a bit arbitrary, but I now need it to support two arguments and I might as well allow a few more while I'm at it. 0.02 5 April 2003 Macros can now substitute the output of subs as well as plain strings. 0.01 3 March 2003 Initial release. Wiki-Toolkit-Formatter-UseMod-0.24/README0000644000175000017500000003241510421647355016134 0ustar domdomNAME Wiki::Toolkit::Formatter::UseMod - UseModWiki-style formatting for Wiki::Toolkit DESCRIPTION A formatter backend for Wiki::Toolkit that supports UseMod-style formatting. SYNOPSIS use Wiki::Toolkit::Formatter::UseMod; # Instantiate - see below for parameter details. my $formatter = Wiki::Toolkit::Formatter::UseMod->new( %config ); # Format some text. my $cooked = $formatter->format($raw); # Find out which other nodes that text would link to. my @links_to = $formatter->find_internal_links($raw); METHODS new my $formatter = Wiki::Toolkit::Formatter::UseMod->new( extended_links => 0, # $FreeLinks implicit_links => 1, # $WikiLinks force_ucfirst_nodes => 1, # $FreeUpper use_headings => 1, # $UseHeadings allowed_tags => [qw(b i)], # defaults to none macros => {}, pass_wiki_to_macros => 0, node_prefix => 'wiki.pl?', node_suffix => '', edit_prefix => 'wiki.pl?action=edit;id=', edit_suffix => '', munge_urls => 0, ); Parameters will default to the values shown above (apart from "allowed_tags", which defaults to allowing no tags). Internal links "node_prefix", "node_suffix", "edit_prefix" and "edit_suffix" allow you to control the URLs generated for links to other wiki pages. So for example with the defaults given above, a link to the Home node will have the URL "wiki.pl?Home" and a link to the edit form for the Home node will have the URL "wiki.pl?action=edit;id=Home" (Note that of course the URLs that you wish to have generated will depend on how your wiki application processes its CGI parameters - you can't just put random stuff in there and hope it works!) Internal links - advanced options If you wish to have greater control over the links, you may use the "munge_node_name" parameter. The value of this should be a subroutine reference. This sub will be called on each internal link after all other formatting and munging *except* URL escaping has been applied. It will be passed the node name as its first parameter and should return a node name. Note that this will affect the URLs of internal links, but not the link text. Example: # The formatter munges links so node names are ucfirst. # Ensure 'state51' always appears in lower case in node names. munge_node_name => sub { my $node_name = shift; $node_name =~ s/State51/state51/g; return $node_name; } Note: This is *advanced* usage and you should only do it if you *really* know what you're doing. Consider in particular whether and how your munged nodes are going to be treated by "retrieve_node". URL munging If you set "munge_urls" to true, then your URLs will be more user-friendly, for example http://example.com/wiki.cgi?Mailing_List_Managers rather than http://example.com/wiki.cgi?Mailing%20List%20Managers The former behaviour is the actual UseMod behaviour, but requires a little fiddling about in your code (see "node_name_to_node_param"), so the default is to not munge URLs. Macros Be aware that macros are processed *after* filtering out disallowed HTML tags and *before* transforming from wiki markup into HTML. They are also not called in any particular order. The keys of macros should be either regexes or strings. The values can be strings, or, if the corresponding key is a regex, can be coderefs. The coderef will be called with the first nine substrings captured by the regex as arguments. I would like to call it with all captured substrings but apparently this is complicated. You may wish to have access to the overall wiki object in the subs defined in your macro. To do this: * Pass the wiki object to the "->formatter" call as described below. * Pass a true value in the "pass_wiki_to_macros" parameter when calling "->new". If you do this, then *all* coderefs will be called with the wiki object as the first parameter, followed by the first nine captured substrings as described above. Note therefore that setting "pass_wiki_to_macros" may cause backwards compatibility issues. Macro examples: # Simple example - substitute a little search box for '@SEARCHBOX' macros => { '@SEARCHBOX' => qq(
), } # More complex example - substitute a list of all nodes in a # category for '@INDEX_LINK [[Category Foo]]' pass_wiki_to_macros => 1, macros => { qr/\@INDEX_LINK\s+\[\[Category\s+([^\]]+)]]/ => sub { my ($wiki, $category) = @_; my @nodes = $wiki->list_nodes_by_metadata( metadata_type => "category", metadata_value => $category, ignore_case => 1, ); my $return = "\n"; foreach my $node ( @nodes ) { $return .= "* " . $wiki->formatter->format_link( wiki => $wiki, link => $node, ) . "\n"; } return $return; }, } format my $html = $formatter->format($submitted_content, $wiki); Escapes any tags which weren't specified as allowed on creation, then interpolates any macros, then translates the raw Wiki language supplied into HTML. A Wiki::Toolkit object can be supplied as an optional second parameter. This object will be used to determine whether a linked-to node exists or not, and alter the presentation of the link accordingly. This is only really in here for use when this method is being called from within Wiki::Toolkit. format_link my $string = $formatter->format_link( link => "Home Node", wiki => $wiki, ); An internal method exposed to make it easy to go from eg * Foo * Bar to * Foo * Bar See Macro Examples above for why you might find this useful. "link" should be something that would go inside your extended link delimiters. "wiki" is optional but should be a Wiki::Toolkit object. If you do supply "wiki" then the method will be able to check whether the node exists yet or not and so will call "->make_edit_link" instead of "->make_internal_link" where appropriate. If you don't supply "wiki" then "->make_internal_link" will be called always. This method used to be private so may do unexpected things if you use it in a way that I haven't tested yet. find_internal_links my @links_to = $formatter->find_internal_links( $content ); Returns a list of all nodes that the supplied content links to. node_name_to_node_param use URI::Escape; $param = $formatter->node_name_to_node_param( "Recent Changes" ); my $url = "wiki.pl?" . uri_escape($param); In usemod, the node name is encoded prior to being used as part of the URL. This method does this encoding (essentially, whitespace is munged into underscores). In addition, if "force_ucfirst_nodes" is in action then the node names will be forced ucfirst if they weren't already. Note that unless "munge_urls" was set to true when "new" was called, this method will do nothing. node_param_to_node_name my $node = $q->param('node') || ""; $node = $formatter->node_param_to_node_name( $node ); In usemod, the node name is encoded prior to being used as part of the URL, so we must decode it before we can get back the original node name. Note that unless "munge_urls" was set to true when "new" was called, this method will do nothing. SUBCLASSING The following methods can be overridden to provide custom behaviour. make_edit_link my $link = $self->make_edit_link( title => "Home Page", url => "http://example.com/?id=Home", ); This method will be passed a title and a url and should return an HTML snippet. For example, you can add a "title" attribute to the link like so: sub make_edit_link { my ($self, %args) = @_; my $title = $args{title}; my $url = $args{url}; return qq|[$title]?|; } make_internal_link my $link = $self->make_internal_link( title => "Home Page", url => "http://example.com/?id=Home", ); This method will be passed a title and a url and should return an HTML snippet. For example, you can add a "class" attribute to the link like so: sub make_internal_link { my ($self, %args) = @_; my $title = $args{title}; my $url = $args{url}; return qq|$title|; } make_external_link my $link = $self->make_external_link( title => "London Perlmongers", url => "http://london.pm.org", ); This method will be passed a title and a url and should return an HTML snippet. For example, you can add a little icon after each external link like so: sub make_external_link { my ($self, %args) = @_; my $title = $args{title}; my $url = $args{url}; return qq|$title |; } AUTHOR Kake Pugh (kake@earth.li). COPYRIGHT Copyright (C) 2003-2004 Kake Pugh. All Rights Reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. CREDITS The OpenGuides London team () sent some very helpful bug reports. A lot of the work of this module is done within chromatic's module, Text::WikiFormat. CAVEATS This doesn't yet support all of UseMod's formatting features and options, by any means. This really truly *is* a 0.* release. Please send bug reports, omissions, patches, and stuff, to me at "kake@earth.li". NOTE ON USEMOD COMPATIBILITY UseModWiki "encodes" node names before making them part of a URL, so for example a node about Wombat Defenestration will have a URL like http://example.com/wiki.cgi?Wombat_Defenestration So if we want to emulate a UseModWiki exactly, we need to munge back and forth between node names as titles, and node names as CGI params. my $formatter = Wiki::Toolkit::Formatter::UseMod->new( munge_urls => 1 ); my $node_param = $q->param('id') || $q->param('keywords') || ""; my $node_name = $formatter->node_param_to_node_name( $node_param ); use URI::Escape; my $url = "http://example.com/wiki.cgi?" . uri_escape( $formatter->node_name_to_node_param( "Wombat Defenestration" ) ); SEE ALSO * Wiki::Toolkit * Text::WikiFormat * UseModWiki () Wiki-Toolkit-Formatter-UseMod-0.24/SIGNATURE0000644000175000017500000000371612011755446016540 0ustar domdomThis file contains message digests of all files listed in MANIFEST, signed via the Module::Signature module, version 0.63. To verify the content in this distribution, first make sure you have Module::Signature installed, then type: % cpansign -v It will check each file's integrity, as well as the signature's validity. If "==> Signature verified OK! <==" is not displayed, the distribution may already have been compromised, and you should not run its Makefile.PL or Build.PL. -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 SHA1 73e32f8aacdd6381e4f180d416849eae14a9581d Changes SHA1 584d79591f2474d80d6374a292a932ca8f60420d MANIFEST SHA1 4e8ebc1677a4d21b015548b2e064273cadb15168 META.yml SHA1 9079152ce554d2a80255917bc629314c3610beeb Makefile.PL SHA1 23533a20ab8966f9982900147bf544e0c23a6a07 README SHA1 c1a0f693e075b09742b504f8aaec14344e745fe5 lib/Wiki/Toolkit/Formatter/UseMod.pm SHA1 7ca8c08ee676aaef11f394be2bc85629381d256c t/default_links.t SHA1 0da3f93b51eab8230d5bd25954d83872acdf8626 t/encode-node-names.t SHA1 b6e39bfdea51d12b17a07af7572b46814e13bef4 t/external_links.t SHA1 5eaab43671e4219d09e3aa5b23f2bd958e174150 t/linebreaks.t SHA1 c3dea30a205dd4ff599629eba912484cbc1bf7d9 t/links.t SHA1 a166cf1b523d08475450d831791f681e515b83e9 t/lists.t SHA1 a39107208bf7b54d8e17577435ed14b55f577ab2 t/macros.t SHA1 7ccf3c4c6a703a50fe425eb4dc623da124ebebe5 t/macros_with_wiki_passed.t SHA1 aaa14f0ddc8c64c2bf23c24ff4dc9318a652d41e t/munge_node_name.t SHA1 7165c638d94c34728ac3ede7b7278c993e9b8394 t/node-suffix.t SHA1 e958cb9352bdeb3a8052aa86e23c3f1460c42943 t/paragraphs.t SHA1 61e28ddd05ab0f3722f2a8cdce80a8f314b86391 t/pod.t SHA1 adf1ca261fa5fbfa3f7eb38e80725d9b83c90cad t/tables.t SHA1 67eb4005ffb64044aa14fcfe273684b2b3c56f9f t/twf-bug.t SHA1 c0c73fe9bbdb76463ecb32b4665f3454d5984f68 t/usemod.t -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iD8DBQFQJ9sjYzuFKFF44qURAusYAKD/K4K+zHN+p9CFkDmcQVE8A1McfACfUzny U15F29bh/v3If0f0e5rL7S0= =lqEe -----END PGP SIGNATURE----- Wiki-Toolkit-Formatter-UseMod-0.24/META.yml0000644000175000017500000000122512011755442016512 0ustar domdom--- #YAML:1.0 name: Wiki-Toolkit-Formatter-UseMod version: 0.24 abstract: ~ author: [] license: unknown distribution_type: module configure_requires: ExtUtils::MakeMaker: 0 build_requires: ExtUtils::MakeMaker: 0 requires: HTML::PullParser: 0 Test::More: 0 Text::WikiFormat: 0.71 URI::Escape: 0 URI::Find::Delimited: 0.02 Wiki::Toolkit: 0 no_index: directory: - t - inc generated_by: ExtUtils::MakeMaker version 6.55_02 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 Wiki-Toolkit-Formatter-UseMod-0.24/MANIFEST0000644000175000017500000000071512011755442016375 0ustar domdomChanges MANIFEST Makefile.PL README lib/Wiki/Toolkit/Formatter/UseMod.pm t/default_links.t t/encode-node-names.t t/external_links.t t/linebreaks.t t/links.t t/lists.t t/macros.t t/macros_with_wiki_passed.t t/munge_node_name.t t/node-suffix.t t/paragraphs.t t/pod.t t/tables.t t/twf-bug.t t/usemod.t META.yml Module meta-data (added by MakeMaker) SIGNATURE Public-key signature (added by MakeMaker) Wiki-Toolkit-Formatter-UseMod-0.24/t/0002755000175000017500000000000012011755442015506 5ustar domdomWiki-Toolkit-Formatter-UseMod-0.24/t/links.t0000644000175000017500000000357411000122345017005 0ustar domdomuse strict; use Test::More; eval { require Test::MockObject; }; if ( $@ ) { plan skip_all => "Can't find Test::MockObject"; } plan tests => 4; my $wikitext = <new; $wiki->mock( "node_exists", sub { my ($self, $node) = @_; return $node eq "ExistingNode" ? 1 : 0; } ); my $formatter = Wiki::Toolkit::Formatter::Kake->new( node_prefix => "/wiki/", node_suffix => ".html", edit_prefix => "/wiki/edit/", edit_suffix => ".html", ); my $html = $formatter->format( $wikitext, $wiki ); like( $html, qr|\[NonExistentNode\]\?|, "can override ->make_edit_link" ); like( $html, qr|ExistingNode|, "can override ->make_internal_link" ); like( $html, qr'http://external.example.com/ ', "can override ->make_external_link" ); like( $html, qr'foo ', "...works for external links with titles too" ); package Wiki::Toolkit::Formatter::Kake; use base "Wiki::Toolkit::Formatter::UseMod"; sub make_edit_link { my ($self, %args) = @_; my $title = $args{title}; my $url = $args{url}; return qq|[$title]?|; } sub make_internal_link { my ($self, %args) = @_; my $title = $args{title}; my $url = $args{url}; return qq|$title|; } sub make_external_link { my ($self, %args) = @_; my $title = $args{title}; my $url = $args{url}; return qq|$title |; } Wiki-Toolkit-Formatter-UseMod-0.24/t/tables.t0000644000175000017500000000151710421647336017154 0ustar domdomuse strict; use Wiki::Toolkit::Formatter::UseMod; use Test::More tests => 8; my $wikitext = <new; my $html = $formatter->format( $wikitext ); like( $html, qr'format( $wikitext ); like( $html, qr' 6; use Wiki::Toolkit::Formatter::UseMod; my $formatter = Wiki::Toolkit::Formatter::UseMod->new; # Test unordered lists. my $wikitext = <format( $wikitext ); like( $html, qr/
  • list item 1<\/li>/, "unordered lists work" ); like( $html, qr/
  • another list item 1<\/li>/, "...also when indented" ); like( $html, qr/
  • foo 1/, "...first level of nested list" ); like( $html, qr/
      \s*
    • bar 1<\/li>/s, "...second level of nested list" ); # Test ordered lists. $wikitext = <format( $wikitext ); like( $html, qr/
        /, "ordered list created" ); like( $html, qr/
      1. item 1/, "items are ordered" ); Wiki-Toolkit-Formatter-UseMod-0.24/t/macros.t0000644000175000017500000000243010421647336017161 0ustar domdomuse strict; use Test::More tests => 7; use Wiki::Toolkit::Formatter::UseMod; my $wikitext = <new( macros => { '@PLAIN_STRING' => "{plain string}", qr/\@TEST_TEXT(\b|$)/ => "{test text}", qr/\@INDEX_ALL(\b|$)/ => sub { return "{an index of all nodes}"; }, qr/\@INDEX\s+\[Category\s+([^\]]+)]/ => sub { return "{an index of things in category $_[0]}" }, qr/\@PAIR\s+(\S*)\s+(\S*)(\b|$)/ => sub { return "{" . join(" ", @_[0, 1]) . "}" }, qr/\@LOTS (\d) (\d) (\d) (\d) (\d) (\d) (\d) (\d) (\d)/ => sub { return join("", @_) } } ); isa_ok( $formatter, "Wiki::Toolkit::Formatter::UseMod" ); my $html = $formatter->format($wikitext); like( $html, qr|{plain string}|, "plain string macros work" ); like( $html, qr|{test text}|, "regex macros work" ); like( $html, qr|{an index of all nodes}|, "no-arg sub macros work" ); like( $html, qr|{an index of things in category Foo}|, "subs with a single arg work" ); like( $html, qr|{one two}|, "subs with two args work" ); like( $html, qr|123456789|, "subs with nine args work" ); Wiki-Toolkit-Formatter-UseMod-0.24/t/macros_with_wiki_passed.t0000644000175000017500000000423410421647336022602 0ustar domdomuse strict; use Wiki::Toolkit; use Wiki::Toolkit::Formatter::UseMod; use Wiki::Toolkit::Setup::SQLite; use Wiki::Toolkit::Store::SQLite; use Test::More; eval { require DBD::SQLite; }; if ( $@ ) { plan skip_all => "DBD::SQLite not installed - no db to test with."; exit 0; } eval { require Wiki::Toolkit; }; if ( $@ ) { plan skip_all => "Wiki::Toolkit not installed"; exit 0; } plan tests => 2; my $dbname = "t/node.db"; # Clear out the database from any previous runs. unlink $dbname; Wiki::Toolkit::Setup::SQLite::setup( { dbname => $dbname } ); my $wikitext = "\@INDEX_LINK [[Category Foo]]"; my $formatter = Wiki::Toolkit::Formatter::UseMod->new( extended_links => 1, macros => { qr/\@INDEX_LINK\s+\[\[Category\s+([^\]]+)]]/ => sub { my ($wiki, $category) = @_; my @nodes = $wiki->list_nodes_by_metadata( metadata_type => "category", metadata_value => $category, ignore_case => 1, ); my $return = "\n"; foreach my $node ( @nodes ) { $return .= "* " . $wiki->formatter->format_link( wiki => $wiki, link => $node, ) . "\n"; } return $return; }, }, pass_wiki_to_macros => 1, ); isa_ok( $formatter, "Wiki::Toolkit::Formatter::UseMod" ); my $store = Wiki::Toolkit::Store::SQLite->new( dbname => $dbname ); my $wiki = Wiki::Toolkit->new( formatter => $formatter, store => $store, ); $wiki->write_node( "Wibble", "wibble", undef, { category => "Foo" } ) or die "Can't write node"; my $html = $formatter->format( $wikitext, $wiki ); like( $html, qr|Wibble|, "macros with wiki passed work OK" ); Wiki-Toolkit-Formatter-UseMod-0.24/t/linebreaks.t0000644000175000017500000000055310421647336020020 0ustar domdomuse strict; use Test::More tests => 1; use Wiki::Toolkit::Formatter::UseMod; my $formatter = Wiki::Toolkit::Formatter::UseMod->new( allowed_tags => [ qw( table tr td ) ], ); my $wikitext = < A table cell WIKI my $html = $formatter->format( $wikitext ); unlike( $html, qr|
        |, "no bogus
        s" ); Wiki-Toolkit-Formatter-UseMod-0.24/t/external_links.t0000644000175000017500000000125112011754666020721 0ustar domdomuse strict; use Wiki::Toolkit::Formatter::UseMod; use Test::More tests => 2; my $wikitext = <new( external_link_class => "external" ); my $html = $formatter->format( $wikitext ); like( $html, qr'http://external.example.com/', "external links with no title appear as expected" ); like( $html, qr'foo', "external links with title appear as expected" ); Wiki-Toolkit-Formatter-UseMod-0.24/t/default_links.t0000644000175000017500000000107212011754666020524 0ustar domdomuse strict; use Wiki::Toolkit::Formatter::UseMod; use Test::More tests => 2; my $wikitext = <new; my $html = $formatter->format( $wikitext ); like( $html, qr'http://external.example.com/', "external links with no title appear as expected" ); like( $html, qr'\[foo\]', "external links with title appear as expected" ); Wiki-Toolkit-Formatter-UseMod-0.24/t/paragraphs.t0000644000175000017500000000074510421647336020034 0ustar domdomuse strict; use Test::More tests => 2; use Wiki::Toolkit::Formatter::UseMod; my $formatter = Wiki::Toolkit::Formatter::UseMod->new; # The CGI linebreak is \r\n, not \n. my $wikitext = "\r\nThis is paragraph 1.\r\n\r\nThis is paragraph 2.\r\n"; my $html = $formatter->format( $wikitext ); like( $html, qr/

        \s*This is paragraph 1./, "first paragraph detected" ); like( $html, qr/

        \s*This is paragraph 2./, "second paragraph, separated from first by blank line, detected" ); Wiki-Toolkit-Formatter-UseMod-0.24/t/twf-bug.t0000644000175000017500000000042610421647336017253 0ustar domdomuse strict; use Test::More tests => 1; use Wiki::Toolkit::Formatter::UseMod; my $formatter = Wiki::Toolkit::Formatter::UseMod->new; my $foo = "x"; $foo .= "" if $foo =~ /x/; my $html = $formatter->format("test"); is( $html, "

        test

        \n", "Text::WikiFormat bug avoided" ); Wiki-Toolkit-Formatter-UseMod-0.24/t/usemod.t0000644000175000017500000001163311000123633017155 0ustar domdomuse strict; local $^W = 1; use Test::More tests => 25; use_ok( "Wiki::Toolkit::Formatter::UseMod" ); print "#\n#### Testing default configuration\n#\n"; my $wikitext = <new; isa_ok( $formatter, "Wiki::Toolkit::Formatter::UseMod" ); my $html = $formatter->format($wikitext); like( $html, qr|WikiText|, "WikiWords made into links" ); like( $html, qr|

        Welcome

        |, "headings work" ); like( $html, qr|

        LinkInAHeader

        |, "...links work in headers" ); like( $html, qr|

        Header with an = in

        |, "...headers may contain =" ); like( $html, qr|
        \s*
         This should be a
        \s*
         definition list with data
        \s*
         but no terms
        \s*
        |, "leading : made into
        " ); like( $html, qr|
        \npig\npig\n
        |, "leading space makes
        " );
        
        my @links = $formatter->find_internal_links($wikitext);
        is_deeply( [ sort @links ], [ "LinkInAHeader", "WikiText", "WikiWord" ],
        	   "find_internal_links seems to work" );
        print "# Found internal links: " . join(", ", sort @links) . "\n";
        
        print "#\n#### Testing HTML escaping\n#\n";
        $wikitext = <
        
        
        WIKITEXT
        
        $formatter = Wiki::Toolkit::Formatter::UseMod->new;
        $html = $formatter->format($wikitext);
        like( $html, qr|£|, "Entities preserved by default." );
        unlike( $html, qr||, "HTML tags escaped by default" );
        
        $formatter = Wiki::Toolkit::Formatter::UseMod->new( allowed_tags => [ "strike" ] );
        $html = $formatter->format($wikitext);
        like( $html, qr||, "...but not when we allow them" );
        unlike( $html, qr||, "...and ones we don't explicitly allow are escaped" );
        like( $html, qr|£|, "Entities still preserved." );
        
        print "#\n#### Testing extended links\n#\n";
        $wikitext = <new;
            $wiki->mock( "node_exists",
        	          sub {
                                my ($self, $node) = @_;
                                if ( $node eq "Extended Link"
                                     or $node eq "Extended Link Two"
        		             or $node eq "Another Link" ) {
        		            return 1;
        		        } else {
        		            return 0;
                                }
        		      }
            );
        
            # Test with munged URLs.
            $formatter = Wiki::Toolkit::Formatter::UseMod->new( extended_links => 1,
                                                                munge_urls     => 1 );
            $html = $formatter->format($wikitext, $wiki);
        
            SKIP: {
                skip "Broken by Text::WikiFormat bug http://rt.cpan.org/Public/Bug/Display.html?id=34402", 5;
        
            like( $html, qr|Extended Link|,
                  "extended links work" );
            like( $html, qr|extended link|,
                  "...and are forced ucfirst" );
            like( $html, qr|titled extended link|,
                  "...and titles work" );
            like( $html, qr|[^ ]title with leading whitespace|,
                  "...and don't show leading whitespace" );
            like( $html, qr||,
                  "...and titled nodes with trailing whitespace are munged correctly "
                  . "before formatting" );
            
            } # end SKIP
        
            # Test with unmunged URLs.
            $formatter = Wiki::Toolkit::Formatter::UseMod->new( extended_links => 1 );
            $html = $formatter->format($wikitext, $wiki);
        
            like( $html, qr|Extended Link|,
                  "extended links work with unmunged URLs" );
            like( $html, qr|extended link|,
                  "...and are forced ucfirst" );
            like( $html,
                  qr|titled extended link|,
                  "...and titles work" );
        
            @links = $formatter->find_internal_links($wikitext);
            print "# Found links: " . join(", ", @links) . "\n";
            my %linkhash = map { $_ => 1 } @links;
            ok( ! defined $linkhash{"extended link"},
                "find_internal_links respects ucfirst" );
            ok( ! defined $linkhash{"Extended Link "},
                "...and drops trailing whitespace" );
            is_deeply( \@links,
                       [ "Extended Link", "Extended Link", "Extended Link",
                          "Extended Link Two", "Another Link" ],
                       "...and gets the right order" );
        }
        Wiki-Toolkit-Formatter-UseMod-0.24/t/node-suffix.t0000644000175000017500000000155111000122345020105 0ustar  domdomuse strict;
        use Test::More;
        use Wiki::Toolkit::Formatter::UseMod;
        
        eval { require Test::MockObject; };
        if ( $@ ) {
            plan skip_all => "Can't find Test::MockObject";
        }
        
        plan tests => 2;
        
        my $wikitext = <new;
        $wiki->mock( "node_exists",
                     sub {
                         my ($self, $node) = @_;
                         return $node eq "ExistingNode" ? 1 : 0;
                     } );
        
        my $formatter = Wiki::Toolkit::Formatter::UseMod->new(
            node_prefix => "/wiki/",
            node_suffix => ".html",
            edit_prefix => "/wiki/edit/",
            edit_suffix => ".html",
        );
        
        my $html = $formatter->format( $wikitext, $wiki );
        
        like( $html, qr|ExistingNode|,
              "node_suffix works" );
        like( $html, qr||,
              "edit_suffix works" );
        Wiki-Toolkit-Formatter-UseMod-0.24/t/pod.t0000644000175000017500000000031611141164014016443 0ustar  domdomuse strict;
        use Test::More;
        eval "use Test::Pod 1.00";
        plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
        my @poddirs = qw( blib blib/script );
        all_pod_files_ok( all_pod_files( @poddirs ) );
        Wiki-Toolkit-Formatter-UseMod-0.24/t/encode-node-names.t0000644000175000017500000000157410421647336021166 0ustar  domdomuse strict;
        use Wiki::Toolkit::Formatter::UseMod;
        use Test::More tests => 4;
        
        my $formatter = Wiki::Toolkit::Formatter::UseMod->new( munge_urls => 1 );
        is( $formatter->node_name_to_node_param( "test page" ),
            "Test_Page", "->node_name_to_node_param forces ucfirst by default" );
        
        $formatter = Wiki::Toolkit::Formatter::UseMod->new( force_ucfirst_nodes => 0,
                                                        munge_urls          => 1 );
        is( $formatter->node_name_to_node_param( "test page" ),
            "test_page", "...but not if force_ucfirst_nodes set to 0" );
        
        $formatter = Wiki::Toolkit::Formatter::UseMod->new;
        is( $formatter->node_name_to_node_param( "Home Page" ), "Home Page",
            "->node_name_to_node_param does nothing if munge_urls not true" );
        is( $formatter->node_param_to_node_name( "Home_Page" ), "Home_Page",
            "->node_param_to_node_name does nothing if munge_urls not true" );
        
        Wiki-Toolkit-Formatter-UseMod-0.24/t/munge_node_name.t0000644000175000017500000000406410421647336021022 0ustar  domdomuse strict;
        use Test::More tests => 3;
        use Wiki::Toolkit::Formatter::UseMod;
        
        eval { require Wiki::Toolkit; require DBD::SQLite; };
        my $test_wiki_available = $@ ? 0 : 1;
        
        SKIP: {
            skip "Either Wiki::Toolkit or DBD::SQLite not installed", 2
              unless $test_wiki_available;
        
            my $dbname = "./t/sqlite.db";
            require Wiki::Toolkit::Setup::SQLite; require Wiki::Toolkit::Store::SQLite;
            Wiki::Toolkit::Setup::SQLite::cleardb( $dbname );
            Wiki::Toolkit::Setup::SQLite::setup( $dbname );
            my $store = Wiki::Toolkit::Store::SQLite->new( dbname => $dbname );
            my $wiki = Wiki::Toolkit->new( store => $store );
            $wiki->write_node( "A state51 Node That Exists", "foo" )
              or die "Can't write test node";
        
            my $wikitext = <new(
                extended_links  => 1,
                munge_urls      => 1,
                munge_node_name => sub {
                                       my $node_name = shift;
                                       $node_name =~ s/State51/state51/g;
                                       return $node_name;
                                   },
            );
            
            my $html = $formatter->format( $wikitext, $wiki );
        
            like( $html, qr|A state51 node that exists|, "->format works with munge_node_name and existing links" );
            
            like( $html, qr|\?|, "->format works with munge_node_name and nonexistent links" );
        
        }
        
        my $wikitext = "[[A state51 node]]";
        
        
        my $formatter = Wiki::Toolkit::Formatter::UseMod->new(
            extended_links  => 1,
            munge_urls      => 1,
            munge_node_name => sub {
                                   my $node_name = shift;
                                   $node_name =~ s/State51/state51/g;
                                   return $node_name;
                               },
        );
        
        my @nodes = $formatter->find_internal_links( $wikitext );
        is_deeply( \@nodes, [ "A state51 Node" ],
                   "->find_internal_links works with munge_node_name" );
        Wiki-Toolkit-Formatter-UseMod-0.24/Makefile.PL0000644000175000017500000000116011001755030017200 0ustar  domdomuse ExtUtils::MakeMaker;
        
        WriteMakefile(
            (MM->can('signature_target') ? (SIGN => 1) : ()),
            NAME         => "Wiki::Toolkit::Formatter::UseMod",
            VERSION_FROM => "lib/Wiki/Toolkit/Formatter/UseMod.pm",
            PREREQ_PM    => { 'Text::WikiFormat'     => '0.71', # 0.7 buggy
                              'HTML::PullParser'     => 0,
                              'Test::More'           => 0,
                              'URI::Escape'          => 0,
                              'URI::Find::Delimited' => '0.02', # earlier buggy
                              'Wiki::Toolkit'        => 0,
                            },
            clean        => { FILES => "t/*.db" },
        );
        Wiki-Toolkit-Formatter-UseMod-0.24/lib/0002755000175000017500000000000012011755442016011 5ustar  domdomWiki-Toolkit-Formatter-UseMod-0.24/lib/Wiki/0002755000175000017500000000000012011755442016714 5ustar  domdomWiki-Toolkit-Formatter-UseMod-0.24/lib/Wiki/Toolkit/0002755000175000017500000000000012011755442020341 5ustar  domdomWiki-Toolkit-Formatter-UseMod-0.24/lib/Wiki/Toolkit/Formatter/0002755000175000017500000000000012011755442022304 5ustar  domdomWiki-Toolkit-Formatter-UseMod-0.24/lib/Wiki/Toolkit/Formatter/UseMod.pm0000644000175000017500000005535512011755414024050 0ustar  domdompackage Wiki::Toolkit::Formatter::UseMod;
        
        use strict;
        
        use vars qw( $VERSION @_links_found );
        $VERSION = '0.24';
        
        use URI::Escape;
        use Text::WikiFormat as => 'wikiformat';
        use HTML::PullParser;
        use URI::Find::Delimited;
        
        =head1 NAME
        
        Wiki::Toolkit::Formatter::UseMod - UseModWiki-style formatting for Wiki::Toolkit
        
        =head1 DESCRIPTION
        
        A formatter backend for L that supports UseMod-style formatting.
        
        =head1 SYNOPSIS
        
          use Wiki::Toolkit::Formatter::UseMod;
        
          # Instantiate - see below for parameter details.
          my $formatter = Wiki::Toolkit::Formatter::UseMod->new( %config );
        
          # Format some text.
          my $cooked = $formatter->format($raw);
        
          # Find out which other nodes that text would link to.
          my @links_to = $formatter->find_internal_links($raw);
        
        =head1 METHODS
        
        =over 4
        
        =item B
        
          my $formatter = Wiki::Toolkit::Formatter::UseMod->new(
                         extended_links      => 0, # $FreeLinks
                         implicit_links      => 1, # $WikiLinks
                         force_ucfirst_nodes => 1, # $FreeUpper
                         use_headings        => 1, # $UseHeadings
                         allowed_tags        => [qw(b i)], # defaults to none
                         macros              => {},
                         pass_wiki_to_macros => 0,
                         node_prefix         => 'wiki.pl?',
                         node_suffix         => '',
                         edit_prefix         => 'wiki.pl?action=edit;id=',
                         edit_suffix         => '',
                         munge_urls          => 0,
                         external_link_class => 'external',
          );
        
        Parameters will default to the values shown above (apart from
        C, which defaults to allowing no tags, and
        C, which defaults to false).
        
        =over 4
        
        =item B
        
        C, C, C and C
        allow you to control the URLs generated for links to other wiki pages.
        So for example with the defaults given above, a link to the Home node
        will have the URL C and a link to the edit form for the
        Home node will have the URL C
        
        (Note that of course the URLs that you wish to have generated will
        depend on how your wiki application processes its CGI parameters - you
        can't just put random stuff in there and hope it works!)
        
        =item B
        
        If you wish to have greater control over the links, you may use the
        C parameter.  The value of this should be a
        subroutine reference.  This sub will be called on each internal link
        after all other formatting and munging I URL escaping has been
        applied.  It will be passed the node name as its first parameter and
        should return a node name.  Note that this will affect the URLs of
        internal links, but not the link text.
        
        Example:
        
          # The formatter munges links so node names are ucfirst.
          # Ensure 'state51' always appears in lower case in node names.
          munge_node_name => sub {
                                 my $node_name = shift;
                                 $node_name =~ s/State51/state51/g;
                                 return $node_name;
                             }
        
        B This is I usage and you should only do it if you
        I know what you're doing.  Consider in particular whether and
        how your munged nodes are going to be treated by C.
        
        =item B
        
        By default, we emulate the UseModWiki behaviour of formatting external
        links with hardcoded square brackets around them.  If you would
        instead prefer to control this with CSS, supply the
        C parameter to C<< ->new >> - the value of this
        parameter will be used as the class applied to the link (so it should
        be a valid CSS class name).  Controlling the appearance with CSS is
        our recommended method, but the default is as described for reasons of
        backward compatibility.
        
        =item B
        
        If you set C to true, then your URLs will be more
        user-friendly, for example
        
          http://example.com/wiki.cgi?Mailing_List_Managers
        
        rather than
        
          http://example.com/wiki.cgi?Mailing%20List%20Managers
        
        The former behaviour is the actual UseMod behaviour, but requires a
        little fiddling about in your code (see C),
        so the default is to B munge URLs.
        
        =item B
        
        Be aware that macros are processed I filtering out disallowed
        HTML tags and I transforming from wiki markup into HTML.  They
        are also not called in any particular order.
        
        The keys of macros should be either regexes or strings. The values can
        be strings, or, if the corresponding key is a regex, can be coderefs.
        The coderef will be called with the first nine substrings captured by
        the regex as arguments. I would like to call it with all captured
        substrings but apparently this is complicated.
        
        You may wish to have access to the overall wiki object in the subs
        defined in your macro.  To do this:
        
        =over
        
        =item *
        
        Pass the wiki object to the C<< ->formatter >> call as described below.
        
        =item *
        
        Pass a true value in the C parameter when calling
        C<< ->new >>.
        
        =back
        
        If you do this, then I coderefs will be called with the wiki object
        as the first parameter, followed by the first nine captured substrings
        as described above.  Note therefore that setting C
        may cause backwards compatibility issues.
        
        =back
        
        Macro examples:
        
          # Simple example - substitute a little search box for '@SEARCHBOX'
        
          macros => {
        
              '@SEARCHBOX' =>
                        qq(
        ), } # More complex example - substitute a list of all nodes in a # category for '@INDEX_LINK [[Category Foo]]' pass_wiki_to_macros => 1, macros => { qr/\@INDEX_LINK\s+\[\[Category\s+([^\]]+)]]/ => sub { my ($wiki, $category) = @_; my @nodes = $wiki->list_nodes_by_metadata( metadata_type => "category", metadata_value => $category, ignore_case => 1, ); my $return = "\n"; foreach my $node ( @nodes ) { $return .= "* " . $wiki->formatter->format_link( wiki => $wiki, link => $node, ) . "\n"; } return $return; }, } =cut sub new { my ($class, @args) = @_; my $self = {}; bless $self, $class; $self->_init(@args) or return undef; return $self; } sub _init { my ($self, %args) = @_; # Store the parameters or their defaults. my %defs = ( extended_links => 0, implicit_links => 1, force_ucfirst_nodes => 1, use_headings => 1, allowed_tags => [], macros => {}, pass_wiki_to_macros => 0, node_prefix => 'wiki.pl?', node_suffix => '', edit_prefix => 'wiki.pl?action=edit;id=', edit_suffix => '', munge_urls => 0, munge_node_name => undef, external_link_class => undef, ); my %collated = (%defs, %args); foreach my $k (keys %defs) { $self->{"_".$k} = $collated{$k}; } return $self; } =item B my $html = $formatter->format($submitted_content, $wiki); Escapes any tags which weren't specified as allowed on creation, then interpolates any macros, then translates the raw Wiki language supplied into HTML. A L object can be supplied as an optional second parameter. This object will be used to determine whether a linked-to node exists or not, and alter the presentation of the link accordingly. This is only really in here for use when this method is being called from within L. =cut sub format { my ($self, $raw, $wiki) = @_; $raw =~ s/\r\n/\n/sg; # CGI newline is \r\n not \n my $safe = ""; my %allowed = map {lc($_) => 1, "/".lc($_) => 1} @{$self->{_allowed_tags}}; # Parse the HTML - even if we're not allowing any tags, because we're # using a custom escaping routine rather than CGI.pm my $parser = HTML::PullParser->new(doc => $raw, start => '"TAG", tag, text', end => '"TAG", tag, text', text => '"TEXT", tag, text'); while (my $token = $parser->get_token) { my ($flag, $tag, $text) = @$token; if ($flag eq "TAG" and !defined $allowed{lc($tag)}) { $safe .= $self->_escape_HTML($text); } else { $safe .= $text; } } # Now do any inline links. my $callback = sub { my ($open, $close, $url, $title, $whitespace) = @_; $title ||= $url; if ( $open && $close ) { return $self->make_external_link( title => $title, url => $url ); } else { return $open . $self->make_external_link( title => $title, url => $url ) . $close; } }; my $finder = URI::Find::Delimited->new( ignore_quoted => 1, callback => $callback ); $finder->find(\$safe); # Now process any macros. my %macros = %{$self->{_macros}}; foreach my $key (keys %macros) { my $value = $macros{$key}; if ( ref $value && ref $value eq 'CODE' ) { if ( $self->{_pass_wiki_to_macros} and $wiki ) { $safe=~ s/$key/$value->($wiki, $1, $2, $3, $4, $5, $6, $7, $8, $9)/eg; } else { $safe=~ s/$key/$value->($1, $2, $3, $4, $5, $6, $7, $8, $9)/eg; } } else { $safe =~ s/$key/$value/g; } } # Finally set up config and call Text::WikiFormat. my %format_opts = $self->_format_opts; my %format_tags = ( # chromatic made most of the regex below. I will document it when # I understand it properly. indent => qr/^(?:\t+|\s{4,}|\s*\*?(?=\**\*+))/, newline => "", # avoid bogus
        paragraph => [ "

        ", "

        \n", "", "\n", 1 ], # no bogus
        extended_link_delimiters => [ '[[', ']]' ], blocks => { ordered => qr/^\s*([\d]+)\.\s*/, unordered => qr/^\s*\*\s*/, definition => qr/^:\s*/, pre => qr/^\s+/, table => qr/^\|\|/, }, definition => [ "
        \n", "
        \n", "
         ", "
        \n" ], pre => [ "
        \n", "
        \n", "", "\n" ], table => [ qq|\n|, "
        \n", sub { my $line = shift; $line =~ s/\|\|$/<\/td>/; $line =~ s/\|\|/<\/td>/g; return ("","$line",""); }, ], # we don't label unordered lists as "not indented" so we can nest them. indented => { definition => 0, ordered => 0, pre => 0, table => 0, }, blockorder => [ qw( header line ordered unordered code definition pre table paragraph )], nests => { map { $_ => 1} qw( ordered unordered ) }, link => sub { my $link = shift; return $self->format_link( link => $link, wiki => $wiki, ); }, ); return wikiformat($safe, \%format_tags, \%format_opts ); } sub _format_opts { my $self = shift; return ( extended => $self->{_extended_links}, prefix => $self->{_node_prefix}, implicit_links => $self->{_implicit_links} ); } =item B my $string = $formatter->format_link( link => "Home Node", wiki => $wiki, ); An internal method exposed to make it easy to go from eg * Foo * Bar to * Foo * Bar See Macro Examples above for why you might find this useful. C should be something that would go inside your extended link delimiters. C is optional but should be a L object. If you do supply C then the method will be able to check whether the node exists yet or not and so will call C<< ->make_edit_link >> instead of C<< ->make_internal_link >> where appropriate. If you don't supply C then C<< ->make_internal_link >> will be called always. This method used to be private so may do unexpected things if you use it in a way that I haven't tested yet. =cut sub format_link { my ($self, %args) = @_; my $link = $args{link}; my %opts = $self->_format_opts; my $wiki = $args{wiki}; my $title; ($link, $title) = split(/\|/, $link, 2) if $opts{extended}; $title =~ s/^\s*// if $title; # strip leading whitespace $title ||= $link; if ( $self->{_force_ucfirst_nodes} ) { $link = $self->_do_freeupper($link); } $link = $self->_munge_spaces($link); $link = $self->{_munge_node_name}($link) if $self->{_munge_node_name}; if (!$link) { return "[Undefined link '$title']"; } my $editlink_not_link = 0; # See whether the linked-to node exists, if we can. if ( $wiki && !$wiki->node_exists( $link ) ) { $editlink_not_link = 1; } $link =~ s/ /_/g if $self->{_munge_urls}; $link = uri_escape( $link ); if ( $editlink_not_link ) { my $prefix = $self->{_edit_prefix}; my $suffix = $self->{_edit_suffix}; return $self->make_edit_link( title => $title, url => $prefix.$link.$suffix, ); } else { my $prefix = $self->{_node_prefix}; my $suffix = $self->{_node_suffix}; return $self->make_internal_link( title => $title, url => $prefix.$link.$suffix, ); } } # CGI.pm is sometimes awkward about actually performing CGI::escapeHTML # if there's a previous instantiation - in the calling script, for example. # So just do it here. sub _escape_HTML { my ($self, $text) = @_; $text =~ s{&}{&}gso; $text =~ s{<}{<}gso; $text =~ s{>}{>}gso; $text =~ s{"}{"}gso; return $text; } =item B my @links_to = $formatter->find_internal_links( $content ); Returns a list of all nodes that the supplied content links to. =cut sub find_internal_links { my ($self, $raw) = @_; @_links_found = (); my %format_opts = $self->_format_opts; my %format_tags = ( extended_link_delimiters => [ '[[', ']]' ], link => sub { my $link = shift; my %opts = $self->_format_opts; my $title; ($link, $title) = split(/\|/, $link, 2) if $opts{extended}; if ( $self->{_force_ucfirst_nodes} ) { $link = $self->_do_freeupper($link); } $link = $self->{_munge_node_name}($link) if $self->{_munge_node_name}; $link = $self->_munge_spaces($link); push @Wiki::Toolkit::Formatter::UseMod::_links_found, $link; return ""; # don't care about output } ); my $foo = wikiformat($raw, \%format_tags, \%format_opts); my @links = @_links_found; @_links_found = (); return @links; } =item B use URI::Escape; $param = $formatter->node_name_to_node_param( "Recent Changes" ); my $url = "wiki.pl?" . uri_escape($param); In usemod, the node name is encoded prior to being used as part of the URL. This method does this encoding (essentially, whitespace is munged into underscores). In addition, if C is in action then the node names will be forced ucfirst if they weren't already. Note that unless C was set to true when C was called, this method will do nothing. =cut sub node_name_to_node_param { my ($self, $node_name) = @_; return $node_name unless $self->{_munge_urls}; my $param = $node_name; $param = $self->_munge_spaces($param); $param = $self->_do_freeupper($param) if $self->{_force_ucfirst_nodes}; $param =~ s/ /_/g; return $param; } =item B my $node = $q->param('node') || ""; $node = $formatter->node_param_to_node_name( $node ); In usemod, the node name is encoded prior to being used as part of the URL, so we must decode it before we can get back the original node name. Note that unless C was set to true when C was called, this method will do nothing. =cut sub node_param_to_node_name { my ($self, $param) = @_; return $param unless $self->{_munge_urls}; # Note that this might not give us back exactly what we started with, # since in the encoding we collapse and trim whitespace; but this is # how usemod does it (as of 0.92) and usemod is what we're emulating. $param =~ s/_/ /g; return $param; } sub _do_freeupper { my ($self, $node) = @_; # This is the FreeUpper usemod behaviour, slightly modified from # their regexp, as we need to do it before we check whether the # node exists ie before we substitute the spaces with underscores. $node = ucfirst($node); $node =~ s|([- _.,\(\)/])([a-z])|$1.uc($2)|ge; return $node; } sub _munge_spaces { my ($self, $node) = @_; # Yes, we really do only munge spaces, not all whitespace. This is # how usemod does it (as of 0.92). $node =~ s/ +/ /g; $node =~ s/^ //; $node =~ s/ $//; return $node } =back =head1 SUBCLASSING The following methods can be overridden to provide custom behaviour. =over =item B my $link = $self->make_edit_link( title => "Home Page", url => "http://example.com/?id=Home", ); This method will be passed a title and a url and should return an HTML snippet. For example, you can add a C attribute to the link like so: sub make_edit_link { my ($self, %args) = @_; my $title = $args{title}; my $url = $args{url}; return qq|[$title]<a href="$url" title="create">?</a>|; } =cut sub make_edit_link { my ($self, %args) = @_; return qq|[$args{title}]<a href="$args{url}">?</a>|; } =item B<make_internal_link> my $link = $self->make_internal_link( title => "Home Page", url => "http://example.com/?id=Home", ); This method will be passed a title and a url and should return an HTML snippet. For example, you can add a C<class> attribute to the link like so: sub make_internal_link { my ($self, %args) = @_; my $title = $args{title}; my $url = $args{url}; return qq|<a href="$url" class="internal">$title</a>|; } =cut sub make_internal_link { my ($self, %args) = @_; return qq|<a href="$args{url}">$args{title}</a>|; } =item B<make_external_link> my $link = $self->make_external_link( title => "London Perlmongers", url => "http://london.pm.org", ); This method will be passed a title and a url and should return an HTML snippet. For example, you can add a little icon after each external link like so: sub make_external_link { my ($self, %args) = @_; my $title = $args{title}; my $url = $args{url}; return qq|<a href="$url">$title</a> <img src="external.gif">|; } =cut sub make_external_link { my ($self, %args) = @_; my ($open, $close) = ( "[", "]" ); my $link_class = $self->{_external_link_class} || ""; if ( $args{title} eq $args{url} || $link_class ) { ($open, $close) = ( "", "" ); } my $ret = qq|$open<a href="$args{url}"| . ( $link_class ? qq| class="$link_class"| : "" ) . qq|>$args{title}</a>$close|; return $ret; } =back =head1 AUTHOR Kake Pugh (kake@earth.li) and the Wiki::Toolkit team. =head1 COPYRIGHT Copyright (C) 2003-2004 Kake Pugh. All Rights Reserved. Copyright (C) 2006-2012 the Wiki::Toolkit team. All Rights Reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 CREDITS The OpenGuides London team (L<http://openguides.org/london/>) sent some very helpful bug reports. A lot of the work of this module is done within chromatic's module, L<Text::WikiFormat>. =head1 CAVEATS This doesn't yet support all of UseMod's formatting features and options, by any means. This really truly I<is> a 0.* release. Please send bug reports, omissions, patches, and stuff, to me at C<kake@earth.li>. =head1 NOTE ON USEMOD COMPATIBILITY UseModWiki "encodes" node names before making them part of a URL, so for example a node about Wombat Defenestration will have a URL like http://example.com/wiki.cgi?Wombat_Defenestration So if we want to emulate a UseModWiki exactly, we need to munge back and forth between node names as titles, and node names as CGI params. my $formatter = Wiki::Toolkit::Formatter::UseMod->new( munge_urls => 1 ); my $node_param = $q->param('id') || $q->param('keywords') || ""; my $node_name = $formatter->node_param_to_node_name( $node_param ); use URI::Escape; my $url = "http://example.com/wiki.cgi?" . uri_escape( $formatter->node_name_to_node_param( "Wombat Defenestration" ) ); =head1 SEE ALSO =over 4 =item * L<Wiki::Toolkit> =item * L<Text::WikiFormat> =item * UseModWiki (L<http://www.usemod.com/cgi-bin/wiki.pl>) =back =cut 1; �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������