Typescript Executor
A couple of months ago, I gave a presentation on TypeScript decorators. I called it "Demystifying Decorators", and it focused on creating a dependency injection library in TypeScript using decorators.
I wanted to present code in an intuitive way, especially since the audience was primarily developers. I found a really awesome framework for creating presentations from HTML called Reveal.
Reveal came with a great toolkit that helped me display code and smoothly transition between slides.
Simple code like this made for a really nice slide:
Even though Reveal has great support for displaying code, it doesn't support executing code live during presentations. This was something I really wanted, as running code live can significantly enhance understanding—especially in a very techy presentation like mine.
Reveal has a solid plugin system, so I started looking for a plugin that could execute code. I found this repo, which is a plugin that exposes the terminal to run arbitrary console commands such as node or python, allowing you to execute the code displayed in your slides.
However, it had some limitations. You have to run a command in the presentation that points to a file containing the same code shown on the slide. Also, if I wanted to run code that depended on external packages, I'd have to install those packages on my machine ahead of time.
What I really wanted was the ability to press a button, run any code shown on the screen, and display the standard output right in the presentation—regardless of dependencies or whether I was using TypeScript or JavaScript.
So, I concluded that I needed two things:
A server that could:
- Accept code,
- Transpile it if it's TypeScript,
- Fetch and install any external dependencies from npm,
- Execute the code, and
- Return whatever logs were printed to standard output.
A Reveal plugin that could:
- Send the content of code blocks to that server, and
- Display the returned output in the presentation.
Making the executor
To make an API which could execute typescript code and return the results we can use any http framework. I opted to use fastify since it's supposed to be blazingly fast 🔥.
Since we want to be able to send Typescript code we have to transpile the code, this can be done with the typescript package:
The executor should also be able to download arbitrary dependencies declared in the code. There is a great library which is made by Google called zx which can help us with that:
zx is intended to be used for scripting generally, but it really fit this use case well since it can install dependencies with the --install flag. By writing the javascript to a temporary file and pointing zx to that file we are avoiding having to interpolate Javascript code into the command line.
Great! Now we can package this app up with Docker and run it in a container for easy management.
Making the plugin
The plugin needs to attach to all of the code elements in reveal.js and inject some JavaScript which will send a http request with the code content to the executor and then display the response.
We attach a function to the global window object and register it as a plugin in index.html
Now we should be able to run the code in the presentation by pressing the Run the code! button
Pressing the button yields this result:
Conclusion
If you made it this far, thanks for sticking along and hope your learned something new.
Another cool thing about using reveal is that you can embed the presentation in an iframe. Below is an example of that 👇
Happy coding! 🌈