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

Update CDN URLs, add option for local libs and SRI attributes #962

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
2 changes: 1 addition & 1 deletion docs/source/customizing.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Under the hood, nbconvert uses [Jinja templates](https://jinja2.readthedocs.io/en/latest/intro.html) to specify how the notebooks should be formatted. These templates can be fully customized, allowing you to use nbconvert to create notebooks in different formats with different styles as well."
"Under the hood, nbconvert uses [Jinja templates](http://jinja.pocoo.org/docs/) to specify how the notebooks should be formatted. These templates can be fully customized, allowing you to use nbconvert to create notebooks in different formats with different styles as well."
]
},
{
Expand Down
18 changes: 16 additions & 2 deletions nbconvert/exporters/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import os

from traitlets import default, Unicode
from traitlets import default, Unicode, Bool
from traitlets.config import Config

from nbconvert.filters.highlight import Highlight2HTML
Expand All @@ -26,6 +26,14 @@ class HTMLExporter(TemplateExporter):
anchor_link_text = Unicode(u'¶',
help="The text used as the text for anchor links.").tag(config=True)

use_local_libs = Bool(False,
help="If True, use local folder libs/ instead of fetching resources from CDN"
).tag(config=True)

use_sri_attr = Bool(False,
help="If True, use SRI hashes for sub-resources, i.e. external javascript and CSS"
).tag(config=True)

@default('file_extension')
def _file_extension_default(self):
return '.html'
Expand Down Expand Up @@ -88,11 +96,17 @@ def process_attachments(self, nb, output):
return output

def from_notebook_node(self, nb, resources=None, **kw):
resources = self._init_resources(resources)
if 'reveal' not in resources:
resources['reveal'] = {}
resources['reveal']['use_local_libs'] = self.use_local_libs
resources['reveal']['use_sri_attr'] = self.use_sri_attr

langinfo = nb.metadata.get('language_info', {})
lexer = langinfo.get('pygments_lexer', langinfo.get('name', None))
highlight_code = self.filters.get('highlight_code', Highlight2HTML(pygments_lexer=lexer, parent=self))
self.register_filter('highlight_code', highlight_code)

output, resources = super(HTMLExporter, self).from_notebook_node(nb, resources, **kw)
output, resources = super(HTMLExporter, self).from_notebook_node(nb, resources=resources, **kw)
att_output = self.process_attachments(nb, output)
return att_output, resources
6 changes: 3 additions & 3 deletions nbconvert/exporters/slides.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def _reveal_url_prefix_default(self):
warn("Please update RevealHelpPreprocessor.url_prefix to "
"SlidesExporter.reveal_url_prefix in config files.")
return self.config.RevealHelpPreprocessor.url_prefix
return 'https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.5.0'
return 'https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.7.0'

reveal_theme = Unicode('simple',
help="""
Expand Down Expand Up @@ -130,7 +130,7 @@ def _reveal_url_prefix_default(self):
).tag(config=True)

require_js_url = Unicode(
"https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js",
"https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js",
help="""
URL to load require.js from.

Expand All @@ -139,7 +139,7 @@ def _reveal_url_prefix_default(self):
).tag(config=True)

jquery_url = Unicode(
"https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js",
"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js",
help="""
URL to load jQuery from.

Expand Down
18 changes: 15 additions & 3 deletions nbconvert/templates/html/full.tpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
{%- extends 'basic.tpl' -%}
{% from 'mathjax.tpl' import mathjax %}
{% from 'urls.tpl' import all_urls, all_attr %}

{% if resources['reveal']['use_local_libs'] == true %}
{% set urls = all_urls.local_paths %}
{% else %}
{% set urls = all_urls.default_cdn %}
{% endif %}

{% if resources['reveal']['use_sri_attr'] == true %}
{% set attr = all_attr.sri_attr %}
{% else %}
{% set attr = all_attr.empty_attr %}
{% endif %}

{%- block header -%}
<!DOCTYPE html>
Expand All @@ -11,8 +23,8 @@
{% set nb_title = nb.metadata.get('title', '') or resources['metadata']['name'] %}
<title>{{nb_title}}</title>

<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="{{urls.require_js_url}}" {{attr.require_js_attr}}></script>
<script src="{{urls.jquery_url}}" {{attr.jquery_attr}}></script>

{% block ipywidgets %}
{%- if "widgets" in nb.metadata -%}
Expand Down Expand Up @@ -87,7 +99,7 @@ div#notebook-container{
<link rel="stylesheet" href="custom.css">

<!-- Loading mathjax macro -->
{{ mathjax() }}
{{ mathjax(urls) }}
{%- endblock html_head -%}
</head>
{%- endblock header -%}
Expand Down
4 changes: 2 additions & 2 deletions nbconvert/templates/html/mathjax.tpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{%- macro mathjax(url='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-AMS_HTML') -%}
{%- macro mathjax(urls) -%}
<!-- Load mathjax -->
<script src="{{url}}"></script>
<script src="{{urls.mathjax_url}}" {{urls.mathjax_attr}}></script>
<!-- MathJax configuration -->
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
Expand Down
56 changes: 56 additions & 0 deletions nbconvert/templates/html/urls.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{# default configuration #}
{% set cdn1_base = 'https://cdnjs.cloudflare.com/ajax/libs/' %}
{% set default_cdn = {
'mathjax_url' : cdn1_base ~ 'mathjax/2.7.5/latest.js?config=TeX-AMS_HTML',
'require_js_url' : cdn1_base ~ 'require.js/2.3.6/require.min.js',
'jquery_url' : cdn1_base ~ 'jquery/3.3.1/jquery.min.js',
'reveal_js_url' : cdn1_base ~ 'reveal.js/3.7.0/js/reveal.min.js',
'font_awesome_url' : cdn1_base ~ 'font-awesome/4.7.0/css/font-awesome.css',
} %}

{# alternative external resources - not yet implemented as switch #}
{% set cdn2_base = 'https://cdn.jsdelivr.net/npm/' %}
{% set alternative_cdn = {
'mathjax_url' : cdn2_base ~ '[email protected]/unpacked/MathJax.min.js',
'require_js_url' : 'https://requirejs.org/docs/release/2.3.6/minified/require.js',
'jquery_url' : cdn2_base ~ '[email protected]/dist/jquery.min.js',
'reveal_js_url' : cdn2_base ~ '[email protected]/js/reveal.min.js',
'font_awesome_url' : 'https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css',
} %}

{# set local paths for resources #}
{% set libs_dir = 'libs/' %}
{% set local_paths = {
'mathjax_url' : libs_dir ~ 'mathjax/2.7.5/latest.js?config=TeX-AMS_HTML',
'require_js_url' : libs_dir ~ 'require.min.js',
'jquery_url' : libs_dir ~ 'jquery.min.js',
'reveal_js_url' : libs_dir ~ 'reveal.min.js',
'font_awesome_url' : libs_dir ~ 'font-awesome.css',
} %}

{% set all_urls = {
'default_cdn' : default_cdn ,
'alternative_cdn' : alternative_cdn ,
'local_paths' : local_paths ,
} %}

{% set empty_attr = {
'mathjax_attr' : '',
'require_js_attr' : '',
'jquery_attr' : '',
'reveal_js_attr' : '',
'font_awesome_attr' : '',
} %}

{% set sri_attr = {
'mathjax_attr' : 'integrity="sha256-WUED7NFzpsmHtLO7bswSz4JSfkhE+cD4ncKeOznwFSY= sha384-paYjEtNXu9X/q6SBQB9EivI88vKEc/TiZWUaaH5j2Hi4vAOnVYmcahbzUELr3LHw sha512-BlZeGCIONWMdv9uCBB3I3hpY94r8I2e4DdNxyl4OOHYg0Y/LwwWDC4ioJr9vRaLNHwQG0oHiFdmqt7UaTCAZ0A==" crossorigin="anonymous"',
'require_js_attr' : 'integrity="sha256-1fEPhSsRKlFKGfK3eO710tEweHh1fwokU5wFGDHO+vg= sha384-38qS6ZDmuc4fn68ICZ1CTMDv4+Yrqtpijvp5fwMNdbumNGNJ7JVJHgWr2X+nJfqM sha512-c3Nl8+7g4LMSTdrm621y7kf9v3SDPnhxLNhcjFJbKECVnmZHTdo+IRO05sNLTH/D3vA6u1X32ehoLC7WFVdheg==" crossorigin="anonymous"',
'jquery_attr' : 'integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8= sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT sha512-+NqPlbbtM1QqiK8ZAo4Yrj2c4lNQoGv8P79DPtKzj++l5jnN39rHA/xsqn8zE9l0uSoxaCdrOgFs6yjyfbBxSg==" crossorigin="anonymous"',
'reveal_js_attr' : 'integrity="sha256-Xr6ZH+/kc7hDVReZLO5khBknteLqu5oen/xnSraXrVk= sha384-YSZJq04Xw1k1QeTgkujYtdAjgN/sspQx01Qx4JPksOst7V7juBOa/XBwsIK+mJ7c sha512-47qp+bUV262nwngjB+lBR1txpTKevoQKlz3d1+0uvu6Zly3Q+Y+tR19xDDk4NnutJ9vu6uojPXQS4S3sOB06qw==" crossorigin="anonymous"',
'font_awesome_attr' : 'integrity="sha256-NuCn4IvuZXdBaFKJOAcsU2Q3ZpwbdFisd5dux4jkQ5w= sha384-FckWOBo7yuyMS7In0aXZ0aoVvnInlnFMwCv77x9sZpFgOonQgnBj1uLwenWVtsEj sha512-5A8nwdMOWrSz20fDsjczgUidUBR8liPYU+WymTZP1lmY9G6Oc7HlZv156XqnsgNUzTyMefFTcsFH/tnJE/+xBg==" crossorigin="anonymous"',
} %}

{% set all_attr = {
'empty_attr' : empty_attr,
'sri_attr' : sri_attr,
} %}