bastebin/templates/view.html

129 lines
4.8 KiB
HTML

{% extends "base.html" %}
{% block title %}{{ cfg.site.name }}{% endblock %}
{% block main_class %}full-page{% endblock %}
{% block nav_actions %}
<span id="navPasteTitle" class="nav-paste-title"></span>
<button onclick="rawView()" class="nav-btn">Raw</button>
<button onclick="copyPaste()" class="nav-btn">Copy</button>
<button onclick="downloadPaste()" class="nav-btn">Download</button>
<a href="{{ url_for('index') }}" class="nav-btn nav-btn-save">New</a>
{% if cfg.theme.allow_user_toggle %}
<button class="theme-toggle" onclick="toggleTheme()">🌙</button>
{% endif %}
{% endblock %}
{% block content %}
<div id="errorState" class="error-inline" style="display:none">
🔐 <strong id="errorTitle">Decryption Failed</strong><span id="errorDetail"></span>
</div>
<div class="view-full" id="viewFull" style="display:none">
<pre id="viewPre"><code id="codeBlock"></code></pre>
</div>
<script type="application/json" id="encryptedPayload">{{ paste.encrypted_data | tojson }}</script>
{% endblock %}
{% block scripts %}
<script>
let _decryptedPaste = null;
const E2E = {{ cfg.features.encrypt_pastes | tojson }};
(async function () {
let rawPayload;
try {
rawPayload = JSON.parse(document.getElementById('encryptedPayload').textContent);
} catch (e) {
showError('Bad Data', 'Could not read the paste payload.');
return;
}
if (E2E) {
const keyBase64 = window.location.hash.slice(1);
if (!keyBase64) {
showError('No Key', 'The decryption key is missing from the URL. Use the full link including the # part.');
return;
}
try {
const key = await PasteCrypto.importKey(keyBase64);
const plaintext = await PasteCrypto.decrypt(rawPayload, key);
_decryptedPaste = JSON.parse(plaintext);
} catch (e) {
showError('Decryption Failed', 'Wrong key or tampered data.');
return;
}
} else {
try {
_decryptedPaste = JSON.parse(rawPayload);
} catch (e) {
showError('Bad Data', 'Could not parse paste data.');
return;
}
}
renderPaste(_decryptedPaste);
})();
function renderPaste(paste) {
const title = paste.title || 'Untitled';
document.title = title + ' — {{ cfg.site.name }}';
document.getElementById('navPasteTitle').textContent = title;
const lang = paste.language || 'text';
const prismLangMap = { text: false, html: 'markup', xml: 'markup', docker: 'docker' };
const prismLang = (lang in prismLangMap) ? prismLangMap[lang] : lang;
const codeBlock = document.getElementById('codeBlock');
const viewPre = document.getElementById('viewPre');
codeBlock.textContent = paste.content || '';
if (prismLang) {
codeBlock.className = 'language-' + prismLang;
viewPre.className = 'language-' + prismLang;
Prism.highlightElement(codeBlock);
}
document.getElementById('viewFull').style.display = 'block';
}
function showError(title, detail) {
document.getElementById('errorTitle').textContent = title;
document.getElementById('errorDetail').textContent = detail;
document.getElementById('errorState').style.display = 'block';
}
function rawView() {
if (!_decryptedPaste) return;
const blob = new Blob([_decryptedPaste.content], { type: 'text/plain; charset=utf-8' });
const url = URL.createObjectURL(blob);
window.open(url, '_blank');
setTimeout(() => URL.revokeObjectURL(url), 10000);
}
async function copyPaste() {
if (!_decryptedPaste) return;
const ok = await copyToClipboard(_decryptedPaste.content);
const btn = document.querySelector('.nav-btn[onclick="copyPaste()"]');
if (btn) { const t = btn.textContent; btn.textContent = ok ? 'Copied!' : 'Failed'; setTimeout(() => btn.textContent = t, 1500); }
}
function downloadPaste() {
if (!_decryptedPaste) return;
const { title = 'untitled', content = '', language = 'text' } = _decryptedPaste;
const extMap = {
javascript: '.js', typescript: '.ts', python: '.py', java: '.java',
c: '.c', cpp: '.cpp', csharp: '.cs', html: '.html', css: '.css',
scss: '.scss', sql: '.sql', json: '.json', yaml: '.yaml', xml: '.xml',
bash: '.sh', powershell: '.ps1', php: '.php', ruby: '.rb', go: '.go',
rust: '.rs', swift: '.swift', kotlin: '.kt', markdown: '.md',
diff: '.diff', docker: '', nginx: '.conf', toml: '.toml', ini: '.ini',
};
const filename = title.replace(/[^a-z0-9.\-]/gi, '_') + (extMap[language] ?? '.txt');
const blob = new Blob([content], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = Object.assign(document.createElement('a'), { href: url, download: filename });
document.body.appendChild(a); a.click(); document.body.removeChild(a);
URL.revokeObjectURL(url);
}
</script>
{% endblock %}