1111
1212import base64
1313import hashlib
14+ import re
1415from html .parser import HTMLParser
1516from typing import NamedTuple
1617
@@ -96,6 +97,25 @@ def handle_endtag(self, tag):
9697 self ._capturing = None
9798
9899
100+ def _hoist_importmap (html : str ) -> str :
101+ # Ariadne's inline module script imports bare specifiers like `from 'react'`;
102+ # its <script type="importmap"> maps those names to URLs. Per spec the
103+ # importmap must come before any module reference, but ariadne emits
104+ # <link rel="modulepreload"> tags first, so the map is ignored and imports
105+ # fail. Move the importmap to just before the first modulepreload.
106+ # See https://github.com/mirumee/ariadne/issues/1326
107+ match = re .search (r'<script type="importmap">.*?</script>\n' , html , re .DOTALL )
108+ if not match or '<link rel="modulepreload"' not in html [: match .start ()]:
109+ return html
110+ importmap = match .group (0 )
111+ html = html .replace (importmap , "" , 1 )
112+ return html .replace (
113+ '<link rel="modulepreload"' ,
114+ importmap + ' <link rel="modulepreload"' ,
115+ 1 ,
116+ )
117+
118+
99119def _inject_sri (html : str ) -> str :
100120 # ariadne already emits `crossorigin="anonymous"` on its external loads;
101121 # we add `integrity=` so SRI verification runs. If ariadne ever changes
@@ -119,6 +139,7 @@ def build_explorer() -> GraphiQLExplorerBuild:
119139 import time so the failure is loud.
120140 """
121141 explorer = ExplorerGraphiQL (title = "IRRD GraphQL" , explorer_plugin = True )
142+ explorer .parsed_html = _hoist_importmap (explorer .parsed_html )
122143 explorer .parsed_html = _inject_sri (explorer .parsed_html )
123144
124145 scan = _ExplorerScan ()
0 commit comments