@empline/preflight 1.1.45 → 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,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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"}
|