Skip to content

Commit

Permalink
refactor: modify iframe.
Browse files Browse the repository at this point in the history
  • Loading branch information
jaywcjlove committed Dec 7, 2023
1 parent 9433d6b commit 1257c74
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 78 deletions.
2 changes: 2 additions & 0 deletions .kktrc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export default (conf: Configuration, env: 'development' | 'production', options:
VERSION: JSON.stringify(pkg.version),
}),
);
conf.module!.exprContextCritical = false;
conf.ignoreWarnings = [{ module: /node_modules[\\/]parse5[\\/]/ }];
if (env === 'production') {
conf.optimization = {
...conf.optimization,
Expand Down
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "1.0.15",
"description": "Online Code Editor for Rapid Web Development.",
"homepage": "https://uiwjs.github.io/react-run-web/",
"funding": "https://jaywcjlove.github.io/#/sponsor",
"main": "cjs/index.js",
"module": "esm/index.js",
"scripts": {
Expand All @@ -14,8 +15,8 @@
"bundle": "ncc build src/index.tsx --target web --filename run-web",
"bundle:min": "ncc build src/index.tsx --target web --filename run-web --minify",
"prettier": "prettier --write \"**/*.{js,jsx,tsx,ts,less,md,json}\"",
"test": "kkt test --env=jsdom --app-src=./website",
"test:coverage": "kkt test --env=jsdom --coverage --app-src=./website"
"test": "tsbb test",
"test:coverage": "tsbb test --coverage --bail"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -59,19 +60,18 @@
"@types/react": "^18.0.34",
"@types/react-dom": "^18.0.11",
"@types/react-test-renderer": "^18.0.0",
"@wcj/dark-mode": "^1.0.15",
"@uiw/react-github-corners": "^1.5.15",
"@uiw/react-markdown-preview": "^4.1.10",
"@uiw/react-split": "^5.8.10",
"@uiw/react-textarea-code-editor": "^3.0.0",
"@wcj/dark-mode": "^1.0.15",
"husky": "^8.0.3",
"kkt": "^7.4.9",
"lint-staged": "^13.2.1",
"prettier": "^2.8.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.10.0",
"react-test-renderer": "^18.2.0",
"tsbb": "^4.1.5"
},
"eslintConfig": {
Expand All @@ -91,5 +91,8 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"dependencies": {
"@uiw/react-iframe": "^1.0.2"
}
}
67 changes: 34 additions & 33 deletions src/__test__/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,43 @@
/* eslint-disable jest/no-conditional-expect */
import TestRenderer from 'react-test-renderer';
import { screen, render, waitFor } from '@testing-library/react';
import RunWeb from '../';

it('Should output a RunWeb', async () => {
const component = TestRenderer.create(<RunWeb />);
let tree = component.toJSON();
if (tree && !Array.isArray(tree)) {
expect(tree.type).toEqual('iframe');
expect(tree.props.title).toEqual('Demo Title');
expect(tree.props.width).toEqual('100%');
expect(tree.props.height).toEqual('100%');
expect(tree.props.style).toEqual({ border: 0 });
expect(tree.props.srcDoc).toBeUndefined();
}
global.URL.createObjectURL = jest.fn((url) => {
return '';
});

it('renders <RunWeb /> test case', async () => {
const { debug } = render(<RunWeb data-testid="iframe" />);
await waitFor(() => {
const iframe = screen.getByTestId('iframe');
expect(iframe).toHaveProperty('srcdoc', '<!DOCTYPE html><html><head></head><body></body></html>');
expect(iframe).toHaveProperty('style.border', '0px');
expect(iframe).toHaveProperty('title', 'Demo Title');
expect(iframe).toHaveProperty('width', '100%');
expect(iframe).toHaveProperty('height', '100%');
});
});

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

it('RunWeb Props css="..."', async () => {
const component = TestRenderer.create(<RunWeb css="body { color:red; }" />);
let tree = component.toJSON();
if (tree && !Array.isArray(tree)) {
expect(tree.type).toEqual('iframe');
expect(tree.props.title).toEqual('Demo Title');
expect(tree.props.width).toEqual('100%');
expect(tree.props.height).toEqual('100%');
expect(tree.props.style).toEqual({ border: 0 });
expect(tree.props.srcDoc).toBeUndefined();
}
const { debug } = render(<RunWeb data-testid="iframe" css="body { color:red; }" />);
await waitFor(() => {
const iframe = screen.getByTestId('iframe');
expect(iframe).toHaveProperty('srcdoc', '<!DOCTYPE html><html><head></head><body></body></html>');
expect(iframe).toHaveProperty('style.border', '0px');
expect(iframe).toHaveProperty('title', 'Demo Title');
expect(iframe).toHaveProperty('width', '100%');
expect(iframe).toHaveProperty('height', '100%');
});
});
47 changes: 14 additions & 33 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useMemo, useRef, useState, useImperativeHandle } from 'react';
import ReactDOM from 'react-dom';
import React from 'react';
import IFrame from '@uiw/react-iframe';

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

export default React.forwardRef<HTMLIFrameElement, RunWebProps>((props, ref) => {
const { html = '', css, js, title = 'Demo Title', head, onLoad, ...other } = props;
const [isLoaded, setIsLoaded] = useState(false);
const frameRef = useRef<HTMLIFrameElement>(null);

useImperativeHandle(ref, () => frameRef.current as HTMLIFrameElement, [frameRef]);

useMemo(() => {
setIsLoaded(false);
const jsString = js ? `<script type="text/javascript">${js}</script>` : '';
const cssString = css ? `<style>${css}</style>` : '';
const result = `<!DOCTYPE html><html><head>${cssString}</head><body>${html}</body>${jsString}</html>`;
const blob = new Blob([result], { type: 'text/html' });
if (frameRef.current) {
frameRef.current.src = URL.createObjectURL(blob);
}
}, [css, html, js]);

function renderFrameContents() {
if (!frameRef.current || !frameRef.current.contentDocument || !frameRef.current.contentWindow) return null;
return [ReactDOM.createPortal(head, frameRef.current.contentDocument.head)];
}

const { html = '', css, js, title = 'Demo Title', head, ...other } = props;
const jsString = js ? `<script type="text/javascript">${js}</script>` : '';
const cssString = css ? `<style>${css}</style>` : '';
const result = `<!DOCTYPE html><html><head>${cssString}</head><body>${html}</body>${jsString}</html>`;
const blob = new Blob([result], { type: 'text/html' });
const url = URL.createObjectURL(blob);
return (
<iframe
<IFrame
title={title}
head={head}
width="100%"
height="100%"
style={{ border: 0 }}
{...other}
onLoad={(evn) => {
setIsLoaded(true);
onLoad && onLoad(evn);
}}
ref={frameRef}
>
{isLoaded && renderFrameContents()}
</iframe>
ref={ref}
src={url}
mountTarget="#mountHere"
/>
);
});
4 changes: 1 addition & 3 deletions src/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
"include": ["../src"],
"compilerOptions": {
"baseUrl": ".",
"outDir": "../cjs",
"emitDeclarationOnly": true,
"noEmit": false
"outDir": "../cjs"
}
}
3 changes: 1 addition & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
"declaration": true,
"jsx": "react-jsx",
"outDir": "cjs",
"noFallthroughCasesInSwitch": true,
"noEmit": true
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}
4 changes: 1 addition & 3 deletions website/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
"extends": "../tsconfig",
"include": ["../website", "../src"],
"compilerOptions": {
"baseUrl": ".",
"emitDeclarationOnly": true,
"noEmit": false
"baseUrl": "."
}
}

0 comments on commit 1257c74

Please sign in to comment.