2016-08-07 17:56:15 +02:00
|
|
|
from __future__ import absolute_import
|
|
|
|
from __future__ import print_function
|
|
|
|
|
2017-03-03 19:01:52 +01:00
|
|
|
from typing import List, Set, Tuple
|
2016-08-07 17:56:15 +02:00
|
|
|
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
|
|
|
|
GENERIC_KEYWORDS = [
|
|
|
|
'active',
|
|
|
|
'alert',
|
|
|
|
'danger',
|
|
|
|
'condensed',
|
|
|
|
'disabled',
|
|
|
|
'error',
|
|
|
|
'expanded',
|
|
|
|
'hide',
|
2016-09-22 02:05:24 +02:00
|
|
|
'show',
|
2016-08-07 17:56:15 +02:00
|
|
|
'notdisplayed',
|
|
|
|
'popover',
|
2016-12-03 01:12:52 +01:00
|
|
|
'no-border',
|
2016-08-07 17:56:15 +02:00
|
|
|
'success',
|
|
|
|
'text-error',
|
|
|
|
'warning',
|
2016-11-11 12:33:51 +01:00
|
|
|
'zoom-in', # TODO: clean these up, they are confusing
|
|
|
|
'zoom-out',
|
2016-11-01 22:32:10 +01:00
|
|
|
'first',
|
|
|
|
'second',
|
2016-12-03 01:12:52 +01:00
|
|
|
'selected',
|
2016-08-07 17:56:15 +02:00
|
|
|
]
|
|
|
|
|
|
|
|
def raise_error(fn, i, line):
|
|
|
|
# type: (str, int, str) -> None
|
|
|
|
error = '''
|
|
|
|
In %s line %d there is the following line of code:
|
|
|
|
|
|
|
|
%s
|
|
|
|
|
|
|
|
Our tools want to be able to identify which modules
|
|
|
|
add which HTML/CSS classes, and we need two things to
|
|
|
|
happen:
|
|
|
|
|
|
|
|
- The code must explicitly name the class.
|
|
|
|
- Only one module can refer to that class (unless
|
|
|
|
it is something generic like an alert class).
|
|
|
|
|
|
|
|
If you get this error, you can usually address it by
|
|
|
|
refactoring your code to be more explicit, or you can
|
|
|
|
move the common code that sets the class to a library
|
|
|
|
module. If neither of those applies, you need to
|
|
|
|
modify %s
|
|
|
|
''' % (fn, i, line, __file__)
|
|
|
|
raise Exception(error)
|
|
|
|
|
|
|
|
def generic(html_class):
|
|
|
|
# type: (str) -> bool
|
|
|
|
for kw in GENERIC_KEYWORDS:
|
|
|
|
if kw in html_class:
|
|
|
|
return True
|
2017-03-03 20:30:49 +01:00
|
|
|
return False
|
2016-08-07 17:56:15 +02:00
|
|
|
|
|
|
|
def display(fns):
|
|
|
|
# type: (List[str]) -> None
|
|
|
|
for tup in find(fns):
|
|
|
|
# this format is for code generation purposes
|
|
|
|
print(' ' * 8 + repr(tup) + ',')
|
|
|
|
|
|
|
|
def find(fns):
|
|
|
|
# type: (List[str]) -> List[Tuple[str, str]]
|
|
|
|
encountered = set() # type: Set[str]
|
|
|
|
tups = [] # type: List[Tuple[str, str]]
|
|
|
|
for fn in fns:
|
|
|
|
lines = list(open(fn))
|
|
|
|
fn = os.path.basename(fn)
|
|
|
|
module_classes = set() # type: Set[str]
|
|
|
|
for i, line in enumerate(lines):
|
|
|
|
if 'addClass' in line:
|
|
|
|
html_classes = [] # type: List[str]
|
|
|
|
m = re.search('addClass\([\'"](.*?)[\'"]', line)
|
|
|
|
if m:
|
|
|
|
html_classes = [m.group(1)]
|
|
|
|
if not html_classes:
|
|
|
|
if 'bar-success' in line:
|
|
|
|
html_classes = ['bar-success', 'bar-danger']
|
|
|
|
elif 'color_class' in line:
|
|
|
|
continue
|
|
|
|
elif 'stream_dark' in line:
|
|
|
|
continue
|
|
|
|
elif fn == 'signup.js' and 'class_to_add' in line:
|
|
|
|
html_classes = ['error', 'success']
|
|
|
|
elif fn == 'ui.js' and 'status_classes' in line:
|
|
|
|
html_classes = ['alert']
|
|
|
|
|
|
|
|
if not html_classes:
|
|
|
|
raise_error(fn, i, line)
|
|
|
|
for html_class in html_classes:
|
|
|
|
if generic(html_class):
|
|
|
|
continue
|
|
|
|
if html_class in module_classes:
|
|
|
|
continue
|
|
|
|
if html_class in encountered:
|
|
|
|
raise_error(fn, i, line)
|
|
|
|
tups.append((fn, html_class))
|
|
|
|
module_classes.add(html_class)
|
|
|
|
encountered.add(html_class)
|
|
|
|
return tups
|