Issue
I've used this tutorial to add a lightweight code editor in my app. Both PrismJS and tutorial added functionnalities are working well but I'm having an issue when I'm pasting some code from somewhere else. In some lines, tabs act like tabs in the input but as a space in the output, which results in having both texts not aligned with each other.
I've tried to put my textarea (the input) inside a pre tag, I've tried to change it's white-space or word-spacing CSS styling, but nothing has improved this issue.
Should I create a regex to turn those tabs in simple spaces everywhere ? It looks like an overkill to me.
Here is the code from the tutorial :
import React, { useState, useEffect } from "react";
import Prism from "prismjs";
const CodeEditor = props => {
const [content, setContent] = useState(props.content);
const handleKeyDown = evt => {
let value = content,
selStartPos = evt.currentTarget.selectionStart;
console.log(evt.currentTarget);
// handle 4-space indent on
if (evt.key === "Tab") {
value =
value.substring(0, selStartPos) +
" " +
value.substring(selStartPos, value.length);
evt.currentTarget.selectionStart = selStartPos + 3;
evt.currentTarget.selectionEnd = selStartPos + 4;
evt.preventDefault();
setContent(value);
}
};
useEffect(() => {
Prism.highlightAll();
}, []);
useEffect(() => {
Prism.highlightAll();
}, [props.language, content]);
return (
<div className="code-edit-container">
<textarea
className="code-input"
value={content}
onChange={evt => setContent(evt.target.value)}
onKeyDown={handleKeyDown}
/>
<pre className="code-output">
<code className={`language-${props.language}`}>{content}</code>
</pre>
</div>
);
};
export default CodeEditor;
.code-edit-container {
position: relative;
height: 500px;
border: 1px solid hsl(0, 0%, 60%);
background-color: hsl(212, 35%, 95%);
margin: 1em 0;
}
.code-input,
.code-output {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
padding: 1rem;
border: none;
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
font-size: 0.8rem;
background: transparent;
white-space: pre-wrap;
line-height: 1.5em;
word-wrap: break-word;
font-size: 1rem;
}
.code-input {
opacity: 1;
margin: 0;
color: hsl(0, 0%, 40%);
resize: none;
}
.code-output {
pointer-events: none;
z-index: 3;
margin: 0;
overflow-y: auto;
}
code {
position: absolute;
top: 0;
left: 0;
margin: 0;
padding: 1rem;
display: block;
color: hsl(0, 0%, 40%);
font-size: 0.8rem;
font-family: "PT Mono", monospace;
}
/* overrides */
.code-edit-container :not(pre) > code[class*="language-"],
.code-edit-container pre[class*="language-"] {
background: transparent;
margin: 0;
}
Edit : I want my input and output texts to be on top of each other (just like in the tutorial) for my users to think they are editing the output (the one with keywords highlighting). But right now, when I paste some code for somewhere else, tabs are messing the alignment between input (more white space before text) and output. So when the user tries to select a word, his cursor might not be on the word it looks it is.
Solution
I used the same tutorial and had the same problem. The solution was to add, to the .code-input, this line of CSS :
tab-size: 4;
The tabs just have different sizes on the two components.
Answered By - FlowRan
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.