@futdevpro/dynamo-eslint 1.20.29 → 1.20.55

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 (93) hide show
  1. package/README.md +80 -0
  2. package/build/configs/ngx.d.ts +29 -0
  3. package/build/configs/ngx.d.ts.map +1 -1
  4. package/build/configs/ngx.js +57 -0
  5. package/build/configs/ngx.js.map +1 -1
  6. package/build/plugin/index.d.ts +5 -0
  7. package/build/plugin/index.d.ts.map +1 -1
  8. package/build/plugin/index.js +13 -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/module-load-failed-branch.d.ts +11 -0
  19. package/build/plugin/rules/angular/module-load-failed-branch.d.ts.map +1 -0
  20. package/build/plugin/rules/angular/module-load-failed-branch.js +58 -0
  21. package/build/plugin/rules/angular/module-load-failed-branch.js.map +1 -0
  22. package/build/plugin/rules/angular/no-unlisted-inner-html.d.ts +15 -0
  23. package/build/plugin/rules/angular/no-unlisted-inner-html.d.ts.map +1 -0
  24. package/build/plugin/rules/angular/no-unlisted-inner-html.js +106 -0
  25. package/build/plugin/rules/angular/no-unlisted-inner-html.js.map +1 -0
  26. package/build/plugin/rules/angular/no-unused-component.d.ts +11 -0
  27. package/build/plugin/rules/angular/no-unused-component.d.ts.map +1 -0
  28. package/build/plugin/rules/angular/no-unused-component.js +78 -0
  29. package/build/plugin/rules/angular/no-unused-component.js.map +1 -0
  30. package/build/plugin/rules/angular/scroll-container-min-h-0.d.ts +11 -0
  31. package/build/plugin/rules/angular/scroll-container-min-h-0.d.ts.map +1 -0
  32. package/build/plugin/rules/angular/scroll-container-min-h-0.js +59 -0
  33. package/build/plugin/rules/angular/scroll-container-min-h-0.js.map +1 -0
  34. package/build/plugin/rules/angular/ui-building-blocks-baseline.interface.d.ts +15 -0
  35. package/build/plugin/rules/angular/ui-building-blocks-baseline.interface.d.ts.map +1 -0
  36. package/build/plugin/rules/angular/ui-building-blocks-baseline.interface.js +3 -0
  37. package/build/plugin/rules/angular/ui-building-blocks-baseline.interface.js.map +1 -0
  38. package/build/plugin/rules/angular/ui-building-blocks-element.interface.d.ts +19 -0
  39. package/build/plugin/rules/angular/ui-building-blocks-element.interface.d.ts.map +1 -0
  40. package/build/plugin/rules/angular/ui-building-blocks-element.interface.js +3 -0
  41. package/build/plugin/rules/angular/ui-building-blocks-element.interface.js.map +1 -0
  42. package/build/plugin/rules/angular/ui-building-blocks-rule-context.util.d.ts +28 -0
  43. package/build/plugin/rules/angular/ui-building-blocks-rule-context.util.d.ts.map +1 -0
  44. package/build/plugin/rules/angular/ui-building-blocks-rule-context.util.js +50 -0
  45. package/build/plugin/rules/angular/ui-building-blocks-rule-context.util.js.map +1 -0
  46. package/build/plugin/rules/angular/ui-building-blocks-scroll-finding.interface.d.ts +12 -0
  47. package/build/plugin/rules/angular/ui-building-blocks-scroll-finding.interface.d.ts.map +1 -0
  48. package/build/plugin/rules/angular/ui-building-blocks-scroll-finding.interface.js +3 -0
  49. package/build/plugin/rules/angular/ui-building-blocks-scroll-finding.interface.js.map +1 -0
  50. package/build/plugin/rules/angular/ui-building-blocks.util.d.ts +111 -0
  51. package/build/plugin/rules/angular/ui-building-blocks.util.d.ts.map +1 -0
  52. package/build/plugin/rules/angular/ui-building-blocks.util.js +377 -0
  53. package/build/plugin/rules/angular/ui-building-blocks.util.js.map +1 -0
  54. package/build/plugin/rules/angular/unused-component-finding.interface.d.ts +14 -0
  55. package/build/plugin/rules/angular/unused-component-finding.interface.d.ts.map +1 -0
  56. package/build/plugin/rules/angular/unused-component-finding.interface.js +3 -0
  57. package/build/plugin/rules/angular/unused-component-finding.interface.js.map +1 -0
  58. package/build/plugin/rules/angular/unused-component.util.d.ts +86 -0
  59. package/build/plugin/rules/angular/unused-component.util.d.ts.map +1 -0
  60. package/build/plugin/rules/angular/unused-component.util.js +243 -0
  61. package/build/plugin/rules/angular/unused-component.util.js.map +1 -0
  62. package/build/plugin/rules/angular/xss-surface-baseline-files.interface.d.ts +8 -0
  63. package/build/plugin/rules/angular/xss-surface-baseline-files.interface.d.ts.map +1 -0
  64. package/build/plugin/rules/angular/xss-surface-baseline-files.interface.js +3 -0
  65. package/build/plugin/rules/angular/xss-surface-baseline-files.interface.js.map +1 -0
  66. package/build/plugin/rules/angular/xss-surface-occurrences.interface.d.ts +6 -0
  67. package/build/plugin/rules/angular/xss-surface-occurrences.interface.d.ts.map +1 -0
  68. package/build/plugin/rules/angular/xss-surface-occurrences.interface.js +3 -0
  69. package/build/plugin/rules/angular/xss-surface-occurrences.interface.js.map +1 -0
  70. package/build/plugin/rules/angular/xss-surface.util.d.ts +44 -0
  71. package/build/plugin/rules/angular/xss-surface.util.d.ts.map +1 -0
  72. package/build/plugin/rules/angular/xss-surface.util.js +121 -0
  73. package/build/plugin/rules/angular/xss-surface.util.js.map +1 -0
  74. package/build/plugin/rules/prefer-interface-over-duplicate-types.d.ts.map +1 -1
  75. package/build/plugin/rules/prefer-interface-over-duplicate-types.js +31 -19
  76. package/build/plugin/rules/prefer-interface-over-duplicate-types.js.map +1 -1
  77. package/build/scripts/lint-strict.d.ts +62 -0
  78. package/build/scripts/lint-strict.d.ts.map +1 -0
  79. package/build/scripts/lint-strict.js +151 -0
  80. package/build/scripts/lint-strict.js.map +1 -0
  81. package/build/scripts/ui-building-blocks-baseline.d.ts +21 -0
  82. package/build/scripts/ui-building-blocks-baseline.d.ts.map +1 -0
  83. package/build/scripts/ui-building-blocks-baseline.js +123 -0
  84. package/build/scripts/ui-building-blocks-baseline.js.map +1 -0
  85. package/build/scripts/unused-components-baseline.d.ts +17 -0
  86. package/build/scripts/unused-components-baseline.d.ts.map +1 -0
  87. package/build/scripts/unused-components-baseline.js +62 -0
  88. package/build/scripts/unused-components-baseline.js.map +1 -0
  89. package/build/scripts/xss-surface-baseline.d.ts +17 -0
  90. package/build/scripts/xss-surface-baseline.d.ts.map +1 -0
  91. package/build/scripts/xss-surface-baseline.js +73 -0
  92. package/build/scripts/xss-surface-baseline.js.map +1 -0
  93. package/package.json +7 -3
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ui_building_blocks_rule_context_util_1 = require("./ui-building-blocks-rule-context.util");
4
+ const ui_building_blocks_util_1 = require("./ui-building-blocks.util");
5
+ /**
6
+ * BFR-QA-004 ② — a module (`…/_modules/<name>/`) whose templates show a LOADING state (`…Loading…`, `inProgress_$`,
7
+ * `loading-skeleton`) must also show a FAILED state somewhere (`@if (…error|…failed…)`, a `…load-failed` /
8
+ * `…error-state` component, a `load…error|failed` test id) — "empty", "loading" and "failed" are three states; without
9
+ * the third a failed load looks like an empty screen (organizer BUG-QA-ORG-032/-034).
10
+ * Reported on each loading state of such a module, unless the module is in the committed baseline.
11
+ */
12
+ const rule = {
13
+ meta: {
14
+ type: 'problem',
15
+ docs: {
16
+ description: 'A module that shows a loading state must also show a load-failed state.',
17
+ recommended: true,
18
+ },
19
+ schema: ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.schema,
20
+ messages: {
21
+ noFailedBranch: 'Module {{module}} shows a loading state but no template of it shows a load-FAILED state — a '
22
+ + 'failed load will look like an empty screen. Add an error branch (e.g. `@if (failed_$()) { … }` with a '
23
+ + 'retry). (BFR-QA-004)',
24
+ baselineUnreadable: ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.baselineUnreadableMessage,
25
+ },
26
+ },
27
+ create(context) {
28
+ const filename = context.filename ?? '';
29
+ const moduleDir = ui_building_blocks_util_1.UiBuildingBlocks_Util.moduleDir(filename);
30
+ if (!moduleDir || !ui_building_blocks_util_1.UiBuildingBlocks_Util.isInScope(filename)) {
31
+ return {};
32
+ }
33
+ return {
34
+ Program() {
35
+ const text = context.sourceCode.text ?? '';
36
+ const loading = ui_building_blocks_util_1.UiBuildingBlocks_Util.loadingOffsets(text, filename);
37
+ if (!loading.length) {
38
+ return;
39
+ }
40
+ const baseline = ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.baseline(context);
41
+ const moduleKey = ui_building_blocks_util_1.UiBuildingBlocks_Util.relativeKey(moduleDir, context.cwd ?? process.cwd());
42
+ if (baseline.modulesWithoutLoadFailedBranch.includes(moduleKey)
43
+ || ui_building_blocks_util_1.UiBuildingBlocks_Util.moduleHasFailedBranch(moduleDir, { filename: filename, text: text })) {
44
+ return;
45
+ }
46
+ loading.forEach((offset) => {
47
+ context.report({
48
+ loc: ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.loc(text, offset),
49
+ messageId: 'noFailedBranch',
50
+ data: { module: moduleKey },
51
+ });
52
+ });
53
+ },
54
+ };
55
+ },
56
+ };
57
+ exports.default = rule;
58
+ //# sourceMappingURL=module-load-failed-branch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-load-failed-branch.js","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/module-load-failed-branch.ts"],"names":[],"mappings":";;AAGA,iGAA2F;AAC3F,uEAAkE;AAElE;;;;;;GAMG;AACH,MAAM,IAAI,GAAoB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,yEAAyE;YACtF,WAAW,EAAE,IAAI;SAClB;QACD,MAAM,EAAE,wEAAiC,CAAC,MAAM;QAChD,QAAQ,EAAE;YACR,cAAc,EAAE,8FAA8F;kBAC1G,wGAAwG;kBACxG,sBAAsB;YAC1B,kBAAkB,EAAE,wEAAiC,CAAC,yBAAyB;SAChF;KACF;IACD,MAAM,CAAC,OAAyB;QAC9B,MAAM,QAAQ,GAAW,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;QAChD,MAAM,SAAS,GAAuB,+CAAqB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAEhF,IAAI,CAAC,SAAS,IAAI,CAAC,+CAAqB,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7D,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO;YACL,OAAO;gBACL,MAAM,IAAI,GAAW,OAAO,CAAC,UAAU,CAAC,IAAI,IAAI,EAAE,CAAC;gBACnD,MAAM,OAAO,GAAa,+CAAqB,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;gBAE/E,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;oBACpB,OAAO;gBACT,CAAC;gBACD,MAAM,QAAQ,GAAwC,wEAAiC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAC1G,MAAM,SAAS,GAAW,+CAAqB,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;gBAErG,IAAI,QAAQ,CAAC,8BAA8B,CAAC,QAAQ,CAAC,SAAS,CAAC;uBAC1D,+CAAqB,CAAC,qBAAqB,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;oBAChG,OAAO;gBACT,CAAC;gBACD,OAAO,CAAC,OAAO,CAAC,CAAC,MAAc,EAAQ,EAAE;oBACvC,OAAO,CAAC,MAAM,CAAC;wBACb,GAAG,EAAE,wEAAiC,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC;wBACxD,SAAS,EAAE,gBAAgB;wBAC3B,IAAI,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE;qBAC5B,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,kBAAe,IAAI,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { Rule } from 'eslint';
2
+ /**
3
+ * BFR-QA-005 — XSS-surface guard: every `[innerHTML]` binding and every `DomSanitizer.bypassSecurityTrust…(…)` call is
4
+ * reported, EXCEPT
5
+ * - in a reviewed, allow-listed file (`allow`), and
6
+ * - up to the committed per-file BASELINE count (`.dynamo/xss-surface-baseline.json`, written by
7
+ * `npx dynamo-xss-surface-baseline`) — so the surfaces that exist today do not fail, only NEW ones do.
8
+ * Optional `escapePipe`: the project's escaping pipe must escape `& < > "` before it produces HTML.
9
+ *
10
+ * Why a rule-level baseline and not ESLint's `--suppress-rule`: the native suppressions are applied only by the ESLint
11
+ * CLI, NOT by the `ESLint` API that `ng lint` uses (measured on eslint 9.39.5) — Angular consumers would never see it.
12
+ */
13
+ declare const rule: Rule.RuleModule;
14
+ export default rule;
15
+ //# sourceMappingURL=no-unlisted-inner-html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-unlisted-inner-html.d.ts","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/no-unlisted-inner-html.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAgC9B;;;;;;;;;;GAUG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAsFhB,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const path = tslib_1.__importStar(require("path"));
5
+ const xss_surface_util_1 = require("./xss-surface.util");
6
+ /** Offset → { line, column } in a source text. */
7
+ function toLoc(text, index) {
8
+ const before = text.slice(0, index);
9
+ const line = before.split('\n').length;
10
+ const lastNewline = before.lastIndexOf('\n');
11
+ return { line: line, column: lastNewline === -1 ? index : index - lastNewline - 1 };
12
+ }
13
+ /**
14
+ * BFR-QA-005 — XSS-surface guard: every `[innerHTML]` binding and every `DomSanitizer.bypassSecurityTrust…(…)` call is
15
+ * reported, EXCEPT
16
+ * - in a reviewed, allow-listed file (`allow`), and
17
+ * - up to the committed per-file BASELINE count (`.dynamo/xss-surface-baseline.json`, written by
18
+ * `npx dynamo-xss-surface-baseline`) — so the surfaces that exist today do not fail, only NEW ones do.
19
+ * Optional `escapePipe`: the project's escaping pipe must escape `& < > "` before it produces HTML.
20
+ *
21
+ * Why a rule-level baseline and not ESLint's `--suppress-rule`: the native suppressions are applied only by the ESLint
22
+ * CLI, NOT by the `ESLint` API that `ng lint` uses (measured on eslint 9.39.5) — Angular consumers would never see it.
23
+ */
24
+ const rule = {
25
+ meta: {
26
+ type: 'problem',
27
+ docs: {
28
+ description: 'Forbid new `[innerHTML]` bindings and `bypassSecurityTrust*` calls outside the reviewed allow-list '
29
+ + 'and the committed baseline (XSS surface).',
30
+ recommended: true,
31
+ },
32
+ schema: [
33
+ {
34
+ type: 'object',
35
+ properties: {
36
+ allow: { type: 'array', items: { type: 'string' } },
37
+ baselineFile: { type: 'string' },
38
+ escapePipe: { type: 'string' },
39
+ },
40
+ additionalProperties: false,
41
+ },
42
+ ],
43
+ messages: {
44
+ innerHtml: 'New `[innerHTML]` binding ({{count}} in this file, baseline {{baseline}}): a string reaches the DOM '
45
+ + 'as HTML. Bind text instead, or pipe it through the escaping pipe and add the file to the reviewed `allow` '
46
+ + 'list (BFR-QA-005).',
47
+ bypass: 'New `bypassSecurityTrust…` call ({{count}} in this file, baseline {{baseline}}): it switches Angular\'s '
48
+ + 'sanitizer off for this value. Add the file to the reviewed `allow` list only after review (BFR-QA-005).',
49
+ escapePipe: 'The escaping pipe is not sound: {{problem}} — user text would reach `[innerHTML]` unescaped '
50
+ + '(BFR-QA-005).',
51
+ baselineUnreadable: 'The XSS-surface baseline {{file}} cannot be read ({{reason}}) — regenerate it with '
52
+ + '`npx dynamo-xss-surface-baseline`.',
53
+ },
54
+ },
55
+ create(context) {
56
+ const filename = context.filename ?? '';
57
+ if (!xss_surface_util_1.XssSurface_Util.isInScope(filename)) {
58
+ return {};
59
+ }
60
+ const options = context.options[0] ?? {};
61
+ const cwd = context.cwd ?? process.cwd();
62
+ const key = xss_surface_util_1.XssSurface_Util.relativeKey(filename, cwd);
63
+ return {
64
+ Program() {
65
+ const text = context.sourceCode.text ?? '';
66
+ const first = { line: 1, column: 0 };
67
+ if (options.escapePipe && key.endsWith(xss_surface_util_1.XssSurface_Util.normalize(options.escapePipe))) {
68
+ xss_surface_util_1.XssSurface_Util.checkEscapePipe(text).forEach((problem) => {
69
+ context.report({ loc: { start: first, end: first }, messageId: 'escapePipe', data: { problem: problem } });
70
+ });
71
+ }
72
+ if ((options.allow ?? []).some((suffix) => key.endsWith(xss_surface_util_1.XssSurface_Util.normalize(suffix)))) {
73
+ return;
74
+ }
75
+ const baselinePath = path.resolve(cwd, options.baselineFile ?? xss_surface_util_1.XssSurface_Util.defaultBaselineFile);
76
+ let baseline;
77
+ try {
78
+ baseline = xss_surface_util_1.XssSurface_Util.readBaseline(baselinePath);
79
+ }
80
+ catch (error) {
81
+ context.report({
82
+ loc: { start: first, end: first },
83
+ messageId: 'baselineUnreadable',
84
+ data: { file: baselinePath, reason: error instanceof Error ? error.message : String(error) },
85
+ });
86
+ baseline = {};
87
+ }
88
+ const found = xss_surface_util_1.XssSurface_Util.scan(text, filename);
89
+ const accepted = baseline[key] ?? { innerHtml: 0, bypass: 0 };
90
+ ['innerHtml', 'bypass'].forEach((kind) => {
91
+ // the occurrences BEYOND the accepted count are the new ones (the later ones in the file)
92
+ found[kind].slice(accepted[kind]).forEach((offset) => {
93
+ const start = toLoc(text, offset);
94
+ context.report({
95
+ loc: { start: start, end: { line: start.line, column: start.column + 1 } },
96
+ messageId: kind,
97
+ data: { count: String(found[kind].length), baseline: String(accepted[kind]) },
98
+ });
99
+ });
100
+ });
101
+ },
102
+ };
103
+ },
104
+ };
105
+ exports.default = rule;
106
+ //# sourceMappingURL=no-unlisted-inner-html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-unlisted-inner-html.js","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/no-unlisted-inner-html.ts"],"names":[],"mappings":";;;AACA,mDAA6B;AAI7B,yDAAqD;AAkBrD,kDAAkD;AAClD,SAAS,KAAK,CAAC,IAAY,EAAE,KAAa;IACxC,MAAM,MAAM,GAAW,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAW,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAC/C,MAAM,WAAW,GAAW,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAErD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,WAAW,GAAG,CAAC,EAAE,CAAC;AACtF,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,IAAI,GAAoB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,qGAAqG;kBAC9G,2CAA2C;YAC/C,WAAW,EAAE,IAAI;SAClB;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;oBACnD,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBAChC,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;iBAC/B;gBACD,oBAAoB,EAAE,KAAK;aAC5B;SACF;QACD,QAAQ,EAAE;YACR,SAAS,EAAE,sGAAsG;kBAC7G,4GAA4G;kBAC5G,oBAAoB;YACxB,MAAM,EAAE,0GAA0G;kBAC9G,yGAAyG;YAC7G,UAAU,EAAE,8FAA8F;kBACtG,eAAe;YACnB,kBAAkB,EAAE,qFAAqF;kBACrG,oCAAoC;SACzC;KACF;IACD,MAAM,CAAC,OAAyB;QAC9B,MAAM,QAAQ,GAAW,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;QAEhD,IAAI,CAAC,kCAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzC,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,OAAO,GAAgC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACtE,MAAM,GAAG,GAAW,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACjD,MAAM,GAAG,GAAW,kCAAe,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAE/D,OAAO;YACL,OAAO;gBACL,MAAM,IAAI,GAAW,OAAO,CAAC,UAAU,CAAC,IAAI,IAAI,EAAE,CAAC;gBACnD,MAAM,KAAK,GAAyB,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;gBAE3D,IAAI,OAAO,CAAC,UAAU,IAAI,GAAG,CAAC,QAAQ,CAAC,kCAAe,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;oBACtF,kCAAe,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,OAAe,EAAQ,EAAE;wBACtE,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;oBAC7G,CAAC,CAAC,CAAC;gBACL,CAAC;gBAED,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAc,EAAW,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,kCAAe,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC7G,OAAO;gBACT,CAAC;gBACD,MAAM,YAAY,GAAW,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,IAAI,kCAAe,CAAC,mBAAmB,CAAC,CAAC;gBAC5G,IAAI,QAA4C,CAAC;gBAEjD,IAAI,CAAC;oBACH,QAAQ,GAAG,kCAAe,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;gBACxD,CAAC;gBAAC,OAAO,KAAc,EAAE,CAAC;oBACxB,OAAO,CAAC,MAAM,CAAC;wBACb,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE;wBACjC,SAAS,EAAE,oBAAoB;wBAC/B,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;qBAC7F,CAAC,CAAC;oBACH,QAAQ,GAAG,EAAE,CAAC;gBAChB,CAAC;gBACD,MAAM,KAAK,GAAqC,kCAAe,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;gBACrF,MAAM,QAAQ,GAA0C,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;gBAEpG,CAAE,WAAW,EAAE,QAAQ,CAAY,CAAC,OAAO,CAAC,CAAC,IAA4B,EAAQ,EAAE;oBAClF,0FAA0F;oBAC1F,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAc,EAAQ,EAAE;wBACjE,MAAM,KAAK,GAAyB,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;wBAExD,OAAO,CAAC,MAAM,CAAC;4BACb,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,EAAE;4BAC1E,SAAS,EAAE,IAAI;4BACf,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE;yBAC9E,CAAC,CAAC;oBACL,CAAC,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,kBAAe,IAAI,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { Rule } from 'eslint';
2
+ /**
3
+ * BFR-QA-006 — an Angular `@Component` that is built but used NOWHERE in the project (the folder ESLint runs in):
4
+ * its selector is in no comment-free template and its class is referenced in no other source in a usage position
5
+ * (an `import` line or an `imports` / `declarations` / `exports` entry is NOT a usage). Reported on the component
6
+ * class, unless it is in the committed baseline (`.dynamo/unused-components-baseline.json`). The scan and its rules:
7
+ * `UnusedComponent_Util`. Meant for APPS — in a library every public component is "unused" inside the package.
8
+ */
9
+ declare const rule: Rule.RuleModule;
10
+ export default rule;
11
+ //# sourceMappingURL=no-unused-component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-unused-component.d.ts","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/no-unused-component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAO9B;;;;;;GAMG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAqEhB,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const path = tslib_1.__importStar(require("path"));
5
+ const ui_building_blocks_rule_context_util_1 = require("./ui-building-blocks-rule-context.util");
6
+ const unused_component_util_1 = require("./unused-component.util");
7
+ /**
8
+ * BFR-QA-006 — an Angular `@Component` that is built but used NOWHERE in the project (the folder ESLint runs in):
9
+ * its selector is in no comment-free template and its class is referenced in no other source in a usage position
10
+ * (an `import` line or an `imports` / `declarations` / `exports` entry is NOT a usage). Reported on the component
11
+ * class, unless it is in the committed baseline (`.dynamo/unused-components-baseline.json`). The scan and its rules:
12
+ * `UnusedComponent_Util`. Meant for APPS — in a library every public component is "unused" inside the package.
13
+ */
14
+ const rule = {
15
+ meta: {
16
+ type: 'problem',
17
+ docs: {
18
+ description: 'An Angular component must be used somewhere (template selector, route, dialog, …) — not only built.',
19
+ recommended: true,
20
+ },
21
+ schema: ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.schema,
22
+ messages: {
23
+ unused: '{{className}} is built but used nowhere: its selector ({{selectors}}) is in no template and nothing '
24
+ + 'routes / opens / creates it (an import or an `imports`/`declarations` entry is not a usage). Wire it in, or '
25
+ + 'delete it. (BFR-QA-006)',
26
+ unusedCommented: '{{className}} is built but used nowhere — and a reference to it is COMMENTED OUT somewhere: a '
27
+ + 'finished feature may be switched off. Wire it back in, or delete it. (BFR-QA-006)',
28
+ baselineUnreadable: 'The unused-components baseline {{file}} cannot be read ({{reason}}) — regenerate it with '
29
+ + '`npx dynamo-unused-components-baseline`.',
30
+ },
31
+ },
32
+ create(context) {
33
+ const filename = context.filename ?? '';
34
+ const normalized = unused_component_util_1.UnusedComponent_Util.normalize(filename);
35
+ if (!normalized.endsWith('.ts') || normalized.endsWith('.spec.ts') || normalized.endsWith('.stories.ts')
36
+ || normalized.endsWith('.d.ts')) {
37
+ return {};
38
+ }
39
+ return {
40
+ Program() {
41
+ const text = context.sourceCode.text ?? '';
42
+ if (!unused_component_util_1.UnusedComponent_Util.componentsOf(text).length) {
43
+ return;
44
+ }
45
+ const cwd = context.cwd ?? process.cwd();
46
+ const options = context.options[0] ?? {};
47
+ const baselinePath = path.resolve(cwd, options.baselineFile ?? unused_component_util_1.UnusedComponent_Util.defaultBaselineFile);
48
+ let accepted = [];
49
+ try {
50
+ accepted = unused_component_util_1.UnusedComponent_Util.readBaseline(baselinePath);
51
+ }
52
+ catch (error) {
53
+ context.report({
54
+ loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
55
+ messageId: 'baselineUnreadable',
56
+ data: { file: baselinePath, reason: error instanceof Error ? error.message : String(error) },
57
+ });
58
+ }
59
+ const key = unused_component_util_1.UnusedComponent_Util.normalize(path.relative(cwd, filename));
60
+ const findings = unused_component_util_1.UnusedComponent_Util.findUnused([{ file: key, text: text }], unused_component_util_1.UnusedComponent_Util.projectIndex(cwd).index);
61
+ findings
62
+ .filter((finding) => !accepted.includes(unused_component_util_1.UnusedComponent_Util.key(finding)))
63
+ .forEach((finding) => {
64
+ context.report({
65
+ loc: ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.loc(text, finding.offset),
66
+ messageId: finding.commentedOut ? 'unusedCommented' : 'unused',
67
+ data: {
68
+ className: finding.className,
69
+ selectors: finding.selectors.length ? finding.selectors.join(', ') : 'none',
70
+ },
71
+ });
72
+ });
73
+ },
74
+ };
75
+ },
76
+ };
77
+ exports.default = rule;
78
+ //# sourceMappingURL=no-unused-component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-unused-component.js","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/no-unused-component.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { Rule } from 'eslint';
2
+ /**
3
+ * BFR-QA-004 ① — a scroll container (`overflow-(y-)auto|scroll`, or a component tag listed as a scroller in the
4
+ * baseline `settings.scrollerTags`) that will NOT scroll: between it and the element giving the chain its height, a
5
+ * column-flex item lacks `min-h-0`, so the chain grows to the content height (organizer BUG-QA-ORG-029).
6
+ * Reported beyond the committed per-file baseline only — today's cases pass, new ones fail.
7
+ * The analysis and its limits: `UiBuildingBlocks_Util.scrollFindings`.
8
+ */
9
+ declare const rule: Rule.RuleModule;
10
+ export default rule;
11
+ //# sourceMappingURL=scroll-container-min-h-0.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-container-min-h-0.d.ts","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/scroll-container-min-h-0.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAO9B;;;;;;GAMG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAiDhB,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ui_building_blocks_rule_context_util_1 = require("./ui-building-blocks-rule-context.util");
4
+ const ui_building_blocks_util_1 = require("./ui-building-blocks.util");
5
+ /**
6
+ * BFR-QA-004 ① — a scroll container (`overflow-(y-)auto|scroll`, or a component tag listed as a scroller in the
7
+ * baseline `settings.scrollerTags`) that will NOT scroll: between it and the element giving the chain its height, a
8
+ * column-flex item lacks `min-h-0`, so the chain grows to the content height (organizer BUG-QA-ORG-029).
9
+ * Reported beyond the committed per-file baseline only — today's cases pass, new ones fail.
10
+ * The analysis and its limits: `UiBuildingBlocks_Util.scrollFindings`.
11
+ */
12
+ const rule = {
13
+ meta: {
14
+ type: 'problem',
15
+ docs: {
16
+ description: 'A scroll container must not sit under a column-flex item without `min-h-0` (it would never '
17
+ + 'scroll).',
18
+ recommended: true,
19
+ },
20
+ schema: ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.schema,
21
+ messages: {
22
+ noMinH0: 'This <{{tag}}> scroll container will not scroll: its ancestor <{{culpritTag}}> (line {{culpritLine}}) '
23
+ + 'is a column-flex item without `min-h-0`, so the chain grows to the content height. Add `min-h-0` there '
24
+ + '(e.g. `class="flex-1 min-h-0"`). ({{count}} in this file, baseline {{baseline}}; BFR-QA-004)',
25
+ baselineUnreadable: ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.baselineUnreadableMessage,
26
+ },
27
+ },
28
+ create(context) {
29
+ const filename = context.filename ?? '';
30
+ if (!ui_building_blocks_util_1.UiBuildingBlocks_Util.isInScope(filename)) {
31
+ return {};
32
+ }
33
+ return {
34
+ Program() {
35
+ const text = context.sourceCode.text ?? '';
36
+ const baseline = ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.baseline(context);
37
+ const key = ui_building_blocks_util_1.UiBuildingBlocks_Util.relativeKey(filename, context.cwd ?? process.cwd());
38
+ const findings = ui_building_blocks_util_1.UiBuildingBlocks_Util.scrollFindings(text, filename, baseline.scrollerTags);
39
+ const accepted = baseline.scrollContainers[key] ?? 0;
40
+ // the findings BEYOND the accepted count are the new ones (the later ones in the file)
41
+ findings.slice(accepted).forEach((finding) => {
42
+ context.report({
43
+ loc: ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.loc(text, finding.offset),
44
+ messageId: 'noMinH0',
45
+ data: {
46
+ tag: finding.tag,
47
+ culpritTag: finding.culpritTag,
48
+ culpritLine: String(ui_building_blocks_rule_context_util_1.UiBuildingBlocks_RuleContext_Util.line(text, finding.culpritOffset)),
49
+ count: String(findings.length),
50
+ baseline: String(accepted),
51
+ },
52
+ });
53
+ });
54
+ },
55
+ };
56
+ },
57
+ };
58
+ exports.default = rule;
59
+ //# sourceMappingURL=scroll-container-min-h-0.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-container-min-h-0.js","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/scroll-container-min-h-0.ts"],"names":[],"mappings":";;AAGA,iGAA2F;AAE3F,uEAAkE;AAElE;;;;;;GAMG;AACH,MAAM,IAAI,GAAoB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,6FAA6F;kBACtG,UAAU;YACd,WAAW,EAAE,IAAI;SAClB;QACD,MAAM,EAAE,wEAAiC,CAAC,MAAM;QAChD,QAAQ,EAAE;YACR,OAAO,EAAE,wGAAwG;kBAC7G,yGAAyG;kBACzG,8FAA8F;YAClG,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,QAAQ,GAAwC,wEAAiC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAC1G,MAAM,GAAG,GAAW,+CAAqB,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;gBAC9F,MAAM,QAAQ,GACZ,+CAAqB,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;gBAC9E,MAAM,QAAQ,GAAW,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAE7D,uFAAuF;gBACvF,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,OAAiD,EAAQ,EAAE;oBAC3F,OAAO,CAAC,MAAM,CAAC;wBACb,GAAG,EAAE,wEAAiC,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC;wBAChE,SAAS,EAAE,SAAS;wBACpB,IAAI,EAAE;4BACJ,GAAG,EAAE,OAAO,CAAC,GAAG;4BAChB,UAAU,EAAE,OAAO,CAAC,UAAU;4BAC9B,WAAW,EAAE,MAAM,CAAC,wEAAiC,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;4BACxF,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;4BAC9B,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;yBAC3B;qBACF,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,kBAAe,IAAI,CAAC"}
@@ -0,0 +1,15 @@
1
+ /** The committed BFR-QA-004 baseline (`.dynamo/ui-building-blocks-baseline.json`), as the rules read it. */
2
+ export interface UiBuildingBlocks_Baseline_Interface {
3
+ /** Component tags that ARE scroll containers (their scrolling lives in their own template / CSS). */
4
+ scrollerTags: string[];
5
+ /** Accepted scroll containers without a `min-h-0` chain, per file (relative, forward slashes). */
6
+ scrollContainers: Record<string, number>;
7
+ /** Accepted modules (relative folder, e.g. `src/app/_modules/tasks`) with a loading state but no failed branch. */
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>;
14
+ }
15
+ //# sourceMappingURL=ui-building-blocks-baseline.interface.d.ts.map
@@ -0,0 +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;IACzC;;;OAGG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClD"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ui-building-blocks-baseline.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-building-blocks-baseline.interface.js","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/ui-building-blocks-baseline.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ /** One element of a template, as the BFR-QA-004 scanner sees it (enough structure for the scroll-chain check). */
2
+ export interface UiBuildingBlocks_Element_Interface {
3
+ /** Lower-case tag name. */
4
+ tag: string;
5
+ /** Class names: static `class`, `[class.x]` bindings and quoted `[ngClass]` keys (a conditional class counts). */
6
+ classes: string[];
7
+ /** A height / max-height is set inline (`style`, `[style.height]`, `[ngStyle]`). */
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;
14
+ /** Offset of the `<` in the SOURCE file (inline templates are shifted to their place in the `.ts`). */
15
+ offset: number;
16
+ /** The enclosing element inside the same template (`undefined` at the template root). */
17
+ parent: UiBuildingBlocks_Element_Interface | undefined;
18
+ }
19
+ //# sourceMappingURL=ui-building-blocks-element.interface.d.ts.map
@@ -0,0 +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;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uGAAuG;IACvG,MAAM,EAAE,MAAM,CAAC;IACf,yFAAyF;IACzF,MAAM,EAAE,kCAAkC,GAAG,SAAS,CAAC;CACxD"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ui-building-blocks-element.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-building-blocks-element.interface.js","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/ui-building-blocks-element.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ import { Rule } from 'eslint';
2
+ import { UiBuildingBlocks_Baseline_Interface } from './ui-building-blocks-baseline.interface';
3
+ /** An ESLint source range. */
4
+ interface UiBuildingBlocks_Loc_Interface {
5
+ start: {
6
+ line: number;
7
+ column: number;
8
+ };
9
+ end: {
10
+ line: number;
11
+ column: number;
12
+ };
13
+ }
14
+ /** Rule plumbing shared by `scroll-container-min-h-0` and `module-load-failed-branch` (one baseline, one reader). */
15
+ export declare class UiBuildingBlocks_RuleContext_Util {
16
+ /** The JSON schema of the shared options (`baselineFile`, relative to the ESLint working directory). */
17
+ static readonly schema: Rule.RuleMetaData['schema'];
18
+ /** The message shown when the baseline cannot be read (never a silent pass). */
19
+ static readonly baselineUnreadableMessage: string;
20
+ /** Reads the baseline; a broken one is REPORTED on the file and treated as empty. */
21
+ static baseline(context: Rule.RuleContext): UiBuildingBlocks_Baseline_Interface;
22
+ /** Offset → ESLint location (1-based line, 0-based column). */
23
+ static loc(text: string, offset: number): UiBuildingBlocks_Loc_Interface;
24
+ /** Offset → 1-based line. */
25
+ static line(text: string, offset: number): number;
26
+ }
27
+ export {};
28
+ //# sourceMappingURL=ui-building-blocks-rule-context.util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-building-blocks-rule-context.util.d.ts","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/ui-building-blocks-rule-context.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B,OAAO,EAAE,mCAAmC,EAAE,MAAM,yCAAyC,CAAC;AAG9F,8BAA8B;AAC9B,UAAU,8BAA8B;IACtC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC;AAED,qHAAqH;AACrH,qBAAa,iCAAiC;IAE5C,wGAAwG;IACxG,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAMjD;IAEF,gFAAgF;IAChF,MAAM,CAAC,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CACiC;IAElF,qFAAqF;IACrF,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,GAAG,mCAAmC;IAkB/E,+DAA+D;IAC/D,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,8BAA8B;IAQxE,6BAA6B;IAC7B,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;CAGlD"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UiBuildingBlocks_RuleContext_Util = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const path = tslib_1.__importStar(require("path"));
6
+ const ui_building_blocks_util_1 = require("./ui-building-blocks.util");
7
+ /** Rule plumbing shared by `scroll-container-min-h-0` and `module-load-failed-branch` (one baseline, one reader). */
8
+ class UiBuildingBlocks_RuleContext_Util {
9
+ /** The JSON schema of the shared options (`baselineFile`, relative to the ESLint working directory). */
10
+ static schema = [
11
+ {
12
+ type: 'object',
13
+ properties: { baselineFile: { type: 'string' } },
14
+ additionalProperties: false,
15
+ },
16
+ ];
17
+ /** The message shown when the baseline cannot be read (never a silent pass). */
18
+ static baselineUnreadableMessage = 'The UI-building-blocks baseline {{file}} cannot be read '
19
+ + '({{reason}}) — regenerate it with `npx dynamo-ui-building-blocks-baseline`.';
20
+ /** Reads the baseline; a broken one is REPORTED on the file and treated as empty. */
21
+ static baseline(context) {
22
+ const options = context.options[0] ?? {};
23
+ const cwd = context.cwd ?? process.cwd();
24
+ const file = path.resolve(cwd, options.baselineFile ?? ui_building_blocks_util_1.UiBuildingBlocks_Util.defaultBaselineFile);
25
+ try {
26
+ return ui_building_blocks_util_1.UiBuildingBlocks_Util.readBaseline(file);
27
+ }
28
+ catch (error) {
29
+ context.report({
30
+ loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
31
+ messageId: 'baselineUnreadable',
32
+ data: { file: file, reason: error instanceof Error ? error.message : String(error) },
33
+ });
34
+ return { scrollerTags: [], scrollContainers: {}, modulesWithoutLoadFailedBranch: [], emptyStatesWithoutGuard: {} };
35
+ }
36
+ }
37
+ /** Offset → ESLint location (1-based line, 0-based column). */
38
+ static loc(text, offset) {
39
+ const before = text.slice(0, offset);
40
+ const line = before.split('\n').length;
41
+ const column = offset - (before.lastIndexOf('\n') + 1);
42
+ return { start: { line: line, column: column }, end: { line: line, column: column + 1 } };
43
+ }
44
+ /** Offset → 1-based line. */
45
+ static line(text, offset) {
46
+ return text.slice(0, offset).split('\n').length;
47
+ }
48
+ }
49
+ exports.UiBuildingBlocks_RuleContext_Util = UiBuildingBlocks_RuleContext_Util;
50
+ //# sourceMappingURL=ui-building-blocks-rule-context.util.js.map
@@ -0,0 +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,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"}
@@ -0,0 +1,12 @@
1
+ /** A scroll container that will not scroll: a column-flex ancestor lets the chain grow to the content height. */
2
+ export interface UiBuildingBlocks_ScrollFinding_Interface {
3
+ /** Offset of the scroll container's `<` in the source file. */
4
+ offset: number;
5
+ /** Tag of the scroll container. */
6
+ tag: string;
7
+ /** Offset of the nearest ancestor that is a column-flex item without `min-h-0`. */
8
+ culpritOffset: number;
9
+ /** Tag of that ancestor. */
10
+ culpritTag: string;
11
+ }
12
+ //# sourceMappingURL=ui-building-blocks-scroll-finding.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-building-blocks-scroll-finding.interface.d.ts","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/ui-building-blocks-scroll-finding.interface.ts"],"names":[],"mappings":"AAAA,iHAAiH;AACjH,MAAM,WAAW,wCAAwC;IACvD,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,mFAAmF;IACnF,aAAa,EAAE,MAAM,CAAC;IACtB,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ui-building-blocks-scroll-finding.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-building-blocks-scroll-finding.interface.js","sourceRoot":"","sources":["../../../../src/plugin/rules/angular/ui-building-blocks-scroll-finding.interface.ts"],"names":[],"mappings":""}