Skip to content

Commit f3b1591

Browse files
authored
Merge pull request #78 from contentstack/fix/DX-825-SRE-vulnerability
fix: sre vulnerability issue fixed
2 parents 4716bf9 + 0242b59 commit f3b1591

File tree

3 files changed

+84
-42
lines changed

3 files changed

+84
-42
lines changed

src/helper/sanitize.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
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';
3+
type AllowedAttributes = 'href' | 'title' | 'target' | 'alt' | 'src' | 'class' | 'id' | 'style';
4+
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'], allowedAttributes: AllowedAttributes[] = ['href', 'title', 'target', 'alt', 'src', 'class', 'id', 'style']): string {
6+
// Regular expression to find and remove all HTML tags except the allowed ones
7+
const sanitized = input.replace(/<\/?([a-z][a-z0-9]*)\b[^<>]*>/gi, (match, tag) => {
8+
return allowedTags.includes(tag.toLowerCase()) ? match : '';
9+
});
10+
11+
// Regular expression to remove all attributes except the allowed ones
12+
const cleaned = sanitized.replace(/\s([a-z:]+)=['"][^'"]*['"]/gi
13+
, (match, attribute) => {
14+
return allowedAttributes.includes(attribute.toLowerCase()) ? match : '';
15+
});
16+
17+
return cleaned;
18+
}
19+

src/options/default-node-options.ts

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,73 +2,77 @@ import { Next, RenderOption } from ".";
22
import MarkType from "../nodes/mark-type";
33
import Node from "../nodes/node";
44
import NodeType from "../nodes/node-type";
5+
import { sanitizeHTML } from "../helper/sanitize";
56

67
export const defaultNodeOption: RenderOption = {
78
[NodeType.DOCUMENT]:(node: Node) => {
89
return ``
910
},
1011
[NodeType.PARAGRAPH]:(node: Node, next: Next) => {
11-
return `<p${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</p>`
12+
return `<p${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))}</p>`
1213
},
1314
[NodeType.LINK]:(node: Node, next: Next) => {
15+
const sanitizedHref = sanitizeHTML(node.attrs.href || node.attrs.url);
1416
if (node.attrs.target) {
15-
return `<a${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} href="${node.attrs.href || node.attrs.url}" target="${node.attrs.target}">${next(node.children)}</a>`
17+
return `<a${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} href="${sanitizedHref}" target="${node.attrs.target}">${sanitizeHTML(next(node.children))}</a>`
1618
}
17-
return `<a${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} href="${node.attrs.href || node.attrs.url}">${next(node.children)}</a>`
19+
return `<a${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} href="${sanitizedHref}">${sanitizeHTML(next(node.children))}</a>`
1820
},
1921
[NodeType.IMAGE]:(node: Node, next: Next) => {
20-
return `<img${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} src="${node.attrs.src || node.attrs.url}" />${next(node.children)}`
22+
const sanitizedSrc = sanitizeHTML(node.attrs.src || node.attrs.url);
23+
return `<img${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} src="${sanitizedSrc}" />${sanitizeHTML(next(node.children))}`
2124
},
2225
[NodeType.EMBED]:(node: Node, next: Next) => {
23-
return `<iframe${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} src="${node.attrs.src || node.attrs.url}">${next(node.children)}</iframe>`
26+
const sanitizedSrc = sanitizeHTML(node.attrs.src || node.attrs.url);
27+
return `<iframe${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} src="${sanitizedSrc}">${sanitizeHTML(next(node.children))}</iframe>`
2428
},
2529
[NodeType.HEADING_1]:(node: Node, next: Next) => {
26-
return `<h1${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</h1>`
30+
return `<h1${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))}</h1>`
2731
},
2832
[NodeType.HEADING_2]:(node: Node, next: Next) => {
29-
return `<h2${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</h2>`
33+
return `<h2${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))}</h2>`
3034
},
3135
[NodeType.HEADING_3]:(node: Node, next: Next) => {
32-
return `<h3${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</h3>`
36+
return `<h3${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))}</h3>`
3337
},
3438
[NodeType.HEADING_4]:(node: Node, next: Next) => {
35-
return `<h4${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</h4>`
39+
return `<h4${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))}</h4>`
3640
},
3741
[NodeType.HEADING_5]:(node: Node, next: Next) => {
38-
return `<h5${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</h5>`
42+
return `<h5${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))}</h5>`
3943
},
4044
[NodeType.HEADING_6]:(node: Node, next: Next) => {
41-
return `<h6${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</h6>`
45+
return `<h6${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))}</h6>`
4246
},
4347
[NodeType.ORDER_LIST]:(node: Node, next: Next) => {
44-
return `<ol${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</ol>`
48+
return `<ol${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))}</ol>`
4549
},
4650
[NodeType.FRAGMENT]:(node: Node, next: Next) => {
47-
return `<fragment>${next(node.children)}</fragment>`
51+
return `<fragment>${sanitizeHTML(next(node.children))}</fragment>`
4852
},
4953
[NodeType.UNORDER_LIST]:(node: Node, next: Next) => {
50-
return `<ul${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</ul>`
54+
return `<ul${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))}</ul>`
5155
},
5256
[NodeType.LIST_ITEM]:(node: Node, next: Next) => {
53-
return `<li${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</li>`
57+
return `<li${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))}</li>`
5458
},
5559
[NodeType.HR]:(node: Node, next: Next) => {
5660
return `<hr>`
5761
},
5862
[NodeType.TABLE]:(node: Node, next: Next) => {
59-
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}"` : ``}>${next(node.children)}</table>`
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>`
6064
},
6165
[NodeType.TABLE_HEADER]:(node: Node, next: Next) => {
62-
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}"` : ``}>${next(node.children)}</thead>`
66+
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>`
6367
},
6468
[NodeType.TABLE_BODY]:(node: Node, next: Next) => {
65-
return `<tbody${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</tbody>`
69+
return `<tbody${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))}</tbody>`
6670
},
6771
[NodeType.TABLE_FOOTER]:(node: Node, next: Next) => {
68-
return `<tfoot${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</tfoot>`
72+
return `<tfoot${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))}</tfoot>`
6973
},
7074
[NodeType.TABLE_ROW]:(node: Node, next: Next) => {
71-
return `<tr${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</tr>`
75+
return `<tr${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))}</tr>`
7276
},
7377
[NodeType.TABLE_HEAD]:(node: Node, next: Next) => {
7478
if (node.attrs.void) return '';
@@ -78,7 +82,7 @@ export const defaultNodeOption: RenderOption = {
7882
`${node.attrs.colSpan ? ` colspan="${node.attrs.colSpan}"` : ``}` +
7983
`${node.attrs.style ? ` style="${node.attrs.style}"` : ``}`+
8084
`${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}`+
81-
`${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}` +
85+
`${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}` +
8286
`</th>`
8387
},
8488
[NodeType.TABLE_DATA]:(node: Node, next: Next) => {
@@ -89,52 +93,52 @@ export const defaultNodeOption: RenderOption = {
8993
`${node.attrs.colSpan ? ` colspan="${node.attrs.colSpan}"` : ``}` +
9094
`${node.attrs.style ? ` style="${node.attrs.style}"` : ``}`+
9195
`${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}`+
92-
`${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}` +
96+
`${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}` +
9397
`</td>`
9498
},
9599
[NodeType.BLOCK_QUOTE]:(node: Node, next: Next) => {
96-
return `<blockquote${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</blockquote>`
100+
return `<blockquote${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</blockquote>`
97101
},
98102
[NodeType.CODE]:(node: Node, next: Next) => {
99-
return `<code${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${next(node.children)}</code>`
103+
return `<code${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``}>${sanitizeHTML(next(node.children))}</code>`
100104
},
101105

102106
['reference']:(node: Node, next: Next) => {
103107
if (node.attrs.type === 'asset') {
104-
return `<img${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} src="${node.attrs['asset-link']}" />`
108+
return `<img${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${sanitizeHTML(node.attrs['class-name'])}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} src="${sanitizeHTML(node.attrs['asset-link'])}" />`
105109
}
106110
return ``
107111
},
108112
['default']:(node: Node, next: Next) => {
109-
return next(node.children)
113+
return sanitizeHTML(next(node.children))
110114
},
111115

112116
[MarkType.BOLD]:(text: string) => {
113-
return `<strong>${text}</strong>`
117+
return `<strong>${sanitizeHTML(text)}</strong>`
114118
},
115119
[MarkType.ITALIC]:(text: string) => {
116-
return `<em>${text}</em>`
120+
return `<em>${sanitizeHTML(text)}</em>`
117121
},
118122
[MarkType.UNDERLINE]:(text: string) => {
119-
return `<u>${text}</u>`
123+
return `<u>${sanitizeHTML(text)}</u>`
120124
},
121125
[MarkType.STRIKE_THROUGH]:(text: string) => {
122-
return `<strike>${text}</strike>`
126+
return `<strike>${sanitizeHTML(text)}</strike>`
123127
},
124128
[MarkType.INLINE_CODE]:(text: string) => {
125-
return `<span>${text}</span>`
129+
return `<span>${sanitizeHTML(text)}</span>`
126130
},
127131
[MarkType.SUBSCRIPT]:(text: string) => {
128-
return `<sub>${text}</sub>`
132+
return `<sub>${sanitizeHTML(text)}</sub>`
129133
},
130134
[MarkType.SUPERSCRIPT]:(text: string) => {
131-
return `<sup>${text}</sup>`
135+
return `<sup>${sanitizeHTML(text)}</sup>`
132136
},
133137
[MarkType.BREAK]:(text: string) => {
134-
return `<br />${text}`
138+
return `<br />${sanitizeHTML(text)}`
135139
},
136140
[MarkType.CLASSNAME_OR_ID]:(text: string, classname: string, id:string) => {
137-
return `<span${classname ? ` class="${classname}"` : ``}${id ? ` id="${id}"` : ``}>${text}</span>`
141+
return `<span${classname ? ` class="${classname}"` : ``}${id ? ` id="${id}"` : ``}>${sanitizeHTML(text)}</span>`
138142
}
139143

140144
}

src/options/default-options.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,32 @@ import { RenderOption } from '.';
33
import { Metadata } from '../Models/metadata-model';
44
import { EmbeddedItem } from '../Models/embedded-object';
55
import { EntryNode } from '../Models/json-rte-model';
6+
import { sanitizeHTML } from '../helper/sanitize'
67

78
export const defaultOptions: RenderOption = {
8-
[StyleType.BLOCK]: (item: EmbeddedItem | EntryNode) =>
9-
`<div><p>${item.title || item.uid}</p><p>Content type: <span>${item._content_type_uid || (item.system ? item.system.content_type_uid : '')}</span></p></div>`,
10-
[StyleType.INLINE]: (item: EmbeddedItem | EntryNode) => `<span>${item.title || item.uid}</span>`,
11-
[StyleType.LINK]: (item: EmbeddedItem | EntryNode, metadata: Metadata) => `<a href="${item.url}">${metadata.text || item.title || item.uid || (item.system ? item.system.uid : '')}</a>`,
12-
[StyleType.DISPLAY]: (item: EmbeddedItem | EntryNode, metadata: Metadata) => `<img src="${item.url}" alt="${metadata.attributes.alt || item.title || item.filename || item.uid
13-
|| (item.system ? item.system.uid : '')}" />`,
14-
[StyleType.DOWNLOAD]: (item: EmbeddedItem | EntryNode, metadata: Metadata) => `<a href="${item.url}">${metadata.text || item.title || item.uid || (item.system ? item.system.content_type_uid : '')}</a>`,
9+
[StyleType.BLOCK]: (item: EmbeddedItem | EntryNode) => {
10+
const title = sanitizeHTML(item.title || item.uid);
11+
const content_type_uid = sanitizeHTML(item._content_type_uid || (item.system ? item.system.content_type_uid : ''));
12+
return `<div><p>${title}</p><p>Content type: <span>${content_type_uid}</span></p></div>`;
13+
},
14+
[StyleType.INLINE]: (item: EmbeddedItem | EntryNode) => {
15+
const title = sanitizeHTML(item.title || item.uid);
16+
return `<span>${title}</span>`;
17+
},
18+
[StyleType.LINK]: (item: EmbeddedItem | EntryNode, metadata: Metadata) => {
19+
const url = sanitizeHTML(item.url || 'undefined');
20+
const text = sanitizeHTML(metadata.text || item.title || item.uid || (item.system ? item.system.uid : ''));
21+
return `<a href="${url}">${text}</a>`;
22+
},
23+
[StyleType.DISPLAY]: (item: EmbeddedItem | EntryNode, metadata: Metadata) => {
24+
const url = sanitizeHTML(item.url || 'undefined');
25+
const alt = sanitizeHTML(metadata.attributes.alt || item.title || item.filename || item.uid
26+
|| (item.system ? item.system.uid : ''));
27+
return `<img src="${url}" alt="${alt}" />`;
28+
},
29+
[StyleType.DOWNLOAD]: (item: EmbeddedItem | EntryNode, metadata: Metadata) => {
30+
const href = sanitizeHTML(item.url || 'undefined');
31+
const text = sanitizeHTML(metadata.text || item.title || item.uid || (item.system ? item.system.content_type_uid : ''));
32+
return `<a href="${href}">${text}</a>`;
33+
},
1534
};

0 commit comments

Comments
 (0)