eric6/ThirdParty/Pygments/pygments/formatters/html.py

changeset 7701
25f42e208e08
parent 7547
21b0534faebc
child 7983
54c5cfbb1e29
equal deleted inserted replaced
7700:a3cf077a8db3 7701:25f42e208e08
3 pygments.formatters.html 3 pygments.formatters.html
4 ~~~~~~~~~~~~~~~~~~~~~~~~ 4 ~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 Formatter for HTML output. 6 Formatter for HTML output.
7 7
8 :copyright: Copyright 2006-2019 by the Pygments team, see AUTHORS. 8 :copyright: Copyright 2006-2020 by the Pygments team, see AUTHORS.
9 :license: BSD, see LICENSE for details. 9 :license: BSD, see LICENSE for details.
10 """ 10 """
11 11
12 import os 12 import os
13 import sys 13 import sys
25 25
26 __all__ = ['HtmlFormatter'] 26 __all__ = ['HtmlFormatter']
27 27
28 28
29 _escape_html_table = { 29 _escape_html_table = {
30 ord('&'): u'&', 30 ord('&'): '&',
31 ord('<'): u'&lt;', 31 ord('<'): '&lt;',
32 ord('>'): u'&gt;', 32 ord('>'): '&gt;',
33 ord('"'): u'&quot;', 33 ord('"'): '&quot;',
34 ord("'"): u'&#39;', 34 ord("'"): '&#39;',
35 } 35 }
36 36
37 37
38 def escape_html(text, table=_escape_html_table): 38 def escape_html(text, table=_escape_html_table):
39 """Escape &, <, > as well as single and double quotes for HTML.""" 39 """Escape &, <, > as well as single and double quotes for HTML."""
60 60
61 61
62 CSSFILE_TEMPLATE = '''\ 62 CSSFILE_TEMPLATE = '''\
63 /* 63 /*
64 generated by Pygments <https://pygments.org/> 64 generated by Pygments <https://pygments.org/>
65 Copyright 2006-2019 by the Pygments team. 65 Copyright 2006-2020 by the Pygments team.
66 Licensed under the BSD license, see LICENSE for details. 66 Licensed under the BSD license, see LICENSE for details.
67 */ 67 */
68 td.linenos { background-color: #f0f0f0; padding-right: 10px; }
69 span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
70 pre { line-height: 125%%; }
71 %(styledefs)s 68 %(styledefs)s
72 ''' 69 '''
73 70
74 DOC_HEADER = '''\ 71 DOC_HEADER = '''\
75 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" 72 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
76 "http://www.w3.org/TR/html4/strict.dtd"> 73 "http://www.w3.org/TR/html4/strict.dtd">
77 <!-- 74 <!--
78 generated by Pygments <https://pygments.org/> 75 generated by Pygments <https://pygments.org/>
79 Copyright 2006-2019 by the Pygments team. 76 Copyright 2006-2020 by the Pygments team.
80 Licensed under the BSD license, see LICENSE for details. 77 Licensed under the BSD license, see LICENSE for details.
81 --> 78 -->
82 <html> 79 <html>
83 <head> 80 <head>
84 <title>%(title)s</title> 81 <title>%(title)s</title>
206 ``'default'``). This option has no effect if the `cssfile` 203 ``'default'``). This option has no effect if the `cssfile`
207 and `noclobber_cssfile` option are given and the file specified in 204 and `noclobber_cssfile` option are given and the file specified in
208 `cssfile` exists. 205 `cssfile` exists.
209 206
210 `noclasses` 207 `noclasses`
211 If set to true, token ``<span>`` tags will not use CSS classes, but 208 If set to true, token ``<span>`` tags (as well as line number elements)
212 inline styles. This is not recommended for larger pieces of code since 209 will not use CSS classes, but inline styles. This is not recommended
213 it increases output size by quite a bit (default: ``False``). 210 for larger pieces of code since it increases output size by quite a bit
211 (default: ``False``).
214 212
215 `classprefix` 213 `classprefix`
216 Since the token types use relatively short class names, they may clash 214 Since the token types use relatively short class names, they may clash
217 with some of your own class names. In this case you can use the 215 with some of your own class names. In this case you can use the
218 `classprefix` option to give a string to prepend to all Pygments-generated 216 `classprefix` option to give a string to prepend to all Pygments-generated
433 self.linenos = 0 431 self.linenos = 0
434 self.linenostart = abs(get_int_opt(options, 'linenostart', 1)) 432 self.linenostart = abs(get_int_opt(options, 'linenostart', 1))
435 self.linenostep = abs(get_int_opt(options, 'linenostep', 1)) 433 self.linenostep = abs(get_int_opt(options, 'linenostep', 1))
436 self.linenospecial = abs(get_int_opt(options, 'linenospecial', 0)) 434 self.linenospecial = abs(get_int_opt(options, 'linenospecial', 0))
437 self.nobackground = get_bool_opt(options, 'nobackground', False) 435 self.nobackground = get_bool_opt(options, 'nobackground', False)
438 self.lineseparator = options.get('lineseparator', u'\n') 436 self.lineseparator = options.get('lineseparator', '\n')
439 self.lineanchors = options.get('lineanchors', '') 437 self.lineanchors = options.get('lineanchors', '')
440 self.linespans = options.get('linespans', '') 438 self.linespans = options.get('linespans', '')
441 self.anchorlinenos = options.get('anchorlinenos', False) 439 self.anchorlinenos = get_bool_opt(options, 'anchorlinenos', False)
442 self.hl_lines = set() 440 self.hl_lines = set()
443 for lineno in get_list_opt(options, 'hl_lines', []): 441 for lineno in get_list_opt(options, 'hl_lines', []):
444 try: 442 try:
445 self.hl_lines.add(int(lineno)) 443 self.hl_lines.add(int(lineno))
446 except ValueError: 444 except ValueError:
493 """ 491 """
494 Return CSS style definitions for the classes produced by the current 492 Return CSS style definitions for the classes produced by the current
495 highlighting style. ``arg`` can be a string or list of selectors to 493 highlighting style. ``arg`` can be a string or list of selectors to
496 insert before the token type classes. 494 insert before the token type classes.
497 """ 495 """
496 style_lines = []
497
498 style_lines.extend(self.get_linenos_style_defs())
499 style_lines.extend(self.get_background_style_defs(arg))
500 style_lines.extend(self.get_token_style_defs(arg))
501
502 return '\n'.join(style_lines)
503
504 def get_token_style_defs(self, arg=None):
505 prefix = self.get_css_prefix(arg)
506
507 styles = [
508 (level, ttype, cls, style)
509 for cls, (style, ttype, level) in self.class2style.items()
510 if cls and style
511 ]
512 styles.sort()
513
514 lines = [
515 '%s { %s } /* %s */' % (prefix(cls), style, repr(ttype)[6:])
516 for (level, ttype, cls, style) in styles
517 ]
518
519 return lines
520
521 def get_background_style_defs(self, arg=None):
522 prefix = self.get_css_prefix(arg)
523 bg_color = self.style.background_color
524 hl_color = self.style.highlight_color
525
526 lines = []
527
528 if arg and not self.nobackground and bg_color is not None:
529 text_style = ''
530 if Text in self.ttype2class:
531 text_style = ' ' + self.class2style[self.ttype2class[Text]][0]
532 lines.insert(
533 0, '%s{ background: %s;%s }' % (
534 prefix(''), bg_color, text_style
535 )
536 )
537 if hl_color is not None:
538 lines.insert(
539 0, '%s { background-color: %s }' % (prefix('hll'), hl_color)
540 )
541
542 return lines
543
544 def get_linenos_style_defs(self):
545 lines = [
546 'pre { %s }' % self._pre_style,
547 'td.linenos pre { %s }' % self._linenos_style,
548 'span.linenos { %s }' % self._linenos_style,
549 'td.linenos pre.special { %s }' % self._linenos_special_style,
550 'span.linenos.special { %s }' % self._linenos_special_style,
551 ]
552
553 return lines
554
555 def get_css_prefix(self, arg):
498 if arg is None: 556 if arg is None:
499 arg = ('cssclass' in self.options and '.'+self.cssclass or '') 557 arg = ('cssclass' in self.options and '.'+self.cssclass or '')
500 if isinstance(arg, str): 558 if isinstance(arg, str):
501 args = [arg] 559 args = [arg]
502 else: 560 else:
508 tmp = [] 566 tmp = []
509 for arg in args: 567 for arg in args:
510 tmp.append((arg and arg + ' ' or '') + cls) 568 tmp.append((arg and arg + ' ' or '') + cls)
511 return ', '.join(tmp) 569 return ', '.join(tmp)
512 570
513 styles = [(level, ttype, cls, style) 571 return prefix
514 for cls, (style, ttype, level) in self.class2style.items() 572
515 if cls and style] 573 @property
516 styles.sort() 574 def _pre_style(self):
517 lines = ['%s { %s } /* %s */' % (prefix(cls), style, repr(ttype)[6:]) 575 return 'line-height: 125%; margin: 0;'
518 for (level, ttype, cls, style) in styles] 576
519 if arg and not self.nobackground and \ 577 @property
520 self.style.background_color is not None: 578 def _linenos_style(self):
521 text_style = '' 579 return 'color: %s; background-color: %s; padding: 0 5px 0 5px;' % (
522 if Text in self.ttype2class: 580 self.style.line_number_color,
523 text_style = ' ' + self.class2style[self.ttype2class[Text]][0] 581 self.style.line_number_background_color
524 lines.insert(0, '%s { background: %s;%s }' % 582 )
525 (prefix(''), self.style.background_color, text_style)) 583
526 if self.style.highlight_color is not None: 584 @property
527 lines.insert(0, '%s.hll { background-color: %s }' % 585 def _linenos_special_style(self):
528 (prefix(''), self.style.highlight_color)) 586 return 'color: %s; background-color: %s; padding: 0 5px 0 5px;' % (
529 return '\n'.join(lines) 587 self.style.line_number_special_color,
588 self.style.line_number_special_background_color
589 )
530 590
531 def _decodeifneeded(self, value): 591 def _decodeifneeded(self, value):
532 if isinstance(value, bytes): 592 if isinstance(value, bytes):
533 if self.encoding: 593 if self.encoding:
534 return value.decode(self.encoding) 594 return value.decode(self.encoding)
571 yield 0, (DOC_HEADER % 631 yield 0, (DOC_HEADER %
572 dict(title=self.title, 632 dict(title=self.title,
573 styledefs=self.get_style_defs('body'), 633 styledefs=self.get_style_defs('body'),
574 encoding=self.encoding)) 634 encoding=self.encoding))
575 635
576 for t, line in inner: 636 yield from inner
577 yield t, line
578 yield 0, DOC_FOOTER 637 yield 0, DOC_FOOTER
579 638
580 def _wrap_tablelinenos(self, inner): 639 def _wrap_tablelinenos(self, inner):
581 dummyoutfile = StringIO() 640 dummyoutfile = StringIO()
582 lncount = 0 641 lncount = 0
590 sp = self.linenospecial 649 sp = self.linenospecial
591 st = self.linenostep 650 st = self.linenostep
592 la = self.lineanchors 651 la = self.lineanchors
593 aln = self.anchorlinenos 652 aln = self.anchorlinenos
594 nocls = self.noclasses 653 nocls = self.noclasses
595 if sp: 654
596 lines = [] 655 lines = []
597 656
598 for i in range(fl, fl+lncount): 657 for i in range(fl, fl+lncount):
599 if i % st == 0: 658 print_line = i % st == 0
600 if i % sp == 0: 659 special_line = sp and i % sp == 0
601 if aln: 660
602 lines.append('<a href="#%s-%d" class="special">%*d</a>' % 661 if print_line:
603 (la, i, mw, i)) 662 line = '%*d' % (mw, i)
604 else: 663 if aln:
605 lines.append('<span class="special">%*d</span>' % (mw, i)) 664 line = '<a href="#%s-%d">%s</a>' % (la, i, line)
606 else: 665 else:
607 if aln: 666 line = ' ' * mw
608 lines.append('<a href="#%s-%d">%*d</a>' % (la, i, mw, i)) 667
609 else: 668 if nocls:
610 lines.append('%*d' % (mw, i)) 669 if special_line:
670 style = ' style="%s"' % self._linenos_special_style
611 else: 671 else:
612 lines.append('') 672 style = ' style="%s"' % self._linenos_style
613 ls = '\n'.join(lines) 673 else:
614 else: 674 if special_line:
615 lines = [] 675 style = ' class="special"'
616 for i in range(fl, fl+lncount):
617 if i % st == 0:
618 if aln:
619 lines.append('<a href="#%s-%d">%*d</a>' % (la, i, mw, i))
620 else:
621 lines.append('%*d' % (mw, i))
622 else: 676 else:
623 lines.append('') 677 style = ''
624 ls = '\n'.join(lines) 678
679 if style:
680 line = '<span%s>%s</span>' % (style, line)
681
682 lines.append(line)
683
684 ls = '\n'.join(lines)
625 685
626 # in case you wonder about the seemingly redundant <div> here: since the 686 # in case you wonder about the seemingly redundant <div> here: since the
627 # content in the other cell also is wrapped in a div, some browsers in 687 # content in the other cell also is wrapped in a div, some browsers in
628 # some configurations seem to mess up the formatting... 688 # some configurations seem to mess up the formatting...
629 if nocls: 689 yield 0, (
630 yield 0, ('<table class="%stable">' % self.cssclass + 690 '<table class="%stable">' % self.cssclass +
631 '<tr><td><div class="linenodiv" ' 691 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
632 'style="background-color: #f0f0f0; padding-right: 10px">' 692 ls + '</pre></div></td><td class="code">'
633 '<pre style="line-height: 125%">' + 693 )
634 ls + '</pre></div></td><td class="code">')
635 else:
636 yield 0, ('<table class="%stable">' % self.cssclass +
637 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
638 ls + '</pre></div></td><td class="code">')
639 yield 0, dummyoutfile.getvalue() 694 yield 0, dummyoutfile.getvalue()
640 yield 0, '</td></tr></table>' 695 yield 0, '</td></tr></table>'
641 696
642 def _wrap_inlinelinenos(self, inner): 697 def _wrap_inlinelinenos(self, inner):
643 # need a list of lines since we need the width of a single number :( 698 # need a list of lines since we need the width of a single number :(
644 lines = list(inner) 699 inner_lines = list(inner)
645 sp = self.linenospecial 700 sp = self.linenospecial
646 st = self.linenostep 701 st = self.linenostep
647 num = self.linenostart 702 num = self.linenostart
648 mw = len(str(len(lines) + num - 1)) 703 mw = len(str(len(inner_lines) + num - 1))
649 704 nocls = self.noclasses
650 if self.noclasses: 705
651 if sp: 706 for _, inner_line in inner_lines:
652 for t, line in lines: 707 print_line = num % st == 0
653 if num % sp == 0: 708 special_line = sp and num % sp == 0
654 style = 'background-color: #ffffc0; padding: 0 5px 0 5px' 709
655 else: 710 if print_line:
656 style = 'background-color: #f0f0f0; padding: 0 5px 0 5px' 711 line = '%*d' % (mw, num)
657 yield 1, '<span style="%s">%*s </span>' % (
658 style, mw, (num % st and ' ' or num)) + line
659 num += 1
660 else: 712 else:
661 for t, line in lines: 713 line = ' ' * mw
662 yield 1, ('<span style="background-color: #f0f0f0; ' 714
663 'padding: 0 5px 0 5px">%*s </span>' % ( 715 if nocls:
664 mw, (num % st and ' ' or num)) + line) 716 if special_line:
665 num += 1 717 style = ' style="%s"' % self._linenos_special_style
666 elif sp: 718 else:
667 for t, line in lines: 719 style = ' style="%s"' % self._linenos_style
668 yield 1, '<span class="lineno%s">%*s </span>' % ( 720 else:
669 num % sp == 0 and ' special' or '', mw, 721 if special_line:
670 (num % st and ' ' or num)) + line 722 style = ' class="linenos special"'
671 num += 1 723 else:
672 else: 724 style = ' class="linenos"'
673 for t, line in lines: 725
674 yield 1, '<span class="lineno">%*s </span>' % ( 726 if style:
675 mw, (num % st and ' ' or num)) + line 727 yield 1, '<span%s>%s</span>' % (style, line) + inner_line
676 num += 1 728 else:
729 yield 1, line + inner_line
730 num += 1
677 731
678 def _wrap_lineanchors(self, inner): 732 def _wrap_lineanchors(self, inner):
679 s = self.lineanchors 733 s = self.lineanchors
680 # subtract 1 since we have to increment i *before* yielding 734 # subtract 1 since we have to increment i *before* yielding
681 i = self.linenostart - 1 735 i = self.linenostart - 1
705 style.append(self.cssstyles) 759 style.append(self.cssstyles)
706 style = '; '.join(style) 760 style = '; '.join(style)
707 761
708 yield 0, ('<div' + (self.cssclass and ' class="%s"' % self.cssclass) + 762 yield 0, ('<div' + (self.cssclass and ' class="%s"' % self.cssclass) +
709 (style and (' style="%s"' % style)) + '>') 763 (style and (' style="%s"' % style)) + '>')
710 for tup in inner: 764 yield from inner
711 yield tup
712 yield 0, '</div>\n' 765 yield 0, '</div>\n'
713 766
714 def _wrap_pre(self, inner): 767 def _wrap_pre(self, inner):
715 style = [] 768 style = []
716 if self.prestyles: 769 if self.prestyles:
717 style.append(self.prestyles) 770 style.append(self.prestyles)
718 if self.noclasses: 771 if self.noclasses:
719 style.append('line-height: 125%') 772 style.append(self._pre_style)
720 style = '; '.join(style) 773 style = '; '.join(style)
721 774
722 if self.filename: 775 if self.filename:
723 yield 0, ('<span class="filename">' + self.filename + '</span>') 776 yield 0, ('<span class="filename">' + self.filename + '</span>')
724 777
725 # the empty span here is to keep leading empty lines from being 778 # the empty span here is to keep leading empty lines from being
726 # ignored by HTML parsers 779 # ignored by HTML parsers
727 yield 0, ('<pre' + (style and ' style="%s"' % style) + '><span></span>') 780 yield 0, ('<pre' + (style and ' style="%s"' % style) + '><span></span>')
728 for tup in inner: 781 yield from inner
729 yield tup
730 yield 0, '</pre>' 782 yield 0, '</pre>'
731 783
732 def _wrap_code(self, inner): 784 def _wrap_code(self, inner):
733 yield 0, '<code>' 785 yield 0, '<code>'
734 for tup in inner: 786 yield from inner
735 yield tup
736 yield 0, '</code>' 787 yield 0, '</code>'
737 788
738 def _format_lines(self, tokensource): 789 def _format_lines(self, tokensource):
739 """ 790 """
740 Just format the tokens, without any wrapping tags. 791 Just format the tokens, without any wrapping tags.

eric ide

mercurial