paste-bin/templates/index.html
Jarian Cottingham 3bc5c16c5d fix: HSTS (#29), CSP (#30), server version (#34), favicon (#35), aria (#36,#37), cleanup loop (#1), startup dirs (#16), health check (#27), docker-compose (#19,#20)
- Add HSTS, CSP headers, remove Server header, fix GIF magic tuple
- Add ARIA landmarks, button labels, inline SVG favicon
- Scheduled cleanup loop (every 5min), /health endpoint
- Remove docker-compose version field, unused named volumes
- Move ensure_dirs to startup, remove duplicate definitions
2026-07-05 04:32:07 +00:00

137 lines
6.3 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PasteBin</title>
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ctext y='.9em' font-size='90'%3E📋%3C/text%3E%3C/svg%3E">
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<div class="container" role="main">
<header>
<h1><a href="/">PasteBin</a></h1>
<p>Share text, images, and files temporarily</p>
</header>
{% if error %}
<div class="error">{{ error }}</div>
{% endif %}
<div class="tabs">
<button class="tab active" data-tab="text" aria-label="Text paste tab" aria-selected="true">Text</button>
<button class="tab" data-tab="image" aria-label="Image paste tab" aria-selected="false">Image</button>
<button class="tab" data-tab="file" aria-label="File paste tab" aria-selected="false">File</button>
</div>
<form method="POST" action="/paste" enctype="multipart/form-data" id="uploadForm">
<input type="hidden" name="paste_type" id="pasteType" value="text">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<div class="form-group">
<label for="title">Title (optional)</label>
<input type="text" id="title" name="title" placeholder="Give your paste a name">
</div>
<div id="text-panel" class="panel active">
<div class="form-group">
<label for="content">Content</label>
<textarea id="content" name="content" placeholder="Paste your text here..." rows="12"></textarea>
</div>
</div>
<div id="image-panel" class="panel">
<div class="form-group">
<label id="file-label">Image (max 20 MB)</label>
<div class="file-input">
<input type="file" id="upload-file" name="file" accept="image/png,image/jpeg,image/gif,image/bmp,image/webp,image/svg+xml,image/tiff" style="display:none">
<label for="upload-file" class="file-label">
<span class="file-icon" id="file-icon">&#128247;</span>
<span class="file-text" id="file-text">Choose image or drag here</span>
</label>
<span id="chosen-filename" class="chosen-file"></span>
</div>
</div>
</div>
<div id="file-panel" class="panel">
<div class="form-group">
<label id="file-label2">File (max 20 MB)</label>
<div class="file-input">
<span class="file-icon">&#128100;</span>
<span class="file-text" id="file-text2">Choose file or drag here</span>
<span id="chosen-filename2" class="chosen-file"></span>
</div>
</div>
</div>
<div class="form-group">
<label for="expiry">Expires</label>
<select id="expiry" name="expiry">
{% for key, label in expiry_options %}
<option value="{{ key }}" {% if key == '1d' %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
</div>
<button type="submit" class="submit-btn">Create Paste</button>
</form>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const tabs = document.querySelectorAll('.tab');
const panels = document.querySelectorAll('.panel');
const pasteTypeInput = document.getElementById('pasteType');
const uploadFile = document.getElementById('upload-file');
const uploadFile2 = document.getElementById('upload-file2');
const chosenFilename = document.getElementById('chosen-filename');
const chosenFilename2 = document.getElementById('chosen-filename2');
const fileIcon = document.getElementById('file-icon');
const fileText = document.getElementById('file-text');
const fileLabel = document.getElementById('file-label');
const contentTextarea = document.getElementById('content');
function switchTab(tabName) {
tabs.forEach(t => t.classList.remove('active'));
panels.forEach(p => p.classList.remove('active'));
document.querySelector('[data-tab="' + tabName + '"]').classList.add('active');
document.getElementById(tabName + '-panel').classList.add('active');
pasteTypeInput.value = tabName;
uploadFile.setAttribute('name', '__unused__');
contentTextarea.setAttribute('name', '__unused__');
if (tabName === 'text') {
contentTextarea.setAttribute('name', 'content');
} else if (tabName === 'image') {
uploadFile.setAttribute('name', 'file');
uploadFile.setAttribute('accept', 'image/png,image/jpeg,image/gif,image/bmp,image/webp,image/tiff');
fileIcon.innerHTML = '&#128247;';
fileText.textContent = 'Choose image or drag here';
fileLabel.textContent = 'Image (max 20 MB)';
} else if (tabName === 'file') {
uploadFile.setAttribute('name', 'file');
uploadFile.removeAttribute('accept');
}
}
tabs.forEach(tab => {
tab.addEventListener('click', function() {
switchTab(this.dataset.tab);
});
});
uploadFile.addEventListener('change', function() {
chosenFilename.textContent = this.files[0] ? this.files[0].name : '';
chosenFilename2.textContent = '';
});
uploadFile2.addEventListener('change', function() {
chosenFilename2.textContent = this.files[0] ? this.files[0].name : '';
chosenFilename.textContent = '';
});
});
</script>
</body>
</html>