feat: chat — les posts affichent le markdown rendu comme un document, code coloré #193
This commit is contained in:
+28
-3
@@ -12,7 +12,7 @@
|
||||
import { api, AuthManager } from "./auth.js";
|
||||
import { t } from "./i18n.js";
|
||||
import { showToast, TabManager } from "./ui.js";
|
||||
import { escapeHtml, safeCreateIcons } from "./utils.js";
|
||||
import { escapeHtml, safeCreateIcons, safeHighlight } from "./utils.js";
|
||||
import { icon } from "./viewer.js";
|
||||
|
||||
const PANEL_ID = "file-chat-panel";
|
||||
@@ -147,7 +147,32 @@ async function _markRead(vault, path) {
|
||||
}
|
||||
|
||||
// URL dans le texte → lien cliquable (partage d'URL #190), texte sinon.
|
||||
function _fillBody(body, text) {
|
||||
/**
|
||||
* Remplit le corps d'un message (#193).
|
||||
*
|
||||
* Quand le serveur a fourni le rendu markdown (`html`, même pipeline que les
|
||||
* documents : mistune + sanitizer BUG-021), on l'injecte dans un `.md-content`
|
||||
* — titres, listes, tableaux, blocs de code — et on colore les blocs avec
|
||||
* highlight.js (`safeHighlight`), exactement comme dans le viewer.
|
||||
*
|
||||
* Sans `html` (message optimiste d'un autre client, cache ancien), on retombe
|
||||
* sur le texte brut avec liens cliquables, comme avant.
|
||||
*/
|
||||
function _fillBody(body, m) {
|
||||
const text = typeof m === "string" ? m : (m && m.text) || "";
|
||||
const html = m && typeof m === "object" ? m.html || "" : "";
|
||||
if (html) {
|
||||
body.classList.add("file-chat-md");
|
||||
const div = document.createElement("div");
|
||||
div.className = "md-content";
|
||||
div.innerHTML = html; // rendu + assaini côté serveur
|
||||
body.appendChild(div);
|
||||
div.querySelectorAll("pre code").forEach((block) => {
|
||||
if (block.querySelector(".secret-mask")) return;
|
||||
safeHighlight(block);
|
||||
});
|
||||
return;
|
||||
}
|
||||
const parts = String(text || "").split(/(https?:\/\/[^\s<>"']+)/g);
|
||||
parts.forEach((part) => {
|
||||
if (!part) return;
|
||||
@@ -341,7 +366,7 @@ export function _messageEl(m, currentUser, delUrl, readMap) {
|
||||
}
|
||||
const body = document.createElement("div");
|
||||
body.className = "file-chat-body";
|
||||
_fillBody(body, m.text);
|
||||
_fillBody(body, m);
|
||||
wrap.appendChild(meta);
|
||||
if (m.text) wrap.appendChild(body);
|
||||
const att = _attachEl(m.attachment);
|
||||
|
||||
@@ -13852,6 +13852,70 @@ body.reading-mode .file-actions {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
/* #193 — un post peut être rendu comme un document markdown (mistune côté
|
||||
serveur + hljs côté client) : on annule le `pre-wrap` hérité (sinon les
|
||||
retours à la ligne du HTML source deviennent des lignes vides) et on
|
||||
compacte la typographie `.md-content` pour une bulle de chat. */
|
||||
.file-chat-body.file-chat-md {
|
||||
white-space: normal;
|
||||
word-break: normal;
|
||||
}
|
||||
.file-chat-body .md-content > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.file-chat-body .md-content > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.file-chat-body .md-content h1,
|
||||
.file-chat-body .md-content h2,
|
||||
.file-chat-body .md-content h3,
|
||||
.file-chat-body .md-content h4,
|
||||
.file-chat-body .md-content h5,
|
||||
.file-chat-body .md-content h6 {
|
||||
font-size: 1rem;
|
||||
margin: 0.7em 0 0.35em;
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.file-chat-body .md-content p {
|
||||
margin: 0.4em 0;
|
||||
}
|
||||
.file-chat-body .md-content ul,
|
||||
.file-chat-body .md-content ol {
|
||||
padding-left: 1.3em;
|
||||
margin: 0.4em 0;
|
||||
}
|
||||
.file-chat-body .md-content pre {
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
.file-chat-body .md-content pre code {
|
||||
font-size: 0.78rem;
|
||||
line-height: 1.45;
|
||||
}
|
||||
.file-chat-body .md-content :not(pre) > code {
|
||||
font-size: 0.82rem;
|
||||
padding: 1px 4px;
|
||||
border-radius: 4px;
|
||||
background: var(--bg-hover, rgba(128, 128, 128, 0.15));
|
||||
}
|
||||
.file-chat-body .md-content table {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
.file-chat-body .md-content img {
|
||||
max-width: 100%;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.file-chat-body .md-content .wikilink,
|
||||
.file-chat-body .md-content .wikilink-anchor {
|
||||
color: var(--accent, #58a6ff);
|
||||
cursor: pointer;
|
||||
}
|
||||
.file-chat-form {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
Reference in New Issue
Block a user