-
Notifications
You must be signed in to change notification settings - Fork 7.7k
MVP: Support Sandpack snippets in TypeScript #5426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
aria-pressed={isCurrent ? true : undefined} | ||
className={classNames( | ||
'text-sm text-primary dark:text-primary-dark inline-flex mx-1 border-black', | ||
isCurrent && 'border-b-4' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried aria-pressed:border-b-4
but this didn't work. Either I misunderstood that API or it would require a Tailwind bump which seems excessive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea this is available with 3.2.0
https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.2.0 may be we can bump the package? its a minor bump only?
|
||
files['/styles.css'] = { | ||
code: [sandboxStyle, files['/styles.css']?.code ?? ''].join('\n\n'), | ||
hidden: !files['/styles.css']?.visible, | ||
hidden: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will extract this change which was revealed by less any
typing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// 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]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deleting instead of hidden: true
since hidden files would still be part of the created CodeSandbox.
Size Changes📦 Next.js Bundle AnalysisThis analysis was generated by the next.js bundle analysis action 🤖
|
Page | Size (compressed) |
---|---|
global |
89.16 KB (🟡 +21 B) |
Details
The global bundle is the javascript bundle that loads alongside every page. It is in its own category because its impact is much higher - an increase to its size means that every page on your website loads slower, and a decrease means every page loads faster.
Any third party scripts you have added directly to your app using the <script>
tag are not accounted for in this analysis
If you want further insight into what is behind the changes, give @next/bundle-analyzer a try!
Three Pages Changed Size
The following pages changed size from the code in this PR compared to its base branch:
Page | Size (compressed) | First Load |
---|---|---|
/404 |
43.99 KB (🟡 +360 B) |
133.15 KB |
/500 |
43.97 KB (🟡 +360 B) |
133.13 KB |
/[[...markdownPath]] |
44.06 KB (🟡 +360 B) |
133.21 KB |
Details
Only the gzipped size is provided here based on an expert tip.
First Load is the size of the global bundle plus the bundle for the individual page. If a user were to show up to your website and land on a given page, the first load size represents the amount of javascript that user would need to download. If next/link
is used, subsequent page loads would only need to download that page's bundle (the number in the "Size" column), since the global bundle has already been downloaded.
Any third party scripts you have added directly to your app using the <script>
tag are not accounted for in this analysis
Next to the size is how much the size has increased or decreased compared with the base branch of this PR. If this percentage has increased by 10% or more, there will be a red status indicator applied, indicating that special attention should be given to this.
I don't think so. My PR just about having the Sandpack snippets in TypeScript. From the PR description in #4720, it doesn't sound like we have any overlap. Though #4720 will eventually benefit from this PR since the snippets will have more accurate completions for snippets written in TypeScript. |
It would be interesting to explore a version that compiles from just TS source. For line or character highlights we can use inline syntax like special comments so that they are automatically translated. I guess auto-formatting is the way to go in that case. |
Do you have an example where we currently use line or character highlights? Just so I can test different implementations. |
@gaearon Now compiles from just the TS version. Produces inconsistent formatting though:
|
@@ -24,6 +26,7 @@ async function markdownToHtml(markdown) { | |||
.use(images) | |||
.use(unrwapImages) | |||
.use(smartyPants) | |||
.use(sandpackTargetLanguages) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why the plugins are listed in remarkPlugins
and composed via .use
. Just .use
didn't produce any change.
@@ -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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bumped this for safe measure since I wasn't sure if "ANY CODE BELOW" also includes changes to imported code.
Hidden files would be part of the CodeSandbox ("Open in CodeSandbox" action.
a71f59f
to
219decf
Compare
- 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
Makes computing JS filename from TS filename complicated
219decf
to
c1e6807
Compare
…ompile" This reverts the malformed TS introduced in commit c1e6807.
Resolve the TODO since throwing seems preferrable
Are there any other sites that do this with good UX? I find it a bit confusing that toggling resets the edits although I get why. It's also confusing I don't see actual type errors if I make a mistake though I assume that's fixable. I do agree that we should probably just enable formatting everywhere and use a consistent Prettier setting. |
Yeah I haven't thought about it. I think it's mostly an issue if you accidentally change the language. I think this is going to be quite the effort to save edits so that you can restore them when you change back the language.
Hopefully just a setting for the Sandbox I need to enable. Will do in this PR. Do we lint the snippets?
MUI has it but I did this as well so not so sure about the "good UX" part 😁 Doesn't have editable when I last checked. Ant design has a switch as well but also not editable. |
Yeah, we load ESLint with code splitting.
Yeah I don't think we should save them, but I do think the way it works is a bit confusing. It's not clear if it "translates" from TS to JS or if it resets. I know it resets but I initially thought it would translate what I wrote lol. |
I think magically "upcasting" the JS+edits to TS+edits is out-of-scope (everybody switching to TS needs that 😉 ). For pristine snippets we don't have to do anything though. When there are edits, we should probably ask if the user wants to keep the edits (potentially causing type-errors) or start fresh with the TypeScript code from the snippet. Not sure if that's easily doable (I remember something about prompts from iframes being deprecated?). Though what do we do when the user resets a snippet that started as JS, had edits and then switched to TypeScripts? Reset to JS or reset to TS? |
I think we'd need a bit of designer help on this. We're busy with the landing but remind me to ask for help after. |
Preview:
The selected "target language" (JS or TS) is selected globally and defaults to TS. It's not persisted at the moment but should be (cookie or localStorage?).
If no TS version is available, we disable the toggle and display the toggle as if JS is selected:

Right now we require duplicating codeblocks in TS and JS (Approach A). This was mainly motivated by having CoreMirror decorations that may not be easy to convert from TS decorations to JS decorations. Though it's unclear yet whether we use them and how we would use them for multiple target languages.Alternatively (approach B), we would either have the codeblocks in TypeScript (and transpile them to JS automatically) or just JavaScript (i.e. not have a TS version (yet)).Right now we transpile+format the TS version when parsing MDX to produce the JS version. This is nice from a snippet author perspective (just need to write TS) but results in inconsistent formatting (e.g. bracket spacing). Either we accept that, or revisit #5192.
IIRC @gaearon was against formatting the snippets which makes both approaches a bit more tricky since
A. We can't easily determine if TS and JS are out-of-sync (by checking the transpiled+formatted TS version against the JS version).
B. Just having a TS version would go against formatting since now the JS version is auto-formatted.
TODO (this PR):
TODO (not necessarily this PR):