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);
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>
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>
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');
};
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();
});
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;
}
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);
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;
}
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
- Indent content in a text area using the Tab key
- Remove indentation in a text area using the Shift+Tab key combination
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)