aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.build.yml10
-rw-r--r--Makefile2
-rw-r--r--_ext/gemtext_builder.py188
-rw-r--r--conf.py1
-rw-r--r--index.rst1
5 files changed, 196 insertions, 6 deletions
diff --git a/.build.yml b/.build.yml
index 49d5db7..1f2891f 100644
--- a/.build.yml
+++ b/.build.yml
@@ -16,8 +16,8 @@ tasks:
- compress: |
cd crowbar-spec/_build/html
tar czf ../crowbar-spec-html.tar.gz *
- #cd ../gmi
- #tar czf ../crowbar-spec-gmi.tar.gz *
+ cd ../gmi
+ tar czf ../crowbar-spec-gmi.tar.gz *
- upload: |
upload-to() {
dest=$1
@@ -26,8 +26,8 @@ tasks:
}
cd crowbar-spec/_build/html
upload-to /var/www/html/crowbar-lang.org/ * ../rinoh/crowbar-spec.pdf ../epub/crowbar-spec.epub
- #cd ../gmi
- #upload-to /var/gemini/gmi/crowbar-lang.org/ * ../rinoh/crowbar-spec.pdf ../epub/crowbar-spec.epub
+ cd ../gmi
+ upload-to /var/gemini/gmi/crowbar-lang.org/ * ../rinoh/crowbar-spec.pdf ../epub/crowbar-spec.epub
- notify: |
cd crowbar-spec
message="crowbar spec updated: $(git log -1 --no-decorate --oneline)"
@@ -36,4 +36,4 @@ artifacts:
- crowbar-spec/_build/rinoh/crowbar-spec.pdf
- crowbar-spec/_build/epub/crowbar-spec.epub
- crowbar-spec/_build/crowbar-spec-html.tar.gz
- #- crowbar-spec/_build/crowbar-spec-gmi.tar.gz
+ - crowbar-spec/_build/crowbar-spec-gmi.tar.gz
diff --git a/Makefile b/Makefile
index ebe0ed5..f3fc47f 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ SOURCEDIR = .
BUILDDIR = _build
PDFINFO = pdfinfo
-all: html pdf epub # gmi
+all: html pdf epub gmi
html: Makefile
@$(SPHINXBUILD) -M html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXFULLOPTS)
diff --git a/_ext/gemtext_builder.py b/_ext/gemtext_builder.py
new file mode 100644
index 0000000..9c31788
--- /dev/null
+++ b/_ext/gemtext_builder.py
@@ -0,0 +1,188 @@
+from pathlib import Path
+from typing import Set
+
+from docutils import nodes, writers
+from docutils.io import StringOutput
+from sphinx.builders import Builder
+from sphinx.util import logging
+from sphinx.util.docutils import SphinxTranslator
+from sphinx.util.osutil import ensuredir, os_path
+
+logger = logging.getLogger(__name__)
+
+class GemtextWriter(writers.Writer):
+ def __init__(self, builder):
+ super().__init__()
+ self.builder = builder
+
+ def translate(self):
+ visitor = self.builder.create_translator(self.document, self.builder)
+ self.document.walkabout(visitor)
+ self.output = '\n'.join(visitor.body) + '\n'
+
+class GemtextTranslator(SphinxTranslator):
+ def __init__(self, document: nodes.document, builder):
+ super().__init__(document, builder)
+ self.heading_level = 0
+ self.current_line = ''
+ self.body = []
+ self.literal = False
+
+ def _finish_line(self):
+ if self.current_line != '':
+ self.body.append(self.current_line)
+ self.current_line = ''
+
+ def visit_document(self, node: nodes.document):
+ self.heading_level = 1
+ self.current_line = ''
+ self.body = []
+ self.literal = False
+
+ def depart_document(self, node: nodes.document):
+ self._finish_line()
+
+ def visit_section(self, node: nodes.section):
+ self.heading_level += 1
+ if len(self.body) > 0 and self.body[-1] != '':
+ self.body.append('')
+
+ def depart_section(self, node: nodes.section):
+ self.heading_level -= 1
+
+ def visit_title(self, node: nodes.title):
+ pass
+
+ def depart_title(self, node: nodes.title):
+ self.current_line = '#' * (self.heading_level - 1) + ' ' + self.current_line
+ self._finish_line()
+ self.body.append('')
+
+ def visit_Text(self, node: nodes.Text):
+ text = node.astext()
+ if not self.literal:
+ text = text.replace('\n', ' ')
+ self.current_line += text
+
+ def depart_Text(self, node: nodes.Text):
+ pass
+
+ def visit_paragraph(self, node: nodes.paragraph):
+ pass
+
+ def depart_paragraph(self, node: nodes.paragraph):
+ self._finish_line()
+
+ def visit_reference(self, node: nodes.reference):
+ pass
+
+ def depart_reference(self, node: nodes.reference):
+ if self.current_line.startswith('=>'):
+ self._finish_line()
+ self.body.append('=> {} {}'.format(node.attributes['refuri'], node.astext()))
+ else:
+ self.current_line = '=> {} {}'.format(node.attributes['refuri'], self.current_line)
+
+ def visit_image(self, node: nodes.image):
+ if self.current_line == '':
+ self.body.append('=> {} {}'.format(node.attributes['uri'], node.attributes['alt']))
+ else:
+ raise NotImplementedError('inline images')
+
+ def depart_image(self, node: nodes.image):
+ pass
+
+ def visit_comment(self, node: nodes.comment):
+ raise nodes.SkipNode
+
+ def visit_strong(self, node: nodes.strong):
+ self.current_line += '**'
+
+ depart_strong = visit_strong
+
+ def visit_emphasis(self, node: nodes.emphasis):
+ self.current_line += '_'
+
+ depart_emphasis = visit_emphasis
+
+ def visit_target(self, node: nodes.target):
+ raise nodes.SkipNode
+
+ def visit_bullet_list(self, node: nodes.bullet_list):
+ pass
+
+ def depart_bullet_list(self, node: nodes.bullet_list):
+ pass
+
+ def visit_list_item(self, node: nodes.list_item):
+ self.current_line += '* '
+
+ def depart_list_item(self, node: nodes.list_item):
+ pass
+
+ def visit_compound(self, node: nodes.compound):
+ pass
+
+ def depart_compound(self, node: nodes.compound):
+ pass
+
+ def visit_inline(self, node: nodes.inline):
+ pass
+
+ def depart_inline(self, node: nodes.inline):
+ pass
+
+ def visit_title_reference(self, nodes: nodes.title_reference):
+ pass
+
+ def depart_title_reference(self, nodes: nodes.title_reference):
+ pass
+
+ def visit_literal(self, nodes: nodes.literal):
+ self.current_line += '`'
+
+ depart_literal = visit_literal
+
+ def visit_literal_block(self, nodes: nodes.literal_block):
+ self.body.append('')
+ self.body.append('```')
+ self.literal = True
+
+ def depart_literal_block(self, nodes: nodes.literal_block):
+ self._finish_line()
+ self.body.append('```')
+ self.body.append('')
+ self.literal = False
+
+class GemtextBuilder(Builder):
+ name = 'gmi'
+ format = 'gmi'
+
+ out_suffix = '.gmi'
+ default_translator_class = GemtextTranslator
+
+ def get_outdated_docs(self):
+ return self.env.found_docs # can't be fucked to implement this right
+
+ def get_target_uri(self, docname: str, typ: str = None):
+ return docname
+
+ def prepare_writing(self, docnames: Set[str]):
+ self.writer = GemtextWriter(self)
+
+ def write_doc(self, docname: str, doctree: nodes.document):
+ destination = StringOutput(encoding='utf-8')
+ self.writer.write(doctree, destination)
+ out_name = Path(self.outdir, os_path(docname) + '.gmi')
+ out_name.parent.mkdir(parents=True, exist_ok=True)
+ with open(out_name, 'w', encoding='utf-8') as out_file:
+ out_file.write(self.writer.output)
+
+def setup(app):
+ app.add_builder(GemtextBuilder)
+
+ return {
+ 'version': '0.1',
+ 'parallel_read_safe': True,
+ 'parallel_write_safe': True,
+ }
diff --git a/conf.py b/conf.py
index 58f2f66..9aa2aa3 100644
--- a/conf.py
+++ b/conf.py
@@ -30,6 +30,7 @@ author = 'boringcactus (Melody Horn)'
extensions = [
'recommonmark',
'crowbar_lexer',
+ 'gemtext_builder',
]
# Add any paths that contain templates here, relative to this directory.
diff --git a/index.rst b/index.rst
index 08ad2d7..76dd607 100644
--- a/index.rst
+++ b/index.rst
@@ -52,6 +52,7 @@ Discuss
.. toctree::
:maxdepth: 2
:hidden:
+ :numbered:
vs-c
tagged-unions