diff --git a/nbconvert/filters/strings.py b/nbconvert/filters/strings.py index 03f068157..c84de083a 100644 --- a/nbconvert/filters/strings.py +++ b/nbconvert/filters/strings.py @@ -41,8 +41,6 @@ "text_base64", ] -from nbconvert.filters.svg_constants import ALLOWED_SVG_ATTRIBUTES, ALLOWED_SVG_TAGS - def wrap_text(text, width=100): """ @@ -91,11 +89,9 @@ def clean_html(element): kwargs['css_sanitizer'] = css_sanitizer return bleach.clean( element, - tags=[*bleach.ALLOWED_TAGS, *ALLOWED_SVG_TAGS, "div", "pre", "code", "span"], - strip_comments=False, + tags=[*bleach.ALLOWED_TAGS, "div", "pre", "code", "span"], attributes={ **bleach.ALLOWED_ATTRIBUTES, - **{svg_tag: list(ALLOWED_SVG_ATTRIBUTES) for svg_tag in ALLOWED_SVG_TAGS}, "*": ["class", "id"], }, **kwargs, diff --git a/nbconvert/filters/svg_constants.py b/nbconvert/filters/svg_constants.py deleted file mode 100644 index 13029bf97..000000000 --- a/nbconvert/filters/svg_constants.py +++ /dev/null @@ -1,190 +0,0 @@ -"""SVG constants for sanitization.""" -# These are lifted from html5lib's sanitizer module, which is deprecated. -# -# Quoth the migration guide (https://github.com/mozilla/bleach/blob/main/docs/migrating.rst#different-allow-lists): -# -# > If you want to stick to the html5lib sanitizer's allow lists, get them from the sanitizer code. -# > It's probably best to copy them as static lists. - -# TODO: Bleach currently drops attribute namespaces; cleaning SVGs will probably require more elbow grease. -# See https://github.com/mozilla/bleach/issues/362 - -ALLOWED_SVG_TAGS = { - "a", - "animate", - "animateColor", - "animateMotion", - "animateTransform", - "circle", - "clipPath", - "defs", - "desc", - "ellipse", - "font-face", - "font-face-name", - "font-face-src", - "g", - "glyph", - "hkern", - "line", - "linearGradient", - "marker", - "metadata", - "missing-glyph", - "mpath", - "path", - "polygon", - "polyline", - "radialGradient", - "rect", - "set", - "stop", - "svg", - "switch", - "text", - "title", - "tspan", - "use", -} -ALLOWED_SVG_ATTRIBUTES = { - "accent-height", - "accumulate", - "additive", - "alphabetic", - "arabic-form", - "ascent", - "attributeName", - "attributeType", - "baseProfile", - "bbox", - "begin", - "by", - "calcMode", - "cap-height", - "class", - "clip-path", - "color", - "color-rendering", - "content", - "cx", - "cy", - "d", - "descent", - "display", - "dur", - "dx", - "dy", - "end", - "fill", - "fill-opacity", - "fill-rule", - "font-family", - "font-size", - "font-stretch", - "font-style", - "font-variant", - "font-weight", - "from", - "fx", - "fy", - "g1", - "g2", - "glyph-name", - "gradientUnits", - "hanging", - "height", - "horiz-adv-x", - "horiz-origin-x", - "id", - "ideographic", - "k", - "keyPoints", - "keySplines", - "keyTimes", - "lang", - "marker-end", - "marker-mid", - "marker-start", - "markerHeight", - "markerUnits", - "markerWidth", - "mathematical", - "max", - "min", - "name", - "offset", - "opacity", - "orient", - "origin", - "overline-position", - "overline-thickness", - "panose-1", - "path", - "pathLength", - "points", - "preserveAspectRatio", - "r", - "refX", - "refY", - "repeatCount", - "repeatDur", - "requiredExtensions", - "requiredFeatures", - "restart", - "rotate", - "rx", - "ry", - "slope", - "stemh", - "stemv", - "stop-color", - "stop-opacity", - "strikethrough-position", - "strikethrough-thickness", - "stroke", - "stroke-dasharray", - "stroke-dashoffset", - "stroke-linecap", - "stroke-linejoin", - "stroke-miterlimit", - "stroke-opacity", - "stroke-width", - "style", - "systemLanguage", - "target", - "text-anchor", - "to", - "transform", - "type", - "u1", - "u2", - "underline-position", - "underline-thickness", - "unicode", - "unicode-range", - "units-per-em", - "values", - "version", - "viewBox", - "visibility", - "width", - "widths", - "x", - "x-height", - "x1", - "x2", - "xlink:actuate", - "xlink:arcrole", - "xlink:href", - "xlink:role", - "xlink:show", - "xlink:title", - "xlink:type", - "xml:base", - "xml:lang", - "xml:space", - "y", - "y1", - "y2", - "zoomAndPan", -} diff --git a/nbconvert/tests/files/issue1849_svg.ipynb b/nbconvert/tests/files/issue1849_svg.ipynb deleted file mode 100644 index 3cbac9d88..000000000 --- a/nbconvert/tests/files/issue1849_svg.ipynb +++ /dev/null @@ -1,500 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "bec574e4-517a-4d87-b4db-f2368491afdc", - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "import matplotlib_inline" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "fbf233aa-84a5-48b4-bb8c-e05bd2e55391", - "metadata": {}, - "outputs": [], - "source": [ - "matplotlib_inline.backend_inline.set_matplotlib_formats('svg')" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "62406ac3-51eb-4810-8b7b-e031ff9abd77", - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " 2022-08-23T17:20:50.390281\n", - " image/svg+xml\n", - " \n", - " \n", - " Matplotlib v3.5.3, https://matplotlib.org/\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "\n" - ], - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot([1, 2]);" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.6" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/nbconvert/tests/test_nbconvertapp.py b/nbconvert/tests/test_nbconvertapp.py index 45deb10fa..ac005164f 100644 --- a/nbconvert/tests/test_nbconvertapp.py +++ b/nbconvert/tests/test_nbconvertapp.py @@ -597,19 +597,6 @@ def test_embedding_images_htmlexporter(self): assert "src='./containerized_deployments.jpeg'" not in text assert text.count("data:image/jpeg;base64") == 3 - def test_embedded_svg_remains(self): - """Check that the HTMLExporter doesn't scrub SVG""" - - with self.create_temp_cwd(["issue1849_svg.ipynb"]): - self.nbconvert("issue1849_svg --log-level 0 --to html") - assert os.path.isfile("issue1849_svg.html") - with open("issue1849_svg.html", encoding="utf8") as f: - text = f.read() - assert '' in text # Must not be escaped - # TODO: these currently break... - # assert '" in text # Must not be stripped - def test_execute_widgets_from_nbconvert(self): """Check jupyter widgets render""" notebook_name = "Unexecuted_widget" diff --git a/share/templates/classic/base.html.j2 b/share/templates/classic/base.html.j2 index 640067bf8..3a0f75f50 100644 --- a/share/templates/classic/base.html.j2 +++ b/share/templates/classic/base.html.j2 @@ -132,7 +132,7 @@ unknown type {{ cell.type }} {%- if output.svg_filename %} {%- else %} -{{ output.data['image/svg+xml'].encode("utf-8") | clean_html }} + {%- endif %} {%- endblock data_svg %} diff --git a/share/templates/lab/base.html.j2 b/share/templates/lab/base.html.j2 index 9f3768484..255b1a662 100644 --- a/share/templates/lab/base.html.j2 +++ b/share/templates/lab/base.html.j2 @@ -164,7 +164,7 @@ unknown type {{ cell.type }} {%- if output.svg_filename %} {%- else %} -{{ output.data['image/svg+xml'].encode("utf-8") | clean_html }} + {%- endif %} {%- endblock data_svg %}