NodeJs editor with CodeMirror
by Julien Roche
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/codemirror.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/codemirror.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/keymap/sublime.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/mode/javascript/javascript.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/theme/nord.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/addon/comment/comment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/addon/edit/closebrackets.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/addon/edit/matchbrackets.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/addon/hint/show-hint.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/addon/hint/show-hint.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/addon/hint/javascript-hint.js"></script>
<script src="https://unpkg.com/[email protected]/dist/jshint.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/addon/lint/lint.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/addon/lint/javascript-lint.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/addon/lint/lint.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/addon/fold/foldcode.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/addon/fold/foldgutter.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/addon/fold/brace-fold.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.2/addon/fold/xml-fold.js"></script>
<script...
CSS
html,
body {
border: none;
height: 100%;
margin: 0 0 0 0;
padding: 0 0 0 0;
width: 100%;
}
.readonly--code {
opacity: 0.5;
}
.readonly--line {
background-color: rgba(0, 0, 0, 0.5);
}
Babel + JSX
const readOnlyLines = [ 0, 3, 6 ];
// Using regexp words will help us to find the unallowed keywords
// See https://regexr.com/4jgr2
// With this, we could have the following information:
/*
const regexp = /\brequire\b/g
undefined
const text = `const a = require('something');
const b = requireText();
const c = require;
const d = require ('something else');`;
text.matchAll(regexp).next();
{ done: false, value: { groups: null, index: 10, input: '..' } }
*/
const INVALID_KEYWORDS = [
'require',
'module',
'import',
'export',
'process',
'global'
];
function generateErrorHintForInvalidKeywords(text, codeMirrorInstance) {
const hints = [];
for (const word of INVALID_KEYWORDS) {
const regexp = new RegExp(`\\b${word}\\b`, 'g');
const iterator = text.matchAll(regexp);
let next = iterator.next();
while(!next.done) {
const index = next.value.index;
const from = codeMirrorInstance.posFromIndex(index);
const line = from.line;
const information = codeMirrorInstance.lineInfo(line);
if (!information.wrapClass || !information.wrapClass.includes('readonly--line')) {
hints.push({
message: `The keyword ${word} is not allowed`,
severity: 'error',
from,
to: codeMirrorInstance.posFromIndex(index + word.length)
});
}
next = iterator.next();
}
}
return hints;
}
function parseErrors(errors, output) {
for ( var i = 0; i < errors.length; i++) {
var error = errors[i];
if (error) {
if (error.line <= 0) {
if (window.console) {
window.console.warn("Cannot display JSHint error (invalid line " + error.line + ")", error);
}
continue;
}
var start = error.character - 1, end = start + 1;
if (error.evidence) {
var index = error.evidence.substring(start).search(/.\b/);
if (index > -1) {
end += index;
}
}
// Convert to format...