Started syntax highlighting
This commit is contained in:
commit
f8a90e39e0
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
Kyler Olsen
|
||||||
|
November 2023
|
||||||
|
*/
|
||||||
|
|
||||||
|
.code {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code > pre {
|
||||||
|
padding: 5px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
overflow: auto;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code > pre > code {
|
||||||
|
display: block;
|
||||||
|
min-height: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-code {
|
||||||
|
background-color: #002240;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-code {
|
||||||
|
color: transparent;
|
||||||
|
/* border: 1px dotted #4242de; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.idle-light .view-code { background-color: #ffffff; color: #000000; }
|
||||||
|
.idle-light .edit-code { caret-color: #000000; }
|
||||||
|
.idle-light .token { color: #000000 }
|
||||||
|
.idle-light .comment { color: #dd0000 }
|
||||||
|
.idle-light .output { color: #000000 }
|
||||||
|
.idle-light .error { color: #000000 }
|
||||||
|
.idle-light .literal { color: #000000 }
|
||||||
|
.idle-light .literal.number { color: #000000 }
|
||||||
|
.idle-light .literal.string { color: #00aa00 }
|
||||||
|
.idle-light .literal.string .format { color: #00aa00 }
|
||||||
|
.idle-light .escape { color: #000000 }
|
||||||
|
.idle-light .name { color: #000000 }
|
||||||
|
.idle-light .name.variable { color: #000000 }
|
||||||
|
.idle-light .name.constant{ color: #000000 }
|
||||||
|
.idle-light .name.function { color: #0000ff }
|
||||||
|
.idle-light .name.class { color: #0000ff }
|
||||||
|
.idle-light .name.attribute { color: #000000 }
|
||||||
|
.idle-light .name.property { color: #000000 }
|
||||||
|
.idle-light .keyword { color: #ff7700 }
|
||||||
|
.idle-light .keyword.operator { color: #ff7700 }
|
||||||
|
.idle-light .builtin { color: #900090 }
|
||||||
|
.idle-light .operator { color: #000000 }
|
||||||
|
.idle-light .punctuation { color: #000000 }
|
||||||
|
|
||||||
|
.idle-dark .view-code { background-color: #002240; color: #ffffff; }
|
||||||
|
.idle-dark .edit-code { caret-color: #ffffff; }
|
||||||
|
.idle-dark .token { color: #ffffff }
|
||||||
|
.idle-dark .comment { color: #dd0000 }
|
||||||
|
.idle-dark .output { color: #ffffff }
|
||||||
|
.idle-dark .error { color: #ffffff }
|
||||||
|
.idle-dark .literal { color: #ffffff }
|
||||||
|
.idle-dark .literal.number { color: #ffffff }
|
||||||
|
.idle-dark .literal.string { color: #02ff02 }
|
||||||
|
.idle-dark .literal.string .format { color: #02ff02 }
|
||||||
|
.idle-dark .escape { color: #ffffff }
|
||||||
|
.idle-dark .name { color: #ffffff }
|
||||||
|
.idle-dark .name.variable { color: #ffffff }
|
||||||
|
.idle-dark .name.constant{ color: #ffffff }
|
||||||
|
.idle-dark .name.function { color: #5e5eff }
|
||||||
|
.idle-dark .name.class { color: #5e5eff }
|
||||||
|
.idle-dark .name.attribute { color: #ffffff }
|
||||||
|
.idle-dark .name.property { color: #ffffff }
|
||||||
|
.idle-dark .keyword { color: #ff8000 }
|
||||||
|
.idle-dark .keyword.operator { color: #ff8000 }
|
||||||
|
.idle-dark .builtin { color: #ff00ff }
|
||||||
|
.idle-dark .operator { color: #ffffff }
|
||||||
|
.idle-dark .punctuation { color: #ffffff }
|
|
@ -0,0 +1,91 @@
|
||||||
|
// Kyler Olsen
|
||||||
|
// November 2023
|
||||||
|
|
||||||
|
class PythonEditor{
|
||||||
|
constructor(ele) {
|
||||||
|
this.element = ele;
|
||||||
|
|
||||||
|
this.element.addEventListener("input", this.textInput.bind(this));
|
||||||
|
this.element.addEventListener("keydown", this.handleKeyDown.bind(this));
|
||||||
|
|
||||||
|
this.view_code = document.createElement("code");
|
||||||
|
this.edit_code = document.createElement("code");
|
||||||
|
this.view_pre = document.createElement("pre");
|
||||||
|
this.edit_pre = document.createElement("pre");
|
||||||
|
|
||||||
|
this.edit_code.contentEditable = true;
|
||||||
|
this.edit_code.spellcheck = false;
|
||||||
|
this.view_pre.classList.add("view-code");
|
||||||
|
this.edit_pre.classList.add("edit-code");
|
||||||
|
|
||||||
|
this.view_pre.appendChild(this.view_code);
|
||||||
|
this.edit_pre.appendChild(this.edit_code);
|
||||||
|
this.element.appendChild(this.view_pre);
|
||||||
|
this.element.appendChild(this.edit_pre);
|
||||||
|
}
|
||||||
|
|
||||||
|
textInput(e) {
|
||||||
|
let text = this.edit_code.innerHTML;
|
||||||
|
syntax_highlight(text).forEach(ele => this.view_code.appendChild(ele));
|
||||||
|
}
|
||||||
|
|
||||||
|
handleKeyDown(e) {
|
||||||
|
if (e.key === "Tab") {
|
||||||
|
e.preventDefault();
|
||||||
|
insertTab(e.target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertTab() {
|
||||||
|
const selection = window.getSelection();
|
||||||
|
|
||||||
|
if (selection.rangeCount > 0) {
|
||||||
|
const range = selection.getRangeAt(0);
|
||||||
|
const startOffset = range.startOffset;
|
||||||
|
const lineStart = range.startContainer.textContent.lastIndexOf('\n', startOffset - 1) + 1;
|
||||||
|
const spacesToAdd = 4 - ((startOffset - lineStart) % 4);
|
||||||
|
const tabSpaces = ' '.repeat(spacesToAdd);
|
||||||
|
|
||||||
|
const tabNode = document.createTextNode(tabSpaces);
|
||||||
|
range.deleteContents();
|
||||||
|
range.insertNode(tabNode);
|
||||||
|
range.setStartAfter(tabNode);
|
||||||
|
range.setEndAfter(tabNode);
|
||||||
|
selection.removeAllRanges();
|
||||||
|
selection.addRange(range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function syntax_highlight(text) {
|
||||||
|
const whitespace = " \n\t";
|
||||||
|
const string_start = `'"`;
|
||||||
|
|
||||||
|
const elements = [];
|
||||||
|
var char = text.substr(0, 1); text = text.substr(1);
|
||||||
|
|
||||||
|
while (text.length) {
|
||||||
|
const element = document.createElement("span");
|
||||||
|
var token_type = "";
|
||||||
|
|
||||||
|
if (whitespace.includes(char))
|
||||||
|
token_type = "whitespace";
|
||||||
|
else if (string_start.includes(char))
|
||||||
|
token_type = "string";
|
||||||
|
|
||||||
|
while (text.length) {
|
||||||
|
if (token_type == "whitespace" && !whitespace.includes(char))
|
||||||
|
break;
|
||||||
|
element.innerText.concat(char);
|
||||||
|
char = text.substr(0, 1); text = text.substr(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
elements.push(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
document.querySelectorAll(".code").forEach(ele => new PythonEditor(ele))
|
||||||
|
});
|
|
@ -0,0 +1,11 @@
|
||||||
|
from http.server import SimpleHTTPRequestHandler
|
||||||
|
|
||||||
|
class MyHandler(SimpleHTTPRequestHandler):
|
||||||
|
extensions_map = {
|
||||||
|
**SimpleHTTPRequestHandler.extensions_map,
|
||||||
|
'.mjs': 'application/javascript',
|
||||||
|
}
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
from http.server import test
|
||||||
|
test(HandlerClass=MyHandler, port=8090)
|
|
@ -0,0 +1,41 @@
|
||||||
|
<!--
|
||||||
|
Kyler Olsen
|
||||||
|
November 2023
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Test</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #001524;
|
||||||
|
}
|
||||||
|
.flex-area {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
width: 95%;
|
||||||
|
}
|
||||||
|
.code {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="editor.css">
|
||||||
|
|
||||||
|
<script src="editor.js" type="module"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="flex-area">
|
||||||
|
<div class="code idle-dark"></div>
|
||||||
|
<div class="code idle-light"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
Loading…
Reference in New Issue