csshtmlheader.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. """Module that pre-processes the notebook for export to HTML.
  2. """
  3. # Copyright (c) Jupyter Development Team.
  4. # Distributed under the terms of the Modified BSD License.
  5. import os
  6. import io
  7. import hashlib
  8. import nbconvert.resources
  9. from traitlets import Unicode
  10. from .base import Preprocessor
  11. try:
  12. from notebook import DEFAULT_STATIC_FILES_PATH
  13. except ImportError:
  14. DEFAULT_STATIC_FILES_PATH = None
  15. class CSSHTMLHeaderPreprocessor(Preprocessor):
  16. """
  17. Preprocessor used to pre-process notebook for HTML output. Adds IPython notebook
  18. front-end CSS and Pygments CSS to HTML output.
  19. """
  20. highlight_class = Unicode('.highlight',
  21. help="CSS highlight class identifier"
  22. ).tag(config=True)
  23. style = Unicode('default',
  24. help='Name of the pygments style to use'
  25. ).tag(config=True)
  26. def __init__(self, *pargs, **kwargs):
  27. Preprocessor.__init__(self, *pargs, **kwargs)
  28. self._default_css_hash = None
  29. def preprocess(self, nb, resources):
  30. """Fetch and add CSS to the resource dictionary
  31. Fetch CSS from IPython and Pygments to add at the beginning
  32. of the html files. Add this css in resources in the
  33. "inlining.css" key
  34. Parameters
  35. ----------
  36. nb : NotebookNode
  37. Notebook being converted
  38. resources : dictionary
  39. Additional resources used in the conversion process. Allows
  40. preprocessors to pass variables into the Jinja engine.
  41. """
  42. resources['inlining'] = {}
  43. resources['inlining']['css'] = self._generate_header(resources)
  44. return nb, resources
  45. def _generate_header(self, resources):
  46. """
  47. Fills self.header with lines of CSS extracted from IPython
  48. and Pygments.
  49. """
  50. from pygments.formatters import HtmlFormatter
  51. header = []
  52. # Construct path to Jupyter CSS
  53. sheet_filename = os.path.join(
  54. os.path.dirname(nbconvert.resources.__file__),
  55. 'style.min.css',
  56. )
  57. # Load style CSS file.
  58. with io.open(sheet_filename, encoding='utf-8') as f:
  59. header.append(f.read())
  60. # Add pygments CSS
  61. formatter = HtmlFormatter(style=self.style)
  62. pygments_css = formatter.get_style_defs(self.highlight_class)
  63. header.append(pygments_css)
  64. # Load the user's custom CSS and IPython's default custom CSS. If they
  65. # differ, assume the user has made modifications to his/her custom CSS
  66. # and that we should inline it in the nbconvert output.
  67. config_dir = resources['config_dir']
  68. custom_css_filename = os.path.join(config_dir, 'custom', 'custom.css')
  69. if os.path.isfile(custom_css_filename):
  70. if DEFAULT_STATIC_FILES_PATH and self._default_css_hash is None:
  71. self._default_css_hash = self._hash(os.path.join(DEFAULT_STATIC_FILES_PATH, 'custom', 'custom.css'))
  72. if self._hash(custom_css_filename) != self._default_css_hash:
  73. with io.open(custom_css_filename, encoding='utf-8') as f:
  74. header.append(f.read())
  75. return header
  76. def _hash(self, filename):
  77. """Compute the hash of a file."""
  78. md5 = hashlib.md5()
  79. with open(filename, 'rb') as f:
  80. md5.update(f.read())
  81. return md5.digest()