devjar 0.2.0 → 0.2.1
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/README.md +8 -3
- package/lib/index.d.ts +13 -0
- package/lib/index.mjs +28 -15
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -17,6 +17,8 @@ import { useLiveCode } from 'devjar'
|
|
|
17
17
|
|
|
18
18
|
function Playground() {
|
|
19
19
|
const { ref, error, load } = useLiveCode({
|
|
20
|
+
// The CDN url of each imported module path in your code
|
|
21
|
+
// e.g. `import React from 'react'` will load react from skypack.dev/react
|
|
20
22
|
getModulePath(modPath) {
|
|
21
23
|
return `https://cdn.skypack.dev/${modPath}`
|
|
22
24
|
}
|
|
@@ -30,15 +32,18 @@ function Playground() {
|
|
|
30
32
|
// load code files and execute them as live code
|
|
31
33
|
function run() {
|
|
32
34
|
load({
|
|
33
|
-
|
|
34
|
-
'
|
|
35
|
+
// `index.js` is the entry of every project
|
|
36
|
+
'index.js': `export default function App() { return 'hello world' }`,
|
|
37
|
+
|
|
38
|
+
// other relative modules can be used in the live coding
|
|
39
|
+
'./mod': `export default function Mod() { return 'mod' }`,
|
|
35
40
|
})
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
// Attach the ref to an iframe element for runtime of code execution
|
|
39
44
|
return (
|
|
40
45
|
<div>
|
|
41
|
-
<button onClick={run}>run</
|
|
46
|
+
<button onClick={run}>run</button>
|
|
42
47
|
<iframe ref={ref} />
|
|
43
48
|
</div>
|
|
44
49
|
)
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
type LiveCodeHandles = {
|
|
4
|
+
load(files: Record<string, string>): void
|
|
5
|
+
ref: React.Ref
|
|
6
|
+
error?: unknown
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type Options = {
|
|
10
|
+
getModulePath(modulePath: string): string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function useLiveCode(options: Options): LiveCodeHandles
|
package/lib/index.mjs
CHANGED
|
@@ -16,10 +16,11 @@ function transformCode(_code, getModulePath, externals) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
function replaceImports(_code, getModulePath, externals) {
|
|
19
|
-
const [imports] = parse(_code)
|
|
20
19
|
let code = ''
|
|
21
20
|
let lastIndex = 0
|
|
22
|
-
|
|
21
|
+
let hasReactImports = false
|
|
22
|
+
const [imports] = parse(_code)
|
|
23
|
+
imports.forEach(({ s, e, ss, se, n }) => {
|
|
23
24
|
code += _code.slice(lastIndex, ss)
|
|
24
25
|
code += _code.substring(ss, s)
|
|
25
26
|
code += isRelative(n)
|
|
@@ -27,22 +28,34 @@ function replaceImports(_code, getModulePath, externals) {
|
|
|
27
28
|
: externals.has(n) ? n : getModulePath(n)
|
|
28
29
|
code += _code.substring(e, se)
|
|
29
30
|
lastIndex = se
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
if (n === 'react') {
|
|
34
|
+
const statement = _code.slice(ss, se)
|
|
35
|
+
if (statement.includes('React')) {
|
|
36
|
+
hasReactImports = true
|
|
37
|
+
}
|
|
38
|
+
}
|
|
30
39
|
})
|
|
31
40
|
code += _code.substring(lastIndex)
|
|
41
|
+
|
|
42
|
+
if (!hasReactImports) {
|
|
43
|
+
code = `import React from 'react';\n${code}`
|
|
44
|
+
}
|
|
32
45
|
return code
|
|
33
46
|
}
|
|
34
47
|
|
|
35
|
-
function createRenderer(
|
|
48
|
+
function createRenderer(createModule_, getModulePath) {
|
|
36
49
|
let reactRoot
|
|
37
50
|
|
|
38
51
|
async function render(files) {
|
|
39
|
-
const mod = await
|
|
40
|
-
const
|
|
41
|
-
const
|
|
52
|
+
const mod = await createModule_(files, { getModulePath })
|
|
53
|
+
const React_ = await self.importShim('react')
|
|
54
|
+
const ReactDOM_ = await self.importShim('react-dom')
|
|
42
55
|
|
|
43
|
-
const _jsx =
|
|
56
|
+
const _jsx = React_.createElement
|
|
44
57
|
const root = document.getElementById('root')
|
|
45
|
-
class ErrorBoundary extends
|
|
58
|
+
class ErrorBoundary extends React_.Component {
|
|
46
59
|
state = {
|
|
47
60
|
error: null,
|
|
48
61
|
}
|
|
@@ -57,16 +70,16 @@ function createRenderer(_React0, _ReactDOM0, _createModule, _getModulePath) {
|
|
|
57
70
|
}
|
|
58
71
|
}
|
|
59
72
|
|
|
60
|
-
const isReact18 = !!
|
|
73
|
+
const isReact18 = !!ReactDOM_.createRoot
|
|
61
74
|
if (isReact18 && !reactRoot) {
|
|
62
|
-
reactRoot =
|
|
75
|
+
reactRoot = ReactDOM_.createRoot(root)
|
|
63
76
|
}
|
|
64
77
|
const Component = mod.default
|
|
65
78
|
const element = _jsx(ErrorBoundary, null, _jsx(Component))
|
|
66
79
|
if (isReact18) {
|
|
67
80
|
reactRoot.render(element)
|
|
68
81
|
} else {
|
|
69
|
-
|
|
82
|
+
ReactDOM_.render(element, root)
|
|
70
83
|
}
|
|
71
84
|
}
|
|
72
85
|
|
|
@@ -76,11 +89,11 @@ function createRenderer(_React0, _ReactDOM0, _createModule, _getModulePath) {
|
|
|
76
89
|
function createMainScript({ getModulePath }) {
|
|
77
90
|
const code = (
|
|
78
91
|
`'use strict';
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
const
|
|
92
|
+
const _createModule = ${createModule.toString()};
|
|
93
|
+
const _createRenderer = ${createRenderer.toString()};
|
|
94
|
+
const _getModulePath = ${getModulePath.toString()};
|
|
82
95
|
|
|
83
|
-
globalThis.__render__ =
|
|
96
|
+
globalThis.__render__ = _createRenderer(_createModule, _getModulePath);
|
|
84
97
|
`)
|
|
85
98
|
return code
|
|
86
99
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devjar",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./lib/index.mjs",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"lib"
|
|
12
12
|
],
|
|
13
|
+
"types": "./lib/index.d.ts",
|
|
13
14
|
"scripts": {
|
|
14
15
|
"build": "next build ./docs",
|
|
15
16
|
"start": "next start ./docs",
|