summaryrefslogtreecommitdiff
path: root/IkiWiki/Plugin/link.pm
blob: f6c3573f75f5508dc810464162e9fb9a1ad8f527 (plain)
  1. #!/usr/bin/perl
  2. package IkiWiki::Plugin::link;
  3. use warnings;
  4. use strict;
  5. use IkiWiki 3.00;
  6. my $link_regexp;
  7. my $email_regexp = qr/^.+@.+$/;
  8. my $url_regexp = qr/^(?:[^:]+:\/\/|mailto:).*/i;
  9. sub import {
  10. hook(type => "getsetup", id => "link", call => \&getsetup);
  11. hook(type => "checkconfig", id => "link", call => \&checkconfig);
  12. hook(type => "linkify", id => "link", call => \&linkify);
  13. hook(type => "scan", id => "link", call => \&scan);
  14. hook(type => "renamepage", id => "link", call => \&renamepage);
  15. }
  16. sub getsetup () {
  17. return
  18. plugin => {
  19. safe => 1,
  20. rebuild => 1,
  21. section => "core",
  22. },
  23. }
  24. sub checkconfig () {
  25. if ($config{prefix_directives}) {
  26. $link_regexp = qr{
  27. \[\[(?=[^!]) # beginning of link
  28. (?:
  29. ([^\]\|]+) # 1: link text
  30. \| # followed by '|'
  31. )? # optional
  32. ([^\n\r\]#]+) # 2: page to link to
  33. (?:
  34. \# # '#', beginning of anchor
  35. ([^\s\]]+) # 3: anchor text
  36. )? # optional
  37. \]\] # end of link
  38. }x;
  39. }
  40. else {
  41. $link_regexp = qr{
  42. \[\[ # beginning of link
  43. (?:
  44. ([^\]\|\n\s]+) # 1: link text
  45. \| # followed by '|'
  46. )? # optional
  47. ([^\s\]#]+) # 2: page to link to
  48. (?:
  49. \# # '#', beginning of anchor
  50. ([^\s\]]+) # 3: anchor text
  51. )? # optional
  52. \]\] # end of link
  53. }x;
  54. }
  55. }
  56. sub is_externallink ($$;$$) {
  57. my $page = shift;
  58. my $url = shift;
  59. my $anchor = shift;
  60. my $force = shift;
  61. if (defined $anchor) {
  62. $url.="#".$anchor;
  63. }
  64. if (! $force && $url =~ /$email_regexp/) {
  65. # url looks like an email address, so we assume it
  66. # is supposed to be an external link if there is no
  67. # page with that name.
  68. return (! (bestlink($page, linkpage($url))))
  69. }
  70. return ($url =~ /$url_regexp/)
  71. }
  72. sub externallink ($$;$) {
  73. my $url = shift;
  74. my $anchor = shift;
  75. my $pagetitle = shift;
  76. if (defined $anchor) {
  77. $url.="#".$anchor;
  78. }
  79. # build pagetitle
  80. if (! $pagetitle) {
  81. $pagetitle = $url;
  82. # use only the email address as title for mailto: urls
  83. if ($pagetitle =~ /^mailto:.*/) {
  84. $pagetitle =~ s/^mailto:([^?]+).*/$1/;
  85. }
  86. }
  87. if ($url !~ /$url_regexp/) {
  88. # handle email addresses (without mailto:)
  89. $url = "mailto:" . $url;
  90. }
  91. return "<a href=\"$url\">$pagetitle</a>";
  92. }
  93. sub linkify (@) {
  94. my %params=@_;
  95. my $page=$params{page};
  96. my $destpage=$params{destpage};
  97. $params{content} =~ s{(\\?)$link_regexp}{
  98. defined $2
  99. ? ( $1
  100. ? "[[$2|$3".(defined $4 ? "#$4" : "")."]]"
  101. : is_externallink($page, $3, $4)
  102. ? externallink($3, $4, $2)
  103. : htmllink($page, $destpage, linkpage($3),
  104. anchor => $4, linktext => pagetitle($2)))
  105. : ( $1
  106. ? "[[$3".(defined $4 ? "#$4" : "")."]]"
  107. : is_externallink($page, $3, $4)
  108. ? externallink($3, $4)
  109. : htmllink($page, $destpage, linkpage($3),
  110. anchor => $4))
  111. }eg;
  112. return $params{content};
  113. }
  114. sub scan (@) {
  115. my %params=@_;
  116. my $page=$params{page};
  117. my $content=$params{content};
  118. while ($content =~ /(?<!\\)$link_regexp/g) {
  119. if (! is_externallink($page, $2, $3, 1)) {
  120. add_link($page, linkpage($2));
  121. }
  122. }
  123. }
  124. sub renamepage (@) {
  125. my %params=@_;
  126. my $page=$params{page};
  127. my $old=$params{oldpage};
  128. my $new=$params{newpage};
  129. $params{content} =~ s{(?<!\\)$link_regexp}{
  130. if (! is_externallink($page, $2, $3)) {
  131. my $linktext=$2;
  132. my $link=$linktext;
  133. if (bestlink($page, linkpage($linktext)) eq $old) {
  134. $link=pagetitle($new, 1);
  135. $link=~s/ /_/g;
  136. if ($linktext =~ m/.*\/*?[A-Z]/) {
  137. # preserve leading cap of last component
  138. my @bits=split("/", $link);
  139. $link=join("/", @bits[0..$#bits-1], ucfirst($bits[$#bits]));
  140. }
  141. if (index($linktext, "/") == 0) {
  142. # absolute link
  143. $link="/$link";
  144. }
  145. }
  146. defined $1
  147. ? ( "[[$1|$link".($3 ? "#$3" : "")."]]" )
  148. : ( "[[$link". ($3 ? "#$3" : "")."]]" )
  149. }
  150. }eg;
  151. return $params{content};
  152. }
  153. 1