Skip to content

Commit f7ea692

Browse files
author
Mark Pilgrim
committed
added support for validating id attributes
--HG-- extra : convert_revision : svn%3Aacbfec75-9323-0410-a652-858a13e371e0/trunk%40976
1 parent dadf711 commit f7ea692

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

src/html5lib/filters/validator.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@
4141
_(u"Duplicate value '%(attributeValue)s' in token list in '%(attributeName)s' attribute on <%(tagName)s>."),
4242
"invalid-attribute-value":
4343
_(u"Invalid value for '%(attributeName)s' attribute on <%(tagName)s>."),
44+
"space-in-id":
45+
_(u"Illegal space character in ID attribute on <%(tagName)s>."),
46+
"duplicate-id":
47+
_(u"Duplicate ID on <%(tagName)s>."),
48+
"attribute-value-can-not-be-blank":
49+
_(u"Value can not be blank: '%(attributeName)s' attribute on <%(tagName)s>."),
4450
})
4551

4652
globalAttributes = frozenset(('class', 'contenteditable', 'contextmenu', 'dir',
@@ -215,6 +221,9 @@ class HTMLConformanceChecker(_base.Filter):
215221
def __init__(self, stream, encoding, parseMeta, **kwargs):
216222
_base.Filter.__init__(self, tokenizer.HTMLTokenizer(
217223
stream, encoding, parseMeta, **kwargs))
224+
self.thingsThatDefineAnID = []
225+
self.thingsThatPointToAnID = []
226+
self.IDsWeHaveKnownAndLoved = []
218227

219228
def __iter__(self):
220229
for token in _base.Filter.__iter__(self):
@@ -329,6 +338,36 @@ def validateAttributeValueContenteditable(self, token, tagName, attrName, attrVa
329338
"datavars": {"tagName": tagName,
330339
"attributeName": attrName}}
331340

341+
def validateAttributeValueId(self, token, tagName, attrName, attrValue):
342+
# This method has side effects. It adds 'token' to the list of
343+
# things that define an ID (self.thingsThatDefineAnID) so that we can
344+
# later check 1) whether an ID is duplicated, and 2) whether all the
345+
# things that point to something else by ID (like <label for> or
346+
# <span contextmenu>) point to an ID that actually exists somewhere.
347+
if not attrValue:
348+
yield {"type": "ParseError",
349+
"data": "attribute-value-can-not-be-blank",
350+
"datavars": {"tagName": tagName,
351+
"attributeName": attrName}}
352+
return
353+
354+
if attrValue in self.IDsWeHaveKnownAndLoved:
355+
yield {"type": "ParseError",
356+
"data": "duplicate-id",
357+
"datavars": {"tagName": tagName}}
358+
self.IDsWeHaveKnownAndLoved.append(attrValue)
359+
self.thingsThatDefineAnID.append(token)
360+
for c in attrValue:
361+
if c in spaceCharacters:
362+
yield {"type": "ParseError",
363+
"data": "space-in-id",
364+
"datavars": {"tagName": tagName}}
365+
yield {"type": "ParseError",
366+
"data": "invalid-attribute-value",
367+
"datavars": {"tagName": tagName,
368+
"attributeName": attrName}}
369+
break
370+
332371
def checkTokenList(self, tagName, attrName, attrValue):
333372
# The "token" in the method name refers to tokens in an attribute value
334373
# i.e. http://www.whatwg.org/specs/web-apps/current-work/#set-of

0 commit comments

Comments
 (0)