assign-gingerly 0.0.16 → 0.0.17
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/README.md +34 -5
- package/buildCSSQuery.js +28 -16
- package/buildCSSQuery.ts +28 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2206,6 +2206,17 @@ console.log(query);
|
|
|
2206
2206
|
const elements = document.querySelectorAll(query);
|
|
2207
2207
|
```
|
|
2208
2208
|
|
|
2209
|
+
**Without selectors (matches any element):**
|
|
2210
|
+
|
|
2211
|
+
```TypeScript
|
|
2212
|
+
const query = buildCSSQuery(config, '');
|
|
2213
|
+
console.log(query);
|
|
2214
|
+
// '[my-component], [enh-my-component], [my-component-theme], [enh-my-component-theme]'
|
|
2215
|
+
|
|
2216
|
+
// Matches any element with these attributes
|
|
2217
|
+
const elements = document.querySelectorAll(query);
|
|
2218
|
+
```
|
|
2219
|
+
|
|
2209
2220
|
### How It Works
|
|
2210
2221
|
|
|
2211
2222
|
`buildCSSQuery` creates a cross-product of:
|
|
@@ -2289,11 +2300,25 @@ buildCSSQuery(config, 'div');
|
|
|
2289
2300
|
|
|
2290
2301
|
### Edge Cases
|
|
2291
2302
|
|
|
2292
|
-
**Empty
|
|
2303
|
+
**Empty selectors return attribute-only selectors:**
|
|
2304
|
+
```TypeScript
|
|
2305
|
+
const config = {
|
|
2306
|
+
spawn: MyClass,
|
|
2307
|
+
withAttrs: {
|
|
2308
|
+
base: 'my-attr',
|
|
2309
|
+
theme: '${base}-theme'
|
|
2310
|
+
}
|
|
2311
|
+
};
|
|
2312
|
+
|
|
2313
|
+
buildCSSQuery(config, '');
|
|
2314
|
+
// '[my-attr], [enh-my-attr], [my-attr-theme], [enh-my-attr-theme]'
|
|
2315
|
+
// Matches any element with these attributes
|
|
2316
|
+
```
|
|
2317
|
+
|
|
2318
|
+
**Empty withAttrs returns empty string:**
|
|
2293
2319
|
```TypeScript
|
|
2294
2320
|
buildCSSQuery({ spawn: MyClass }, 'div'); // '' (no withAttrs)
|
|
2295
2321
|
buildCSSQuery({ spawn: MyClass, withAttrs: {} }, 'div'); // '' (empty withAttrs)
|
|
2296
|
-
buildCSSQuery({ spawn: MyClass, withAttrs: { base: 'x' } }, ''); // '' (empty selectors)
|
|
2297
2322
|
```
|
|
2298
2323
|
|
|
2299
2324
|
**Deduplication:**
|
|
@@ -2312,14 +2337,15 @@ buildCSSQuery(config, ' div , span , p ');
|
|
|
2312
2337
|
|
|
2313
2338
|
1. **Mount Observer Integration**: Find elements that need enhancement
|
|
2314
2339
|
```TypeScript
|
|
2315
|
-
|
|
2340
|
+
// Match any element with the attributes
|
|
2341
|
+
const query = buildCSSQuery(enhancementConfig, '');
|
|
2316
2342
|
const observer = new MutationObserver(() => {
|
|
2317
2343
|
const elements = document.querySelectorAll(query);
|
|
2318
2344
|
elements.forEach(el => enhance(el));
|
|
2319
2345
|
});
|
|
2320
2346
|
```
|
|
2321
2347
|
|
|
2322
|
-
2. **
|
|
2348
|
+
2. **Specific Element Types**: Enhance only certain element types
|
|
2323
2349
|
```TypeScript
|
|
2324
2350
|
const query = buildCSSQuery(config, 'template, script');
|
|
2325
2351
|
document.querySelectorAll(query).forEach(el => {
|
|
@@ -2345,10 +2371,13 @@ function buildCSSQuery(
|
|
|
2345
2371
|
**Parameters:**
|
|
2346
2372
|
- `config`: Enhancement configuration with `withAttrs` property
|
|
2347
2373
|
- `selectors`: Comma-separated CSS selectors (e.g., `'div, span'`)
|
|
2374
|
+
- If empty string or whitespace only, returns attribute selectors without element prefix
|
|
2375
|
+
- This matches any element with the specified attributes
|
|
2348
2376
|
|
|
2349
2377
|
**Returns:**
|
|
2350
2378
|
- CSS query string with cross-product of selectors and attributes
|
|
2351
|
-
-
|
|
2379
|
+
- If selectors is empty: returns attribute-only selectors (e.g., `'[attr], [enh-attr]'`)
|
|
2380
|
+
- If withAttrs is missing or empty: returns empty string
|
|
2352
2381
|
|
|
2353
2382
|
**Throws:**
|
|
2354
2383
|
- Error if template variables have circular references
|
package/buildCSSQuery.js
CHANGED
|
@@ -65,6 +65,7 @@ function extractAttributeNames(withAttrs) {
|
|
|
65
65
|
*
|
|
66
66
|
* @param config - Enhancement configuration with withAttrs
|
|
67
67
|
* @param selectors - Comma-separated CSS selectors to match (e.g., 'template, script')
|
|
68
|
+
* If empty, returns just the attribute selectors without element prefix
|
|
68
69
|
* @returns CSS query string with cross-product of selectors and attributes
|
|
69
70
|
*
|
|
70
71
|
* @example
|
|
@@ -76,36 +77,47 @@ function extractAttributeNames(withAttrs) {
|
|
|
76
77
|
* }
|
|
77
78
|
* };
|
|
78
79
|
*
|
|
80
|
+
* // With selectors
|
|
79
81
|
* buildCSSQuery(config, 'div, span');
|
|
80
82
|
* // Returns: 'div[my-attr], span[my-attr], div[enh-my-attr], span[enh-my-attr],
|
|
81
83
|
* // div[my-attr-theme], span[my-attr-theme], div[enh-my-attr-theme], span[enh-my-attr-theme]'
|
|
84
|
+
*
|
|
85
|
+
* // Without selectors (matches any element)
|
|
86
|
+
* buildCSSQuery(config, '');
|
|
87
|
+
* // Returns: '[my-attr], [enh-my-attr], [my-attr-theme], [enh-my-attr-theme]'
|
|
82
88
|
*/
|
|
83
89
|
export function buildCSSQuery(config, selectors) {
|
|
84
90
|
// Validate inputs
|
|
85
|
-
if (!config.withAttrs
|
|
86
|
-
return '';
|
|
87
|
-
}
|
|
88
|
-
// Parse and normalize selectors
|
|
89
|
-
const selectorList = selectors
|
|
90
|
-
.split(',')
|
|
91
|
-
.map(s => s.trim())
|
|
92
|
-
.filter(s => s.length > 0);
|
|
93
|
-
if (selectorList.length === 0) {
|
|
91
|
+
if (!config.withAttrs) {
|
|
94
92
|
return '';
|
|
95
93
|
}
|
|
96
|
-
// Extract and resolve attribute names
|
|
94
|
+
// Extract and resolve attribute names first
|
|
97
95
|
const attrNames = extractAttributeNames(config.withAttrs);
|
|
98
96
|
if (attrNames.length === 0) {
|
|
99
97
|
return '';
|
|
100
98
|
}
|
|
101
|
-
//
|
|
99
|
+
// Parse and normalize selectors
|
|
100
|
+
const selectorList = selectors
|
|
101
|
+
? selectors.split(',').map(s => s.trim()).filter(s => s.length > 0)
|
|
102
|
+
: [];
|
|
103
|
+
// Build queries
|
|
102
104
|
const queries = [];
|
|
103
|
-
|
|
105
|
+
if (selectorList.length === 0) {
|
|
106
|
+
// No selectors provided - return just attribute selectors
|
|
104
107
|
for (const attrName of attrNames) {
|
|
105
|
-
|
|
106
|
-
queries.push(
|
|
107
|
-
|
|
108
|
-
|
|
108
|
+
queries.push(`[${attrName}]`);
|
|
109
|
+
queries.push(`[enh-${attrName}]`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// Build cross-product of selectors × attributes × prefixes
|
|
114
|
+
for (const selector of selectorList) {
|
|
115
|
+
for (const attrName of attrNames) {
|
|
116
|
+
// Unprefixed version
|
|
117
|
+
queries.push(`${selector}[${attrName}]`);
|
|
118
|
+
// enh- prefixed version
|
|
119
|
+
queries.push(`${selector}[enh-${attrName}]`);
|
|
120
|
+
}
|
|
109
121
|
}
|
|
110
122
|
}
|
|
111
123
|
// Deduplicate and join
|
package/buildCSSQuery.ts
CHANGED
|
@@ -83,6 +83,7 @@ function extractAttributeNames(withAttrs: AttrPatterns<any>): string[] {
|
|
|
83
83
|
*
|
|
84
84
|
* @param config - Enhancement configuration with withAttrs
|
|
85
85
|
* @param selectors - Comma-separated CSS selectors to match (e.g., 'template, script')
|
|
86
|
+
* If empty, returns just the attribute selectors without element prefix
|
|
86
87
|
* @returns CSS query string with cross-product of selectors and attributes
|
|
87
88
|
*
|
|
88
89
|
* @example
|
|
@@ -94,45 +95,54 @@ function extractAttributeNames(withAttrs: AttrPatterns<any>): string[] {
|
|
|
94
95
|
* }
|
|
95
96
|
* };
|
|
96
97
|
*
|
|
98
|
+
* // With selectors
|
|
97
99
|
* buildCSSQuery(config, 'div, span');
|
|
98
100
|
* // Returns: 'div[my-attr], span[my-attr], div[enh-my-attr], span[enh-my-attr],
|
|
99
101
|
* // div[my-attr-theme], span[my-attr-theme], div[enh-my-attr-theme], span[enh-my-attr-theme]'
|
|
102
|
+
*
|
|
103
|
+
* // Without selectors (matches any element)
|
|
104
|
+
* buildCSSQuery(config, '');
|
|
105
|
+
* // Returns: '[my-attr], [enh-my-attr], [my-attr-theme], [enh-my-attr-theme]'
|
|
100
106
|
*/
|
|
101
107
|
export function buildCSSQuery(
|
|
102
108
|
config: EnhancementConfig,
|
|
103
109
|
selectors: string
|
|
104
110
|
): string {
|
|
105
111
|
// Validate inputs
|
|
106
|
-
if (!config.withAttrs
|
|
112
|
+
if (!config.withAttrs) {
|
|
107
113
|
return '';
|
|
108
114
|
}
|
|
109
115
|
|
|
110
|
-
//
|
|
111
|
-
const selectorList = selectors
|
|
112
|
-
.split(',')
|
|
113
|
-
.map(s => s.trim())
|
|
114
|
-
.filter(s => s.length > 0);
|
|
115
|
-
|
|
116
|
-
if (selectorList.length === 0) {
|
|
117
|
-
return '';
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Extract and resolve attribute names
|
|
116
|
+
// Extract and resolve attribute names first
|
|
121
117
|
const attrNames = extractAttributeNames(config.withAttrs);
|
|
122
118
|
|
|
123
119
|
if (attrNames.length === 0) {
|
|
124
120
|
return '';
|
|
125
121
|
}
|
|
126
122
|
|
|
127
|
-
//
|
|
123
|
+
// Parse and normalize selectors
|
|
124
|
+
const selectorList = selectors
|
|
125
|
+
? selectors.split(',').map(s => s.trim()).filter(s => s.length > 0)
|
|
126
|
+
: [];
|
|
127
|
+
|
|
128
|
+
// Build queries
|
|
128
129
|
const queries: string[] = [];
|
|
129
130
|
|
|
130
|
-
|
|
131
|
+
if (selectorList.length === 0) {
|
|
132
|
+
// No selectors provided - return just attribute selectors
|
|
131
133
|
for (const attrName of attrNames) {
|
|
132
|
-
|
|
133
|
-
queries.push(
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
queries.push(`[${attrName}]`);
|
|
135
|
+
queries.push(`[enh-${attrName}]`);
|
|
136
|
+
}
|
|
137
|
+
} else {
|
|
138
|
+
// Build cross-product of selectors × attributes × prefixes
|
|
139
|
+
for (const selector of selectorList) {
|
|
140
|
+
for (const attrName of attrNames) {
|
|
141
|
+
// Unprefixed version
|
|
142
|
+
queries.push(`${selector}[${attrName}]`);
|
|
143
|
+
// enh- prefixed version
|
|
144
|
+
queries.push(`${selector}[enh-${attrName}]`);
|
|
145
|
+
}
|
|
136
146
|
}
|
|
137
147
|
}
|
|
138
148
|
|
package/package.json
CHANGED