feat: add markdown playground component view toggle and attachment handling

This commit is contained in:
2025-10-15 21:05:31 -04:00
parent 7fd4f5bf8e
commit c2315735ff
15 changed files with 3556 additions and 155 deletions
@@ -3,13 +3,15 @@ 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],
imports: [CommonModule, FormsModule, HttpClientModule, MarkdownViewerComponent],
template: `
<div class="h-full flex flex-col bg-gray-50 dark:bg-gray-900">
<!-- Header -->
@@ -28,7 +30,8 @@ const DEFAULT_MD_PATH = 'assets/samples/markdown-playground.md';
<h2 class="text-sm font-semibold text-gray-700 dark:text-gray-300">Markdown Source</h2>
</div>
<textarea
[(ngModel)]="sample"
[ngModel]="sample()"
(ngModelChange)="sample.set($event)"
class="flex-1 p-4 font-mono text-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 resize-none focus:outline-none"
placeholder="Entrez votre Markdown ici..."
spellcheck="false"
@@ -39,15 +42,35 @@ const DEFAULT_MD_PATH = 'assets/samples/markdown-playground.md';
<div class="flex-1 flex flex-col bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden">
<div class="px-4 py-2 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-750 flex items-center justify-between">
<h2 class="text-sm font-semibold text-gray-700 dark:text-gray-300">Preview</h2>
<button
(click)="resetToDefault()"
class="text-xs px-3 py-1 rounded bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-300"
>
Reset
</button>
<div class="flex items-center gap-2">
<button
(click)="toggleViewMode()"
class="text-xs px-3 py-1 rounded bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-300"
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-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-300"
>
Reset
</button>
</div>
</div>
<div class="flex-1 overflow-auto p-4">
<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="prose prose-slate dark:prose-invert max-w-none"
[innerHTML]="renderedHtml()"
></div>
@@ -98,6 +121,7 @@ export class MarkdownPlaygroundComponent {
private http = inject(HttpClient);
sample = signal<string>('');
useComponentView = signal<boolean>(true);
renderedHtml = computed(() => {
const markdown = this.sample();
@@ -117,8 +141,14 @@ export class MarkdownPlaygroundComponent {
this.http.get(DEFAULT_MD_PATH, { responseType: 'text' }).subscribe({
next: (text) => this.sample.set(text ?? ''),
error: (err) => {
console.error('Failed to load default markdown:', err);
this.sample.set('');
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('');
}
});
}
});
}
@@ -126,4 +156,8 @@ export class MarkdownPlaygroundComponent {
resetToDefault(): void {
this.loadDefaultSample();
}
toggleViewMode(): void {
this.useComponentView.update(v => !v);
}
}