Skip to content

Commit

Permalink
do not allow html by default
Browse files Browse the repository at this point in the history
  • Loading branch information
lekoala committed Feb 9, 2024
1 parent d1c685c commit 9f8f8f0
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 7 deletions.
6 changes: 3 additions & 3 deletions demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -563,8 +563,8 @@ <h1>Demo</h1>
</div>
<div class="row mb-3 g-3">
<div class="col-md-4">
<label for="showDisabled" class="form-label">Tags (show disabled)</label>
<select class="form-select" id="showDisabled" name="showDisabled[]" multiple data-allow-clear="true" data-show-disabled="true">
<label for="showDisabled" class="form-label">Tags (show disabled + allow html)</label>
<select class="form-select" id="showDisabled" name="showDisabled[]" multiple data-allow-clear="true" data-show-disabled="true" data-allow-html="1">
<option disabled hidden value="">Choose a tag...</option>
<option value="1" selected="selected">Apple</option>
<option value="2">Banana</option>
Expand Down Expand Up @@ -766,7 +766,7 @@ <h1>Demo</h1>
<div class="col-md-4">
<label for="addOnBlur" class="form-label">Add on blur (+ keep open)</label>
<select class="form-select" id="addOnBlur" name="addOnBlur[]" multiple data-allow-new="true" data-allow-clear="1"
data-add-on-blur="1" data-kee-open="1" data-suggestions-threshold="0">
data-add-on-blur="1" data-keep-open="1" data-suggestions-threshold="0">
<option value="">Type a tag...</option>
<!-- you need at least one option with the placeholder -->
<option value="1">Apple</option>
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ Options can be either passed to the constructor (eg: optionName) or in data-opti
| fetchOptions | <code>Object</code> | Any other fetch options (https://developer.mozilla.org/en-US/docs/Web/API/fetch#syntax) |
| liveServer | <code>Boolean</code> | Should the endpoint be called each time on input |
| noCache | <code>Boolean</code> | Prevent caching by appending a timestamp |
| allowHtml | <code>Boolean</code> | Allow html in input (can lead to script injection) |
| debounceTime | <code>Number</code> | Debounce time for live server |
| notFoundMessage | <code>String</code> | Display a no suggestions found message. Leave empty to disable |
| onRenderItem | [<code>RenderCallback</code>](#RenderCallback) | Callback function that returns the suggestion |
Expand Down
23 changes: 19 additions & 4 deletions tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
* @property {Object} fetchOptions Any other fetch options (https://developer.mozilla.org/en-US/docs/Web/API/fetch#syntax)
* @property {Boolean} liveServer Should the endpoint be called each time on input
* @property {Boolean} noCache Prevent caching by appending a timestamp
* @property {Boolean} allowHtml Allow html in input (can lead to script injection)
* @property {Number} debounceTime Debounce time for live server
* @property {String} notFoundMessage Display a no suggestions found message. Leave empty to disable
* @property {RenderCallback} onRenderItem Callback function that returns the suggestion
Expand Down Expand Up @@ -193,9 +194,13 @@ const DEFAULTS = {
fetchOptions: {},
liveServer: false,
noCache: true,
allowHtml: false,
debounceTime: 300,
notFoundMessage: "",
onRenderItem: (item, label, inst) => {
if (!inst.config("allowHtml")) {
return sanitize(label);
}
return label;
},
onSelectItem: (item, inst) => {},
Expand Down Expand Up @@ -265,12 +270,21 @@ function calcTextWidth(text, size = null) {
span.style.width = "auto";
span.style.position = "absolute";
span.style.whiteSpace = "no-wrap";
span.innerHTML = text;
span.innerHTML = sanitize(text);
const width = Math.ceil(span.clientWidth);
document.body.removeChild(span);
return width;
}

/**
* @link https://stackoverflow.com/questions/3043775/how-to-escape-html
* @param {string} text
* @returns {string}
*/
function sanitize(text) {
return new Option(text).innerHTML;
}

/**
* @param {String} str
* @returns {String}
Expand Down Expand Up @@ -1405,7 +1419,7 @@ class Tags {
const newChildSpan = ce("span");
newChild.append(newChildSpan);
newChildSpan.classList.add(...["dropdown-header", "text-truncate"]);
newChildSpan.innerHTML = suggestion["group"];
newChildSpan.innerHTML = sanitize(suggestion["group"]);
this._dropElement.appendChild(newChild);

if (suggestion["items"]) {
Expand Down Expand Up @@ -1471,6 +1485,7 @@ class Tags {
});
newChildLink.dataset.searchData = JSON.stringify(searchData);
newChildLink.setAttribute("href", "#");
// sanitized if needed by onRenderItem
newChildLink.innerHTML = textContent;
this._dropElement.appendChild(newChild);

Expand Down Expand Up @@ -2281,7 +2296,7 @@ class Tags {
if (!opt) {
opt = ce("option");
opt.value = value;
opt.textContent = text; // innerText is not well supported by jsdom
opt.innerText = text;
// Pass along data provided
for (const [key, value] of Object.entries(data)) {
opt.dataset[key] = value;
Expand Down Expand Up @@ -2336,7 +2351,7 @@ class Tags {
const allowClear = this._config.allowClear && !disabled;

// create span
let html = text;
let html = this._config.allowHtml ? text : sanitize(text);

/**
* @type {HTMLSpanElement}
Expand Down

0 comments on commit 9f8f8f0

Please sign in to comment.