2024-09-17 11:21:21 -05:00
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "UTF-8" / >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" / >
< title > SneedCode - Code Editor< / title >
< style >
body,
html {
margin: 0;
padding: 0;
height: 100%;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
"Helvetica Neue", sans-serif;
}
.container {
display: flex;
2024-09-18 11:50:37 -05:00
height: 97.4%;
2024-09-17 11:21:21 -05:00
}
.sidebar {
2024-09-18 11:53:07 -05:00
width: 6.9%;
2024-09-17 11:21:21 -05:00
background-color: #333;
display: flex;
flex-direction: column;
align-items: center;
padding-top: 10px;
}
.sidebar-icon {
2024-09-18 11:52:25 -05:00
width: 64%;
2024-09-18 11:47:00 -05:00
height: auto;
2024-09-17 11:21:21 -05:00
margin-bottom: 20px;
cursor: pointer;
transition: background-color 0.3s;
padding: 5px;
border-radius: 5px;
}
.sidebar-icon:hover {
background-color: #4a4a4a;
}
.main-content {
flex: 1;
display: flex;
}
.file-explorer {
2024-09-18 11:53:07 -05:00
width: 24%;
2024-09-17 11:21:21 -05:00
background-color: #252526;
color: #fff;
padding: 10px;
overflow-y: auto;
transition: width 0.3s ease;
}
.file-explorer.hidden {
width: 0;
padding: 0;
overflow: hidden;
}
.file-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 5px;
cursor: pointer;
}
.file-item:hover {
background-color: #2a2d2e;
}
.file-actions {
display: none;
}
.file-item:hover .file-actions {
display: block;
}
.file-action {
cursor: pointer;
margin-left: 5px;
}
.editor {
flex: 1;
background-color: #1e1e1e;
padding: 10px;
}
.CodeMirror {
height: 100% !important;
}
.status-bar {
2024-09-18 11:50:37 -05:00
height: 2%;
2024-09-17 11:21:21 -05:00
background-color: #007acc;
color: #fff;
display: flex;
align-items: center;
2024-09-18 11:44:05 -05:00
padding: .3vw;
2024-09-18 11:49:07 -05:00
font-size: 1em;
2024-09-17 11:21:21 -05:00
}
#toggle-explorer {
transition: transform 0.3s ease;
}
#toggle-explorer.flipped {
transform: rotate(180deg);
}
< / style >
< link
rel="stylesheet"
2024-09-18 08:09:39 -05:00
href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/codemirror.min.css"
2024-09-17 11:21:21 -05:00
/>
< link
rel="stylesheet"
2024-09-18 08:09:39 -05:00
href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/theme/dracula.min.css"
2024-09-17 11:21:21 -05:00
/>
< / head >
< body >
< div class = "container" >
< div class = "sidebar" >
2024-09-17 19:05:24 -05:00
< svg
class="about-icon"
2024-09-17 11:21:21 -05:00
viewBox="0 0 24 24"
fill="#fff"
2024-09-17 19:05:24 -05:00
id="file-icon"
onclick="alert('sneedCode. Made by Sneed Group with love. Licensed under the SPL-R5')"
2024-09-17 11:21:21 -05:00
>
2024-09-17 19:05:24 -05:00
< path
d="M3 3v18h18V3H3zm16 16H5V5h14v14zM7 7h2v2H7V7zm4 0h2v2h-2V7zm4 0h2v2h-2V7z"
/>
2024-09-17 11:21:21 -05:00
< / svg >
< svg
class="sidebar-icon"
viewBox="0 0 24 24"
fill="#fff"
2024-09-17 19:05:24 -05:00
id="toggle-explorer"
2024-09-17 11:21:21 -05:00
>
2024-09-17 19:05:24 -05:00
< path d = "M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" / >
2024-09-17 11:21:21 -05:00
< / svg >
2024-09-17 19:05:24 -05:00
< hr >
2024-09-17 11:21:21 -05:00
< svg
class="sidebar-icon"
viewBox="0 0 24 24"
fill="#fff"
id="new-file-icon"
>
< path
d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zM6 20V4h7v5h5v11H6z"
/>
< path d = "M13 11h-2v3H8v2h3v3h2v-3h3v-2h-3z" / >
< / svg >
< svg
class="sidebar-icon"
viewBox="0 0 24 24"
fill="#fff"
id="save-icon"
>
< path
d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"
/>
< / svg >
< svg
class="sidebar-icon"
viewBox="0 0 24 24"
fill="#fff"
id="save-as-icon"
>
< path
d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"
/>
< g transform = "translate(15, 15) scale(0.5)" >
< rect
x="0"
y="0"
width="14"
height="14"
fill="#333"
rx="2"
ry="2"
/>
< path d = "M6 2v4H2v2h4v4h2V8h4V6H8V2H6z" fill = "#fff" / >
< / g >
< / svg >
< svg
class="sidebar-icon"
viewBox="0 0 24 24"
fill="#fff"
id="open-file-icon"
>
< path
d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zM6 20V4h7v5h5v11H6z"
/>
< / svg >
< svg
class="sidebar-icon"
viewBox="0 0 24 24"
fill="#fff"
id="open-folder-icon"
>
< path
d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"
/>
< / svg >
2024-09-17 19:05:24 -05:00
< hr >
2024-09-17 18:31:55 -05:00
< svg
class="sidebar-icon"
viewBox="0 0 24 24"
fill="#fff"
id="open-plugin-icon"
>
< path d = "M15 10H9v5h6v-5zM21 4h-4V2H7v2H3c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM7 4h10v2H7V4zm12 16H5V8h14v12z" / >
< / svg >
< svg
class="sidebar-icon"
viewBox="0 0 24 24"
fill="#fff"
id="open-folder-plugins-icon"
>
< path d = "M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z" / >
< / svg >
2024-09-17 11:21:21 -05:00
< / div >
< div class = "main-content" >
< div class = "file-explorer" >
< h3 > Explorer< / h3 >
< div id = "file-list" > < / div >
< / div >
< div class = "editor" >
< textarea id = "code-area" spellcheck = "false" > < / textarea >
< / div >
< / div >
< / div >
< div class = "status-bar" > SneedCode 1.0.0 | UTF-8 | Markdown< / div >
2024-09-18 08:09:39 -05:00
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/codemirror.min.js" > < / script >
2024-09-18 08:39:46 -05:00
2024-09-18 11:44:05 -05:00
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/markdown/markdown.min.js" > < / script >
2024-09-18 08:09:39 -05:00
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/javascript/javascript.min.js" > < / script >
2024-09-18 08:39:46 -05:00
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/xml/xml.min.js" > < / script >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/css/css.min.js" > < / script >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/go/go.min.js" > < / script >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/python/python.min.js" > < / script >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/json/json.min.js" > < / script >
2024-09-18 08:09:39 -05:00
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/htmlmixed/htmlmixed.min.js" > < / script >
2024-09-18 10:33:42 -05:00
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/shell/shell.min.js" > < / script >
2024-09-18 11:15:28 -05:00
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/vbscript/vbscript.min.js" > < / script >
2024-09-18 10:33:42 -05:00
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/powershell/powershell.min.js" > < / script >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/php/php.min.js" > < / script >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/clike/clike.min.js" > < / script >
2024-09-18 10:48:51 -05:00
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/ruby/ruby.min.js" > < / script >
2024-09-18 11:15:28 -05:00
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/vb/vb.min.js" > < / script >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/lua/lua.min.js" > < / script >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.17/mode/swift/swift.min.js" > < / script >
2024-09-18 08:39:46 -05:00
2024-09-17 11:21:21 -05:00
< script >
document.addEventListener("DOMContentLoaded", () => {
2024-09-17 19:41:33 -05:00
codeArea = document.getElementById("code-area");
editor = CodeMirror.fromTextArea(codeArea, {
2024-09-17 11:21:21 -05:00
lineNumbers: true,
theme: "dracula",
autoCloseBrackets: true,
matchBrackets: true,
2024-09-18 10:33:42 -05:00
indentUnit: 1,
tabSize: 4,
indentWithTabs: true,
2024-09-17 11:21:21 -05:00
lineWrapping: true,
});
editor.setSize("100%", "100%");
2024-09-17 19:41:33 -05:00
fileList = document.getElementById("file-list");
files = {
2024-09-17 11:21:21 -05:00
"Welcome2SneedCode.md":
2024-09-18 10:33:42 -05:00
"# Welcome to sneedCode\n\nThis is a speedy web-based code editor made \n to look familiar to the user but with a different workflow. \n\n Made with < 3 by the Sneed Group . " ,
2024-09-17 11:21:21 -05:00
};
2024-09-17 19:41:33 -05:00
currentFile = "Welcome2SneedCode.md";
2024-09-17 11:21:21 -05:00
function updateFileList() {
fileList.innerHTML = "";
Object.keys(files).forEach((fileName) => {
const fileItem = document.createElement("div");
fileItem.className = "file-item";
fileItem.innerHTML = `
< span > ${fileName}< / span >
< span class = "file-actions" >
< span class = "file-action" onclick = "renameFile('${fileName}')" > 🖊️< / span >
< span class = "file-action" onclick = "deleteFile('${fileName}')" > 🗑️< / span >
< / span >
`;
fileItem.onclick = (e) => {
if (!e.target.classList.contains("file-action")) {
openFile(fileName);
}
};
fileList.appendChild(fileItem);
});
}
2024-09-18 08:54:19 -05:00
funcUpdateList = updateFileList;
2024-09-17 11:21:21 -05:00
function openFile(fileName) {
currentFile = fileName;
editor.setValue(files[fileName]);
editor.setOption("mode", getFileMode(fileName));
updateStatusBar();
}
2024-09-18 08:54:19 -05:00
funcOpenFile = openFile;
2024-09-17 11:21:21 -05:00
function getFileMode(fileName) {
const extension = fileName.split(".").pop().toLowerCase();
switch (extension) {
case "js":
return "javascript";
case "html":
2024-09-18 08:39:46 -05:00
return "htmlmixed";
2024-09-17 11:21:21 -05:00
case "css":
return "css";
case "md":
2024-09-18 11:44:05 -05:00
return "markdown";
2024-09-18 08:24:41 -05:00
case "go":
2024-09-18 08:19:19 -05:00
return "go";
2024-09-18 10:33:42 -05:00
case "c":
return "clike";
2024-09-18 08:19:19 -05:00
case "cpp":
2024-09-18 10:33:42 -05:00
return "clike";
2024-09-18 08:19:19 -05:00
case "h":
2024-09-18 10:33:42 -05:00
return "clike";
2024-09-18 11:15:28 -05:00
case "java":
return "clike";
case "javap":
return "clike";
case "class":
return "clike";
case "kt":
return "clike";
case "swift":
return "swift";
case "cs":
return "clike";
2024-09-18 08:19:19 -05:00
case "json":
return "json";
case "xml":
return "xml";
case "py":
return "python";
2024-09-18 10:33:42 -05:00
case "sh":
return "shell";
2024-09-18 11:15:28 -05:00
case "vbs":
return "vb";
case "vb":
return "vbnet";
2024-09-18 10:33:42 -05:00
case "ps1":
return "powershell";
case "php":
2024-09-18 10:48:51 -05:00
return "php";
case "rb":
return "ruby";
2024-09-18 11:15:28 -05:00
case "lua":
return "lua";
case "luau":
return "lua";
2024-09-17 11:21:21 -05:00
default:
return "text/plain";
}
}
2024-09-18 10:48:51 -05:00
funcGetMode = getFileMode;
2024-09-18 08:54:19 -05:00
2024-09-17 11:21:21 -05:00
function updateStatusBar() {
const statusBar = document.querySelector(".status-bar");
const mode = editor.getOption("mode");
statusBar.textContent = `SneedCode 1.0.0 | UTF-8 | ${
mode.charAt(0).toUpperCase() + mode.slice(1)
}`;
}
2024-09-18 08:54:19 -05:00
funcUpdateStatusBar = updateStatusBar;
2024-09-17 11:21:21 -05:00
window.renameFile = (oldName) => {
const newName = prompt("Enter new file name:", oldName);
if (newName & & newName !== oldName) {
files[newName] = files[oldName];
delete files[oldName];
if (currentFile === oldName) {
currentFile = newName;
}
updateFileList();
updateStatusBar();
}
};
window.deleteFile = (fileName) => {
2024-09-18 08:43:45 -05:00
if (confirm(`Are you sure you want to delete ${fileName} from the list of files you are working on? (This WILL remove any changes!)`)) {
2024-09-17 11:21:21 -05:00
delete files[fileName];
if (currentFile === fileName) {
currentFile = Object.keys(files)[0] || "";
if (currentFile) {
openFile(currentFile);
} else {
editor.setValue("");
}
}
updateFileList();
}
};
function quickSaveFile(content) {
2024-09-17 19:11:54 -05:00
const fileName = prompt("File name to quick save as:", `${currentFile}`);
if (fileName) {
const blob = new Blob([content], { type: "text/plain" });
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = fileName;
a.click();
URL.revokeObjectURL(a.href);
} else {
alert("No filename provided. Canceling save...")
}
2024-09-17 11:21:21 -05:00
}
2024-09-18 08:54:19 -05:00
funcQuickSave = quickSaveFile;
2024-09-17 11:21:21 -05:00
async function saveAs(content) {
const blob = new Blob([content], { type: "text/plain" });
2024-09-17 18:41:37 -05:00
const extension = currentFile.split(".").pop().toLowerCase();
2024-09-17 11:21:21 -05:00
const fileHandle = await window.showSaveFilePicker({
types: [
{
description: "Source code",
2024-09-17 18:41:37 -05:00
accept: { "text/plain": [`.${extension || "txt"}`] },
2024-09-17 11:21:21 -05:00
},
],
});
const fileStream = await fileHandle.createWritable();
await fileStream.write(blob);
await fileStream.close();
}
2024-09-18 08:54:19 -05:00
funcSaveAs = saveAs
2024-09-17 11:21:21 -05:00
document.getElementById("save-icon").addEventListener("click", () => {
files[currentFile] = editor.getValue();
const srcCode = files[currentFile];
quickSaveFile(srcCode);
});
document
.getElementById("save-as-icon")
.addEventListener("click", () => {
files[currentFile] = editor.getValue();
const srcCode = files[currentFile];
saveAs(srcCode);
});
document
.getElementById("open-file-icon")
.addEventListener("click", () => {
const input = document.createElement("input");
input.type = "file";
input.accept = "*";
input.onchange = (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = (event) => {
files[file.name] = event.target.result;
updateFileList();
openFile(file.name);
};
reader.readAsText(file);
};
input.click();
});
document
.getElementById("open-folder-icon")
.addEventListener("click", () => {
const input = document.createElement("input");
input.type = "file";
input.webkitdirectory = true;
input.onchange = (e) => {
const folderFiles = e.target.files;
for (let i = 0; i < folderFiles.length ; i + + ) {
const file = folderFiles[i];
const reader = new FileReader();
reader.onload = (event) => {
files[file.name] = event.target.result;
updateFileList();
};
reader.readAsText(file);
}
if (folderFiles.length > 0) {
openFile(folderFiles[0].name);
}
};
input.click();
});
document
.getElementById("new-file-icon")
.addEventListener("click", () => {
const fileName = prompt(
"Enter the name of the new file:",
"new_file.js"
);
if (fileName) {
files[fileName] = "";
updateFileList();
openFile(fileName);
}
});
2024-09-17 18:31:55 -05:00
document
.getElementById("open-plugin-icon")
.addEventListener("click", () => {
const input = document.createElement("input");
input.type = "file";
input.accept = ".js";
input.onchange = (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = (event) => {
try {
// Load and execute JavaScript code from the file
new Function(event.target.result)();
alert(`Plugin "${file.name}" executed successfully.`);
} catch (err) {
alert(`Failed to execute plugin "${file.name}": ${err.message}`);
}
};
reader.readAsText(file);
};
input.click();
});
document
.getElementById("open-folder-plugins-icon")
.addEventListener("click", () => {
const input = document.createElement("input");
input.type = "file";
input.webkitdirectory = true;
input.onchange = (e) => {
const folderFiles = e.target.files;
let allFilesLoaded = true;
for (let i = 0; i < folderFiles.length ; i + + ) {
const file = folderFiles[i];
if (file.name.endsWith(".js")) {
const reader = new FileReader();
reader.onload = (event) => {
try {
// Load and execute JavaScript code from the file
new Function(event.target.result)();
console.log(`Plugin "${file.name}" executed successfully.`);
} catch (err) {
console.error(`Failed to execute plugin "${file.name}": ${err.message}`);
allFilesLoaded = false;
}
};
reader.readAsText(file);
}
}
if (allFilesLoaded) {
alert("All plugins executed successfully.");
} else {
alert("Some plugins failed to execute. Check console for details.");
}
};
input.click();
});
2024-09-17 11:21:21 -05:00
editor.on("change", () => {
files[currentFile] = editor.getValue();
});
// Toggle file explorer
2024-09-18 08:54:19 -05:00
toggleExplorer = document.getElementById("toggle-explorer");
fileExplorer = document.querySelector(".file-explorer");
2024-09-17 11:21:21 -05:00
let isExplorerVisible = true;
2024-09-18 08:54:19 -05:00
function te() {
2024-09-17 11:21:21 -05:00
isExplorerVisible = !isExplorerVisible;
fileExplorer.classList.toggle("hidden", !isExplorerVisible);
toggleExplorer.classList.toggle("flipped", !isExplorerVisible);
2024-09-18 08:54:19 -05:00
}
toggleExplorer.addEventListener("click", () => {
te()
2024-09-17 11:21:21 -05:00
});
2024-09-18 08:54:19 -05:00
funcToggleExplorer = te
2024-09-17 11:21:21 -05:00
updateFileList();
openFile("Welcome2SneedCode.md");
});
< / script >
< / body >
< / html >