boop.py 3.64 KB
Newer Older
1
2
3
#!/bin/env python3

import os
4
import sys
5
import shutil
6
import locale
7

8
9
import markdown

10
11
12
13
14
import boopsy


locale.setlocale(locale.LC_ALL, "fr_FR.utf8")

15

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class ProgramError(Exception):
    """Exception raised during the program execution.

    Examples:

    >>> try:
    ...     raise ProgramError("Oops")
    ... except ProgramError as e:
    ...     print(e.args[0])
    Oops
    """

    pass


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
def dir_tree(path):
    """List all the tree directory under the given path.
    """
    for filename in os.listdir(path):
        full_path = os.path.join(path, filename)
        if os.path.isdir(full_path):
            for sub_filename in dir_tree(full_path):
                yield os.path.join(filename, sub_filename)
        else:
            yield filename


def mkdirs_for_file(filepath):
    """Create parent directories for a given file.
    """
    path = os.path.dirname(filepath)
    os.makedirs(path, exist_ok=True)


50
51
52
53
54
55
56
57
58
59
60
61
62
63
def convert_meta_to_article_vars(meta):
    """Convert Markdown Meta to vars for article layout.
    """
    article_vars = {}
    for key, values in meta.items():
        article_key = f"ARTICLE_{key.upper()}"
        # The Markdown's meta extension extract all the values in arrays, even
        # if there is only one value. Because there is no iteration system in
        # the template system, for the moment we just get the first value of
        # the array.
        article_vars[article_key] = values[0]
    return article_vars


64
def main():
65
66
67
68
69
    # Check that content directory exists on the filesystem
    content_path = os.path.join(os.curdir, "content")
    if not os.path.isdir(content_path):
        raise ProgramError("./content directory does not exist")

70
    # Make sure output dir doesn't exist
71
72
    output_path = os.path.join(os.curdir, "output")
    if os.path.isdir(output_path):
73
        # it should be a directory...
74
        shutil.rmtree(output_path)
75
76
77
    elif os.path.exists(output_path):
        # ... but it also can be a simple file if user created it manually!
        os.remove(output_path)
78

79
    md = markdown.Markdown(extensions=["meta", "fenced_code", "attr_list"])
80

81
    # And copy the files from ./content to ./output
82
    for filepath in dir_tree(content_path):
83
        base, ext = os.path.splitext(filepath)
84
85
        content_filepath = os.path.join(content_path, filepath)
        output_filepath = os.path.join(output_path, filepath)
86
87
        if ext == ".md":
            output_filepath = os.path.join(output_path, f"{base}.html")
88
89
90
91

        # First we need to create all the parent directories for our file
        mkdirs_for_file(output_filepath)

92
93
94
95
96
        if ext == ".md":
            # Then, if it is a Markdown file, we convert it
            with open(content_filepath, "r") as content_file:
                html = md.convert(content_file.read())

97
98
99
100
101
102
103
104
105
106
            # We initialize the template
            article_template_filepath = os.path.join("theme", "article.html")
            template = boopsy.Template(article_template_filepath)

            # We get the local variables from the Markdown file (metadata)
            # which will be accessible in the article template
            article_vars = convert_meta_to_article_vars(md.Meta)
            article_vars["ARTICLE_CONTENT"] = html

            # And we write the content in the output file
107
            with open(output_filepath, "w") as output_file:
108
                output_file.write(template.render(article_vars))
109
110
111
        else:
            # ... else, we simply copy the file to the output directory
            shutil.copyfile(content_filepath, output_filepath)
112
113
114


if __name__ == "__main__":
115
116
117
118
119
    try:
        main()
        print("Boop!")
    except ProgramError as e:
        print(e.args[0], file=sys.stderr)