@stacksjs/sanitizer 0.2.198 → 0.2.200
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -465
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,466 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
var strict = {
|
|
4
|
-
allowedTags: [
|
|
5
|
-
"p",
|
|
6
|
-
"br",
|
|
7
|
-
"strong",
|
|
8
|
-
"em",
|
|
9
|
-
"u",
|
|
10
|
-
"span",
|
|
11
|
-
"h1",
|
|
12
|
-
"h2",
|
|
13
|
-
"h3",
|
|
14
|
-
"h4",
|
|
15
|
-
"h5",
|
|
16
|
-
"h6",
|
|
17
|
-
"ul",
|
|
18
|
-
"ol",
|
|
19
|
-
"li",
|
|
20
|
-
"code",
|
|
21
|
-
"pre"
|
|
22
|
-
],
|
|
23
|
-
allowedAttributes: {
|
|
24
|
-
"*": ["class", "id"]
|
|
25
|
-
},
|
|
26
|
-
allowedSchemes: ["http", "https", "mailto"],
|
|
27
|
-
allowDataAttributes: false,
|
|
28
|
-
allowAriaAttributes: true,
|
|
29
|
-
stripTags: true,
|
|
30
|
-
allowComments: false
|
|
31
|
-
};
|
|
32
|
-
var basic = {
|
|
33
|
-
allowedTags: [
|
|
34
|
-
"p",
|
|
35
|
-
"br",
|
|
36
|
-
"strong",
|
|
37
|
-
"em",
|
|
38
|
-
"u",
|
|
39
|
-
"span",
|
|
40
|
-
"div",
|
|
41
|
-
"h1",
|
|
42
|
-
"h2",
|
|
43
|
-
"h3",
|
|
44
|
-
"h4",
|
|
45
|
-
"h5",
|
|
46
|
-
"h6",
|
|
47
|
-
"ul",
|
|
48
|
-
"ol",
|
|
49
|
-
"li",
|
|
50
|
-
"a",
|
|
51
|
-
"img",
|
|
52
|
-
"code",
|
|
53
|
-
"pre",
|
|
54
|
-
"blockquote",
|
|
55
|
-
"table",
|
|
56
|
-
"thead",
|
|
57
|
-
"tbody",
|
|
58
|
-
"tr",
|
|
59
|
-
"th",
|
|
60
|
-
"td"
|
|
61
|
-
],
|
|
62
|
-
allowedAttributes: {
|
|
63
|
-
"*": ["class", "id"],
|
|
64
|
-
a: ["class", "id", "href", "title", "target", "rel"],
|
|
65
|
-
img: ["class", "id", "src", "alt", "title", "width", "height"],
|
|
66
|
-
td: ["class", "id", "colspan", "rowspan", "align"],
|
|
67
|
-
th: ["class", "id", "colspan", "rowspan", "align", "scope"]
|
|
68
|
-
},
|
|
69
|
-
allowedSchemes: ["http", "https", "mailto", "tel"],
|
|
70
|
-
allowDataAttributes: false,
|
|
71
|
-
allowAriaAttributes: true,
|
|
72
|
-
stripTags: true,
|
|
73
|
-
allowComments: false
|
|
74
|
-
};
|
|
75
|
-
var relaxed = {
|
|
76
|
-
allowedTags: [
|
|
77
|
-
"p",
|
|
78
|
-
"br",
|
|
79
|
-
"strong",
|
|
80
|
-
"em",
|
|
81
|
-
"u",
|
|
82
|
-
"span",
|
|
83
|
-
"div",
|
|
84
|
-
"section",
|
|
85
|
-
"article",
|
|
86
|
-
"aside",
|
|
87
|
-
"h1",
|
|
88
|
-
"h2",
|
|
89
|
-
"h3",
|
|
90
|
-
"h4",
|
|
91
|
-
"h5",
|
|
92
|
-
"h6",
|
|
93
|
-
"ul",
|
|
94
|
-
"ol",
|
|
95
|
-
"li",
|
|
96
|
-
"dl",
|
|
97
|
-
"dt",
|
|
98
|
-
"dd",
|
|
99
|
-
"a",
|
|
100
|
-
"img",
|
|
101
|
-
"figure",
|
|
102
|
-
"figcaption",
|
|
103
|
-
"code",
|
|
104
|
-
"pre",
|
|
105
|
-
"kbd",
|
|
106
|
-
"samp",
|
|
107
|
-
"var",
|
|
108
|
-
"blockquote",
|
|
109
|
-
"q",
|
|
110
|
-
"cite",
|
|
111
|
-
"table",
|
|
112
|
-
"thead",
|
|
113
|
-
"tbody",
|
|
114
|
-
"tfoot",
|
|
115
|
-
"tr",
|
|
116
|
-
"th",
|
|
117
|
-
"td",
|
|
118
|
-
"caption",
|
|
119
|
-
"del",
|
|
120
|
-
"ins",
|
|
121
|
-
"sub",
|
|
122
|
-
"sup",
|
|
123
|
-
"abbr",
|
|
124
|
-
"address",
|
|
125
|
-
"time",
|
|
126
|
-
"hr",
|
|
127
|
-
"video",
|
|
128
|
-
"audio",
|
|
129
|
-
"source",
|
|
130
|
-
"track"
|
|
131
|
-
],
|
|
132
|
-
allowedAttributes: {
|
|
133
|
-
"*": ["class", "id", "title"],
|
|
134
|
-
a: ["class", "id", "href", "title", "target", "rel"],
|
|
135
|
-
img: ["class", "id", "src", "srcset", "alt", "title", "width", "height", "loading"],
|
|
136
|
-
video: ["class", "id", "src", "width", "height", "controls", "preload", "poster"],
|
|
137
|
-
audio: ["class", "id", "src", "controls", "preload"],
|
|
138
|
-
source: ["src", "type"],
|
|
139
|
-
track: ["src", "kind", "srclang", "label"],
|
|
140
|
-
td: ["class", "id", "colspan", "rowspan", "align"],
|
|
141
|
-
th: ["class", "id", "colspan", "rowspan", "align", "scope"],
|
|
142
|
-
time: ["class", "id", "datetime"],
|
|
143
|
-
abbr: ["class", "id", "title"]
|
|
144
|
-
},
|
|
145
|
-
allowedSchemes: ["http", "https", "mailto", "tel", "data"],
|
|
146
|
-
allowDataAttributes: true,
|
|
147
|
-
allowAriaAttributes: true,
|
|
148
|
-
stripTags: true,
|
|
149
|
-
allowComments: false
|
|
150
|
-
};
|
|
151
|
-
var markdown = {
|
|
152
|
-
allowedTags: [
|
|
153
|
-
"p",
|
|
154
|
-
"br",
|
|
155
|
-
"strong",
|
|
156
|
-
"em",
|
|
157
|
-
"span",
|
|
158
|
-
"h1",
|
|
159
|
-
"h2",
|
|
160
|
-
"h3",
|
|
161
|
-
"h4",
|
|
162
|
-
"h5",
|
|
163
|
-
"h6",
|
|
164
|
-
"ul",
|
|
165
|
-
"ol",
|
|
166
|
-
"li",
|
|
167
|
-
"a",
|
|
168
|
-
"img",
|
|
169
|
-
"code",
|
|
170
|
-
"pre",
|
|
171
|
-
"blockquote",
|
|
172
|
-
"table",
|
|
173
|
-
"thead",
|
|
174
|
-
"tbody",
|
|
175
|
-
"tr",
|
|
176
|
-
"th",
|
|
177
|
-
"td",
|
|
178
|
-
"del",
|
|
179
|
-
"ins",
|
|
180
|
-
"hr",
|
|
181
|
-
"input"
|
|
182
|
-
],
|
|
183
|
-
allowedAttributes: {
|
|
184
|
-
"*": ["class", "id"],
|
|
185
|
-
a: ["class", "id", "href", "title"],
|
|
186
|
-
img: ["class", "id", "src", "alt", "title"],
|
|
187
|
-
code: ["class"],
|
|
188
|
-
td: ["align"],
|
|
189
|
-
th: ["align", "scope"],
|
|
190
|
-
input: ["type", "checked", "disabled"]
|
|
191
|
-
},
|
|
192
|
-
allowedSchemes: ["http", "https", "mailto"],
|
|
193
|
-
allowDataAttributes: false,
|
|
194
|
-
allowAriaAttributes: false,
|
|
195
|
-
stripTags: true,
|
|
196
|
-
allowComments: false
|
|
197
|
-
};
|
|
198
|
-
function getPreset(name) {
|
|
199
|
-
switch (name) {
|
|
200
|
-
case "strict":
|
|
201
|
-
return strict;
|
|
202
|
-
case "basic":
|
|
203
|
-
return basic;
|
|
204
|
-
case "relaxed":
|
|
205
|
-
return relaxed;
|
|
206
|
-
case "markdown":
|
|
207
|
-
return markdown;
|
|
208
|
-
default:
|
|
209
|
-
return basic;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// src/sanitizer.ts
|
|
214
|
-
var DEFAULT_OPTIONS = {
|
|
215
|
-
allowedTags: [],
|
|
216
|
-
allowedAttributes: {},
|
|
217
|
-
allowedSchemes: ["http", "https", "mailto"],
|
|
218
|
-
allowDataAttributes: false,
|
|
219
|
-
allowAriaAttributes: true,
|
|
220
|
-
stripTags: true,
|
|
221
|
-
allowComments: false
|
|
222
|
-
};
|
|
223
|
-
var DANGEROUS_TAGS = [
|
|
224
|
-
"script",
|
|
225
|
-
"iframe",
|
|
226
|
-
"object",
|
|
227
|
-
"embed",
|
|
228
|
-
"applet",
|
|
229
|
-
"base",
|
|
230
|
-
"link",
|
|
231
|
-
"meta",
|
|
232
|
-
"style"
|
|
233
|
-
];
|
|
234
|
-
var URL_ATTRIBUTES = [
|
|
235
|
-
"href",
|
|
236
|
-
"src",
|
|
237
|
-
"action",
|
|
238
|
-
"formaction",
|
|
239
|
-
"data",
|
|
240
|
-
"poster",
|
|
241
|
-
"cite",
|
|
242
|
-
"background",
|
|
243
|
-
"longdesc"
|
|
244
|
-
];
|
|
245
|
-
var EVENT_ATTRIBUTES_REGEX = /^on\w+/i;
|
|
246
|
-
function sanitize(html, options) {
|
|
247
|
-
const result = sanitizeWithInfo(html, options);
|
|
248
|
-
return result.html;
|
|
249
|
-
}
|
|
250
|
-
function sanitizeWithInfo(html, options) {
|
|
251
|
-
const opts = typeof options === "string" ? getPreset(options) : { ...DEFAULT_OPTIONS, ...options };
|
|
252
|
-
const removedTags = [];
|
|
253
|
-
const removedAttributes = [];
|
|
254
|
-
let result = html;
|
|
255
|
-
let modified = false;
|
|
256
|
-
if (!opts.allowComments) {
|
|
257
|
-
const commentRegex = /<!--[\s\S]*?-->/g;
|
|
258
|
-
if (commentRegex.test(result)) {
|
|
259
|
-
result = result.replace(commentRegex, "");
|
|
260
|
-
modified = true;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
const tagRegex = /<(\/?)([a-zA-Z][\w-]*)([^>]*)>/g;
|
|
264
|
-
result = result.replace(tagRegex, (match, closing, tagName, attributesStr) => {
|
|
265
|
-
const lowerTag = tagName.toLowerCase();
|
|
266
|
-
if (DANGEROUS_TAGS.includes(lowerTag)) {
|
|
267
|
-
if (!removedTags.includes(lowerTag)) {
|
|
268
|
-
removedTags.push(lowerTag);
|
|
269
|
-
}
|
|
270
|
-
modified = true;
|
|
271
|
-
return opts.stripTags ? "" : escapeHtml(match);
|
|
272
|
-
}
|
|
273
|
-
const allowedTags = opts.allowedTags || [];
|
|
274
|
-
if (allowedTags.length > 0 && !allowedTags.includes(lowerTag)) {
|
|
275
|
-
if (!removedTags.includes(lowerTag)) {
|
|
276
|
-
removedTags.push(lowerTag);
|
|
277
|
-
}
|
|
278
|
-
modified = true;
|
|
279
|
-
return opts.stripTags ? "" : escapeHtml(match);
|
|
280
|
-
}
|
|
281
|
-
if (closing) {
|
|
282
|
-
return match;
|
|
283
|
-
}
|
|
284
|
-
const sanitizedAttrs = sanitizeAttributes(attributesStr, lowerTag, opts, removedAttributes);
|
|
285
|
-
if (sanitizedAttrs !== attributesStr) {
|
|
286
|
-
modified = true;
|
|
287
|
-
}
|
|
288
|
-
if (opts.transformTag) {
|
|
289
|
-
const attributes = parseAttributes(sanitizedAttrs);
|
|
290
|
-
const transformed = opts.transformTag(lowerTag, attributes);
|
|
291
|
-
if (transformed === null) {
|
|
292
|
-
if (!removedTags.includes(lowerTag)) {
|
|
293
|
-
removedTags.push(lowerTag);
|
|
294
|
-
}
|
|
295
|
-
modified = true;
|
|
296
|
-
return "";
|
|
297
|
-
}
|
|
298
|
-
if (transformed.tagName !== lowerTag || JSON.stringify(transformed.attributes) !== JSON.stringify(attributes)) {
|
|
299
|
-
modified = true;
|
|
300
|
-
return buildTag(transformed.tagName, transformed.attributes);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
return `<${tagName}${sanitizedAttrs}>`;
|
|
304
|
-
});
|
|
305
|
-
return {
|
|
306
|
-
html: result,
|
|
307
|
-
modified,
|
|
308
|
-
removedTags: removedTags.length > 0 ? removedTags : undefined,
|
|
309
|
-
removedAttributes: removedAttributes.length > 0 ? removedAttributes : undefined
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
function sanitizeAttributes(attributesStr, tagName, options, removedAttributes) {
|
|
313
|
-
if (!attributesStr.trim()) {
|
|
314
|
-
return attributesStr;
|
|
315
|
-
}
|
|
316
|
-
const attributes = parseAttributes(attributesStr);
|
|
317
|
-
const sanitized = {};
|
|
318
|
-
for (const [name, value] of Object.entries(attributes)) {
|
|
319
|
-
const lowerName = name.toLowerCase();
|
|
320
|
-
if (EVENT_ATTRIBUTES_REGEX.test(lowerName)) {
|
|
321
|
-
if (!removedAttributes.includes(lowerName)) {
|
|
322
|
-
removedAttributes.push(lowerName);
|
|
323
|
-
}
|
|
324
|
-
continue;
|
|
325
|
-
}
|
|
326
|
-
if (!isAttributeAllowed(lowerName, tagName, options)) {
|
|
327
|
-
if (!removedAttributes.includes(lowerName)) {
|
|
328
|
-
removedAttributes.push(lowerName);
|
|
329
|
-
}
|
|
330
|
-
continue;
|
|
331
|
-
}
|
|
332
|
-
if (URL_ATTRIBUTES.includes(lowerName)) {
|
|
333
|
-
if (!isUrlSafe(value, options)) {
|
|
334
|
-
if (!removedAttributes.includes(lowerName)) {
|
|
335
|
-
removedAttributes.push(lowerName);
|
|
336
|
-
}
|
|
337
|
-
continue;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
if (lowerName === "style" && options.allowedStyles) {
|
|
341
|
-
sanitized[name] = sanitizeStyle(value, options.allowedStyles);
|
|
342
|
-
} else {
|
|
343
|
-
sanitized[name] = value;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
return buildAttributes(sanitized);
|
|
347
|
-
}
|
|
348
|
-
function isAttributeAllowed(attrName, tagName, options) {
|
|
349
|
-
const allowedAttrs = options.allowedAttributes;
|
|
350
|
-
if (!allowedAttrs) {
|
|
351
|
-
return false;
|
|
352
|
-
}
|
|
353
|
-
if (attrName.startsWith("data-")) {
|
|
354
|
-
return options.allowDataAttributes || false;
|
|
355
|
-
}
|
|
356
|
-
if (attrName.startsWith("aria-")) {
|
|
357
|
-
return options.allowAriaAttributes || false;
|
|
358
|
-
}
|
|
359
|
-
if (Array.isArray(allowedAttrs)) {
|
|
360
|
-
return allowedAttrs.includes(attrName);
|
|
361
|
-
}
|
|
362
|
-
if (allowedAttrs[tagName]?.includes(attrName)) {
|
|
363
|
-
return true;
|
|
364
|
-
}
|
|
365
|
-
if (allowedAttrs["*"]?.includes(attrName)) {
|
|
366
|
-
return true;
|
|
367
|
-
}
|
|
368
|
-
return false;
|
|
369
|
-
}
|
|
370
|
-
function isUrlSafe(url, options) {
|
|
371
|
-
if (options.urlValidator) {
|
|
372
|
-
return options.urlValidator(url);
|
|
373
|
-
}
|
|
374
|
-
const trimmed = url.trim().toLowerCase();
|
|
375
|
-
const cleaned = trimmed.replace(/[\s\x00-\x1F]/g, "");
|
|
376
|
-
const dangerousProtocols = ["javascript:", "data:text/html", "vbscript:", "file:"];
|
|
377
|
-
for (const protocol of dangerousProtocols) {
|
|
378
|
-
if (cleaned.startsWith(protocol)) {
|
|
379
|
-
return false;
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
if (options.allowedSchemes && options.allowedSchemes.length > 0) {
|
|
383
|
-
if (!cleaned.includes(":")) {
|
|
384
|
-
return true;
|
|
385
|
-
}
|
|
386
|
-
const hasAllowedScheme = options.allowedSchemes.some((scheme) => {
|
|
387
|
-
return cleaned.startsWith(`${scheme}:`);
|
|
388
|
-
});
|
|
389
|
-
if (!hasAllowedScheme) {
|
|
390
|
-
return false;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
return true;
|
|
394
|
-
}
|
|
395
|
-
function sanitizeStyle(style, allowedStyles) {
|
|
396
|
-
const properties = style.split(";").filter((p) => p.trim());
|
|
397
|
-
const sanitized = [];
|
|
398
|
-
for (const prop of properties) {
|
|
399
|
-
const colonIndex = prop.indexOf(":");
|
|
400
|
-
if (colonIndex === -1)
|
|
401
|
-
continue;
|
|
402
|
-
const name = prop.substring(0, colonIndex).trim().toLowerCase();
|
|
403
|
-
const value = prop.substring(colonIndex + 1).trim();
|
|
404
|
-
if (allowedStyles.includes(name)) {
|
|
405
|
-
if (!value.toLowerCase().includes("javascript:") && !value.toLowerCase().includes("expression(")) {
|
|
406
|
-
sanitized.push(`${name}: ${value}`);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
return sanitized.join("; ");
|
|
411
|
-
}
|
|
412
|
-
function parseAttributes(attributesStr) {
|
|
413
|
-
const attributes = {};
|
|
414
|
-
const attrRegex = /([\w-]+)(?:=(?:"([^"]*)"|'([^']*)'|([^\s>]+)))?/g;
|
|
415
|
-
let match;
|
|
416
|
-
while (match = attrRegex.exec(attributesStr)) {
|
|
417
|
-
const name = match[1];
|
|
418
|
-
const value = match[2] || match[3] || match[4] || "";
|
|
419
|
-
attributes[name] = value;
|
|
420
|
-
}
|
|
421
|
-
return attributes;
|
|
422
|
-
}
|
|
423
|
-
function buildAttributes(attributes) {
|
|
424
|
-
const parts = [];
|
|
425
|
-
for (const [name, value] of Object.entries(attributes)) {
|
|
426
|
-
if (value === "") {
|
|
427
|
-
parts.push(name);
|
|
428
|
-
} else {
|
|
429
|
-
const escaped = value.replace(/"/g, """);
|
|
430
|
-
parts.push(`${name}="${escaped}"`);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
return parts.length > 0 ? ` ${parts.join(" ")}` : "";
|
|
434
|
-
}
|
|
435
|
-
function buildTag(tagName, attributes) {
|
|
436
|
-
return `<${tagName}${buildAttributes(attributes)}>`;
|
|
437
|
-
}
|
|
438
|
-
function escapeHtml(text) {
|
|
439
|
-
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
440
|
-
}
|
|
441
|
-
function isSafe(html, options) {
|
|
442
|
-
const result = sanitizeWithInfo(html, options);
|
|
443
|
-
return !result.modified;
|
|
444
|
-
}
|
|
445
|
-
function stripTags(html) {
|
|
446
|
-
return html.replace(/<[^>]*>/g, "");
|
|
447
|
-
}
|
|
448
|
-
function escape(text) {
|
|
449
|
-
return escapeHtml(text);
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
// src/index.ts
|
|
453
|
-
var src_default = sanitize;
|
|
454
|
-
export {
|
|
455
|
-
stripTags,
|
|
456
|
-
strict,
|
|
457
|
-
sanitizeWithInfo,
|
|
458
|
-
sanitize,
|
|
459
|
-
relaxed,
|
|
460
|
-
markdown,
|
|
461
|
-
isSafe,
|
|
462
|
-
getPreset,
|
|
463
|
-
escape,
|
|
464
|
-
src_default as default,
|
|
465
|
-
basic
|
|
466
|
-
};
|
|
2
|
+
var L={allowedTags:["p","br","strong","em","u","span","h1","h2","h3","h4","h5","h6","ul","ol","li","code","pre"],allowedAttributes:{"*":["class","id"]},allowedSchemes:["http","https","mailto"],allowDataAttributes:!1,allowAriaAttributes:!0,stripTags:!0,allowComments:!1},B={allowedTags:["p","br","strong","em","u","span","div","h1","h2","h3","h4","h5","h6","ul","ol","li","a","img","code","pre","blockquote","table","thead","tbody","tr","th","td"],allowedAttributes:{"*":["class","id"],a:["class","id","href","title","target","rel"],img:["class","id","src","alt","title","width","height"],td:["class","id","colspan","rowspan","align"],th:["class","id","colspan","rowspan","align","scope"]},allowedSchemes:["http","https","mailto","tel"],allowDataAttributes:!1,allowAriaAttributes:!0,stripTags:!0,allowComments:!1},x={allowedTags:["p","br","strong","em","u","span","div","section","article","aside","h1","h2","h3","h4","h5","h6","ul","ol","li","dl","dt","dd","a","img","figure","figcaption","code","pre","kbd","samp","var","blockquote","q","cite","table","thead","tbody","tfoot","tr","th","td","caption","del","ins","sub","sup","abbr","address","time","hr","video","audio","source","track"],allowedAttributes:{"*":["class","id","title"],a:["class","id","href","title","target","rel"],img:["class","id","src","srcset","alt","title","width","height","loading"],video:["class","id","src","width","height","controls","preload","poster"],audio:["class","id","src","controls","preload"],source:["src","type"],track:["src","kind","srclang","label"],td:["class","id","colspan","rowspan","align"],th:["class","id","colspan","rowspan","align","scope"],time:["class","id","datetime"],abbr:["class","id","title"]},allowedSchemes:["http","https","mailto","tel","data"],allowDataAttributes:!0,allowAriaAttributes:!0,stripTags:!0,allowComments:!1},_={allowedTags:["p","br","strong","em","span","h1","h2","h3","h4","h5","h6","ul","ol","li","a","img","code","pre","blockquote","table","thead","tbody","tr","th","td","del","ins","hr","input"],allowedAttributes:{"*":["class","id"],a:["class","id","href","title"],img:["class","id","src","alt","title"],code:["class"],td:["align"],th:["align","scope"],input:["type","checked","disabled"]},allowedSchemes:["http","https","mailto"],allowDataAttributes:!1,allowAriaAttributes:!1,stripTags:!0,allowComments:!1};function M(q){switch(q){case"strict":return L;case"basic":return B;case"relaxed":return x;case"markdown":return _;default:return B}}var I={allowedTags:[],allowedAttributes:{},allowedSchemes:["http","https","mailto"],allowDataAttributes:!1,allowAriaAttributes:!0,stripTags:!0,allowComments:!1},z=["script","iframe","object","embed","applet","base","link","meta","style"],E=["href","src","action","formaction","data","poster","cite","background","longdesc"],R=/^on\w+/i;function W(q,C){return k(q,C).html}function k(q,C){let D=typeof C==="string"?M(C):{...I,...C},j=[],K=[],J=q,Q=!1;if(!D.allowComments){let P=/<!--[\s\S]*?-->/g;if(P.test(J))J=J.replace(P,""),Q=!0}let Y=/<(\/?)([a-zA-Z][\w-]*)([^>]*)>/g;return J=J.replace(Y,(P,y,O,F)=>{let X=O.toLowerCase();if(z.includes(X)){if(!j.includes(X))j.push(X);return Q=!0,D.stripTags?"":V(P)}let G=D.allowedTags||[];if(G.length>0&&!G.includes(X)){if(!j.includes(X))j.push(X);return Q=!0,D.stripTags?"":V(P)}if(y)return P;let $=S(F,X,D,K);if($!==F)Q=!0;if(D.transformTag){let H=f($),Z=D.transformTag(X,H);if(Z===null){if(!j.includes(X))j.push(X);return Q=!0,""}if(Z.tagName!==X||JSON.stringify(Z.attributes)!==JSON.stringify(H))return Q=!0,v(Z.tagName,Z.attributes)}return`<${O}${$}>`}),{html:J,modified:Q,removedTags:j.length>0?j:void 0,removedAttributes:K.length>0?K:void 0}}function S(q,C,D,j){if(!q.trim())return q;let K=f(q),J={};for(let[Q,Y]of Object.entries(K)){let P=Q.toLowerCase();if(R.test(P)){if(!j.includes(P))j.push(P);continue}if(!h(P,C,D)){if(!j.includes(P))j.push(P);continue}if(E.includes(P)){if(!c(Y,D)){if(!j.includes(P))j.push(P);continue}}if(P==="style"&&D.allowedStyles)J[Q]=w(Y,D.allowedStyles);else J[Q]=Y}return U(J)}function h(q,C,D){let j=D.allowedAttributes;if(!j)return!1;if(q.startsWith("data-"))return D.allowDataAttributes||!1;if(q.startsWith("aria-"))return D.allowAriaAttributes||!1;if(Array.isArray(j))return j.includes(q);if(j[C]?.includes(q))return!0;if(j["*"]?.includes(q))return!0;return!1}function c(q,C){if(C.urlValidator)return C.urlValidator(q);let j=q.trim().toLowerCase().replace(/[\s\x00-\x1F]/g,""),K=["javascript:","data:text/html","vbscript:","file:"];for(let J of K)if(j.startsWith(J))return!1;if(C.allowedSchemes&&C.allowedSchemes.length>0){if(!j.includes(":"))return!0;if(!C.allowedSchemes.some((Q)=>{return j.startsWith(`${Q}:`)}))return!1}return!0}function w(q,C){let D=q.split(";").filter((K)=>K.trim()),j=[];for(let K of D){let J=K.indexOf(":");if(J===-1)continue;let Q=K.substring(0,J).trim().toLowerCase(),Y=K.substring(J+1).trim();if(C.includes(Q)){if(!Y.toLowerCase().includes("javascript:")&&!Y.toLowerCase().includes("expression("))j.push(`${Q}: ${Y}`)}}return j.join("; ")}function f(q){let C={},D=/([\w-]+)(?:=(?:"([^"]*)"|'([^']*)'|([^\s>]+)))?/g,j;while(j=D.exec(q)){let K=j[1],J=j[2]||j[3]||j[4]||"";C[K]=J}return C}function U(q){let C=[];for(let[D,j]of Object.entries(q))if(j==="")C.push(D);else{let K=j.replace(/"/g,""");C.push(`${D}="${K}"`)}return C.length>0?` ${C.join(" ")}`:""}function v(q,C){return`<${q}${U(C)}>`}function V(q){return q.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function T(q,C){return!k(q,C).modified}function N(q){return q.replace(/<[^>]*>/g,"")}function A(q){return V(q)}var s=W;export{N as stripTags,L as strict,k as sanitizeWithInfo,W as sanitize,x as relaxed,_ as markdown,T as isSafe,M as getPreset,A as escape,s as default,B as basic};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/sanitizer",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.200",
|
|
5
5
|
"description": "A fast, native Bun-powered HTML sanitizer with DOMPurify-like features. Protection against XSS and malicious content.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.org>",
|
|
7
7
|
"license": "MIT",
|