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.
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:
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.
Generators have two important methods. You're not forced to create both; only the existing ones will be called.