FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
html5lib-python/src/html5lib/serializer/htmlserializer.py at python3-old · moben/html5lib-python · GitHub
moben
/
html5lib-python
Public
forked from
html5lib/html5lib-python
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
html5lib-python
/
src
/
html5lib
/
serializer
/
htmlserializer.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
221 lines (194 loc) · 8.41 KB
Breadcrumbs
html5lib-python
/
src
/
html5lib
/
serializer
/
htmlserializer.py
Copy path
File metadata and controls
221 lines (194 loc) · 8.41 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
try
:
frozenset
except
NameError
:
# Import from the sets module for python 2.3
from
sets
import
ImmutableSet
as
frozenset
import
gettext
_
=
gettext
.
gettext
from
html5lib
.
constants
import
voidElements
,
booleanAttributes
,
spaceCharacters
from
html5lib
.
constants
import
rcdataElements
from
xml
.
sax
.
saxutils
import
escape
spaceCharacters
=
""
.
join
(
spaceCharacters
)
try
:
from
codecs
import
register_error
,
xmlcharrefreplace_errors
except
ImportError
:
unicode_encode_errors
=
"strict"
else
:
unicode_encode_errors
=
"htmlentityreplace"
from
html5lib
.
constants
import
entities
encode_entity_map
=
{}
for
k
,
v
in
list
(
entities
.
items
()):
if
v
!=
"&"
and
encode_entity_map
.
get
(
v
)
!=
k
.
lower
():
# prefer < over < and similarly for &, >, etc.
encode_entity_map
[
v
]
=
k
def
htmlentityreplace_errors
(
exc
):
if
isinstance
(
exc
, (
UnicodeEncodeError
,
UnicodeTranslateError
)):
res
=
[]
for
c
in
exc
.
object
[
exc
.
start
:
exc
.
end
]:
e
=
encode_entity_map
.
get
(
c
)
if
e
:
res
.
append
(
"&"
)
res
.
append
(
e
)
if
not
e
.
endswith
(
";"
):
res
.
append
(
";"
)
else
:
res
.
append
(
c
.
encode
(
exc
.
encoding
,
"xmlcharrefreplace"
))
return
(
""
.
join
(
res
),
exc
.
end
)
else
:
return
xmlcharrefreplace_errors
(
exc
)
register_error
(
unicode_encode_errors
,
htmlentityreplace_errors
)
del
register_error
def
encode
(
text
,
encoding
):
return
text
.
encode
(
encoding
,
unicode_encode_errors
)
class
HTMLSerializer
(
object
):
quote_attr_values
=
False
quote_char
=
'"'
use_best_quote_char
=
True
minimize_boolean_attributes
=
True
use_trailing_solidus
=
False
space_before_trailing_solidus
=
True
escape_lt_in_attrs
=
False
escape_rcdata
=
False
inject_meta_charset
=
True
strip_whitespace
=
False
sanitize
=
False
omit_optional_tags
=
True
options
=
(
"quote_attr_values"
,
"quote_char"
,
"use_best_quote_char"
,
"minimize_boolean_attributes"
,
"use_trailing_solidus"
,
"space_before_trailing_solidus"
,
"omit_optional_tags"
,
"strip_whitespace"
,
"inject_meta_charset"
,
"escape_lt_in_attrs"
,
"escape_rcdata"
,
'use_trailing_solidus'
,
"sanitize"
)
def
__init__
(
self
,
**
kwargs
):
if
'quote_char'
in
kwargs
:
self
.
use_best_quote_char
=
False
for
attr
in
self
.
options
:
setattr
(
self
,
attr
,
kwargs
.
get
(
attr
,
getattr
(
self
,
attr
)))
self
.
errors
=
[]
self
.
strict
=
False
def
serialize
(
self
,
treewalker
,
encoding
=
None
):
in_cdata
=
False
self
.
errors
=
[]
if
encoding
and
self
.
inject_meta_charset
:
from
html5lib
.
filters
.
inject_meta_charset
import
Filter
treewalker
=
Filter
(
treewalker
,
encoding
)
# XXX: WhitespaceFilter should be used before OptionalTagFilter
# for maximum efficiently of this latter filter
if
self
.
strip_whitespace
:
from
html5lib
.
filters
.
whitespace
import
Filter
treewalker
=
Filter
(
treewalker
)
if
self
.
sanitize
:
from
html5lib
.
filters
.
sanitizer
import
Filter
treewalker
=
Filter
(
treewalker
)
if
self
.
omit_optional_tags
:
from
html5lib
.
filters
.
optionaltags
import
Filter
treewalker
=
Filter
(
treewalker
)
for
token
in
treewalker
:
type
=
token
[
"type"
]
if
type
==
"Doctype"
:
doctype
=
"<!DOCTYPE %s>"
%
token
[
"name"
]
if
encoding
:
yield
doctype
.
encode
(
encoding
)
else
:
yield
doctype
elif
type
in
(
"Characters"
,
"SpaceCharacters"
):
if
type
==
"SpaceCharacters"
or
in_cdata
:
if
in_cdata
and
token
[
"data"
].
find
(
"</"
)
>=
0
:
self
.
serializeError
(
_
(
"Unexpected </ in CDATA"
))
if
encoding
:
yield
token
[
"data"
].
encode
(
encoding
,
"strict"
)
else
:
yield
token
[
"data"
]
elif
encoding
:
yield
encode
(
escape
(
token
[
"data"
]),
encoding
)
else
:
yield
escape
(
token
[
"data"
])
elif
type
in
(
"StartTag"
,
"EmptyTag"
):
name
=
token
[
"name"
]
if
name
in
rcdataElements
and
not
self
.
escape_rcdata
:
in_cdata
=
True
elif
in_cdata
:
self
.
serializeError
(
_
(
"Unexpected child element of a CDATA element"
))
attrs
=
token
[
"data"
]
if
hasattr
(
attrs
,
"items"
):
attrs
=
list
(
attrs
.
items
())
attrs
.
sort
()
attributes
=
[]
for
k
,
v
in
attrs
:
if
encoding
:
k
=
k
.
encode
(
encoding
,
"strict"
)
attributes
.
append
(
' '
)
attributes
.
append
(
k
)
if
(
not
self
.
minimize_boolean_attributes
or
(
k
not
in
booleanAttributes
.
get
(
name
,
tuple
())
and
k
not
in
booleanAttributes
.
get
(
""
,
tuple
()))):
attributes
.
append
(
"="
)
if
self
.
quote_attr_values
or
not
v
:
quote_attr
=
True
else
:
quote_attr
=
False
for
char
in
spaceCharacters
+
">
\"
'="
:
if
char
in
v
:
quote_attr
=
True
break
v
=
v
.
replace
(
"&"
,
"&"
)
if
self
.
escape_lt_in_attrs
:
v
=
v
.
replace
(
"<"
,
"<"
)
if
encoding
:
v
=
encode
(
v
,
encoding
)
if
quote_attr
:
quote_char
=
self
.
quote_char
if
self
.
use_best_quote_char
:
if
"'"
in
v
and
'"'
not
in
v
:
quote_char
=
'"'
elif
'"'
in
v
and
"'"
not
in
v
:
quote_char
=
"'"
if
quote_char
==
"'"
:
v
=
v
.
replace
(
"'"
,
"'"
)
else
:
v
=
v
.
replace
(
'"'
,
"""
)
attributes
.
append
(
quote_char
)
attributes
.
append
(
v
)
attributes
.
append
(
quote_char
)
else
:
attributes
.
append
(
v
)
if
name
in
voidElements
and
self
.
use_trailing_solidus
:
if
self
.
space_before_trailing_solidus
:
attributes
.
append
(
" /"
)
else
:
attributes
.
append
(
"/"
)
if
encoding
:
yield
"<%s%s>"
%
(
name
.
encode
(
encoding
,
"strict"
),
""
.
join
(
attributes
))
else
:
yield
"<%s%s>"
%
(
name
,
""
.
join
(
attributes
))
elif
type
==
"EndTag"
:
name
=
token
[
"name"
]
if
name
in
rcdataElements
:
in_cdata
=
False
elif
in_cdata
:
self
.
serializeError
(
_
(
"Unexpected child element of a CDATA element"
))
end_tag
=
"</%s>"
%
name
if
encoding
:
end_tag
=
end_tag
.
encode
(
encoding
,
"strict"
)
yield
end_tag
elif
type
==
"Comment"
:
data
=
token
[
"data"
]
if
data
.
find
(
"--"
)
>=
0
:
self
.
serializeError
(
_
(
"Comment contains --"
))
comment
=
"<!--%s-->"
%
token
[
"data"
]
if
encoding
:
comment
=
comment
.
encode
(
encoding
,
unicode_encode_errors
)
yield
comment
else
:
self
.
serializeError
(
token
[
"data"
])
def
render
(
self
,
treewalker
,
encoding
=
None
):
if
encoding
:
return
""
.
join
(
list
(
self
.
serialize
(
treewalker
,
encoding
)))
else
:
return
""
.
join
(
list
(
self
.
serialize
(
treewalker
)))
def
serializeError
(
self
,
data
=
"XXX ERROR MESSAGE NEEDED"
):
# XXX The idea is to make data mandatory.
self
.
errors
.
append
(
data
)
if
self
.
strict
:
raise
SerializeError
def
SerializeError
(
Exception
):
"""Error in serialized tree"""
pass
Back
|
FazBrowse Home
|
New Git URL