ObsiViewer/src/app/features/tests/markdown-playground/markdown-playground.component.ts

164 lines
5.6 KiB
TypeScript

import { Component, signal, computed, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { MarkdownService } from '../../../../services/markdown.service';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { MarkdownViewerComponent } from '../../../../components/markdown-viewer/markdown-viewer.component';
const DEFAULT_MD_PATH = 'assets/samples/markdown-playground.md';
const DEFAULT_MD_PATH_ABS = '/assets/samples/markdown-playground.md';
@Component({
selector: 'app-markdown-playground',
standalone: true,
imports: [CommonModule, FormsModule, HttpClientModule, MarkdownViewerComponent],
template: `
<div class="h-full flex flex-col bg-surface1 dark:bg-main">
<!-- Header -->
<header class="bg-card dark:bg-card border-b border-border dark:border-border px-6 py-4">
<h1 class="text-2xl font-semibold text-main dark:text-gray-100">Markdown Playground</h1>
<p class="text-sm text-muted dark:text-muted mt-1">
Page de test interne pour valider tous les formatages Markdown supportés par ObsiViewer.
</p>
</header>
<!-- Content -->
<div class="flex-1 flex gap-4 p-4 overflow-hidden">
<!-- Editor Panel -->
<div class="flex-1 flex flex-col bg-card dark:bg-card rounded-lg border border-border dark:border-border overflow-hidden">
<div class="px-4 py-2 border-b border-border dark:border-border bg-surface1 dark:bg-gray-750">
<h2 class="text-sm font-semibold text-main dark:text-main">Markdown Source</h2>
</div>
<textarea
[ngModel]="sample()"
(ngModelChange)="sample.set($event)"
class="flex-1 p-4 font-mono text-sm bg-card dark:bg-card text-main dark:text-gray-100 resize-none focus:outline-none"
placeholder="Entrez votre Markdown ici..."
spellcheck="false"
></textarea>
</div>
<!-- Preview Panel -->
<div class="flex-1 flex flex-col bg-card dark:bg-card rounded-lg border border-border dark:border-border overflow-hidden">
<div class="px-4 py-2 border-b border-border dark:border-border bg-surface1 dark:bg-gray-750 flex items-center justify-between">
<h2 class="text-sm font-semibold text-main dark:text-main">Preview</h2>
<div class="flex items-center gap-2">
<button
(click)="toggleViewMode()"
class="text-xs px-3 py-1 rounded bg-surface2 dark:bg-surface2 hover:bg-muted dark:hover:bg-gray-600 text-main dark:text-main"
title="Toggle between inline and component view"
>
{{ useComponentView() ? 'Inline View' : 'Component View' }}
</button>
<button
(click)="resetToDefault()"
class="text-xs px-3 py-1 rounded bg-surface2 dark:bg-surface2 hover:bg-muted dark:hover:bg-gray-600 text-main dark:text-main"
>
Reset
</button>
</div>
</div>
<div class="flex-1 overflow-auto" [class.p-4]="!useComponentView()">
<!-- Component View -->
<app-markdown-viewer
*ngIf="useComponentView()"
[content]="sample()"
[allNotes]="[]"
[showToolbar]="false"
[fullscreenMode]="false">
</app-markdown-viewer>
<!-- Inline View -->
<div
*ngIf="!useComponentView()"
class="md-view"
[innerHTML]="renderedHtml()"
></div>
</div>
</div>
</div>
</div>
`,
styles: [`
:host {
display: block;
height: 100%;
}
textarea {
tab-size: 2;
}
textarea::-webkit-scrollbar {
width: 8px;
height: 8px;
}
textarea::-webkit-scrollbar-track {
background: transparent;
}
textarea::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.2);
border-radius: 4px;
}
textarea::-webkit-scrollbar-thumb:hover {
background: rgba(0, 0, 0, 0.3);
}
.dark textarea::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.2);
}
.dark textarea::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.3);
}
`]
})
export class MarkdownPlaygroundComponent {
private markdownService = inject(MarkdownService);
private http = inject(HttpClient);
sample = signal<string>('');
useComponentView = signal<boolean>(true);
renderedHtml = computed(() => {
const markdown = this.sample();
try {
return this.markdownService.render(markdown, [], undefined);
} catch (error) {
console.error('Markdown render error:', error);
return `<div class="text-red-500">Erreur de rendu: ${error}</div>`;
}
});
constructor() {
this.loadDefaultSample();
}
private loadDefaultSample(): void {
this.http.get(DEFAULT_MD_PATH, { responseType: 'text' }).subscribe({
next: (text) => this.sample.set(text ?? ''),
error: (err) => {
console.warn('Fallback: retry loading default markdown via absolute path', err);
this.http.get(DEFAULT_MD_PATH_ABS, { responseType: 'text' }).subscribe({
next: (text) => this.sample.set(text ?? ''),
error: (err2) => {
console.error('Failed to load default markdown (both paths):', err2);
this.sample.set('');
}
});
}
});
}
resetToDefault(): void {
this.loadDefaultSample();
}
toggleViewMode(): void {
this.useComponentView.update(v => !v);
}
}