Giter VIP home page Giter VIP logo

contentstack-utils-javascript's Introduction

Contentstack JavaScript Utils SDK:

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.

This guide will help you get started with Contentstack JavaScript Utils SDK to build apps powered by Contentstack.

Prerequisites

To get started with JavaScript, you will need the following:

  • Node.js 10 or later

SDK Installation and Setup

Note: If you are using JavaScript Contentstack SDK, you don’t need to run the command as ‘@contentstack/utils’ is already imported in the SDK.

Use the following command to install Contentstack JavaScript Utils SDK:

npm i @contentstack/utils

Usage

Let’s learn how you can use Utils SDK to render RTE embedded items and Supercharged RTE Json to HTML.

Create Render Option

To render embedded items on the front-end, use the renderOptions function, and define the UI elements you want to show in the front-end of your website, as shown in the example below:

const renderOption = {
	// to render Supercharged RTE NodeType content like paragraph, link, table, order list, un-order list and more.
	p: (node, next) => {
		return `<p class='class-id'>${next(node.children)}</p>` // you will need to call next function with node children contents
	},
	h1: (node, next) => {
		return `<h1 class='class-id'>${next(node.children)}</h1>` // you will need to call next function with node children contents
	},
	// to render Supercharged RTE MarkType content like bold, italic, underline, strikethrough, inlineCode, subscript, and superscript
	bold: (text) => {
		return `<b>${next(node.children)}</b>`
	},
	// to render block-type embedded items  
	block: {  
		'product': (item, metadata) => {  
			return `<div>  
					<h2 >${item.title}</h2>  
					<img src=${item.product_image.url} alt=${item.product_image.title}/>  
					<p>${item.price}</p>  
					</div>`  
		},
		// to render the default  
		'$default': (item, metadata) => {  
			return `<div>  
					<h2>${item.title}</h2>  
					<p>${item.description}</p>  
					</div>`
		}  
	},
	// to display inline embedded items  
	inline: {  
		'$default': (item, metadata) => {  
			return `<span><b>${item.title}</b> - ${item.description}</span>`
		}  
	},
	// to display embedded items inserted via link  
	link: (item, metadata) => {  
		return `<a href="${metadata.attributes.href}">${metadata.text}</a>`
	},
	// to display assets  
	display: (item, metadata) => {  
		return `<img src=${metadata.attributes.src} alt=${metadata.alt} />`
	}  
}

Basic Queries

Contentstack Utils SDK lets you interact with the Content Delivery APIs and retrieve embedded items from the RTE field of an entry.

Fetch Embedded Item(s) from a Single Entry

Render HTML RTE Embedded object

To get an embedded item of a single entry, you need to provide the stack API key, environment name, delivery token, content type and entry UID. Then, use the includeEmbeddedItems and Contentstack.Utils.render functions as shown below:

import * as Contentstack from  'contentstack'  
const stack = Contentstack.Stack({  
        api_key: '<API_KEY>',  
        delivery_token: '<ENVIRONMENT_SPECIFIC_DELIVERY_TOKEN>',  
        environment: '<ENVIRONMENT>'})  
  
stack.ContentType('<CONTENT_TYPE_UID>')  
	 .Entry('<ENTRY_UID>')  
	 .toJSON()  
	 .includeEmbeddedItems() // include embedded items  
	 .fetch()  
	 .then(entry => {  
			Contentstack.Utils.render({ entry, renderOption })  
	 })

If you have multiple RTE fields in an entry and want to fetch the embedded items from a particular RTE field, you need to provide a path of those RTE fields.

Refer to the example code below:

//code to render embedded item from an RTE field and from another RTE field nested within a group field
Contentstack.Utils.render({ entry, path: ["rte_fieldUid", "group.rteFieldUID"], renderOption })

Render Supercharged RTE contents

To get a single entry, you need to provide the stack API key, environment name, delivery token, content type and entry UID. Then, use Contentstack.Utils.jsonToHTML function as shown below:

import * as Contentstack from  'contentstack'  
const stack = Contentstack.Stack({  
        api_key: '<API_KEY>',  
        delivery_token: '<ENVIRONMENT_SPECIFIC_DELIVERY_TOKEN>',  
        environment: '<ENVIRONMENT>'})  
  
stack.ContentType('<CONTENT_TYPE_UID>')  
	 .Entry('<ENTRY_UID>')  
	 .toJSON()  
	 .fetch()  
	 .then(entry => {  
			Contentstack.Utils.jsonToHTML({ 
				entry, 
				path: ["rte_fieldUid", "group.rteFieldUID"], 
				renderOption 
			})  
	 })

Node: Supercharged RTE also supports Embedded items to get all embedded items while fetching entry use includeEmbeddedItems function.

Fetch Embedded Item(s) from Multiple Entries

Render HTML RTE Embedded object

To get embedded items from multiple entries, you need to provide the content type UID. You can also use the path variable in case the entries have multiple RTE fields.

import Contentstack from  'contentstack'  
const stack = Contentstack.Stack({  
        api_key: '<API_KEY>',  
        delivery_token: '<ENVIRONMENT_SPECIFIC_DELIVERY_TOKEN>',  
        environment: '<ENVIRONMENT>'})  
  
stack.ContentType('<CONTENT_TYPE_UID>')  
	 .Query()  
	 .toJSON()  
	 .where('title', '<entry_title_to_search>')  
	 .includeEmbeddedItems() // include embedded items  
	 .find()  
	 .then(result => {  
		result.forEach(entry => {  
		    Contentstack.Utils.render({ 
				entry, 
				path: ['rte', 'group.rteFieldUID'], 
				renderOption 
			})  
	    })  
     })

Render Supercharged RTE contents

To get a multiple entries, you need to provide the stack API key, environment name, delivery token, content type and entry UID. Then, use Contentstack.Utils.jsonToHTML function as shown below:

import * as Contentstack from  'contentstack'  
const stack = Contentstack.Stack({  
        api_key: '<API_KEY>',  
        delivery_token: '<ENVIRONMENT_SPECIFIC_DELIVERY_TOKEN>',  
        environment: '<ENVIRONMENT>'})  
  
stack.ContentType('<CONTENT_TYPE_UID>')  
	 .Query()  
	 .toJSON()  
	 .where('title', '<entry_title_to_search>')  
	 .find()  
	 .then(result => {  
		result.forEach(entry => {  
			Contentstack.Utils.jsonToHTML({ 
				entry, 
				path: ["rte_fieldUid", "group.rteFieldUID"], 
				renderOption 
			})
		})  
     })

Node: Supercharged RTE also supports Embedded items to get all embedded items while fetching entry use includeEmbeddedItems function.

contentstack-utils-javascript's People

Contributors

abhinav-from-contentstack avatar aravindbuilt avatar christopherjennings avatar contentstack-admin avatar cs-raj avatar deepak-kharah avatar dependabot[bot] avatar harshithad0703 avatar nadeem-cs avatar nandeesh-gajula avatar netrajpatel avatar reeshika-h avatar snyk-bot avatar uttamukkoji avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

contentstack-utils-javascript's Issues

[NextJS] TypeError: DOMPurify__namespace.sanitize is not a function

I encountered an issue while using the @contentstack/utils library in my project, specifically when attempting to use DOMPurify for HTML sanitization. The DOMPurify.sanitize function was not recognized, leading to a TypeError in my application. This issue seems to stem from how DOMPurify is being imported and used within the library, particularly in a server-side context, such as with NextJS.

To resolve this issue, I decided to replace dompurify with isomorphic-dompurify, which provides better compatibility for both server-side and client-side environments. The following patch demonstrates the changes I made to the @contentstack/utils library to replace DOMPurify with isomorphic-dompurify.

I believe this change can be beneficial for others who may face similar issues, and I would like to suggest incorporating this modification into the library.

Here is the diff that solved my problem:

diff --git a/node_modules/@contentstack/utils/dist/index.es.js b/node_modules/@contentstack/utils/dist/index.es.js
index 7d073f8..e54871a 100644
--- a/node_modules/@contentstack/utils/dist/index.es.js
+++ b/node_modules/@contentstack/utils/dist/index.es.js
@@ -2,7 +2,7 @@
 
 Object.defineProperty(exports, '__esModule', { value: true });
 
-var DOMPurify = require('dompurify');
+var DOMPurify = require('isomorphic-dompurify');
 
 function _interopNamespace(e) {
   if (e && e.__esModule) return e;
diff --git a/node_modules/@contentstack/utils/dist/index.es.js.map b/node_modules/@contentstack/utils/dist/index.es.js.map
index c923ae6..d00a4ed 100644
--- a/node_modules/@contentstack/utils/dist/index.es.js.map
+++ b/node_modules/@contentstack/utils/dist/index.es.js.map
@@ -1 +1 @@
-{"version":3,"file":"index.es.js","sources":["../src/Models/metadata-model.ts","../src/embedded-types/style-type.ts","../src/helper/html-to-json.ts","../src/extensions/index.ts","../src/options/default-options.ts","../src/helper/find-embeded-object.ts","../src/helper/find-render-content.ts","../src/render-embedded-objects.ts","../src/nodes/node-type.ts","../src/nodes/mark-type.ts","../src/nodes/node.ts","../src/nodes/document.ts","../src/nodes/text-node.ts","../src/options/default-node-options.ts","../src/helper/enumerate-entries.ts","../src/json-to-html.ts","../src/gql.ts","../src/entry-editable.ts"],"sourcesContent":["import StyleType from '../embedded-types/style-type';\nimport TextNode from '../nodes/text-node';\nexport interface Metadata {\n  text: string;\n  attributes: Attributes;\n\n  itemUid: string | undefined;\n  itemType: 'entry' | 'asset' | undefined;\n  styleType: StyleType | undefined;\n  contentTypeUid: string | undefined;\n}\n\nexport interface Attributes {\n  type?: 'entry' | 'asset';\n  class?: string;\n  id?: string;\n  [key: string]: any;\n  style?: styleObjType | string;\n  'sys-style-type'?: string;\n}\nexport type styleObjType = { [key: string]: any };\n\nexport interface EntryAttributes extends Attributes {\n  'data-sys-entry-uid': string;\n  'data-sys-entry-local': string;\n  'data-sys-content-type-uid': string;\n}\n\nexport interface AssetAttributes extends Attributes {\n  'data-sys-asset-uid': string;\n  'data-sys-asset-filelink': string;\n  'data-sys-asset-contenttype': string;\n}\n\nexport function createMetadata(attribute: Attributes): Metadata {\n  return {\n    text: attribute['#text'],\n    itemUid: attribute['data-sys-entry-uid'] || attribute['data-sys-asset-uid'],\n    itemType: attribute.type,\n    styleType: attribute['sys-style-type'] as StyleType,\n    attributes: attribute,\n    contentTypeUid: attribute['data-sys-content-type-uid'],\n  };\n}\n\nexport function nodeToMetadata(attribute: Attributes, textNode: TextNode): Metadata {\n  return {\n    text: textNode.text,\n    itemUid: attribute['entry-uid'] || attribute['asset-uid'],\n    itemType: attribute.type,\n    styleType: attribute['display-type'] as StyleType,\n    attributes: attribute,\n    contentTypeUid: attribute['content-type-uid'],\n  };\n}\n\nexport function attributeToString(attributes: Attributes): string {\n  let result = '';\n  for (const key in attributes) {\n    if (Object.prototype.hasOwnProperty.call(attributes, key)) {\n      let element = attributes[key];\n      if (element instanceof Array) {\n        let elementString = '';\n        let isFirst = true;\n        element.forEach((value) => {\n          if (isFirst) {\n            elementString += `${value}`;\n            isFirst = false;\n          } else {\n            elementString += `, ${value}`;\n          }\n        });\n        element = elementString;\n      } else if (typeof element === 'object') {\n        let elementString = '';\n        for (const elementKey in element) {\n          if (Object.prototype.hasOwnProperty.call(element, elementKey)) {\n            const value = element[elementKey];\n            elementString += `${elementKey}:${value}; `;\n          }\n        }\n        element = elementString;\n      }\n      result += ` ${key}=\"${element}\"`;\n    }\n  }\n  return result;\n}\n","enum StyleType {\n  BLOCK = 'block',\n  INLINE = 'inline',\n  LINK = 'link',\n  DISPLAY = 'display',\n  DOWNLOAD = 'download'\n}\n\nexport default StyleType;\n","\nexport function elementToJson(element: Element): object {\n  let obj: any = { };\n  for (let i = 0; i<element.attributes.length; i++) {\n    obj[element.attributes.item(i).name] = element.attributes.item(i).value\n  }\n  \n  element.childNodes.forEach((chileNode) => {\n    const node: ChildNode = (chileNode)\n    obj = {\n      ...obj,\n      ...parseElement(node)\n    }\n  })\n  return obj\n}\n\nfunction parseElement(node: ChildNode): any {\n  const obj: any = {}\n  if (node.nodeType === 3) {\n    obj['#text'] = node.textContent;\n  }else if (node.nodeType === 1) {\n    obj[node.nodeName.toLowerCase()] = elementToJson(node as Element)\n  }\n  return obj\n}\n","import { elementToJson } from '../helper/html-to-json';\nimport { Metadata, createMetadata, Attributes } from '../Models/metadata-model';\nconst frameflag = 'documentfragmentcontainer';\n\ndeclare global {\n  interface String {\n    forEachEmbeddedItem(callbackfn: (embededObjectTag: string, object: Metadata) => void): void;\n  }\n}\n\nString.prototype.forEachEmbeddedItem = function (\n  callbackfn: (embededObjectTag: string, object: Metadata) => void,\n): void {\n\n  const str = `<${frameflag}>${this.toString()}</${frameflag}>`;\n  const root = (new DOMParser()).parseFromString(str, 'text/html')\n  const embeddedEntries = root.querySelectorAll(\".embedded-entry\")\n  \n  embeddedEntries.forEach((element) => {    \n    callbackfn(element.outerHTML, createMetadata(elementToJson(element) as Attributes))\n  })\n  const embeddedAsset = root.querySelectorAll(\".embedded-asset\")\n  embeddedAsset.forEach((element) => {\n    callbackfn(element.outerHTML, createMetadata(elementToJson(element) as Attributes))\n  })\n};\n","import StyleType from '../embedded-types/style-type';\nimport { RenderOption } from '.';\nimport { Metadata } from '../Models/metadata-model';\nimport { EmbeddedItem } from '../Models/embedded-object';\nimport { EntryNode } from '../Models/json-rte-model';\nimport * as DOMPurify from 'dompurify';\n\nexport const defaultOptions: RenderOption = {\n  [StyleType.BLOCK]: (item: EmbeddedItem | EntryNode) => {\n    const title = DOMPurify.sanitize(item.title || item.uid);\n    const contentTypeUid = DOMPurify.sanitize(item._content_type_uid || (item.system ? item.system.content_type_uid : ''));\n    return `<div><p>${title}</p><p>Content type: <span>${contentTypeUid}</span></p></div>`;\n  },\n  [StyleType.INLINE]: (item: EmbeddedItem | EntryNode) => {\n    const title = DOMPurify.sanitize(item.title || item.uid);\n    return `<span>${title}</span>`;\n  },\n  [StyleType.LINK]: (item: EmbeddedItem | EntryNode, metadata: Metadata) => {\n    const url = DOMPurify.sanitize(item.url || 'undefined');\n    const text = DOMPurify.sanitize(metadata.text || item.title || item.uid || (item

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.