# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""
Presubmit for Chromium HTML resources. See chrome/browser/PRESUBMIT.py.
"""

import regex_check


class HtmlChecker(object):
  def __init__(self, input_api, output_api, file_filter=None):
    self.input_api = input_api
    self.output_api = output_api
    self.file_filter = file_filter

  def ClassesUseDashFormCheck(self, line_number, line):
    regex = self.input_api.re.compile("""
        (?:^|\s)                    # start of line or whitespace
        (class="[^"]*[A-Z_][^"]*")  # class contains caps or '_'
        """,
        self.input_api.re.VERBOSE)
    return regex_check.RegexCheck(self.input_api.re, line_number, line, regex,
        "Classes should use dash-form.")

  def DoNotCloseSingleTagsCheck(self, line_number, line):
    regex = r"(/>)"
    return regex_check.RegexCheck(self.input_api.re, line_number, line, regex,
        "Do not close single tags.")

  def DoNotUseBrElementCheck(self, line_number, line):
    regex = r"(<br)"
    return regex_check.RegexCheck(self.input_api.re, line_number, line, regex,
        "Do not use <br>; place blocking elements (<div>) as appropriate.")

  def DoNotUseInputTypeButtonCheck(self, line_number, line):
    regex = self.input_api.re.compile("""
        (<input [^>]*  # "<input " followed by anything but ">"
        type="button"  # type="button"
        [^>]*>)        # anything but ">" then ">"
        """,
        self.input_api.re.VERBOSE)
    return regex_check.RegexCheck(self.input_api.re, line_number, line, regex,
        'Use the button element instead of <input type="button">')

  def DoNotUseSingleQuotesCheck(self, line_number, line):
    regex = self.input_api.re.compile("""
        <\S+                           # The tag name.
        (?:\s+\S+\$?="[^"]*"|\s+\S+)*  # Correctly quoted or non-value props.
        \s+(\S+\$?='[^']*')            # Find incorrectly quoted (foo='bar').
        [^>]*>                         # To the end of the tag.
        """,
        self.input_api.re.MULTILINE | self.input_api.re.VERBOSE)
    return regex_check.RegexCheck(self.input_api.re, line_number, line, regex,
        'Use double quotes rather than single quotes in HTML properties')

  def I18nContentJavaScriptCaseCheck(self, line_number, line):
    regex = self.input_api.re.compile("""
        (?:^|\s)                      # start of line or whitespace
        i18n-content="                # i18n-content="
        ([A-Z][^"]*|[^"]*[-_][^"]*)"  # starts with caps or contains '-' or '_'
        """,
        self.input_api.re.VERBOSE)
    return regex_check.RegexCheck(self.input_api.re, line_number, line, regex,
        "For i18n-content use javaScriptCase.")

  def LabelCheck(self, line_number, line):
    regex = self.input_api.re.compile("""
        (?:^|\s)     # start of line or whitespace
        <label[^>]+? # <label tag
        (for=)       # for=
        """,
        self.input_api.re.VERBOSE)
    return regex_check.RegexCheck(self.input_api.re, line_number, line, regex,
        "Avoid 'for' attribute on <label>. Place the input within the <label>, "
        "or use aria-labelledby for <select>.")

  def QuotePolymerBindings(self, line_number, line):
    regex = self.input_api.re.compile(r"=(\[\[|\{\{)")
    return regex_check.RegexCheck(self.input_api.re, line_number, line, regex,
        'Please use quotes around Polymer bindings (i.e. attr="[[prop]]")')

  def RunChecks(self):
    """Check for violations of the Chromium web development style guide. See
       http://chromium.org/developers/web-development-style-guide
    """
    results = []

    affected_files = self.input_api.change.AffectedFiles(
        file_filter=self.file_filter, include_deletes=False)

    for f in affected_files:
      errors = []

      for line_number, line in f.ChangedContents():
        errors.extend(filter(None, [
            self.ClassesUseDashFormCheck(line_number, line),
            self.DoNotCloseSingleTagsCheck(line_number, line),
            self.DoNotUseBrElementCheck(line_number, line),
            self.DoNotUseInputTypeButtonCheck(line_number, line),
            self.I18nContentJavaScriptCaseCheck(line_number, line),
            self.LabelCheck(line_number, line),
            self.QuotePolymerBindings(line_number, line),
        ]))

      if errors:
        abs_local_path = f.AbsoluteLocalPath()
        file_indicator = 'Found HTML style issues in %s' % abs_local_path
        prompt_msg = file_indicator + '\n\n' + '\n'.join(errors) + '\n'
        results.append(self.output_api.PresubmitPromptWarning(prompt_msg))

    return results
