diff --git a/src/app/editor/components/block/blocks/code-block.component.ts b/src/app/editor/components/block/blocks/code-block.component.ts index 96c90d8..ff8216e 100644 --- a/src/app/editor/components/block/blocks/code-block.component.ts +++ b/src/app/editor/components/block/blocks/code-block.component.ts @@ -9,12 +9,14 @@ import { inject, HostListener, ChangeDetectionStrategy, - ChangeDetectorRef + ChangeDetectorRef, + ViewEncapsulation } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { Block, CodeProps } from '../../../core/models/block.model'; import { CodeThemeService } from '../../../services/code-theme.service'; +import hljs from 'highlight.js/lib/common'; @Component({ selector: 'app-code-block', @@ -22,6 +24,7 @@ import { CodeThemeService } from '../../../services/code-theme.service'; imports: [CommonModule, FormsModule], styleUrls: ['./code-themes.css'], changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None, template: `
@@ -352,19 +355,34 @@ import { CodeThemeService } from '../../../services/code-theme.service'; class="rounded-b-md border border-t-0 border-border overflow-hidden transition-colors duration-200" [ngClass]="getThemeClass()" > -
-            @if (highlightedHtml) {
-              
-            } @else {
-              
-                {{ props.code || '' }}
-              
+          
+
+              @if (highlightedHtml) {
+                
+              } @else {
+                
+                  {{ props.code || '' }}
+                
+              }
+            
+ + @if (props.showLineNumbers) { + } -
+
} @@ -703,20 +721,16 @@ export class CodeBlockComponent implements AfterViewInit { this._lastHighlightSignature = signature; try { - // Use the common Highlight.js bundle (works better with modern bundlers) - const hljsModule = await import('highlight.js/lib/common'); - const hljs: any = (hljsModule as any).default ?? hljsModule; - let html: string; try { - const hasLang = !!(lang && typeof hljs.getLanguage === 'function' && hljs.getLanguage(lang)); + const hasLang = !!(lang && typeof (hljs as any).getLanguage === 'function' && (hljs as any).getLanguage(lang)); if (hasLang) { - html = hljs.highlight(code, { language: lang }).value; + html = (hljs as any).highlight(code, { language: lang }).value; } else { - html = hljs.highlightAuto(code).value; + html = (hljs as any).highlightAuto(code).value; } } catch { - html = hljs.highlightAuto(code).value; + html = (hljs as any).highlightAuto(code).value; } this.highlightedHtml = html; diff --git a/vault/tests/nimbus-editor-snapshot.md b/vault/tests/nimbus-editor-snapshot.md index 313623c..a654810 100644 --- a/vault/tests/nimbus-editor-snapshot.md +++ b/vault/tests/nimbus-editor-snapshot.md @@ -10,27 +10,45 @@ documentModelFormat: "block-model-v1" "title": "Page Tests", "blocks": [ { - "id": "block_1763591049445_1hgsuarl4", + "id": "block_1763595565820_kugx72rs2", + "type": "bookmark", + "props": { + "url": "https://antigravity.google/support", + "title": "Google Antigravity", + "description": "Google Antigravity - Build the new way", + "siteName": "Google Antigravity", + "imageUrl": "https://antigravity.google/assets/image/sitecards/sitecard-default.png", + "faviconUrl": "assets/image/antigravity-logo.png", + "loading": false, + "error": null + }, + "meta": { + "createdAt": "2025-11-19T23:39:25.820Z", + "updatedAt": "2025-11-19T23:48:19.732Z" + } + }, + { + "id": "block_1763591724959_af8w3g4ra", "type": "code", "props": { - "code": "#!/usr/bin/env pwsh\r\n# Script de démarrage rapide pour ObsiViewer en mode développement\r\n\r\nparam(\r\n [string]$VaultPath = \"./vault\",\r\n [switch]$SkipMeili,\r\n [switch]$ResetMeili,\r\n [switch]$Help\r\n)\r\n\r\nif ($Help) {\r\n Write-Host @\"\r\nUsage: .\\start-dev.ps1 [-VaultPath ] [-SkipMeili] [-Help]\r\n\r\nOptions:\r\n -VaultPath Chemin vers votre vault Obsidian (défaut: ./vault)\r\n -SkipMeili Ne pas démarrer Meilisearch\r\n -ResetMeili Supprimer le conteneur et le volume Meilisearch avant de redémarrer\r\n -SkipMeili Ne pas démarrer Meilisearch\r\n -Help Afficher cette aide\r\n\r\nExemples:\r\n .\\start-dev.ps1\r\n .\\start-dev.ps1 -VaultPath C:\\Users\\moi\\Documents\\MonVault\r\n .\\start-dev.ps1 -SkipMeili\r\n\"@\r\n exit 0\r\n}\r\n\r\n$ErrorActionPreference = \"Stop\"\r\n\r\nWrite-Host \"🚀 Démarrage d'ObsiViewer en mode développement\" -ForegroundColor Cyan\r\nWrite-Host \"\"\r\n\r\n# Diagnostic: Vérifier les variables Meilisearch existantes\r\n$meiliVars = Get-ChildItem Env: | Where-Object { $_.Name -like 'MEILI*' }\r\nif ($meiliVars) {\r\n Write-Host \"⚠️ Variables Meilisearch détectées dans l'environnement:\" -ForegroundColor Yellow\r\n foreach ($var in $meiliVars) {\r\n Write-Host \" $($var.Name) = $($var.Value)\" -ForegroundColor Gray\r\n }\r\n Write-Host \" Ces variables seront purgées...\" -ForegroundColor Yellow\r\n Write-Host \"\"\r\n}\r\n\r\n# Vérifier que le vault existe\r\nif (-not (Test-Path $VaultPath)) {\r\n Write-Host \"⚠️ Le vault n'existe pas: $VaultPath\" -ForegroundColor Yellow\r\n Write-Host \" Création du dossier...\" -ForegroundColor Yellow\r\n New-Item -ItemType Directory -Path $VaultPath -Force | Out-Null\r\n}\r\n\r\n$VaultPathAbsolute = Resolve-Path $VaultPath\r\nWrite-Host \"📁 Vault: $VaultPathAbsolute\" -ForegroundColor Green\r\n\r\n# Vérifier si .env existe\r\nif (-not (Test-Path \".env\")) {\r\n Write-Host \"⚠️ Fichier .env manquant\" -ForegroundColor Yellow\r\n if (Test-Path \".env.example\") {\r\n Write-Host \" Copie de .env.example vers .env...\" -ForegroundColor Yellow\r\n Copy-Item \".env.example\" \".env\"\r\n }\r\n}\r\n\r\n# Purger TOUTES les variables d'environnement Meilisearch conflictuelles\r\n$meiliVarsToPurge = Get-ChildItem Env: | Where-Object { $_.Name -like 'MEILI*' }\r\nif ($meiliVarsToPurge) {\r\n Write-Host \"🧹 Purge des variables Meilisearch existantes...\" -ForegroundColor Cyan\r\n foreach ($var in $meiliVarsToPurge) {\r\n Remove-Item \"Env:\\$($var.Name)\" -ErrorAction SilentlyContinue\r\n Write-Host \" ✓ $($var.Name) supprimée\" -ForegroundColor Gray\r\n }\r\n Write-Host \"\"\r\n}\r\n\r\n# Définir les variables d'environnement pour la session\r\n$env:VAULT_PATH = $VaultPathAbsolute\r\n$env:MEILI_MASTER_KEY = \"devMeiliKey123\"\r\n$env:MEILI_HOST = \"http://127.0.0.1:7700\"\r\n$env:PORT = \"4000\"\r\n\r\nWrite-Host \"✅ Variables d'environnement définies:\" -ForegroundColor Green\r\nWrite-Host \" VAULT_PATH=$env:VAULT_PATH\" -ForegroundColor Gray\r\nWrite-Host \" MEILI_MASTER_KEY=devMeiliKey123\" -ForegroundColor Gray\r\nWrite-Host \" MEILI_HOST=$env:MEILI_HOST\" -ForegroundColor Gray\r\n\r\n# Démarrer Meilisearch si demandé\r\nif (-not $SkipMeili) {\r\n Write-Host \"\"\r\n Write-Host \"🔍 Démarrage de Meilisearch...\" -ForegroundColor Cyan\r\n \r\n if ($ResetMeili) {\r\n Write-Host \"🧹 Réinitialisation de Meilisearch (conteneur + volume)...\" -ForegroundColor Yellow\r\n try {\r\n Push-Location \"docker-compose\"\r\n docker compose down -v meilisearch 2>$null | Out-Null\r\n Pop-Location\r\n } catch {\r\n Pop-Location 2>$null\r\n }\r\n # Forcer la suppression ciblée si nécessaire\r\n docker rm -f obsiviewer-meilisearch 2>$null | Out-Null\r\n docker volume rm -f docker-compose_meili_data 2>$null | Out-Null\r\n }\r\n\r\n # Vérifier si Meilisearch est déjà en cours\r\n $meiliRunning = docker ps --filter \"name=obsiviewer-meilisearch\" --format \"{{.Names}}\" 2>$null\r\n \r\n if ($meiliRunning) {\r\n Write-Host \" ✓ Meilisearch déjà en cours\" -ForegroundColor Green\r\n } else {\r\n npm run meili:up\r\n Write-Host \" ⏳ Attente du démarrage de Meilisearch...\" -ForegroundColor Yellow\r\n }\r\n \r\n # Attendre la santé du service /health\r\n $healthTimeoutSec = 30\r\n $healthUrl = \"http://127.0.0.1:7700/health\"\r\n $startWait = Get-Date\r\n while ($true) {\r\n try {\r\n $resp = Invoke-RestMethod -Uri $healthUrl -Method GET -TimeoutSec 3\r\n if ($resp.status -eq \"available\") {\r\n Write-Host \" ✓ Meilisearch est prêt\" -ForegroundColor Green\r\n break\r\n }\r\n } catch {\r\n # ignore and retry\r\n }\r\n if (((Get-Date) - $startWait).TotalSeconds -ge $healthTimeoutSec) {\r\n Write-Host \" ⚠️ Timeout d'attente de Meilisearch (continuer quand même)\" -ForegroundColor Yellow\r\n break\r\n }\r\n Start-Sleep -Milliseconds 500\r\n }\r\n\r\n Write-Host \"\"\r\n Write-Host \"📊 Indexation du vault...\" -ForegroundColor Cyan\r\n npm run meili:reindex\r\n}\r\n\r\nWrite-Host \"\"\r\nWrite-Host \"✅ Configuration terminée!\" -ForegroundColor Green\r\nWrite-Host \"\"\r\nWrite-Host \"Les variables d'environnement sont définies dans cette session PowerShell.\" -ForegroundColor Yellow\r\nWrite-Host \"\"\r\nWrite-Host \"Pour démarrer l'application, ouvrez 2 terminaux:\" -ForegroundColor Yellow\r\nWrite-Host \"\"\r\nWrite-Host \"Terminal 1 (Backend):\" -ForegroundColor Cyan\r\nWrite-Host \" node server/index.mjs\" -ForegroundColor White\r\nWrite-Host \" (Les variables VAULT_PATH, MEILI_MASTER_KEY sont déjà définies)\" -ForegroundColor Gray\r\nWrite-Host \"\"\r\nWrite-Host \"Terminal 2 (Frontend):\" -ForegroundColor Cyan\r\nWrite-Host \" npm run dev\" -ForegroundColor White\r\nWrite-Host \"\"\r\nWrite-Host \"⚠️ IMPORTANT: Si vous fermez ce terminal, les variables seront perdues.\" -ForegroundColor Yellow\r\nWrite-Host \" Relancez ce script ou définissez manuellement:\" -ForegroundColor Yellow\r\nWrite-Host \" `$env:VAULT_PATH='$VaultPathAbsolute'\" -ForegroundColor Gray\r\nWrite-Host \" `$env:MEILI_MASTER_KEY='devMeiliKey123'\" -ForegroundColor Gray\r\nWrite-Host \" Remove-Item Env:\\MEILI_API_KEY -ErrorAction SilentlyContinue\" -ForegroundColor Gray\r\nWrite-Host \"\"\r\nWrite-Host \"Accès:\" -ForegroundColor Yellow\r\nWrite-Host \" Frontend: http://localhost:3000\" -ForegroundColor White\r\nWrite-Host \" Backend API: http://localhost:4000\" -ForegroundColor White\r\nWrite-Host \" Meilisearch: http://localhost:7700\" -ForegroundColor White\r\nWrite-Host \"\"\r\n", - "lang": "powershell", - "theme": "default", + "code": "{\r\n \"id\": \"block_1763149113471_461xyut80\",\r\n \"title\": \"Page Tests\",\r\n \"blocks\": [\r\n {\r\n \"id\": \"block_1763591049445_1hgsuarl4\",\r\n \"type\": \"code\",\r\n \"props\": {\r\n \"code\": \"#!/usr/bin/env pwsh\\r\\n# Script de démarrage rapide pour ObsiViewer en mode développement\\r\\n\\r\\nparam(\\r\\n [string]$VaultPath = \\\"./vault\\\",\\r\\n [switch]$SkipMeili,\\r\\n [switch]$ResetMeili,\\r\\n [switch]$Help\\r\\n)\\r\\n\\r\\nif ($Help) {\\r\\n Write-Host @\\\"\\r\\nUsage: .\\\\start-dev.ps1 [-VaultPath ] [-SkipMeili] [-Help]\\r\\n\\r\\nOptions:\\r\\n -VaultPath Chemin vers votre vault Obsidian (défaut: ./vault)\\r\\n -SkipMeili Ne pas démarrer Meilisearch\\r\\n -ResetMeili Supprimer le conteneur et le volume Meilisearch avant de redémarrer\\r\\n -SkipMeili Ne pas démarrer Meilisearch\\r\\n -Help Afficher cette aide\\r\\n\\r\\nExemples:\\r\\n .\\\\start-dev.ps1\\r\\n .\\\\start-dev.ps1 -VaultPath C:\\\\Users\\\\moi\\\\Documents\\\\MonVault\\r\\n .\\\\start-dev.ps1 -SkipMeili\\r\\n\\\"@\\r\\n exit 0\\r\\n}\\r\\n\\r\\n$ErrorActionPreference = \\\"Stop\\\"\\r\\n\\r\\nWrite-Host \\\"🚀 Démarrage d'ObsiViewer en mode développement\\\" -ForegroundColor Cyan\\r\\nWrite-Host \\\"\\\"\\r\\n\\r\\n# Diagnostic: Vérifier les variables Meilisearch existantes\\r\\n$meiliVars = Get-ChildItem Env: | Where-Object { $_.Name -like 'MEILI*' }\\r\\nif ($meiliVars) {\\r\\n Write-Host \\\"⚠️ Variables Meilisearch détectées dans l'environnement:\\\" -ForegroundColor Yellow\\r\\n foreach ($var in $meiliVars) {\\r\\n Write-Host \\\" $($var.Name) = $($var.Value)\\\" -ForegroundColor Gray\\r\\n }\\r\\n Write-Host \\\" Ces variables seront purgées...\\\" -ForegroundColor Yellow\\r\\n Write-Host \\\"\\\"\\r\\n}\\r\\n\\r\\n# Vérifier que le vault existe\\r\\nif (-not (Test-Path $VaultPath)) {\\r\\n Write-Host \\\"⚠️ Le vault n'existe pas: $VaultPath\\\" -ForegroundColor Yellow\\r\\n Write-Host \\\" Création du dossier...\\\" -ForegroundColor Yellow\\r\\n New-Item -ItemType Directory -Path $VaultPath -Force | Out-Null\\r\\n}\\r\\n\\r\\n$VaultPathAbsolute = Resolve-Path $VaultPath\\r\\nWrite-Host \\\"📁 Vault: $VaultPathAbsolute\\\" -ForegroundColor Green\\r\\n\\r\\n# Vérifier si .env existe\\r\\nif (-not (Test-Path \\\".env\\\")) {\\r\\n Write-Host \\\"⚠️ Fichier .env manquant\\\" -ForegroundColor Yellow\\r\\n if (Test-Path \\\".env.example\\\") {\\r\\n Write-Host \\\" Copie de .env.example vers .env...\\\" -ForegroundColor Yellow\\r\\n Copy-Item \\\".env.example\\\" \\\".env\\\"\\r\\n }\\r\\n}\\r\\n\\r\\n# Purger TOUTES les variables d'environnement Meilisearch conflictuelles\\r\\n$meiliVarsToPurge = Get-ChildItem Env: | Where-Object { $_.Name -like 'MEILI*' }\\r\\nif ($meiliVarsToPurge) {\\r\\n Write-Host \\\"🧹 Purge des variables Meilisearch existantes...\\\" -ForegroundColor Cyan\\r\\n foreach ($var in $meiliVarsToPurge) {\\r\\n Remove-Item \\\"Env:\\\\$($var.Name)\\\" -ErrorAction SilentlyContinue\\r\\n Write-Host \\\" ✓ $($var.Name) supprimée\\\" -ForegroundColor Gray\\r\\n }\\r\\n Write-Host \\\"\\\"\\r\\n}\\r\\n\\r\\n# Définir les variables d'environnement pour la session\\r\\n$env:VAULT_PATH = $VaultPathAbsolute\\r\\n$env:MEILI_MASTER_KEY = \\\"devMeiliKey123\\\"\\r\\n$env:MEILI_HOST = \\\"http://127.0.0.1:7700\\\"\\r\\n$env:PORT = \\\"4000\\\"\\r\\n\\r\\nWrite-Host \\\"✅ Variables d'environnement définies:\\\" -ForegroundColor Green\\r\\nWrite-Host \\\" VAULT_PATH=$env:VAULT_PATH\\\" -ForegroundColor Gray\\r\\nWrite-Host \\\" MEILI_MASTER_KEY=devMeiliKey123\\\" -ForegroundColor Gray\\r\\nWrite-Host \\\" MEILI_HOST=$env:MEILI_HOST\\\" -ForegroundColor Gray\\r\\n\\r\\n# Démarrer Meilisearch si demandé\\r\\nif (-not $SkipMeili) {\\r\\n Write-Host \\\"\\\"\\r\\n Write-Host \\\"🔍 Démarrage de Meilisearch...\\\" -ForegroundColor Cyan\\r\\n \\r\\n if ($ResetMeili) {\\r\\n Write-Host \\\"🧹 Réinitialisation de Meilisearch (conteneur + volume)...\\\" -ForegroundColor Yellow\\r\\n try {\\r\\n Push-Location \\\"docker-compose\\\"\\r\\n docker compose down -v meilisearch 2>$null | Out-Null\\r\\n Pop-Location\\r\\n } catch {\\r\\n Pop-Location 2>$null\\r\\n }\\r\\n # Forcer la suppression ciblée si nécessaire\\r\\n docker rm -f obsiviewer-meilisearch 2>$null | Out-Null\\r\\n docker volume rm -f docker-compose_meili_data 2>$null | Out-Null\\r\\n }\\r\\n\\r\\n # Vérifier si Meilisearch est déjà en cours\\r\\n $meiliRunning = docker ps --filter \\\"name=obsiviewer-meilisearch\\\" --format \\\"{{.Names}}\\\" 2>$null\\r\\n \\r\\n if ($meiliRunning) {\\r\\n Write-Host \\\" ✓ Meilisearch déjà en cours\\\" -ForegroundColor Green\\r\\n } else {\\r\\n npm run meili:up\\r\\n Write-Host \\\" ⏳ Attente du démarrage de Meilisearch...\\\" -ForegroundColor Yellow\\r\\n }\\r\\n \\r\\n # Attendre la santé du service /health\\r\\n $healthTimeoutSec = 30\\r\\n $healthUrl = \\\"http://127.0.0.1:7700/health\\\"\\r\\n $startWait = Get-Date\\r\\n while ($true) {\\r\\n try {\\r\\n $resp = Invoke-RestMethod -Uri $healthUrl -Method GET -TimeoutSec 3\\r\\n if ($resp.status -eq \\\"available\\\") {\\r\\n Write-Host \\\" ✓ Meilisearch est prêt\\\" -ForegroundColor Green\\r\\n break\\r\\n }\\r\\n } catch {\\r\\n # ignore and retry\\r\\n }\\r\\n if (((Get-Date) - $startWait).TotalSeconds -ge $healthTimeoutSec) {\\r\\n Write-Host \\\" ⚠️ Timeout d'attente de Meilisearch (continuer quand même)\\\" -ForegroundColor Yellow\\r\\n break\\r\\n }\\r\\n Start-Sleep -Milliseconds 500\\r\\n }\\r\\n\\r\\n Write-Host \\\"\\\"\\r\\n Write-Host \\\"📊 Indexation du vault...\\\" -ForegroundColor Cyan\\r\\n npm run meili:reindex\\r\\n}\\r\\n\\r\\nWrite-Host \\\"\\\"\\r\\nWrite-Host \\\"✅ Configuration terminée!\\\" -ForegroundColor Green\\r\\nWrite-Host \\\"\\\"\\r\\nWrite-Host \\\"Les variables d'environnement sont définies dans cette session PowerShell.\\\" -ForegroundColor Yellow\\r\\nWrite-Host \\\"\\\"\\r\\nWrite-Host \\\"Pour démarrer l'application, ouvrez 2 terminaux:\\\" -ForegroundColor Yellow\\r\\nWrite-Host \\\"\\\"\\r\\nWrite-Host \\\"Terminal 1 (Backend):\\\" -ForegroundColor Cyan\\r\\nWrite-Host \\\" node server/index.mjs\\\" -ForegroundColor White\\r\\nWrite-Host \\\" (Les variables VAULT_PATH, MEILI_MASTER_KEY sont déjà définies)\\\" -ForegroundColor Gray\\r\\nWrite-Host \\\"\\\"\\r\\nWrite-Host \\\"Terminal 2 (Frontend):\\\" -ForegroundColor Cyan\\r\\nWrite-Host \\\" npm run dev\\\" -ForegroundColor White\\r\\nWrite-Host \\\"\\\"\\r\\nWrite-Host \\\"⚠️ IMPORTANT: Si vous fermez ce terminal, les variables seront perdues.\\\" -ForegroundColor Yellow\\r\\nWrite-Host \\\" Relancez ce script ou définissez manuellement:\\\" -ForegroundColor Yellow\\r\\nWrite-Host \\\" `$env:VAULT_PATH='$VaultPathAbsolute'\\\" -ForegroundColor Gray\\r\\nWrite-Host \\\" `$env:MEILI_MASTER_KEY='devMeiliKey123'\\\" -ForegroundColor Gray\\r\\nWrite-Host \\\" Remove-Item Env:\\\\MEILI_API_KEY -ErrorAction SilentlyContinue\\\" -ForegroundColor Gray\\r\\nWrite-Host \\\"\\\"\\r\\nWrite-Host \\\"Accès:\\\" -ForegroundColor Yellow\\r\\nWrite-Host \\\" Frontend: http://localhost:3000\\\" -ForegroundColor White\\r\\nWrite-Host \\\" Backend API: http://localhost:4000\\\" -ForegroundColor White\\r\\nWrite-Host \\\" Meilisearch: http://localhost:7700\\\" -ForegroundColor White\\r\\nWrite-Host \\\"\\\"\\r\\n\",\r\n \"lang\": \"powershell\",\r\n \"theme\": \"default\",\r\n \"showLineNumbers\": true,\r\n \"enableWrap\": false,\r\n \"collapsed\": false,\r\n \"font\": \"courier\",\r\n \"autoDetectLang\": false\r\n },\r\n \"meta\": {\r\n \"createdAt\": \"2025-11-19T22:24:09.445Z\",\r\n \"updatedAt\": \"2025-11-19T22:33:16.600Z\"\r\n }\r\n }\r\n ],\r\n \"meta\": {\r\n \"createdAt\": \"2025-11-14T19:38:33.471Z\",\r\n \"updatedAt\": \"2025-11-19T22:33:16.600Z\"\r\n }\r\n}\n", + "lang": "json", "showLineNumbers": true, "enableWrap": false, "collapsed": true, - "font": "courier", - "autoDetectLang": false + "autoDetectLang": false, + "theme": "darcula", + "font": "fira" }, "meta": { - "createdAt": "2025-11-19T22:24:09.445Z", - "updatedAt": "2025-11-19T22:29:31.546Z" + "createdAt": "2025-11-19T22:35:24.959Z", + "updatedAt": "2025-11-19T23:39:21.275Z" } } ], "meta": { "createdAt": "2025-11-14T19:38:33.471Z", - "updatedAt": "2025-11-19T22:29:31.546Z" + "updatedAt": "2025-11-19T23:48:19.732Z" } } ```