272 lines
8.4 KiB
JavaScript
272 lines
8.4 KiB
JavaScript
import { autoResize, placeCursorAtEnd } from './utils.js'
|
|
import { createNewPage } from './page.js';
|
|
|
|
function applyBlocType(bloc, type, extra = {}) {
|
|
bloc.dataset.type = type;
|
|
|
|
let metadata = {};
|
|
|
|
switch (type) {
|
|
case "TEXTE":
|
|
metadata = {};
|
|
break;
|
|
case "TITRE":
|
|
metadata = { level: extra.level || 1 };
|
|
break;
|
|
case "LISTE":
|
|
metadata = { style: extra.style || "bullet" };
|
|
break;
|
|
case "CODE":
|
|
metadata = { language: extra.language || "plaintext", theme: "light" };
|
|
break;
|
|
case "PAGE":
|
|
metadata = {
|
|
pageId: extra.pageId || "nouvelle-page-id",
|
|
title: extra.title || "Nouvelle page"
|
|
};
|
|
break;
|
|
case "SEPARATEUR":
|
|
metadata = {};
|
|
break;
|
|
case "CITATION":
|
|
metadata = {
|
|
type: extra.type || "normal"
|
|
};
|
|
break;
|
|
default:
|
|
console.warn("Type de bloc inconnu :", type);
|
|
}
|
|
|
|
setBlocMetadata(bloc, metadata);
|
|
renderBlocStyle(bloc);
|
|
}
|
|
|
|
export function renderBlocStyle(bloc) {
|
|
if (!bloc || !bloc.dataset) return;
|
|
|
|
clearBlocStyles(bloc);
|
|
|
|
const type = bloc.dataset.type || 'TEXTE';
|
|
|
|
switch (type) {
|
|
case 'TEXTE':
|
|
bloc.classList.add('is-text');
|
|
break;
|
|
|
|
case 'TITRE':
|
|
const metadata = getBlocDataMetadata(bloc);
|
|
const level = metadata.level || '1';
|
|
bloc.classList.add('is-title', `is-title-${level}`);
|
|
break;
|
|
|
|
case 'LISTE':
|
|
renderListe(bloc);
|
|
bloc.classList.add('is-list');
|
|
break;
|
|
|
|
case 'CODE':
|
|
bloc.classList.add('is-code-block');
|
|
bloc.style.whiteSpace = "pre";
|
|
bloc.dataset.language || 'plaintext';
|
|
break;
|
|
|
|
case 'PAGE':
|
|
bloc.classList.add('is-page-link');
|
|
break;
|
|
|
|
case 'SEPARATEUR':
|
|
bloc.classList.add('is-separator');
|
|
bloc.contentEditable = "false";
|
|
break;
|
|
|
|
case "CITATION":
|
|
const metadataCitation = getBlocDataMetadata(bloc);
|
|
const citationType = metadataCitation.type || 'normal';
|
|
bloc.classList.add('is-quote', `is-quote-${citationType}`);
|
|
break;
|
|
|
|
default:
|
|
bloc.classList.add('is-text');
|
|
break;
|
|
}
|
|
|
|
autoResize(bloc);
|
|
}
|
|
|
|
export function clearBlocStyles(bloc) {
|
|
bloc.classList.remove(
|
|
'is-title', 'is-title-1', 'is-title-2', 'is-title-3',
|
|
'is-quote', 'is-quote-info', 'is-quote-warning', 'is-quote-normal',
|
|
'is-code-block', 'is-list', 'is-page-link', 'is-separator', 'is-text'
|
|
);
|
|
bloc.style.whiteSpace = "normal";
|
|
}
|
|
|
|
export function renderListe(bloc) {
|
|
const metadata = getBlocDataMetadata(bloc);
|
|
const style = metadata.style || 'bullet';
|
|
const tag = style === 'number' ? 'ol' : 'ul';
|
|
|
|
const lignes = bloc.textContent.split('\n').filter(line => line.trim() !== '');
|
|
const items = lignes.map(line => `<li>${line.trim()}</li>`).join('');
|
|
bloc.innerHTML = `<${tag}>${items}</${tag}>`;
|
|
}
|
|
|
|
export function handleSlashCommand(bloc, texte) {
|
|
return new Promise((resolve) => {
|
|
const parts = texte.trim().substring(1).split(" ");
|
|
const command = parts[0].toLowerCase();
|
|
const param = parts.slice(1).join(" ");
|
|
|
|
switch (command) {
|
|
case "page":
|
|
const pageId = new URLSearchParams(window.location.search).get("id");
|
|
createNewPage(param || "Nouvelle page", pageId).then(data => {
|
|
if (data && data.id) {
|
|
const lien = `/Projet/AfficherPage?id=${data.id}`;
|
|
bloc.innerHTML = `<a href="${lien}">${param || "Nouvelle page"}</a>`;
|
|
applyBlocType(bloc, "PAGE", { pageId: data.id, title: param, from: pageId });
|
|
autoResize(bloc);
|
|
resolve();
|
|
} else {
|
|
console.error("Erreur de création de page");
|
|
resolve();
|
|
}
|
|
}).catch(error => {
|
|
console.error("Erreur lors de la création de la page :", error);
|
|
resolve();
|
|
});
|
|
break;
|
|
|
|
case "h1":
|
|
case "h2":
|
|
case "h3":
|
|
applyBlocType(bloc, "TITRE", { level: parseInt(command[1] || "1") });
|
|
bloc.textContent = param;
|
|
autoResize(bloc);
|
|
resolve();
|
|
break;
|
|
|
|
case "ul":
|
|
applyBlocType(bloc, "LISTE", { style: "bullet" });
|
|
bloc.textContent = '';
|
|
autoResize(bloc);
|
|
resolve();
|
|
break;
|
|
|
|
case "ol":
|
|
applyBlocType(bloc, "LISTE", { style: "numbered" });
|
|
bloc.textContent = '';
|
|
autoResize(bloc);
|
|
resolve();
|
|
break;
|
|
|
|
case "code":
|
|
applyBlocType(bloc, "CODE", { language: param || "plaintext" });
|
|
bloc.textContent = '';
|
|
autoResize(bloc);
|
|
resolve();
|
|
break;
|
|
|
|
case "hr":
|
|
applyBlocType(bloc, "SEPARATEUR", {}); // ou un type adapté selon ta logique
|
|
bloc.innerText = ' ';
|
|
autoResize(bloc);
|
|
resolve(true);
|
|
break;
|
|
|
|
default:
|
|
console.log(`Commande non reconnue: ${command}`);
|
|
resolve();
|
|
break;
|
|
}
|
|
|
|
bloc.focus();
|
|
placeCursorAtEnd(bloc);
|
|
});
|
|
}
|
|
|
|
export async function handleMarkdownSyntax(bloc, texte) {
|
|
// Vérifier si c'est un titre
|
|
if (texte.startsWith('#')) {
|
|
const level = texte.split(' ')[0].length; // Compter le nombre de # pour le niveau du titre
|
|
if (level >= 1 && level <= 6) {
|
|
applyBlocType(bloc, "TITRE", { level: level });
|
|
bloc.textContent = texte.replace(/^#+\s*/, '');
|
|
autoResize(bloc);
|
|
}
|
|
}
|
|
// Vérifier si c'est une citation
|
|
else if (texte.startsWith('>')) {
|
|
const citation = detectCitation(texte);
|
|
applyBlocType(bloc, "CITATION", { type: citation.type });
|
|
bloc.textContent = citation.content;
|
|
autoResize(bloc);
|
|
}
|
|
// Vérifier si c'est un bloc de code
|
|
else if (texte.startsWith('```')) {
|
|
applyBlocType(bloc, "CODE", {});
|
|
bloc.textContent = texte.replace(/^```(.*)$/, '');
|
|
autoResize(bloc);
|
|
}
|
|
// Vérifier si c'est un séparateur horizontal (Markdown)
|
|
else if (texte.match(/^(\*{3,}|\-{3,}|_{3,})$/)) {
|
|
applyBlocType(bloc, "SEPARATEUR", {});
|
|
bloc.textContent = '';
|
|
autoResize(bloc);
|
|
}
|
|
// Vérifier si c'est une liste
|
|
else if (texte.match(/^(\s*([-*+])\s+.+|\s*\d+\.\s+.+)(\n|$)/m)) {
|
|
const lignes = texte.split('\n').filter(line => line.trim() !== '');
|
|
let style = 'bullet';
|
|
|
|
if (lignes.every(line => line.trim().match(/^\d+\.\s+/))) {
|
|
style = 'number';
|
|
} else if (lignes.every(line => line.trim().match(/^[-*+]\s+/))) {
|
|
style = 'bullet';
|
|
} else {
|
|
return; // Pas une vraie liste structurée
|
|
}
|
|
|
|
const contenu = lignes.map(line => line.replace(/^(\d+\.\s+|[-*+]\s+)/, '')).join('\n');
|
|
applyBlocType(bloc, "LISTE", { style: style });
|
|
bloc.textContent = contenu;
|
|
renderListe(bloc);
|
|
autoResize(bloc);
|
|
}
|
|
}
|
|
|
|
export function getBlocDataMetadata(bloc) {
|
|
try {
|
|
return JSON.parse(bloc.getAttribute('data-metadata') || "{}");
|
|
} catch (e) {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
export function setBlocMetadata(bloc, metadata) {
|
|
const metadataStr = JSON.stringify(metadata);
|
|
bloc.dataset.metadata = metadataStr;
|
|
bloc.setAttribute('data-metadata', metadataStr);
|
|
}
|
|
|
|
const citationTypes = {
|
|
'>!': 'danger',
|
|
'>i': 'info',
|
|
/* '>w': 'warning',
|
|
'>s': 'success',*/
|
|
'>': 'normal' // doit rester en dernier
|
|
};
|
|
|
|
function detectCitation(texte) {
|
|
for (const prefix in citationTypes) {
|
|
if (texte.startsWith(prefix)) {
|
|
return {
|
|
type: citationTypes[prefix],
|
|
content: texte.replace(new RegExp(`^${prefix}\\s*`), '')
|
|
};
|
|
}
|
|
}
|
|
return null;
|
|
}
|