# Code block

- Entry point: `@koobiq/components/code-block`
- NgModule: `KbqCodeBlockModule`
- Page: https://koobiq.io/en/components/code-block/overview

## Overview

`<kbq-code-block>` is a component that displays reformatted text content with syntax highlighting.

Note

For the component to work, the [`highlight.js@^11`](https://github.com/highlightjs/highlight.js/tree/11.10.0) dependency is required:

```bash
npm install highlight.js@^11
```

### Configuring highlight.js

By default, the component loads the `highlight.js` core, which has no languages, and shows the code as plain text. Register the languages of your files with `kbqCodeBlockHighlightJsConfigProvider`:

```typescript
providers: [
    kbqCodeBlockHighlightJsConfigProvider({
        languages: {
            typescript: () => import('highlight.js/lib/languages/typescript'),
            css: () => import('highlight.js/lib/languages/css'),
            html: () => import('highlight.js/lib/languages/xml')
        }
    })
];
```

Languages are loaded lazily on first use. Plain text needs no entry: the component falls back to it for a file whose language is not specified or not registered. Note that the `html` language is an alias of `xml` in `highlight.js`, so register `xml` to enable HTML syntax highlighting.

To highlight any language, load the full bundle with all of them (\~1 MB):

```typescript
providers: [
    kbqCodeBlockHighlightJsConfigProvider({
        core: () => import('highlight.js')
    })
];
```

### Line numbers

Numbering lines is useful for referencing a specific location in the document. Line numbers are disabled by default and can be enabled using the `lineNumbers` attribute.

**Example: Code-block with lineNumbers attribute** (`code-block-overview`)

```ts code-block-overview-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import {
    KbqCodeBlockFile,
    kbqCodeBlockHighlightJsConfigProvider,
    KbqCodeBlockModule
} from '@koobiq/components/code-block';
import { KbqToggleModule } from '@koobiq/components/toggle';

@Component({
    selector: 'code-block-overview-example',
    imports: [
        KbqCodeBlockModule,
        KbqToggleModule,
        FormsModule
    ],
    template: `
        <kbq-toggle class="layout-margin-bottom-m" [(ngModel)]="lineNumbers">Line numbers</kbq-toggle>
        <kbq-code-block canToggleSoftWrap [files]="files" [lineNumbers]="lineNumbers" />
    `,
    providers: [
        kbqCodeBlockHighlightJsConfigProvider({
            languages: {
                javascript: () => import('highlight.js/lib/languages/javascript')
            }
        })
    ],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class CodeBlockOverviewExample {
    readonly files: KbqCodeBlockFile[] = [
        {
            content: `function getVulnerabilities() {\n\treturn ['BruteForce', 'Complex Attack', 'DDoS', 'HIPS alert', 'IDS/IPS Alert', 'Zero-Day Exploit', 'XSS', 'Malware', 'Ransomware', 'Phishing'];\n};`,
            language: 'javascript'
        }
    ];

    lineNumbers: boolean = true;
}
```

### Header with title

In the header, you can specify the document name or define the syntax. A shadow appears in the header when scrolling.

**Example: Code block header pinned** (`code-block-header-pinned`)

```ts code-block-header-pinned-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import {
    KbqCodeBlockFile,
    kbqCodeBlockHighlightJsConfigProvider,
    KbqCodeBlockModule
} from '@koobiq/components/code-block';
import { KbqIcon } from '@koobiq/components/icon';
import { KbqToggleModule } from '@koobiq/components/toggle';

@Component({
    selector: 'code-block-header-pinned-example',
    imports: [
        KbqCodeBlockModule,
        KbqToggleModule,
        KbqIcon,
        FormsModule
    ],
    template: `
        <kbq-code-block
            canToggleSoftWrap
            lineNumbers
            filled
            [canDownload]="true"
            [files]="files"
            [softWrap]="true"
            [hideTabs]="false"
        >
            <ng-template let-file let-fallback="fallbackFileName" kbqCodeBlockTabLinkContent>data</ng-template>
        </kbq-code-block>

        <kbq-code-block
            canToggleSoftWrap
            lineNumbers
            [canDownload]="true"
            [softWrap]="true"
            [files]="files"
            [hideTabs]="false"
        >
            <ng-template let-file let-fallback="fallbackFileName" kbqCodeBlockTabLinkContent>
                <i kbq-icon="kbq-diamond_16" class="layout-margin-right-xs"></i>
                <span class="kbq-caps-normal-strong">
                    {{ file.language || fallback }}
                </span>
            </ng-template>
        </kbq-code-block>
    `,
    styles: `
        .kbq-code-block {
            height: 350px;
            &:first-of-type {
                margin-bottom: var(--kbq-size-xs);
            }
        }
    `,
    providers: [
        kbqCodeBlockHighlightJsConfigProvider({
            languages: {
                json: () => import('highlight.js/lib/languages/json')
            }
        })
    ],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class CodeBlockHeaderPinnedExample {
    readonly files: KbqCodeBlockFile[] = [
        {
            language: 'json',
            content: `{
  "data": [{
    "id": "1",
    "attributes": {
      "title": "JSON:API paints my hyper-super-duper mighty bikeshed!",
      "body": "The shortest article. Ever."
    },
    "relationships": {
      "author": {
        "data": {"id": "42", "type": "people"}
      }
    }
  }],
  "included": [
    {
      "type": "people",
      "id": "42",
      "attributes": {
        "name": "John"
      }
    }
  ]
}`
        }
    ];
}
```

### Changing the block height

The block can expand to fill the available screen area if reviewing the code is one of the main tasks in the interface. When screen space is limited or the code only supplements the main content, a developer can use a block with a fixed height, configured using the `maxHeight` attribute.

For compactness, it can be useful to show a portion of the document with the option to expand everything, using the `viewAll` attribute. The block will increase in height and all the code will be visible, avoiding double scrolling. In the collapsed state, there is no scrolling and the line wrap toggle is unavailable. If you change the wrap mode and then collapse and expand the code, the setting is preserved.

**Example: Code-block with maxHeight attribute** (`code-block-with-max-height`)

```ts code-block-with-max-height-example.ts
import { ChangeDetectionStrategy, Component, model } from '@angular/core';
import { FormsModule } from '@angular/forms';
import {
    KbqCodeBlockFile,
    kbqCodeBlockHighlightJsConfigProvider,
    KbqCodeBlockModule
} from '@koobiq/components/code-block';
import { KbqToggleModule } from '@koobiq/components/toggle';

@Component({
    selector: 'code-block-with-max-height-example',
    imports: [
        KbqCodeBlockModule,
        KbqToggleModule,
        FormsModule
    ],
    template: `
        <kbq-toggle class="layout-margin-bottom-m layout-margin-right-m" [(ngModel)]="viewAll">Show all</kbq-toggle>
        <kbq-toggle [(ngModel)]="filled">Filled</kbq-toggle>

        <kbq-code-block
            canToggleSoftWrap
            maxHeight="200"
            lineNumbers
            [filled]="filled()"
            [files]="files"
            [(viewAll)]="viewAll"
        />
    `,
    providers: [
        kbqCodeBlockHighlightJsConfigProvider({
            languages: {
                xml: () => import('highlight.js/lib/languages/xml')
            }
        })
    ],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class CodeBlockWithMaxHeightExample {
    readonly files: KbqCodeBlockFile[] = [
        {
            content: `<?xml version="1.0" encoding="UTF-8" ?>\n<vulnerabilities>\n\t<vulnerability>\n\t\t<name>Cross-site scripting</name>\n\t\t<abbreviation>XSS</abbreviation>\n\t\t<description>Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 "traditional" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network.</description>\n\t</vulnerability>\n\t<vulnerability>\n\t\t<name>Denial-of-service attack</name>\n\t\t<abbreviation>DoS</abbreviation>\n\t\t<description>In computing, a denial-of-service attack (DoS attack) is a cyber-attack in which the perpetrator seeks to make a machine or network resource unavailable to its intended users by temporarily or indefinitely disrupting services of a host connected to a network. Denial of service is typically accomplished by flooding the targeted machine or resource with superfluous requests in an attempt to overload systems and prevent some or all legitimate requests from being fulfilled. The range of attacks varies widely, spanning from inundating a server with millions of requests to slow its performance, overwhelming a server with a substantial amount of invalid data, to submitting requests with an illegitimate IP address.</description>\n\t</vulnerability>\n<vulnerabilities>`,
            language: 'xml'
        }
    ];

    readonly viewAll = model(false);
    readonly filled = model(false);
}
```

### Soft line wrap

By default, lines do not wrap. The wrap mode can be configured in advance using the `softWrap` attribute, and the user can also be given the ability to control this with a toggle button in the action panel, enabled using the `canToggleSoftWrap` attribute.

The icon in the button represents the future state after activation; the icon changes after the wrap mode is toggled.

**Example: Code-block with \[softWrap]="true" attribute** (`code-block-with-soft-wrap`)

```ts code-block-with-soft-wrap-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import {
    KbqCodeBlockFile,
    kbqCodeBlockHighlightJsConfigProvider,
    KbqCodeBlockModule
} from '@koobiq/components/code-block';
import { KbqToggleModule } from '@koobiq/components/toggle';

@Component({
    selector: 'code-block-with-soft-wrap-example',
    imports: [
        KbqCodeBlockModule,
        KbqToggleModule,
        FormsModule
    ],
    template: `
        <kbq-toggle class="layout-margin-bottom-m" [(ngModel)]="softWrap">Word wrap</kbq-toggle>
        <kbq-code-block canToggleSoftWrap lineNumbers [files]="files" [(softWrap)]="softWrap" />
    `,
    providers: [
        kbqCodeBlockHighlightJsConfigProvider({
            languages: {
                json: () => import('highlight.js/lib/languages/json')
            }
        })
    ],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class CodeBlockWithSoftWrapExample {
    readonly files: KbqCodeBlockFile[] = [
        {
            content: `[\n\t{\n\t\t"name": "Cross-site scripting",\n\t\t"abbreviation": "XSS",\n\t\t"description": "Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 \"traditional\" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network."\n\t}\n]`,
            language: 'json'
        }
    ];

    softWrap: boolean = false;
}
```

### Displaying multiple documents

Multiple documents are placed in the block within tabs. The tab title is formed from the `filename` field. If needed, tabs can be hidden using the `hideTabs` attribute, and the active tab can be set using the `activeFileIndex` attribute.

Tabs are hidden automatically for a single document with an empty `filename`.

**Example: Code-block with tabs** (`code-block-with-tabs`)

```ts code-block-with-tabs-example.ts
import { ChangeDetectionStrategy, Component, model } from '@angular/core';
import { FormsModule } from '@angular/forms';
import {
    KbqCodeBlockFile,
    kbqCodeBlockHighlightJsConfigProvider,
    KbqCodeBlockModule
} from '@koobiq/components/code-block';
import { KbqToggleModule } from '@koobiq/components/toggle';

@Component({
    selector: 'code-block-with-tabs-example',
    imports: [
        KbqCodeBlockModule,
        KbqToggleModule,
        FormsModule
    ],
    template: `
        <kbq-toggle class="layout-margin-right-m layout-margin-bottom-m" [(ngModel)]="hideTabs">Hide tabs</kbq-toggle>
        <kbq-toggle class="layout-margin-right-m" [(ngModel)]="filled">Filled</kbq-toggle>
        <kbq-toggle [(ngModel)]="lineNumbers">Line numbers</kbq-toggle>

        <kbq-code-block
            canToggleSoftWrap
            [activeFileIndex]="1"
            [canDownload]="true"
            [files]="files"
            [hideTabs]="hideTabs()"
            [filled]="filled()"
            [lineNumbers]="lineNumbers()"
        />
    `,
    providers: [
        kbqCodeBlockHighlightJsConfigProvider({
            languages: {
                html: () => import('highlight.js/lib/languages/xml'),
                typescript: () => import('highlight.js/lib/languages/typescript'),
                css: () => import('highlight.js/lib/languages/css')
            }
        })
    ],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class CodeBlockWithTabsExample {
    readonly files: KbqCodeBlockFile[] = [
        {
            language: 'html',
            filename: 'index.html',
            content: `<!DOCTYPE html>\n<html lang="en">\n\t<head>\n\t\t<title>Koobiq</title>\n\t\t<meta charset="UTF-8" />\n\t\t<base href="/">\n\t\t<link href="https://fonts.googleapis.com" rel="preconnect" />\n\t\t<link crossorigin href="https://fonts.gstatic.com" rel="preconnect" />\n\t\t<link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" rel="stylesheet" />\n\t</head>\n\t<body>\n\t\t<app-root>Loading...</app-root>\n\t</body>\n</html>`
        },
        {
            language: 'typescript',
            filename: 'main.ts',
            content: `import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { bootstrapApplication } from '@angular/platform-browser';\nimport { KbqLink } from '@koobiq/components/link';\n\n@Component({\n\timports: [KbqLink],\n\tselector: 'app-root',\n\ttemplate: \`<a kbqLink target="_blank" href="https://koobiq.io/">Koobiq</a>\`,\n\tchangeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class App {}\n\nbootstrapApplication(App).catch((error) => console.error(error));`
        },
        {
            language: 'css',
            filename: 'main.css',
            content: `body {\n\tmargin: 0;\n\tfont-family: var(--kbq-typography-text-normal-font-family);\n\tfont-size: var(--kbq-typography-text-normal-font-size);\n\tfont-weight: var(--kbq-typography-text-normal-font-weight);\n\tline-height: var(--kbq-typography-text-normal-line-height);\n\ttext-transform: var(--kbq-typography-text-normal-text-transform);\n\tfont-feature-settings: var(--kbq-typography-text-normal-font-feature-settings);\n\tletter-spacing: var(--kbq-typography-text-normal-letter-spacing);\n\tbackground: var(--kbq-background-bg);\n\tcolor: var(--kbq-foreground-contrast);\n}\n\na {\n\tcolor: var(--kbq-link-text);\n\ttext-decoration: none;\n}`
        }
    ];

    readonly hideTabs = model(false);
    readonly filled = model(false);
    readonly lineNumbers = model(true);
}
```

The tab header block is displayed without a shadow by default. If content extends beyond the area, a shadow appears under the tab header block when the code block content is scrolled.

**Example: Code-block with tabs and shadow** (`code-block-with-tabs-and-shadow`)

```ts code-block-with-tabs-and-shadow-example.ts
import { AfterViewInit, ChangeDetectionStrategy, Component, viewChild } from '@angular/core';
import {
    KbqCodeBlock,
    KbqCodeBlockFile,
    kbqCodeBlockHighlightJsConfigProvider,
    KbqCodeBlockModule
} from '@koobiq/components/code-block';

@Component({
    selector: 'code-block-with-tabs-and-shadow-example',
    imports: [KbqCodeBlockModule],
    template: `
        <kbq-code-block
            lineNumbers
            canToggleSoftWrap
            [activeFileIndex]="2"
            [softWrap]="true"
            [files]="files"
            [style.height.px]="350"
        />
    `,
    providers: [
        kbqCodeBlockHighlightJsConfigProvider({
            languages: {
                html: () => import('highlight.js/lib/languages/xml'),
                typescript: () => import('highlight.js/lib/languages/typescript'),
                css: () => import('highlight.js/lib/languages/css')
            }
        })
    ],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class CodeBlockWithTabsAndShadowExample implements AfterViewInit {
    readonly codeBlock = viewChild.required(KbqCodeBlock);

    readonly files: KbqCodeBlockFile[] = [
        {
            language: 'html',
            filename: 'index.html',
            content: `<!DOCTYPE html>\n<html lang="en">\n\t<head>\n\t\t<title>Koobiq</title>\n\t\t<meta charset="UTF-8" />\n\t\t<base href="/">\n\t\t<link href="https://fonts.googleapis.com" rel="preconnect" />\n\t\t<link crossorigin href="https://fonts.gstatic.com" rel="preconnect" />\n\t\t<link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" rel="stylesheet" />\n\t</head>\n\t<body>\n\t\t<app-root>Loading...</app-root>\n\t</body>\n</html>`
        },
        {
            language: 'typescript',
            filename: 'main.ts',
            content: `import { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { bootstrapApplication } from '@angular/platform-browser';\nimport { KbqLink } from '@koobiq/components/link';\n\n@Component({\n\timports: [KbqLink],\n\tselector: 'app-root',\n\ttemplate: \`<a kbqLink target="_blank" href="https://koobiq.io/">Koobiq</a>\`,\n\tchangeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class App {}\n\nbootstrapApplication(App).catch((error) => console.error(error));`
        },
        {
            language: 'css',
            filename: 'main.css',
            content: `body {\n\tmargin: 0;\n\tfont-family: var(--kbq-typography-text-normal-font-family);\n\tfont-size: var(--kbq-typography-text-normal-font-size);\n\tfont-weight: var(--kbq-typography-text-normal-font-weight);\n\tline-height: var(--kbq-typography-text-normal-line-height);\n\ttext-transform: var(--kbq-typography-text-normal-text-transform);\n\tfont-feature-settings: var(--kbq-typography-text-normal-font-feature-settings);\n\tletter-spacing: var(--kbq-typography-text-normal-letter-spacing);\n\tbackground: var(--kbq-background-bg);\n\tcolor: var(--kbq-foreground-contrast);\n}\n\na {\n\tcolor: var(--kbq-link-text);\n\ttext-decoration: none;\n}`
        }
    ];

    ngAfterViewInit(): void {
        this.codeBlock().scrollTo({ bottom: 0, behavior: 'instant' });
    }
}
```

### Visual styling

Two visual styles are available for the block: with a border or with a background contrasting to the page background. The contrasting background prevents the block from getting lost on a screen with varied content, and is configured using the `filled` attribute.

**Example: Code-block with filled attribute** (`code-block-with-filled`)

```ts code-block-with-filled-example.ts
import { ChangeDetectionStrategy, Component, model } from '@angular/core';
import { FormsModule } from '@angular/forms';
import {
    KbqCodeBlockFile,
    kbqCodeBlockHighlightJsConfigProvider,
    KbqCodeBlockModule
} from '@koobiq/components/code-block';
import { KbqToggleModule } from '@koobiq/components/toggle';

@Component({
    selector: 'code-block-with-filled-example',
    imports: [
        KbqCodeBlockModule,
        KbqToggleModule,
        FormsModule
    ],
    template: `
        <kbq-toggle class="layout-margin-bottom-m layout-margin-right-m" [(ngModel)]="filled">Filled</kbq-toggle>
        <kbq-toggle class="layout-margin-bottom-m" [(ngModel)]="alwaysShowActionbar">Always show actionbar</kbq-toggle>

        <kbq-code-block [files]="files" [filled]="filled()" [alwaysShowActionbar]="alwaysShowActionbar()" />
    `,
    providers: [
        kbqCodeBlockHighlightJsConfigProvider({
            languages: {
                bash: () => import('highlight.js/lib/languages/bash')
            }
        })
    ],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class CodeBlockWithFilledExample {
    readonly files: KbqCodeBlockFile[] = [
        {
            language: 'bash',
            content: 'npm install @koobiq/components'
        }
    ];

    readonly filled = model(true);
    readonly alwaysShowActionbar = model(false);
}
```

### Without borders

When the code block should fill an entire container or screen, it is best to use a style without a border and background, configured using the `noBorder` attribute.

**Example: Code-block with noBorder attribute** (`code-block-with-no-border`)

```ts code-block-with-no-border-example.ts
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { KbqButtonModule } from '@koobiq/components/button';
import {
    KbqCodeBlockFile,
    kbqCodeBlockHighlightJsConfigProvider,
    KbqCodeBlockModule
} from '@koobiq/components/code-block';
import { KbqSidepanelModule, KbqSidepanelService } from '@koobiq/components/sidepanel';

@Component({
    selector: 'code-block-with-no-border-example',
    imports: [
        KbqCodeBlockModule,
        KbqSidepanelModule,
        KbqButtonModule
    ],
    template: `
        <button kbq-button (click)="sidepanel.open(template)">Open sidepanel</button>
        <ng-template #template>
            <kbq-code-block
                canToggleSoftWrap
                noBorder
                lineNumbers
                style="height: 100%"
                [files]="files"
                [softWrap]="true"
            />
        </ng-template>
    `,
    providers: [
        kbqCodeBlockHighlightJsConfigProvider({
            languages: {
                xml: () => import('highlight.js/lib/languages/xml')
            }
        })
    ],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class CodeBlockWithNoBorderExample {
    readonly files: KbqCodeBlockFile[] = [
        {
            content: `<?xml version="1.0" encoding="UTF-8" ?>\n<vulnerabilities>\n\t<vulnerability>\n\t\t<name>Cross-site scripting</name>\n\t\t<abbreviation>XSS</abbreviation>\n\t\t<description>Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 "traditional" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network.</description>\n\t</vulnerability>\n\t<vulnerability>\n\t\t<name>Denial-of-service attack</name>\n\t\t<abbreviation>DoS</abbreviation>\n\t\t<description>In computing, a denial-of-service attack (DoS attack) is a cyber-attack in which the perpetrator seeks to make a machine or network resource unavailable to its intended users by temporarily or indefinitely disrupting services of a host connected to a network. Denial of service is typically accomplished by flooding the targeted machine or resource with superfluous requests in an attempt to overload systems and prevent some or all legitimate requests from being fulfilled. The range of attacks varies widely, spanning from inundating a server with millions of requests to slow its performance, overwhelming a server with a substantial amount of invalid data, to submitting requests with an illegitimate IP address.</description>\n\t</vulnerability>\n\t<vulnerability>\n\t\t<name>Cross-site scripting</name>\n\t\t<abbreviation>XSS</abbreviation>\n\t\t<description>Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 "traditional" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network.</description>\n\t</vulnerability>\n\t<vulnerability>\n\t\t<name>Cross-site scripting</name>\n\t\t<abbreviation>XSS</abbreviation>\n\t\t<description>Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 "traditional" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network.</description>\n\t</vulnerability>\n\t<vulnerability>\n\t\t<name>Cross-site scripting</name>\n\t\t<abbreviation>XSS</abbreviation>\n\t\t<description>Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 "traditional" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network.</description>\n\t</vulnerability>\n\t<vulnerability>\n\t\t<name>Cross-site scripting</name>\n\t\t<abbreviation>XSS</abbreviation>\n\t\t<description>Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 "traditional" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network.</description>\n\t</vulnerability>\n\t<vulnerability>\n\t\t<name>Cross-site scripting</name>\n\t\t<abbreviation>XSS</abbreviation>\n\t\t<description>Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 "traditional" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network.</description>\n\t</vulnerability>\n\t<vulnerability>\n\t\t<name>Cross-site scripting</name>\n\t\t<abbreviation>XSS</abbreviation>\n\t\t<description>Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 "traditional" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network.</description>\n\t</vulnerability>\n\t<vulnerability>\n\t\t<name>Cross-site scripting</name>\n\t\t<abbreviation>XSS</abbreviation>\n\t\t<description>Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 "traditional" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network.</description>\n\t</vulnerability>\n\t<vulnerability>\n\t\t<name>Cross-site scripting</name>\n\t\t<abbreviation>XSS</abbreviation>\n\t\t<description>Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 "traditional" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network.</description>\n\t</vulnerability>\n\t<vulnerability>\n\t\t<name>Cross-site scripting</name>\n\t\t<abbreviation>XSS</abbreviation>\n\t\t<description>Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 "traditional" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network.</description>\n\t</vulnerability>\n\t<vulnerability>\n\t\t<name>Cross-site scripting</name>\n\t\t<abbreviation>XSS</abbreviation>\n\t\t<description>Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 "traditional" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network.</description>\n\t</vulnerability>\n<vulnerabilities>`,
            language: 'xml',
            link: 'https://github.com/koobiq/angular-components'
        }
    ];

    readonly sidepanel = inject(KbqSidepanelService);
}
```

### Action panel

The action panel is located in the upper-right corner of the block and remains fixed while scrolling. The component configuration determines which actions are available.

The panel is always visible when tabs are shown, as well as on iOS and Android devices. When tabs are hidden, it appears on hover on other devices.

The `alwaysShowActionbar` attribute keeps the panel visible regardless of tabs or hover. It is disabled by default.

```html
<kbq-code-block [files]="files" canCopy alwaysShowActionbar />
```

To enable the option for all code blocks within an injector scope, use the provider:

```typescript
providers: [kbqCodeBlockDefaultOptionsProvider({ alwaysShowActionbar: true })];
```

#### Changing wrap mode

The user can toggle the wrap mode using a toggle button; this option is disabled by default and can be configured using the `canToggleSoftWrap` attribute.

```html
<kbq-code-block [files]="files" canToggleSoftWrap />
```

#### Downloading the document

The user can save/download the document to a file; this option is disabled by default and can be configured using the `canDownload` attribute.

The file name and extension are taken from the `filename` field. The default file name is _code_, and the default extension is _txt_.

```html
<kbq-code-block [files]="files" canDownload />
```

#### Copying the document text

The user can copy the document text; this option is enabled by default and can be configured using the `canCopy` attribute.

```html
<kbq-code-block [files]="files" canCopy="false" />
```

#### Opening the document in an external system

The address is taken from the `link` field. The link opens in a new tab.

**Example: Code-block with link** (`code-block-with-link`)

```ts code-block-with-link-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import {
    KbqCodeBlockFile,
    kbqCodeBlockHighlightJsConfigProvider,
    KbqCodeBlockModule
} from '@koobiq/components/code-block';

@Component({
    selector: 'code-block-with-link-example',
    imports: [KbqCodeBlockModule],
    template: `
        <kbq-code-block lineNumbers canCopy="false" [files]="files" />
    `,
    providers: [
        kbqCodeBlockHighlightJsConfigProvider({
            languages: {
                xml: () => import('highlight.js/lib/languages/xml')
            }
        })
    ],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class CodeBlockWithLinkExample {
    readonly files: KbqCodeBlockFile[] = [
        {
            link: 'https://en.wikipedia.org/wiki/Cross-site_scripting',
            filename: 'vulnerabilities.xml',
            content: `<?xml version="1.0" encoding="UTF-8" ?>\n<vulnerabilities>\n\t<vulnerability>\n\t\t<name>Cross-site scripting</name>\n\t\t<abbreviation>XSS</abbreviation>\n\t\t<description>Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 "traditional" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network.</description>\n\t</vulnerability>\n<vulnerabilities>`,
            language: 'xml'
        }
    ];
}
```

## API

### Components

#### KbqCodeBlock (component)

Component which highlights blocks of code.

```ts
@Component({ selector: 'kbq-code-block', exportAs: 'kbqCodeBlock' })
class KbqCodeBlock {
    readonly lineNumbers = input<boolean>(false);
    readonly filled = input<boolean>(false);
    readonly canToggleSoftWrap = input<boolean>(false);
    readonly softWrap = model<boolean>(false);
    readonly viewAll = model<boolean>(false);
    readonly maxHeight = input<number | undefined>();
    readonly canDownload = input<boolean>(false);
    readonly canCopy = input<boolean>(true);
    readonly alwaysShowActionbar = input<boolean>(
        this.defaultOptions?.alwaysShowActionbar ?? false
    );
    readonly files = input<KbqCodeBlockFile[]>([]);
    readonly activeFileIndex = model<number>(0);
    readonly noBorder = input<boolean>(false);
    readonly hideTabs = model<boolean>(false);
    toggleViewAll(): void;
    scrollTo(options: KbqScrollbarScrollToOptions): void;
    toggleSoftWrap(): void;
}
```

- `[lineNumbers]`: `boolean` — Whether to display line numbers.
- `[filled]`: `boolean` — Whether the code block should be filled.
- `[canToggleSoftWrap]`: `boolean` — Added soft wrap toggle button.
- `[(softWrap)]`: `boolean` — Whether sequences of whitespace should be preserved.
- `[(viewAll)]`: `boolean` — Allows to view all the code, otherwise it will be hidden.
  Works only with `maxHeight` property.
- `[maxHeight]`: `number | undefined` — Maximum height of the code block content, other parts will be hidden.
  Can be toggled by `viewAll` property.
- `[canDownload]`: `boolean` — Added download code button.
- `[canCopy]`: `boolean` — Added copy code button.
- `[alwaysShowActionbar]`: `boolean` — Whether the actionbar should remain visible when tabs are hidden.
- `[files]`: `KbqCodeBlockFile[]` — Files to display.
- `[(activeFileIndex)]`: `number` — Defines which file (index) is active.
- `[noBorder]`: `boolean` — Whether to hide border.
- `[(hideTabs)]`: `boolean` — Whether to hide header tabs. A single file without a filename hides them regardless - read
  `tabsHidden` for what the header actually does.
  Makes actionbar floating if tabs are hidden.
- `[localeOverrides]`: `KbqPartialLocaleData | undefined` — Localized strings for this element and its subtree, keyed by locale section. Every key is optional at
  every depth.
- `toggleViewAll()`: `void` — Toggles the `viewAll` property.

  When `viewAll` is set to `true`, the content of the code block will be
  displayed in its entirety. When set to `false`, the content will be
  limited to the `maxHeight` property. If the content exceeds the
  `maxHeight`, it will be scrolled to the top and the `viewAll` button
  will be displayed.
- `scrollTo()`: `void` — Scrolls the code content to the specified position.
- `toggleSoftWrap()`: `void` — Toggles `softWrap` property.

  When `softWrap` is set to `true`, the content of the code block will be
  wrapped if it exceeds the height of the component. When set to `false`
  the content will not be wrapped.

### Directives

#### KbqCodeBlockTabLinkContent (directive)

Marks a template as a custom tab link.

```ts
@Directive({
    selector: 'ng-template[kbqCodeBlockTabLinkContent]',
    exportAs: 'kbqCodeBlockTabLinkContent'
})
class KbqCodeBlockTabLinkContent {}
```

### Types

#### KbqCodeBlockDefaultOptions (type)

Default options for `kbq-code-block`.

```ts
type KbqCodeBlockDefaultOptions = Partial<{
    alwaysShowActionbar: boolean;
}>;
```

- `alwaysShowActionbar?`: `boolean` — Whether the actionbar should remain visible when tabs are hidden.

#### KbqCodeBlockFile (type)

Code block file object.

```ts
type KbqCodeBlockFile = {
    content: string;
    filename?: string;
    language?: string;
    link?: string;
};
```

- `content`: `string` — Code content.
- `filename?`: `string` — File name, which will be displayed in UI and when downloading.
  If not provided, will be set to `KBQ_CODE_BLOCK_FALLBACK_FILE_NAME`.
- `language?`: `string` — File language, required for correct syntax highlighting. It has to be registered in `languages` of
  `KbqCodeBlockHighlightJsConfig`, unless the full bundle of highlight.js is loaded. If not provided or not
  registered, will be set to `KBQ_CODE_BLOCK_FALLBACK_FILE_LANGUAGE`, or to `plaintext` if that is not registered
  either.

  See the [list of supported languages](https://github.com/highlightjs/highlight.js/blob/11-stable/SUPPORTED_LANGUAGES.md).
- `link?`: `string` — Link to the file, which will be opened in a new window.
  Adds `openExternalSystem` button.

#### KbqCodeBlockHighlightJsConfig (type)

Configuration of highlight.js, which highlights the code of a code block: how to load it and which languages to
register. Without a configuration, the code block loads the highlight.js core, which has no languages, and shows the
code as plain text. Provide it with `kbqCodeBlockHighlightJsConfigProvider`.

```ts
type KbqCodeBlockHighlightJsConfig = Partial<{
    core: () => Promise<{ default: HLJSApi }>;
    languages: Record<string, () => Promise<{ default: LanguageFn }>>;
}>;
```

- `core?`: `() => Promise<{ default: HLJSApi }>` — Lazy loader for the highlight.js instance. The core has no languages: register the ones the files use in
  `languages`, or load all of them with `() => import('highlight.js')`, the full bundle of about 1 MB.
  Defaults to `() => import('highlight.js/lib/core')`.
- `languages?`: `Record<string, () => Promise<{ default: LanguageFn }>>` — Map of language name to lazy loader for that language's LanguageFn. A language of highlight.js loads from
  `highlight.js/lib/languages/<name>`, where `<name>` is the name of its file in
  [src/languages](https://github.com/highlightjs/highlight.js/tree/11-stable/src/languages). Plain text needs no
  entry: the code block registers it as the fallback language.

#### KbqTabLinkTemplateContext (type)

Context provided to the tab link template: `$implicit` is the code block file for the current tab, and
`fallbackFileName` is displayed when the file has no explicit name.

```ts
type KbqTabLinkTemplateContext = {
    $implicit: KbqCodeBlockFile;
    fallbackFileName: string;
};
```

### Constants

#### KBQ_CODE_BLOCK_DEFAULT_OPTIONS (const)

Injection token used to configure the default options for all `kbq-code-block` components.

```ts
const KBQ_CODE_BLOCK_DEFAULT_OPTIONS: InjectionToken<KbqCodeBlockDefaultOptions>;
```

#### KBQ_CODE_BLOCK_FALLBACK_FILE_LANGUAGE (const)

Fallback language for code block if language is not supported/specified. It has to be registered in `languages` of
`KbqCodeBlockHighlightJsConfig`, unless it is plain text or the full bundle of highlight.js is loaded, or the code
block falls back to `plaintext`.

See the [list of supported languages](https://github.com/highlightjs/highlight.js/blob/11-stable/SUPPORTED_LANGUAGES.md).

```ts
const KBQ_CODE_BLOCK_FALLBACK_FILE_LANGUAGE: InjectionToken<string>;
```

#### KBQ_CODE_BLOCK_FALLBACK_FILE_NAME (const)

Fallback file name for code block if file name is not specified.

```ts
const KBQ_CODE_BLOCK_FALLBACK_FILE_NAME: InjectionToken<string>;
```

#### KBQ_CODE_BLOCK_HIGHLIGHT_JS_CONFIG (const)

Injection token for configuring `KbqCodeBlockHighlightJsConfig`.

```ts
const KBQ_CODE_BLOCK_HIGHLIGHT_JS_CONFIG: InjectionToken<KbqCodeBlockHighlightJsConfig>;
```

#### KBQ_CODE_BLOCK_LOCALE_CONFIGURATION (const)

Localization configuration provider.

```ts
const KBQ_CODE_BLOCK_LOCALE_CONFIGURATION: InjectionToken<KbqCodeBlockLocaleConfiguration>;
```

#### kbqCodeBlockDefaultOptionsProvider (const)

Utility provider for `KBQ_CODE_BLOCK_DEFAULT_OPTIONS`.

```ts
const kbqCodeBlockDefaultOptionsProvider: (
    options: KbqCodeBlockDefaultOptions
) => Provider;
```

#### kbqCodeBlockFallbackFileLanguageProvider (const)

Utility provider for `KBQ_CODE_BLOCK_FALLBACK_FILE_LANGUAGE`.

```ts
const kbqCodeBlockFallbackFileLanguageProvider: (
    language: string
) => Provider;
```

#### kbqCodeBlockFallbackFileNameProvider (const)

Utility provider for `KBQ_CODE_BLOCK_FALLBACK_FILE_NAME`.

```ts
const kbqCodeBlockFallbackFileNameProvider: (
    fileName: string
) => Provider;
```

#### kbqCodeBlockHighlightJsConfigProvider (const)

Utility provider for `KBQ_CODE_BLOCK_HIGHLIGHT_JS_CONFIG`.

```ts
providers: [
  kbqCodeBlockHighlightJsConfigProvider({
    languages: {
      typescript: () => import('highlight.js/lib/languages/typescript'),
      css: () => import('highlight.js/lib/languages/css'),
      html: () => import('highlight.js/lib/languages/xml')
    }
  })
]
```

```ts
const kbqCodeBlockHighlightJsConfigProvider: (
    options: KbqCodeBlockHighlightJsConfig
) => Provider;
```

#### kbqCodeBlockLocaleConfigurationProvider (const)

Utility provider for `KBQ_CODE_BLOCK_LOCALE_CONFIGURATION`. Only the strings you pass are overridden;
the rest keep following the active locale.

```ts
const kbqCodeBlockLocaleConfigurationProvider: (
    configuration: KbqDeepPartial<KbqCodeBlockLocaleConfiguration>
) => Provider;
```

## Examples

### Custom localization

**Example: Code-block with custom locale configuration, without KBQ\_LOCALE\_SERVICE** (`code-block-with-custom-locale-configuration`)

```ts code-block-with-custom-locale-configuration-example.ts
import { ChangeDetectionStrategy, Component } from '@angular/core';
import {
    KbqCodeBlockFile,
    kbqCodeBlockHighlightJsConfigProvider,
    kbqCodeBlockLocaleConfigurationProvider,
    KbqCodeBlockModule
} from '@koobiq/components/code-block';
import { KBQ_LOCALE_SERVICE } from '@koobiq/components/core';

@Component({
    selector: 'code-block-with-custom-locale-configuration-example',
    imports: [KbqCodeBlockModule],
    template: `
        <kbq-code-block canToggleSoftWrap maxHeight="200" lineNumbers [canDownload]="true" [files]="files" />
    `,
    providers: [
        kbqCodeBlockHighlightJsConfigProvider({
            languages: {
                xml: () => import('highlight.js/lib/languages/xml')
            }
        }),
        // Disable global KBQ_LOCALE_SERVICE for locale configuration overriding
        { provide: KBQ_LOCALE_SERVICE, useValue: null },
        kbqCodeBlockLocaleConfigurationProvider({
            softWrapOnTooltip: '*CUSTOM* Enable word wrap',
            softWrapOffTooltip: '*CUSTOM* Disable word wrap',
            downloadTooltip: '*CUSTOM* Download',
            copiedTooltip: '*CUSTOM* ✓ Copied',
            copyTooltip: '*CUSTOM* Copy',
            viewAllText: '*CUSTOM* Show all',
            viewLessText: '*CUSTOM* Show less',
            openExternalSystemTooltip: '*CUSTOM* Open in the external system'
        })
    ],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class CodeBlockWithCustomLocaleConfigurationExample {
    readonly files: KbqCodeBlockFile[] = [
        {
            content: `<?xml version="1.0" encoding="UTF-8" ?>\n<vulnerabilities>\n\t<vulnerability>\n\t\t<name>Cross-site scripting</name>\n\t\t<abbreviation>XSS</abbreviation>\n\t\t<description>Cross-site scripting (XSS) is a type of security vulnerability that can be found in some web applications. XSS attacks enable attackers to inject client-side scripts into web pages viewed by other users. A cross-site scripting vulnerability may be used by attackers to bypass access controls such as the same-origin policy. During the second half of 2007, XSSed documented 11,253 site-specific cross-site vulnerabilities, compared to 2,134 "traditional" vulnerabilities documented by Symantec. XSS effects vary in range from petty nuisance to significant security risk, depending on the sensitivity of the data handled by the vulnerable site and the nature of any security mitigation implemented by the site's owner network.</description>\n\t</vulnerability>\n\t<vulnerability>\n\t\t<name>Denial-of-service attack</name>\n\t\t<abbreviation>DoS</abbreviation>\n\t\t<description>In computing, a denial-of-service attack (DoS attack) is a cyber-attack in which the perpetrator seeks to make a machine or network resource unavailable to its intended users by temporarily or indefinitely disrupting services of a host connected to a network. Denial of service is typically accomplished by flooding the targeted machine or resource with superfluous requests in an attempt to overload systems and prevent some or all legitimate requests from being fulfilled. The range of attacks varies widely, spanning from inundating a server with millions of requests to slow its performance, overwhelming a server with a substantial amount of invalid data, to submitting requests with an illegitimate IP address.</description>\n\t</vulnerability>\n<vulnerabilities>`,
            language: 'xml',
            link: 'https://github.com/koobiq/angular-components'
        }
    ];
}
```
