Skip to content

Commit 7ec4309

Browse files
authored
feat: convert GroupItemMetadataProvider Formatter to native HTML for CSP (#925)
* feat: convert GroupItemMetadataProvider Formatter to native HTML for CSP - in order to depend less on the use of `innerHTML`, we should convert internal code that have Formatter to use native HTML element to be more CSP compliant. However please note that the user will have to convert themselve the GroupTotals Formatter to native element as well for full CSP compliance on that section of the code
1 parent b6d02cd commit 7ec4309

File tree

2 files changed

+29
-13
lines changed

2 files changed

+29
-13
lines changed

src/slick.grid.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -524,11 +524,11 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
524524
* @param target - target element to apply to
525525
* @param val - input value can be either a string or an HTMLElement
526526
*/
527-
applyHtmlCode(target: HTMLElement, val: string | HTMLElement) {
527+
applyHtmlCode(target: HTMLElement, val: string | HTMLElement | DocumentFragment) {
528528
if (target) {
529-
if (val instanceof HTMLElement) {
529+
if (val instanceof HTMLElement || val instanceof DocumentFragment) {
530530
target.appendChild(val);
531-
} else {
531+
} else if (typeof val === 'string') {
532532
if (this._options.enableHtmlRendering) {
533533
target.innerHTML = this.sanitizeHtmlString(val as string);
534534
} else {

src/slick.groupitemmetadataprovider.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,22 +59,38 @@ export class SlickGroupItemMetadataProvider {
5959
Utils.extend(true, this._options, inputOptions);
6060
}
6161

62-
protected defaultGroupCellFormatter(_row: number, _cell: number, _value: any, _columnDef: Column, item: any): string {
62+
protected defaultGroupCellFormatter(_row: number, _cell: number, _value: any, _columnDef: Column, item: any) {
6363
if (!this._options.enableExpandCollapse) {
6464
return item.title;
6565
}
6666

6767
const indentation = `${item.level * 15}px`;
68+
const toggleClass = item.collapsed ? this._options.toggleCollapsedCssClass : this._options.toggleExpandedCssClass;
6869

69-
return (this._options.checkboxSelect ? '<span class="' + this._options.checkboxSelectCssClass +
70-
' ' + (item.selectChecked ? 'checked' : 'unchecked') + '"></span>' : '') +
71-
'<span class="' + this._options.toggleCssClass + ' ' +
72-
(item.collapsed ? this._options.toggleCollapsedCssClass : this._options.toggleExpandedCssClass) +
73-
'" style="margin-left:' + indentation + '">' +
74-
'</span>' +
75-
'<span class="' + this._options.groupTitleCssClass + '" level="' + item.level + '">' +
76-
item.title +
77-
'</span>';
70+
// use a DocumentFragment to avoid creating an extra div container
71+
const containerElm = document.createDocumentFragment();
72+
73+
// 1. optional row checkbox span to select the entire group rows
74+
if (this._options.checkboxSelect) {
75+
containerElm.appendChild(Utils.createDomElement('span', { className: `${this._options.checkboxSelectCssClass} ${item.selectChecked ? 'checked' : 'unchecked'}` }));
76+
}
77+
78+
// 2. group toggle span
79+
containerElm.appendChild(Utils.createDomElement('span', {
80+
className: `${this._options.toggleCssClass} ${toggleClass}`,
81+
ariaExpanded: String(!item.collapsed),
82+
style: { marginLeft: indentation }
83+
}));
84+
85+
// 3. group title span
86+
const groupTitleElm = Utils.createDomElement('span', { className: this._options.groupTitleCssClass || '' });
87+
groupTitleElm.setAttribute('level', item.level);
88+
(item.title instanceof HTMLElement)
89+
? groupTitleElm.appendChild(item.title)
90+
: this._grid.applyHtmlCode(groupTitleElm, item.title ?? '');
91+
containerElm.appendChild(groupTitleElm);
92+
93+
return containerElm;
7894
}
7995

8096
protected defaultTotalsCellFormatter(_row: number, _cell: number, _value: any, columnDef: Column, item: any, grid: SlickGrid) {

0 commit comments

Comments
 (0)