window.onload = function() {
CodeMirror.defineMode("javascript-hidden-chars", function(config, parserConfig) {
var alterList = ["alter1", "alter2"];
var spacesCount = 0;
var hiddenCharsOverlay = {
token: function(stream, state) {
if (stream.match(/(?= )/)) {
let alterSpace = spacesCount++ % alterList.length;
stream.eat(/ /);
return `space special-chars ${alterList[alterSpace]}`;
}
while (stream.next() != null && !stream.match(" ", false)) {}
return null;
}
};
return CodeMirror.overlayMode(
CodeMirror.getMode(
config,
parserConfig.backdrop || "javascript"
),
hiddenCharsOverlay
);
});
var editorSimple = CodeMirror(document.querySelector("#simple-parser"), {
lineNumbers: true,
lineWrapping: true,
foldGutter: true,
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
mode: "javascript-hidden-chars",
value: `// Demo code (the actual new parser character stream implementation)
function StringStream(string) {
this.pos = 0;
this.string = string;
}
StringStream.prototype = {
done: function() {return this.pos >= this.string.length;},
peek: function() {return this.string.charAt(this.pos);},
next: function() {
if (this.pos < this.string.length)
return this.string.charAt(this.pos++);
},
eat: function(match) {
var ch = this.string.charAt(this.pos);
if (typeof match == "string") var ok = ch == match;
else var ok = ch && match.test ? match.test(ch) : match(ch);
if (ok) {this.pos++; return ch;}
},
eatWhile: function(match) {
var start = this.pos;
while (this.eat(match));
if (this.pos > start) return this.string.slice(start, this.pos);
},
backUp: function(n) {this.pos -= n;},
column: function() {return this.pos;},
eatSpace: function() {
var start = this.pos;
while (/\s/.test(this.string.charAt(this.pos))) this.pos++;
return this.pos - start;
},
match: function(pattern, consume, caseInsensitive) {
if (typeof pattern == "string") {
function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
if (consume !== false) this.pos += str.length;
return true;
}
}
else {
var match = this.string.slice(this.pos).match(pattern);
if (match && consume !== false) this.pos += match[0].length;
return match;
}
}
};
`
});
}
body {
background: #4CB8C4;
/* fallback for old browsers */
background: -webkit-linear-gradient(to right, #3CD3AD, #4CB8C4);
/* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, #3CD3AD, #4CB8C4);
/* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}
.container-editor {
font-size: 15px;
}
.CodeMirror-code div:not(:last-child) .CodeMirror-line:after {
content: "↵";
text-align: center;
opacity: 0.5;
z-index: 1;
height: inherit;
position: absolute;
white-space: nowrap;
pointer-events: none;
}
.cm-special-chars,
.cm-tab {
position: relative;
opacity: 0.5;
}
.cm-special-chars:after,
.cm-tab:after {
opacity: 0.4;
text-align: center;
left: 0;
top: 0;
width: 100%;
position: absolute;
overflow: hidden;
white-space: nowrap;
pointer-events: none;
}
.cm-space {
white-space: break-spaces;
word-break: break-all;
}
.cm-space:after {
content: '·';
width: inherit;
}
.cm-tab {
white-space: pre-wrap;
}
.cm-tab:after {
content: '<---';
direction: rtl;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.63.1/codemirror.min.css" />
<link rel="stylesheet" href="https://codemirror.net/addon/fold/foldgutter.css" />
<div id="simple-parser" class="container-editor"></div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.63.1/codemirror.min.js"></script>
<script type="text/javascript" src="https://codemirror.net/mode/javascript/javascript.js"></script>
<script type="text/javascript" src="https://codemirror.net/addon/mode/overlay.js"></script>
<script type="text/javascript" src="https://codemirror.net/addon/fold/foldcode.js"></script>
<script type="text/javascript" src="https://codemirror.net/addon/fold/foldgutter.js"></script>
<script type="text/javascript" src="https://codemirror.net/addon/fold/comment-fold.js"></script>
<script type="text/javascript" src="https://codemirror.net/addon/fold/indent-fold.js"></script>
<script type="text/javascript" src="https://codemirror.net/addon/fold/brace-fold.js"></script>