NETReporter 3.2.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 (ToDo #139), off by default (`EDITOR_AI_ENABLED=true`). A side panel (Ctrl+I, the *Asistent* button, the command palette) changes the template from a description in plain words ("add a column Sleva after Cena", "change the primary color") and a button *Opravit s AI* in the diagnostics panel repairs errors (safe quick fixes run locally first, the model gets only the errors that remain). The model works on a private copy through tools (`get_template`, `get_template_outline`, `get_template_part`, `edit_template` with the operations `set`, `replace`, `insert`, `append`, `remove`, `move`, `replace_template`, `validate_template`, `get_node_schema`), checks the result with the same validation as the editor and the editor writes it as one undo step. Editing is locked while a run is in progress (read-only JSON, a bar with *Zrušit*). The panel shows progress, the changed places, token usage and an estimated cost. Only the template without embedded binary data goes to the model; test data, assets and uploaded documents are not sent. - AI assistant models: a local OpenAI-compatible model of the operator (`EDITOR_AI_LOCAL_URL`, `EDITOR_AI_LOCAL_MODEL`, `EDITOR_AI_LOCAL_CONTEXT_TOKENS`, only for the new role Assistant and for administrators) and models with the user's own key: Anthropic (Claude Sonnet 5.5 by default, Opus 5.5, Haiku 5.5) and OpenAI-compatible presets of the administrator (`Assistant:Providers`). The user never enters an endpoint address. The key is encrypted by the editor with Data Protection (bound to the user and the provider) and ReportServer stores only the opaque value. All options are documented in `doc/netreporter-knihovna/dev/19-ai-asistent.md` (the section `Assistant` and the `EDITOR_AI_*` variables, `deploy/k8s/03-configmap.yaml`, `deploy/compose/.env.sample`). - Ollama as the local model: the context comes from `PARAMETER num_ctx` in the Modelfile of the model (not from an environment variable, and `/v1` cannot set it); a prompt longer than the context is silently truncated. The administrator guide describes the check. - ReportServer: user settings of the assistant and the encrypted API keys (migration `AddUserAssistant`: tables `UserAssistantSettings` and `UserAssistantKeys`, at most 20 keys per user), endpoints `GET/PUT /me/assistant-settings`, `GET /me/assistant-keys`, `GET/PUT/DELETE /me/assistant-keys/{providerId}`, and the matching methods of `ContentApiClient`. Deleting a user deletes the settings and keys. - Accounts: the new role **Assistant** (migration `AddAssistantRole`, shown as *Asistent (lokální AI)* on the page Users) and the policy `AssistantLocalAccess`. A role change takes effect after the next sign-in. - AI assistant: template review. The button *Zkontrolovat šablonu* (and the command *Zkontrolovat šablonu (AI)*) sends the template to the model, which returns findings about business document essentials, accessibility (missing `alt`, contrast, tiny text), wording and consistency; it does not change the template. Each finding has *Ukázat* (selects the node) and *Opravit* (runs an edit with the finding as the instruction). The review is one call without tools, so it needs only a context of 32k tokens. The panel stays mounted when it is closed, so the instruction, the result card and the findings survive Ctrl+I. - AI assistant: sample data from a description. The new tab *Data* creates realistic data for the preview from a description ("an invoice with 4 to 6 items, one foreign customer, one item with a discount"), with consistent amounts and dates and valid company IDs and IBANs, all fictitious. The model gets only the description and the structure of the data fields the template reads (the data contract skeleton with illustrative values), never the template or the user's data. The answer is merged into the skeleton, so the template always decides the field names and types; the result becomes the custom JSON of the preview after confirmation. - AI assistant: translation of the static texts of a template. The new tab *Překlad* translates labels, headings, table headers and static cell texts, `alt`, chart and payment QR captions, the page number format and the watermark text into a chosen language. Only the texts are sent (each wording once), never the template or data; bindings and expressions stay untouched and a translation that changes a `{{…}}` placeholder is discarded. The proposed pairs are shown for approval and the selected ones are written as one undo step. Until the template has language variants (ToDo #134) the result is a copy of the template in another language, so save it under a new name. - AI assistant: expression from a description. The new tab *Výraz* turns a description in plain words ("discount in percent, empty when zero", "total in words") into a text value with a binding or a C# expression for the selected node. The model gets only the description and the names and kinds of the variables and data fields in scope (shown under *Co se pošle modelu*), never the template or values. The expression is not compiled or run while the assistant writes it: the editor only checks the syntax with Roslyn and rejects dangerous constructs (files, network, processes, reflection); the user copies the text or inserts it into the selected Text node (one undo step) and sees the result in the preview. - AI assistant: help over the documentation. The new tab *Nápověda* in the panel answers questions about the template format ("how do I make zebra rows in a table?") from the documentation chapters of the template format, validation, styles, bindings, charts and icons, which the model searches and reads with the tools `search_docs` and `read_docs`; the answer lists the sections it read and *Udělat to v šabloně* turns the question into an edit instruction. The template and its data are never sent. The editor now bundles the same documentation files as the API and the MCP server (`src/Documentation.props`); code blocks in answers render as blocks. - AI assistant: token usage per user and operation, the basis for future billing. After every operation the editor writes one record (`POST /me/assistant-usage`, idempotent by a client-generated `Id`): user, time, operation (`edit`, `fix`, `review`, `help`, `expression`, `translate`, `data`, `document`), provider kind and id, model, input tokens (with the part read from cache), output tokens, model calls, duration, outcome (`completed`, `failed`, `cancelled`, `timeout`, `refused`, `limit`) and an estimated cost in USD at the price list of that time. Failed and cancelled operations are recorded too, because tokens are paid anyway; a failed write never fails the operation (retries, an in-memory queue, the log as a last resort). Records are append-only and survive deleting the account. ReportServer: table `AssistantUsage` (migration `AddAssistantUsage`), `GET /me/assistant-usage` (own totals) and `GET /admin/assistant-usage` (all users, filter `userId`, grouping by `user`, `operation`, `provider`, `model`, `day`). `ContentApiClient` has `RecordAssistantUsageAsync` and `GetAssistantUsageAsync`. - AI assistant: template from a document. The new tab *Dokument* builds a new template from a PDF (rendered page by page with PDFium, new dependency `PDFtoImage`) or up to 5 page images (PNG, JPEG, WebP) of an invoice, order or form: layout, tables and styles, with the values that change turned into bindings. The images are first resized to 1600 px on the longest side, re-encoded as lossy WebP and stripped of metadata (`AssistantImagePreprocessor`, new dependency `SkiaSharp` with the dependency-free Linux native assets), which saves tokens and transfer. The document is data of level 2: a model with the user's key needs a confirmation before every run, and `EDITOR_AI_LOCAL_DATA_LEVEL=1` or `EDITOR_AI_USER_KEY_DATA_LEVEL=1` turns it off. The run starts from a blank A4 template (not from the demo template of the editor) and may write up to 32 000 tokens per answer, because the whole template comes in one tool call. The result replaces the template in the editor as a new unsaved one (one Undo step). `tools/assistant-eval` has `--document` (renders a sample template to an image, sends it and saves the result). - Template editor: `TemplateEditGuard` knows the change kind `Assistant` (a node may disappear, new errors degrade the result like in other edits). - Documentation: `doc/netreporter-knihovna/user/asistent-v-editoru.md` (user guide) and `doc/netreporter-knihovna/dev/19-ai-asistent.md` (deployment, architecture, evaluation with `tools/assistant-eval`). - AI assistant: trial rendering. The assistant gets the tool `render_check` (renders the working copy with generated sample data and reports the page count and the render diagnostics, for example a broken layout, an unresolved binding or a document that never ends) and, for models with image input, `render_page_image` (a rendered page as an image, at most 4 per run) to compare a result with the document in the template-from-a-document task. The rendering is closed (no files, no network, only embedded `data:` images; assets and embedded binaries show as grey boxes) and C# expressions `{{# … }}` are not evaluated, only counted, because they are code written by a model that also reads untrusted text. In the evaluation (17 scenarios on DeepSeek) the success stays 17/17 at about one extra call per run. - AI assistant: `get_data_shape` gives the model the structure of the data the preview currently uses (field paths and value kinds, never values), so that new columns and texts bind to existing fields instead of invented names. Not offered without preview data and not for the diagnostics repair. - AI assistant: the button *Vytvořit podle dokumentu* in the gallery dialog opens the assistant on the tab *Dokument*. - AI assistant: a one-time check of the local model after the editor starts (`AssistantLocalModelProbe`): a prompt of about 50k tokens with a code at the beginning proves that the server does not silently truncate the context (Ollama with a small `num_ctx`). The result (available, truncates the context, unavailable) is logged and shown in the settings dialog. - AI assistant: a warning in the result card when a run costs more than `EDITOR_AI_COST_WARNING_USD` (default 1). Examples of the OpenAI-compatible presets (`Assistant__Providers__0__*`) and the new variable in `deploy/k8s/03-configmap.yaml` and `deploy/compose/`. - AI assistant evaluation: `tools/assistant-eval --render` gives a run the rendering tools. - AI assistant: the library of blocks and themes. The tools `list_snippets` and `insert_snippet` insert a ready-made block (address block, invoice header, page footer, payment QR, VAT recap, the user's own and public ones) into the working copy and add the styles and palette colors it needs exactly like the editor does (the template's own style or color wins); `list_themes` and `apply_theme` restyle the whole template like the theme menu (palette, fonts, sizes and colors of styles, borders and spacing stay). Both are one atomic change of the working copy and are not offered in the diagnostics repair. Evaluation: 21/21 on DeepSeek with `--library --render`. - AI assistant: trial rendering over the user's own preview data (data level 2). When the preview uses a custom JSON (not a shipped sample set), `render_check` and `render_page_image` can render over it and catch what generated data cannot show (a text too long for its box, a table with many rows, the page count). It works only if the administrator allows it (`EDITOR_AI_LOCAL_DATA_LEVEL` and `EDITOR_AI_USER_KEY_DATA_LEVEL` above 1); with a local model it runs by itself, with a model with the user's own key only after the user ticks *Vykreslovat nad mými daty náhledu* for that run. The result card says when the rendering used the user's data. Without it the data are generated as before and no value leaves the process. - AI assistant: mapping of the user's data to a template (the opposite direction of the tab *Data*). The user pastes a sample document (JSON or XML such as ISDOC, up to 1 MB); the model gets the list of the fields the template reads and an overview of the sample (paths, kinds, one example value per field), never the template, and proposes pairs *template field → data field*. Code validates the proposal (both paths exist, kinds and arrays match, items belong to the mapped array, the path can be written in a binding) and adds the missing array pairs; the user approves the pairs and the editor rewrites the paths in the template bindings in one undo step, optionally setting the sample as the preview data. C# expressions are reported, not rewritten. The sample is user data (data level 2), so the same cap and confirmation as for the document tab apply. - Library: the new public `NetReporter.Template.DataContract.TemplateBindingRewriter` rewrites the data paths in the bindings of a template according to a map from contract paths to new paths (`$.Items[*].Name` → `$.lines[*].title`). It knows the scopes of `repeat`, `rows.as`, `Chart.as` and ISDOC like the data contract analyzer (`item.Name` becomes `item.title`, `totalSums.qty` follows the new field name, a value outside the array becomes an absolute path), keeps formats and `a ?? b`, rewrites sources, sort keys and conditions, and reports the C# expressions it cannot rewrite safely. `IsBindablePath` tells whether a path can be written in a binding. - AI assistant: the template from a document no longer copies what identifies the issuer or the customer (a web address, an e-mail, a phone number, a bank account, a company ID, a company name and address) as static text; the model binds them to fields. - AI assistant: large templates. The outline the model gets (`get_template_outline` and the first message of a long template) now shows the whole document at a coarser level (the deepest level that fits, with `(+N nested)` after a node) and shortens a long list of siblings to its beginning and end with a marker in the middle, instead of cutting after the first 400 nodes, so the model can find the end of a long document. A template goes whole into the first message of an edit only up to about 12k estimated tokens (about 36 KB); a larger one is read by the model in parts. Measured with an inflated template: the local model went from 2/6 to 5/6, DeepSeek 6/6. - AI assistant evaluation: `--library` (library scenarios `lib-*`), `--map template sample-file` (mapping of the user's data, samples in `tools/assistant-eval/samples/`) and `--long tokens` (the sample template inflated to a given size with three edits aimed at the last block; ToDo #175). 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