OLD | NEW |
| (Empty) |
1 # Copyright 2014 The Chromium Authors. All rights reserved. | |
2 # Use of this source code is governed by a BSD-style license that can be | |
3 # found in the LICENSE file. | |
4 | |
5 """ | |
6 Presubmit for Chromium HTML resources. See chrome/browser/PRESUBMIT.py. | |
7 """ | |
8 | |
9 import regex_check | |
10 | |
11 | |
12 class HtmlChecker(object): | |
13 def __init__(self, input_api, output_api, file_filter=None): | |
14 self.input_api = input_api | |
15 self.output_api = output_api | |
16 self.file_filter = file_filter | |
17 | |
18 def ClassesUseDashFormCheck(self, line_number, line): | |
19 regex = self.input_api.re.compile(""" | |
20 (?:^|\s) # start of line or whitespace | |
21 (class="[^"]*[A-Z_][^"]*") # class contains caps or '_' | |
22 """, | |
23 self.input_api.re.VERBOSE) | |
24 return regex_check.RegexCheck(self.input_api.re, line_number, line, regex, | |
25 "Classes should use dash-form.") | |
26 | |
27 def DoNotCloseSingleTagsCheck(self, line_number, line): | |
28 regex = r"(/>)" | |
29 return regex_check.RegexCheck(self.input_api.re, line_number, line, regex, | |
30 "Do not close single tags.") | |
31 | |
32 def DoNotUseBrElementCheck(self, line_number, line): | |
33 regex = r"(<br)" | |
34 return regex_check.RegexCheck(self.input_api.re, line_number, line, regex, | |
35 "Do not use <br>; place blocking elements (<div>) as appropriate.") | |
36 | |
37 def DoNotUseInputTypeButtonCheck(self, line_number, line): | |
38 regex = self.input_api.re.compile(""" | |
39 (<input [^>]* # "<input " followed by anything but ">" | |
40 type="button" # type="button" | |
41 [^>]*>) # anything but ">" then ">" | |
42 """, | |
43 self.input_api.re.VERBOSE) | |
44 return regex_check.RegexCheck(self.input_api.re, line_number, line, regex, | |
45 'Use the button element instead of <input type="button">') | |
46 | |
47 def DoNotUseSingleQuotesCheck(self, line_number, line): | |
48 regex = self.input_api.re.compile(""" | |
49 <\S+ # The tag name. | |
50 (?:\s+\S+\$?="[^"]*"|\s+\S+)* # Correctly quoted or non-value props. | |
51 \s+(\S+\$?='[^']*') # Find incorrectly quoted (foo='bar'). | |
52 [^>]*> # To the end of the tag. | |
53 """, | |
54 self.input_api.re.MULTILINE | self.input_api.re.VERBOSE) | |
55 return regex_check.RegexCheck(self.input_api.re, line_number, line, regex, | |
56 'Use double quotes rather than single quotes in HTML properties') | |
57 | |
58 def I18nContentJavaScriptCaseCheck(self, line_number, line): | |
59 regex = self.input_api.re.compile(""" | |
60 (?:^|\s) # start of line or whitespace | |
61 i18n-content=" # i18n-content=" | |
62 ([A-Z][^"]*|[^"]*[-_][^"]*)" # starts with caps or contains '-' or '_' | |
63 """, | |
64 self.input_api.re.VERBOSE) | |
65 return regex_check.RegexCheck(self.input_api.re, line_number, line, regex, | |
66 "For i18n-content use javaScriptCase.") | |
67 | |
68 def LabelCheck(self, line_number, line): | |
69 regex = self.input_api.re.compile(""" | |
70 (?:^|\s) # start of line or whitespace | |
71 <label[^>]+? # <label tag | |
72 (for=) # for= | |
73 """, | |
74 self.input_api.re.VERBOSE) | |
75 return regex_check.RegexCheck(self.input_api.re, line_number, line, regex, | |
76 "Avoid 'for' attribute on <label>. Place the input within the <label>, " | |
77 "or use aria-labelledby for <select>.") | |
78 | |
79 def QuotePolymerBindings(self, line_number, line): | |
80 regex = self.input_api.re.compile(r"=(\[\[|\{\{)") | |
81 return regex_check.RegexCheck(self.input_api.re, line_number, line, regex, | |
82 'Please use quotes around Polymer bindings (i.e. attr="[[prop]]")') | |
83 | |
84 def RunChecks(self): | |
85 """Check for violations of the Chromium web development style guide. See | |
86 https://chromium.googlesource.com/chromium/src/+/master/styleguide/web/we
b.md | |
87 """ | |
88 results = [] | |
89 | |
90 affected_files = self.input_api.change.AffectedFiles( | |
91 file_filter=self.file_filter, include_deletes=False) | |
92 | |
93 for f in affected_files: | |
94 if not f.LocalPath().endswith('.html'): | |
95 continue | |
96 | |
97 errors = [] | |
98 | |
99 for line_number, line in f.ChangedContents(): | |
100 errors.extend(filter(None, [ | |
101 self.ClassesUseDashFormCheck(line_number, line), | |
102 self.DoNotCloseSingleTagsCheck(line_number, line), | |
103 self.DoNotUseBrElementCheck(line_number, line), | |
104 self.DoNotUseInputTypeButtonCheck(line_number, line), | |
105 self.I18nContentJavaScriptCaseCheck(line_number, line), | |
106 self.LabelCheck(line_number, line), | |
107 self.QuotePolymerBindings(line_number, line), | |
108 ])) | |
109 | |
110 if errors: | |
111 abs_local_path = f.AbsoluteLocalPath() | |
112 file_indicator = 'Found HTML style issues in %s' % abs_local_path | |
113 prompt_msg = file_indicator + '\n\n' + '\n'.join(errors) + '\n' | |
114 results.append(self.output_api.PresubmitPromptWarning(prompt_msg)) | |
115 | |
116 return results | |
OLD | NEW |