Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add createRequire and remove imports #65

Merged
merged 1 commit into from
Jan 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 33 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ Run your React code on the go [https://react-runner.vercel.app](https://react-ru
- Function component
- Class component, **with class fields support**
- Composing components with `render` or `export default`
- Support `Typescript`
- Server Side Rendering
- Support `Typescript`
- Support `import` statement via `createRequire` utility

Hacker News [in react-runner](https://react-runner.vercel.app/#hacker-news) vs [in real world](https://react-runner.vercel.app/examples/hacker-news), with the same code

Expand All @@ -27,31 +28,49 @@ npm install --save react-runner

- **code** `string`, _required_ the code to be ran
- **scope** `object` globals that could be used in `code`
- **imports** `object` imports that could be used in `code`

### Predefined scope

```js
{
React,
jsxPragma: React.createElement, // useful if you are using Emotion with `css` prop
jsxFragmentPragma: React.Fragment,
}
```

## Usage

```jsx
import { useRunner } from 'react-runner'

const { element, error } = useRunner({ code, scope, imports })
const { element, error } = useRunner({ code, scope })
```

or use `Runner` as a component directly and handle error with `onRendered`

```jsx
import { Runner } from 'react-runner'

const element = (
<Runner
code={code}
scope={scope}
imports={imports}
onRendered={handleRendered}
/>
)
const element = <Runner code={code} scope={scope} onRendered={handleRendered} />
```

### `import` statement

```js
// you can define your own version of `createRequire`
import { createRequire } from 'react-runner'
import * as YourPkg from 'your-pkg'

const scope = {
require: createRquire({
'your-pkg': YourPkg,
}),
}
```

then in your code you can use `import Foo, { Bar } from 'your-pkg'`

## Browser support

```
Expand All @@ -70,7 +89,7 @@ I love it, but I love arrow functions for event handlers instead of bind them ma
and I don't want to change my code to be compliant with restrictions, so I created this project,
use [Sucrase](https://github.com/alangpierce/sucrase) instead of [Bublé](https://github.com/bublejs/buble) to transpile the code.

If you are using `react-live` in your project and want a smooth transition, `react-live-runner` is there for you which provide the identical way to play with:
If you are using `react-live` in your project and want a smooth transition, `react-live-runner` is there for you which provide the identical way to play with, and `react-live-runner` re-exports `react-runner` so you can use everything in `react-runner` by importing `react-live-runner`

```jsx
import {
Expand All @@ -81,7 +100,7 @@ import {
} from 'react-live-runner'

...
<LiveProvider code={code} scope={scope} imports={imports}>
<LiveProvider code={code} scope={scope}>
<LiveEditor />
<LivePreview />
<LiveError />
Expand All @@ -97,7 +116,6 @@ import { useLiveRunner, CodeEditor } from 'react-live-runner'
const { element, error, code, onChange } = useLiveRunner({
initialCode,
scope,
imports,
transformCode,
})

Expand All @@ -117,7 +135,7 @@ import { useState, useEffect } from 'react'
import { useRunner } from 'react-runner'

const [code, onChange] = useState(initialCode)
const { element, error } = useRunner({ code, scope, imports })
const { element, error } = useRunner({ code, scope })

useEffect(() => {
onChange(initialCode)
Expand Down
48 changes: 33 additions & 15 deletions packages/react-live-runner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ Run your React code on the go [https://react-runner.vercel.app](https://react-ru
- Function component
- Class component, **with class fields support**
- Composing components with `render` or `export default`
- Support `Typescript`
- Server Side Rendering
- Support `Typescript`
- Support `import` statement via `createRequire` utility

Hacker News [in react-runner](https://react-runner.vercel.app/#hacker-news) vs [in real world](https://react-runner.vercel.app/examples/hacker-news), with the same code

Expand All @@ -27,31 +28,49 @@ npm install --save react-runner

- **code** `string`, _required_ the code to be ran
- **scope** `object` globals that could be used in `code`
- **imports** `object` imports that could be used in `code`

### Predefined scope

```js
{
React,
jsxPragma: React.createElement, // useful if you are using Emotion with `css` prop
jsxFragmentPragma: React.Fragment,
}
```

## Usage

```jsx
import { useRunner } from 'react-runner'

const { element, error } = useRunner({ code, scope, imports })
const { element, error } = useRunner({ code, scope })
```

or use `Runner` as a component directly and handle error with `onRendered`

```jsx
import { Runner } from 'react-runner'

const element = (
<Runner
code={code}
scope={scope}
imports={imports}
onRendered={handleRendered}
/>
)
const element = <Runner code={code} scope={scope} onRendered={handleRendered} />
```

### `import` statement

```js
// you can define your own version of `createRequire`
import { createRequire } from 'react-runner'
import * as YourPkg from 'your-pkg'

const scope = {
require: createRquire({
'your-pkg': YourPkg,
}),
}
```

then in your code you can use `import Foo, { Bar } from 'your-pkg'`

## Browser support

```
Expand All @@ -70,7 +89,7 @@ I love it, but I love arrow functions for event handlers instead of bind them ma
and I don't want to change my code to be compliant with restrictions, so I created this project,
use [Sucrase](https://github.com/alangpierce/sucrase) instead of [Bublé](https://github.com/bublejs/buble) to transpile the code.

If you are using `react-live` in your project and want a smooth transition, `react-live-runner` is there for you which provide the identical way to play with:
If you are using `react-live` in your project and want a smooth transition, `react-live-runner` is there for you which provide the identical way to play with, and `react-live-runner` re-exports `react-runner` so you can use everything in `react-runner` by importing `react-live-runner`

```jsx
import {
Expand All @@ -81,7 +100,7 @@ import {
} from 'react-live-runner'

...
<LiveProvider code={code} scope={scope} imports={imports}>
<LiveProvider code={code} scope={scope}>
<LiveEditor />
<LivePreview />
<LiveError />
Expand All @@ -97,7 +116,6 @@ import { useLiveRunner, CodeEditor } from 'react-live-runner'
const { element, error, code, onChange } = useLiveRunner({
initialCode,
scope,
imports,
transformCode,
})

Expand All @@ -117,7 +135,7 @@ import { useState, useEffect } from 'react'
import { useRunner } from 'react-runner'

const [code, onChange] = useState(initialCode)
const { element, error } = useRunner({ code, scope, imports })
const { element, error } = useRunner({ code, scope })

useEffect(() => {
onChange(initialCode)
Expand Down
48 changes: 33 additions & 15 deletions packages/react-runner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ Run your React code on the go [https://react-runner.vercel.app](https://react-ru
- Function component
- Class component, **with class fields support**
- Composing components with `render` or `export default`
- Support `Typescript`
- Server Side Rendering
- Support `Typescript`
- Support `import` statement via `createRequire` utility

Hacker News [in react-runner](https://react-runner.vercel.app/#hacker-news) vs [in real world](https://react-runner.vercel.app/examples/hacker-news), with the same code

Expand All @@ -27,31 +28,49 @@ npm install --save react-runner

- **code** `string`, _required_ the code to be ran
- **scope** `object` globals that could be used in `code`
- **imports** `object` imports that could be used in `code`

### Predefined scope

```js
{
React,
jsxPragma: React.createElement, // useful if you are using Emotion with `css` prop
jsxFragmentPragma: React.Fragment,
}
```

## Usage

```jsx
import { useRunner } from 'react-runner'

const { element, error } = useRunner({ code, scope, imports })
const { element, error } = useRunner({ code, scope })
```

or use `Runner` as a component directly and handle error with `onRendered`

```jsx
import { Runner } from 'react-runner'

const element = (
<Runner
code={code}
scope={scope}
imports={imports}
onRendered={handleRendered}
/>
)
const element = <Runner code={code} scope={scope} onRendered={handleRendered} />
```

### `import` statement

```js
// you can define your own version of `createRequire`
import { createRequire } from 'react-runner'
import * as YourPkg from 'your-pkg'

const scope = {
require: createRquire({
'your-pkg': YourPkg,
}),
}
```

then in your code you can use `import Foo, { Bar } from 'your-pkg'`

## Browser support

```
Expand All @@ -70,7 +89,7 @@ I love it, but I love arrow functions for event handlers instead of bind them ma
and I don't want to change my code to be compliant with restrictions, so I created this project,
use [Sucrase](https://github.com/alangpierce/sucrase) instead of [Bublé](https://github.com/bublejs/buble) to transpile the code.

If you are using `react-live` in your project and want a smooth transition, `react-live-runner` is there for you which provide the identical way to play with:
If you are using `react-live` in your project and want a smooth transition, `react-live-runner` is there for you which provide the identical way to play with, and `react-live-runner` re-exports `react-runner` so you can use everything in `react-runner` by importing `react-live-runner`

```jsx
import {
Expand All @@ -81,7 +100,7 @@ import {
} from 'react-live-runner'

...
<LiveProvider code={code} scope={scope} imports={imports}>
<LiveProvider code={code} scope={scope}>
<LiveEditor />
<LivePreview />
<LiveError />
Expand All @@ -97,7 +116,6 @@ import { useLiveRunner, CodeEditor } from 'react-live-runner'
const { element, error, code, onChange } = useLiveRunner({
initialCode,
scope,
imports,
transformCode,
})

Expand All @@ -117,7 +135,7 @@ import { useState, useEffect } from 'react'
import { useRunner } from 'react-runner'

const [code, onChange] = useState(initialCode)
const { element, error } = useRunner({ code, scope, imports })
const { element, error } = useRunner({ code, scope })

useEffect(() => {
onChange(initialCode)
Expand Down
6 changes: 3 additions & 3 deletions packages/react-runner/src/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { create } from 'react-test-renderer'

import { generateElement } from '../utils'
import { generateElement, createRequire } from '../utils'

test('empty code', () => {
const element = generateElement({ code: `` })
Expand Down Expand Up @@ -227,7 +227,7 @@ test('imports', () => {
const element = generateElement({
code: `import Foo from 'foo'
render(<Foo />)`,
imports: { foo: () => 'hello' },
scope: { require: createRequire({ foo: () => 'hello' }) },
})

expect(element).toMatchInlineSnapshot(`<foo />`)
Expand All @@ -239,7 +239,7 @@ test('invalid imports', () => {
generateElement({
code: `import Foo from 'foo'
render(<Foo />)`,
imports: { bar: () => 'hello' },
scope: { require: createRequire({ bar: () => 'hello' }) },
})
).toThrowErrorMatchingInlineSnapshot(`"Module not found: 'foo'"`)
})
4 changes: 2 additions & 2 deletions packages/react-runner/src/transform.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { transform as _transform } from 'sucrase'

export const transform = (code: string, hasImports?: boolean) => {
export const transform = (code: string, transformImports?: boolean) => {
return _transform(code, {
transforms: hasImports
transforms: transformImports
? ['jsx', 'typescript', 'imports']
: ['jsx', 'typescript'],
production: true,
Expand Down
2 changes: 0 additions & 2 deletions packages/react-runner/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@ export type RunnerOptions = {
code: string
/** globals that could be used in code */
scope?: Scope
/** imports that could be used in code */
imports?: Scope
}
5 changes: 0 additions & 5 deletions packages/react-runner/src/useRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,17 @@ export type UseRunnerReturn = {
export const useRunner = ({
code,
scope,
imports,
disableCache,
}: UseRunnerProps): UseRunnerReturn => {
const isMountRef = useRef(true)
const elementRef = useRef<ReactElement | null>(null)
const scopeRef = useRef(scope)
scopeRef.current = scope
const importsRef = useRef(imports)
importsRef.current = imports

const [state, setState] = useState<UseRunnerReturn>(() => {
const element = createElement(Runner, {
code,
scope: scopeRef.current,
imports: importsRef.current,
onRendered: (error) => {
if (error) {
setState({
Expand All @@ -54,7 +50,6 @@ export const useRunner = ({
const element = createElement(Runner, {
code,
scope: scopeRef.current,
imports: importsRef.current,
onRendered: (error) => {
if (error) {
setState({
Expand Down
Loading