@@ -21279,16 +21279,106 @@ async function wolfnoteFromCurrentView() {
2127921279 if (!visible) return;
2128021280
2128121281 const pageTitle = document.getElementById('page-title')?.textContent || 'WolfStack';
21282+ const hostname = document.getElementById('hostname-display')?.textContent || '';
2128221283 const timestamp = new Date().toLocaleString();
2128321284 const title = `${pageTitle} — ${timestamp}`;
2128421285
21285- // Clone the visible content and extract meaningful HTML
21286- const clone = visible.cloneNode(true);
21287- // Remove scripts, hidden elements, and buttons to clean up
21288- clone.querySelectorAll('script, style, .modal-overlay, button, .btn').forEach(el => el.remove());
21286+ // Extract clean data from the page instead of raw HTML
21287+ const sections = [];
21288+
21289+ // Extract card contents — each .card is a section
21290+ visible.querySelectorAll('.card').forEach(card => {
21291+ const header = card.querySelector('.card-header h3, .card-header h4');
21292+ const heading = header ? header.textContent.trim() : '';
21293+
21294+ // Extract tables as clean HTML tables
21295+ const tables = card.querySelectorAll('table.data-table, table');
21296+ tables.forEach(tbl => {
21297+ const rows = [];
21298+ tbl.querySelectorAll('thead tr').forEach(tr => {
21299+ const cells = [];
21300+ tr.querySelectorAll('th').forEach(th => {
21301+ const text = th.textContent.trim();
21302+ if (text && text !== 'Actions') cells.push(`<th style="padding:8px 12px;text-align:left;border-bottom:2px solid #444;font-weight:600;font-size:13px;">${escapeHtml(text)}</th>`);
21303+ });
21304+ if (cells.length) rows.push(`<tr style="background:#2a2a3a;">${cells.join('')}</tr>`);
21305+ });
21306+ tbl.querySelectorAll('tbody tr').forEach(tr => {
21307+ const cells = [];
21308+ tr.querySelectorAll('td').forEach((td, i) => {
21309+ // Skip the last column if it's Actions
21310+ const headerRow = tbl.querySelector('thead tr');
21311+ const ths = headerRow ? headerRow.querySelectorAll('th') : [];
21312+ if (ths[i] && ths[i].textContent.trim() === 'Actions') return;
21313+ const text = td.textContent.trim();
21314+ cells.push(`<td style="padding:6px 12px;border-bottom:1px solid #333;font-size:13px;">${escapeHtml(text)}</td>`);
21315+ });
21316+ if (cells.length) rows.push(`<tr>${cells.join('')}</tr>`);
21317+ });
21318+ if (rows.length) {
21319+ sections.push({ heading, html: `<table style="width:100%;border-collapse:collapse;margin:8px 0 16px 0;">${rows.join('')}</table>` });
21320+ }
21321+ });
2128921322
21290- // Get the HTML content, wrapped with margins
21291- const content = `<div style="margin: 16px 20px;"><h2>${escapeHtml(pageTitle)}</h2><p style="color:#888;font-size:12px;">Captured from WolfStack on ${escapeHtml(timestamp)}</p><hr style="border:none;border-top:1px solid #333;margin:12px 0;">${clone.innerHTML}</div>`;
21323+ // If no tables, extract key-value pairs and text content
21324+ if (tables.length === 0) {
21325+ const body = card.querySelector('.card-body');
21326+ if (body) {
21327+ // Look for stat items, grid items, or just text
21328+ const items = [];
21329+ body.querySelectorAll('.stat-item, [class*="stat"], [class*="metric"]').forEach(el => {
21330+ const label = el.querySelector('.stat-label, [class*="label"]');
21331+ const value = el.querySelector('.stat-value, [class*="value"]');
21332+ if (label && value) items.push(`<li><strong>${escapeHtml(label.textContent.trim())}</strong>: ${escapeHtml(value.textContent.trim())}</li>`);
21333+ });
21334+ if (items.length) {
21335+ sections.push({ heading, html: `<ul style="margin:8px 0 16px 0;padding-left:20px;line-height:1.8;">${items.join('')}</ul>` });
21336+ } else {
21337+ // Fallback: extract visible text content
21338+ const text = body.innerText.trim();
21339+ if (text && text.length > 5) {
21340+ sections.push({ heading, html: `<p style="margin:8px 0 16px 0;line-height:1.7;white-space:pre-wrap;">${escapeHtml(text.substring(0, 3000))}</p>` });
21341+ }
21342+ }
21343+ }
21344+ }
21345+ });
21346+
21347+ // If no cards found, extract raw text as fallback
21348+ if (sections.length === 0) {
21349+ const text = visible.innerText.trim();
21350+ if (text) sections.push({ heading: '', html: `<p style="line-height:1.7;white-space:pre-wrap;">${escapeHtml(text.substring(0, 5000))}</p>` });
21351+ }
21352+
21353+ // Build a professional sysadmin report document
21354+ const sectionCount = sections.length;
21355+ const body = sections.map((s, i) =>
21356+ (s.heading ? `<h3 style="margin:28px 0 10px 0;font-size:15px;font-weight:600;color:#e2e8f0;letter-spacing:0.3px;text-transform:uppercase;border-left:3px solid #6366f1;padding-left:12px;">${escapeHtml(s.heading)}</h3>` : '') + s.html +
21357+ (i < sectionCount - 1 ? '<div style="border-bottom:1px solid #1e293b;margin:16px 0;"></div>' : '')
21358+ ).join('');
21359+
21360+ const content = `<div style="max-width:800px;margin:0 auto;padding:36px 44px;font-family:'SF Mono',SFMono-Regular,Menlo,Consolas,'Liberation Mono',monospace,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;color:#cbd5e1;background:#0f172a;border-radius:12px;line-height:1.6;border:1px solid #1e293b;">
21361+ <div style="display:flex;align-items:center;gap:12px;margin-bottom:20px;">
21362+ <div style="width:40px;height:40px;border-radius:8px;background:linear-gradient(135deg,#6366f1,#8b5cf6);display:flex;align-items:center;justify-content:center;font-size:20px;flex-shrink:0;">🐺</div>
21363+ <div>
21364+ <h1 style="margin:0;font-size:20px;font-weight:700;color:#f1f5f9;letter-spacing:-0.3px;">WolfStack — ${escapeHtml(pageTitle)}</h1>
21365+ <p style="margin:2px 0 0 0;font-size:12px;color:#64748b;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">Infrastructure Report${hostname ? ' — ' + escapeHtml(hostname) : ''}</p>
21366+ </div>
21367+ </div>
21368+ <table style="width:100%;border-collapse:collapse;margin:0 0 24px 0;font-size:12px;color:#94a3b8;">
21369+ <tr>
21370+ <td style="padding:6px 0;border-bottom:1px solid #1e293b;"><strong style="color:#cbd5e1;">Generated</strong></td>
21371+ <td style="padding:6px 0;border-bottom:1px solid #1e293b;">${escapeHtml(timestamp)}</td>
21372+ <td style="padding:6px 0;border-bottom:1px solid #1e293b;"><strong style="color:#cbd5e1;">View</strong></td>
21373+ <td style="padding:6px 0;border-bottom:1px solid #1e293b;">${escapeHtml(pageTitle)}</td>
21374+ </tr>
21375+ </table>
21376+ ${body}
21377+ <div style="margin-top:32px;padding-top:16px;border-top:1px solid #1e293b;display:flex;justify-content:space-between;align-items:center;">
21378+ <span style="font-size:11px;color:#475569;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">This report was auto-generated by WolfStack. Data reflects the state at the time of capture.</span>
21379+ <span style="font-size:11px;color:#6366f1;font-weight:600;">wolfstack.org</span>
21380+ </div>
21381+ </div>`;
2129221382
2129321383 try {
2129421384 const resp = await fetch('/api/wolfnote/notes', {
0 commit comments