Skip to content

Commit 2366f91

Browse files
committed
update: added skill files
1 parent bc5a09b commit 2366f91

8 files changed

Lines changed: 419 additions & 0 deletions

File tree

.cursor/rules/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Cursor (optional)
2+
3+
**Cursor** users: start at **[`AGENTS.md`](../../AGENTS.md)** at the repository root. All conventions live in **`skills/*/SKILL.md`**.
4+
5+
This folder only points contributors to **`AGENTS.md`** so editor-specific configuration does not duplicate the canonical documentation.

AGENTS.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Contentstack Utils .NET – Agent guide
2+
3+
**Universal entry point** for contributors and AI agents. Detailed conventions live in **`skills/*/SKILL.md`**.
4+
5+
## What this repo is
6+
7+
| Field | Detail |
8+
|-------|--------|
9+
| **Name:** | [contentstack-utils-dotnet](https://github.com/contentstack/contentstack-utils-dotnet) |
10+
| **Purpose:** | NuGet library **`contentstack.utils`**: JSON RTE → HTML rendering, embedded entry/asset rendering, GQL-oriented helpers, variant metadata (`GetVariantMetadataTags` / `GetVariantAliases`), Live Preview–style editable tags (`addEditableTags`). This is **not** a full Contentstack Delivery or Management HTTP SDK. |
11+
| **Out of scope (if any):** | No built-in HTTP client to Contentstack APIs; consumers use the Contentstack .NET Delivery SDK or other clients. This package focuses on parsing, rendering, and JSON helpers. |
12+
13+
## Tech stack (at a glance)
14+
15+
| Area | Details |
16+
|------|---------|
17+
| **Language** | C#; library multi-targets **netstandard2.0**, **net47**, **net472** ([`Contentstack.Utils/Contentstack.Utils.csproj`](Contentstack.Utils/Contentstack.Utils.csproj)); test project **net7.0** ([`Contentstack.Utils.Tests/Contentstack.Utils.Tests.csproj`](Contentstack.Utils.Tests/Contentstack.Utils.Tests.csproj)). |
18+
| **Build** | **dotnet** + solution [`Contentstack.Utils.sln`](Contentstack.Utils.sln); shared package version in [`Directory.Build.props`](Directory.Build.props) (e.g. `Version` **1.2.0**). |
19+
| **Tests** | **xUnit**, **Microsoft.NET.Test.Sdk**, **coverlet.collector**; JSON fixtures under [`Contentstack.Utils.Tests/Resources/`](Contentstack.Utils.Tests/Resources/). |
20+
| **Lint / coverage** | No repo-level `.editorconfig` or format workflow; tests use **Coverlet** (`XPlat code coverage`) via the shell scripts. |
21+
| **Key dependencies** | **HtmlAgilityPack**, **Newtonsoft.Json** in the library; tests reference compatible Newtonsoft.Json. |
22+
23+
## Commands (quick reference)
24+
25+
| Command type | Command |
26+
|--------------|---------|
27+
| **Build** | `dotnet build Contentstack.Utils.sln` (add `-c Release` for release configuration). |
28+
| **Test (quick, local)** | `dotnet test Contentstack.Utils.sln` — from repo root; no TRX/coverage (fastest feedback). |
29+
| **Test (CI parity)** | `sh ./Scripts/run-unit-test-case.sh` — clears `Contentstack.Utils.Tests/TestResults`, runs `dotnet test` on the test project with TRX logging and coverage. |
30+
| **Test + HTML coverage report** | `bash ./Scripts/run-test-case.sh` — tests the **solution**, then runs `python3 Scripts/generate_test_report.py` to emit HTML under `Contentstack.Utils.Tests/TestResults/Coverage-.../index.html`. |
31+
| **Pack (release)** | `dotnet pack -c Release -o out` (see [`.github/workflows/nuget-publish.yml`](.github/workflows/nuget-publish.yml)). |
32+
| **SCA (local parity with CI)** | `dotnet restore ./Contentstack.Utils.sln`, then from `Contentstack.Utils`: `snyk test` (requires Snyk CLI and `SNYK_TOKEN`; see [`sca-scan.yml`](.github/workflows/sca-scan.yml)). |
33+
34+
**CI:** [`.github/workflows/unit-test.yml`](.github/workflows/unit-test.yml) runs `run-unit-test-case.sh` on Windows for `pull_request` and `push`.
35+
36+
## CI and automation (workflows)
37+
38+
| Workflow | Trigger | Role |
39+
|----------|---------|------|
40+
| [`unit-test.yml`](.github/workflows/unit-test.yml) | `pull_request`, `push` | Windows: unit tests via `Scripts/run-unit-test-case.sh`. |
41+
| [`check-branch.yml`](.github/workflows/check-branch.yml) | `pull_request` | Merges into **`master`** are only allowed from **`staging`** (otherwise fails with a PR comment). |
42+
| [`nuget-publish.yml`](.github/workflows/nuget-publish.yml) | `release` (created) | `dotnet pack -c Release -o out`; push package to NuGet.org and GitHub Packages. |
43+
| [`sca-scan.yml`](.github/workflows/sca-scan.yml) | PR (opened, synchronize, reopened) | Ubuntu: `dotnet restore`, **Snyk** `snyk test` under `Contentstack.Utils`. |
44+
| [`policy-scan.yml`](.github/workflows/policy-scan.yml) | PR (public repos) | Requires `SECURITY.md` and a license file containing the current year. |
45+
| [`codeql-analysis.yml`](.github/workflows/codeql-analysis.yml) | `pull_request` (branches `*`) | CodeQL analysis for **csharp** (autobuild). |
46+
| [`issues-jira.yml`](.github/workflows/issues-jira.yml) | `issues` (opened) | Creates Jira tickets from GitHub issues (secrets). |
47+
48+
## Where the documentation lives: skills
49+
50+
| Skill | Path | What it covers |
51+
|-------|------|----------------|
52+
| Dev workflow | [`skills/dev-workflow/SKILL.md`](skills/dev-workflow/SKILL.md) | Branches, build/test/pack, CI, security workflows, CODEOWNERS, Talisman. |
53+
| Testing | [`skills/testing/SKILL.md`](skills/testing/SKILL.md) | xUnit layout, fixtures, mocks, coverage scripts, alignment with CI. |
54+
| Code review | [`skills/code-review/SKILL.md`](skills/code-review/SKILL.md) | PR expectations, checklist, security notes. |
55+
| Contentstack Utils (API) | [`skills/contentstack-utils/SKILL.md`](skills/contentstack-utils/SKILL.md) | Public API, package boundaries, `Utils` / GQL / variants, dependencies. |
56+
| C# style (this repo) | [`skills/csharp-style/SKILL.md`](skills/csharp-style/SKILL.md) | Folder layout, namespaces, naming consistency, TFMs. |
57+
58+
An index with “when to use” hints is in [`skills/README.md`](skills/README.md).
59+
60+
## Using Cursor (optional)
61+
62+
If you use **Cursor**, [`.cursor/rules/README.md`](.cursor/rules/README.md) only points to **[`AGENTS.md`](AGENTS.md)** at the repo root. All conventions live in **`skills/*/SKILL.md`**—same docs as for any other tool.

skills/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Skills – Contentstack Utils .NET
2+
3+
Source of truth for detailed guidance is **`skills/*/SKILL.md`**. Read **[`AGENTS.md`](../AGENTS.md)** first, then open the skill that matches your task.
4+
5+
## When to use which skill
6+
7+
| Skill folder | Use when |
8+
|--------------|----------|
9+
| [`dev-workflow`](dev-workflow/SKILL.md) | Branch rules, local build/pack, test scripts, CI workflows, versioning, security scans, CODEOWNERS, Talisman. |
10+
| [`testing`](testing/SKILL.md) | Writing or running xUnit tests, fixtures, mocks, coverage, matching CI behavior. |
11+
| [`code-review`](code-review/SKILL.md) | Preparing or reviewing PRs, release/docs expectations, dependency risk. |
12+
| [`contentstack-utils`](contentstack-utils/SKILL.md) | Public API (`Utils`, GQL helpers, variants, `Options`), NuGet package boundaries, converters, dependencies. |
13+
| [`csharp-style`](csharp-style/SKILL.md) | Where to put new types, namespaces, naming consistency, multi-target framework constraints. |
14+
15+
Each folder contains **`SKILL.md`** with YAML frontmatter (`name`, `description`).

skills/code-review/SKILL.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
name: code-review
3+
description: Use for PR expectations, review checklist, docs/changelog, and security considerations in contentstack-utils-dotnet.
4+
---
5+
6+
# Code review – Contentstack Utils .NET
7+
8+
## When to use
9+
10+
- Opening or reviewing a pull request.
11+
- Deciding whether README/CHANGELOG updates or extra tests are required.
12+
- Assessing impact of new dependencies or public API changes.
13+
14+
## Instructions
15+
16+
### Branch and ownership
17+
18+
- Merges into **`master`** are expected from **`staging`** only (see [`check-branch.yml`](../../.github/workflows/check-branch.yml)). Align your PR base/head with team process.
19+
- [`CODEOWNERS`](../../CODEOWNERS) may request reviews from **`@contentstack/devex-pr-reviewers`** and security admins for workflow or `.snyk` changes.
20+
21+
### Checklist
22+
23+
- **Behavior**: New or changed logic in [`Contentstack.Utils`](../../Contentstack.Utils/) should have **xUnit** coverage in [`Contentstack.Utils.Tests`](../../Contentstack.Utils.Tests/) unless truly non-functional (e.g. comment-only).
24+
- **Public API**: User-visible changes should update [`README.md`](../../README.md) and [`CHANGELOG.md`](../../CHANGELOG.md) as appropriate.
25+
- **Multi-targeting**: The library builds **netstandard2.0**, **net47**, **net472**. After API or dependency changes, verify `dotnet build` succeeds for all target frameworks (or rely on CI).
26+
- **Dependencies**: New or upgraded NuGet packages affect **Snyk** ([`sca-scan.yml`](../../.github/workflows/sca-scan.yml)) and **CodeQL** ([`codeql-analysis.yml`](../../.github/workflows/codeql-analysis.yml)). Ensure licenses and advisories are acceptable.
27+
- **Secrets**: Never commit API keys, tokens, or connection strings. CI uses GitHub secrets only.
28+
29+
### Severity labels (optional)
30+
31+
Teams may use **Blocker** (must fix before merge), **Major** (should fix or track), **Minor** (nit / follow-up)—keep comments actionable.
32+
33+
## References
34+
35+
- [`skills/dev-workflow/SKILL.md`](../dev-workflow/SKILL.md) — CI and branch rules.
36+
- [`skills/testing/SKILL.md`](../testing/SKILL.md) — how to add tests.
37+
- [`skills/contentstack-utils/SKILL.md`](../contentstack-utils/SKILL.md) — API surface and boundaries.

skills/contentstack-utils/SKILL.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
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

Comments
 (0)