diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | _css/style.css | 11 | ||||
-rw-r--r-- | _layout/page_foot.html | 12 | ||||
-rw-r--r-- | _libs/formbox/comment.html | 7 | ||||
-rw-r--r-- | _libs/formbox/comment.xml | 1 | ||||
-rwxr-xr-x | _libs/formbox/format | 71 | ||||
-rw-r--r-- | _rss/comments.xml | 11 | ||||
-rw-r--r-- | _rss/head.xml | 4 | ||||
-rw-r--r-- | _rss/item.xml | 6 | ||||
-rw-r--r-- | index.md | 2 | ||||
-rw-r--r-- | utils.jl | 24 |
11 files changed, 125 insertions, 25 deletions
diff --git a/.gitignore b/.gitignore index 2355507..0a3ca5a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ __site/ _css/fonts/ _css/katex.min.css _libs/fediring +_libs/formbox/mbox _libs/highlight/ _libs/katex/ _libs/openring/out.html diff --git a/_css/style.css b/_css/style.css index 790c177..af502d7 100644 --- a/_css/style.css +++ b/_css/style.css @@ -204,7 +204,7 @@ code, .hljs { padding: 0.1em 0.2em; } -.hljs { +.hljs, .comment pre > code { display: block; line-height: 1.45em; overflow-x: auto; @@ -227,6 +227,15 @@ code, .hljs { .hljs-selector-pseudo, .hljs-template-tag, .hljs-template-variable, .hljs-addition { color: var(--red) } +.comment { + background-color: #8881; + clear: both; + margin: 1ex 0; + overflow: hidden; + padding: 1ex; +} +.comment p { margin: 1ex } + .openring { display: flex; flex-wrap: wrap; diff --git a/_layout/page_foot.html b/_layout/page_foot.html index 848d42e..88d33ea 100644 --- a/_layout/page_foot.html +++ b/_layout/page_foot.html @@ -1,11 +1,11 @@ {{isnotempty tags}}<small class=tags><strong>Tags:</strong>{{for tag in tags}} <a href=/tag/{{tag}}>{{tag}}</a>{{end}}</small> <small class=right>—{{isempty rss}}{{author}}, - {{else}}{{mailto_comment}}, {{end}}{{date}}</small><br>{{end}} + {{else}}<a href="{{mailto_comment}}" title="Reply via email">{{author}}</a>, + {{end}}{{date}}</small><br>{{end}} -{{isnotempty rss}}<section class=comments> - <h2>Comments</h2> - <p>To reply, follow the <code>mailto</code> link - in the the author's name.</p> -</section>{{end}} +{{isnotempty rss}}<h2>Comments</h2> +{{comments_rendered}} +<p>To reply, follow the <code>mailto</code> link + in the the author's name.</p>{{end}} {{insert footer.html}} diff --git a/_libs/formbox/comment.html b/_libs/formbox/comment.html new file mode 100644 index 0000000..60459d9 --- /dev/null +++ b/_libs/formbox/comment.html @@ -0,0 +1,7 @@ +<div class=comment> + {body} + <p class=right>—{author}, + <a href="https://lists.sr.ht/~cnx/site/{message_id}" + title="View source">{date}</a></p> + {children} +</div> diff --git a/_libs/formbox/comment.xml b/_libs/formbox/comment.xml index 2078071..5f183a0 100644 --- a/_libs/formbox/comment.xml +++ b/_libs/formbox/comment.xml @@ -4,7 +4,6 @@ <pubDate>{date}</pubDate> <dc:creator>{author}</dc:creator> <title>On {date}, {author} wrote:</title> - <description>{subject}</description> <content:encoded><![CDATA[{body}]]></content:encoded> </item> {children} diff --git a/_libs/formbox/format b/_libs/formbox/format new file mode 100755 index 0000000..39e6132 --- /dev/null +++ b/_libs/formbox/format @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# Format mbox as HTML/XML +# Copyright (C) 2021 Nguyễn Gia Phong +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +from argparse import ArgumentParser +from email.header import decode_header +from email.utils import parsedate_to_datetime +from functools import partial +from itertools import starmap +from mailbox import mbox +from pathlib import Path +from urllib.parse import quote + +from bleach import clean, linkify +from markdown import markdown + +sanitise = partial(clean, tags=('a', 'code', 'em', 'strong', 'sub', 'sup', + 'blockquote', 'p', 'pre', 'ul', 'ol', 'li'), + protocols=('ftp', 'gemini', 'gopher', 'http', 'https', + 'irc', 'ircs', 'mailto', 'matrix', 'xmpp')) + + +def extract(archive, parent): + for message_id, message in archive.copy().items(): + # TODO: handle multipart + if message['In-Reply-To'] != parent: continue + archive.pop(message_id) + yield message, extract(archive, message_id) + + +def decode(header): + for string, charset in decode_header(header): + encoding = 'utf-8' if charset is None else charset + yield string.decode(encoding) + + +def render(template, forest, parent): + for self, children in forest: + message_id = self['Message-Id'] + date = parsedate_to_datetime(self['Date']).date().isoformat() + author, address = decode(self['From']) + body = sanitise(linkify(markdown(self.get_payload(), + output_format='html5'))) + rendered_children = render(template, children, message_id) + yield template.format(message_id=quote(message_id), + date=date, author=author, body=body, + children='\n'.join(rendered_children)) + + +parser = ArgumentParser() +parser.add_argument('mbox') +parser.add_argument('id') +parser.add_argument('template', type=Path) +args = parser.parse_args() + +archive = {m['Message-Id']: m for m in mbox(args.mbox)} +template = args.template.read_text() +print(*render(template, extract(archive, args.id), args.id), sep='', end='') diff --git a/_rss/comments.xml b/_rss/comments.xml index be8fa6c..13d514b 100644 --- a/_rss/comments.xml +++ b/_rss/comments.xml @@ -4,7 +4,14 @@ xmlns:content="http://purl.org/rss/1.0/modules/content" xmlns:dc="http://purl.org/dc/elements/1.1"> <channel> -<title>Comments on {{fd2rss rss_title}}</title> +<title>Re: {{fd2rss rss_title}}</title> <link>{{fd_full_url}}</link> -<description></description> +<atom:link href="{{comment_rss_feed_url}}" + rel="self" + type="application/rss+xml"/> +<description>Comments on {{fd2rss rss_title}}</description> +<language>en</language> <generator>Formbox</generator> +{{comment_rss_items}} +</channel> +</rss> diff --git a/_rss/head.xml b/_rss/head.xml index 929038f..e27fe5e 100644 --- a/_rss/head.xml +++ b/_rss/head.xml @@ -6,9 +6,7 @@ <channel> <title>{{website_title}}</title> <link>{{website_url}}</link> -<atom:link href="{{fd_rss_feed_url}}" - rel="self" - type="application/rss+xml"/> +<atom:link href="{{fd_rss_feed_url}}" rel="self" type="application/rss+xml"/> <description>{{website_description}}</description> <copyright><![CDATA[{{copyright}} under CC BY-SA 4.0]]></copyright> <language>en</language> diff --git a/_rss/item.xml b/_rss/item.xml index 76f892a..8a808ff 100644 --- a/_rss/item.xml +++ b/_rss/item.xml @@ -5,10 +5,8 @@ <description>{{fd2rss rss_description}}</description> {{for tag in tags}}<category>{{tag}}</category>{{end}} <pubDate>{{RFC822 rss_pubdate}}</pubDate> - <content:encoded> - <![CDATA[{{fix_relative_links fd_page_html}} - <a href="{{mailto_comment}}">Reply</a>]]> - </content:encoded> + <content:encoded><![CDATA[{{fix_relative_links fd_page_html}} + <a href="{{mailto_comment}}">Reply via email</a>]]></content:encoded> <comments><![CDATA[{{comments}}]]></comments> <wfw:commentRss>{{comment_rss}}</wfw:commentRss> </item> diff --git a/index.md b/index.md index d360f1d..1c1166b 100644 --- a/index.md +++ b/index.md @@ -15,7 +15,7 @@ in the [Fediverse][]: * Matrix: [@cnx:halogen.city] [^culture]: Not necessarily mutually exclusive -[^xmpp]: Also XMPP, but mostly inactive +[^xmpp]: Or XMPP where I'm rarely active [^pgp]: PGP: [27148B2C06A2224B], also on [OpenPGP] [My name is]: https://www.youtube.com/watch?v=LDj8kkVwisY diff --git a/utils.jl b/utils.jl index 5a6e1c4..81c56fa 100644 --- a/utils.jl +++ b/utils.jl @@ -11,19 +11,32 @@ function hfun_abslink(args) end dir_url() = strip(dirname(locvar(:fd_url)), '/') -message_id() = @sprintf("<%s@cnx>", dir_url()) +message_id() = "<$(dir_url())@cnx>" hfun_comments() = @sprintf("https://lists.sr.ht/~cnx/site?search=%s:%s", "In-Reply-To", message_id()) +function render_comments(template) + prefix = joinpath(path(:libs), "formbox") + format = joinpath(prefix, "format") + mbox = joinpath(prefix, "mbox") + template_path = joinpath(prefix, template) + readchomp(`python3 $format $mbox $(message_id()) $template_path`) +end + +hfun_comments_rendered() = render_comments("comment.html") + function hfun_comment_rss() rpath = joinpath(dir_url(), "comments.xml") open(joinpath(path(:site), rpath), "w") do feed write(feed, convert_html(readchomp(joinpath(path(:rss), "comments.xml")))) - #write(feed, read(`python3 formbox.py mbox $(message_id()) $item_template`, String)) end joinpath(globvar(:website_url), rpath) end +hfun_comment_rss_feed_url() = joinpath(dirname(locvar(:fd_full_url)), + "comments.xml") +hfun_comment_rss_items() = render_comments("comment.xml") + function hfun_fediring(args) adj = readlines(joinpath(path(:libs), "fediring"))[parse(Int, args[1])] "<a href=https://$adj>$(args[2])</a>" @@ -33,11 +46,8 @@ hfun_github(args) = "<a href=https://github.com/$(args[1])>@$(args[1])</a>" hfun_job_url() = get(ENV, "JOB_URL", "https://builds.sr.ht/~cnx/site") function hfun_mailto_comment() - @sprintf("<a href='mailto:%s?%s=%s&%s=Re: %s' title='Reply via email'>%s</a>", - "~cnx/site@lists.sr.ht", - "In-Reply-To", message_id(), - "Subject", locvar(:title), - globvar(:author)) + @sprintf("mailto:%s?%s=%s&%s=Re: %s", "~cnx/site@lists.sr.ht", + "In-Reply-To", message_id(), "Subject", locvar(:title)) end hfun_openring() = readchomp(joinpath(path(:libs), "openring", "out.html")) |