plus-8.x-4.x-dev/js/Html.es6.js
js/Html.es6.js
(function (Drupal) {
/**
* @class Html
*
* The partial JavaScript counterpart of \Drupal\Component\Utility\Html.
*
* Does not contain the DOM traversals or AJAX methods.
*/
class Html {
/**
* An array of previously cleaned HTML classes.
*
* @var {Object}
*/
static classes = {};
/**
* An array of the initial IDs used in one request.
*
* @var {Object}
*/
static seenIdsInit = null;
/**
* An array of IDs, including incremented versions when an ID is duplicated.
*
* @var {Object}
*/
static seenIds = null;
/**
* Prepares a string for use as a CSS identifier (element, class, or ID name).
*
* Note: this is essentially a direct copy from
* \Drupal\Component\Utility\Html::cleanCssIdentifier
*
* @param {String} identifier
* The identifier to clean.
* @param {Object} [filter]
* An object of string replacements to use on the identifier.
*
* @return {String}
* The cleaned identifier.
*/
static cleanCssIdentifier(identifier, filter) {
filter = filter || {
' ': '-',
'_': '-',
'/': '-',
'[': '-',
']': ''
};
if (filter['__'] === void 0) {
identifier = identifier.replace('__', '#DOUBLE_UNDERSCORE#', identifier);
}
identifier = identifier.replace(Object.keys(filter), Object.values(filter), identifier);
if (filter['__'] === void 0) {
identifier = identifier.replace('#DOUBLE_UNDERSCORE#', '__', identifier);
}
identifier = identifier.replace(/[^\u002D\u0030-\u0039\u0041-\u005A\u005F\u0061-\u007A\u00A1-\uFFFF]/g, '');
identifier = identifier.replace(['/^[0-9]/', '/^(-[0-9])|^(--)/'], ['_', '__'], identifier);
return identifier;
}
/**
* Decodes all HTML entities including numerical ones to regular UTF-8 bytes.
*
* Double-escaped entities will only be decoded once ("<" becomes
* "<", not "<").
*
* Double-escaped entities will only be decoded once ("&lt;" becomes
* "<", not "<"). Be careful when using this function, as it will revert
* previous sanitization efforts (<script> will become <script>).
*
* This method is not the opposite of Html.escape. For example, this method
* will convert "é" to "é", whereas Html::escape() will not convert
* "é" to "é".
*
* @param {String} text
* The text to decode entities in.
*
* @return string
* The input $text, with all HTML entities decoded once.
*
* @see \Drupal\Component\Utility\Html::decodeEntities
* @see Html.escape
* @see https://stackoverflow.com/a/7394787
*
* @todo Consider replacing with https://www.npmjs.com/package/html-entities
* once jsdelivr support is added.
*/
static decodeEntities(text) {
const el = document.createElement('textarea');
el.innerHTML = text;
return el.value;
}
/**
* Escapes text by converting special characters to HTML entities.
*
* This method escapes HTML for sanitization purposes by replacing the
* following special characters with their HTML entity equivalents:
* - & (ampersand) becomes &
* - " (double quote) becomes "
* - ' (single quote) becomes '
* - < (less than) becomes <
* - > (greater than) becomes >
* Special characters that have already been escaped will be double-escaped
* (for example, "<" becomes "&lt;").
*
* This method is not the opposite of Html.decodeEntities. For example,
* this method will not encode "é" to "é", whereas
* Html::decodeEntities() will convert all HTML entities to UTF-8 bytes,
* including "é" and "<" to "é" and "<".
*
* @param {String} text
* The input text.
*
* @return {String}
* The text with all HTML special characters converted.
*
* @see htmlspecialchars()
* @see \Drupal\Component\Utility\Html::decodeEntities()
*
* @todo Consider replacing with https://www.npmjs.com/package/html-entities
* once jsdelivr support is added.
*/
static escape(text) {
// Immediately return an empty string if there is no text.
return text === void 0 || text === null ? '' : text.toString()
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/</g, '<')
.replace(/>/g, '>');
}
/**
* Prepares a string for use as a valid class name.
*
* Do not pass one string containing multiple classes as they will be
* incorrectly concatenated with dashes, i.e. "one two" will become "one-two".
*
* @param {*} className
* The class name to clean. It can be a string or anything that can be cast
* to string.
*
* @return {String}
* The cleaned class name.
*/
static getClass(className) {
className = '' + className;
if (this.classes[className] === void 0) {
this.classes[className] = this.cleanCssIdentifier(className.toLowerCase());
}
return this.classes[className];
}
/**
* Prepares a string for use as a valid HTML ID and guarantees uniqueness.
*
* @param {String} id
* The ID to clean.
*
* @return {String}
* The cleaned ID.
*/
static getUniqueId(id) {
if (this.seenIdsInit === null) {
this.seenIdsInit = {};
}
if (this.seenIds === null) {
this.seenIds = this.seenIdsInit;
}
id = this.getId(id);
if (this.seenIds[id] !== void 0) {
id = id + '--' + ++this.seenIds[id];
}
else {
this.seenIds[id] = 1;
}
return id;
}
/**
* Prepares a string for use as a valid HTML ID.
*
* @param {String} id
* The ID to clean.
*
* @return {String}
* The cleaned ID.
*
* @see this.getUniqueId
*/
static getId(id) {
return id
.toLowerCase()
.replace(']', '').replace(/\s|_|\[/, '-')
.replace(/[^A-Za-z0-9\-_]/, '')
.replace(/[-]+/, '-');
}
/**
* Resets the list of seen IDs.
*/
static resetSeenIds() {
this.seenIds = null;
}
}
Drupal.Html = Html;
// Replace core's "checkPlain" method.
Drupal.checkPlain = Drupal.Html.escape;
})(window.Drupal);
