Skip to content

AI

AiCodeBlockView

Bit.BlazorUI.AICodeBlock

BitAiCodeBlockView shows a block of code with a header naming its language or file, a copy button, and syntax highlighting for fifteen languages and their aliases out of the box. Highlighting is deferred while the block is still streaming - colors that shift as the lexer changes its mind about an unterminated string are worse than none - and applied once, the moment the block is complete. Every token kind is painted with a role color of the theme and restyled through a public CSS variable of its own. Every fenced code block of a BitAiMarkdownView is one, unless the app registered a renderer of its own for its language.

Notes

To use this component, you need to install the Bit.BlazorUI.AI(opens in a new tab) nuget package, as described in the Optional steps of the Getting started page. The copy button writes to the clipboard from the package's script.

It needs no chat session. The highlighter is a lexical one written in C#, so it runs in every render mode with no script of its own and never fails on half-written code; the code is rendered as text, never as markup, so whatever a model writes in it stays inert. Copying takes the code exactly as it is - the line numbers are generated content and are never part of it. BitAiUiOptions.ShowCodeCopy and BitAiUiOptions.ShowLineNumbers turn the copy button and the line numbers on and off for every block at once (see AiOptionsProvider). Accessibility: the code scrolls sideways in a group named after the file or the language (BitAiStrings.CodeBlock, "csharp code"), which takes the keyboard focus while it has something to scroll, so a long line can be read without a pointer; and the code is laid out left to right in right-to-left text too, so its punctuation stays where it was written. See it at work in the Streaming and Artifacts scenarios.

Usage

Every example is live. Open its code to see exactly what produced the component running underneath.

Basic

Code is the source and Language the identifier that picks a highlighter, also shown in the header beside the copy button. Without a language the header says text and the code is not colored.

csharp
using Bit.BlazorUI;

// Registers the AI components with a transport of your own.
builder.Services.AddBitBlazorUIAIServices(ai => ai.UseTransport<MyTransport>());

var app = builder.Build();
app.Run();

text
A block with no language is plain text.

File name

FileName is shown in the header in place of the language, which still picks the highlighter.

appsettings.json
{
  "Logging": { "LogLevel": { "Default": "Information" } },
  "AllowedHosts": "*",
  "Ai": { "Model": "demo-model-1", "MaxTokens": 4096, "Stream": true }
}

Header

ShowHeader set to false leaves the header bar out - and the copy button with it - for a block that is only read.

dotnet add package Bit.BlazorUI.AI

Streaming

While IsStreaming is true the code is shown as plain text, however much of it has arrived; it is highlighted once, the moment IsStreaming turns false. A BitAiMarkdownView sets it while the closing fence of a block has not arrived yet.



python

Line numbers & copy

ShowLineNumbers of the AI options numbers every line of every block, and ShowCodeCopy (on by default) shows the copy button: a BitAiOptionsProvider sets them for a region. The numbers sit in a gutter of their own and are never copied or selected with the code.

csharp
using Bit.BlazorUI;

// Registers the AI components with a transport of your own.
builder.Services.AddBitBlazorUIAIServices(ai => ai.UseTransport<MyTransport>());

var app = builder.Build();
app.Run();

Languages

Fifteen languages are highlighted out of the box (BitAiBuiltInLanguages), each also under its aliases - the names models write in their fences, matched without regard to case: cs is C#, ts is highlighted as JavaScript, xml and razor as HTML, kotlin as Java, ini as TOML. A language that is not registered renders as plain text, which is still correct, only not colored.


Aliases: cs, c#, dotnet

csharp
[Authorize]
public sealed record Message(string Author, string Text, DateTimeOffset At)
{
    public bool IsRecent => DateTimeOffset.UtcNow - At < TimeSpan.FromMinutes(5);
}

Custom language

BitAiLanguageRegistry.Register adds a language - or replaces a built-in one, under all of its aliases - from a BitAiLanguageDefinition: a lexical description (keywords, types, constants, comments, strings and a few switches) rather than a grammar. Register once, at startup; this page registers GraphQL as it initializes.

graphql
# The conversations of the signed-in user.
query Conversations($first: Int = 20) @cached(ttl: 60) {
  conversations(first: $first, archived: false) {
    id
    title
    messages(last: 1) { text createdAt }
  }
}

Token colors

Each kind of token (BitAiTokenKind) is painted with a role color of the theme - its -fg shade, legible on the page in both color schemes and in every preset - or a neutral text color, and has a public variable of its own: keywords --bit-AiCodeBlockView-keyword-color, types -type-color, strings -string-color, numbers -number-color, comments -comment-color, functions -function-color, operators -operator-color, punctuation -punctuation-color, properties -property-color, tags -tag-color, attributes -attribute-color, constants -constant-color, diff lines -inserted-color, -deleted-color and -meta-color, labels -label-color and variables -variable-color. Set them on any ancestor to give every block a palette of your own.

csharp
[Obsolete("Use CountAsync")]
public static int Count(string path, bool recursive = false)
{
    // Keywords, types, strings, numbers, comments, functions, operators and constants.
    var total = Directory.GetFiles(path).Length + 0x10;
    return recursive ? total * 2 : total;
}

html
<button type="submit" class="primary" disabled>Send</button>

json
{ "name": "bit", "stars": 1200, "archived": false, "license": null }

diff
--- a/appsettings.json
+++ b/appsettings.json
@@ -2 +2 @@
-  "Model": "demo-model-1",
+  "Model": "demo-model-2",

rust
fn first<'a>(items: &'a [String]) -> Option<&'a String> {
    'outer: for item in items { break 'outer; }
    items.first()
}

powershell
$files = Get-ChildItem -Path $env:TEMP -Recurse | Where-Object { $_.Length -gt 1MB }

Highlighter

BitAiSyntaxHighlighter.Highlight is the highlighter the code block uses, for an app that colors code anywhere else. It returns the tokens of the code in the language registered under a name - a BitAiCodeToken each, its Kind with the Start and the Length of its text - in order and never overlapping; the text between them is plain, and a language that is not registered returns none. Slice reads the text of a token back from the code. Edit the code and watch its tokens follow.


csharp
var total = Math.Max(count, 1) * 2; // never zero

Type varPlain totalOperator =Type MathOperator .Function MaxPunctuation (Plain countPunctuation ,Number 1Punctuation )Operator *Number 2Punctuation ;Comment // never zero

Disabled

A Disabled code block still shows its code, highlighted as ever, and disables its copy button with it: nothing is copied from the header. The code itself can still be selected.

bash
dotnet add package Bit.BlazorUI.AI

Cascading parameters

BitParams with a BitAiCodeBlockViewParams sets the defaults of every code block inside it - here no header - and a parameter of the block itself still wins.

dotnet new blazor -o MyChat

dotnet add package Bit.BlazorUI.AI

bash
dotnet run

Style & Class

Style and Class reach the root, Styles and Classes its parts: the Header with its Label and CopyButton, the scrolling Body, the Pre and Code elements, and every numbered Line. The public --bit-AiCodeBlockView-* variables (see the CSS variables table) restyle the block and its tokens.

bash
dotnet add package Bit.BlazorUI.AI

bash
dotnet add package Bit.BlazorUI.AI

bash
dotnet add package Bit.BlazorUI.AI

bash
dotnet add package Bit.BlazorUI.AI

bash
dotnet add package Bit.BlazorUI.AI

RTL

In right-to-left text the header is mirrored - the label at the right, the copy button at the left - whether the direction comes from Dir or from a dir attribute around the block. The code itself stays left to right, as it is written.

مثال.cs
// سلام دنیا
Console.WriteLine("سلام دنیا");

CSS variables

The public custom properties this component reads off its root, for what no parameter covers.

Every variable is read with a fallback and never declared by the component, so it inherits like any other custom property: set one on :root (or in a [bit-theme] block) to restyle every instance, on any ancestor to restyle the ones inside it, or on the Style of one instance to restyle it - and any instance nested inside it, which inherits the value too; a parameter changes one alone, as does the real CSS property on the instance's Style / Styles when that property does not inherit (opacity: 1 keeps one disabled instance undimmed without undimming a disabled one inside it), while an inherited one such as color or font-family also reaches the nested instances that do not set it themselves. Leave a variable unset and the component falls back to the theme token beside it.

BitAiCodeBlockView CSS variables

Name Default value Description
--bit-AiCodeBlockView-background 4% of var(--bit-clr-fg-pri) Background of the block: a translucent wash of the text color, so it reads on whatever the message sits on.
--bit-AiCodeBlockView-color inherit Text color of the code (and of the plain text between the tokens).
--bit-AiCodeBlockView-border-color var(--bit-clr-brd-sec) Border of the block and the line under its header.
--bit-AiCodeBlockView-radius var(--bit-shp-radius-surface) Corner radius of the block.
--bit-AiCodeBlockView-header-background 4% of var(--bit-clr-fg-pri) Background of the header bar.
--bit-AiCodeBlockView-header-color var(--bit-clr-fg-sec) Text color of the header bar.
--bit-AiCodeBlockView-padding spacing(1.5) Padding around the code.
--bit-AiCodeBlockView-font-family var(--bit-tpg-font-family-mono) Font of the code and of the header label.
--bit-AiCodeBlockView-font-size var(--bit-tpg-fs-sm) Text size of the code.
--bit-AiCodeBlockView-line-number-color var(--bit-clr-fg-ter) Color of the line numbers.
--bit-AiCodeBlockView-keyword-color var(--bit-clr-pri-fg) Color of the keywords.
--bit-AiCodeBlockView-type-color var(--bit-clr-suc-fg) Color of the type names.
--bit-AiCodeBlockView-string-color var(--bit-clr-swr-fg) Color of the string and character literals.
--bit-AiCodeBlockView-number-color var(--bit-clr-sec-fg) Color of the numeric literals.
--bit-AiCodeBlockView-comment-color color-mix(in srgb, var(--bit-clr-fg-ter), var(--bit-clr-fg-pri) 15%) Color of the comments (set in italics). The tertiary text color has a little of the text color mixed in, which keeps it legible on the tint of the block.
--bit-AiCodeBlockView-function-color color-mix(in srgb, var(--bit-clr-wrn-fg), var(--bit-clr-fg-pri) 15%) Color of the function and command names. The warning shade has a little of the text color mixed in, which keeps it legible on the tint of the block.
--bit-AiCodeBlockView-operator-color var(--bit-clr-fg-sec) Color of the operators.
--bit-AiCodeBlockView-punctuation-color var(--bit-clr-fg-sec) Color of the punctuation.
--bit-AiCodeBlockView-property-color var(--bit-clr-pri-fg) Color of the keys and properties (JSON, YAML, CSS).
--bit-AiCodeBlockView-tag-color var(--bit-clr-err-fg) Color of the markup tags.
--bit-AiCodeBlockView-attribute-color var(--bit-clr-sec-fg) Color of the markup attributes and the annotations.
--bit-AiCodeBlockView-constant-color var(--bit-clr-sec-fg) Color of true, false, null and the other constants.
--bit-AiCodeBlockView-inserted-color var(--bit-clr-suc-fg) Color of the lines a diff adds.
--bit-AiCodeBlockView-deleted-color var(--bit-clr-err-fg) Color of the lines a diff removes.
--bit-AiCodeBlockView-meta-color color-mix(in srgb, var(--bit-clr-fg-ter), var(--bit-clr-fg-pri) 15%) Color of the file headers and the hunk markers of a diff. The tertiary text color has a little of the text color mixed in, as the comments' has.
--bit-AiCodeBlockView-label-color the type color Color of the lifetimes and loop labels (set in italics); it falls back to --bit-AiCodeBlockView-type-color.
--bit-AiCodeBlockView-variable-color the property color Color of the variables written with a sigil ($name); it falls back to --bit-AiCodeBlockView-property-color.

API

Every parameter, public member, sub-class and enum this component exposes.

BitAiCodeBlockView parameters

Name Type Default value Description
Classes BitAiCodeBlockViewClassStyles? null Custom CSS classes for different parts of the code block.
Code string string.Empty The source to display. It is rendered as text, never as markup, and it is what the copy button copies - exactly, without the line numbers.
FileName string? null A file name shown in the header in place of the language (which still picks the highlighter).
IsStreaming bool false Whether the block is still receiving content, which holds the highlighting back: the code is shown as plain text while it is true, and highlighted once when it turns false.
Language string? null The language identifier used to pick a highlighter (an id or alias of BitAiLanguageRegistry, matched without regard to case; an unknown one is plain text), also shown in the header when there is no file name - text when it is null too.
ShowHeader bool true Shows the header bar with the language (or file name) and the copy button. The copy button also needs BitAiUiOptions.ShowCodeCopy, which is on by default.
Styles BitAiCodeBlockViewClassStyles? null Custom CSS styles for different parts of the code block.

BitComponentBase parameters

Name Type Default value Description
AriaLabel string? null Gets or sets the accessible label for the component, used by assistive technologies.
Class string? null Gets or sets the CSS class name(s) to apply to the rendered element.
Dir BitDir? null Gets or sets the text directionality for the component's content.
Disabled bool false Gets or sets a value indicating whether the component is disabled and cannot respond to user interaction.
ForceAnimation bool false Gets or sets a value indicating whether the component's animations play at their full duration even when reduced motion is requested.
HtmlAttributes Dictionary<string, object> new Dictionary<string, object>() Captures additional HTML attributes to be applied to the rendered element, in addition to the component's parameters. An attribute written on the component wins over an entry of the same name.
Id string? null Gets or sets the unique identifier for the component's root element.
Style string? null Gets or sets the CSS style string to apply to the rendered element.
TabIndex string? null Gets or sets the tab order index for the component when navigating with the keyboard.
Visibility BitVisibility BitVisibility.Visible Gets or sets the visibility state (visible, hidden, or collapsed) of the component.

BitComponentBase public members

Name Type Default value Description
UniqueId Guid Guid.NewGuid() Gets the readonly unique identifier for the component's root element, assigned when the component instance is constructed.
RootElement ElementReference Gets the reference to the root HTML element associated with this component.

BitAiCodeBlockViewClassStyles properties

Name Type Default value Description
Root string? null Custom CSS classes/styles for the root element of the BitAiCodeBlockView.
Header string? null Custom CSS classes/styles for the header bar of the BitAiCodeBlockView, which holds the language and the copy button.
Label string? null Custom CSS classes/styles for the language (or file name) label in the header of the BitAiCodeBlockView.
CopyButton BitAiCopyButtonClassStyles? null Custom CSS classes/styles for the copy button (a BitAiCopyButton) in the header of the BitAiCodeBlockView.
Body string? null Custom CSS classes/styles for the scroll container of the code of the BitAiCodeBlockView.
Pre string? null Custom CSS classes/styles for the pre element of the BitAiCodeBlockView.
Code string? null Custom CSS classes/styles for the code element of the BitAiCodeBlockView (which also carries the class language-<Language>).
Line string? null Custom CSS classes/styles for every numbered line of the BitAiCodeBlockView (rendered only while BitAiUiOptions.ShowLineNumbers is on).

BitAiBuiltInLanguages properties

The languages registered by default, chosen by what models write in chat: application languages, the data formats around them and the shell. Each is a static BitAiLanguageDefinition property, registered under its id and every alias; anything else falls back to plain text.

Name Type Default value Description
CSharp BitAiLanguageDefinition csharp - aliases cs, c#, dotnet.
JavaScript BitAiLanguageDefinition javascript, TypeScript included - aliases js, jsx, typescript, ts, tsx, mjs, cjs.
Python BitAiLanguageDefinition python - aliases py, python3.
Json BitAiLanguageDefinition json, keys highlighted as properties - aliases jsonc, json5.
Html BitAiLanguageDefinition html, with the tag-aware scanner - aliases xml, svg, xhtml, razor, cshtml, vue.
Css BitAiLanguageDefinition css - aliases scss, sass, less.
Sql BitAiLanguageDefinition sql, matched without regard to case - aliases postgresql, mysql, tsql, sqlite, plsql.
Shell BitAiLanguageDefinition bash - aliases sh, shell, zsh, console.
PowerShell BitAiLanguageDefinition powershell, with $variables and hyphenated commands - aliases ps1, pwsh, ps, posh.
Go BitAiLanguageDefinition go - alias golang.
Rust BitAiLanguageDefinition rust, with lifetimes and labels - alias rs.
Java BitAiLanguageDefinition java - aliases kotlin, kt, groovy, scala.
Yaml BitAiLanguageDefinition yaml - alias yml.
Toml BitAiLanguageDefinition toml - aliases ini, cfg, conf, properties, editorconfig.
Diff BitAiLanguageDefinition diff, with added, removed and header lines - alias patch.
All IReadOnlyList<BitAiLanguageDefinition> Every built-in language, in the order above.

BitAiLanguageRegistry properties

The static registry of the languages the highlighter knows, keyed by id and alias without regard to case. It starts with BitAiBuiltInLanguages.All; register once, at startup.

Name Type Default value Description
Register(BitAiLanguageDefinition language) void Adds a language, or replaces the one of the same id - under every alias it was registered with too, so ```cs follows a replaced csharp.
Find(string? name) BitAiLanguageDefinition? The language registered under an id or alias, or null.
IsSupported(string? name) bool Whether a language is registered under the name, which is whether a block of it is highlighted.
All IReadOnlyCollection<BitAiLanguageDefinition> The distinct registered languages, ordered by id.

BitAiLanguageDefinition properties

Describes a language well enough to highlight it: a lexical description rather than a grammar, which colors the fragments a chat holds correctly and never fails on incomplete input. Created with new BitAiLanguageDefinition(id), the rest set as init-only properties.

Name Type Default value Description
Id string The canonical identifier, matching the fence info string. Set through the constructor; it cannot be blank.
Aliases IReadOnlyList<string> [] Other names that select this language.
Keywords IReadOnlySet<string> empty Words highlighted as keywords (a hyphenated word too, where HyphenatedCommands is on).
Types IReadOnlySet<string> empty Words highlighted as type names.
Constants IReadOnlySet<string> empty Words highlighted as constants, such as boolean and null literals.
LineComments IReadOnlyList<string> ["//"] Sequences that start a comment running to the end of the line.
BlockComments IReadOnlyList<(string Open, string Close)> [("/*", "*/")] Paired sequences that delimit a block comment.
StringDelimiters IReadOnlyList<char> ['"', '\''] Characters that delimit a string literal.
StringEscapes bool true Whether StringEscapeCharacter escapes the next character inside a string.
StringEscapeCharacter char '\\' The character that escapes the next one inside a string: a backslash in most languages, a backtick in PowerShell.
MultiLineStrings bool false Whether a string literal may span lines.
IsMarkup bool false Whether the language is markup, which switches to the tag-aware scanner (tags, attributes, attribute values).
ColonProperties bool false Whether identifiers before a colon are highlighted as properties, as in JSON and YAML.
IgnoreCase bool false Whether words are matched case-insensitively, as in SQL.
AnnotationPrefix char? null The character that introduces an annotation or attribute, such as @. A [ only counts at the start of a line, as C# attributes are written; a # may be followed by [ or ![, as Rust attributes are.
Lifetimes bool false Whether an apostrophe before a name is a lifetime or label rather than an unterminated character literal, as in Rust's 'a and 'outer:.
UrlFunctions bool false Whether url(...) holds a string even when unquoted, as in CSS, so the // of an address is not read as a comment.
VariablePrefix char? null The character that introduces a variable, such as PowerShell's $: the sigil and the name after it, or a braced name such as ${my var}, are one variable token.
HyphenatedCommands bool false Whether hyphenated words are commands and switches, as in PowerShell: Get-ChildItem is a function and -Recurse a parameter, while a hyphenated word listed in Keywords, such as -eq, is a keyword.

BitAiSyntaxHighlighter properties

The static highlighter the code block uses, for an app that colors code anywhere else.

Name Type Default value Description
Highlight(string? code, string? language) IReadOnlyList<BitAiCodeToken> The tokens of the code in the language registered under that id or alias (BitAiLanguageRegistry), in order; none for an empty code or a language that is not registered. It never fails on incomplete code.

BitAiCodeToken properties

One highlighted span of the code, a readonly record struct: offsets rather than substrings, so highlighting a large file allocates one list rather than a string per token.

Name Type Default value Description
Kind BitAiTokenKind The category of the token, which selects its CSS class.
Start int Where the token starts in the code, in UTF-16 code units.
Length int How long the token is.
Slice(string source) ReadOnlySpan<char> The text of the token, read from the code it was produced from.

BitAiTokenKind enum

Name Value Description
Plain 0 Text with no special meaning: no span of its own, the color of the code.
Keyword 1 A language keyword: bit-aicbv-kwd, --bit-AiCodeBlockView-keyword-color.
Type 2 A built-in or well-known type name: bit-aicbv-typ, --bit-AiCodeBlockView-type-color.
String 3 A string literal, including interpolated ones: bit-aicbv-str, --bit-AiCodeBlockView-string-color.
Number 4 A numeric literal: bit-aicbv-num, --bit-AiCodeBlockView-number-color.
Comment 5 A comment, set in italics: bit-aicbv-cmt, --bit-AiCodeBlockView-comment-color.
Operator 6 An operator: bit-aicbv-opr, --bit-AiCodeBlockView-operator-color.
Punctuation 7 Brackets, commas and semicolons: bit-aicbv-pnc, --bit-AiCodeBlockView-punctuation-color.
Function 8 An identifier in call position, a command: bit-aicbv-fnc, --bit-AiCodeBlockView-function-color.
Property 9 A property or field name, including a JSON key: bit-aicbv-prp, --bit-AiCodeBlockView-property-color.
Tag 10 A markup tag name: bit-aicbv-tag, --bit-AiCodeBlockView-tag-color.
Attribute 11 A markup attribute name, or an annotation: bit-aicbv-atr, --bit-AiCodeBlockView-attribute-color.
Constant 12 A language constant such as a boolean or null literal: bit-aicbv-cst, --bit-AiCodeBlockView-constant-color.
Inserted 13 An added line in a diff: bit-aicbv-ins, --bit-AiCodeBlockView-inserted-color.
Deleted 14 A removed line in a diff: bit-aicbv-del, --bit-AiCodeBlockView-deleted-color.
Meta 15 A file header or hunk marker in a diff: bit-aicbv-met, --bit-AiCodeBlockView-meta-color.
Label 16 A lifetime or loop label, such as Rust's 'a or 'outer, set in italics: bit-aicbv-lab, --bit-AiCodeBlockView-label-color.
Variable 17 A variable introduced by a sigil, such as PowerShell's $name: bit-aicbv-vrb, --bit-AiCodeBlockView-variable-color.

BitVisibility enum

Name Value Description
Visible 0 The content of the component is visible.
Hidden 1 The content of the component is hidden, but the space it takes on the page remains (visibility:hidden).
Collapsed 2 The component is hidden (display:none).

BitDir enum

Name Value Description
Ltr 0 Ltr (left to right) is to be used for languages that are written from the left to the right (like English).
Rtl 1 Rtl (right to left) is to be used for languages that are written from the right to the left (like Arabic).
Auto 2 Auto lets the user agent decide. It uses a basic algorithm as it parses the characters inside the element until it finds a character with a strong directionality, then applies that directionality to the whole element.

Feedback

Found a mistake, a gap, or something that could be clearer? Every page and every component is one click from its source.