This repository was archived by the owner on Dec 26, 2023. It is now read-only.
forked from feincms/feincms
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtidy.py
More file actions
87 lines (69 loc) · 2.7 KB
/
Copy pathtidy.py
File metadata and controls
87 lines (69 loc) · 2.7 KB
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
# encoding: utf-8
"""Utilities for dealing with HTML content"""
import re
import tidylib
# Based on http://stackoverflow.com/questions/92438/stripping-non-printable-characters-from-a-string-in-python
#
# We omit chars 9-13 (tab, newline, vertical tab, form feed, return) and 32
# (space) to avoid clogging our reports with warnings about common,
# non-problematic codes but still allow stripping things which will cause lxml
# to choke
CONTROL_CHAR_RE = re.compile('[%s]' % "".join(
re.escape(unichr(c)) for c in range(0, 8) + range(14, 31) + range(127, 160)
))
def tidy_html(html):
"""
Process an input string containing HTML and return a tuple (xhtml,
errors, warnings) containing the output of tidylib and lists of
validation errors and warnings.
Input must be unicode.
Output will be valid XHTML.
"""
if not isinstance(html, unicode):
raise ValueError("tidyhtml must be called with a Unicode string!")
warnings = list()
# First, deal with embedded control codes:
html, sub_count = CONTROL_CHAR_RE.subn(" ", html)
if sub_count:
warnings.append("Stripped %d control characters from body: %s" % (
sub_count,
set(ord(i) for i in CONTROL_CHAR_RE.findall(html))
))
# tidylib.tidy_fragment will choke if given a full HTML document. This is a
# primitive content sniff to decide whether to call tidy_document instead:
if "<html" in html[:1024]:
tidy_f = tidylib.tidy_document
doc_mode = True
else:
tidy_f = tidylib.tidy_fragment
doc_mode = False
html, messages = tidy_f(
html.strip(),
{
"char-encoding": "utf8",
"clean": False,
"drop-empty-paras": False,
"drop-font-tags": True,
"drop-proprietary-attributes": False,
"fix-backslash": True,
"indent": True,
"output-xhtml": True,
}
)
messages = filter(None, (l.strip() for l in messages.split("\n") if l))
# postprocess warnings to avoid HTML fragments being reported as lacking
# doctype and title:
errors = list()
warnings = list()
for msg in messages:
if not doc_mode and "Warning: missing <!DOCTYPE> declaration" in msg:
continue
if not doc_mode and "Warning: inserting missing 'title' element" in msg:
continue
if not doc_mode and "Warning: inserting implicit <body>" in msg:
continue
if "Error:" in msg:
errors.append(msg)
else:
warnings.append(msg)
return html, errors, warnings