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

import os
4
import sys
5
import shutil
6
import distutils.dir_util
7
import locale
8

9
10
import markdown

11
12
13
14
15
import boopsy


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

16

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

    Examples:

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

    pass


32
33
34
35
36
37
38
39
40
41
42
43
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


44
45
46
47
48
49
50
51
52
53
54
55
56
57
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


58
def main():
59
    # Make sure ./site folder is empty
berumuron's avatar
berumuron committed
60
    output_path = os.path.join(os.curdir, "site")
61
    if os.path.isdir(output_path):
62
        # it should be a directory...
63
        shutil.rmtree(output_path)
64
65
66
    elif os.path.exists(output_path):
        # ... but it also can be a simple file if user created it manually!
        os.remove(output_path)
67
68
69
70
71
72
73
74
75
    os.makedirs(output_path, exist_ok=True)

    # Check that index file exists and copy it under the ./site folder
    index_filepath = os.path.join(os.curdir, "index.html")
    if not os.path.exists(index_filepath):
        raise ProgramError("./index.html file does not exist")
    index_output_filepath = os.path.join(output_path, "index.html")
    shutil.copyfile(index_filepath, index_output_filepath)

76
77
78
79
80
81
    # Check that a ./theme/static folder exists and copy its content under the
    # ./site folder
    static_dirpath = os.path.join(os.curdir, "theme", "static")
    if os.path.isdir(static_dirpath):
        distutils.dir_util.copy_tree(static_dirpath, output_path)

82
83
84
    # Check that articles directory exists on the filesystem
    articles_path = os.path.join(os.curdir, "articles")
    if not os.path.isdir(articles_path):
85
86
        # If not, just stop here
        return
87

88
    md = markdown.Markdown(extensions=["meta", "fenced_code", "attr_list"])
89

90
    # And copy the files from ./articles to ./site
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
    for filename in dir_tree(articles_path):
        base, ext = os.path.splitext(filename)
        if ext != ".md":
            # Don't consider files which are not Markdown
            next

        article_filepath = os.path.join(articles_path, filename)
        output_filepath = os.path.join(output_path, f"{base}.html")

        # We convert the file's content into HTML
        with open(article_filepath, "r") as article_file:
            html = md.convert(article_file.read())

        # 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
        with open(output_filepath, "w") as output_file:
            output_file.write(template.render(article_vars))
116
117
118


if __name__ == "__main__":
119
120
121
122
123
    try:
        main()
        print("Boop!")
    except ProgramError as e:
        print(e.args[0], file=sys.stderr)