Almost-minimal filesystem based blog.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

468 lines
15 KiB

v6.0.0: expand EntryStore, test more, cache harder This commit is something of a hairball, the result of evenings-and-weekends hacking building up a set of changes that got out of hand in parallel. If I had the energy to spare, I would break it apart into semantically-related changes, but I don't - and I suppose all this crap being rolled together is at least reflective of how the code was written. These changes are really half-finished, at best. Eventual goals: - App::WRT shouldn't directly touch the filesystem - App::WRT::EntryStore should model the entry archive completely - App::WRT::Renderer should say what to write to the publication directory - This one's a maybe: Filesystem interaction should pass through App::WRT::FileIO or something like it so that EntryStore and Renderer can be more usefully tested, with mocked writes (maybe) I do think this represents an inflection point in the long, silly life of this program: It includes a handful of new tests, and a number of the code changes were in turn easy to make because the test suite begins to model the code in a useful way. It's less and less necessary to run wrt against the p1k3.com archives to be sure that I haven't trashed something. Breaking changes to note: - Will no longer render HTML for nonexistent entries - Months and years which are flatfiles or contain an index are handled differently, albeit less brokenly - EntryStore includes index files in its overall list of entries (this seems to break less than I thought), which trickles out to bin/wrt-ls Overall changes herein: - App::WRT::Date - Move month_name() in here from App::WRT, add tests. - App::WRT::EntryStore - Hash file types for entries (directory or flatfile) - Use keys of file type hash for complete list of entries. - has_prop($entry, $property) - is_dir($entry), is_file($entry), is_extant($entry) - parent_of($entry) - has_index($entry) - Make EntryStore cache whether a file is a flatfile or a directory, as well as its existence, in a single hash. - Include index flatfiles in @source_files for use by has_index() - Various tests. - App::WRT::FileIO - Still duplicates a bunch of shit from Util, so that needs sorted. - App::WRT::Renderer - Convert to a proper class. - Add experimental FileIO class to use in Renderer (imperfect, tricky, still thinking about this). The idea is to separate out the concerns of reading and writing the filesystem. - App::WRT - Refactor display() and improve tests - Use "@entries" instead of "@options" for clarity - Handle entry names that might evaluate as false - Test running display() without any params - Rename expand_option() -> expand_alias(), refactor - Use EntryStore::has_prop() to detect wrt-noexpand.prop - year(), month(), entry() partially rewritten to use EntryStore - year() should handle months which are a flatfile - Refactor icon_markup() to use is_file() / is_dir() / is_extant(), add tests. - Add subtitle to feeds - bin/wrt-ls is now a "modulino" with tests - bin/display errors on non-existent entries - Build.PL - Remove bogus XML::Feed dependency
5 years ago
v6.0.0: expand EntryStore, test more, cache harder This commit is something of a hairball, the result of evenings-and-weekends hacking building up a set of changes that got out of hand in parallel. If I had the energy to spare, I would break it apart into semantically-related changes, but I don't - and I suppose all this crap being rolled together is at least reflective of how the code was written. These changes are really half-finished, at best. Eventual goals: - App::WRT shouldn't directly touch the filesystem - App::WRT::EntryStore should model the entry archive completely - App::WRT::Renderer should say what to write to the publication directory - This one's a maybe: Filesystem interaction should pass through App::WRT::FileIO or something like it so that EntryStore and Renderer can be more usefully tested, with mocked writes (maybe) I do think this represents an inflection point in the long, silly life of this program: It includes a handful of new tests, and a number of the code changes were in turn easy to make because the test suite begins to model the code in a useful way. It's less and less necessary to run wrt against the p1k3.com archives to be sure that I haven't trashed something. Breaking changes to note: - Will no longer render HTML for nonexistent entries - Months and years which are flatfiles or contain an index are handled differently, albeit less brokenly - EntryStore includes index files in its overall list of entries (this seems to break less than I thought), which trickles out to bin/wrt-ls Overall changes herein: - App::WRT::Date - Move month_name() in here from App::WRT, add tests. - App::WRT::EntryStore - Hash file types for entries (directory or flatfile) - Use keys of file type hash for complete list of entries. - has_prop($entry, $property) - is_dir($entry), is_file($entry), is_extant($entry) - parent_of($entry) - has_index($entry) - Make EntryStore cache whether a file is a flatfile or a directory, as well as its existence, in a single hash. - Include index flatfiles in @source_files for use by has_index() - Various tests. - App::WRT::FileIO - Still duplicates a bunch of shit from Util, so that needs sorted. - App::WRT::Renderer - Convert to a proper class. - Add experimental FileIO class to use in Renderer (imperfect, tricky, still thinking about this). The idea is to separate out the concerns of reading and writing the filesystem. - App::WRT - Refactor display() and improve tests - Use "@entries" instead of "@options" for clarity - Handle entry names that might evaluate as false - Test running display() without any params - Rename expand_option() -> expand_alias(), refactor - Use EntryStore::has_prop() to detect wrt-noexpand.prop - year(), month(), entry() partially rewritten to use EntryStore - year() should handle months which are a flatfile - Refactor icon_markup() to use is_file() / is_dir() / is_extant(), add tests. - Add subtitle to feeds - bin/wrt-ls is now a "modulino" with tests - bin/display errors on non-existent entries - Build.PL - Remove bogus XML::Feed dependency
5 years ago
v6.0.0: expand EntryStore, test more, cache harder This commit is something of a hairball, the result of evenings-and-weekends hacking building up a set of changes that got out of hand in parallel. If I had the energy to spare, I would break it apart into semantically-related changes, but I don't - and I suppose all this crap being rolled together is at least reflective of how the code was written. These changes are really half-finished, at best. Eventual goals: - App::WRT shouldn't directly touch the filesystem - App::WRT::EntryStore should model the entry archive completely - App::WRT::Renderer should say what to write to the publication directory - This one's a maybe: Filesystem interaction should pass through App::WRT::FileIO or something like it so that EntryStore and Renderer can be more usefully tested, with mocked writes (maybe) I do think this represents an inflection point in the long, silly life of this program: It includes a handful of new tests, and a number of the code changes were in turn easy to make because the test suite begins to model the code in a useful way. It's less and less necessary to run wrt against the p1k3.com archives to be sure that I haven't trashed something. Breaking changes to note: - Will no longer render HTML for nonexistent entries - Months and years which are flatfiles or contain an index are handled differently, albeit less brokenly - EntryStore includes index files in its overall list of entries (this seems to break less than I thought), which trickles out to bin/wrt-ls Overall changes herein: - App::WRT::Date - Move month_name() in here from App::WRT, add tests. - App::WRT::EntryStore - Hash file types for entries (directory or flatfile) - Use keys of file type hash for complete list of entries. - has_prop($entry, $property) - is_dir($entry), is_file($entry), is_extant($entry) - parent_of($entry) - has_index($entry) - Make EntryStore cache whether a file is a flatfile or a directory, as well as its existence, in a single hash. - Include index flatfiles in @source_files for use by has_index() - Various tests. - App::WRT::FileIO - Still duplicates a bunch of shit from Util, so that needs sorted. - App::WRT::Renderer - Convert to a proper class. - Add experimental FileIO class to use in Renderer (imperfect, tricky, still thinking about this). The idea is to separate out the concerns of reading and writing the filesystem. - App::WRT - Refactor display() and improve tests - Use "@entries" instead of "@options" for clarity - Handle entry names that might evaluate as false - Test running display() without any params - Rename expand_option() -> expand_alias(), refactor - Use EntryStore::has_prop() to detect wrt-noexpand.prop - year(), month(), entry() partially rewritten to use EntryStore - year() should handle months which are a flatfile - Refactor icon_markup() to use is_file() / is_dir() / is_extant(), add tests. - Add subtitle to feeds - bin/wrt-ls is now a "modulino" with tests - bin/display errors on non-existent entries - Build.PL - Remove bogus XML::Feed dependency
5 years ago
v6.0.0: expand EntryStore, test more, cache harder This commit is something of a hairball, the result of evenings-and-weekends hacking building up a set of changes that got out of hand in parallel. If I had the energy to spare, I would break it apart into semantically-related changes, but I don't - and I suppose all this crap being rolled together is at least reflective of how the code was written. These changes are really half-finished, at best. Eventual goals: - App::WRT shouldn't directly touch the filesystem - App::WRT::EntryStore should model the entry archive completely - App::WRT::Renderer should say what to write to the publication directory - This one's a maybe: Filesystem interaction should pass through App::WRT::FileIO or something like it so that EntryStore and Renderer can be more usefully tested, with mocked writes (maybe) I do think this represents an inflection point in the long, silly life of this program: It includes a handful of new tests, and a number of the code changes were in turn easy to make because the test suite begins to model the code in a useful way. It's less and less necessary to run wrt against the p1k3.com archives to be sure that I haven't trashed something. Breaking changes to note: - Will no longer render HTML for nonexistent entries - Months and years which are flatfiles or contain an index are handled differently, albeit less brokenly - EntryStore includes index files in its overall list of entries (this seems to break less than I thought), which trickles out to bin/wrt-ls Overall changes herein: - App::WRT::Date - Move month_name() in here from App::WRT, add tests. - App::WRT::EntryStore - Hash file types for entries (directory or flatfile) - Use keys of file type hash for complete list of entries. - has_prop($entry, $property) - is_dir($entry), is_file($entry), is_extant($entry) - parent_of($entry) - has_index($entry) - Make EntryStore cache whether a file is a flatfile or a directory, as well as its existence, in a single hash. - Include index flatfiles in @source_files for use by has_index() - Various tests. - App::WRT::FileIO - Still duplicates a bunch of shit from Util, so that needs sorted. - App::WRT::Renderer - Convert to a proper class. - Add experimental FileIO class to use in Renderer (imperfect, tricky, still thinking about this). The idea is to separate out the concerns of reading and writing the filesystem. - App::WRT - Refactor display() and improve tests - Use "@entries" instead of "@options" for clarity - Handle entry names that might evaluate as false - Test running display() without any params - Rename expand_option() -> expand_alias(), refactor - Use EntryStore::has_prop() to detect wrt-noexpand.prop - year(), month(), entry() partially rewritten to use EntryStore - year() should handle months which are a flatfile - Refactor icon_markup() to use is_file() / is_dir() / is_extant(), add tests. - Add subtitle to feeds - bin/wrt-ls is now a "modulino" with tests - bin/display errors on non-existent entries - Build.PL - Remove bogus XML::Feed dependency
5 years ago
v6.0.0: expand EntryStore, test more, cache harder This commit is something of a hairball, the result of evenings-and-weekends hacking building up a set of changes that got out of hand in parallel. If I had the energy to spare, I would break it apart into semantically-related changes, but I don't - and I suppose all this crap being rolled together is at least reflective of how the code was written. These changes are really half-finished, at best. Eventual goals: - App::WRT shouldn't directly touch the filesystem - App::WRT::EntryStore should model the entry archive completely - App::WRT::Renderer should say what to write to the publication directory - This one's a maybe: Filesystem interaction should pass through App::WRT::FileIO or something like it so that EntryStore and Renderer can be more usefully tested, with mocked writes (maybe) I do think this represents an inflection point in the long, silly life of this program: It includes a handful of new tests, and a number of the code changes were in turn easy to make because the test suite begins to model the code in a useful way. It's less and less necessary to run wrt against the p1k3.com archives to be sure that I haven't trashed something. Breaking changes to note: - Will no longer render HTML for nonexistent entries - Months and years which are flatfiles or contain an index are handled differently, albeit less brokenly - EntryStore includes index files in its overall list of entries (this seems to break less than I thought), which trickles out to bin/wrt-ls Overall changes herein: - App::WRT::Date - Move month_name() in here from App::WRT, add tests. - App::WRT::EntryStore - Hash file types for entries (directory or flatfile) - Use keys of file type hash for complete list of entries. - has_prop($entry, $property) - is_dir($entry), is_file($entry), is_extant($entry) - parent_of($entry) - has_index($entry) - Make EntryStore cache whether a file is a flatfile or a directory, as well as its existence, in a single hash. - Include index flatfiles in @source_files for use by has_index() - Various tests. - App::WRT::FileIO - Still duplicates a bunch of shit from Util, so that needs sorted. - App::WRT::Renderer - Convert to a proper class. - Add experimental FileIO class to use in Renderer (imperfect, tricky, still thinking about this). The idea is to separate out the concerns of reading and writing the filesystem. - App::WRT - Refactor display() and improve tests - Use "@entries" instead of "@options" for clarity - Handle entry names that might evaluate as false - Test running display() without any params - Rename expand_option() -> expand_alias(), refactor - Use EntryStore::has_prop() to detect wrt-noexpand.prop - year(), month(), entry() partially rewritten to use EntryStore - year() should handle months which are a flatfile - Refactor icon_markup() to use is_file() / is_dir() / is_extant(), add tests. - Add subtitle to feeds - bin/wrt-ls is now a "modulino" with tests - bin/display errors on non-existent entries - Build.PL - Remove bogus XML::Feed dependency
5 years ago
7 years ago
  1. =pod
  2. =head1 NAME
  3. App::WRT - WRiting Tool, a static site/blog generator and related utilities
  4. =for HTML <a href="https://travis-ci.org/brennen/wrt"><img src="https://travis-ci.org/brennen/wrt.svg?branch=master"></a>
  5. =head1 SYNOPSIS
  6. Using the commandline tools:
  7. $ mkdir project
  8. $ cd project
  9. $ wrt init # set up some defaults
  10. $ wrt config # dump configuration values
  11. $ wrt ls # list entries
  12. $ wrt display new # print HTML for new entries to stdout
  13. $ wrt render-all # publish HTML to project/public/
  14. Using App::WRT in library form:
  15. #!/usr/bin/env perl
  16. use App::WRT;
  17. my $w = App::WRT->new(
  18. entry_dir => 'archives',
  19. url_root => '/',
  20. # etc.
  21. );
  22. print $w->display(@ARGV);
  23. =head1 INSTALLING
  24. It's possible but not likely this would run on a Perl as old as 5.10.0. In
  25. practice, I know that it works under 5.26.2. It should be fine on any
  26. reasonably modern Linux distribution, and may work on MacOS or a BSD of your
  27. choosing. It's possible that it would run under the Windows Subsystem for
  28. Linux, but it would definitely fail under vanilla Windows; it currently makes
  29. too many assumptions about things like directory path separators and filesystem
  30. semantics.
  31. (Although I would like the code to be more robust across platforms, this is not
  32. a problem I feel much urgency about solving at the moment, since I'm pretty
  33. sure I am the only user of this software. Patches would certainly be welcome.)
  34. To install the latest development version from the main repo:
  35. $ git clone https://code.p1k3.com/gitea/brennen/wrt.git
  36. $ cd wrt
  37. $ perl Build.PL
  38. $ ./Build installdeps
  39. $ ./Build test
  40. $ ./Build install
  41. To install the latest version released on CPAN:
  42. $ cpanm App::WRT
  43. Or:
  44. $ cpan -i App::WRT
  45. You will likely need to use C<sudo> or C<su> to get a systemwide install.
  46. =head1 DESCRIPTION
  47. This started life somewhere around 2001 as C<display.pl>, a CGI script to
  48. concatenate fragments of handwritten HTML by date. It has since accumulated
  49. several of the usual weblog features (lightweight markup, feed generation,
  50. embedded Perl, poetry tools, image galleries, and ill-advised dependencies),
  51. but the basic idea hasn't changed that much.
  52. The C<wrt> utility now generates static HTML files, instead of expecting to
  53. run as a CGI script. This is a better idea, for the most part.
  54. By default, entries are stored in a simple directory tree under C<entry_dir>.
  55. Like:
  56. archives/2001/1/1
  57. archives/2001/1/2/index
  58. archives/2001/1/2/sub_entry
  59. Which will publish files like so:
  60. public/index.html
  61. public/all/index.html
  62. public/2001/index.html
  63. public/2001/1/index.html
  64. public/2001/1/1/index.html
  65. public/2001/1/2/index.html
  66. public/2001/1/2/sub_entry/index.html
  67. Contents will be generated for each year and for the entire collection of dated
  68. entries. Month indices will consist of all entries for that month. A
  69. top-level index file will consist of the most recent month's entries.
  70. It's possible (although not as flexible as it ought to be) to redefine the
  71. directory layout. (See C<%default{entry_map}> below.)
  72. An entry may be either a plain UTF-8 text file, or a directory containing
  73. several such files. If it's a directory, a file named "index" will be treated
  74. as the text of the entry, and all other lower-case filenames without extensions
  75. will be treated as sub-entries or documents within that entry, and displayed
  76. accordingly. Links to certain other filetypes will be displayed as well.
  77. Directories may be nested to an arbitrary depth, although it's probably not a
  78. good idea to go very deep with the current display logic.
  79. A PNG or JPEG file with a name like
  80. 2001/1/1.icon.png
  81. 2001/1/1/index.icon.png
  82. 2001/1/1/whatever.icon.png
  83. 2001/1/1/whatever/index.icon.png
  84. will be treated as an icon for the corresponding entry file.
  85. =head2 MARKUP
  86. Entries may consist of hand-written HTML (to be passed along without further
  87. interpretation), a supported form of lightweight markup, or some combination
  88. thereof. Actually, an entry may consist of any darn thing you please, as long
  89. as Perl will agree that it is text, but presumably you're going to be feeding
  90. this to a browser.
  91. Header tags (<h1>, <h2>, etc.) will be used to display titles in feeds and
  92. other places.
  93. Other special markup is indicated by a variety of HTML-like container tags.
  94. B<Embedded Perl> - evaluated and replaced by whatever value you return
  95. (evaluated in a scalar context):
  96. <perl>my $dog = "Ralph."; return $dog;</perl>
  97. This code is evaluated before any other processing is done, so you can return
  98. any other markup understood by the script and have it handled appropriately.
  99. B<Interpolated variables> - actually keys to the hash underlying the App::WRT
  100. object, for the moment:
  101. <perl>$self->{title} = "About Ralph, My Dog"; return '';</perl>
  102. <p>The title is <em>${title}</em>.</p>
  103. This is likely to change at some point, so don't build anything too elaborate
  104. on it.
  105. Embedded code and variables are intended only for use in the F<template> file,
  106. where it's handy to drop in titles or conditionalize aspects of a layout. You
  107. want to be careful with this sort of thing - it's useful in small doses, but
  108. it's also a maintainability nightmare waiting to happen.
  109. B<Includes> - replaced by the contents of the enclosed file path, from the
  110. root of the current wrt project:
  111. <include>path/to/file</include>
  112. This is a bit constraining, since it doesn't currently allow for files outside
  113. of the current project, but is useful for including HTML generated by an
  114. external script in a page.
  115. B<Several forms of lightweight markup>:
  116. <markdown>John Gruber's Markdown, by way of
  117. Text::Markdown::Discount</markdown>
  118. <textile>Dean Allen's Textile, via Brad Choate's
  119. Text::Textile.</textile>
  120. <freeverse>An easy way to
  121. get properly broken lines
  122. plus -- em dashes --
  123. for poetry and such.</freeverse>
  124. B<And a couple of shortcuts>:
  125. <image>filename.ext
  126. alt text, if any</image>
  127. <list>
  128. one list item
  129. another list item
  130. </list>
  131. As it stands, freeverse, image, and list are not particularly robust.
  132. =head2 TEMPLATES
  133. A single template, specified by the C<template_dir> and C<template> config
  134. values, is used to render all pages. See F<example/templates/basic> for an
  135. example, or run C<wrt init> in an empty directory and look at
  136. F<templates/default>.
  137. Here's a short example:
  138. <!DOCTYPE html>
  139. <html>
  140. <head>
  141. <meta charset="UTF-8">
  142. <title>${title_prefix} - ${title}</title>
  143. </head>
  144. <body>
  145. ${content}
  146. </body>
  147. </html>
  148. Within templates, C<${foo}> will be replaced with the corresponding
  149. configuration value. C<${content}> will always be set to the content of the
  150. current entry.
  151. =head2 CONFIGURATION
  152. Configuration is read from a F<wrt.json> in the directory where the C<wrt>
  153. utility is invoked, or can (usually) be specified with the C<--config> option.
  154. See F<example/wrt.json> for a sample configuration.
  155. Under the hood, configuration is done by combining a hash called C<%default>
  156. with values pulled out of the JSON file. Most defaults can be overwritten
  157. from the config file, but changing some would require writing Perl, since
  158. they contain things like subroutine references.
  159. =over
  160. =item %default
  161. Here's a verbatim copy of C<%default>, with some commentary about values.
  162. my %default = (
  163. root_dir => '.', # dir for wrt repository
  164. entry_dir => 'archives', # dir for entry files
  165. publish_dir => 'public', # dir to publish site to
  166. url_root => "/", # root URL for building links
  167. image_url_root => '', # same for images
  168. template_dir => 'templates', # dir for template files
  169. template => 'default', # template to use
  170. title => '', # current title (used in template)
  171. title_prefix => '', # a string to slap in front of titles
  172. stylesheet_url => undef, # path to a CSS file (used in template)
  173. favicon_url => undef, # path to a favicon (used in template)
  174. feed_alias => 'feed', # what entry path should correspond to feed?
  175. feed_length => 30, # how many entries should there be in the feed?
  176. author => undef, # author name (used in template, feed)
  177. description => undef, # site description (used in template)
  178. content => undef, # place to stash content for templates
  179. embedded_perl => 1, # evaluate embedded <perl> tags?
  180. default_entry => 'new', # what to display if no entry specified
  181. cache_includes => 0, # should included files be cached in memory?
  182. # A license string for site content:
  183. license => 'public domain',
  184. # A string value to replace all pages with (useful for occasional
  185. # situations where every page of a site should serve some other
  186. # content in-place, like Net Neutrality protest blackouts):
  187. overlay => undef,
  188. # What gets considered an entry _path_:
  189. entrypath_expr => qr/^ ([a-z0-9_\/-]+) $/x,
  190. # What gets considered a subentry file (slightly misleading
  191. # terminology here):
  192. subentry_expr => qr/^[0-9a-z_-]+(\.(tgz|zip|tar[.]gz|gz|txt))?$/,
  193. # We'll show links for these, but not display them inline:
  194. binfile_expr => qr/[.](tgz|zip|tar[.]gz|gz|txt|pdf)$/,
  195. );
  196. =item $default{entry_map}
  197. A hashref which will dispatch entries matching various regexen to the
  198. appropriate output methods. The default looks something like this:
  199. nnnn/[nn/nn/]doc_name - a document within a day.
  200. nnnn/nn/nn - a specific day.
  201. nnnn/nn - a month.
  202. nnnn - a year.
  203. doc_name - a document in the root directory.
  204. You can re-map things to an arbitrary archive layout.
  205. Since the entry map is a hash, and handle() simply loops over its keys, there
  206. is no guaranteed precedence of patterns. Be extremely careful that no entry
  207. will match more than one pattern, or you will wind up with unexpected behavior.
  208. A good way to ensure that this does not happen is to use patterns like:
  209. qr(
  210. ^ # start of string
  211. [0-9/]{4}/ # year
  212. [0-9]{1,2}/ # month
  213. [0-9]{1,2] # day
  214. $ # end of string
  215. )x
  216. ...always marking the start and end of the string explicitly.
  217. This may eventually be rewritten to use an array so that the order can be
  218. explicitly specified.
  219. =item $default{entry_descriptions}
  220. A hashref which contains a map of entry titles to entry descriptions.
  221. =item $default{title_cache}
  222. A hashref which contains a cache of entry titles, populated by the renderer.
  223. =back
  224. =head2 METHODS AND INTERNALS
  225. For no bigger than this thing is, the internals are convoluted. (This is
  226. because it's spaghetti code originally written in a now-archaic language by a
  227. teenager who didn't know how to program.)
  228. =over
  229. =item new_from_file($config_file)
  230. Takes a filename to pull JSON config data out of, and returns a new App::WRT
  231. instance with the parameters set in that file.
  232. =item new(%params)
  233. Get a new WRT object with the specified parameters set.
  234. =item display($entry1, $entry2, ...)
  235. Return a string containing the given entries, which are in the form of
  236. date/entry strings. If no parameters are given, default to default_entry().
  237. display() expands aliases ("new" and "all", for example) as necessary, collects
  238. output from handle($entry), and wraps the whole thing in a template file.
  239. If C<overlay> is set, will return the value of overlay regardless of options.
  240. (This is useful for hackily replacing every page in a site with a single blob
  241. of HTML, for example if you're participating in some sort of blackout or
  242. something.)
  243. =item handle($entry)
  244. Return the text of an individual entry.
  245. =item expand_alias($option)
  246. Expands/converts 'all', 'new', and 'fulltext' to appropriate values.
  247. Removes trailing slashes.
  248. =item link_bar(@extra_links)
  249. Returns a little context-sensitive navigation bar.
  250. =item year($year)
  251. List out the updates for a year.
  252. =item month($month)
  253. Prints the entries in a given month (nnnn/nn).
  254. =item entry_stamped($entry, $level)
  255. Wraps entry() + a datestamp in entry_markup().
  256. =item entry_topic_list($entry)
  257. Get a list of topics (by tag-* files) for the entry. This hardcodes part of a
  258. p1k3-specific thing which should be moved into wrt entirely.
  259. =item entry($entry)
  260. Returns the contents of a given entry. Calls dir_list and icon_markup.
  261. Recursively calls itself.
  262. =item get_sub_entries($entry_loc)
  263. Returns "sub entries" based on the C<subentry_expr> regexp.
  264. =item list_contents($entry, @entries)
  265. Returns links (maybe with icons) for a set of sub-entries within an entry.
  266. =item icon_markup($entry, $alt)
  267. Check if an icon exists for a given entry if so, return markup to include it.
  268. Icons are PNG or JPEG image files following a specific naming convention:
  269. index.icon.[png|jp(e)g] for directories
  270. [filename].icon.[png|jp(e)g] for flat text files
  271. Calls image_size, uses filename to determine type.
  272. =item datestamp($entry)
  273. Returns a nice html datestamp / breadcrumbs for a given entry.
  274. =item fragment_slurp($file)
  275. Read a text fragment, call line_parse() and eval_perl() to take care of
  276. lightweight markup sections and interpret embedded code, and then return it as
  277. a string. Takes one parameter, the name of the file.
  278. =item root_locations($file)
  279. Given a file/entry, return the appropriate concatenations with entry_dir and
  280. url_root.
  281. =item feed_print(@entries)
  282. Return an Atom feed for the given list of entries.
  283. Requires XML::Atom::SimpleFeed.
  284. XML::Atom::SimpleFeed will give bogus results with input that's just a string
  285. of octets (I think) if it contains characters outside of US-ASCII. In order to
  286. spit out clean UTF-8 output, we need to use Encode::decode() to flag entry
  287. content as UTF-8 / represent it internally as a string of characters. There's
  288. a whole lot I don't really understand about how this is handled in Perl, and it
  289. may be a locus of bugs elsewhere in wrt, but for now I'm just dealing with it
  290. here.
  291. Some references on that:
  292. =over
  293. =item * L<https://github.com/ap/XML-Atom-SimpleFeed/issues/2>
  294. =item * L<https://rt.cpan.org/Public/Bug/Display.html?id=19722>
  295. =item * L<https://cpanratings.perl.org/dist/XML-Atom-SimpleFeed>
  296. =item * L<perlunitut>
  297. =back
  298. =back
  299. =head1 SEE ALSO
  300. walawiki.org, Blosxom, rassmalog, Text::Textile, XML::Atom::SimpleFeed,
  301. Image::Size, CGI::Fast, and about a gazillion static site generators.
  302. =head1 AUTHOR
  303. Copyright 2001-2017 Brennen Bearnes
  304. =head1 LICENSE
  305. wrt is free software; you can redistribute it and/or modify
  306. it under the terms of the GNU General Public License as published by
  307. the Free Software Foundation; either version 2 of the License, or
  308. (at your option) any later version.
  309. This program is distributed in the hope that it will be useful,
  310. but WITHOUT ANY WARRANTY; without even the implied warranty of
  311. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  312. GNU General Public License for more details.
  313. You should have received a copy of the GNU General Public License
  314. along with this program. If not, see <http://www.gnu.org/licenses/>.