Search code examples
blobstoresveltewritablecreateobjecturl

Svelte: how to create a Blob from `writable store`?


How can I use a "writable store" to create a "blob"?

I am new to Svelte. I am trying to code a simple markdown editor for visually impaired users. The content of the "textarea" is stored in a "writable store" for further use:

  • speech-synthesis
  • markdown-preview
  • the content of an existing text file is stored in it
  • save text to file

But saving the text content via download to a file does not work.

<script>
  let blob = new Bob([$textStore], type:"text/plain");
  let url = URL.createObjectURL(blob);
</script>

<button>
  <a href={url} download="untitled.md" id="link">Download 
  </a>
</button>

An empty file is saved or it has the content "[object Object]", when I use curley brackets:

let blob = new Blob ([{$textStore}], {type: 'text/plain'});

File for testing:

// TextStore.js        
import { writable } from "svelte/store";
    
export const textStore = writable('');
<!-- EditorTest.svelte -->
<script>
  import { textStore } from "./TextStore.js";

  let blob = new Blob ([{$textStore}], {type: 'text/plain'});
  let url = URL.createObjectURL(blob);
</script>


<h1>Blob-Test</h1>
<textarea bind:value={$textStore} cols="20" rows="5"></textarea>
<hr>
<pre>{$textStore}</pre>
<br>
<button>
  <a href={url} download="untitled.md" id="link">Save</a>
</button>

Can someone help, thanks a lot already.


Solution

  • The main issue is, that the code is not reacting to the changes. The Blob is created once at the beginning, when the store is still empty. You could make it reactive using $:, but that is not a great idea, as it unnecessarily re-creates the Blob over and over.

    I would recommend using a click handler on the button (the link inside it is invalid HTML anyway), and then creating the Blob there:

    <button on:click={onDownload}>
        Save
    </button>
    
    function onDownload() {
        const blob = new Blob([$textStore], {type: 'text/plain'});
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.download = 'file.md';
        link.href = url;
        link.click();
        URL.revokeObjectURL(url); // Object URLs should be revoked after use
    }