Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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.
27 changes: 11 additions & 16 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,29 @@ 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)
crack (1.0.1)
Expand All @@ -36,14 +36,10 @@ 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)
racc (1.8.1)
rake (13.3.1)
Expand All @@ -70,12 +66,11 @@ 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)
hashdiff (>= 0.4.0, < 2.0.0)
yard (0.9.38)
yard (0.9.39)

PLATFORMS
arm64-darwin-22
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