Skip to content

Commit 18485cc

Browse files
authored
Merge pull request #126 from contentstack/staging
DX | 22-01-2025 | Hotfix
2 parents 97b8f2b + 02b0838 commit 18485cc

File tree

11 files changed

+94
-57
lines changed

11 files changed

+94
-57
lines changed

.github/workflows/check-branch.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ jobs:
88
runs-on: ubuntu-latest
99
steps:
1010
- name: Comment PR
11-
if: github.base_ref == 'master' && github.head_ref != 'staging'
11+
if: github.base_ref == 'staging' && github.head_ref != 'development'
1212
uses: thollander/actions-comment-pull-request@v2
1313
with:
1414
message: |
15-
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.
15+
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.
1616
- name: Check branch
17-
if: github.base_ref == 'master' && github.head_ref != 'staging'
17+
if: github.base_ref == 'staging' && github.head_ref != 'development'
1818
run: |
19-
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."
19+
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."
2020
exit 1

.github/workflows/npm-publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ jobs:
2929
registry-url: 'https://npm.pkg.github.com'
3030
scope: '@contentstack'
3131
- run: npm ci
32-
- run: npm publish
32+
- run: npm publish --access public
3333
env:
3434
NODE_AUTH_TOKEN: ${{ secrets.GIT_TOKEN }}

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## [1.3.16](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.16) (2025-01-27)
4+
- Enh: Added support for colgroup and col tags inside table tag
5+
- Fix: Updated rendorOption code block in reaadme file
6+
37
## [1.3.15](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.15) (2024-11-18)
48
- Fix: Added Table merge cell functionality
59

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
The MIT License (MIT)
22

33

4-
Copyright (c) 2016-2024 Contentstack
4+
Copyright (c) 2016-2025 Contentstack
55

66
Permission is hereby granted, free of charge, to any person obtaining a copy
77
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 55 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -23,48 +23,61 @@ Let’s learn how you can use Utils SDK to render RTE embedded items and Superch
2323
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:
2424
```js
2525
const renderOption = {
26-
// to render Supercharged RTE NodeType content like paragraph, link, table, order list, un-order list and more.
27-
p: (node, next) => {
28-
return `<p class='class-id'>${next(node.children)}</p>` // you will need to call next function with node children contents
29-
},
30-
h1: (node, next) => {
31-
return `<h1 class='class-id'>${next(node.children)}</h1>` // you will need to call next function with node children contents
32-
},
33-
// to render Supercharged RTE MarkType content like bold, italic, underline, strikethrough, inlineCode, subscript, and superscript
34-
bold: (text) => {
35-
return `<b>${next(node.children)}</b>`
36-
},
37-
// to render block-type embedded items
38-
block: {
39-
'product': (item, metadata) => {
40-
return `<div>
41-
<h2 >${item.title}</h2>
42-
<img src=${item.product_image.url} alt=${item.product_image.title}/>
43-
<p>${item.price}</p>
44-
</div>`
45-
},
46-
// to render the default
47-
'$default': (item, metadata) => {
48-
return `<div>
49-
<h2>${item.title}</h2>
50-
<p>${item.description}</p>
51-
</div>`
52-
}
53-
},
54-
// to display inline embedded items
55-
inline: {
56-
'$default': (item, metadata) => {
57-
return `<span><b>${item.title}</b> - ${item.description}</span>`
58-
}
59-
},
60-
// to display embedded items inserted via link
61-
link: (item, metadata) => {
62-
return `<a href="${metadata.attributes.href}">${metadata.text}</a>`
63-
},
64-
// to display assets
65-
display: (item, metadata) => {
66-
return `<img src=${metadata.attributes.src} alt=${metadata.alt} />`
67-
}
26+
// To render paragraph nodes
27+
p: (node, next) => `<p class="class-id">${next(node.children)}</p>`,
28+
// To render heading level 1 nodes
29+
h1: (node, next) => `<h1 class="class-id">${next(node.children)}</h1>`,
30+
// To render bold text
31+
bold: (text) => `<b>${text}</b>`,
32+
// To render block-type embedded items
33+
block: {
34+
product: (item) =>
35+
`<div>
36+
<h2>${item.title}</h2>
37+
<img src="${item.product_image.url}" alt="${item.product_image.title}" />
38+
<p>${item.price}</p>
39+
</div>`,
40+
$default: (item) =>
41+
`<div>
42+
<h2>${item.title}</h2>
43+
<p>${item.description}</p>
44+
</div>`,
45+
},
46+
// To render inline embedded items
47+
inline: {
48+
$default: (item) =>
49+
`<span><b>${item.title}</b> - ${item.description}</span>`,
50+
},
51+
// To render link (a) nodes
52+
a: (node) => {
53+
const { attrs, children } = node;
54+
const childText = children.map((child) => child.text || '').join('');
55+
return `<a href="${attrs.url}" target="${attrs.target || '_self'}">${childText}</a>`;
56+
},
57+
// To render embedded assets
58+
display: (item, metadata) => {
59+
const { attributes } = metadata;
60+
return `<img src="${attributes.src}" alt="${attributes.alt || 'Asset'}" />`;
61+
},
62+
// To render embedded entry & asset references
63+
reference: (node) => {
64+
const { attrs, children } = node;
65+
const childText = children.map((child) => child.text || '').join('');
66+
if (attrs.type === 'entry') {
67+
return `<a href="${attrs.href}" class="${attrs['class-name'] || ''}">${childText}</a>`;
68+
} else if (attrs.type === 'asset') {
69+
if (attrs['display-type'] === 'link') {
70+
return `<a href="${attrs['asset-link']}" class="${attrs['class-name'] || ''}" target="_blank">${attrs['asset-name'] || 'View Asset'}</a>`;
71+
}
72+
73+
if (attrs['display-type'] === 'display') {
74+
return `<img src="${attrs['asset-link']}" alt="${attrs['asset-alt'] || attrs['asset-name']}" class="${attrs['class-name'] || ''}" />`;
75+
}
76+
}
77+
return childText; // Fallback for unknown references
78+
},
79+
// Default handler for unknown nodes
80+
default: (node, next) => `<div>${next(node.children)}</div>`,
6881
}
6982
```
7083

__test__/mock/json-element-mock-result.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const h6Html = "<h6>Nunc porta diam vitae purus semper, ut consequat lorem vehic
99
const orderListHtml = "<ol class=\"table\" id=\"table_id\"><li style=\"text-align:justify;\" class=\"class\">Morbi in quam molestie, fermentum diam vitae, bibendum ipsum.</li><li style=\"text-align:justify;\">Pellentesque mattis lacus in quam aliquam congue</li><li style=\"text-align:justify;\">Integer feugiat leo dignissim, lobortis enim vitae, mollis lectus.</li><li style=\"text-align:justify;\">Sed in ante lacinia, molestie metus eu, fringilla sapien.</li></ol>"
1010
const unorderListHtml = "<ul class=\"table\" id=\"table_id\"><li>Sed quis metus sed mi hendrerit mollis vel et odio.</li><li>Integer vitae sem dignissim, elementum libero vel, fringilla massa.</li><li>Integer imperdiet arcu sit amet tortor faucibus aliquet.</li><li>Aenean scelerisque velit vitae dui vehicula, at congue massa sagittis.</li></ul>"
1111
const imgHtml = "<img src=\"https://image.url/Donald.jog.png\" />"
12-
const tableHtml = "<table><thead class=\"class\"><tr><th><p>Header 1</p></th><th><p>Header 2</p></th></tr></thead><tbody class=\"class\" id=\"id\"><tr class=\"class\" id=\"id\"><td><p>Body row 1 data 1</p></td><td class=\"class\" id=\"id\"><p>Body row 1 data 2</p></td></tr><tr id=\"class\"><td><p>Body row 2 data 1</p></td><td><p class=\"class\">Body row 2 data 2</p></td></tr></tbody></table>"
12+
const tableHtml = "<table><colgroup data-width=\"500\"><col style=\"width:50.00%\"/><col style=\"width:50.00%\"/></colgroup><thead class=\"class\"><tr><th><p>Header 1</p></th><th><p>Header 2</p></th></tr></thead><tbody class=\"class\" id=\"id\"><tr class=\"class\" id=\"id\"><td><p>Body row 1 data 1</p></td><td class=\"class\" id=\"id\"><p>Body row 1 data 2</p></td></tr><tr id=\"class\"><td><p>Body row 2 data 1</p></td><td><p class=\"class\">Body row 2 data 2</p></td></tr></tbody></table>"
1313
const blockquoteHtml = "<blockquote>Praesent eu ex sed nibh venenatis pretium.</blockquote>"
1414
const codeHtml = "<code>Code template.</code>"
1515
const linkInPHtml = "<strong><em><u><sub></sub></u></em></strong><a href=\"LINK.com\">LINK</a>"

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@contentstack/utils",
3-
"version": "1.3.15",
3+
"version": "1.3.16",
44
"description": "Contentstack utilities for Javascript",
55
"main": "dist/index.es.js",
66
"types": "dist/types/index.d.ts",

src/helper/sanitize.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11

2-
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';
3-
type AllowedAttributes = 'href' | 'title' | 'target' | 'alt' | 'src' | 'class' | 'id' | 'style' | 'colspan' | 'rowspan' | 'content-type-uid' | 'data-sys-asset-uid' | 'sys-style-type' | 'data-type';
2+
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';
3+
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';
44

5-
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 {
5+
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 {
66
// Regular expression to find and remove all HTML tags except the allowed ones
77
const sanitized = input.replace(/<\/?([a-z][a-z0-9]*)\b[^<>]*>/gi, (match, tag) => {
88
return allowedTags.includes(tag.toLowerCase()) ? match : '';

src/nodes/node-type.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ enum NodeType {
2727
TABLE_ROW = 'tr',
2828
TABLE_HEAD = 'th',
2929
TABLE_DATA = 'td',
30+
COL_GROUP = 'colgroup',
31+
COL = 'col',
3032

3133
BLOCK_QUOTE = 'blockquote',
3234
CODE = 'code',

src/options/default-node-options.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,26 @@ export const defaultNodeOption: RenderOption = {
5959
[NodeType.HR]:(node: Node, next: Next) => {
6060
return `<hr>`
6161
},
62-
[NodeType.TABLE]:(node: Node, next: Next) => {
63-
return `<table${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</table>`
62+
[NodeType.TABLE]: (node: Node, next: Next) => {
63+
// Generate colgroup if colWidths attribute is present
64+
let colgroupHTML = '';
65+
if (node.attrs.colWidths && Array.isArray(node.attrs.colWidths)) {
66+
const totalWidth = node.attrs.colWidths.reduce((sum, width) => sum + width, 0);
67+
colgroupHTML = `<${NodeType.COL_GROUP} data-width="${totalWidth}">`;
68+
node.attrs.colWidths.forEach(colWidth => {
69+
const widthPercentage = (colWidth / totalWidth) * 100;
70+
colgroupHTML += `<${NodeType.COL} style="width:${widthPercentage.toFixed(2)}%"/>`;
71+
});
72+
colgroupHTML += `</${NodeType.COL_GROUP}>`;
73+
}
74+
75+
// Generate table with colgroup and other attributes
76+
return `<table${node.attrs.style ? ` style="${node.attrs.style}"` : ``}` +
77+
`${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}` +
78+
`${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>` +
79+
`${colgroupHTML}` +
80+
`${sanitizeHTML(next(node.children))}` +
81+
`</table>`;
6482
},
6583
[NodeType.TABLE_HEADER]:(node: Node, next: Next) => {
6684
return `<thead${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</thead>`

0 commit comments

Comments
 (0)