@lifecorner/angular-ui-kit 3.6.0 → 3.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as i0 from "@angular/core";
|
|
2
|
-
import { ChangeDetectionStrategy, Component, computed,
|
|
3
|
-
import { DomSanitizer } from "@angular/platform-browser";
|
|
2
|
+
import { ChangeDetectionStrategy, Component, computed, input, signal } from "@angular/core";
|
|
4
3
|
import { IconComponent, ɵprovideKitIcons } from "@lifecorner/angular-ui-kit/icon";
|
|
5
4
|
import { ICON_CHECK } from "@lifecorner/angular-ui-kit/icons";
|
|
6
5
|
const SHARED_RULES = [
|
|
@@ -73,17 +72,13 @@ const LANGUAGE_RULES = {
|
|
|
73
72
|
}
|
|
74
73
|
],
|
|
75
74
|
html: [
|
|
76
|
-
{
|
|
77
|
-
pattern: /<!--[\s\S]*?-->/g,
|
|
78
|
-
className: "token-comment"
|
|
79
|
-
},
|
|
80
75
|
...SHARED_RULES,
|
|
81
76
|
{
|
|
82
|
-
pattern:
|
|
77
|
+
pattern: /<\/?[\w-]+/g,
|
|
83
78
|
className: "token-tag"
|
|
84
79
|
},
|
|
85
80
|
{
|
|
86
|
-
pattern:
|
|
81
|
+
pattern: /\/?>/g,
|
|
87
82
|
className: "token-tag"
|
|
88
83
|
},
|
|
89
84
|
{
|
|
@@ -242,22 +237,21 @@ const LANGUAGE_RULES = {
|
|
|
242
237
|
}
|
|
243
238
|
]
|
|
244
239
|
};
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
240
|
+
const EMPTY_LINE = [{
|
|
241
|
+
text: String.fromCharCode(160),
|
|
242
|
+
className: null
|
|
243
|
+
}];
|
|
244
|
+
function tokenize(code, language) {
|
|
250
245
|
const rules = LANGUAGE_RULES[language];
|
|
251
|
-
if (!rules) return
|
|
246
|
+
if (!rules) return [];
|
|
252
247
|
const tokens = [];
|
|
253
248
|
for (const rule of rules) {
|
|
254
249
|
const regex = new RegExp(rule.pattern.source, rule.pattern.flags);
|
|
255
250
|
let match;
|
|
256
|
-
while ((match = regex.exec(
|
|
251
|
+
while ((match = regex.exec(code)) !== null) tokens.push({
|
|
257
252
|
start: match.index,
|
|
258
253
|
end: match.index + match[0].length,
|
|
259
|
-
className: rule.className
|
|
260
|
-
text: match[0]
|
|
254
|
+
className: rule.className
|
|
261
255
|
});
|
|
262
256
|
}
|
|
263
257
|
tokens.sort((a, b) => a.start - b.start || b.end - a.end);
|
|
@@ -267,15 +261,35 @@ function highlightCode(code, language) {
|
|
|
267
261
|
filtered.push(token);
|
|
268
262
|
lastEnd = token.end;
|
|
269
263
|
}
|
|
270
|
-
|
|
264
|
+
return filtered;
|
|
265
|
+
}
|
|
266
|
+
function highlightLines(code, language) {
|
|
267
|
+
const lines = [[]];
|
|
268
|
+
const append = (text, className) => {
|
|
269
|
+
text.split("\n").forEach((part, i) => {
|
|
270
|
+
if (i > 0) lines.push([]);
|
|
271
|
+
if (!part) return;
|
|
272
|
+
const line = lines[lines.length - 1];
|
|
273
|
+
const cls = i === 0 ? className : null;
|
|
274
|
+
const last = line[line.length - 1];
|
|
275
|
+
if (cls === null && last?.className === null) line[line.length - 1] = {
|
|
276
|
+
text: last.text + part,
|
|
277
|
+
className: null
|
|
278
|
+
};
|
|
279
|
+
else line.push({
|
|
280
|
+
text: part,
|
|
281
|
+
className: cls
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
};
|
|
271
285
|
let cursor = 0;
|
|
272
|
-
for (const token of
|
|
273
|
-
|
|
274
|
-
|
|
286
|
+
for (const token of tokenize(code, language)) {
|
|
287
|
+
append(code.slice(cursor, token.start), null);
|
|
288
|
+
append(code.slice(token.start, token.end), token.className);
|
|
275
289
|
cursor = token.end;
|
|
276
290
|
}
|
|
277
|
-
|
|
278
|
-
return
|
|
291
|
+
append(code.slice(cursor), null);
|
|
292
|
+
return lines.map((line) => line.length ? line : EMPTY_LINE);
|
|
279
293
|
}
|
|
280
294
|
var CodeBlockComponent = class CodeBlockComponent {
|
|
281
295
|
code = input.required(...ngDevMode ? [{ debugName: "code" }] : /* istanbul ignore next */ []);
|
|
@@ -289,10 +303,7 @@ var CodeBlockComponent = class CodeBlockComponent {
|
|
|
289
303
|
copiedLabel = input("Copied", ...ngDevMode ? [{ debugName: "copiedLabel" }] : /* istanbul ignore next */ []);
|
|
290
304
|
copiedAnnouncement = input("Copied to clipboard", ...ngDevMode ? [{ debugName: "copiedAnnouncement" }] : /* istanbul ignore next */ []);
|
|
291
305
|
copied = signal(false, ...ngDevMode ? [{ debugName: "copied" }] : /* istanbul ignore next */ []);
|
|
292
|
-
|
|
293
|
-
highlightedLines = computed(() => {
|
|
294
|
-
return highlightCode(this.code(), this.language()).split("\n").map((line) => this.sanitizer.bypassSecurityTrustHtml(line || " "));
|
|
295
|
-
}, ...ngDevMode ? [{ debugName: "highlightedLines" }] : /* istanbul ignore next */ []);
|
|
306
|
+
highlightedLines = computed(() => highlightLines(this.code(), this.language()), ...ngDevMode ? [{ debugName: "highlightedLines" }] : /* istanbul ignore next */ []);
|
|
296
307
|
lineNumbers = computed(() => {
|
|
297
308
|
return this.code().split("\n").map((_, i) => i + 1);
|
|
298
309
|
}, ...ngDevMode ? [{ debugName: "lineNumbers" }] : /* istanbul ignore next */ []);
|
|
@@ -396,8 +407,8 @@ var CodeBlockComponent = class CodeBlockComponent {
|
|
|
396
407
|
}
|
|
397
408
|
},
|
|
398
409
|
ngImport: i0,
|
|
399
|
-
template: "<div [class]=\"codeClasses()\">\n @if (showHeader()) {\n <div class=\"code-block__header\">\n <span class=\"code-block__language\">{{ headerLabel() }}</span>\n @if (showCopy()) {\n <button\n type=\"button\"\n class=\"code-block__copy\"\n [attr.aria-label]=\"copied() ? copiedLabel() : copyAriaLabel()\"\n (click)=\"copyToClipboard()\"\n >\n @if (copied()) {\n <lc-icon name=\"check\" size=\"sm\" />\n <span>{{ copiedLabel() }}</span>\n } @else {\n <lc-icon name=\"clipboard-document\" size=\"sm\" />\n <span>{{ copyLabel() }}</span>\n }\n </button>\n <span class=\"code-block__live\" role=\"status\" aria-live=\"polite\">{{ copied() ? copiedAnnouncement() : '' }}</span>\n }\n </div>\n }\n <div class=\"code-block__body\">\n <pre class=\"code-block__pre\"><code class=\"code-block__code\">@for (line of highlightedLines(); track $index; let i = $index) {<span class=\"code-block__line\">@if (showLineNumbers()) {<span class=\"code-block__line-number\">{{ lineNumbers()[i] }}</span>}<span class=\"code-block__line-content\" [
|
|
400
|
-
styles: [".code-block{--lc-code-block-bg: #0c1722;--lc-code-block-ink: #eef4f6;--lc-code-block-muted: #93a4ad;--lc-code-block-muted-strong: #c4d2d9;--lc-code-block-border: #24343f;position:relative;border:1px solid var(--lc-code-block-border);border-radius:var(--border-radius-md);overflow:hidden;font-family:var(--typography-font-family-mono, \"SF Mono\", \"Fira Code\", \"Fira Mono\", monospace);font-size:var(--typography-font-size-sm, .875rem);line-height:1.1;background-color:var(--lc-code-block-bg);color:var(--lc-code-block-ink)}.code-block__header{display:flex;justify-content:space-between;align-items:center;min-height:2.75rem;padding:0 .25rem 0 1rem;background-color:#00000040;border-bottom:1px solid var(--lc-code-block-border)}.code-block__language{font-size:var(--typography-font-size-xs, .75rem);color:var(--lc-code-block-muted);text-transform:lowercase;-webkit-user-select:none;user-select:none}.code-block__copy{display:inline-flex;align-items:center;justify-content:center;gap:.25rem;min-height:2.75rem;min-width:2.75rem;padding:0 .75rem;border:none;border-radius:var(--border-radius-sm);background:transparent;color:var(--lc-code-block-muted);font-size:var(--typography-font-size-xs, .75rem);font-family:inherit;cursor:pointer;transition:color .15s ease,background-color .15s ease}.code-block__copy:hover{color:var(--lc-code-block-muted-strong);background-color:#ffffff0f}.code-block__copy:focus-visible{outline:none;color:var(--lc-code-block-muted-strong);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary-500) 40%,transparent)}.code-block__live{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.code-block__body{overflow-x:auto}.code-block__pre{margin:0;padding:1rem;background:transparent;color:inherit;border-radius:0}.code-block__code{display:block}.code-block__line{display:flex}.code-block__line-number{display:inline-block;min-width:2.5rem;padding-right:1rem;text-align:right;color:var(--lc-code-block-muted);-webkit-user-select:none;user-select:none;flex-shrink:0}.code-block__line-content{flex:1;white-space:pre}.code-block__line-content ::ng-deep .token-keyword{color:#c678dd}.code-block__line-content ::ng-deep .token-string{color:#98c379}.code-block__line-content ::ng-deep .token-number{color:#d19a66}.code-block__line-content ::ng-deep .token-comment{color
|
|
410
|
+
template: "<div [class]=\"codeClasses()\">\n @if (showHeader()) {\n <div class=\"code-block__header\">\n <span class=\"code-block__language\">{{ headerLabel() }}</span>\n @if (showCopy()) {\n <button\n type=\"button\"\n class=\"code-block__copy\"\n [attr.aria-label]=\"copied() ? copiedLabel() : copyAriaLabel()\"\n (click)=\"copyToClipboard()\"\n >\n @if (copied()) {\n <lc-icon name=\"check\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ copiedLabel() }}</span>\n } @else {\n <lc-icon name=\"clipboard-document\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ copyLabel() }}</span>\n }\n </button>\n <span class=\"code-block__live\" role=\"status\" aria-live=\"polite\">{{ copied() ? copiedAnnouncement() : '' }}</span>\n }\n </div>\n }\n <div class=\"code-block__body\">\n <pre class=\"code-block__pre\"><code class=\"code-block__code\">@for (line of highlightedLines(); track $index; let i = $index) {<span class=\"code-block__line\">@if (showLineNumbers()) {<span class=\"code-block__line-number\">{{ lineNumbers()[i] }}</span>}<span class=\"code-block__line-content\">@for (segment of line; track $index) {@if (segment.className) {<span [attr.class]=\"segment.className\">{{ segment.text }}</span>}@else{{{ segment.text }}}}</span></span>\n}</code></pre>\n </div>\n</div>\n",
|
|
411
|
+
styles: [".code-block{--lc-code-block-bg: #0c1722;--lc-code-block-ink: #eef4f6;--lc-code-block-muted: #93a4ad;--lc-code-block-muted-strong: #c4d2d9;--lc-code-block-border: #24343f;position:relative;border:1px solid var(--lc-code-block-border);border-radius:var(--border-radius-md);overflow:hidden;font-family:var(--typography-font-family-mono, \"SF Mono\", \"Fira Code\", \"Fira Mono\", monospace);font-size:var(--typography-font-size-sm, .875rem);line-height:1.1;background-color:var(--lc-code-block-bg);color:var(--lc-code-block-ink)}.code-block__header{display:flex;justify-content:space-between;align-items:center;min-height:2.75rem;padding:0 .25rem 0 1rem;background-color:#00000040;border-bottom:1px solid var(--lc-code-block-border)}.code-block__language{font-size:var(--typography-font-size-xs, .75rem);color:var(--lc-code-block-muted);text-transform:lowercase;-webkit-user-select:none;user-select:none}.code-block__copy{display:inline-flex;align-items:center;justify-content:center;gap:.25rem;min-height:2.75rem;min-width:2.75rem;padding:0 .75rem;border:none;border-radius:var(--border-radius-sm);background:transparent;color:var(--lc-code-block-muted);font-size:var(--typography-font-size-xs, .75rem);font-family:inherit;cursor:pointer;transition:color .15s ease,background-color .15s ease}.code-block__copy:hover{color:var(--lc-code-block-muted-strong);background-color:#ffffff0f}.code-block__copy:focus-visible{outline:none;color:var(--lc-code-block-muted-strong);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary-500) 40%,transparent)}.code-block__live{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.code-block__body{overflow-x:auto}.code-block__pre{margin:0;padding:1rem;background:transparent;color:inherit;border-radius:0}.code-block__code{display:block}.code-block__line{display:flex}.code-block__line-number{display:inline-block;min-width:2.5rem;padding-right:1rem;text-align:right;color:var(--lc-code-block-muted);-webkit-user-select:none;user-select:none;flex-shrink:0}.code-block__line-content{flex:1;white-space:pre}.code-block__line-content ::ng-deep .token-keyword{color:#c678dd}.code-block__line-content ::ng-deep .token-string{color:#98c379}.code-block__line-content ::ng-deep .token-number{color:#d19a66}.code-block__line-content ::ng-deep .token-comment{color:var(--lc-code-block-muted);font-style:italic}.code-block__line-content ::ng-deep .token-type{color:#e5c07b}.code-block__line-content ::ng-deep .token-constant{color:#d19a66}.code-block__line-content ::ng-deep .token-decorator{color:#61afef}.code-block__line-content ::ng-deep .token-tag{color:#e06c75}.code-block__line-content ::ng-deep .token-attr{color:#d19a66}.code-block__line-content ::ng-deep .token-selector{color:#e06c75}.code-block__line-content ::ng-deep .token-property{color:#61afef}.code-block__line-content ::ng-deep .token-unit{color:#d19a66}.code-block__line-content ::ng-deep .token-variable{color:#e06c75}.code-block__line-content ::ng-deep .token-builtin{color:#61afef}.code-block__line-content ::ng-deep .token-flag{color:#56b6c2}\n"],
|
|
401
412
|
dependencies: [{
|
|
402
413
|
kind: "component",
|
|
403
414
|
type: IconComponent,
|
|
@@ -429,8 +440,8 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
429
440
|
imports: [IconComponent],
|
|
430
441
|
viewProviders: [ɵprovideKitIcons([ICON_CHECK])],
|
|
431
442
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
432
|
-
template: "<div [class]=\"codeClasses()\">\n @if (showHeader()) {\n <div class=\"code-block__header\">\n <span class=\"code-block__language\">{{ headerLabel() }}</span>\n @if (showCopy()) {\n <button\n type=\"button\"\n class=\"code-block__copy\"\n [attr.aria-label]=\"copied() ? copiedLabel() : copyAriaLabel()\"\n (click)=\"copyToClipboard()\"\n >\n @if (copied()) {\n <lc-icon name=\"check\" size=\"sm\" />\n <span>{{ copiedLabel() }}</span>\n } @else {\n <lc-icon name=\"clipboard-document\" size=\"sm\" />\n <span>{{ copyLabel() }}</span>\n }\n </button>\n <span class=\"code-block__live\" role=\"status\" aria-live=\"polite\">{{ copied() ? copiedAnnouncement() : '' }}</span>\n }\n </div>\n }\n <div class=\"code-block__body\">\n <pre class=\"code-block__pre\"><code class=\"code-block__code\">@for (line of highlightedLines(); track $index; let i = $index) {<span class=\"code-block__line\">@if (showLineNumbers()) {<span class=\"code-block__line-number\">{{ lineNumbers()[i] }}</span>}<span class=\"code-block__line-content\" [
|
|
433
|
-
styles: [".code-block{--lc-code-block-bg: #0c1722;--lc-code-block-ink: #eef4f6;--lc-code-block-muted: #93a4ad;--lc-code-block-muted-strong: #c4d2d9;--lc-code-block-border: #24343f;position:relative;border:1px solid var(--lc-code-block-border);border-radius:var(--border-radius-md);overflow:hidden;font-family:var(--typography-font-family-mono, \"SF Mono\", \"Fira Code\", \"Fira Mono\", monospace);font-size:var(--typography-font-size-sm, .875rem);line-height:1.1;background-color:var(--lc-code-block-bg);color:var(--lc-code-block-ink)}.code-block__header{display:flex;justify-content:space-between;align-items:center;min-height:2.75rem;padding:0 .25rem 0 1rem;background-color:#00000040;border-bottom:1px solid var(--lc-code-block-border)}.code-block__language{font-size:var(--typography-font-size-xs, .75rem);color:var(--lc-code-block-muted);text-transform:lowercase;-webkit-user-select:none;user-select:none}.code-block__copy{display:inline-flex;align-items:center;justify-content:center;gap:.25rem;min-height:2.75rem;min-width:2.75rem;padding:0 .75rem;border:none;border-radius:var(--border-radius-sm);background:transparent;color:var(--lc-code-block-muted);font-size:var(--typography-font-size-xs, .75rem);font-family:inherit;cursor:pointer;transition:color .15s ease,background-color .15s ease}.code-block__copy:hover{color:var(--lc-code-block-muted-strong);background-color:#ffffff0f}.code-block__copy:focus-visible{outline:none;color:var(--lc-code-block-muted-strong);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary-500) 40%,transparent)}.code-block__live{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.code-block__body{overflow-x:auto}.code-block__pre{margin:0;padding:1rem;background:transparent;color:inherit;border-radius:0}.code-block__code{display:block}.code-block__line{display:flex}.code-block__line-number{display:inline-block;min-width:2.5rem;padding-right:1rem;text-align:right;color:var(--lc-code-block-muted);-webkit-user-select:none;user-select:none;flex-shrink:0}.code-block__line-content{flex:1;white-space:pre}.code-block__line-content ::ng-deep .token-keyword{color:#c678dd}.code-block__line-content ::ng-deep .token-string{color:#98c379}.code-block__line-content ::ng-deep .token-number{color:#d19a66}.code-block__line-content ::ng-deep .token-comment{color
|
|
443
|
+
template: "<div [class]=\"codeClasses()\">\n @if (showHeader()) {\n <div class=\"code-block__header\">\n <span class=\"code-block__language\">{{ headerLabel() }}</span>\n @if (showCopy()) {\n <button\n type=\"button\"\n class=\"code-block__copy\"\n [attr.aria-label]=\"copied() ? copiedLabel() : copyAriaLabel()\"\n (click)=\"copyToClipboard()\"\n >\n @if (copied()) {\n <lc-icon name=\"check\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ copiedLabel() }}</span>\n } @else {\n <lc-icon name=\"clipboard-document\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ copyLabel() }}</span>\n }\n </button>\n <span class=\"code-block__live\" role=\"status\" aria-live=\"polite\">{{ copied() ? copiedAnnouncement() : '' }}</span>\n }\n </div>\n }\n <div class=\"code-block__body\">\n <pre class=\"code-block__pre\"><code class=\"code-block__code\">@for (line of highlightedLines(); track $index; let i = $index) {<span class=\"code-block__line\">@if (showLineNumbers()) {<span class=\"code-block__line-number\">{{ lineNumbers()[i] }}</span>}<span class=\"code-block__line-content\">@for (segment of line; track $index) {@if (segment.className) {<span [attr.class]=\"segment.className\">{{ segment.text }}</span>}@else{{{ segment.text }}}}</span></span>\n}</code></pre>\n </div>\n</div>\n",
|
|
444
|
+
styles: [".code-block{--lc-code-block-bg: #0c1722;--lc-code-block-ink: #eef4f6;--lc-code-block-muted: #93a4ad;--lc-code-block-muted-strong: #c4d2d9;--lc-code-block-border: #24343f;position:relative;border:1px solid var(--lc-code-block-border);border-radius:var(--border-radius-md);overflow:hidden;font-family:var(--typography-font-family-mono, \"SF Mono\", \"Fira Code\", \"Fira Mono\", monospace);font-size:var(--typography-font-size-sm, .875rem);line-height:1.1;background-color:var(--lc-code-block-bg);color:var(--lc-code-block-ink)}.code-block__header{display:flex;justify-content:space-between;align-items:center;min-height:2.75rem;padding:0 .25rem 0 1rem;background-color:#00000040;border-bottom:1px solid var(--lc-code-block-border)}.code-block__language{font-size:var(--typography-font-size-xs, .75rem);color:var(--lc-code-block-muted);text-transform:lowercase;-webkit-user-select:none;user-select:none}.code-block__copy{display:inline-flex;align-items:center;justify-content:center;gap:.25rem;min-height:2.75rem;min-width:2.75rem;padding:0 .75rem;border:none;border-radius:var(--border-radius-sm);background:transparent;color:var(--lc-code-block-muted);font-size:var(--typography-font-size-xs, .75rem);font-family:inherit;cursor:pointer;transition:color .15s ease,background-color .15s ease}.code-block__copy:hover{color:var(--lc-code-block-muted-strong);background-color:#ffffff0f}.code-block__copy:focus-visible{outline:none;color:var(--lc-code-block-muted-strong);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary-500) 40%,transparent)}.code-block__live{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.code-block__body{overflow-x:auto}.code-block__pre{margin:0;padding:1rem;background:transparent;color:inherit;border-radius:0}.code-block__code{display:block}.code-block__line{display:flex}.code-block__line-number{display:inline-block;min-width:2.5rem;padding-right:1rem;text-align:right;color:var(--lc-code-block-muted);-webkit-user-select:none;user-select:none;flex-shrink:0}.code-block__line-content{flex:1;white-space:pre}.code-block__line-content ::ng-deep .token-keyword{color:#c678dd}.code-block__line-content ::ng-deep .token-string{color:#98c379}.code-block__line-content ::ng-deep .token-number{color:#d19a66}.code-block__line-content ::ng-deep .token-comment{color:var(--lc-code-block-muted);font-style:italic}.code-block__line-content ::ng-deep .token-type{color:#e5c07b}.code-block__line-content ::ng-deep .token-constant{color:#d19a66}.code-block__line-content ::ng-deep .token-decorator{color:#61afef}.code-block__line-content ::ng-deep .token-tag{color:#e06c75}.code-block__line-content ::ng-deep .token-attr{color:#d19a66}.code-block__line-content ::ng-deep .token-selector{color:#e06c75}.code-block__line-content ::ng-deep .token-property{color:#61afef}.code-block__line-content ::ng-deep .token-unit{color:#d19a66}.code-block__line-content ::ng-deep .token-variable{color:#e06c75}.code-block__line-content ::ng-deep .token-builtin{color:#61afef}.code-block__line-content ::ng-deep .token-flag{color:#56b6c2}\n"]
|
|
434
445
|
}]
|
|
435
446
|
}],
|
|
436
447
|
propDecorators: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-code-block.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/code-block/code-block.component.ts","../../../../libs/angular-ui-kit/src/lib/code-block/code-block.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n inject,\n input,\n computed,\n signal,\n} from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_CHECK } from '@lifecorner/angular-ui-kit/icons';\n\nexport type CodeBlockLanguage =\n | 'typescript'\n | 'javascript'\n | 'html'\n | 'css'\n | 'scss'\n | 'json'\n | 'bash'\n | 'python'\n | 'java'\n | 'text';\n\ninterface TokenRule {\n pattern: RegExp;\n className: string;\n}\n\nconst SHARED_RULES: TokenRule[] = [\n // Strings (double/single/backtick)\n { pattern: /`(?:[^`\\\\]|\\\\.)*`/g, className: 'token-string' },\n { pattern: /\"(?:[^\"\\\\]|\\\\.)*\"/g, className: 'token-string' },\n { pattern: /'(?:[^'\\\\]|\\\\.)*'/g, className: 'token-string' },\n // Numbers\n { pattern: /\\b\\d+(?:\\.\\d+)?\\b/g, className: 'token-number' },\n];\n\nconst LANGUAGE_RULES: Record<string, TokenRule[]> = {\n typescript: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /@\\w+/g, className: 'token-decorator' },\n { pattern: /\\b(?:import|export|from|const|let|var|function|return|if|else|for|while|class|interface|type|enum|extends|implements|new|this|super|async|await|yield|of|in|as|is|readonly|public|private|protected|static|abstract|override|get|set|constructor|declare|namespace|module|require)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:string|number|boolean|void|null|undefined|never|any|unknown|object|symbol|bigint)\\b/g, className: 'token-type' },\n { pattern: /\\b(?:true|false|null|undefined|NaN|Infinity)\\b/g, className: 'token-constant' },\n { pattern: /(?<=\\b(?:class|interface|type|enum|extends|implements)\\s+)\\w+/g, className: 'token-type' },\n ],\n javascript: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /\\b(?:import|export|from|const|let|var|function|return|if|else|for|while|class|extends|new|this|super|async|await|yield|of|in|typeof|instanceof|delete|throw|try|catch|finally|switch|case|default|break|continue|do)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:true|false|null|undefined|NaN|Infinity)\\b/g, className: 'token-constant' },\n ],\n html: [\n { pattern: /<!--[\\s\\S]*?-->/g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /<\\/?[\\w-]+/g, className: 'token-tag' },\n { pattern: /\\/?>/g, className: 'token-tag' },\n { pattern: /\\b[\\w-]+(?==)/g, className: 'token-attr' },\n ],\n css: [\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /[.#][\\w-]+/g, className: 'token-selector' },\n { pattern: /\\b(?:px|rem|em|%|vh|vw|s|ms|deg|fr)\\b/g, className: 'token-unit' },\n { pattern: /[\\w-]+(?=\\s*:)/g, className: 'token-property' },\n ],\n scss: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /\\$[\\w-]+/g, className: 'token-variable' },\n { pattern: /@(?:use|forward|import|mixin|include|extend|if|else|each|for|while|function|return)\\b/g, className: 'token-keyword' },\n { pattern: /&/g, className: 'token-selector' },\n { pattern: /[.#][\\w-]+/g, className: 'token-selector' },\n ],\n json: [\n ...SHARED_RULES,\n { pattern: /\\b(?:true|false|null)\\b/g, className: 'token-constant' },\n { pattern: /\"(?:[^\"\\\\]|\\\\.)*\"(?=\\s*:)/g, className: 'token-property' },\n ],\n bash: [\n { pattern: /#.*$/gm, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /\\$[\\w{][\\w}]*/g, className: 'token-variable' },\n { pattern: /\\b(?:if|then|else|elif|fi|for|do|done|while|until|case|esac|function|in|select|time|coproc)\\b/g, className: 'token-keyword' },\n { pattern: /(?:^|\\s)(?:npm|npx|yarn|pnpm|git|cd|ls|mkdir|rm|cp|mv|echo|cat|grep|find|sed|awk|curl|wget|docker|node|python|pip|brew|apt|sudo)\\b/g, className: 'token-builtin' },\n { pattern: /--?[\\w-]+/g, className: 'token-flag' },\n ],\n python: [\n { pattern: /#.*$/gm, className: 'token-comment' },\n { pattern: /\"\"\"[\\s\\S]*?\"\"\"/g, className: 'token-string' },\n { pattern: /'''[\\s\\S]*?'''/g, className: 'token-string' },\n ...SHARED_RULES,\n { pattern: /@\\w+/g, className: 'token-decorator' },\n { pattern: /\\b(?:def|class|import|from|as|return|if|elif|else|for|while|break|continue|pass|raise|try|except|finally|with|yield|lambda|assert|del|global|nonlocal|async|await|in|not|and|or|is)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:True|False|None)\\b/g, className: 'token-constant' },\n { pattern: /\\b(?:str|int|float|bool|list|dict|tuple|set|bytes|type|object|Exception|ValueError|TypeError|KeyError|IndexError|AttributeError|RuntimeError|StopIteration)\\b/g, className: 'token-type' },\n { pattern: /\\b(?:print|len|range|enumerate|zip|map|filter|sorted|reversed|isinstance|issubclass|hasattr|getattr|setattr|super|property|staticmethod|classmethod|open|input)\\b/g, className: 'token-builtin' },\n { pattern: /\\bself\\b/g, className: 'token-variable' },\n ],\n java: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /@\\w+/g, className: 'token-decorator' },\n { pattern: /\\b(?:abstract|assert|break|case|catch|class|continue|default|do|else|enum|extends|final|finally|for|if|implements|import|instanceof|interface|native|new|package|private|protected|public|return|static|strictfp|super|switch|synchronized|this|throw|throws|transient|try|volatile|while|var|record|sealed|permits|yield)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:true|false|null)\\b/g, className: 'token-constant' },\n { pattern: /\\b(?:void|int|long|short|byte|float|double|char|boolean|String|Integer|Long|Double|Float|Boolean|Character|Object|Class|List|Map|Set|ArrayList|HashMap|HashSet|Optional|Stream|Collectors)\\b/g, className: 'token-type' },\n { pattern: /\\b(?:System|Math|Arrays|Collections|Objects|Thread|Runnable)\\b/g, className: 'token-builtin' },\n ],\n};\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\nfunction highlightCode(code: string, language: string): string {\n const escaped = escapeHtml(code);\n const rules = LANGUAGE_RULES[language];\n if (!rules) return escaped;\n\n // Collect all matches with positions\n const tokens: { start: number; end: number; className: string; text: string }[] = [];\n\n for (const rule of rules) {\n const regex = new RegExp(rule.pattern.source, rule.pattern.flags);\n let match: RegExpExecArray | null;\n while ((match = regex.exec(escaped)) !== null) {\n tokens.push({\n start: match.index,\n end: match.index + match[0].length,\n className: rule.className,\n text: match[0],\n });\n }\n }\n\n // Sort by start position, longer matches first for same position\n tokens.sort((a, b) => a.start - b.start || b.end - a.end);\n\n // Remove overlapping tokens (keep first/longest)\n const filtered: typeof tokens = [];\n let lastEnd = 0;\n for (const token of tokens) {\n if (token.start >= lastEnd) {\n filtered.push(token);\n lastEnd = token.end;\n }\n }\n\n // Build highlighted string\n let result = '';\n let cursor = 0;\n for (const token of filtered) {\n if (token.start > cursor) {\n result += escaped.slice(cursor, token.start);\n }\n result += `<span class=\"${token.className}\">${token.text}</span>`;\n cursor = token.end;\n }\n result += escaped.slice(cursor);\n\n return result;\n}\n\n@Component({\n selector: 'lc-code-block',\n standalone: true,\n imports: [IconComponent],\n viewProviders: [ɵprovideKitIcons([ICON_CHECK])],\n templateUrl: './code-block.component.html',\n styleUrls: ['./code-block.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Code block component for displaying syntax-highlighted source code.\n *\n * Features:\n * - Syntax highlighting for 10+ languages (TypeScript, Python, Java, etc.)\n * - Optional line numbers\n * - Copy-to-clipboard button\n * - Optional header with filename and language label\n * - Dark-mode compatible color scheme\n *\n * @example\n * ```html\n * <lc-code-block [code]=\"source\" language=\"typescript\" [showLineNumbers]=\"true\" />\n * ```\n */\nexport class CodeBlockComponent {\n /** Code content to display */\n code = input.required<string>();\n\n /** Language label */\n language = input<CodeBlockLanguage>('text');\n\n /** Optional filename to display */\n filename = input<string>();\n\n /** Whether to show line numbers */\n showLineNumbers = input<boolean>(true);\n\n /** Whether to show copy button */\n showCopy = input<boolean>(true);\n\n /** Whether the code block has a header bar */\n showHeader = input<boolean>(true);\n\n /** Visible label of the copy button. */\n copyLabel = input('Copy');\n\n /** Accessible name of the copy button. */\n copyAriaLabel = input('Copy code');\n\n /** Label of the copy button after copying (also its accessible name). */\n copiedLabel = input('Copied');\n\n /** Announced to screen readers after copying. */\n copiedAnnouncement = input('Copied to clipboard');\n\n protected copied = signal(false);\n\n private readonly sanitizer = inject(DomSanitizer);\n\n protected highlightedLines = computed<SafeHtml[]>(() => {\n const highlighted = highlightCode(this.code(), this.language());\n return highlighted.split('\\n').map(line =>\n this.sanitizer.bypassSecurityTrustHtml(line || ' ')\n );\n });\n\n protected lineNumbers = computed(() => {\n return this.code().split('\\n').map((_, i) => i + 1);\n });\n\n protected headerLabel = computed(() => {\n return this.filename() || this.language();\n });\n\n protected codeClasses = computed(() => {\n return ['code-block', `code-block--${this.language()}`].join(' ');\n });\n\n protected async copyToClipboard(): Promise<void> {\n try {\n await navigator.clipboard.writeText(this.code());\n this.copied.set(true);\n setTimeout(() => this.copied.set(false), 2000);\n } catch {\n // Fallback: just ignore if clipboard API not available\n }\n }\n}\n","<div [class]=\"codeClasses()\">\n @if (showHeader()) {\n <div class=\"code-block__header\">\n <span class=\"code-block__language\">{{ headerLabel() }}</span>\n @if (showCopy()) {\n <button\n type=\"button\"\n class=\"code-block__copy\"\n [attr.aria-label]=\"copied() ? copiedLabel() : copyAriaLabel()\"\n (click)=\"copyToClipboard()\"\n >\n @if (copied()) {\n <lc-icon name=\"check\" size=\"sm\" />\n <span>{{ copiedLabel() }}</span>\n } @else {\n <lc-icon name=\"clipboard-document\" size=\"sm\" />\n <span>{{ copyLabel() }}</span>\n }\n </button>\n <span class=\"code-block__live\" role=\"status\" aria-live=\"polite\">{{ copied() ? copiedAnnouncement() : '' }}</span>\n }\n </div>\n }\n <div class=\"code-block__body\">\n <pre class=\"code-block__pre\"><code class=\"code-block__code\">@for (line of highlightedLines(); track $index; let i = $index) {<span class=\"code-block__line\">@if (showLineNumbers()) {<span class=\"code-block__line-number\">{{ lineNumbers()[i] }}</span>}<span class=\"code-block__line-content\" [innerHTML]=\"line\"></span></span>\n}</code></pre>\n </div>\n</div>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-code-block.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/code-block/code-block.component.ts","../../../../libs/angular-ui-kit/src/lib/code-block/code-block.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n input,\n computed,\n signal,\n} from '@angular/core';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_CHECK } from '@lifecorner/angular-ui-kit/icons';\n\nexport type CodeBlockLanguage =\n | 'typescript'\n | 'javascript'\n | 'html'\n | 'css'\n | 'scss'\n | 'json'\n | 'bash'\n | 'python'\n | 'java'\n | 'text';\n\ninterface TokenRule {\n pattern: RegExp;\n className: string;\n}\n\nconst SHARED_RULES: TokenRule[] = [\n // Strings (double/single/backtick)\n { pattern: /`(?:[^`\\\\]|\\\\.)*`/g, className: 'token-string' },\n { pattern: /\"(?:[^\"\\\\]|\\\\.)*\"/g, className: 'token-string' },\n { pattern: /'(?:[^'\\\\]|\\\\.)*'/g, className: 'token-string' },\n // Numbers\n { pattern: /\\b\\d+(?:\\.\\d+)?\\b/g, className: 'token-number' },\n];\n\nconst LANGUAGE_RULES: Record<string, TokenRule[]> = {\n typescript: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /@\\w+/g, className: 'token-decorator' },\n { pattern: /\\b(?:import|export|from|const|let|var|function|return|if|else|for|while|class|interface|type|enum|extends|implements|new|this|super|async|await|yield|of|in|as|is|readonly|public|private|protected|static|abstract|override|get|set|constructor|declare|namespace|module|require)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:string|number|boolean|void|null|undefined|never|any|unknown|object|symbol|bigint)\\b/g, className: 'token-type' },\n { pattern: /\\b(?:true|false|null|undefined|NaN|Infinity)\\b/g, className: 'token-constant' },\n { pattern: /(?<=\\b(?:class|interface|type|enum|extends|implements)\\s+)\\w+/g, className: 'token-type' },\n ],\n javascript: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /\\b(?:import|export|from|const|let|var|function|return|if|else|for|while|class|extends|new|this|super|async|await|yield|of|in|typeof|instanceof|delete|throw|try|catch|finally|switch|case|default|break|continue|do)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:true|false|null|undefined|NaN|Infinity)\\b/g, className: 'token-constant' },\n ],\n // The tokenizer reads the raw source (3.6.1): `<` and `>` instead of the\n // `<`/`>` the escaped text had. Up to 3.6.0 an html comment rule ran on\n // that escaped text and never matched; it is gone, so comments stay plain.\n html: [\n ...SHARED_RULES,\n { pattern: /<\\/?[\\w-]+/g, className: 'token-tag' },\n { pattern: /\\/?>/g, className: 'token-tag' },\n { pattern: /\\b[\\w-]+(?==)/g, className: 'token-attr' },\n ],\n css: [\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /[.#][\\w-]+/g, className: 'token-selector' },\n { pattern: /\\b(?:px|rem|em|%|vh|vw|s|ms|deg|fr)\\b/g, className: 'token-unit' },\n { pattern: /[\\w-]+(?=\\s*:)/g, className: 'token-property' },\n ],\n scss: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /\\$[\\w-]+/g, className: 'token-variable' },\n { pattern: /@(?:use|forward|import|mixin|include|extend|if|else|each|for|while|function|return)\\b/g, className: 'token-keyword' },\n { pattern: /&/g, className: 'token-selector' },\n { pattern: /[.#][\\w-]+/g, className: 'token-selector' },\n ],\n json: [\n ...SHARED_RULES,\n { pattern: /\\b(?:true|false|null)\\b/g, className: 'token-constant' },\n { pattern: /\"(?:[^\"\\\\]|\\\\.)*\"(?=\\s*:)/g, className: 'token-property' },\n ],\n bash: [\n { pattern: /#.*$/gm, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /\\$[\\w{][\\w}]*/g, className: 'token-variable' },\n { pattern: /\\b(?:if|then|else|elif|fi|for|do|done|while|until|case|esac|function|in|select|time|coproc)\\b/g, className: 'token-keyword' },\n { pattern: /(?:^|\\s)(?:npm|npx|yarn|pnpm|git|cd|ls|mkdir|rm|cp|mv|echo|cat|grep|find|sed|awk|curl|wget|docker|node|python|pip|brew|apt|sudo)\\b/g, className: 'token-builtin' },\n { pattern: /--?[\\w-]+/g, className: 'token-flag' },\n ],\n python: [\n { pattern: /#.*$/gm, className: 'token-comment' },\n { pattern: /\"\"\"[\\s\\S]*?\"\"\"/g, className: 'token-string' },\n { pattern: /'''[\\s\\S]*?'''/g, className: 'token-string' },\n ...SHARED_RULES,\n { pattern: /@\\w+/g, className: 'token-decorator' },\n { pattern: /\\b(?:def|class|import|from|as|return|if|elif|else|for|while|break|continue|pass|raise|try|except|finally|with|yield|lambda|assert|del|global|nonlocal|async|await|in|not|and|or|is)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:True|False|None)\\b/g, className: 'token-constant' },\n { pattern: /\\b(?:str|int|float|bool|list|dict|tuple|set|bytes|type|object|Exception|ValueError|TypeError|KeyError|IndexError|AttributeError|RuntimeError|StopIteration)\\b/g, className: 'token-type' },\n { pattern: /\\b(?:print|len|range|enumerate|zip|map|filter|sorted|reversed|isinstance|issubclass|hasattr|getattr|setattr|super|property|staticmethod|classmethod|open|input)\\b/g, className: 'token-builtin' },\n { pattern: /\\bself\\b/g, className: 'token-variable' },\n ],\n java: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /@\\w+/g, className: 'token-decorator' },\n { pattern: /\\b(?:abstract|assert|break|case|catch|class|continue|default|do|else|enum|extends|final|finally|for|if|implements|import|instanceof|interface|native|new|package|private|protected|public|return|static|strictfp|super|switch|synchronized|this|throw|throws|transient|try|volatile|while|var|record|sealed|permits|yield)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:true|false|null)\\b/g, className: 'token-constant' },\n { pattern: /\\b(?:void|int|long|short|byte|float|double|char|boolean|String|Integer|Long|Double|Float|Boolean|Character|Object|Class|List|Map|Set|ArrayList|HashMap|HashSet|Optional|Stream|Collectors)\\b/g, className: 'token-type' },\n { pattern: /\\b(?:System|Math|Arrays|Collections|Objects|Thread|Runnable)\\b/g, className: 'token-builtin' },\n ],\n};\n\n/** A run of source text; `className` is one `token-*` class, or `null` for plain text. */\ninterface CodeSegment {\n readonly text: string;\n readonly className: string | null;\n}\n\n/** One rendered line: its segments in order. */\ntype CodeLine = readonly CodeSegment[];\n\n/**\n * What an empty line renders: U+00A0, the glyph the ` ` of 3.6.0\n * produced, so the line keeps its height and a selection its text.\n */\nconst EMPTY_LINE: CodeLine = [{ text: String.fromCharCode(0xa0), className: null }];\n\n/** Matches of the language's rules on the raw source, sorted, without overlaps. */\nfunction tokenize(code: string, language: string): { start: number; end: number; className: string }[] {\n const rules = LANGUAGE_RULES[language];\n if (!rules) return [];\n\n // Collect all matches with positions\n const tokens: { start: number; end: number; className: string }[] = [];\n\n for (const rule of rules) {\n const regex = new RegExp(rule.pattern.source, rule.pattern.flags);\n let match: RegExpExecArray | null;\n while ((match = regex.exec(code)) !== null) {\n tokens.push({\n start: match.index,\n end: match.index + match[0].length,\n className: rule.className,\n });\n }\n }\n\n // Sort by start position, longer matches first for same position\n tokens.sort((a, b) => a.start - b.start || b.end - a.end);\n\n // Remove overlapping tokens (keep first/longest)\n const filtered: typeof tokens = [];\n let lastEnd = 0;\n for (const token of tokens) {\n if (token.start >= lastEnd) {\n filtered.push(token);\n lastEnd = token.end;\n }\n }\n return filtered;\n}\n\n/**\n * The highlighted source as lines of text segments, rendered by the template\n * as text nodes and `<span class=\"token-…\">` elements: no markup string, so\n * nothing for Trusted Types to block and nothing in the source is parsed.\n *\n * A token that runs across a line break keeps its class on the part before\n * the first break only; the later parts are plain, as the HTML parser closed\n * the open span at each line end up to 3.6.0.\n */\nfunction highlightLines(code: string, language: string): CodeLine[] {\n const lines: CodeSegment[][] = [[]];\n const append = (text: string, className: string | null) => {\n text.split('\\n').forEach((part, i) => {\n if (i > 0) lines.push([]);\n if (!part) return;\n const line = lines[lines.length - 1];\n const cls = i === 0 ? className : null;\n const last = line[line.length - 1];\n if (cls === null && last?.className === null) {\n line[line.length - 1] = { text: last.text + part, className: null };\n } else {\n line.push({ text: part, className: cls });\n }\n });\n };\n\n let cursor = 0;\n for (const token of tokenize(code, language)) {\n append(code.slice(cursor, token.start), null);\n append(code.slice(token.start, token.end), token.className);\n cursor = token.end;\n }\n append(code.slice(cursor), null);\n\n return lines.map(line => (line.length ? line : EMPTY_LINE));\n}\n\n@Component({\n selector: 'lc-code-block',\n standalone: true,\n imports: [IconComponent],\n viewProviders: [ɵprovideKitIcons([ICON_CHECK])],\n templateUrl: './code-block.component.html',\n styleUrls: ['./code-block.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Code block component for displaying syntax-highlighted source code.\n *\n * Features:\n * - Syntax highlighting for 10+ languages (TypeScript, Python, Java, etc.)\n * - Optional line numbers\n * - Copy-to-clipboard button\n * - Optional header with filename and language label\n * - Dark-mode compatible color scheme\n *\n * @example\n * ```html\n * <lc-code-block [code]=\"source\" language=\"typescript\" [showLineNumbers]=\"true\" />\n * ```\n */\nexport class CodeBlockComponent {\n /** Code content to display */\n code = input.required<string>();\n\n /** Language label */\n language = input<CodeBlockLanguage>('text');\n\n /** Optional filename to display */\n filename = input<string>();\n\n /** Whether to show line numbers */\n showLineNumbers = input<boolean>(true);\n\n /** Whether to show copy button */\n showCopy = input<boolean>(true);\n\n /** Whether the code block has a header bar */\n showHeader = input<boolean>(true);\n\n /** Visible label of the copy button. */\n copyLabel = input('Copy');\n\n /** Accessible name of the copy button. */\n copyAriaLabel = input('Copy code');\n\n /** Label of the copy button after copying (also its accessible name). */\n copiedLabel = input('Copied');\n\n /** Announced to screen readers after copying. */\n copiedAnnouncement = input('Copied to clipboard');\n\n protected copied = signal(false);\n\n protected highlightedLines = computed<CodeLine[]>(() =>\n highlightLines(this.code(), this.language())\n );\n\n protected lineNumbers = computed(() => {\n return this.code().split('\\n').map((_, i) => i + 1);\n });\n\n protected headerLabel = computed(() => {\n return this.filename() || this.language();\n });\n\n protected codeClasses = computed(() => {\n return ['code-block', `code-block--${this.language()}`].join(' ');\n });\n\n protected async copyToClipboard(): Promise<void> {\n try {\n await navigator.clipboard.writeText(this.code());\n this.copied.set(true);\n setTimeout(() => this.copied.set(false), 2000);\n } catch {\n // Fallback: just ignore if clipboard API not available\n }\n }\n}\n","<div [class]=\"codeClasses()\">\n @if (showHeader()) {\n <div class=\"code-block__header\">\n <span class=\"code-block__language\">{{ headerLabel() }}</span>\n @if (showCopy()) {\n <button\n type=\"button\"\n class=\"code-block__copy\"\n [attr.aria-label]=\"copied() ? copiedLabel() : copyAriaLabel()\"\n (click)=\"copyToClipboard()\"\n >\n @if (copied()) {\n <lc-icon name=\"check\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ copiedLabel() }}</span>\n } @else {\n <lc-icon name=\"clipboard-document\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ copyLabel() }}</span>\n }\n </button>\n <span class=\"code-block__live\" role=\"status\" aria-live=\"polite\">{{ copied() ? copiedAnnouncement() : '' }}</span>\n }\n </div>\n }\n <div class=\"code-block__body\">\n <pre class=\"code-block__pre\"><code class=\"code-block__code\">@for (line of highlightedLines(); track $index; let i = $index) {<span class=\"code-block__line\">@if (showLineNumbers()) {<span class=\"code-block__line-number\">{{ lineNumbers()[i] }}</span>}<span class=\"code-block__line-content\">@for (segment of line; track $index) {@if (segment.className) {<span [attr.class]=\"segment.className\">{{ segment.text }}</span>}@else{{{ segment.text }}}}</span></span>\n}</code></pre>\n </div>\n</div>\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { SafeHtml } from "@angular/platform-browser";
|
|
2
1
|
import * as i0 from "@angular/core";
|
|
3
2
|
export type CodeBlockLanguage = 'typescript' | 'javascript' | 'html' | 'css' | 'scss' | 'json' | 'bash' | 'python' | 'java' | 'text';
|
|
3
|
+
/** A run of source text; `className` is one `token-*` class, or `null` for plain text. */
|
|
4
|
+
interface CodeSegment {
|
|
5
|
+
readonly text: string;
|
|
6
|
+
readonly className: string | null;
|
|
7
|
+
}
|
|
8
|
+
/** One rendered line: its segments in order. */
|
|
9
|
+
type CodeLine = readonly CodeSegment[];
|
|
4
10
|
export declare class CodeBlockComponent {
|
|
5
11
|
/** Code content to display */
|
|
6
12
|
code: import("@angular/core").InputSignal<string>;
|
|
@@ -23,8 +29,7 @@ export declare class CodeBlockComponent {
|
|
|
23
29
|
/** Announced to screen readers after copying. */
|
|
24
30
|
copiedAnnouncement: import("@angular/core").InputSignal<string>;
|
|
25
31
|
protected copied: import("@angular/core").WritableSignal<boolean>;
|
|
26
|
-
|
|
27
|
-
protected highlightedLines: import("@angular/core").Signal<SafeHtml[]>;
|
|
32
|
+
protected highlightedLines: import("@angular/core").Signal<CodeLine[]>;
|
|
28
33
|
protected lineNumbers: import("@angular/core").Signal<number[]>;
|
|
29
34
|
protected headerLabel: import("@angular/core").Signal<string>;
|
|
30
35
|
protected codeClasses: import("@angular/core").Signal<string>;
|
|
@@ -82,4 +87,5 @@ export declare class CodeBlockComponent {
|
|
|
82
87
|
"isSignal": true;
|
|
83
88
|
};
|
|
84
89
|
}, {}, never, never, true, never>;
|
|
85
|
-
}
|
|
90
|
+
}
|
|
91
|
+
export {};
|