document.execCommand and document.queryCommandState doesn’t work in Svelte

I want to create a text editor, but there are some confusing problems that have come up :

  • The text formatting doesn’t work unless text is selected first
  • The color change on the buttons when the formatting is active sometimes works and sometimes doesn’t. I’ve tried three methods : wrapping it in a function didn’t work, adding an arrow function () => in the onClick makes the color appear active even before I click, and when I do click, it doesn’t change. Using document.queryCommandState directly without wrapping in a function didn’t work either.

And is using bind:innerHTML as I did safe for security? If it’s not safe, what is the safe way?

<script>
    function formatText(command){
        document.execCommand(command, false, null);
    }
    
    function isFormatActive(command){
        return document.queryCommandState(command);
    }
</script>

<div class="bg-black text-white font-lg font-bold">
    <button class:bg-emerald-950={isFormatActive("italic")} on:click={() => formatText("italic")} class="p-4">
        <i>I</i>
    </button>
    <button class:bg-emerald-950={() => isFormatActive('bold')} on:click={() => formatText('bold')} class="p-4">
        <b>B</b>
    </button>
    <button class:bg-emerald-950={document.queryCommandState('underline')} on:click={() => formatText('underline')} class="p-4">
        <u>U</u>
    </button>
</div>
<div class="bg-emerald-500 text-white p-4 rounded-lg focus:border-none focus:outline-none" contenteditable="true">hello</div>