feat: rename batman toolbelt buttons and add Full Page Raw with HTML to markdown conversion

This commit is contained in:
Russell Ballestrini 2025-07-02 15:24:16 -04:00
parent b1e9cfca9c
commit fa4eaa57da

111
src/ui.js
View file

@ -1040,11 +1040,98 @@ async function openUncloseaiEmbeddedModalNew() {
-webkit-overflow-scrolling: touch;
`;
// HTML to Markdown converter function
function htmlToMarkdown(html) {
// Create a temporary element to parse HTML
const temp = document.createElement('div');
temp.innerHTML = html;
// Remove script and style elements
temp.querySelectorAll('script, style, noscript').forEach(el => el.remove());
let markdown = '';
function processNode(node) {
if (node.nodeType === Node.TEXT_NODE) {
return node.textContent.trim();
}
if (node.nodeType !== Node.ELEMENT_NODE) return '';
const tag = node.tagName.toLowerCase();
const children = Array.from(node.childNodes).map(processNode).join('');
switch (tag) {
case 'h1': return `# ${children}\n\n`;
case 'h2': return `## ${children}\n\n`;
case 'h3': return `### ${children}\n\n`;
case 'h4': return `#### ${children}\n\n`;
case 'h5': return `##### ${children}\n\n`;
case 'h6': return `###### ${children}\n\n`;
case 'p': return `${children}\n\n`;
case 'br': return '\n';
case 'strong': case 'b': return `**${children}**`;
case 'em': case 'i': return `*${children}*`;
case 'code': return `\`${children}\``;
case 'pre': return `\`\`\`\n${children}\n\`\`\`\n\n`;
case 'a':
const href = node.getAttribute('href');
return href ? `[${children}](${href})` : children;
case 'img':
const src = node.getAttribute('src');
const alt = node.getAttribute('alt') || '';
return src ? `![${alt}](${src})` : '';
case 'ul': case 'ol':
return `${children}\n`;
case 'li': return `- ${children}\n`;
case 'blockquote': return `> ${children}\n\n`;
default: return children;
}
}
return processNode(temp).trim();
}
let readPageAudio = null;
let isReadingPage = false;
const controlActions = [
{ text: "📖 Read", action: () => window.readPageWithHermes() },
{ text: "🔊 TTS", action: () => window.openTTSModal() },
{ text: "🌐 Translate", action: () => window.openTranslateModal() },
{ text: "📋 Full Raw", action: async () => {
{ text: "📖 Read Page", action: async (button) => {
// If already playing, pause
if (readPageAudio && !readPageAudio.paused) {
readPageAudio.pause();
button.textContent = "📖 Read Page";
isReadingPage = false;
return;
}
// If paused, resume
if (readPageAudio && readPageAudio.paused && readPageAudio.currentTime > 0) {
readPageAudio.play();
button.textContent = "⏸️ Pause";
isReadingPage = true;
return;
}
// Start new reading
button.textContent = "⏳ Processing...";
button.disabled = true;
try {
await window.readPageWithHermes();
// Note: The actual audio handling would need to be integrated with readPageWithHermes
button.textContent = "⏸️ Pause";
isReadingPage = true;
} catch (error) {
alert("Failed to read page: " + error.message);
button.textContent = "📖 Read Page";
} finally {
button.disabled = false;
}
}},
{ text: "🔊 TTS Anything", action: (btn) => window.openTTSModal() },
{ text: "🌐 Translate", action: (btn) => window.openTranslateModal() },
{ text: "📋 Full Chat Raw", action: async () => {
try {
const { getChatHistory } = await import('./chat.js');
const history = getChatHistory();
@ -1062,7 +1149,7 @@ async function openUncloseaiEmbeddedModalNew() {
alert("Failed to copy: " + error.message);
}
}},
{ text: "📄 Full HTML", action: async () => {
{ text: "📄 Full Chat HTML", action: async () => {
try {
const { getChatHistory } = await import('./chat.js');
const history = getChatHistory();
@ -1080,6 +1167,18 @@ async function openUncloseaiEmbeddedModalNew() {
} catch (error) {
alert("Failed to copy: " + error.message);
}
}},
{ text: "📝 Full Page Raw", action: async () => {
try {
// Get the entire page HTML
const pageHtml = document.documentElement.outerHTML;
// Convert to markdown
const markdown = htmlToMarkdown(pageHtml);
await navigator.clipboard.writeText(markdown);
alert("Full page copied as markdown!");
} catch (error) {
alert("Failed to copy page: " + error.message);
}
}}
];
@ -1104,7 +1203,7 @@ async function openUncloseaiEmbeddedModalNew() {
btn.style.background = '#f8f9fa';
btn.style.borderColor = '#dee2e6';
};
btn.onclick = action;
btn.onclick = () => action(btn);
controls.appendChild(btn);
});