React code editor and syntax highlighter using PrismJS
In this react article, you will learn how to create a code editor and highlight the syntax using PrismJS. Prism.js is a lightweight, extensible syntax highlighter, built with modern web standards in mind.
Checkout more articles on ReactJS
- Convert HTML element or document into Image in React
- Generate a random string in JavaScript
- How to implement a line chart in React
- How to fix ReactDOM.render is no longer supported in React 18
- How to use componentWillUnmount() in React Hooks
Demo Application
Output - React code editor and syntax highlighter using PrismJS - Clue Mediator
Steps to implement code editor and highlight the syntax
- Create a React application
- Install dependencies
- Add code editor
- Highlight the syntax using Prism.js
- Output
File Structure
-
react-code-editor
-
node_modules
-
public
- index.html
-
src
- App.js
- index.css
- index.js
- editor.css
- prism-vsc-dark-plus.css
-
package-lock.json
-
package.json
-
README.md
-
1. Create a React application
Set up a React application using `create-react-app`. Run the following command to create a React app.
npx create-react-app react-code-editor
2. Install dependencies
Here we will use the react-simple-code-editor and prismjs NPM packages to create a demo. Run the following command to install the packages.
npm i prismjs react-simple-code-editor
3. Add code editor
Let’s use the following sample code.
const codeSnippet = `function add(a, b) {
return a + b;
}
add(5, 10);
// Output: 15
`;
Next, we have to import the `react-simple-code-editor` to render the editor in the React component.
import Editor from 'react-simple-code-editor';
// ...
// ...
const [code, setCode] = useState(codeSnippet);
// ...
// ...
return (
<editor value={code} onvaluechange="{code" ==""> setCode(code)}
highlight={(code) => { }}
padding={10}
style={{
fontFamily: '"Fira code", "Fira Mono", monospace',
fontSize: 12
}}
/>
);
</editor>
4. Highlight the syntax using Prism.js
After rendering the editor, we will highlight the syntax using Prism.js. Here, we are importing the core component and javascript component to highlight the syntax in JavaScript format.
Import the following code in your component. Here, we have wrapped the `Editor` with the title bar to design the editor.
import { highlight, languages } from 'prismjs/components/prism-core';
import 'prismjs/components/prism-clike';
import 'prismjs/components/prism-javascript';
// ...
// ...
<div class="window">
<div class="title-bar">
<div class="title-buttons">
<div class="title-button"></div>
<div class="title-button"></div>
<div class="title-button"></div>
</div>
</div>
<div class="editor_wrap">
<editor value={code} onvaluechange="{code" ==""> setCode(code)}
highlight={code => highlight(code, languages.js)}
padding={10}
style={{
fontFamily: '"Fira code", "Fira Mono", monospace',
fontSize: 12
}}
/>
</editor></div>
</div>
Let’s import the following CSS.
prism-vsc-dark-plus.css
pre[class*="language-"],
code[class*="language-"] {
color: #d4d4d4;
font-size: 13px;
text-shadow: none;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::selection,
code[class*="language-"]::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
pre[class*="language-"],
code[class*="language-"] {
text-shadow: none;
}
}
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
background: #1e1e1e;
}
:not(pre) > code[class*="language-"] {
padding: .1em .3em;
border-radius: .3em;
color: #db4c69;
background: #f9f2f4;
}
/*********************************************************
* Tokens
*/
.namespace {
opacity: .7;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #6a9955;
}
.token.punctuation {
color: #d4d4d4;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #b5cea8;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #ce9178;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #d4d4d4;
background: #1e1e1e;
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #c586c0;
}
.token.function {
color: #dcdcaa;
}
.token.regex,
.token.important,
.token.variable {
color: #d16969;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.constant {
color: #9CDCFE;
}
.token.class-name {
color: #4EC9B0;
}
.token.parameter {
color: #9CDCFE;
}
.token.interpolation {
color: #9CDCFE;
}
.token.punctuation.interpolation-punctuation {
color: #569cd6;
}
.token.boolean {
color: #569cd6;
}
.token.property {
color: #9cdcfe;
}
.token.selector {
color: #d7ba7d;
}
.token.tag {
color: #569cd6;
}
.token.attr-name {
color: #9cdcfe;
}
.token.attr-value {
color: #ce9178;
}
.token.entity {
color: #4ec9b0;
cursor: unset;
}
.token.namespace {
color: #4ec9b0;
}
/*********************************************************
* Language Specific
*/
pre[class*="language-javascript"],
code[class*="language-javascript"] {
color: #4ec9b0;
}
pre[class*="language-css"],
code[class*="language-css"] {
color: #CE9178;
}
pre[class*="language-html"],
code[class*="language-html"] {
color: #d4d4d4;
}
.language-html .token.punctuation {
color: #808080;
}
/*********************************************************
* Line highlighting
*/
pre[data-line] {
position: relative;
}
pre[class*="language-"] > code[class*="language-"] {
position: relative;
z-index: 1;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
padding: inherit 0;
margin-top: 1em;
background: #f7ebc6;
box-shadow: inset 5px 0 0 #f7d87c;
z-index: 0;
pointer-events: none;
line-height: inherit;
white-space: pre;
}
editor.css
.window {
position: relative;
margin: 30px;
border-radius: 6px;
background-color: #1a1e22;
color: #fff;
width: calc(100% - 60px);
overflow: hidden;
}
.title-bar {
height: 40px;
background-color: rgb(231 231 231 / 6%);
position: relative;
}
.title-text {
color: #afafaf;
position: absolute;
left: 80px;
bottom: 0;
margin: 0;
padding: 7px 16px;
font-size: 15px;
min-width: 10px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
}
.title-text span {
outline: none;
}
.title-text img {
width: 20px;
margin-right: 10px;
}
.title-buttons {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
left: 10px;
top: 50%;
transform: translateY(-50%);
}
.title-button {
background-color: #3a3a3a;
width: 10px;
height: 10px;
border-radius: 50px;
margin: 0 5px;
}
.title-button:nth-child(1) {
background-color: #ff5656;
}
.title-button:nth-child(2) {
background-color: #ffbc6a;
}
.title-button:nth-child(3) {
background-color: #67f772;
}
.editor_wrap {
height: calc(100% - 60px);
overflow-y: auto;
padding: 10px;
}
.editor_wrap textarea {
outline: none;
}
5. Output
Let’s put all code together and see how it looks.
App.js
import React, { useState } from 'react';
import Editor from 'react-simple-code-editor';
import { highlight, languages } from 'prismjs/components/prism-core';
import 'prismjs/components/prism-clike';
import 'prismjs/components/prism-javascript';
import './prism-vsc-dark-plus.css';
import './editor.css';
const codeSnippet = `function add(a, b) {
return a + b;
}
add(5, 10);
// Output: 15
`;
function App() {
const [code, setCode] = useState(codeSnippet);
return (
<div class="App">
<h3>React code editor and syntax highlighter using PrismJS - <a href="https://www.cluemediator.com/" target="_blank" rel="noopener">Clue Mediator</a></h3>
<div class="window">
<div class="title-bar">
<div class="title-buttons">
<div class="title-button"></div>
<div class="title-button"></div>
<div class="title-button"></div>
</div>
</div>
<div class="editor_wrap">
<editor value={code} onvaluechange="{code" ==""> setCode(code)}
highlight={code => highlight(code, languages.js)}
padding={10}
style={{
fontFamily: '"Fira code", "Fira Mono", monospace',
fontSize: 12
}}
/>
</editor></div>
</div>
</div>
);
}
export default App;
Run the application and check the output in the browser.
I hope you find this article helpful.
Thank you for reading. Happy Coding..!! 🙂