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

changeset 7547
21b0534faebc
parent 6942
2602857055c5
child 7701
25f42e208e08
equal deleted inserted replaced
7546:bf5f777260a6 7547:21b0534faebc
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-2017 by the Pygments team, see AUTHORS. 8 :copyright: Copyright 2006-2019 by the Pygments team, see AUTHORS.
9 :license: BSD, see LICENSE for details. 9 :license: BSD, see LICENSE for details.
10 """ 10 """
11
12 from __future__ import print_function
13 11
14 import os 12 import os
15 import sys 13 import sys
16 import os.path 14 import os.path
15 from io import StringIO
17 16
18 from pygments.formatter import Formatter 17 from pygments.formatter import Formatter
19 from pygments.token import Token, Text, STANDARD_TYPES 18 from pygments.token import Token, Text, STANDARD_TYPES
20 from pygments.util import get_bool_opt, get_int_opt, get_list_opt, \ 19 from pygments.util import get_bool_opt, get_int_opt, get_list_opt
21 StringIO, string_types, iteritems
22 20
23 try: 21 try:
24 import ctags 22 import ctags
25 except ImportError: 23 except ImportError:
26 ctags = None 24 ctags = None
38 36
39 37
40 def escape_html(text, table=_escape_html_table): 38 def escape_html(text, table=_escape_html_table):
41 """Escape &, <, > as well as single and double quotes for HTML.""" 39 """Escape &, <, > as well as single and double quotes for HTML."""
42 return text.translate(table) 40 return text.translate(table)
41
42
43 def webify(color):
44 if color.startswith('calc') or color.startswith('var'):
45 return color
46 else:
47 return '#' + color
43 48
44 49
45 def _get_ttype_class(ttype): 50 def _get_ttype_class(ttype):
46 fname = STANDARD_TYPES.get(ttype) 51 fname = STANDARD_TYPES.get(ttype)
47 if fname: 52 if fname:
53 fname = STANDARD_TYPES.get(ttype) 58 fname = STANDARD_TYPES.get(ttype)
54 return fname + aname 59 return fname + aname
55 60
56 61
57 CSSFILE_TEMPLATE = '''\ 62 CSSFILE_TEMPLATE = '''\
63 /*
64 generated by Pygments <https://pygments.org/>
65 Copyright 2006-2019 by the Pygments team.
66 Licensed under the BSD license, see LICENSE for details.
67 */
58 td.linenos { background-color: #f0f0f0; padding-right: 10px; } 68 td.linenos { background-color: #f0f0f0; padding-right: 10px; }
59 span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } 69 span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
60 pre { line-height: 125%%; } 70 pre { line-height: 125%%; }
61 %(styledefs)s 71 %(styledefs)s
62 ''' 72 '''
63 73
64 DOC_HEADER = '''\ 74 DOC_HEADER = '''\
65 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" 75 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
66 "http://www.w3.org/TR/html4/strict.dtd"> 76 "http://www.w3.org/TR/html4/strict.dtd">
67 77 <!--
78 generated by Pygments <https://pygments.org/>
79 Copyright 2006-2019 by the Pygments team.
80 Licensed under the BSD license, see LICENSE for details.
81 -->
68 <html> 82 <html>
69 <head> 83 <head>
70 <title>%(title)s</title> 84 <title>%(title)s</title>
71 <meta http-equiv="content-type" content="text/html; charset=%(encoding)s"> 85 <meta http-equiv="content-type" content="text/html; charset=%(encoding)s">
72 <style type="text/css"> 86 <style type="text/css">
320 Defaults to an empty string, resulting in just `#prefix-number` links. 334 Defaults to an empty string, resulting in just `#prefix-number` links.
321 335
322 .. versionadded:: 1.6 336 .. versionadded:: 1.6
323 337
324 `filename` 338 `filename`
325 A string used to generate a filename when rendering <pre> blocks, 339 A string used to generate a filename when rendering ``<pre>`` blocks,
326 for example if displaying source code. 340 for example if displaying source code.
327 341
328 .. versionadded:: 2.1 342 .. versionadded:: 2.1
343
344 `wrapcode`
345 Wrap the code inside ``<pre>`` blocks using ``<code>``, as recommended
346 by the HTML5 specification.
347
348 .. versionadded:: 2.4
329 349
330 350
331 **Subclassing the HTML formatter** 351 **Subclassing the HTML formatter**
332 352
333 .. versionadded:: 0.7 353 .. versionadded:: 0.7
393 self.cssfile = self._decodeifneeded(options.get('cssfile', '')) 413 self.cssfile = self._decodeifneeded(options.get('cssfile', ''))
394 self.noclobber_cssfile = get_bool_opt(options, 'noclobber_cssfile', False) 414 self.noclobber_cssfile = get_bool_opt(options, 'noclobber_cssfile', False)
395 self.tagsfile = self._decodeifneeded(options.get('tagsfile', '')) 415 self.tagsfile = self._decodeifneeded(options.get('tagsfile', ''))
396 self.tagurlformat = self._decodeifneeded(options.get('tagurlformat', '')) 416 self.tagurlformat = self._decodeifneeded(options.get('tagurlformat', ''))
397 self.filename = self._decodeifneeded(options.get('filename', '')) 417 self.filename = self._decodeifneeded(options.get('filename', ''))
418 self.wrapcode = get_bool_opt(options, 'wrapcode', False)
398 419
399 if self.tagsfile: 420 if self.tagsfile:
400 if not ctags: 421 if not ctags:
401 raise RuntimeError('The "ctags" package must to be installed ' 422 raise RuntimeError('The "ctags" package must to be installed '
402 'to be able to use the "tagsfile" feature.') 423 'to be able to use the "tagsfile" feature.')
412 self.linenos = 0 433 self.linenos = 0
413 self.linenostart = abs(get_int_opt(options, 'linenostart', 1)) 434 self.linenostart = abs(get_int_opt(options, 'linenostart', 1))
414 self.linenostep = abs(get_int_opt(options, 'linenostep', 1)) 435 self.linenostep = abs(get_int_opt(options, 'linenostep', 1))
415 self.linenospecial = abs(get_int_opt(options, 'linenospecial', 0)) 436 self.linenospecial = abs(get_int_opt(options, 'linenospecial', 0))
416 self.nobackground = get_bool_opt(options, 'nobackground', False) 437 self.nobackground = get_bool_opt(options, 'nobackground', False)
417 self.lineseparator = options.get('lineseparator', '\n') 438 self.lineseparator = options.get('lineseparator', u'\n')
418 self.lineanchors = options.get('lineanchors', '') 439 self.lineanchors = options.get('lineanchors', '')
419 self.linespans = options.get('linespans', '') 440 self.linespans = options.get('linespans', '')
420 self.anchorlinenos = options.get('anchorlinenos', False) 441 self.anchorlinenos = options.get('anchorlinenos', False)
421 self.hl_lines = set() 442 self.hl_lines = set()
422 for lineno in get_list_opt(options, 'hl_lines', []): 443 for lineno in get_list_opt(options, 'hl_lines', []):
449 c2s = self.class2style = {} 470 c2s = self.class2style = {}
450 for ttype, ndef in self.style: 471 for ttype, ndef in self.style:
451 name = self._get_css_class(ttype) 472 name = self._get_css_class(ttype)
452 style = '' 473 style = ''
453 if ndef['color']: 474 if ndef['color']:
454 style += 'color: #%s; ' % ndef['color'] 475 style += 'color: %s; ' % webify(ndef['color'])
455 if ndef['bold']: 476 if ndef['bold']:
456 style += 'font-weight: bold; ' 477 style += 'font-weight: bold; '
457 if ndef['italic']: 478 if ndef['italic']:
458 style += 'font-style: italic; ' 479 style += 'font-style: italic; '
459 if ndef['underline']: 480 if ndef['underline']:
460 style += 'text-decoration: underline; ' 481 style += 'text-decoration: underline; '
461 if ndef['bgcolor']: 482 if ndef['bgcolor']:
462 style += 'background-color: #%s; ' % ndef['bgcolor'] 483 style += 'background-color: %s; ' % webify(ndef['bgcolor'])
463 if ndef['border']: 484 if ndef['border']:
464 style += 'border: 1px solid #%s; ' % ndef['border'] 485 style += 'border: 1px solid %s; ' % webify(ndef['border'])
465 if style: 486 if style:
466 t2c[ttype] = name 487 t2c[ttype] = name
467 # save len(ttype) to enable ordering the styles by 488 # save len(ttype) to enable ordering the styles by
468 # hierarchy (necessary for CSS cascading rules!) 489 # hierarchy (necessary for CSS cascading rules!)
469 c2s[name] = (style[:-2], ttype, len(ttype)) 490 c2s[name] = (style[:-2], ttype, len(ttype))
474 highlighting style. ``arg`` can be a string or list of selectors to 495 highlighting style. ``arg`` can be a string or list of selectors to
475 insert before the token type classes. 496 insert before the token type classes.
476 """ 497 """
477 if arg is None: 498 if arg is None:
478 arg = ('cssclass' in self.options and '.'+self.cssclass or '') 499 arg = ('cssclass' in self.options and '.'+self.cssclass or '')
479 if isinstance(arg, string_types): 500 if isinstance(arg, str):
480 args = [arg] 501 args = [arg]
481 else: 502 else:
482 args = list(arg) 503 args = list(arg)
483 504
484 def prefix(cls): 505 def prefix(cls):
488 for arg in args: 509 for arg in args:
489 tmp.append((arg and arg + ' ' or '') + cls) 510 tmp.append((arg and arg + ' ' or '') + cls)
490 return ', '.join(tmp) 511 return ', '.join(tmp)
491 512
492 styles = [(level, ttype, cls, style) 513 styles = [(level, ttype, cls, style)
493 for cls, (style, ttype, level) in iteritems(self.class2style) 514 for cls, (style, ttype, level) in self.class2style.items()
494 if cls and style] 515 if cls and style]
495 styles.sort() 516 styles.sort()
496 lines = ['%s { %s } /* %s */' % (prefix(cls), style, repr(ttype)[6:]) 517 lines = ['%s { %s } /* %s */' % (prefix(cls), style, repr(ttype)[6:])
497 for (level, ttype, cls, style) in styles] 518 for (level, ttype, cls, style) in styles]
498 if arg and not self.nobackground and \ 519 if arg and not self.nobackground and \
533 file=sys.stderr) 554 file=sys.stderr)
534 cssfilename = self.cssfile 555 cssfilename = self.cssfile
535 # write CSS file only if noclobber_cssfile isn't given as an option. 556 # write CSS file only if noclobber_cssfile isn't given as an option.
536 try: 557 try:
537 if not os.path.exists(cssfilename) or not self.noclobber_cssfile: 558 if not os.path.exists(cssfilename) or not self.noclobber_cssfile:
538 cf = open(cssfilename, "w") 559 with open(cssfilename, "w") as cf:
539 cf.write(CSSFILE_TEMPLATE % 560 cf.write(CSSFILE_TEMPLATE %
540 {'styledefs': self.get_style_defs('body')}) 561 {'styledefs': self.get_style_defs('body')})
541 cf.close()
542 except IOError as err: 562 except IOError as err:
543 err.strerror = 'Error writing CSS file: ' + err.strerror 563 err.strerror = 'Error writing CSS file: ' + err.strerror
544 raise 564 raise
545 565
546 yield 0, (DOC_HEADER_EXTERNALCSS % 566 yield 0, (DOC_HEADER_EXTERNALCSS %
707 yield 0, ('<pre' + (style and ' style="%s"' % style) + '><span></span>') 727 yield 0, ('<pre' + (style and ' style="%s"' % style) + '><span></span>')
708 for tup in inner: 728 for tup in inner:
709 yield tup 729 yield tup
710 yield 0, '</pre>' 730 yield 0, '</pre>'
711 731
732 def _wrap_code(self, inner):
733 yield 0, '<code>'
734 for tup in inner:
735 yield tup
736 yield 0, '</code>'
737
712 def _format_lines(self, tokensource): 738 def _format_lines(self, tokensource):
713 """ 739 """
714 Just format the tokens, without any wrapping tags. 740 Just format the tokens, without any wrapping tags.
715 Yield individual lines. 741 Yield individual lines.
716 """ 742 """
813 """ 839 """
814 Wrap the ``source``, which is a generator yielding 840 Wrap the ``source``, which is a generator yielding
815 individual lines, in custom generators. See docstring 841 individual lines, in custom generators. See docstring
816 for `format`. Can be overridden. 842 for `format`. Can be overridden.
817 """ 843 """
818 return self._wrap_div(self._wrap_pre(source)) 844 if self.wrapcode:
845 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
846 else:
847 return self._wrap_div(self._wrap_pre(source))
819 848
820 def format_unencoded(self, tokensource, outfile): 849 def format_unencoded(self, tokensource, outfile):
821 """ 850 """
822 The formatting process uses several nested generators; which of 851 The formatting process uses several nested generators; which of
823 them are used is determined by the user's options. 852 them are used is determined by the user's options.

eric ide

mercurial