devjar 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/core.mjs CHANGED
@@ -15,33 +15,68 @@ function transformCode(_code, getModuleUrl, externals) {
15
15
  return replaceImports(code, getModuleUrl, externals)
16
16
  }
17
17
 
18
- function replaceImports(_code, getModuleUrl, externals) {
18
+ function replaceImports(source, getModuleUrl, externals) {
19
19
  let code = ''
20
20
  let lastIndex = 0
21
21
  let hasReactImports = false
22
- const [imports] = parse(_code)
23
- imports.forEach(({ s, e, ss, se, n }) => {
24
- code += _code.slice(lastIndex, ss)
25
- code += _code.substring(ss, s)
26
- code += isRelative(n)
27
- ? ('@' + n.slice(2))
28
- : externals.has(n) ? n : getModuleUrl(n)
29
- code += _code.substring(e, se)
30
- lastIndex = se
22
+ const [imports] = parse(source)
23
+ const cssImports = []
24
+ let cssImportIndex = 0
25
+
26
+ // start, end, statementStart, statementEnd, assertion, name
27
+ imports.forEach(({ s, e, ss, se, a, n }) => {
28
+ let isCss = false
29
+ code += source.slice(lastIndex, ss) // content from last import to beginning of this line
30
+
31
31
 
32
+ // handle imports
33
+ if (n.endsWith('.css')) {
34
+ isCss = true
35
+ // Map './styles.css' -> '@styles.css', and collect it
36
+ const cssPath = `${'@' + n.slice(2)}`
37
+ cssImports.push(cssPath)
38
+
39
+ } else {
40
+ code += source.substring(ss, s)
41
+ code += isRelative(n)
42
+ ? ('@' + n.slice(2))
43
+ : externals.has(n) ? n : getModuleUrl(n)
44
+ code += source.substring(e, se)
45
+ }
46
+
47
+ lastIndex = se
32
48
 
33
49
  if (n === 'react') {
34
- const statement = _code.slice(ss, se)
50
+ const statement = source.slice(ss, se)
35
51
  if (statement.includes('React')) {
36
52
  hasReactImports = true
37
53
  }
38
54
  }
55
+
56
+ cssImports.forEach(cssPath => {
57
+ code += `\nimport sheet${cssImportIndex} from "${cssPath}" assert { type: "css" };\n`
58
+ cssImportIndex++
59
+ })
39
60
  })
40
- code += _code.substring(lastIndex)
61
+
62
+ if (cssImports.length) {
63
+ code += `const __customStyleSheets = [`
64
+ for (let i = 0; i < cssImports.length; i++) {
65
+ code += `sheet${i}`
66
+ if (i < cssImports.length - 1) {
67
+ code += `, `
68
+ }
69
+ }
70
+ code += `];\n`
71
+ code += `document.adoptedStyleSheets = [...document.adoptedStyleSheets, ...__customStyleSheets];\n`
72
+ }
73
+
74
+ code += source.substring(lastIndex)
41
75
 
42
76
  if (!hasReactImports) {
43
77
  code = `import React from 'react';\n${code}`
44
78
  }
79
+
45
80
  return code
46
81
  }
47
82
 
@@ -101,11 +136,31 @@ globalThis.__render__ = _createRenderer(_createModule, getModuleUrl);
101
136
  return code
102
137
  }
103
138
 
139
+ function createEsShimOptionsScript() {
140
+ return `window.esmsInitOptions = {
141
+ polyfillEnable: ['css-modules', 'json-modules'],
142
+ onerror: error => console.log(error),
143
+ }`
144
+ }
145
+
146
+ function useScript() {
147
+ return useRef(typeof window !== 'undefined' ? document.createElement('script') : null)
148
+ }
149
+
150
+ function setScript(scriptRef, scriptContent, { type } = {}) {
151
+ const script = scriptRef.current
152
+ if (type) script.type = type
153
+
154
+ script.src = `data:text/javascript;utf-8,${encodeURIComponent(scriptContent)}`
155
+ return script
156
+ }
157
+
104
158
  function useLiveCode({ getModuleUrl }) {
105
159
  const iframeRef = useRef()
106
160
  const [error, setError] = useState()
107
161
  const rerender = useState({})[1]
108
- const scriptRef = useRef(typeof window !== 'undefined' ? document.createElement('script') : null)
162
+ const appScriptRef = useScript()
163
+ const esShimOptionsScript = useScript()
109
164
  const uid = useId()
110
165
 
111
166
  // Let getModuleUrl executed on parent window side since it might involve
@@ -127,27 +182,31 @@ function useLiveCode({ getModuleUrl }) {
127
182
 
128
183
  useEffect(() => {
129
184
  const iframe = iframeRef.current
130
- const doc = iframe && iframe.contentDocument
131
-
132
- if (iframe) {
133
- const doc = iframe.contentDocument
134
- const div = document.createElement('div')
135
- const script = scriptRef.current
136
- const scriptContent = createMainScript({ uid })
185
+ if (!iframe || !iframe.contentDocument) return
186
+
187
+ const doc = iframe.contentDocument
188
+ const div = document.createElement('div')
189
+ div.id = 'root'
190
+
191
+ const appScriptContent = createMainScript({ uid })
192
+ const scriptOptionsContent = createEsShimOptionsScript()
193
+
194
+ const esmShimOptionsScript = setScript(esShimOptionsScript, scriptOptionsContent)
195
+ const appScript = setScript(appScriptRef, appScriptContent, { type: 'module' })
196
+ // const script = scriptRef.current
197
+ // script.type = 'module'
198
+ // script.id = 'main'
199
+ // script.src = `data:text/javascript;utf-8,${encodeURIComponent(scriptContent)}`
137
200
 
138
- div.id = 'root'
139
- script.type = 'module'
140
- script.id = 'main'
141
- script.src = `data:text/javascript;utf-8,${encodeURIComponent(scriptContent)}`
142
-
143
- doc.body.appendChild(div)
144
- doc.body.appendChild(script)
145
- }
201
+ doc.body.appendChild(div)
202
+ doc.body.appendChild(esmShimOptionsScript)
203
+ doc.body.appendChild(appScript)
204
+
146
205
  return () => {
147
- if (iframe) {
148
- doc.body.removeChild(doc.getElementById('root'))
149
- doc.body.removeChild(doc.getElementById('main'))
150
- }
206
+ if (!iframe || !iframe.contentDocument) return
207
+ doc.body.removeChild(div)
208
+ doc.body.removeChild(esmShimOptionsScript)
209
+ doc.body.removeChild(appScript)
151
210
  }
152
211
  }, [])
153
212
 
@@ -158,6 +217,7 @@ function useLiveCode({ getModuleUrl }) {
158
217
  }
159
218
 
160
219
  if (files) {
220
+ // { 'react', 'react-dom' }
161
221
  const overrideExternals =
162
222
  new Set(Object.keys(files).filter(name => !isRelative(name) && name !== 'index.js'))
163
223
 
@@ -166,14 +226,25 @@ function useLiveCode({ getModuleUrl }) {
166
226
  overrideExternals.add('react-dom')
167
227
 
168
228
  try {
229
+ /**
230
+ * transformedFiles
231
+ * {
232
+ * 'index.js': '...',
233
+ * '@mod1': '...',
234
+ * '@mod2': '...',
235
+ */
169
236
  const transformedFiles = Object.keys(files).reduce((res, filename) => {
170
237
  const key = isRelative(filename) ? ('@' + filename.slice(2)) : filename
171
- res[key] = transformCode(files[filename], getModuleUrl, overrideExternals)
238
+ if (filename.endsWith('.css')) {
239
+ res[key] = files[filename]
240
+ } else {
241
+ res[key] = transformCode(files[filename], getModuleUrl, overrideExternals)
242
+ }
172
243
  return res
173
244
  }, {})
174
245
 
175
246
  const iframe = iframeRef.current
176
- const script = scriptRef.current
247
+ const script = appScriptRef.current
177
248
  if (iframe) {
178
249
  const render = iframe.contentWindow.__render__
179
250
  if (render) {
@@ -187,6 +258,7 @@ function useLiveCode({ getModuleUrl }) {
187
258
  }
188
259
  setError()
189
260
  } catch (e) {
261
+ console.error(e)
190
262
  setError(e)
191
263
  }
192
264
  }
package/lib/module.mjs CHANGED
@@ -27,15 +27,17 @@ async function createModule(files, { getModuleUrl }) {
27
27
  }
28
28
 
29
29
 
30
- function createInlinedModule(code) {
30
+ function createInlinedModule(code, type) {
31
+ if (type === 'css') return `data:text/css;utf-8,${encodeURIComponent(code)}`
32
+
31
33
  return `data:text/javascript;utf-8,${encodeURIComponent(code)}`
32
34
  }
33
35
 
34
36
  await setupImportMap()
35
37
  const imports = Object.fromEntries(
36
- Object.entries(files).map(([key, code]) => [
37
- key,
38
- createInlinedModule(code),
38
+ Object.entries(files).map(([fileName, code]) => [
39
+ fileName,
40
+ createInlinedModule(code, fileName.endsWith('.css') ? 'css' : 'js'),
39
41
  ])
40
42
  )
41
43
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devjar",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./lib/index.mjs",
@@ -12,9 +12,9 @@
12
12
  ],
13
13
  "types": "./lib/index.d.ts",
14
14
  "scripts": {
15
- "build": "next build ./docs",
16
- "start": "next start ./docs",
17
- "dev": "next dev ./docs"
15
+ "build:site": "next build ./site",
16
+ "start": "next start ./site",
17
+ "dev": "next dev ./site"
18
18
  },
19
19
  "peerDependencies": {
20
20
  "react": "^18.2.0"
@@ -28,7 +28,7 @@
28
28
  "codice": "latest",
29
29
  "devjar": "link:./",
30
30
  "lodash-es": "^4.17.21",
31
- "next": "^13.1.6",
31
+ "next": "^13.2.0",
32
32
  "react": "^18.2.0",
33
33
  "react-dom": "^18.2.0",
34
34
  "sugar-high": "^0.4.5"