Skip to content

chore: Added colgroup tag support #124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion __test__/mock/json-element-mock-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const h6Html = "<h6>Nunc porta diam vitae purus semper, ut consequat lorem vehic
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>"
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>"
const imgHtml = "<img src=\"https://image.url/Donald.jog.png\" />"
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>"
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>"
const blockquoteHtml = "<blockquote>Praesent eu ex sed nibh venenatis pretium.</blockquote>"
const codeHtml = "<code>Code template.</code>"
const linkInPHtml = "<strong><em><u><sub></sub></u></em></strong><a href=\"LINK.com\">LINK</a>"
Expand Down
6 changes: 3 additions & 3 deletions src/helper/sanitize.ts
Original file line number Diff line number Diff line change
@@ -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 : '';
Expand Down
2 changes: 2 additions & 0 deletions src/nodes/node-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
22 changes: 20 additions & 2 deletions src/options/default-node-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,26 @@ export const defaultNodeOption: RenderOption = {
[NodeType.HR]:(node: Node, next: Next) => {
return `<hr>`
},
[NodeType.TABLE]:(node: Node, next: Next) => {
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>`
[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 += `</${NodeType.COL_GROUP}>`;
}

// Generate table with colgroup and other attributes
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}"` : ``}>` +
`${colgroupHTML}` +
`${sanitizeHTML(next(node.children))}` +
`</table>`;
},
[NodeType.TABLE_HEADER]:(node: Node, next: Next) => {
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>`
Expand Down
Loading