Skip to content

Commit

Permalink
feat(Sandpack): individual files options
Browse files Browse the repository at this point in the history
  • Loading branch information
abernier committed Oct 31, 2024
1 parent 0577670 commit e275e69
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 22 deletions.
37 changes: 37 additions & 0 deletions docs/getting-started/authoring.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,43 @@ Instead of `files`, a `folder` prop allow you to pass a folder containing all th

</details>

It is also possible to pass some individual [file format](https://sandpack.codesandbox.io/docs/getting-started/usage#file-format) configuration:

```tsx
<Sandpack
template="react-ts"
folder="authoring-sandpack-cloud"
files={{
'/App.tsx': {
readOnly: true,
active: true,
},
'/styles.css': {
hidden: true
}
}}
/>
```

<details>
<summary>Result</summary>

<Sandpack
template="react-ts"
folder="authoring-sandpack-cloud"
files={{
'/App.tsx': {
readOnly: true,
active: true,
},
'/styles.css': {
hidden: true
}
}}
/>

</details>

### `Codesandbox`

```md
Expand Down
57 changes: 35 additions & 22 deletions src/components/mdx/Sandpack/Sandpack.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import cn from '@/lib/cn'
import { crawl } from '@/utils/docs'
import { Sandpack as SP } from '@codesandbox/sandpack-react'
import {
Sandpack as SP,
type SandpackFile,
type SandpackFiles,
type SandpackProps,
} from '@codesandbox/sandpack-react'
import fs from 'node:fs'
import path from 'node:path'
import { ComponentProps } from 'react'

type Files = Record<string, Omit<SandpackFile, 'code'>>

function getSandpackDependencies(folder: string) {
const pkgPath = `${folder}/package.json`
Expand All @@ -13,49 +19,56 @@ function getSandpackDependencies(folder: string) {
return JSON.parse(str).dependencies as Record<string, string>
}

type File = { code: string }

async function getSandpackFiles(folder: string, extensions = ['js', 'ts', 'jsx', 'tsx', 'css']) {
async function getSandpackFiles(
folder: string,
files: Files = {},
extensions = ['js', 'ts', 'jsx', 'tsx', 'css'],
) {
const filepaths = await crawl(
folder,
(dir) =>
!dir.includes('node_modules') && extensions.map((ext) => dir.endsWith(ext)).some(Boolean),
)
// console.log('filepaths', filepaths)

const files = filepaths.reduce(
(acc, filepath) => {
const relativeFilepath = path.relative(folder, filepath)

return {
...acc,
[`/${relativeFilepath}`]: {
code: fs.readFileSync(filepath, 'utf-8'),
},
}
},
{} as Record<string, File>,
)
return filepaths.reduce((acc, filepath) => {
const relativeFilepath = path.relative(folder, filepath)

return files
const key = `/${relativeFilepath}`
const file = files[key]
return {
...acc,
[key]: {
...file,
code: fs.readFileSync(filepath, 'utf-8'),
},
}
}, {} as SandpackFiles)
}

// https://sandpack.codesandbox.io/docs/getting-started/usage
export const Sandpack = async ({
className,
folder,
files,
...props
}: { className: string; folder?: string } & ComponentProps<typeof SP>) => {
}: {
className: string
folder?: string
files?: Files
} & Omit<SandpackProps, 'files'>) => {
// console.log('folder', folder)

const files = folder ? await getSandpackFiles(folder) : props.files
const _files = folder ? await getSandpackFiles(folder, files) : files
// console.log('_files', _files)

const pkgDeps = folder ? getSandpackDependencies(folder) : null
const dependencies = pkgDeps ?? props.customSetup?.dependencies
const customSetup = {
...props.customSetup,
dependencies,
}
// console.log('customSetup', customSetup)

const options = {
...props.options,
Expand All @@ -64,7 +77,7 @@ export const Sandpack = async ({

return (
<div className={cn(className, 'sandpack')}>
<SP {...props} files={files} customSetup={customSetup} options={options} />
<SP {...props} files={_files} customSetup={customSetup} options={options} />
</div>
)
}

0 comments on commit e275e69

Please sign in to comment.