SLWEB(1)

๐Ÿ“ฆ version 0.10.2, in nixos 26.05, nixpkgs unstable

๐Ÿ’– NAME ๐Ÿ’–

okay so bestie, this is SLWEB(1) from the General Commands Manual, and itโ€™s all about slweb โ€” the Simple static website generator. Thatโ€™s the whole NAME vibe: slweb โ€” Simple static website generator. โœจ


๐ŸŒธ SYNOPSIS ๐ŸŒธ

slweb -h | --help | -V | --full-version | -v | --version
slweb [-b | --body-only] [-d directory | --basedir directory] [-p URL |
      --global-link-prefix URL] [filename]

โœจ DESCRIPTION โœจ

okay so slweb is a static website generator which aims at being simplistic. It transforms custom Markdown-like syntax into HTML. Itโ€™s giving tiny tool, big output energy. ๐Ÿ’…

here are the flags, bestie:

  • -b, --body-only โ€” only add the contents of the <body> tag, skipping <html> and <head>.
  • -d directory, --basedir directory โ€” set the base directory for image file paths to pass to identify(1), includes ({include} and {incdir}) and favicons. Defaults to the current directory (".").
  • -h, --help โ€” print the usage information screen.
  • -p URL, --global-link-prefix URL โ€” set URL as a global prefix for relative links.
  • -V, --full-version โ€” print full version (like -v), followed by copyright notice, and exit.
  • -v, --version โ€” print program version and commit date, and exit.

Files processed by slweb are using a minimal subset of Markdown with added directives. ๐Ÿซถ

๐Ÿฆ‹ Supported Markdown features ๐Ÿฆ‹

  • Backticks. Text inside backticks will be put inside <code></code>. Text surrounded by triple backticks (```) on the lines by themselves will be put inside <pre></pre>. Any โ€œless-thanโ€ characters inside backticks will be converted to &lt; and โ€œampersandโ€ characters to &amp;. Any text following the first triple backticks until the end of the line will be ignored. This is to account for language highlighting specification, which isn't yet supported. no cap.
  • Blockquotes. Starting the line with > will surround it with a <blockquote> tag. Multiple lines are supported. ๐ŸŽ€
  • Bold/italic. Text inside *asterisks* or _underlines_ will be put inside <em></em>. Text inside **double asterisks** or __double underlines__ will be put inside <strong></strong>. ***More than two*** of the ___same symbol___ should be avoided. periodt.
  • Break marks. To address combinations of lists and โ€œrawโ€ tags, which are problematic to mix together, slweb supports explicitly marking a tag with a โ€œbreak markโ€. This currently means that when such a tag is introduced, any running list item and list will be closed prior to outputting the tag. Tags with break marks are introduced by prepending the exclamation mark to the tag name. For example, without a break mark, the input:
- Some list
{break-here}

produces the following output:

<ul><li><p>Some list
<break-here></li></ul>

When changed to:

- Some list
{!break-here}

slweb will output:

<ul><li><p>Some list
</li></ul>
<break-here>

Same for end tags:

{dl}{dt}{p}Introduction{/dt}
{dd}
- One
- Two
{/dd}{/dl}

produces:

<dl><dt><p>Introduction</dt>
<dd>
<ul><li><p>One
</li>
<li><p>Two
</dd></dl></li></ul>

while

{dl}{dt}{p}Introduction{/dt}
{dd}
- One
- Two
{/!dd}{/dl}

produces:

<dl><dt><p>Introduction</dt>
<dd>
<ul><li><p>One
</li>
<li><p>Two
</li></ul>
</dd></dl>
  • Footnotes (regular and inline). Two-part regular footnotes can be added in a manner similar to links (see โ€œLinksโ€). Inline footnotes are also supported. ๐Ÿงš
    • Regular footnotes have two mandatory parts: first, the footnote mark is represented by [^footnoteid], where footnoteid is the footnote identifier. Second, the text of the footnote is represented by [^footnoteid]: sometext, with sometext being the text of the footnote. Footnote text construct needs to begin at the start of a line, and it is the most practical to have it placed near the bottom of the file, similar to normal links.

Combined, the input:

This is a text[^first].

[^first]: With a footnote!

gives (some lines are wrapped for this manual):

<p>This is a text<a href="#footnote-1" id="footnote-text-1">
<sup>1</sup></a>.

<hr>
<p id="footnote-1"><a href="#footnote-text-1">1.</a>
With a footnote!
  • Inline footnotes can be added by using the construct ^[footnotetext]. For example, input
Inline footnote^[Footnote text] in a paragraph.

will produce

Inline footnote<a href="#inline-footnote-1"
id="inline-footnote-text-1"><sup>1</sup></a> in a
paragraph.
<hr>
<p id="inline-footnote-1"><a href="#inline-footnote-text-1">
1.</a> Footnote text

The horizontal rule and the list of footnotes is output only once, before the end of HTML document body. Rule and the list of footnotes can be surrounded by a div with the โ€œfootnotesโ€ id by setting the YAML variable add-footnote-div to 1 (see โ€œadd-footnote-divโ€).

โš ๏ธ heads up: inline and regular footnotes can be used at the same time, but they don't share the numbering. This doesn't affect functionality, but it does affect presentation, as some footnote numbers will overlap. As a result, whenever slweb encounters both footnote types in the same document, a warning will be issued to stderr. ๐Ÿ’€
  • Headings. A line starting with # followed by space will be put inside <h?></h?>, where ? stands for 1-4, depending on the number of hash signs. Tags will have id attributes set to heading-?, with ? set to the number representing its position within the list of all headings. ๐Ÿ‘‘
  • Horizontal rules. Three dashes at the start of the line will produce a <hr> in the output. As this Markdown feature clashes with YAML block boundaries, it will work only if YAML block is present in the input and before the three dashes for the horizontal rule. Any text following the three dashes on the same line will be ignored.

Alternatively, three asterisks (***) can be used instead of dashes, avoiding the necessity for a YAML block preceding the asterisks.

  • Images. Similar to links (see โ€œLinksโ€), images can be added by using:
![Some title](/path/to/image.png)

Which will produce:

<figure>
<a href="/path/to/image.png" title="Some title" class="image"
  target="_blank"><img src="/path/to/image.png" alt="Some title"
  width="100" height="50" ></a><figcaption>Some title</figcaption>
</figure>

The attributes width and height will be determined automatically using the command identify(1) (if present), provided the src attribute contains a valid file path. (Also see image-file-prefix).

As with links, a form similar to the โ€œregular formโ€ of links can also be used, using the image id instead of the direct URL.

If the additional link or <figure>/<figcaption> tags are not desirable, they can be turned off by setting add-image-links and add-figcaption to 0. ๐ŸŒธ

  • Keyboard tags. Text inside ||double bars|| will be put inside <kbd></kbd> tags. As with backticks, any โ€œless-thanโ€ character will be converted to &lt;. ๐ŸŽ€
  • Line breaks. Two spaces followed by a newline will become <br>.
  • Links.

Special case is the form

[=somemacro Link title](https://anything)

which prepends the body of a macro somemacro into the <a></a> tag (here broken into multiple lines for clarity):

<a href="https://anything">
<!-- contents of somemacro -->
Link title</a>

This can, for example, be used to add SVG icons to links. See โ€œMacrosโ€.

Also, the form [(Link title)](http://asite.com) will surround the link title (text between <a></a> tags) with <span></span>, like so:

<a href="http://asite.com"><span>Link title</span></a>

This allows for separate styling of link text. It can be combined with the macro-form:

[=somemacro (Link title)](http://asite.com)

It will prepend the body of a macro somemacro outside of the <span></span>:

<a href="http://asite.com">
<!-- contents of somemacro -->
<span>Link title</span></a>

Exception is the form

[Some text (parenthesized)](https://somelink),

which won't output <span> tags, and will simply include the parentheses in the output instead. This form doesn't apply to macro-form

[=macro Some (text)](http://link),

which will always output <span> tags.

  • Regular links. Everything said about inline links applies to regular links, with the exception that instead of the parenthesized URL, link text inside brackets should be followed by link id (different than the id attribute!) inside brackets, and a separate definition of that link id is needed, usually near the end of input.

For example:

Here's a link to [my website][mw].

[mw]: https://mysite.com

will produce:

<p>Here's a link to <a href="https://mysite.com">my website</a>.

This can help reduce the amount of code in the text of the page.

  • Lists. Lines starting with a dash (-), an asterisk (*) or lowercase โ€œoโ€, followed by a space, will start an unordered list (if used for the first time) and start a list item. Input:
Colors are:

- Red
- Green
- Blue

and so on.

will produce:

<p>Colors are:

<ul>
<li><p>Red
</li>
<li><p>Green
</li>
<li><p>Blue
</li></ul>
<p>And so on.

okay so bestie, one more list thing before we keep going: if you indent a line after a blank line with two spaces, it creates a paragraph inside the list item. Otherwise it ends the list. Like this:

- This is a text inside a list item.

    Remarkably, this paragraph is as well.
- This is already a second item.

This is after the list.

turns into this HTML:

<ul><li><p>This is a text inside a list item.
<p>Remarkably, this paragraph is as well.
</li>
<li><p>This is already a second item.</li></ul>
<p>This is after the list.

And lists can't be nested โ€” if characters inside an existing list would otherwise start a list, they just get inserted as-is in the output. periodt.

  • Non-breaking hyphen. Tilde followed by a hyphen (~-) will insert &#8209; in the output. tiny ghost hyphen energy ๐Ÿ’…
  • Non-breaking space. Two consecutive tildes (~~) will produce &nbsp; in the output.
  • Paragraphs. Text surrounded by newlines will be prepended by <p> tag. See โ€œKnown limitationsโ€.
  • Strikethrough. Text surrounded by tildes (~) will be put inside <s></s>. slay.
  • Tables. Lines starting with vertical bars (|) will be transformed into HTML tables. The first such line is treated as a header row, second as the alignment specifier (currently ignored), and the rest regular rows. Table cells and header cells are specified by additional bar characters. For example, input:
| Month | Jan | Feb | Mar | Apr |
|-------|-----|-----|-----|-----|
| Qty   | 2.35| 1.2 |  8  |  15 |

will be transformed into:

<table>
<thead>
<tr><th> Month </th><th> Jan </th><th> Feb </th><th> Mar </th>
<th> Apr </th></tr>
</thead>
<tbody>
<tr><td> Qty   </td><td> 2.35</td><td> 1.2 </td><td>  8  </td>
<td>  15 </td></tr>
</tbody>
</table>
  • Partial tables are a modification of Markdown tables, allowing them to be combined with the TSV or CSV directive. In order for tables to work with templating, they need two additional lines at the top and the bottom, to mark the start and the end of the table. All the lines in partial tables need to start with |, with only the character following at-mark being different:
|@\------|-----|-----|-----|-----|
{tsv "../tsv/sales" 1}
|@#  $#1 | $#2 | $#3 | $#4 | $#5 |
{/tsv}
|@-------|-----|-----|-----|-----|
{tsv "../tsv/sales"}
|@    $1 | $2  | $3  | $4  | $5  |
{/tsv}
|@/------|-----|-----|-----|-----|

The rest of the line following the third character in top, bottom and lines separating header from body is ignored by the parser and is included in this example only for aesthetic purposes. See โ€œTSV/CSV templatingโ€.

  • Zero width space. Tilde followed by an exclamation mark (~!) will produce &#8203; in the output. invisible icon behavior โœจ

๐ŸŒˆ Math mode ๐ŸŒˆ

Math mode is supported through KaTeX. With katex installed, anything between dollar signs ($) will be transformed into MathML and HTML markup. To generate display math, use double dollar signs ($$). The text between the dollar signs in both cases should be LaTeX source code, and is passed to katex. The KaTeX stylesheet is not included, and needs to be included separately through the stylesheet or inline-stylesheet YAML variables (see โ€œstylesheetโ€, โ€œinline-stylesheetโ€). math girlie knows ๐Ÿ’–

๐ŸŽ€ Directives ๐ŸŽ€

  • Brand โ€œwatermarkโ€. Directive {made-by} results in a div to be output at the end of the document, with the id made-by containing the โ€œwatermarkโ€ text and a link to the slweb home page. cute little signature ๐Ÿ’…
  • General tags. Directive {sometag}{/sometag} will be transformed into <sometag></sometag>.
  • Class attributes. Directive {tag.myclass mysecondclass}{/tag} will be transformed into <tag class="myclass mysecondclass"></tag>. Only one class attribute is permitted per tag directive (subsequent dots will be inserted as part of the class attribute), but you can include multiple classes by separating them with a space, just like in HTML, and you can have both a class attribute and an id attribute per tag.

A variation of this is to use a special form {.myclass}{/.myclass}, which will be transformed into <div class="myclass"></div>.

  • Id attributes. Directive {tag#myid}{/tag} will be transformed into <tag id="myid"></tag>. Only one id attribute is permitted per tag directive (subsequent hash signs will be included as part of the id attribute), and you can have both an id attribute and a class attribute per tag.

A variation of this is to use a special form {#myid}{/#myid}, which will be transformed into <div id="myid"></div>.

  • Includes. Directive {include "somefile"} will fork, parse somefile.slw (related to basedir) and output the resulting HTML as if the option --body-only was specified. All YAML variables will be preserved.
  • Macros. Macros can be declared using the directive {=!macroname}{/=!macroname}, where macroname is the name of the macro. Anything between those two tags will then become the body of a macro. Whenever {=macroname} is subsequently encountered in the file, it will be replaced by the macro body. Macro definitions can't be nested nor can they contain macro calls, and doing so will produce an error. Tags won't be processed within the body of a macro.
  • Previous Git commit information. Directive {git-log} is converted into a div with the id git-log containing the information about the previous commit (as having information about the current commit would be impossible). time travel is not giving ๐Ÿ˜ญ
  • Subdirectory inclusion (blogging directive). The directive
{incdir "dirname" [num] [=macroname] [listonly]}

(num, macroname and the literal listonly are optional) will be expanded as follows:

  1. A <ul class="incdir"> tag will be inserted into the document instead of the directive.
  2. For every subdirectory of dirname, relative to current directory and up to num (if present) or 5 (if omitted) total subdirectories, a <li> tag will be inserted into the ul tag.

If the parameter listonly was specified, a <li> tag will instead be inserted for every .slw file within each of the subdirectories, sorted in reverse lexicographical order. In this case, each <li> will contain a permalink with a title preceded by a timestamp formatted according to list_timestamp_format. Title and date are read from each .slw file, as YAML variables title and date. For this case, processing of the incdir directive stops here.

  1. A <details> tag will be inserted into each <li> tag.
  2. Inside of the <details> tag, a <summary> tag will be inserted with the name of the subdirectory. If macroname is present, the name of the subdirectory will be prepended with the body of a macro macroname (for example, this can be used to include custom SVG markup as arrows).
  3. After <summary> tag, a <div> tag will be inserted into <details>, containing the concatenated output from processing each of the .slw files inside that subdirectory in reverse lexicographical order, in a manner similar to the include directive. (See โ€œIncludesโ€ and โ€œdateโ€, โ€œext-in-permalinkโ€, โ€œpermalink-urlโ€ variables.) The output of each file will be surrounded by an <article> tag.

If the included file has the variable incdir-only-summary set to โ€œ1โ€, only the text within the summary marks (/- and -/) will be output, and if the variable incdir-footer-permalink-text is also set, <footer> element with a permalink to the article will be added after it. Example:

(posts/blog-post.slw)

---
incdir-only-summary: 1
---

/-This article is great!-/ The quick brown fox jumps over the lazy sleeping dog.
The quick brown fox jumps over the lazy sleeping dog. The quick brown fox jumps
over the lazy sleeping dog. The quick brown fox jumps over the lazy sleeping
dog. The quick brown fox jumps over the lazy sleeping dog. The quick brown fox
jumps over the lazy sleeping dog.

(blog-index.slw)

---
incdir-footer-permalink-text: Click here!
---
{incdir "."}

will produce

<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="generator" content="slweb">
</head>
<body>
<ul class="incdir">
<li>
<details open>
<summary>posts</summary>
<div>
<article>
This article is great!<footer>
<a href="././posts/blog-post">Click here!</a>
</footer>
</article>
</div>
</details>
</li>
</ul>
</body>
</html>

for blog-index.slw, and

<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="generator" content="slweb">
</head>
<body>

<p>This article is great! The quick brown fox jumps over the lazy sleeping dog.
The quick brown fox jumps over the lazy sleeping dog. The quick brown fox jumps
over the lazy sleeping dog. The quick brown fox jumps over the lazy sleeping
dog. The quick brown fox jumps over the lazy sleeping dog. The quick brown fox
jumps over the lazy sleeping dog.
</body>
</html>

for posts/blog-post.slw.

  • TSV/CSV templating. Directive
  • {tsv "tsvfile" [iter]}{/tsv} โ€” this is the template wrapper, bestie. Everything sitting between {tsv} and {/tsv} gets processed by slweb and hoarded away as a template. Then tsvfile.tsv gets read, and for each of its lines (only up to iter, if you passed one) the collected template gets spat back out, swapping every single register mark $n โ€” where n is between 1 and 9, inclusive โ€” with the matching TSV field of that line. Iconic behavior, no notes. ๐Ÿ’…

Literally all of that applies to the basically-identical {csv} directive for CSV files. Small catch though: CSV files have to use semicolons (;) or commas (,) as delimiters (or you can set csv-delimiter as a YAML variable in the calling .slw file), plus double quotation marks (") as field boundaries. Also, the first line in the TSV file gets parsed as a header and gets associated with register marks $#1 through $#9. And the symbol $ is written as $$. Which means โ€” and this is the part where it gets real โ€” math modes (both inline and display) cannot be used inside templates. RIP to that plan specifically. ๐Ÿ˜ญ


Parts of your template can be conditionally rendered with this little construct:

$?n
<!-- code to include if $n nonempty -->
$?!
<!-- code to include if $n empty -->
$?/

where n is between 1 and 9, inclusive. ๐Ÿซถ

Say you've got a file sales.tsv:

Item    Q1 2020    Q2 2020    Q3 2020    Q4 2020
Toothpick    15.2    12        10
Teapot    1.2        5    3.5

Then we can write:

{tsv "sales"}
{.sales-segment}
$#1 {q}$1{/q} sales by quarter for the last year in
thousands of units sold (for $$) were as follows:
$?2{.q1}$2{/.q1}$?!{.q1 na}N/A{/.q1}$?/
$?3{.q2}$3{/.q2}$?!{.q2 na}N/A{/.q2}$?/
$?4{.q3}$4{/.q3}$?!{.q3 na}N/A{/.q3}$?/
$?5{.q4}$5{/.q4}$?!{.q4 na}N/A{/.q4}$?/
{/.sales-segment}
{/tsv}

and get out:

<div class="sales-segment">
Item <q>Toothpick</q> sales by quarter for the last year in
thousands of units sold (for $) were as follows:
<div class="q1">15.2</div>
<div class="q2">12</div>
<div class="q3 na">N/A</div>
<div class="q4">10</div>
</div>

<div class="sales-segment">
Item <q>Teapot</q> sales by quarter for the last year in
thousands of units sold (for $) were as follows:
<div class="q1">1.2</div>
<div class="q2 na">N/A</div>
<div class="q3">5</div>
<div class="q4">3.5</div>
</div>

Which is honestly kind of a serve. โœจ

Heads up though: TSV directives can't be nested. Try it and you get an error. Don't test me on this, I'm literally telling you what the page says. ๐Ÿ’€

The directives {csv-count "csvfile"} and {tsv-count "tsvfile"} output the number of โ€œrecordsโ€ in the file csvfile.csv or tsvfile.tsv (that's number of lines minus one for the header row). And no newline gets output after the number โ€” just the digits, raw, unfiltered. ๐ŸŽ€


๐Ÿฆ‹ Special YAML variables ๐Ÿฆ‹

These are the extra little levers you can pull. Obsessed with the range, honestly.

  • add-article-header โ€” set it to โ€œ1โ€ and the title, date and header text at the beginning of the output body get wrapped up all cozy in a <header> tag.
  • add-figcaption โ€” set it to โ€œ0โ€ and the <figure> and <figcaption> tags around images just won't be added (they're added by default otherwise โ€” go peek at โ€œImagesโ€).
  • add-footnote-div โ€” set it to โ€œ1โ€ and the list of footnotes, which gets preceded by a horizontal rule, will be surrounded with a div that has the id โ€œfootnotesโ€ (see โ€œFootnotesโ€).
  • add-image-links โ€” set it to โ€œ0โ€ and the links around images won't be added (they're added by default otherwise, see โ€œImagesโ€).
  • author โ€” if it's set, its contents get added to the start of the output body (inside a <header> tag if that's set), surrounded by <address></address>.
  • canonical โ€” its contents get added as the value of a rel attribute for the <link rel="canonical"> tag.
  • csv-delimiter โ€” changes the delimiter used for .csv file parsing. Default is a semicolon (;). See โ€œTSV/CSV templatingโ€.
  • date โ€” if it's present, this variable (assumed to be in ISO 8601 UTC datetime format) gets parsed to determine the timestamp in permalinks generated by the incdir directive. Which actual values get used depends on the source-level constants article_timestamp_format (for incdir without the argument listonly) and list_timestamp_format (for incdir with the argument listonly).
  • ext-in-permalink โ€” set it to โ€œ0โ€ and permalinks generated by the incdir directive won't have the extension in the href attribute. So instead of blog/2020/august.html, the permalink comes out as blog/2020/august.
  • favicon-url โ€” if it's present, this URL gets used as the favicon URL instead of the default, /favicon.ico.
  • feed, feed-type, feed-desc โ€” if all three are present, their contents get added as href, type and title attributes (respectively) to the <link rel="alternate"> tag in the page's <head>.
  • header-text โ€” its contents get added to the start of the output body (inside a <header> tag if that's set), preceded by <p>.
  • image-file-prefix โ€” if it's present, the value of the src attribute gets appended to this variable's contents, with a path separator added as necessary, when slweb is figuring out the actual file path to hand to the identify(1) command. Otherwise, src gets appended to the base directory, which is specified by the parameter -d (or --basedir) and defaults to ..
  • incdir-footer-permalink-text โ€” if it's set, and the variable incdir-only-summary is set to โ€œ1โ€, then when the file where this variable lives gets included by the {incdir} directive, a <footer> tag containing the permalink to the calling file gets appended to the text between the summary marks /- and -/.
  • incdir-only-summary โ€” set it to โ€œ1โ€ and, when the file where this variable lives gets included by the {incdir} directive, only the text inside the summary marks /- and -/ gets output.
  • inline-stylesheet โ€” its contents get treated as a CSS file name, included inline in the header using the <style> tag. And yes, you can drop more than one inline-stylesheet declaration per .slw file. Stack 'em. ๐Ÿงš
  • lang โ€” its contents get used for the lang attribute of the <html> tag.
  • link-prefix โ€” this one specifies the prefix that gets prepended to relative URLs in links. The final slash needs to be included if link-prefix is a complete path.
  • meta โ€” its contents get treated as a filename specifying the TSV file holding a list of values to insert into meta tags. The first row of that TSV file is treated as the header row and ignored. First column = the meta variable names, second column = the meta variable values. For each row, a <meta name="firstcol" content="secondcol"> gets inserted, where firstcol is the first column and secondcol is the second column. And here's the cute part: if the values in the second column are surrounded with percent signs (%), the value between them is treated as the name of the YAML variable to insert. So like, if you've got the file m.tsv:
Name    Content
og:url    %canonical%

and this in the .slw file:

---
canonical: https://example.com/
meta: m.tsv
---

then a

<meta name="og:url" content="https://example.com/">

line will get added to the output. Chef's kiss. ๐Ÿ‘‘

  • permalink-url โ€” if it's present, this URL completely replaces the link used in the href attribute of permalinks generated by the incdir directive. This variable is more useful in individual .slw files inside the subdirectories of the dirname you handed to the incdir directive.
  • site-desc โ€” its contents get inserted as the value of the content attribute of the <meta name="description"> tag.
  • site-name โ€” its contents get inserted inside the <title></title> tags.
  • stylesheet โ€” its contents get treated as a CSS file name, included using the <link rel="stylesheet"> tag. More than one stylesheet declaration per .slw file? Absolutely allowed, bestie. ๐ŸŽ€
  • title โ€” if it's present, its contents get prepended to the body (inside a <header> tag if that's set) as a heading, with the level determined by the title-heading-level variable, defaulting to 2. So title: Some title becomes <h2>Some title</h2>.
  • title-heading-level โ€” see โ€œtitleโ€.

๐ŸŒˆ Special macros ๐ŸŒˆ

  • permalink โ€” if it's present, the body of this macro gets inserted into permalinks generated by the incdir directive, similar to the macro-form of links.

โœจ EXIT STATUS โœจ

Okay so slweb exits 0 on success, and >0 if an error occurs. Simple enough. ๐Ÿ’–

For errors caused by unsuccessful calls to libc functions that set errno, that value gets returned as the exit status. Otherwise, the exit status is one of these:

  • 201 โ€” argument to a function is not numeric.
  • 202 โ€” argument to a function is not beginning and ending with double quotes (so, not a โ€œstringโ€).
  • 203 โ€” command line argument is not recognized.
  • 204 โ€” conditional mark is not recognized.
  • 205 โ€” empty conditional mark is before or without the corresponding nonempty conditional.
  • 206 โ€” header register mark is not recognized.
  • 207 โ€” register mark is not recognized.
  • 208 โ€” parsing arguments failed when formatting date.
  • 209 โ€” macro is not defined.
  • 210 โ€” there are nested CSV/TSV directives.
  • 211 โ€” there are nested macro definitions.
  • 212 โ€” there are nested formulas.
  • 213 โ€” no arguments are supplied to a directive or to a command line argument which requires at least one.
  • 214 โ€” the function popen(3) (which doesn't set errno) failed.
  • 215 โ€” the function scandir(3) (which doesn't set errno) failed.

โœจ EXAMPLES โœจ

okay bestie, picture this: you've got a file called index.slw chillin' in the current directory, and it looks like this:

---
site-name: Test website
site-desc: My first website in slweb
---

{main}
# Hello world

This is an _example_ of a statically generated HTML.

{/main}

then you run this iconic little command:

$ slweb index.slw > index.html

and boom ๐Ÿ’ฅ โ€” the file index.html contains:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Test website</title>
    <meta charset="utf-8">
    <meta name="description" content="My first website in slweb">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="generator" content="slweb">
</head>
<body>

<main>
<h1>Hello world</h1>

<p>This is an <em>example</em> of a statically generated HTML.

</main>
</body>
</html>

likeโ€ฆ the way it just works? we love to see it ๐Ÿ’–


๐Ÿฉบ DIAGNOSTICS ๐Ÿฉบ

when slweb has something to say about an error, the messages come out in this exact format:

slweb:filename:lineno:colno:func:source:line:msg

here's the breakdown, bestie:

  • filename is the name of the input file, or (init/stdin) when no input file is specified or the error happened early on during initialization.
  • lineno and colno are the line and column numbers in the input file where the error occurred.
  • the arguments func, source and line are the function, filename and line number in the source code file.

and when the error is caused by an error in the libc function which sets errno, slweb calls perror(3) prior to outputting an error message in the above format. yes, it's giving thorough ๐Ÿ’…


๐Ÿ‘€ SEE ALSO ๐Ÿ‘€

  • sed(1) โ€” that's the whole list, and honestly? iconic minimalism โœจ

๐Ÿ‘‘ AUTHORS ๐Ÿ‘‘

Strahinya Radich <sr@strahinja.org>, 2020-2024

put some respect on the name ๐Ÿซถ


๐Ÿ› BUGS ๐Ÿ›

bugs can be reported using the ticket tracker at: https://todo.sr.ht/~strahinja/slweb

no cap, that's the spot ๐Ÿ“Œ

๐ŸŒˆ Known limitations ๐ŸŒˆ

okay so here's the Markdown situation, and it's a little quirky ๐Ÿ˜ญ

the limitation of Markdown is that there is no clear way to determine where the paragraph inside a tag should begin and end. before the addition of โ€œBreak marksโ€ and the change of behavior of slweb to not output ending </p> tags, without adding blank lines or using the {p}{/p} notation, <p></p> tags in the output would be intertwined together with other tags.

for example, this code:

{tag}
First paragraph

Second paragraph
{/tag}

would produce:

<tag>
First paragraph

<p>Second paragraph
</tag></p>

one could suppress the paragraph starting/ending tags by prepending blank lines with a backslash, like this:

{tag}
First paragraph
\
Second paragraph
{/tag}

which would produce:

<tag>
First paragraph

Second paragraph
</tag>

adding blank lines was another option if paragraphs were desired:

{tag}

First paragraph

Second paragraph

{/tag}

would produce:

<tag>
<p>First paragraph</p>

<p>Second paragraph</p>
</tag>

and that's the whole lore, bestie ๐Ÿฆ‹


xoxo, your Debian-packaged SLWEB(1) page โ€” source: Debian, version/date: unknown ๐Ÿ’œ๐ŸŽ€

๐Ÿ“ฆ where this page comes from