Repository: jupyter/nbconvert
Pull request #2063 (2023-10-31 14:11:54)

Support es modules in js includes
Straightforward update, adds a second argument to `include_js` resource to add module type to script tag. Tested on a real example to confirm working, and added a simple test to ensure the right html is created (Though this test does not run in a browser). 


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b85bf5d5..99ec1870 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1355,6 +1355,7 @@ raw template
 {%- endblock in_prompt -%}
     """
 
+
 exporter_attr = AttrExporter()
 output_attr, _ = exporter_attr.from_notebook_node(nb)
 assert "raw template" in output_attr
diff --git a/nbconvert/exporters/html.py b/nbconvert/exporters/html.py
index 97501ffe..c2d14be4 100644
--- a/nbconvert/exporters/html.py
+++ b/nbconvert/exporters/html.py
@@ -304,10 +304,10 @@ class HTMLExporter(TemplateExporter):
             code = """<style type="text/css">\n%s</style>""" % data
             return markupsafe.Markup(code)
 
-        def resources_include_js(name):
-            """Get the resources include JS for a name."""
+        def resources_include_js(name, module=False):
+            """Get the resources include JS for a name. If module=True, import as ES module"""
             env = self.environment
-            code = """<script>\n%s</script>""" % (env.loader.get_source(env, name)[0])
+            code = f"""<script {'type="module"' if module else ""}>\n{env.loader.get_source(env, name)[0]}</script>"""
             return markupsafe.Markup(code)
 
         def resources_include_url(name):
diff --git a/pyproject.toml b/pyproject.toml
index ed910a6a..e656fa14 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -61,7 +61,6 @@ qtpdf = ["nbconvert[qtpng]"]
 webpdf = ["playwright"]
 test = [
     "pytest",
-    "pytest-dependency",
     "ipykernel",
     "ipywidgets>=7",
     "flaky",


Test patch:
diff --git a/tests/exporters/files/esmodule.html.j2 b/tests/exporters/files/esmodule.html.j2
new file mode 100644
index 00000000..b71ce799
--- /dev/null
+++ b/tests/exporters/files/esmodule.html.j2
@@ -0,0 +1,4 @@
+{%- extends 'lab/index.html.j2' -%}
+{%- block html_head_js -%}
+{{ resources.include_js("esmodule.js", True) }}
+{%- endblock html_head_js -%}
diff --git a/tests/exporters/files/esmodule.js b/tests/exporters/files/esmodule.js
new file mode 100644
index 00000000..949bba22
--- /dev/null
+++ b/tests/exporters/files/esmodule.js
@@ -0,0 +1,2 @@
+const blerg = true
+export { blerg };
diff --git a/tests/exporters/test_templateexporter.py b/tests/exporters/test_templateexporter.py
index 06891afe..593cfc70 100644
--- a/tests/exporters/test_templateexporter.py
+++ b/tests/exporters/test_templateexporter.py
@@ -307,6 +307,15 @@ class TestExporter(ExportersTestsBase):
         output, resources = exporter.from_notebook_node(nb)
         assert "UNIQUE" in output
 
+    def test_local_template_file_esmodule_js(self):
+        template_file = os.path.join(self._get_files_path(), "esmodule.html.j2")
+        exporter = HTMLExporter(template_file=template_file, template_name="lab")
+        nb = v4.new_notebook()
+        nb.cells.append(v4.new_code_cell("some_text"))
+        output, resources = exporter.from_notebook_node(nb)
+        print(output[:1000])
+        assert '<script type="module">\nconst blerg = true' in output
+
     def test_raw_template_attr(self):
         """
         Verify that you can assign a in memory template string by overwriting