summaryrefslogtreecommitdiff
path: root/src/pyssg/pyssg.py
blob: 4de80d5ecf6447227c5e65fdc90eccc4a3e13cef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import os
import sys
import logging
from logging import Logger
from importlib.resources import path as rpath
from typing import Union
from configparser import ConfigParser

from jinja2 import Environment, FileSystemLoader
from markdown import Markdown
from yafg import YafgExtension
from MarkdownHighlight.highlight import HighlightExtension
from markdown_checklist.extension import ChecklistExtension

from .utils import create_dir, copy_file, sanity_check_path
from .arg_parser import get_parsed_arguments
from .configuration import get_parsed_config, DEFAULT_CONFIG_PATH, VERSION
from .database import Database
from .builder import Builder

log: Logger = logging.getLogger(__name__)


def main() -> None:
    args: dict[str, Union[str, bool]] = vars(get_parsed_arguments())

    if args['debug']:
        # need to modify the root logger specifically,
        #   as it is the one that holds the config
        #   (__name__ happens to resolve to pyssg in __init__)
        root_logger: Logger = logging.getLogger('pyssg')
        root_logger.setLevel(logging.DEBUG)
        for handler in root_logger.handlers:
            handler.setLevel(logging.DEBUG)
        log.debug('changed logging level to DEBUG')

    if not len(sys.argv) > 1 or (len(sys.argv) == 2 and args['debug']):
        log.info('pyssg v%s - no arguments passed, --help for more', VERSION)
        sys.exit(0)

    if args['version']:
        log.info('pyssg v%s', VERSION)
        sys.exit(0)

    log.debug('checking config file path')
    config_path: str = args['config'] if args['config'] else DEFAULT_CONFIG_PATH
    config_path = os.path.normpath(os.path.expandvars(config_path))
    sanity_check_path(config_path)
    config_dir, _ = os.path.split(config_path)
    log.debug('checked config file path, final config path "%s"', config_path)

    if args['copy_default_config']:
        log.info('copying default config file')
        create_dir(config_dir)
        with rpath('pyssg.plt', 'default.ini') as p:
            copy_file(p, config_path)
        sys.exit(0)

    if not os.path.exists(config_path):
        log.error('config file does\'t exist in path "%s"; make sure'
                  ' the path is correct; use --copy-default-config if it\'s the'
                  ' first time if you haven\'t already', config_path)
        sys.exit(1)

    config: ConfigParser = get_parsed_config(config_path)

    if args['init']:
        log.info('initializing the directory structure and copying over templates')
        create_dir(config.get('path', 'src'))
        create_dir(os.path.join(config.get('path', 'dst'), 'tag'), True)
        create_dir(config.get('path', 'plt'))
        files: list[str] = ('index.html',
                            'page.html',
                            'tag.html',
                            'rss.xml',
                            'sitemap.xml')
        log.debug('list of files to copy over: (%s)', ', '.join(files))
        for f in files:
            plt_file: str = os.path.join(config.get('path', 'plt'), f)
            with rpath('pyssg.plt', f) as p:
                copy_file(p, plt_file)
        sys.exit(0)

    if args['build']:
        log.debug('building the html files')
        db: Database = Database(os.path.join(config.get('path', 'src'), '.files'))
        db.read()

        # the autoescape option could be a security risk if used in a dynamic
        # website, as far as i can tell
        log.debug('initializing the jinja environment')
        env: Environment = Environment(loader=FileSystemLoader(config.get('path', 'plt')),
                                       autoescape=False,
                                       trim_blocks=True,
                                       lstrip_blocks=True)

        # md extensions
        exts: list = ['extra',
                      'meta',
                      'sane_lists',
                      'smarty',
                      'toc',
                      'wikilinks',
                      # stripTitle generates an error when True,
                      # if there is no title attr
                      YafgExtension(stripTitle=False,
                                    figureClass="",
                                    figcaptionClass="",
                                    figureNumbering=False,
                                    figureNumberClass="number",
                                    figureNumberText="Figure"),
                      HighlightExtension(),
                      ChecklistExtension()]
        log.debug('list of md extensions: (%s)', ', '.join(exts))
        log.debug('initializing markdown parser')
        md: Markdown = Markdown(extensions=exts,
                                output_format='html5')
        builder: Builder = Builder(config, env, db, md)
        builder.build()

        db.write()
        sys.exit(0)