Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
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`
41 changes: 41 additions & 0 deletions skills/swift-style/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
name: swift-style
description: SwiftLint, Sources layout, Kanna/libxml2, platforms, naming, access control for all Swift in this repo.
---

# Swift style and repo layout – Contentstack Utils Swift

## When to use

- Editing any Swift under `Sources/` or `Tests/`.
- Adding files or changing platform/deployment assumptions.

## Tooling

- Run **SwiftLint** with `.swiftlint.yml`. Do not relax rules for new code without team agreement.
- **`Sources/Kanna/`** is excluded from SwiftLint—do not copy patterns into `Sources/ContentstackUtils/` that would fail lint there.

## Package layout

- **Library code:** `Sources/ContentstackUtils/`.
- **Vendored Kanna:** `Sources/Kanna/`—treat as third-party unless you are deliberately upgrading the vendored copy; prefer fixes in `ContentstackUtils` or documented Kanna upgrades.

## Platforms and libxml2

- **Deployment targets:** macOS 10.13+, iOS/tvOS 11+, watchOS 4+ (`Package.swift`). Avoid newer SDK-only APIs without availability checks or a deliberate target bump.
- **libxml2:** Apple platforms use system libxml where applicable; Linux uses the `libxml2` system target and `pkg-config`. Keep `Modules/` and `Package.swift` conditionals in sync when changing platform support.

## Naming and API surface

- Swift conventions: types `UpperCamelCase`, members `lowerCamelCase`.
- Preserve established **public** names even when imperfect (e.g. historical typos) unless doing a **semver-major** cleanup with maintainer agreement.

## Imports and access control

- `import Foundation` as needed; HTML parsing follows existing Kanna usage in this package.
- Mark **`public` / `open`** intentionally; keep implementation `internal` or `private` unless tests use established `@testable` patterns.

## References

- `skills/framework/SKILL.md` (SPM, podspec, CI)
- `skills/testing/SKILL.md` (lint exclusions in tests)
40 changes: 40 additions & 0 deletions skills/testing/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
name: testing
description: XCTest—layout, mocks, fixtures, SwiftLint/Slather, offline tests, Linux manifests.
---

# Testing – Contentstack Utils Swift

## When to use

- Adding or changing tests under `Tests/ContentstackUtilsTests/`.
- Debugging flaky tests; improving fixtures or mocks.

## Runner and tooling

- **XCTest** via **`swift test`** (SPM) and/or Xcode scheme **`ContentstackUtils-Package`** (`ContentstackUtils.xcodeproj`), matching `.github/workflows/ci.yml`.
- **SwiftLint:** `.swiftlint.yml`; **`Tests/ContentstackUtilsTests/Constants.swift`** is excluded—other test files are linted.
- **Slather:** `.slather.yml` ignores `Tests/*` in coverage reports; still add tests for new production code in `Sources/ContentstackUtils/` when practical.

## Test naming and layout

- **Target:** `ContentstackUtilsTests`; path **`Tests/ContentstackUtilsTests/`**.
- **File names:** `*Tests.swift`, `*Test.swift`, or feature-oriented names (`GQLJsonToHtml.swift`, `JsonNodes.swift`, `VariantUtilityTests.swift`).
- **Fixtures and mocks:** Prefer `JsonNodes.swift`, `JsonNodesHtmlResults.swift`, `EmbededModelMock.swift`, `CustomRenderOptionMock.swift`, `TestClient.swift`, etc., before adding parallel helpers.

## Integration vs unit

- No separate integration tree: tests live in **`ContentstackUtilsTests`** with mocks for API-shaped payloads—**no live network** or credentials in CI.

## Linux / discovery

- Maintain **`XCTestManifests.swift`** if your workflow requires explicit Linux test discovery.

## Secrets

- Tests are **offline**; do not commit API keys or real tokens.

## References

- `skills/dev-workflow/SKILL.md`
- `skills/code-review/SKILL.md`