1- import getSelector from './get-selector' ;
21import getAncestry from './get-ancestry' ;
32import getXpath from './get-xpath' ;
43import getNodeFromTree from './get-node-from-tree' ;
@@ -7,30 +6,80 @@ import cache from '../base/cache';
76
87const CACHE_KEY = 'DqElm.RunOptions' ;
98
10- function truncate ( str , maxLength ) {
11- maxLength = maxLength || 300 ;
9+ function getFullPathSelector ( elm ) {
10+ if ( elm . nodeName === 'BODY' ) {
11+ return 'BODY' ;
12+ }
13+
14+ if ( cache . get ( 'getFullPathSelector' ) === undefined ) {
15+ cache . set ( 'getFullPathSelector' , new WeakMap ( ) ) ;
16+ }
1217
13- if ( str . length > maxLength ) {
14- var index = str . indexOf ( '>' ) ;
15- str = str . substring ( 0 , index + 1 ) ;
18+ // Check cache first
19+ const sourceCache = cache . get ( 'getFullPathSelector' ) ;
20+ if ( sourceCache . has ( elm ) ) {
21+ return sourceCache . get ( elm ) ;
1622 }
1723
18- return str ;
24+ const element = elm ;
25+ const names = [ ] ;
26+ while ( elm . parentElement && elm . nodeName !== 'BODY' ) {
27+ if ( elm . id ) {
28+ names . unshift ( '#' + elm . getAttribute ( 'id' ) ) ;
29+ break ;
30+ } else {
31+ let c = 1 ,
32+ e = elm ;
33+ for ( ; e . previousElementSibling ; e = e . previousElementSibling , c ++ ) { }
34+ names . unshift ( elm . nodeName + ':nth-child(' + c + ')' ) ;
35+ }
36+ elm = elm . parentElement ;
37+ }
38+
39+ const selector = names . join ( '>' ) ;
40+ sourceCache . set ( element , selector ) ;
41+ return selector ;
1942}
2043
2144function getSource ( element ) {
22- if ( ! element ?. outerHTML ) {
45+ if ( ! element ) {
2346 return '' ;
2447 }
25- var source = element . outerHTML ;
26- if ( ! source && typeof window . XMLSerializer === 'function' ) {
27- source = new window . XMLSerializer ( ) . serializeToString ( element ) ;
48+
49+ // Initialize cache if needed
50+ if ( cache . get ( 'getSourceEfficient' ) === undefined ) {
51+ cache . set ( 'getSourceEfficient' , new WeakMap ( ) ) ;
52+ }
53+
54+ // Check cache first
55+ const sourceCache = cache . get ( 'getSourceEfficient' ) ;
56+ if ( sourceCache . has ( element ) ) {
57+ return sourceCache . get ( element ) ;
2858 }
29- let htmlString = truncate ( source || '' ) ;
30- // Remove unwanted attributes
31- const regex = / \s * d a t a - p e r c y - [ ^ = ] + = " [ ^ " ] * " / g;
32- htmlString = htmlString . replace ( regex , '' ) ;
33- return htmlString ;
59+
60+ // Compute value if not cached
61+ const tagName = element . nodeName ?. toLowerCase ( ) ;
62+ if ( ! tagName ) {
63+ return '' ;
64+ }
65+
66+ let result ;
67+ try {
68+ const attributes = Array . from ( element . attributes || [ ] )
69+ . filter ( attr => ! attr . name . startsWith ( 'data-percy-' ) )
70+ . map ( attr => `${ attr . name } ="${ attr . value } "` )
71+ . join ( ' ' ) ;
72+
73+ result = attributes ? `<${ tagName } ${ attributes } >` : `<${ tagName } >` ;
74+
75+ // Store in cache
76+ sourceCache . set ( element , result ) ;
77+ } catch ( e ) {
78+ // Handle potential errors (like accessing attributes on non-element nodes)
79+ result = `<${ tagName || 'unknown' } >` ;
80+ }
81+
82+ return result ;
3483}
3584
3685/**
@@ -94,7 +143,9 @@ DqElement.prototype = {
94143 * @return {String }
95144 */
96145 get selector ( ) {
97- return this . spec . selector || [ getSelector ( this . element , this . _options ) ] ;
146+ return (
147+ this . spec . selector || [ getFullPathSelector ( this . element , this . _options ) ]
148+ ) ;
98149 } ,
99150
100151 /**
0 commit comments