tinygo-org / playground

TinyGo playground and VS Code extension
https://play.tinygo.org/
BSD 3-Clause "New" or "Revised" License
30 stars 7 forks source link

Support share snippets functionality #12

Open s0xzwasd opened 3 years ago

s0xzwasd commented 3 years ago

It would be great if I could share a code snippet with other people like https://play.golang.org/ (Share button).

Deleplace commented 2 years ago

It seems that 3 approaches are popular in online playgrounds:

a) The playground owner manages storage for user snippets b) The playground accepts Gist IDs in its URL, and dynamically fetches the code. Users need to create their Gists from outside the playground. c) The playground has a Save button, that creates a Gist in the playground's GitHub account d) The playground has a Save button, which (via an integration with GitHub's auth) creates a Gist on behalf of the user

(b) is minimal work for the playground's maintainer. It keeps the playground stateless. That's what DartPad does. It's less convenient for the snippet writer though.

aykevl commented 2 years ago

I most certainly would like to add this feature! It's not entirely straightforward though.

a) The playground owner manages storage for user snippets

This is the nicest, and is used by many playgrounds (most importantly by play.tinygo.org), but I'm a little bit unsure about handling user data like that. Ideally I want a service I can put online and then ignore. I'm not a sysadmin.

b) The playground accepts Gist IDs in its URL, and dynamically fetches the code. Users need to create their Gists from outside the playground.

Thank you for the suggestion! I didn't think of that. It is doable, but not as straightforward as it might seem. For the TinyGo playground, the data looks more like this:

{
    "defaultHumanName": "Circuit Playground Express",
    "code": "package main\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\nconst led = machine.A3\n\nfunc main() {\n\tprintln(\"Hello, TinyGo\")\n\tled.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tfor {\n\t\tled.Low()\n\t\ttime.Sleep(time.Second)\n\n\t\tled.High()\n\t\ttime.Sleep(time.Second)\n\t}\n}\n",
    "parts": {
        "main": {
            "location": "parts/circuitplay-express.json",
            "x": 0,
            "y": 0
        },
        "9ibtl21zeiq": {
            "config": {
                "type": "led",
                "humanName": "LED",
                "svg": "led-tht-5mm.svg",
                "color": [255, 0, 0],
                "id": "9ibtl21zeiq"
            },
            "x": 28.707291666666663,
            "y": -25.730729166666663
        }
    },
    "wires": [
        {
            "from": "main.A3",
            "to": "9ibtl21zeiq.anode"
        }
    ],
    "created": "2022-01-26T14:03:30.542Z",
    "name": "circuitplay-express-2022-01-26T14:03:30.542Z"
}

For a gist, I suppose we could extract the code field and store it as a separate file for easier readability. To create this data, a 'Save' button would be essential.

There are also security implications. The referenced JSON file (parts/circuitplay-express.json) references a SVG file, and the SVG file is treated as a document in the webpage, meaning that it could theoretically execute JavaScript. Not a big breach, but still not what you'd expect when you open a snippet from someone else. I've locked it down a lot by using a Content-Security-Policy, but I think security could be tightened a bit more.

aykevl commented 2 months ago

I've implemented this in the PR over here: https://github.com/tinygo-org/tinygo-site/pull/410#issuecomment-2331636015