@docusaurus/theme-live-codeblock 2.0.0-beta.2 → 2.0.0-beta.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { type TransformOptions, type TransformOutput } from '@philpl/buble';
8
+ export { features } from '@philpl/buble';
9
+ export declare function transform(source: string, options: TransformOptions): TransformOutput;
@@ -4,17 +4,22 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
-
8
7
  // fork of Buble which removes Buble's large dependency and weighs in
9
8
  // at a smaller size of ~51kB
10
9
  // https://github.com/FormidableLabs/react-live#what-bundle-size-can-i-expect
11
- const {transform, features: bubleFeatures} = require('@philpl/buble');
12
-
10
+ import {transform as bubleTransform} from '@philpl/buble';
13
11
  // This file is designed to mimic what's written in
14
12
  // https://github.com/kitten/buble/blob/mini/src/index.js, with custom transforms options,
15
13
  // so that webpack can consume it correctly.
16
- exports.features = bubleFeatures;
17
-
18
- exports.transform = function customTransform(source, options) {
19
- return transform(source, {...options, transforms: {asyncAwait: false}});
20
- };
14
+ export {features} from '@philpl/buble';
15
+ export function transform(source, options) {
16
+ return bubleTransform(source, {
17
+ ...options,
18
+ transforms: {
19
+ asyncAwait: false,
20
+ classes: false,
21
+ getterSetter: false,
22
+ ...options.transforms,
23
+ },
24
+ });
25
+ }
package/lib/index.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import type { LoadContext, Plugin } from '@docusaurus/types';
8
+ export default function themeLiveCodeblock(context: LoadContext): Plugin;
9
+ export { validateThemeConfig } from './validateThemeConfig';
package/lib/index.js ADDED
@@ -0,0 +1,47 @@
1
+ 'use strict';
2
+ /**
3
+ * Copyright (c) Facebook, Inc. and its affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ Object.defineProperty(exports, '__esModule', {value: true});
9
+ exports.validateThemeConfig = void 0;
10
+ const theme_translations_1 = require('@docusaurus/theme-translations');
11
+ function themeLiveCodeblock(context) {
12
+ const {
13
+ i18n: {currentLocale},
14
+ } = context;
15
+ return {
16
+ name: 'docusaurus-theme-live-codeblock',
17
+ getThemePath() {
18
+ return '../lib/theme';
19
+ },
20
+ getTypeScriptThemePath() {
21
+ return '../src/theme';
22
+ },
23
+ getDefaultCodeTranslationMessages() {
24
+ return (0, theme_translations_1.readDefaultCodeTranslationMessages)({
25
+ locale: currentLocale,
26
+ name: 'theme-live-codeblock',
27
+ });
28
+ },
29
+ configureWebpack() {
30
+ return {
31
+ resolve: {
32
+ alias: {
33
+ buble: require.resolve('./custom-buble.js'),
34
+ },
35
+ },
36
+ };
37
+ },
38
+ };
39
+ }
40
+ exports.default = themeLiveCodeblock;
41
+ var validateThemeConfig_1 = require('./validateThemeConfig');
42
+ Object.defineProperty(exports, 'validateThemeConfig', {
43
+ enumerable: true,
44
+ get: function () {
45
+ return validateThemeConfig_1.validateThemeConfig;
46
+ },
47
+ });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { type Props } from '@theme-init/CodeBlock';
8
+ declare const _default: (props: Props) => JSX.Element;
9
+ export default _default;
@@ -4,22 +4,18 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
-
8
7
  import React from 'react';
9
8
  import Playground from '@theme/Playground';
10
9
  import ReactLiveScope from '@theme/ReactLiveScope';
11
10
  import CodeBlock from '@theme-init/CodeBlock';
12
-
13
11
  const withLiveEditor = (Component) => {
14
- const WrappedComponent = (props) => {
12
+ function WrappedComponent(props) {
15
13
  if (props.live) {
14
+ // @ts-expect-error: we have deliberately widened the type of language prop
16
15
  return <Playground scope={ReactLiveScope} {...props} />;
17
16
  }
18
-
19
17
  return <Component {...props} />;
20
- };
21
-
18
+ }
22
19
  return WrappedComponent;
23
20
  };
24
-
25
21
  export default withLiveEditor(CodeBlock);
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ /// <reference types="react" />
8
+ import type { Props } from '@theme/Playground';
9
+ export default function Playground({ children, transformCode, ...props }: Props): JSX.Element;
@@ -4,19 +4,23 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
-
8
- import * as React from 'react';
7
+ import React from 'react';
9
8
  import {LiveProvider, LiveEditor, LiveError, LivePreview} from 'react-live';
10
9
  import clsx from 'clsx';
11
10
  import Translate from '@docusaurus/Translate';
12
11
  import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
13
- import usePrismTheme from '@theme/hooks/usePrismTheme';
12
+ import BrowserOnly from '@docusaurus/BrowserOnly';
13
+ import {usePrismTheme} from '@docusaurus/theme-common';
14
14
  import styles from './styles.module.css';
15
-
15
+ import useIsBrowser from '@docusaurus/useIsBrowser';
16
16
  function Header({children}) {
17
17
  return <div className={clsx(styles.playgroundHeader)}>{children}</div>;
18
18
  }
19
-
19
+ function LivePreviewLoader() {
20
+ // Is it worth improving/translating?
21
+ // eslint-disable-next-line @docusaurus/no-untranslated-text
22
+ return <div>Loading...</div>;
23
+ }
20
24
  function ResultWithHeader() {
21
25
  return (
22
26
  <>
@@ -27,14 +31,31 @@ function ResultWithHeader() {
27
31
  Result
28
32
  </Translate>
29
33
  </Header>
34
+ {/* https://github.com/facebook/docusaurus/issues/5747 */}
30
35
  <div className={styles.playgroundPreview}>
31
- <LivePreview />
32
- <LiveError />
36
+ <BrowserOnly fallback={<LivePreviewLoader />}>
37
+ {() => (
38
+ <>
39
+ <LivePreview />
40
+ <LiveError />
41
+ </>
42
+ )}
43
+ </BrowserOnly>
33
44
  </div>
34
45
  </>
35
46
  );
36
47
  }
37
-
48
+ function ThemedLiveEditor() {
49
+ const isBrowser = useIsBrowser();
50
+ return (
51
+ <LiveEditor
52
+ // We force remount the editor on hydration,
53
+ // otherwise dark prism theme is not applied
54
+ key={String(isBrowser)}
55
+ className={styles.playgroundEditor}
56
+ />
57
+ );
58
+ }
38
59
  function EditorWithHeader() {
39
60
  return (
40
61
  <>
@@ -45,27 +66,23 @@ function EditorWithHeader() {
45
66
  Live Editor
46
67
  </Translate>
47
68
  </Header>
48
- <LiveEditor className={styles.playgroundEditor} />
69
+ <ThemedLiveEditor />
49
70
  </>
50
71
  );
51
72
  }
52
-
53
73
  export default function Playground({children, transformCode, ...props}) {
54
74
  const {
55
- isClient,
56
- siteConfig: {
57
- themeConfig: {
58
- liveCodeBlock: {playgroundPosition},
59
- },
60
- },
75
+ siteConfig: {themeConfig},
61
76
  } = useDocusaurusContext();
77
+ const {
78
+ liveCodeBlock: {playgroundPosition},
79
+ } = themeConfig;
62
80
  const prismTheme = usePrismTheme();
63
-
64
81
  return (
65
82
  <div className={styles.playgroundContainer}>
83
+ {/* @ts-expect-error: type incompatibility with refs */}
66
84
  <LiveProvider
67
- key={isClient}
68
- code={isClient ? children.replace(/\n$/, '') : ''}
85
+ code={children.replace(/\n$/, '')}
69
86
  transformCode={transformCode || ((code) => `${code};`)}
70
87
  theme={prismTheme}
71
88
  {...props}>
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ .playgroundContainer {
9
+ margin-bottom: var(--ifm-leading);
10
+ border-radius: var(--ifm-global-radius);
11
+ box-shadow: var(--ifm-global-shadow-lw);
12
+ overflow: hidden;
13
+ }
14
+
15
+ .playgroundHeader {
16
+ letter-spacing: 0.08rem;
17
+ padding: 0.75rem;
18
+ text-transform: uppercase;
19
+ font-weight: bold;
20
+ background: var(--ifm-color-emphasis-200);
21
+ color: var(--ifm-color-content);
22
+ font-size: var(--ifm-code-font-size);
23
+ }
24
+
25
+ .playgroundHeader:first-of-type {
26
+ background: var(--ifm-color-emphasis-600);
27
+ color: var(--ifm-color-content-inverse);
28
+ }
29
+
30
+ .playgroundEditor {
31
+ font: var(--ifm-code-font-size) / var(--ifm-pre-line-height)
32
+ var(--ifm-font-family-monospace) !important;
33
+ /* rtl:ignore */
34
+ direction: ltr;
35
+ }
36
+
37
+ .playgroundPreview {
38
+ padding: 1rem;
39
+ background-color: var(--ifm-pre-background);
40
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import React from 'react';
8
+ declare const ReactLiveScope: {
9
+ createFactory<T extends HTMLElement>(type: keyof React.ReactHTML): React.HTMLFactory<T>;
10
+ createFactory(type: keyof React.ReactSVG): React.SVGFactory;
11
+ createFactory<P extends React.DOMAttributes<T_1>, T_1 extends Element>(type: string): React.DOMFactory<P, T_1>;
12
+ createFactory<P_1>(type: React.FunctionComponent<P_1>): React.FunctionComponentFactory<P_1>;
13
+ createFactory<P_2>(type: React.ClassType<P_2, React.ClassicComponent<P_2, any>, React.ClassicComponentClass<P_2>>): React.CFactory<P_2, React.ClassicComponent<P_2, any>>;
14
+ createFactory<P_3, T_2 extends React.Component<P_3, any, any>, C extends React.ComponentClass<P_3, any>>(type: React.ClassType<P_3, T_2, C>): React.CFactory<P_3, T_2>;
15
+ createFactory<P_4>(type: React.ComponentClass<P_4, any>): React.Factory<P_4>;
16
+ createElement(type: "input", props?: (React.InputHTMLAttributes<HTMLInputElement> & React.ClassAttributes<HTMLInputElement>) | null | undefined, ...children: React.ReactNode[]): React.DetailedReactHTMLElement<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>;
17
+ createElement<P_5 extends React.HTMLAttributes<T_3>, T_3 extends HTMLElement>(type: keyof React.ReactHTML, props?: (React.ClassAttributes<T_3> & P_5) | null | undefined, ...children: React.ReactNode[]): React.DetailedReactHTMLElement<P_5, T_3>;
18
+ createElement<P_6 extends React.SVGAttributes<T_4>, T_4 extends SVGElement>(type: keyof React.ReactSVG, props?: (React.ClassAttributes<T_4> & P_6) | null | undefined, ...children: React.ReactNode[]): React.ReactSVGElement;
19
+ createElement<P_7 extends React.DOMAttributes<T_5>, T_5 extends Element>(type: string, props?: (React.ClassAttributes<T_5> & P_7) | null | undefined, ...children: React.ReactNode[]): React.DOMElement<P_7, T_5>;
20
+ createElement<P_8 extends {}>(type: React.FunctionComponent<P_8>, props?: (React.Attributes & P_8) | null | undefined, ...children: React.ReactNode[]): React.FunctionComponentElement<P_8>;
21
+ createElement<P_9 extends {}>(type: React.ClassType<P_9, React.ClassicComponent<P_9, any>, React.ClassicComponentClass<P_9>>, props?: (React.ClassAttributes<React.ClassicComponent<P_9, any>> & P_9) | null | undefined, ...children: React.ReactNode[]): React.CElement<P_9, React.ClassicComponent<P_9, any>>;
22
+ createElement<P_10 extends {}, T_6 extends React.Component<P_10, any, any>, C_1 extends React.ComponentClass<P_10, any>>(type: React.ClassType<P_10, T_6, C_1>, props?: (React.ClassAttributes<T_6> & P_10) | null | undefined, ...children: React.ReactNode[]): React.CElement<P_10, T_6>;
23
+ createElement<P_11 extends {}>(type: string | React.FunctionComponent<P_11> | React.ComponentClass<P_11, any>, props?: (React.Attributes & P_11) | null | undefined, ...children: React.ReactNode[]): React.ReactElement<P_11, string | React.JSXElementConstructor<any>>;
24
+ cloneElement<P_12 extends React.HTMLAttributes<T_7>, T_7 extends HTMLElement>(element: React.DetailedReactHTMLElement<P_12, T_7>, props?: P_12 | undefined, ...children: React.ReactNode[]): React.DetailedReactHTMLElement<P_12, T_7>;
25
+ cloneElement<P_13 extends React.HTMLAttributes<T_8>, T_8 extends HTMLElement>(element: React.ReactHTMLElement<T_8>, props?: P_13 | undefined, ...children: React.ReactNode[]): React.ReactHTMLElement<T_8>;
26
+ cloneElement<P_14 extends React.SVGAttributes<T_9>, T_9 extends SVGElement>(element: React.ReactSVGElement, props?: P_14 | undefined, ...children: React.ReactNode[]): React.ReactSVGElement;
27
+ cloneElement<P_15 extends React.DOMAttributes<T_10>, T_10 extends Element>(element: React.DOMElement<P_15, T_10>, props?: (React.DOMAttributes<T_10> & P_15) | undefined, ...children: React.ReactNode[]): React.DOMElement<P_15, T_10>;
28
+ cloneElement<P_16>(element: React.FunctionComponentElement<P_16>, props?: (Partial<P_16> & React.Attributes) | undefined, ...children: React.ReactNode[]): React.FunctionComponentElement<P_16>;
29
+ cloneElement<P_17, T_11 extends React.Component<P_17, any, any>>(element: React.CElement<P_17, T_11>, props?: (Partial<P_17> & React.ClassAttributes<T_11>) | undefined, ...children: React.ReactNode[]): React.CElement<P_17, T_11>;
30
+ cloneElement<P_18>(element: React.ReactElement<P_18, string | React.JSXElementConstructor<any>>, props?: (Partial<P_18> & React.Attributes) | undefined, ...children: React.ReactNode[]): React.ReactElement<P_18, string | React.JSXElementConstructor<any>>;
31
+ createContext<T_12>(defaultValue: T_12): React.Context<T_12>;
32
+ isValidElement<P_19>(object: {} | null | undefined): object is React.ReactElement<P_19, string | React.JSXElementConstructor<any>>;
33
+ createRef<T_13>(): React.RefObject<T_13>;
34
+ forwardRef<T_14, P_20 = {}>(render: React.ForwardRefRenderFunction<T_14, P_20>): React.ForwardRefExoticComponent<React.PropsWithoutRef<P_20> & React.RefAttributes<T_14>>;
35
+ memo<P_21 extends object>(Component: React.FunctionComponent<P_21>, propsAreEqual?: ((prevProps: Readonly<P_21>, nextProps: Readonly<P_21>) => boolean) | undefined): React.NamedExoticComponent<P_21>;
36
+ memo<T_15 extends React.ComponentType<any>>(Component: T_15, propsAreEqual?: ((prevProps: Readonly<React.ComponentProps<T_15>>, nextProps: Readonly<React.ComponentProps<T_15>>) => boolean) | undefined): React.MemoExoticComponent<T_15>;
37
+ lazy<T_16 extends React.ComponentType<any>>(factory: () => Promise<{
38
+ default: T_16;
39
+ }>): React.LazyExoticComponent<T_16>;
40
+ useContext<T_17>(context: React.Context<T_17>): T_17;
41
+ useState<S>(initialState: S | (() => S)): [S, React.Dispatch<React.SetStateAction<S>>];
42
+ useState<S_1 = undefined>(): [S_1 | undefined, React.Dispatch<React.SetStateAction<S_1 | undefined>>];
43
+ useReducer<R extends React.ReducerWithoutAction<any>, I>(reducer: R, initializerArg: I, initializer: (arg: I) => React.ReducerStateWithoutAction<R>): [React.ReducerStateWithoutAction<R>, React.DispatchWithoutAction];
44
+ useReducer<R_1 extends React.ReducerWithoutAction<any>>(reducer: R_1, initializerArg: React.ReducerStateWithoutAction<R_1>, initializer?: undefined): [React.ReducerStateWithoutAction<R_1>, React.DispatchWithoutAction];
45
+ useReducer<R_2 extends React.Reducer<any, any>, I_1>(reducer: R_2, initializerArg: I_1 & React.ReducerState<R_2>, initializer: (arg: I_1 & React.ReducerState<R_2>) => React.ReducerState<R_2>): [React.ReducerState<R_2>, React.Dispatch<React.ReducerAction<R_2>>];
46
+ useReducer<R_3 extends React.Reducer<any, any>, I_2>(reducer: R_3, initializerArg: I_2, initializer: (arg: I_2) => React.ReducerState<R_3>): [React.ReducerState<R_3>, React.Dispatch<React.ReducerAction<R_3>>];
47
+ useReducer<R_4 extends React.Reducer<any, any>>(reducer: R_4, initialState: React.ReducerState<R_4>, initializer?: undefined): [React.ReducerState<R_4>, React.Dispatch<React.ReducerAction<R_4>>];
48
+ useRef<T_18>(initialValue: T_18): React.MutableRefObject<T_18>;
49
+ useRef<T_19>(initialValue: T_19 | null): React.RefObject<T_19>;
50
+ useRef<T_20 = undefined>(): React.MutableRefObject<T_20 | undefined>;
51
+ useLayoutEffect(effect: React.EffectCallback, deps?: React.DependencyList | undefined): void;
52
+ useEffect(effect: React.EffectCallback, deps?: React.DependencyList | undefined): void;
53
+ useImperativeHandle<T_21, R_5 extends T_21>(ref: React.Ref<T_21> | undefined, init: () => R_5, deps?: React.DependencyList | undefined): void;
54
+ useCallback<T_22 extends Function>(callback: T_22, deps: React.DependencyList): T_22;
55
+ useMemo<T_23>(factory: () => T_23, deps: React.DependencyList | undefined): T_23;
56
+ useDebugValue<T_24>(value: T_24, format?: ((value: T_24) => any) | undefined): void;
57
+ useDeferredValue<T_25>(value: T_25): T_25;
58
+ useTransition(): [boolean, React.TransitionStartFunction];
59
+ startTransition(scope: React.TransitionFunction): void;
60
+ useId(): string;
61
+ useInsertionEffect(effect: React.EffectCallback, deps?: React.DependencyList | undefined): void;
62
+ useSyncExternalStore<Snapshot>(subscribe: (onStoreChange: () => void) => () => void, getSnapshot: () => Snapshot, getServerSnapshot?: (() => Snapshot) | undefined): Snapshot;
63
+ Children: {
64
+ map<T_26, C_2>(children: C_2 | readonly C_2[], fn: (child: C_2, index: number) => T_26): C_2 extends null | undefined ? C_2 : Exclude<T_26, boolean | null | undefined>[];
65
+ forEach<C_3>(children: C_3 | readonly C_3[], fn: (child: C_3, index: number) => void): void;
66
+ count(children: any): number;
67
+ only<C_4>(children: C_4): C_4 extends any[] ? never : C_4;
68
+ toArray(children: React.ReactNode | React.ReactNode[]): (string | number | React.ReactElement<any, string | React.JSXElementConstructor<any>> | React.ReactFragment | React.ReactPortal)[];
69
+ };
70
+ Fragment: React.ExoticComponent<{
71
+ children?: React.ReactNode;
72
+ }>;
73
+ StrictMode: React.ExoticComponent<{
74
+ children?: React.ReactNode;
75
+ }>;
76
+ Suspense: React.ExoticComponent<React.SuspenseProps>;
77
+ version: string;
78
+ Profiler: React.ExoticComponent<React.ProfilerProps>;
79
+ Component: typeof React.Component;
80
+ PureComponent: typeof React.PureComponent;
81
+ React: typeof React;
82
+ };
83
+ export default ReactLiveScope;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import React from 'react';
8
+ // Add react-live imports you need here
9
+ const ReactLiveScope = {
10
+ React,
11
+ ...React,
12
+ };
13
+ export default ReactLiveScope;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { Joi } from '@docusaurus/utils-validation';
8
+ import type { ThemeConfig, ThemeConfigValidationContext } from '@docusaurus/types';
9
+ export declare const DEFAULT_CONFIG: {
10
+ playgroundPosition: string;
11
+ };
12
+ export declare const Schema: Joi.ObjectSchema<any>;
13
+ export declare function validateThemeConfig({ validate, themeConfig, }: ThemeConfigValidationContext<ThemeConfig>): ThemeConfig;
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+ /**
3
+ * Copyright (c) Facebook, Inc. and its affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ Object.defineProperty(exports, '__esModule', {value: true});
9
+ exports.validateThemeConfig = exports.Schema = exports.DEFAULT_CONFIG = void 0;
10
+ const utils_validation_1 = require('@docusaurus/utils-validation');
11
+ exports.DEFAULT_CONFIG = {
12
+ playgroundPosition: 'bottom',
13
+ };
14
+ exports.Schema = utils_validation_1.Joi.object({
15
+ liveCodeBlock: utils_validation_1.Joi.object({
16
+ playgroundPosition: utils_validation_1.Joi.string()
17
+ .equal('top', 'bottom')
18
+ .default(exports.DEFAULT_CONFIG.playgroundPosition),
19
+ })
20
+ .label('themeConfig.liveCodeBlock')
21
+ .default(exports.DEFAULT_CONFIG),
22
+ });
23
+ function validateThemeConfig({validate, themeConfig}) {
24
+ return validate(exports.Schema, themeConfig);
25
+ }
26
+ exports.validateThemeConfig = validateThemeConfig;
package/package.json CHANGED
@@ -1,11 +1,22 @@
1
1
  {
2
2
  "name": "@docusaurus/theme-live-codeblock",
3
- "version": "2.0.0-beta.2",
3
+ "version": "2.0.0-beta.20",
4
4
  "description": "Docusaurus live code block component.",
5
- "main": "src/index.js",
5
+ "main": "lib/index.js",
6
+ "types": "src/theme-live-codeblock.d.ts",
7
+ "sideEffects": [
8
+ "lib/theme/Playground/*"
9
+ ],
6
10
  "publishConfig": {
7
11
  "access": "public"
8
12
  },
13
+ "scripts": {
14
+ "build": "yarn build:server && yarn build:client && yarn build:copy && yarn build:format",
15
+ "build:server": "tsc --project tsconfig.server.json",
16
+ "build:client": "tsc --project tsconfig.client.json",
17
+ "build:copy": "node copyUntypedFiles.mjs",
18
+ "build:format": "prettier --config ../../.prettierrc --write \"lib/**/*.js\""
19
+ },
9
20
  "repository": {
10
21
  "type": "git",
11
22
  "url": "https://github.com/facebook/docusaurus.git",
@@ -13,20 +24,26 @@
13
24
  },
14
25
  "license": "MIT",
15
26
  "dependencies": {
16
- "@docusaurus/core": "2.0.0-beta.2",
17
- "@docusaurus/utils-validation": "2.0.0-beta.2",
27
+ "@docusaurus/core": "2.0.0-beta.20",
28
+ "@docusaurus/theme-common": "2.0.0-beta.20",
29
+ "@docusaurus/theme-translations": "2.0.0-beta.20",
30
+ "@docusaurus/utils-validation": "2.0.0-beta.20",
18
31
  "@philpl/buble": "^0.19.7",
19
32
  "clsx": "^1.1.1",
20
- "parse-numeric-range": "^1.2.0",
21
- "prism-react-renderer": "^1.2.1",
22
- "react-live": "^2.2.3"
33
+ "fs-extra": "^10.1.0",
34
+ "react-live": "2.2.3",
35
+ "tslib": "^2.4.0"
36
+ },
37
+ "devDependencies": {
38
+ "@docusaurus/types": "2.0.0-beta.20",
39
+ "@types/buble": "^0.20.1"
23
40
  },
24
41
  "peerDependencies": {
25
42
  "react": "^16.8.4 || ^17.0.0",
26
43
  "react-dom": "^16.8.4 || ^17.0.0"
27
44
  },
28
45
  "engines": {
29
- "node": ">=12.13.0"
46
+ "node": ">=14"
30
47
  },
31
- "gitHead": "883f07fddffaf1657407c8e202e370cc436e25f7"
48
+ "gitHead": "ed5cdba401a5948e187e927039b142a0decc702d"
32
49
  }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ // fork of Buble which removes Buble's large dependency and weighs in
9
+ // at a smaller size of ~51kB
10
+ // https://github.com/FormidableLabs/react-live#what-bundle-size-can-i-expect
11
+ import {
12
+ transform as bubleTransform,
13
+ type TransformOptions,
14
+ type TransformOutput,
15
+ } from '@philpl/buble';
16
+
17
+ // This file is designed to mimic what's written in
18
+ // https://github.com/kitten/buble/blob/mini/src/index.js, with custom transforms options,
19
+ // so that webpack can consume it correctly.
20
+ export {features} from '@philpl/buble';
21
+
22
+ export function transform(
23
+ source: string,
24
+ options: TransformOptions,
25
+ ): TransformOutput {
26
+ return bubleTransform(source, {
27
+ ...options,
28
+ transforms: {
29
+ asyncAwait: false,
30
+ classes: false,
31
+ getterSetter: false,
32
+ ...options.transforms,
33
+ },
34
+ });
35
+ }
package/src/deps.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ declare module '@philpl/buble' {
9
+ import type {TransformOptions as OriginalTransformOptions} from 'buble';
10
+ // eslint-disable-next-line import/no-extraneous-dependencies, no-restricted-syntax
11
+ export * from 'buble';
12
+ export const features: string[];
13
+ export type TransformOptions = OriginalTransformOptions & {
14
+ transforms?: OriginalTransformOptions['transforms'] & {
15
+ asyncAwait?: boolean;
16
+ getterSetter?: boolean;
17
+ };
18
+ };
19
+ }
package/src/index.ts ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import {readDefaultCodeTranslationMessages} from '@docusaurus/theme-translations';
9
+ import type {LoadContext, Plugin} from '@docusaurus/types';
10
+
11
+ export default function themeLiveCodeblock(context: LoadContext): Plugin {
12
+ const {
13
+ i18n: {currentLocale},
14
+ } = context;
15
+
16
+ return {
17
+ name: 'docusaurus-theme-live-codeblock',
18
+
19
+ getThemePath() {
20
+ return '../lib/theme';
21
+ },
22
+ getTypeScriptThemePath() {
23
+ return '../src/theme';
24
+ },
25
+
26
+ getDefaultCodeTranslationMessages() {
27
+ return readDefaultCodeTranslationMessages({
28
+ locale: currentLocale,
29
+ name: 'theme-live-codeblock',
30
+ });
31
+ },
32
+
33
+ configureWebpack() {
34
+ return {
35
+ resolve: {
36
+ alias: {
37
+ buble: require.resolve('./custom-buble.js'),
38
+ },
39
+ },
40
+ };
41
+ },
42
+ };
43
+ }
44
+
45
+ export {validateThemeConfig} from './validateThemeConfig';
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import React from 'react';
9
+ import Playground from '@theme/Playground';
10
+ import ReactLiveScope from '@theme/ReactLiveScope';
11
+ import CodeBlock, {type Props} from '@theme-init/CodeBlock';
12
+
13
+ const withLiveEditor = (Component: typeof CodeBlock) => {
14
+ function WrappedComponent(props: Props) {
15
+ if (props.live) {
16
+ // @ts-expect-error: we have deliberately widened the type of language prop
17
+ return <Playground scope={ReactLiveScope} {...props} />;
18
+ }
19
+
20
+ return <Component {...props} />;
21
+ }
22
+
23
+ return WrappedComponent;
24
+ };
25
+
26
+ export default withLiveEditor(CodeBlock);
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ import React from 'react';
9
+ import {LiveProvider, LiveEditor, LiveError, LivePreview} from 'react-live';
10
+ import clsx from 'clsx';
11
+ import Translate from '@docusaurus/Translate';
12
+ import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
13
+ import BrowserOnly from '@docusaurus/BrowserOnly';
14
+ import {usePrismTheme} from '@docusaurus/theme-common';
15
+ import styles from './styles.module.css';
16
+ import useIsBrowser from '@docusaurus/useIsBrowser';
17
+ import type {Props} from '@theme/Playground';
18
+ import type {ThemeConfig} from '@docusaurus/theme-live-codeblock';
19
+
20
+ function Header({children}: {children: React.ReactNode}) {
21
+ return <div className={clsx(styles.playgroundHeader)}>{children}</div>;
22
+ }
23
+
24
+ function LivePreviewLoader() {
25
+ // Is it worth improving/translating?
26
+ // eslint-disable-next-line @docusaurus/no-untranslated-text
27
+ return <div>Loading...</div>;
28
+ }
29
+
30
+ function ResultWithHeader() {
31
+ return (
32
+ <>
33
+ <Header>
34
+ <Translate
35
+ id="theme.Playground.result"
36
+ description="The result label of the live codeblocks">
37
+ Result
38
+ </Translate>
39
+ </Header>
40
+ {/* https://github.com/facebook/docusaurus/issues/5747 */}
41
+ <div className={styles.playgroundPreview}>
42
+ <BrowserOnly fallback={<LivePreviewLoader />}>
43
+ {() => (
44
+ <>
45
+ <LivePreview />
46
+ <LiveError />
47
+ </>
48
+ )}
49
+ </BrowserOnly>
50
+ </div>
51
+ </>
52
+ );
53
+ }
54
+
55
+ function ThemedLiveEditor() {
56
+ const isBrowser = useIsBrowser();
57
+ return (
58
+ <LiveEditor
59
+ // We force remount the editor on hydration,
60
+ // otherwise dark prism theme is not applied
61
+ key={String(isBrowser)}
62
+ className={styles.playgroundEditor}
63
+ />
64
+ );
65
+ }
66
+
67
+ function EditorWithHeader() {
68
+ return (
69
+ <>
70
+ <Header>
71
+ <Translate
72
+ id="theme.Playground.liveEditor"
73
+ description="The live editor label of the live codeblocks">
74
+ Live Editor
75
+ </Translate>
76
+ </Header>
77
+ <ThemedLiveEditor />
78
+ </>
79
+ );
80
+ }
81
+
82
+ export default function Playground({
83
+ children,
84
+ transformCode,
85
+ ...props
86
+ }: Props): JSX.Element {
87
+ const {
88
+ siteConfig: {themeConfig},
89
+ } = useDocusaurusContext();
90
+ const {
91
+ liveCodeBlock: {playgroundPosition},
92
+ } = themeConfig as ThemeConfig;
93
+ const prismTheme = usePrismTheme();
94
+
95
+ return (
96
+ <div className={styles.playgroundContainer}>
97
+ {/* @ts-expect-error: type incompatibility with refs */}
98
+ <LiveProvider
99
+ code={children.replace(/\n$/, '')}
100
+ transformCode={transformCode || ((code) => `${code};`)}
101
+ theme={prismTheme}
102
+ {...props}>
103
+ {playgroundPosition === 'top' ? (
104
+ <>
105
+ <ResultWithHeader />
106
+ <EditorWithHeader />
107
+ </>
108
+ ) : (
109
+ <>
110
+ <EditorWithHeader />
111
+ <ResultWithHeader />
112
+ </>
113
+ )}
114
+ </LiveProvider>
115
+ </div>
116
+ );
117
+ }
@@ -7,6 +7,9 @@
7
7
 
8
8
  .playgroundContainer {
9
9
  margin-bottom: var(--ifm-leading);
10
+ border-radius: var(--ifm-global-radius);
11
+ box-shadow: var(--ifm-global-shadow-lw);
12
+ overflow: hidden;
10
13
  }
11
14
 
12
15
  .playgroundHeader {
@@ -22,23 +25,16 @@
22
25
  .playgroundHeader:first-of-type {
23
26
  background: var(--ifm-color-emphasis-600);
24
27
  color: var(--ifm-color-content-inverse);
25
- border-top-left-radius: var(--ifm-global-radius);
26
- border-top-right-radius: var(--ifm-global-radius);
27
28
  }
28
29
 
29
30
  .playgroundEditor {
30
31
  font: var(--ifm-code-font-size) / var(--ifm-pre-line-height)
31
32
  var(--ifm-font-family-monospace) !important;
32
- /*rtl:ignore*/
33
+ /* rtl:ignore */
33
34
  direction: ltr;
34
35
  }
35
36
 
36
37
  .playgroundPreview {
37
- border: 1px solid var(--ifm-color-emphasis-200);
38
38
  padding: 1rem;
39
- }
40
-
41
- .playgroundPreview:last-of-type, .playgroundEditor:last-of-type {
42
- border-bottom-left-radius: var(--ifm-global-radius);
43
- border-bottom-right-radius: var(--ifm-global-radius);
39
+ background-color: var(--ifm-pre-background);
44
40
  }
File without changes
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ declare module '@docusaurus/theme-live-codeblock' {
9
+ export type ThemeConfig = {
10
+ liveCodeBlock: {
11
+ playgroundPosition: 'top' | 'bottom';
12
+ };
13
+ };
14
+ }
15
+
16
+ declare module '@theme/Playground' {
17
+ import type {LiveProviderProps} from 'react-live';
18
+
19
+ export interface Props extends LiveProviderProps {
20
+ children: string;
21
+ }
22
+ export default function Playground(props: LiveProviderProps): JSX.Element;
23
+ }
24
+
25
+ declare module '@theme/ReactLiveScope' {
26
+ type Scope = {
27
+ [key: string]: unknown;
28
+ };
29
+
30
+ const ReactLiveScope: Scope;
31
+ export default ReactLiveScope;
32
+ }
package/src/types.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ /// <reference types="@docusaurus/theme-classic" />
9
+ /// <reference types="@docusaurus/module-type-aliases" />
10
+
11
+ declare module '@theme-init/CodeBlock' {
12
+ import type CodeBlock from '@theme/CodeBlock';
13
+ import type {Props as BaseProps} from '@theme/CodeBlock';
14
+
15
+ export interface Props extends BaseProps {
16
+ live?: boolean;
17
+ }
18
+ const CodeBlockComp: typeof CodeBlock;
19
+ export default CodeBlockComp;
20
+ }
@@ -5,14 +5,17 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- const {Joi} = require('@docusaurus/utils-validation');
8
+ import {Joi} from '@docusaurus/utils-validation';
9
+ import type {
10
+ ThemeConfig,
11
+ ThemeConfigValidationContext,
12
+ } from '@docusaurus/types';
9
13
 
10
- const DEFAULT_CONFIG = {
14
+ export const DEFAULT_CONFIG = {
11
15
  playgroundPosition: 'bottom',
12
16
  };
13
- exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
14
17
 
15
- const Schema = Joi.object({
18
+ export const Schema = Joi.object({
16
19
  liveCodeBlock: Joi.object({
17
20
  playgroundPosition: Joi.string()
18
21
  .equal('top', 'bottom')
@@ -21,8 +24,10 @@ const Schema = Joi.object({
21
24
  .label('themeConfig.liveCodeBlock')
22
25
  .default(DEFAULT_CONFIG),
23
26
  });
24
- exports.Schema = Schema;
25
27
 
26
- exports.validateThemeConfig = function ({validate, themeConfig}) {
28
+ export function validateThemeConfig({
29
+ validate,
30
+ themeConfig,
31
+ }: ThemeConfigValidationContext<ThemeConfig>): ThemeConfig {
27
32
  return validate(Schema, themeConfig);
28
- };
33
+ }
@@ -1,91 +0,0 @@
1
- /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- const {validateThemeConfig, DEFAULT_CONFIG} = require('../validateThemeConfig');
9
-
10
- function testValidateThemeConfig(themeConfig) {
11
- function validate(schema, cfg) {
12
- const {value, error} = schema.validate(cfg, {
13
- convert: false,
14
- });
15
- if (error) {
16
- throw error;
17
- }
18
- return value;
19
- }
20
-
21
- return validateThemeConfig({validate, themeConfig});
22
- }
23
-
24
- describe('validateThemeConfig', () => {
25
- test('undefined config', () => {
26
- const liveCodeBlock = undefined;
27
- expect(testValidateThemeConfig({liveCodeBlock})).toEqual({
28
- liveCodeBlock: {
29
- ...DEFAULT_CONFIG,
30
- },
31
- });
32
- });
33
-
34
- test('unexist config', () => {
35
- expect(testValidateThemeConfig({})).toEqual({
36
- liveCodeBlock: {
37
- ...DEFAULT_CONFIG,
38
- },
39
- });
40
- });
41
-
42
- test('empty config', () => {
43
- const liveCodeBlock = {};
44
- expect(testValidateThemeConfig({liveCodeBlock})).toEqual({
45
- liveCodeBlock: {
46
- ...DEFAULT_CONFIG,
47
- },
48
- });
49
- });
50
-
51
- test('playgroundPosition top', () => {
52
- const liveCodeBlock = {
53
- playgroundPosition: 'top',
54
- };
55
- expect(testValidateThemeConfig({liveCodeBlock})).toEqual({
56
- liveCodeBlock: {
57
- ...DEFAULT_CONFIG,
58
- ...liveCodeBlock,
59
- },
60
- });
61
- });
62
-
63
- test('playgroundPosition bottom', () => {
64
- const liveCodeBlock = {
65
- playgroundPosition: 'bottom',
66
- };
67
- expect(testValidateThemeConfig({liveCodeBlock})).toEqual({
68
- liveCodeBlock: {
69
- ...DEFAULT_CONFIG,
70
- ...liveCodeBlock,
71
- },
72
- });
73
- });
74
-
75
- test('playgroundPosition invalid string', () => {
76
- const liveCodeBlock = {playgroundPosition: 'invalid'};
77
- expect(() =>
78
- testValidateThemeConfig({liveCodeBlock}),
79
- ).toThrowErrorMatchingInlineSnapshot(
80
- `"\\"liveCodeBlock.playgroundPosition\\" must be one of [top, bottom]"`,
81
- );
82
- });
83
- test('playgroundPosition invalid boolean', () => {
84
- const liveCodeBlock = {playgroundPosition: true};
85
- expect(() =>
86
- testValidateThemeConfig({liveCodeBlock}),
87
- ).toThrowErrorMatchingInlineSnapshot(
88
- `"\\"liveCodeBlock.playgroundPosition\\" must be one of [top, bottom]"`,
89
- );
90
- });
91
- });
package/src/index.js DELETED
@@ -1,33 +0,0 @@
1
- /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- const path = require('path');
9
- const {validateThemeConfig} = require('./validateThemeConfig');
10
-
11
- function theme() {
12
- return {
13
- name: 'docusaurus-theme-live-codeblock',
14
-
15
- getThemePath() {
16
- return path.resolve(__dirname, './theme');
17
- },
18
-
19
- configureWebpack() {
20
- return {
21
- resolve: {
22
- alias: {
23
- buble: path.resolve(__dirname, './custom-buble.js'),
24
- },
25
- },
26
- };
27
- },
28
- };
29
- }
30
-
31
- module.exports = theme;
32
-
33
- theme.validateThemeConfig = validateThemeConfig;