mdBook icon indicating copy to clipboard operation
mdBook copied to clipboard

Open up support for alternative playground languages

Open vanceism7 opened this issue 3 years ago • 12 comments

This PR opens up the ability for the playground to run code for languages other than rust.

It adds an option to set which language is "playground-able" in book.toml, and then uses that config option to choose whether the html pre blocks and friends should be wrapped around that code. Overall, it's a pretty minor change, but this allows others languages with playgrounds (e.g: purescript) to have active code blocks in mdbook.

(It looks like the remainder of the heavy lifting to implement the playground for other languages rests in the hands of an alternative book.js via mdbook init --theme.)

Related to #350 and purescript-contrib/purescript-book#91

Im happy to make changes if anything seems wrong. Thanks!

vanceism7 avatar Feb 26 '22 21:02 vanceism7

I'm just a random user who is also interested in this :smiley:

I think this looks like a nice first step, but would it not be necessary to also override the hard-coded play.rust-lang.org strings in book.js? Or perhaps you wanted to make this as a follow-up change?

mgeisler avatar May 30 '22 12:05 mgeisler

I'm just a random user who is also interested in this 😃

I think this looks like a nice first step, but would it not be necessary to also override the hard-coded play.rust-lang.org strings in book.js? Or perhaps you wanted to make this as a follow-up change?

Yea, the book.js change is intended to be done as a follow-up. I think the reason for separating the changes was because the book.js change is a little bit more involved, and book.js is a lot more language specific than this change. Having to manually modify book.js isnt ideal, but with this PR, atleast it gives determined users the ability to actually do it successfully

vanceism7 avatar May 30 '22 14:05 vanceism7

Having to manually modify book.js isnt ideal, but with this PR, atleast it gives determined users the ability to actually do it successfully

Okay, thanks, that makes sense to me!

mgeisler avatar Jun 01 '22 15:06 mgeisler

  • This PR is great.
  • Can a set of other languages ​​be built in? Such as golang, typescript and dart. This is convenient to use. (Of course, it is also allowed to specify custom playgrounds)
  • mdbook is a very handy project for writing tutorials for beginners.
  • I just want to use mdbook to write some flutter/golang tutorials. Use playground to run examples.

some online playgrounds:

  • [x] golang: https://go.dev/play/
  • [x] dart: https://dartpad.dev/?
  • [x] typescript: https://www.typescriptlang.org/play
  • [x] more others: https://fiddles.io/

hhstore avatar Jun 17 '22 00:06 hhstore

Have there been any updates on merge status? This would be a great feature to have, and would love to use it in a project of mine that currently only has static snippets.

mjh316 avatar Sep 19 '22 00:09 mjh316

@ehuss Hey, I know this PR is a bit out of date now, but just wondering if we could get a review on this. Thanks!

vanceism7 avatar Sep 19 '22 00:09 vanceism7

@vanceism7 can you resolve the conflicts? we can look at getting it merged after that

Dylan-DPC avatar Sep 19 '22 07:09 Dylan-DPC

@Dylan-DPC Updated. Thanks for the quick response!

vanceism7 avatar Sep 19 '22 17:09 vanceism7

This isn't really clear to me how it is supposed to work. Can you provide more information about what the intention here is?

I would expect at a minimum that there would be some kind of mapping of language to a URL to post the code to. From what I can tell, this changes it so that arbitrary languages can be sent to https://play.rust-lang.org/, but I'm not clear why that would be desired. I don't think the rust playground supports any other languages, nor or there any plans to do that?

ehuss avatar Sep 19 '22 19:09 ehuss

As mdbook currently is, one can create their own book.js using `mdbook init --theme, and modify it to use a different playground url, but mdbook will still forcibly disable the ability to run any code snippet that isn't explicitly rust. The intention of this PR is that we don't disable code snippets just because they're not using rust. It doesn't explicitly enable support for alternative playgrounds, it just opens up the ability to do it, instead of making it forbidden as is currently the case.

I think ideally, it'd be nice if we could add another config field alongside the language field, that allows the user to specify what playground url they want to use, and have that propagate within book.js without needing to create a custom theme. But IIRC, book.js also has a lot of rust specific stuff in it, so I don't think enabling alternative backend support would be that trivial. This atleast gets the ball rolling in that direction though, and technically adds the ability for anyone already using mdbook to make an alternative language work.

vanceism7 avatar Sep 19 '22 21:09 vanceism7

If you are already modifying the javascript, would it be possible to just change the query to modify the code elements with your language (instead of looking for .playground)?

I would prefer to not add an option that is as low-level as "add playground class to this one language". Ideally I'd like to see a general strategy of how alternate languages could be supported. It is OK to make incremental progress towards that goal.

Does https://try.purescript.org/ have a relatively simple API for sending a blob of code and getting the output?

ehuss avatar Sep 19 '22 22:09 ehuss

Hmm, I see what you're saying. I think in a world where each mdbook site only supports one runnable language, this change makes sense in the sense that book.js sort of standardizes itself on looking for code snippets with the .playground class, rather than having every language write queries for random classes in its own custom book.js. But if we wanted to have a general way for mdbook to run multiple languages at once, this change probably isn't very satisfactory currently.

If we wanted to run multiple languages at once, you'd probably want to change the languages config field to an array of strings, and have users list all the languages they want to be runnable. Then maybe you'd tag each code snippet with playground-{your-language}. But then again, maybe that's not even needed because you can just query for language-{your-language}.

Maybe the right way to generalize alternative backends is to (somehow) get a list of runnable languages to call querySelectorAll on, and then for each language in that list, we have an action we run that hits that languages playground and handles the response for it.

So that we go from this:

(function codeSnippets() {
    ...

    var playgrounds = Array.from(document.querySelectorAll(".playground"));
    if (playgrounds.length > 0) {
        fetch_with_timeout("https://play.rust-lang.org/meta/crates", {
            ...
        })
        .then(response => response.json())
        .then(response => {
            // get list of crates available in the rust playground
            let playground_crates = response.crates.map(item => item["id"]);
            playgrounds.forEach(block => handle_crate_list_update(block, playground_crates));
        });
    }

to something like this (pseudo code)

(function codeSnippets() {
    ...
    foreach( var playgroundClass in playgroundsList ) {
      var playgrounds = Array.from(document.querySelectorAll(playgroundClass));
      if (playgrounds.length > 0) {
        var env = playgroundRunners[playgroundClass].initializeRunner(); // Something like grabbing rust crates could go here
        playgrounds.forEach(block => playgroundRunners[playgroundClass].eval(block, env);
    }

Then to get alternative backends in, we'd probably just need contributions of js modules from the community that handle connecting to that languages playground. Something like a Rust.js, Purescript.js and whatever else could exist as small modules that just export the two functions initializeRunner and eval. Or the user just throws <mylanguage>.js into their own book and the book theme will read it automatically.

Well, thinking that all through, we probably want to close this PR now 😅

Does https://try.purescript.org/ have a relatively simple API for sending a blob of code and getting the output?

Yea, try purescript has a pretty simple api. Its actually compile.purescript.org. I think you just POST to it with the body being a blob of code and it spits back a response at you https://github.com/purescript/trypurescript#server-api

I have a working example of mdbook with live purescript code snippets here: https://gitlab.com/vanceism7/prog-book/-/tree/vjp/ps-live-code-editor

Thanks for taking the time!

vanceism7 avatar Sep 19 '22 23:09 vanceism7