refactor(live-codeblock): migrate theme to TS (#6583)

* refactor(live-codeblock): migrate theme to TS

* Don't make it visible
This commit is contained in:
Joshua Chen 2022-02-02 17:48:06 +08:00 committed by GitHub
parent 58de17b51e
commit 250d9c8cf5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 98 additions and 20 deletions

View file

@ -3,12 +3,16 @@
"version": "2.0.0-beta.15", "version": "2.0.0-beta.15",
"description": "Docusaurus live code block component.", "description": "Docusaurus live code block component.",
"main": "lib/index.js", "main": "lib/index.js",
"types": "src/theme-live-codeblock.d.ts",
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
}, },
"scripts": { "scripts": {
"build": "tsc && node copyUntypedFiles.mjs", "build": "yarn build:server && yarn build:client && yarn build:copy && yarn build:format",
"watch": "node copyUntypedFiles.mjs && tsc --watch" "build:server": "tsc --project tsconfig.server.json",
"build:client": "tsc --project tsconfig.client.json",
"build:copy": "node copyUntypedFiles.mjs",
"build:format": "prettier --config ../../.prettierrc --write \"lib/**/*.js\""
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View file

@ -7,9 +7,9 @@
import path from 'path'; import path from 'path';
import {readDefaultCodeTranslationMessages} from '@docusaurus/theme-translations'; import {readDefaultCodeTranslationMessages} from '@docusaurus/theme-translations';
import type {DocusaurusContext, Plugin} from '@docusaurus/types'; import type {LoadContext, Plugin} from '@docusaurus/types';
export default function theme(context: DocusaurusContext): Plugin { export default function themeLiveCodeblock(context: LoadContext): Plugin {
const { const {
i18n: {currentLocale}, i18n: {currentLocale},
} = context; } = context;
@ -18,7 +18,10 @@ export default function theme(context: DocusaurusContext): Plugin {
name: 'docusaurus-theme-live-codeblock', name: 'docusaurus-theme-live-codeblock',
getThemePath() { getThemePath() {
return path.resolve(__dirname, './theme'); return path.resolve(__dirname, '../lib/theme');
},
getTypeScriptThemePath() {
return path.resolve(__dirname, '../src/theme');
}, },
getDefaultCodeTranslationMessages() { getDefaultCodeTranslationMessages() {

View file

@ -0,0 +1,32 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
declare module '@docusaurus/theme-live-codeblock' {
export type ThemeConfig = {
liveCodeBlock: {
playgroundPosition: 'top' | 'bottom';
};
};
}
declare module '@theme/Playground' {
import type {LiveProviderProps} from 'react-live';
export interface Props extends LiveProviderProps {
children: string;
}
export default function Playground(props: LiveProviderProps): JSX.Element;
}
declare module '@theme/ReactLiveScope' {
interface Scope {
[key: string]: unknown;
}
const ReactLiveScope: Scope;
export default ReactLiveScope;
}

View file

@ -8,11 +8,12 @@
import React from 'react'; import React from 'react';
import Playground from '@theme/Playground'; import Playground from '@theme/Playground';
import ReactLiveScope from '@theme/ReactLiveScope'; import ReactLiveScope from '@theme/ReactLiveScope';
import CodeBlock from '@theme-init/CodeBlock'; import CodeBlock, {type Props} from '@theme-init/CodeBlock';
const withLiveEditor = (Component) => { const withLiveEditor = (Component: typeof CodeBlock) => {
function WrappedComponent(props) { function WrappedComponent(props: Props) {
if (props.live) { if (props.live) {
// @ts-expect-error: we have deliberately widened the type of language prop
return <Playground scope={ReactLiveScope} {...props} />; return <Playground scope={ReactLiveScope} {...props} />;
} }

View file

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import * as React from 'react'; import React from 'react';
import {LiveProvider, LiveEditor, LiveError, LivePreview} from 'react-live'; import {LiveProvider, LiveEditor, LiveError, LivePreview} from 'react-live';
import clsx from 'clsx'; import clsx from 'clsx';
import Translate from '@docusaurus/Translate'; import Translate from '@docusaurus/Translate';
@ -14,8 +14,10 @@ import BrowserOnly from '@docusaurus/BrowserOnly';
import {usePrismTheme} from '@docusaurus/theme-common'; import {usePrismTheme} from '@docusaurus/theme-common';
import styles from './styles.module.css'; import styles from './styles.module.css';
import useIsBrowser from '@docusaurus/useIsBrowser'; import useIsBrowser from '@docusaurus/useIsBrowser';
import type {Props} from '@theme/Playground';
import type {ThemeConfig} from '@docusaurus/theme-live-codeblock';
function Header({children}) { function Header({children}: {children: React.ReactNode}) {
return <div className={clsx(styles.playgroundHeader)}>{children}</div>; return <div className={clsx(styles.playgroundHeader)}>{children}</div>;
} }
@ -55,7 +57,7 @@ function ThemedLiveEditor() {
<LiveEditor <LiveEditor
// We force remount the editor on hydration, // We force remount the editor on hydration,
// otherwise dark prism theme is not applied // otherwise dark prism theme is not applied
key={isBrowser} key={String(isBrowser)}
className={styles.playgroundEditor} className={styles.playgroundEditor}
/> />
); );
@ -76,18 +78,22 @@ function EditorWithHeader() {
); );
} }
export default function Playground({children, transformCode, ...props}) { export default function Playground({
children,
transformCode,
...props
}: Props): JSX.Element {
const { const {
siteConfig: { siteConfig: {themeConfig},
themeConfig: {
liveCodeBlock: {playgroundPosition},
},
},
} = useDocusaurusContext(); } = useDocusaurusContext();
const {
liveCodeBlock: {playgroundPosition},
} = themeConfig as ThemeConfig;
const prismTheme = usePrismTheme(); const prismTheme = usePrismTheme();
return ( return (
<div className={styles.playgroundContainer}> <div className={styles.playgroundContainer}>
{/* @ts-expect-error: type incompatibility with refs */}
<LiveProvider <LiveProvider
code={children.replace(/\n$/, '')} code={children.replace(/\n$/, '')}
transformCode={transformCode || ((code) => `${code};`)} transformCode={transformCode || ((code) => `${code};`)}

View file

@ -0,0 +1,18 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/// <reference types="@docusaurus/theme-classic" />
declare module '@theme-init/CodeBlock' {
import type CodeBlock, {Props as BaseProps} from '@theme/CodeBlock';
export interface Props extends BaseProps {
live?: boolean;
}
const CodeBlockComp: typeof CodeBlock;
export default CodeBlockComp;
}

View file

@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "esnext",
"jsx": "react-native"
},
"include": ["src/theme/", "src/*.d.ts", "src/custom-buble.ts"]
}

View file

@ -0,0 +1,5 @@
{
"extends": "./tsconfig.json",
"include": ["src/*.ts"],
"exclude": ["src/custom-buble.ts"]
}

View file

@ -18,10 +18,11 @@
}, },
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"build": "yarn build:server && yarn build:browser && yarn build:copy", "build": "yarn build:server && yarn build:client && yarn build:copy && yarn build:format",
"build:server": "tsc --project tsconfig.server.json", "build:server": "tsc --project tsconfig.server.json",
"build:browser": "tsc --project tsconfig.browser.json", "build:client": "tsc --project tsconfig.client.json",
"build:copy": "node copyUntypedFiles.mjs" "build:copy": "node copyUntypedFiles.mjs",
"build:format": "prettier --config ../../.prettierrc --write \"lib/**/*.js\""
}, },
"dependencies": { "dependencies": {
"@docsearch/react": "^3.0.0-alpha.39", "@docsearch/react": "^3.0.0-alpha.39",