aboutsummaryrefslogtreecommitdiffstats
path: root/mitmproxy/contentviews/css.py
blob: 44b33761e17710e6473e136055d4100d881d7431 (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
import re
import time

from mitmproxy.contentviews import base
from mitmproxy.utils import strutils

"""
A custom CSS prettifier. Compared to other prettifiers, its main features are:

- Implemented in pure Python.
- Modifies whitespace only.
- Works with any input.
- Considerably faster than e.g. cssutils.
"""

CSS_SPECIAL_AREAS = (
    "'" + strutils.SINGLELINE_CONTENT + strutils.NO_ESCAPE + "'",
    '"' + strutils.SINGLELINE_CONTENT + strutils.NO_ESCAPE + '"',
    r"/\*" + strutils.MULTILINE_CONTENT + r"\*/",
    "//" + strutils.SINGLELINE_CONTENT + "$"
)
CSS_SPECIAL_CHARS = "{};:"


def beautify(data: str, indent: str = "    "):
    """Beautify a string containing CSS code"""
    data = strutils.escape_special_areas(
        data.strip(),
        CSS_SPECIAL_AREAS,
        CSS_SPECIAL_CHARS,
    )

    # Add newlines
    data = re.sub(r"\s*;\s*", ";\n", data)
    data = re.sub(r"\s*{\s*", " {\n", data)
    data = re.sub(r"\s*}\s*", "\n}\n\n", data)

    # Fix incorrect ":" placement
    data = re.sub(r"\s*:\s*(?=[^{]+})", ": ", data)
    # Fix no space after ","
    data = re.sub(r"\s*,\s*", ", ", data)

    # indent
    data = re.sub("\n[ \t]+", "\n", data)
    data = re.sub("\n(?![}\n])(?=[^{]*})", "\n" + indent, data)

    data = strutils.unescape_special_areas(data)
    return data.rstrip("\n") + "\n"


class ViewCSS(base.View):
    name = "CSS"
    content_types = [
        "text/css"
    ]

    def __call__(self, data, **metadata):
        data = data.decode("utf8", "surrogateescape")
        beautified = beautify(data)
        return "CSS", base.format_text(beautified)


if __name__ == "__main__":  # pragma: no cover
    with open("../tools/web/static/vendor.css") as f:
        data = f.read()

    t = time.time()
    x = beautify(data)
    print("Beautifying vendor.css took {:.2}s".format(time.time() - t))