Open iliakan opened 2 months ago
I'm not sure if Astro supports this out-of-the-box (cc. @Nemikolh, ???). But one thing you could do is convert the content.md
into content.mdx
, import the script contents as raw string
and add it to markup:
---
type: lesson
title: Example
---
import landing from "./_files/landing.js?raw"
# Test
<script>
{landing}
</script>
But if you just want to add some interactivity to lesson markdown, I would recommend to check Astro docs: https://docs.astro.build/en/basics/astro-components/ and https://docs.astro.build/en/guides/client-side-scripts/
With Astro's content collection, I would advise against having code that is part of your app inside your content/*
folders (the only exception being content/config.ts
which is treated specially by Astro).
I find that it's usually nicer to have the following structure:
src
├── utils
│ └── script.ts
├── content
│ ├── config.ts
│ └── tutorial
│ ├── meta.md
│ └── ...
...
Which then let you import your script like this in any content.mdx
:
---
type: lesson
title: Example
---
import "@utils/script";
# My lesson
The nice thing is that you can import your script using the same import in any lesson.
If you want to add a ui element, you might find it useful to have a component instead which let's you access and modify the state of the tutorial:
With a src/components/UpdateFileButton.tsx
file:
import tutorialStore from 'tutorialkit:store';
interface Props {
path: string;
content: string;
}
export function UpdateFileButton({ path, content }: Props) {
function writeFile() {
tutorialStore.updateFile(path, content);
}
return (
<button onClick={writeFile}>
Update file
</button>
);
}
You can then use it like this in your lessons:
---
type: lesson
title: Example
---
import { UpdateFileButton } from "@components/UpdateFileButton";
# My lesson
<UpdateFileButton client:load path="/index.js" content="console.log('Hello world!')" />
So it's ok to put images in content, but not scripts? Even if the script is for a particular lesson only?
@iliakan could you describe your use case a bit more? What does the landing.js
do? Why does it need to be run outside webcontainer as well?
@AriPerkkio for this particular case I was going to create a landing script to nicely show callouts above the webcontainer and the editor, to introduce the environment in a clear visual style.
So it's ok to put images in content, but not scripts? Even if the script is for a particular lesson only?
I mean you can also have them there but it won't be as nice as having them outside in terms of DX with vite
because we exclude those folders from vite's optimizeDeps
entry:
https://github.com/stackblitz/tutorialkit/blob/1eb41fd917ceff08fe9484bd07e732cb673a7a1f/packages/astro/src/index.ts#L87-L89
So IIRC, it means that vite
won't be scanning those scripts and they might load a bit slower in development.
Note that they are excluded for a reason: we do not want vite to try to resolve imports for file that ends in WebContainer as it leads to confusing errors
Describe the bug
Adding an external script to a lesson doesn't work.
Steps to reproduce
<script src="landing.js"></script>
tocontent.md
of a lesson.landing.js
file withconsole.log(1)
in the lesson folder.npm run dev
and open the lesson in the browser.Expected behavior
Astro supports scripts. I'd expect the script to work.
Platform
P.S.
Adding
image.png
to the lesson and including it as![](ball.png)
works.Perhaps, there's an alternative "proper" way to add an external script?