@futdevpro/dynamo-eslint 1.20.51 → 1.20.57

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.
Files changed (40) hide show
  1. package/README.md +35 -2
  2. package/build/configs/ngx.d.ts +6 -0
  3. package/build/configs/ngx.d.ts.map +1 -1
  4. package/build/configs/ngx.js +20 -0
  5. package/build/configs/ngx.js.map +1 -1
  6. package/build/plugin/index.d.ts +1 -0
  7. package/build/plugin/index.d.ts.map +1 -1
  8. package/build/plugin/index.js +2 -0
  9. package/build/plugin/index.js.map +1 -1
  10. package/build/plugin/rules/angular/empty-state-guard.util.d.ts +58 -0
  11. package/build/plugin/rules/angular/empty-state-guard.util.d.ts.map +1 -0
  12. package/build/plugin/rules/angular/empty-state-guard.util.js +158 -0
  13. package/build/plugin/rules/angular/empty-state-guard.util.js.map +1 -0
  14. package/build/plugin/rules/angular/empty-state-requires-guard.d.ts +10 -0
  15. package/build/plugin/rules/angular/empty-state-requires-guard.d.ts.map +1 -0
  16. package/build/plugin/rules/angular/empty-state-requires-guard.js +61 -0
  17. package/build/plugin/rules/angular/empty-state-requires-guard.js.map +1 -0
  18. package/build/plugin/rules/angular/ui-building-blocks-baseline.interface.d.ts +5 -0
  19. package/build/plugin/rules/angular/ui-building-blocks-baseline.interface.d.ts.map +1 -1
  20. package/build/plugin/rules/angular/ui-building-blocks-element.interface.d.ts +5 -0
  21. package/build/plugin/rules/angular/ui-building-blocks-element.interface.d.ts.map +1 -1
  22. package/build/plugin/rules/angular/ui-building-blocks-rule-context.util.js +1 -1
  23. package/build/plugin/rules/angular/ui-building-blocks-rule-context.util.js.map +1 -1
  24. package/build/plugin/rules/angular/ui-building-blocks.util.d.ts +10 -1
  25. package/build/plugin/rules/angular/ui-building-blocks.util.d.ts.map +1 -1
  26. package/build/plugin/rules/angular/ui-building-blocks.util.js +44 -4
  27. package/build/plugin/rules/angular/ui-building-blocks.util.js.map +1 -1
  28. package/build/plugin/rules/prefer-enum-over-string-union.d.ts.map +1 -1
  29. package/build/plugin/rules/prefer-enum-over-string-union.js +5 -42
  30. package/build/plugin/rules/prefer-enum-over-string-union.js.map +1 -1
  31. package/build/plugin/rules/prefer-interface-over-duplicate-types.d.ts.map +1 -1
  32. package/build/plugin/rules/prefer-interface-over-duplicate-types.js +31 -19
  33. package/build/plugin/rules/prefer-interface-over-duplicate-types.js.map +1 -1
  34. package/build/scripts/lint-strict.d.ts +62 -0
  35. package/build/scripts/lint-strict.d.ts.map +1 -0
  36. package/build/scripts/lint-strict.js +151 -0
  37. package/build/scripts/lint-strict.js.map +1 -0
  38. package/build/scripts/ui-building-blocks-baseline.js +17 -2
  39. package/build/scripts/ui-building-blocks-baseline.js.map +1 -1
  40. package/package.json +4 -3
package/README.md CHANGED
@@ -198,6 +198,17 @@ This package includes custom ESLint rules for Dynamo conventions:
198
198
  show a loading state (`…Loading…`, `inProgress_$`, `loading-skeleton`) but none of which shows a failed state
199
199
  (`@if (…error|…failed…)`, a `…load-failed` / `…error-state` component, a `load…error|failed` test id). A list OF
200
200
  errors (`errors`) is not a failed state.
201
+ - **`@futdevpro/dynamo/empty-state-requires-guard`** (BFR-QA-003): an empty-state message — a Hungarian "none / not
202
+ yet" sentence (`Nincs…`, `Még nincs…`, also in an empty-state component's `message`) or a `@for … @empty` branch —
203
+ with no loading / failed guard: neither an ancestor `@if` / `@else if` of the same template nor any template up the
204
+ rendering parent chain guards it (`inProgress`, `failed_$()`, `loading`, `skeleton`, `load-failed`, `…Loaded_$()`).
205
+ Unguarded, the user reads "none" WHILE the data loads and AFTER a failed load. Not reported: the empty-state
206
+ component tag alone (it is also a "select something" placeholder), a permission denial ("Nincs jogosultság…").
207
+ Known limits: a guard passed through an `[input]`, an i18n-bound message, a descriptive "Nincs…" sentence, an
208
+ `@empty` over a locally computed list — silence a NEW such case with
209
+ `<!-- eslint-disable-next-line @futdevpro/dynamo/empty-state-requires-guard -->`. Counted per file in the same
210
+ baseline (`emptyStatesWithoutGuard`); the `ngx` preset switches it on **only when the baseline has that section**,
211
+ i.e. after you regenerate the baseline with a version that knows the rule.
201
212
 
202
213
  **Adopt them in a project** (run in the folder ESLint runs in, e.g. `client/`):
203
214
  ```bash
@@ -205,8 +216,8 @@ This package includes custom ESLint rules for Dynamo conventions:
205
216
  npx dynamo-ui-building-blocks-baseline --scroller-tag app-pull-to-refresh # a component that IS a scroll container
206
217
  npx dynamo-ui-building-blocks-baseline --check # exit 1 on a new case
207
218
  ```
208
- Exactly like the XSS guard: the `ngx` preset switches both rules on (`error`) **only when that baseline file
209
- exists**, so a dependency bump never breaks a `--max-warnings=0` lint step. The listed scroller tags live in the
219
+ Exactly like the XSS guard: the `ngx` preset switches the first two rules on (`error`) **only when that baseline file
220
+ exists** (the empty-state rule: only when it also has its section), so a dependency bump never breaks a `--max-warnings=0` lint step. The listed scroller tags live in the
210
221
  baseline's `settings`, so the rules and the generator always agree. Lower the baseline when you fix a case.
211
222
 
212
223
  ### Unused Component Rule
@@ -266,6 +277,28 @@ Add to your `package.json`:
266
277
  }
267
278
  ```
268
279
 
280
+ ### Strict lint gate — `dynamo-lint-strict`
281
+
282
+ A release/CI gate whose exit code comes from ESLint's **aggregated** counters (the project's own flat config):
283
+
284
+ ```bash
285
+ dynamo-lint-strict [patterns...] [--max-warnings <n>] [--json]
286
+ dynamo-lint-strict src --max-warnings 0 # zero-warning gate
287
+ dynamo-lint-strict src --max-warnings 1200 # ratchet for a known warning backlog
288
+ ```
289
+
290
+ | exit | meaning |
291
+ |---|---|
292
+ | `0` | 0 errors (parsing errors included) and warnings within the budget |
293
+ | `1` | any error, or more warnings than `--max-warnings` |
294
+ | `2` | lint could not run — config error, no file matched, crash (**never** a pass) |
295
+
296
+ - **Warning budget:** without `--max-warnings` warnings are reported but don't fail; set it explicitly for a gate.
297
+ - **`--json`:** the last stdout line is `{ errorCount, fatalErrorCount, warningCount, fileCount, maxWarnings, legacyEslintignore, passed, exitCode }`.
298
+ - **`.eslintignore` is dead in ESLint 9 flat config** — the files listed there ARE linted. The gate reports it loudly;
299
+ move the patterns into an `ignores` entry of `eslint.config.*`:
300
+ `module.exports = [ ...require('@futdevpro/dynamo-eslint/ngx'), { ignores: [ 'dist-electron/**' ] } ];`
301
+
269
302
  ### Explicit legacy boolean-name exceptions
270
303
 
271
304
  `dynamo-validate-naming` is strict by default. A consumer that must preserve an existing persisted or public
@@ -17,6 +17,12 @@ declare const xssSurfaceGuard: Record<string, string>;
17
17
  * changes, so `--max-warnings=0` lint steps do not break on the bump.
18
18
  */
19
19
  declare const uiBuildingBlocksGuard: Record<string, string>;
20
+ /**
21
+ * BFR-QA-003 — the empty-state guard rides on the SAME baseline file, but switches on only when that file carries the
22
+ * `emptyStatesWithoutGuard` section (i.e. it was regenerated with a version that knows the rule). A baseline written
23
+ * before the rule existed would otherwise make every current unguarded message a NEW error on the package bump.
24
+ */
25
+ declare const emptyStateGuard: Record<string, string>;
20
26
  /**
21
27
  * BFR-QA-006 — the built-but-unused component guard (project-wide) is switched on the same way, by COMMITTING its
22
28
  * baseline (`npx dynamo-unused-components-baseline`). Measured 2026-09-24 on 35 Angular apps: 81 of 1209 components
@@ -1 +1 @@
1
- {"version":3,"file":"ngx.d.ts","sourceRoot":"","sources":["../../src/configs/ngx.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,aAAa,KAAoB,CAAC;AACxC,QAAA,MAAM,aAAa,KAA4B,CAAC;AAChD,QAAA,MAAM,EAAE,KAAgB,CAAC;AACzB,QAAA,MAAM,IAAI,KAAkB,CAAC;AAE7B;;;;;GAKG;AACH,QAAA,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAEtC,CAAC;AAEP;;;;;;GAMG;AACH,QAAA,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAM1C,CAAC;AAET;;;;GAIG;AACH,QAAA,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGzC,CAAC"}
1
+ {"version":3,"file":"ngx.d.ts","sourceRoot":"","sources":["../../src/configs/ngx.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,aAAa,KAAoB,CAAC;AACxC,QAAA,MAAM,aAAa,KAA4B,CAAC;AAChD,QAAA,MAAM,EAAE,KAAgB,CAAC;AACzB,QAAA,MAAM,IAAI,KAAkB,CAAC;AAE7B;;;;;GAKG;AACH,QAAA,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAEtC,CAAC;AAEP;;;;;;GAMG;AACH,QAAA,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAM1C,CAAC;AAET;;;;GAIG;AACH,QAAA,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAaxC,CAAC;AAEL;;;;GAIG;AACH,QAAA,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGzC,CAAC"}
@@ -24,6 +24,24 @@ const uiBuildingBlocksGuard = fs.existsSync(path.join(process.cwd(), '.dynamo',
24
24
  '@futdevpro/dynamo/module-load-failed-branch': 'error',
25
25
  }
26
26
  : {};
27
+ /**
28
+ * BFR-QA-003 — the empty-state guard rides on the SAME baseline file, but switches on only when that file carries the
29
+ * `emptyStatesWithoutGuard` section (i.e. it was regenerated with a version that knows the rule). A baseline written
30
+ * before the rule existed would otherwise make every current unguarded message a NEW error on the package bump.
31
+ */
32
+ const emptyStateGuard = (() => {
33
+ const file = path.join(process.cwd(), '.dynamo', 'ui-building-blocks-baseline.json');
34
+ try {
35
+ const parsed = fs.existsSync(file) ? JSON.parse(fs.readFileSync(file, 'utf8')) : undefined;
36
+ const hasSection = typeof parsed === 'object' && parsed !== null
37
+ && typeof Reflect.get(parsed, 'emptyStatesWithoutGuard') === 'object';
38
+ return hasSection ? { '@futdevpro/dynamo/empty-state-requires-guard': 'error' } : {};
39
+ }
40
+ catch {
41
+ // an unreadable baseline is reported by the other two rules (`baselineUnreadable`) — this one stays off
42
+ return {};
43
+ }
44
+ })();
27
45
  /**
28
46
  * BFR-QA-006 — the built-but-unused component guard (project-wide) is switched on the same way, by COMMITTING its
29
47
  * baseline (`npx dynamo-unused-components-baseline`). Measured 2026-09-24 on 35 Angular apps: 81 of 1209 components
@@ -79,6 +97,7 @@ module.exports = [
79
97
  '@futdevpro/dynamo/effect-signal-loop': 'warn',
80
98
  ...xssSurfaceGuard,
81
99
  ...uiBuildingBlocksGuard,
100
+ ...emptyStateGuard,
82
101
  ...unusedComponentGuard,
83
102
  },
84
103
  },
@@ -120,6 +139,7 @@ module.exports = [
120
139
  '@futdevpro/dynamo/no-ngfor-directive': 'warn',
121
140
  ...xssSurfaceGuard,
122
141
  ...uiBuildingBlocksGuard,
142
+ ...emptyStateGuard,
123
143
  },
124
144
  },
125
145
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"ngx.js","sourceRoot":"","sources":["../../src/configs/ngx.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngx.js","sourceRoot":"","sources":["../../src/configs/ngx.ts"],"names":[],"mappings":"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"}
@@ -27,6 +27,7 @@ declare const _default: {
27
27
  'no-unlisted-inner-html': import("eslint").Rule.RuleModule;
28
28
  'scroll-container-min-h-0': import("eslint").Rule.RuleModule;
29
29
  'module-load-failed-branch': import("eslint").Rule.RuleModule;
30
+ 'empty-state-requires-guard': import("eslint").Rule.RuleModule;
30
31
  'no-unused-component': import("eslint").Rule.RuleModule;
31
32
  };
32
33
  configs: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,kBAiEE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,kBAkEE"}
@@ -27,6 +27,7 @@ const no_ngfor_directive_1 = tslib_1.__importDefault(require("./rules/angular/no
27
27
  const no_unlisted_inner_html_1 = tslib_1.__importDefault(require("./rules/angular/no-unlisted-inner-html"));
28
28
  const scroll_container_min_h_0_1 = tslib_1.__importDefault(require("./rules/angular/scroll-container-min-h-0"));
29
29
  const module_load_failed_branch_1 = tslib_1.__importDefault(require("./rules/angular/module-load-failed-branch"));
30
+ const empty_state_requires_guard_1 = tslib_1.__importDefault(require("./rules/angular/empty-state-requires-guard"));
30
31
  const no_unused_component_1 = tslib_1.__importDefault(require("./rules/angular/no-unused-component"));
31
32
  module.exports = {
32
33
  rules: {
@@ -61,6 +62,7 @@ module.exports = {
61
62
  // BFR-QA-004 — UI building blocks guard (baseline-aware)
62
63
  'scroll-container-min-h-0': scroll_container_min_h_0_1.default,
63
64
  'module-load-failed-branch': module_load_failed_branch_1.default,
65
+ 'empty-state-requires-guard': empty_state_requires_guard_1.default,
64
66
  // BFR-QA-006 — built-but-unused component guard (baseline-aware, project-wide)
65
67
  'no-unused-component': no_unused_component_1.default,
66
68
  },
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":";;AAAA,oFAAuD;AACvD,uFAA0D;AAC1D,sFAAyD;AACzD,2FAA6D;AAC7D,uFAA4D;AAC5D,kIAAgF;AAChF,0GAAiE;AACjE,kHAAmE;AACnE,sHAA4E;AAC5E,sFAAwD;AAExD,+EAAiD;AACjD,iFAAmD;AACnD,+FAAiE;AACjE,iGAAkE;AAClE,2GAA4E;AAC5E,+FAAiE;AACjE,6GAA8E;AAE9E,kGAAoE;AACpE,8GAA+E;AAC/E,oGAAsE;AACtE,oHAAoF;AACpF,8GAA+E;AAC/E,kGAAoE;AACpE,oGAAsE;AACtE,4GAA6E;AAC7E,gHAAgF;AAChF,kHAAmF;AACnF,sGAAwE;AAExE,iBAAS;IACP,KAAK,EAAE;QACL,gBAAgB,EAAE,wBAAiB;QACnC,cAAc,EAAE,sBAAe;QAC/B,gBAAgB,EAAE,wBAAgB;QAClC,cAAc,EAAE,sBAAiB;QACjC,uCAAuC,EAAE,+CAAmB;QAC5D,2BAA2B,EAAE,mCAAgB;QAC7C,+BAA+B,EAAE,uCAAc;QAC/C,iCAAiC,EAAE,yCAAqB;QACxD,iBAAiB,EAAE,yBAAiB;QAEpC,iBAAiB,EAAE,yBAAkB;QAErC,gDAAgD;QAChD,YAAY,EAAE,oBAAY;QAC1B,aAAa,EAAE,qBAAa;QAC5B,oBAAoB,EAAE,4BAAoB;QAC1C,qBAAqB,EAAE,6BAAoB;QAC3C,0BAA0B,EAAE,kCAAyB;QACrD,oBAAoB,EAAE,4BAAoB;QAC1C,2BAA2B,EAAE,mCAA0B;QAEvD,kEAAkE;QAClE,mBAAmB,EAAE,2BAAmB;QACxC,yBAAyB,EAAE,iCAAwB;QACnD,oBAAoB,EAAE,4BAAoB;QAC1C,4BAA4B,EAAE,oCAA0B;QACxD,yBAAyB,EAAE,iCAAwB;QACnD,mBAAmB,EAAE,2BAAmB;QACxC,oBAAoB,EAAE,4BAAoB;QAC1C,kDAAkD;QAClD,wBAAwB,EAAE,gCAAuB;QACjD,yDAAyD;QACzD,0BAA0B,EAAE,kCAAwB;QACpD,2BAA2B,EAAE,mCAA0B;QACvD,+EAA+E;QAC/E,qBAAqB,EAAE,6BAAqB;KAC7C;IACD,OAAO,EAAE;QACP,WAAW,EAAE;YACX,KAAK,EAAE;gBACL,kCAAkC,EAAE,MAAM;gBAC1C,gCAAgC,EAAE,MAAM;gBACxC,kCAAkC,EAAE,MAAM;gBAC1C,gCAAgC,EAAE,MAAM;gBACxC,yDAAyD,EAAE,MAAM;gBACjE,6CAA6C,EAAE,MAAM;gBACrD,iDAAiD,EAAE,MAAM;gBACzD,mDAAmD,EAAE,MAAM;gBAC3D,mCAAmC,EAAE,MAAM;gBAE3C,mCAAmC,EAAE,MAAM;gBAE3C,gDAAgD;gBAChD,8BAA8B,EAAE,MAAM;gBACtC,+BAA+B,EAAE,MAAM;gBACvC,sCAAsC,EAAE,MAAM;gBAC9C,uCAAuC,EAAE,MAAM;gBAC/C,4CAA4C,EAAE,MAAM;gBACpD,sCAAsC,EAAE,MAAM;gBAC9C,6CAA6C,EAAE,MAAM;aACtD;SACF;KACF;CACF,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":";;AAAA,oFAAuD;AACvD,uFAA0D;AAC1D,sFAAyD;AACzD,2FAA6D;AAC7D,uFAA4D;AAC5D,kIAAgF;AAChF,0GAAiE;AACjE,kHAAmE;AACnE,sHAA4E;AAC5E,sFAAwD;AAExD,+EAAiD;AACjD,iFAAmD;AACnD,+FAAiE;AACjE,iGAAkE;AAClE,2GAA4E;AAC5E,+FAAiE;AACjE,6GAA8E;AAE9E,kGAAoE;AACpE,8GAA+E;AAC/E,oGAAsE;AACtE,oHAAoF;AACpF,8GAA+E;AAC/E,kGAAoE;AACpE,oGAAsE;AACtE,4GAA6E;AAC7E,gHAAgF;AAChF,kHAAmF;AACnF,oHAAqF;AACrF,sGAAwE;AAExE,iBAAS;IACP,KAAK,EAAE;QACL,gBAAgB,EAAE,wBAAiB;QACnC,cAAc,EAAE,sBAAe;QAC/B,gBAAgB,EAAE,wBAAgB;QAClC,cAAc,EAAE,sBAAiB;QACjC,uCAAuC,EAAE,+CAAmB;QAC5D,2BAA2B,EAAE,mCAAgB;QAC7C,+BAA+B,EAAE,uCAAc;QAC/C,iCAAiC,EAAE,yCAAqB;QACxD,iBAAiB,EAAE,yBAAiB;QAEpC,iBAAiB,EAAE,yBAAkB;QAErC,gDAAgD;QAChD,YAAY,EAAE,oBAAY;QAC1B,aAAa,EAAE,qBAAa;QAC5B,oBAAoB,EAAE,4BAAoB;QAC1C,qBAAqB,EAAE,6BAAoB;QAC3C,0BAA0B,EAAE,kCAAyB;QACrD,oBAAoB,EAAE,4BAAoB;QAC1C,2BAA2B,EAAE,mCAA0B;QAEvD,kEAAkE;QAClE,mBAAmB,EAAE,2BAAmB;QACxC,yBAAyB,EAAE,iCAAwB;QACnD,oBAAoB,EAAE,4BAAoB;QAC1C,4BAA4B,EAAE,oCAA0B;QACxD,yBAAyB,EAAE,iCAAwB;QACnD,mBAAmB,EAAE,2BAAmB;QACxC,oBAAoB,EAAE,4BAAoB;QAC1C,kDAAkD;QAClD,wBAAwB,EAAE,gCAAuB;QACjD,yDAAyD;QACzD,0BAA0B,EAAE,kCAAwB;QACpD,2BAA2B,EAAE,mCAA0B;QACvD,4BAA4B,EAAE,oCAA2B;QACzD,+EAA+E;QAC/E,qBAAqB,EAAE,6BAAqB;KAC7C;IACD,OAAO,EAAE;QACP,WAAW,EAAE;YACX,KAAK,EAAE;gBACL,kCAAkC,EAAE,MAAM;gBAC1C,gCAAgC,EAAE,MAAM;gBACxC,kCAAkC,EAAE,MAAM;gBAC1C,gCAAgC,EAAE,MAAM;gBACxC,yDAAyD,EAAE,MAAM;gBACjE,6CAA6C,EAAE,MAAM;gBACrD,iDAAiD,EAAE,MAAM;gBACzD,mDAAmD,EAAE,MAAM;gBAC3D,mCAAmC,EAAE,MAAM;gBAE3C,mCAAmC,EAAE,MAAM;gBAE3C,gDAAgD;gBAChD,8BAA8B,EAAE,MAAM;gBACtC,+BAA+B,EAAE,MAAM;gBACvC,sCAAsC,EAAE,MAAM;gBAC9C,uCAAuC,EAAE,MAAM;gBAC/C,4CAA4C,EAAE,MAAM;gBACpD,sCAAsC,EAAE,MAAM;gBAC9C,6CAA6C,EAAE,MAAM;aACtD;SACF;KACF;CACF,CAAC"}
@@ -0,0 +1,58 @@
1
+ /** One empty-state message of a file, as the BFR-QA-003 rule sees it. */
2
+ export interface EmptyStateGuard_Finding_Interface {
3
+ /** Offset in the SOURCE file (inline templates are shifted to their place in the `.ts`). */
4
+ offset: number;
5
+ /** An ancestor `@if` / `@else if` block of the SAME template is a loading / failed guard. */
6
+ ownGuard: boolean;
7
+ }
8
+ /**
9
+ * BFR-QA-003 — an empty-state message ("Nincs …" — also in an empty-state component's `message` — or a `@for … @empty` branch)
10
+ * must sit behind a loading- or failed-state guard: "empty", "loading" and "failed" are THREE states — an unguarded
11
+ * "Nincs X" also shows WHILE loading and AFTER a failed load (a false statement to the user). Measured by the QA lane on
12
+ * the organizer: 5 of 18 empty-state messages had no guard.
13
+ *
14
+ * The guard may be OWN (an ancestor `@if` / `@else if` in the same template) or the PARENT's: the component is
15
+ * rendered by a template that itself guards (the kanban case — the list's "Nincs lejárt feladat." is guarded by the
16
+ * board's `@if (tasksLoad.inProgress_$()) … @else if (failed_$())`). Logic ported from the QA lane's
17
+ * `empty-state-guard-audit.ts` v2 (parent-chain version, which removed the v1's 14 false alarms).
18
+ *
19
+ * KNOWN LIMIT (kept from the audit): a guard handed over at runtime through an `[input]` is not visible.
20
+ */
21
+ export declare class EmptyStateGuard_Util {
22
+ /** The rule id. */
23
+ static readonly ruleId: string;
24
+ /**
25
+ * An empty-state message: a Hungarian "none / not yet" sentence (also inside an empty-state component's `message`),
26
+ * or an `@empty` branch. ⚠️ The empty-state COMPONENT TAG alone does not count — measured on the organizer: the same
27
+ * `<app-a-empty-data>` is also a "nothing selected yet" placeholder ("Válasszon ki egy feladatot…"), which claims no
28
+ * emptiness. Nor does a PERMISSION denial ("Nincs jogosultságod…" — measured on the organizer's permission-denied
29
+ * page: no data is loaded there, so there is nothing to guard).
30
+ * KNOWN LIMIT: a message bound through i18n (`[message]="texts.none"`) is not visible to a template rule.
31
+ */
32
+ static readonly emptyStatePattern: RegExp;
33
+ /** A loading- or failed-state guard in a condition / template. */
34
+ static readonly guardPattern: RegExp;
35
+ /** The empty-state messages of a file, each with whether an ancestor block of its own template guards it. */
36
+ static findings(text: string, filename: string): EmptyStateGuard_Finding_Interface[];
37
+ /**
38
+ * Where an empty state ends: an `@empty` block at its closing brace, a message inside a tag's attributes at the
39
+ * tag's `>` (measured: `message="Nincs bolt"` + `description="Még nincs felvéve bolt…"` = ONE state), otherwise
40
+ * at its line end.
41
+ */
42
+ private static extentOf;
43
+ /**
44
+ * Per line: whether an ANCESTOR `@if` / `@else if` block is a guard (brace-depth tracking; the `@empty` line itself
45
+ * belongs to its `@for`, which is not a guard).
46
+ */
47
+ static enclosingGuards(lines: string[]): boolean[];
48
+ /**
49
+ * Whether the component owning `filename`'s template is rendered by a template that guards (recursively up the
50
+ * parent chain). `root` = the project root (the scan of `no-unused-component` is reused and cached).
51
+ */
52
+ static guardedByParent(filename: string, root: string): boolean;
53
+ /** The element selectors (`app-x`) of the component that owns the file's template. */
54
+ static ownSelectors(filename: string): string[];
55
+ /** Recursive parent-chain walk: a template rendering one of `selectors` guards, or ITS parents do. */
56
+ private static parentGuards;
57
+ }
58
+ //# sourceMappingURL=empty-state-guard.util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"empty-state-guard.util.d.ts","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/empty-state-guard.util.ts"],"names":[],"mappings":"AAKA,yEAAyE;AACzE,MAAM,WAAW,iCAAiC;IAChD,4FAA4F;IAC5F,MAAM,EAAE,MAAM,CAAC;IACf,6FAA6F;IAC7F,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,oBAAoB;IAE/B,mBAAmB;IACnB,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAkD;IAEhF;;;;;;;OAOG;IACH,MAAM,CAAC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAGvC;IAEF,kEAAkE;IAClE,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CACqE;IAEzG,6GAA6G;IAC7G,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,iCAAiC,EAAE;IA4BpF;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ;IAmBvB;;;OAGG;IACH,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE;IA2BlD;;;OAGG;IACH,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAW/D,sFAAsF;IACtF,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAa/C,sGAAsG;IACtG,OAAO,CAAC,MAAM,CAAC,YAAY;CAkC5B"}
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EmptyStateGuard_Util = void 0;
4
+ const fs_1 = require("fs");
5
+ const ui_building_blocks_util_1 = require("./ui-building-blocks.util");
6
+ const unused_component_util_1 = require("./unused-component.util");
7
+ /**
8
+ * BFR-QA-003 — an empty-state message ("Nincs …" — also in an empty-state component's `message` — or a `@for … @empty` branch)
9
+ * must sit behind a loading- or failed-state guard: "empty", "loading" and "failed" are THREE states — an unguarded
10
+ * "Nincs X" also shows WHILE loading and AFTER a failed load (a false statement to the user). Measured by the QA lane on
11
+ * the organizer: 5 of 18 empty-state messages had no guard.
12
+ *
13
+ * The guard may be OWN (an ancestor `@if` / `@else if` in the same template) or the PARENT's: the component is
14
+ * rendered by a template that itself guards (the kanban case — the list's "Nincs lejárt feladat." is guarded by the
15
+ * board's `@if (tasksLoad.inProgress_$()) … @else if (failed_$())`). Logic ported from the QA lane's
16
+ * `empty-state-guard-audit.ts` v2 (parent-chain version, which removed the v1's 14 false alarms).
17
+ *
18
+ * KNOWN LIMIT (kept from the audit): a guard handed over at runtime through an `[input]` is not visible.
19
+ */
20
+ class EmptyStateGuard_Util {
21
+ /** The rule id. */
22
+ static ruleId = '@futdevpro/dynamo/empty-state-requires-guard';
23
+ /**
24
+ * An empty-state message: a Hungarian "none / not yet" sentence (also inside an empty-state component's `message`),
25
+ * or an `@empty` branch. ⚠️ The empty-state COMPONENT TAG alone does not count — measured on the organizer: the same
26
+ * `<app-a-empty-data>` is also a "nothing selected yet" placeholder ("Válasszon ki egy feladatot…"), which claims no
27
+ * emptiness. Nor does a PERMISSION denial ("Nincs jogosultságod…" — measured on the organizer's permission-denied
28
+ * page: no data is loaded there, so there is nothing to guard).
29
+ * KNOWN LIMIT: a message bound through i18n (`[message]="texts.none"`) is not visible to a template rule.
30
+ */
31
+ static emptyStatePattern = new RegExp('(?:Nincs|Nincsenek|Még nincs|Még nincsenek|Meg nincs|Meg nincsenek)\\s+(?!jogosult)[a-zA-ZÀ-ſ]|'
32
+ + '@empty\\b');
33
+ /** A loading- or failed-state guard in a condition / template. */
34
+ static guardPattern = /inProgress|failed_?\$?\(|loadInProgress|isLoading|loading_?\$?\(|skeleton|load-failed|Loaded_?\$?\(/i;
35
+ /** The empty-state messages of a file, each with whether an ancestor block of its own template guards it. */
36
+ static findings(text, filename) {
37
+ const result = [];
38
+ ui_building_blocks_util_1.UiBuildingBlocks_Util.templates(text, filename).forEach((template) => {
39
+ const code = ui_building_blocks_util_1.UiBuildingBlocks_Util.blankComments(template.text);
40
+ const guarded = EmptyStateGuard_Util.enclosingGuards(code.split('\n'));
41
+ const regex = new RegExp(EmptyStateGuard_Util.emptyStatePattern.source, 'g');
42
+ // ONE finding per empty state: anything inside an `@empty` block belongs to that block
43
+ // (measured: `@empty { <app-a-empty-data message="Nincs…"> }` counted twice before)
44
+ const covered = [];
45
+ let match = regex.exec(code);
46
+ while (match !== null) {
47
+ const at = match.index;
48
+ if (!covered.some(([start, end]) => at > start && at < end)) {
49
+ const line = code.slice(0, at).split('\n').length - 1;
50
+ result.push({ offset: template.offset + at, ownGuard: guarded[line] });
51
+ covered.push([at, EmptyStateGuard_Util.extentOf(code, at, match[0])]);
52
+ }
53
+ match = regex.exec(code);
54
+ }
55
+ });
56
+ return result;
57
+ }
58
+ /**
59
+ * Where an empty state ends: an `@empty` block at its closing brace, a message inside a tag's attributes at the
60
+ * tag's `>` (measured: `message="Nincs bolt"` + `description="Még nincs felvéve bolt…"` = ONE state), otherwise
61
+ * at its line end.
62
+ */
63
+ static extentOf(code, at, matched) {
64
+ if (matched.startsWith('@empty')) {
65
+ let depth = 0;
66
+ for (let i = code.indexOf('{', at); i >= 0 && i < code.length; i++) {
67
+ depth += code[i] === '{' ? 1 : code[i] === '}' ? -1 : 0;
68
+ if (!depth) {
69
+ return i;
70
+ }
71
+ }
72
+ return code.length;
73
+ }
74
+ const inTag = code.lastIndexOf('<', at) > code.lastIndexOf('>', at);
75
+ const end = code.indexOf(inTag ? '>' : '\n', at);
76
+ return end < 0 ? code.length : end;
77
+ }
78
+ /**
79
+ * Per line: whether an ANCESTOR `@if` / `@else if` block is a guard (brace-depth tracking; the `@empty` line itself
80
+ * belongs to its `@for`, which is not a guard).
81
+ */
82
+ static enclosingGuards(lines) {
83
+ const out = lines.map(() => false);
84
+ const stack = [];
85
+ let depth = 0;
86
+ lines.forEach((line, index) => {
87
+ out[index] = stack.some((frame) => frame.guard);
88
+ const control = /@(if|else if|else|for|empty)\s*(\([^)]*\))?/.exec(line);
89
+ const opens = (line.match(/\{/g) ?? []).length;
90
+ const closes = (line.match(/\}/g) ?? []).length;
91
+ if (control && opens > 0) {
92
+ stack.push({
93
+ guard: (control[1] === 'if' || control[1] === 'else if') && EmptyStateGuard_Util.guardPattern.test(control[2] ?? ''),
94
+ depth: depth,
95
+ });
96
+ out[index] = stack.some((frame) => frame.guard);
97
+ }
98
+ depth += opens - closes;
99
+ while (stack.length && depth <= stack[stack.length - 1].depth) {
100
+ stack.pop();
101
+ }
102
+ });
103
+ return out;
104
+ }
105
+ /**
106
+ * Whether the component owning `filename`'s template is rendered by a template that guards (recursively up the
107
+ * parent chain). `root` = the project root (the scan of `no-unused-component` is reused and cached).
108
+ */
109
+ static guardedByParent(filename, root) {
110
+ const selectors = EmptyStateGuard_Util.ownSelectors(filename);
111
+ if (!selectors.length) {
112
+ return false;
113
+ }
114
+ const sources = unused_component_util_1.UnusedComponent_Util.projectIndex(root).sources;
115
+ return EmptyStateGuard_Util.parentGuards(selectors, sources, new Set());
116
+ }
117
+ /** The element selectors (`app-x`) of the component that owns the file's template. */
118
+ static ownSelectors(filename) {
119
+ const tsFile = filename.endsWith('.html') ? filename.replace(/\.html$/, '.ts') : filename;
120
+ if (!(0, fs_1.existsSync)(tsFile)) {
121
+ return [];
122
+ }
123
+ return unused_component_util_1.UnusedComponent_Util.componentsOf((0, fs_1.readFileSync)(tsFile, 'utf8'))
124
+ .flatMap((component) => component.selectors)
125
+ .map((selector) => (/^[a-z][\w-]*/.exec(selector) ?? [''])[0])
126
+ .filter((element) => element.includes('-'));
127
+ }
128
+ /** Recursive parent-chain walk: a template rendering one of `selectors` guards, or ITS parents do. */
129
+ static parentGuards(selectors, sources, seen) {
130
+ const fresh = selectors.filter((s) => !seen.has(s));
131
+ if (!fresh.length) {
132
+ return false;
133
+ }
134
+ fresh.forEach((s) => {
135
+ seen.add(s);
136
+ });
137
+ return sources.some((source) => {
138
+ const templates = ui_building_blocks_util_1.UiBuildingBlocks_Util.templates(source.text, source.file)
139
+ .map((t) => ui_building_blocks_util_1.UiBuildingBlocks_Util.blankComments(t.text)).join('\n');
140
+ if (!fresh.some((s) => new RegExp('<' + s + '(?![\\w-])').test(templates))) {
141
+ return false;
142
+ }
143
+ if (EmptyStateGuard_Util.guardPattern.test(templates)) {
144
+ return true;
145
+ }
146
+ const parentTs = source.file.endsWith('.html') ? source.file.replace(/\.html$/, '.ts') : source.file;
147
+ const parent = sources.find((s) => s.file === parentTs);
148
+ const parentSelectors = parent
149
+ ? unused_component_util_1.UnusedComponent_Util.componentsOf(parent.text).flatMap((c) => c.selectors)
150
+ .map((selector) => (/^[a-z][\w-]*/.exec(selector) ?? [''])[0])
151
+ .filter((element) => element.includes('-'))
152
+ : [];
153
+ return EmptyStateGuard_Util.parentGuards(parentSelectors, sources, seen);
154
+ });
155
+ }
156
+ }
157
+ exports.EmptyStateGuard_Util = EmptyStateGuard_Util;
158
+ //# sourceMappingURL=empty-state-guard.util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"empty-state-guard.util.js","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/empty-state-guard.util.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { Rule } from 'eslint';
2
+ /**
3
+ * BFR-QA-003 — an empty-state message must sit behind a loading- or failed-state guard (own ancestor block, or the
4
+ * rendering parent's). Baseline-counted per file like `scroll-container-min-h-0`: the accepted count of a file is
5
+ * silent, every ADDITIONAL unguarded message is reported. Switched on by the `ngx` preset only when the project's
6
+ * UI-building-blocks baseline carries the `emptyStatesWithoutGuard` section.
7
+ */
8
+ declare const rule: Rule.RuleModule;
9
+ export default rule;
10
+ //# sourceMappingURL=empty-state-requires-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"empty-state-requires-guard.d.ts","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/empty-state-requires-guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAO9B;;;;;GAKG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAqDhB,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const empty_state_guard_util_1 = require("./empty-state-guard.util");
4
+ const ui_building_blocks_rule_context_util_1 = require("./ui-building-blocks-rule-context.util");
5
+ const ui_building_blocks_util_1 = require("./ui-building-blocks.util");
6
+ /**
7
+ * BFR-QA-003 — an empty-state message must sit behind a loading- or failed-state guard (own ancestor block, or the
8
+ * rendering parent's). Baseline-counted per file like `scroll-container-min-h-0`: the accepted count of a file is
9
+ * silent, every ADDITIONAL unguarded message is reported. Switched on by the `ngx` preset only when the project's
10
+ * UI-building-blocks baseline carries the `emptyStatesWithoutGuard` section.
11
+ */
12
+ const rule = {
13
+ meta: {
14
+ type: 'problem',
15
+ docs: {
16
+ description: 'An empty-state message ("Nincs …", a `@for … @empty` branch) needs a loading / failed guard.',
17
+ recommended: true,
18
+ },
19
+ schema: ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.schema,
20
+ messages: {
21
+ noGuard: 'This empty-state message has no loading / failed guard — not in an ancestor `@if` of this template, '
22
+ + 'and not in any template that renders this component. While the data loads, or after a failed load, the '
23
+ + 'user would read "none" — a false statement. Put it in the `@else` of a loading / failed chain (e.g. '
24
+ + '`@if (load.inProgress_$()) {…} @else if (load.failed_$()) {…} @else { … }`). ({{count}} in this file, '
25
+ + 'baseline {{baseline}}; BFR-QA-003)',
26
+ baselineUnreadable: ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.baselineUnreadableMessage,
27
+ },
28
+ },
29
+ create(context) {
30
+ const filename = context.filename ?? '';
31
+ if (!ui_building_blocks_util_1.UiBuildingBlocks_Util.isInScope(filename)) {
32
+ return {};
33
+ }
34
+ return {
35
+ Program() {
36
+ const text = context.sourceCode.text ?? '';
37
+ const own = empty_state_guard_util_1.EmptyStateGuard_Util.findings(text, filename)
38
+ .filter((finding) => !finding.ownGuard);
39
+ if (!own.length) {
40
+ return;
41
+ }
42
+ const cwd = context.cwd ?? process.cwd();
43
+ // the parent chain is looked up only when this template has unguarded messages (the project scan is cached)
44
+ if (empty_state_guard_util_1.EmptyStateGuard_Util.guardedByParent(filename, cwd)) {
45
+ return;
46
+ }
47
+ const baseline = ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.baseline(context);
48
+ const accepted = baseline.emptyStatesWithoutGuard?.[ui_building_blocks_util_1.UiBuildingBlocks_Util.relativeKey(filename, cwd)] ?? 0;
49
+ own.slice(accepted).forEach((finding) => {
50
+ context.report({
51
+ loc: ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.loc(text, finding.offset),
52
+ messageId: 'noGuard',
53
+ data: { count: String(own.length), baseline: String(accepted) },
54
+ });
55
+ });
56
+ },
57
+ };
58
+ },
59
+ };
60
+ exports.default = rule;
61
+ //# sourceMappingURL=empty-state-requires-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"empty-state-requires-guard.js","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/empty-state-requires-guard.ts"],"names":[],"mappings":";;AAEA,qEAAmG;AAEnG,iGAA2F;AAC3F,uEAAkE;AAElE;;;;;GAKG;AACH,MAAM,IAAI,GAAoB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,8FAA8F;YAC3G,WAAW,EAAE,IAAI;SAClB;QACD,MAAM,EAAE,wEAAiC,CAAC,MAAM;QAChD,QAAQ,EAAE;YACR,OAAO,EAAE,sGAAsG;kBAC3G,yGAAyG;kBACzG,sGAAsG;kBACtG,wGAAwG;kBACxG,oCAAoC;YACxC,kBAAkB,EAAE,wEAAiC,CAAC,yBAAyB;SAChF;KACF;IACD,MAAM,CAAC,OAAyB;QAC9B,MAAM,QAAQ,GAAW,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;QAEhD,IAAI,CAAC,+CAAqB,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/C,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO;YACL,OAAO;gBACL,MAAM,IAAI,GAAW,OAAO,CAAC,UAAU,CAAC,IAAI,IAAI,EAAE,CAAC;gBACnD,MAAM,GAAG,GAAwC,6CAAoB,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;qBAC3F,MAAM,CAAC,CAAC,OAA0C,EAAW,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAEtF,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;oBAChB,OAAO;gBACT,CAAC;gBACD,MAAM,GAAG,GAAW,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;gBAEjD,4GAA4G;gBAC5G,IAAI,6CAAoB,CAAC,eAAe,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC;oBACxD,OAAO;gBACT,CAAC;gBACD,MAAM,QAAQ,GAAwC,wEAAiC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAC1G,MAAM,QAAQ,GACZ,QAAQ,CAAC,uBAAuB,EAAE,CAAC,+CAAqB,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;gBAE5F,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,OAA0C,EAAQ,EAAE;oBAC/E,OAAO,CAAC,MAAM,CAAC;wBACb,GAAG,EAAE,wEAAiC,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC;wBAChE,SAAS,EAAE,SAAS;wBACpB,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE;qBAChE,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,kBAAe,IAAI,CAAC"}
@@ -6,5 +6,10 @@ export interface UiBuildingBlocks_Baseline_Interface {
6
6
  scrollContainers: Record<string, number>;
7
7
  /** Accepted modules (relative folder, e.g. `src/app/_modules/tasks`) with a loading state but no failed branch. */
8
8
  modulesWithoutLoadFailedBranch: string[];
9
+ /**
10
+ * BFR-QA-003: accepted empty-state messages without a loading / failed guard, per file. OPTIONAL — absent in a
11
+ * baseline generated before the rule existed (the `ngx` preset then keeps the rule off).
12
+ */
13
+ emptyStatesWithoutGuard?: Record<string, number>;
9
14
  }
10
15
  //# sourceMappingURL=ui-building-blocks-baseline.interface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ui-building-blocks-baseline.interface.d.ts","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/ui-building-blocks-baseline.interface.ts"],"names":[],"mappings":"AAAA,4GAA4G;AAC5G,MAAM,WAAW,mCAAmC;IAClD,qGAAqG;IACrG,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,kGAAkG;IAClG,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,mHAAmH;IACnH,8BAA8B,EAAE,MAAM,EAAE,CAAC;CAC1C"}
1
+ {"version":3,"file":"ui-building-blocks-baseline.interface.d.ts","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/ui-building-blocks-baseline.interface.ts"],"names":[],"mappings":"AAAA,4GAA4G;AAC5G,MAAM,WAAW,mCAAmC;IAClD,qGAAqG;IACrG,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,kGAAkG;IAClG,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,mHAAmH;IACnH,8BAA8B,EAAE,MAAM,EAAE,CAAC;IACzC;;;OAGG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClD"}
@@ -6,6 +6,11 @@ export interface UiBuildingBlocks_Element_Interface {
6
6
  classes: string[];
7
7
  /** A height / max-height is set inline (`style`, `[style.height]`, `[ngStyle]`). */
8
8
  heightStyle: boolean;
9
+ /**
10
+ * BFR-MASTERPROMPTER-075: positioned out of the flex flow at RUNTIME — the `[dynamo-overlay]` directive
11
+ * (`DyNX_setOverlay`: `position: absolute`, 100 % × 100 %). Not visible in the classes, so it is read from the tag.
12
+ */
13
+ outOfFlow?: boolean;
9
14
  /** Offset of the `<` in the SOURCE file (inline templates are shifted to their place in the `.ts`). */
10
15
  offset: number;
11
16
  /** The enclosing element inside the same template (`undefined` at the template root). */
@@ -1 +1 @@
1
- {"version":3,"file":"ui-building-blocks-element.interface.d.ts","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/ui-building-blocks-element.interface.ts"],"names":[],"mappings":"AAAA,kHAAkH;AAClH,MAAM,WAAW,kCAAkC;IACjD,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,kHAAkH;IAClH,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,oFAAoF;IACpF,WAAW,EAAE,OAAO,CAAC;IACrB,uGAAuG;IACvG,MAAM,EAAE,MAAM,CAAC;IACf,yFAAyF;IACzF,MAAM,EAAE,kCAAkC,GAAG,SAAS,CAAC;CACxD"}
1
+ {"version":3,"file":"ui-building-blocks-element.interface.d.ts","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/ui-building-blocks-element.interface.ts"],"names":[],"mappings":"AAAA,kHAAkH;AAClH,MAAM,WAAW,kCAAkC;IACjD,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,kHAAkH;IAClH,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,oFAAoF;IACpF,WAAW,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uGAAuG;IACvG,MAAM,EAAE,MAAM,CAAC;IACf,yFAAyF;IACzF,MAAM,EAAE,kCAAkC,GAAG,SAAS,CAAC;CACxD"}
@@ -31,7 +31,7 @@ class UiBuildingBlocks_RuleContext_Util {
31
31
  messageId: 'baselineUnreadable',
32
32
  data: { file: file, reason: error instanceof Error ? error.message : String(error) },
33
33
  });
34
- return { scrollerTags: [], scrollContainers: {}, modulesWithoutLoadFailedBranch: [] };
34
+ return { scrollerTags: [], scrollContainers: {}, modulesWithoutLoadFailedBranch: [], emptyStatesWithoutGuard: {} };
35
35
  }
36
36
  }
37
37
  /** Offset → ESLint location (1-based line, 0-based column). */
@@ -1 +1 @@
1
- {"version":3,"file":"ui-building-blocks-rule-context.util.js","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/ui-building-blocks-rule-context.util.ts"],"names":[],"mappings":";;;;AACA,mDAA6B;AAG7B,uEAAkE;AAQlE,qHAAqH;AACrH,MAAa,iCAAiC;IAE5C,wGAAwG;IACxG,MAAM,CAAU,MAAM,GAAgC;QACpD;YACE,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;YAChD,oBAAoB,EAAE,KAAK;SAC5B;KACF,CAAC;IAEF,gFAAgF;IAChF,MAAM,CAAU,yBAAyB,GAAW,0DAA0D;UAC1G,6EAA6E,CAAC;IAElF,qFAAqF;IACrF,MAAM,CAAC,QAAQ,CAAC,OAAyB;QACvC,MAAM,OAAO,GAA8B,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACpE,MAAM,GAAG,GAAW,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACjD,MAAM,IAAI,GAAW,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,IAAI,+CAAqB,CAAC,mBAAmB,CAAC,CAAC;QAE1G,IAAI,CAAC;YACH,OAAO,+CAAqB,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,CAAC,MAAM,CAAC;gBACb,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;gBACnE,SAAS,EAAE,oBAAoB;gBAC/B,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;aACrF,CAAC,CAAC;YAEH,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,8BAA8B,EAAE,EAAE,EAAE,CAAC;QACxF,CAAC;IACH,CAAC;IAED,+DAA+D;IAC/D,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,MAAc;QACrC,MAAM,MAAM,GAAW,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAW,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;QAC/C,MAAM,MAAM,GAAW,MAAM,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAE/D,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,EAAE,CAAC;IAC5F,CAAC;IAED,6BAA6B;IAC7B,MAAM,CAAC,IAAI,CAAC,IAAY,EAAE,MAAc;QACtC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAClD,CAAC;;AA9CH,8EA+CC"}
1
+ {"version":3,"file":"ui-building-blocks-rule-context.util.js","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/ui-building-blocks-rule-context.util.ts"],"names":[],"mappings":";;;;AACA,mDAA6B;AAG7B,uEAAkE;AAQlE,qHAAqH;AACrH,MAAa,iCAAiC;IAE5C,wGAAwG;IACxG,MAAM,CAAU,MAAM,GAAgC;QACpD;YACE,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;YAChD,oBAAoB,EAAE,KAAK;SAC5B;KACF,CAAC;IAEF,gFAAgF;IAChF,MAAM,CAAU,yBAAyB,GAAW,0DAA0D;UAC1G,6EAA6E,CAAC;IAElF,qFAAqF;IACrF,MAAM,CAAC,QAAQ,CAAC,OAAyB;QACvC,MAAM,OAAO,GAA8B,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACpE,MAAM,GAAG,GAAW,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACjD,MAAM,IAAI,GAAW,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,IAAI,+CAAqB,CAAC,mBAAmB,CAAC,CAAC;QAE1G,IAAI,CAAC;YACH,OAAO,+CAAqB,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,CAAC,MAAM,CAAC;gBACb,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;gBACnE,SAAS,EAAE,oBAAoB;gBAC/B,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;aACrF,CAAC,CAAC;YAEH,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,8BAA8B,EAAE,EAAE,EAAE,uBAAuB,EAAE,EAAE,EAAE,CAAC;QACrH,CAAC;IACH,CAAC;IAED,+DAA+D;IAC/D,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,MAAc;QACrC,MAAM,MAAM,GAAW,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAW,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;QAC/C,MAAM,MAAM,GAAW,MAAM,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAE/D,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,EAAE,CAAC;IAC5F,CAAC;IAED,6BAA6B;IAC7B,MAAM,CAAC,IAAI,CAAC,IAAY,EAAE,MAAc;QACtC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAClD,CAAC;;AA9CH,8EA+CC"}
@@ -39,6 +39,10 @@ export declare class UiBuildingBlocks_Util {
39
39
  static readonly loadingPattern: RegExp;
40
40
  /** A failed / error state in a template (`errors` — a list OF errors — is not one). */
41
41
  static readonly failedPattern: RegExp;
42
+ /** BFR-MASTERPROMPTER-075 ⓐ: the `[dynamo-overlay]` directive attribute (runtime `position: absolute`). */
43
+ private static readonly outOfFlowAttribute;
44
+ /** BFR-MASTERPROMPTER-075 ⓒ: a loading match whose condition is the bare `loading` flag (`@if (loading)`). */
45
+ private static readonly subFrameLoadingCondition;
42
46
  private static readonly voidTags;
43
47
  private static readonly scrollClasses;
44
48
  /** Classes that stop a flex item from growing with its content (min-height 0 or a non-visible overflow). */
@@ -62,6 +66,11 @@ export declare class UiBuildingBlocks_Util {
62
66
  static scrollFindings(text: string, filename: string, scrollerTags: string[]): UiBuildingBlocks_ScrollFinding_Interface[];
63
67
  /** ② Offsets of the loading states in a file's templates (comments / interpolations ignored). */
64
68
  static loadingOffsets(text: string, filename: string): number[];
69
+ /**
70
+ * BFR-MASTERPROMPTER-075 ⓒ: the component (inline template: this file; external template: its sibling `.ts`)
71
+ * extends `DyNX_SubFrame_Component`. An unreadable sibling ⇒ `false` (measure, never silence).
72
+ */
73
+ static isSubFrameComponent(text: string, filename: string): boolean;
65
74
  /** ② Whether a file's templates show a failed / error state. */
66
75
  static hasFailedBranch(text: string, filename: string): boolean;
67
76
  /** ② The module folder of a file: the path up to the FIRST `_modules/<name>` segment (`undefined` = not in one). */
@@ -94,7 +103,7 @@ export declare class UiBuildingBlocks_Util {
94
103
  /** Static `class`, `[class.x]` bindings and the quoted keys of `[ngClass]`. */
95
104
  private static classesOf;
96
105
  /** Comments → spaces (offsets and line breaks preserved). */
97
- private static blankComments;
106
+ static blankComments(text: string): string;
98
107
  /** Comments AND `{{ … }}` interpolations → spaces, so a `<` in an expression is never read as a tag. */
99
108
  private static blankNonMarkup;
100
109
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ui-building-blocks.util.d.ts","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/ui-building-blocks.util.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ui-building-blocks.util.d.ts","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/ui-building-blocks.util.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mCAAmC,EAAE,MAAM,yCAAyC,CAAC;AAC9F,OAAO,EAAE,kCAAkC,EAAE,MAAM,wCAAwC,CAAC;AAC5F,OAAO,EAAE,wCAAwC,EAAE,MAAM,+CAA+C,CAAC;AAEzG,iFAAiF;AACjF,UAAU,mCAAmC;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,qBAAqB;IAEhC,6GAA6G;IAC7G,MAAM,CAAC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAA8C;IAEzF,4CAA4C;IAC5C,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAI/B;IAEF;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAIpC;IAEF,uFAAuF;IACvF,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAQnC;IAEF,2GAA2G;IAC3G,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAgD;IAE1F,8GAA8G;IAC9G,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAmC;IAEnF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAE7B;IAEH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAElC;IAEH,4GAA4G;IAC5G,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAA0F;IAE/H,sFAAsF;IACtF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAA2E;IAErH,4GAA4G;IAC5G,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CACvB;IAEd,mEAAmE;IACnE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAA6E;IAEhH,qGAAqG;IACrG,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAQ3C;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,mCAAmC,EAAE;IAmBvF,kFAAkF;IAClF,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,kCAAkC,EAAE;IA2CrF,2FAA2F;IAC3F,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,wCAAwC,EAAE;IAgDzH,iGAAiG;IACjG,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAsB/D;;;OAGG;IACH,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;IAenE,gEAAgE;IAChE,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;IAK/D,oHAAoH;IACpH,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAOtD;;;OAGG;IACH,MAAM,CAAC,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO;IAsBrG,mFAAmF;IACnF,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE;IAuB/C,kFAAkF;IAClF,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IAOzD,gHAAgH;IAChH,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,mCAAmC;IAiD9E,uBAAuB;IACvB,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAIvC,yGAAyG;IACzG,OAAO,CAAC,MAAM,CAAC,KAAK;IAMpB,mFAAmF;IACnF,OAAO,CAAC,MAAM,CAAC,KAAK;IAIpB,OAAO,CAAC,MAAM,CAAC,UAAU;IAKzB,gHAAgH;IAChH,OAAO,CAAC,MAAM,CAAC,WAAW;IAM1B,OAAO,CAAC,MAAM,CAAC,cAAc;IAK7B,OAAO,CAAC,MAAM,CAAC,YAAY;IAO3B,+EAA+E;IAC/E,OAAO,CAAC,MAAM,CAAC,SAAS;IAyBxB,6DAA6D;IAC7D,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAI1C,wGAAwG;IACxG,OAAO,CAAC,MAAM,CAAC,cAAc;CAS9B"}