| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package App::Followme::Guide; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 1 |  |  | 1 |  | 741 | use 5.008005; | 
|  | 1 |  |  |  |  | 3 |  | 
| 4 | 1 |  |  | 1 |  | 5 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 19 |  | 
| 5 | 1 |  |  | 1 |  | 5 | use warnings; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 22 |  | 
| 6 | 1 |  |  | 1 |  | 560 | use integer; | 
|  | 1 |  |  |  |  | 16 |  | 
|  | 1 |  |  |  |  | 5 |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 | 1 |  |  | 1 |  | 35 | use base qw(Pod::Text); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 697 |  | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | #---------------------------------------------------------------------- | 
| 11 |  |  |  |  |  |  | # Create a new object to display the pod in this document | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | sub new { | 
| 14 | 1 |  |  | 1 | 1 | 1522 | my ($pkg) = @_; | 
| 15 |  |  |  |  |  |  |  | 
| 16 | 1 |  |  |  |  | 9 | my $self = Pod::Text->new(); | 
| 17 | 1 |  |  |  |  | 182 | return bless($self, $pkg); | 
| 18 |  |  |  |  |  |  | } | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | #---------------------------------------------------------------------- | 
| 21 |  |  |  |  |  |  | # Print the pod from this file into a string | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | sub print { | 
| 24 | 1 |  |  | 1 | 0 | 1733 | my ($self) = @_; | 
| 25 |  |  |  |  |  |  |  | 
| 26 | 1 |  |  |  |  | 2 | my $result; | 
| 27 | 1 |  |  |  |  | 8 | $self->output_string(\$result); | 
| 28 | 1 |  |  |  |  | 2502 | $self->parse_file(__FILE__); | 
| 29 |  |  |  |  |  |  |  | 
| 30 | 1 |  |  |  |  | 111253 | return $result; | 
| 31 |  |  |  |  |  |  | } | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | 1; | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | =pod | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | =encoding utf-8 | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | =head1 NAME | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | App::Followme::Guide - How to install, configure, and run followme | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | followme [directory] | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | Updates a static website after changes. Constant portions of each page are | 
| 50 |  |  |  |  |  |  | updated to match, text files are converted to html, indexes are created | 
| 51 |  |  |  |  |  |  | for files in the archive, and changed files are uploaded to the remote server. | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | The followme script is run on the directory or file passed as its argument. If | 
| 54 |  |  |  |  |  |  | no argument is given, it is run on the current directory. | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | If a file is passed, the script is run on the directory the file is in. In | 
| 57 |  |  |  |  |  |  | addition, the script is run in quick mode, meaning that only the directory | 
| 58 |  |  |  |  |  |  | the file is in is checked for changes. Otherwise, not only that directory, but | 
| 59 |  |  |  |  |  |  | all directories below it are checked. | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | =head1 CHANGES | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | This version is version two of followme. In the past the code constructed a hash | 
| 64 |  |  |  |  |  |  | and passed it to the template, which used the values in the hash to produce the | 
| 65 |  |  |  |  |  |  | web page. In version two the code passes an object to the template, which calls | 
| 66 |  |  |  |  |  |  | the build method for each variable in the template, passing the name of the | 
| 67 |  |  |  |  |  |  | variable and a filename to retrieve it from as arguments. The module then | 
| 68 |  |  |  |  |  |  | returns the value, which is used to fill in the template. The major user visible | 
| 69 |  |  |  |  |  |  | change is that the template syntax has changed, the new syntax is a subset of the | 
| 70 |  |  |  |  |  |  | previous syntax. Please see L<App::Followme::Template> for a description of the | 
| 71 |  |  |  |  |  |  | template syntax. | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | The second change is that the configuration parameters of some of the modules | 
| 74 |  |  |  |  |  |  | has changed. The new configuration parameters are described in each module. | 
| 75 |  |  |  |  |  |  | The motivation for the change is that placing the variable building in a separate | 
| 76 |  |  |  |  |  |  | class allows more than one type of file to be handled by modules placed in the | 
| 77 |  |  |  |  |  |  | configurarion file. Each class handles a type of file and the name of the class | 
| 78 |  |  |  |  |  |  | which builds the variables is a configuration parameter. | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | The third change is that the configuration file format has changed | 
| 81 |  |  |  |  |  |  | to use a subset of yaml instead of . The new configuration file format is decribed | 
| 82 |  |  |  |  |  |  | below. The biggest change is to how modules are assigned to run_before and | 
| 83 |  |  |  |  |  |  | run_after. Previously this is how the configuration file would look: | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  | author = Your Name | 
| 86 |  |  |  |  |  |  | run_before = App::Followme::FormatPage | 
| 87 |  |  |  |  |  |  | run_before = App::Followme::ConvertPage | 
| 88 |  |  |  |  |  |  | run_after = App::Followme::CreateSitemap | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | This is how the same lines in the configuration file look now: | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  | author: Your Name | 
| 93 |  |  |  |  |  |  | run_before: | 
| 94 |  |  |  |  |  |  | - App::Followme::FormatPage | 
| 95 |  |  |  |  |  |  | - App::Followme::ConvertPage | 
| 96 |  |  |  |  |  |  | run_after: | 
| 97 |  |  |  |  |  |  | - App::Followme::CreateSitemap | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | =head1 INSTALLATION | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | First, install the L<App::Followme> module from CPAN. It will copy the | 
| 102 |  |  |  |  |  |  | followme script to /usr/local/bin, so it will be on your search path. | 
| 103 |  |  |  |  |  |  |  | 
| 104 |  |  |  |  |  |  | sudo cpanm App::Followme | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | Then create a folder to contain the new website. Run followme with the | 
| 107 |  |  |  |  |  |  | init option in that directory | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | mkdir website | 
| 110 |  |  |  |  |  |  | cd website | 
| 111 |  |  |  |  |  |  | followme --init | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | When you run followme with the --init flag, it will install the initial | 
| 114 |  |  |  |  |  |  | templates and configuration files. The initial setup is configured to update | 
| 115 |  |  |  |  |  |  | pages to maintain a consistent look for the site and simplify the onboarding of | 
| 116 |  |  |  |  |  |  | new content. | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | The first page will serve as a prototype for the rest of your site. When you | 
| 119 |  |  |  |  |  |  | look at the html page, you will see that it contains comments looking like | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | <!-- section primary --> | 
| 122 |  |  |  |  |  |  | <!-- endsection primary --> | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | These comments mark the parts of the prototype that will change from page to | 
| 125 |  |  |  |  |  |  | page from the parts that are constant across the entire site. Everything | 
| 126 |  |  |  |  |  |  | outside the comments is the constant portion of the page. When you have | 
| 127 |  |  |  |  |  |  | more than one html page in the folder, you can edit any page, run followme, | 
| 128 |  |  |  |  |  |  | and the other pages will be updated to match it. | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | So you should edit your first page and add any other files you need to create | 
| 131 |  |  |  |  |  |  | the look of your site, such as the style sheets. | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | You can also use followme on an existing site. Run the command | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | followme --init | 
| 136 |  |  |  |  |  |  |  | 
| 137 |  |  |  |  |  |  | in the top directory of your site. The init option will not overwrite any | 
| 138 |  |  |  |  |  |  | existing files in your site. Then look at the convert page template it has | 
| 139 |  |  |  |  |  |  | created: | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | cat _templates/convert_page.htm | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | Edit an existing page on your site to have all the section comments in this | 
| 144 |  |  |  |  |  |  | template. In the template shipped with this package there are three section | 
| 145 |  |  |  |  |  |  | names: meta, primary, and secondary. The meta section is in the html header | 
| 146 |  |  |  |  |  |  | and contains the page metadata, although it may also contain other content | 
| 147 |  |  |  |  |  |  | tht varies between pages. The primary section contains the page content that | 
| 148 |  |  |  |  |  |  | is maintained by you. None of this package's modules will change it. The | 
| 149 |  |  |  |  |  |  | secondary section contains content that is updated by the modules in this | 
| 150 |  |  |  |  |  |  | package and you will not normally change it. | 
| 151 |  |  |  |  |  |  |  | 
| 152 |  |  |  |  |  |  | After you edit a single page, you can place the App::Followme::EditSections | 
| 153 |  |  |  |  |  |  | module in the configuration file, after the run_efore line: | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | run_before: | 
| 156 |  |  |  |  |  |  | - App::Followme::EditSections | 
| 157 |  |  |  |  |  |  | - App::Followme::FormatPage | 
| 158 |  |  |  |  |  |  | - App::Followme::ConvertPage | 
| 159 |  |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  | If you then run followme, it will modify the other pages on your website to | 
| 161 |  |  |  |  |  |  | match the page you have edited. Then remove the EditSections module from | 
| 162 |  |  |  |  |  |  | the configuration file. | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | =head1 CONFIGURATION | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | The configuration file for followme is followme.cfg in the top directory of | 
| 167 |  |  |  |  |  |  | your site. Configuration file lines are in a subset of yaml format. The format | 
| 168 |  |  |  |  |  |  | is described in L<App::Followme::NestedText>. Briefy, the top level is a hash, | 
| 169 |  |  |  |  |  |  | with name-value pairs in the format | 
| 170 |  |  |  |  |  |  |  | 
| 171 |  |  |  |  |  |  | name: value | 
| 172 |  |  |  |  |  |  |  | 
| 173 |  |  |  |  |  |  | There should be no space between the name and the colon and one space between | 
| 174 |  |  |  |  |  |  | the colon and value. The value may also be an array. The array elements are listed | 
| 175 |  |  |  |  |  |  | one per line preceded by a dash: | 
| 176 |  |  |  |  |  |  |  | 
| 177 |  |  |  |  |  |  | name: | 
| 178 |  |  |  |  |  |  | - first value | 
| 179 |  |  |  |  |  |  | - second value | 
| 180 |  |  |  |  |  |  |  | 
| 181 |  |  |  |  |  |  | Configuration files may also contain blank lines or comment lines | 
| 182 |  |  |  |  |  |  | starting with a C<#>. Subdirectories of the top directory may also contain | 
| 183 |  |  |  |  |  |  | configuration files. Values in these configuration files are combined with those | 
| 184 |  |  |  |  |  |  | set in the configuration files in directories above it, If it has a parameter of | 
| 185 |  |  |  |  |  |  | the same name as a configuration file in a higher directory, it overrides it for | 
| 186 |  |  |  |  |  |  | that directory and its subdirectories. | 
| 187 |  |  |  |  |  |  |  | 
| 188 |  |  |  |  |  |  | Configuration files contain the names of the Perl modules to be run by followme | 
| 189 |  |  |  |  |  |  | in the parameters named run_before and run_after. These parameters should be | 
| 190 |  |  |  |  |  |  | arrays, and thus are listed one per line indented from the field name and preceded | 
| 191 |  |  |  |  |  |  | by a dash: | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | run_before: | 
| 194 |  |  |  |  |  |  | - App::Followme::FormatPage | 
| 195 |  |  |  |  |  |  | - App::Followme::ConvertPage | 
| 196 |  |  |  |  |  |  | run_after: | 
| 197 |  |  |  |  |  |  | - App::Followme::CreateSitemap | 
| 198 |  |  |  |  |  |  |  | 
| 199 |  |  |  |  |  |  | Perl modules are run in the order they appear in the configuration file. If they | 
| 200 |  |  |  |  |  |  | are named run_before then they are run before modules in any configuration files | 
| 201 |  |  |  |  |  |  | contained in subdirectories. If they are named run_after, they are run after | 
| 202 |  |  |  |  |  |  | modules which are named in the configuration files in subdirectories. Other | 
| 203 |  |  |  |  |  |  | parameters in the configuration files are written to a hash. This hash is passed | 
| 204 |  |  |  |  |  |  | to the new method of each module as it loaded, overriding the default values of | 
| 205 |  |  |  |  |  |  | the parameters when creating the new object. | 
| 206 |  |  |  |  |  |  |  | 
| 207 |  |  |  |  |  |  | These modules are distributed with followme: | 
| 208 |  |  |  |  |  |  |  | 
| 209 |  |  |  |  |  |  | =over 4 | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | =item L<App::Followme::FormatPage> | 
| 212 |  |  |  |  |  |  |  | 
| 213 |  |  |  |  |  |  | This module updates the web pages in a folder to match the most recently | 
| 214 |  |  |  |  |  |  | modified page. Each web page has sections that are different from other pages | 
| 215 |  |  |  |  |  |  | and other sections that are the same. The sections that differ are enclosed in | 
| 216 |  |  |  |  |  |  | html comments that look like | 
| 217 |  |  |  |  |  |  |  | 
| 218 |  |  |  |  |  |  | <!-- section name--> | 
| 219 |  |  |  |  |  |  | <!-- endsection name --> | 
| 220 |  |  |  |  |  |  |  | 
| 221 |  |  |  |  |  |  | and indicate where the section begins and ends. When a page is changed, this | 
| 222 |  |  |  |  |  |  | module checks the text outside of these comments. If that text has changed. the | 
| 223 |  |  |  |  |  |  | other pages on the site are also changed to match the page that has changed. | 
| 224 |  |  |  |  |  |  | Each page updated by substituting all its named blocks into corresponding block | 
| 225 |  |  |  |  |  |  | in the changed page. The effect is that all the text outside the named blocks | 
| 226 |  |  |  |  |  |  | are updated to be the same across all the web pages. | 
| 227 |  |  |  |  |  |  |  | 
| 228 |  |  |  |  |  |  | In addition to normal section blocks, there are per folder section blocks. | 
| 229 |  |  |  |  |  |  | The contents of these blocks is kept constant across all files in a folder and | 
| 230 |  |  |  |  |  |  | all subfolders of it. If the block is changed in one file in the folder, it will | 
| 231 |  |  |  |  |  |  | be updated in all the other files. Per folder section blocks look like | 
| 232 |  |  |  |  |  |  |  | 
| 233 |  |  |  |  |  |  | <!-- section name in folder_name --> | 
| 234 |  |  |  |  |  |  | <!-- endsection name --> | 
| 235 |  |  |  |  |  |  |  | 
| 236 |  |  |  |  |  |  | where folder_name is the the folder the content is kept constant across. The | 
| 237 |  |  |  |  |  |  | folder name is not a full path, it is the last folder in the path. | 
| 238 |  |  |  |  |  |  |  | 
| 239 |  |  |  |  |  |  | =item L<App::Followme::ConvertPage> | 
| 240 |  |  |  |  |  |  |  | 
| 241 |  |  |  |  |  |  | This module changes text files to html files. By default the text files are | 
| 242 |  |  |  |  |  |  | in Markdown format, though other converters can be used. Markdown format is | 
| 243 |  |  |  |  |  |  | described at: | 
| 244 |  |  |  |  |  |  |  | 
| 245 |  |  |  |  |  |  | http://daringfireball.net/projects/markdown/ | 
| 246 |  |  |  |  |  |  |  | 
| 247 |  |  |  |  |  |  | It builds several variables and substitutes them into the page template. The | 
| 248 |  |  |  |  |  |  | most significant variable is body, which is the contents of the text file | 
| 249 |  |  |  |  |  |  | after it has been converted to html. The title is built from the title of | 
| 250 |  |  |  |  |  |  | the file if one is put at the top of the file. If the file has no | 
| 251 |  |  |  |  |  |  | title, it is built from the file name, replacing dashes with blanks and | 
| 252 |  |  |  |  |  |  | capitalizing each word, The url and absolute_url are built from the html file | 
| 253 |  |  |  |  |  |  | name. To change the look of the html page, edit the page template. Only blocks | 
| 254 |  |  |  |  |  |  | inside the section comments will be in the resulting page, editing the text | 
| 255 |  |  |  |  |  |  | outside it will have no effect on the resulting page. A complete listing of the | 
| 256 |  |  |  |  |  |  | variables is given in the variables section. | 
| 257 |  |  |  |  |  |  |  | 
| 258 |  |  |  |  |  |  | =item L<App::Followme::CreateIndex> | 
| 259 |  |  |  |  |  |  |  | 
| 260 |  |  |  |  |  |  | This module builds an index for a directory containing links to all the files | 
| 261 |  |  |  |  |  |  | with the specified extension contained in it. The same variables mentioned above | 
| 262 |  |  |  |  |  |  | are calculated for each file, with the exception of body. Comments that look like | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  | <!-- for @files --> | 
| 265 |  |  |  |  |  |  | <!-- endfor --> | 
| 266 |  |  |  |  |  |  |  | 
| 267 |  |  |  |  |  |  | indicate the section of the template that is repeated for each file contained | 
| 268 |  |  |  |  |  |  | in the index. | 
| 269 |  |  |  |  |  |  |  | 
| 270 |  |  |  |  |  |  | =item L<App::Followme::CreateGallery> | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | Create a photo gallery for images in a directory. Each image must have a | 
| 273 |  |  |  |  |  |  | thumbnail image whose name has the suffix "-thumb". The suffix name is a | 
| 274 |  |  |  |  |  |  | configuration parameter. The code is very similar to | 
| 275 |  |  |  |  |  |  | L<App::Followme::CreateIndex>, but the template is more complex, so it is a | 
| 276 |  |  |  |  |  |  | separate module. | 
| 277 |  |  |  |  |  |  |  | 
| 278 |  |  |  |  |  |  | =item L<App::Followme::CreateRss> | 
| 279 |  |  |  |  |  |  |  | 
| 280 |  |  |  |  |  |  | This module creates an rss file from the metadata of the most recently updated | 
| 281 |  |  |  |  |  |  | files in a directory. It is a companion to App::Followme::CreateIndex and should | 
| 282 |  |  |  |  |  |  | be used if you also want an rss file. | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | =item L<App::Followme::CreateSitemap> | 
| 285 |  |  |  |  |  |  |  | 
| 286 |  |  |  |  |  |  | This module creates a sitemap file, which is a text file containing the url of | 
| 287 |  |  |  |  |  |  | every page on the site, one per line. It is also intended as a simple example of | 
| 288 |  |  |  |  |  |  | how to write a module that can be run by followme. | 
| 289 |  |  |  |  |  |  |  | 
| 290 |  |  |  |  |  |  | =item L<App::Followme::UploadSite> | 
| 291 |  |  |  |  |  |  |  | 
| 292 |  |  |  |  |  |  | This module uploads changed files to a remote site. The default method to do the | 
| 293 |  |  |  |  |  |  | uploads is local copy, but that can be changed by changing the parameter upload_pkg. | 
| 294 |  |  |  |  |  |  | This package computes a checksum for every file in the site. If the checksum has | 
| 295 |  |  |  |  |  |  | changed since the last time it was run, the file is uploaded to the remote site. | 
| 296 |  |  |  |  |  |  | If there is a checksum, but no local file, the file is deleted from the remote | 
| 297 |  |  |  |  |  |  | site. If followme is run in quick mode, only files whose modification date is | 
| 298 |  |  |  |  |  |  | later then the last time it was run are checked. | 
| 299 |  |  |  |  |  |  |  | 
| 300 |  |  |  |  |  |  | =back | 
| 301 |  |  |  |  |  |  |  | 
| 302 |  |  |  |  |  |  | =head1 RUNNING | 
| 303 |  |  |  |  |  |  |  | 
| 304 |  |  |  |  |  |  | The followme script is run on the directory or file passed as its argument. If | 
| 305 |  |  |  |  |  |  | no argument is given, it is run on the current directory. If a file is passed, | 
| 306 |  |  |  |  |  |  | the script is run on the directory the file is in and followme is run in | 
| 307 |  |  |  |  |  |  | quick mode. Quick mode is an implicit promise that only the named file has | 
| 308 |  |  |  |  |  |  | been changed since last time. Each module can make of this assumption what it | 
| 309 |  |  |  |  |  |  | will, but it is supposed to shorten the list of files examined. | 
| 310 |  |  |  |  |  |  |  | 
| 311 |  |  |  |  |  |  | Followme looks for its configuration files in all the directories above the | 
| 312 |  |  |  |  |  |  | directory it is run from and runs all the modules it finds in them. But they are | 
| 313 |  |  |  |  |  |  | are only run on the folder it is run from and subfolders of it. Followme only | 
| 314 |  |  |  |  |  |  | looks at the folder it is run from to determine if other files in the folder | 
| 315 |  |  |  |  |  |  | need to be updated. So after changing a file, followme should be run from the | 
| 316 |  |  |  |  |  |  | directory containing the file. | 
| 317 |  |  |  |  |  |  | Templates support the basic control structures in Perl: "for" loops and | 
| 318 |  |  |  |  |  |  | "if-else" blocks. Creating output is a two step process. First you generate a | 
| 319 |  |  |  |  |  |  | subroutine from one or more templates, then you call the subroutine with your | 
| 320 |  |  |  |  |  |  | data to generate the output. | 
| 321 |  |  |  |  |  |  |  | 
| 322 |  |  |  |  |  |  | The template format is line oriented. Commands are enclosed in html comments | 
| 323 |  |  |  |  |  |  | (<!-- -->). A command may be preceded by white space. If a command is a block | 
| 324 |  |  |  |  |  |  | command, it is terminated by the word "end" followed by the command name. For | 
| 325 |  |  |  |  |  |  | example, the "for" command is terminated by an "endfor" command and the "if" | 
| 326 |  |  |  |  |  |  | command by an "endif" command. | 
| 327 |  |  |  |  |  |  |  | 
| 328 |  |  |  |  |  |  | All lines may contain variables. As in Perl, variables are a sigil character | 
| 329 |  |  |  |  |  |  | ('$' or '@') followed by one or more word characters. For example, C<$name> or | 
| 330 |  |  |  |  |  |  | C<@names>. To indicate a literal character instead of a variable, precede the | 
| 331 |  |  |  |  |  |  | sigil with a backslash. When you run the subroutine that this module generates, | 
| 332 |  |  |  |  |  |  | you pass it a metadata object. The subroutine replaces variables in the template | 
| 333 |  |  |  |  |  |  | with the value in the field built by the metadata object. | 
| 334 |  |  |  |  |  |  |  | 
| 335 |  |  |  |  |  |  | If the first non-white characters on a line are the command start string, the | 
| 336 |  |  |  |  |  |  | line is interpreted as a command. The command name continues up to the first | 
| 337 |  |  |  |  |  |  | white space character. The text following the initial span of white space is the | 
| 338 |  |  |  |  |  |  | command argument. The argument continues up to the command end string. | 
| 339 |  |  |  |  |  |  |  | 
| 340 |  |  |  |  |  |  | Variables in the template have the same format as ordinary Perl variables, | 
| 341 |  |  |  |  |  |  | a string of word characters starting with a sigil character. for example, | 
| 342 |  |  |  |  |  |  |  | 
| 343 |  |  |  |  |  |  | $body @files | 
| 344 |  |  |  |  |  |  |  | 
| 345 |  |  |  |  |  |  | are examples of variables. Array variable names (variable names starting with | 
| 346 |  |  |  |  |  |  | a C<@>) may have a suffix that indicates how the array is sorted. You can add | 
| 347 |  |  |  |  |  |  | a suffix to a scalar variable (variable names strting with a C<$>) but it | 
| 348 |  |  |  |  |  |  | will have no effect. The format for the name is: | 
| 349 |  |  |  |  |  |  |  | 
| 350 |  |  |  |  |  |  | @data_field[_by_$sort_field][_reversed] | 
| 351 |  |  |  |  |  |  |  | 
| 352 |  |  |  |  |  |  | the brackets are not part of the variable name. They are there to indicate that | 
| 353 |  |  |  |  |  |  | these sections are optional. Two examples of variables with sort suffixes are | 
| 354 |  |  |  |  |  |  |  | 
| 355 |  |  |  |  |  |  | @files_by_size | 
| 356 |  |  |  |  |  |  | @all_files_by_mdate_reversed | 
| 357 |  |  |  |  |  |  |  | 
| 358 |  |  |  |  |  |  | The second suffix, _reversed, indicates that the variable is sorted from | 
| 359 |  |  |  |  |  |  | largest to smallest instead of the usual format, from smallest to largest. | 
| 360 |  |  |  |  |  |  | When used with date fields _reversed indicates the variable is sorted from | 
| 361 |  |  |  |  |  |  | most recent to oldest. | 
| 362 |  |  |  |  |  |  |  | 
| 363 |  |  |  |  |  |  | The following commands are supported in templates: | 
| 364 |  |  |  |  |  |  |  | 
| 365 |  |  |  |  |  |  | =over 4 | 
| 366 |  |  |  |  |  |  |  | 
| 367 |  |  |  |  |  |  | =item do | 
| 368 |  |  |  |  |  |  |  | 
| 369 |  |  |  |  |  |  | The remainder of the line is interpreted as Perl code. | 
| 370 |  |  |  |  |  |  |  | 
| 371 |  |  |  |  |  |  | =item for | 
| 372 |  |  |  |  |  |  |  | 
| 373 |  |  |  |  |  |  | Expand the text between the "for" and "endfor" commands several times. The | 
| 374 |  |  |  |  |  |  | argument to the "for" command should be an expression evaluating to a list. The | 
| 375 |  |  |  |  |  |  | code will expand the text in the for block once for each element in the list. | 
| 376 |  |  |  |  |  |  |  | 
| 377 |  |  |  |  |  |  | <ul> | 
| 378 |  |  |  |  |  |  | <!-- for @files --> | 
| 379 |  |  |  |  |  |  | <li><a href="$url">$title</a></li> | 
| 380 |  |  |  |  |  |  | <!-- endfor --> | 
| 381 |  |  |  |  |  |  | </ul> | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  | =item if | 
| 384 |  |  |  |  |  |  |  | 
| 385 |  |  |  |  |  |  | The text until the matching C<endif> is included only if the expression in the | 
| 386 |  |  |  |  |  |  | "if" command is true. If false, the text is skipped. | 
| 387 |  |  |  |  |  |  |  | 
| 388 |  |  |  |  |  |  | <div class="column"> | 
| 389 |  |  |  |  |  |  | <!-- for @files --> | 
| 390 |  |  |  |  |  |  | <!-- if $count % 20 == 0 --> | 
| 391 |  |  |  |  |  |  | </div> | 
| 392 |  |  |  |  |  |  | <div class="column"> | 
| 393 |  |  |  |  |  |  | <!-- endif --> | 
| 394 |  |  |  |  |  |  | $title<br /> | 
| 395 |  |  |  |  |  |  | <!-- endfor --> | 
| 396 |  |  |  |  |  |  | </div> | 
| 397 |  |  |  |  |  |  |  | 
| 398 |  |  |  |  |  |  | =item else | 
| 399 |  |  |  |  |  |  |  | 
| 400 |  |  |  |  |  |  | The "if" and "for" commands can contain an C<else>. The text before the "else" | 
| 401 |  |  |  |  |  |  | is included if the expression in the enclosing command is true and the | 
| 402 |  |  |  |  |  |  | text after the "else" is included if the "if" command is false or the "for" | 
| 403 |  |  |  |  |  |  | command does not execute. You can also place an "elsif" command inside a block, | 
| 404 |  |  |  |  |  |  | which includes the following text if its expression is true. | 
| 405 |  |  |  |  |  |  |  | 
| 406 |  |  |  |  |  |  | =back | 
| 407 |  |  |  |  |  |  |  | 
| 408 |  |  |  |  |  |  | =head1 TEMPLATES | 
| 409 |  |  |  |  |  |  |  | 
| 410 |  |  |  |  |  |  | Templates are read either from the same directory as the configuration file | 
| 411 |  |  |  |  |  |  | containing the name of the module being run or from the _templates subdirectory | 
| 412 |  |  |  |  |  |  | of the top directory of the site. For more information about the use of | 
| 413 |  |  |  |  |  |  | templates, see L<App::Followme::Template>. | 
| 414 |  |  |  |  |  |  |  | 
| 415 |  |  |  |  |  |  | =head1 VARIABLES | 
| 416 |  |  |  |  |  |  |  | 
| 417 |  |  |  |  |  |  | Templates contain if commands, for loops and variables. The following variables | 
| 418 |  |  |  |  |  |  | are arrays that can be used as arguments to for loops: | 
| 419 |  |  |  |  |  |  |  | 
| 420 |  |  |  |  |  |  | =over 4 | 
| 421 |  |  |  |  |  |  |  | 
| 422 |  |  |  |  |  |  | =item @files | 
| 423 |  |  |  |  |  |  |  | 
| 424 |  |  |  |  |  |  | An array of files in a directory. The files in the list are controlled by the | 
| 425 |  |  |  |  |  |  | configuration variables extension, exclude, and exclude_index. | 
| 426 |  |  |  |  |  |  |  | 
| 427 |  |  |  |  |  |  | =item @all_files | 
| 428 |  |  |  |  |  |  |  | 
| 429 |  |  |  |  |  |  | An array of all files in a directory and its subdirectories. The files are | 
| 430 |  |  |  |  |  |  | controlled by the same configuration variables as @files. | 
| 431 |  |  |  |  |  |  |  | 
| 432 |  |  |  |  |  |  | =item @top_files | 
| 433 |  |  |  |  |  |  |  | 
| 434 |  |  |  |  |  |  | An array of the most recently modified files in a directory and its | 
| 435 |  |  |  |  |  |  | subdirectories. The number of files in the array is controlled by configuration | 
| 436 |  |  |  |  |  |  | variable list_length. The files in the list are controlled by the same | 
| 437 |  |  |  |  |  |  | configuration variables as used by @files. | 
| 438 |  |  |  |  |  |  |  | 
| 439 |  |  |  |  |  |  | =item @folders | 
| 440 |  |  |  |  |  |  |  | 
| 441 |  |  |  |  |  |  | An array of subdirectories in a directory. The subdirectories in the list are | 
| 442 |  |  |  |  |  |  | controlled by the configuration parameter exclude_dirs. | 
| 443 |  |  |  |  |  |  |  | 
| 444 |  |  |  |  |  |  | =item @breadcrumbs | 
| 445 |  |  |  |  |  |  |  | 
| 446 |  |  |  |  |  |  | An array of index file urls of the directories above the directory containing | 
| 447 |  |  |  |  |  |  | the current file. | 
| 448 |  |  |  |  |  |  |  | 
| 449 |  |  |  |  |  |  | =item @related_files | 
| 450 |  |  |  |  |  |  |  | 
| 451 |  |  |  |  |  |  | A list of files with the same file root name as a specified file. This | 
| 452 |  |  |  |  |  |  | list is not filtered by the configuration variables extension and exclude. | 
| 453 |  |  |  |  |  |  |  | 
| 454 |  |  |  |  |  |  | =item @newest_file | 
| 455 |  |  |  |  |  |  |  | 
| 456 |  |  |  |  |  |  | An array with one element, the most recently modified file in a directory | 
| 457 |  |  |  |  |  |  | or its subdirectories. It is an array so that other variables can be used | 
| 458 |  |  |  |  |  |  | inside its for loop. | 
| 459 |  |  |  |  |  |  |  | 
| 460 |  |  |  |  |  |  | =back | 
| 461 |  |  |  |  |  |  |  | 
| 462 |  |  |  |  |  |  | The following variables can only be used inside of loops: | 
| 463 |  |  |  |  |  |  |  | 
| 464 |  |  |  |  |  |  | =over 4 | 
| 465 |  |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | =item @loop | 
| 467 |  |  |  |  |  |  |  | 
| 468 |  |  |  |  |  |  | A copy of the array in the enclosing for loop. This is used to build double | 
| 469 |  |  |  |  |  |  | for loops over the same array. | 
| 470 |  |  |  |  |  |  |  | 
| 471 |  |  |  |  |  |  | =item @thumb_file | 
| 472 |  |  |  |  |  |  |  | 
| 473 |  |  |  |  |  |  | An array with only one element, the name of the thumbnail file for an image file. | 
| 474 |  |  |  |  |  |  | It is an array so that other variables that are functions of the name can be used | 
| 475 |  |  |  |  |  |  | inside its for loop. | 
| 476 |  |  |  |  |  |  |  | 
| 477 |  |  |  |  |  |  | =item $is_first | 
| 478 |  |  |  |  |  |  |  | 
| 479 |  |  |  |  |  |  | True for the first pass through the for loop, false for all following passes. Used | 
| 480 |  |  |  |  |  |  | in if statements. | 
| 481 |  |  |  |  |  |  |  | 
| 482 |  |  |  |  |  |  | =item $is_last | 
| 483 |  |  |  |  |  |  |  | 
| 484 |  |  |  |  |  |  | True for the last pass through the for loop, false for all previous passes. Used in | 
| 485 |  |  |  |  |  |  | if statements. | 
| 486 |  |  |  |  |  |  |  | 
| 487 |  |  |  |  |  |  | =item $count | 
| 488 |  |  |  |  |  |  |  | 
| 489 |  |  |  |  |  |  | The count of the pass through the loop. Starts at one and goes up to the number of | 
| 490 |  |  |  |  |  |  | elements in the array. | 
| 491 |  |  |  |  |  |  |  | 
| 492 |  |  |  |  |  |  | =item $target | 
| 493 |  |  |  |  |  |  |  | 
| 494 |  |  |  |  |  |  | The count prefixed by a string, which is set by the configuration variable | 
| 495 |  |  |  |  |  |  | target_prefix. It is used to construct tatgets for links within a web page. | 
| 496 |  |  |  |  |  |  |  | 
| 497 |  |  |  |  |  |  | =item $target_previous | 
| 498 |  |  |  |  |  |  |  | 
| 499 |  |  |  |  |  |  | The count of the previous pass through the for loop, prefixed by the configuration | 
| 500 |  |  |  |  |  |  | variable target_prefix. It is a zero length string for the first pass through the | 
| 501 |  |  |  |  |  |  | loop. | 
| 502 |  |  |  |  |  |  |  | 
| 503 |  |  |  |  |  |  | =item $target_next | 
| 504 |  |  |  |  |  |  |  | 
| 505 |  |  |  |  |  |  | The count of the next pass through the for loop, prefixed by the configuration | 
| 506 |  |  |  |  |  |  | variable target_prefix. It is a zero length string for the last pass through the | 
| 507 |  |  |  |  |  |  | loop. | 
| 508 |  |  |  |  |  |  |  | 
| 509 |  |  |  |  |  |  | =item $url_previous | 
| 510 |  |  |  |  |  |  |  | 
| 511 |  |  |  |  |  |  | The relative url of the previous file processed by the for loop. It is a zero | 
| 512 |  |  |  |  |  |  | length string for the first pass through the for loop. | 
| 513 |  |  |  |  |  |  |  | 
| 514 |  |  |  |  |  |  | =item $url_next | 
| 515 |  |  |  |  |  |  |  | 
| 516 |  |  |  |  |  |  | The relative url of the next file to be processed by the for loop. It is a zero | 
| 517 |  |  |  |  |  |  | length string for the last pass through the for loop. | 
| 518 |  |  |  |  |  |  |  | 
| 519 |  |  |  |  |  |  | =back | 
| 520 |  |  |  |  |  |  |  | 
| 521 |  |  |  |  |  |  | The following variables can be used inside or outside of for loop. If used inside, | 
| 522 |  |  |  |  |  |  | the refer to the filename of the current iteration of the loop. If outside, they | 
| 523 |  |  |  |  |  |  | refer to the current file being processed. | 
| 524 |  |  |  |  |  |  |  | 
| 525 |  |  |  |  |  |  | =over 4 | 
| 526 |  |  |  |  |  |  |  | 
| 527 |  |  |  |  |  |  | =item $remote_url | 
| 528 |  |  |  |  |  |  |  | 
| 529 |  |  |  |  |  |  | The absolute url of the top folder on the site on the remote system. Set by the | 
| 530 |  |  |  |  |  |  | configuration variable of the same name. | 
| 531 |  |  |  |  |  |  |  | 
| 532 |  |  |  |  |  |  | =item $site_url | 
| 533 |  |  |  |  |  |  |  | 
| 534 |  |  |  |  |  |  | The absolute url of the top folder on the site on the local system. Set by the | 
| 535 |  |  |  |  |  |  | configuration variable of the same name. If the configuration variable is not | 
| 536 |  |  |  |  |  |  | set, it is constructed from the name of the top folder of the site. | 
| 537 |  |  |  |  |  |  |  | 
| 538 |  |  |  |  |  |  | =item $url | 
| 539 |  |  |  |  |  |  |  | 
| 540 |  |  |  |  |  |  | The url of a file, relative to the url of the top folder. | 
| 541 |  |  |  |  |  |  |  | 
| 542 |  |  |  |  |  |  | =item $index_url | 
| 543 |  |  |  |  |  |  |  | 
| 544 |  |  |  |  |  |  | The relative url of the index file in the same folder | 
| 545 |  |  |  |  |  |  |  | 
| 546 |  |  |  |  |  |  | =item $absolute_url | 
| 547 |  |  |  |  |  |  |  | 
| 548 |  |  |  |  |  |  | The relative url of a file prefixed by the site url. | 
| 549 |  |  |  |  |  |  |  | 
| 550 |  |  |  |  |  |  | =item $url_base | 
| 551 |  |  |  |  |  |  |  | 
| 552 |  |  |  |  |  |  | The relative url of a file without any file extension. Used to create the urls of | 
| 553 |  |  |  |  |  |  | any related files. | 
| 554 |  |  |  |  |  |  |  | 
| 555 |  |  |  |  |  |  | =item $name | 
| 556 |  |  |  |  |  |  |  | 
| 557 |  |  |  |  |  |  | The name of a file. | 
| 558 |  |  |  |  |  |  |  | 
| 559 |  |  |  |  |  |  | =item $extension | 
| 560 |  |  |  |  |  |  |  | 
| 561 |  |  |  |  |  |  | The extension of a filename. | 
| 562 |  |  |  |  |  |  |  | 
| 563 |  |  |  |  |  |  | =item $is_index | 
| 564 |  |  |  |  |  |  |  | 
| 565 |  |  |  |  |  |  | True if a file is an index file, that is, its name minus the extension is "index". | 
| 566 |  |  |  |  |  |  | Used in if statements. | 
| 567 |  |  |  |  |  |  |  | 
| 568 |  |  |  |  |  |  | =item $date | 
| 569 |  |  |  |  |  |  |  | 
| 570 |  |  |  |  |  |  | The creation date of a file, if available, the date of last modification, if not. | 
| 571 |  |  |  |  |  |  | The format of this variable is set by the configuration variable date_format. | 
| 572 |  |  |  |  |  |  |  | 
| 573 |  |  |  |  |  |  | =item $mdate | 
| 574 |  |  |  |  |  |  |  | 
| 575 |  |  |  |  |  |  | The date of last modification of a file. The format of this variable is set by | 
| 576 |  |  |  |  |  |  | the configuration variable date_format. | 
| 577 |  |  |  |  |  |  |  | 
| 578 |  |  |  |  |  |  | =item $size | 
| 579 |  |  |  |  |  |  |  | 
| 580 |  |  |  |  |  |  | The size of the file in bytes. | 
| 581 |  |  |  |  |  |  |  | 
| 582 |  |  |  |  |  |  | =item $title | 
| 583 |  |  |  |  |  |  |  | 
| 584 |  |  |  |  |  |  | The title of a file. Constructed from the filename if it is not otherwise | 
| 585 |  |  |  |  |  |  | available. | 
| 586 |  |  |  |  |  |  |  | 
| 587 |  |  |  |  |  |  | =item $body | 
| 588 |  |  |  |  |  |  |  | 
| 589 |  |  |  |  |  |  | The body text of a file. | 
| 590 |  |  |  |  |  |  |  | 
| 591 |  |  |  |  |  |  | =item $summary | 
| 592 |  |  |  |  |  |  |  | 
| 593 |  |  |  |  |  |  | A summary of the file, constructed from the first paragraph of the body. | 
| 594 |  |  |  |  |  |  |  | 
| 595 |  |  |  |  |  |  | =item $description | 
| 596 |  |  |  |  |  |  |  | 
| 597 |  |  |  |  |  |  | A description of the contents of the file, constructed from the first sentence | 
| 598 |  |  |  |  |  |  | of the body if it is not otherwise available. | 
| 599 |  |  |  |  |  |  |  | 
| 600 |  |  |  |  |  |  | =item $keywords | 
| 601 |  |  |  |  |  |  |  | 
| 602 |  |  |  |  |  |  | A comma separated list of keywords describing a file. Constructed from the name | 
| 603 |  |  |  |  |  |  | of the folder containing the file if it is not otherwise available. | 
| 604 |  |  |  |  |  |  |  | 
| 605 |  |  |  |  |  |  | =item $author | 
| 606 |  |  |  |  |  |  |  | 
| 607 |  |  |  |  |  |  | The name of the author of a file. Taken from the configuration variable of the | 
| 608 |  |  |  |  |  |  | same name if it is not otherwise available. | 
| 609 |  |  |  |  |  |  |  | 
| 610 |  |  |  |  |  |  | =back | 
| 611 |  |  |  |  |  |  |  | 
| 612 |  |  |  |  |  |  | =head1 MODULES | 
| 613 |  |  |  |  |  |  |  | 
| 614 |  |  |  |  |  |  | New modules can be written and then invoked via the configuration file, exactly | 
| 615 |  |  |  |  |  |  | like the modules that have been distributed with App::Followme. Each module to | 
| 616 |  |  |  |  |  |  | be run must have new and run methods. An object of the module's class is created | 
| 617 |  |  |  |  |  |  | by calling the new method with the a reference to a hash containing the | 
| 618 |  |  |  |  |  |  | configuration parameters. The run method is then called with the directory as | 
| 619 |  |  |  |  |  |  | its argument. | 
| 620 |  |  |  |  |  |  |  | 
| 621 |  |  |  |  |  |  | The signature of the new method is | 
| 622 |  |  |  |  |  |  |  | 
| 623 |  |  |  |  |  |  | $obj = $module_name->new($configuration); | 
| 624 |  |  |  |  |  |  |  | 
| 625 |  |  |  |  |  |  | where $configuration is a reference to a hash containing the configuration | 
| 626 |  |  |  |  |  |  | parameters. $module name is the same as the name in the configuration file. | 
| 627 |  |  |  |  |  |  |  | 
| 628 |  |  |  |  |  |  | All the modules distributed with App::Followme subclass | 
| 629 |  |  |  |  |  |  | App::Followme::Module to access its methods, which provide consistent | 
| 630 |  |  |  |  |  |  | behavior, such as looping over files and template handling. It also supplies a | 
| 631 |  |  |  |  |  |  | new method, so if you subclass it, you will not need to supply a new method in | 
| 632 |  |  |  |  |  |  | your class. | 
| 633 |  |  |  |  |  |  |  | 
| 634 |  |  |  |  |  |  | The signature of the run method is | 
| 635 |  |  |  |  |  |  |  | 
| 636 |  |  |  |  |  |  | $obj->run($directory); | 
| 637 |  |  |  |  |  |  |  | 
| 638 |  |  |  |  |  |  | where $obj is the object created by the new method and $directory is the name | 
| 639 |  |  |  |  |  |  | of the directory the module is being run on. All modules included in | 
| 640 |  |  |  |  |  |  | App::Followme use L<App::Followme::Module> as a base class, so they can use its | 
| 641 |  |  |  |  |  |  | methods, such as visiting all files in a directory and compiling a template. If | 
| 642 |  |  |  |  |  |  | you wish to write your own module, you can use L<App::Followme::CreateSitemap> | 
| 643 |  |  |  |  |  |  | as a guide. If you use App::Followme::Module as a base class, you should not | 
| 644 |  |  |  |  |  |  | supply your own new method, but rely on the new method in | 
| 645 |  |  |  |  |  |  | L<App::Followme::ConfiguredObject>, which you will inherit. | 
| 646 |  |  |  |  |  |  |  | 
| 647 |  |  |  |  |  |  | =head1 LICENSE | 
| 648 |  |  |  |  |  |  |  | 
| 649 |  |  |  |  |  |  | Copyright (C) Bernie Simon. | 
| 650 |  |  |  |  |  |  |  | 
| 651 |  |  |  |  |  |  | This library is free software; you can redistribute it and/or modify | 
| 652 |  |  |  |  |  |  | it under the same terms as Perl itself. | 
| 653 |  |  |  |  |  |  |  | 
| 654 |  |  |  |  |  |  | =head1 AUTHOR | 
| 655 |  |  |  |  |  |  |  | 
| 656 |  |  |  |  |  |  | Bernie Simon E<lt>bernie.simon@gmail.comE<gt> | 
| 657 |  |  |  |  |  |  |  | 
| 658 |  |  |  |  |  |  | =cut |