NETReporter 3.4.0

NETReporter

Knihovna pro generování reportů (PDF, SVG, HTML, JSON) z deklarativních JSON šablon a JSON dat.

Šablona popisuje stránku, sekce, rozvržení, styly a bindingy na data; knihovna ji zvaliduje, vyhodnotí nad daty a vykreslí. PDF a SVG kreslí QuestPDF, grafy OxyPlot.

Instalace

Balíček je v privátním NuGet feedu Advisor Software:

dotnet nuget add source https://nuget.advisor-soft.com/v3/index.json --name AdvisorSoft
dotnet add package NETReporter

Požadavky: .NET 10.

Rozhraní (IReportRenderer, ITemplateTools) a sdílené typy (RenderOptions, diagnostiky…) jsou v balíčku NETReporter.Abstractions, který se nainstaluje sám. Aplikace, která report jen zadává a vykreslí ho ReportServer, použije místo této knihovny tenký klient NETReporter.Client (bez QuestPDF a dalších těžkých závislostí; přihlášení API tokenem): viz docs/user/pouziti-knihovny.md a průvodce klientem v repozitáři.

Rychlý start

using NetReporter;

var renderer = new ReportRenderer();

await using var template = File.OpenRead("template.json");
await using var data = File.OpenRead("data.json");
await using var pdf = await renderer.RenderAsync(template, data);   // výchozí formát je PDF

await using var file = File.Create("report.pdf");
await pdf.CopyToAsync(file);

S DI kontejnerem (ReportRenderer se registruje jako singleton):

services.AddNetReporter();                        // ReportRenderer, TemplateSchemaParser, TemplateAnalyzer, VisualTreeBuilder
services.AddNetReporter<MyPipelineObserver>();    // + vlastní IReportPipelineObserver

var renderer = serviceProvider.GetRequiredService<ReportRenderer>();

RenderAsync bere šablonu a data jako Stream a vrací Stream s výstupem (pozice 0). Při neplatné šabloně vyhodí InvalidOperationException s diagnostikami (zpráva + JSON cesta).

Šablona v kostce

{
  "version": "1.0",
  "meta": { "name": "Faktura", "culture": "cs-CZ", "palette": { "primary": "#1A73E8" } },
  "page": { "size": "A4", "orientation": "Portrait", "marginsMm": { "top": 15, "right": 12, "bottom": 15, "left": 12 } },
  "styles": {
    "base": { "font": "Arial", "fontSize": 9 },
    "h1": { "fontSize": 16, "bold": true, "color": "primary" }
  },
  "content": {
    "root": {
      "type": "Stack",
      "gapMm": 3,
      "items": [
        { "type": "Text", "text": "Faktura {{$.Number}}", "styleRef": "h1" },
        { "type": "Text", "text": "Vystaveno: {{$.Issued:dd.MM.yyyy}}, celkem {{$.Total:C2}}" },
        {
          "type": "Table",
          "columns": [
            { "key": "name", "header": "Položka", "width": "3*" },
            { "key": "price", "header": "Cena", "width": "1*", "align": "Right" }
          ],
          "rows": {
            "source": "$.Items",
            "as": "item",
            "cells": {
              "name": { "text": "{{item.Name}}" },
              "price": { "text": "{{item.Price:N2}}" }
            }
          }
        }
      ]
    }
  },
  "pageFooter": {
    "root": { "type": "PageNumbers", "mode": "Current", "showTotal": true, "separator": " / " }
  }
}
  • Sekce: pageBackground, pageHeader, reportHeader, content, reportFooter, firstPageFooter, pageFooter, pageOverlay.
  • Vodoznak a razítko: kořenové watermark (text nebo obrázek, podmínka visibleIf, průhlednost v barvě) na každé stránce PDF, SVG, HTML i JSON; z kódu RenderOptions.Watermark.
  • Rozvržení: Stack, Row, Box, Absolute, Spacer, PageBreak; libovolný uzel lze opakovat nad kolekcí přes "repeat": { "source": "$.Items", "as": "item" }; "keepTogether": true (u Stack, Row, Box, Text, Paragraph, Table) zabrání zalomení uzlu přes stránku – nevejde-li se na zbytek stránky, přesune se celý na další.
  • Obsah: Text, Paragraph, HttpLink, Image, Line, PageNumbers, Barcode, Code2D (QR, DataMatrix…), PaymentQr (QR platba SPAYD a EPC s kontrolou IBAN), Checkbox, Emoji (barevné emoji Twemoji jako vektor), Icon (ikony FontAwesome Free, s licencí i Pro, jako vektor), Table (skupiny, souhrny, stránkování), Chart.
  • Binding: {{$.Cesta.K.Hodnote}} (kořen dat), {{alias.Pole}} (položka repeat/tabulky/grafu), formát za dvojtečkou ({{$.Total:N2}}, {{$.Date:dd.MM.yyyy}}), C# výrazy s prefixem # ({{#item.Qty * item.Price}}), systémové proměnné now, page.number, page.total. Formátuje se podle meta.culture.
  • Styly: pojmenované styly v styles (base platí pro vše), odkaz styleRef a inline style; písmo, barvy (#RRGGBB nebo název z meta.palette), okraje a výplně v mm, rámečky, zarovnání. Styl lze vybrat podle dat – styleRef může obsahovat binding, jehož výsledkem je jméno stylu ("styleRef": "{{# item.Overdue ? \"overdue\" : \"\" }}"); tabulky mají styl řádku rows.styleRef a buňky rows.cells.<key>.styleRef / style.

Kompletní popis formátu je v přibalené dokumentaci (viz níže) – kapitola 02_template_format.md.

Grafy

{
  "type": "Chart",
  "chartType": "Column",
  "source": "$.Months",
  "as": "m",
  "category": "{{m.Month}}",
  "series": [
    { "name": "2025", "value": "m.Revenue", "color": "primary" },
    { "name": "Plán", "value": "#m.Revenue * 1.1", "dashed": true }
  ],
  "valueAxis": { "format": "N0" },
  "legend": { "position": "Top" }
}

Typy Column, Bar, Line, Area, Pie, Donut; více sérií, paleta, legenda, osy, popisky hodnot, skládání. Kombinovaný graf: série může přepsat typ ("type": "Line") a čáry mohou mít druhou osu vpravo ("axis": "Secondary" + secondaryValueAxis). Grafy jsou vektorové ve všech výstupech. Podrobnosti: 02_template_format.md §7.11 a 17-charts.md.

Výstupní formáty

await using var output = await renderer.RenderAsync(template, data, new RenderOptions { Format = RenderFormat.Svg });
Formát Popis
RenderFormat.Pdf výchozí; plnohodnotné PDF se stránkováním
RenderFormat.Svg stejný layout a stránkování jako PDF; jeden SVG se stránkami pod sebou (data-pages, <svg data-page="N">)
RenderFormat.Html HTML náhled bez stránkování (vhodný pro editor/prohlížeč)
RenderFormat.Json strukturovaný výsledek renderu – vyhodnocené texty, data grafů, metadata obrázků a kódů; pro automatické a AI kontroly
RenderFormat.Webp obrázek stránky se stejným layoutem jako PDF (ztrátový, bílé pozadí); RenderAsync vrací první stránku, všechny RenderWebpPagesAsync
RenderFormat.Png obrázek stránky bezeztrátově (bílé neprůhledné pozadí); RenderAsync vrací první stránku, všechny RenderPngPagesAsync
RenderFormat.Jpeg obrázek stránky ztrátově, bez průhlednosti; RenderAsync vrací první stránku, všechny RenderJpegPagesAsync

Každou SVG stránku zvlášť vrací RenderSvgPagesAsync:

IReadOnlyList<string> pages = await renderer.RenderSvgPagesAsync(template, data);

Do SVG se nevkládají fonty – prohlížeč použije písmo nainstalované v systému (pozice znaků zůstanou zachované).

Každou stránku jako obrázek WebP vrací RenderWebpPagesAsync (rozlišení RenderOptions.ImageDpi 1–600, výchozí 288, kvalita ImageQuality; všechny stránky jsou najednou v paměti):

IReadOnlyList<byte[]> pages = await renderer.RenderWebpPagesAsync(template, data, new RenderOptions { ImageDpi = 150 });

Stejně funguje RenderPngPagesAsync (bezeztrátově, ImageQuality se ignoruje) a RenderJpegPagesAsync (ztrátově, kvalita ImageQuality).

Ladění šablon: new RenderOptions { Format = RenderFormat.Html, RenderBindingsAsExpressions = true } zobrazí místo hodnot samotné binding výrazy. RenderOptions.DebugMode přidá k HTML výstupu ladicí atributy (data-nr-type s typem uzlu u prvků s id), ladicí CSS a skript pro vizuální editor šablon; výstup bez něj se nemění.

Limit stránek: PDF/SVG render skončí RenderPageLimitExceededException po překročení RenderOptions.MaxPages (výchozí 10 000, 0 = bez limitu) – ochrana před šablonou se zacykleným layoutem. CancellationToken se kontroluje i během generování stránek. Všechny formáty se renderují souběžně: od QuestPDF 2026.9 je souběžné generování PDF/SVG v jednom procesu bezpečné a ReportRenderer ho neserializuje, takže propustnost roste s počtem vláken.

Metadata PDF

Vlastnosti dokumentu (Název, Autor, Předmět, Klíčová slova, Aplikace, Jazyk) se nastavují v meta.document. Hodnoty jsou texty s bindingy vyhodnocené nad daty; prázdný výsledek se nezapíše, klíčová slova mohou být pole a bez language se použije meta.culture. Metadata se zapisují jen do PDF.

"meta": {
  "name": "Faktura",
  "culture": "cs-CZ",
  "document": { "title": "Faktura {{$.Number}}", "author": "{{$.Supplier}}", "keywords": [ "faktura", "{{$.Number}}" ] }
}

Podrobnosti: 02_template_format.md §1.4.

Profesionální PDF

Hlavičkový papír, připojená PDF, PDF/A, přílohy a šifrování se doplňují do PDF po vygenerování (post-processing přes qpdf z balíčku QuestPDF; šablony bez těchto funkcí dávají stejné PDF jako dřív).

Hlavičkový papír a připojená PDF (šablona; fragment): page.letterhead vloží stránku PDF pod obsah stránek, meta.document.append připojí PDF za dokument. Zdroj je cesta k souboru, http(s) URL nebo data URI, nejčastěji {{$.Assets.Název}}:

"meta": { "assets": { "Hlavicka": "data:application/pdf;base64,JVBERi0…" },
          "document": { "append": [ "https://firma.cz/vop.pdf" ] } },
"page": { "size": "A4", "orientation": "Portrait", "marginsMm": { "top": 40, "right": 15, "bottom": 25, "left": 15 },
          "letterhead": { "src": "{{$.Assets.Hlavicka}}", "pages": "FirstAndRest" } }

pages: All (výchozí), First, FirstAndRest (první stránka 1. stránkou podkladu, ostatní 2. stránkou). Nedostupný zdroj render nezastaví: PDF vznikne bez něj a RenderOptions.OnBindingDiagnostics (nebo pozorovatel) dostane varování NRP036 s JSON cestou zdroje; kontrolujte je, než fakturu odešlete. Server, který renderuje cizí šablony, má nastavit ResourcePolicy = ResourcePolicy.Server (zdroje ze souborů zakázané, stahování jen z veřejných adres, limity velikosti a času).

PDF/A-3b s přílohou (ISDOC), vstupní data v PDF a heslo:

var options = new RenderOptions
{
    PdfConformance = PdfConformance.PdfA3B,
    Attachments = [ IsdocWriter.CreateAttachment(isdocInvoice) ],   // ISDOC z dat faktury (NetReporter.Isdoc), nebo vlastní new PdfAttachment { ... }
    EmbedData = true,                                   // vstupní JSON jako data.json (null = podle meta.document.embedData)
};

// šifrování (AES-256) nejde spojit s PDF/A
var secured = new RenderOptions { Encryption = new PdfEncryption { UserPassword = "ctenar", OwnerPassword = "vlastnik", AllowModification = false } };

PDF/A-2b přílohy nepovoluje. Volby PDF u jiného formátu než PDF a neslučitelné volby jsou ArgumentException. IsdocWriter složí ISDOC 6.0.2 z IsdocInvoice (součty a rekapitulaci DPH dopočítá, UUID je stabilní, výstup je ověřený proti oficiálnímu XSD); PDF/A ověřte nástrojem veraPDF. Podrobnosti: user/pouziti-knihovny.md a dev/07_renderer_questpdf.md.

Validace šablony

Šablonu lze zkontrolovat bez renderu. Parser ji ověří proti vestavěnému schématu a vrátí diagnostiky s JSON cestou k chybě:

using NetReporter.Common;
using NetReporter.Template.Parsing;

var parser = new TemplateSchemaParser();                  // výchozí ParserValidationMode.Strict
var result = parser.Parse(templateJson);

if (!result.Success)
{
    foreach (var d in result.Diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error))
        Console.WriteLine($"{d.JsonPath}: {d.Message} ({d.Code})");
}
  • Strict hlásí neznámé vlastnosti a chybný obsah stylů (neznámá vlastnost, špatný typ, neplatný enum) jako chybu, Compat jako varování (new TemplateSchemaParser(validationMode: ParserValidationMode.Compat); při renderu new RenderOptions { ValidationMode = ParserValidationMode.Compat }, varování pak dostane pozorovatel v ParseCompletedContext.Diagnostics).
  • Diagnostiky mají stabilní Code a JsonPath (např. $.content.root.items[2].rows.source).
  • Schéma šablon (typy uzlů, vlastnosti, enumy) vrací TemplateSchemaProvider.Create().

Podrobnosti: kapitola 03_parser_and_validation.md.

Data, která šablona čte

Chybějící datové pole se vykreslí prázdné a nikdo o tom nezjistí. Analyzátor zjistí ze šablony (bez renderu), která pole dat čte, a složí z nich JSON Schema nebo ukázková data:

using NetReporter.Template.DataContract;

var contract = new TemplateDataContractAnalyzer().Analyze(templateJson);
foreach (var field in contract.EnumerateFields())
    Console.WriteLine($"{field.Path}  {field.Kind}");          // $.Invoice.Items[*].Total  Number

string schema = contract.ToJsonSchema();                        // JSON Schema 2020-12, bez povinných polí
string sample = new TemplateSampleDataGenerator().GenerateJson(contract);   // deterministická ukázková data

Druh pole se odvodí z použití, formátu a názvu (názvový odhad kontrakt označí); C# výrazy {{# …}} se čtou jen podle zápisu. Podrobnosti: user/pouziti-knihovny.md a kapitola 05_binding_system.md.

Sledování pipeline

IReportPipelineObserver dostává události OnPipelineStarted, OnParseStarted/Completed, OnRenderStarted/Completed (doba, velikost výstupu) a OnError (fáze, kategorie, stabilní kód chyby) – vhodné pro metriky a logování. Registruje se přes AddNetReporter<TObserver>() nebo konstruktor ReportRenderer. Knihovna loguje přes ILogger, pokud předáte ILoggerFactory.

RenderCompletedContext v OnRenderCompleted nese také BindingDiagnostics a OmittedBindingDiagnostics: chyby v bindingech (nedokončené {{, nečíselná hodnota grafu…) render nezastaví, takže je jinak neuvidíte. Shodné diagnostiky se slučují a počet omezuje RenderOptions.MaxBindingDiagnostics (výchozí 200, 0 sběr vypne). Při selhání renderu je (do chyby nasbírané) nese i PipelineError v OnError.

Dokumentace v balíčku

Balíček obsahuje dokumentaci knihovny a šablon ve složce docs/ (po instalaci v %USERPROFILE%\.nuget\packages\netreporter\<verze>\docs\, na Linuxu ~/.nuget/packages/netreporter/<verze>/docs/). Rozcestník je docs/README.md:

Soubor Obsah
docs/user/pouziti-knihovny.md průvodce použitím knihovny krok za krokem
docs/dev/02_template_format.md formát šablony – sekce, uzly, vlastnosti, repeat, tabulky, grafy
docs/dev/03_parser_and_validation.md parser a validace šablon, diagnostiky
docs/dev/04_style_system.md stylovací systém
docs/dev/05_binding_system.md binding a výrazy
docs/dev/17-charts.md grafy – chování a omezení
docs/dev/18-emoji-a-ikony.md emoji a ikony FontAwesome – vestavěné sady, Pro a stahování verzí, licence
docs/dev/01_introduction.md, 06_runtime_pipeline.md, 07_renderer_questpdf.md, 08_program_flow_example.md, 09_extensibility.md architektura knihovny, pipeline, renderer, rozšiřitelnost

Seznam změn všech verzí je v souboru CHANGELOG.md v kořeni balíčku; změny konkrétní verze ukazuje NuGet v release notes balíčku.

Licence

MIT, © Advisor Software s.r.o.

Zdrojový kód, ukázkové šablony a změny verzí: repozitář projektu.

No packages depend on NETReporter.

- Template editor (AI assistant): prompt variants. Each model (and each operation binding) has a prompt variant, *heavy* (the full rules, the default) or *light* (`system-rules.light.md`, `template-cheatsheet.light.md`, `document-rules.light.md`: 13 to 22 % shorter, numbered imperative rules, a step-by-step procedure and, for the task template from a document, one example of a labelled grid), independent of the schema profile `Full`/`Compact`. The safety rules are in both, a prompt is byte-stable per variant (prompt cache), and a resource without a light variant (review, translation...) is shared. Measured on the 17 scenarios of `tools/assistant-eval` (new switch `--variant heavy|light`): a local `kat-coder` (Ollama, no reasoning, 2 runs each) 29/34 heavy against 31/34 light with 10.4 s instead of 18.8 s per run, DeepSeek 17/17 for both. The *Ollama* template of the model page defaults to light. - Template editor (AI assistant): the models, their parameters and keys are administered **at runtime** by the owner on the new page *Modely asistenta* (`/admin/assistant-models`; the gear button of the editor bar and the item in the user menu, shown to owners only). A model is OpenAI-compatible (`openai`, Ollama or vLLM through `/v1`) or Anthropic-compatible (`anthropic`, for example DeepSeek at `https://api.deepseek.com/anthropic`) and has the endpoint, the model name, the key (write-only, shown as `…a1b2`), the context budget, tool calling, image input, the prompt variant, the data level cap, the concurrency and runs per hour, the prices and a cache breakpoint switch. Two default slots (*simple*: review, expression, translation, sample data, data mapping, help; *complex*: edit, fix, template from a document) bind the operations to models and each of the nine operations can override the model, the reasoning, the round count, the output caps and the timeout, so a document conversion can run on a hosted DeepSeek while the small operations stay on a local Ollama. The page validates with the same rules as the server, tests a connection and the context length (the long probe asks before it spends money on a hosted model), imports the model from the environment variables and warns when a binding would leave an operation unusable. A change applies to the next run on this pod at once and on the other pods within 30 seconds; runs in flight finish with their snapshot. - **Behavior change** Template editor (AI assistant): the environment variables `EDITOR_AI_LOCAL_*`, `EDITOR_AI_MAX_ITERATIONS`, `EDITOR_AI_DOCUMENT_MAX_ITERATIONS`, `EDITOR_AI_RUN_TIMEOUT_SECONDS` are now only a **seed**: while the owner has saved nothing (the API returns revision 0, or the API is an older version without the endpoint), they build one model `local` bound to every operation, exactly as before; a saved configuration, even with no model, takes over completely. `EDITOR_AI_ENABLED` is now tri-state: not set means *on when the catalog has a usable model*, `false` switches the assistant off and hides the page (it had to be `true` before). `EDITOR_AI_ANTHROPIC_ENABLED`, `EDITOR_AI_USER_KEY_DATA_LEVEL`, `EDITOR_AI_COST_WARNING_USD` and `Assistant:Providers:*` are removed and ignored. The startup probe of the local model is gone (the editor has no service identity to read the configuration at startup); the same check is the *Otestovat kontext* button of the page. The deploy samples (`deploy/k8s/03-configmap.yaml`, `deploy/compose/.env.sample`, `docker-compose.sample.yml`) say so. - **Behavior change** Template editor (AI assistant): **the keys of the users and the model selector are removed.** Every model is managed and paid by the operator, so the panel no longer offers a model, an API key, the Anthropic models, the OpenAI-compatible presets, the per-run consent to sending data or the cost warning; each tab shows the line *Model: … (u provozovatele / hostovaná služba)* and where the template goes. The page *Nastavení* and the user key storage UI are deleted. The assistant is available to users with the role **Asistent**, **Admin** or **Owner** (an editor without the role who used their own key loses the assistant); an owner must also be Editor or Admin to reach the editor, like in the ReportServer UI. Before updating, an owner should create the models on the new page; the keys stored by users are not used any more. - ReportServer (migration `AddAssistantModelConfig`): the tables `AssistantModelConfigs` (one row: the revision as a concurrency token and the `jsonb` document of the models and bindings without secrets) and `AssistantModelSecrets` (the key encrypted by the editor with Data Protection bound to the model id, and its hint), the endpoints `GET/PUT /owner/assistant/models` (policy `InteractiveOwner`; `ETag` `"r{revision}"`, `If-Match` required: `428` without it, `412` with the current revision on a conflict, `400 ASSISTANT_CONFIG_INVALID` with the list of problems) and `GET /assistant/runtime-config` (the new policy `AssistantRuntime`: role Assistant, Admin or Owner, JWT only, and the claim `azp` = `template-editor`, so a JWT from a direct API login never receives the encrypted keys; `Cache-Control: no-store`, `304`). The validation `AssistantConfigRules` is shared with the editor page and refuses addresses with credentials and link-local or cloud metadata addresses (SSRF). `GET/PUT /me/assistant-settings` and `/me/assistant-keys` with their tables stay for one release (older editor pods during a rolling update) and will be removed with the stored user keys. The usage ledger records every managed model as `ProviderKind = local` with the model id as `ProviderId`, and the operation *data mapping* as `data`. - Template editor (AI assistant) fix: the task *template from a document* ended with *Vyčerpán počet kol* or lost the labels of a form. Measured against DeepSeek with a one-page PDF form: without reasoning the model spent 11 to 14 rounds on `get_node_schema` calls it did not need and bound the static labels to invented data fields of a `Table`; with low reasoning it finishes in 4 rounds and keeps the labels. Changes: the task now defaults to **low reasoning** (the other operations stay without reasoning) and to the output caps 32 000 / 48 000 tokens with reasoning per response and 60 000 / 120 000 per run (high reasoning exhausted 32 000); the `Full` prompt says that the schema digest is complete (`get_node_schema` is only for `page` and `watermark`); the rules for a document say that a static grid of labels and values is `Row` + `Box` + `Text` and that `Table` is only for rows from data; the check *server truncates the context* no longer counts the model's reasoning (DeepSeek drops it after the next user message, the reported input then falls by tens of thousands of tokens and a good run was marked as failed); fixing diagnostics is no longer capped at 6 rounds by the code (the binding sets it); the help chat and the one-shot functions take their round count and output cap from the binding. - Template editor (AI assistant): the task *template from a document* (the tab *Dokument*) has its own round limit, `EDITOR_AI_DOCUMENT_MAX_ITERATIONS` (`Assistant:DocumentMaxIterations`, default 30, 2 to 100). It shared `EDITOR_AI_MAX_ITERATIONS` (default 12, at most 30) with the edits, and converting a PDF with a complex form ended with *Vyčerpán počet kol* before the template was finished. Edits keep `EDITOR_AI_MAX_ITERATIONS`, fixing diagnostics keeps its 6 rounds. The repeated-failure guard still stops a model that sends the same failing call five times. - Template editor (AI assistant): documented that `EDITOR_AI_LOCAL_CONTEXT_TOKENS` is only the editor's budget (the wrap-up request at 75 % and the end of the run at 90 % of the context; nothing is sent to the model) and that a hosted DeepSeek can be set to `1000000`; the samples `deploy/k8s/03-configmap.yaml` and `deploy/compose/.env.sample` say so, and `docker-compose.sample.yml` passes the new variable. Celý seznam změn: CHANGELOG.md v balíčku a https://dev.azure.com/advsoft/Knihovny/_git/NetReporter?path=/src/NetReporter/CHANGELOG.md

Version Downloads Last updated
3.9.2 3 10/28/2026
3.9.1 1 10/27/2026
3.9.0 6 10/20/2026
3.8.1 6 10/19/2026
3.8.0 4 10/19/2026
3.7.0 4 10/19/2026
3.6.0 6 10/17/2026
3.5.1 62 10/15/2026
3.5.0 4 10/15/2026
3.4.2 5 10/15/2026
3.4.0 4 10/12/2026
3.3.0 5 10/11/2026
3.2.2 5 10/10/2026
3.2.1 4 10/10/2026
3.2.0 4 10/10/2026
3.1.1 4 10/09/2026
3.1.0 5 10/09/2026
3.0.1 8 10/08/2026
3.0.0 5 10/08/2026
2.2.1 5 10/05/2026
2.2.0 4 10/05/2026
2.1.0 9 10/04/2026
2.0.1 8 10/04/2026
2.0.0 5 10/03/2026
1.7.0 6 10/03/2026
1.6.0 5 10/02/2026
1.5.0 12 10/02/2026
1.4.0 6 10/01/2026
1.3.0 4 10/01/2026
1.2.0 5 10/01/2026
1.1.1 6 09/30/2026
1.1.0 8 09/30/2026
1.0.10 4 09/29/2026
1.0.9 4 09/29/2026
1.0.8 16 09/29/2026
1.0.7 115 09/24/2026
1.0.6 9 09/24/2026
1.0.5 7 09/24/2026
1.0.4 11 09/24/2026
1.0.3 8 09/24/2026
1.0.2 13 09/23/2026
1.0.0 7 09/23/2026
0.9.1 13 09/23/2026
0.9.0 87 09/14/2026
0.8.1 25 02/20/2026
0.8.1-preview.1 34 02/13/2026
0.7.1-preview.2 32 02/10/2026
0.7.1-preview.1 33 02/10/2026
0.7.0 30 02/10/2026
0.0.6 28 02/01/2026
0.0.5 19 02/01/2026
0.0.0-alpha.0.17 35 02/01/2026