Build a simple code editor
Written byPhuoc Nguyen
Created
03 Oct, 2023
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:
js
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);
#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.html
<textarea
autocapitalize="off"
autocomplete="off"
autocorrect="off"
spellcheck="false"
></textarea>
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.html
<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>
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.
js
const highlight = () => {
mirroredEle.innerHTML = Prism.highlight(textarea.value, Prism.languages.javascript, 'javascript');
};
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.js
textarea.addEventListener('input', () => {
highlight();
});
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:
css
.container__textarea {
-webkit-text-fill-color: transparent;
}
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`
.js
// Before
// containerEle.prepend(mirroredEle);
// Now
containerEle.appendChild(mirroredEle);
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.
css
.container__mirror {
pointer-events: none;
}
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
Questions? 🙋
Do you have any questions about front-end development? If so, feel free to create a new issue on GitHub using the button below. I'm happy to help with any topic you'd like to learn more about, even beyond what's covered in this post.
While I have a long list of upcoming topics, I'm always eager to prioritize your questions and ideas for future content. Let's learn and grow together! Sharing knowledge is the best way to elevate ourselves 🥷.
Recent posts ⚡
Newsletter 🔔
If you're into front-end technologies and you want to see more of the content I'm creating, then you might want to consider subscribing to my newsletter.
By subscribing, you'll be the first to know about new articles, products, and exclusive promotions.
Don't worry, I won't spam you. And if you ever change your mind, you can unsubscribe at any time.
Phước Nguyễn