Skip to content
Merged
5 changes: 5 additions & 0 deletions .cursor/rules/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Cursor (optional)

**Cursor** users: start at the repo root **[`AGENTS.md`](../../AGENTS.md)**. All conventions live in **`skills/*/SKILL.md`** (universal for any editor or tool).

This folder only points contributors here so nothing editor-specific duplicates the canonical docs.
53 changes: 53 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Contentstack Utils Swift – Agent guide

**Universal entry point** for anyone automating or assisting work in this repo—AI agents (Cursor, Copilot, CLI tools), reviewers, and contributors. Conventions and detailed guidance live in **`skills/*/SKILL.md`**, not in editor-specific config, so the same instructions apply whether or not you use Cursor.

## What this repo is

- **Name:** [contentstack-utils-swift](https://github.com/contentstack/contentstack-utils-swift)
- **Purpose:** Swift library that renders Contentstack **RTE** (rich text) and related JSON to HTML, with hooks for embedded entries/assets and helpers for **variant** metadata.
- **Out of scope:** This package does **not** ship HTTP clients or stack credentials. Apps fetch content with the [Content Delivery / Swift SDK](https://www.contentstack.com/docs/developers/sdks/content-delivery-sdk/swift) (or other clients), then pass strings or dictionaries into ContentstackUtils.

## Tech stack (at a glance)

| Area | Details |
|------|---------|
| Language | Swift 5 (`Package.swift`, podspec) |
| Build | SwiftPM; CocoaPods `ContentstackUtils.podspec`; Xcode `ContentstackUtils.xcodeproj` |
| Tests | XCTest → `Tests/ContentstackUtilsTests/` |
| Lint / coverage | SwiftLint `.swiftlint.yml`; Slather `.slather.yml` (scheme `ContentstackUtils-Package`) |
| HTML/XML | Vendored Kanna `Sources/Kanna/`; libxml2 via `Modules/` |

## Commands (quick reference)

```bash
swift build && swift test
swiftlint
```

CI-style Xcode (see `.github/workflows/ci.yml`):

```bash
xcodebuild -project "ContentstackUtils.xcodeproj" -scheme "ContentstackUtils-Package" -destination "OS=13.4.1,name=iPhone 11 Pro" test
```

CocoaPods: `pod 'ContentstackUtils', '~> …'` — see `README.md` and `ContentstackUtils.podspec` for the current version.

## Where the real documentation lives: skills

Read these **`SKILL.md` files** for full conventions—**this is the source of truth** for implementation and review:

| Skill | Path | What it covers |
|-------|------|----------------|
| **Development workflow** | [`skills/dev-workflow/SKILL.md`](skills/dev-workflow/SKILL.md) | Branches, CI, build/test/lint commands, PR expectations, TDD note, Slather |
| **Contentstack Utils (SDK)** | [`skills/contentstack-utils/SKILL.md`](skills/contentstack-utils/SKILL.md) | Public API: `ContentstackUtils`, `Option` / `Renderable`, RTE/JSON, GQL, variants, errors, semver, no network layer |
| **Swift style & repo layout** | [`skills/swift-style/SKILL.md`](skills/swift-style/SKILL.md) | SwiftLint, `Sources/` layout, Kanna/libxml2, platforms, naming, access control |
| **Testing** | [`skills/testing/SKILL.md`](skills/testing/SKILL.md) | XCTest layout, mocks, fixtures, SwiftLint/Slather, offline tests, `XCTestManifests` |
| **Code review** | [`skills/code-review/SKILL.md`](skills/code-review/SKILL.md) | PR checklist (API, errors, deps/SCA, tests, vendored code), Blocker/Major/Minor |
| **Framework / build** | [`skills/framework/SKILL.md`](skills/framework/SKILL.md) | SPM targets, `Modules/` libxml2, Kanna vendoring, deployment targets, podspec, CI `xcodebuild` |

An index with short “when to use” hints is in [`skills/README.md`](skills/README.md).

## Using Cursor

If you use **Cursor**, [`.cursor/rules/README.md`](.cursor/rules/README.md) only points to **`AGENTS.md`**—same source of truth as everyone else; no separate `.mdc` rule files.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

All notable changes to this project will be documented in this file.

## [Unreleased]

### Documentation

- 2026-04-02: Added CocoaPods deprecation guidance for **new** projects—**SPM** is recommended for ContentstackUtils; clarified companion role vs the core Swift CDA SDK. Updated README (Important section), added root **DEPRECATION.md** (customer-facing only), added **Docs/overview.md** banner with link to `DEPRECATION.md`.

## [1.5.0] - 2026-03-31

- **`getVariantMetadataTags`** is the canonical API for `data-csvariants`; **`getDataCsvariantsAttribute`** is deprecated (delegates to it until removed in a major release).
Expand Down
33 changes: 33 additions & 0 deletions DEPRECATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# CocoaPods distribution for ContentstackUtils

This notice applies to developers who integrate **ContentstackUtils** using **CocoaPods** (`ContentstackUtils` pod).

## What this package is

**ContentstackUtils** is a **companion library** for the [Contentstack Swift SDK](https://github.com/contentstack/contentstack-swift). It provides utilities (for example JSON RTE rendering and embedded items) for use **alongside** the Swift Content Delivery API (CDA) client. It is **not** a replacement for the core CDA SDK—you still use the [Swift SDK](https://github.com/contentstack/contentstack-swift) for stack, queries, and delivery.

## What we recommend for new work

For **new** projects and new integrations, we recommend adding **ContentstackUtils** with **Swift Package Manager (SPM)** from this repository, and using the **Swift SDK** via SPM as well. That keeps your dependency graph aligned with current tooling and our primary distribution path.

- **Contentstack Swift SDK (source):** [github.com/contentstack/contentstack-swift](https://github.com/contentstack/contentstack-swift)
- **Swift SDK on Swift Package Index:** [swiftpackageindex.com/contentstack/contentstack-swift](https://swiftpackageindex.com/contentstack/contentstack-swift)
- **Swift CDA reference:** [Content Delivery SDK — Swift reference](https://www.contentstack.com/docs/developers/sdks/content-delivery-sdk/swift/reference)

**Version alignment:** Use ContentstackUtils versions that match the guidance in this repository’s README (keep Utils in step with the Swift SDK version you use).

We are **deprecating CocoaPods as the recommended way** to add ContentstackUtils for **new** work. CocoaPods remains part of the broader ecosystem, but our product direction favors **SPM** for Apple platforms. For background on how the CocoaPods ecosystem is evolving, see [CocoaPods Specs Repo](https://blog.cocoapods.org/CocoaPods-Specs-Repo/).

## If you already use CocoaPods

**Existing** apps that already depend on the `ContentstackUtils` pod can continue to ship as they do today. You are not required to migrate on a fixed deadline to keep using what you have. When you are ready to standardize on SPM or refresh dependencies, plan a migration at your own pace.

## Maintenance and features

We continue to maintain ContentstackUtils for supported integration paths. **New** feature work and documentation will emphasize **SPM** and the Swift SDK. CocoaPods-based setups may receive necessary maintenance but are not our focus for new capabilities.

## Support

Questions or help with your integration: [support@contentstack.io](mailto:support@contentstack.io).

See also the **Important** section at the top of the [README](./README.md).
7 changes: 7 additions & 0 deletions Docs/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# ContentstackUtils — overview

## Important

**ContentstackUtils** is a **companion** to the [Contentstack Swift SDK](https://github.com/contentstack/contentstack-swift), not the core CDA client. Prefer **Swift Package Manager** for new work; the **CocoaPods** pod is **not** recommended for new projects. Existing CocoaPods users can keep shipping until they choose to migrate.

Full details: **[DEPRECATION.md](../DEPRECATION.md)** · [README](../README.md) · [Swift SDK reference](https://www.contentstack.com/docs/developers/sdks/content-delivery-sdk/swift/reference)
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
# ![Contentstack](https://www.contentstack.com/docs/static/images/contentstack.png)

# Contentstack Swift SDK
# ContentstackUtils

![ContentstackUtils CI](https://github.com/contentstack/contentstack-utils-swift/workflows/ContentstackUtils%20CI/badge.svg)

## Important

**ContentstackUtils** is a **companion** library for the [Contentstack Swift SDK](https://github.com/contentstack/contentstack-swift)—utilities for JSON RTE, embedded items, and related helpers; it is **not** the core Content Delivery API (CDA) client. Add **ContentstackUtils** with Swift Package Manager from [`contentstack/contentstack-utils-swift`](https://github.com/contentstack/contentstack-utils-swift), add the [Swift SDK](https://github.com/contentstack/contentstack-swift) the same way (see also [Swift Package Index](https://swiftpackageindex.com/contentstack/contentstack-swift)), and **align versions** between them as described in this README.

We are **deprecating CocoaPods** (`pod 'ContentstackUtils'`) as the recommended integration path for **new** projects—prefer SPM. **Existing** CocoaPods users can keep shipping; migrate when it suits you. This applies only to the **CocoaPods delivery channel**, not to the Swift libraries themselves.

Read the full customer-facing notice: **[DEPRECATION.md](./DEPRECATION.md)**. Swift CDA reference: [Swift SDK reference](https://www.contentstack.com/docs/developers/sdks/content-delivery-sdk/swift/reference). Optional context: [CocoaPods Specs Repo](https://blog.cocoapods.org/CocoaPods-Specs-Repo/).

---

Contentstack is a headless CMS with an API-first approach. It is a CMS that developers can use to build powerful cross-platform applications in their favorite languages. Build your application frontend, and Contentstack will take care of the rest. [Read More](https://www.contentstack.com/).

Contentstack provides iOS SDK to build application on top of iOS. Given below is the detailed guide and helpful resources to get started with our iOS SDK.
Expand Down
19 changes: 19 additions & 0 deletions skills/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Skills – Contentstack Utils Swift

**This directory is the source of truth** for conventions (workflow, SDK API, style, tests, review, build). Read **`AGENTS.md`** at the repo root for the index and quick commands; each skill is a folder with **`SKILL.md`** (YAML frontmatter: `name`, `description`).

## When to use which skill

| Skill folder | Use when |
|--------------|----------|
| **dev-workflow** | Branches, CI, `swift build` / `swift test` / `swiftlint`, `xcodebuild`, PRs, Slather, optional TDD |
| **contentstack-utils** | `ContentstackUtils`, `Option` / `Renderable`, RTE/JSON, GQL, variants, errors, semver, docs |
| **swift-style** | SwiftLint, `Sources/` vs Kanna, libxml2/platforms, naming, access control |
| **testing** | XCTest layout, mocks, fixtures, offline tests, `XCTestManifests` |
| **code-review** | PR checklist, Blocker/Major/Minor, API and security gates |
| **framework** | `Package.swift`, `Modules/`, Kanna vendoring, podspec, CI scheme |

## How to use these docs

- **Humans / any AI tool:** Start at **`AGENTS.md`**, then open the relevant **`skills/<name>/SKILL.md`**.
- **Cursor users:** **`.cursor/rules/README.md`** only points to **`AGENTS.md`** so guidance stays universal—no duplicate `.mdc` rule sets.
60 changes: 60 additions & 0 deletions skills/code-review/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
name: code-review
description: PR checklist—API stability, docs, errors, compatibility, dependencies/SCA, tests, vendored code; Blocker/Major/Minor.
---

# Code review – Contentstack Utils Swift

## When to use

- Reviewing a PR, self-review before submit, or automated review prompts.

## Instructions

Work through the checklist below. Optionally tag findings: **Blocker**, **Major**, **Minor**.

### API design and stability

- [ ] **Public API:** New or changed `public` / `open` types in `Sources/ContentstackUtils/` are necessary, semver-conscious, and documented (`README.md` / `CHANGELOG.md` when user-visible).
- [ ] **Backward compatibility:** No breaking changes unless explicitly justified (e.g. major version). Prefer additive behavior and default `Option()` paths.
- [ ] **Naming:** Matches existing Utils and RTE terminology (`ContentstackUtils`, `Option`, `Node`, `GQL`, etc.).

### Error handling and robustness

- [ ] **Errors:** New `throws` paths use clear domain types (e.g. `VariantUtilityError`); callers can distinguish invalid input from parsing failures where relevant.
- [ ] **Optionals:** No force-unwraps on public code paths; document preconditions for non-optional parameters.
- [ ] **RTE JSON:** Decoding and HTML traversal stay tolerant of documented stack payload shapes; embedded-item regressions are called out.

### Dependencies and security

- [ ] **Dependencies:** `Package.swift` / `ContentstackUtils.podspec` changes are justified; versions do not introduce known vulnerabilities.
- [ ] **SCA:** Address security findings (e.g. Snyk, org scanners) in the PR or via an agreed follow-up.

### Testing

- [ ] **Coverage:** New or modified behavior in `Sources/ContentstackUtils/` has tests under `Tests/ContentstackUtilsTests/` when feasible.
- [ ] **Quality:** Tests are readable, deterministic, and follow naming/mocks conventions.

### Vendored and native code

- [ ] **Kanna / libxml2 / `Modules/`:** Reviewed for upstream parity, licensing, and Apple vs Linux builds.

### Severity (optional)

| Level | Examples |
|-------|----------|
| **Blocker** | Breaking public API without approval; security issue; no tests for new code where tests are practical |
| **Major** | Inconsistent errors; README examples that do not compile |
| **Minor** | Style; minor docs |

### Detailed review themes (from checklist sections)

- **API:** Breaking `public`/`open` without semver/CHANGELOG/podspec alignment.
- **Errors:** `throws` changes that confuse callers without a version strategy.
- **README:** Examples must match real APIs (`jsonToHtml` overloads, `GQL.jsonToHtml`).
- **Dependencies:** New packages in `Package.swift` / podspec need justification.

## References

- `skills/testing/SKILL.md`
- `skills/contentstack-utils/SKILL.md`
55 changes: 55 additions & 0 deletions skills/contentstack-utils/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
name: contentstack-utils
description: Public API—ContentstackUtils, Option/Renderable, RTE/JSON, GQL, variants, errors; no bundled HTTP client.
---

# Contentstack Utils – SDK skill

## When to use

- Implementing or changing RTE/HTML rendering, JSON RTE parsing, or variant helpers.
- Updating `README.md` / `CHANGELOG.md` / podspec for user-visible behavior.
- Assessing semver impact of `public` / `open` changes.

## Main entry (consumer API)

- Consumers `import ContentstackUtils` and use **`ContentstackUtils`**: e.g. `render(content:_:)`, `render(contents:_:)`, `jsonToHtml(node:_:)`, `getVariantAliases`, nested **`GQL.jsonToHtml(rte:_:)`**.
- Keep the static surface small and documented; breaking changes need semver and changelog notes.

## Customization

- Subclass or extend via **`Option`** (open class) conforming to **`Renderable`**: `renderItem(embeddedObject:metadata:)`, `renderMark(markType:text:)`, `renderNode(nodeType:node:next:)`.
- Do not remove or rename open hooks without a **major** version.

## Data model

- RTE JSON uses **`Node`**, **`JSONNode`** / **`JSONNodes`**, **`MarkType`**, **`StyleType`**, **`Metadata`**, embedded entry/asset types (`EmbeddedObject`, `EmbeddedEntry`, etc.).
- Preserve **`Codable`** / decoding compatibility with Contentstack Delivery and GraphQL payloads.

## Errors

- Expose domain failures with nested types where appropriate (e.g. **`ContentstackUtils.VariantUtilityError.invalidArgument`**).
- Use **`throws`** for recoverable failures; avoid force-unwraps on public paths.

## HTML and documentation

- Rendering uses Kanna/HTML internally; keep output predictable for documented inputs.
- Document new node types or GQL JSON shapes in **`README.md`** / **`CHANGELOG.md`**.

## No network layer

- This package does **not** ship HTTP clients or tokens.
- README examples showing **`Stack`**, **`fetch`**, or **Apollo** are integration sketches only—do **not** add hard dependencies on the main Contentstack iOS SDK or Apollo in **`Package.swift`** unless product explicitly requires it.

## Legacy naming

- Some names (e.g. **`embdeddedItems`**) are entrenched; changing them is a **breaking** API change—coordinate with maintainers.

## Docs and versioning

- Align **`ContentstackUtils.podspec`** and git tags with releases. Follow **semver** for `public` / `open` changes.

## References

- [Contentstack](https://www.contentstack.com/)
- `skills/swift-style/SKILL.md`, `skills/framework/SKILL.md`
51 changes: 51 additions & 0 deletions skills/dev-workflow/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
name: dev-workflow
description: Branches, CI, build/test/lint, PR expectations, coverage—standard workflow for Contentstack Utils Swift.
---

# Development workflow – Contentstack Utils Swift

## When to use

- Setting up locally, opening a PR, or aligning with CI.
- Answering “how do we run tests?” or “which branch targets `master`?”

## Branches

- Use feature branches (e.g. `feat/...`, `fix/...`, ticket branches).
- **CI** runs on push to `master` and on pull requests targeting `master` or `next` (`.github/workflows/ci.yml`).
- **Merges into `master`** may be gated: PRs whose base is `master` are often expected to come from **`staging`**; other heads may fail the check-branch workflow (`.github/workflows/check-branch.yml`). Confirm with your team before opening PRs to `master`.

## Running tests and build

- **SPM:** `swift build`, `swift test`
- **CI-style Xcode (iOS Simulator):**
`xcodebuild -project "ContentstackUtils.xcodeproj" -scheme "ContentstackUtils-Package" -destination "OS=13.4.1,name=iPhone 11 Pro" test`
Adjust `-destination` for your local Xcode/Simulator.

Run tests before opening a PR. Default tests use **offline** mocks and fixtures—no `.env` or live stack credentials.

## Lint

- **SwiftLint:** `swiftlint` (`.swiftlint.yml`)

## Pull requests

- Build passes: `swift build` and `swift test` (and `xcodebuild` if you touch Xcode-specific paths).
- Follow the **code-review** skill (`skills/code-review/SKILL.md`) before merge.
- Prefer backward-compatible public API; call out breaking changes and semver.
- Describe behavior and update `CHANGELOG.md` / version metadata (`ContentstackUtils.podspec`, tags) when releasing—per team process.
- Security/policy scans may run in CI (e.g. `.github/workflows/sca-scan.yml`, `policy-scan.yml`).

## Optional: TDD

If the team uses TDD: RED → GREEN → REFACTOR. Test structure is in `skills/testing/SKILL.md`.

## Coverage

- **Slather** (`.slather.yml`, scheme `ContentstackUtils-Package`): use after tests to inspect `Sources/ContentstackUtils/` coverage.

## References

- `skills/testing/SKILL.md`
- `skills/code-review/SKILL.md`
39 changes: 39 additions & 0 deletions skills/framework/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
name: framework
description: SPM targets, libxml2 Modules, vendored Kanna, deployment targets, CocoaPods podspec, CI xcodebuild.
---

# Framework / build – Contentstack Utils Swift

## When to use

- Editing `Package.swift`, `Modules/`, or `Sources/Kanna/`.
- Changing deployment targets or conditional libxml linking.
- Updating `ContentstackUtils.podspec` or CI assumptions (scheme, destination).

## Swift Package Manager

- **Product:** `ContentstackUtils`.
- **Targets:** `ContentstackUtils` (sources under `Sources/`), `ContentstackUtilsTests`, system library **`libxml2`** → **`Modules/`**.
- **Apple vs Linux:** Conditional `libxml2` dependency and `pkg-config` as in `Package.swift`—preserve behavior when refactoring.

## Vendored Kanna

- **`Sources/Kanna/`** is excluded from SwiftLint. Updates = intentional vendoring (license, diff, cross-platform build).

## CocoaPods

- **`ContentstackUtils.podspec`:** e.g. `source_files` `Sources/**/*.{swift}`, `HEADER_SEARCH_PATHS` / `-lxml2` for libxml. Keep aligned with SPM layout and tagged releases.

## Platforms

- Declared in `Package.swift` / podspec (e.g. macOS 10.13+, iOS/tvOS 11+, watchOS 4+). See also **`skills/swift-style/SKILL.md`** for API availability and naming.

## CI

- **GitHub Actions** uses **xcodebuild** with scheme **`ContentstackUtils-Package`**. After changing parsing or linking, validate with both **`swift test`** and Xcode builds.

## References

- `skills/swift-style/SKILL.md`
- `skills/dev-workflow/SKILL.md`
Loading