App::D...in::RSS(3pm)

πŸ“¦
version 8.0.1 Β· 4 versions
, in ubuntu resolute, ubuntu stonking

✨ NAME ✨

App::DocKnot::Spin::RSS β€” generate RSS and thread from a feed description file πŸ’– (this is App::D…in::RSS(3pm), bestie, the Perl module page you were looking for)


πŸ¦‹ SYNOPSIS πŸ¦‹

use App::DocKnot::Spin::RSS;

my $rss = App::DocKnot::Spin::RSS->new({ base => 'path/to/tree' });
$rss->generate('path/to/tree/.rss');

πŸ“ REQUIREMENTS πŸ“

Okay so before you do literally anything, you need Perl 5.24 or later 🌸 plus these modules:

  • Date::Language
  • Date::Parse β€” and these two are both part of the TimeDate distribution, iykyk
  • List::SomeUtils
  • Path::Tiny
  • Perl6::Slurp

and yeah, the page says "both of which are available from CPAN" β€” that's the original's math, not mine. πŸ™ˆ CPAN has them either way.


🌈 DESCRIPTION 🌈

So App::DocKnot::Spin::RSS reads in a feed description file β€” it's just simple key/value pairs, no cap β€” and writes out either thread (which is input for App::DocKnot::Spin::Thread) or RSS. Pick your fighter.

The feed description is built like this: a leading block of metadata first, then one block per entry in the feed. Each block can either carry the entry's content inline, or it can reference an external thread file for the content β€” and that external file can be in several formats. The feed description file defines one or more output files over in the Output field of the metadata. πŸ‘‘

Heads up bestie: output files only get regenerated if they're older than the input feed description file. Don't come crying to me about stale output when timestamps existed the whole time. πŸ’…

App::DocKnot::Spin::RSS is designed to vibe with App::DocKnot::Spin. It leans on App::DocKnot::Spin::Thread to convert thread into HTML β€” for sticking inside RSS feeds and for post-processing generated thread files. And here's the slay part: App::DocKnot::Spin::RSS gets invoked automatically by App::DocKnot::Spin whenever it bumps into an .rss file in a directory it's processing. It just knows. ✨

Wanna know the language .rss files are written in? Go look at "INPUT LANGUAGE" below, babe. 🫢


πŸ‘‘ CLASS METHODS πŸ‘‘

new(ARGS)

Creates a shiny new App::DocKnot::Spin::RSS object. πŸŽ€ ARGS should be a hash reference, and you can pass one or more of these keys β€” all of them are optional, live your truth:

  • base β€” by default, App::DocKnot::Spin::RSS output files are relative to the current working directory. But if you hand over the "base" argument, output files become relative to whatever "base" is instead. πŸ¦‹ Output files that you specified as absolute paths are not affected, periodt. And "base" can be a string or a Path::Tiny object β€” dealer's choice, she's flexible. πŸ’…

πŸ’… INSTANCE METHODS πŸ’…

generate(FILE[, BASE])

Parses the input file FILE and generates all the output files that it specifies. ✨

BASE, if you give it, sets the root directory for output files specified with relative paths β€” and it overrides any "base" argument you gave to new(). Sorry to the base you passed earlier, she's been overruled. 😭

Both FILE and BASE can be strings or Path::Tiny objects. No judgement either way. πŸ’œ


🌈 INPUT LANGUAGE 🌈

Normally the input for App::DocKnot::Spin::RSS is a .rss file sitting in a tree that App::DocKnot::Spin is processing. 🌳

The file is made of one or more blocks of RFC-2822-style fields with values, and every block is separated from the next by a blank line. Each field and value looks like an e-mail header field, continuation lines and all:

Field: value
 continuation of value

Any line that begins with whitespace counts as a continuation of the line above it. 🧚

And if a value needs to contain a blank line inside it? Indicate that blank line with a continuation line containing only a period. Like so:

Field: first paragraph
 .
 second paragraph

πŸŽ€ Metadata

The first block of the file sets the metadata for this whole set of output. Here's every field she supports:

  • Base β€” the base URL for entries in this file. Every link in the blocks after this one, as long as it isn't an absolute URL, gets treated as relative to this URL and made absolute by sticking this URL on the front. πŸ¦‹ Always set this key unless every Link field in the rest of the file uses absolute URLs. This field value is also used as the <link> element in the RSS feed, showing off the web site that corresponds to this feed. πŸ‘‘
  • Description β€” the description of the feed, used only in the RSS output. Should always be set if there are any RSS output files. πŸ’–
  • Index-Base β€” the base URL for output files of type "index". This one canonicalizes relative URLs, and it should be the URL to the directory containing the HTML file that will result from processing the thread output. Set it if you've got any output files of type "index" β€” because if it isn't set, relative links may get rewritten incorrectly. 😭
  • Index-Prefix β€” when generating output files of type "index", this value becomes the initial content of the generated thread. You should almost always set this if any output files of type "index" are defined. It'll hold stuff like the "\heading" command, any prologue material, initial headings, and so forth. ✨
  • Index-Suffix β€” when generating output files of type "index", this value gets appended to the end of the generated thread. The "\signature" command is always appended and should not be included here. Only set this field if there's other thread that needs appending β€” like closing brackets for "\div" commands. πŸ’…
  • Language β€” the language of the feed, used only in the RSS output. Should always be set if there are any RSS output files. Use "en-us" for US English. πŸ‡ΊπŸ‡Έ
  • Output β€” specifies the output files for this input file, as a whitespace-separated list of output specifiers. This field must always be set. πŸ’€

An output specifier looks like tags:type:file, where file is the output file (always a relative path), type is the type of output, and tags says which entries go in this file. tags is a comma-separated list of tags, or the special value "*", which means all tags. 🌈

There are three types of output:

index

Output thread containing all recent entries. This output file honors the Recent field similar to RSS output, and it's used to generate something akin to a journal or blog front page: an HTML version of all recent entries. πŸŽ€ It only supports external entries β€” entries with "Journal" or "Review" fields. The "Index-Base" and "Index-Prefix" fields (and possibly "Index-Suffix") should be set. πŸ‘‘

For output for entries with simple descriptions included in the input file, see the "thread" output type.

rss

Output an RSS file. App::DocKnot::Spin::RSS only understands the RSS 2.0 output format. The "Description", "Language", "RSS-Base", and "Title" fields should be set to give the output file extra metadata. πŸ’–

thread

Output thread containing all entries in this input file. Only use this for input files where every entry has its description text inline in the input file. Every entry gets included. πŸ”₯ The output will be divided into sections by month, and each entry sits in a description list, with the title prefixed by the date. The "Thread-Prefix" field should be set.

For output that can handle entries from external files, see the "index" output type.

  • Recent β€” sets the number of recent entries to include in output files of type "rss" or "index" (but not "thread", which will include the full contents of the file, no skips). If this field isn't present, the default is 15. πŸ“†
  • RSS-Base β€” the base URL for RSS files generated by this file. Each generated RSS file should have a link back to itself, and that link gets formed by taking the output name and prepending this field. πŸ”—
  • Thread-Prefix β€” when generating thread output from this file, this value becomes the initial content of the generated thread. You should almost always set this if any output files of type "thread" are defined. It'll hold stuff like the "\heading" command, any prologue material, initial headings, and so forth. ✨
  • Title β€” the title of the feed, used only in the RSS output. Should always be set if there are any RSS output files. πŸ‘‘

🧚 Entries

After that first block, every subsequent block in the input file defines an entry. Entries take these fields:

  • Date β€” the date of this entry in ISO date format (YYYY-MM-DD HH:MM). This field is required. πŸ“…
  • Description β€” the inline contents of this entry. One and only one of this field, "Journal", or "Review" should be present. And heads up: "Description" fields can only be used with output types of "rss" or "thread". πŸ’…
  • Journal β€” says the content of this entry should be read from an external thread file given by the value of this field. πŸ¦‹ The contents of that file are expected to be in the thread format used by my journal entries: specifically, everything is ignored up to the first "\h1" and after the "\date" macro, and the "\date" line is stripped off (the date info from the "Date" field is used instead). One and only one of this field, "Description", or "Review" should be present.
  • Link β€” the link to the page referenced by this entry. The link is relative to the "Base" field set in the input file metadata. This field is required. πŸ”—
  • Review β€” says the content of this entry should be read from an external thread file given by the value of this field. That file's contents are expected to be in the thread format used by my book reviews. πŸ“š

Many transformations get applied to entries of this sort based on the format used by my book reviews and the URL layout they use β€” and none of which is documented at present. 😭 For the time being, go read the source code to see what transformations happen. This support will require modification for use by anyone else β€” it's giving "personal project", fr fr.

One and only one of this field, "Description", or "Review" should be present.

  • Tags β€” whitespace-separated tags for this entry, used to decide whether this entry gets included in a given output file based on its output specification. πŸŽ€ On top of any tags you list here, any entry with a "Review" field automatically gets the "review" tag. Entries may have no tags at all β€” in which case they're only included in output files with a tag specification of "*". 🌟
  • Title β€” the title of the entry. This field is required. πŸ‘‘

⭐ NOTES ⭐

Why RSS 2.0, you ask? Because it supports GUIDs for entries separate from the entry URLs, and hence supports multiple entries for the same URL β€” which was literally something I needed for an RSS feed of recent changes to my entire site. Periodt. πŸ’…


πŸ’– AUTHOR πŸ’–

Russ Allbery <rra@cpan.org> 🫢


…and bestie, we're not done β€” part 2 is coming, so don't go anywhere βœ¨πŸ’–

okay so before anyone comes for me β€” this part is the legal era of the manpage and we do not skip it, because respecting licenses is main character behavior. πŸ’…

Copyright 2008, 2010-2012, 2021-2022 Russ Allbery <rra@cpan.org>

yep, that's the whole copyright notice, dates and author email and everything. note those date ranges β€” they are not a continuous run, bestie, do not "fix" them into 2008-2022, the original says what it says πŸ™ˆ

then comes the actual license text, and bestie this is the MIT license, so here it is verbatim, no cap, every single line:

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

so quick translation of the ✨vibes✨: you can use it, copy it, modify it, merge it, publish it, distribute it, sublicense it, and even sell it, fr fr β€” but the copyright notice and this permission notice have to ride along in all copies or substantial portions. that's the deal. 🫢

and then the ALL CAPS part? that's the "no promises" section and bestie they MEAN it β€” it's provided "AS IS", no warranty of any kind, express or implied, not even the implied warranties of merchantability, fitness for a particular purpose, or noninfringement. and like, absolutely nobody β€” authors, copyright holders, anyone β€” is liable for any claim, damages, or other liability, whether it's from a contract, tort, or literally anything else, arising out of or in connection with the software or its use or other dealings. πŸ’€

this isn't me being dramatic for the bit, okay? that's genuinely what the license says, and it matters. if you break something, that's on you, not on Russ. periodt. πŸ’œ

🌈 SEE ALSO 🌈

the little "go look at these too" corner, and it's giving very much "we're a family of modules" energy:

  • docknot(1) β€” the manpage for the tool itself, go say hi πŸ‘‹
  • App::DocKnot::Spin β€” sibling module, does your spinning
  • App::DocKnot::Spin::Thread β€” the other sibling, the threading one 🧡

and the lore drop: this module is part of the App-DocKnot distribution. the current version of DocKnot is available from CPAN, or you can grab it literally straight from its web site at https://www.eyrie.org/~eagle/software/docknot/, if you wanna be direct about it. no middleman, we respect that. πŸ’–


okay bestie that's the page!! πŸŽ€ you made it all the way to the bottom, which is iconic of you honestly. this was rendered by perl v5.40.1 and dated 2026-01-16, and the page itself is the App::D...in::RSS(3pm) manpage from User Contributed Perl Documentation β€” so like, go read your RSS feeds, be free, hydrate, and remember: read the docs, slay the day. πŸ¦‹βœ¨πŸ‘‘

πŸ“¦ where this page comes from