💾 Archived View for gemini.hyperlinkyourheart.com › gemicandocs › pages › gemican-internals.gmi captured on 2023-12-28 at 15:18:05. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2021-11-30)

-=-=-=-=-=-=-

Gemican internals

This section describe how Gemican works internally. As you'll see, it's quite simple, but a bit of documentation doesn't hurt. :)

You can also find in the report section an excerpt of a report the original author wrote with some software design information.

Overall structure

What Gemican does is take a list of files and process them into some sort of output. Usually, the input files are Gemtext and Markdown files, and the output is a gemlog, but both input and output can be anything you want.

The logic is separated into different classes and concepts:

How to implement a new reader?

Is there an awesome markup language you want to add to Gemican? Well, the only thing you have to do is to create a class with a `read` method that returns HTML content and some metadata.

Take a look at the Markdown reader:

from gemican.readers import MarkdownMetaDataReader

try:
    from md2gemini import md2gemini
except ImportError:
    md2gemini = False  # NOQA


def _markdown_link_func(link):
    """Link func that undoes the url-encoding that md2gemini has done"""
    return unquote(link)


class MarkdownReader(MarkdownMetaDataReader):
    """Reader for Markdown files"""

    enabled = bool(md2gemini)
    file_extensions = ['md', 'markdown', 'mkd', 'mdown']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.markdown_settings = self.settings['MARKDOWN']
        if 'link_func' not in self.markdown_settings:
            self.markdown_settings['link_func'] = _markdown_link_func

    def read(self, source_path):
        """Parse content and metadata of markdown files"""

        text, meta = super().read(source_path)

        self._source_path = source_path
        content = md2gemini(text, **self.markdown_settings).rstrip('\ufeff')
        # md2gemini does not include a newline at the end even if one
        # was present in the content.
        if len(content) > 0:
            content += '\r\n'
        return content, meta

Simple, isn't it?

If your new reader requires additional Python dependencies, then you should wrap their `import` statements in a `try...except` block. Then inside the reader's class, set the `enabled` class attribute to mark import success or failure. This makes it possible for users to continue using their favourite markup method without needing to install modules for formats they don't use.

How to implement a new generator?

Generators have two important methods. You're not forced to create both; only the existing ones will be called.

1: https://palletsprojects.com/p/jinja/

↩ Index