```
feat: add line numbers to code blocks with gutter styling - Implemented line number display with absolute positioned gutter (40px width, right-aligned text) - Added dynamic padding to pre element based on showLineNumbers state (3.5rem left padding when enabled) - Moved hljs import to top-level for better performance and removed redundant dynamic imports - Added ViewEncapsulation.None to enable global hljs theme styling - Enhanced gutter styling with semi-transparent background, border, and pointer
This commit is contained in:
parent
2a5047b7f0
commit
b695095593
@ -9,12 +9,14 @@ import {
|
|||||||
inject,
|
inject,
|
||||||
HostListener,
|
HostListener,
|
||||||
ChangeDetectionStrategy,
|
ChangeDetectionStrategy,
|
||||||
ChangeDetectorRef
|
ChangeDetectorRef,
|
||||||
|
ViewEncapsulation
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { Block, CodeProps } from '../../../core/models/block.model';
|
import { Block, CodeProps } from '../../../core/models/block.model';
|
||||||
import { CodeThemeService } from '../../../services/code-theme.service';
|
import { CodeThemeService } from '../../../services/code-theme.service';
|
||||||
|
import hljs from 'highlight.js/lib/common';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-code-block',
|
selector: 'app-code-block',
|
||||||
@ -22,6 +24,7 @@ import { CodeThemeService } from '../../../services/code-theme.service';
|
|||||||
imports: [CommonModule, FormsModule],
|
imports: [CommonModule, FormsModule],
|
||||||
styleUrls: ['./code-themes.css'],
|
styleUrls: ['./code-themes.css'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
template: `
|
template: `
|
||||||
<div class="relative group w-full">
|
<div class="relative group w-full">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
@ -352,10 +355,12 @@ import { CodeThemeService } from '../../../services/code-theme.service';
|
|||||||
class="rounded-b-md border border-t-0 border-border overflow-hidden transition-colors duration-200"
|
class="rounded-b-md border border-t-0 border-border overflow-hidden transition-colors duration-200"
|
||||||
[ngClass]="getThemeClass()"
|
[ngClass]="getThemeClass()"
|
||||||
>
|
>
|
||||||
|
<div class="relative w-full">
|
||||||
<pre
|
<pre
|
||||||
class="m-0 max-h-[400px] overflow-auto text-sm leading-6 px-3 py-3 custom-scrollbar"
|
class="m-0 max-h-[400px] overflow-auto text-sm leading-6 custom-scrollbar"
|
||||||
[class.whitespace-pre-wrap]="props.enableWrap"
|
[class.whitespace-pre-wrap]="props.enableWrap"
|
||||||
[style.font-family]="getFontFamily()"
|
[style.font-family]="getFontFamily()"
|
||||||
|
[style.padding]="props.showLineNumbers ? '12px 12px 12px 3.5rem' : '12px'"
|
||||||
>
|
>
|
||||||
@if (highlightedHtml) {
|
@if (highlightedHtml) {
|
||||||
<code class="hljs block" [innerHTML]="highlightedHtml" [style.font-family]="getFontFamily()"></code>
|
<code class="hljs block" [innerHTML]="highlightedHtml" [style.font-family]="getFontFamily()"></code>
|
||||||
@ -365,6 +370,19 @@ import { CodeThemeService } from '../../../services/code-theme.service';
|
|||||||
</code>
|
</code>
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
@if (props.showLineNumbers) {
|
||||||
|
<div
|
||||||
|
class="absolute top-0 left-0 py-3 w-10 text-right text-xs leading-6 text-neutral-500 pointer-events-none select-none border-r border-white/5 bg-black/5 h-full"
|
||||||
|
[style.font-family]="getFontFamily()"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
@for (line of lineNumbers; track $index) {
|
||||||
|
<div class="pr-2">{{ line }}</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@ -703,20 +721,16 @@ export class CodeBlockComponent implements AfterViewInit {
|
|||||||
this._lastHighlightSignature = signature;
|
this._lastHighlightSignature = signature;
|
||||||
|
|
||||||
try {
|
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;
|
let html: string;
|
||||||
try {
|
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) {
|
if (hasLang) {
|
||||||
html = hljs.highlight(code, { language: lang }).value;
|
html = (hljs as any).highlight(code, { language: lang }).value;
|
||||||
} else {
|
} else {
|
||||||
html = hljs.highlightAuto(code).value;
|
html = (hljs as any).highlightAuto(code).value;
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
html = hljs.highlightAuto(code).value;
|
html = (hljs as any).highlightAuto(code).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.highlightedHtml = html;
|
this.highlightedHtml = html;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user