@blumintinc/eslint-plugin-blumint 1.20.124 → 1.20.125

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/index.js CHANGED
@@ -223,7 +223,7 @@ function noFrontendImportsFromFunctionsPatterns(pattern) {
223
223
  module.exports = {
224
224
  meta: {
225
225
  name: '@blumintinc/eslint-plugin-blumint',
226
- version: '1.20.124',
226
+ version: '1.20.125',
227
227
  },
228
228
  parseOptions: {
229
229
  ecmaVersion: 2020,
@@ -508,15 +508,30 @@ exports.enforceQueryKeyTs = (0, createRule_1.createRule)({
508
508
  return null;
509
509
  }
510
510
  /**
511
- * Generate auto-fix suggestion for string literals
511
+ * The `QUERY_KEY_*` constant a key value names, or null when it names none.
512
+ *
513
+ * A key that is empty, or built only from the characters normalization
514
+ * folds into separators and then strips, leaves nothing after the prefix:
515
+ * the bare `QUERY_KEY_` that emitted is a name `queryKeys.ts` neither
516
+ * exports nor plausibly would, so applying it traded a report for a file
517
+ * that no longer compiles. Declining here leaves the report standing with
518
+ * no fix, which is the honest outcome — the author has to choose a real
519
+ * key, and no rewrite can choose one for them.
520
+ *
521
+ * The test is on the derived text alone, so it answers the same way for
522
+ * every notation the same value can be written in; putting it in
523
+ * `staticKeyOf` instead would gate the fix on content at the point that
524
+ * exists to keep notation out of the gate (#1803, #1813).
512
525
  */
513
526
  function generateAutoFix(keyValue) {
514
- // Simple heuristic to suggest query key constant names
515
527
  const normalizedKey = keyValue
516
528
  .toUpperCase()
517
529
  .replace(/[^A-Z0-9]/g, '_')
518
530
  .replace(/_+/g, '_')
519
531
  .replace(/^_|_$/g, '');
532
+ if (normalizedKey === '') {
533
+ return null;
534
+ }
520
535
  return `QUERY_KEY_${normalizedKey}`;
521
536
  }
522
537
  return {
@@ -179,6 +179,13 @@ exports.ensurePointerEventsNone = (0, createRule_1.createRule)({
179
179
  const absolutePositionedStyles = new Map();
180
180
  // Track style objects that already have pointer-events defined
181
181
  const stylesWithPointerEvents = new Map();
182
+ // Track style objects that declare a `pointerEvents` key whose value cannot
183
+ // be read statically (a member expression, a call, a ternary, an
184
+ // interpolated template). Such a value earns no exemption — it might be
185
+ // 'auto', so the report stands — but it does veto the fix: the rule's only
186
+ // remedy is to append a `pointerEvents` key, and an object literal with two
187
+ // identical keys does not compile (TS1117).
188
+ const stylesWithUnreadablePointerEvents = new Map();
182
189
  // Track style objects that are hit-slop touch-target extensions: an
183
190
  // absolute/fixed overlay whose inset offsets only extend beyond the origin
184
191
  // box (>=1 negative, none positive). A browser attributes pointer events on
@@ -192,6 +199,7 @@ exports.ensurePointerEventsNone = (0, createRule_1.createRule)({
192
199
  function processStyleObject(node) {
193
200
  let hasAbsolutePosition = false;
194
201
  let pointerEventsValue;
202
+ let hasUnreadablePointerEvents = false;
195
203
  let hasNegativeOffset = false;
196
204
  let hasPositiveOffset = false;
197
205
  // Check each property in the style object
@@ -204,12 +212,17 @@ exports.ensurePointerEventsNone = (0, createRule_1.createRule)({
204
212
  if (isAbsoluteOrFixedPosition(propertyName, propertyValue)) {
205
213
  hasAbsolutePosition = true;
206
214
  }
207
- // Check if this is pointer-events property. A value that cannot be read
208
- // statically never clears one already read: the rule's only remedy is to
209
- // append a `pointerEvents` key, which would duplicate the existing one.
210
- if (isPointerEventsProperty(propertyName) &&
211
- propertyValue !== undefined) {
212
- pointerEventsValue = propertyValue;
215
+ // Check if this is pointer-events property. A value that can be read
216
+ // decides the exemption; one that cannot is recorded separately, because
217
+ // the key's presence vetoes the fix even where it cannot prove the
218
+ // overlay is inert. An unreadable value never clears one already read.
219
+ if (isPointerEventsProperty(propertyName)) {
220
+ if (propertyValue !== undefined) {
221
+ pointerEventsValue = propertyValue;
222
+ }
223
+ else {
224
+ hasUnreadablePointerEvents = true;
225
+ }
213
226
  }
214
227
  // Track inset offsets to detect hit-slop touch-target extensions
215
228
  if (INSET_PROPERTIES.has(propertyName)) {
@@ -227,6 +240,7 @@ exports.ensurePointerEventsNone = (0, createRule_1.createRule)({
227
240
  if (pointerEventsValue !== undefined) {
228
241
  stylesWithPointerEvents.set(node, pointerEventsValue);
229
242
  }
243
+ stylesWithUnreadablePointerEvents.set(node, hasUnreadablePointerEvents);
230
244
  // A hit-slop extension only enlarges the tappable area: it is
231
245
  // absolute/fixed and its inset offsets extend outward (>=1 negative, none
232
246
  // positive). Such overlays cannot occlude the control they belong to.
@@ -257,6 +271,13 @@ exports.ensurePointerEventsNone = (0, createRule_1.createRule)({
257
271
  selector: formatSelector(selector),
258
272
  },
259
273
  fix(fixer) {
274
+ // The object already declares `pointerEvents`, but in a spelling
275
+ // whose value cannot be read. Appending the key is the rule's only
276
+ // remedy, and here it would emit a duplicate key that does not
277
+ // compile. A report with no fix is the correct outcome: the reader
278
+ // decides what the opaque value resolves to.
279
+ if (stylesWithUnreadablePointerEvents.get(node))
280
+ return null;
260
281
  // Find the last property in the object
261
282
  const sourceCode = context.sourceCode;
262
283
  const properties = node.properties;
@@ -336,7 +336,20 @@ exports.preferGlobalRouterStateKey = (0, createRule_1.createRule)({
336
336
  return null;
337
337
  }
338
338
  /**
339
- * Generate auto-fix suggestion for string literals
339
+ * The `QUERY_KEY_*` constant a key value names, or null when it names none.
340
+ *
341
+ * A key that is empty, or built only from the characters normalization
342
+ * folds into separators and then strips, leaves nothing after the prefix:
343
+ * the bare `QUERY_KEY_` that emitted is a name `queryKeys.ts` neither
344
+ * exports nor plausibly would, so applying it traded a report for a file
345
+ * that no longer compiles. Declining here leaves the report standing with
346
+ * no fix, which is the honest outcome — the author has to choose a real
347
+ * key, and no rewrite can choose one for them.
348
+ *
349
+ * The test is on the derived text alone, so it answers the same way for
350
+ * every notation the same value can be written in; putting it in
351
+ * `staticKeyOf` instead would gate the fix on content at the point that
352
+ * exists to keep notation out of the gate (#1804, #1811).
340
353
  */
341
354
  function generateAutoFix(keyValue) {
342
355
  const normalizedKey = keyValue
@@ -344,6 +357,9 @@ exports.preferGlobalRouterStateKey = (0, createRule_1.createRule)({
344
357
  .replace(/[^A-Z0-9]/g, '_')
345
358
  .replace(/_+/g, '_')
346
359
  .replace(/^_|_$/g, '');
360
+ if (normalizedKey === '') {
361
+ return null;
362
+ }
347
363
  return `QUERY_KEY_${normalizedKey}`;
348
364
  }
349
365
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blumintinc/eslint-plugin-blumint",
3
- "version": "1.20.124",
3
+ "version": "1.20.125",
4
4
  "description": "Custom eslint rules for use within BluMint",
5
5
  "author": {
6
6
  "name": "Brodie McGuire",
@@ -1,4 +1,34 @@
1
1
  [
2
+ {
3
+ "version": "1.20.125",
4
+ "date": "2026-08-06T17:33:56.677Z",
5
+ "rules": [
6
+ {
7
+ "name": "enforce-querykey-ts",
8
+ "changeType": "fix",
9
+ "issues": [
10
+ 1813
11
+ ],
12
+ "summary": "decline the fix when a key normalizes to nothing (closes #1813)"
13
+ },
14
+ {
15
+ "name": "ensure-pointer-events-none",
16
+ "changeType": "fix",
17
+ "issues": [
18
+ 1810
19
+ ],
20
+ "summary": "decline the fix when an existing pointerEvents value is unreadable (closes #1810)"
21
+ },
22
+ {
23
+ "name": "prefer-global-router-state-key",
24
+ "changeType": "fix",
25
+ "issues": [
26
+ 1811
27
+ ],
28
+ "summary": "decline the fix when a key normalizes to nothing (closes #1811)"
29
+ }
30
+ ]
31
+ },
2
32
  {
3
33
  "version": "1.20.124",
4
34
  "date": "2026-08-06T15:15:14.462Z",