| blib/lib/SVN/Notify/HTML.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 128 | 128 | 100.0 |
| branch | 51 | 56 | 91.0 |
| condition | 21 | 24 | 87.5 |
| subroutine | 14 | 14 | 100.0 |
| pod | 9 | 9 | 100.0 |
| total | 223 | 231 | 96.5 |
| line | stmt | bran | cond | sub | pod | time | code | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | package SVN::Notify::HTML; | |||||||||||||
| 2 | ||||||||||||||
| 3 | 198 | 198 | 384114 | use strict; | ||||||||||
| 198 | 366 | |||||||||||||
| 198 | 5903 | |||||||||||||
| 4 | 198 | 198 | 1022 | use HTML::Entities; | ||||||||||
| 198 | 450 | |||||||||||||
| 198 | 12327 | |||||||||||||
| 5 | 198 | 198 | 65306 | use SVN::Notify (); | ||||||||||
| 198 | 576 | |||||||||||||
| 198 | 440223 | |||||||||||||
| 6 | ||||||||||||||
| 7 | $SVN::Notify::HTML::VERSION = '2.87'; | |||||||||||||
| 8 | @SVN::Notify::HTML::ISA = qw(SVN::Notify); | |||||||||||||
| 9 | ||||||||||||||
| 10 | __PACKAGE__->register_attributes( | |||||||||||||
| 11 | linkize => 'linkize', | |||||||||||||
| 12 | css_url => 'css-url=s', | |||||||||||||
| 13 | wrap_log => 'wrap-log', | |||||||||||||
| 14 | ); | |||||||||||||
| 15 | ||||||||||||||
| 16 | =head1 Name | |||||||||||||
| 17 | ||||||||||||||
| 18 | SVN::Notify::HTML - Subversion activity HTML notification | |||||||||||||
| 19 | ||||||||||||||
| 20 | =head1 Synopsis | |||||||||||||
| 21 | ||||||||||||||
| 22 | Use F |
|||||||||||||
| 23 | ||||||||||||||
| 24 | svnnotify --repos-path "$1" --revision "$2" \ | |||||||||||||
| 25 | --to developers@example.com --handler HTML [options] | |||||||||||||
| 26 | ||||||||||||||
| 27 | Use the class in a custom script: | |||||||||||||
| 28 | ||||||||||||||
| 29 | use SVN::Notify::HTML; | |||||||||||||
| 30 | ||||||||||||||
| 31 | my $notifier = SVN::Notify::HTML->new(%params); | |||||||||||||
| 32 | $notifier->prepare; | |||||||||||||
| 33 | $notifier->execute; | |||||||||||||
| 34 | ||||||||||||||
| 35 | =head1 Description | |||||||||||||
| 36 | ||||||||||||||
| 37 | This subclass of L |
|||||||||||||
| 38 | messages for Subversion activity, rather than the default plain text. | |||||||||||||
| 39 | ||||||||||||||
| 40 | =head1 Prerequisites | |||||||||||||
| 41 | ||||||||||||||
| 42 | In addition to the modules required by SVN::Notify, this class requires: | |||||||||||||
| 43 | ||||||||||||||
| 44 | =over | |||||||||||||
| 45 | ||||||||||||||
| 46 | =item HTML::Entities | |||||||||||||
| 47 | ||||||||||||||
| 48 | =back | |||||||||||||
| 49 | ||||||||||||||
| 50 | =head1 Usage | |||||||||||||
| 51 | ||||||||||||||
| 52 | To use SVN::Notify::HTML, simply follow the L |
|||||||||||||
| 53 | in SVN::Notify, but when using F |
|||||||||||||
| 54 | ||||||||||||||
| 55 | =cut | |||||||||||||
| 56 | ||||||||||||||
| 57 | ############################################################################## | |||||||||||||
| 58 | ||||||||||||||
| 59 | =head1 Class Interface | |||||||||||||
| 60 | ||||||||||||||
| 61 | =head2 Constructor | |||||||||||||
| 62 | ||||||||||||||
| 63 | =head3 new | |||||||||||||
| 64 | ||||||||||||||
| 65 | my $notifier = SVN::Notify::HTML->new(%params); | |||||||||||||
| 66 | ||||||||||||||
| 67 | Constructs and returns a new SVN::Notify object. All parameters supported by | |||||||||||||
| 68 | SVN::Notity are supported here, but SVN::Notify::HTML supports a few | |||||||||||||
| 69 | additional parameters: | |||||||||||||
| 70 | ||||||||||||||
| 71 | =over | |||||||||||||
| 72 | ||||||||||||||
| 73 | =item linkize | |||||||||||||
| 74 | ||||||||||||||
| 75 | svnnotify --linkize | |||||||||||||
| 76 | ||||||||||||||
| 77 | A boolean attribute to specify whether or not to "linkize" the SVN log | |||||||||||||
| 78 | message--that is, to turn any URLs or email addresses in the log message into | |||||||||||||
| 79 | links. | |||||||||||||
| 80 | ||||||||||||||
| 81 | =item css_url | |||||||||||||
| 82 | ||||||||||||||
| 83 | svnnotify --css-url http://example.com/svnnotify.css | |||||||||||||
| 84 | ||||||||||||||
| 85 | URL for a CSS file that will can style the HTML output by SVN::Notify::HTML or | |||||||||||||
| 86 | its subclasses. Note that the URL will be added to the output via a | |||||||||||||
| 87 | C<< >> tag I |
|||||||||||||
| 88 | SVN::Notify::HTML or its subclasses. What that means is that the CSS file | |||||||||||||
| 89 | specified by C |
|||||||||||||
| 90 | override the default settings. This approach nicely takes advantage of the | |||||||||||||
| 91 | "cascading" abilities of CSS. | |||||||||||||
| 92 | ||||||||||||||
| 93 | =item ticket_map | |||||||||||||
| 94 | ||||||||||||||
| 95 | svnnotify --ticket-map '(BUG-(\d+))=http://bugs.example.com/?show=%s' | |||||||||||||
| 96 | ||||||||||||||
| 97 | This attribute is inherited from L |
|||||||||||||
| 98 | are slightly different: the regular expression passed as the regular | |||||||||||||
| 99 | expression used for the key should return I |
|||||||||||||
| 100 | text to link and the ticket ID itself. For example, '(BUG-(\d+))' will match | |||||||||||||
| 101 | "BUG-1234567", and "BUG-1234567" will be used for the link text, while | |||||||||||||
| 102 | "1234567" will be used to fill in the C |
|||||||||||||
| 103 | set of parentheses capture the whole string, while the parentheses around | |||||||||||||
| 104 | C<\d+> match the number only. Also note that it is wise to use "\b" on either | |||||||||||||
| 105 | side of the regular expression to insure that you don't get spurious matches. | |||||||||||||
| 106 | So a better version would be '\b(BUG-(\d+))\b'. | |||||||||||||
| 107 | ||||||||||||||
| 108 | As a fallback, if your regular expression returns only a single match string, | |||||||||||||
| 109 | it will be used both for the link text and for the the ticket URL generated | |||||||||||||
| 110 | from C |
|||||||||||||
| 111 | number in 'BUG-1234567', as only the number has been captured by the regular | |||||||||||||
| 112 | expression. But two matches are of course recommended (and likely to work | |||||||||||||
| 113 | better, as well). | |||||||||||||
| 114 | ||||||||||||||
| 115 | You can use more complicated regular expressions if commit messages are likely | |||||||||||||
| 116 | to format ticket numbers in various ways. For example, this regular | |||||||||||||
| 117 | expression: | |||||||||||||
| 118 | ||||||||||||||
| 119 | \b\[?\s*(Ticket\s*#\s*(\d+))\s*\]?\b' | |||||||||||||
| 120 | ||||||||||||||
| 121 | Will match: | |||||||||||||
| 122 | ||||||||||||||
| 123 | String Matched Link Text Ticket Number | |||||||||||||
| 124 | --------------------|--------------------|--------------- | |||||||||||||
| 125 | [Ticket#1234] [Ticket#1234] 1234 | |||||||||||||
| 126 | [ Ticket # 1234 ] [ Ticket # 1234 ] 1234 | |||||||||||||
| 127 | Ticket #1234 Ticket #1234 1234 | |||||||||||||
| 128 | Ticket # 1234 Ticket #1234 1234 | |||||||||||||
| 129 | ||||||||||||||
| 130 | In any of these cases, you can see that the match is successful, properly | |||||||||||||
| 131 | creates the link text (simply using the text as typed in by the committer, and | |||||||||||||
| 132 | correctly extracts the ticket number for use in the URL. | |||||||||||||
| 133 | ||||||||||||||
| 134 | To learn more about the power of Regular expressions, I highly recommend | |||||||||||||
| 135 | _Mastering Regular Expressions, Second Edition_, by Jeffrey Friedl. | |||||||||||||
| 136 | ||||||||||||||
| 137 | =item wrap_log | |||||||||||||
| 138 | ||||||||||||||
| 139 | svnnotify --wrap-log | |||||||||||||
| 140 | ||||||||||||||
| 141 | A boolean attribute to specify whether or not to wrap the log message in the | |||||||||||||
| 142 | output HTML. By default, log messages are I |
|||||||||||||
| 143 | that they should appear exactly as typed. But if that's not the case, specify | |||||||||||||
| 144 | this option to wrap the log message. | |||||||||||||
| 145 | ||||||||||||||
| 146 | =back | |||||||||||||
| 147 | ||||||||||||||
| 148 | =cut | |||||||||||||
| 149 | ||||||||||||||
| 150 | ############################################################################## | |||||||||||||
| 151 | ||||||||||||||
| 152 | =head2 Class Methods | |||||||||||||
| 153 | ||||||||||||||
| 154 | =head3 content_type | |||||||||||||
| 155 | ||||||||||||||
| 156 | Returns the content type of the notification message, "text/html". Used to set | |||||||||||||
| 157 | the Content-Type header for the message. | |||||||||||||
| 158 | ||||||||||||||
| 159 | =cut | |||||||||||||
| 160 | ||||||||||||||
| 161 | 1139 | 1139 | 1 | 12249 | sub content_type { 'text/html' } | |||||||||
| 162 | ||||||||||||||
| 163 | ############################################################################## | |||||||||||||
| 164 | ||||||||||||||
| 165 | =head1 Instance Interface | |||||||||||||
| 166 | ||||||||||||||
| 167 | =head2 Instance Methods | |||||||||||||
| 168 | ||||||||||||||
| 169 | =head3 start_html | |||||||||||||
| 170 | ||||||||||||||
| 171 | $notifier->start_html($file_handle); | |||||||||||||
| 172 | ||||||||||||||
| 173 | This method starts the HTML of the notification message. It outputs the | |||||||||||||
| 174 | opening C<< >>, C<< >>, and C<< >> tags. Note that if the | |||||||||||||
| 175 | C |
|||||||||||||
| 176 | C<< >> tag. | |||||||||||||
| 177 | ||||||||||||||
| 178 | All of the HTML will be passed to any "start_html" output filters. See | |||||||||||||
| 179 | L |
|||||||||||||
| 180 | filters. | |||||||||||||
| 181 | ||||||||||||||
| 182 | =cut | |||||||||||||
| 183 | ||||||||||||||
| 184 | sub start_html { | |||||||||||||
| 185 | 1077 | 1077 | 1 | 11514 | my ($self, $out) = @_; | |||||||||
| 186 | 1077 | 22754 | my $lang = $self->language; | |||||||||||
| 187 | 1077 | 11565 | my $char = lc $self->encoding; | |||||||||||
| 188 | ||||||||||||||
| 189 | my @html = ( | |||||||||||||
| 190 | qq{ | |||||||||||||
| 191 | qq{"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n}, | |||||||||||||
| 192 | qq{ | |||||||||||||
| 193 | ($lang ? qq{ xml:lang="$lang"} : ()), | |||||||||||||
| 194 | qq{>\n 195 | qq{charset=$char" />\n}, | ||||||||||||
| 196 | ( $self->{css_url} | |||||||||||||
| 197 | ? ( | |||||||||||||
| 198 | ' 199 | 1077 | 100 | 30575 | encode_entities($self->{css_url}), | |||||||||
| 100 | ||||||||||||||
| 200 | qq{" />\n} | |||||||||||||
| 201 | ) : () | |||||||||||||
| 202 | ), | |||||||||||||
| 203 | ' |
|||||||||||||
| 204 | qq{\n\n\n\n} | |||||||||||||
| 205 | ); | |||||||||||||
| 206 | ||||||||||||||
| 207 | 1077 | 185454 | print $out @{ $self->run_filters( start_html => \@html ) }; | |||||||||||
| 1077 | 5791 | |||||||||||||
| 208 | 1077 | 3904 | return $self; | |||||||||||
| 209 | } | |||||||||||||
| 210 | ||||||||||||||
| 211 | ############################################################################## | |||||||||||||
| 212 | ||||||||||||||
| 213 | =head3 start_body | |||||||||||||
| 214 | ||||||||||||||
| 215 | This method starts the body of the HTML notification message. It first calls | |||||||||||||
| 216 | C |
|||||||||||||
| 238 | ||||||||||||||
| 239 | 1077 | 7235 | my @html = ( qq{ \n} ); |
|||||||||||
| 240 | 1077 | 100 | 9613 | if (my $header = $self->header) { | ||||||||||
| 241 | 13 | 100 | 439 | push @html, ( | ||||||||||
| 242 | ' ', |
|||||||||||||
| 243 | ( $header =~ /^ ? $header : encode_entities($header, '<>&"') ), | |||||||||||||
| 244 | "\n", | |||||||||||||
| 245 | ); | |||||||||||||
| 246 | } | |||||||||||||
| 247 | ||||||||||||||
| 248 | 1077 | 3633 | print $out @{ $self->run_filters( start_body => \@html ) }; | |||||||||||
| 1077 | 3991 | |||||||||||||
| 249 | 1077 | 3634 | return $self; | |||||||||||
| 250 | } | |||||||||||||
| 251 | ||||||||||||||
| 252 | ############################################################################## | |||||||||||||
| 253 | ||||||||||||||
| 254 | =head3 output_css | |||||||||||||
| 255 | ||||||||||||||
| 256 | $notifier->output_css($file_handle); | |||||||||||||
| 257 | ||||||||||||||
| 258 | This method starts outputs the CSS for the HTML message. It is called by | |||||||||||||
| 259 | C |
|||||||||||||
| 260 | appropriate C<< |