sveltejs / sites

Monorepo for the sites in the Svelte ecosystem
https://svelte.dev
MIT License
290 stars 124 forks source link

Svelte REPL PermaSharing. #446

Open cycle4passion opened 1 year ago

cycle4passion commented 1 year ago

There have been issues raised about sharing REPL contents. Currently REPL sharing relies on the author ideally forking their REPL and not deleting it or modifying it at some point in future.

#339 Encapsulated URL Sharing #113 Changing content if not forked

I got the idea from Shawn Wang @swyx, where he was talking about using the URL for state management. I thought this might be a great way to share Svelte REPL code without server storage requirements, and the content would be permanent rather than relying on author keeping the code unmodified and available. In fact it would mean less server requirements as the forking would be less. It could also be possible to run the generated link through a shortener service to make it's length more reasonable. However this may limit the permanence factor relying on another service.

The general idea would be during onMount of the REPL, it would look for data and name params in the URL, and if present loads that data instead of the stock hello world.

To give live illustration of the premise is tough. This is because services such as the Svelte REPL itself, Stackblitz etc make it hard to see/change the URL. The code represents a bare bones proof of concept, and talking point on whether is worthwhile to pursue a PR.

If you wanted to run the code you can fork it here https://github.com/cycle4passion/https---github.com-cycle4passion-svelte-repl-permashare

but you can get the idea with this.

<script>
// This data would be available from REPL
let name = 'Custom Name for Permalink';
let data = {
  components: [
    {
      name: 'App',
      type: 'svelte',
      source: `<scr` + `ipt>
         import "./data.js"
         let name = 'world';
         </scr` + `ipt>

         <h1>Hello {name}!</h1>`,
    },
    {
        name: 'data',
    type: 'js',
    source: `export let data = [0,1,2];`,
    },
  ]
};

  // update the URL with params data;
  createPermalink(data, name);

  // now pull in the params data from the URL to update the REPL.
  consumePermalink();

function consumePermalink() {
  //  get search params
  const params = new URLSearchParams(window.location.search);
  const name = decodeURI(params.get('name'));
  const data = JSON.parse(decodeURI(params.get('data')));

  // update REPL with name;
  // update REPL components
  // repl.set({ components: data.components });

  // just for illustration
  data.components.forEach(({ name, type, source }, idx) => {
    console.log(`Tab ${idx + 1} Name is: ${name}.${type}`);
    console.log(`Tab ${idx + 1} Source is : ${source}`);
  });
}

function createPermalink(data, name) {
  // get existing search params
  const params = new URLSearchParams(decodeURIComponent(window.location.search));
  // update search params with new source and name
  params.set('name', encodeURI(name));
  params.set('data', encodeURI(JSON.stringify(data)));
  // write to URL
  window.history.replaceState({}, '', `${location.pathname}?${params.toString()}`);
}
</script>
Prinzhorn commented 3 months ago

On my quest to find the source code for the Svelte5 REPL I ended up here. I think this issue can be closed now? https://svelte-5-preview.vercel.app/ stores state in the hash. I'd be glad for any pointers where I can find the current hash-based implementation.

Prinzhorn commented 3 months ago

Found it:

https://github.com/sveltejs/svelte/blob/2491eb7c8503c08693a7e72b152557668d19f54b/sites/svelte-5-preview/src/routes/%2Bpage.svelte#L32-L78

benmccann commented 3 months ago

https://svelte-5-preview.vercel.app/ is temporary and will go away when Svelte 5 is launched

Conduitry commented 3 months ago

There's an open question about what the nature of the more permanent REPL for Svelte 5 will be. There are definitely benefits to encoding the whole thing in the URL (permalinks, no database), but the Svelte 4 mechanism also has benefits. If we could come up with a good way to combine these two (maybe default to automatically creating hash fragment permalinks, but let the user save/overwrite a given version in the database?), then that would be nice.