@empline/preflight 1.1.44 → 1.1.46

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.
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Layout Overflow Containment Preflight
4
+ *
5
+ * Detects dashboard/page layouts where the main content area lacks proper
6
+ * overflow containment, which can cause horizontal page scrollbars.
7
+ *
8
+ * When a flex container has `minWidth: 0` (to allow shrinking) but no
9
+ * `overflow: hidden`, scrollable children (like TableContainer) won't
10
+ * properly trigger internal scrolling - instead the content can expand
11
+ * and create page-level horizontal scrollbars.
12
+ *
13
+ * BLOCKING: Yes - horizontal page scrollbars are a significant UX issue
14
+ */
15
+ import { PreflightCheckResult } from "../../core/types";
16
+ export declare const id = "ui/layout-overflow-containment";
17
+ export declare const name = "Layout Overflow Containment";
18
+ export declare const description = "Ensures dashboard layouts contain overflow to prevent page-level scrollbars";
19
+ export declare const category = "ui";
20
+ export declare const blocking = true;
21
+ export declare const tags: string[];
22
+ export declare function run(): Promise<PreflightCheckResult>;
23
+ //# sourceMappingURL=layout-overflow-containment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout-overflow-containment.d.ts","sourceRoot":"","sources":["../../../src/checks/ui/layout-overflow-containment.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAKH,OAAO,EAAE,oBAAoB,EAAoB,MAAM,kBAAkB,CAAC;AAI1E,eAAO,MAAM,EAAE,mCAAmC,CAAC;AACnD,eAAO,MAAM,IAAI,gCAAgC,CAAC;AAClD,eAAO,MAAM,WAAW,gFAAgF,CAAC;AACzG,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,IAAI,UAA6C,CAAC;AA0I/D,wBAAsB,GAAG,IAAI,OAAO,CAAC,oBAAoB,CAAC,CA2DzD"}
@@ -0,0 +1,240 @@
1
+ #!/usr/bin/env tsx
2
+ "use strict";
3
+ /**
4
+ * Layout Overflow Containment Preflight
5
+ *
6
+ * Detects dashboard/page layouts where the main content area lacks proper
7
+ * overflow containment, which can cause horizontal page scrollbars.
8
+ *
9
+ * When a flex container has `minWidth: 0` (to allow shrinking) but no
10
+ * `overflow: hidden`, scrollable children (like TableContainer) won't
11
+ * properly trigger internal scrolling - instead the content can expand
12
+ * and create page-level horizontal scrollbars.
13
+ *
14
+ * BLOCKING: Yes - horizontal page scrollbars are a significant UX issue
15
+ */
16
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ var desc = Object.getOwnPropertyDescriptor(m, k);
19
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
20
+ desc = { enumerable: true, get: function() { return m[k]; } };
21
+ }
22
+ Object.defineProperty(o, k2, desc);
23
+ }) : (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ o[k2] = m[k];
26
+ }));
27
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
28
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
29
+ }) : function(o, v) {
30
+ o["default"] = v;
31
+ });
32
+ var __importStar = (this && this.__importStar) || (function () {
33
+ var ownKeys = function(o) {
34
+ ownKeys = Object.getOwnPropertyNames || function (o) {
35
+ var ar = [];
36
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
37
+ return ar;
38
+ };
39
+ return ownKeys(o);
40
+ };
41
+ return function (mod) {
42
+ if (mod && mod.__esModule) return mod;
43
+ var result = {};
44
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
45
+ __setModuleDefault(result, mod);
46
+ return result;
47
+ };
48
+ })();
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.tags = exports.blocking = exports.category = exports.description = exports.name = exports.id = void 0;
51
+ exports.run = run;
52
+ const fs = __importStar(require("node:fs"));
53
+ const path = __importStar(require("node:path"));
54
+ const glob_1 = require("glob");
55
+ const console_chars_1 = require("../../utils/console-chars");
56
+ // METADATA
57
+ exports.id = "ui/layout-overflow-containment";
58
+ exports.name = "Layout Overflow Containment";
59
+ exports.description = "Ensures dashboard layouts contain overflow to prevent page-level scrollbars";
60
+ exports.category = "ui";
61
+ exports.blocking = true;
62
+ exports.tags = ["ui", "layout", "responsive", "overflow"];
63
+ // Patterns that indicate a layout file
64
+ const LAYOUT_FILE_PATTERNS = [
65
+ "**/*Layout*.tsx",
66
+ "**/*PageLayout*.tsx",
67
+ "**/layout.tsx",
68
+ "**/DashboardPage*.tsx",
69
+ ];
70
+ const EXCLUDE_PATTERNS = [
71
+ "**/node_modules/**",
72
+ "**/.next/**",
73
+ "**/dist/**",
74
+ "**/*.test.tsx",
75
+ "**/*.spec.tsx",
76
+ ];
77
+ // Pattern: flex container with minWidth: 0 but no overflow handling
78
+ const MIN_WIDTH_ZERO_PATTERN = /minWidth:\s*0/;
79
+ const OVERFLOW_PATTERN = /overflow:\s*["']?(hidden|auto|scroll)/;
80
+ const OVERFLOW_X_PATTERN = /overflowX:\s*["']?(hidden|auto|scroll)/;
81
+ const OVERFLOW_CLASS_PATTERN = /overflow-(?:hidden|auto|x-hidden|y-auto)/;
82
+ // Pattern: CSSProperties object assignment for main/content areas
83
+ const CONTENT_STYLE_PATTERN = /(content|main|container)Style.*?{([^}]+)}/is;
84
+ function analyzeLayoutFile(filePath) {
85
+ const issues = [];
86
+ const content = fs.readFileSync(filePath, "utf-8");
87
+ const lines = content.split("\n");
88
+ const relativePath = path.relative(process.cwd(), filePath);
89
+ // Check for flex containers with minWidth: 0 but no overflow
90
+ // This is the exact pattern that causes page-level horizontal scrollbars
91
+ // Find style objects that have minWidth: 0
92
+ for (let i = 0; i < lines.length; i++) {
93
+ const line = lines[i];
94
+ // Skip comments and preflight-ignore
95
+ if (line.includes("//") && line.includes("preflight-ignore"))
96
+ continue;
97
+ if (line.includes("/*") && line.includes("preflight-ignore"))
98
+ continue;
99
+ // Check if this line has minWidth: 0
100
+ if (MIN_WIDTH_ZERO_PATTERN.test(line)) {
101
+ // Look at surrounding context (the style object) for overflow handling
102
+ const contextStart = Math.max(0, i - 15);
103
+ const contextEnd = Math.min(lines.length, i + 15);
104
+ const context = lines.slice(contextStart, contextEnd).join("\n");
105
+ // Find the style object boundaries
106
+ const beforeLine = content.substring(0, content.split("\n").slice(0, i).join("\n").length);
107
+ const lastBracePos = beforeLine.lastIndexOf("{");
108
+ const styleObjectStart = beforeLine.substring(lastBracePos);
109
+ // Get the full style object by finding matching braces
110
+ let braceCount = 1;
111
+ let endIndex = i;
112
+ for (let j = i; j < lines.length && braceCount > 0; j++) {
113
+ const jLine = lines[j];
114
+ for (const char of jLine) {
115
+ if (char === "{")
116
+ braceCount++;
117
+ if (char === "}")
118
+ braceCount--;
119
+ }
120
+ endIndex = j;
121
+ if (braceCount === 0)
122
+ break;
123
+ }
124
+ const styleObjectLines = lines.slice(contextStart, endIndex + 1).join("\n");
125
+ // Check if this style object has overflow handling
126
+ const hasOverflow = OVERFLOW_PATTERN.test(styleObjectLines) ||
127
+ OVERFLOW_X_PATTERN.test(styleObjectLines);
128
+ // Check if it's a scroll container (which intentionally scrolls)
129
+ const isScrollContainer = /scrollContainer|scroll.*container/i.test(styleObjectLines);
130
+ // Check for flex: 1 (indicating main content area)
131
+ const isFlexExpand = /flex:\s*1|flex:\s*['"]?1/.test(styleObjectLines);
132
+ // If it has minWidth: 0 and flex expansion but no overflow, flag it
133
+ if (!hasOverflow && isFlexExpand && !isScrollContainer) {
134
+ // Check if there's a comment explaining why overflow is not needed
135
+ const hasExplanation = /no.*overflow|overflow.*not.*need|intentional/i.test(context);
136
+ if (!hasExplanation) {
137
+ issues.push({
138
+ file: relativePath,
139
+ line: i + 1,
140
+ pattern: "minWidth: 0 without overflow containment",
141
+ message: `Flex container has minWidth: 0 but no overflow handling. This can cause page-level horizontal scrollbars when content (like tables) exceeds available width. Add \`overflow: "hidden"\` to force scrollable children to scroll internally.`,
142
+ });
143
+ }
144
+ }
145
+ }
146
+ }
147
+ // Check for dashboard/page layouts that render TableContainer without overflow
148
+ if (content.includes("TableContainer") || content.includes("overflow-x-auto")) {
149
+ // Check if the layout has a main content wrapper with overflow hidden
150
+ const hasContentOverflow = /component=["']main["'].*overflow/i.test(content) ||
151
+ /main.*overflow.*hidden/i.test(content) ||
152
+ OVERFLOW_CLASS_PATTERN.test(content);
153
+ // Check if there's a proper container hierarchy
154
+ const hasProperContainment = content.includes("overflow: \"hidden\"") ||
155
+ content.includes("overflow: 'hidden'") ||
156
+ content.includes("overflow-hidden");
157
+ if (!hasContentOverflow && !hasProperContainment) {
158
+ // Only flag if this is actually a layout file, not a component using tables
159
+ const isLayoutFile = /Layout|Page\s*\(|export\s+default\s+function\s+\w+Page/.test(content);
160
+ if (isLayoutFile) {
161
+ issues.push({
162
+ file: relativePath,
163
+ line: 1,
164
+ pattern: "Layout with scrollable content but no overflow containment",
165
+ message: `This layout renders scrollable content (TableContainer) but may lack proper overflow containment on the parent. Ensure the main content area has \`overflow: "hidden"\` to prevent page-level horizontal scrollbars.`,
166
+ });
167
+ }
168
+ }
169
+ }
170
+ return issues;
171
+ }
172
+ async function run() {
173
+ const startTime = Date.now();
174
+ const findings = [];
175
+ // Get layout files
176
+ const allFiles = [];
177
+ for (const pattern of LAYOUT_FILE_PATTERNS) {
178
+ const matches = await (0, glob_1.glob)(pattern, {
179
+ cwd: process.cwd(),
180
+ ignore: EXCLUDE_PATTERNS,
181
+ });
182
+ allFiles.push(...matches);
183
+ }
184
+ // Deduplicate files
185
+ const uniqueFiles = [...new Set(allFiles)];
186
+ console.log(`\n${console_chars_1.emoji.search} ${exports.name}`);
187
+ console.log(` Checking ${uniqueFiles.length} layout files...`);
188
+ // Analyze each file
189
+ const allIssues = [];
190
+ for (const file of uniqueFiles) {
191
+ const filePath = path.join(process.cwd(), file);
192
+ if (!fs.existsSync(filePath))
193
+ continue;
194
+ const issues = analyzeLayoutFile(filePath);
195
+ allIssues.push(...issues);
196
+ }
197
+ // Convert to findings
198
+ for (const issue of allIssues) {
199
+ findings.push({
200
+ level: "error",
201
+ message: issue.message,
202
+ file: issue.file,
203
+ startLine: issue.line,
204
+ ruleId: "layout-overflow-containment",
205
+ suggestion: `Add \`overflow: "hidden"\` to the flex container to contain horizontal overflow.`,
206
+ });
207
+ }
208
+ const passed = findings.length === 0;
209
+ if (passed) {
210
+ console.log(` ${console_chars_1.emoji.success} All layouts have proper overflow containment`);
211
+ }
212
+ else {
213
+ console.log(` ${console_chars_1.emoji.error} Found ${findings.length} layout(s) missing overflow containment`);
214
+ for (const finding of findings) {
215
+ console.log(` ${finding.file}:${finding.startLine}`);
216
+ console.log(` ${finding.message}`);
217
+ }
218
+ }
219
+ return {
220
+ passed,
221
+ findings,
222
+ duration: Date.now() - startTime,
223
+ };
224
+ }
225
+ // CLI entry point
226
+ async function main() {
227
+ const result = await run();
228
+ if (result.passed) {
229
+ console.log(`\n${console_chars_1.emoji.success} LAYOUT OVERFLOW CONTAINMENT CHECK PASSED`);
230
+ process.exit(0);
231
+ }
232
+ process.exit(1);
233
+ }
234
+ if (require.main === module) {
235
+ main().catch((err) => {
236
+ console.error(`${console_chars_1.emoji.error} Preflight failed:`, err);
237
+ process.exit(1);
238
+ });
239
+ }
240
+ //# sourceMappingURL=layout-overflow-containment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout-overflow-containment.js","sourceRoot":"","sources":["../../../src/checks/ui/layout-overflow-containment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Responsive Text Truncation Detection Preflight
4
+ *
5
+ * Detects components that may truncate text at smaller viewport sizes
6
+ * without using responsive typography. This can cause:
7
+ * - Unreadable text in KPI/stat cards
8
+ * - Important labels being cut off
9
+ * - Poor mobile user experience
10
+ *
11
+ * Best Practices:
12
+ * - Use responsive font sizes (text-xs sm:text-sm md:text-base)
13
+ * - Scale icons alongside text for visual balance
14
+ * - Don't force 4-column grids at small breakpoints
15
+ * - Consider line-clamp-2 instead of truncation for important text
16
+ *
17
+ * BLOCKING: No - This is a warning to help improve responsive design
18
+ */
19
+ import { PreflightCheckResult } from "../../core/types";
20
+ export declare const id = "ui/responsive-text-truncation";
21
+ export declare const name = "Responsive Text Truncation";
22
+ export declare const description = "Detects text truncation patterns that may cause readability issues on smaller screens";
23
+ export declare const category = "ui";
24
+ export declare const blocking = false;
25
+ export declare const tags: string[];
26
+ export declare function run(): Promise<PreflightCheckResult>;
27
+ //# sourceMappingURL=responsive-text-truncation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responsive-text-truncation.d.ts","sourceRoot":"","sources":["../../../src/checks/ui/responsive-text-truncation.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,EAAE,oBAAoB,EAAoB,MAAM,kBAAkB,CAAC;AAI1E,eAAO,MAAM,EAAE,kCAAkC,CAAC;AAClD,eAAO,MAAM,IAAI,+BAA+B,CAAC;AACjD,eAAO,MAAM,WAAW,0FAA0F,CAAC;AACnH,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAC9B,eAAO,MAAM,IAAI,UAAsD,CAAC;AAuKxE,wBAAsB,GAAG,IAAI,OAAO,CAAC,oBAAoB,CAAC,CA2EzD"}
@@ -0,0 +1,294 @@
1
+ #!/usr/bin/env tsx
2
+ "use strict";
3
+ /**
4
+ * Responsive Text Truncation Detection Preflight
5
+ *
6
+ * Detects components that may truncate text at smaller viewport sizes
7
+ * without using responsive typography. This can cause:
8
+ * - Unreadable text in KPI/stat cards
9
+ * - Important labels being cut off
10
+ * - Poor mobile user experience
11
+ *
12
+ * Best Practices:
13
+ * - Use responsive font sizes (text-xs sm:text-sm md:text-base)
14
+ * - Scale icons alongside text for visual balance
15
+ * - Don't force 4-column grids at small breakpoints
16
+ * - Consider line-clamp-2 instead of truncation for important text
17
+ *
18
+ * BLOCKING: No - This is a warning to help improve responsive design
19
+ */
20
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ var desc = Object.getOwnPropertyDescriptor(m, k);
23
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
24
+ desc = { enumerable: true, get: function() { return m[k]; } };
25
+ }
26
+ Object.defineProperty(o, k2, desc);
27
+ }) : (function(o, m, k, k2) {
28
+ if (k2 === undefined) k2 = k;
29
+ o[k2] = m[k];
30
+ }));
31
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
32
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
33
+ }) : function(o, v) {
34
+ o["default"] = v;
35
+ });
36
+ var __importStar = (this && this.__importStar) || (function () {
37
+ var ownKeys = function(o) {
38
+ ownKeys = Object.getOwnPropertyNames || function (o) {
39
+ var ar = [];
40
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
41
+ return ar;
42
+ };
43
+ return ownKeys(o);
44
+ };
45
+ return function (mod) {
46
+ if (mod && mod.__esModule) return mod;
47
+ var result = {};
48
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
49
+ __setModuleDefault(result, mod);
50
+ return result;
51
+ };
52
+ })();
53
+ Object.defineProperty(exports, "__esModule", { value: true });
54
+ exports.tags = exports.blocking = exports.category = exports.description = exports.name = exports.id = void 0;
55
+ exports.run = run;
56
+ const fs = __importStar(require("node:fs"));
57
+ const path = __importStar(require("node:path"));
58
+ const glob_1 = require("glob");
59
+ const console_chars_1 = require("../../utils/console-chars");
60
+ // METADATA
61
+ exports.id = "ui/responsive-text-truncation";
62
+ exports.name = "Responsive Text Truncation";
63
+ exports.description = "Detects text truncation patterns that may cause readability issues on smaller screens";
64
+ exports.category = "ui";
65
+ exports.blocking = false; // Warning-level check
66
+ exports.tags = ["ui", "responsive", "typography", "accessibility"];
67
+ const FILE_PATTERNS = [
68
+ "app/**/*.tsx",
69
+ "components/**/*.tsx",
70
+ "src/**/*.tsx",
71
+ ];
72
+ const EXCLUDE_PATTERNS = [
73
+ "**/node_modules/**",
74
+ "**/.next/**",
75
+ "**/dist/**",
76
+ "**/*.test.tsx",
77
+ "**/*.spec.tsx",
78
+ "**/*.stories.tsx",
79
+ ];
80
+ // Pattern: text-overflow: ellipsis or truncate class
81
+ const TRUNCATION_PATTERNS = [
82
+ /textOverflow:\s*["']?ellipsis/,
83
+ /text-overflow:\s*ellipsis/,
84
+ /\btruncate\b/,
85
+ /whiteSpace:\s*["']?nowrap/,
86
+ /white-space:\s*nowrap/,
87
+ ];
88
+ // Pattern: Fixed font sizes without responsive modifiers
89
+ const FIXED_FONT_PATTERNS = [
90
+ /fontSize:\s*["']?\d+px/,
91
+ /fontSize:\s*["']?\d+rem/,
92
+ /text-\[(\d+px|\d+rem)\](?!\s+sm:|\s+md:|\s+lg:)/,
93
+ ];
94
+ // Pattern: Responsive font patterns (these are GOOD)
95
+ const RESPONSIVE_FONT_PATTERNS = [
96
+ /text-\w+\s+sm:text-/,
97
+ /text-\w+\s+md:text-/,
98
+ /clamp\s*\(/i,
99
+ /fontSize.*clamp/i,
100
+ ];
101
+ // Pattern: Aggressive grid columns at small breakpoints
102
+ const AGGRESSIVE_GRID_PATTERNS = [
103
+ /columns:\s*\{[^}]*md:\s*[4-9]/, // 4+ columns at md
104
+ /grid-cols-[4-9](?!\s+sm:|\s+md:|\s+lg:)/, // Fixed 4+ columns
105
+ /grid-template-columns.*repeat\s*\(\s*[4-9]/, // 4+ columns in CSS
106
+ ];
107
+ function analyzeFile(filePath) {
108
+ const issues = [];
109
+ const content = fs.readFileSync(filePath, "utf-8");
110
+ const lines = content.split("\n");
111
+ const relativePath = path.relative(process.cwd(), filePath);
112
+ // Skip if file has preflight-ignore for this check
113
+ if (content.includes("preflight-ignore-truncation"))
114
+ return issues;
115
+ // Check if this is a StatCard, KPI, or metric display component
116
+ const isStatOrKpiComponent = /StatCard|KPI|Metric|Dashboard.*Card|stat.*card/i.test(content) ||
117
+ /stats\s*=\s*\[/i.test(content);
118
+ for (let i = 0; i < lines.length; i++) {
119
+ const line = lines[i];
120
+ const lineNum = i + 1;
121
+ // Skip comments
122
+ if (line.trim().startsWith("//") || line.trim().startsWith("/*"))
123
+ continue;
124
+ if (line.includes("preflight-ignore"))
125
+ continue;
126
+ // Check for truncation without responsive fonts
127
+ const hasTruncation = TRUNCATION_PATTERNS.some(p => p.test(line));
128
+ if (hasTruncation) {
129
+ // Look at surrounding context (10 lines) for responsive font patterns
130
+ const contextStart = Math.max(0, i - 5);
131
+ const contextEnd = Math.min(lines.length, i + 5);
132
+ const context = lines.slice(contextStart, contextEnd).join("\n");
133
+ const hasResponsiveFonts = RESPONSIVE_FONT_PATTERNS.some(p => p.test(context));
134
+ const hasFixedFonts = FIXED_FONT_PATTERNS.some(p => p.test(context));
135
+ if (!hasResponsiveFonts && (hasFixedFonts || isStatOrKpiComponent)) {
136
+ issues.push({
137
+ file: relativePath,
138
+ line: lineNum,
139
+ pattern: "truncation-without-responsive-font",
140
+ message: `Text truncation detected without responsive font sizing. On smaller screens, text may be cut off and unreadable. Consider using responsive classes like "text-xs sm:text-sm".`,
141
+ severity: "warning",
142
+ });
143
+ }
144
+ }
145
+ // Check for aggressive grid columns
146
+ for (const pattern of AGGRESSIVE_GRID_PATTERNS) {
147
+ if (pattern.test(line)) {
148
+ // Check if this is a StatCardGrid or similar
149
+ const nearbyContext = lines.slice(Math.max(0, i - 3), Math.min(lines.length, i + 3)).join("\n");
150
+ if (/StatCardGrid|stat.*grid|kpi.*grid|metric.*grid/i.test(nearbyContext)) {
151
+ issues.push({
152
+ file: relativePath,
153
+ line: lineNum,
154
+ pattern: "aggressive-grid-columns",
155
+ message: `Grid shows 4+ columns at medium breakpoint, which may cause stat cards to truncate text. Consider using fewer columns at smaller breakpoints (e.g., md: 2 instead of md: 4).`,
156
+ severity: "warning",
157
+ });
158
+ }
159
+ }
160
+ }
161
+ }
162
+ // Check for StatCardGrid usage with aggressive column settings
163
+ const statCardGridMatch = content.match(/StatCardGrid[^>]*columns=\{\s*\{([^}]+)\}/);
164
+ if (statCardGridMatch) {
165
+ const columnConfig = statCardGridMatch[1];
166
+ // Check if md is set to 4+ while sm is 2 or less
167
+ const mdMatch = columnConfig.match(/md:\s*(\d+)/);
168
+ const smMatch = columnConfig.match(/sm:\s*(\d+)/);
169
+ if (mdMatch && parseInt(mdMatch[1]) >= 4 && (!smMatch || parseInt(smMatch[1]) <= 2)) {
170
+ // Find the line number
171
+ const lineIndex = content.substring(0, statCardGridMatch.index).split("\n").length;
172
+ issues.push({
173
+ file: relativePath,
174
+ line: lineIndex,
175
+ pattern: "stat-card-grid-aggressive",
176
+ message: `StatCardGrid jumps from ${smMatch ? smMatch[1] : "1-2"} columns to ${mdMatch[1]} columns at md breakpoint. This sudden change can cause text truncation. Consider a more gradual progression (e.g., xs: 2, sm: 2, md: 3, lg: 4).`,
177
+ severity: "warning",
178
+ });
179
+ }
180
+ }
181
+ // Check for StatCard titles that are too long (max 12 chars recommended)
182
+ const STAT_CARD_MAX_TITLE_LENGTH = 12;
183
+ const statCardTitlePattern = /title:\s*["']([^"']+)["']/g;
184
+ let titleMatch;
185
+ while ((titleMatch = statCardTitlePattern.exec(content)) !== null) {
186
+ const title = titleMatch[1];
187
+ if (title.length > STAT_CARD_MAX_TITLE_LENGTH) {
188
+ // Check if this is in a StatCard or stat-related context
189
+ const matchIndex = titleMatch.index;
190
+ const nearbyContent = content.substring(Math.max(0, matchIndex - 200), matchIndex + 100);
191
+ if (/stat|Stat|KPI|metric|Metric/i.test(nearbyContent)) {
192
+ const lineIndex = content.substring(0, matchIndex).split("\n").length;
193
+ issues.push({
194
+ file: relativePath,
195
+ line: lineIndex,
196
+ pattern: "stat-card-title-too-long",
197
+ message: `StatCard title "${title}" (${title.length} chars) exceeds recommended max of ${STAT_CARD_MAX_TITLE_LENGTH}. This will truncate on smaller screens. Use a shorter label (e.g., "Pending" instead of "Pending Verification").`,
198
+ severity: "warning",
199
+ });
200
+ }
201
+ }
202
+ }
203
+ return issues;
204
+ }
205
+ async function run() {
206
+ const startTime = Date.now();
207
+ const findings = [];
208
+ // Get files to check
209
+ const allFiles = [];
210
+ for (const pattern of FILE_PATTERNS) {
211
+ const matches = await (0, glob_1.glob)(pattern, {
212
+ cwd: process.cwd(),
213
+ ignore: EXCLUDE_PATTERNS,
214
+ });
215
+ allFiles.push(...matches);
216
+ }
217
+ // Deduplicate
218
+ const uniqueFiles = [...new Set(allFiles)];
219
+ console.log(`\n${console_chars_1.emoji.search} ${exports.name}`);
220
+ console.log(` Checking ${uniqueFiles.length} files for text truncation patterns...`);
221
+ // Analyze each file
222
+ const allIssues = [];
223
+ for (const file of uniqueFiles) {
224
+ const filePath = path.join(process.cwd(), file);
225
+ if (!fs.existsSync(filePath))
226
+ continue;
227
+ const issues = analyzeFile(filePath);
228
+ allIssues.push(...issues);
229
+ }
230
+ // Deduplicate by file + line + pattern
231
+ const seen = new Set();
232
+ const uniqueIssues = allIssues.filter(issue => {
233
+ const key = `${issue.file}:${issue.line}:${issue.pattern}`;
234
+ if (seen.has(key))
235
+ return false;
236
+ seen.add(key);
237
+ return true;
238
+ });
239
+ // Convert to findings
240
+ for (const issue of uniqueIssues) {
241
+ findings.push({
242
+ level: issue.severity,
243
+ message: issue.message,
244
+ file: issue.file,
245
+ startLine: issue.line,
246
+ ruleId: "responsive-text-truncation",
247
+ suggestion: issue.pattern === "truncation-without-responsive-font"
248
+ ? "Use responsive Tailwind classes: text-xs sm:text-sm md:text-base"
249
+ : "Use gradual column progression: columns={{ xs: 2, sm: 2, md: 3, lg: 4 }}",
250
+ });
251
+ }
252
+ // This is a warning-level check, so it always passes but reports issues
253
+ const warningCount = findings.filter(f => f.level === "warning").length;
254
+ const passed = true; // Non-blocking check
255
+ if (warningCount === 0) {
256
+ console.log(` ${console_chars_1.emoji.success} No text truncation issues detected`);
257
+ }
258
+ else {
259
+ console.log(` ${console_chars_1.emoji.warning} Found ${warningCount} potential truncation issue(s)`);
260
+ // Show first few
261
+ for (const finding of findings.slice(0, 5)) {
262
+ console.log(` ${finding.file}:${finding.startLine}`);
263
+ }
264
+ if (findings.length > 5) {
265
+ console.log(` ... and ${findings.length - 5} more`);
266
+ }
267
+ }
268
+ return {
269
+ passed,
270
+ findings,
271
+ duration: Date.now() - startTime,
272
+ };
273
+ }
274
+ // CLI entry point
275
+ async function main() {
276
+ const result = await run();
277
+ const warnings = result.findings?.filter(f => f.level === "warning") || [];
278
+ if (warnings.length > 0) {
279
+ console.log(`\n${console_chars_1.emoji.warning} RESPONSIVE TEXT TRUNCATION CHECK: ${warnings.length} warning(s)`);
280
+ console.log(`\nTip: Add responsive font classes to prevent text truncation on small screens.`);
281
+ console.log(`Example: className="text-xs sm:text-sm md:text-base"`);
282
+ }
283
+ else {
284
+ console.log(`\n${console_chars_1.emoji.success} RESPONSIVE TEXT TRUNCATION CHECK PASSED`);
285
+ }
286
+ process.exit(0); // Non-blocking
287
+ }
288
+ if (require.main === module) {
289
+ main().catch((err) => {
290
+ console.error(`${console_chars_1.emoji.error} Preflight failed:`, err);
291
+ process.exit(1);
292
+ });
293
+ }
294
+ //# sourceMappingURL=responsive-text-truncation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responsive-text-truncation.js","sourceRoot":"","sources":["../../../src/checks/ui/responsive-text-truncation.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empline/preflight",
3
- "version": "1.1.44",
3
+ "version": "1.1.46",
4
4
  "description": "Distributable preflight validation system with app-specific plugin support",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",