Skip to content

Commit d7c8be8

Browse files
committed
fix: module normalization
1 parent 33ec67d commit d7c8be8

File tree

5 files changed

+34
-42
lines changed

5 files changed

+34
-42
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"@types/react": "^19.0.7",
3232
"@types/react-dom": "^19.0.3",
3333
"bunchee": "^6.3.2",
34-
"codice": "^0.4.4",
34+
"codice": "^0.5.0",
3535
"devjar": "link:./",
3636
"next": "^15.1.5",
3737
"react": "^19.0.0",

pnpm-lock.yaml

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

site/app/page.tsx

+3-26
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import FileTab from '../ui/file-tab'
99
const CDN_HOST = 'https://esm.sh'
1010

1111
const defaultFiles = {
12-
'page.js': `\
12+
'index.js': `\
1313
import { useState } from 'react'
1414
15-
import Text from './mod1'
15+
import Text from './text'
1616
import './styles.css'
1717
1818
export default function App() {
@@ -68,7 +68,7 @@ const defaultFiles = {
6868
}
6969

7070
export default function Page() {
71-
const [activeFile, setActiveFile] = useState('page.js')
71+
const [activeFile, setActiveFile] = useState('index.js')
7272
const [files, setFiles] = useState(defaultFiles)
7373
const [error, setError] = useState(null)
7474

@@ -95,29 +95,6 @@ export default function Page() {
9595
))}
9696

9797
<FileTab files={files} setFiles={setFiles} setActiveFile={setActiveFile} />
98-
{/* <div
99-
role="button"
100-
className="filetab filetab--new"
101-
>
102-
<span
103-
onClick={() => {
104-
105-
}}
106-
>{`+`}</span>
107-
<input
108-
type='input'
109-
onChange={(e) => {
110-
const filename = e.target.value
111-
// const modId = Object.keys(files).length
112-
const newFilename = filename // './mod' + modId
113-
setFiles({
114-
...files,
115-
[newFilename]: `export default function Mod${filename}() {}`,
116-
})
117-
setActiveFile(newFilename)
118-
}}
119-
/>
120-
</div> */}
12198
</div>
12299
<Editor
123100
highlight={highlight}

src/core.ts

+17-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { init, parse } from 'es-module-lexer'
55

66
let esModuleLexerInit
77
const isRelative = s => s.startsWith('./')
8+
const removeExtension = (str: string) => str.replace(/\.[^/.]+$/, '')
89

910
function transformCode(_code, getModuleUrl, externals) {
1011
const code = transform(_code, {
@@ -77,6 +78,7 @@ function replaceImports(source, getModuleUrl, externals) {
7778
return code
7879
}
7980

81+
// createRenderer is going to be stringified and executed in the iframe
8082
function createRenderer(createModule_, getModuleUrl) {
8183
let reactRoot
8284

@@ -132,7 +134,7 @@ function createEsShimOptionsScript() {
132134
return `\
133135
window.esmsInitOptions = {
134136
polyfillEnable: ['css-modules', 'json-modules'],
135-
onerror: error => console.log(error),
137+
onerror: console.error,
136138
}`
137139
}
138140

@@ -240,11 +242,18 @@ function useLiveCode({ getModuleUrl }: { getModuleUrl?: (name: string) => string
240242
* '@mod2': '...',
241243
*/
242244
const transformedFiles = Object.keys(files).reduce((res, filename) => {
243-
const key = isRelative(filename) ? ('@' + filename.slice(2)) : filename
245+
// 1. Remove ./
246+
// 2. For non css files, remove extension
247+
// e.g. './styles.css' -> '@styles.css'
248+
// e.g. './foo.js' -> '@foo'
249+
const moduleKey = isRelative(filename) ? ('@' + filename.slice(2)) : filename
250+
244251
if (filename.endsWith('.css')) {
245-
res[key] = files[filename]
252+
res[moduleKey] = files[filename]
246253
} else {
247-
res[key] = transformCode(files[filename], getModuleUrl, overrideExternals)
254+
// JS or TS files
255+
const normalizedModuleKey = removeExtension(moduleKey)
256+
res[normalizedModuleKey] = transformCode(files[filename], getModuleUrl, overrideExternals)
248257
}
249258
return res
250259
}, {})
@@ -259,6 +268,10 @@ function useLiveCode({ getModuleUrl }: { getModuleUrl?: (name: string) => string
259268
// if render is not loaded yet, wait until it's loaded
260269
script.onload = () => {
261270
iframe.contentWindow.__render__(transformedFiles)
271+
.catch((err) => {
272+
setError(err)
273+
})
274+
262275
}
263276
}
264277
}

src/module.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ declare global {
88
}
99
}
1010

11-
// importShim
1211
function importShim(url: string): Promise<any>
1312
}
1413

15-
async function createModule(files, { getModuleUrl }) {
16-
let currentImportMap
17-
let shim
14+
async function createModule(
15+
files: Record<string, string>,
16+
{ getModuleUrl }: { getModuleUrl: (name: string) => string }
17+
): Promise<void> {
18+
let currentImportMap: HTMLScriptElement | undefined
19+
let shim: any
1820

1921
async function setupImportMap() {
2022
if (shim) return shim
@@ -26,7 +28,7 @@ async function createModule(files, { getModuleUrl }) {
2628
await shim
2729
}
2830

29-
function updateImportMap(imports) {
31+
function updateImportMap(imports: Record<string, string>) {
3032
imports['react'] = getModuleUrl('react')
3133
imports['react-dom'] = getModuleUrl('react-dom')
3234
imports['react-dom/client'] = getModuleUrl('react-dom/client')
@@ -57,7 +59,7 @@ async function createModule(files, { getModuleUrl }) {
5759
)
5860

5961
updateImportMap(imports)
60-
return self.importShim('index.js')
62+
return self.importShim('index')
6163
}
6264

6365
export { createModule }

0 commit comments

Comments
 (0)