boop.py 4.04 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
import boopsy


14
locale.setlocale(locale.LC_ALL, "")
15

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
class Article:
33
34
35
    def __init__(self, slug, article_content):
        self.slug = slug

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
        # We convert the file's content into HTML
        md = markdown.Markdown(extensions=["meta", "fenced_code", "attr_list"])
        self.content = md.convert(article_content)

        # We get the local variables from the Markdown file (metadata)
        # which will be accessible in the article template
        self.meta = {}
        for key, values in md.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.
            self.meta[article_key] = values[0]

        # And we initialize a template for the article
        article_template_filepath = os.path.join("theme", "article.html")
        self.template = boopsy.Template(article_template_filepath)

    def render(self):
        variables = self.meta.copy()
        variables["ARTICLE_CONTENT"] = self.content
        return self.template.render(variables)


61
62
63
64
65
66
67
68
69
70
71
72
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


73
def main():
74
    # Make sure ./site folder is empty
berumuron's avatar
berumuron committed
75
    output_path = os.path.join(os.curdir, "site")
76
    if os.path.isdir(output_path):
77
        # it should be a directory...
78
        shutil.rmtree(output_path)
79
80
81
    elif os.path.exists(output_path):
        # ... but it also can be a simple file if user created it manually!
        os.remove(output_path)
82
83
84
85
86
87
88
89
90
    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)

91
92
93
94
95
96
    # 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)

97
98
99
    # Check that articles directory exists on the filesystem
    articles_path = os.path.join(os.curdir, "articles")
    if not os.path.isdir(articles_path):
100
101
        # If not, just stop here
        return
102

103
104
    # List files from ./articles
    articles = []
105
    for filename in dir_tree(articles_path):
106
        slug, ext = os.path.splitext(filename)
107
108
        if ext != ".md":
            # Don't consider files which are not Markdown
109
            continue
110

111
        # We read the article file and initialize an Article from it
112
        article_filepath = os.path.join(articles_path, filename)
113
        with open(article_filepath, "r") as article_file:
114
115
            article = Article(slug, article_file.read())
            articles.append(article)
116

117
118
119
    # And write them in the ./site folder
    for article in articles:
        output_filepath = os.path.join(output_path, f"{article.slug}.html")
120
        with open(output_filepath, "w") as output_file:
121
            output_file.write(article.render())
122
123
124


if __name__ == "__main__":
125
126
127
128
129
    try:
        main()
        print("Boop!")
    except ProgramError as e:
        print(e.args[0], file=sys.stderr)