@@ -9,12 +9,86 @@ const path = require('path');
99const { transformFileAsync } = require ( '@babel/core' ) ;
1010const pretty = require ( 'pretty' ) ;
1111
12+ // Paths
1213const EXAMPLES = path . resolve ( __dirname , '../..' ) ;
14+ const SPECTACLE_PATH = path . resolve ( __dirname , '../../../packages/spectacle' ) ;
1315const SRC_FILE = path . join ( EXAMPLES , 'js/index.js' ) ;
1416const DEST_FILE = path . join ( EXAMPLES , 'one-page/index.html' ) ;
1517
18+ // Dependencies.
19+ const ESM_SH_VERSION = 'v121' ; // v121, stable, etc.
20+ const {
21+ dependencies,
22+ peerDependencies
23+ } = require ( `${ SPECTACLE_PATH } /package.json` ) ;
24+ const reactPkgPath = require . resolve ( 'react/package.json' , {
25+ paths : [ SPECTACLE_PATH ]
26+ } ) ;
27+ const { version : reactVersion } = require ( reactPkgPath ) ;
28+ const DEPS = `deps=react@${ reactVersion } ` ;
29+
30+ // Toggle dev resources. (Use if debugging load / dependency errors).
31+ const IS_DEV = false ;
32+ const DEV = IS_DEV ? '&dev' : '' ;
33+
34+ // Use local built spectacle? Toggle to `true` for dev-only.
35+ // Note: Due to CORS, you'll need to run `pnpm run --filter ./examples/one-page start` and
36+ // open http://localhost:5000/examples/one-page to work.
37+ const USE_LOCAL = false ;
38+
39+ // ================================================================================================
40+ // Import Map
41+ // ================================================================================================
42+ const importUrl = ( k , v , extra = '' ) => {
43+ // Pin react.
44+ if ( k === 'react' ) {
45+ v = reactVersion ;
46+ }
47+
48+ return `https://esm.sh/${ ESM_SH_VERSION } /${ k } @${ v } ${ extra } ?${ DEPS } ${ DEV } ` ;
49+ } ;
50+
51+ const getImportMap = ( ) => {
52+ // Start with extra imports for one-page alone.
53+ const importMap = {
54+ htm : importUrl ( 'htm' , '^3' ) ,
55+ spectacle : USE_LOCAL
56+ ? '../../packages/spectacle/lib/index.mjs'
57+ : importUrl ( 'spectacle' , '^10' )
58+ } ;
59+
60+ Object . entries ( Object . assign ( { } , dependencies , peerDependencies ) )
61+ . sort ( ( a , b ) => a [ 0 ] . localeCompare ( b [ 0 ] ) )
62+ . forEach ( ( [ k , v ] ) => {
63+ // General
64+ importMap [ k ] = importUrl ( k , v ) ;
65+
66+ // Special case internal deps
67+ if ( k === 'react' ) {
68+ importMap [ `${ k } /jsx-runtime` ] = importUrl ( k , v , '/jsx-runtime' ) ;
69+ }
70+ if ( k === 'react-syntax-highlighter' ) {
71+ importMap [ `${ k } /dist/cjs/styles/prism/vs-dark.js` ] = importUrl (
72+ k ,
73+ v ,
74+ '/dist/esm/styles/prism/vs-dark.js'
75+ ) ;
76+ importMap [ `${ k } /dist/cjs/styles/prism/index.js` ] = importUrl (
77+ k ,
78+ v ,
79+ '/dist/esm/styles/prism/index.js'
80+ ) ;
81+ }
82+ } ) ;
83+
84+ return importMap ;
85+ } ;
86+
87+ // ================================================================================================
88+ // Rewriting
89+ // ================================================================================================
1690const htmImport = `
17- import htm from 'https://unpkg.com/ htm@^3?module ';
91+ import htm from 'htm';
1892const html = htm.bind(React.createElement);
1993`
2094 . replace ( / / gm, '' )
@@ -27,7 +101,7 @@ const spectacleImportReplacer = (match, imports) => {
27101 . map ( ( i ) => ` ${ i . trim ( ) } ` )
28102 . join ( `,\n` ) ;
29103
30- return `const {\n${ imports } \n} = Spectacle ;\n\n${ htmImport } ` ;
104+ return `import {\n${ imports } \n} from 'spectacle' ;\n\n${ htmImport } ` ;
31105} ;
32106
33107const getSrcContent = async ( src ) => {
@@ -40,7 +114,6 @@ const getSrcContent = async (src) => {
40114 // Mutate exports and comments.
41115 code = code
42116 // Mutate exports to our global imports.
43- . replace ( / i m p o r t R e a c t ( | D O M ) f r o m ' r e a c t ( | - d o m ) ' ; [ \n ] * / gm, '' )
44117 . replace ( / i m p o r t { [ ] * ( .* ) } f r o m ' s p e c t a c l e ' ; / , spectacleImportReplacer )
45118 // Hackily fix / undo babel's poor control comment placment.
46119 . replace ( / \/ \/ S P E C T A C L E _ C L I / gm, '\n// SPECTACLE_CLI' )
@@ -84,17 +157,27 @@ const getSrcContent = async (src) => {
84157 return code ;
85158} ;
86159
160+ // ================================================================================================
161+ // Output
162+ // ================================================================================================
87163const writeDestContent = async ( destFile , code ) => {
88164 // Format for indentation in index.html.
89165 const indent = ' ' ;
90- code = `${ indent } ${ code } ` ;
91- code = code . split ( '\n' ) . join ( `\n${ indent } ` ) ;
166+ code = `${ indent } ${ code . split ( '\n' ) . join ( `\n${ indent } ` ) } ` ;
167+
168+ // Import map
169+ let importMap = JSON . stringify ( { imports : getImportMap ( ) } , null , 2 ) ;
170+ importMap = `${ indent } ${ importMap . split ( '\n' ) . join ( `\n${ indent } ` ) } ` ;
92171
93172 // Get destination content.
94173 let destContent = ( await fs . readFile ( destFile ) ) . toString ( ) ;
95174
96175 // Mutate in our updated code.
97176 destContent = destContent
177+ . replace (
178+ / ( < s c r i p t t y p e = " i m p o r t m a p " > \n ) [ \s \S ] * ?( \n [ ] * < \/ s c r i p t > ) / m,
179+ ( match , open , close ) => `${ open } ${ importMap } ${ close } `
180+ )
98181 . replace (
99182 / ( < s c r i p t t y p e = " m o d u l e " > \n ) [ \s \S ] * ?( \n [ ] * < \/ s c r i p t > \n [ ] * < \/ b o d y > \n [ ] * < \/ h t m l > ) / m,
100183 ( match , open , close ) => `${ open } ${ code } ${ close } `
0 commit comments