Hamburger Icon
  • Labs icon Lab
  • Core Tech
Labs

Guided: Build a Markdown Previewer in Svelte

In this Guided Code Lab you will learn the basics of Svelte, an increasingly popular JavaScript front-end framework. By building a Markdown previewer you will learn all the basics on Svelte, including how to write a component, add reactivity, and share state between components.

Labs

Path Info

Level
Clock icon Intermediate
Duration
Clock icon 37m
Published
Clock icon Jan 19, 2024

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Introduction

    In this Guided Code Lab you will build a basic Markdown previewer using Svelte. It will have a straightforward layout featuring an input area where users can enter Markdown and a live preview area that dynamically displays the corresponding HTML output.


    Svelte is a modern frontend framework that is unique in its approach to building user interfaces. Unlike traditional frameworks like React, Angular, or Vue, which use a virtual DOM to track changes, Svelte shifts much of the work to compile-time. This results in faster and more efficient applications, as Svelte compiles your code to highly optimized vanilla JavaScript at build time.

    Svelte is gaining popularity for a few reasons:

    • Ease of Learning: With less boilerplate and a straightforward approach, Svelte is easier to grasp for beginners.
    • Performance: Due to compile-time optimizations, Svelte applications can be more performant, especially for smaller projects.
    • Readability and Maintenance: Svelte's syntax is clean and easy to understand, promoting maintainability.

    Because this environment does not have internet access this project has already been scaffolded for you using Vite, required assets have been downloaded, and unneeded files have been removed. (Picnic CSS) has also been added to provide basic styling of native HTML elements.

    Steps taken to set up the project
    # Create a starter Svelte project
    pnpm create vite@latest
    
    # Install marked
    pnpm i marked
    
    # Remove files and folders that will not be used
    rm -rf .vscode/ public/vite.svg src/assets/ src/app.css src/lib/Counter.svelte README.md
    
    # Download a CSS stylesheet to public/
    wget https://raw.githubusercontent.com/franciscop/picnic/master/picnic.min.css -P public/
    
    # Create files for the two Svelte components that will be used
    touch src/lib/{MarkdownPreview,MarkdownEditor}.svelte
    
    # Delete everything from the App component
    > src/App.svelte
    
    # Update the title of index.html
    # Import the Picnic CSS stylesheet instead of vite.svg
    # Remove import of app.css
    sed -i 's/<title>.*<\/title>/<title>Svelte Markdown Previewer<\/title>/' index.html
    sed -i '/vite.svg/c\<link rel="stylesheet" href="/picnic.min.css">' index.html
    sed -i '/app\.css/d' src/main.js
    
    

    There are some additional packages and changes that are not reflected in the preceding code. These exist to facilitate task validation in this Guided Code Lab and are not relevant to the learning objectives.


    info> In the terminal, run pnpm dev --host to start a dev server. The application will be available, with hot module replacement, at {{localhost:5173}}. Open this URL in a different tab so you can observe your changes in real time.

    The completed components for this application are available for your reference in the solution directory.

  2. Challenge

    Components

    Svelte's syntax is a superset of HTML, enhancing the native web technologies — HTML, CSS, and JavaScript — with features that help give both users and developers a better experience.

    Svelte components encapsulate HTML, CSS, and JavaScript in a single .svelte file with three optional sections: a script block containing JavaScript, HTML markup, and a style block containing CSS that will automatically be scoped to the component at compile time. Components can be nested by importing them in the script block (import Example from './Example.svelte') and then including them as if they are an HTML element: <Example />. In your app you will see the three headings and textarea input.

    You can visualize Svelte scoping CSS to each component by adding some styles for h2 in MarkdownPreview. Notice how any styles you add don't affect the Markdown Preview heading even though typically CSS would affect all h2 elements on the page.

  3. Challenge

    Reactivity in Svelte

    Adding reactivity to Svelte components is extremely simple: declare a variable and then reference it in the HTML markup by wrapping it in { }. Any time a variable is assigned — or reassigned — the UI will update accordingly.

    For example, declaring let name in the script block of your component will allow you to reference the value of name in the HTML markup: <h1>{name}</h1>. When you reassign this variable then the h1 element will update accordingly.

    info> Because the Svelte compiler depends on assignment to determine when to update the UI, mutating a variable may not work as intended. For instance, using .push() on an array will not work trigger an update. You will need to assign the variable to itself: animals = animals.push("cat"). Now you need to add an event handler to update the value of the markdown as a user types in the textarea element.

    The hard way to do this would be to assign value={markdown} and then add an onchange handler to assign the value of event.target.value to the markdown variable. And you would also want a keydown event listener since onchange is only fired after the textarea loses focus.

    The Svelte way to do this is to add bind:value={markdown} and let Svelte do the menial work.

    This directive allows a two way flow of data to ensure the value of textarea is always in sync with the value of markdown. info> Since this component only has one input you can write even less code by renaming markdown to value and then adding bind:value. (Note: The rest of this Code Lab will assume the variable is still named markdown) Your app will look the same as last step, but if you want to see your work in action, add {markdown} to MarkdownEditor and watch it update as you type into the input.

  4. Challenge

    Properties

    Since this application will need to share the value of markdown between multiple components, you will need to do some refactoring. In this case, the simplest solution is to have App manage the value and share it with both children components by passing markdown as a property, often called props.

    To create a prop in a component export a variable: export let greeting. Consumers can now pass a value: <UserProfile name={name}>.

    info> If that looks redundant, Svelte agrees. Since the variable being passed shares a name with the prop, you can wrap it in curly braces: <UserProfile {name}>. If you pass markdown to MarkdownEditor the value of the textarea will initially be set correctly, but when you type the value of markdown will not update because props are a one-way data flow by default.

    Like with the textarea in MarkdownEditor, you can bind the value of a variable to create a two-way connection: <UserProfile bind:name>. Now in your app you can see the Markdown Preview section update as you type in the textarea input.

  5. Challenge

    Rendering the HTML

    Now that your app is sharing the markdown variable with all the components that need it, you can work on getting the preview working.

    Add {markdown} right below the h2 element and you will see it updates in real time as you type in the textarea. You can use any appropriate JavaScript library to convert this Markdown into HTML markup, but in this case you will use marked. You should now see HTML code rendered in the Markdown Preview section of the application. To have Svelte to render this text as actual HTML elements on the page you can use a special tag.

    danger> Svelte does not sanitize expressions when using this tag. This means it will render all HTML which can be a serious risk in an untrusted environment. Your app now renders HTML as you type Markdown!

  6. Challenge

    Next Steps

    You now have a real-time markdown previewer built in Svelte!

    If you want to keep exploring Svelte, here are a few things you might consider:

    • How can you change the style of the component based on its state? (style:property)
    • This application updates the page in real time, but users of assistive technologies like screen readers may not be aware of these changes. How can you use an ARIA live region to ensure all users have a good experience using this application?
    • Currently the MarkdownPreview component is blank when the markdown variable is undefined. How can you use a logic block or slot to provide a default state to the component?
    • How can you use a Svelte store to share the value of markdown across components, even deeply nested ones, without needing to manage it in the App component?
    • What would the process be to sanitize the input before rendering it with @html?
    • Refreshing the page clears the input. How can you persist this value across a page refresh?

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.