Fluent Emoji 3D: Unicode-Emojis durch Microsoft Fluent Emoji ersetzen
- emoji.js: Emoji-Replacement-Engine mit umfassendem Unicode 15.0 Regex - String-basiert (replaceEmojisWithFluent) in renderMarkdown() - DOM-basiert (parseFluentEmojis) als Post-Processing via TreeWalker - CDN: @lobehub/fluent-emoji-3d@1.1.0 via jsdelivr (WebP/3D) - Intelligenter Fallback: fe0f-Varianten, dann Original-Unicode - Fail-Cache verhindert wiederholte Requests für fehlende Emojis - User-Nachrichten werden jetzt als Markdown gerendert (renderMarkdown) - [Datei: ...] Refs: Platzhalter-Mechanismus vor Markdown-Parsing - Reply-Quotes bleiben durch Wrapper-Div erhalten - parseFluentEmojis an allen Render-Stellen integriert: addAssistantBubble, endStreamBubble, _renderUserTextContent, _renderSystemPromptBlocks, history._renderMessagesIntoFragment, history.loadLatestArchive - CSS: .fluent-emoji Klasse (1.2em, inline, scale 1.25) - CSS: white-space:pre-wrap nur noch für .msg:not(.markdown)
This commit is contained in:
1 parent
e2c887aee6
commit
5d132585d5
6 files changed
+156
-33
No files matched your search
+35
-30
@@ -43,6 +43,8 @@ function renderMarkdown(text) {
|
||||
+ '<img class="krea-thumb" src="' + thumbUrl + '" alt="' + safeFn + '" loading="lazy">'
|
||||
+ '</span>';
|
||||
});
|
||||
// Unicode-Emojis durch Fluent Emoji 3D ersetzen (außerhalb von Code-Blöcken)
|
||||
html = replaceEmojisWithFluent(html);
|
||||
// Code-Blöcke wiederherstellen
|
||||
html = html.replace(/%%CODE(\d+)%%/g, function(m, idx) {
|
||||
return codeBlocks[parseInt(idx)];
|
||||
@@ -200,47 +202,47 @@ function renderUserContent(container, text) {
|
||||
}
|
||||
|
||||
function _renderUserTextContent(container, raw) {
|
||||
// [Datei: path] oder [Datei: path:1-10] erkennen
|
||||
// [Datei: path] oder [Datei: path:1-10] durch Platzhalter ersetzen (vor Markdown-Parsing)
|
||||
const pattern = /\[Datei: ([^\]]+)\]/g;
|
||||
let last = 0;
|
||||
let match;
|
||||
const frag = document.createDocumentFragment();
|
||||
const fileRefs = [];
|
||||
const mdText = raw.replace(pattern, function(m, ref) {
|
||||
fileRefs.push(ref);
|
||||
return '%%FILEREF' + (fileRefs.length - 1) + '%%';
|
||||
});
|
||||
|
||||
while ((match = pattern.exec(raw)) !== null) {
|
||||
// Text vor dem Tag
|
||||
if (match.index > last) {
|
||||
frag.appendChild(document.createTextNode(raw.slice(last, match.index)));
|
||||
}
|
||||
// Markdown rendern
|
||||
let html = renderMarkdown(mdText);
|
||||
|
||||
const ref = match[1]; // z.B. "src/foo.cs:10-25"
|
||||
// Pfad ohne Zeilenangabe extrahieren
|
||||
// Platzhalter durch File-Ref-Chips ersetzen (als HTML)
|
||||
html = html.replace(/%%FILEREF(\d+)%%/g, function(m, idx) {
|
||||
const ref = fileRefs[parseInt(idx)];
|
||||
const filePath = ref.replace(/:\d+(-\d+)?$/, '');
|
||||
const chip = document.createElement('span');
|
||||
chip.className = 'file-ref-chip';
|
||||
// Schöne Darstellung: Icon + Kurzpfad
|
||||
const fileName = filePath.includes('/') ? filePath.substring(filePath.lastIndexOf('/') + 1) : filePath;
|
||||
const lineInfo = ref.replace(filePath, '').trim(); // z.B. ":10-25"
|
||||
chip.innerHTML = '<i class="fa fa-file-text-o"></i> ' + esc(fileName + lineInfo);
|
||||
chip.title = ref;
|
||||
chip.style.cursor = 'pointer';
|
||||
chip.addEventListener('click', () => {
|
||||
openFileExplorer({ sessionId: getCurrentSessionId(), initialFile: filePath });
|
||||
const lineInfo = ref.replace(filePath, '').trim();
|
||||
return '<span class="file-ref-chip" data-filepath="' + esc(filePath) + '" title="' + esc(ref) + '" style="cursor:pointer">'
|
||||
+ '<i class="fa fa-file-text-o"></i> ' + esc(fileName + lineInfo) + '</span>';
|
||||
});
|
||||
|
||||
// In ein Wrapper-Div rendern (damit vorherige Elemente wie Reply-Quotes erhalten bleiben)
|
||||
const wrap = document.createElement('div');
|
||||
wrap.className = 'user-text-content';
|
||||
wrap.innerHTML = html;
|
||||
container.appendChild(wrap);
|
||||
|
||||
// Click-Handler für File-Ref-Chips nachträglich binden
|
||||
wrap.querySelectorAll('.file-ref-chip[data-filepath]').forEach(function(chip) {
|
||||
chip.addEventListener('click', function() {
|
||||
openFileExplorer({ sessionId: getCurrentSessionId(), initialFile: chip.dataset.filepath });
|
||||
});
|
||||
frag.appendChild(chip);
|
||||
last = match.index + match[0].length;
|
||||
}
|
||||
});
|
||||
|
||||
// Resttext
|
||||
if (last < raw.length) {
|
||||
frag.appendChild(document.createTextNode(raw.slice(last)));
|
||||
}
|
||||
|
||||
container.appendChild(frag);
|
||||
// Fluent Emoji DOM-Parsing
|
||||
parseFluentEmojis(wrap);
|
||||
}
|
||||
|
||||
function addUserBubble(text, streamed = false, timestamp = '', messageId = null, isMarked = false) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'msg user' + (isMarked ? ' marked' : '');
|
||||
div.className = 'msg user markdown' + (isMarked ? ' marked' : '');
|
||||
div.dataset.role = 'user';
|
||||
div.dataset.timestamp = timestamp || new Date().toISOString();
|
||||
if (messageId) div.dataset.messageId = messageId;
|
||||
@@ -259,6 +261,7 @@ function addAssistantBubble(text, timestamp = '', messageId = null, isMarked = f
|
||||
div.dataset.timestamp = timestamp || new Date().toISOString();
|
||||
if (messageId) div.dataset.messageId = messageId;
|
||||
div.innerHTML = renderMarkdown(text);
|
||||
parseFluentEmojis(div);
|
||||
wrapKreaGalleries(div);
|
||||
_addReplyButton(div);
|
||||
_addMarkButton(div, messageId, isMarked);
|
||||
@@ -324,6 +327,7 @@ function endStreamBubble() {
|
||||
if (!_streamText.trim()) _streamDiv.remove();
|
||||
else {
|
||||
_streamDiv.innerHTML = renderMarkdown(_streamText);
|
||||
parseFluentEmojis(_streamDiv);
|
||||
wrapKreaGalleries(_streamDiv);
|
||||
}
|
||||
}
|
||||
@@ -645,6 +649,7 @@ function _renderSystemPromptBlocks(container, blocks) {
|
||||
var content = document.createElement('div');
|
||||
content.className = 'sp-block-content markdown';
|
||||
content.innerHTML = renderMarkdown(block.content);
|
||||
parseFluentEmojis(content);
|
||||
wrapper.appendChild(content);
|
||||
|
||||
container.appendChild(wrapper);
|
||||
|
||||
Reference in new issue
Block a user