| Class | HTMLConformanceChecker |
| In: |
lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb
|
| Parent: | HTML5::Filters::Base |
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 267
267: def initialize(stream, *args)
268: super(HTML5::HTMLTokenizer.new(stream, *args))
269: @things_that_define_an_id = []
270: @things_that_point_to_an_id = []
271: @ids_we_have_known_and_loved = []
272: end
Attribute validation
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 655
655: def check_attribute_values(token)
656: tag_name = token.fetch(:name, "")
657: for attr_name, attr_value in token.fetch(:data, [])
658: attr_name = attr_name.downcase
659: method = "validate_attribute_value_#{tag_name.to_s.underscore}_#{attr_name.to_s.underscore}"
660: if respond_to?(method)
661: send(method, token, tag_name, attr_name, attr_value) do |t|
662: yield t
663: end
664: else
665: method = "validate_attribute_value_#{attr_name.to_s.underscore}"
666: if respond_to?(method)
667: send(method, token, tag_name, attr_name, attr_value) do |t|
668: yield t
669: end
670: end
671: end
672: end
673: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 514
514: def check_boolean(token, tag_name, attr_name, attr_value)
515: enumerated_values = [attr_name, '']
516: if !enumerated_values.include?(attr_value)
517: yield( {:type => "ParseError",
518: :data => "invalid-boolean-value",
519: :datavars => {"tagName" => tag_name,
520: "attributeName" => attr_name,
521: "enumeratedValues" => enumerated_values}})
522: yield( {:type => "ParseError",
523: :data => "invalid-attribute-value",
524: :datavars => {"tagName" => tag_name,
525: "attributeName" => attr_name}})
526: end
527: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 581
581: def check_browsing_context(token, tag_name, attr_name, attr_value)
582: return if not attr_value
583: return if attr_value[0] != ?_
584: attr_value.downcase!
585: return if ['_self', '_parent', '_top', '_blank'].include?(attr_value)
586: yield({:type => "ParseError",
587: :data => "invalid-browsing-context",
588: :datavars => {"tagName" => tag_name,
589: "attributeName" => attr_name}})
590: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 640
640: def check_date_time(token, tag_name, attr_name, attr_value)
641: # XXX
642: state = 'begin' # ('begin', '...
643: # for c in attr_value
644: # if state == 'begin' =>
645: # if SPACE_CHARACTERS.include?(c)
646: # continue
647: # elsif digits.include?(c)
648: # state = ...
649: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 492
492: def check_enumerated_value(token, tag_name, attr_name, attr_value, enumerated_values)
493: if !attr_value || attr_value.length == 0
494: yield( {:type => "ParseError",
495: :data => "attribute-value-can-not-be-blank",
496: :datavars => {"tagName" => tag_name,
497: "attributeName" => attr_name}})
498: return
499: end
500: attr_value.downcase!
501: if !enumerated_values.include?(attr_value)
502: yield( {:type => "ParseError",
503: :data => "invalid-enumerated-value",
504: :datavars => {"tagName" => tag_name,
505: "attribute_name" => attr_name,
506: "enumeratedValues" => enumerated_values}})
507: yield( {:type => "ParseError",
508: :data => "invalid-attribute-value",
509: :datavars => {"tagName" => tag_name,
510: "attributeName" => attr_name}})
511: end
512: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 577
577: def check_floating_point_number(token, tag_name, attr_name, attr_value)
578: # XXX
579: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 429
429: def check_id(token, tag_name, attr_name, attr_value)
430: if !attr_value || attr_value.length == 0
431: yield({:type => "ParseError",
432: :data => "attribute-value-can-not-be-blank",
433: :datavars => {"tagName" => tag_name,
434: "attributeName" => attr_name}})
435: end
436: attr_value.each_byte do |b|
437: c = [b].pack('c*')
438: if HTML5::SPACE_CHARACTERS.include?(c)
439: yield( {:type => "ParseError",
440: :data => "space-in-id",
441: :datavars => {"tagName" => tag_name,
442: "attributeName" => attr_name}})
443: yield( {:type => "ParseError",
444: :data => "invalid-attribute-value",
445: :datavars => {"tagName" => tag_name,
446: "attributeName" => attr_name}})
447: break
448: end
449: end
450: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 529
529: def check_integer(token, tag_name, attr_name, attr_value)
530: sign = 1
531: number_string = ''
532: state = 'begin' # ('begin', 'initial-number', 'number', 'trailing-junk')
533: error = {:type => "ParseError",
534: :data => "invalid-integer-value",
535: :datavars => {"tagName" => tag_name,
536: "attributeName" => attr_name,
537: "attributeValue" => attr_value}}
538: attr_value.scan(/./) do |c|
539: if state == 'begin'
540: if HTML5::SPACE_CHARACTERS.include?(c)
541: next
542: elsif c == '-'
543: sign = -1
544: state = 'initial-number'
545: elsif HTML5::DIGITS.include?(c)
546: number_string += c
547: state = 'in-number'
548: else
549: yield error
550: return
551: end
552: elsif state == 'initial-number'
553: if !HTML5::DIGITS.include?(c)
554: yield error
555: return
556: end
557: number_string += c
558: state = 'in-number'
559: elsif state == 'in-number'
560: if HTML5::DIGITS.include?(c)
561: number_string += c
562: else
563: state = 'trailing-junk'
564: end
565: elsif state == 'trailing-junk'
566: next
567: end
568: end
569: if number_string.length == 0
570: yield( {:type => "ParseError",
571: :data => "attribute-value-can-not-be-blank",
572: :datavars => {"tagName" => tag_name,
573: "attributeName" => attr_name}})
574: end
575: end
def checkURI(token, tag_name, attr_name, attr_value)
is_valid, error_code = rfc3987.is_valid_uri(attr_value)
if not is_valid
yield {:type => "ParseError",
:data => error_code,
:datavars => {"tagName" => tag_name,
"attributeName" => attr_name}}
yield {:type => "ParseError",
:data => "invalid-attribute-value",
:datavars => {"tagName" => tag_name,
"attributeName" => attr_name}}
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 415
415: def check_iri(token, tag_name, attr_name, attr_value)
416: is_valid, error_code = is_valid_iri(attr_value)
417: if !is_valid
418: yield({:type => "ParseError",
419: :data => error_code,
420: :datavars => {"tagName" => tag_name,
421: "attributeName" => attr_name}})
422: yield({:type => "ParseError",
423: :data => "invalid-attribute-value",
424: :datavars => {"tagName" => tag_name,
425: "attributeName" => attr_name}})
426: end
427: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 592
592: def check_lang_code(token, tag_name, attr_name, attr_value)
593: return if !attr_value || attr_value == '' # blank is OK
594: if not is_valid_lang_code(attr_value)
595: yield( {:type => "ParseError",
596: :data => "invalid-lang-code",
597: :datavars => {"tagName" => tag_name,
598: "attributeName" => attr_name,
599: "attributeValue" => attr_value}})
600: end
601: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 624
624: def check_link_relation(token, tag_name, attr_name, attr_value)
625: check_token_list(tag_name, attr_name, attr_value) do |t|
626: yield t
627: end
628: value_list = parse_token_list(attr_value)
629: allowed_values = tag_name == 'link' ? @@link_rel_values : @@a_rel_values
630: for current_value in value_list
631: if !allowed_values.include?(current_value)
632: yield({:type => "ParseError",
633: :data => "invalid-rel",
634: :datavars => {"tagName" => tag_name,
635: "attributeName" => attr_name}})
636: end
637: end
638: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 620
620: def check_media_query(token, tag_name, attr_name, attr_value)
621: # XXX
622: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 603
603: def check_mime_type(token, tag_name, attr_name, attr_value)
604: # XXX needs tests
605: if not attr_value
606: yield( {:type => "ParseError",
607: :data => "attribute-value-can-not-be-blank",
608: :datavars => {"tagName" => tag_name,
609: "attributeName" => attr_name}})
610: end
611: if not is_valid_mime_type(attr_value)
612: yield( {:type => "ParseError",
613: :data => "invalid-mime-type",
614: :datavars => {"tagName" => tag_name,
615: "attributeName" => attr_name,
616: "attributeValue" => attr_value}})
617: end
618: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 369
369: def check_start_tag_required_attributes(token)
370: # check for presence of required attributes
371: name = (token[:name] || "").downcase
372: if @@required_attribute_map.keys().include?(name)
373: attrs_present = (token[:data] || []).collect{|t| t[0]}
374: for attr_name in @@required_attribute_map[name]
375: if !attrs_present.include?(attr_name)
376: yield( {:type => "ParseError",
377: :data => "missing-required-attribute",
378: :datavars => {"tagName" => name,
379: "attributeName" => attr_name}})
380: end
381: end
382: end
383: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 385
385: def check_start_tag_unknown_attributes(token)
386: # check for recognized attribute names
387: name = token[:name].downcase
388: allowed_attributes = @@global_attributes | @@allowed_attribute_map.fetch(name, [])
389: for attr_name, attr_value in token.fetch(:data, [])
390: if !allowed_attributes.include?(attr_name.downcase())
391: yield( {:type => "ParseError",
392: :data => "unknown-attribute",
393: :datavars => {"tagName" => name,
394: "attributeName" => attr_name}})
395: end
396: end
397: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 472
472: def check_token_list(tag_name, attr_name, attr_value)
473: # The "token" in the method name refers to tokens in an attribute value
474: # i.e. http://www.whatwg.org/specs/web-apps/current-work/#set-of
475: # but the "token" parameter refers to the token generated from
476: # HTMLTokenizer. Sorry for the confusion.
477: value_list = parse_token_list(attr_value)
478: value_dict = {}
479: for current_value in value_list
480: if value_dict.has_key?(current_value)
481: yield({:type => "ParseError",
482: :data => "duplicate-value-in-token-list",
483: :datavars => {"tagName" => tag_name,
484: "attributeName" => attr_name,
485: "attributeValue" => current_value}})
486: break
487: end
488: value_dict[current_value] = 1
489: end
490: end
Start tag validation helpers
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 359
359: def check_unknown_start_tag(token)
360: # check for recognized tag name
361: name = (token[:name] || "").downcase
362: if !@@allowed_attribute_map.keys.include?(name)
363: yield({:type => "ParseError",
364: :data => "unknown-start-tag",
365: :datavars => {"tagName" => name}})
366: end
367: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 274
274: def each
275: __getobj__.each do |token|
276: method = "validate_#{token.fetch(:type, '-').to_s.underscore}_#{token.fetch(:name, '-').to_s.underscore}"
277: if respond_to?(method)
278: send(method, token){|t| yield t }
279: else
280: method = "validate_#{token.fetch(:type, '-').to_s.underscore}"
281: if respond_to?(method)
282: send(method, token) do |t|
283: yield t
284: end
285: end
286: end
287: yield token
288: end
289: eof do |t|
290: yield t
291: end
292: end
Whole document validation (IDs, etc.)
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 801
801: def eof
802: for token in @things_that_point_to_an_id
803: tag_name = token.fetch(:name, "").downcase
804: attrs_dict = token[:data] # by now html5parser has "normalized" the attrs list into a dict.
805: # hooray for obscure side effects!
806: attr_value = attrs_dict.fetch("contextmenu", "")
807: if attr_value and (!@ids_we_have_known_and_loved.include?(attr_value))
808: yield( {:type => "ParseError",
809: :data => "id-does-not-exist",
810: :datavars => {"tagName" => tag_name,
811: "attributeName" => "contextmenu",
812: "attributeValue" => attr_value}})
813: else
814: for ref_token in @things_that_define_an_id
815: id = ref_token.fetch(:data, {}).fetch("id", "")
816: if not id
817: continue
818: end
819: if id == attr_value
820: if ref_token.fetch(:name, "").downcase != "men"
821: yield( {:type => "ParseError",
822: :data => "contextmenu-must-point-to-menu"})
823: end
824: break
825: end
826: end
827: end
828: end
829: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 452
452: def parse_token_list(value)
453: valueList = []
454: currentValue = ''
455: (value + ' ').each_byte do |b|
456: c = [b].pack('c*')
457: if HTML5::SPACE_CHARACTERS.include?(c)
458: if currentValue.length > 0
459: valueList << currentValue
460: currentValue = ''
461: end
462: else
463: currentValue += c
464: end
465: end
466: if currentValue.length > 0
467: valueList << currentValue
468: end
469: valueList
470: end
Alias for check_lang_code
Alias for check_media_query
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 769
769: def validate_attribute_value_a_ping(token, tag_name, attr_name, attr_value)
770: value_list = parse_token_list(attr_value)
771: for current_value in value_list
772: checkIRI(token, tag_name, attr_name, attr_value) do |t|
773: yield t
774: end
775: end
776: end
Alias for check_link_relation
Alias for check_browsing_context
Alias for check_browsing_context
Alias for check_iri
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 675
675: def validate_attribute_value_class(token, tag_name, attr_name, attr_value)
676: check_token_list(tag_name, attr_name, attr_value) do |t|
677: yield t
678: yield( {:type => "ParseError",
679: :data => "invalid-attribute-value",
680: :datavars => {"tagName" => tag_name,
681: "attributeName" => attr_name}})
682: end
683: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 685
685: def validate_attribute_value_contenteditable(token, tag_name, attr_name, attr_value)
686: check_enumerated_value(token, tag_name, attr_name, attr_value, ['true', 'false', '']) do |t|
687: yield t
688: end
689: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 706
706: def validate_attribute_value_contextmenu(token, tag_name, attr_name, attr_value)
707: check_id(token, tag_name, attr_name, attr_value) do |t|
708: yield t
709: end
710: @things_that_point_to_an_id << token
711: end
Alias for check_date_time
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 691
691: def validate_attribute_value_dir(token, tag_name, attr_name, attr_value)
692: check_enumerated_value(token, tag_name, attr_name, attr_value, ['ltr', 'rtl']) do |t|
693: yield t
694: end
695: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 697
697: def validate_attribute_value_draggable(token, tag_name, attr_name, attr_value)
698: check_enumerated_value(token, tag_name, attr_name, attr_value, ['true', 'false']) do |t|
699: yield t
700: end
701: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 742
742: def validate_attribute_value_html_xmlns(token, tag_name, attr_name, attr_value)
743: if attr_value != "http://www.w3.org/1999/xhtml"
744: yield( {:type => "ParseError",
745: :data => "invalid-root-namespace",
746: :datavars => {"tagName" => tag_name,
747: "attributeName" => attr_name}})
748: end
749: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 713
713: def validate_attribute_value_id(token, tag_name, attr_name, attr_value)
714: # This method has side effects. It adds 'token' to the list of
715: # things that define an ID (@things_that_define_an_id) so that we can
716: # later check 1) whether an ID is duplicated, and 2) whether all the
717: # things that point to something else by ID (like <label for> or
718: # <span contextmenu>) point to an ID that actually exists somewhere.
719: check_id(token, tag_name, attr_name, attr_value) do |t|
720: yield t
721: end
722: return if not attr_value
723: if @ids_we_have_known_and_loved.include?(attr_value)
724: yield( {:type => "ParseError",
725: :data => "duplicate-id",
726: :datavars => {"tagName" => tag_name}})
727: end
728: @ids_we_have_known_and_loved << attr_value
729: @things_that_define_an_id << token
730: end
Alias for check_date_time
Alias for check_lang_code
Alias for check_media_query
Alias for check_link_relation
Alias for check_mime_type
Alias for check_floating_point_number
Alias for check_floating_point_number
Alias for check_floating_point_number
Alias for check_floating_point_number
Alias for check_floating_point_number
Alias for check_floating_point_number
Alias for check_floating_point_number
Alias for check_floating_point_number
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 734
734: def validate_attribute_value_ref(token, tag_name, attr_name, attr_value)
735: # XXX
736: end
Alias for check_media_query
Alias for check_boolean
Alias for check_mime_type
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 738
738: def validate_attribute_value_template(token, tag_name, attr_name, attr_value)
739: # XXX
740: end
Alias for check_date_time
Start tag validation
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 298
298: def validate_start_tag(token)
299: check_unknown_start_tag(token){|t| yield t}
300: check_start_tag_required_attributes(token) do |t|
301: yield t
302: end
303: check_start_tag_unknown_attributes(token) do |t|
304: yield t
305: end
306: check_attribute_values(token) do |t|
307: yield t
308: end
309: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 311
311: def validate_start_tag_embed(token)
312: check_start_tag_required_attributes(token) do |t|
313: yield t
314: end
315: check_attribute_values(token) do |t|
316: yield t
317: end
318: # spec says "any attributes w/o namespace"
319: # so don't call check_start_tag_unknown_attributes
320: end
# File lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb, line 322
322: def validate_start_tag_input(token)
323: check_attribute_values(token) do |t|
324: yield t
325: end
326: attr_dict = Hash[*token[:data].collect{|(name, value)| [name.downcase, value]}.flatten]
327: input_type = attr_dict.fetch('type', "text")
328: if !@@input_type_allowed_attribute_map.keys().include?(input_type)
329: yield({:type => "ParseError",
330: :data => "unknown-input-type",
331: :datavars => {:attrValue => input_type}})
332: end
333: allowed_attributes = @@input_type_allowed_attribute_map.fetch(input_type, [])
334: attr_dict.each do |attr_name, attr_value|
335: if !@@allowed_attribute_map['input'].include?(attr_name)
336: yield({:type => "ParseError",
337: :data => "unknown-attribute",
338: :datavars => {"tagName" => "input",
339: "attributeName" => attr_name}})
340: elsif !allowed_attributes.include?(attr_name)
341: yield({:type => "ParseError",
342: :data => "attribute-not-allowed-on-this-input-type",
343: :datavars => {"attributeName" => attr_name,
344: "inputType" => input_type}})
345: end
346: if @@input_type_deprecated_attribute_map.fetch(input_type, []).include?(attr_name)
347: yield({:type => "ParseError",
348: :data => "deprecated-attribute",
349: :datavars => {"attributeName" => attr_name,
350: "inputType" => input_type}})
351: end
352: end
353: end