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 **[AGENTS.md](../../AGENTS.md)**. All conventions live in **`skills/*/SKILL.md`**.

This folder only points contributors to **`AGENTS.md`** so editor-specific config does not duplicate the canonical docs.
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.6
3.1.4
49 changes: 49 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Contentstack Utils Ruby – Agent guide

**Universal entry point** for contributors and AI agents. Detailed conventions live in **`skills/*/SKILL.md`**.

## What this repo is

| Field | Detail |
|--------|--------|
| **Name:** | [contentstack/contentstack-utils-ruby](https://github.com/contentstack/contentstack-utils-ruby) |
| **Purpose:** | Ruby gem that renders Contentstack rich text and JSON RTE (including GraphQL-shaped payloads) to HTML, with pluggable rendering via `ContentstackUtils::Model::Options` subclasses. |
| **Out of scope (if any):** | This package does not ship an HTTP client or stack SDK; it pairs with the separate Contentstack Ruby delivery client for entry data and `_embedded_items`. |

## Tech stack (at a glance)

| Area | Details |
|------|---------|
| Language | Ruby **≥ 3.1** (see `contentstack_utils.gemspec` and `.ruby-version` for local dev) |
| Build | **Bundler** + **RubyGems**; `contentstack_utils.gemspec`, `Gemfile` |
| Tests | **RSpec**; specs under `spec/**/*_spec.rb`, loaded via `spec/spec_helper.rb` |
| Lint / coverage | No RuboCop in-repo; **SimpleCov** in `spec/spec_helper.rb`; API docs via **YARD** (`.yardopts`, `rake yard`) |
| Runtime deps | **activesupport** (7.x), **nokogiri** (HTML / XML for legacy RTE strings) |

## Commands (quick reference)

| Command type | Command |
|--------------|---------|
| Install deps | `bundle install` |
| Build (default task) | `bundle exec rake` (runs **spec**) |
| Test | `bundle exec rake spec` or `bundle exec rspec` |
| Docs | `bundle exec rake yard` |

**CI / automation:** There is no dedicated workflow that runs `rspec` on every push; local verification is `bundle exec rake`. Other workflows include branch checks (PRs into `master`), release publish, CodeQL, policy/SCA scans—see `.github/workflows/`.

## Where the documentation lives: skills

| Skill | Path | What it covers |
|-------|------|----------------|
| Code review | `skills/code-review/SKILL.md` | PR checklist for this gem |
| Contentstack Utils SDK | `skills/contentstack-utils/SKILL.md` | Public API, models, CDA vs GQL paths, versioning |
| Development workflow | `skills/dev-workflow/SKILL.md` | Branches, Bundler/Rake, gem build, workflows |
| Framework & packaging | `skills/framework/SKILL.md` | Gemspec, dependencies, Ruby version, release |
| Ruby style and layout | `skills/ruby-style/SKILL.md` | Module layout, naming, matching existing code |
| Testing | `skills/testing/SKILL.md` | RSpec layout, mocks, SimpleCov, WebMock |

An index with “when to use” hints is in `skills/README.md`.

## Using Cursor (optional)

If you use **Cursor**, **`.cursor/rules/README.md`** is the only file under `.cursor/rules`; it points to **`AGENTS.md`**—same docs as everyone else.
29 changes: 12 additions & 17 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,31 @@ PATH
remote: .
specs:
contentstack_utils (1.2.3)
activesupport (>= 8.0)
nokogiri (>= 1.19)
activesupport (>= 7.0, < 8)
nokogiri (>= 1.13, < 1.19)

GEM
remote: https://rubygems.org/
specs:
activesupport (8.1.3)
activesupport (7.2.3.1)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
json
logger (>= 1.4.2)
minitest (>= 5.1)
minitest (>= 5.1, < 6)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1)
addressable (2.8.9)
addressable (2.9.0)
public_suffix (>= 2.0.2, < 8.0)
base64 (0.3.0)
bigdecimal (4.0.1)
benchmark (0.5.0)
bigdecimal (4.1.1)
concurrent-ruby (1.3.6)
connection_pool (3.0.2)
connection_pool (2.5.5)
crack (1.0.1)
bigdecimal
rexml
Expand All @@ -36,15 +36,11 @@ GEM
hashdiff (1.2.1)
i18n (1.14.8)
concurrent-ruby (~> 1.0)
json (2.19.3)
logger (1.7.0)
minitest (6.0.2)
drb (~> 2.0)
prism (~> 1.5)
nokogiri (1.19.2-arm64-darwin)
minitest (5.27.0)
nokogiri (1.18.10-arm64-darwin)
racc (~> 1.4)
prism (1.9.0)
public_suffix (7.0.5)
public_suffix (6.0.2)
racc (1.8.1)
rake (13.3.1)
rexml (3.4.4)
Expand All @@ -70,7 +66,6 @@ GEM
simplecov_json_formatter (0.1.4)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uri (1.1.1)
webmock (3.26.2)
addressable (>= 2.8.0)
crack (>= 0.3.2)
Expand Down
6 changes: 3 additions & 3 deletions contentstack_utils.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Gem::Specification.new do |s|
s.authors = [%q{Contentstack}]
s.email = ["support@contentstack.com"]

s.required_ruby_version = '>= 3.0'
s.required_ruby_version = '>= 3.1'

s.license = "MIT"
s.homepage = "https://github.com/contentstack/contentstack-utils-ruby"
Expand All @@ -21,8 +21,8 @@ Gem::Specification.new do |s|
s.test_files = s.files.grep(%r{^spec/})
s.require_paths = ["lib"]

s.add_dependency 'activesupport', '>= 8.0'
s.add_dependency 'nokogiri', '>= 1.19'
s.add_dependency 'activesupport', '>= 7.0', '< 8'
s.add_dependency 'nokogiri', '>= 1.13', '< 1.19'

s.add_development_dependency 'rake', '~> 13.0'
s.add_development_dependency 'rspec', '~> 3.13'
Expand Down
16 changes: 16 additions & 0 deletions skills/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Skills – Contentstack Utils Ruby

Source of truth for detailed guidance. Read [AGENTS.md](../AGENTS.md) first, then open the skill that matches your task.

## When to use which skill

| Skill folder | Use when |
|--------------|----------|
| `code-review` | Preparing or reviewing a PR |
| `contentstack-utils` | Changing rendering behavior, JSON RTE / GQL paths, options API, or public `lib/` entry points |
| `dev-workflow` | Setting up the repo, running tests/docs, opening PRs, understanding CI and release |
| `framework` | Gemspec, Bundler, Ruby version constraints, activesupport/nokogiri dependencies, gem build/release |
| `ruby-style` | File layout, modules, or staying consistent with existing Ruby style in this repo |
| `testing` | Adding or changing specs, fixtures, mocks, or coverage |

Each folder contains `SKILL.md` with YAML frontmatter (`name`, `description`).
44 changes: 44 additions & 0 deletions skills/code-review/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
name: code-review
description: Use when reviewing or preparing a PR for this gem—behavior, tests, API compatibility, and release notes.
---

# Code review – Contentstack Utils Ruby

## When to use

- Authoring a pull request that changes rendering, models, or dependencies
- Reviewing someone else’s PR before merge
- Checking release readiness (version + changelog)

## Instructions

### Blockers (fix before merge)

- **Tests:** `bundle exec rake` (or `bundle exec rspec`) passes locally
- **Breaking API:** unintended removal or signature change of public methods on **`ContentstackUtils`**, **`ContentstackUtils::GQL`**, or **`ContentstackUtils::Model::Options`** without version bump and changelog entry
- **Security:** no secrets in code, fixtures, or logs; HTML output changes reviewed for injection or XSS risk when embedding untrusted fields

### Major (should address)

- **CHANGELOG.md** updated for user-visible behavior fixes or features
- **`lib/contentstack_utils/version.rb`** updated when publishing a release (if this PR is release-bound)
- New JSON/RTE node types or GQL shapes covered by **`spec/lib/utils_spec.rb`** (or focused new spec files)
- Dependency range changes in **`contentstack_utils.gemspec`** justified and compatible with Ruby **≥ 3.1**

### Minor (nice to have)

- **README.md** examples match actual class names (**`Options`**, not a non-existent **`Option`** unless aliased)
- YARD or comments only where they clarify non-obvious RTE or GQL mapping

### Process

- Respect **CODEOWNERS** and branch policy (**`master`** vs **`staging`**) described in [dev-workflow](../dev-workflow/SKILL.md)

## References

- [AGENTS.md](../../AGENTS.md)
- [Development workflow](../dev-workflow/SKILL.md)
- [Contentstack Utils SDK](../contentstack-utils/SKILL.md)
- [Framework & packaging](../framework/SKILL.md)
- [Testing](../testing/SKILL.md)
51 changes: 51 additions & 0 deletions skills/contentstack-utils/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
name: contentstack-utils
description: Use when changing the public Ruby API, RTE rendering (HTML string or JSON), GQL payloads, Model::Options/Metadata, or integration boundaries with the delivery client.
---

# Contentstack Utils SDK – Contentstack Utils Ruby

## When to use

- Implementing or fixing HTML output for rich text / JSON RTE
- Extending or subclassing rendering options (`ContentstackUtils::Model::Options`)
- Parsing GraphQL-shaped RTE (`ContentstackUtils::GQL`)
- Changing load paths or public entry points under `lib/` (gemspec and dependency ranges: see [framework](../framework/SKILL.md))

## Instructions

### Entry points

- **`lib/contentstack_utils.rb`** — requires version and `utils`
- **`lib/contentstack_utils/utils.rb`** — main module **`ContentstackUtils`** with class methods:
- **`render_content(content, options)`** — legacy HTML string RTE (array of strings or single string); uses Nokogiri and `_embedded_items` on the entry passed via options
- **`json_to_html(content, options)`** — JSON RTE document tree (Hash/Array) for CDA-style payloads with embedded items on the entry
- Internal helpers such as **`json_doc_to_html`** (used by GQL path)
- **`ContentstackUtils::GQL`** — **`json_to_html(content, options)`** for GraphQL responses: expects keys like `json` and optional `embedded_itemsConnection.edges`; reuses `ContentstackUtils.json_doc_to_html` with a GQL-specific reference resolver

### Models and extension points

- **`ContentstackUtils::Model::Options`** (`lib/contentstack_utils/model/options.rb`) — default **`render_option`**, **`render_mark`**, **`render_node`**; subclass for custom HTML (see tests under `spec/mock/custom_render_option.rb`)
- **`ContentstackUtils::Model::Metadata`** — built from DOM nodes (HTML path) or JSON reference nodes
- **`ContentstackUtils::Interface::Rendarable`** (`lib/contentstack_utils/interface/renderable.rb`) — base for options; implement **`render_option`** in subclasses

### Data contracts

- **CDA / delivery JSON path:** options may carry an **`entry`** hash with **`_embedded_items`** keyed by field UIDs
- **GQL path:** payload uses **`embedded_itemsConnection.edges`** with **`node`** objects; reference resolution matches **`metadata.item_uid`** to **`node.system.uid`**

### Boundaries

- HTTP and stack access belong to the separate **Contentstack Ruby** client; this gem only renders given content + embedded metadata

### Versioning

- Public API and behavior changes should be reflected in `CHANGELOG.md` and `lib/contentstack_utils/version.rb`

## References

- Product overview: [README.md](../../README.md)
- [Framework & packaging](../framework/SKILL.md)
- [Testing](../testing/SKILL.md)
- [Ruby style and layout](../ruby-style/SKILL.md)
- [Contentstack documentation](https://www.contentstack.com/docs/)
53 changes: 53 additions & 0 deletions skills/dev-workflow/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
name: dev-workflow
description: Use when setting up the dev environment, running build/test/docs, or understanding CI, branches, and gem release for this repo.
---

# Development workflow – Contentstack Utils Ruby

## When to use

- Cloning the repo or onboarding a new contributor
- Running tests, generating docs, or building the gem locally
- Understanding branch rules and GitHub Actions for this repository

## Instructions

### Prerequisites

- Ruby **≥ 3.1** (matches `s.required_ruby_version` in `contentstack_utils.gemspec`)
- Bundler; install gems with `bundle install`

### Everyday commands

- **Run tests (default Rake task):** `bundle exec rake` or `bundle exec rake spec`
- **RSpec directly:** `bundle exec rspec` (pattern `spec/**/*_spec.rb` is configured in `Rakefile`)
- **YARD API docs:** `bundle exec rake yard` (see `.yardopts` for included paths)
- **Build gem artifact:** `gem build contentstack_utils.gemspec` (also used in `.github/workflows/release-gem.yml`)

### Version and changelog

- Gem version lives in `lib/contentstack_utils/version.rb` as `ContentstackUtils::VERSION`
- Document user-visible changes in `CHANGELOG.md` when releasing

### Branches and PRs

- `.github/workflows/check-branch.yml` blocks merging into **`master`** unless the head branch is **`staging`** (organizational policy). Prefer PRs that follow team conventions for `master` / `staging`.
- Use `CODEOWNERS` for required reviewers when applicable

### CI and automation (no RSpec workflow today)

- **Release:** `.github/workflows/release-gem.yml` — on GitHub **release created**, builds and pushes to RubyGems (note: workflow pins Ruby 2.7 for publish; align with gemspec minimum when changing)
- **Security / compliance:** CodeQL, policy scan, SCA scan — see `.github/workflows/`
- **Issues:** Jira integration workflow in `.github/workflows/issues-jira.yml`

### Optional housekeeping

- `.talismanrc` is used for secret scanning hooks in some environments; do not commit credentials or tokens

## References

- [AGENTS.md](../../AGENTS.md)
- [Contentstack Utils SDK](../contentstack-utils/SKILL.md)
- [Framework & packaging](../framework/SKILL.md)
- [Testing](../testing/SKILL.md)
44 changes: 44 additions & 0 deletions skills/framework/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
name: framework
description: Use when changing the gemspec, Bundler setup, Ruby/runtime constraints, or runtime dependencies (activesupport, nokogiri) and native extension implications.
---

# Framework & packaging – Contentstack Utils Ruby

## When to use

- Editing **`contentstack_utils.gemspec`** (dependencies, `required_ruby_version`, files list)
- Changing **`Gemfile`** / **`Gemfile.lock`** workflow or documenting install for contributors
- Evaluating impact of **nokogiri** (native extension) or **activesupport** version ranges on consumers

## Instructions

### Gem definition

- **`contentstack_utils.gemspec`** — canonical metadata: `s.files` from `git ls-files`, `spec/` as test files, `lib` as `require_paths`
- **`Gemfile`** — `gemspec` only; runtime and development dependencies are declared in the gemspec

### Runtime dependencies (as shipped)

- **activesupport** `>= 7.0`, `< 8`
- **nokogiri** `>= 1.13`, `< 1.19` — HTML/XML parsing for legacy string RTE paths; consumers need a compatible platform build

### Development dependencies

- **rake**, **rspec**, **webmock**, **simplecov**, **yard** — see gemspec; used for tasks in `Rakefile` and CI-style local checks

### Ruby version

- **`s.required_ruby_version`** is **>= 3.1**; `.ruby-version` pins a team default for local dev
- **Release workflow** (`.github/workflows/release-gem.yml`) uses its own Ruby pin for `gem build` / `gem push`; keep it aligned with gemspec when updating

### Build and publish

- Local artifact: `gem build contentstack_utils.gemspec`
- Publishing is triggered by GitHub **release** per `release-gem.yml`

## References

- [Development workflow](../dev-workflow/SKILL.md)
- [Contentstack Utils SDK](../contentstack-utils/SKILL.md)
- [Ruby style and layout](../ruby-style/SKILL.md)
Loading
Loading