|
| 1 | +--- |
| 2 | +name: contentstack-utils |
| 3 | +description: Use for the contentstack.utils NuGet API—Utils, GQL, Options, variants, converters, code flows, and integration boundaries. |
| 4 | +--- |
| 5 | + |
| 6 | +# Contentstack Utils (API) – Contentstack Utils .NET |
| 7 | + |
| 8 | +## When to use |
| 9 | + |
| 10 | +- Implementing or extending JSON RTE → HTML rendering or embedded content behavior. |
| 11 | +- Adding node types, converters, or variant/metadata helpers. |
| 12 | +- Choosing whether logic belongs in this package vs the Contentstack .NET Delivery SDK. |
| 13 | + |
| 14 | +## Instructions |
| 15 | + |
| 16 | +### Package and namespaces |
| 17 | + |
| 18 | +- **NuGet package id:** `contentstack.utils` ([`Contentstack.Utils.csproj`](../../Contentstack.Utils/Contentstack.Utils.csproj)). |
| 19 | +- **Root namespace:** `Contentstack.Utils`. Sub-namespaces follow folders: **`Contentstack.Utils.Models`**, **`Contentstack.Utils.Interfaces`**, **`Contentstack.Utils.Enums`**, **`Contentstack.Utils.Extensions`**, **`Contentstack.Utils.Converters`**. |
| 20 | + |
| 21 | +### Models (library) |
| 22 | + |
| 23 | +Source files under [`Contentstack.Utils/Models/`](../../Contentstack.Utils/Models/): |
| 24 | + |
| 25 | +- [`JsonRTENode.cs`](../../Contentstack.Utils/Models/JsonRTENode.cs), [`JsonRTENodes.cs`](../../Contentstack.Utils/Models/JsonRTENodes.cs) — GQL-shaped RTE wrappers. |
| 26 | +- [`Metadata.cs`](../../Contentstack.Utils/Models/Metadata.cs) — embed metadata; implicit conversions from **HtmlAgilityPack** `HtmlNode` and RTE `Node`. |
| 27 | +- [`Node.cs`](../../Contentstack.Utils/Models/Node.cs), [`TextNode.cs`](../../Contentstack.Utils/Models/TextNode.cs) — RTE tree nodes. |
| 28 | +- [`Options.cs`](../../Contentstack.Utils/Models/Options.cs) — default rendering; subclass for custom HTML. |
| 29 | + |
| 30 | +### Interfaces (embedding and rendering) |
| 31 | + |
| 32 | +- **`IEntryEmbedable`** — [`IEntryEmbedable.cs`](../../Contentstack.Utils/Interfaces/IEntryEmbedable.cs): `embeddedItems` map for resolving references. |
| 33 | +- **`IEmbeddedObject`**, **`IEmbeddedEntry`**, **`EditableEntry`**, **`IEmbeddedAsset`** — [`IEmbeddedObject.cs`](../../Contentstack.Utils/Interfaces/IEmbeddedObject.cs). |
| 34 | +- **`IRenderable`**, **`NodeChildrenCallBack`** — [`IOptions.cs`](../../Contentstack.Utils/Interfaces/IOptions.cs). |
| 35 | +- **`IEdges<T>`** — [`IEdges.cs`](../../Contentstack.Utils/Interfaces/IEdges.cs) (GQL edge list). Spelling **`IEntryEmbedable`** matches the existing public API. |
| 36 | + |
| 37 | +### Core type: `Contentstack.Utils.Utils` |
| 38 | + |
| 39 | +[`Utils.cs`](../../Contentstack.Utils/Utils.cs) exposes static helpers including: |
| 40 | + |
| 41 | +- **`JsonToHtml`**: Overloads for `Node`, `List<Node>` — see [Code flows](#code-flows). |
| 42 | +- **`RenderContent`**: Overloads for `string` and `List<string>` HTML — see [Code flows](#code-flows). |
| 43 | +- **`Utils.GQL`**: `JsonToHtml` for `JsonRTENode<T>` / `JsonRTENodes<T>` where `T : IEmbeddedObject` — see [Code flows](#code-flows). |
| 44 | +- **`addEditableTags`**: Adds Live Preview–style **`data-cslp`** (or object-shaped) metadata on **`EditableEntry`** graphs for a given content type and locale (see [`Utils.addEditableTags`](../../Contentstack.Utils/Utils.cs)). |
| 45 | +- **Variants / metadata:** |
| 46 | + - **`GetVariantAliases`** — reads each entry’s `publish_details` → `variants` object and collects non-empty **`alias`** values per variant entry (implementation: **`ExtractVariantAliasesFromEntry`** in [`Utils.cs`](../../Contentstack.Utils/Utils.cs), approx. lines 401–426). |
| 47 | + - **`GetVariantMetadataTags`** — wraps alias data into a **`JObject`** with key **`data-csvariants`** (compact JSON string). |
| 48 | + - **`GetDataCsvariantsAttribute`** — **Obsolete**; use **`GetVariantMetadataTags`** instead (same behavior; see XML comments on [`Utils`](../../Contentstack.Utils/Utils.cs)). |
| 49 | + |
| 50 | +### Rendering hooks (`Options` / `IRenderable`) |
| 51 | + |
| 52 | +Subclass or configure **[`Options.cs`](../../Contentstack.Utils/Models/Options.cs)** (`Options : IRenderable`) to override: |
| 53 | + |
| 54 | +- **`RenderOption(IEmbeddedObject, Metadata)`** |
| 55 | +- **`RenderNode(string nodeType, Node, NodeChildrenCallBack)`** |
| 56 | +- **`RenderMark(MarkType, string text, string className, string Id)`** |
| 57 | + |
| 58 | +### JSON serialization |
| 59 | + |
| 60 | +- [`NodeJsonConverter.cs`](../../Contentstack.Utils/Converters/NodeJsonConverter.cs) and [`RTEJsonConverter.cs`](../../Contentstack.Utils/Converters/RTEJsonConverter.cs) integrate with **Newtonsoft.Json** for RTE node graphs. New node shapes should follow the same converter and model patterns. |
| 61 | + |
| 62 | +### Dependencies |
| 63 | + |
| 64 | +- **HtmlAgilityPack**: HTML load, query, and embedded-object replacement for `RenderContent`. |
| 65 | +- **Newtonsoft.Json**: JSON models (`JObject`, `JArray`, converters). Upgrades should stay compatible with consumers and pass Snyk/CI. |
| 66 | + |
| 67 | +### Out of scope |
| 68 | + |
| 69 | +- This library **does not** ship an HTTP client for Contentstack Delivery or Management APIs. Apps typically use **Contentstack .NET SDK** (or REST) to fetch entries, then use **Utils** to render RTE HTML or process JSON. Keep HTTP, auth, and caching in application or SDK layers. |
| 70 | + |
| 71 | +### Authoritative source |
| 72 | + |
| 73 | +- **Signatures and full behavior** live in C# under [`Contentstack.Utils/`](../../Contentstack.Utils/). This skill summarizes; when in doubt, read the implementation (especially [`Utils.cs`](../../Contentstack.Utils/Utils.cs)). |
| 74 | + |
| 75 | +## Code flows |
| 76 | + |
| 77 | +Stepwise behavior with pointers into [`Utils.cs`](../../Contentstack.Utils/Utils.cs). Line numbers are approximate; verify against the file after large edits. |
| 78 | + |
| 79 | +### RTE JSON → HTML (`JsonToHtml`) |
| 80 | + |
| 81 | +1. **`JsonToHtml(Node, Options)`** (approx. lines 97–113) builds a **`referenceToHtml`** delegate: for **`reference`** nodes it calls **`findEmbeddedObject`** using **`options.entry.embeddedItems`**, then **`options.RenderOption`** when a match exists. |
| 82 | +2. **`nodeChildrenToHtml`** (lines 115–118) concatenates HTML for each child via **`nodeToHtml`**. |
| 83 | +3. **`nodeToHtml`** (lines 121–131): **`type == "text"`** → **`textToHtml`** (lines 133+), which applies marks in order via **`RenderMark`**; **`type == "reference"`** → **`referenceToHtml`**; **otherwise** → **`options.RenderNode`** with a callback that recurses into **`nodeChildrenToHtml`**. |
| 84 | + |
| 85 | +### GQL RTE (`Utils.GQL.JsonToHtml`) |
| 86 | + |
| 87 | +- Reuses **`nodeChildrenToHtml`** / **`nodeToHtml`**. **`referenceToHtml`** is built by **`GQL.refernceToHtml`** (lines 32–50): find **`IEdges<T>`** where **`edge.Node`** matches **`Metadata.ItemUid`** and **`ContentTypeUid`**, then **`options.RenderOption(edge.Node, metadata)`**. Entry points: **`GQL.JsonToHtml(JsonRTENode<T>, ...)`** (lines 17–20) and list overload (lines 22–30). |
| 88 | + |
| 89 | +### HTML string with embeds (`RenderContent`) |
| 90 | + |
| 91 | +1. **`RenderContent(string, Options)`** (lines 64–82): **`HtmlDocument.LoadHtml`**, then **`FindEmbeddedObject`** extension on [`HtmlDocumentExtension.cs`](../../Contentstack.Utils/Extensions/HtmlDocumentExtension.cs) (selects nodes with class **`embedded-asset`** or **`embedded-entry`**). |
| 92 | +2. Each **HtmlNode** is passed to the callback; **`Metadata`** is produced via **implicit conversion** from **`HtmlNode`** ([`Metadata.cs`](../../Contentstack.Utils/Models/Metadata.cs), lines 46–68). |
| 93 | +3. **`findEmbeddedObject`** resolves **`IEmbeddedObject`** from **`options.entry.embeddedItems`**; result string replaces **`metadata.OuterHTML`** in the accumulated HTML. |
| 94 | + |
| 95 | +### Variant metadata (`GetVariantAliases` / `GetVariantMetadataTags`) |
| 96 | + |
| 97 | +- **`ExtractVariantAliasesFromEntry`**: requires **`entry["publish_details"]`** as **`JObject`**, then **`publish_details["variants"]`** as **`JObject`**; for each property, reads **`alias`** from the nested object when present (lines 401–426). |
| 98 | +- **`GetVariantMetadataTags`** builds **`{ "data-csvariants": <compact JSON string> }`** from **`GetVariantAliases`** results (lines 365–380). |
| 99 | + |
| 100 | +### Diagrams (high level) |
| 101 | + |
| 102 | +```mermaid |
| 103 | +flowchart TD |
| 104 | + rteEntry[JsonToHtml_Node_or_List] |
| 105 | + rteEntry --> nodeChildren[nodeChildrenToHtml] |
| 106 | + nodeChildren --> nodeTo[nodeToHtml] |
| 107 | + nodeTo -->|text| textTo[textToHtml_RenderMark_chain] |
| 108 | + nodeTo -->|reference| refDel[referenceToHtml_findEmbeddedObject_RenderOption] |
| 109 | + nodeTo -->|other_types| renderNode[RenderNode_recursive_callback] |
| 110 | +``` |
| 111 | + |
| 112 | +```mermaid |
| 113 | +flowchart TD |
| 114 | + htmlEntry[RenderContent_string] |
| 115 | + htmlEntry --> load[HtmlDocument_LoadHtml] |
| 116 | + load --> find[FindEmbeddedObject_extension] |
| 117 | + find --> meta[HtmlNode_to_Metadata_implicit] |
| 118 | + meta --> resolve[findEmbeddedObject_embeddedItems] |
| 119 | + resolve --> replace[Replace_OuterHTML_with_RenderOption] |
| 120 | +``` |
| 121 | + |
| 122 | +## References |
| 123 | + |
| 124 | +- [`skills/csharp-style/SKILL.md`](../csharp-style/SKILL.md) — layout and naming in this repo. |
| 125 | +- [`skills/testing/SKILL.md`](../testing/SKILL.md) — how to test API changes. |
| 126 | +- [Product README](../../README.md) — install and usage examples. |
| 127 | +- [Contentstack .NET Utils on NuGet](https://www.nuget.org/packages/contentstack.utils) — package listing (verify version). |
0 commit comments