chore: update Angular cache with new TypeScript definitions

This commit is contained in:
2025-09-28 12:16:14 -04:00
parent f68440656e
commit 7f913ab33c
11 changed files with 349 additions and 27 deletions
+70 -17
View File
@@ -12,7 +12,7 @@ export class MarkdownService {
private readonly tagPaletteSize = 12;
private tagColorCache = new Map<string, number>();
render(markdown: string, allNotes: Note[]): string {
render(markdown: string, allNotes: Note[], currentNote?: Note): string {
let html = markdown;
// Process code blocks first to prevent inner content from being parsed
@@ -101,11 +101,31 @@ export class MarkdownService {
});
html = html.replace(/^>\s(.*)/gm, '<blockquote class="border-l-4 border-gray-300 dark:border-gray-500 pl-4 py-2 my-4 italic text-gray-700 dark:text-gray-300">$1</blockquote>');
// Task lists
const transformTaskItem = (_match: string, marker: string, rawContent: string) => {
const isChecked = marker.toLowerCase() === 'x';
const classes = [
'md-task-item',
'text-obs-l-text-main',
'dark:text-obs-d-text-main'
];
if (isChecked) {
classes.push('md-task-item--done');
}
const content = rawContent.trim();
const checkboxState = isChecked ? 'checked' : '';
const ariaChecked = isChecked ? 'true' : 'false';
return `<li class="${classes.join(' ')}"><label class="md-task"><input type="checkbox" class="md-task-checkbox" ${checkboxState} disabled aria-checked="${ariaChecked}" tabindex="-1"><span class="md-task-label-text">${content}</span></label></li>`;
};
html = html.replace(/^\s*(?:[\-\*]|\d+\.)\s+\[( |x|X)\]\s+(.*)$/gm, transformTaskItem);
// Lists (simple implementation)
html = html.replace(/^\s*[\-\*]\s(.*)/gm, '<li class="ml-6 list-disc">$1</li>');
html = html.replace(/^\s*\d+\.\s(.*)/gm, '<li class="ml-6 list-decimal">$1</li>');
html = html.replace(/<\/li>\n<li/g, '</li><li'); // Fix spacing
html = html.replace(/(<li.*<\/li>)/gs, (match) => {
if (match.includes('md-task-item')) return `<ul class="mb-4 md-task-list">${match}</ul>`;
if (match.includes('list-disc')) return `<ul class="mb-4">${match}</ul>`;
if (match.includes('list-decimal')) return `<ol class="mb-4">${match}</ol>`;
return match;
@@ -116,29 +136,62 @@ export class MarkdownService {
if (inlineCode.includes('\n')) {
return match;
}
return `<code class="inline-code">${this.escapeHtml(inlineCode)}</code>`;
});
// Internal Links [[link|alias]] or [[link]]
html = html.replace(/\[\[([^|\]\n]+)(?:\|([^\]\n]+))?\]\]/g, (match, link, alias) => {
const targetText = alias || link;
const targetId = link.toLowerCase().replace(/\s+/g, '-');
const noteExists = allNotes.some(n => n.id === targetId || n.title === link);
const classes = noteExists ? 'text-obs-l-accent dark:text-obs-d-accent hover:underline cursor-pointer' : 'text-red-500 dark:text-red-400 cursor-not-allowed';
return `<a data-note-id="${targetId}" data-note-title="${link}" class="${classes}">${targetText}</a>`;
const safeContent = this.escapeHtml(inlineCode.trim());
return `<code class="inline-code">${safeContent}</code>`;
});
// External Links [text](url)
html = html.replace(/\[(.*?)\]\((.*?)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer" class="text-blue-600 dark:text-blue-400 hover:underline">$1</a>');
// External images ![alt](url "title")
html = html.replace(/!\[(.*?)\]\(((?:https?|ftp|file):\/\/[^\s\)]*)(?:\s+"(.*?)")?\)/g, (match, alt, url, title) => {
const safeAlt = this.escapeHtml(alt ?? '');
const safeUrl = this.escapeHtml(url ?? '');
const safeTitle = title ? this.escapeHtml(title) : '';
const titleAttr = title ? ` title="${safeTitle}"` : '';
const captionSource = title && title.trim() ? title : alt;
const safeCaption = captionSource ? this.escapeHtml(captionSource) : '';
const figcaption = safeCaption
? `<figcaption class="text-center text-sm text-obs-l-text-muted dark:text-obs-d-text-muted">${safeCaption}</figcaption>`
: '';
return `<figure class="my-4 md-attachment-figure">
<img src="${safeUrl}" alt="${safeAlt}"${titleAttr} loading="lazy" class="rounded-lg max-w-full h-auto mx-auto">
${figcaption}
</figure>`;
});
// Embedded Files ![[file.png]]
html = html.replace(/!\[\[(.*?)\]\]/g, (match, filename) => {
return `<figure class="my-4"><img src="https://picsum.photos/600/400?random=${Math.random()}" alt="${filename}" class="rounded-lg max-w-full h-auto mx-auto"><figcaption class="text-center text-sm text-obs-l-text-muted dark:text-obs-d-text-muted mt-2">${filename}</figcaption></figure>`;
// External links [text](url "title")
html = html.replace(/\[(.*?)\]\(((?:https?|ftp|file|mailto):\/\/[^\s\)]*)(?:\s+"(.*?)")?\)/g, (match, label, url, title) => {
const safeLabel = this.escapeHtml(label ?? '');
const safeUrl = this.escapeHtml(url ?? '');
const safeTitle = title ? this.escapeHtml(title) : '';
const titleAttr = title ? ` title="${safeTitle}"` : '';
return `<a href="${safeUrl}"${titleAttr} target="_blank" rel="noopener noreferrer" class="md-external-link">${safeLabel}</a>`;
});
// Embedded Files ![[file.png]] using Attachements-Path from HOME.md (traité avant les liens internes)
const homeNote = allNotes.find(n =>
(n.fileName?.toLowerCase?.() === 'home.md') ||
(n.originalPath?.toLowerCase?.() === 'home') ||
(n.originalPath?.toLowerCase?.().endsWith('/home'))
);
const attachmentsBase = (() => {
if (!homeNote) return '';
const fm = homeNote.frontmatter || {};
const key = Object.keys(fm).find(k => k?.toLowerCase?.() === 'attachements-path' || k?.toLowerCase?.() === 'attachments-path');
const raw = key ? `${fm[key] ?? ''}` : '';
return raw;
})();
html = html.replace(/!\[\[(.*?)\]\]/g, (match, rawName) => {
const filename = `${rawName}`.trim();
const safeAlt = this.escapeHtml(filename);
const notePath = (currentNote?.filePath || currentNote?.originalPath || '').replace(/\\/g, '/');
const src = `/api/attachments/resolve?name=${encodeURIComponent(filename)}&note=${encodeURIComponent(notePath)}&base=${encodeURIComponent(attachmentsBase)}`;
return `<figure class="my-4 md-attachment-figure">
<img src="${src}" alt="${safeAlt}" loading="lazy" class="rounded-lg max-w-full h-auto mx-auto md-attachment-image" data-attachment-name="${safeAlt}" data-error-message="&lt;div class=&#39;missing-attachment text-center text-sm text-red-500 dark:text-red-400&#39;&gt;Attachement ${this.escapeHtml(filename).replace(/'/g, '&#39;')} introuvable&lt;/div&gt;">
<figcaption class="text-center text-sm text-obs-l-text-muted dark:text-obs-d-text-muted">${safeAlt}</figcaption>
</figure>`;
});
// Horizontal Rule
html = html.replace(/^-{3,}/gm, '<hr class="my-6 border-obs-l-border dark:border-obs-d-border">');
// Paragraphs and line breaks
html = html.split('\n').map(p => p.trim() === '' ? '' : `<p>${p}</p>`).join('').replace(/<\/p><p>/g, '</p><br><p>');