feat: rename batman toolbelt buttons and add Full Page Raw with HTML to markdown conversion
This commit is contained in:
parent
b1e9cfca9c
commit
fa4eaa57da
1 changed files with 105 additions and 6 deletions
111
src/ui.js
111
src/ui.js
|
|
@ -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 ? `` : '';
|
||||
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);
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue