import { statSync } from 'fs'; import { join } from 'path'; // Get cache-busting query parameter function getCacheBuster() { const isDev = process.env.NODE_ENV === 'development'; const distDir = join(import.meta.dirname, '../dist'); const bundleFilename = isDev ? 'editor.bundle.dev.js' : 'editor.bundle.prod.js'; // Use file modification time for cache busting // This provides a stable value that only changes when the bundle is rebuilt try { const stats = statSync(join(distDir, bundleFilename)); return `v=${stats.mtime.getTime()}`; } catch { // Fallback if bundle file doesn't exist yet return `v=${Date.now()}`; } } function escapeHtml(str) { return str .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } function truncateMiddle(str, maxLength = 90) { if (str.length <= maxLength) return str; if (maxLength <= 1) return '…'; const remaining = maxLength - 1; const head = Math.ceil(remaining / 2); const tail = Math.floor(remaining / 2); return `${str.slice(0, head)}…${str.slice(-tail)}`; } function renderUploadsTable(uploads, documentPath) { const renderUploadRow = (upload) => { const isHidden = upload.hidden; const uploadUrl = documentPath === '/' ? `/uploads/${encodeURIComponent(upload.original_filename)}` : `${documentPath}/uploads/${encodeURIComponent(upload.original_filename)}`; return ` ${escapeHtml(upload.original_filename)} ${new Date(upload.created_at).toLocaleDateString()} `; }; const rows = uploads.map(upload => renderUploadRow(upload)).join(''); const emptyState = uploads.length === 0 ? 'No uploads yet. Drag and drop files or use the upload button below.' : ''; return `
${rows}${emptyState}
Filename Date

You can also drag and drop files onto any editor panel

`; } function renderRedirectsTable(redirects) { const rows = redirects .map(redirect => ` ${escapeHtml(redirect.path)} ${new Date(redirect.created_at).toLocaleDateString()} `) .join(''); const emptyState = redirects.length === 0 ? 'No redirects yet. Add old paths below that should redirect to this document.' : ''; return `
${rows}${emptyState}
Old Path Date
`; } export function htmlEditorPage(options) { const { state, fallbackPath } = options; // Handle non-existent documents - create default state const clientState = state || { document: { id: 0, // New document without ID yet path: fallbackPath || '/', published: false, title: '', content: '', data: '{}', style: '', script: '', server: '', template_id: null, slot_id: null, mime_type: 'text/html; charset=UTF-8', extension: '.html', content_type: 'markdown', data_type: null, has_eta: false, created_at: new Date(), updated_at: new Date(), uploads: [], redirects: [], draft: false, template: undefined, slot: undefined, }, render: { html: '' }, api: [], }; const api = clientState.api; const document = clientState.document; const cacheBuster = getCacheBuster(); // For text/plain documents, wrap content in proper HTML for preview let renderHtml = clientState.render.html; if (document.mime_type?.startsWith('text/plain')) { const escaped = renderHtml.replace(/&/g, '&').replace(//g, '>'); renderHtml = ` ${escaped} `; } const html = ` ${escapeHtml(document.path)}

General

${document.template?.title && document.template?.path ? ` ` : ''}
${document.slot?.title && document.slot?.path ? ` ` : ''}

Content type for the document (e.g., application/xml)

File extension for content (e.g., .xml, .svg, .csv, .vcard)

Uploads

${renderUploadsTable((document.uploads || []), document.path)}

Redirects

${renderRedirectsTable((document.redirects || []))}

Old paths that redirect (301) to this document's current path

Browser

These settings are stored in your browser's local storage.

Wrap long lines in the editor (Ctrl+\\)

Danger Zone

Delete this document
Once you delete a document, there is no going back. Please be certain.
Sign out
Sign out of your current session.
`; return new Response(html, { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8', }, }); } //# sourceMappingURL=htmlEditorPage.js.map