@@ -46,6 +46,7 @@ type RenderInternalOptions =
46
46
47
47
function render ( parseResult : ParseResult , { path, pages, preview, hash} : RenderOptions & RenderInternalOptions ) : string {
48
48
const showSidebar = pages && pages . length > 1 ;
49
+ const imports = getImportMap ( parseResult ) ;
49
50
return `<!DOCTYPE html>
50
51
<meta charset="utf-8">
51
52
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
54
55
} <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css2?family=Source+Serif+Pro:ital,wght@0,400;0,600;0,700;1,400;1,600;1,700&display=swap">
55
56
<link rel="stylesheet" type="text/css" href="/_observablehq/style.css">
56
57
<script type="importmap">
57
- ${ JSON . stringify (
58
- {
59
- imports : Object . fromEntries (
60
- parseResult . imports
61
- . map ( ( { name} ) => name )
62
- . filter ( ( name ) => name . startsWith ( "npm:" ) )
63
- . concat ( [ "npm:d3" , "npm:htl" , "npm:@observablehq/plot" , "npm:@observablehq/inputs" ] ) // recommended libraries
64
- . map ( ( name ) => [ name , `https://cdn.jsdelivr.net/npm/${ name . slice ( 4 ) } /+esm` ] )
65
- . concat ( [ [ "npm:@observablehq/runtime" , "/_observablehq/runtime.js" ] ] )
66
- )
67
- } ,
68
- null ,
69
- 2
70
- ) }
58
+ ${ JSON . stringify ( { imports : Object . fromEntries ( imports ) } , null , 2 ) }
71
59
</script>
72
- <link rel="modulepreload" href="/_observablehq/runtime.js">
60
+ ${ imports . map ( ( [ , href ] ) => ` <link rel="modulepreload" href="${ href } ">` ) . join ( "\n" ) }
73
61
<script type="module">
74
62
75
63
import {${ preview ? "open, " : "" } define} from "/_observablehq/client.js";
@@ -116,6 +104,25 @@ ${parseResult.html}</main>
116
104
` ;
117
105
}
118
106
107
+ function getImportMap ( parseResult : ParseResult ) : [ name : string , href : string ] [ ] {
108
+ const modules = new Set ( [ "npm:@observablehq/runtime" ] ) ;
109
+ if ( parseResult . cells . some ( ( c ) => c . inputs ?. includes ( "d3" ) || c . inputs ?. includes ( "Plot" ) ) ) modules . add ( "npm:d3" ) ;
110
+ if ( parseResult . cells . some ( ( c ) => c . inputs ?. includes ( "Plot" ) ) ) modules . add ( "npm:@observablehq/plot" ) ;
111
+ if ( parseResult . cells . some ( ( c ) => c . inputs ?. includes ( "htl" ) || c . inputs ?. includes ( "Inputs" ) ) ) modules . add ( "npm:htl" ) ;
112
+ if ( parseResult . cells . some ( ( c ) => c . inputs ?. includes ( "Inputs" ) ) ) modules . add ( "npm:@observablehq/inputs" ) ;
113
+ for ( const { name} of parseResult . imports ) {
114
+ if ( name . startsWith ( "npm:" ) ) {
115
+ modules . add ( name ) ;
116
+ }
117
+ }
118
+ return Array . from ( modules , ( name ) => [
119
+ name ,
120
+ name === "npm:@observablehq/runtime"
121
+ ? "/_observablehq/runtime.js" // self-hosted
122
+ : `https://cdn.jsdelivr.net/npm/${ name . slice ( 4 ) } /+esm`
123
+ ] ) ;
124
+ }
125
+
119
126
// TODO Adopt Hypertext Literal?
120
127
function escapeDoubleQuoted ( value ) : string {
121
128
return `${ value } ` . replace ( / [ " & ] / g, entity ) ;
0 commit comments