DEV Community

Cover image for Build a simple code editor
Phuoc Nguyen
Phuoc Nguyen

Posted on • Originally published at phuoc.ng

Build a simple code editor

Building a code editor from scratch can seem daunting, especially for new programmers. There are several challenges to overcome, such as syntax highlighting, auto-completion, and error detection, in order to create a functional and user-friendly code editor.

However, sometimes we don't need a complex code editor with all the bells and whistles. For simple tasks like editing configuration files or modifying small scripts, a basic code editor will suffice. While they may not be suitable for advanced coding tasks, they are perfect for quick edits or when you need to jot down some code quickly.

In this post, we'll learn how to build a simple code editor using JavaScript. So, let's get started!

Mirroring the main editor

We want to allow users to edit content using a text area. However, a plain text area won't allow us to add advanced features like syntax highlighting, which is essential for a code editor.

To achieve these features, we will use a technique introduced in this series. We will mirror the text area with an additional element. This time, we will use the pre tag for the mirrored element, as pre tags are commonly used to display code.

Here is some sample code to remind you of the approach we've been following in this series:

const containerEle = document.getElementById('container');
const textarea = document.getElementById('textarea');

const mirroredEle = document.createElement('pre');
mirroredEle.textContent = textarea.value;
mirroredEle.classList.add('container__mirror');

containerEle.prepend(mirroredEle);
Enter fullscreen mode Exit fullscreen mode

Disabling spell check

When building a code editor, it's crucial to disable the spell check feature in the text area. This is because spell check can be a major distraction for developers who need to focus on writing code, not prose. Furthermore, programming languages often use specific syntax and terminology that may not be recognized by the spell checker. Disabling spell check ensures that the developer's attention remains on writing code without any unnecessary interruptions.

To disable spell check in the text area, we can use HTML attributes. By adding spellcheck="false" to the <textarea> tag, we can turn off spell check. We can also add other attributes like autocorrect="off", autocomplete="off", and autocapitalize="off" to further optimize the text area for coding purposes.

<textarea
    autocapitalize="off"
    autocomplete="off"
    autocorrect="off"
    spellcheck="false"
></textarea>
Enter fullscreen mode Exit fullscreen mode

By using these attributes, we can ensure that our code editor is optimized for writing code without any unnecessary distractions or interruptions from auto-correct or spell-check features. So, let's focus on writing great code without worrying about spelling errors!

Highlighting syntax

Syntax highlighting is a crucial feature for any code editor. It helps developers quickly identify different parts of their code by colorizing them based on their function or type. This can help catch syntax errors, misspelled variables or functions, and other common coding mistakes, saving time and preventing frustration. Without syntax highlighting, reading and understanding code can be challenging.

Luckily, implementing syntax highlighting in our simple code editor is easy with the use of external libraries. There are several JavaScript libraries available, such as Prism and Highlight.js. For our editor, we'll use Prism since it's easy to use and supports a wide range of programming languages.

To get started, we need to insert Prism's default theme into the <head> tag and load two scripts into the <body> tag.

<head>
    ...
    <link rel="stylesheet" href="https://unpkg.com/prismjs@1.29.0/themes/prism.min.css">
</head>
<body>
    ...
    <script src="https://unpkg.com/prismjs@1.29.0/prism.js"></script>
    <script src="https://unpkg.com/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
</body>
Enter fullscreen mode Exit fullscreen mode

Then, we can highlight our code using Prism's simple function. Once the code is highlighted, we can set the result to the mirrored element and make the text area value invisible by setting the color property to transparent.

const highlight = () => {
    mirroredEle.innerHTML = Prism.highlight(textarea.value, Prism.languages.javascript, 'javascript');
};
Enter fullscreen mode Exit fullscreen mode

To make sure that the syntax highlighting updates every time we change the text in the area, we need to add an event listener to the text area. This will let us run the highlight() function again and again whenever a change is made.

textarea.addEventListener('input', () => {
    highlight();
});
Enter fullscreen mode Exit fullscreen mode

By adding syntax highlighting to our code editor, we can make it much more user-friendly and efficient for developers who are working on small coding tasks or editing configuration files. With this feature in place, developers can quickly identify errors and improve their coding experience.

Making syntax highlighting colors visible

We've encountered a problem with our code editor - we can't interact with the text area to update its content. This is because the color property is set to transparent. But don't worry, we have a solution: we can replace the color property with -webkit-text-fill-color.

Using -webkit-text-fill-color ensures that the text color is set while preserving its transparency. This means we can see the highlighted content in the mirrored element, while still maintaining a transparent background for our syntax-highlighted code.

Here's how we can solve the issue:

.container__textarea {
    -webkit-text-fill-color: transparent;
}
Enter fullscreen mode Exit fullscreen mode

This CSS rule sets -webkit-text-fill-color to transparent, allowing us to see the highlighted content. However, when we focus on the text area, -webkit-text-fill-color sets the cursor's color to black, making it visible.

With this technique, we can create a simple and functional code editor that allows developers to easily edit their code without any distractions or interruptions.

Preventing users from interacting with the mirrored element

Let's talk about an issue we face when working with a mirrored element. When we try to select text, the highlighted colors disappear. This happens because the text area is placed on top of the mirrored element. To fix this, we can simply reverse the order by using the appendChild function instead of prepend.

// Before
// containerEle.prepend(mirroredEle);

// Now
containerEle.appendChild(mirroredEle);
Enter fullscreen mode Exit fullscreen mode

Now, when you select text, the highlighted colors are preserved. However, there is still one more issue to address: users can't interact with the text area, as it is placed below the mirrored element. Fortunately, we can resolve this problem with a single CSS property.

.container__mirror {
    pointer-events: none;
}
Enter fullscreen mode Exit fullscreen mode

To make sure users can interact with an element on a webpage, we need to use a CSS property called pointer-events. This property controls whether an element can be the target of mouse events. By setting pointer-events to none on the mirrored element, we allow users to interact with the text area as they normally would.

If we didn't set pointer-events to none, the mirrored element would capture all mouse events instead of passing them through to the text area. This would prevent users from editing their code or selecting text.

Luckily, by using pointer-events: none, we can make sure users can interact with the text area while still being able to see their code in the mirrored element. It's a win-win!

Supporting keyboard shortcuts

Supporting keyboard shortcuts in a code editor is crucial for boosting developer productivity. It's a faster and more efficient way to navigate menus and perform actions compared to using a mouse or touchpad. Plus, it can help reduce strain on your hands and wrists, especially if you spend long hours coding.

Here are a couple of additional posts to help you add common shortcuts:

While there's certainly room for improvement, such as adding Undo/Redo shortcuts, that's beyond the scope of this post. But don't worry, you can take on those tasks on your own.

Let's check out the final demo together!

See also


It's highly recommended that you visit the original post to play with the interactive demos.

If you found this series helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!

If you want more helpful content like this, feel free to follow me:

Top comments (0)