Skip to content

Commit

Permalink
Message markdown highlighting adjustment to remove multiple calls
Browse files Browse the repository at this point in the history
Added click message bubble to auto copy text.
  • Loading branch information
fingerthief committed Mar 10, 2024
1 parent 18ad0b0 commit ea5be7b
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 38 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# [Try MinimalGPT/MinimalPaLM/MinimalClaude](https://minimalgpt.app/)

<p><img src="https://img.shields.io/badge/build-passing-brightgreen" alt="Build Status">
<img src="https://img.shields.io/badge/version-4.2.1-blue" alt="Version">
<img src="https://img.shields.io/badge/version-4.2.2-blue" alt="Version">
<img src="https://img.shields.io/badge/license-MIT-green" alt="License"></p>

**MinimalGPT** is an open-source LLM chat web app designed to be as self-contained as possible. All conversations are stored locally on the client's device, with the only information being sent to the server being API calls to GPT, PaLM or Claude chat when the user sends a message and when a user saves a conversation to generate a conversation title.
Expand Down
8 changes: 4 additions & 4 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
<div class="settings-header">
<h2 data-bind="click: () => { window.location.reload(true); }">
<span class="fa-solid fa-arrows-rotate"></span>
Settings | V4.2.1
Settings | V4.2.2
</h2>
</div>
<div class="sidebar-content-container">
Expand Down Expand Up @@ -213,7 +213,7 @@ <h2>Conversations</h2>
<span class="fa-solid fa-circle-user fa-lg icon" data-bind="visible: role === 'user'"></span>
<span data-bind="text: (role === 'user' ? 'User' : (role !== 'user' && $index() > 0 && $parent.messages()[$index() - 1].content.toLowerCase().startsWith('image::')) ? 'DALL-E' : 'GPT')"></span>
</div>
<span id="message-contents" data-bind="html: $parent.formatMessage(content, false)"></span>
<span id="message-contents" data-bind="html: $parent.formatMessage(content, false), click: $parent.copyText"></span>
</div>
</div>
</div>
Expand All @@ -229,7 +229,7 @@ <h2>Conversations</h2>
<span class="fa-solid fa-circle-user fa-lg icon" data-bind="visible: role === 'user'"></span>
<span data-bind="text: role === 'user' ? 'User' : 'PaLM'"></span>
</div>
<span id="message-contents" data-bind="html: $parent.formatMessage(content, false)"></span>
<span id="message-contents" data-bind="html: $parent.formatMessage(content, false), click: $parent.copyText"></span>
</div>
</div>
</div>
Expand All @@ -245,7 +245,7 @@ <h2>Conversations</h2>
<span class="fa-solid fa-circle-user fa-lg icon" data-bind="visible: role === 'user'"></span>
<span data-bind="text: role === 'user' ? 'User' : 'Claude'"></span>
</div>
<span id="message-contents" data-bind="html: $parent.formatMessage(content, false)"></span>
<span id="message-contents" data-bind="html: $parent.formatMessage(content, false), click: $parent.copyText"></span>
</div>
</div>
</div>
Expand Down
73 changes: 41 additions & 32 deletions js/app-view-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function AppViewModel() {
self.filterText = ko.observable("");

hljs.configure({ ignoreUnescapedHTML: true });

self.conversationTitles = ko.observableArray(loadConversationTitles());
self.storedConversations = ko.observableArray(loadStoredConversations());
self.selectedConversation = ko.observable(self.storedConversations()[self.storedConversations().length]);
Expand All @@ -70,33 +70,6 @@ export function AppViewModel() {
}
};

// Markdown configuration
const defaults = {
html: false,
xhtmlOut: false,
breaks: false,
langPrefix: 'language-',
linkify: true,
typographer: true,
_highlight: false,
_strict: false,
_view: 'src'
};

defaults.highlight = function (str, lang) {
const md = window.markdownit(defaults);
var esc = md.utils.escapeHtml;
if (lang && hljs.getLanguage(lang)) {
try {
return '<pre class="hljs"><code>' +
hljs.highlight(lang, str, true).value +
'</code></pre>';
} catch (__) { }
} else {
return '<pre class="hljs"><code>' + esc(str) + '</code></pre>';
}
};

// Event listeners and element setup
const floatingSearchField = document.getElementById('floating-search-field');
floatingSearchField.addEventListener('transitionend', zIndexAfterTransition);
Expand Down Expand Up @@ -438,7 +411,6 @@ export function AppViewModel() {

function updateUI(content) {
self.streamedMessageText((self.streamedMessageText() || "") + content);
hljs.highlightAll();
self.scrollToBottom();
}

Expand Down Expand Up @@ -613,7 +585,6 @@ export function AppViewModel() {
addMessage('assistant', response);
self.saveMessages();
self.scrollToBottom();
hljs.highlightAll();
} catch (error) {
console.error("Error sending message:", error);
}
Expand All @@ -638,9 +609,36 @@ export function AppViewModel() {
localStorage.setItem("gpt-conversations", JSON.stringify(self.storedConversations()));
};

const defaults = {
html: true,
xhtmlOut: false,
breaks: false,
langPrefix: 'language-',
linkify: true,
typographer: true,
_highlight: true,
_strict: false,
_view: 'src'
};

defaults.highlight = function (str, lang) {
const md = window.markdownit(defaults);
var esc = md.utils.escapeHtml;
if (lang && hljs.getLanguage(lang)) {
try {
return '<pre class="hljs"><code>' +
hljs.highlight(lang, str, true).value +
'</code></pre>';
} catch (__) { }
} else {
return '<pre class="hljs"><code>' + esc(str) + '</code></pre>';
}
};

self.formatMessage = function (message, isStartup) {
let md = window.markdownit(defaults);
let renderedMessage = wrapCodeSnippets(md.render(message));
hljs.highlightAll(md, renderedMessage)
return renderedMessage;
};

Expand Down Expand Up @@ -680,8 +678,19 @@ export function AppViewModel() {
self.loadSelectedConversation();
};

self.copyText = function (content) {
navigator.clipboard.writeText(content);
self.copyText = function (element) {
const handler = () => {
const content = element.textContent;
navigator.clipboard.writeText(content)
.then(() => {
console.log('Content copied to clipboard');
})
.catch((error) => {
console.error('Failed to copy content: ', error);
});
};

return handler;
}

self.clearMessages = async function () {
Expand Down
1 change: 0 additions & 1 deletion js/gpt-api-access.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ export function loadConversationTitles() {
}

export function loadStoredConversations() {
hljs.highlightAll();
const storedConversations = localStorage.getItem("gpt-conversations");
return storedConversations ? JSON.parse(storedConversations) : [];
}

0 comments on commit ea5be7b

Please sign in to comment.