From 54c48047e366e31aa1e58f0af5a815d18dec5f21 Mon Sep 17 00:00:00 2001 From: sunil-lakshman <104969541+sunil-lakshman@users.noreply.github.com> Date: Tue, 10 Dec 2024 15:19:37 +0530 Subject: [PATCH 1/3] chore: Updated rendorOption in readme file (#123) --- CHANGELOG.md | 2 + README.md | 97 +++++++++++++++++++++++++++-------------------- package-lock.json | 4 +- package.json | 2 +- 4 files changed, 60 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2ba45d..3edc932 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ # Changelog +## [1.3.16](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.16) (2024-12-11) + - Fix: Updated rendorOption code block in reaadme file ## [1.3.15](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.15) (2024-11-18) - Fix: Added Table merge cell functionality diff --git a/README.md b/README.md index 112559a..26d3197 100644 --- a/README.md +++ b/README.md @@ -23,48 +23,61 @@ Let’s learn how you can use Utils SDK to render RTE embedded items and Superch 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: ```js const renderOption = { - // to render Supercharged RTE NodeType content like paragraph, link, table, order list, un-order list and more. - p: (node, next) => { - return `

${next(node.children)}

` // you will need to call next function with node children contents - }, - h1: (node, next) => { - return `

${next(node.children)}

` // 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 `${next(node.children)}` - }, - // to render block-type embedded items - block: { - 'product': (item, metadata) => { - return `
-

${item.title}

- ${item.product_image.title}/ -

${item.price}

-
` - }, - // to render the default - '$default': (item, metadata) => { - return `
-

${item.title}

-

${item.description}

-
` - } - }, - // to display inline embedded items - inline: { - '$default': (item, metadata) => { - return `${item.title} - ${item.description}` - } - }, - // to display embedded items inserted via link - link: (item, metadata) => { - return `${metadata.text}` - }, - // to display assets - display: (item, metadata) => { - return `${metadata.alt}` - } + // To render paragraph nodes + p: (node, next) => `

${next(node.children)}

`, + // To render heading level 1 nodes + h1: (node, next) => `

${next(node.children)}

`, + // To render bold text + bold: (text) => `${text}`, + // To render block-type embedded items + block: { + product: (item) => + `
+

${item.title}

+ ${item.product_image.title} +

${item.price}

+
`, + $default: (item) => + `
+

${item.title}

+

${item.description}

+
`, + }, + // To render inline embedded items + inline: { + $default: (item) => + `${item.title} - ${item.description}`, + }, + // To render link (a) nodes + a: (node) => { + const { attrs, children } = node; + const childText = children.map((child) => child.text || '').join(''); + return `${childText}`; + }, + // To render embedded assets + display: (item, metadata) => { + const { attributes } = metadata; + return `${attributes.alt || 'Asset'}`; + }, + // To render embedded entry & asset references + reference: (node) => { + const { attrs, children } = node; + const childText = children.map((child) => child.text || '').join(''); + if (attrs.type === 'entry') { + return `${childText}`; + } else if (attrs.type === 'asset') { + if (attrs['display-type'] === 'link') { + return `${attrs['asset-name'] || 'View Asset'}`; + } + + if (attrs['display-type'] === 'display') { + return `${attrs['asset-alt'] || attrs['asset-name']}`; + } + } + return childText; // Fallback for unknown references + }, + // Default handler for unknown nodes + default: (node, next) => `
${next(node.children)}
`, } ``` diff --git a/package-lock.json b/package-lock.json index aaef3a7..1f48aba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@contentstack/utils", - "version": "1.3.15", + "version": "1.3.16", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentstack/utils", - "version": "1.3.15", + "version": "1.3.16", "license": "MIT", "devDependencies": { "@babel/preset-env": "^7.26.0", diff --git a/package.json b/package.json index 294c75a..c159b0c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/utils", - "version": "1.3.15", + "version": "1.3.16", "description": "Contentstack utilities for Javascript", "main": "dist/index.es.js", "types": "dist/types/index.d.ts", From 2d621f55c9c8f6525c96607a3dabbb41e80120ac Mon Sep 17 00:00:00 2001 From: sunil-lakshman <104969541+sunil-lakshman@users.noreply.github.com> Date: Tue, 21 Jan 2025 13:30:52 +0530 Subject: [PATCH 2/3] chore: Added colgroup tag support (#124) --- CHANGELOG.md | 4 +++- LICENSE | 2 +- __test__/mock/json-element-mock-result.ts | 2 +- src/helper/sanitize.ts | 6 +++--- src/nodes/node-type.ts | 2 ++ src/options/default-node-options.ts | 22 ++++++++++++++++++++-- 6 files changed, 30 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3edc932..8379a89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog -## [1.3.16](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.16) (2024-12-11) + +## [1.3.16](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.16) (2025-01-27) + - Enh: Added support for colgroup and col tags inside table tag - Fix: Updated rendorOption code block in reaadme file ## [1.3.15](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.15) (2024-11-18) diff --git a/LICENSE b/LICENSE index 66737f1..0c5a253 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ The MIT License (MIT) -Copyright (c) 2016-2024 Contentstack +Copyright (c) 2016-2025 Contentstack Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/__test__/mock/json-element-mock-result.ts b/__test__/mock/json-element-mock-result.ts index 0951311..a4fab81 100644 --- a/__test__/mock/json-element-mock-result.ts +++ b/__test__/mock/json-element-mock-result.ts @@ -9,7 +9,7 @@ const h6Html = "
Nunc porta diam vitae purus semper, ut consequat lorem vehic const orderListHtml = "
  1. Morbi in quam molestie, fermentum diam vitae, bibendum ipsum.
  2. Pellentesque mattis lacus in quam aliquam congue
  3. Integer feugiat leo dignissim, lobortis enim vitae, mollis lectus.
  4. Sed in ante lacinia, molestie metus eu, fringilla sapien.
" const unorderListHtml = "" const imgHtml = "" -const tableHtml = "

Header 1

Header 2

Body row 1 data 1

Body row 1 data 2

Body row 2 data 1

Body row 2 data 2

" +const tableHtml = "

Header 1

Header 2

Body row 1 data 1

Body row 1 data 2

Body row 2 data 1

Body row 2 data 2

" const blockquoteHtml = "
Praesent eu ex sed nibh venenatis pretium.
" const codeHtml = "Code template." const linkInPHtml = "LINK" diff --git a/src/helper/sanitize.ts b/src/helper/sanitize.ts index ec66426..b2d66ca 100644 --- a/src/helper/sanitize.ts +++ b/src/helper/sanitize.ts @@ -1,8 +1,8 @@ -type AllowedTags = 'p' | 'a' | 'strong' | 'em' | 'ul' | 'ol' | 'li' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'sub' | 'u' | 'table' | 'thead' | 'tbody' | 'tr' | 'th' | 'td' | 'span' | 'fragment' | 'strike' | 'sup' | 'br'| 'img'; -type AllowedAttributes = 'href' | 'title' | 'target' | 'alt' | 'src' | 'class' | 'id' | 'style' | 'colspan' | 'rowspan' | 'content-type-uid' | 'data-sys-asset-uid' | 'sys-style-type' | 'data-type'; +type AllowedTags = 'p' | 'a' | 'strong' | 'em' | 'ul' | 'ol' | 'li' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'sub' | 'u' | 'table' | 'thead' | 'tbody' | 'tr' | 'th' | 'td' | 'span' | 'fragment' | 'strike' | 'sup' | 'br'| 'img' | 'colgroup' | 'col' | 'div'; +type AllowedAttributes = 'href' | 'title' | 'target' | 'alt' | 'src' | 'class' | 'id' | 'style' | 'colspan' | 'rowspan' | 'content-type-uid' | 'data-sys-asset-uid' | 'sys-style-type' | 'data-type' | 'data-width' | 'data-rows' | 'data-cols'; -export function sanitizeHTML(input: string, allowedTags: AllowedTags[] = ['p', 'a', 'strong', 'em', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'sub', 'u', 'table', 'thead', 'tbody', 'tr', 'th', 'td', 'span', 'fragment', 'sup', 'strike', 'br', 'img'], allowedAttributes: AllowedAttributes[] = ['href', 'title', 'target', 'alt', 'src', 'class', 'id', 'style', 'colspan', 'rowspan', 'content-type-uid', 'data-sys-asset-uid', 'sys-style-type', 'data-type']): string { +export function sanitizeHTML(input: string, allowedTags: AllowedTags[] = ['p', 'a', 'strong', 'em', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'sub', 'u', 'table', 'thead', 'tbody', 'tr', 'th', 'td', 'span', 'fragment', 'sup', 'strike', 'br', 'img', 'colgroup', 'col', 'div'], allowedAttributes: AllowedAttributes[] = ['href', 'title', 'target', 'alt', 'src', 'class', 'id', 'style', 'colspan', 'rowspan', 'content-type-uid', 'data-sys-asset-uid', 'sys-style-type', 'data-type', 'data-width', 'data-rows', 'data-cols']): string { // Regular expression to find and remove all HTML tags except the allowed ones const sanitized = input.replace(/<\/?([a-z][a-z0-9]*)\b[^<>]*>/gi, (match, tag) => { return allowedTags.includes(tag.toLowerCase()) ? match : ''; diff --git a/src/nodes/node-type.ts b/src/nodes/node-type.ts index d7b6fa7..392cc70 100644 --- a/src/nodes/node-type.ts +++ b/src/nodes/node-type.ts @@ -27,6 +27,8 @@ enum NodeType { TABLE_ROW = 'tr', TABLE_HEAD = 'th', TABLE_DATA = 'td', + COL_GROUP = 'colgroup', + COL = 'col', BLOCK_QUOTE = 'blockquote', CODE = 'code', diff --git a/src/options/default-node-options.ts b/src/options/default-node-options.ts index ca516d1..f6a64a2 100644 --- a/src/options/default-node-options.ts +++ b/src/options/default-node-options.ts @@ -59,8 +59,26 @@ export const defaultNodeOption: RenderOption = { [NodeType.HR]:(node: Node, next: Next) => { return `
` }, - [NodeType.TABLE]:(node: Node, next: Next) => { - return `${sanitizeHTML(next(node.children))}` + [NodeType.TABLE]: (node: Node, next: Next) => { + // Generate colgroup if colWidths attribute is present + let colgroupHTML = ''; + if (node.attrs.colWidths && Array.isArray(node.attrs.colWidths)) { + const totalWidth = node.attrs.colWidths.reduce((sum, width) => sum + width, 0); + colgroupHTML = `<${NodeType.COL_GROUP} data-width="${totalWidth}">`; + node.attrs.colWidths.forEach(colWidth => { + const widthPercentage = (colWidth / totalWidth) * 100; + colgroupHTML += `<${NodeType.COL} style="width:${widthPercentage.toFixed(2)}%"/>`; + }); + colgroupHTML += ``; + } + + // Generate table with colgroup and other attributes + return `` + + `${colgroupHTML}` + + `${sanitizeHTML(next(node.children))}` + + ``; }, [NodeType.TABLE_HEADER]:(node: Node, next: Next) => { return `${sanitizeHTML(next(node.children))}` From af8ca414cee5999de895ebb5a49a1f71033aa534 Mon Sep 17 00:00:00 2001 From: sunil-lakshman <104969541+sunil-lakshman@users.noreply.github.com> Date: Tue, 21 Jan 2025 13:33:14 +0530 Subject: [PATCH 3/3] chore: Updated check branch workflow file (#116) * chore: Updated check branch workflow file * chore: updated workflow file --- .github/workflows/check-branch.yml | 8 ++++---- .github/workflows/npm-publish.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/check-branch.yml b/.github/workflows/check-branch.yml index 8a3a32a..c63e084 100644 --- a/.github/workflows/check-branch.yml +++ b/.github/workflows/check-branch.yml @@ -8,13 +8,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Comment PR - if: github.base_ref == 'master' && github.head_ref != 'staging' + if: github.base_ref == 'staging' && github.head_ref != 'development' uses: thollander/actions-comment-pull-request@v2 with: message: | - We regret to inform you that you are currently not able to merge your changes into the master branch due to restrictions applied by our SRE team. To proceed with merging your changes, we kindly request that you create a pull request from the staging branch. Our team will then review the changes and work with you to ensure a successful merge into the master branch. + We regret to inform you that you are currently not able to merge your changes into the master branch due to restrictions applied by our SRE team. To proceed with merging your changes, we kindly request that you create a pull request from the development branch. Our team will then review the changes and work with you to ensure a successful merge into the master branch. - name: Check branch - if: github.base_ref == 'master' && github.head_ref != 'staging' + if: github.base_ref == 'staging' && github.head_ref != 'development' run: | - echo "ERROR: We regret to inform you that you are currently not able to merge your changes into the master branch due to restrictions applied by our SRE team. To proceed with merging your changes, we kindly request that you create a pull request from the staging branch. Our team will then review the changes and work with you to ensure a successful merge into the master branch." + echo "ERROR: We regret to inform you that you are currently not able to merge your changes into the master branch due to restrictions applied by our SRE team. To proceed with merging your changes, we kindly request that you create a pull request from the development branch. Our team will then review the changes and work with you to ensure a successful merge into the master branch." exit 1 \ No newline at end of file diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index d11409a..350b03d 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -29,6 +29,6 @@ jobs: registry-url: 'https://npm.pkg.github.com' scope: '@contentstack' - run: npm ci - - run: npm publish + - run: npm publish --access public env: NODE_AUTH_TOKEN: ${{ secrets.GIT_TOKEN }}