tried to add formatting to nebot page

This commit is contained in:
2025-09-12 19:16:34 +12:00
parent 70cd3571d1
commit 36a4e58017
2 changed files with 69 additions and 7 deletions
+40 -4
View File
@@ -196,9 +196,19 @@
if(!chat){ return; }
chat.messages.forEach(m=>{
const div = h('div',{class:'msg '+m.role});
div.innerHTML = '<div class="markdown">'+renderMarkdown(m.content)+'</div>';
const mdEl = h('div', { class: 'markdown' });
// If libs are ready, render now; otherwise, show plain text and mark for deferred upgrade
if (window.marked && window.DOMPurify) {
mdEl.innerHTML = renderMarkdown(m.content);
} else {
mdEl.textContent = m.content || '';
mdEl.dataset.raw = m.content || '';
deferredMarkdown.add(mdEl);
scheduleDeferredMarkdownCheck();
}
div.appendChild(mdEl);
// Enhance links for security
// Enhance links for security (in case already rendered)
div.querySelectorAll('a[href]').forEach(a => {
a.setAttribute('target', '_blank');
a.setAttribute('rel', 'noopener noreferrer');
@@ -308,6 +318,8 @@
typeNext();
}
// Keep a registry of handlers so we can remove previous listeners reliably
const streamHandlers = new Map();
function subscribeStream(id){
const channel = 'ollama-chat:stream:' + id;
console.log('[Nebot Page] Subscribing to stream channel:', channel);
@@ -316,9 +328,12 @@
typingQueue = [];
isTyping = false;
// Remove any existing listeners for this channel
// Remove any existing listener registered earlier for this channel
if (window.electronAPI && window.electronAPI.removeListener) {
window.electronAPI.removeListener(channel, handleStreamPayload);
const prev = streamHandlers.get(channel);
if (prev) {
try { window.electronAPI.removeListener(channel, prev); } catch {}
}
}
function handleStreamPayload(...args) {
@@ -398,6 +413,7 @@
if (window.electronAPI && window.electronAPI.on) {
console.log('[Nebot Page] Setting up stream listener via electronAPI');
window.electronAPI.on(channel, handleStreamPayload);
streamHandlers.set(channel, handleStreamPayload);
} else {
console.warn('[Nebot Page] electronAPI.on not available for stream subscription');
}
@@ -583,4 +599,24 @@
initializeSettings().then(() => {
refreshList().then(()=>{ if(state.chats[0]) openChat(state.chats[0].id); });
});
// Listen for title updates from main (auto-generated titles)
try {
if (window.electronAPI && typeof window.electronAPI.on === 'function') {
window.electronAPI.on('ollama-chat:chat-updated', (payload) => {
const data = payload || {};
const { id, title } = data;
if (!id || !title) return;
// Update local state and rerender list
const item = state.chats.find(c => c.id === id);
if (item) {
item.title = title;
renderChatList();
} else {
// Fallback: refresh list from disk if we don't have it
refreshList();
}
});
}
} catch (e) { console.warn('[Nebot Page] failed to attach chat-updated listener', e); }
})();
+27 -1
View File
@@ -7,7 +7,10 @@ try {
marked = require('marked');
hljs = require('highlight.js');
createDOMPurify = require('dompurify');
DOMPurify = createDOMPurify(window);
// Defer DOMPurify creation until DOM is ready to avoid early failures in some contexts
try {
DOMPurify = createDOMPurify(window);
} catch {}
marked.setOptions({
breaks: true,
highlight(code, lang) {
@@ -24,15 +27,38 @@ try {
// Expose to page context so page.html no longer needs CDN scripts
try {
if (typeof window !== 'undefined') {
// Note: with contextIsolation enabled, assigning to window does not expose to main world.
// Keep assignments for same-world consumers, but also expose explicitly via contextBridge below.
window.marked = marked;
window.DOMPurify = DOMPurify;
window.hljs = hljs;
}
} catch {}
// Explicitly expose to main world so internal pages (browser://nebot) can use these libs
try {
if (marked) contextBridge.exposeInMainWorld('marked', marked);
if (hljs) contextBridge.exposeInMainWorld('hljs', hljs);
if (DOMPurify) contextBridge.exposeInMainWorld('DOMPurify', DOMPurify);
} catch {}
} catch (e) {
// If libs aren't available yet, we'll gracefully render as plain text.
}
// If DOMPurify wasn't ready, create and expose it after DOM is ready
try {
window.addEventListener('DOMContentLoaded', () => {
try {
if (!DOMPurify && createDOMPurify) {
DOMPurify = createDOMPurify(window);
}
if (DOMPurify) {
try { contextBridge.exposeInMainWorld('DOMPurify', DOMPurify); } catch {}
try { window.DOMPurify = DOMPurify; } catch {}
}
} catch {}
});
} catch {}
const pluginId = 'ollama-chat';
// Expose minimal API for page scripts (optional)