Markdown, small improvements

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
Ettore Di Giacinto
2025-11-10 13:48:29 +01:00
parent 0f49c22572
commit f2190ab71c
3 changed files with 80 additions and 34 deletions

View File

@@ -305,7 +305,7 @@
class="rounded-t-lg max-h-48 max-w-96 object-cover mt-3"
loading="lazy">
</div>
<p class="text-base leading-relaxed text-gray-500 dark:text-gray-400" x-text="selectedBackend?.description"></p>
<div class="text-base leading-relaxed text-gray-500 dark:text-gray-400" x-html="renderMarkdown(selectedBackend?.description)"></div>
<template x-if="selectedBackend?.tags && selectedBackend.tags.length > 0">
<div>
<p class="text-sm mb-3 font-semibold text-gray-900 dark:text-white">Tags</p>
@@ -599,6 +599,17 @@ function backendsGallery() {
}
},
renderMarkdown(text) {
if (!text) return '';
try {
const html = marked.parse(text);
return DOMPurify.sanitize(html);
} catch (error) {
console.error('Error rendering markdown:', error);
return text;
}
},
openModal(backend) {
this.selectedBackend = backend;
},

View File

@@ -265,25 +265,8 @@ SOFTWARE.
{{ end }}
{{ end }}
<div x-data="{ activeTab: 'actions' }" class="space-y-4">
<!-- Tab navigation -->
<div class="flex border-b border-[#101827]">
<button
@click="activeTab = 'actions'"
:class="activeTab === 'actions' ? 'border-b-2 border-[#38BDF8] text-[#E5E7EB]' : 'text-[#94A3B8] hover:text-[#E5E7EB]'"
class="py-2 px-4 text-sm font-medium">
Actions
</button>
<button
@click="activeTab = 'settings'"
:class="activeTab === 'settings' ? 'border-b-2 border-[#38BDF8] text-[#E5E7EB]' : 'text-[#94A3B8] hover:text-[#E5E7EB]'"
class="py-2 px-4 text-sm font-medium">
Settings
</button>
</div>
<!-- Actions tab -->
<div x-show="activeTab === 'actions'" class="space-y-3">
<div x-data="{ showPromptForm: false }" class="space-y-3">
<!-- Actions -->
<button
@click="$store.chat.clear()"
id="clear"
@@ -300,17 +283,6 @@ SOFTWARE.
>
<i class="fas fa-book mr-2 text-[#38BDF8]"></i> Documentation
</a>
<a
href="browse?term={{.Model}}"
class="w-full flex items-center px-3 py-2 text-sm rounded text-[#E5E7EB] bg-[#1E293B] hover:bg-[#1E293B]/80 border border-[#38BDF8]/20 hover:border-[#38BDF8]/40 transition-colors glow-on-hover"
>
<i class="fas fa-brain mr-2 text-[#38BDF8]"></i> Browse Model
</a>
</div>
<!-- Settings tab -->
<div x-show="activeTab === 'settings'" x-data="{ showPromptForm: false }" class="space-y-3">
<!-- Token Usage Statistics -->
<div class="bg-[#1E293B] border border-[#38BDF8]/20 rounded-lg p-3 space-y-2">
<div class="flex items-center justify-between mb-2">
@@ -457,7 +429,6 @@ SOFTWARE.
</button>
</form>
</div>
</div>
</div>
</div>
</div>
@@ -759,7 +730,7 @@ SOFTWARE.
<div class="flex justify-center items-center">
{{ if $galleryConfig.Icon }}<img class="lazy rounded-t-lg max-h-48 max-w-96 object-cover mt-3 entered loaded" src="{{$galleryConfig.Icon}}" loading="lazy"/>{{end}}
</div>
<p class="text-base leading-relaxed text-gray-500 dark:text-gray-400">{{ $galleryConfig.Description }}</p>
<div id="model-info-description" class="text-base leading-relaxed text-gray-500 dark:text-gray-400">{{ $galleryConfig.Description }}</div>
<hr>
<p class="text-sm font-semibold text-gray-900 dark:text-white">Links</p>
<ul>
@@ -798,6 +769,59 @@ SOFTWARE.
});
// Context size is now initialized in the Alpine store initialization above
// Process markdown in model info modal when it opens
document.addEventListener('DOMContentLoaded', () => {
const modalElement = document.getElementById('model-info-modal');
const descriptionElement = document.getElementById('model-info-description');
if (modalElement && descriptionElement) {
// Process markdown on initial load
const processMarkdown = () => {
if (descriptionElement && typeof marked !== 'undefined' && typeof DOMPurify !== 'undefined') {
const originalText = descriptionElement.textContent || descriptionElement.innerText;
if (originalText) {
try {
const html = marked.parse(originalText);
descriptionElement.innerHTML = DOMPurify.sanitize(html);
} catch (error) {
console.error('Error rendering markdown:', error);
}
}
}
};
// Process immediately if modal is already visible
if (!modalElement.classList.contains('hidden')) {
processMarkdown();
}
// Listen for modal show events (Flowbite uses data-modal-show attribute changes)
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes' && mutation.attributeName === 'aria-hidden') {
const isHidden = modalElement.getAttribute('aria-hidden') === 'true';
if (!isHidden) {
// Modal is now visible, process markdown
setTimeout(processMarkdown, 100);
}
}
});
});
observer.observe(modalElement, {
attributes: true,
attributeFilter: ['aria-hidden', 'class']
});
// Also listen for click events on modal toggle buttons
document.querySelectorAll('[data-modal-toggle="model-info-modal"]').forEach(button => {
button.addEventListener('click', () => {
setTimeout(processMarkdown, 200);
});
});
}
});
</script>
</body>
</html>

View File

@@ -359,7 +359,7 @@
class="lazy rounded-t-lg max-h-48 max-w-96 object-cover mt-3"
loading="lazy">
</div>
<p class="text-base leading-relaxed text-gray-500 dark:text-gray-400" x-text="selectedModel?.description"></p>
<div class="text-base leading-relaxed text-gray-500 dark:text-gray-400" x-html="renderMarkdown(selectedModel?.description)"></div>
<hr>
<template x-if="selectedModel?.urls && selectedModel.urls.length > 0">
<div>
@@ -669,6 +669,17 @@ function modelsGallery() {
}
},
renderMarkdown(text) {
if (!text) return '';
try {
const html = marked.parse(text);
return DOMPurify.sanitize(html);
} catch (error) {
console.error('Error rendering markdown:', error);
return text;
}
},
openModal(model) {
this.selectedModel = model;
},