@cypress/unique-selector 0.4.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/getData.js +7 -23
- package/lib/getName.js +19 -0
- package/lib/index.js +34 -56
- package/lib/isUnique.js +6 -2
- package/package.json +8 -11
- package/.babelrc +0 -3
- package/.eslintrc +0 -42
- package/.history/package-lock_20211116100405.json +0 -7884
- package/.history/package-lock_20211116101347.json +0 -7884
- package/.history/package_20180226102655.json +0 -62
- package/.history/package_20211018091805.json +0 -62
- package/.history/package_20211018091928.json +0 -62
- package/.history/package_20211116101343.json +0 -62
- package/.history/src/getData_20211116100405.js +0 -24
- package/.history/src/getData_20211116100500.js +0 -24
- package/.history/src/getData_20211116100511.js +0 -24
- package/.history/src/getData_20211116100803.js +0 -25
- package/.history/src/getData_20211116100925.js +0 -25
- package/.history/src/getData_20211116101054.js +0 -25
- package/.history/src/getData_20211116101058.js +0 -25
- package/.history/src/getData_20211116101234.js +0 -26
- package/.history/src/getData_20211116101243.js +0 -28
- package/.history/src/getData_20211116101301.js +0 -29
- package/.history/test/unique-selector_20180226102601.js +0 -131
- package/.history/test/unique-selector_20211018092001.js +0 -131
- package/.history/test/unique-selector_20211018092018.js +0 -131
- package/.history/test/unique-selector_20211018092209.js +0 -132
- package/.history/test/unique-selector_20211018092230.js +0 -132
- package/.history/test/unique-selector_20211018092245.js +0 -130
- package/.travis.yml +0 -11
- package/component.json +0 -12
- package/src/getAttributes.js +0 -20
- package/src/getClasses.js +0 -38
- package/src/getCombinations.js +0 -44
- package/src/getData.js +0 -29
- package/src/getID.js +0 -17
- package/src/getNthChild.js +0 -33
- package/src/getParents.js +0 -19
- package/src/getTag.js +0 -9
- package/src/index.js +0 -197
- package/src/isElement.js +0 -17
- package/src/isUnique.js +0 -12
- package/static/bundle.js +0 -5
- package/test/index.html +0 -0
- package/test/unique-selector.js +0 -146
package/component.json
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "unique-selector",
|
|
3
|
-
"repo": "ericclemmons/unique-selector",
|
|
4
|
-
"description": "Given a DOM element, return a unique CSS selector matching only that element",
|
|
5
|
-
"version": "0.0.1",
|
|
6
|
-
"keywords": ["element", "css", "selector"],
|
|
7
|
-
"development": {
|
|
8
|
-
"visionmedia/mocha-cloud": "*"
|
|
9
|
-
},
|
|
10
|
-
"license": "MIT",
|
|
11
|
-
"scripts": ["index.js"]
|
|
12
|
-
}
|
package/src/getAttributes.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Returns the Attribute selectors of the element
|
|
3
|
-
* @param { DOM Element } element
|
|
4
|
-
* @param { Array } array of attributes to ignore
|
|
5
|
-
* @return { Array }
|
|
6
|
-
*/
|
|
7
|
-
export function getAttributes( el, attributesToIgnore = ['id', 'class', 'length'] )
|
|
8
|
-
{
|
|
9
|
-
const { attributes } = el;
|
|
10
|
-
const attrs = [ ...attributes ];
|
|
11
|
-
|
|
12
|
-
return attrs.reduce( ( sum, next ) =>
|
|
13
|
-
{
|
|
14
|
-
if ( ! ( attributesToIgnore.indexOf( next.nodeName ) > -1 ) )
|
|
15
|
-
{
|
|
16
|
-
sum.push( `[${next.nodeName}="${next.value}"]` );
|
|
17
|
-
}
|
|
18
|
-
return sum;
|
|
19
|
-
}, [] );
|
|
20
|
-
}
|
package/src/getClasses.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import 'css.escape';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Get class names for an element
|
|
5
|
-
*
|
|
6
|
-
* @pararm { Element } el
|
|
7
|
-
* @return { Array }
|
|
8
|
-
*/
|
|
9
|
-
export function getClasses( el )
|
|
10
|
-
{
|
|
11
|
-
if( !el.hasAttribute( 'class' ) )
|
|
12
|
-
{
|
|
13
|
-
return [];
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
return Array.prototype.slice.call( el.classList );
|
|
18
|
-
} catch (e) {
|
|
19
|
-
let className = el.getAttribute( 'class' );
|
|
20
|
-
|
|
21
|
-
// remove duplicate and leading/trailing whitespaces
|
|
22
|
-
className = className.trim().replace( /\s+/g, ' ' );
|
|
23
|
-
|
|
24
|
-
// split into separate classnames
|
|
25
|
-
return className.split( ' ' );
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Returns the Class selectors of the element
|
|
31
|
-
* @param { Object } element
|
|
32
|
-
* @return { Array }
|
|
33
|
-
*/
|
|
34
|
-
export function getClassSelectors( el )
|
|
35
|
-
{
|
|
36
|
-
const classList = getClasses( el ).filter( Boolean );
|
|
37
|
-
return classList.map( cl => `.${CSS.escape( cl )}` );
|
|
38
|
-
}
|
package/src/getCombinations.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Recursively combinate items.
|
|
3
|
-
* @param { Array } result
|
|
4
|
-
* @param { Array } items
|
|
5
|
-
* @param { Array } data
|
|
6
|
-
* @param { Number } start
|
|
7
|
-
* @param { Number } end
|
|
8
|
-
* @param { Number } index
|
|
9
|
-
* @param { Number } k
|
|
10
|
-
*/
|
|
11
|
-
function kCombinations( result, items, data, start, end, index, k )
|
|
12
|
-
{
|
|
13
|
-
if( index === k )
|
|
14
|
-
{
|
|
15
|
-
result.push( data.slice( 0, index ).join( '' ) );
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
for( let i = start; i <= end && end - i + 1 >= k - index; ++i )
|
|
20
|
-
{
|
|
21
|
-
data[index] = items[i];
|
|
22
|
-
kCombinations( result, items, data, i + 1, end, index + 1, k );
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Returns all the possible selector combinations
|
|
28
|
-
* @param { Array } items
|
|
29
|
-
* @param { Number } k
|
|
30
|
-
* @return { Array }
|
|
31
|
-
*/
|
|
32
|
-
export function getCombinations( items, k )
|
|
33
|
-
{
|
|
34
|
-
const result = [],
|
|
35
|
-
n = items.length,
|
|
36
|
-
data = [];
|
|
37
|
-
|
|
38
|
-
for( var l = 1; l <= k; ++l )
|
|
39
|
-
{
|
|
40
|
-
kCombinations( result, items, data, 0, n - 1, 0, l );
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return result;
|
|
44
|
-
}
|
package/src/getData.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Returns the data-{dataAttr} selector of the element
|
|
3
|
-
* @param { String } selectorType - The type of selector to return.
|
|
4
|
-
* @param { String } attributes - The attributes of the element.
|
|
5
|
-
* @return { String | null } - The data-{dataAttr} selector of the element.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export const getData = ( selectorType, attributes ) =>
|
|
9
|
-
{
|
|
10
|
-
for ( let i = 0; i < attributes.length; i++ )
|
|
11
|
-
{
|
|
12
|
-
// extract node name + value
|
|
13
|
-
const { nodeName, value } = attributes[ i ];
|
|
14
|
-
|
|
15
|
-
// if this matches our selector
|
|
16
|
-
if ( nodeName === selectorType )
|
|
17
|
-
{
|
|
18
|
-
if ( value )
|
|
19
|
-
{
|
|
20
|
-
// if we have value that needs quotes
|
|
21
|
-
return `[${nodeName}="${value}"]`;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return `[${nodeName}]`;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return null;
|
|
29
|
-
};
|
package/src/getID.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import 'css.escape';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Returns the Tag of the element
|
|
5
|
-
* @param { Object } element
|
|
6
|
-
* @return { String }
|
|
7
|
-
*/
|
|
8
|
-
export function getID( el )
|
|
9
|
-
{
|
|
10
|
-
const id = el.getAttribute( 'id' );
|
|
11
|
-
|
|
12
|
-
if( id !== null && id !== '')
|
|
13
|
-
{
|
|
14
|
-
return `#${CSS.escape( id )}`;
|
|
15
|
-
}
|
|
16
|
-
return null;
|
|
17
|
-
}
|
package/src/getNthChild.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { isElement } from './isElement';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Returns the selectors based on the position of the element relative to its siblings
|
|
5
|
-
* @param { Object } element
|
|
6
|
-
* @return { Array }
|
|
7
|
-
*/
|
|
8
|
-
export function getNthChild( element )
|
|
9
|
-
{
|
|
10
|
-
let counter = 0;
|
|
11
|
-
let k;
|
|
12
|
-
let sibling;
|
|
13
|
-
const { parentNode } = element;
|
|
14
|
-
|
|
15
|
-
if( Boolean( parentNode ) )
|
|
16
|
-
{
|
|
17
|
-
const { childNodes } = parentNode;
|
|
18
|
-
const len = childNodes.length;
|
|
19
|
-
for ( k = 0; k < len; k++ )
|
|
20
|
-
{
|
|
21
|
-
sibling = childNodes[ k ];
|
|
22
|
-
if( isElement( sibling ) )
|
|
23
|
-
{
|
|
24
|
-
counter++;
|
|
25
|
-
if( sibling === element )
|
|
26
|
-
{
|
|
27
|
-
return `:nth-child(${counter})`;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return null;
|
|
33
|
-
}
|
package/src/getParents.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { isElement } from './isElement';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Returns all the element and all of its parents
|
|
5
|
-
* @param { DOM Element }
|
|
6
|
-
* @return { Array of DOM elements }
|
|
7
|
-
*/
|
|
8
|
-
export function getParents( el )
|
|
9
|
-
{
|
|
10
|
-
const parents = [];
|
|
11
|
-
let currentElement = el;
|
|
12
|
-
while( isElement( currentElement ) )
|
|
13
|
-
{
|
|
14
|
-
parents.push( currentElement );
|
|
15
|
-
currentElement = currentElement.parentNode;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return parents;
|
|
19
|
-
}
|
package/src/getTag.js
DELETED
package/src/index.js
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Expose `unique`
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { getID } from './getID';
|
|
6
|
-
import { getClassSelectors } from './getClasses';
|
|
7
|
-
import { getCombinations } from './getCombinations';
|
|
8
|
-
import { getAttributes } from './getAttributes';
|
|
9
|
-
import { getNthChild } from './getNthChild';
|
|
10
|
-
import { getTag } from './getTag';
|
|
11
|
-
import { isUnique } from './isUnique';
|
|
12
|
-
import { getParents } from './getParents';
|
|
13
|
-
import { getData } from './getData';
|
|
14
|
-
|
|
15
|
-
const dataRegex = /^data-(.+)/;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Returns all the selectors of the element
|
|
19
|
-
* @param { Object } element
|
|
20
|
-
* @return { Object }
|
|
21
|
-
*/
|
|
22
|
-
function getAllSelectors( el, selectors, attributesToIgnore )
|
|
23
|
-
{
|
|
24
|
-
const funcs =
|
|
25
|
-
{
|
|
26
|
-
'tag' : getTag,
|
|
27
|
-
'nth-child' : getNthChild,
|
|
28
|
-
'attributes' : elem => getAttributes( elem, attributesToIgnore ),
|
|
29
|
-
'class' : getClassSelectors,
|
|
30
|
-
'id' : getID,
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
return selectors
|
|
34
|
-
.filter( ( selector ) => !dataRegex.test( selector ) )
|
|
35
|
-
.reduce( ( res, next ) =>
|
|
36
|
-
{
|
|
37
|
-
res[ next ] = funcs[ next ]( el );
|
|
38
|
-
return res;
|
|
39
|
-
}, {} );
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Tests uniqueNess of the element inside its parent
|
|
44
|
-
* @param { Object } element
|
|
45
|
-
* @param { String } Selectors
|
|
46
|
-
* @return { Boolean }
|
|
47
|
-
*/
|
|
48
|
-
function testUniqueness( element, selector )
|
|
49
|
-
{
|
|
50
|
-
const { parentNode } = element;
|
|
51
|
-
const elements = parentNode.querySelectorAll( selector );
|
|
52
|
-
return elements.length === 1 && elements[ 0 ] === element;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Tests all selectors for uniqueness and returns the first unique selector.
|
|
57
|
-
* @param { Object } element
|
|
58
|
-
* @param { Array } selectors
|
|
59
|
-
* @return { String }
|
|
60
|
-
*/
|
|
61
|
-
function getFirstUnique( element, selectors )
|
|
62
|
-
{
|
|
63
|
-
return selectors.find( testUniqueness.bind( null, element ) );
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Checks all the possible selectors of an element to find one unique and return it
|
|
68
|
-
* @param { Object } element
|
|
69
|
-
* @param { Array } items
|
|
70
|
-
* @param { String } tag
|
|
71
|
-
* @return { String }
|
|
72
|
-
*/
|
|
73
|
-
function getUniqueCombination( element, items, tag )
|
|
74
|
-
{
|
|
75
|
-
let combinations = getCombinations( items, 3 ),
|
|
76
|
-
firstUnique = getFirstUnique( element, combinations );
|
|
77
|
-
|
|
78
|
-
if( Boolean( firstUnique ) )
|
|
79
|
-
{
|
|
80
|
-
return firstUnique;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if( Boolean( tag ) )
|
|
84
|
-
{
|
|
85
|
-
combinations = combinations.map( combination => tag + combination );
|
|
86
|
-
firstUnique = getFirstUnique( element, combinations );
|
|
87
|
-
|
|
88
|
-
if( Boolean( firstUnique ) )
|
|
89
|
-
{
|
|
90
|
-
return firstUnique;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Returns a uniqueSelector based on the passed options
|
|
99
|
-
* @param { DOM } element
|
|
100
|
-
* @param { Array } options
|
|
101
|
-
* @return { String }
|
|
102
|
-
*/
|
|
103
|
-
function getUniqueSelector( element, selectorTypes, attributesToIgnore )
|
|
104
|
-
{
|
|
105
|
-
let foundSelector;
|
|
106
|
-
|
|
107
|
-
const attributes = [...element.attributes];
|
|
108
|
-
|
|
109
|
-
const elementSelectors = getAllSelectors( element, selectorTypes, attributesToIgnore );
|
|
110
|
-
|
|
111
|
-
for( let selectorType of selectorTypes )
|
|
112
|
-
{
|
|
113
|
-
let selector = elementSelectors[ selectorType ];
|
|
114
|
-
|
|
115
|
-
// if we are a data attribute
|
|
116
|
-
if ( dataRegex.test( selectorType ) )
|
|
117
|
-
{
|
|
118
|
-
const dataSelector = getData( selectorType, attributes );
|
|
119
|
-
|
|
120
|
-
// if we found a selector via data attributes
|
|
121
|
-
if ( dataSelector )
|
|
122
|
-
{
|
|
123
|
-
selector = dataSelector;
|
|
124
|
-
selectorType = 'data';
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if ( !Boolean( selector ) ) continue;
|
|
129
|
-
|
|
130
|
-
switch ( selectorType )
|
|
131
|
-
{
|
|
132
|
-
case 'data' :
|
|
133
|
-
case 'id' :
|
|
134
|
-
case 'tag':
|
|
135
|
-
if ( testUniqueness( element, selector ) )
|
|
136
|
-
{
|
|
137
|
-
return selector;
|
|
138
|
-
}
|
|
139
|
-
break;
|
|
140
|
-
case 'class':
|
|
141
|
-
case 'attributes':
|
|
142
|
-
if ( selector.length )
|
|
143
|
-
{
|
|
144
|
-
foundSelector = getUniqueCombination( element, selector, elementSelectors.tag );
|
|
145
|
-
if ( foundSelector )
|
|
146
|
-
{
|
|
147
|
-
return foundSelector;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
break;
|
|
151
|
-
|
|
152
|
-
case 'nth-child':
|
|
153
|
-
return selector;
|
|
154
|
-
|
|
155
|
-
default:
|
|
156
|
-
break;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
return '*';
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Generate unique CSS selector for given DOM element
|
|
164
|
-
*
|
|
165
|
-
* @param {Element} el
|
|
166
|
-
* @return {String}
|
|
167
|
-
* @api private
|
|
168
|
-
*/
|
|
169
|
-
|
|
170
|
-
export default function unique( el, options={} )
|
|
171
|
-
{
|
|
172
|
-
const { selectorTypes=['id', 'class', 'tag', 'nth-child'], attributesToIgnore= ['id', 'class', 'length'] } = options;
|
|
173
|
-
const allSelectors = [];
|
|
174
|
-
const parents = getParents( el );
|
|
175
|
-
|
|
176
|
-
for( let elem of parents )
|
|
177
|
-
{
|
|
178
|
-
const selector = getUniqueSelector( elem, selectorTypes, attributesToIgnore );
|
|
179
|
-
if( Boolean( selector ) )
|
|
180
|
-
{
|
|
181
|
-
allSelectors.push( selector );
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const selectors = [];
|
|
186
|
-
for( let it of allSelectors )
|
|
187
|
-
{
|
|
188
|
-
selectors.unshift( it );
|
|
189
|
-
const selector = selectors.join( ' > ' );
|
|
190
|
-
if( isUnique( el, selector ) )
|
|
191
|
-
{
|
|
192
|
-
return selector;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return null;
|
|
197
|
-
}
|
package/src/isElement.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Determines if the passed el is a DOM element
|
|
3
|
-
*/
|
|
4
|
-
export function isElement( el )
|
|
5
|
-
{
|
|
6
|
-
let isElem;
|
|
7
|
-
|
|
8
|
-
if ( typeof HTMLElement === 'object' )
|
|
9
|
-
{
|
|
10
|
-
isElem = el instanceof HTMLElement;
|
|
11
|
-
}
|
|
12
|
-
else
|
|
13
|
-
{
|
|
14
|
-
isElem = !!el && ( typeof el === 'object' ) && el.nodeType === 1 && typeof el.nodeName === 'string';
|
|
15
|
-
}
|
|
16
|
-
return isElem;
|
|
17
|
-
}
|
package/src/isUnique.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Checks if the selector is unique
|
|
3
|
-
* @param { Object } element
|
|
4
|
-
* @param { String } selector
|
|
5
|
-
* @return { Array }
|
|
6
|
-
*/
|
|
7
|
-
export function isUnique( el, selector )
|
|
8
|
-
{
|
|
9
|
-
if( !Boolean( selector ) ) return false;
|
|
10
|
-
const elems = el.ownerDocument.querySelectorAll( selector );
|
|
11
|
-
return elems.length === 1 && elems[ 0 ] === el;
|
|
12
|
-
}
|