From 03ba759512c15024163b801a7b25d5fa37048538 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Sat, 31 Dec 2022 16:36:46 +0100 Subject: [PATCH 01/16] Improve type-safety when using `createFileMap` --- beta/src/components/MDX/Sandpack/SandpackRoot.tsx | 2 +- beta/src/components/MDX/Sandpack/createFileMap.ts | 6 +++--- beta/src/components/MDX/Sandpack/index.tsx | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/beta/src/components/MDX/Sandpack/SandpackRoot.tsx b/beta/src/components/MDX/Sandpack/SandpackRoot.tsx index 4b3f41527d9..e21a0067abc 100644 --- a/beta/src/components/MDX/Sandpack/SandpackRoot.tsx +++ b/beta/src/components/MDX/Sandpack/SandpackRoot.tsx @@ -74,7 +74,7 @@ function SandpackRoot(props: SandpackProps) { files['/styles.css'] = { code: [sandboxStyle, files['/styles.css']?.code ?? ''].join('\n\n'), - hidden: !files['/styles.css']?.visible, + hidden: !files['/styles.css']?.hidden, }; return ( diff --git a/beta/src/components/MDX/Sandpack/createFileMap.ts b/beta/src/components/MDX/Sandpack/createFileMap.ts index 89d53cfd2f3..ea6c17252de 100644 --- a/beta/src/components/MDX/Sandpack/createFileMap.ts +++ b/beta/src/components/MDX/Sandpack/createFileMap.ts @@ -4,9 +4,9 @@ import type {SandpackFile} from '@codesandbox/sandpack-react'; -export const createFileMap = (codeSnippets: any) => { - return codeSnippets.reduce( - (result: Record, codeSnippet: React.ReactElement) => { +export const createFileMap = (codeSnippets: React.ReactElement[]) => { + return codeSnippets.reduce>( + (result, codeSnippet) => { if ((codeSnippet.type as any).mdxName !== 'pre') { return result; } diff --git a/beta/src/components/MDX/Sandpack/index.tsx b/beta/src/components/MDX/Sandpack/index.tsx index 3591e058144..eb90099d1bd 100644 --- a/beta/src/components/MDX/Sandpack/index.tsx +++ b/beta/src/components/MDX/Sandpack/index.tsx @@ -46,20 +46,20 @@ const SandpackGlimmer = ({code}: {code: string}) => ( ); export default memo(function SandpackWrapper(props: any): any { - const codeSnippet = createFileMap(Children.toArray(props.children)); + const codeSnippets = Children.toArray(props.children) as React.ReactElement[]; + const files = createFileMap(codeSnippets); // To set the active file in the fallback we have to find the active file first. // If there are no active files we fallback to App.js as default. - let activeCodeSnippet = Object.keys(codeSnippet).filter( + let activeCodeSnippet = Object.keys(files).filter( (fileName) => - codeSnippet[fileName]?.active === true && - codeSnippet[fileName]?.hidden === false + files[fileName]?.active === true && files[fileName]?.hidden === false ); let activeCode; if (!activeCodeSnippet.length) { - activeCode = codeSnippet['/App.js'].code; + activeCode = files['/App.js'].code; } else { - activeCode = codeSnippet[activeCodeSnippet[0]].code; + activeCode = files[activeCodeSnippet[0]].code; } return ( From f0d6705277f7084d70bffd5fd69ca8db9c79d21d Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Sat, 31 Dec 2022 16:44:28 +0100 Subject: [PATCH 02/16] Update beta/src/components/MDX/Sandpack/SandpackRoot.tsx --- beta/src/components/MDX/Sandpack/SandpackRoot.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/components/MDX/Sandpack/SandpackRoot.tsx b/beta/src/components/MDX/Sandpack/SandpackRoot.tsx index e21a0067abc..ea75a50a99b 100644 --- a/beta/src/components/MDX/Sandpack/SandpackRoot.tsx +++ b/beta/src/components/MDX/Sandpack/SandpackRoot.tsx @@ -74,7 +74,7 @@ function SandpackRoot(props: SandpackProps) { files['/styles.css'] = { code: [sandboxStyle, files['/styles.css']?.code ?? ''].join('\n\n'), - hidden: !files['/styles.css']?.hidden, + hidden: files['/styles.css']?.hidden, }; return ( From 13880e90e5c6adbe9c29ae7ce14c3982aa6ba9ee Mon Sep 17 00:00:00 2001 From: eps1lon Date: Fri, 30 Dec 2022 11:13:32 +0100 Subject: [PATCH 03/16] MVP: Support snippets in TypeScript --- .../components/MDX/Sandpack/NavigationBar.tsx | 41 +++++++++++++++++++ .../components/MDX/Sandpack/SandpackRoot.tsx | 17 ++++++-- .../MDX/Sandpack/SnippetLanguage.tsx | 24 +++++++++++ .../components/MDX/Sandpack/createFileMap.ts | 12 ++++++ beta/src/components/MDX/Sandpack/index.tsx | 34 ++++++++++++--- .../content/learn/keeping-components-pure.md | 24 +++++++++++ 6 files changed, 143 insertions(+), 9 deletions(-) create mode 100644 beta/src/components/MDX/Sandpack/SnippetLanguage.tsx diff --git a/beta/src/components/MDX/Sandpack/NavigationBar.tsx b/beta/src/components/MDX/Sandpack/NavigationBar.tsx index 8c884a5d8a7..a984550e5c8 100644 --- a/beta/src/components/MDX/Sandpack/NavigationBar.tsx +++ b/beta/src/components/MDX/Sandpack/NavigationBar.tsx @@ -9,6 +9,7 @@ import { useState, useEffect, Fragment, + useContext, } from 'react'; import cn from 'classnames'; import { @@ -19,8 +20,10 @@ import { import {OpenInCodeSandboxButton} from './OpenInCodeSandboxButton'; import {ResetButton} from './ResetButton'; import {DownloadButton} from './DownloadButton'; +import {SnippetTargetLanguageContext} from './SnippetLanguage'; import {IconChevron} from '../../Icon/IconChevron'; import {Listbox} from '@headlessui/react'; +import classNames from 'classnames'; export function useEvent(fn: any): any { const ref = useRef(null); @@ -39,6 +42,43 @@ const getFileName = (filePath: string): string => { return filePath.slice(lastIndexOfSlash + 1); }; +function SnippetTargetLanguageButton(props: any) { + const {children, snippetTargetLanguage} = props; + const { + setSnippetTargetLanguage, + snippetTargetLanguage: currentSnippetTargetLanguage, + } = useContext(SnippetTargetLanguageContext); + + const isCurrent = currentSnippetTargetLanguage === snippetTargetLanguage; + + return ( + + ); +} + +function SnippetTargetLanguageToggle() { + return ( +
+ + JS + + + + TS + +
+ ); +} + export function NavigationBar({providedFiles}: {providedFiles: Array}) { const {sandpack} = useSandpack(); const containerRef = useRef(null); @@ -179,6 +219,7 @@ export function NavigationBar({providedFiles}: {providedFiles: Array}) {
+ diff --git a/beta/src/components/MDX/Sandpack/SandpackRoot.tsx b/beta/src/components/MDX/Sandpack/SandpackRoot.tsx index ea75a50a99b..87a62e0bc35 100644 --- a/beta/src/components/MDX/Sandpack/SandpackRoot.tsx +++ b/beta/src/components/MDX/Sandpack/SandpackRoot.tsx @@ -9,10 +9,12 @@ import {SandpackLogLevel} from '@codesandbox/sandpack-client'; import {CustomPreset} from './CustomPreset'; import {createFileMap} from './createFileMap'; import {CustomTheme} from './Themes'; +import {SnippetTargetLanguageContext} from './SnippetLanguage'; type SandpackProps = { children: React.ReactNode; autorun?: boolean; + defaultActiveFile: string; showDevTools?: boolean; }; @@ -67,10 +69,18 @@ ul { `.trim(); function SandpackRoot(props: SandpackProps) { - let {children, autorun = true, showDevTools = false} = props; + let { + children, + autorun = true, + defaultActiveFile, + showDevTools = false, + } = props; const [devToolsLoaded, setDevToolsLoaded] = useState(false); const codeSnippets = Children.toArray(children) as React.ReactElement[]; - const files = createFileMap(codeSnippets); + const {snippetTargetLanguage} = React.useContext( + SnippetTargetLanguageContext + ); + const files = createFileMap(codeSnippets, snippetTargetLanguage); files['/styles.css'] = { code: [sandboxStyle, files['/styles.css']?.code ?? ''].join('\n\n'), @@ -80,10 +90,11 @@ function SandpackRoot(props: SandpackProps) { return (
void; +} + +export const SnippetTargetLanguageContext = + createContext({ + snippetTargetLanguage: 'ts', + setSnippetTargetLanguage: () => { + throw new TypeError( + `Could not change snippet language since no was used in this React tree. This is a bug.` + ); + }, + }); + +if (process.env.NODE_ENV !== 'production') { + SnippetTargetLanguageContext.displayName = 'SnippetTargetLanguageContext'; +} diff --git a/beta/src/components/MDX/Sandpack/createFileMap.ts b/beta/src/components/MDX/Sandpack/createFileMap.ts index ea6c17252de..2b579db5656 100644 --- a/beta/src/components/MDX/Sandpack/createFileMap.ts +++ b/beta/src/components/MDX/Sandpack/createFileMap.ts @@ -27,6 +27,8 @@ export const createFileMap = (codeSnippets: React.ReactElement[]) => { } else { if (props.className === 'language-js') { filePath = '/App.js'; + } else if (props.className === 'language-tsx') { + filePath = '/App.tsx'; } else if (props.className === 'language-css') { filePath = '/styles.css'; } else { @@ -40,6 +42,16 @@ export const createFileMap = (codeSnippets: React.ReactElement[]) => { `File ${filePath} was defined multiple times. Each file snippet should have a unique path name` ); } + + if (snippetTargetLanguage === 'js' && /\.(mts|ts|tsx)$/.test(filePath)) { + fileHidden = true; + } else if ( + snippetTargetLanguage === 'ts' && + /\.(mjs|js|jsx)$/.test(filePath) + ) { + fileHidden = true; + } + result[filePath] = { code: (props.children || '') as string, hidden: fileHidden, diff --git a/beta/src/components/MDX/Sandpack/index.tsx b/beta/src/components/MDX/Sandpack/index.tsx index eb90099d1bd..b98fca744c8 100644 --- a/beta/src/components/MDX/Sandpack/index.tsx +++ b/beta/src/components/MDX/Sandpack/index.tsx @@ -2,8 +2,13 @@ * Copyright (c) Facebook, Inc. and its affiliates. */ -import {lazy, memo, Children, Suspense} from 'react'; +import {lazy, memo, Children, Suspense, useState, useMemo} from 'react'; import {createFileMap} from './createFileMap'; +import { + SnippetTargetLanguage, + SnippetTargetLanguageContext, + SnippetTargetLanguageContextValue, +} from './SnippetLanguage'; const SandpackRoot = lazy(() => import('./SandpackRoot')); @@ -46,6 +51,16 @@ const SandpackGlimmer = ({code}: {code: string}) => ( ); export default memo(function SandpackWrapper(props: any): any { + const defaultSnippetTargetLanguage = 'ts'; + const [snippetTargetLanguage, setSnippetTargetLanguage] = + useState(defaultSnippetTargetLanguage); + const contextValue = useMemo((): SnippetTargetLanguageContextValue => { + return { + snippetTargetLanguage, + setSnippetTargetLanguage, + }; + }, [snippetTargetLanguage]); + const codeSnippets = Children.toArray(props.children) as React.ReactElement[]; const files = createFileMap(codeSnippets); @@ -55,16 +70,23 @@ export default memo(function SandpackWrapper(props: any): any { (fileName) => files[fileName]?.active === true && files[fileName]?.hidden === false ); - let activeCode; + let defaultActiveCodeSnippet; if (!activeCodeSnippet.length) { - activeCode = files['/App.js'].code; + if (snippetTargetLanguage === 'ts' && '/App.tsx' in files) { + defaultActiveCodeSnippet = files['/App.tsx']; + } else { + defaultActiveCodeSnippet = files['/App.js']; + } } else { - activeCode = files[activeCodeSnippet[0]].code; + defaultActiveCodeSnippet = files[activeCodeSnippet[0]]; } return ( - }> - + }> + + + ); }); diff --git a/beta/src/content/learn/keeping-components-pure.md b/beta/src/content/learn/keeping-components-pure.md index 60760edc5c0..6072adcfb31 100644 --- a/beta/src/content/learn/keeping-components-pure.md +++ b/beta/src/content/learn/keeping-components-pure.md @@ -73,6 +73,30 @@ export default function App() { } ``` +```ts App.tsx +function Recipe({ drinkers }: { drinkers: number }) { + return ( +
    +
  1. Boil {drinkers} cups of water.
  2. +
  3. Add {drinkers} spoons of tea and {0.5 * drinkers} spoons of spice.
  4. +
  5. Add {0.5 * drinkers} cups of milk to boil and sugar to taste.
  6. +
+ ); +} + +export default function App() { + return ( +
+

Spiced Chai Recipe

+

For two

+ +

For a gathering

+ +
+ ); +} +``` + When you pass `drinkers={2}` to `Recipe`, it will return JSX containing `2 cups of water`. Always. From a70e3f175eeff91052d4289f3192f8d7dc775d49 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Fri, 30 Dec 2022 11:20:45 +0100 Subject: [PATCH 04/16] Switch snippet target language globally --- beta/src/components/Layout/MarkdownPage.tsx | 24 ++++++++++++++++- .../components/MDX/Sandpack/createFileMap.ts | 6 ++++- beta/src/components/MDX/Sandpack/index.tsx | 26 +++++++++---------- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/beta/src/components/Layout/MarkdownPage.tsx b/beta/src/components/Layout/MarkdownPage.tsx index c44298c05b4..6546c0074fa 100644 --- a/beta/src/components/Layout/MarkdownPage.tsx +++ b/beta/src/components/Layout/MarkdownPage.tsx @@ -9,6 +9,11 @@ import {Seo} from 'components/Seo'; import PageHeading from 'components/PageHeading'; import {useRouteMeta} from './useRouteMeta'; import {useActiveSection} from '../../hooks/useActiveSection'; +import { + SnippetTargetLanguage, + SnippetTargetLanguageContext, + SnippetTargetLanguageContextValue, +} from '../MDX/Sandpack/SnippetLanguage'; import {TocContext} from '../MDX/TocContext'; import(/* webpackPrefetch: true */ '../MDX/CodeBlock/CodeBlock'); @@ -31,6 +36,18 @@ export function MarkdownPage< const title = meta.title || route?.title || ''; const description = meta.description || route?.description || ''; const isHomePage = section === 'home'; + + const defaultSnippetTargetLanguage = 'ts'; + const [snippetTargetLanguage, setSnippetTargetLanguage] = + React.useState(defaultSnippetTargetLanguage); + const snippetTargetLanguageContextValue = + React.useMemo((): SnippetTargetLanguageContextValue => { + return { + snippetTargetLanguage, + setSnippetTargetLanguage, + }; + }, [snippetTargetLanguage]); + return ( <>
@@ -44,7 +61,12 @@ export function MarkdownPage< )}
- {children} + + + {children} + +
{ +export const createFileMap = ( + codeSnippets: React.ReactElement[], + snippetTargetLanguage: SnippetTargetLanguage +) => { return codeSnippets.reduce>( (result, codeSnippet) => { if ((codeSnippet.type as any).mdxName !== 'pre') { diff --git a/beta/src/components/MDX/Sandpack/index.tsx b/beta/src/components/MDX/Sandpack/index.tsx index b98fca744c8..abb1e853f0c 100644 --- a/beta/src/components/MDX/Sandpack/index.tsx +++ b/beta/src/components/MDX/Sandpack/index.tsx @@ -2,7 +2,15 @@ * Copyright (c) Facebook, Inc. and its affiliates. */ -import {lazy, memo, Children, Suspense, useState, useMemo} from 'react'; +import { + lazy, + memo, + Children, + Suspense, + useState, + useMemo, + useContext, +} from 'react'; import {createFileMap} from './createFileMap'; import { SnippetTargetLanguage, @@ -51,18 +59,10 @@ const SandpackGlimmer = ({code}: {code: string}) => ( ); export default memo(function SandpackWrapper(props: any): any { - const defaultSnippetTargetLanguage = 'ts'; - const [snippetTargetLanguage, setSnippetTargetLanguage] = - useState(defaultSnippetTargetLanguage); - const contextValue = useMemo((): SnippetTargetLanguageContextValue => { - return { - snippetTargetLanguage, - setSnippetTargetLanguage, - }; - }, [snippetTargetLanguage]); + const {snippetTargetLanguage} = useContext(SnippetTargetLanguageContext); const codeSnippets = Children.toArray(props.children) as React.ReactElement[]; - const files = createFileMap(codeSnippets); + const files = createFileMap(codeSnippets, snippetTargetLanguage); // To set the active file in the fallback we have to find the active file first. // If there are no active files we fallback to App.js as default. @@ -84,9 +84,7 @@ export default memo(function SandpackWrapper(props: any): any { return ( }> - - - + ); }); From fe5a17e402e5b28b02249b08dbaff09fd2f60613 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Fri, 30 Dec 2022 14:38:52 +0100 Subject: [PATCH 05/16] Only hide JS if TS is available --- .../components/MDX/Sandpack/createFileMap.ts | 37 ++++++++++++++----- beta/src/components/MDX/Sandpack/index.tsx | 17 ++++++--- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/beta/src/components/MDX/Sandpack/createFileMap.ts b/beta/src/components/MDX/Sandpack/createFileMap.ts index e56cfc7a4c0..19111a01d6f 100644 --- a/beta/src/components/MDX/Sandpack/createFileMap.ts +++ b/beta/src/components/MDX/Sandpack/createFileMap.ts @@ -9,7 +9,11 @@ export const createFileMap = ( codeSnippets: React.ReactElement[], snippetTargetLanguage: SnippetTargetLanguage ) => { - return codeSnippets.reduce>( + let hasTSVersion = false; + const isTSFile = (filePath: string) => /\.(mts|ts|tsx)$/.test(filePath); + const isJSFile = (filePath: string) => /\.(mjs|js|jsx)$/.test(filePath); + + const fileMap = codeSnippets.reduce>( (result, codeSnippet) => { if ((codeSnippet.type as any).mdxName !== 'pre') { return result; @@ -47,23 +51,36 @@ export const createFileMap = ( ); } - if (snippetTargetLanguage === 'js' && /\.(mts|ts|tsx)$/.test(filePath)) { - fileHidden = true; - } else if ( - snippetTargetLanguage === 'ts' && - /\.(mjs|js|jsx)$/.test(filePath) - ) { - fileHidden = true; - } - result[filePath] = { code: (props.children || '') as string, hidden: fileHidden, active: fileActive, }; + if (isTSFile(filePath)) { + hasTSVersion = true; + } + return result; }, {} ); + + for (const filePath in fileMap) { + let fileHidden = fileMap[filePath].hidden; + + // Only hide JS files if we have a TS version available. + // If no TS version is available we continue to display JS files. + // Assuming that if one file is available as TS, every file is. + // Assuming a JS version is available all the time. + if (snippetTargetLanguage === 'ts' && isJSFile(filePath) && hasTSVersion) { + fileHidden = true; + } else if (snippetTargetLanguage === 'js' && isTSFile(filePath)) { + fileHidden = true; + } + + fileMap[filePath].hidden = fileHidden; + } + + return fileMap; }; diff --git a/beta/src/components/MDX/Sandpack/index.tsx b/beta/src/components/MDX/Sandpack/index.tsx index abb1e853f0c..0370d44770f 100644 --- a/beta/src/components/MDX/Sandpack/index.tsx +++ b/beta/src/components/MDX/Sandpack/index.tsx @@ -70,21 +70,26 @@ export default memo(function SandpackWrapper(props: any): any { (fileName) => files[fileName]?.active === true && files[fileName]?.hidden === false ); - let defaultActiveCodeSnippet; + let defaultActiveCodeSnippetName; if (!activeCodeSnippet.length) { if (snippetTargetLanguage === 'ts' && '/App.tsx' in files) { - defaultActiveCodeSnippet = files['/App.tsx']; + defaultActiveCodeSnippetName = '/App.tsx'; } else { - defaultActiveCodeSnippet = files['/App.js']; + defaultActiveCodeSnippetName = '/App.js'; } } else { - defaultActiveCodeSnippet = files[activeCodeSnippet[0]]; + defaultActiveCodeSnippetName = activeCodeSnippet[0]; } return ( }> - + fallback={ + + }> + ); }); From 4b36d9e1dd75fe26f0bcf02e494d5f55f5cb62c4 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Fri, 30 Dec 2022 14:42:23 +0100 Subject: [PATCH 06/16] Demo with multi-file snippets --- beta/src/content/learn/describing-the-ui.md | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/beta/src/content/learn/describing-the-ui.md b/beta/src/content/learn/describing-the-ui.md index 6df4c0475fe..20f05131d5d 100644 --- a/beta/src/content/learn/describing-the-ui.md +++ b/beta/src/content/learn/describing-the-ui.md @@ -93,6 +93,21 @@ export default function Gallery() { } ``` +```tsx Gallery.tsx active +import Profile from './Profile'; + +export default function Gallery() { + return ( +
+

Amazing scientists

+ + + +
+ ); +} +``` + ```js Profile.js export default function Profile() { return ( @@ -104,6 +119,17 @@ export default function Profile() { } ``` +```tsx Profile.tsx +export default function Profile() { + return ( + Alan L. Hart + ); +} +``` + ```css img { margin: 0 10px 10px 0; } ``` From 1493104f46cf77ed46fbc26c88e9347c0d40c6f2 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Fri, 30 Dec 2022 14:44:21 +0100 Subject: [PATCH 07/16] Remove files instead of hide them Hidden files would be part of the CodeSandbox ("Open in CodeSandbox" action. --- beta/src/components/MDX/Sandpack/createFileMap.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/beta/src/components/MDX/Sandpack/createFileMap.ts b/beta/src/components/MDX/Sandpack/createFileMap.ts index 19111a01d6f..1303558993e 100644 --- a/beta/src/components/MDX/Sandpack/createFileMap.ts +++ b/beta/src/components/MDX/Sandpack/createFileMap.ts @@ -67,19 +67,15 @@ export const createFileMap = ( ); for (const filePath in fileMap) { - let fileHidden = fileMap[filePath].hidden; - - // Only hide JS files if we have a TS version available. + // Only remove JS files if we have a TS version available. // If no TS version is available we continue to display JS files. // Assuming that if one file is available as TS, every file is. // Assuming a JS version is available all the time. if (snippetTargetLanguage === 'ts' && isJSFile(filePath) && hasTSVersion) { - fileHidden = true; + delete fileMap[filePath]; } else if (snippetTargetLanguage === 'js' && isTSFile(filePath)) { - fileHidden = true; + delete fileMap[filePath]; } - - fileMap[filePath].hidden = fileHidden; } return fileMap; From f08d6e1bc1262a791ef333345de47c96801a51a9 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Sat, 31 Dec 2022 16:19:33 +0100 Subject: [PATCH 08/16] Compile JS version from TS - would crash if both TS and JS version are manually authored - Should we throw if we failed to compile TS? Now we just warn and display the TS version --- beta/plugins/markdownToHtml.js | 3 + .../remark-sandpack-target-languages.js | 80 +++++++++++++++++++ beta/src/content/learn/describing-the-ui.md | 26 ------ .../content/learn/keeping-components-pure.md | 24 ------ beta/src/pages/[[...markdownPath]].js | 2 +- 5 files changed, 84 insertions(+), 51 deletions(-) create mode 100644 beta/plugins/remark-sandpack-target-languages.js diff --git a/beta/plugins/markdownToHtml.js b/beta/plugins/markdownToHtml.js index 0d5fe7afb48..15eedaef9ce 100644 --- a/beta/plugins/markdownToHtml.js +++ b/beta/plugins/markdownToHtml.js @@ -5,6 +5,7 @@ const images = require('remark-images'); // Improved image syntax const unrwapImages = require('remark-unwrap-images'); // Removes

wrapper around images const smartyPants = require('./remark-smartypants'); // Cleans up typography const html = require('remark-html'); +const sandpackTargetLanguages = require('./remark-sandpack-target-languages'); module.exports = { remarkPlugins: [ @@ -13,6 +14,7 @@ module.exports = { images, unrwapImages, smartyPants, + sandpackTargetLanguages, ], markdownToHtml, }; @@ -24,6 +26,7 @@ async function markdownToHtml(markdown) { .use(images) .use(unrwapImages) .use(smartyPants) + .use(sandpackTargetLanguages) .use(html) .process(markdown); return result.toString(); diff --git a/beta/plugins/remark-sandpack-target-languages.js b/beta/plugins/remark-sandpack-target-languages.js new file mode 100644 index 00000000000..3637199283d --- /dev/null +++ b/beta/plugins/remark-sandpack-target-languages.js @@ -0,0 +1,80 @@ +const {transform} = require('@babel/core'); +const path = require('path'); +const prettier = require('prettier'); +const visit = require('unist-util-visit'); + +/** + * Adds an additional JS codeblock to children which which is based on the corresponding TypeScript codeblock. + * The resulting JS code is formatted with Prettier. + */ +module.exports = () => { + return async function transformer(tree, file) { + const prettierConfig = await prettier.resolveConfig( + file.path ?? + // TODO: When testing, `file.path` was always undefined + // Now the formatting of the TS codeblock might use a different formatting config than the resolved config here. + // E.g. when `content/learn/.prettierrc` exists it would be ignored at this point. + file.cwd + ); + + visit(tree, 'mdxJsxFlowElement', (node) => { + if (node.name === 'Sandpack') { + const childrenWithJSTargetLanguage = node.children.flatMap((child) => { + if ( + child.type === 'code' && + (child.lang === 'tsx' || child.lang === 'ts') + ) { + const codeTSNode = child; + // By default we assume `/App.tsx` + // TODO: We should just require a filename i.e. `meta` so that we don't have an assumption that spreads throughout the codebase. + const [tsFileName = '/App.tsx', ...rest] = + codeTSNode.meta?.split(' ') ?? []; + // Gallery.tsx -> Gallery.js + // data.ts -> data.js + const jsFileName = tsFileName.replace(/\.(ts|tsx)$/, '.js'); + const meta = [jsFileName, ...rest].join(' '); + const codeTS = codeTSNode.value; + let codeJS = codeTS; + try { + codeJS = transform(codeTS, { + filename: tsFileName, + presets: [ + [ + '@babel/preset-typescript', + {allExtensions: true, isTSX: tsFileName.endsWith('.tsx')}, + ], + ], + }).code; + codeJS = prettier.format(codeJS, { + ...prettierConfig, + filepath: jsFileName, + }); + } catch (error) { + // TODO: Test behavior when we just let it throw here. + // We're mostly handling malformed snippet code here. + console.warn(`Failed to compile ${meta}:\n${codeTS}\n${error}`); + } + const codeJSNode = { + type: 'code', + lang: 'js', + meta, + value: codeJS, + }; + + // We can't just append since this would result in a different order of snippets if some snippets are not TS and visible: + // App.tsx, styles.css -> styles.css, App.js + // So we splice the transpiled version in instead: + // App.tsx, styles.css -> App.tsx, App.js, styles.css + return [codeTSNode, codeJSNode]; + } else { + return child; + } + }); + + if (childrenWithJSTargetLanguage.length !== node.children) { + node.children = childrenWithJSTargetLanguage; + } + } + }); + }; +}; diff --git a/beta/src/content/learn/describing-the-ui.md b/beta/src/content/learn/describing-the-ui.md index 20f05131d5d..c715cdc9006 100644 --- a/beta/src/content/learn/describing-the-ui.md +++ b/beta/src/content/learn/describing-the-ui.md @@ -78,21 +78,6 @@ export default function App() { } ``` -```js Gallery.js active -import Profile from './Profile.js'; - -export default function Gallery() { - return ( -

-

Amazing scientists

- - - -
- ); -} -``` - ```tsx Gallery.tsx active import Profile from './Profile'; @@ -108,17 +93,6 @@ export default function Gallery() { } ``` -```js Profile.js -export default function Profile() { - return ( - Alan L. Hart - ); -} -``` - ```tsx Profile.tsx export default function Profile() { return ( diff --git a/beta/src/content/learn/keeping-components-pure.md b/beta/src/content/learn/keeping-components-pure.md index 6072adcfb31..77bcd969496 100644 --- a/beta/src/content/learn/keeping-components-pure.md +++ b/beta/src/content/learn/keeping-components-pure.md @@ -49,30 +49,6 @@ React is designed around this concept. **React assumes that every component you -```js App.js -function Recipe({ drinkers }) { - return ( -
    -
  1. Boil {drinkers} cups of water.
  2. -
  3. Add {drinkers} spoons of tea and {0.5 * drinkers} spoons of spice.
  4. -
  5. Add {0.5 * drinkers} cups of milk to boil and sugar to taste.
  6. -
- ); -} - -export default function App() { - return ( -
-

Spiced Chai Recipe

-

For two

- -

For a gathering

- -
- ); -} -``` - ```ts App.tsx function Recipe({ drinkers }: { drinkers: number }) { return ( diff --git a/beta/src/pages/[[...markdownPath]].js b/beta/src/pages/[[...markdownPath]].js index ccff50d83e2..fe854f7ee7d 100644 --- a/beta/src/pages/[[...markdownPath]].js +++ b/beta/src/pages/[[...markdownPath]].js @@ -55,7 +55,7 @@ function reviveNodeOnClient(key, val) { // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~ IMPORTANT: BUMP THIS IF YOU CHANGE ANY CODE BELOW ~~~ -const DISK_CACHE_BREAKER = 7; +const DISK_CACHE_BREAKER = 8; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Put MDX output into JSON for client. From 5822741ff625d70499470891b606fcfb36e457cb Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Sat, 31 Dec 2022 16:29:31 +0100 Subject: [PATCH 09/16] Update beta/src/content/learn/keeping-components-pure.md --- beta/src/content/learn/keeping-components-pure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/content/learn/keeping-components-pure.md b/beta/src/content/learn/keeping-components-pure.md index 77bcd969496..706a1a971b0 100644 --- a/beta/src/content/learn/keeping-components-pure.md +++ b/beta/src/content/learn/keeping-components-pure.md @@ -49,7 +49,7 @@ React is designed around this concept. **React assumes that every component you -```ts App.tsx +```tsx App.tsx function Recipe({ drinkers }: { drinkers: number }) { return (
    From c53a4fc2bb8808931490052d9d80c23cdec0bef8 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Sun, 1 Jan 2023 09:46:30 +0100 Subject: [PATCH 10/16] Drop support for mjs and mts Makes computing JS filename from TS filename complicated --- beta/src/components/MDX/Sandpack/createFileMap.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/beta/src/components/MDX/Sandpack/createFileMap.ts b/beta/src/components/MDX/Sandpack/createFileMap.ts index 1303558993e..03a59e65c24 100644 --- a/beta/src/components/MDX/Sandpack/createFileMap.ts +++ b/beta/src/components/MDX/Sandpack/createFileMap.ts @@ -10,8 +10,8 @@ export const createFileMap = ( snippetTargetLanguage: SnippetTargetLanguage ) => { let hasTSVersion = false; - const isTSFile = (filePath: string) => /\.(mts|ts|tsx)$/.test(filePath); - const isJSFile = (filePath: string) => /\.(mjs|js|jsx)$/.test(filePath); + const isTSFile = (filePath: string) => /\.(ts|tsx)$/.test(filePath); + const isJSFile = (filePath: string) => /\.(js|jsx)$/.test(filePath); const fileMap = codeSnippets.reduce>( (result, codeSnippet) => { From 4c417a9e08420321726e255531b0d757c6bd1cd8 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Sun, 1 Jan 2023 10:21:20 +0100 Subject: [PATCH 11/16] Don't allow switching target language if only JS is available --- .../components/MDX/Sandpack/CustomPreset.tsx | 10 ++- .../components/MDX/Sandpack/NavigationBar.tsx | 65 ++++++++++++++----- .../components/MDX/Sandpack/SandpackRoot.tsx | 6 +- .../components/MDX/Sandpack/createFileMap.ts | 10 +-- beta/src/components/MDX/Sandpack/index.tsx | 2 +- 5 files changed, 67 insertions(+), 26 deletions(-) diff --git a/beta/src/components/MDX/Sandpack/CustomPreset.tsx b/beta/src/components/MDX/Sandpack/CustomPreset.tsx index 7ef53657979..022b981b3da 100644 --- a/beta/src/components/MDX/Sandpack/CustomPreset.tsx +++ b/beta/src/components/MDX/Sandpack/CustomPreset.tsx @@ -22,11 +22,13 @@ export const CustomPreset = memo(function CustomPreset({ showDevTools, onDevToolsLoad, devToolsLoaded, + hasTSVersion, providedFiles, }: { showDevTools: boolean; devToolsLoaded: boolean; onDevToolsLoad: () => void; + hasTSVersion: boolean; providedFiles: Array; }) { const {lintErrors, lintExtensions} = useSandpackLint(); @@ -44,6 +46,7 @@ export const CustomPreset = memo(function CustomPreset({ showDevTools={showDevTools} onDevToolsLoad={onDevToolsLoad} devToolsLoaded={devToolsLoaded} + hasTSVersion={hasTSVersion} providedFiles={providedFiles} lintErrors={lintErrors} lintExtensions={lintExtensions} @@ -56,6 +59,7 @@ const SandboxShell = memo(function SandboxShell({ showDevTools, onDevToolsLoad, devToolsLoaded, + hasTSVersion, providedFiles, lintErrors, lintExtensions, @@ -64,6 +68,7 @@ const SandboxShell = memo(function SandboxShell({ showDevTools: boolean; devToolsLoaded: boolean; onDevToolsLoad: () => void; + hasTSVersion: boolean; providedFiles: Array; lintErrors: Array; lintExtensions: Array; @@ -76,7 +81,10 @@ const SandboxShell = memo(function SandboxShell({
    - + { return filePath.slice(lastIndexOfSlash + 1); }; -function SnippetTargetLanguageButton(props: any) { - const {children, snippetTargetLanguage} = props; - const { - setSnippetTargetLanguage, - snippetTargetLanguage: currentSnippetTargetLanguage, - } = useContext(SnippetTargetLanguageContext); - - const isCurrent = currentSnippetTargetLanguage === snippetTargetLanguage; +function SnippetTargetLanguageButton({ + children, + active, + disabled, + snippetTargetLanguage, +}: { + children: React.ReactNode; + active: boolean; + disabled?: boolean | undefined; + snippetTargetLanguage: SnippetTargetLanguage; +}) { + const {setSnippetTargetLanguage} = useContext(SnippetTargetLanguageContext); return ( ); } -function SnippetTargetLanguageToggle() { +function SnippetTargetLanguageToggle({hasTSVersion}: {hasTSVersion: boolean}) { + const {snippetTargetLanguage} = useContext(SnippetTargetLanguageContext); + return (
    - + JS - + TS
    ); } -export function NavigationBar({providedFiles}: {providedFiles: Array}) { +export function NavigationBar({ + hasTSVersion, + providedFiles, +}: { + hasTSVersion: boolean; + providedFiles: Array; +}) { const {sandpack} = useSandpack(); const containerRef = useRef(null); const tabsRef = useRef(null); @@ -219,7 +248,7 @@ export function NavigationBar({providedFiles}: {providedFiles: Array}) {
    - + diff --git a/beta/src/components/MDX/Sandpack/SandpackRoot.tsx b/beta/src/components/MDX/Sandpack/SandpackRoot.tsx index 87a62e0bc35..512e3170a48 100644 --- a/beta/src/components/MDX/Sandpack/SandpackRoot.tsx +++ b/beta/src/components/MDX/Sandpack/SandpackRoot.tsx @@ -80,7 +80,10 @@ function SandpackRoot(props: SandpackProps) { const {snippetTargetLanguage} = React.useContext( SnippetTargetLanguageContext ); - const files = createFileMap(codeSnippets, snippetTargetLanguage); + const {files, hasTSVersion} = createFileMap( + codeSnippets, + snippetTargetLanguage + ); files['/styles.css'] = { code: [sandboxStyle, files['/styles.css']?.code ?? ''].join('\n\n'), @@ -105,6 +108,7 @@ function SandpackRoot(props: SandpackProps) { showDevTools={showDevTools} onDevToolsLoad={() => setDevToolsLoaded(true)} devToolsLoaded={devToolsLoaded} + hasTSVersion={hasTSVersion} providedFiles={Object.keys(files)} /> diff --git a/beta/src/components/MDX/Sandpack/createFileMap.ts b/beta/src/components/MDX/Sandpack/createFileMap.ts index 03a59e65c24..a696c3c4ac5 100644 --- a/beta/src/components/MDX/Sandpack/createFileMap.ts +++ b/beta/src/components/MDX/Sandpack/createFileMap.ts @@ -13,7 +13,7 @@ export const createFileMap = ( const isTSFile = (filePath: string) => /\.(ts|tsx)$/.test(filePath); const isJSFile = (filePath: string) => /\.(js|jsx)$/.test(filePath); - const fileMap = codeSnippets.reduce>( + const files = codeSnippets.reduce>( (result, codeSnippet) => { if ((codeSnippet.type as any).mdxName !== 'pre') { return result; @@ -66,17 +66,17 @@ export const createFileMap = ( {} ); - for (const filePath in fileMap) { + for (const filePath in files) { // Only remove JS files if we have a TS version available. // If no TS version is available we continue to display JS files. // Assuming that if one file is available as TS, every file is. // Assuming a JS version is available all the time. if (snippetTargetLanguage === 'ts' && isJSFile(filePath) && hasTSVersion) { - delete fileMap[filePath]; + delete files[filePath]; } else if (snippetTargetLanguage === 'js' && isTSFile(filePath)) { - delete fileMap[filePath]; + delete files[filePath]; } } - return fileMap; + return {files, hasTSVersion}; }; diff --git a/beta/src/components/MDX/Sandpack/index.tsx b/beta/src/components/MDX/Sandpack/index.tsx index 0370d44770f..a814fe3ec7d 100644 --- a/beta/src/components/MDX/Sandpack/index.tsx +++ b/beta/src/components/MDX/Sandpack/index.tsx @@ -62,7 +62,7 @@ export default memo(function SandpackWrapper(props: any): any { const {snippetTargetLanguage} = useContext(SnippetTargetLanguageContext); const codeSnippets = Children.toArray(props.children) as React.ReactElement[]; - const files = createFileMap(codeSnippets, snippetTargetLanguage); + const {files} = createFileMap(codeSnippets, snippetTargetLanguage); // To set the active file in the fallback we have to find the active file first. // If there are no active files we fallback to App.js as default. From 7338361f944aada51a25a22fa90a76eee629d578 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Sun, 1 Jan 2023 10:27:44 +0100 Subject: [PATCH 12/16] Ensure import graph actually uses TS --- beta/src/content/learn/describing-the-ui.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/content/learn/describing-the-ui.md b/beta/src/content/learn/describing-the-ui.md index c715cdc9006..2bb8933523f 100644 --- a/beta/src/content/learn/describing-the-ui.md +++ b/beta/src/content/learn/describing-the-ui.md @@ -69,7 +69,7 @@ You can declare many components in one file, but large files can get difficult t ```js App.js hidden -import Gallery from './Gallery.js'; +import Gallery from './Gallery'; export default function App() { return ( From c1e6807d522995a5797ee449d94c17760c803230 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Sun, 1 Jan 2023 10:29:56 +0100 Subject: [PATCH 13/16] REVERT BEFORE MERGE: Test what happens in prod if unable to compile --- beta/plugins/remark-sandpack-target-languages.js | 4 +++- beta/src/content/learn/describing-the-ui.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/beta/plugins/remark-sandpack-target-languages.js b/beta/plugins/remark-sandpack-target-languages.js index 3637199283d..ab667804597 100644 --- a/beta/plugins/remark-sandpack-target-languages.js +++ b/beta/plugins/remark-sandpack-target-languages.js @@ -52,7 +52,9 @@ module.exports = () => { } catch (error) { // TODO: Test behavior when we just let it throw here. // We're mostly handling malformed snippet code here. - console.warn(`Failed to compile ${meta}:\n${codeTS}\n${error}`); + throw new Error( + `Failed to compile ${meta}:\n${codeTS}\n${error}` + ); } const codeJSNode = { type: 'code', diff --git a/beta/src/content/learn/describing-the-ui.md b/beta/src/content/learn/describing-the-ui.md index 2bb8933523f..d8dd55c8ace 100644 --- a/beta/src/content/learn/describing-the-ui.md +++ b/beta/src/content/learn/describing-the-ui.md @@ -94,7 +94,7 @@ export default function Gallery() { ``` ```tsx Profile.tsx -export default function Profile() { +export dfault function Profile() { return ( Date: Sun, 1 Jan 2023 10:33:56 +0100 Subject: [PATCH 14/16] Revert "REVERT BEFORE MERGE: Test what happens in prod if unable to compile" This reverts the malformed TS introduced in commit c1e6807d522995a5797ee449d94c17760c803230. --- beta/src/content/learn/describing-the-ui.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/content/learn/describing-the-ui.md b/beta/src/content/learn/describing-the-ui.md index d8dd55c8ace..2bb8933523f 100644 --- a/beta/src/content/learn/describing-the-ui.md +++ b/beta/src/content/learn/describing-the-ui.md @@ -94,7 +94,7 @@ export default function Gallery() { ``` ```tsx Profile.tsx -export dfault function Profile() { +export default function Profile() { return ( Date: Sun, 1 Jan 2023 10:34:29 +0100 Subject: [PATCH 15/16] Improve error reporting when failing to compile Resolve the TODO since throwing seems preferrable --- beta/plugins/remark-sandpack-target-languages.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/beta/plugins/remark-sandpack-target-languages.js b/beta/plugins/remark-sandpack-target-languages.js index ab667804597..a28aafb544a 100644 --- a/beta/plugins/remark-sandpack-target-languages.js +++ b/beta/plugins/remark-sandpack-target-languages.js @@ -50,10 +50,8 @@ module.exports = () => { filepath: jsFileName, }); } catch (error) { - // TODO: Test behavior when we just let it throw here. - // We're mostly handling malformed snippet code here. throw new Error( - `Failed to compile ${meta}:\n${codeTS}\n${error}` + `Failed to compile ${tsFileName}:\n${codeTS}\n${error}` ); } const codeJSNode = { From 32b5a2a0b2ef1abda6d246be1734944a248a499e Mon Sep 17 00:00:00 2001 From: eps1lon Date: Sun, 1 Jan 2023 10:40:04 +0100 Subject: [PATCH 16/16] Ensure newly required Babel presets are installed --- beta/package.json | 1 + beta/yarn.lock | 127 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) diff --git a/beta/package.json b/beta/package.json index 6e2d373a694..690f7aeb6b4 100644 --- a/beta/package.json +++ b/beta/package.json @@ -45,6 +45,7 @@ "@babel/core": "^7.12.9", "@babel/plugin-transform-modules-commonjs": "^7.18.6", "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", "@mdx-js/mdx": "^2.1.3", "@types/body-scroll-lock": "^2.6.1", "@types/classnames": "^2.2.10", diff --git a/beta/yarn.lock b/beta/yarn.lock index 9db85c1b1ae..31bc5f487ae 100644 --- a/beta/yarn.lock +++ b/beta/yarn.lock @@ -198,6 +198,15 @@ "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" +"@babel/generator@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.7.tgz#f8ef57c8242665c5929fe2e8d82ba75460187b4a" + integrity sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw== + dependencies: + "@babel/types" "^7.20.7" + "@jridgewell/gen-mapping" "^0.3.2" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" @@ -215,6 +224,19 @@ browserslist "^4.20.2" semver "^6.3.0" +"@babel/helper-create-class-features-plugin@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.7.tgz#d0e1f8d7e4ed5dac0389364d9c0c191d948ade6f" + integrity sha512-LtoWbDXOaidEf50hmdDqn9g8VEzsorMexoWMQdQODbvmqYmaF23pBP5VNPAGIFHsFQCIeKokDiz3CH5Y2jlY6w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-member-expression-to-functions" "^7.20.7" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-replace-supers" "^7.20.7" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-environment-visitor@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" @@ -265,6 +287,13 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-member-expression-to-functions@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.20.7.tgz#a6f26e919582275a93c3aa6594756d71b0bb7f05" + integrity sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw== + dependencies: + "@babel/types" "^7.20.7" + "@babel/helper-module-imports@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" @@ -286,11 +315,35 @@ "@babel/traverse" "^7.19.0" "@babel/types" "^7.19.0" +"@babel/helper-optimise-call-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" + integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== + dependencies: + "@babel/types" "^7.18.6" + "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.19.0": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf" integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw== +"@babel/helper-plugin-utils@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" + integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== + +"@babel/helper-replace-supers@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz#243ecd2724d2071532b2c8ad2f0f9f083bcae331" + integrity sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-member-expression-to-functions" "^7.20.7" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.7" + "@babel/types" "^7.20.7" + "@babel/helper-simple-access@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" @@ -317,6 +370,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56" integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw== +"@babel/helper-string-parser@^7.19.4": + version "7.19.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" + integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== + "@babel/helper-validator-identifier@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" @@ -327,6 +385,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076" integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== +"@babel/helper-validator-identifier@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + "@babel/helper-validator-option@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" @@ -369,6 +432,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.0.tgz#497fcafb1d5b61376959c1c338745ef0577aa02c" integrity sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw== +"@babel/parser@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.7.tgz#66fe23b3c8569220817d5feb8b9dcdc95bb4f71b" + integrity sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg== + "@babel/plugin-syntax-jsx@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" @@ -376,6 +444,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-syntax-typescript@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" + integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/plugin-transform-modules-commonjs@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz#afd243afba166cca69892e24a8fd8c9f2ca87883" @@ -419,6 +494,15 @@ "@babel/helper-annotate-as-pure" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-typescript@^7.18.6": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.7.tgz#673f49499cd810ae32a1ea5f3f8fab370987e055" + integrity sha512-m3wVKEvf6SoszD8pu4NZz3PvfKRCMgk6D6d0Qi9hNnlM5M6CFS92EgF4EiHVLKbU0r/r7ty1hg7NPZwE7WRbYw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.20.7" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-typescript" "^7.20.0" + "@babel/preset-react@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d" @@ -431,6 +515,15 @@ "@babel/plugin-transform-react-jsx-development" "^7.18.6" "@babel/plugin-transform-react-pure-annotations" "^7.18.6" +"@babel/preset-typescript@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" + integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-typescript" "^7.18.6" + "@babel/runtime-corejs3@^7.10.2": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.16.8.tgz#ea533d96eda6fdc76b1812248e9fbd0c11d4a1a7" @@ -464,6 +557,15 @@ "@babel/parser" "^7.18.10" "@babel/types" "^7.18.10" +"@babel/template@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" + integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@babel/traverse@^7.19.0": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.0.tgz#eb9c561c7360005c592cc645abafe0c3c4548eed" @@ -480,6 +582,22 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.20.7": + version "7.20.10" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.10.tgz#2bf98239597fcec12f842756f186a9dde6d09230" + integrity sha512-oSf1juCgymrSez8NI4A2sr4+uB/mFd9MXplYGPEBnfAuWmmyeVcHa6xLPiaRBcXkcb/28bgxmQLTVwFKE1yfsg== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.7" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + debug "^4.1.0" + globals "^11.1.0" + "@babel/traverse@^7.7.0": version "7.16.10" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.10.tgz#448f940defbe95b5a8029975b051f75993e8239f" @@ -513,6 +631,15 @@ "@babel/helper-validator-identifier" "^7.18.6" to-fast-properties "^2.0.0" +"@babel/types@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f" + integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + "@code-hike/classer@^0.0.0-aa6efee": version "0.0.0-e48fa74" resolved "https://registry.yarnpkg.com/@code-hike/classer/-/classer-0.0.0-e48fa74.tgz#17243ca84d5af303c51e62b378e8db65e01cd3f4"