Add: Complete Ablog support

This commit is contained in:
Kujiu 2021-02-03 00:33:19 +01:00
parent f510a9b2cc
commit 2e32729b5b
Signed by: kujiu
GPG key ID: ABBB2CAC6855599F
3 changed files with 166 additions and 12 deletions

View file

@ -46,6 +46,11 @@ class GeminiBuilder(TextBuilder):
super().__init__(app)
self.add_footer = True
self.baseurl = self.config.gemini_baseurl
self.footer_enabled = True
self.header_enabled = True
if self.baseurl:
# Creepy trick...
self.config.blog_baseurl = self.baseurl
self.images = []
def prepare_writing(self, docnames: Set[str]) -> None:

View file

@ -17,11 +17,12 @@ from docutils import nodes
import ablog
from ablog.blog import Blog, os_path_join, revise_pending_xrefs
from ablog.blog import Post, Blog, os_path_join, revise_pending_xrefs
logger = logging.getLogger(__name__)
text_type = str
class Page:
""" Mini translator for gemini """
@ -31,8 +32,11 @@ class Page:
self.builder = builder
def add_title(self, text: str, level: int = 1) -> None:
self.body += '# ' * level
self.body += text + '\n'
self.body += '#' * level
self.body += ' ' + text + '\n'
def add_item(self, text: str) -> None:
self.body += '* %s\n' % text
def add_link(self, uri: str, desc: str = None) -> None:
self.body += '=> %s' % uri
@ -40,6 +44,9 @@ class Page:
self.body += ' %s' % desc
self.body += '\n'
def add_raw(self, text: str) -> None:
self.body += text
def end_block(self) -> None:
self.body += '\n'
@ -48,7 +55,7 @@ class Page:
self.body += '\n\n'
def write(self):
path = os.path.join(self.builder.outdir, self.docname)
path = os.path.join(self.builder.outdir, self.docname + self.builder.out_suffix)
folder = os.path.dirname(path)
if not os.path.exists(folder):
os.makedirs(folder)
@ -57,7 +64,7 @@ class Page:
out.write(self.body)
def to_gemini(builder, post, pagename, fulltext=False):
def to_gemini(builder, post, pagename: str, fulltext: bool = False):
"""
Convert post to gemini format
"""
@ -86,6 +93,61 @@ def to_gemini(builder, post, pagename, fulltext=False):
return gemini
def add_post_to_page(builder, doc: Page, post) -> None:
doc.add_title(post.title, 2)
doc.add_link(
builder.config.gemini_baseurl + post.docname + builder.out_suffix,
_("Read post")
)
doc.end_block()
if post.published:
doc.add_item(_("Date: %s") % post.date.strftime(builder.config.post_date_format))
else:
doc.add_item(_("Draft"))
if post.date != post.update:
doc.add_item(_("Update: %s") % post.update.strftime(ablog.post_date_format))
for author in post.author:
doc.add_link(
builder.config.gemini_baseurl + author.docname,
_("Author: %s" % str(author))
)
for location in post.location:
doc.add_link(
builder.config.gemini_baseurl + location.docname,
_("Location: %s" % str(location))
)
for language in post.language:
doc.add_link(
builder.config.gemini_baseurl + language.docname,
_("Language: %s" % str(language))
)
for category in post.category:
doc.add_link(
builder.config.gemini_baseurl + category.docname,
_("Category: %s" % str(category))
)
for tag in post.tags:
doc.add_link(
builder.config.gemini_baseurl + tag.docname,
_("Tag: %s" % str(tag))
)
doc.end_block()
builder.footer_enabled = False
builder.header_enabled = False
doc.add_paragraph(to_gemini(builder, post, post.docname, fulltext=False))
builder.footer_enabled = True
builder.header_enabled = True
def generate_archive_pages(builder):
"""
Generate archive pages for all posts, categories, tags, authors, and
@ -177,12 +239,34 @@ def generate_archive_pages(builder):
doc.add_title(str(collection))
if context["atom_feed"]:
doc.add_link(
collection.path+"/atom.xml",
builder.config.gemini_baseurl+collection.path+"/atom.xml",
_("Atom feed")
)
doc.end_block()
doc.write()
doc.end_block()
for subcoll in collection:
if isinstance(subcoll, Post):
add_post_to_page(builder, doc, subcoll)
continue
doc.add_title(str(subcoll), 2)
doc.add_link(
builder.get_target_uri(post.docname),
_("Go to collection")
)
doc.end_block()
for post in subcoll:
doc.add_link(
builder.config.gemini_baseurl + post.docname + builder.out_suffix,
_("Read post")
)
doc.end_block()
doc.add_raw(ablog_footer(builder))
doc.add_paragraph(builder.config.gemini_footer)
doc.write()
def generate_atom_feeds(builder):
@ -190,6 +274,8 @@ def generate_atom_feeds(builder):
Generate archive pages for all posts, categories, tags, authors, and
drafts (from ablog).
"""
builder.footer_enabled = False
builder.header_enabled = False
blog = Blog(builder.app)
url = builder.config.gemini_baseurl
@ -277,3 +363,57 @@ def generate_atom_feeds(builder):
with open(feed_path, "w", encoding="utf-8") as out:
feed_str = feed.atom_str(pretty=True)
out.write(feed_str.decode())
builder.footer_enabled = True
builder.header_enabled = True
def ablog_header(builder) -> str:
""" Generate header for Atom """
header = ''
blog = Blog(builder.app)
if builder.current_docname in blog.posts:
post = blog.posts[builder.current_docname]
header = _('By %s') % ', '.join([str(author) for author in post.author]) + '\n'
header += post.date.strftime(builder.config.post_date_format)
header += '\n'
if post.date != post.update:
header += _('Updated on %s') % \
post.update.strftime(builder.config.post_date_format)
header += '\n'
header += '\n'
return header
def ablog_footer(builder) -> str:
""" Generate footer for Atom """
blog = Blog(builder.app)
baseurl = builder.config.gemini_baseurl
if not baseurl:
return
footer = '\n\n'
footer += _('# Blog menu')
footer += '\n'
for title, catalog in [
(_("Authors"), blog.author),
(_("Locations"), blog.location),
(_("Languages"), blog.language),
(_("Categories"), blog.category),
]:
footer += '## %s\n' % title
footer += '=> %s %s\n' % (baseurl + catalog.docname + builder.out_suffix, _("All"))
for coll in catalog:
footer += '=> %s %s\n' % (baseurl + coll.docname + builder.out_suffix, str(coll))
footer += '\n'
footer += '## %s\n' % _("All posts")
footer += '=> %s %s\n' % (baseurl + blog.archive.docname + builder.out_suffix, _("All posts"))
footer += '\n'
footer += '## %s\n' % _("Tags")
footer += '=> %s %s\n' % (baseurl + blog.tags.docname + builder.out_suffix, _("Tags"))
footer += '\n'
return footer

View file

@ -93,9 +93,17 @@ class GeminiTranslator(SphinxTranslator):
self.pre = True
def visit_document(self, node: Element) -> None:
pass
if 'ablog' in self.builder.config.extensions and self.builder.header_enabled:
from .ablog_compatibility import ablog_header
self.add_text(ablog_header(self.builder))
def depart_document(self, node: Element) -> None:
if not self.builder.footer_enabled:
return
if 'ablog' in self.builder.config.extensions:
from .ablog_compatibility import ablog_footer
self.add_text(ablog_footer(self.builder))
if self.builder.add_footer:
self.add_text(self.config.gemini_footer)
@ -402,12 +410,13 @@ class GeminiTranslator(SphinxTranslator):
def visit_image(self, node: Element) -> None:
self.end_block()
uri = relative_uri(self.builder.current_docname, node['uri'])
full_uri = uri
if self.builder.config.gemini_baseurl:
uri = self.builder.config.gemini_baseurl + node['uri']
full_uri = self.builder.config.gemini_baseurl + node['uri']
if 'alt' in node.attributes:
self.add_link(uri, __('[image: %s]') % node['alt'])
self.add_link(full_uri, __('[image: %s]') % node['alt'])
else:
self.add_link(uri)
self.add_link(full_uri)
self.end_block()
self.builder.images.append(posixpath.join(self.builder.imgpath, uri))
raise nodes.SkipNode