Skip to content

Commit 1257c74

Browse files
committed
refactor: modify iframe.
1 parent 9433d6b commit 1257c74

File tree

7 files changed

+60
-78
lines changed

7 files changed

+60
-78
lines changed

.kktrc.ts

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export default (conf: Configuration, env: 'development' | 'production', options:
3030
VERSION: JSON.stringify(pkg.version),
3131
}),
3232
);
33+
conf.module!.exprContextCritical = false;
34+
conf.ignoreWarnings = [{ module: /node_modules[\\/]parse5[\\/]/ }];
3335
if (env === 'production') {
3436
conf.optimization = {
3537
...conf.optimization,

package.json

+7-4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"version": "1.0.15",
44
"description": "Online Code Editor for Rapid Web Development.",
55
"homepage": "https://uiwjs.github.io/react-run-web/",
6+
"funding": "https://jaywcjlove.github.io/#/sponsor",
67
"main": "cjs/index.js",
78
"module": "esm/index.js",
89
"scripts": {
@@ -14,8 +15,8 @@
1415
"bundle": "ncc build src/index.tsx --target web --filename run-web",
1516
"bundle:min": "ncc build src/index.tsx --target web --filename run-web --minify",
1617
"prettier": "prettier --write \"**/*.{js,jsx,tsx,ts,less,md,json}\"",
17-
"test": "kkt test --env=jsdom --app-src=./website",
18-
"test:coverage": "kkt test --env=jsdom --coverage --app-src=./website"
18+
"test": "tsbb test",
19+
"test:coverage": "tsbb test --coverage --bail"
1920
},
2021
"repository": {
2122
"type": "git",
@@ -59,19 +60,18 @@
5960
"@types/react": "^18.0.34",
6061
"@types/react-dom": "^18.0.11",
6162
"@types/react-test-renderer": "^18.0.0",
62-
"@wcj/dark-mode": "^1.0.15",
6363
"@uiw/react-github-corners": "^1.5.15",
6464
"@uiw/react-markdown-preview": "^4.1.10",
6565
"@uiw/react-split": "^5.8.10",
6666
"@uiw/react-textarea-code-editor": "^3.0.0",
67+
"@wcj/dark-mode": "^1.0.15",
6768
"husky": "^8.0.3",
6869
"kkt": "^7.4.9",
6970
"lint-staged": "^13.2.1",
7071
"prettier": "^2.8.7",
7172
"react": "^18.2.0",
7273
"react-dom": "^18.2.0",
7374
"react-router-dom": "^6.10.0",
74-
"react-test-renderer": "^18.2.0",
7575
"tsbb": "^4.1.5"
7676
},
7777
"eslintConfig": {
@@ -91,5 +91,8 @@
9191
"last 1 firefox version",
9292
"last 1 safari version"
9393
]
94+
},
95+
"dependencies": {
96+
"@uiw/react-iframe": "^1.0.2"
9497
}
9598
}

src/__test__/index.test.tsx

+34-33
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,43 @@
1-
/* eslint-disable jest/no-conditional-expect */
2-
import TestRenderer from 'react-test-renderer';
1+
import { screen, render, waitFor } from '@testing-library/react';
32
import RunWeb from '../';
43

5-
it('Should output a RunWeb', async () => {
6-
const component = TestRenderer.create(<RunWeb />);
7-
let tree = component.toJSON();
8-
if (tree && !Array.isArray(tree)) {
9-
expect(tree.type).toEqual('iframe');
10-
expect(tree.props.title).toEqual('Demo Title');
11-
expect(tree.props.width).toEqual('100%');
12-
expect(tree.props.height).toEqual('100%');
13-
expect(tree.props.style).toEqual({ border: 0 });
14-
expect(tree.props.srcDoc).toBeUndefined();
15-
}
4+
global.URL.createObjectURL = jest.fn((url) => {
5+
return '';
6+
});
7+
8+
it('renders <RunWeb /> test case', async () => {
9+
const { debug } = render(<RunWeb data-testid="iframe" />);
10+
await waitFor(() => {
11+
const iframe = screen.getByTestId('iframe');
12+
expect(iframe).toHaveProperty('srcdoc', '<!DOCTYPE html><html><head></head><body></body></html>');
13+
expect(iframe).toHaveProperty('style.border', '0px');
14+
expect(iframe).toHaveProperty('title', 'Demo Title');
15+
expect(iframe).toHaveProperty('width', '100%');
16+
expect(iframe).toHaveProperty('height', '100%');
17+
});
1618
});
1719

1820
it('RunWeb Props js="..."', async () => {
19-
const component = TestRenderer.create(<RunWeb js="console.log('hello world!')" />);
20-
let tree = component.toJSON();
21-
if (tree && !Array.isArray(tree)) {
22-
expect(tree.type).toEqual('iframe');
23-
expect(tree.props.title).toEqual('Demo Title');
24-
expect(tree.props.width).toEqual('100%');
25-
expect(tree.props.height).toEqual('100%');
26-
expect(tree.props.style).toEqual({ border: 0 });
27-
expect(tree.props.srcDoc).toBeUndefined();
28-
}
21+
const { debug } = render(<RunWeb data-testid="iframe" title="Example" js="console.log('hello world!')" />);
22+
await waitFor(() => {
23+
// debug()
24+
const iframe = screen.getByTestId('iframe');
25+
expect(iframe).toHaveProperty('srcdoc', '<!DOCTYPE html><html><head></head><body></body></html>');
26+
expect(iframe).toHaveProperty('style.border', '0px');
27+
expect(iframe).toHaveProperty('title', 'Example');
28+
expect(iframe).toHaveProperty('width', '100%');
29+
expect(iframe).toHaveProperty('height', '100%');
30+
});
2931
});
3032

3133
it('RunWeb Props css="..."', async () => {
32-
const component = TestRenderer.create(<RunWeb css="body { color:red; }" />);
33-
let tree = component.toJSON();
34-
if (tree && !Array.isArray(tree)) {
35-
expect(tree.type).toEqual('iframe');
36-
expect(tree.props.title).toEqual('Demo Title');
37-
expect(tree.props.width).toEqual('100%');
38-
expect(tree.props.height).toEqual('100%');
39-
expect(tree.props.style).toEqual({ border: 0 });
40-
expect(tree.props.srcDoc).toBeUndefined();
41-
}
34+
const { debug } = render(<RunWeb data-testid="iframe" css="body { color:red; }" />);
35+
await waitFor(() => {
36+
const iframe = screen.getByTestId('iframe');
37+
expect(iframe).toHaveProperty('srcdoc', '<!DOCTYPE html><html><head></head><body></body></html>');
38+
expect(iframe).toHaveProperty('style.border', '0px');
39+
expect(iframe).toHaveProperty('title', 'Demo Title');
40+
expect(iframe).toHaveProperty('width', '100%');
41+
expect(iframe).toHaveProperty('height', '100%');
42+
});
4243
});

src/index.tsx

+14-33
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import React, { useMemo, useRef, useState, useImperativeHandle } from 'react';
2-
import ReactDOM from 'react-dom';
1+
import React from 'react';
2+
import IFrame from '@uiw/react-iframe';
33

44
export interface RunWebProps extends React.IframeHTMLAttributes<HTMLIFrameElement> {
55
css?: string;
@@ -10,42 +10,23 @@ export interface RunWebProps extends React.IframeHTMLAttributes<HTMLIFrameElemen
1010
}
1111

1212
export default React.forwardRef<HTMLIFrameElement, RunWebProps>((props, ref) => {
13-
const { html = '', css, js, title = 'Demo Title', head, onLoad, ...other } = props;
14-
const [isLoaded, setIsLoaded] = useState(false);
15-
const frameRef = useRef<HTMLIFrameElement>(null);
16-
17-
useImperativeHandle(ref, () => frameRef.current as HTMLIFrameElement, [frameRef]);
18-
19-
useMemo(() => {
20-
setIsLoaded(false);
21-
const jsString = js ? `<script type="text/javascript">${js}</script>` : '';
22-
const cssString = css ? `<style>${css}</style>` : '';
23-
const result = `<!DOCTYPE html><html><head>${cssString}</head><body>${html}</body>${jsString}</html>`;
24-
const blob = new Blob([result], { type: 'text/html' });
25-
if (frameRef.current) {
26-
frameRef.current.src = URL.createObjectURL(blob);
27-
}
28-
}, [css, html, js]);
29-
30-
function renderFrameContents() {
31-
if (!frameRef.current || !frameRef.current.contentDocument || !frameRef.current.contentWindow) return null;
32-
return [ReactDOM.createPortal(head, frameRef.current.contentDocument.head)];
33-
}
34-
13+
const { html = '', css, js, title = 'Demo Title', head, ...other } = props;
14+
const jsString = js ? `<script type="text/javascript">${js}</script>` : '';
15+
const cssString = css ? `<style>${css}</style>` : '';
16+
const result = `<!DOCTYPE html><html><head>${cssString}</head><body>${html}</body>${jsString}</html>`;
17+
const blob = new Blob([result], { type: 'text/html' });
18+
const url = URL.createObjectURL(blob);
3519
return (
36-
<iframe
20+
<IFrame
3721
title={title}
22+
head={head}
3823
width="100%"
3924
height="100%"
4025
style={{ border: 0 }}
4126
{...other}
42-
onLoad={(evn) => {
43-
setIsLoaded(true);
44-
onLoad && onLoad(evn);
45-
}}
46-
ref={frameRef}
47-
>
48-
{isLoaded && renderFrameContents()}
49-
</iframe>
27+
ref={ref}
28+
src={url}
29+
mountTarget="#mountHere"
30+
/>
5031
);
5132
});

src/tsconfig.json

+1-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
"include": ["../src"],
44
"compilerOptions": {
55
"baseUrl": ".",
6-
"outDir": "../cjs",
7-
"emitDeclarationOnly": true,
8-
"noEmit": false
6+
"outDir": "../cjs"
97
}
108
}

tsconfig.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
"declaration": true,
1616
"jsx": "react-jsx",
1717
"outDir": "cjs",
18-
"noFallthroughCasesInSwitch": true,
19-
"noEmit": true
18+
"noFallthroughCasesInSwitch": true
2019
},
2120
"include": ["src"]
2221
}

website/tsconfig.json

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
"extends": "../tsconfig",
33
"include": ["../website", "../src"],
44
"compilerOptions": {
5-
"baseUrl": ".",
6-
"emitDeclarationOnly": true,
7-
"noEmit": false
5+
"baseUrl": "."
86
}
97
}

0 commit comments

Comments
 (0)