mirror of
https://github.com/JonasunderscoreJones/selfhosted-overleaf-project-share.git
synced 2025-10-24 09:39:19 +02:00
split into multiple files
This commit is contained in:
parent
4667f9393d
commit
0142211c81
3 changed files with 344 additions and 345 deletions
181
public/main.css
Normal file
181
public/main.css
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css');
|
||||
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #1e1e1e;
|
||||
color: white;
|
||||
user-select: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header {
|
||||
height: 40px;
|
||||
background: #1b222c;
|
||||
color: #afb5c0;
|
||||
padding: 0 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #444;
|
||||
font-weight: bold;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.subheader {
|
||||
padding: 0.5rem 1rem;
|
||||
background: #2f3a4c;
|
||||
color: #bbb;
|
||||
font-size: 14px;
|
||||
border-bottom: 3px solid #444;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 200px;
|
||||
background: #495365;
|
||||
border-right: 1px solid #444;
|
||||
overflow-y: auto;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sidebar ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.sidebar li {
|
||||
padding: 0.25rem 1rem;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.sidebar li:hover {
|
||||
background: #2f3a4c;
|
||||
}
|
||||
|
||||
.sidebar li.active {
|
||||
background: #098842;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.editor-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.editor {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.editor pre {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
flex: 1;
|
||||
background: #2d2d2d;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.preview {
|
||||
flex: 1;
|
||||
padding: 0.5rem;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.preview iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.pdf-error {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
padding: 1rem 2rem;
|
||||
border-radius: 6px;
|
||||
display: none;
|
||||
z-index: 10;
|
||||
user-select: none;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
footer {
|
||||
height: 30px;
|
||||
background: #222;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
padding-top: 5px;
|
||||
color: #777;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Draggable separator */
|
||||
#dragbar {
|
||||
width: 10px;
|
||||
cursor: ew-resize;
|
||||
background: #444;
|
||||
flex-shrink: 0;
|
||||
transition: background-color 0.2s ease;
|
||||
user-select: none;
|
||||
}
|
||||
#dragbar:hover {
|
||||
background: #666;
|
||||
}
|
||||
.rounded-button {
|
||||
margin-left: auto;
|
||||
color: white;
|
||||
background-color: #098842;
|
||||
border-radius: 100px;
|
||||
padding: 0.25rem 1rem;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.rounded-button:hover {
|
||||
background-color: #1e6941;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
.left-button {
|
||||
margin-right: auto;
|
||||
margin-left: 0;
|
||||
border-radius: 20px 100px 100px 20px;
|
||||
}
|
||||
.right-button {
|
||||
margin-left: auto;
|
||||
margin-right: 0;
|
||||
border-radius: 100px 20px 20px 100px;
|
||||
}
|
||||
.files-header {
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
161
public/main.js
Normal file
161
public/main.js
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
const projectId = window.location.pathname.split("/")[2];
|
||||
const base = `/projects/${projectId}`;
|
||||
const fileListEl = document.getElementById("file-list");
|
||||
const codeEl = document.getElementById("code");
|
||||
const pdfEl = document.getElementById("pdf");
|
||||
const pdfErrorEl = document.getElementById("pdf-error");
|
||||
|
||||
const sidebarEl = document.querySelector(".sidebar");
|
||||
const editorEl = document.querySelector(".editor");
|
||||
const previewContainerEl = document.querySelector(".preview-container");
|
||||
const dragbar = document.getElementById("dragbar");
|
||||
const mainEl = document.querySelector("main");
|
||||
|
||||
document.getElementById("open-in-editor-button").onclick = () => {
|
||||
window.open(`https://tex.jonasjones.dev/project/${projectId}`, "_blank");
|
||||
};
|
||||
|
||||
// Set project ID in header
|
||||
document.getElementById("project-id").textContent = projectId;
|
||||
|
||||
async function listFiles() {
|
||||
try {
|
||||
const res = await fetch(`${base}/`);
|
||||
if (!res.ok) throw new Error("Failed to fetch file list");
|
||||
const text = await res.text();
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(text, "text/html");
|
||||
const links = Array.from(doc.querySelectorAll("a"));
|
||||
|
||||
const sourceFiles = [];
|
||||
let pdfFiles = [];
|
||||
|
||||
for (const link of links) {
|
||||
const name = link.getAttribute("href");
|
||||
if (!name) continue;
|
||||
if (name === '../' || name.endsWith('/')) continue;
|
||||
if (/\.(tex|bib|cls|sty|txt)$/i.test(name)) {
|
||||
sourceFiles.push(name);
|
||||
} else if (name.toLowerCase().endsWith(".pdf")) {
|
||||
pdfFiles.push(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceFiles.length === 0) {
|
||||
codeEl.textContent = "// No source files found.";
|
||||
}
|
||||
|
||||
// Add files to sidebar WITHOUT numbering
|
||||
sourceFiles.forEach((file, idx) => {
|
||||
const li = document.createElement("li");
|
||||
li.textContent = file;
|
||||
if (idx === 0) li.classList.add("active");
|
||||
li.onclick = () => {
|
||||
document.querySelectorAll(".sidebar li").forEach(el => el.classList.remove("active"));
|
||||
li.classList.add("active");
|
||||
loadSourceFile(file);
|
||||
};
|
||||
fileListEl.appendChild(li);
|
||||
});
|
||||
|
||||
if (sourceFiles.length > 0) {
|
||||
loadSourceFile(sourceFiles[0]);
|
||||
}
|
||||
|
||||
// PDF fallback: output.pdf > main.pdf > any .pdf
|
||||
let pdfToLoad = pdfFiles.find(f => f.toLowerCase() === "output.pdf")
|
||||
|| pdfFiles.find(f => f.toLowerCase() === "main.pdf")
|
||||
|| pdfFiles[0];
|
||||
|
||||
if (pdfToLoad) {
|
||||
loadPDF(pdfToLoad);
|
||||
document.getElementById("download-pdf-button").href = pdfToLoad;
|
||||
} else {
|
||||
showPDFError(true);
|
||||
document.getElementById("download-pdf-button").style.display = "none";
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
codeEl.textContent = `// Error loading file list: ${err.message}`;
|
||||
showPDFError(true);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadSourceFile(file) {
|
||||
try {
|
||||
const res = await fetch(`${base}/${file}`);
|
||||
if (!res.ok) throw new Error("Failed to load file");
|
||||
const content = await res.text();
|
||||
|
||||
codeEl.textContent = content;
|
||||
|
||||
// Change prism language class based on file extension
|
||||
const ext = file.split('.').pop().toLowerCase();
|
||||
codeEl.className = `language-${ext === "tex" ? "latex" : ext}`;
|
||||
Prism.highlightElement(codeEl);
|
||||
} catch (err) {
|
||||
codeEl.textContent = `// Error loading file: ${err.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
function loadPDF(pdfFile) {
|
||||
showPDFError(false);
|
||||
pdfEl.src = `${base}/${pdfFile}`;
|
||||
}
|
||||
|
||||
function showPDFError(show) {
|
||||
pdfErrorEl.style.display = show ? "block" : "none";
|
||||
if (show) {
|
||||
pdfEl.style.display = "none";
|
||||
} else {
|
||||
pdfEl.style.display = "block";
|
||||
}
|
||||
}
|
||||
|
||||
pdfEl.onerror = () => {
|
||||
showPDFError(true);
|
||||
};
|
||||
|
||||
pdfEl.onload = () => {
|
||||
showPDFError(false);
|
||||
};
|
||||
|
||||
// Draggable vertical separator
|
||||
let isDragging = false;
|
||||
|
||||
dragbar.addEventListener("mousedown", e => {
|
||||
isDragging = true;
|
||||
document.body.style.cursor = "ew-resize";
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
window.addEventListener("mouseup", e => {
|
||||
if (isDragging) {
|
||||
isDragging = false;
|
||||
document.body.style.cursor = "";
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("mousemove", e => {
|
||||
if (!isDragging) return;
|
||||
|
||||
const containerRect = mainEl.getBoundingClientRect();
|
||||
|
||||
const sidebarWidth = sidebarEl.offsetWidth;
|
||||
const availableWidth = containerRect.width - sidebarWidth - dragbar.offsetWidth;
|
||||
|
||||
let newEditorWidth = e.clientX - containerRect.left - sidebarWidth;
|
||||
newEditorWidth = Math.max(200, Math.min(newEditorWidth, availableWidth - 200));
|
||||
|
||||
if (availableWidth - newEditorWidth < 415) {
|
||||
newEditorWidth = availableWidth - 415;
|
||||
}
|
||||
|
||||
editorEl.style.flex = "none";
|
||||
previewContainerEl.style.flex = "none";
|
||||
|
||||
editorEl.style.width = newEditorWidth + "px";
|
||||
previewContainerEl.style.width = (availableWidth - newEditorWidth) + "px";
|
||||
});
|
||||
|
||||
listFiles();
|
||||
|
|
@ -5,188 +5,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Project Viewer</title>
|
||||
<link rel="stylesheet" href="/prism.css" />
|
||||
<style>
|
||||
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css');
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #1e1e1e;
|
||||
color: white;
|
||||
user-select: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header {
|
||||
height: 40px;
|
||||
background: #1b222c;
|
||||
color: #afb5c0;
|
||||
padding: 0 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #444;
|
||||
font-weight: bold;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.subheader {
|
||||
padding: 0.5rem 1rem;
|
||||
background: #2f3a4c;
|
||||
color: #bbb;
|
||||
font-size: 14px;
|
||||
border-bottom: 3px solid #444;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 200px;
|
||||
background: #495365;
|
||||
border-right: 1px solid #444;
|
||||
overflow-y: auto;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sidebar ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.sidebar li {
|
||||
padding: 0.25rem 1rem;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.sidebar li:hover {
|
||||
background: #2f3a4c;
|
||||
}
|
||||
|
||||
.sidebar li.active {
|
||||
background: #098842;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.editor-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.editor {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.editor pre {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
flex: 1;
|
||||
background: #2d2d2d;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.preview {
|
||||
flex: 1;
|
||||
padding: 0.5rem;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.preview iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.pdf-error {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
padding: 1rem 2rem;
|
||||
border-radius: 6px;
|
||||
display: none;
|
||||
z-index: 10;
|
||||
user-select: none;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
footer {
|
||||
height: 30px;
|
||||
background: #222;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
padding-top: 5px;
|
||||
color: #777;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Draggable separator */
|
||||
#dragbar {
|
||||
width: 10px;
|
||||
cursor: ew-resize;
|
||||
background: #444;
|
||||
flex-shrink: 0;
|
||||
transition: background-color 0.2s ease;
|
||||
user-select: none;
|
||||
}
|
||||
#dragbar:hover {
|
||||
background: #666;
|
||||
}
|
||||
.rounded-button {
|
||||
margin-left: auto;
|
||||
color: white;
|
||||
background-color: #098842;
|
||||
border-radius: 100px;
|
||||
padding: 0.25rem 1rem;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.rounded-button:hover {
|
||||
background-color: #1e6941;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
.left-button {
|
||||
margin-right: auto;
|
||||
margin-left: 0;
|
||||
border-radius: 20px 100px 100px 20px;
|
||||
}
|
||||
.right-button {
|
||||
margin-left: auto;
|
||||
margin-right: 0;
|
||||
border-radius: 100px 20px 20px 100px;
|
||||
}
|
||||
.files-header {
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/main.css" />
|
||||
</head>
|
||||
<body>
|
||||
<header><a id="header-content"><a>LaTeX Project Viewer (Read-only) -</a><a id="project-id" style="margin-left: 3px;"></a><a id="open-in-editor-button" class="rounded-button">Open in Editor <svg xmlns="http://www.w3.org/2000/svg" width="11px" height="11px" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path fill="#ffffff" d="M320 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l82.7 0L201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L448 109.3l0 82.7c0 17.7 14.3 32 32 32s32-14.3 32-32l0-160c0-17.7-14.3-32-32-32L320 0zM80 32C35.8 32 0 67.8 0 112L0 432c0 44.2 35.8 80 80 80l320 0c44.2 0 80-35.8 80-80l0-112c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 112c0 8.8-7.2 16-16 16L80 448c-8.8 0-16-7.2-16-16l0-320c0-8.8 7.2-16 16-16l112 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L80 32z"/></svg></a></a></header>
|
||||
|
|
@ -220,168 +39,6 @@
|
|||
<footer>Static viewer for LaTeX projects - by Jonas_Jones</footer>
|
||||
|
||||
<script src="/prism.js"></script>
|
||||
<script>
|
||||
const projectId = window.location.pathname.split("/")[2];
|
||||
const base = `/projects/${projectId}`;
|
||||
const fileListEl = document.getElementById("file-list");
|
||||
const codeEl = document.getElementById("code");
|
||||
const pdfEl = document.getElementById("pdf");
|
||||
const pdfErrorEl = document.getElementById("pdf-error");
|
||||
|
||||
const sidebarEl = document.querySelector(".sidebar");
|
||||
const editorEl = document.querySelector(".editor");
|
||||
const previewContainerEl = document.querySelector(".preview-container");
|
||||
const dragbar = document.getElementById("dragbar");
|
||||
const mainEl = document.querySelector("main");
|
||||
|
||||
document.getElementById("open-in-editor-button").onclick = () => {
|
||||
window.open(`https://tex.jonasjones.dev/project/${projectId}`, "_blank");
|
||||
};
|
||||
|
||||
// Set project ID in header
|
||||
document.getElementById("project-id").textContent = projectId;
|
||||
|
||||
async function listFiles() {
|
||||
try {
|
||||
const res = await fetch(`${base}/`);
|
||||
if (!res.ok) throw new Error("Failed to fetch file list");
|
||||
const text = await res.text();
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(text, "text/html");
|
||||
const links = Array.from(doc.querySelectorAll("a"));
|
||||
|
||||
const sourceFiles = [];
|
||||
let pdfFiles = [];
|
||||
|
||||
for (const link of links) {
|
||||
const name = link.getAttribute("href");
|
||||
if (!name) continue;
|
||||
if (name === '../' || name.endsWith('/')) continue;
|
||||
if (/\.(tex|bib|cls|sty|txt)$/i.test(name)) {
|
||||
sourceFiles.push(name);
|
||||
} else if (name.toLowerCase().endsWith(".pdf")) {
|
||||
pdfFiles.push(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceFiles.length === 0) {
|
||||
codeEl.textContent = "// No source files found.";
|
||||
}
|
||||
|
||||
// Add files to sidebar WITHOUT numbering
|
||||
sourceFiles.forEach((file, idx) => {
|
||||
const li = document.createElement("li");
|
||||
li.textContent = file;
|
||||
if (idx === 0) li.classList.add("active");
|
||||
li.onclick = () => {
|
||||
document.querySelectorAll(".sidebar li").forEach(el => el.classList.remove("active"));
|
||||
li.classList.add("active");
|
||||
loadSourceFile(file);
|
||||
};
|
||||
fileListEl.appendChild(li);
|
||||
});
|
||||
|
||||
if (sourceFiles.length > 0) {
|
||||
loadSourceFile(sourceFiles[0]);
|
||||
}
|
||||
|
||||
// PDF fallback: output.pdf > main.pdf > any .pdf
|
||||
let pdfToLoad = pdfFiles.find(f => f.toLowerCase() === "output.pdf")
|
||||
|| pdfFiles.find(f => f.toLowerCase() === "main.pdf")
|
||||
|| pdfFiles[0];
|
||||
|
||||
if (pdfToLoad) {
|
||||
loadPDF(pdfToLoad);
|
||||
document.getElementById("download-pdf-button").href = pdfToLoad;
|
||||
} else {
|
||||
showPDFError(true);
|
||||
document.getElementById("download-pdf-button").style.display = "none";
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
codeEl.textContent = `// Error loading file list: ${err.message}`;
|
||||
showPDFError(true);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadSourceFile(file) {
|
||||
try {
|
||||
const res = await fetch(`${base}/${file}`);
|
||||
if (!res.ok) throw new Error("Failed to load file");
|
||||
const content = await res.text();
|
||||
|
||||
codeEl.textContent = content;
|
||||
|
||||
// Change prism language class based on file extension
|
||||
const ext = file.split('.').pop().toLowerCase();
|
||||
codeEl.className = `language-${ext === "tex" ? "latex" : ext}`;
|
||||
Prism.highlightElement(codeEl);
|
||||
} catch (err) {
|
||||
codeEl.textContent = `// Error loading file: ${err.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
function loadPDF(pdfFile) {
|
||||
showPDFError(false);
|
||||
pdfEl.src = `${base}/${pdfFile}`;
|
||||
}
|
||||
|
||||
function showPDFError(show) {
|
||||
pdfErrorEl.style.display = show ? "block" : "none";
|
||||
if (show) {
|
||||
pdfEl.style.display = "none";
|
||||
} else {
|
||||
pdfEl.style.display = "block";
|
||||
}
|
||||
}
|
||||
|
||||
pdfEl.onerror = () => {
|
||||
showPDFError(true);
|
||||
};
|
||||
|
||||
pdfEl.onload = () => {
|
||||
showPDFError(false);
|
||||
};
|
||||
|
||||
// Draggable vertical separator
|
||||
let isDragging = false;
|
||||
|
||||
dragbar.addEventListener("mousedown", e => {
|
||||
isDragging = true;
|
||||
document.body.style.cursor = "ew-resize";
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
window.addEventListener("mouseup", e => {
|
||||
if (isDragging) {
|
||||
isDragging = false;
|
||||
document.body.style.cursor = "";
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("mousemove", e => {
|
||||
if (!isDragging) return;
|
||||
|
||||
const containerRect = mainEl.getBoundingClientRect();
|
||||
|
||||
const sidebarWidth = sidebarEl.offsetWidth;
|
||||
const availableWidth = containerRect.width - sidebarWidth - dragbar.offsetWidth;
|
||||
|
||||
let newEditorWidth = e.clientX - containerRect.left - sidebarWidth;
|
||||
newEditorWidth = Math.max(200, Math.min(newEditorWidth, availableWidth - 200));
|
||||
|
||||
if (availableWidth - newEditorWidth < 415) {
|
||||
newEditorWidth = availableWidth - 415;
|
||||
}
|
||||
|
||||
editorEl.style.flex = "none";
|
||||
previewContainerEl.style.flex = "none";
|
||||
|
||||
editorEl.style.width = newEditorWidth + "px";
|
||||
previewContainerEl.style.width = (availableWidth - newEditorWidth) + "px";
|
||||
});
|
||||
|
||||
listFiles();
|
||||
</script>
|
||||
<script src="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue