Skip to content

Commit 9b0b66a

Browse files
authored
Merge branch 'development' into bug/VB-797-lowercase-locale
2 parents 62ee914 + 31f6b5a commit 9b0b66a

File tree

10 files changed

+216
-15
lines changed

10 files changed

+216
-15
lines changed

.talismanrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,9 @@ fileignoreconfig:
1414
checksum: d455330cc4f9306889fb299171364a37ad2c3bafe1fbd334033edc94f21694a6
1515
- filename: package.json
1616
checksum: 033eb21070795be5b426183f52d784347110fcb724bc9f8d63f94898ac5f0086
17+
- filename: src/Models/metadata-model.ts
18+
checksum: a101e109db1ec6ee0cb16a116f9b099e547c3104881e4fa1eaef2849e2d0aaf0
19+
- filename: src/json-to-html.ts
20+
checksum: a843710fc9f54bf4c7996f39561dc66491d62a9d9eeca50fa2c7c37bd6141f53
21+
- filename: src/render-embedded-objects.ts
22+
checksum: 35d56d4f7b625611fef18414fccdbff014c1d90d02e17eb0efa4d6166b73e23b

CONTRIBUTING.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Contributing to Contentstack Utils JavaScript
2+
3+
Thank you for your interest in contributing to Contentstack Utils JavaScript. This document provides guidelines and instructions for contributing.
4+
5+
## Pull Request Target Branch
6+
7+
**All pull requests must be raised against the `development` branch.**
8+
9+
Do not open PRs against `master` or `staging`. Create your feature or fix branch from `development`, and open your PR to merge into `development`. Maintainers will handle promotion to other branches after review.
10+
11+
## Getting Started
12+
13+
### Prerequisites
14+
15+
- **Node.js** 10 or later
16+
- **npm** (comes with Node.js)
17+
- **Git**
18+
19+
### Development Setup
20+
21+
1. **Fork the repository** on GitHub and clone your fork locally:
22+
23+
```bash
24+
git clone https://github.com/YOUR_USERNAME/contentstack-utils-javascript.git
25+
cd contentstack-utils-javascript
26+
```
27+
28+
2. **Add the upstream remote** (optional, for syncing with the main repo):
29+
30+
```bash
31+
git remote add upstream https://github.com/contentstack/contentstack-utils-javascript.git
32+
```
33+
34+
3. **Create a branch from `development`** for your work:
35+
36+
```bash
37+
git fetch upstream
38+
git checkout development
39+
git pull upstream development
40+
git checkout -b your-feature-or-fix-name
41+
```
42+
43+
4. **Install dependencies:**
44+
45+
```bash
46+
npm install
47+
```
48+
49+
5. **Build the project:**
50+
51+
```bash
52+
npm run build
53+
```
54+
55+
## Development Workflow
56+
57+
### Running Tests
58+
59+
- Run the full test suite: `npm test`
60+
- Run tests in watch mode (for development): `npm run test:debug`
61+
62+
All tests must pass before submitting a PR. New features and bug fixes should include or update tests as appropriate.
63+
64+
### Code Style
65+
66+
- **ESLint:** The project uses ESLint. Fix auto-fixable issues with your editor or by running the linter.
67+
- **Prettier:** Code is formatted with Prettier. Use `npm run format` to format `src/**/*.ts`.
68+
69+
Ensure your code adheres to the existing style so that CI and pre-commit checks pass.
70+
71+
### Commit Messages
72+
73+
This project uses [Conventional Commits](https://www.conventionalcommits.org/) enforced by Commitlint.
74+
75+
- Use a **type** and a **short subject** (e.g. `feat: add jsonToHTML option`, `fix: handle empty nodes`).
76+
- Allowed types include: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`, `sample`.
77+
- Subject should be lowercase, imperative, and not end with a period.
78+
- Add a blank line and a longer body when the change needs more explanation.
79+
80+
Husky runs a commit-msg hook to validate commit messages. Invalid messages will be rejected.
81+
82+
### Pre-commit Hooks
83+
84+
Husky is used for Git hooks. Before each commit, the pre-commit hook runs. Ensure your working tree is clean and that tests and lint pass locally to avoid failed commits.
85+
86+
## Submitting Changes
87+
88+
1. **Keep your branch up to date** with `development`:
89+
90+
```bash
91+
git fetch upstream
92+
git rebase upstream/development
93+
```
94+
95+
2. **Open a Pull Request** against the **`development`** branch (not `master` or `staging`).
96+
97+
3. **Fill out the PR template** (if one exists) and provide:
98+
- A clear title and description of the change
99+
- Link to any related issue
100+
- Summary of testing done
101+
102+
4. **Address review feedback** promptly. Maintainers may request changes before merging.
103+
104+
5. **Do not force-push** after review has started unless the maintainer asks you to; use new commits for updates when possible so review history is preserved.
105+
106+
## Reporting Issues
107+
108+
- Use the GitHub issue tracker for bugs and feature requests.
109+
- Search existing issues first to avoid duplicates.
110+
- Include steps to reproduce for bugs, and your environment (Node version, OS).
111+
- For security issues, see [SECURITY.md](SECURITY.md).
112+
113+
## Additional Resources
114+
115+
- [README](README.md) – Project overview and usage
116+
- [CHANGELOG](CHANGELOG.md) – Version history and changes
117+
- [SECURITY](SECURITY.md) – Security and vulnerability reporting
118+
- [CODEOWNERS](CODEOWNERS) – Code ownership and review expectations
119+
120+
Thank you for contributing.

LICENSE

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
The MIT License (MIT)
1+
MIT License
22

3-
4-
Copyright (c) 2016-2025 Contentstack
3+
Copyright (c) 2016-2026 Contentstack
54

65
Permission is hereby granted, free of charge, to any person obtaining a copy
76
of this software and associated documentation files (the "Software"), to deal
@@ -10,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
109
copies of the Software, and to permit persons to whom the Software is
1110
furnished to do so, subject to the following conditions:
1211

13-
The above copyright notice and this permission notice shall be included in
14-
all copies or substantial portions of the Software.
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
1514

1615
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1716
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1817
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1918
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2019
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22-
THE SOFTWARE.
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

src/Models/metadata-model.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,15 @@ export function nodeToMetadata(attribute: Attributes, textNode: TextNode): Metad
5656
};
5757
}
5858

59+
/**
60+
* Serializes an Attributes object to a string of HTML attribute key-value pairs
61+
* (e.g. ` key1="value1" key2="value2"`). Keys containing forbidden characters
62+
* are skipped. Values are HTML-entity-encoded. Arrays are joined with `, `;
63+
* nested objects are serialized as `key:value;` pairs.
64+
*
65+
* @param attributes - The attributes object to serialize (e.g. from a node or metadata).
66+
* @returns A string starting with a space, followed by `key="value"` pairs suitable for inclusion in an HTML tag.
67+
*/
5968
export function attributeToString(attributes: Attributes): string {
6069
let result = '';
6170
for (const key in attributes) {

src/endpoints.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,17 @@ export interface RegionsResponse {
1818
regions: RegionData[];
1919
}
2020

21+
/**
22+
* Returns the Contentstack API endpoint(s) for a given region and optional service.
23+
* Region can be an ID (e.g. `'us'`, `'eu'`) or an alias. Throws if the region is
24+
* invalid or empty.
25+
*
26+
* @param region - Region ID or alias (e.g. `'us'`, `'eu'`). Default: `'us'`.
27+
* @param service - Optional service name to return a single endpoint (e.g. `'delivery'`). If empty, returns all endpoints for the region.
28+
* @param omitHttps - If true, strips the `https://` prefix from the returned URL(s). Default: false.
29+
* @returns A single endpoint URL string if `service` is provided, otherwise the full endpoints object for the region.
30+
* @throws Error if region is empty, invalid, or if the requested service is not found.
31+
*/
2132
export function getContentstackEndpoint(region: string = 'us', service: string = '', omitHttps: boolean = false): string | ContentstackEndpoints {
2233
// Validate empty region before any processing
2334
if (region === '') {

src/entry-editable.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ interface AppliedVariants {
66
metaKey: string
77
}
88

9+
/**
10+
* Adds Contentstack Live Preview (CSLP) data tags to an entry for editable UIs.
11+
* Mutates the entry by attaching a `$` property with tag strings or objects
12+
* (e.g. `data-cslp` / `data-cslp-parent-field`) for each field, including nested
13+
* objects and references. Supports variant-aware tagging when the entry has
14+
* applied variants.
15+
*
16+
* @param entry - The entry (EmbeddedItem) to tag. Must have uid and optional system/applied variants.
17+
* @param contentTypeUid - Content type UID (e.g. `blog_post`). Used as part of the tag path.
18+
* @param tagsAsObject - If true, tags are stored as objects (e.g. `{ "data-cslp": "..." }`); if false, as strings (e.g. `data-cslp=...`).
19+
* @param locale - Locale code for the tag path (default: `'en-us'`).
20+
* @param options.useLowerCaseLocale - Optional boolean to make locale case-insensitive.
21+
*/
922
export function addTags(entry: EntryModel, contentTypeUid: string, tagsAsObject: boolean, locale: string = 'en-us', options?: {
1023
useLowerCaseLocale?: boolean
1124
}): void {

src/gql.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,22 @@ function enumerateKeys(option: {
4848
}))
4949
}
5050
}
51+
52+
/**
53+
* GraphQL API utilities for Contentstack. Provides methods to work with
54+
* content fetched via the GraphQL API, including rendering Supercharged RTE
55+
* (JSON) with embedded items from the GQL response.
56+
*/
5157
export const GQL = {
58+
/**
59+
* Converts Supercharged RTE (JSON) content to HTML for entries from a GraphQL response.
60+
* Uses `embedded_itemsConnection.edges` to resolve embedded items. Mutates the entry
61+
* JSON in-place by replacing JSON RTE content with the generated HTML.
62+
*
63+
* @param option - Configuration for conversion.
64+
* @param option.entry - Entry or array of entries (EmbeddedItem) from a GQL response with JSON RTE and embedded_itemsConnection.
65+
* @param option.paths - Key paths to the JSON RTE fields on the entry.
66+
* @param option.renderOption - Optional render options to customize how nodes and embedded items are rendered to HTML.
67+
*/
5268
jsonToHTML
5369
}

src/json-to-html.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@ import { enumerate, enumerateContents } from './helper/enumerate-entries';
1010

1111
export type AnyNode = TextNode | Node;
1212

13+
/**
14+
* Converts Supercharged RTE (JSON) content to HTML for one or more entries.
15+
* Walks the given paths on each entry, finds JSON RTE content, resolves embedded
16+
* items from the entry, and renders nodes using the optional renderOption. Mutates
17+
* the entry JSON in-place by replacing content with the generated HTML.
18+
*
19+
* @param option - Configuration for conversion.
20+
* @param option.entry - Entry or array of entries that contain Supercharged RTE (JSON) fields.
21+
* @param option.paths - Key paths to the JSON RTE fields (e.g. `['rte_field_uid', 'group.rte_uid']`).
22+
* @param option.renderOption - Optional render options to customize how nodes and embedded items are rendered to HTML.
23+
*/
1324
export function jsonToHTML(option: {
1425
entry: EntryEmbedable| EntryEmbedable[],
1526
paths: string[],

src/render-embedded-objects.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@ import { findEmbeddedItems, findRenderString } from './helper/find-embeded-objec
55
import { EntryEmbedable } from './Models/embedded-object';
66
import { findRenderContent } from './helper/find-render-content';
77
/**
8-
*
9-
* @param {EntryEmbedable| EntryEmbedable[]} entry - Objects that contains RTE with embedded objects
10-
* @param {string[]} paths - Key paths for RTE contents in Entry object
11-
* @param {RenderOption?} renderOption - Optional render options to render content
8+
* Renders RTE (Rich Text Editor) content with embedded objects in-place.
9+
* Mutates the entry/entries by replacing embedded item tags with HTML produced
10+
* by the provided render options. Works with a single entry or an array of entries.
11+
*
12+
* @param option - Configuration for rendering.
13+
* @param option.entry - Entry or array of entries containing RTE fields with embedded objects.
14+
* @param option.renderOption - Optional render options (node/item handlers) to produce HTML for embedded content.
15+
* @param option.paths - Optional key paths to specific RTE fields. If omitted, all RTE paths on the entry are rendered.
1216
*/
1317
export function render(option: {
1418
entry: EntryEmbedable| EntryEmbedable[],
@@ -46,10 +50,13 @@ export function render(option: {
4650
}
4751

4852
/**
49-
*
50-
* @param {string | string[]} content - RTE content to render
51-
* @param {EntryEmbedable} options.entry - Entry object containing embedded objects
52-
* @param {RenderOption?} options.renderOption - Optional render options to render content
53+
* Renders a single RTE content string or array of strings by replacing embedded
54+
* item tags with HTML. Uses the entry and renderOption from the given option to
55+
* resolve embedded references and produce output.
56+
*
57+
* @param content - RTE content string or array of strings containing embedded item tags.
58+
* @param option - Must include the entry (for resolving embedded items) and optionally renderOption.
59+
* @returns The same shape as content: a string or array of strings with embedded tags replaced by rendered HTML.
5360
*/
5461
export function renderContent(content: (string | string[]), option: Option): (string| string[]) {
5562
// return blank if content not present

src/updateAssetURLForGQL.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
/**
2+
* Updates asset URLs in a GraphQL response in-place. Walks the response data,
3+
* finds RTE fields that have `embedded_itemsConnection`, and sets each
4+
* embedded asset's `asset-link` attribute in the JSON to the asset's `url`
5+
* from the response. Use after fetching content via GraphQL so RTE JSON
6+
* contains correct asset URLs for rendering.
7+
*
8+
* @param gqlResponse - The raw GraphQL response object (e.g. `{ data: { ... } }`). Modified in place.
9+
*/
110
export function updateAssetURLForGQL(gqlResponse:any) {
211
try {
312
const response = gqlResponse?.data;

0 commit comments

Comments
 (0)