Skip to content

Commit

Permalink
feat(v2): add typescript support for live code blocks (#2824)
Browse files Browse the repository at this point in the history
  • Loading branch information
9oelM committed Jan 2, 2021
1 parent 869e118 commit e08d15b
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 4 deletions.
1 change: 1 addition & 0 deletions packages/docusaurus-theme-live-codeblock/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
"license": "MIT",
"dependencies": {
"@babel/standalone": "^7.12.12",
"@docusaurus/core": "2.0.0-alpha.70",
"@philpl/buble": "^0.19.7",
"clsx": "^1.1.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,55 @@ import clsx from 'clsx';

import styles from './styles.module.css';

function Playground({children, theme, transformCode, ...props}) {
const typescriptExtensions = ['ts', 'tsx'];
const transformJs = (code) => `${code};`;

function Playground({children, theme, className, scope}) {
const [tsTranspileError, setTsTranspileError] = React.useState(null);
const transformTs = React.useCallback((code) => {
try {
// eslint-disable-next-line global-require
const {code: transformed} = require('@babel/standalone').transform(code, {
filename: 'transformedCode.ts',
presets: [
'react',
[
'typescript',
{
isTSX: true,
allExtensions: true,
},
],
],
});
setTsTranspileError(null);

return transformed;
} catch (e) {
setTsTranspileError(e.message);
}

return '() => null;';
}, []);

const isTypescriptCode = React.useMemo(
() =>
typescriptExtensions.some((extension) => className.endsWith(extension)),
[className],
);

const transformCode = React.useMemo(() => {
return isTypescriptCode ? transformTs : transformJs;
}, [isTypescriptCode, transformTs]);

return (
<LiveProvider
scope={scope}
code={children.replace(/\n$/, '')}
transformCode={transformCode || ((code) => `${code};`)}
transformCode={transformCode}
theme={theme}
{...props}>
language={isTypescriptCode ? 'typescript' : 'javascript'}
className={className}>
<div
className={clsx(
styles.playgroundHeader,
Expand All @@ -35,7 +77,7 @@ function Playground({children, theme, transformCode, ...props}) {
</div>
<div className={styles.playgroundPreview}>
<LivePreview />
<LiveError />
{tsTranspileError ? <pre>{tsTranspileError}</pre> : <LiveError />}
</div>
</LiveProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,31 @@ function Clock(props) {
}
```

Typescript is also supported. Simply replace `jsx live` with `tsx live`, then you are good to go.

```tsx live
() => {
const [date, setDate] = useState<Readonly<Date>>(new Date());
useEffect(() => {
var timerID: number = setInterval(() => tick(), 1000);
return function cleanup() {
clearInterval(timerID);
};
}, []);
function tick(): void {
setDate(new Date());
}
return (
<div>
<h2>It is {date.toLocaleTimeString()}.</h2>
</div>
);
}
```

:::caution react-live and imports

It is not possible to import components directly from the react-live code editor, you have to define available imports upfront.
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,11 @@
dependencies:
regenerator-runtime "^0.13.4"

"@babel/standalone@^7.12.12":
version "7.12.12"
resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.12.12.tgz#f858ab1c76d9c4c23fe0783a0330ad37755f0176"
integrity sha512-sHuNDN9NvPHsDAmxPD3RpsIeqCoFSW+ySa6+3teInrYe9y0Gn5swLQ2ZE7Zk6L8eBBESZM2ob1l98qWauQfDMA==

"@babel/template@^7.10.4", "@babel/template@^7.7.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278"
Expand Down

0 comments on commit e08d15b

Please sign in to comment.