123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- Object.defineProperty(exports, '__esModule', { value: true });
- const is = require('./is.js');
- const worldwide = require('./worldwide.js');
- const WINDOW = worldwide.getGlobalObject();
- const DEFAULT_MAX_STRING_LENGTH = 80;
- function htmlTreeAsString(
- elem,
- options = {},
- ) {
- if (!elem) {
- return '<unknown>';
- }
-
-
-
-
- try {
- let currentElem = elem ;
- const MAX_TRAVERSE_HEIGHT = 5;
- const out = [];
- let height = 0;
- let len = 0;
- const separator = ' > ';
- const sepLength = separator.length;
- let nextStr;
- const keyAttrs = Array.isArray(options) ? options : options.keyAttrs;
- const maxStringLength = (!Array.isArray(options) && options.maxStringLength) || DEFAULT_MAX_STRING_LENGTH;
- while (currentElem && height++ < MAX_TRAVERSE_HEIGHT) {
- nextStr = _htmlElementAsString(currentElem, keyAttrs);
- // bail out if
- // - nextStr is the 'html' element
- // - the length of the string that would be created exceeds maxStringLength
- // (ignore this limit if we are on the first iteration)
- if (nextStr === 'html' || (height > 1 && len + out.length * sepLength + nextStr.length >= maxStringLength)) {
- break;
- }
- out.push(nextStr);
- len += nextStr.length;
- currentElem = currentElem.parentNode;
- }
- return out.reverse().join(separator);
- } catch (_oO) {
- return '<unknown>';
- }
- }
- /**
- * Returns a simple, query-selector representation of a DOM element
- * e.g. [HTMLElement] => input#foo.btn[name=baz]
- * @returns generated DOM path
- */
- function _htmlElementAsString(el, keyAttrs) {
- const elem = el
- ;
- const out = [];
- let className;
- let classes;
- let key;
- let attr;
- let i;
- if (!elem || !elem.tagName) {
- return '';
- }
- // @ts-expect-error WINDOW has HTMLElement
- if (WINDOW.HTMLElement) {
- // If using the component name annotation plugin, this value may be available on the DOM node
- if (elem instanceof HTMLElement && elem.dataset && elem.dataset['sentryComponent']) {
- return elem.dataset['sentryComponent'];
- }
- }
- out.push(elem.tagName.toLowerCase());
- // Pairs of attribute keys defined in `serializeAttribute` and their values on element.
- const keyAttrPairs =
- keyAttrs && keyAttrs.length
- ? keyAttrs.filter(keyAttr => elem.getAttribute(keyAttr)).map(keyAttr => [keyAttr, elem.getAttribute(keyAttr)])
- : null;
- if (keyAttrPairs && keyAttrPairs.length) {
- keyAttrPairs.forEach(keyAttrPair => {
- out.push(`[${keyAttrPair[0]}="${keyAttrPair[1]}"]`);
- });
- } else {
- if (elem.id) {
- out.push(`#${elem.id}`);
- }
- // eslint-disable-next-line prefer-const
- className = elem.className;
- if (className && is.isString(className)) {
- classes = className.split(/\s+/);
- for (i = 0; i < classes.length; i++) {
- out.push(`.${classes[i]}`);
- }
- }
- }
- const allowedAttrs = ['aria-label', 'type', 'name', 'title', 'alt'];
- for (i = 0; i < allowedAttrs.length; i++) {
- key = allowedAttrs[i];
- attr = elem.getAttribute(key);
- if (attr) {
- out.push(`[${key}="${attr}"]`);
- }
- }
- return out.join('');
- }
- /**
- * A safe form of location.href
- */
- function getLocationHref() {
- try {
- return WINDOW.document.location.href;
- } catch (oO) {
- return '';
- }
- }
- /**
- * Gets a DOM element by using document.querySelector.
- *
- * This wrapper will first check for the existance of the function before
- * actually calling it so that we don't have to take care of this check,
- * every time we want to access the DOM.
- *
- * Reason: DOM/querySelector is not available in all environments.
- *
- * We have to cast to any because utils can be consumed by a variety of environments,
- * and we don't want to break TS users. If you know what element will be selected by
- * `document.querySelector`, specify it as part of the generic call. For example,
- * `const element = getDomElement<Element>('selector');`
- *
- * @param selector the selector string passed on to document.querySelector
- */
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- function getDomElement(selector) {
- if (WINDOW.document && WINDOW.document.querySelector) {
- return WINDOW.document.querySelector(selector) ;
- }
- return null;
- }
- /**
- * Given a DOM element, traverses up the tree until it finds the first ancestor node
- * that has the `data-sentry-component` attribute. This attribute is added at build-time
- * by projects that have the component name annotation plugin installed.
- *
- * @returns a string representation of the component for the provided DOM element, or `null` if not found
- */
- function getComponentName(elem) {
- // @ts-expect-error WINDOW has HTMLElement
- if (!WINDOW.HTMLElement) {
- return null;
- }
- let currentElem = elem ;
- const MAX_TRAVERSE_HEIGHT = 5;
- for (let i = 0; i < MAX_TRAVERSE_HEIGHT; i++) {
- if (!currentElem) {
- return null;
- }
- if (currentElem instanceof HTMLElement && currentElem.dataset['sentryComponent']) {
- return currentElem.dataset['sentryComponent'];
- }
- currentElem = currentElem.parentNode;
- }
- return null;
- }
- exports.getComponentName = getComponentName;
- exports.getDomElement = getDomElement;
- exports.getLocationHref = getLocationHref;
- exports.htmlTreeAsString = htmlTreeAsString;
- //# sourceMappingURL=browser.js.map
|