summaryrefslogtreecommitdiffstats
path: root/aurweb/scripts/rendercomment.py
blob: 5e18fd599b609142076c81e3a53b264f6c1d143b (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
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env python3

import re
import pygit2
import sys
import bleach
import markdown

import aurweb.config
import aurweb.db

repo_path = aurweb.config.get('serve', 'repo-path')
commit_uri = aurweb.config.get('options', 'commit_uri')


class LinkifyPreprocessor(markdown.preprocessors.Preprocessor):
    _urlre = re.compile(r'(\b(?:https?|ftp):\/\/[\w\/\#~:.?+=&%@!\-;,]+?'
                        r'(?=[.:?\-;,]*(?:[^\w\/\#~:.?+=&%@!\-;,]|$)))')

    def run(self, lines):
        return [self._urlre.sub(r'<\1>', line) for line in lines]


class LinkifyExtension(markdown.extensions.Extension):
    def extendMarkdown(self, md, md_globals):
        md.preprocessors.add('linkify', LinkifyPreprocessor(md), '_end')


class FlysprayLinksPreprocessor(markdown.preprocessors.Preprocessor):
    _fsre = re.compile(r'\b(FS#(\d+))\b')
    _sub = r'[\1](https://bugs.archlinux.org/task/\2)'

    def run(self, lines):
        return [self._fsre.sub(self._sub, line) for line in lines]


class FlysprayLinksExtension(markdown.extensions.Extension):
    def extendMarkdown(self, md, md_globals):
        preprocessor = FlysprayLinksPreprocessor(md)
        md.preprocessors.add('flyspray-links', preprocessor, '_end')


class GitCommitsPreprocessor(markdown.preprocessors.Preprocessor):
    _oidre = re.compile(r'(\b)([0-9a-f]{7,40})(\b)')
    _repo = pygit2.Repository(repo_path)
    _head = None

    def __init__(self, md, head):
        self._head = head
        super(markdown.preprocessors.Preprocessor, self).__init__(md)

    def handleMatch(self, m):
        oid = m.group(2)
        if oid not in self._repo:
            return oid

        prefixlen = 12
        while prefixlen < 40:
            if oid[:prefixlen] in self._repo:
                break
            prefixlen += 1

        html = '[`' + oid[:prefixlen] + '`]'
        html += '(' + commit_uri % (self._head, oid[:prefixlen]) + ')'

        return html

    def run(self, lines):
        return [self._oidre.sub(self.handleMatch, line) for line in lines]


class GitCommitsExtension(markdown.extensions.Extension):
    _head = None

    def __init__(self, head):
        self._head = head
        super(markdown.extensions.Extension, self).__init__()

    def extendMarkdown(self, md, md_globals):
        preprocessor = GitCommitsPreprocessor(md, self._head)
        md.preprocessors.add('git-commits', preprocessor, '_end')


class HeadingTreeprocessor(markdown.treeprocessors.Treeprocessor):
    def run(self, doc):
        for elem in doc:
            if elem.tag == 'h1':
                elem.tag = 'h5'
            elif elem.tag in ['h2', 'h3', 'h4', 'h5']:
                elem.tag = 'h6'


class HeadingExtension(markdown.extensions.Extension):
    def extendMarkdown(self, md, md_globals):
        md.treeprocessors.add('heading', HeadingTreeprocessor(md), '_end')


def get_comment(conn, commentid):
    cur = conn.execute('SELECT PackageComments.Comments, PackageBases.Name '
                       'FROM PackageComments INNER JOIN PackageBases '
                       'ON PackageBases.ID = PackageComments.PackageBaseID '
                       'WHERE PackageComments.ID = ?', [commentid])
    return cur.fetchone()


def save_rendered_comment(conn, commentid, html):
    conn.execute('UPDATE PackageComments SET RenderedComment = ? WHERE ID = ?',
                 [html, commentid])


def main():
    commentid = int(sys.argv[1])

    conn = aurweb.db.Connection()

    text, pkgbase = get_comment(conn, commentid)
    html = markdown.markdown(text, extensions=['fenced_code',
                                               LinkifyExtension(),
                                               FlysprayLinksExtension(),
                                               GitCommitsExtension(pkgbase),
                                               HeadingExtension()])
    allowed_tags = (bleach.sanitizer.ALLOWED_TAGS +
                    ['p', 'pre', 'h4', 'h5', 'h6', 'br', 'hr'])
    html = bleach.clean(html, tags=allowed_tags)
    save_rendered_comment(conn, commentid, html)

    conn.commit()
    conn.close()


if __name__ == '__main__':
    main()