linter: Add support for automatic checking for 4 space indents in CSS.

In this commit we modify our CSS parser not only to render the text from
a given CSS tokens produced but also enforce 4 space indentation on it.
Also we enforce some basic rules we would like our CSS to follow such as
* Always have "\n" in between the starting of body({) and body itself
  and ending of the body and the closing of body(}).
* Use 4 space indents while having but something within the block
  structure ( { .... } ).
* Have single space after ',' in between multiple selectors.
* Have only a single space in between selector and the starting of
  block structure ({ ... }) if block structure starts on same line as
  of selector.
  eg. body {
          body content here
      }
  Notice single space between 'body' and '{'.

Fixes: #1659.
This commit is contained in:
adnrs96
2017-03-17 17:04:45 +05:30
committed by Tim Abbott
parent 257187a239
commit b3cbb13a79
3 changed files with 158 additions and 17 deletions

View File

@@ -257,6 +257,99 @@ def parse_value(tokens, start, end):
post_fluff=post_fluff,
)
def handle_prefluff(pre_fluff, indent=False):
# type: (str, bool) -> str
pre_fluff_lines = pre_fluff.split('\n')
formatted_pre_fluff_lines = []
comment_indent = ''
general_indent = ''
if indent:
general_indent = ' '
for i, ln in enumerate(pre_fluff_lines):
line_indent = ''
if ln.strip() != '':
if not i:
line_indent = general_indent
comment_indent = ' '
else:
if comment_indent:
if ('*/' in ln or '*' in ln) and (ln.strip()[:2] in ('*/', '* ', '*')):
line_indent = general_indent
if '*/' in ln:
comment_indent = ''
else:
line_indent = general_indent + comment_indent
else:
line_indent = general_indent
comment_indent = ' '
elif len(pre_fluff_lines) == 1 and indent and ln != '':
line_indent = ' '
formatted_pre_fluff_lines.append(line_indent + ln.strip())
if formatted_pre_fluff_lines[-1] != '':
if formatted_pre_fluff_lines[-1].strip() == '' and indent:
formatted_pre_fluff_lines[-1] = ''
formatted_pre_fluff_lines.append('')
pre_fluff = '\n'.join(formatted_pre_fluff_lines)
res = ''
if indent:
if '\n' in pre_fluff:
res = pre_fluff + ' '
elif pre_fluff == '':
res = ' '
else:
res = pre_fluff.rstrip() + ' '
else:
res = pre_fluff
return res
def handle_postfluff(post_fluff, indent=False, space_after_first_line=False):
# type: (str, bool, bool) -> str
post_fluff_lines = post_fluff.split('\n')
formatted_post_fluff_lines = []
comment_indent = ''
general_indent = ''
if indent:
general_indent = ' '
for i, ln in enumerate(post_fluff_lines):
line_indent = ''
if ln.strip() != '':
if i:
if comment_indent:
if ('*/' in ln or '*' in ln) and (ln.strip()[:2] in ('*/', '* ', '*')):
line_indent = general_indent
if '*/' in ln:
comment_indent = ''
else:
line_indent = general_indent + comment_indent
else:
line_indent = general_indent
comment_indent = ' '
elif indent and not i and len(post_fluff_lines) > 2:
formatted_post_fluff_lines.append('')
line_indent = general_indent
comment_indent = ' '
elif space_after_first_line:
line_indent = ' '
if not i:
comment_indent = ' '
elif not i:
comment_indent = ' '
formatted_post_fluff_lines.append(line_indent + ln.strip())
if len(formatted_post_fluff_lines) == 1 and not space_after_first_line:
if formatted_post_fluff_lines[-1].strip() == '':
if formatted_post_fluff_lines[-1] != '':
formatted_post_fluff_lines[-1] = ' '
else:
formatted_post_fluff_lines.append('')
elif formatted_post_fluff_lines[-1].strip() == '':
formatted_post_fluff_lines[-1] = ''
if len(formatted_post_fluff_lines) == 1 and indent:
formatted_post_fluff_lines.append('')
elif space_after_first_line:
formatted_post_fluff_lines.append('')
post_fluff = '\n'.join(formatted_post_fluff_lines)
return post_fluff
#### Begin CSS classes here
@@ -286,7 +379,14 @@ class CssNestedSection(object):
res += self.pre_fluff
res += self.selector_list.text()
res += '{'
res += self.section_list.text()
section_list_lines = self.section_list.text().split('\n')
formatted_section_list = []
for ln in section_list_lines:
if ln.strip() == '':
formatted_section_list.append('')
else:
formatted_section_list.append(' ' + ln)
res += '\n'.join(formatted_section_list)
res += '}'
res += self.post_fluff
return res
@@ -303,10 +403,10 @@ class CssSection(object):
def text(self):
# type: () -> str
res = ''
res += self.pre_fluff
res += handle_prefluff(self.pre_fluff)
res += self.selector_list.text()
res += self.declaration_block.text()
res += self.post_fluff
res += handle_postfluff(self.post_fluff, space_after_first_line=True)
return res
class CssSelectorList(object):
@@ -317,7 +417,16 @@ class CssSelectorList(object):
def text(self):
# type: () -> str
res = ','.join(sel.text() for sel in self.selectors)
res = ''
for i, sel in enumerate(self.selectors):
sel_list_render = sel.text()
if i != 0 and sel_list_render[0] != '\n':
res += ' '
res += sel_list_render
if i != len(self.selectors) - 1:
res += ','
if res[-1] != ' ' and res[-1] != '\n':
res += ' '
return res
class CssSelector(object):
@@ -331,9 +440,9 @@ class CssSelector(object):
def text(self):
# type: () -> str
res = ''
res += self.pre_fluff
res += handle_prefluff(self.pre_fluff)
res += ' '.join(level.s for level in self.levels)
res += self.post_fluff
res += handle_postfluff(self.post_fluff)
return res
class CssDeclarationBlock(object):
@@ -363,7 +472,7 @@ class CssDeclaration(object):
def text(self):
# type: () -> str
res = ''
res += self.pre_fluff
res += handle_prefluff(self.pre_fluff, True)
res += self.css_property
res += ':'
value_text = self.css_value.text()
@@ -374,7 +483,7 @@ class CssDeclaration(object):
res += ' '
res += value_text.strip()
res += ';'
res += self.post_fluff
res += handle_postfluff(self.post_fluff, True, True)
return res
class CssValue(object):