diff options
Diffstat (limited to '')
-rw-r--r-- | v2/.envrc | 11 | ||||
-rw-r--r-- | v2/.gitignore | 20 | ||||
-rw-r--r-- | v2/Makefile | 2 | ||||
-rwxr-xr-x | v2/aux/po4a-cfg.sh | 4 | ||||
-rw-r--r-- | v2/dynamic.mk | 55 | ||||
-rw-r--r-- | v2/po/euandre.org.pot | 208 | ||||
-rw-r--r-- | v2/po/pt.po | 198 | ||||
-rwxr-xr-x | v2/src/bin/absolute | 2 | ||||
-rwxr-xr-x | v2/src/bin/collections | 69 | ||||
-rwxr-xr-x | v2/src/bin/conf (renamed from v2/src/development/genconf.sh) | 42 | ||||
-rwxr-xr-x | v2/src/bin/feed | 91 | ||||
-rwxr-xr-x | v2/src/bin/html (renamed from v2/src/development/genhtml.sh) | 21 | ||||
-rwxr-xr-x | v2/src/bin/lang-for | 73 | ||||
-rwxr-xr-x | v2/src/bin/langs | 69 | ||||
-rwxr-xr-x | v2/src/bin/makemake | 142 | ||||
-rwxr-xr-x | v2/src/bin/security-txt (renamed from v2/src/development/security-txt.sh.in) | 24 | ||||
-rwxr-xr-x | v2/src/bin/url-for | 30 | ||||
-rwxr-xr-x | v2/src/bin/xmlentry | 81 | ||||
-rw-r--r-- | v2/src/content/en/about.md (renamed from v2/src/content/about.md) | 6 | ||||
-rw-r--r-- | v2/src/content/en/pastebins/raku-tuple-type-annotation.md (renamed from v2/src/content/pastebins/raku-tuple-type-annotation.md) | 6 | ||||
-rw-r--r-- | v2/src/content/en/pastebins/sicp-exercise-3-19.md (renamed from v2/src/content/pastebins/sicp-exercise-3-19.md) | 6 | ||||
-rw-r--r-- | v2/src/content/en/tils/lisp-three-way-conditional.md (renamed from v2/src/content/tils/lisp-three-way-conditional.md) | 6 | ||||
-rw-r--r-- | v2/src/content/favicon.ico | bin | 0 -> 1150 bytes | |||
-rw-r--r-- | v2/src/content/pt/pastebins/exercicios-sicp-e-19.md | 103 | ||||
-rw-r--r-- | v2/src/content/pt/sobre.md | 9 | ||||
-rw-r--r-- | v2/src/lib.sh (renamed from v2/src/development/lib.sh) | 0 | ||||
-rw-r--r-- | v2/src/lib/base.conf (renamed from v2/src/lib/base-conf.in) | 5 | ||||
-rw-r--r-- | v2/src/lib/entry.xml | 22 | ||||
-rw-r--r-- | v2/src/lib/feed.xml | 15 |
29 files changed, 1132 insertions, 188 deletions
@@ -1,6 +1,15 @@ #!/bin/sh set -eu -export PATH="$PWD/src/bin:$PATH" export GIT_DIR="$PWD"/../.git export GIT_WORK_TREE="$PWD"/../ + +export PATH="$PWD/src/bin:$PATH" + +export DOMAIN='euandre.org' +export EMAIL='eu@euandre.org' +export CONTENT_PREFIX='src/content' +export COLLECTIONS=' +tils +pastebins +' diff --git a/v2/.gitignore b/v2/.gitignore index 0f413a8..379a382 100644 --- a/v2/.gitignore +++ b/v2/.gitignore @@ -1,17 +1,21 @@ /generated.mk /*.sentinel -/src/lib/base-conf -/src/development/security-txt.sh /public/ -/src/content/*.conf -/src/content/*.content -/src/content/*.html -/src/content/*.md.tmp -/src/content/*.snippets -/src/content/*.html.*.txt +/src/content/*/feeds/ /src/content/*/*.conf /src/content/*/*.content /src/content/*/*.html /src/content/*/*.md.tmp +/src/content/*/*.htmlbody /src/content/*/*.snippets /src/content/*/*.html.*.txt +/src/content/*/*/*.conf +/src/content/*/*/*.content +/src/content/*/*/*.html +/src/content/*/*/*.md.tmp +/src/content/*/*/*.htmlbody +/src/content/*/*/*.snippets +/src/content/*/*/*.html.*.txt +/src/content/*/*/*.sortdata +/src/content/*/*/*.sortref +/src/content/*/*/*.xmlentry diff --git a/v2/Makefile b/v2/Makefile index e7a7279..4db38c7 100644 --- a/v2/Makefile +++ b/v2/Makefile @@ -12,7 +12,7 @@ generated.mk: ALWAYS @sh src/bin/makemake > generated.mk po/po4a.cfg: ALWAYS - @sh aux/po4a-cfg.sh | ifnew $@ + @sh aux/po4a-cfg.sh < po/mappings.cfg | ifnew $@ po4a $@ ALWAYS: diff --git a/v2/aux/po4a-cfg.sh b/v2/aux/po4a-cfg.sh index b20e303..384b2fb 100755 --- a/v2/aux/po4a-cfg.sh +++ b/v2/aux/po4a-cfg.sh @@ -107,3 +107,7 @@ git ls-files | grep -F '.en.' | while read -r file; do # shellcheck disable=2016 printf '[type: %s] %s $lang:%s\n' "$TYPE" "$file" "$VAR_FILE" done + +if [ ! -t 0 ]; then + cat +fi diff --git a/v2/dynamic.mk b/v2/dynamic.mk index b31e269..768ba30 100644 --- a/v2/dynamic.mk +++ b/v2/dynamic.mk @@ -1,6 +1,4 @@ .POSIX: -DOMAIN = euandre.org -EMAIL = eu@euandre.org default: all @@ -8,48 +6,42 @@ default: all include generated.mk - .SUFFIXES: -.SUFFIXES: .in .md .conf .content .html - -.in: - sed \ - -e 's|@DOMAIN@|$(DOMAIN)|g' \ - -e 's|@EMAIL@|$(EMAIL)|g' \ - < $< > $@ - if [ -x $< ]; then chmod +x $@; fi +.SUFFIXES: .md .content .conf .html .xmlentry -.md.conf: - sh src/development/genconf.sh $< > $@ .md.content: awk 'sep >= 2; /^---$$/ {sep++}' < $< > $@ +.md.conf: + conf $< > $@ + .md.html: - sh src/development/genhtml.sh $< > $@ + html $< > $@ +.md.xmlentry: + xmlentry $< > $@ -sed.in-files = \ - src/lib/base-conf \ - src/development/security-txt.sh \ derived-assets = \ $(all-generated) \ - $(sed.in-files) \ - public/favicon.ico \ - + $(feeds) \ -$(all-generated.conf) $(all-generated.content): $(non-content) -$(sed.in-files): dynamic.mk all: public -$(all-generated.conf): src/lib/base-conf + +$(all-generated.conf) $(all-generated.content): $(non-content) +$(all-generated.conf): src/lib/base.conf + +$(all-generated.xml): + feed $@ clean: rm -rf \ public/ $(derived-assets) *.sentinel generated.mk \ - src/content/*.html.*.txt src/content/*/*.html.*.txt + src/content/*/*.html.*.txt src/content/*/*/*.html.*.txt \ + src/content/*/*/*.sortdata src/content/**/feeds/ \ public: $(derived-assets) public-copy-content.sentinel public-copy-code-snippets.sentinel @@ -58,14 +50,10 @@ public-mkdir.sentinel: mkdir -p public touch $@ -public/favicon.ico: public-mkdir.sentinel src/content/favicon.svg - convert src/content/favicon.svg $@ - content = \ $(all-generated.html) \ + $(all-generated.xml) \ $(static-content) \ - src/content/public.asc.txt \ - src/content/.well-known/security.txt \ public-copy-content.sentinel: $(content) public-content-mkdir.sentinel echo $? | tr ' ' '\n' | grep '^src/content/' | sed 's|^src/content/||' | \ @@ -86,11 +74,15 @@ public-content-mkdir.sentinel: $(content) $(all-generated.snippets) xargs -P`nproc` -I% mkdir -p public/% touch $@ + +src/content/favicon.ico: src/content/favicon.svg + convert src/content/favicon.svg $@ + src/content/public.asc.txt: gpg --armour --export '$(EMAIL)' > $@ -src/content/.well-known/security.txt: src/content/public.asc.txt src/development/security-txt.sh - sh src/development/security-txt.sh > $@ +src/content/.well-known/security.txt: src/content/public.asc.txt src/bin/security-txt + security-txt > $@ @@ -98,7 +90,6 @@ test-files = \ aux/checks/shellcheck.sh \ aux/checks/todos.sh \ -aux/checks/shellcheck.sh: src/lib/base-conf $(test-files): ALWAYS sh $@ diff --git a/v2/po/euandre.org.pot b/v2/po/euandre.org.pot index 6a9d04f..cd5c76e 100644 --- a/v2/po/euandre.org.pot +++ b/v2/po/euandre.org.pot @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2023-04-04 17:03-0300\n" +"POT-Creation-Date: 2023-04-05 15:41-0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -37,7 +37,7 @@ msgid "export about_url_name='about.html'" msgstr "" #. type: Content of: <p> -#: src/lib/comment.en.html:2 +#: src/lib/comment.en.html:3 msgid "" "<a href=\"$mailto_uri\">Comment</a> and see <a " "href=\"$discussions_url\">existing discussions</a> | <a " @@ -63,3 +63,207 @@ msgstr "" #: src/lib/update.en.html:2 msgid "$formatted_update" msgstr "" + +#. type: Plain text +#: src/content/en/about.md:1 src/content/en/about.md:5 +#: src/content/en/pastebins/sicp-exercise-3-19.md:1 +#: src/content/en/pastebins/sicp-exercise-3-19.md:7 +#, no-wrap +msgid "---\n" +msgstr "" + +#. type: Plain text +#: src/content/en/about.md:4 +msgid "title: About" +msgstr "" + +#. type: Plain text +#: src/content/en/about.md:8 +msgid "It's all about me, baby!" +msgstr "" + +#. type: Plain text +#: src/content/en/about.md:11 +msgid "``` xablau ```" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:4 +msgid "title: SICP exercise 3.19" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:6 +msgid "date: 2021-09-02" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:10 +msgid "Some content here, before:" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:20 +#, no-wrap +msgid "" +"```scheme\n" +"(define (cycle? l)\n" +" (define (rec l x)\n" +" (cond\n" +" ((null? x) false)\n" +" ((eq? l x) true)\n" +" (true (rec l (cdr x)))))\n" +" (rec l (cdr l)))\n" +"```\n" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:22 +msgid "Sample interactive session:" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:39 +#, no-wrap +msgid "" +"```scheme\n" +"scheme@(guile-user)> (define true #t)\n" +"scheme@(guile-user)> (define false #f)\n" +"scheme@(guile-user)>\n" +"(define (cycle? l)\n" +" (define (rec l x)\n" +" (cond\n" +" ((null? x) false)\n" +" ((eq? l x) true)\n" +" (true (rec l (cdr x)))))\n" +" (rec l (cdr l)))\n" +"scheme@(guile-user)> (cycle? '(1 2 3))\n" +"$9 = #f\n" +"scheme@(guile-user)> (cycle? (make-cycle '(1 2 3)))\n" +"$10 = #t\n" +"```\n" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:41 +msgid "# An h1" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:43 +msgid "a list:" +msgstr "" + +#. type: Bullet: '1. ' +#: src/content/en/pastebins/sicp-exercise-3-19.md:47 +#, markdown-text +msgid "one" +msgstr "" + +#. type: Bullet: '2. ' +#: src/content/en/pastebins/sicp-exercise-3-19.md:47 +#, markdown-text +msgid "two" +msgstr "" + +#. type: Bullet: '3. ' +#: src/content/en/pastebins/sicp-exercise-3-19.md:47 +#, markdown-text +msgid "three" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:49 +msgid "some content." +msgstr "" + +#. type: Bullet: '- ' +#: src/content/en/pastebins/sicp-exercise-3-19.md:53 +#, markdown-text +msgid "item" +msgstr "" + +#. type: Bullet: '- ' +#: src/content/en/pastebins/sicp-exercise-3-19.md:53 +#, markdown-text +msgid "another" +msgstr "" + +#. type: Bullet: '- ' +#: src/content/en/pastebins/sicp-exercise-3-19.md:53 +#, markdown-text +msgid "yet another" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:55 +msgid "## An h2" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:57 +msgid "Xablau:" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:60 +msgid "``` xupliu 1" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:63 +msgid "3 4" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:70 +msgid "dez ```" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:72 +msgid "Foi `wikiwiu`." +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:74 +msgid "a very long code block:" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:80 +#, no-wrap +msgid "" +"```\n" +"wef\n" +"wef wef wef wef\n" +"wef wef wef wef we " +"fwef wef wef wef wef \n" +"```\n" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:82 +msgid "Someone said:" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:84 +msgid "> Xablau, xupliu." +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:87 +msgid "### A repeated header ### A repeated header" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:89 +msgid "a big list:" +msgstr "" + +#. type: Bullet: '1. ' +#: src/content/en/pastebins/sicp-exercise-3-19.md:107 +#, markdown-text +msgid "a" +msgstr "" diff --git a/v2/po/pt.po b/v2/po/pt.po index a01f659..3aceac9 100644 --- a/v2/po/pt.po +++ b/v2/po/pt.po @@ -19,7 +19,7 @@ msgid "export about_url_name='about.html'" msgstr "" #. type: Content of: <p> -#: src/lib/comment.en.html:2 +#: src/lib/comment.en.html:3 msgid "" "<a href=\"$mailto_uri\">Comment</a> and see <a href=\"$discussions_url" "\">existing discussions</a> | <a href=\"$sourcecode_url\">view source</a>" @@ -44,3 +44,199 @@ msgstr "" #: src/lib/update.en.html:2 msgid "$formatted_update" msgstr "" + +#. type: Plain text +#: src/content/en/about.md:1 src/content/en/about.md:5 +#: src/content/en/pastebins/sicp-exercise-3-19.md:1 +#: src/content/en/pastebins/sicp-exercise-3-19.md:7 +#, no-wrap +msgid "---\n" +msgstr "" + +#. type: Plain text +#: src/content/en/about.md:4 +msgid "title: About" +msgstr "" + +#. type: Plain text +#: src/content/en/about.md:8 +msgid "It's all about me, baby!" +msgstr "" + +#. type: Plain text +#: src/content/en/about.md:11 +msgid "``` xablau ```" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:4 +msgid "title: SICP exercise 3.19" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:6 +msgid "date: 2021-09-02" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:10 +msgid "Some content here, before:" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:20 +#, no-wrap +msgid "" +"```scheme\n" +"(define (cycle? l)\n" +" (define (rec l x)\n" +" (cond\n" +" ((null? x) false)\n" +" ((eq? l x) true)\n" +" (true (rec l (cdr x)))))\n" +" (rec l (cdr l)))\n" +"```\n" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:22 +msgid "Sample interactive session:" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:39 +#, no-wrap +msgid "" +"```scheme\n" +"scheme@(guile-user)> (define true #t)\n" +"scheme@(guile-user)> (define false #f)\n" +"scheme@(guile-user)>\n" +"(define (cycle? l)\n" +" (define (rec l x)\n" +" (cond\n" +" ((null? x) false)\n" +" ((eq? l x) true)\n" +" (true (rec l (cdr x)))))\n" +" (rec l (cdr l)))\n" +"scheme@(guile-user)> (cycle? '(1 2 3))\n" +"$9 = #f\n" +"scheme@(guile-user)> (cycle? (make-cycle '(1 2 3)))\n" +"$10 = #t\n" +"```\n" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:41 +msgid "# An h1" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:43 +msgid "a list:" +msgstr "" + +#. type: Bullet: '1. ' +#: src/content/en/pastebins/sicp-exercise-3-19.md:47 +msgid "one" +msgstr "" + +#. type: Bullet: '2. ' +#: src/content/en/pastebins/sicp-exercise-3-19.md:47 +msgid "two" +msgstr "" + +#. type: Bullet: '3. ' +#: src/content/en/pastebins/sicp-exercise-3-19.md:47 +msgid "three" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:49 +msgid "some content." +msgstr "" + +#. type: Bullet: '- ' +#: src/content/en/pastebins/sicp-exercise-3-19.md:53 +msgid "item" +msgstr "" + +#. type: Bullet: '- ' +#: src/content/en/pastebins/sicp-exercise-3-19.md:53 +msgid "another" +msgstr "" + +#. type: Bullet: '- ' +#: src/content/en/pastebins/sicp-exercise-3-19.md:53 +msgid "yet another" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:55 +msgid "## An h2" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:57 +msgid "Xablau:" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:60 +msgid "``` xupliu 1" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:63 +msgid "3 4" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:70 +msgid "dez ```" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:72 +msgid "Foi `wikiwiu`." +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:74 +msgid "a very long code block:" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:80 +#, no-wrap +msgid "" +"```\n" +"wef\n" +"wef wef wef wef\n" +"wef wef wef wef we fwef wef wef wef wef \n" +"```\n" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:82 +msgid "Someone said:" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:84 +msgid "> Xablau, xupliu." +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:87 +msgid "### A repeated header ### A repeated header" +msgstr "" + +#. type: Plain text +#: src/content/en/pastebins/sicp-exercise-3-19.md:89 +msgid "a big list:" +msgstr "" + +#. type: Bullet: '1. ' +#: src/content/en/pastebins/sicp-exercise-3-19.md:107 +msgid "a" +msgstr "" diff --git a/v2/src/bin/absolute b/v2/src/bin/absolute index 6434219..ecf5a64 100755 --- a/v2/src/bin/absolute +++ b/v2/src/bin/absolute @@ -62,6 +62,6 @@ done shift $((OPTIND - 1)) -. src/lib/base-conf +. src/lib/base.conf printf 'https://%s%s' "$domain" "$(cat)" diff --git a/v2/src/bin/collections b/v2/src/bin/collections new file mode 100755 index 0000000..1df0c39 --- /dev/null +++ b/v2/src/bin/collections @@ -0,0 +1,69 @@ +#!/bin/sh +set -eu + +usage() { + cat <<-'EOF' + Usage: + collections + collections -h + EOF +} + +help() { + cat <<-'EOF' + + + Options: + -h, --help show this message + + + List the registered collections to STDOUT. + + This is done by emiting the content of the "$COLLECTIONS" + environment variable. + + + Examples: + + Just run it: + + $ collections + tils + pastebins + EOF +} + + +for flag in "$@"; do + case "$flag" in + --) + break + ;; + --help) + usage + help + exit + ;; + *) + ;; + esac +done + +while getopts 'h' flag; do + case "$flag" in + h) + usage + help + exit + ;; + *) + usage >&2 + exit 2 + esac +done +shift $((OPTIND - 1)) + + +echo "$COLLECTIONS" | + tr ' ' '\n' | + grep . diff --git a/v2/src/development/genconf.sh b/v2/src/bin/conf index f9dfc14..ac02d98 100755 --- a/v2/src/development/genconf.sh +++ b/v2/src/bin/conf @@ -5,8 +5,8 @@ set -eu usage() { cat <<-'EOF' Usage: - src/development/genconf.sh FILENAME - src/development/genconf.sh -h + conf FILENAME + conf -h EOF } @@ -28,7 +28,7 @@ help() { Get the "frontmatter" of src/f.conf: - $ src/development/genconf.sh src/f.md > src/f.conf + $ conf src/f.md > src/f.conf EOF } @@ -63,7 +63,7 @@ while getopts 'h' flag; do done shift $((OPTIND - 1)) -. src/development/lib.sh +. src/lib.sh FILENAME="${1:-}" eval "$(assert_arg "$FILENAME" 'FILENAME')" @@ -73,7 +73,7 @@ escape() { sed 's|\([`"$]\)|\\\1|g' } -tee "$FILENAME".tmp < src/lib/base-conf +tee "$FILENAME".tmp < src/lib/base.conf DELIMITER=0 while read -r line; do if [ "$line" = '---' ]; then @@ -95,6 +95,11 @@ done < "$FILENAME" | tee -a "$FILENAME".tmp . "$FILENAME".tmp rm -f "$FILENAME".tmp + +lang="$(lang-for "$FILENAME")" +export lang +printf 'export lang="%s"\n' "$lang" + cat src/lib/base."${lang:?}".conf # shellcheck source=/dev/null . src/lib/base."$lang".conf @@ -104,19 +109,30 @@ if [ -z "${title:-}" ]; then fi if [ -n "${date:-}" ]; then - formatted_date="$(LANG="$lang" date -d "${date:?}" +"${date_fmt:?}")" + date_iso="$(date -ud "${date:?}" -Is)" + printf 'export date_iso="%s"\n' "$date_iso" + + formatted_date="$(LANG="$lang" date -ud "${date:?}" +"${date_fmt:?}")" export formatted_date printf 'export date_html="%s"\n' "$(envsubst < src/lib/date."$lang".html | escape)" + + echo "${FILENAME%.md}.xmlentry" > "$(dirname "$FILENAME")/$date_iso.sortdata" + touch "${FILENAME%.md}.sortref" fi if [ -n "${update:-}" ]; then - formatted_update="$(LANG="$lang" date -d "${update:?}" +"${date_fmt:?}")" + update_iso="$(date -ud "${update:?}" -Is)" + printf 'export update_iso="%s"\n' "$update_iso" + + formatted_update="$(LANG="$lang" date -ud "${update:?}" +"${date_fmt:?}")" export formatted_update printf 'export update_html="%s"\n' "$(envsubst < src/lib/update."$lang".html | escape)" + + printf 'export update_xml=" <updated>%s</updated>"\n' "$update_iso" fi -url_part="$(printf '%s' "${FILENAME%.md}.html" | sed 's|^src/content/||')" +url_part="$(printf '%s' "${FILENAME%.md}.html" | sed "s|^$CONTENT_PREFIX||")" title_uri="$(uri "$title")" printf 'export title_html="%s"\n' "$(printf '%s' "$title" | htmlesc | escape)" @@ -127,13 +143,13 @@ printf 'export mailto_uri="%s%s"\n' "${mailto_uri_prefix:?}" "$title_uri" printf 'export discussions_url="%s%s"\n' "${discussions_url_prefix:?}" "$title_uri" printf 'export sourcecode_url="%s%s"\n' "${sourcecode_url_prefix:?}" "$FILENAME" -printf 'export style_url="%s"\n' "$(url-for -g 'style.css')" -printf 'export favicon_url="%s"\n' "$(url-for -g 'favicon.svg')" -printf 'export pubkey_url="%s"\n' "$(url-for -g 'public.asc.txt')" +printf 'export style_url="%s"\n' "$(url-for 'style.css')" +printf 'export favicon_url="%s"\n' "$(url-for 'favicon.svg')" +printf 'export pubkey_url="%s"\n' "$(url-for 'public.asc.txt')" -for f in src/content/img/*.svg; do +for f in "$CONTENT_PREFIX"/img/*.svg; do name="$(basename "$f" .svg | sed 's|-|_|g')" - printf 'export icon_%s_url="%s"\n' "$name" "$(url-for -g "img/$(basename "$f")")" + printf 'export icon_%s_url="%s"\n' "$name" "$(url-for "img/$(basename "$f")")" done # FIXME: special treatment of root diff --git a/v2/src/bin/feed b/v2/src/bin/feed new file mode 100755 index 0000000..96c40a6 --- /dev/null +++ b/v2/src/bin/feed @@ -0,0 +1,91 @@ +#!/bin/sh +set -eu + +usage() { + cat <<-'EOF' + Usage: + feed FILENAME + feed -h + EOF +} + +help() { + cat <<-'EOF' + + + Options: + -h, --help show this message + + FILENAME the target feed to be generated + + + Generate FILENAME as an Atom feed. The collection type and + language are inferred by the name of FILENAME. + + + Examples: + + Generate a feed for TILs: + + $ feed src/en/feeds/til.xml + EOF +} + + +for flag in "$@"; do + case "$flag" in + --) + break + ;; + --help) + usage + help + exit + ;; + *) + ;; + esac +done + +while getopts 'h' flag; do + case "$flag" in + h) + usage + help + exit + ;; + *) + usage >&2 + exit 2 + ;; + esac +done +shift $((OPTIND - 1)) + +. src/lib.sh + +FILENAME="${1:-}" +eval "$(assert_arg "$FILENAME" 'FILENAME')" + + +COLLECTION="$(basename "$FILENAME" '.xml')" +LANGUAGE="$(lang-for "$FILENAME")" +DIR="$(dirname "$(dirname "$FILENAME")")/$COLLECTION" + + +. src/lib/base.conf +# shellcheck source=/dev/null +. src/lib/base."$LANGUAGE".conf + +now="$(date -uIs)" +url="$(url-for "${FILENAME#"$CONTENT_PREFIX"}" | absolute)" +site_name_html="$(htmlesc "${site_name:?}")" +export now url site_name_html + + +mkdir -p "$(dirname "$FILENAME")" +{ + envsubst < src/lib/feed.xml + find "$DIR"/*.sortdata | sort -nr | xargs cat | xargs cat + printf '</feed>\n' +} > "$FILENAME" diff --git a/v2/src/development/genhtml.sh b/v2/src/bin/html index 1b2718a..7e6809c 100755 --- a/v2/src/development/genhtml.sh +++ b/v2/src/bin/html @@ -4,34 +4,29 @@ set -eu usage() { cat <<-'EOF' Usage: - genhtml.sh FILENAME - genhtml.sh -h + html FILENAME + html -h EOF } help() { cat <<-'EOF' + Options: -h, --help show this message - FILENAME the name of the input file, to also be used as - URL + FILENAME the name of the input file .md file Process the FILENAME, and generate a full HTML page. - The FILENAME is used to infer the output URL, by removing the - `src/content/` prefix, and replacing the trailing `.md` with - `.html`. This URL is used to build the self-referencing - "canonical" link, extracting plaintext snippets, etc. - Examples: Generate the HTML for a pastebin: - $ sh genhtml.sh src/content/a-paste.md > src/content/a-paste.html + $ html src/a-paste.md > src/a-paste.html EOF } @@ -66,7 +61,7 @@ while getopts 'h' flag; do done shift $((OPTIND - 1)) -. src/development/lib.sh +. src/lib.sh FILENAME="${1:-}" eval "$(assert_arg "$FILENAME" 'FILENAME')" @@ -118,7 +113,7 @@ markdown_to_html() { extract_plaintext_snippets() { SNIPPETS="${FILENAME%.md}.snippets" - rm -f "$SNIPPETS" + printf '' > "$SNIPPETS" F="$(mkstemp)" cat > "$F" ( @@ -220,5 +215,5 @@ emit_body() { } envsubst < src/lib/preamble.html -emit_body +emit_body | tee "${FILENAME%.md}.htmlbody" envsubst < src/lib/postamble.html diff --git a/v2/src/bin/lang-for b/v2/src/bin/lang-for new file mode 100755 index 0000000..f7c57a9 --- /dev/null +++ b/v2/src/bin/lang-for @@ -0,0 +1,73 @@ +#!/bin/sh +set -eu + +usage() { + cat <<-'EOF' + Usage: + lang-for FILE + lang-for -h + EOF +} + +help() { + cat <<-'EOF' + + + Options: + -h, --help show this message + + FILE the path of the file to get the language for + + + Say the language of the given file, using the path of FILE. + + + Examples: + + Get "en" for "src/en/some-pt.md": + + $ lang-for src/en/some-pt.md + en + EOF +} + + +for flag in "$@"; do + case "$flag" in + --) + break + ;; + --help) + usage + help + exit + ;; + *) + ;; + esac +done + +while getopts 'h' flag; do + case "$flag" in + h) + usage + help + exit + ;; + *) + usage >&2 + exit 2 + ;; + esac +done +shift $((OPTIND - 1)) + +. src/lib.sh + + +FILE="${1:-}" +eval "$(assert_arg "$FILE" 'FILE')" + + +echo "${FILE#"$CONTENT_PREFIX"/}" | + cut -d/ -f1 diff --git a/v2/src/bin/langs b/v2/src/bin/langs new file mode 100755 index 0000000..8e8aa63 --- /dev/null +++ b/v2/src/bin/langs @@ -0,0 +1,69 @@ +#!/bin/sh +set -eu + +usage() { + cat <<-'EOF' + Usage: + langs + langs -h + EOF +} + +help() { + cat <<-'EOF' + + + Options: + -h, --help show this message + + + List the supported languages, including english, to STDOUT. + + This is done in the same way that po4a(1) does it: by listing + the po/*.po files, and getting the name from it. + + + Examples: + + Just run it: + + $ langs + en + pt + EOF +} + + +for flag in "$@"; do + case "$flag" in + --) + break + ;; + --help) + usage + help + exit + ;; + *) + ;; + esac +done + +while getopts 'h' flag; do + case "$flag" in + h) + usage + help + exit + ;; + *) + usage >&2 + exit 2 + esac +done +shift $((OPTIND - 1)) + + +echo po/en.po po/*.po | + tr ' ' '\n' | + sed 's|^po/\(.*\)\.po$|\1|' diff --git a/v2/src/bin/makemake b/v2/src/bin/makemake index e95a040..fdd0e68 100755 --- a/v2/src/bin/makemake +++ b/v2/src/bin/makemake @@ -64,84 +64,110 @@ varlist() { printf '\n' } -html_deps() { - "$@" | sed 's/^\(.*\)\.md$/\1.conf \1.content: \1.md/' - "$@" | sed 's/^\(.*\)\.md$/\1.snippets \1.html: \1.conf \1.content/' - printf '\n' -} - - -content_mds() { - { - if [ "$r" = 'pages' ]; then - echo src/content/*.md - else - echo src/content/"$r"/*.md - fi - } | tr ' ' '\n' -} - -RESOURCES=' -pages -pastebins -tils -' EXTENSIONS=' -.md .conf .content .html .snippets +.htmlbody ' -for r in $RESOURCES; do - content_mds "$r" | varlist "$r".md - for e in $EXTENSIONS; do - if [ "$e" = '.md' ]; then - continue +COLL_EXTENSIONS=' +.sortref +.xmlentry +' + +page_ext_filter="^($(echo "$COLL_EXTENSIONS" | + tr ' ' '\n' | + grep . | + paste -sd'|' +))\$" + + +extensions() { + echo "$EXTENSIONS" "$COLL_EXTENSIONS" "$@" | + tr ' ' '\n' | + grep . +} + + +printf '.POSIX:\n\n\n' +for lang in $(langs); do + for c in pages $(collections); do + if [ "$c" = 'pages' ]; then + filter="$page_ext_filter" + dir="$CONTENT_PREFIX/$lang" + else + filter='^$' + dir="$CONTENT_PREFIX/$lang/$c" fi - # shellcheck disable=2016 - printf '%s%s = $(%s.md:.md=%s)\n' "$r" "$e" "$r" "$e" - done - printf '%s =' "$r" - for e in $EXTENSIONS; do - if [ "$e" = '.md' ]; then + + mds() { + # find "$dir"/*.md # FIXME + find "$dir"/*.md 2>/dev/null + } + + exts() { + extensions | grep -Ev "$filter" + } + + mds | varlist "$c.$lang.md" + exts | sed "s|^\(.*\)\$|$c.$lang\1 = \$($c.$lang.md:.md=\1)|" + exts | sed "s|^\(.*\)\$|\$($c.$lang\1)|" | varlist "$c.$lang" + + mds | sed 's/^\(.*\)\.md$/\1.conf \1.content: \1.md/' + mds | sed 's/^\(.*\)\.md$/\1.snippets \1.htmlbody \1.html: \1.conf \1.content/' + if [ "$c" = 'pages' ]; then continue fi - # shellcheck disable=2016 - printf ' $(%s%s)' "$r" "$e" + + mds | sed 's/^\(.*\)\.md$/\1.sortref: \1.md/' + mds | sed 's/^\(.*\)\.md$/\1.xmlentry: \1.html/' + + echo "$CONTENT_PREFIX/$lang/feeds/$c.xml: \$($c.$lang.xmlentry)" + + printf '\n\n' done - printf '\n' - html_deps content_mds "$r" - printf '\n' -done + for e in $(extensions); do + { + if ! printf '%s\n' "$e" | grep -qE "$page_ext_filter"; then + echo pages + fi + collections + } | + sed "s|^\(.*\)\$|\$(\1.$lang$e)|" | + varlist "all-generated.$lang$e" + done -all_resources() { - echo "$RESOURCES" | tr ' ' '\n' | grep . -} + collections | + sed "s|^\(.*\)\$|$CONTENT_PREFIX/$lang/feeds/\1.xml|" | + varlist "all-generated.$lang.xml" -all_vars() { - EXT="$1" - # shellcheck disable=2016 - all_resources | - sed 's|^|$(|' | - sed "s|$|$EXT)|" | - varlist all-generated"$EXT" -} + extensions '.xml' | + sed "s|^\(.*\)\$|\$(all-generated.$lang\1)|" | + varlist "all-generated.$lang" -for e in $EXTENSIONS; do - all_vars "$e" + printf '\n' +done + +for e in $(extensions .xml); do + langs | + sed "s|^\(.*\)\$|\$(all-generated.\1$e)|" | + varlist "all-generated$e" done -all_vars '' + +# shellcheck disable=2016 +langs | + sed 's|^\(.*\)$|$(all-generated.\1)|' | + varlist 'all-generated' -git ls-files | - grep -v '^src/content/' | +git ls-files src/ | + grep -v ^"$CONTENT_PREFIX"/ | varlist 'non-content' -git ls-files src/content/ | +git ls-files "$CONTENT_PREFIX"/ | grep -v '\.md$' | - grep -Ev "src/content/($(all_resources | paste -sd'|'))/" | varlist 'static-content' diff --git a/v2/src/development/security-txt.sh.in b/v2/src/bin/security-txt index 8f6613f..7026969 100755 --- a/v2/src/development/security-txt.sh.in +++ b/v2/src/bin/security-txt @@ -4,8 +4,8 @@ set -eu usage() { cat <<-'EOF' Usage: - src/development/security-txt.sh - src/development/security-txt.sh -h + security-txt + security-txt -h EOF } @@ -25,7 +25,7 @@ help() { Just run it: - $ sh src/development/security-txt.sh > .well-known/security.txt + $ security-txt > .well-known/security.txt EOF } @@ -62,21 +62,21 @@ shift $((OPTIND - 1)) EXPIRES="$( - LANG=C.UTF-8 gpg --list-key eu@euandre.org | + LANG=C.UTF-8 gpg --list-key "$EMAIL" | awk '/^pub/ { print substr($(NF), 1, 10) }' )T00:00:00z" -LANGS="en$( - echo po/??.po | - sed 's|\.po$||' | - sed 's|^po/|, |' | - paste -sd, +LANGUAGES="$( + langs | + sed 's|^|, |' | + tr -d '\n' | + sed 's|^, ||' )" cat <<-EOF - Contact: mailto:@EMAIL@ - Encryption: https://@DOMAIN@/public.asc.txt + Contact: mailto:$EMAIL + Encryption: $(url-for 'public.asc.txt' | absolute) Expires: $EXPIRES - Preferred-Languages: $LANGS + Preferred-Languages: $LANGUAGES EOF diff --git a/v2/src/bin/url-for b/v2/src/bin/url-for index d4099bc..adaccd7 100755 --- a/v2/src/bin/url-for +++ b/v2/src/bin/url-for @@ -4,7 +4,7 @@ set -eu usage() { cat <<-'EOF' Usage: - url-for [-g] FILE + url-for FILE url-for -h EOF } @@ -13,7 +13,6 @@ help() { cat <<-'EOF' Options: - -g global file, not specific to a single language -h, --help show this message FILE the path for the URL to be constructed @@ -25,7 +24,7 @@ help() { Examples: - Get the URL for "about.html", when $base_url is "v2" and $lang is "en": + Get the URL for "en/about.html", when $base_url is "v2": $ url-for 'about.html' /v2/en/about.html @@ -33,8 +32,8 @@ help() { Get the URL for "static/favicon.svg", when $base_url is empty: - $ url-for -g 'static/favicon.svg' - /static/favicon.svg + $ url-for 'img/link.svg' + /img/link.svg EOF } @@ -54,12 +53,8 @@ for flag in "$@"; do esac done -GLOBAL=false -while getopts 'gh' flag; do +while getopts 'h' flag; do case "$flag" in - g) - GLOBAL=true - ;; h) usage help @@ -73,22 +68,19 @@ while getopts 'gh' flag; do done shift $((OPTIND - 1)) -. src/development/lib.sh - +. src/lib.sh FILE="${1:-}" +eval "$(assert_arg "$FILE" 'FILE')" + + if [ "$FILE" = '/' ]; then FILE='' fi -. src/lib/base-conf +. src/lib/base.conf # shellcheck source=/dev/null . src/lib/base."${lang:?}".conf -if [ "$GLOBAL" = true ]; then - L='' -else - L="${lang:?}/" -fi -printf '%s%s%s' "${base_url:-/}" "$L" "$FILE" +printf '%s%s' "${base_url:-/}" "$FILE" diff --git a/v2/src/bin/xmlentry b/v2/src/bin/xmlentry new file mode 100755 index 0000000..b0760ae --- /dev/null +++ b/v2/src/bin/xmlentry @@ -0,0 +1,81 @@ +#!/bin/sh +set -eu + +usage() { + cat <<-'EOF' + Usage: + xmlentry FILENAME + xmlentry -h + EOF +} + +help() { + cat <<-'EOF' + + + Options: + -h, --help show this message + + FILENAME the name of the input .md file + + + Process FILE, and generate an Atom feed entry. + + + Examples: + + Generate the XML entry for a TIL: + + $ xmlentry src/tils/a-til.md > src/tils/a-til.xml + EOF +} + + +for flag in "$@"; do + case "$flag" in + --) + break + ;; + --help) + usage + help + exit + ;; + *) + ;; + esac +done + +while getopts 'h' flag; do + case "$flag" in + h) + usage + help + exit + ;; + *) + usage >&2 + exit 2 + ;; + esac +done +shift $((OPTIND - 1)) + +. src/lib.sh + +FILENAME="${1:-}" +eval "$(assert_arg "$FILENAME" 'FILENAME')" + + +# shellcheck source=/dev/null +. "${FILENAME%.md}.conf" + +envsubst < src/lib/entry.xml + +head -n1 < "${FILENAME%.md}.htmlbody" | htmlesc +printf ' </summary>\n' +printf ' <content type="html" xml:base="%s">\n' "${url:?}" + +htmlesc < "${FILENAME%.md}.htmlbody" +printf ' </content>\n' +printf ' </entry>\n' diff --git a/v2/src/content/about.md b/v2/src/content/en/about.md index b10f26b..1e39407 100644 --- a/v2/src/content/about.md +++ b/v2/src/content/en/about.md @@ -2,12 +2,6 @@ title: About -layout: page - -lang: en - -ref: aboud - --- It's all about me, baby! diff --git a/v2/src/content/pastebins/raku-tuple-type-annotation.md b/v2/src/content/en/pastebins/raku-tuple-type-annotation.md index 3d5ff34..5877470 100644 --- a/v2/src/content/pastebins/raku-tuple-type-annotation.md +++ b/v2/src/content/en/pastebins/raku-tuple-type-annotation.md @@ -4,12 +4,6 @@ title: Raku tuple type annotation date: 2019-12-29 -layout: post - -lang: en - -ref: raku-tuple-type-annotation - --- ```perl diff --git a/v2/src/content/pastebins/sicp-exercise-3-19.md b/v2/src/content/en/pastebins/sicp-exercise-3-19.md index 8834889..3188dce 100644 --- a/v2/src/content/pastebins/sicp-exercise-3-19.md +++ b/v2/src/content/en/pastebins/sicp-exercise-3-19.md @@ -4,12 +4,6 @@ title: SICP exercise 3.19 date: 2021-09-02 -layout: post - -lang: en - -id: sicp-exercise-3-19 - --- Some content here, before: diff --git a/v2/src/content/tils/lisp-three-way-conditional.md b/v2/src/content/en/tils/lisp-three-way-conditional.md index 81920c4..cd7a034 100644 --- a/v2/src/content/tils/lisp-three-way-conditional.md +++ b/v2/src/content/en/tils/lisp-three-way-conditional.md @@ -6,12 +6,6 @@ date: 2021-04-24 3 update: 2021-08-14 -layout: post - -lang: en - -ref: three-way-conditional-for-number-signs-on-lisp - --- A useful macro from Paul Graham's [On Lisp][on-lisp] book: diff --git a/v2/src/content/favicon.ico b/v2/src/content/favicon.ico Binary files differnew file mode 100644 index 0000000..8f2130a --- /dev/null +++ b/v2/src/content/favicon.ico diff --git a/v2/src/content/pt/pastebins/exercicios-sicp-e-19.md b/v2/src/content/pt/pastebins/exercicios-sicp-e-19.md new file mode 100644 index 0000000..d4db88d --- /dev/null +++ b/v2/src/content/pt/pastebins/exercicios-sicp-e-19.md @@ -0,0 +1,103 @@ +--- + +title: SICP exercise 3.19 + +date: 2021-09-02 + +--- + +Some content here, before: + +```scheme +(define (cycle? l) + (define (rec l x) + (cond + ((null? x) false) + ((eq? l x) true) + (true (rec l (cdr x))))) + (rec l (cdr l))) +``` + +Sample interactive session: + +```scheme +scheme@(guile-user)> (define true #t) +scheme@(guile-user)> (define false #f) +scheme@(guile-user)> +(define (cycle? l) + (define (rec l x) + (cond + ((null? x) false) + ((eq? l x) true) + (true (rec l (cdr x))))) + (rec l (cdr l))) +scheme@(guile-user)> (cycle? '(1 2 3)) +$9 = #f +scheme@(guile-user)> (cycle? (make-cycle '(1 2 3))) +$10 = #t +``` + +# An h1 + +a list: + +1. one +2. two +3. three + +some content. + +- item +- another +- yet another + +## An h2 + +Xablau: + +``` xupliu 1 + +3 4 + + + + + +dez ``` + +Foi `wikiwiu`. + +a very long code block: + +``` +wef +wef wef wef wef +wef wef wef wef we fwef wef wef wef wef +``` + +Someone said: + +> Xablau, xupliu. + +### A repeated header ### A repeated header + +a big list: + +1. a +1. a +1. a +1. a +1. a +1. a +1. a +1. a +1. a +1. a +1. a +1. a +1. a +1. a +1. a +1. a +1. a +1. a diff --git a/v2/src/content/pt/sobre.md b/v2/src/content/pt/sobre.md new file mode 100644 index 0000000..97eecf8 --- /dev/null +++ b/v2/src/content/pt/sobre.md @@ -0,0 +1,9 @@ +--- + +title: About + +--- + +It's all about me, baby! + +``` xablau ``` diff --git a/v2/src/development/lib.sh b/v2/src/lib.sh index 9d183f9..9d183f9 100644 --- a/v2/src/development/lib.sh +++ b/v2/src/lib.sh diff --git a/v2/src/lib/base-conf.in b/v2/src/lib/base.conf index 4ec09cb..319d08c 100644 --- a/v2/src/lib/base-conf.in +++ b/v2/src/lib/base.conf @@ -1,10 +1,9 @@ -export domain='@DOMAIN@' -export email='@EMAIL@' +export domain="$DOMAIN" +export email="$EMAIL" export base_url='' export list_addr='~euandreh/public-inbox@lists.sr.ht' export mailto_uri_prefix="mailto:$list_addr?Subject=Re%3A%20" export discussions_url_prefix="https://lists.sr.ht/~euandreh/public-inbox?search=" export sourcecode_url_prefix="https://$domain/git/$domain/tree/" export author='EuAndreh' -export lang='en' export pubkey_id='81F90EC3CD356060' # FIXME diff --git a/v2/src/lib/entry.xml b/v2/src/lib/entry.xml new file mode 100644 index 0000000..e4a47c7 --- /dev/null +++ b/v2/src/lib/entry.xml @@ -0,0 +1,22 @@ + <entry xml:lang="$lang"> + <title type="html"> + $title_html + </title> + <link type="text/html" rel="alternative" href="$url" title="$title_html" /> + <published> + $date_iso + </published> +$update_xml + <id> + $url + </id> + <author> + <name> + $author + </name> + <email> + $email + </email> + </author> + + <summary type="html"> diff --git a/v2/src/lib/feed.xml b/v2/src/lib/feed.xml new file mode 100644 index 0000000..6fd82a4 --- /dev/null +++ b/v2/src/lib/feed.xml @@ -0,0 +1,15 @@ +<feed + xmlns="http://www.w3.org/2005/Atom" + xmlns:content="http://purl.org/rss/1.0/modules/content/" + xml:lang="$lang"> + <link href="$url" rel="self" type="application/atom+xml" /> + <link href="$homepage_url" rel="alternate" type="text/html" hreflang="$lang" /> + <title>$site_name_html</title> + <subtitle>{{ site.t[include.kind].feed.title[include.lang] | smartify | xml_escape }}</subtitle> + <id>$url</id> + <updated>$now</updated> + + <author> + <name>$author</name> + <email>$email</email> + </author> |