diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0e4b479..bf33c7d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
# Changelog
+## UNRELEASED
+- Added `allowedEmptyAttributes` option and kept empty `alt` value by default.
+
## 2.11.0 (2023-06-21)
- Fix to allow `false` in `allowedClasses` attributes. Thanks to [Kevin Jiang](https://github.com/KevinSJ) for this fix!
diff --git a/index.js b/index.js
index b834977..4ea238a 100644
--- a/index.js
+++ b/index.js
@@ -295,9 +295,11 @@ function sanitizeHtml(html, options, _recursing) {
delete frame.attribs[a];
return;
}
- // If the value is empty, and this is a known non-boolean attribute, delete it
+ // If the value is empty, check if the attribute is in the allowedEmptyAttributes array.
+ // If it is not in the allowedEmptyAttributes array, and it is a known non-boolean attribute, delete it
// List taken from https://html.spec.whatwg.org/multipage/indices.html#attributes-3
- if (value === '' && (options.nonBooleanAttributes.includes(a) || options.nonBooleanAttributes.includes('*'))) {
+ if (value === '' && (!options.allowedEmptyAttributes.includes(a)) && (options.nonBooleanAttributes.includes(a) ||
+ options.nonBooleanAttributes.includes('*'))) {
delete frame.attribs[a];
return;
}
@@ -474,6 +476,8 @@ function sanitizeHtml(html, options, _recursing) {
result += ' ' + a;
if (value && value.length) {
result += '="' + escapeHtml(value, true) + '"';
+ } else if (options.allowedEmptyAttributes.includes(a)) {
+ result += '=""';
}
} else {
delete frame.attribs[a];
@@ -876,6 +880,9 @@ sanitizeHtml.defaults = {
// these attributes would make sense if we did.
img: [ 'src', 'srcset', 'alt', 'title', 'width', 'height', 'loading' ]
},
+ allowedEmptyAttributes: [
+ 'alt'
+ ],
// Lots of these won't come up by default because we don't allow them
selfClosing: [ 'img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link', 'meta' ],
// URL schemes we permit
diff --git a/test/test.js b/test/test.js
index c938b33..0ce92a2 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1616,4 +1616,27 @@ describe('sanitizeHtml', function() {
nonBooleanAttributes: [ '*' ]
}), '');
});
+ it('should not remove empty alt attribute value by default', function() {
+ assert.equal(sanitizeHtml('', {
+ allowedAttributes: { img: [ 'alt', 'src' ] },
+ allowedTags: [ 'img' ]
+ }), '');
+ });
+ it('should not remove empty alt attribute value by default when disabled', function() {
+ assert.equal(sanitizeHtml('', {
+ allowedAttributes: { img: [ 'alt', 'src' ] },
+ allowedTags: [ 'img' ],
+ nonBooleanAttributes: []
+ }), '');
+ });
+ it('should set empty value to attribute specified in allowedEmptyAttributes option', function() {
+ assert.equal(sanitizeHtml('hello', {
+ allowedEmptyAttributes: [ 'href' ]
+ }), 'hello');
+ });
+ it('should not remove empty attribute specified in allowedEmptyAttributes option', function() {
+ assert.equal(sanitizeHtml('hello', {
+ allowedEmptyAttributes: [ 'href' ]
+ }), 'hello');
+ });
});