slides.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. """HTML slide show Exporter class"""
  2. # Copyright (c) Jupyter Development Team.
  3. # Distributed under the terms of the Modified BSD License.
  4. from copy import deepcopy
  5. from warnings import warn
  6. from traitlets import Bool, Unicode, default
  7. from .html import HTMLExporter
  8. def prepare(nb):
  9. """Add some convenience metadata on cells for the slide template."""
  10. nb = deepcopy(nb)
  11. for cell in nb.cells:
  12. # Make sure every cell has a slide_type
  13. cell.metadata.slide_type = cell.metadata.get('slideshow', {}).get('slide_type', '-')
  14. # Find the first visible cell
  15. for index, cell in enumerate(nb.cells):
  16. if cell.metadata.slide_type not in {'notes', 'skip'}:
  17. cell.metadata.slide_type = 'slide'
  18. cell.metadata.slide_start = True
  19. cell.metadata.subslide_start = True
  20. first_slide_ix = index
  21. break
  22. else:
  23. raise ValueError("All cells are hidden, cannot create slideshow")
  24. in_fragment = False
  25. for index, cell in enumerate(nb.cells[first_slide_ix+1:],
  26. start=(first_slide_ix+1)):
  27. previous_cell = nb.cells[index - 1]
  28. # Slides are <section> elements in the HTML, subslides (the vertically
  29. # stacked slides) are also <section> elements inside the slides,
  30. # and fragments are <div>s within subslides. Subslide and fragment
  31. # elements can contain content:
  32. # <section>
  33. # <section>
  34. # (content)
  35. # <div class="fragment">(content)</div>
  36. # </section>
  37. # </section>
  38. # Get the slide type. If type is subslide or slide,
  39. # end the last slide/subslide/fragment as applicable.
  40. if cell.metadata.slide_type == 'slide':
  41. previous_cell.metadata.slide_end = True
  42. cell.metadata.slide_start = True
  43. if cell.metadata.slide_type in {'subslide', 'slide'}:
  44. previous_cell.metadata.fragment_end = in_fragment
  45. previous_cell.metadata.subslide_end = True
  46. cell.metadata.subslide_start = True
  47. in_fragment = False
  48. elif cell.metadata.slide_type == 'fragment':
  49. cell.metadata.fragment_start = True
  50. if in_fragment:
  51. previous_cell.metadata.fragment_end = True
  52. else:
  53. in_fragment = True
  54. # The last cell will always be the end of a slide
  55. nb.cells[-1].metadata.fragment_end = in_fragment
  56. nb.cells[-1].metadata.subslide_end = True
  57. nb.cells[-1].metadata.slide_end = True
  58. return nb
  59. class SlidesExporter(HTMLExporter):
  60. """Exports HTML slides with reveal.js"""
  61. export_from_notebook = "Reveal.js slides"
  62. reveal_url_prefix = Unicode(
  63. help="""The URL prefix for reveal.js (version 3.x).
  64. This defaults to the reveal CDN, but can be any url pointing to a copy
  65. of reveal.js.
  66. For speaker notes to work, this must be a relative path to a local
  67. copy of reveal.js: e.g., "reveal.js".
  68. If a relative path is given, it must be a subdirectory of the
  69. current directory (from which the server is run).
  70. See the usage documentation
  71. (https://nbconvert.readthedocs.io/en/latest/usage.html#reveal-js-html-slideshow)
  72. for more details.
  73. """
  74. ).tag(config=True)
  75. @default('reveal_url_prefix')
  76. def _reveal_url_prefix_default(self):
  77. if 'RevealHelpPreprocessor.url_prefix' in self.config:
  78. warn("Please update RevealHelpPreprocessor.url_prefix to "
  79. "SlidesExporter.reveal_url_prefix in config files.")
  80. return self.config.RevealHelpPreprocessor.url_prefix
  81. return 'https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0'
  82. reveal_theme = Unicode('simple',
  83. help="""
  84. Name of the reveal.js theme to use.
  85. We look for a file with this name under
  86. ``reveal_url_prefix``/css/theme/``reveal_theme``.css.
  87. https://github.com/hakimel/reveal.js/tree/master/css/theme has
  88. list of themes that ship by default with reveal.js.
  89. """
  90. ).tag(config=True)
  91. reveal_transition = Unicode('slide',
  92. help="""
  93. Name of the reveal.js transition to use.
  94. The list of transitions that ships by default with reveal.js are:
  95. none, fade, slide, convex, concave and zoom.
  96. """
  97. ).tag(config=True)
  98. reveal_scroll = Bool(False,
  99. help="""
  100. If True, enable scrolling within each slide
  101. """
  102. ).tag(config=True)
  103. require_js_url = Unicode(
  104. "https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js",
  105. help="""
  106. URL to load require.js from.
  107. Defaults to loading from cdnjs.
  108. """
  109. ).tag(config=True)
  110. jquery_url = Unicode(
  111. "https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js",
  112. help="""
  113. URL to load jQuery from.
  114. Defaults to loading from cdnjs.
  115. """
  116. ).tag(config=True)
  117. font_awesome_url = Unicode(
  118. "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css",
  119. help="""
  120. URL to load font awesome from.
  121. Defaults to loading from cdnjs.
  122. """
  123. ).tag(config=True)
  124. @default('file_extension')
  125. def _file_extension_default(self):
  126. return '.slides.html'
  127. @default('template_file')
  128. def _template_file_default(self):
  129. return 'slides_reveal.tpl'
  130. output_mimetype = 'text/html'
  131. def from_notebook_node(self, nb, resources=None, **kw):
  132. resources = self._init_resources(resources)
  133. if 'reveal' not in resources:
  134. resources['reveal'] = {}
  135. resources['reveal']['url_prefix'] = self.reveal_url_prefix
  136. resources['reveal']['theme'] = self.reveal_theme
  137. resources['reveal']['transition'] = self.reveal_transition
  138. resources['reveal']['scroll'] = self.reveal_scroll
  139. resources['reveal']['require_js_url'] = self.require_js_url
  140. resources['reveal']['jquery_url'] = self.jquery_url
  141. resources['reveal']['font_awesome_url'] = self.font_awesome_url
  142. nb = prepare(nb)
  143. return super(SlidesExporter, self).from_notebook_node(nb, resources=resources, **kw)