Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Solarized line number colors #1477

Merged
merged 9 commits into from
Jul 4, 2020
Merged
2 changes: 1 addition & 1 deletion AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Other contributors, listed alphabetically, are:
* Sven Efftinge -- Xtend lexer
* Artem Egorkine -- terminal256 formatter
* Matthew Fernandez -- CAmkES lexer
* Paweł Fertyk -- GDScript lexer
* Paweł Fertyk -- GDScript lexer, HTML formatter improvements
* Michael Ficarra -- CPSA lexer
* James H. Fisher -- PostScript lexer
* William S. Fulton -- SWIG lexer
Expand Down
233 changes: 142 additions & 91 deletions pygments/formatters/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,6 @@ def _get_ttype_class(ttype):
Copyright 2006-2019 by the Pygments team.
Licensed under the BSD license, see LICENSE for details.
*/
td.linenos { background-color: #f0f0f0; padding-right: 10px; }
span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
pre { line-height: 125%%; }
%(styledefs)s
'''

Expand Down Expand Up @@ -208,9 +205,10 @@ class HtmlFormatter(Formatter):
`cssfile` exists.

`noclasses`
If set to true, token ``<span>`` tags will not use CSS classes, but
inline styles. This is not recommended for larger pieces of code since
it increases output size by quite a bit (default: ``False``).
If set to true, token ``<span>`` tags (as well as line number elements)
will not use CSS classes, but inline styles. This is not recommended
for larger pieces of code since it increases output size by quite a bit
(default: ``False``).

`classprefix`
Since the token types use relatively short class names, they may clash
Expand Down Expand Up @@ -438,7 +436,7 @@ def __init__(self, **options):
self.lineseparator = options.get('lineseparator', u'\n')
self.lineanchors = options.get('lineanchors', '')
self.linespans = options.get('linespans', '')
self.anchorlinenos = options.get('anchorlinenos', False)
self.anchorlinenos = get_bool_opt(options, 'anchorlinenos', False)
self.hl_lines = set()
for lineno in get_list_opt(options, 'hl_lines', []):
try:
Expand Down Expand Up @@ -495,6 +493,66 @@ def get_style_defs(self, arg=None):
highlighting style. ``arg`` can be a string or list of selectors to
insert before the token type classes.
"""
style_lines = []

style_lines.extend(self.get_linenos_style_defs())
style_lines.extend(self.get_background_style_defs(arg))
style_lines.extend(self.get_token_style_defs(arg))

return '\n'.join(style_lines)

def get_token_style_defs(self, arg=None):
prefix = self.get_css_prefix(arg)

styles = [
(level, ttype, cls, style)
for cls, (style, ttype, level) in self.class2style.items()
if cls and style
]
styles.sort()

lines = [
'%s { %s } /* %s */' % (prefix(cls), style, repr(ttype)[6:])
for (level, ttype, cls, style) in styles
]

return lines

def get_background_style_defs(self, arg=None):
prefix = self.get_css_prefix(arg)
bg_color = self.style.background_color
hl_color = self.style.highlight_color

lines = []

if arg and not self.nobackground and bg_color is not None:
text_style = ''
if Text in self.ttype2class:
text_style = ' ' + self.class2style[self.ttype2class[Text]][0]
lines.insert(
0, '%s{ background: %s;%s }' % (
prefix(''), bg_color, text_style
)
)
if hl_color is not None:
lines.insert(
0, '%s { background-color: %s }' % (prefix('hll'), hl_color)
)

return lines

def get_linenos_style_defs(self):
lines = [
'pre { %s }' % self._pre_style,
'td.linenos pre { %s }' % self._linenos_style,
'span.linenos { %s }' % self._linenos_style,
'td.linenos pre.special { %s }' % self._linenos_special_style,
'span.linenos.special { %s }' % self._linenos_special_style,
]

return lines

def get_css_prefix(self, arg):
if arg is None:
arg = ('cssclass' in self.options and '.'+self.cssclass or '')
if isinstance(arg, str):
Expand All @@ -510,23 +568,25 @@ def prefix(cls):
tmp.append((arg and arg + ' ' or '') + cls)
return ', '.join(tmp)

styles = [(level, ttype, cls, style)
for cls, (style, ttype, level) in self.class2style.items()
if cls and style]
styles.sort()
lines = ['%s { %s } /* %s */' % (prefix(cls), style, repr(ttype)[6:])
for (level, ttype, cls, style) in styles]
if arg and not self.nobackground and \
self.style.background_color is not None:
text_style = ''
if Text in self.ttype2class:
text_style = ' ' + self.class2style[self.ttype2class[Text]][0]
lines.insert(0, '%s { background: %s;%s }' %
(prefix(''), self.style.background_color, text_style))
if self.style.highlight_color is not None:
lines.insert(0, '%s.hll { background-color: %s }' %
(prefix(''), self.style.highlight_color))
return '\n'.join(lines)
return prefix

@property
def _pre_style(self):
return 'line-height: 125%; margin: 0;'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious - in which way margin: 0 makes it look better? In my case, it looks less pretty because there is no margin after the code. This looks more obvious when you write some explanation on the top and code after that few times, for example:

Oct-27-2020 18-30-12

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another example:

With margin: 0

Screen Shot 2020-10-27 at 6 43 35 PM

Without margin: 0

Screen Shot 2020-10-27 at 6 44 02 PM

I trying to override the CSS now and I was curious why this change was made.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're seeing (I guess) because your theme doesn't have margin/padding on the paragraph either. I'd try to override the style if you care about specific padding/margin. That said, the margin: 0 was not intentional (I think) so I'll revert that for 2.7.3.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in 4dede40

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Anteru :).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! I'm sorry if I'm a bit too late, but I'm pretty I've introduced the margin: 0 rule for a reason. Since I've worked on this one some time ago, I'm not sure what exactly was it, but I'd guess it had something to do with making the table and non-table styles look more similar. An alternative might be that it had something to do with highlighting lines/special lines. There was a lot of different combinations of styles and highlight rules etc. and I believe margin: 0 was introduced to make everything work better in regard to some of these combinations.

Having said that, if it actually looks better without margin: 0 and it doesn't break anything else, I'm totally OK with removing this rule :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't find the case where it would matter, and it does break various themes -- if you can point me to a problematic case then we can revisit alternative solutions. Ideally theme authors should have a way to override Pygments CSS rules, but for now this seems to be causing too much fallout :(

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to add all problematic cases to the test suite :P But while working on this a lot of dependencies came up and it's possible I've changed one thing too many ;) If you could just add a proper test with an explanation/justification, I would be very grateful. Right now, unfortunately, I'm not able to spend any time fixing this or checking why exactly was this change made. Reverting it seems like a good solution, as long as it's documented ;)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. I ran a bunch of manual tests and also spot-checked the test cases, and couldn't find a problematic case. Was hoping you'd remember something particularly problematic, but given the feedback we got, it seems that any rule changing the margin will cause more harm than good :(


@property
def _linenos_style(self):
return 'color: %s; background-color: %s; padding: 0 5px 0 5px;' % (
self.style.line_number_color,
self.style.line_number_background_color
)

@property
def _linenos_special_style(self):
return 'color: %s; background-color: %s; padding: 0 5px 0 5px;' % (
self.style.line_number_special_color,
self.style.line_number_special_background_color
)

def _decodeifneeded(self, value):
if isinstance(value, bytes):
Expand Down Expand Up @@ -592,88 +652,79 @@ def _wrap_tablelinenos(self, inner):
la = self.lineanchors
aln = self.anchorlinenos
nocls = self.noclasses
if sp:
lines = []

for i in range(fl, fl+lncount):
if i % st == 0:
if i % sp == 0:
if aln:
lines.append('<a href="#%s-%d" class="special">%*d</a>' %
(la, i, mw, i))
else:
lines.append('<span class="special">%*d</span>' % (mw, i))
else:
if aln:
lines.append('<a href="#%s-%d">%*d</a>' % (la, i, mw, i))
else:
lines.append('%*d' % (mw, i))

lines = []

for i in range(fl, fl+lncount):
print_line = i % st == 0
special_line = sp and i % sp == 0

if print_line:
line = '%*d' % (mw, i)
if aln:
line = '<a href="#%s-%d">%s</a>' % (la, i, line)
else:
line = ' ' * mw

if nocls:
if special_line:
style = ' style="%s"' % self._linenos_special_style
else:
lines.append('')
ls = '\n'.join(lines)
else:
lines = []
for i in range(fl, fl+lncount):
if i % st == 0:
if aln:
lines.append('<a href="#%s-%d">%*d</a>' % (la, i, mw, i))
else:
lines.append('%*d' % (mw, i))
style = ' style="%s"' % self._linenos_style
else:
if special_line:
style = ' class="special"'
else:
lines.append('')
ls = '\n'.join(lines)
style = ''

line = '<pre%s>%s</pre>' % (style, line)

lines.append(line)

ls = '\n'.join(lines)

# in case you wonder about the seemingly redundant <div> here: since the
# content in the other cell also is wrapped in a div, some browsers in
# some configurations seem to mess up the formatting...
if nocls:
yield 0, ('<table class="%stable">' % self.cssclass +
'<tr><td><div class="linenodiv" '
'style="background-color: #f0f0f0; padding-right: 10px">'
'<pre style="line-height: 125%">' +
ls + '</pre></div></td><td class="code">')
else:
yield 0, ('<table class="%stable">' % self.cssclass +
'<tr><td class="linenos"><div class="linenodiv"><pre>' +
ls + '</pre></div></td><td class="code">')
yield 0, (
'<table class="%stable">' % self.cssclass +
'<tr><td class="linenos"><div class="linenodiv">' +
ls + '</div></td><td class="code">'
)
yield 0, dummyoutfile.getvalue()
yield 0, '</td></tr></table>'

def _wrap_inlinelinenos(self, inner):
# need a list of lines since we need the width of a single number :(
lines = list(inner)
inner_lines = list(inner)
sp = self.linenospecial
st = self.linenostep
num = self.linenostart
mw = len(str(len(lines) + num - 1))
mw = len(str(len(inner_lines) + num - 1))
nocls = self.noclasses

if self.noclasses:
if sp:
for t, line in lines:
if num % sp == 0:
style = 'background-color: #ffffc0; padding: 0 5px 0 5px'
else:
style = 'background-color: #f0f0f0; padding: 0 5px 0 5px'
yield 1, '<span style="%s">%*s </span>' % (
style, mw, (num % st and ' ' or num)) + line
num += 1
for _, inner_line in inner_lines:
print_line = num % st == 0
special_line = sp and num % sp == 0

if print_line:
line = '%*d' % (mw, num)
else:
for t, line in lines:
yield 1, ('<span style="background-color: #f0f0f0; '
'padding: 0 5px 0 5px">%*s </span>' % (
mw, (num % st and ' ' or num)) + line)
num += 1
elif sp:
for t, line in lines:
yield 1, '<span class="lineno%s">%*s </span>' % (
num % sp == 0 and ' special' or '', mw,
(num % st and ' ' or num)) + line
num += 1
else:
for t, line in lines:
yield 1, '<span class="lineno">%*s </span>' % (
mw, (num % st and ' ' or num)) + line
num += 1
line = ' ' * mw

if nocls:
if special_line:
style = ' style="%s"' % self._linenos_special_style
else:
style = ' style="%s"' % self._linenos_style
else:
if special_line:
style = ' class="linenos special"'
else:
style = ' class="linenos"'

yield 1, '<span%s>%s</span>' % (style, line) + inner_line
num += 1

def _wrap_lineanchors(self, inner):
s = self.lineanchors
Expand Down Expand Up @@ -716,7 +767,7 @@ def _wrap_pre(self, inner):
if self.prestyles:
style.append(self.prestyles)
if self.noclasses:
style.append('line-height: 125%')
style.append(self._pre_style)
style = '; '.join(style)

if self.filename:
Expand Down
12 changes: 12 additions & 0 deletions pygments/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,5 +176,17 @@ class Style(metaclass=StyleMeta):
#: highlight background color
highlight_color = '#ffffcc'

#: line number font color
line_number_color = '#000000'

#: line number background color
line_number_background_color = '#f0f0f0'

#: special line number font color
line_number_special_color = '#000000'

#: special line number background color
line_number_special_background_color = '#ffffc0'

#: Style definitions for individual token types.
styles = {}
4 changes: 4 additions & 0 deletions pygments/styles/solarized.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ class SolarizedDarkStyle(Style):
styles = make_style(DARK_COLORS)
background_color = DARK_COLORS['base03']
highlight_color = DARK_COLORS['base02']
line_number_color = DARK_COLORS['base01']
line_number_background_color = DARK_COLORS['base02']


class SolarizedLightStyle(SolarizedDarkStyle):
Expand All @@ -128,3 +130,5 @@ class SolarizedLightStyle(SolarizedDarkStyle):
styles = make_style(LIGHT_COLORS)
background_color = LIGHT_COLORS['base03']
highlight_color = LIGHT_COLORS['base02']
line_number_color = LIGHT_COLORS['base01']
line_number_background_color = LIGHT_COLORS['base02']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="highlight">
<pre>
<span></span>
<span class="linenos">1</span><span class="c1"># a</span>
<span class="linenos">2</span><span class="c1"># b</span>
<span class="linenos">3</span><span class="c1"># c</span>
</pre>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="highlight">
<pre>
<span></span>
<span class="linenos">1</span><span class="c1"># a</span>
<span class="linenos">2</span><span class="c1"># b</span>
<span class="linenos">3</span><span class="c1"># c</span>
</pre>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="highlight">
<pre>
<span></span>
<span class="linenos">1</span><span class="c1"># a</span>
<span class="linenos">2</span><span class="c1"># b</span>
<span class="linenos special">3</span><span class="c1"># c</span>
</pre>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="highlight">
<pre>
<span></span>
<span class="linenos">1</span><span class="c1"># a</span>
<span class="linenos">2</span><span class="c1"># b</span>
<span class="linenos special">3</span><span class="c1"># c</span>
</pre>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="highlight">
<pre>
<span></span>
<span class="linenos"> 8</span><span class="c1"># a</span>
<span class="linenos"> 9</span><span class="c1"># b</span>
<span class="linenos">10</span><span class="c1"># c</span>
</pre>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="highlight">
<pre>
<span></span>
<span class="linenos"> 8</span><span class="c1"># a</span>
<span class="linenos"> 9</span><span class="c1"># b</span>
<span class="linenos">10</span><span class="c1"># c</span>
</pre>
</div>
Loading