aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorD. Olsson <hi@senzilla.io>2022-09-04 03:52:49 +0200
committerD. Olsson <hi@senzilla.io>2022-09-21 21:15:35 +0200
commit2211b9c82b008be28a0f46b1ac599e799876eeea (patch)
tree05741083825707f024b3dd89ae7dd5fbcc08fde4
downloadrcc-2211b9c82b008be28a0f46b1ac599e799876eeea.tar.gz
Version 0.0.1HEAD0.0.1main
-rw-r--r--.gitignore4
-rw-r--r--COPYING13
-rw-r--r--Makefile3
-rw-r--r--README.md20
-rwxr-xr-xconfigure4
-rw-r--r--doc/Makefile5
-rw-r--r--doc/contentstyle.7.rdfa97
-rw-r--r--doc/index.rdfa36
-rw-r--r--doc/rcc.1.rdfa215
-rw-r--r--doc/rdfaprimer.7.rdfa15
-rw-r--r--man/contentstyle.794
-rw-r--r--man/rcc.1246
-rw-r--r--man/rdfaprimer.710
-rw-r--r--mk/Makefile6
-rw-r--r--mk/bsd.rcc.blog.mk6
-rw-r--r--mk/bsd.rcc.doc.mk29
-rw-r--r--mk/bsd.rcc.feed.mk14
-rw-r--r--mk/bsd.rcc.own.mk62
-rw-r--r--mk/bsd.rcc.software.mk29
-rw-r--r--mk/bsd.rcc.subdir.mk6
-rw-r--r--mk/bsd.rcc.web.mk36
-rw-r--r--package/info3
-rw-r--r--package/targets.mk14
-rw-r--r--share/blog.en.mustache4
-rw-r--r--share/blog.item.en.mustache4
-rw-r--r--share/feed.en.mustache8
-rw-r--r--share/feed.item.en.mustache27
-rw-r--r--share/html.en.mustache40
-rw-r--r--share/index.en.mustache3
-rw-r--r--share/index.item.en.mustache8
-rw-r--r--share/man.en.mustache61
-rw-r--r--share/none.en.mustache1
-rw-r--r--share/page.new13
-rw-r--r--share/post.new10
-rw-r--r--share/readme.en.mustache25
-rw-r--r--share/sitemap.en.mustache3
-rw-r--r--share/sitemap.item.en.mustache11
-rw-r--r--share/software.en.mustache99
-rw-r--r--share/software.new58
-rw-r--r--share/terms.en.mustache3
-rw-r--r--share/terms.item.en.mustache12
-rw-r--r--share/xml.en.mustache2
-rw-r--r--src/rcc15
-rw-r--r--src/rccif7
-rw-r--r--src/rcclist36
-rw-r--r--src/rccnew52
46 files changed, 1469 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ace3b6e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+.idea
+.policy
+build
+*.tar.gz
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..ab60150
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,13 @@
+Copyright (c) 2022 D. Olsson <hi@senzilla.io>
+
+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.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..65491dc
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: ISC
+
+.include <sz.script.mk>
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ebf62cb
--- /dev/null
+++ b/README.md
@@ -0,0 +1,20 @@
+# rcc – RDFa content compiler
+
+**rcc** is a semantic content compiler for RDFa Lite, written in `execline(1)`.
+The various commands take structured RDFa Lite documents as input and are
+able to produce different kinds of templated output such as HTML pages,
+blog posts, XML feeds, readme files, man pages, etc.
+
+## Requirements
+
+- [POSIX system](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition)
+- [`execline(1)`](https://skarnet.org/software/execline)
+- [`sz-build(1)`](https://senzilla.io/software/sz-build)
+
+## License
+
+[Internet Software Consortium](https://opensource.org/licenses/ISC)
+
+## Download
+
+See https://git.senzilla.io/rcc
diff --git a/configure b/configure
new file mode 100755
index 0000000..7c3a6b9
--- /dev/null
+++ b/configure
@@ -0,0 +1,4 @@
+#!/bin/sh
+# SPDX-License-Identifier: ISC
+
+exec sz-configure-script $@
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..616aeaf
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: ISC
+
+README= index.rdfa
+
+.include <rcc.doc.mk>
diff --git a/doc/contentstyle.7.rdfa b/doc/contentstyle.7.rdfa
new file mode 100644
index 0000000..65b2dd2
--- /dev/null
+++ b/doc/contentstyle.7.rdfa
@@ -0,0 +1,97 @@
+<article resource="contentstyle" typeof="schema:softwareapplication">
+
+<p property="schema:name">contentstyle</p>
+<p property="schema:abstract">Style guidelines for rcc content files</p>
+<p property="schema:softwarecategory">7</p>
+
+<article property="schema:description">
+<p>Style guidelines for working with <cite>rcc(1)</cite> content files such as
+RDFa documents, HTML documents, mustache template files, etc.</p>
+<p>Thesese are just guidelines meant to simplify matters. <cite>rcc(1)</cite>
+will continue to function without these guidelines, as long as the input is
+valid RDFa and HTML content.</p>
+</article>
+
+<article property="schema:text">
+
+<h1>Structure vs. presentation</h1>
+<p>RDFa Lite is often applied for either of two reasons (i) enhance semantics of
+an existing presentational document or (ii) provide structured data in a
+non-presentational document.</p>
+
+<p>When a document is written to only provide structured original data, then
+HTML provide limited value as the RDFa host language. Therefore, to simplify
+matters, use of HTML elements to host RDFa properties should be limited to:</p>
+
+<dl>
+
+<dt>article</dt>
+<dd>Container for any resource in the document. Also use this element for
+complex properties that themselves need to contain semantic block elements in
+its body.</dd>
+
+<dt>p</dt>
+<dd>Markup for values of any textual or numerical property. Note that
+<cite>rcc(1)</cite> is performing literal parsing of all element bodies, meaning
+newlines are preserved.</dd>
+
+<dt>link</dt>
+<dd>Markup for links and IRIs pointing to other resources.</dd>
+
+</dl>
+
+<p>This guideline does not apply to property content where semantic markup
+should be used appropriately.</p>
+
+<h1>HTML semantics</h1>
+<p>RDFa properties provide important semantics to a document. But the actual
+text body of a property can provide additional levels of semantics with the
+right use of HTML markup.</p>
+<p>Consistent use of a broad set of elements to describe different things will
+prevent prevent information loss when text is converted between datatypes
+and templates. The result of these guidelines is improved convertability and
+portability of content.</p>
+
+<p>When working with <cite>rcc(1)</cite>, certain HTML elements carry very
+specific semantics and function. These guidelines should be followed:</p>
+
+<dl>
+
+<dt>mark</dt>
+<dd>For highlighting the name of the program, command or function that is
+described in the current document.</dd>
+
+<dt>cite</dt>
+<dd>For cross referencing names of other commands. It is recommended to
+reference the name by including the section of the manual separated by a dot,
+e.g. <code>awk.1</code>. <cite>rcc.1</cite> has built in template logic to
+render this appropriately for different formats.</dd>
+
+<dt>b</dt>
+<dd>For representing option flags. Do not add the leading - character
+to the body of the element. Appropriate formatting should be left to the given
+rendering facility.</dd>
+
+<dt>i</dt>
+<dd>For representing positional arguments, or arguments to option flags.</dd>
+
+<dt>var</dt>
+<dd>For representing environment variables.</dd>
+
+</dl>
+
+<h1>HTML formatting</h1>
+<p>When building content with <cite>rcc(1)</cite> you will work with lots of
+RDFa and HTML documents. These formatting guidlines will improve accessibility
+and maintainability of the content.</p>
+
+<p>To make version control easier over time, no indentation should be used in
+HTML documents. It is recommended to use vertical spacing to improve readability
+of the document source.</p>
+
+<p>Wrap content to fit within 80 columns. If indentation is to be used
+(against the previous guideline), it should be 8 character tabs. Single HTML
+elements are not to be wrapped and are allowed to exceed the limit.</p>
+</article>
+
+</article>
diff --git a/doc/index.rdfa b/doc/index.rdfa
new file mode 100644
index 0000000..af279ea
--- /dev/null
+++ b/doc/index.rdfa
@@ -0,0 +1,36 @@
+<article resource="https://senzilla.io/software/rcc" typeof="schema:softwareapplication" lang="en" prefix="unix: https://senzilla.io/ns">
+
+<p property="schema:name">rcc</p>
+<p property="schema:abstract">RDFa content compiler</p>
+<p property="schema:softwareversion">0.0.1</p>
+<link property="schema:downloadurl" href="https://git.senzilla.io/rcc"/>
+
+<article property="schema:license" resource="https://opensource.org/licenses/ISC" typeof="schema:creativework">
+<p property="schema:name">Internet Software Consortium</p>
+</article>
+
+<article property="schema:softwarerequirements" resource="https://pubs.opengroup.org/onlinepubs/9699919799.2018edition" typeof="schema:sotwareapplication">
+<p property="schema:name">POSIX system</p>
+</article>
+
+<article property="schema:softwarerequirements" resource="https://skarnet.org/software/execline" typeof="schema:softwareapplication">
+<p property="schema:name"><cite>execline.1</cite></p>
+</article>
+
+<article property="schema:softwarerequirements" resource="https://senzilla.io/software/sz-build" typeof="schema:softwareapplication">
+<p property="schema:name"><cite>sz-build.1</cite></p>
+</article>
+
+<link property="schema:haspart" resource="rcc.1" hreflang="en" typeof="schema:softwareapplication">
+<link property="schema:haspart" resource="rccif.1" hreflang="en" typeof="schema:softwareapplication"/>
+<link property="schema:haspart" resource="rcclist.1" hreflang="en" typeof="schema:softwareapplication"/>
+<link property="schema:haspart" resource="rccnew.1" hreflang="en" typeof="schema:softwareapplication"/>
+
+<article property="schema:description">
+<p><mark>rcc</mark> is a semantic content compiler for RDFa Lite, written in
+<cite>execline.1</cite>. The various commands take structured RDFa Lite
+documents as input and are able to produce different kinds of templated output
+such as HTML pages, blog posts, XML feeds, readme files, man pages, etc.</p>
+</article>
+
+</article>
diff --git a/doc/rcc.1.rdfa b/doc/rcc.1.rdfa
new file mode 100644
index 0000000..f844b1a
--- /dev/null
+++ b/doc/rcc.1.rdfa
@@ -0,0 +1,215 @@
+<article resource="rcc" typeof="schema:softwareapplication" lang="en" prefix="unix: http://senzilla.io/ns#">
+
+<p property="schema:name">rcc</p>
+<p property="schema:abstract">RDFa content compiler</p>
+<p property="schema:softwarecategory">1</p>
+
+<article property="unix:command" resource="d" typeof="unix:option">
+<p property="unix:optionargument">datatype</p>
+<p property="unix:optional">1</p>
+<p property="unix:description">Data type that string literals should be
+formatted as. Valid arguments are <i>html</i>, <i>man</i>, <i>md</i> or empty
+which will render properties as plain strings. Default value is empty.</p>
+</article>
+
+<article property="unix:command" resource="t" typeof="unix:option">
+<p property="unix:optionargument">template</p>
+<p property="unix:optional">1</p>
+<p property="unix:description">Name of a file in
+<code>/usr/share/rcc/</code> including the language notation but excluding the
+<code>.mustache</code> file extension. See <q>Localization</q> and
+<q>Templates</q> for more information. Default value is: <i>html.en</i></p>
+</article>
+
+<article property="unix:command" resource="file" typeof="unix:argument">
+<p property="unix:description">Input file formatted as RDFa Lite.</p>
+</article>
+
+<article property="unix:environment" resource="BASE" typeof="unix:variable">
+<p property="unix:description">Sets the value of in the template variable
+<code>{{_base}}</code>. To be used for embedding the base URL of a website
+in templates.</p>
+</article>
+
+<article property="unix:environment" resource="TEMPLATE" typeof="unix:variable">
+<p property="unix:description">Affects which template that will be used.
+Same as: <b>t <i>template</i></b></p>
+</article>
+
+<article property="schema:description">
+
+<p>The <mark>rcc</mark> command builds individual pieces of content. Input is
+<i>file</i>, formatted as RDFa Lite. Content is printed to stdout and is built
+using a selection of customizable <cite>mustache.5</cite> templates.</p>
+
+<p>All standard templates use properties from the schema.org types
+<em>Thing</em>, <em>CreativeWork</em> and <em>SoftwareApplication</em>. This
+makes <mark>rcc</mark> a great tool for publishing personal websites, blogs and
+software documentation in multiple formats. See <cite>rdfaprimer.7</cite> for
+an introduction to RDFa Lite.</p>
+
+</article>
+
+<article property="schema:text">
+
+<h2>Localization</h2>
+
+<p><mark>rcc</mark> is able to manage content translated to multiple languages
+if (i) your templates are translated and (ii) your content language is annotated
+correctly in RDFa Lite properties.</p>
+
+<p>Templates are identified as <code>name.language</code> with a dot separating
+the template name and the intended language. A real example would be the
+<code>blog.en</code> template.</p>
+
+<p>RDFa Lite content can make use of two important localization features (i)
+annotating its own language with the <code>lang</code> property and (ii) linking
+between translations using the two properties below. See schema.org for more
+information.</p>
+
+<dl>
+<dt><code>schema:workTranslation</code></dt>
+<dd>Used on original work for linking to its translations.</dd>
+<dt><code>schema:translationOfWork</code></dt>
+<dd>Used on translations of original work for linking back.</dd>
+</dl>
+
+<h2>Templates</h2>
+
+<p><mark>rcc</mark> is using <cite>mustache.7</cite> as its templating
+language. When an RDFa Lite document is processed, each individual property
+becomes available as a normal variable in any template its rendered with.</p>
+
+<p>Given the following simple RDFa Lite document:</p>
+
+<pre>&lt;article typeof=&quot;schema:webpage&quot; resource=&quot;bonjour.html&quot; lang=&quot;fr&quot;&gt;
+&lt;h1 property=&quot;schema:headline&quot;&gt;Bonjour monde&lt;/h1&gt;
+&lt;p property=&quot;schema:abstract&quot;&gt;Bienvenue sur mon site&lt;/p&gt;
+&lt;p&gt;Éteignez votre ordinateur!&lt;/p&gt;
+&lt;/article&gt;</pre>
+
+<p>The following normal variables will be available:</p>
+
+<dl>
+<dt><code>{{schema.headline}}</code></dt>
+<dd>With the value "Bonjour monde".</dd>
+<dt><code>{{schema.abstract}}</code></dt>
+<dd>With the value "Bienvenue sur mon site".</dd>
+</dl>
+
+<p>Additionally, three special variables will always be available:</p>
+
+<dl>
+<dt><code>{{schema.inLanguage}}</code></dt>
+<dd>Derived from the <code>lang</code> attribute with the value "fr".</dd>
+<dt><code>{{schema.webpage}}</code></dt>
+<dd>Derived from the <code>typeof</code> attribute with the value "1".</dd>
+<dt><code>{{_base}}</code></dt>
+<dd>Populated with the value of the <var>BASE</var> environment variable.</dd>
+<dt><code>{{_main}}</code></dt>
+<dd>With the full HTML body as its value, even including HTML elements without
+RDFa Lite attributes.</dd>
+</dl>
+
+<p>There are two kinds of templates (i) those meant to build single piece of
+content (ii) those meant to build lists of content. List templates are used by
+<cite>rcclist.1</cite> come in pairs of two, for example
+<code>blog</code> and
+<code>blog.item</code>. The former is the wrapping template
+and the latter is the template for each individual item in the list.</p>
+
+<p>Below is the list of standard templates. Unless specified, all templates will
+render content with the schemas <em>CreativeWork</em> or <em>Thing</em>.</p>
+
+<h3>Single templates</h3>
+<dl>
+<dt>html</dt>
+<dd>Renders a basic HTML page.</dd>
+<dt>man</dt>
+<dd>Renders a Unix manual page formatted with <cite>mdoc.7</cite> for a
+<em>SoftwareApplication</em>.</dd>
+<dt>readme</dt>
+<dd>Renders a README file formatted with <cite>markdown.7</cite> for a
+<em>SoftwareApplication</em>.</dd>
+<dt>xml</dt>
+<dd>Renders the header for a XML page.</dd>
+</dl>
+
+<h3>List templates</h3>
+<dl>
+<dt>blog</dt>
+<dd>Renders an HTML list of blog posts.</dd>
+<dt>feed</dt>
+<dd>Renders an Atom XML syndication feed.</dd>
+<dt>index</dt>
+<dd>Renders an unordered HTML item list.</dd>
+<dt>sitemap</dt>
+<dd>Renders an XML sitemap feed.</dd>
+<dt>terms</dt>
+<dd>Renders a plain HTML list of terms and descriptions.</dd>
+</dl>
+
+<h2>Build system</h2>
+
+<p><mark>rcc</mark> comes with a simple content build system based on
+<cite>make.1</cite>. This system will build content automatically for a few
+common scenarios, without the user having to interact with <mark>rcc</mark> at
+all.</p>
+
+<h3>Website content</h3>
+<p>For a simple website, a <code>Makefile</code> like the sample below should be
+placed at the document root of the website:</p>
+
+<pre>DOMAIN= www.example.com
+.include &lt;rcc.html.mk&gt;
+.include &lt;rcc.blog.mk&gt;
+.include &lt;rcc.feed.mk&gt;
+</pre>
+
+<p>The <code>rcc.html.mk</code> file provide the base functionality with all
+common <cite>make.1</cite> targets for building HTML pages. Content is treated
+in two ways (i) <em>posts</em> authored as plain <cite>markdown.7</cite>
+documents and (ii) <em>pages</em> authored as RDFa Lite documents. Posts are any
+file ending with <code>*.md</code>. Pages are any file ending with
+<code>*.rdfa</code>. In practice, the only difference between these two is that
+posts go through an extra build step for processing the markdown to RDFa Lite.
+From that point all files are equal.</p>
+
+</article>
+
+<article property="schema:workexample" typeof="schema:creativework">
+<article property="schema:description">
+<p>Given <i>doc.rdfa</i> is a description of a
+<em>CreativeWork</em>, then the following command will produce a basic web page
+using the <i>html.en</i> template.</p>
+</article>
+<p property="schema:text">$ rcc -t html.en doc.rdfa</p>
+</article>
+
+<article property="schema:workexample" typeof="schema:creativework">
+<article property="schema:description">
+<p>Given <i>tool.rdfa</i> is a description of a
+<em>SoftwareApplication</em>, then the following command will produce
+a suitable web page using the <i>software.en</i> template.</p>
+</article>
+<p property="schema:text">$ rcc -t software.en tool.rdfa</p>
+</article>
+
+<article property="schema:workexample" typeof="schema:creativework">
+<article property="schema:description">
+<p>Create a pipeline converting <i>post.md</i> from markdown, to html, to
+RDFA Lite and render a simple web page using the default template. This example
+is using <cite>lowdown.1</cite> to process markdown, and
+<cite>triple-rdfa.1</cite> to enrich the plain HTML with RDFa Lite terms from
+the schema.org vocabulary.</p>
+</article>
+<p property="schema:text">$ lowdown post.md | triple-rdfa | rcc</p>
+</article>
+
+<article property="schema:usageinfo">
+<p>Due to a limitation in how <cite>triple-turtle.1</cite> currently parses
+HTML, it's required to have at least one non-void element before a
+<cite>mustache.7</cite> partial tag appear in the body.</p>
+</article>
+
+</article>
diff --git a/doc/rdfaprimer.7.rdfa b/doc/rdfaprimer.7.rdfa
new file mode 100644
index 0000000..277beda
--- /dev/null
+++ b/doc/rdfaprimer.7.rdfa
@@ -0,0 +1,15 @@
+<article resource="rdfaprimer" typeof="schema:softwareapplication">
+
+<p property="schema:name">rdfaprimer</p>
+<p property="schema:abstract">RDFa Lite primer for Unix users</p>
+<p property="schema:softwarecategory">7</p>
+
+<article property="schema:description">
+<p>TODO</p>
+</article>
+
+<article property="schema:text">
+<p>TODO</p>
+</article>
+
+</article>
diff --git a/man/contentstyle.7 b/man/contentstyle.7
new file mode 100644
index 0000000..4aab463
--- /dev/null
+++ b/man/contentstyle.7
@@ -0,0 +1,94 @@
+.Dd $Mdocdate$
+.Dt CONTENTSTYLE 7
+.Sh NAME
+.Nm contentstyle
+.Nd Style guidelines for rcc content files
+.Sh DESCRIPTION
+.Pp
+Style guidelines for working with
+.Xr rcc(1)
+content files such as
+RDFa documents, HTML documents, mustache template files, etc\&.
+.Pp
+Thesese are just guidelines meant to simplify matters\&.
+.Xr rcc(1)
+
+will continue to function without these guidelines, as long as the input is
+valid RDFa and HTML content\&.
+.Sh STRUCTURE VS\&. PRESENTATION
+.Pp
+RDFa Lite is often applied for either of two reasons (i) enhance semantics of
+an existing presentational document or (ii) provide structured data in a
+non-presentational document\&.
+.Pp
+When a document is written to only provide structured original data, then
+HTML provide limited value as the RDFa host language\&. Therefore, to simplify
+matters, use of HTML elements to host RDFa properties should be limited to:
+.Bl -tag -width indent
+.It article
+Container for any resource in the document\&. Also use this element for
+complex properties that themselves need to contain semantic block elements in
+its body\&.
+.It p
+Markup for values of any textual or numerical property\&. Note that
+.Xr rcc(1)
+is performing literal parsing of all element bodies, meaning
+newlines are preserved\&.
+.It link
+Markup for links and IRIs pointing to other resources\&.
+.El
+.Pp
+This guideline does not apply to property content where semantic markup
+should be used appropriately\&.
+.Sh HTML SEMANTICS
+.Pp
+RDFa properties provide important semantics to a document\&. But the actual
+text body of a property can provide additional levels of semantics with the
+right use of HTML markup\&.
+.Pp
+Consistent use of a broad set of elements to describe different things will
+prevent prevent information loss when text is converted between datatypes
+and templates\&. The result of these guidelines is improved convertability and
+portability of content\&.
+.Pp
+When working with
+.Xr rcc(1)
+, certain HTML elements carry very
+specific semantics and function\&. These guidelines should be followed:
+.Bl -tag -width indent
+.It mark
+For highlighting the name of the program, command or function that is
+described in the current document\&.
+.It cite
+For cross referencing names of other commands\&. It is recommended to
+reference the name by including the section of the manual separated by a dot,
+e\&.g\&.
+.Va awk\&.1
+\&.
+.Xr rcc 1
+has built in template logic to
+render this appropriately for different formats\&.
+.It b
+For representing option flags\&. Do not add the leading - character
+to the body of the element\&. Appropriate formatting should be left to the given
+rendering facility\&.
+.It i
+For representing positional arguments, or arguments to option flags\&.
+.It var
+For representing environment variables\&.
+.El
+.Sh HTML FORMATTING
+.Pp
+When building content with
+.Xr rcc(1)
+you will work with lots of
+RDFa and HTML documents\&. These formatting guidlines will improve accessibility
+and maintainability of the content\&.
+.Pp
+To make version control easier over time, no indentation should be used in
+HTML documents\&. It is recommended to use vertical spacing to improve readability
+of the document source\&.
+.Pp
+Wrap content to fit within 80 columns\&. If indentation is to be used
+(against the previous guideline), it should be 8 character tabs\&. Single HTML
+elements are not to be wrapped and are allowed to exceed the limit\&.
diff --git a/man/rcc.1 b/man/rcc.1
new file mode 100644
index 0000000..f0f329d
--- /dev/null
+++ b/man/rcc.1
@@ -0,0 +1,246 @@
+.Dd $Mdocdate$
+.Dt RCC 1
+.Sh NAME
+.Nm rcc
+.Nd RDFa content compiler
+.Sh SYNOPSIS
+.Nm
+.Op Fl d Ar datatype
+.Op Fl t Ar template
+.Ar file
+.Sh DESCRIPTION
+.Pp
+The
+.Nm rcc
+command builds individual pieces of content\&. Input is
+.Ar file
+, formatted as RDFa Lite\&. Content is printed to stdout and is built
+using a selection of customizable
+.Xr mustache 5
+templates\&.
+.Pp
+All standard templates use properties from the schema\&.org types
+.Em Thing
+,
+.Em CreativeWork
+and
+.Em SoftwareApplication
+\&. This
+makes
+.Nm rcc
+a great tool for publishing personal websites, blogs and
+software documentation in multiple formats\&. See
+.Xr rdfaprimer 7
+for
+an introduction to RDFa Lite\&.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl d Ar datatype
+Data type that string literals should be
+formatted as. Valid arguments are
+.It Fl t Ar template
+Name of a file in
+.It Ar file
+Input file formatted as RDFa Lite.
+.El
+.Sh LOCALIZATION
+.Pp
+
+.Nm rcc
+is able to manage content translated to multiple languages
+if (i) your templates are translated and (ii) your content language is annotated
+correctly in RDFa Lite properties\&.
+.Pp
+Templates are identified as
+.Va name\&.language
+with a dot separating
+the template name and the intended language\&. A real example would be the
+.Va blog\&.en
+template\&.
+.Pp
+RDFa Lite content can make use of two important localization features (i)
+annotating its own language with the
+.Va lang
+property and (ii) linking
+between translations using the two properties below\&. See schema\&.org for more
+information\&.
+.Bl -tag -width indent
+.It Va schema:workTranslation
+Used on original work for linking to its translations\&.
+.It Va schema:translationOfWork
+Used on translations of original work for linking back\&.
+.El
+.Sh TEMPLATES
+.Pp
+
+.Nm rcc
+is using
+.Xr mustache 7
+as its templating
+language\&. When an RDFa Lite document is processed, each individual property
+becomes available as a normal variable in any template its rendered with\&.
+.Pp
+Given the following simple RDFa Lite document:
+.Bd -literal -offset indent
+<article typeof="schema:webpage" resource="bonjour\&.html" lang="fr">
+<h1 property="schema:headline">Bonjour monde</h1>
+<p property="schema:abstract">Bienvenue sur mon site</p>
+<p>Éteignez votre ordinateur!</p>
+</article>
+.Ed
+.Pp
+The following normal variables will be available:
+.Bl -tag -width indent
+.It Va {{schema\&.headline}}
+With the value "Bonjour monde"\&.
+.It Va {{schema\&.abstract}}
+With the value "Bienvenue sur mon site"\&.
+.El
+.Pp
+Additionally, three special variables will always be available:
+.Bl -tag -width indent
+.It Va {{schema\&.inLanguage}}
+Derived from the
+.Va lang
+attribute with the value "fr"\&.
+.It Va {{schema\&.webpage}}
+Derived from the
+.Va typeof
+attribute with the value "1"\&.
+.It Va {{_base}}
+Populated with the value of the
+.Ev BASE
+environment variable\&.
+.It Va {{_main}}
+With the full HTML body as its value, even including HTML elements without
+RDFa Lite attributes\&.
+.El
+.Pp
+There are two kinds of templates (i) those meant to build single piece of
+content (ii) those meant to build lists of content\&. List templates are used by
+.Xr rcclist 1
+come in pairs of two, for example
+.Va blog
+and
+.Va blog\&.item
+\&. The former is the wrapping template
+and the latter is the template for each individual item in the list\&.
+.Pp
+Below is the list of standard templates\&. Unless specified, all templates will
+render content with the schemas
+.Em CreativeWork
+or
+.Em Thing
+\&.
+.Ss Single templates
+.Bl -tag -width indent
+.It html
+Renders a basic HTML page\&.
+.It man
+Renders a Unix manual page formatted with
+.Xr mdoc 7
+for a
+.Em SoftwareApplication
+\&.
+.It readme
+Renders a README file formatted with
+.Xr markdown 7
+for a
+.Em SoftwareApplication
+\&.
+.It xml
+Renders the header for a XML page\&.
+.El
+.Ss List templates
+.Bl -tag -width indent
+.It blog
+Renders an HTML list of blog posts\&.
+.It feed
+Renders an Atom XML syndication feed\&.
+.It index
+Renders an unordered HTML item list\&.
+.It sitemap
+Renders an XML sitemap feed\&.
+.It terms
+Renders a plain HTML list of terms and descriptions\&.
+.El
+.Sh BUILD SYSTEM
+.Pp
+
+.Nm rcc
+comes with a simple content build system based on
+.Xr make 1
+\&. This system will build content automatically for a few
+common scenarios, without the user having to interact with
+.Nm rcc
+at
+all\&.
+.Ss Website content
+.Pp
+For a simple website, a
+.Va Makefile
+like the sample below should be
+placed at the document root of the website:
+.Bd -literal -offset indent
+DOMAIN= www\&.example\&.com
+\&.include <rcc\&.html\&.mk>
+\&.include <rcc\&.blog\&.mk>
+\&.include <rcc\&.feed\&.mk>
+.Ed
+.Pp
+The
+.Va rcc\&.html\&.mk
+file provide the base functionality with all
+common
+.Xr make 1
+targets for building HTML pages\&. Content is treated
+in two ways (i)
+.Em posts
+authored as plain
+.Xr markdown 7
+
+documents and (ii)
+.Em pages
+authored as RDFa Lite documents\&. Posts are any
+file ending with
+.Va *\&.md
+\&. Pages are any file ending with
+.Va *\&.rdfa
+\&. In practice, the only difference between these two is that
+posts go through an extra build step for processing the markdown to RDFa Lite\&.
+From that point all files are equal\&.
+.Sh ENVIRONMENT
+.Pp
+The following environment variables affect the execution:
+.Bl -tag -width Ds
+.It Ev BASE
+Sets the value of in the template variable
+.It Ev TEMPLATE
+Affects which template that will be used.
+Same as:
+.El
+.Sh EXAMPLES
+.Pp
+Given
+.Bd -literal -offset indent
+$ rcc -t html.en doc.rdfa
+.Ed
+.Pp
+Given
+.Bd -literal -offset indent
+$ rcc -t software.en tool.rdfa
+.Ed
+.Pp
+Create a pipeline converting
+.Bd -literal -offset indent
+$ lowdown post.md | triple-rdfa | rcc
+.Ed
+.Sh CAVEATS
+.Pp
+Due to a limitation in how
+.Xr triple-turtle 1
+currently parses
+HTML, it\&'s required to have at least one non-void element before a
+.Xr mustache 7
+partial tag appear in the body\&. \ No newline at end of file
diff --git a/man/rdfaprimer.7 b/man/rdfaprimer.7
new file mode 100644
index 0000000..53398b6
--- /dev/null
+++ b/man/rdfaprimer.7
@@ -0,0 +1,10 @@
+.Dd $Mdocdate$
+.Dt RDFAPRIMER 7
+.Sh NAME
+.Nm rdfaprimer
+.Nd RDFa Lite primer for Unix users
+.Sh DESCRIPTION
+.Pp
+TODO
+.Pp
+TODO
diff --git a/mk/Makefile b/mk/Makefile
new file mode 100644
index 0000000..798c62d
--- /dev/null
+++ b/mk/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: ISC
+
+BSDMK= rcc.blog.mk rcc.doc.mk rcc.feed.mk rcc.own.mk \
+ rcc.software.mk rcc.subdir.mk rcc.web.mk
+
+.include <sz.make.mk>
diff --git a/mk/bsd.rcc.blog.mk b/mk/bsd.rcc.blog.mk
new file mode 100644
index 0000000..83128ce
--- /dev/null
+++ b/mk/bsd.rcc.blog.mk
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: ISC
+
+blog/index.${XLANG}.html: ${RPOSTS}
+ ${ENV} pipeline echo "$>" '' pipeline tr " " "\n" '' redirfd -w 1 $@ ecclist -t blog.${XLANG}.html index.${XLANG}.rdfa
+
+TARGETS+= blog/index.${XLANG}.html
diff --git a/mk/bsd.rcc.doc.mk b/mk/bsd.rcc.doc.mk
new file mode 100644
index 0000000..4092bf7
--- /dev/null
+++ b/mk/bsd.rcc.doc.mk
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: ISC
+
+.include <rcc.own.mk>
+
+.MAIN: all
+.PHONY: all install
+
+ROOT?= ..
+MANDIR= ${ROOT}/man
+
+.for m in ${MAN_TARGETS}
+_MAN_TARGET=${MANDIR}/${m:T}
+all: ${_MAN_TARGET}
+test: ${m}.rdfa
+
+${_MAN_TARGET}: ${m}.rdfa
+ ${ENV} redirfd -w 1 $@ rcc -dman -tman.${PLANG} $>
+.endfor
+
+.if defined(README)
+all: ${ROOT}/README.md
+test: ${README}
+
+${ROOT}/README.md: ${README}
+ ${ENV} redirfd -w 1 $@ rcc -dmd -treadme.${PLANG} $>
+.endif
+
+test:
+ @${TIDY} $>
diff --git a/mk/bsd.rcc.feed.mk b/mk/bsd.rcc.feed.mk
new file mode 100644
index 0000000..17a4412
--- /dev/null
+++ b/mk/bsd.rcc.feed.mk
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: ISC
+
+.include <rcc.own.mk>
+
+feed.${XLANG}.xml sitemap.${XLANG}.xml:
+ ${ENV} pipeline echo "$>" '' pipeline tr " " "\n" '' redirfd -w 1 $@ rcclist -t ${@F} index.${XLANG}.rdfa
+
+sitemap.xml: sitemap.${XLANG}.xml
+ ln -s $> $@
+
+feed.${XLANG}.xml: ${RPOSTS}
+sitemap.${XLANG}.xml: ${RPOSTS} ${RPAGES}
+
+WTARGETS+= feed.${XLANG}.xml sitemap.${XLANG}.xml sitemap.xml
diff --git a/mk/bsd.rcc.own.mk b/mk/bsd.rcc.own.mk
new file mode 100644
index 0000000..3a0f990
--- /dev/null
+++ b/mk/bsd.rcc.own.mk
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: ISC
+
+.if exists(Makefile.inc)
+.include "Makefile.inc"
+.elif exists(../Makefile.inc)
+.include "../Makefile.inc"
+.endif
+
+.if exists(${.CURDIR}/.policy)
+.include "${.CURDIR}/.policy"
+.elif exists(${.CURDIR}/../.policy)
+.include "${.CURDIR}/../.policy"
+.endif
+
+.if exists(${.CURDIR}/package/targets.mk)
+.include "${.CURDIR}/package/targets.mk"
+.elif exists(${.CURDIR}/../package/targets.mk)
+.include "${.CURDIR}/../package/targets.mk"
+.endif
+
+.if exists(${.CURDIR}/package/deps.mk)
+.include "${.CURDIR}/package/deps.mk"
+.elif exists(${.CURDIR}/../package/deps.mk)
+.include "${.CURDIR}/../package/deps.mk"
+.endif
+
+LANG?= en_US.UTF-8
+XLANG!= heredoc 0 ${LANG} cut -c -2 # Current language
+PLANG?= ${XLANG} # Preferred language
+
+DOMAIN?= localhost
+BASE?= https://${DOMAIN}
+ENV?= env BASE=${BASE}
+
+TIDY?= tidy -errors -quiet --show-filename yes --show-info no \
+ --show-body-only yes --drop-empty-elements no
+
+RROOT!= pipeline find . -name "*.rdfa" -maxdepth 1 '' cut -c 3-
+RDIRS!= pipeline find . -type d -maxdepth 1 -not -path "*/.*" -exec test ! -e {}/Makefile \; -print '' cut -c 3-
+
+.if !empty(RDIRS)
+MPOSTS!= pipeline find ${RDIRS} -name "*.md" '' sort -r
+RPOSTS?= ${MPOSTS:.md=.rdfa}
+RPAGES!= find ${RDIRS} -name "*.rdfa"
+.endif
+
+RLISTS!= pipeline find . -name "*.rcclist" '' cut -c 3-
+MLISTS?= ${RLISTS:.rcclist=.mustache}
+
+# Web targets
+WROOT?= ${RROOT:.rdfa=.html}
+WPAGES?= ${RPAGES:.rdfa=.html}
+WPOSTS?= ${RPOSTS:.rdfa=.html}
+WTARGETS?= ${RPOSTS} ${WPOSTS} ${WROOT} ${WPAGES} ${MLISTS}
+WINSTALL!= pipeline find . -name "*.html" -o -name "*.xml" -o \
+ -name "*.jpg" -o -name "*.png" -o -name "*.css" '' cut -c 3-
+
+# Installation
+INSTALL= sz-install
+DESTDIR?= /var/www/htdocs/${DOMAIN}
+
+RCC_OWN_MK=Done
diff --git a/mk/bsd.rcc.software.mk b/mk/bsd.rcc.software.mk
new file mode 100644
index 0000000..e0ac202
--- /dev/null
+++ b/mk/bsd.rcc.software.mk
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: ISC
+
+.include <rcc.own.mk>
+
+SPAGES= ${INDEX} ${PAGES}
+RPAGES= ${PAGES:%=${DIR}/%}
+TPAGES= ${SPAGES:.rdfa=.${XLANG}.html}
+
+.MAIN: all
+_INDEX=${INDEX:%.rdfa=%.${XLANG}.rdfa}
+all: ${_INDEX}
+install: ;
+
+${_INDEX}: ${INDEX:%=${DIR}/%}
+ cp $> $@
+
+clean:
+ @rm -f ${TPAGES}
+
+.for s in ${SPAGES}
+_PAGE=${s:%.rdfa=%.${XLANG}.html}
+all: ${_PAGE}
+
+${_PAGE}: ${DIR}/${s:T}
+ ${ENV} rcc -dhtml -tsoftware.${XLANG} ${DIR}/${s:T} > $@
+.endfor
+
+test: ${RPAGES}
+ @${TIDY} $>
diff --git a/mk/bsd.rcc.subdir.mk b/mk/bsd.rcc.subdir.mk
new file mode 100644
index 0000000..8f51f2f
--- /dev/null
+++ b/mk/bsd.rcc.subdir.mk
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: ISC
+
+.include <rcc.own.mk>
+.include <bsd.subdir.mk>
+
+MAKE= ${ENV} make
diff --git a/mk/bsd.rcc.web.mk b/mk/bsd.rcc.web.mk
new file mode 100644
index 0000000..ac36be5
--- /dev/null
+++ b/mk/bsd.rcc.web.mk
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: ISC
+
+.include <rcc.own.mk>
+
+.MAIN: all
+.PHONY: all clean test test-rdfa test-html
+.SUFFIXES: .html .md .mustache .rcclist .rdfa
+
+all: ${WTARGETS}
+
+clean:
+.for f in ${WTARGETS}
+ rm -f ${f}
+.endfor
+
+.md.rdfa:
+ ${ENV} redirfd -w 1 $@ triple $<
+
+.rdfa.html:
+ ${ENV} cd ${<D} redirfd -w 1 ${@F} rcc ${<F}
+
+.rcclist.mustache:
+ ${ENV} cd ${<D} ./${<F} redirfd -w 1 ${@F} rcclist
+
+.for f in ${WINSTALL}
+${DESTDIR}/${f}: ${f}
+ ${INSTALL} -Dm 0444 $> $@
+.endfor
+
+test: test-rdfa test-html
+
+test-rdfa: ${RPOSTS} ${RPAGES}
+ @${TIDY} $>
+
+test-html: ${TPOSTS} ${TPAGES}
+ @${TIDY} $>
diff --git a/package/info b/package/info
new file mode 100644
index 0000000..acedbac
--- /dev/null
+++ b/package/info
@@ -0,0 +1,3 @@
+package=rcc
+version=0.0.1
+category=textproc
diff --git a/package/targets.mk b/package/targets.mk
new file mode 100644
index 0000000..8cd9e13
--- /dev/null
+++ b/package/targets.mk
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: ISC
+
+BIN_TARGETS= rcc rccif rcclist rccnew
+
+SHARE_TARGETS= blog.en.mustache blog.item.en.mustache feed.en.mustache \
+ feed.item.en.mustache html.en.mustache index.en.mustache \
+ index.item.en.mustache man.en.mustache none.en.mustache \
+ readme.en.mustache sitemap.en.mustache \
+ sitemap.item.en.mustache software.en.mustache \
+ terms.en.mustache terms.item.en.mustache xml.en.mustache
+
+SHARE_TARGETS+= page.new post.new software.new
+
+MAN_TARGETS= contentstyle.7 rcc.1 rdfaprimer.7
diff --git a/share/blog.en.mustache b/share/blog.en.mustache
new file mode 100644
index 0000000..a0cd7a4
--- /dev/null
+++ b/share/blog.en.mustache
@@ -0,0 +1,4 @@
+<h1>Blog</h1>
+<dl typeof="schema:blog">
+{{_main}}
+</dl>
diff --git a/share/blog.item.en.mustache b/share/blog.item.en.mustache
new file mode 100644
index 0000000..f7e58b7
--- /dev/null
+++ b/share/blog.item.en.mustache
@@ -0,0 +1,4 @@
+<dt>{{schema.datepublished:0:10}}</dt>
+<dd property="schema:blogpost" typeof="{{a}}">
+<cite property="schema:headline"><a property="schema:url" href="{{.}}">{{schema.headline}}</a></cite>
+</dd>
diff --git a/share/feed.en.mustache b/share/feed.en.mustache
new file mode 100644
index 0000000..ff47e2d
--- /dev/null
+++ b/share/feed.en.mustache
@@ -0,0 +1,8 @@
+<feed xmlns="http://www.w3.org/2005/Atom">
+<title>{{schema.headline}}</title>
+<subtitle>{{schema.abstract}}</subtitle>
+<id>{{_base}}/</id>
+<link rel="self" href="{{_base}}/atom.{{schema.inlanguage}}.xml"/>
+<link rel="alternate" href="{{_base}}/"/>
+{{_main}}
+</feed>
diff --git a/share/feed.item.en.mustache b/share/feed.item.en.mustache
new file mode 100644
index 0000000..ac8e1c2
--- /dev/null
+++ b/share/feed.item.en.mustache
@@ -0,0 +1,27 @@
+<entry>
+{{#schema.headline}}
+<title>{{schema.headline}}</title>
+{{/schema.headline}}
+{{^schema.headline}}
+<title>{{schema.name}}</title>
+{{/schema.headline}}
+<id>{{_base}}{{.}}</id>
+<link href="{{_base}}{{.}}"/>
+{{#schema.datepublished}}
+<published>{{schema.datepublished}}</published>
+{{/schema.datepublished}}
+{{#schema.datemodified}}
+<updated>{{schema.datemodified}}</updated>
+{{/schema.datemodified}}
+{{#schema.author}}
+<author>
+<name>{{schema.author}}</name>
+</author>
+{{/schema.author}}
+{{#schema.abstract}}
+<summary>{{schema.abstract}}</summary>
+{{/schema.abstract}}
+{{^schema.abstract}}
+<summary>{{schema.description}}</summary>
+{{/schema.abstract}}
+</entry>
diff --git a/share/html.en.mustache b/share/html.en.mustache
new file mode 100644
index 0000000..03e9781
--- /dev/null
+++ b/share/html.en.mustache
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html typeof="{{a}}" resource="{{.}}" lang="{{schema.inlanguage}}">
+<head>
+<meta charset="utf-8"/>
+<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
+{{#schema.datepublished}}
+<meta property="schema:datepublished" content="{{schema.datepublished}}"/>
+{{/schema.datepublished}}
+{{#schema.datemodified}}
+<meta property="schema:datemodified" content="{{schema.datemodified}}"/>
+{{/schema.datemodified}}
+<link rel="stylesheet" href="/style.css"/>
+{{#schema.worktranslation}}
+<link ref="alternate" type="text/html" hreflang="{{schema.inlanguage}}" href="{{.}}"/>
+{{/schema.worktranslation}}
+{{#schema.translationofwork}}
+<link ref="alternate" type="text/html" hreflang="{{schema.inlanguage}}" href="{{.}}"/>
+{{/schema.translationofwork}}
+<link rel="alternate" type="application/atom+xml" href="/feed.{{schema.inlanguage}}.xml"/>
+{{#schema.headline}}
+<title>{{schema.headline}}</title>
+{{/schema.headline}}
+{{^schema.headline}}
+<title>{{schema.name}}</title>
+{{/schema.headline}}
+</head>
+<body>
+<header>
+{{>nav}}
+</header>
+<main>
+{{_main}}
+{{#schema.author}}
+<footer>
+<address property="schema:author">{{schema.author}}</address>
+</footer>
+{{/schema.author}}
+</main>
+</body>
+</html>
diff --git a/share/index.en.mustache b/share/index.en.mustache
new file mode 100644
index 0000000..61880b9
--- /dev/null
+++ b/share/index.en.mustache
@@ -0,0 +1,3 @@
+<ul typeof="schema:itemlist">
+{{_main}}
+</ul>
diff --git a/share/index.item.en.mustache b/share/index.item.en.mustache
new file mode 100644
index 0000000..9c9c66a
--- /dev/null
+++ b/share/index.item.en.mustache
@@ -0,0 +1,8 @@
+<li property="schema:itemlistelement" typeof="{{a}}">
+{{#schema.headline}}
+<a property="schema:url" href="{{.}}">{{schema.headline}}</a>
+{{/schema.headline}}
+{{^schema.headline}}
+<a property="schema:url" href="{{.}}">{{schema.name}}</a>
+{{/schema.headline}}
+</li>
diff --git a/share/man.en.mustache b/share/man.en.mustache
new file mode 100644
index 0000000..96ef239
--- /dev/null
+++ b/share/man.en.mustache
@@ -0,0 +1,61 @@
+.Dd $Mdocdate$
+.Dt {{schema.name:U}} {{schema.softwarecategory}}
+{{#schema.operatingsystem}}
+.Os {{schema.operatingsystem:N}}
+{{/schema.operatingsystem}}
+.Sh NAME
+.Nm {{schema.name:N}}
+.Nd {{schema.abstract:N}}
+{{#unix.command.1}}
+.Sh SYNOPSIS
+.Nm
+{{#unix.command}}
+.{{#unix.optional}}Op {{/unix.optional}}
+{{#unix.option}}Fl {{.}}{{/unix.option}}{{#unix.optionargument}} Ar {{unix.optionargument}}{{/unix.optionargument}}
+{{#unix.argument}}Ar {{.}}{{/unix.argument}}
+{{/unix.command}}
+{{/unix.command.1}}
+.Sh DESCRIPTION
+{{schema.description:N}}
+{{#unix.command.1}}
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+{{#unix.command}}
+.It {{#unix.option}}Fl {{.}}{{/unix.option}}{{#unix.optionargument}} Ar {{unix.optionargument}}{{/unix.optionargument}}
+{{#unix.argument}}Ar {{.}} {{/unix.argument}}
+{{unix.description:N}}
+{{/unix.command}}
+.El
+{{/unix.command.1}}
+{{#schema.text}}
+{{schema.text:N}}
+{{/schema.text}}
+{{#unix.environment.1}}
+.Sh ENVIRONMENT
+.Pp
+The following environment variables affect the execution:
+.Bl -tag -width Ds
+{{#unix.environment}}
+.It Ev {{.:N}}
+{{unix.description:N}}
+{{/unix.environment}}
+.El
+{{/unix.environment.1}}
+{{#schema.workexample.1}}
+.Sh EXAMPLES
+{{#schema.workexample}}
+{{schema.description:N}}
+.Bd -literal -offset indent
+{{schema.text:N}}
+.Ed
+{{/schema.workexample}}
+{{/schema.workexample.1}}
+{{#schema.author}}
+.Sh AUTHORS
+.An {{schema.author}}
+{{/schema.author}}
+{{#schema.usageinfo}}
+.Sh CAVEATS
+{{schema.usageinfo}}
+{{/schema.usageinfo}}
diff --git a/share/none.en.mustache b/share/none.en.mustache
new file mode 100644
index 0000000..9cb2408
--- /dev/null
+++ b/share/none.en.mustache
@@ -0,0 +1 @@
+{{_main}}
diff --git a/share/page.new b/share/page.new
new file mode 100644
index 0000000..f031757
--- /dev/null
+++ b/share/page.new
@@ -0,0 +1,13 @@
+<!--
+vi: syntax=html
+-->
+<article typeof="schema:webpage" resource="@BASE@@PATH@" lang="@LANG@">
+
+<h1 property="schema:headline">@NAME@</h1>
+
+<meta property="schema:datemodified" content="@NOW@"/>
+<link property="schema:worktranslation" typeof="schema:creativework" hreflang="@TRANS@" href="@TRANSURL@"/>
+
+<p>@TEXT@</p>
+
+</article>
diff --git a/share/post.new b/share/post.new
new file mode 100644
index 0000000..738e14f
--- /dev/null
+++ b/share/post.new
@@ -0,0 +1,10 @@
+<!--
+vi: syntax=markdown
+-->
+# @NAME@
+
+<meta property="schema:author" content="@AUTHOR@"/>
+<meta property="schema:datepublished" content="@NOW@"/>
+<link property="schema:worktranslation" typeof="schema:creativework" hreflang="@TRANS@" href="@BASE@@PATH@"/>
+
+@TEXT@
diff --git a/share/readme.en.mustache b/share/readme.en.mustache
new file mode 100644
index 0000000..df610ab
--- /dev/null
+++ b/share/readme.en.mustache
@@ -0,0 +1,25 @@
+# {{schema.name}} – {{schema.abstract}}
+
+{{schema.description:W}}
+
+{{#schema.softwarerequirements.1}}
+## Requirements
+
+{{#schema.softwarerequirements}}
+- [{{schema.name}}]({{.}})
+{{/schema.softwarerequirements}}
+{{/schema.softwarerequirements.1}}
+
+{{#schema.license.1}}
+## License
+
+{{#schema.license}}
+[{{schema.name}}]({{.}})
+{{/schema.license}}
+{{/schema.license.1}}
+
+{{#schema.downloadurl}}
+## Download
+
+See {{schema.downloadurl}}
+{{/schema.downloadurl}}
diff --git a/share/sitemap.en.mustache b/share/sitemap.en.mustache
new file mode 100644
index 0000000..b57673e
--- /dev/null
+++ b/share/sitemap.en.mustache
@@ -0,0 +1,3 @@
+<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
+{{_main}}
+</urlset>
diff --git a/share/sitemap.item.en.mustache b/share/sitemap.item.en.mustache
new file mode 100644
index 0000000..3f729f3
--- /dev/null
+++ b/share/sitemap.item.en.mustache
@@ -0,0 +1,11 @@
+<url>
+<loc>{{_base}}{{.}}</loc>
+{{#schema.datemodified}}
+<lastmod>{{schema.datemodified}}</lastmod>
+{{/schema.datemodified}}
+{{^schema.datemodified}}
+{{#schema.datepublished}}
+<lastmod>{{schema.datepublished}}</lastmod>
+{{/schema.datepublished}}
+{{/schema.datemodified}}
+</url>
diff --git a/share/software.en.mustache b/share/software.en.mustache
new file mode 100644
index 0000000..6ee2829
--- /dev/null
+++ b/share/software.en.mustache
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<html typeof="{{a}}" resource="{{.}}" lang="{{schema.inlanguage}}">
+<head>
+<meta charset="utf-8"/>
+<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
+{{#schema.worktranslation}}
+<link ref="alternate" type="text/html" hreflang="{{schema.inlanguage}}" href="{{.}}"/>
+{{/schema.worktranslation}}
+{{#schema.translationofwork}}
+<link ref="alternate" type="text/html" hreflang="{{schema.inlanguage}}" href="{{.}}"/>
+{{/schema.translationofwork}}
+<link rel="stylesheet" href="/style.css"/>
+<title>{{schema.name}}</title>
+</head>
+<body>
+<header>
+{{>nav}}
+</header>
+<main>
+<h1>{{schema.name}}</h1>
+<p><mark>{{schema.name}}</mark> – {{schema.abstract}}</p>
+{{#unix.command.1}}
+<p><mark>{{schema.name}}</mark>
+{{#unix.command}}
+{{#unix.optional}}[{{/unix.optional}}
+{{#unix.option}}<b>-{{.}}</b>{{/unix.option}}
+{{#unix.optionargument}} <i>{{unix.optionargument}}</i>{{/unix.optionargument}}
+{{#unix.argument}}<i>{{.}}</i>{{/unix.argument}}
+{{#unix.optional}}]{{/unix.optional}}
+{{/unix.command}}
+{{/unix.command.1}}</p>
+{{schema.description}}
+{{#unix.command.1}}
+<p>The options are as follows:</p>
+<dl>
+{{#unix.command}}
+<dt>{{#unix.option}}<b>-{{.}}</b>{{/unix.option}}
+{{#unix.optionargument}} <i>{{unix.optionargument}}</i>{{/unix.optionargument}}
+{{#unix.argument}}<i>{{.}}</i>{{/unix.argument}}</dt>
+<dd>{{unix.description}}</dd>
+{{/unix.command}}
+</dl>
+{{/unix.command.1}}
+{{#schema.text}}
+{{schema.text}}
+{{/schema.text}}
+{{#unix.environment.1}}
+<h2>Environment</h2>
+<p>The following environment variables affect the execution:</p>
+<dl>
+{{#unix.environment}}
+<dt><var>{{.}}</var></dt>
+<dd>{{unix.description}}</dd>
+{{/unix.environment}}
+</dl>
+{{/unix.environment.1}}
+{{#schema.workexample.1}}
+<h2>Examples</h2>
+{{#schema.workexample}}
+{{schema.description:N}}
+<pre><code>{{schema.text:}}</code></pre>
+{{/schema.workexample}}
+{{/schema.workexample.1}}
+{{#schema.softwarerequirements.1}}
+<h2>Requirements</h2>
+<ul>
+{{#schema.softwarerequirements}}
+<li><a href="{{.}}"><cite>{{schema.name}}</cite></a></li>
+{{/schema.softwarerequirements}}
+</ul>
+{{/schema.softwarerequirements.1}}
+{{#schema.license.1}}
+<h2>License</h2>
+{{#schema.license}}
+<p><a href="{{.}}"><cite>{{schema.name}}</cite></a></p>
+{{/schema.license}}
+{{/schema.license.1}}
+{{#schema.downloadurl}}
+<h2>Download</h2>
+{{#schema.softwareversion}}
+<p>Current version: <code>{{schema.softwareversion}}</code></p>
+{{/schema.softwareversion}}
+<p>Repository: <a href="{{schema.downloadurl}}">{{schema.downloadurl}}</a></p>
+{{/schema.downloadurl}}
+{{#schema.usageinfo}}
+<h2>Caveats</h2>
+{{schema.usageinfo}}
+{{/schema.usageinfo}}
+{{#schema.haspart.1}}
+<h1>Components</h1>
+<ul>
+{{#schema.haspart}}
+<li><a href="{{.}}.{{schema.inlanguage}}.html"><cite>{{.:X}}</cite></a></li>
+{{/schema.haspart}}
+</ul>
+{{/schema.haspart.1}}
+</main>
+</body>
+</html>
diff --git a/share/software.new b/share/software.new
new file mode 100644
index 0000000..eb4e174
--- /dev/null
+++ b/share/software.new
@@ -0,0 +1,58 @@
+<!--
+vi: syntax=html
+-->
+<article resource="@BASE@@PATH@" typeof="schema:softwareapplication" lang="@LANG@" prefix="unix: https://senzilla.io/ns">
+
+<p property="schema:name">@NAME@</p>
+<p property="schema:abstract">@ABSTRACT@</p>
+<p property="schema:softwareversion">@VERSION@</p>
+<link property="schema:downloadurl" href="@BASE@@PATH@"/>
+
+<article property="schema:license" resource="@LICENSEURL@" typeof="schema:creativework">
+<p property="schema:name">@LICENSENAME@</p>
+</article>
+
+<article property="schema:softwarerequirements" resource="https://pubs.opengroup.org/onlinepubs/9699919799.2018edition" typeof="schema:sotwareapplication">
+<p property="schema:name">POSIX system</p>
+</article>
+
+<article property="schema:softwarerequirements" resource="@REQURL1@" typeof="schema:softwareapplication">
+<p property="schema:name">@REQNAME1@</p>
+</article>
+
+<article property="schema:softwarerequirements" resource="@REQURL2@" typeof="schema:softwareapplication">
+<p property="schema:name">@REQNAME2@</p>
+</article>
+
+<article property="unix:command" resource="@OPTIONNAME1@" typeof="unix:option">
+<p property="unix:optionargument">@OPTIONARGUMENT1@</p>
+<p property="unix:optional">1</p>
+<p property="unix:description">@OPTIONDESCRIPTION1@</p>
+</article>
+
+<article property="unix:command" resource="@ARGUMENTNAME1@" typeof="unix:argument">
+<p property="unix:description">@ARGUMENTDESCRIPTION1@</p>
+</article>
+
+<article property="unix:environment" resource="@ENV1@" typeof="unix:variable">
+<p property="unix:description">@ENVDESCRIPTION1@</p>
+</article>
+
+<link property="schema:haspart" resource="@COMPONENTURL1@" hreflang="@COMPONENTLANG1@" typeof="schema:softwareapplication"/>
+
+<article property="schema:description">
+<p>@DESCRIPTION@</p>
+</article>
+
+<article property="schema:text">
+<p>@TEXT@</p>
+</article>
+
+<article property="schema:workexample" typeof="schema:creativework">
+<article property="schema:description">
+<p>@EXAMPLEDESCRIPTION1@</p>
+</article>
+<p property="schema:text">@EXAMPLECOMMAND1@</p>
+</article>
+
+</article>
diff --git a/share/terms.en.mustache b/share/terms.en.mustache
new file mode 100644
index 0000000..58589e3
--- /dev/null
+++ b/share/terms.en.mustache
@@ -0,0 +1,3 @@
+<dl>
+{{_main}}
+</dl>
diff --git a/share/terms.item.en.mustache b/share/terms.item.en.mustache
new file mode 100644
index 0000000..eb90c67
--- /dev/null
+++ b/share/terms.item.en.mustache
@@ -0,0 +1,12 @@
+{{#schema.headline}}
+<dt><a href="{{.}}">{{schema.headline}}</a></dt>
+{{/schema.headline}}
+{{^schema.headline}}
+<dt><a href="{{.}}">{{schema.name}}</a></dt>
+{{/schema.headline}}
+{{#schema.description}}
+<dd>{{schema.description}}</dd>
+{{/schema.description}}
+{{^schema.description}}
+<dd>{{schema.abstract}}</dd>
+{{/schema.description}}
diff --git a/share/xml.en.mustache b/share/xml.en.mustache
new file mode 100644
index 0000000..4a50a20
--- /dev/null
+++ b/share/xml.en.mustache
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+{{_main}}
diff --git a/src/rcc b/src/rcc
new file mode 100644
index 0000000..c431389
--- /dev/null
+++ b/src/rcc
@@ -0,0 +1,15 @@
+#!@SHEBANGDIR@/execlineb
+# SPDX-License-Identifier: ISC
+
+elgetopt d:t:
+importas -uD html.en deftemplate TEMPLATE
+multisubstitute {
+ importas -uD "" datatype ELGETOPT_d
+ importas -uD $deftemplate template ELGETOPT_t
+ elgetpositionals
+}
+multidefine -d . $template { name lang }
+export DATATYPE $datatype
+pipeline { triple-turtle $1 }
+pipeline { triple-text }
+mustawk - @PACKAGE_SHAREDIR@/${name}.${lang}.mustache
diff --git a/src/rccif b/src/rccif
new file mode 100644
index 0000000..336c9bd
--- /dev/null
+++ b/src/rccif
@@ -0,0 +1,7 @@
+#!@SHEBANGDIR@/execlineb -S3
+# SPDX-License-Identifier: ISC
+
+pipeline { triple-turtle $3 }
+pipeline { triple-text }
+if { s6-grep -qE ${1}[[:space:]]${2} }
+s6-echo $3
diff --git a/src/rcclist b/src/rcclist
new file mode 100644
index 0000000..8263df3
--- /dev/null
+++ b/src/rcclist
@@ -0,0 +1,36 @@
+#!@SHEBANGDIR@/execlineb
+# SPDX-License-Identifier: ISC
+
+elgetopt d:f:t:
+multisubstitute {
+ importas -uD index.en.html deftemplate TEMPLATE
+ importas -uD "" deffilter FILTER
+}
+multisubstitute {
+ importas -uD $deftemplate template ELGETOPT_t
+ importas -uD $deffilter filter ELGETOPT_f
+}
+multidefine -d . $template { name lang type }
+multisubstitute {
+ define listpath @PACKAGE_SHAREDIR@/${name}.${lang}.mustache
+ define itempath @PACKAGE_SHAREDIR@/${name}.item.${lang}.mustache
+ define typepath @PACKAGE_SHAREDIR@/${type}.${lang}.mustache
+ importas -uD "" datatype ELGETOPT_d
+ elgetpositionals
+}
+export DATATYPE $datatype
+export LIST 1
+pipeline {
+ ifthenelse { test -z "$1" }
+ { pipeline { triple-turtle $1 } triple-text }
+ { echo "---\n---" }
+ pipeline { xargs triple-turtle }
+ pipeline { triple-text }
+ export FILTER $filter
+ mustawk - $itempath
+}
+pipeline {
+ export HEAD 1
+ mustawk - $listpath
+}
+mustawk - $typepath
diff --git a/src/rccnew b/src/rccnew
new file mode 100644
index 0000000..cebb45f
--- /dev/null
+++ b/src/rccnew
@@ -0,0 +1,52 @@
+#!/@SHEBANGDIR@/execlineb
+# SPDX-License-Identifier: ISC
+
+importas -i HOME HOME
+envfile -I ${HOME}/.rccnew
+# Variables from the environment
+multisubstitute {
+ importas -uD @AUTHOR@ envauthor AUTHOR
+ importas -uD "" envbase BASE
+ importas -uD en_US.UTF-8 envlang LANG
+ importas -uD "Internet Software Consortium" envlicensename LICENSENAME
+ importas -uD https://opensource.org/licenses/ISC envlicenseurl LICENSEURL
+ importas -uD @REQNAME1@ envreqname1 REQNAME1
+ importas -uD @REQNAME2@ envreqname2 REQNAME2
+ importas -uD @REQURL1@ envrequrl1 REQURL1
+ importas -uD @REQURL2@ envrequrl2 REQURL2
+ importas -uD 0.0.1 envversion VERSION
+}
+backtick -E xlang { heredoc 0 $envlang cut -c -2 }
+elgetopt a:b:l:t:v:
+# Variables from options
+multisubstitute {
+ importas -uD $envauthor optauthor ELGETOPT_a
+ importas -uD $envbase optbase ELGETOPT_b
+ importas -uD $xlang optlang ELGETOPT_l
+ importas -uD $envversion optversion ELGETOPT_v
+ importas -uD post template ELGETOPT_t
+ importas -uD vim editor EDITOR
+ importas -i path 1
+}
+shift -n 1
+backtick -E file { basename $path }
+backtick -E name { dollarat -nd " " }
+backtick -E now { date +%Y-%m-%dT%H:%M:%S%Z }
+if {
+ redirfd -r 0 @PACKAGE_SHAREDIR@/${template}.new
+ redirfd -w 1 $file
+ sed "s#@AUTHOR@#${optauthor}#g;
+ s#@BASE@#${optbase}#g;
+ s#@LANG@#${optlang}#g;
+ s#@LICENSEURL@#${envlicenseurl}#g;
+ s#@LICENSENAME@#${envlicensename}#g;
+ s#@NAME@#${name}#g;
+ s#@NOW@#${now}#g;
+ s#@PATH@#${path}#g;
+ s#@REQNAME1@#${envreqname1}#g;
+ s#@REQNAME2@#${envreqname2}#g;
+ s#@REQURL1@#${envrequrl1}#g;
+ s#@REQURL2@#${envrequrl2}#g;
+ s#@VERSION@#${optversion}#g;"
+}
+sh -c "${editor} -c 'execute \"normal /@\n\"' ${file}"