Class: AssertValidHtml::Validator

Inherits:
Object
  • Object
show all
Defined in:
lib/assert_valid_html/validator.rb

Defined Under Namespace

Classes: ValidationError

Constant Summary collapse

ALLOWED_ATTRIBUTES =
%w[
  media hreflang rel target value charset autofocus placeholder form
  required disabled autocomplete min max multiple pattern step list
  novalidate formaction formenctype formmethod formnovalidate formtarget
  type label contextmenu scoped async manifest sizes reversed sandbox
  seamless srcdoc contenteditable draggable hidden role data-\\S* aria-\\S*
  spellcheck
]
ALLOWED_ELEMENTS =
%w[
  section article aside hgroup header footer nav figure figcaption video
  audio source embed progress meter time ruby rt rp wbr canvas command
  details datalist keygen output
]
IGNORED =
[
  /Warning: trimming empty/,
  /lacks "summary" attribute/,
  /<meta> lacks "content" attribute/, # HTML5
  /proprietary attribute "xmlns:fb"/, # Facebook
  /<\/?fb:/                           #    //
]

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(html) ⇒ Validator

Returns a new instance of Validator.



45
46
47
48
# File 'lib/assert_valid_html/validator.rb', line 45

def initialize(html)
  @html  = html
  @lines = html.split(/\n/)
end

Class Method Details

.ignore(regexp) ⇒ Object



30
31
32
# File 'lib/assert_valid_html/validator.rb', line 30

def self.ignore(regexp)
  ignored << regexp
end

.ignoredObject



34
35
36
# File 'lib/assert_valid_html/validator.rb', line 34

def self.ignored
  @ignored ||= IGNORED.dup
end

.ignored_regexpObject



38
39
40
41
42
43
# File 'lib/assert_valid_html/validator.rb', line 38

def self.ignored_regexp
  Regexp.new((ignored + [
    %r{proprietary attribute "(?:#{ALLOWED_ATTRIBUTES.join("|")})"},
    %r{discarding unexpected </?(?:#{ALLOWED_ELEMENTS.join("|")})>}
  ]).join("|"))
end

Instance Method Details

#context(line) ⇒ Object



64
65
66
67
68
69
70
# File 'lib/assert_valid_html/validator.rb', line 64

def context(line)
  top    = [0, line - 6].max
  bottom = [[@lines.length - 1, 0].max, line + 4].min
  (top..bottom).to_a.zip(@lines[top..bottom]).map{ |number, text|
    "%s %3d | %s" % [number + 1 == line ? "*" : " ", number + 1, text]
  }.join("\n")
end

#errorsObject



54
55
56
57
58
59
60
61
62
# File 'lib/assert_valid_html/validator.rb', line 54

def errors
  @errors ||= (
    ignored = self.class.ignored_regexp
    tidy(@html).split(/\n/).select {|w| w =~ /Warning/ && w !~ ignored }
  ).inject([]){ |array, error|
    line, message = parse_tidy_message(error)
    array << ValidationError.new(message, line, context(line))
  }
end

#messageObject



72
73
74
75
76
77
78
# File 'lib/assert_valid_html/validator.rb', line 72

def message
  if valid?
    "HTML is valid"
  else
    (["HTML is invalid"] + errors.map{ |e| e.message + "\n" + e.context }).join("\n\n")
  end
end

#valid?Boolean

Returns:

  • (Boolean)


50
51
52
# File 'lib/assert_valid_html/validator.rb', line 50

def valid?
  errors.empty?
end