29
Build a markdown editor-viewer in Svelte
Before we dive into writing the code, this blog assumes that the reader knows the basics of Svelte(I will anyway explain each line of code).
- A
textarea
to enter markdown data. - A
button
clicking on which will show formatted data.
Let's first create the textarea
and the button
and bind the textarea
to the component.
<script>
let rawData = '';
</script>
<main class='main-container'>
<form class='form'>
<textarea type='text' bind:value={rawData} class='markdown-input' placeholder='Enter your markdown content here...'/>
<button class='show-btn' on:click={() => ({})}>
Show Preview
</button>
</form>
</main>
Here, we have taken a main
tag with class='main-container'
and we will use it at the end for styling the UI. The <textarea type='text' bind:value={rawData} class='markdown-input' placeholder='Enter your markdown content here...'/>
binds the textarea
with rawData
which means when we will change the value inside textarea
, the same value will be updated in rawData
variable. The button
for now is not doing anything on click.
On clicking the button, we want to hide the editor and process the markdown value stored in rawData
and show it in the UI. To process the markdown, we will use marked
package which is quite easy to use. We need to conditionally show the rendered markdown only when the Show Preview
button is clicked, and so we will use Svelte's if-else
directive.
<script>
import marked from 'marked';
let rawData = '';
let preview = false;
function showPreview() {
preview = true;
}
</script>
<main class='main-container'>
{#if preview}
<div>
{@html marked(rawData)}
</div>
{:else}
<form class='form'>
<textarea type='text' bind:value={rawData} class='markdown-input' placeholder='Enter your markdown content here...'/>
<button class='show-btn' on:click={showPreview}>
Show Preview
</button>
</form>
{/if}
</main>
We have taken preview
as false
by default and based on it's value we are conditionally rendering either the form
or the formatted markdown using @html marked(rawData)
.
If we only put this marked(rawData)
, it would render the html
equivalent of the markdown
as plain strings. We want the output of marked(rawData)
to be rendered as html
so we will use @html
directive.
showPreview
function get invoked on clicking the button
which then assigns preview = true
and hence the UI is re-rendered and the if
condition is satisfied and hence the preview is shown.
Let's use the classes assigned in the above steps to style the app.
<script>
import marked from 'marked';
let rawData = '';
let preview = false;
function showPreview() {
preview = true;
}
</script>
<main class='main-container'>
{#if preview}
<div>
{@html marked(rawData)}
</div>
{:else}
<form class='form'>
<textarea type='text' bind:value={rawData} class='markdown-input' placeholder='Enter your markdown content here...'/>
<button class='show-btn' on:click={showPreview}>
Show Preview
</button>
</form>
{/if}
</main>
<style>
.main-container {
display: flex;
flex-direction: column;
padding: 1rem 0.6rem;
margin: 0;
height: 100%;
width: 100%;
}
.form {
height: 100%;
width: 95%;
}
.markdown-input {
width: 100%;
height: 90%;
border: unset;
border: 1px solid #9c9a9a;
padding: 0.8rem 1rem;
border-radius: 10px;
background: transparent;
}
.markdown-input::placeholder {
font-size: 1.2rem;
font-weight: 100;
font-family: sans-serif;
letter-spacing: 1px;
}
.markdown-input:focus {
outline: unset;
}
.show-btn {
width: 100%;
padding: 0.6rem 1.5rem;
background: transparent;
font-weight: 300;
font-size: 1.5rem;
border-radius: 10px;
border: 1px solid #9c9a9a;
}
</style>
We have used vanilla CSS so it would be self-explanatory.
We can make it more intuitive by adding one more enhancement. Currently, once we click on show preview
we can't go back to EDIT mode. Let's add one more function to assign preview = false
when the preview area is double-clicked. We will rename the showPreview
to togglePreview
and assign preview = !preview
.
<script>
import marked from 'marked';
let rawData = '';
let preview = false;
function togglePreview() {
preview = !preview;
}
</script>
<main class='main-container'>
{#if preview}
<div on:dblclick={togglePreview}>
{@html marked(rawData)}
</div>
{:else}
<form class='form'>
<textarea type='text' bind:value={rawData} class='markdown-input' placeholder='Enter your markdown content here...'/>
<button class='show-btn' on:click={togglePreview}>
Show Preview
</button>
</form>
{/if}
</main>
<div on:dblclick={togglePreview}>
invokes togglePreview
on double-clicking the div
showing the preview.
That is it! We have built a markdown preview application using Svelte. Hope you like it and learn something new. Do leave your comments and suggestions to keep me motivated.
Thank you all for reading this.
29