<commit_before>.\"	$Id$
.\"
.\" Copyright (c) 2013--2017, 2019 <NAME> <<EMAIL>>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate$
.Dt SBLG 1
.Os
.Sh NAME
.Nm sblg
.Nd static blog utility
.Sh SYNOPSIS
.Nm sblg
.Op Fl acjlLrV
.Op Fl C Ar file
.Op Fl o Ar file
.Op Fl s Ar sort
.Op Fl t Ar template
.Ar
.Sh DESCRIPTION
The
.Nm
utility knits together XML articles and templates in a number of ways.
.Bl -bullet
.It
Standalone mode
.Pq Fl c
links single articles with a template with an article stub, which is
filled in with the article.
For example,
.Qq sblg -c foo.xml bar.xml
creates
.Pa foo.html
and
.Pa bar.html
from a template populated by the
.Pa foo.xml
and
.Pa bar.xml
article contents, respectively.
.It
Blog mode (default) links multiple articles with a template consisting
of articles and navigation stubs.
For example,
.Qq sblg -o foo.html bar.html baz.html
links
.Pa bar.html
and
.Pa baz.html
into
.Pa foo.html
from a template.
.It
Atom mode
.Pq Fl a
links multiple articles with an Atom feed template.
.It
JSON mode
.Pq Fl j
formats all articles as a JSON feed.
.It
Combined mode
.Pq Fl C
links multiple articles in standalone style, i.e., multiple navigation
stubs, a single article stub.
For example,
.Qq sblg -o foo.html -C bar.html baz.html bar.html
will show only
.Pa bar.html
in the article list of
.Pa foo.html ,
but both
.Pa bar.html
and
.Pa baz.html
in its navigation.
You can also use
.Fl L
to run the process for each input file (much faster).
.It
Tag-listing mode with
.Fl l .
.El
.Pp
By default,
.Nm
operates in blog mode as if
.Qq sblg -o blog.html -t blog-template.xml ...
were specified.
Its arguments are as follows:
.Bl -tag -width Ds
.It Fl a
Creates an Atom feed from its input files.
.It Fl c
Create standalone articles instead of merging articles together.
.It Fl l
Instead of emitting any output files, simply process the input and
report a table of tags.
This table consists of the input file name, a tab, then the tag.
.Pq Also known as article-major order.
The tag has escaped white-space printed as unescaped.
You can also use
.Fl r
to have tag-major order and
.Fl j
for JSON output.
Specify
.Fl l
twice to show matches (tags for article-major, articles for tag-major)
all on one tab-separated line, instead of one per line.
.It Fl r
Print the
.Fl l
tag listing in
.Dq tag-major
order wherein the first column is the tag and the second column is the
article.
If the
.Fl j
flag is specified, this is JSON formatted.
.It Fl j
JSON output mode.
This behaves as in blog mode, but outputs JSON instead of XML.
If
.Fl l
is specified, the tag listing will be displayed in JSON instead.
See
.Sx JSON Schema
for details.
.It Fl C Ar file
Like
.Fl c ,
but creating a blog with a single
.Li <article data-sblg-article="1">
for the
.Ar file
while using the remaining arguments are other files used in
.Li <nav data-sblg-nav="1"> .
.It Fl L
Like
.Fl C ,
but acting on all input files, translating the input to output files
such as in
.Fl c
without
.Fl o .
If there are multiple articles in an output file, the output is
recreated for each (so only the last will remain).
So running with
.Dq article0.xml article1.xml
will produce
.Dq article0.html article1.html
as if
.Fl C
were seperately specified for both.
This avoids needing to parse all inputs for each input.
.It Fl o Ar file
Output file.
If unspecified, standalone articles have
.Li .html
appended to the input file name, unless the input file extension is
.Li .xml ,
in which case the
.Li .xml
is replaced by
.Li .html .
If multiple input files are specified,
.Fl o
is ignored.
If unspecified for the blog,
.Ar blog.html
is used by default.
If unspecified for the Atom feed or JSON,
.Ar atom.xml
or
.Ar blog.json ,
respectively,
is used by default.
Use
.Fl o Ar \-
for standard output.
.It Fl s Ar sort
Change how articles are sorted before being written into navigation or
article entries.
The default is
.Ar date ,
which sorts oldest-newest by date.
You can also specify
.Ar filename ,
which sorts in increasing A\(enZ case-sensitive order of the source
filename;
.Ar cmdline
for the command-line order;
.Ar ititle
for the case-insensitive document title; or
.Ar title
for the case-sensitive document title.
Each sort may be prefixed with
.Qq r
(e.g.,
.Ar rcmdline )
to reverse the sort.
.It Fl t Ar template
Template for all modes.
If unspecified, defaults to
.Ar article-template.xml
for
.Fl c ,
.Ar atom-template.xml
for
.Fl a ,
and
.Ar blog-template.xml
otherwise.
.It V
Emits the verion as
.Li sblg-xx.yy.zz
and exits.
.It Ar
Input files.
In standalone mode with
.Fl c ,
input XML files are merged with a template into an output file.
Otherwise, multiple input files are merged into a single blog.
.El
.Pp
All input must be well-formed XML.
(Element names and attributes are case-sensitive.)
HTML is assumed only with the default suffix re-write rule for
.Fl c
without
.Fl o .
Input articles may be XML fragments or full documents: only the
.Li <article data-sblg-article="1">
tree within the article is considered.
.Ss Article Input
Article input files consist of XML fragments or whole documents.
They usually consist of the following within the document:
.Bd -literal
<article data-sblg-article="1">
  <header>
    <h1>Article Name</h1>
    <address>Author Name</address>
    <time datetime="2013-06-29">29 June, 2013</time>
  </header>
  <aside>
    This is used as the feed <b>abstract</b>.
  </aside>
  <p>
    Some text in the <b>content</b>.
    <img src="foo.jpg" alt="An image for the feed" />
  </p>
</article>
.Ed
.Pp
When processed with
.Nm ,
all data outside of the
.Li <article data-sblg-article="1">
element is discarded.
Then the article is scanned for the following:
.Bl -bullet
.It
the article title (both as text data only and inclusive of markup) is
extracted from the first
.Li <hn>
.Pq header 1\(en4 ;
.It
the article publication date is extracted from the datetime attribute of
the first
.Li <time>
(which must be a date, YYYY-MM-DD, or time, YYYY-MM-DDTHH:MM:SSZ)
interpreted in UTC;
.It
the author (both as text data only and inclusive of markup) from the
first
.Li <address> ;
.It
the first
.Li <aside>
is used for the feed abstract; and
.It
the first
.Li <img>
is associated as the article's image.
.El
.Pp
If unspecified, the default article title text (and mark-up) is
.Qq Untitled article ,
the default author text (and mark-up) is the
.Qq Unknown author ,
the publication time is set to the document's file-system creation time,
the abstract is left empty, and the image is empty.
.Pp
All content is recorded in case the
.Li data-sblg-content
Boolean value is used in an Atom feed.
.Pp
There are a number of special attributes that are recognised in the
input file.
.Bl -tag -width Ds
.It Li data-sblg-aside=string
Sets the aside material as otherwise would be set from the first
.Li <aside>
element.
It overrides the previously set aside.
.It Li data-sblg-author=url
Sets the author as otherwise would be set from the first
.Li <address>
element.
It overrides the previously set author.
.It Li data-sblg-datetime=datetime
Overrides the first
.Li <time>
element.
This must be YYYY-MM-DD or YYYY-MM-DDTH:MM:SSZ.
It overrides the previously set date.
.It Li data-sblg-img=url
Overrides the first
.Li <img>
link to be the image associated with the article.
It overrides the previously set image.
.It Li data-sblg-lang=string
May only be set on the
.Li <article>
and specifies one or more space-separated languages for the document.
You can escape spaces with a backslash
.Pq Dq \e
if you have spaces in the tag name, e.g.,
.Dq foo\e bar .
These languages are removed in the
.Dq stripping
operations for the
.Sx Tag Symbols .
.It Li data-sblg-set-xxx=string
This allows arbitrary values to be attached to the article.
For example, specifying
.Li data-sblg-set-foo="bar"
sets the
.Li foo
keyword to
.Li bar .
If specified multiple times for the same key, only the last value is
used.
These may be retrieved with
.Li ${sblg-get}
or queried with
.Li ${sblg-has}
of the
.Sx Tag Symbols .
.It Li data-sblg-sort=first|last
May only be set on the
.Li <article>
element and overrides the article's position relative to other articles.
This can be either
.Li first
or
.Li last .
If multiple articles have the same sort override, they are ordered in
the natural way.
.It Li data-sblg-tags=string
This tag may be specified on any element within the article and consists
of space-separated tag names.
You can escape spaces with a backslash
.Pq Dq \e
if you have spaces in the tag name, e.g.,
.Dq foo\e bar .
These tags are extracted for navigation tag operation.
It may not contain any tabs.
.It Li data-sblg-title=string
Sets the title as otherwise would be set in a
.Li <hN>
element.
It overrides the previously set title.
.El
.Ss Standalone Template
The standalone template file must be a well-formed XML file where the
first
.Li <article data-sblg-article="1">
element is replaced by the article text.
All of this element's children are removed.
.Bd -literal
<body>
  <header>This consists of a single blog entry.</header>
  <article>This is kept.</article>
  <article data-sblg-article="1">This is removed.</article>
  <footer>Something.</footer>
</body>
.Ed
.Pp
Article templates may contain the following attributes:
.Bl -tag -width Ds
.It Li data-sblg-article=boolean
If set to true, the contents are replaced with the input article.
.It Li data-sblg-ign-once=boolean
If an
.Li <article data-sblg-article="1">
element contains this set to true, the element is not processed as an
article and the
.Li data-sblg-ign-once
attribute is removed.
.El
.Pp
See
.Sx Tag Symbols
for a list of symbols that will be replaced if found in attribute value
or textual contexts.
These may occur anywhere in the template document.
.Ss Blog Template
The blog template file must also be a well-formed XML file where each
.Li <article data-sblg-article="1">
element is replaced by ordered (by default, newest to oldest) article
contents.
If there aren't enough articles, the element is removed.
Furthermore,
.Li <nav data-sblg-nav="1">
elements are replaced by the same list of articles within an
unordered list.
.Pp
Usually, the
.Li <article>
tags are used for displaying full articles, while
.Li <nav>
tags are used for displaying navigation to articles, such as just their
titles, dates, and links.
.Bd -literal
<body>
  <header>This consists of two blog entries.</header>
  <nav data-sblg-nav="1" />
  <article data-sblg-article="1" />
  <article data-sblg-article="1" />
  <footer>Something.</footer>
</body>
.Ed
.Pp
Article templates may contain several attributes.
.Bl -tag -width Ds
.It Li data-sblg-article=boolean
If set to true, the contents are replaced with the input article.
.It Li data-sblg-articletag=string
If an
.Li <article data-sblg-article="1">
element contains this, limit displayed articles to those matching the
space-separated tags or
.Li ${sblg-get|xxx}
when in
.Fl L
or
.Fl C
mode.
.It Li data-sblg-ign-once=boolean
If an
.Li <article data-sblg-article="1">
element contains this set to true, the element is not processed as an
article and the
.Li data-sblg-ign-once
attribute is removed.
.It Li data-sblg-permlink=boolean
If an
.Li <article data-sblg-article="1">
element contains this set to true, a permanent link to the article's
input filename is emitted after the
.Li <article data-sblg-article="1">
within a 
.Li <div data-sblg-permlink="1">
element.
.El
.Pp
The navigation element may contain several attributes.
.Bl -tag -width Ds
.It Li data-sblg-navcontent=boolean
If true, reproduces the mark-up content of the
.Li <nav>
within an unordered list item for each article shown, replacing
.Sx Tag Symbols
for the current article.
If not true,
.Nm
populates an unordered list with article title text in a link and the
publication date.
.It Li data-sblg-navsort=sort
Overrides the global search order given with
.Fl s .
Uses the same names.
If the search name is not recognised, the attribute is silently ignored
and the global search order used.
.It Li data-sblg-navstart=number
How many articles will skip being displayed (so if you have tags, it
will only account for articles that would meet those tags) before
showing the first navigation entry.
Starts at one (a value of zero is the same as a value of one).
.It Li data-sblg-navsz=number
If the
.Li <nav>
element contains this attribute with a positive integer, it is used to
limit the number of navigation entries.
.It Li data-sblg-navtag=string
Only articles with matching tags are shown.
You can specify multiple space-separated tags, for instance,
.Li data-sblg-navtag="foo bar"
will search for foo or bar.
Tags to be matched against are extracted from the space-separated
.Li data-sblg-tags
element of each article's topmost
.Li <article>
element.
Escape spaces with a backslash
.Pq Dq \e
if you have spaces in the tag name, e.g.,
.Dq foo\e bar .
Use
.Li ${sblg-get|xxx}
or (for multi-word values)
.Li ${sblg-get-escaped|xxx}
when in
.Fl C
or
.Fl L
mode to use the current article's set data as part of a string, e.g.,
.Li location-${sblg-get|location} .
.It Li data-sblg-navxml=boolean
Like
.Li data-sblg-navcontent ,
but without the surrounding list elements.
The
.Li data-sblg-navxml
attribute does not print any additional
.Li <nav> ,
.Li <ul> ,
or
.Li <li>
HTML tags and can be used to generate custom XML files, such as sitemaps.
.El
.Ss Combined Template
This is identical to the
.Sx Blog Template
except that a single article is noted with
.Fl C ,
and this is the only article displayed in the article stub.
Furthermore, like in standalone mode,
.Sx Tag Symbols
may be used anywhere in the document template and refer to the current
article unless within a navigation element, in which case the symbol
resolves to the currently-printed article.
In the given example,
.Bd -literal
<body>
  <header>This consists of two blog entries.</header>
  <nav data-sblg-nav="1" />
  <article data-sblg-article="1" />
  <article data-sblg-article="1" />
  <footer>Something.</footer>
</body>
.Ed
.Pp
the navigation would be populated by all articles, but only the first
article stub would be filled in with the specified article.
The second would be removed.
.Pp
This follows the usual rules of
.Li data-sblg-articletag ,
so if the article you specify with
.Fl C
doesn't have the correct tag, it won't inline the article.
.Ss Atom Template
The Atom template file must be a well-formed XML file where each
.Li <entry>
element with a Boolean
.Li data-sblg-entry
attribute is replaced by ordered (newest to oldest) article information.
If there aren't enough articles, the element is removed.
The template may contain pre-existing entries.
.Pp
The following is a minimal template: anything less will not conform to
the Atom specification:
.Bd -literal
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <link href="http://example.org" />
  <title>A Title Here</title>
  <updated />
  <id />
  <entry data-sblg-entry="1" data-sblg-forall="1" />
</feed>
.Ed
.Pp
The recognised elements are as follows.
Un-recognised elements are printed verbatim.
.Bl -tag -width Ds
.It Li <entry data-sblg-entry="1">
Filled-in article entry.
If the attribute is not specified, the entry is retained verbatim.
Otherwise it is filled in with an article's information.
.It Li <id>
If this is empty, it is filled in with the URL in
.Li <link [rel="alternate"]> ,
which must exist.
Otherwise, the value is copied and used for subsequent feed entries.
.It Li <link [rel="alternate"]>
Unless an
.Li <id>
is provided, the
.Li href
attribute must be a full URL, e.g.,
.Li <link href="https://kristaps.bsd.lv/"> .
Otherwise, it may be a relative path.
This element
.Em must be first .
.It Li <updated>
This is filled in with the most recent article.
Its contents are discarded.
.El
.Pp
There are a number of special attributes that may be given to the above
elements.
.Bl -tag -width Ds
.It Li data-sblg-altlink=boolean
If an
.Li <entry data-sblg-entry="1">
element contains this set to true, the alternate
.Li <link>
is printed.
.It Li data-sblg-altlink-fmt=string
If both
.Li data-sblg-entry
and
.Li data-sblg-altlink
are true for an
.Li <entry> ,
the value is used as the link address.
Accepts
.Sx Tag Symbols ,
most commonly being
.Li ${sblg-base} .
.It Li data-sblg-atomcontent=boolean
If
.Li <entry data-sblg-entry="1">
contains this set to true, the contents are printed directly and the
.Sx Tag Symbols
are processed.
This overrides
.Li data-sblg-altlink
and
.Li data-sblg-content .
.It Li data-sblg-content=boolean
If
.Li <entry data-sblg-entry="1">
contains this set to true, the article's contents (everything
within the
.Li <article data-sblg-article="1"> )
are inlined within the
.Li <content>
element with type
.Li html .
.Sx Tag Symbols
are processed.
.It Li data-sblg-entry=boolean
Each
.Li <entry>
element with this is filled in with article content.
.It Li data-sblg-forall=boolean
If an
.Li <entry data-sblg-entry="1">
element contains this set to true, it is used for all remaining
articles.
Any
.Li <entry data-sblg-entry="1">
following this are discarded.
.El
.Pp
If not using
.Li data-sblg-atomcontent ,
entries are filled in with a
.Li <title> ,
.Li <id> ,
.Li <author> ,
HTML
.Li <content>
.Po
specified in the article as an
.Li <aside>
.Pc ,
and alternate
.Li <link> .
The
.Li <id>
is constructed by appending the source filename, hash print, and date
following the feed's
.Li <id>
or
.Li <link>
element.
.Pp
When filling in HTML content,
.Nm
will strip away HTML attributes that do not fit into a white-list.
This white-list is defined by the W3C's Feed Validator.
.Ss JSON Schema
.Nm
can produce JSON with the
.Fl j
flag.
The schema is documented in
.Pa @SHAREDIR@/schema.json .
If
.Fl l
is specified, the output schema is simply an array as follows.
Let
.Pa source1.xml
and
.Pa source2.xml
be input files with a variety of tags.
.Bd -literal
[
 {"src": "source1.xml",
  "tags": ["tag1","tag2"]},
 {"src": "source2.xml",
  "tags": ["tag1"]}
]
.Ed
.Pp
If, however,
.Fl r
is also specified, the reverse format is used:
.Bd -literal
[
 {"tag": "tag1",
  "srcs": ["source1.xml","source2.xml"]},
 {"tag": "tag2",
  "srcs": ["source1.xml"]}
]
.Ed
.Ss Tag Symbols
Within the template for
.Fl c
or
.Fl C ,
or in any article contents written (either into an article or navigation
entry), the following special strings are replaced.
These symbols concern the current article being processed: in a
navigation entry, or as article contents.
In the event of the positional
.Dq next
and
.Dq prev
symbols, these refer to the article's position within the input
articles.
Obviously,
.Fl c
has only a single article.
.Pp
In general, these must be considered strict values, e.g.,
.Li ${sblg-aside}
and not
.Li ${ sblg-aside } .
Some symbols accept optional arguments, which have the format
.Li ${sblg-tags[|argument]} .
Here,
.Li \&|argument
may be omitted.
.Bl -tag -width -Ds
.It Li ${sblg-abscount}
The total number of articles.
This is only valid in
.Li <nav data-sblg-nav="1"> ,
otherwise it always prints 1.
See also
.Li ${sblg-count}
and
.Li ${sblg-setcount} .
.It Li ${sblg-abspos}
The position (from 1) of the article's position in the list of all
articles.
This is only valid in a
.Li <nav data-sblg-nav="1">
context, otherwise it always prints 1.
See also
.Li ${sblg-pos} .
.It Li ${sblg-aside}
The article's first aside with markup.
.It Li ${sblg-asidetext}
The article's first aside, textual parts only.
.It Li ${sblg-author}
The article's author with markup.
.It Li ${sblg-authortext}
The article's author, textual parts only
.It Li ${sblg-base}
The full filename (including directory) with the last suffix part
chopped off.
For example,
.Pa foo/bar.xml
becomes
.Pa foo/bar .
The
.Li ${sblg-stripbase}
variant will strip off the directory part and any sufix.
For example,
.Pa foo/bar.xml
becomes
.Pa bar .
The
.Li ${sblg-striplangbase}
variant will also strip the language.
For example, if
.Dq en
language was specified on the article,
.Pa foo/bar.en.xml
becomes
.Pa bar .
.It Li ${sblg-count}
The total number of articles that will be shown, i.e., taking into
consideration the navigation length and offset.
In standalone mode, this is always 1.
In
.Li <nav data-sblg-nav="1"> ,
it's the total number within the navigation.
See also
.Li ${sblg-abscount}
and
.Li ${sblg-setcount} .
.It Li ${sblg-date}
The publication date as YYYY-MM-DD (UTC).
.It Li ${sblg-datetime}
The publication date and time as YYYY-MM-DDTHH:MM:SSZ (UTC).
.It Li ${sblg-datetime-fmt[|fmt]}
A human-readable representation of the date and, if specified, time in
local time.
This accepts an optional format string passed to
.Xr strftime 3 .
If the format string is empty or
.Dq auto ,
a human-readable date
.Pq with Li %x
or date-time
.Pq Li %c
is printed.
.It Li ${sblg-img}
The article's associated image.
This will be an empty string if no image was specified.
.It Li ${sblg-first-base}
The first (newest) base name in the list of articles.
There are also
.Li ${sblg-first-stripbase}
and
.Li ${sblg-first-striplangbase}
variants.
.Pq See Li ${sblg-base} .
.It Li ${sblg-last-base}
The last (oldest) base name in the list of articles.
There are also
.Li ${sblg-last-stripbase}
and
.Li ${sblg-last-striplangbase}
variants.
.Pq See Li ${sblg-base} .
.It Li ${sblg-next-base}
The next base name when chronologically ordered from newest to oldest,
wrapping back to the beginning for the last.
There are also
.Li ${sblg-next-stripbase}
and
.Li ${sblg-next-striplangbase}
variants.
.Pq See Li ${sblg-base} .
.It Li ${sblg-next-has}
Prints
.Li sblg-next-has
if there exists a next article in the ordered set, otherwise prints
nothing.
.It Li ${sblg-pos}
The position (from 1) of the articles actually shown.
This always starts at 1 and increments by one, regardless the tag
filtering or starting position.
In standalone mode, it always prints 1.
In blog mode (outside of a
.Li <nav>
context), it shows the position in the input files.
Within a
.Li <nav>
context, it shows the position within the navigation.
.It Li ${sblg-pos-frac}
The fractional (0\(en1) value of
.Li ${sblg-pos}/$(sblg-count} .
.It Li ${sblg-pos-pct}
The percentage (0\(en100, not including the percent sign) form of
.Li ${sblg-pos-frac} .
.It Li ${sblg-prev-base}
The previous base name when chronologically ordered from newest to
oldest, wrapping back to the beginning for the last.
There are also
.Li ${sblg-prev-stripbase}
and
.Li ${sblg-prev-striplangbase}
variants.
.Pq See Li ${sblg-base} .
.It Li ${sblg-prev-has}
Prints
.Li sblg-prev-has
if there exists a previous article in the ordered set, otherwise prints
nothing.
.It Li ${sblg-get[|key]}
Print the value of
.Li key
assigned in
.Li data-sblg-set-key .
If unspecified or the key was not found, this is ignored and omitted
from output.
The lookup is case sensitive.
.It Li ${sblg-get-escaped[|key]}
Like
.Li ${sblg-get[|key]} ,
but escapes the value of the key so that it may be used for
.Li data-sblg-navtag
or
.Li data-sblg-articletag
attribute values for multi-word tags.
.It Li ${sblg-has[|key]}
Like
.Li ${sblg-get[|key]} ,
but queries with the
.Li key
exists.
If it is specified and it does exist, then the string
.Li sblg-has-key
is printed.
This is useful in
.Li class
attributes to test whether a given key has been specified.
.It Li ${sblg-setcount}
In
.Li <nav data-sblg-nav="1"> ,
this is the number of articles matching any requested tags.
See also
.Li ${sblg-count}
and
.Li ${sblg-abscount} .
.It Li ${sblg-source}
The source file when passed for parsing.
.It Li ${sblg-tags[|tagspec]}
List of unique tags in the article, optionally filtered by those having
the prefix
.Li tagspec .
If the prefix is not specified, all tags.
Each tag (e.g., TAG) is listed as
.Li <span class="sblg-tag">TAG</span> .
If no tags were found, a single
.Li <span class="sblg-tags-notfound"></span><commit_msg>Specify that ${sblg-setcount} is like ${sblg-count}, not ${sblg-abscount}.<commit_after>.\"	$Id$
.\"
.\" Copyright (c) 2013--2017, 2019 <NAME> <<EMAIL>>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate$
.Dt SBLG 1
.Os
.Sh NAME
.Nm sblg
.Nd static blog utility
.Sh SYNOPSIS
.Nm sblg
.Op Fl acjlLrV
.Op Fl C Ar file
.Op Fl o Ar file
.Op Fl s Ar sort
.Op Fl t Ar template
.Ar
.Sh DESCRIPTION
The
.Nm
utility knits together XML articles and templates in a number of ways.
.Bl -bullet
.It
Standalone mode
.Pq Fl c
links single articles with a template with an article stub, which is
filled in with the article.
For example,
.Qq sblg -c foo.xml bar.xml
creates
.Pa foo.html
and
.Pa bar.html
from a template populated by the
.Pa foo.xml
and
.Pa bar.xml
article contents, respectively.
.It
Blog mode (default) links multiple articles with a template consisting
of articles and navigation stubs.
For example,
.Qq sblg -o foo.html bar.html baz.html
links
.Pa bar.html
and
.Pa baz.html
into
.Pa foo.html
from a template.
.It
Atom mode
.Pq Fl a
links multiple articles with an Atom feed template.
.It
JSON mode
.Pq Fl j
formats all articles as a JSON feed.
.It
Combined mode
.Pq Fl C
links multiple articles in standalone style, i.e., multiple navigation
stubs, a single article stub.
For example,
.Qq sblg -o foo.html -C bar.html baz.html bar.html
will show only
.Pa bar.html
in the article list of
.Pa foo.html ,
but both
.Pa bar.html
and
.Pa baz.html
in its navigation.
You can also use
.Fl L
to run the process for each input file (much faster).
.It
Tag-listing mode with
.Fl l .
.El
.Pp
By default,
.Nm
operates in blog mode as if
.Qq sblg -o blog.html -t blog-template.xml ...
were specified.
Its arguments are as follows:
.Bl -tag -width Ds
.It Fl a
Creates an Atom feed from its input files.
.It Fl c
Create standalone articles instead of merging articles together.
.It Fl l
Instead of emitting any output files, simply process the input and
report a table of tags.
This table consists of the input file name, a tab, then the tag.
.Pq Also known as article-major order.
The tag has escaped white-space printed as unescaped.
You can also use
.Fl r
to have tag-major order and
.Fl j
for JSON output.
Specify
.Fl l
twice to show matches (tags for article-major, articles for tag-major)
all on one tab-separated line, instead of one per line.
.It Fl r
Print the
.Fl l
tag listing in
.Dq tag-major
order wherein the first column is the tag and the second column is the
article.
If the
.Fl j
flag is specified, this is JSON formatted.
.It Fl j
JSON output mode.
This behaves as in blog mode, but outputs JSON instead of XML.
If
.Fl l
is specified, the tag listing will be displayed in JSON instead.
See
.Sx JSON Schema
for details.
.It Fl C Ar file
Like
.Fl c ,
but creating a blog with a single
.Li <article data-sblg-article="1">
for the
.Ar file
while using the remaining arguments are other files used in
.Li <nav data-sblg-nav="1"> .
.It Fl L
Like
.Fl C ,
but acting on all input files, translating the input to output files
such as in
.Fl c
without
.Fl o .
If there are multiple articles in an output file, the output is
recreated for each (so only the last will remain).
So running with
.Dq article0.xml article1.xml
will produce
.Dq article0.html article1.html
as if
.Fl C
were seperately specified for both.
This avoids needing to parse all inputs for each input.
.It Fl o Ar file
Output file.
If unspecified, standalone articles have
.Li .html
appended to the input file name, unless the input file extension is
.Li .xml ,
in which case the
.Li .xml
is replaced by
.Li .html .
If multiple input files are specified,
.Fl o
is ignored.
If unspecified for the blog,
.Ar blog.html
is used by default.
If unspecified for the Atom feed or JSON,
.Ar atom.xml
or
.Ar blog.json ,
respectively,
is used by default.
Use
.Fl o Ar \-
for standard output.
.It Fl s Ar sort
Change how articles are sorted before being written into navigation or
article entries.
The default is
.Ar date ,
which sorts oldest-newest by date.
You can also specify
.Ar filename ,
which sorts in increasing A\(enZ case-sensitive order of the source
filename;
.Ar cmdline
for the command-line order;
.Ar ititle
for the case-insensitive document title; or
.Ar title
for the case-sensitive document title.
Each sort may be prefixed with
.Qq r
(e.g.,
.Ar rcmdline )
to reverse the sort.
.It Fl t Ar template
Template for all modes.
If unspecified, defaults to
.Ar article-template.xml
for
.Fl c ,
.Ar atom-template.xml
for
.Fl a ,
and
.Ar blog-template.xml
otherwise.
.It V
Emits the verion as
.Li sblg-xx.yy.zz
and exits.
.It Ar
Input files.
In standalone mode with
.Fl c ,
input XML files are merged with a template into an output file.
Otherwise, multiple input files are merged into a single blog.
.El
.Pp
All input must be well-formed XML.
(Element names and attributes are case-sensitive.)
HTML is assumed only with the default suffix re-write rule for
.Fl c
without
.Fl o .
Input articles may be XML fragments or full documents: only the
.Li <article data-sblg-article="1">
tree within the article is considered.
.Ss Article Input
Article input files consist of XML fragments or whole documents.
They usually consist of the following within the document:
.Bd -literal
<article data-sblg-article="1">
  <header>
    <h1>Article Name</h1>
    <address>Author Name</address>
    <time datetime="2013-06-29">29 June, 2013</time>
  </header>
  <aside>
    This is used as the feed <b>abstract</b>.
  </aside>
  <p>
    Some text in the <b>content</b>.
    <img src="foo.jpg" alt="An image for the feed" />
  </p>
</article>
.Ed
.Pp
When processed with
.Nm ,
all data outside of the
.Li <article data-sblg-article="1">
element is discarded.
Then the article is scanned for the following:
.Bl -bullet
.It
the article title (both as text data only and inclusive of markup) is
extracted from the first
.Li <hn>
.Pq header 1\(en4 ;
.It
the article publication date is extracted from the datetime attribute of
the first
.Li <time>
(which must be a date, YYYY-MM-DD, or time, YYYY-MM-DDTHH:MM:SSZ)
interpreted in UTC;
.It
the author (both as text data only and inclusive of markup) from the
first
.Li <address> ;
.It
the first
.Li <aside>
is used for the feed abstract; and
.It
the first
.Li <img>
is associated as the article's image.
.El
.Pp
If unspecified, the default article title text (and mark-up) is
.Qq Untitled article ,
the default author text (and mark-up) is the
.Qq Unknown author ,
the publication time is set to the document's file-system creation time,
the abstract is left empty, and the image is empty.
.Pp
All content is recorded in case the
.Li data-sblg-content
Boolean value is used in an Atom feed.
.Pp
There are a number of special attributes that are recognised in the
input file.
.Bl -tag -width Ds
.It Li data-sblg-aside=string
Sets the aside material as otherwise would be set from the first
.Li <aside>
element.
It overrides the previously set aside.
.It Li data-sblg-author=url
Sets the author as otherwise would be set from the first
.Li <address>
element.
It overrides the previously set author.
.It Li data-sblg-datetime=datetime
Overrides the first
.Li <time>
element.
This must be YYYY-MM-DD or YYYY-MM-DDTH:MM:SSZ.
It overrides the previously set date.
.It Li data-sblg-img=url
Overrides the first
.Li <img>
link to be the image associated with the article.
It overrides the previously set image.
.It Li data-sblg-lang=string
May only be set on the
.Li <article>
and specifies one or more space-separated languages for the document.
You can escape spaces with a backslash
.Pq Dq \e
if you have spaces in the tag name, e.g.,
.Dq foo\e bar .
These languages are removed in the
.Dq stripping
operations for the
.Sx Tag Symbols .
.It Li data-sblg-set-xxx=string
This allows arbitrary values to be attached to the article.
For example, specifying
.Li data-sblg-set-foo="bar"
sets the
.Li foo
keyword to
.Li bar .
If specified multiple times for the same key, only the last value is
used.
These may be retrieved with
.Li ${sblg-get}
or queried with
.Li ${sblg-has}
of the
.Sx Tag Symbols .
.It Li data-sblg-sort=first|last
May only be set on the
.Li <article>
element and overrides the article's position relative to other articles.
This can be either
.Li first
or
.Li last .
If multiple articles have the same sort override, they are ordered in
the natural way.
.It Li data-sblg-tags=string
This tag may be specified on any element within the article and consists
of space-separated tag names.
You can escape spaces with a backslash
.Pq Dq \e
if you have spaces in the tag name, e.g.,
.Dq foo\e bar .
These tags are extracted for navigation tag operation.
It may not contain any tabs.
.It Li data-sblg-title=string
Sets the title as otherwise would be set in a
.Li <hN>
element.
It overrides the previously set title.
.El
.Ss Standalone Template
The standalone template file must be a well-formed XML file where the
first
.Li <article data-sblg-article="1">
element is replaced by the article text.
All of this element's children are removed.
.Bd -literal
<body>
  <header>This consists of a single blog entry.</header>
  <article>This is kept.</article>
  <article data-sblg-article="1">This is removed.</article>
  <footer>Something.</footer>
</body>
.Ed
.Pp
Article templates may contain the following attributes:
.Bl -tag -width Ds
.It Li data-sblg-article=boolean
If set to true, the contents are replaced with the input article.
.It Li data-sblg-ign-once=boolean
If an
.Li <article data-sblg-article="1">
element contains this set to true, the element is not processed as an
article and the
.Li data-sblg-ign-once
attribute is removed.
.El
.Pp
See
.Sx Tag Symbols
for a list of symbols that will be replaced if found in attribute value
or textual contexts.
These may occur anywhere in the template document.
.Ss Blog Template
The blog template file must also be a well-formed XML file where each
.Li <article data-sblg-article="1">
element is replaced by ordered (by default, newest to oldest) article
contents.
If there aren't enough articles, the element is removed.
Furthermore,
.Li <nav data-sblg-nav="1">
elements are replaced by the same list of articles within an
unordered list.
.Pp
Usually, the
.Li <article>
tags are used for displaying full articles, while
.Li <nav>
tags are used for displaying navigation to articles, such as just their
titles, dates, and links.
.Bd -literal
<body>
  <header>This consists of two blog entries.</header>
  <nav data-sblg-nav="1" />
  <article data-sblg-article="1" />
  <article data-sblg-article="1" />
  <footer>Something.</footer>
</body>
.Ed
.Pp
Article templates may contain several attributes.
.Bl -tag -width Ds
.It Li data-sblg-article=boolean
If set to true, the contents are replaced with the input article.
.It Li data-sblg-articletag=string
If an
.Li <article data-sblg-article="1">
element contains this, limit displayed articles to those matching the
space-separated tags or
.Li ${sblg-get|xxx}
when in
.Fl L
or
.Fl C
mode.
.It Li data-sblg-ign-once=boolean
If an
.Li <article data-sblg-article="1">
element contains this set to true, the element is not processed as an
article and the
.Li data-sblg-ign-once
attribute is removed.
.It Li data-sblg-permlink=boolean
If an
.Li <article data-sblg-article="1">
element contains this set to true, a permanent link to the article's
input filename is emitted after the
.Li <article data-sblg-article="1">
within a 
.Li <div data-sblg-permlink="1">
element.
.El
.Pp
The navigation element may contain several attributes.
.Bl -tag -width Ds
.It Li data-sblg-navcontent=boolean
If true, reproduces the mark-up content of the
.Li <nav>
within an unordered list item for each article shown, replacing
.Sx Tag Symbols
for the current article.
If not true,
.Nm
populates an unordered list with article title text in a link and the
publication date.
.It Li data-sblg-navsort=sort
Overrides the global search order given with
.Fl s .
Uses the same names.
If the search name is not recognised, the attribute is silently ignored
and the global search order used.
.It Li data-sblg-navstart=number
How many articles will skip being displayed (so if you have tags, it
will only account for articles that would meet those tags) before
showing the first navigation entry.
Starts at one (a value of zero is the same as a value of one).
.It Li data-sblg-navsz=number
If the
.Li <nav>
element contains this attribute with a positive integer, it is used to
limit the number of navigation entries.
.It Li data-sblg-navtag=string
Only articles with matching tags are shown.
You can specify multiple space-separated tags, for instance,
.Li data-sblg-navtag="foo bar"
will search for foo or bar.
Tags to be matched against are extracted from the space-separated
.Li data-sblg-tags
element of each article's topmost
.Li <article>
element.
Escape spaces with a backslash
.Pq Dq \e
if you have spaces in the tag name, e.g.,
.Dq foo\e bar .
Use
.Li ${sblg-get|xxx}
or (for multi-word values)
.Li ${sblg-get-escaped|xxx}
when in
.Fl C
or
.Fl L
mode to use the current article's set data as part of a string, e.g.,
.Li location-${sblg-get|location} .
.It Li data-sblg-navxml=boolean
Like
.Li data-sblg-navcontent ,
but without the surrounding list elements.
The
.Li data-sblg-navxml
attribute does not print any additional
.Li <nav> ,
.Li <ul> ,
or
.Li <li>
HTML tags and can be used to generate custom XML files, such as sitemaps.
.El
.Ss Combined Template
This is identical to the
.Sx Blog Template
except that a single article is noted with
.Fl C ,
and this is the only article displayed in the article stub.
Furthermore, like in standalone mode,
.Sx Tag Symbols
may be used anywhere in the document template and refer to the current
article unless within a navigation element, in which case the symbol
resolves to the currently-printed article.
In the given example,
.Bd -literal
<body>
  <header>This consists of two blog entries.</header>
  <nav data-sblg-nav="1" />
  <article data-sblg-article="1" />
  <article data-sblg-article="1" />
  <footer>Something.</footer>
</body>
.Ed
.Pp
the navigation would be populated by all articles, but only the first
article stub would be filled in with the specified article.
The second would be removed.
.Pp
This follows the usual rules of
.Li data-sblg-articletag ,
so if the article you specify with
.Fl C
doesn't have the correct tag, it won't inline the article.
.Ss Atom Template
The Atom template file must be a well-formed XML file where each
.Li <entry>
element with a Boolean
.Li data-sblg-entry
attribute is replaced by ordered (newest to oldest) article information.
If there aren't enough articles, the element is removed.
The template may contain pre-existing entries.
.Pp
The following is a minimal template: anything less will not conform to
the Atom specification:
.Bd -literal
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <link href="http://example.org" />
  <title>A Title Here</title>
  <updated />
  <id />
  <entry data-sblg-entry="1" data-sblg-forall="1" />
</feed>
.Ed
.Pp
The recognised elements are as follows.
Un-recognised elements are printed verbatim.
.Bl -tag -width Ds
.It Li <entry data-sblg-entry="1">
Filled-in article entry.
If the attribute is not specified, the entry is retained verbatim.
Otherwise it is filled in with an article's information.
.It Li <id>
If this is empty, it is filled in with the URL in
.Li <link [rel="alternate"]> ,
which must exist.
Otherwise, the value is copied and used for subsequent feed entries.
.It Li <link [rel="alternate"]>
Unless an
.Li <id>
is provided, the
.Li href
attribute must be a full URL, e.g.,
.Li <link href="https://kristaps.bsd.lv/"> .
Otherwise, it may be a relative path.
This element
.Em must be first .
.It Li <updated>
This is filled in with the most recent article.
Its contents are discarded.
.El
.Pp
There are a number of special attributes that may be given to the above
elements.
.Bl -tag -width Ds
.It Li data-sblg-altlink=boolean
If an
.Li <entry data-sblg-entry="1">
element contains this set to true, the alternate
.Li <link>
is printed.
.It Li data-sblg-altlink-fmt=string
If both
.Li data-sblg-entry
and
.Li data-sblg-altlink
are true for an
.Li <entry> ,
the value is used as the link address.
Accepts
.Sx Tag Symbols ,
most commonly being
.Li ${sblg-base} .
.It Li data-sblg-atomcontent=boolean
If
.Li <entry data-sblg-entry="1">
contains this set to true, the contents are printed directly and the
.Sx Tag Symbols
are processed.
This overrides
.Li data-sblg-altlink
and
.Li data-sblg-content .
.It Li data-sblg-content=boolean
If
.Li <entry data-sblg-entry="1">
contains this set to true, the article's contents (everything
within the
.Li <article data-sblg-article="1"> )
are inlined within the
.Li <content>
element with type
.Li html .
.Sx Tag Symbols
are processed.
.It Li data-sblg-entry=boolean
Each
.Li <entry>
element with this is filled in with article content.
.It Li data-sblg-forall=boolean
If an
.Li <entry data-sblg-entry="1">
element contains this set to true, it is used for all remaining
articles.
Any
.Li <entry data-sblg-entry="1">
following this are discarded.
.El
.Pp
If not using
.Li data-sblg-atomcontent ,
entries are filled in with a
.Li <title> ,
.Li <id> ,
.Li <author> ,
HTML
.Li <content>
.Po
specified in the article as an
.Li <aside>
.Pc ,
and alternate
.Li <link> .
The
.Li <id>
is constructed by appending the source filename, hash print, and date
following the feed's
.Li <id>
or
.Li <link>
element.
.Pp
When filling in HTML content,
.Nm
will strip away HTML attributes that do not fit into a white-list.
This white-list is defined by the W3C's Feed Validator.
.Ss JSON Schema
.Nm
can produce JSON with the
.Fl j
flag.
The schema is documented in
.Pa @SHAREDIR@/schema.json .
If
.Fl l
is specified, the output schema is simply an array as follows.
Let
.Pa source1.xml
and
.Pa source2.xml
be input files with a variety of tags.
.Bd -literal
[
 {"src": "source1.xml",
  "tags": ["tag1","tag2"]},
 {"src": "source2.xml",
  "tags": ["tag1"]}
]
.Ed
.Pp
If, however,
.Fl r
is also specified, the reverse format is used:
.Bd -literal
[
 {"tag": "tag1",
  "srcs": ["source1.xml","source2.xml"]},
 {"tag": "tag2",
  "srcs": ["source1.xml"]}
]
.Ed
.Ss Tag Symbols
Within the template for
.Fl c
or
.Fl C ,
or in any article contents written (either into an article or navigation
entry), the following special strings are replaced.
These symbols concern the current article being processed: in a
navigation entry, or as article contents.
In the event of the positional
.Dq next
and
.Dq prev
symbols, these refer to the article's position within the input
articles.
Obviously,
.Fl c
has only a single article.
.Pp
In general, these must be considered strict values, e.g.,
.Li ${sblg-aside}
and not
.Li ${ sblg-aside } .
Some symbols accept optional arguments, which have the format
.Li ${sblg-tags[|argument]} .
Here,
.Li \&|argument
may be omitted.
.Bl -tag -width -Ds
.It Li ${sblg-abscount}
The total number of articles.
This is only valid in
.Li <nav data-sblg-nav="1"> ,
otherwise it always prints 1.
See also
.Li ${sblg-count}
and
.Li ${sblg-setcount} .
.It Li ${sblg-abspos}
The position (from 1) of the article's position in the list of all
articles.
This is only valid in a
.Li <nav data-sblg-nav="1">
context, otherwise it always prints 1.
See also
.Li ${sblg-pos} .
.It Li ${sblg-aside}
The article's first aside with markup.
.It Li ${sblg-asidetext}
The article's first aside, textual parts only.
.It Li ${sblg-author}
The article's author with markup.
.It Li ${sblg-authortext}
The article's author, textual parts only
.It Li ${sblg-base}
The full filename (including directory) with the last suffix part
chopped off.
For example,
.Pa foo/bar.xml
becomes
.Pa foo/bar .
The
.Li ${sblg-stripbase}
variant will strip off the directory part and any sufix.
For example,
.Pa foo/bar.xml
becomes
.Pa bar .
The
.Li ${sblg-striplangbase}
variant will also strip the language.
For example, if
.Dq en
language was specified on the article,
.Pa foo/bar.en.xml
becomes
.Pa bar .
.It Li ${sblg-count}
The total number of articles that will be shown, i.e., taking into
consideration the navigation length and offset.
In standalone mode, this is always 1.
In
.Li <nav data-sblg-nav="1"> ,
it's the total number within the navigation.
See also
.Li ${sblg-abscount}
and
.Li ${sblg-setcount} .
.It Li ${sblg-date}
The publication date as YYYY-MM-DD (UTC).
.It Li ${sblg-datetime}
The publication date and time as YYYY-MM-DDTHH:MM:SSZ (UTC).
.It Li ${sblg-datetime-fmt[|fmt]}
A human-readable representation of the date and, if specified, time in
local time.
This accepts an optional format string passed to
.Xr strftime 3 .
If the format string is empty or
.Dq auto ,
a human-readable date
.Pq with Li %x
or date-time
.Pq Li %c
is printed.
.It Li ${sblg-img}
The article's associated image.
This will be an empty string if no image was specified.
.It Li ${sblg-first-base}
The first (newest) base name in the list of articles.
There are also
.Li ${sblg-first-stripbase}
and
.Li ${sblg-first-striplangbase}
variants.
.Pq See Li ${sblg-base} .
.It Li ${sblg-last-base}
The last (oldest) base name in the list of articles.
There are also
.Li ${sblg-last-stripbase}
and
.Li ${sblg-last-striplangbase}
variants.
.Pq See Li ${sblg-base} .
.It Li ${sblg-next-base}
The next base name when chronologically ordered from newest to oldest,
wrapping back to the beginning for the last.
There are also
.Li ${sblg-next-stripbase}
and
.Li ${sblg-next-striplangbase}
variants.
.Pq See Li ${sblg-base} .
.It Li ${sblg-next-has}
Prints
.Li sblg-next-has
if there exists a next article in the ordered set, otherwise prints
nothing.
.It Li ${sblg-pos}
The position (from 1) of the articles actually shown.
This always starts at 1 and increments by one, regardless the tag
filtering or starting position.
In standalone mode, it always prints 1.
In blog mode (outside of a
.Li <nav>
context), it shows the position in the input files.
Within a
.Li <nav>
context, it shows the position within the navigation.
.It Li ${sblg-pos-frac}
The fractional (0\(en1) value of
.Li ${sblg-pos}/$(sblg-count} .
.It Li ${sblg-pos-pct}
The percentage (0\(en100, not including the percent sign) form of
.Li ${sblg-pos-frac} .
.It Li ${sblg-prev-base}
The previous base name when chronologically ordered from newest to
oldest, wrapping back to the beginning for the last.
There are also
.Li ${sblg-prev-stripbase}
and
.Li ${sblg-prev-striplangbase}
variants.
.Pq See Li ${sblg-base} .
.It Li ${sblg-prev-has}
Prints
.Li sblg-prev-has
if there exists a previous article in the ordered set, otherwise prints
nothing.
.It Li ${sblg-get[|key]}
Print the value of
.Li key
assigned in
.Li data-sblg-set-key .
If unspecified or the key was not found, this is ignored and omitted
from output.
The lookup is case sensitive.
.It Li ${sblg-get-escaped[|key]}
Like
.Li ${sblg-get[|key]} ,
but escapes the value of the key so that it may be used for
.Li data-sblg-navtag
or
.Li data-sblg-articletag
attribute values for multi-word tags.
.It Li ${sblg-has[|key]}
Like
.Li ${sblg-get[|key]} ,
but queries with the
.Li key
exists.
If it is specified and it does exist, then the string
.Li sblg-has-key
is printed.
This is useful in
.Li class
attributes to test whether a given key has been specified.
.It Li ${sblg-setcount}
Like
.Li ${sblg-count} ,
but only the articles matching the requested tags.
See also
.Li ${sblg-count}
and
.Li ${sblg-abscount} .
.It Li ${sblg-source}
The source file when passed for parsing.
.It Li ${sblg-tags[|tagspec]}
List of unique tags in the article, optionally filtered by those having
the prefix
.Li tagspec .
If the prefix is not specified, all tags.
Each tag (e.g., TAG) is listed as
.Li <span class="sblg-tag">TAG</span> .
If no tags were found, a single
.Li <span class="sblg-tags-notfound"></span>
{'fraction_non_alphanumeric': 0.09024410122661886, 'fraction_numerical': 0.004217775785484331, 'mean_word_length': 3.7437657065532575, 'pattern_counts': {'":': 16, '<': 260, '<?xml version=': 2, '>': 260, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 54}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '587620', 'n_tokens_mistral': 16374, 'n_tokens_neox': 15849, 'n_words': 7615}