@justinmoto/frontend-guardian-core 0.1.14 → 0.1.16

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.
@@ -1 +1 @@
1
- {"version":3,"file":"scanEngine.d.ts","sourceRoot":"","sources":["../src/scanEngine.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AACF,MAAM,MAAM,SAAS,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAClF,MAAM,MAAM,UAAU,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;IAAC,UAAU,EAAE,SAAS,EAAE,CAAA;CAAE,CAAC;AA2W/G,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAa/E;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,UAAU,CAG7E"}
1
+ {"version":3,"file":"scanEngine.d.ts","sourceRoot":"","sources":["../src/scanEngine.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AACF,MAAM,MAAM,SAAS,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAClF,MAAM,MAAM,UAAU,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;IAAC,UAAU,EAAE,SAAS,EAAE,CAAA;CAAE,CAAC;AAsZ/G,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAa/E;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,UAAU,CAG7E"}
@@ -3,8 +3,20 @@ import _traverse from "@babel/traverse";
3
3
  const traverse = (typeof _traverse === "function" ? _traverse : _traverse.default);
4
4
  import md5 from "md5";
5
5
  import JSZip from "jszip";
6
- const EXT = [".js", ".jsx", ".ts", ".tsx"];
6
+ const EXT = [".js", ".jsx", ".ts", ".tsx", ".css"];
7
7
  const IGNORE_PATH_PARTS = ["node_modules", ".next", "dist", "build", ".git"];
8
+ function extractApplyClassesFromCss(code) {
9
+ const out = [];
10
+ const regex = /@apply\s+([^;]+);/g;
11
+ let match;
12
+ while ((match = regex.exec(code)) !== null) {
13
+ const lineNum = code.slice(0, match.index).split("\n").length;
14
+ const value = match[1].replace(/\s+/g, " ").trim();
15
+ if (value)
16
+ out.push({ value, line: lineNum });
17
+ }
18
+ return out;
19
+ }
8
20
  function isCodeFile(path) {
9
21
  return EXT.some((e) => path.toLowerCase().endsWith(e));
10
22
  }
@@ -167,6 +179,57 @@ function runAnalysis(fileContents) {
167
179
  return spacingByContext.get(context);
168
180
  }
169
181
  for (const { path: filePath, code } of sourceOnly) {
182
+ const isCss = filePath.toLowerCase().endsWith(".css");
183
+ if (isCss) {
184
+ const classEntries = extractApplyClassesFromCss(code);
185
+ for (const { value: cn, line } of classEntries) {
186
+ const context = isCardLike(cn) ? "card" : "default";
187
+ const spacingData = getSpacingMap(context);
188
+ const parts = cn.split(/\s+/).filter(Boolean);
189
+ for (const p of parts) {
190
+ if (/^p[xy]?-[a-z0-9]+$/.test(p) || /^m[xy]?-[a-z0-9]+$/.test(p)) {
191
+ const key = p.replace(/[0-9]+$/, "N");
192
+ if (!spacingData.has(key))
193
+ spacingData.set(key, { values: new Set(), locations: [] });
194
+ const entry = spacingData.get(key);
195
+ entry.values.add(p);
196
+ if (entry.locations.length < MAX_LOCATIONS)
197
+ entry.locations.push({ file: filePath, line });
198
+ }
199
+ if (/^rounded[a-z0-9-]*$/.test(p)) {
200
+ if (!radiusByFile.has(filePath))
201
+ radiusByFile.set(filePath, { values: new Set(), line });
202
+ radiusByFile.get(filePath).values.add(p);
203
+ }
204
+ if (/^(bg|text|border)-(.+)$/.test(p)) {
205
+ if (!colorClassesByFile.has(filePath))
206
+ colorClassesByFile.set(filePath, new Set());
207
+ colorClassesByFile.get(filePath).add(p);
208
+ const colorPart = p.replace(/^(bg|text|border)-/, "");
209
+ if (/\[#|\[rgb|\[hsl/.test(colorPart)) {
210
+ arbitraryColorByFile.set(filePath, line);
211
+ const hexMatch = colorPart.match(/\[#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})\]/);
212
+ if (hexMatch) {
213
+ let hex = hexMatch[1].toLowerCase();
214
+ if (hex.length === 3)
215
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
216
+ const key = "#" + hex;
217
+ if (!hexUsedInPlaces.has(key))
218
+ hexUsedInPlaces.set(key, []);
219
+ const locs = hexUsedInPlaces.get(key);
220
+ if (locs.length < MAX_LOCATIONS)
221
+ locs.push({ file: filePath, line });
222
+ }
223
+ }
224
+ }
225
+ if (PX_ARBITRARY.test(p) && !BORDER_PX_ONLY.test(p)) {
226
+ if (pixelUsageLocations.length < MAX_LOCATIONS)
227
+ pixelUsageLocations.push({ file: filePath, line });
228
+ }
229
+ }
230
+ }
231
+ continue;
232
+ }
170
233
  try {
171
234
  const ast = parser.parse(code, { sourceType: "module", plugins: ["jsx", "typescript"], attachComment: false });
172
235
  const unusedList = getUnusedImportsWithLine(ast);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@justinmoto/frontend-guardian-core",
3
- "version": "0.1.14",
4
- "description": "Scan engine for Frontend Guardian. To run scans from the CLI use: npx frontend-guardian .",
3
+ "version": "0.1.16",
4
+ "description": "Scan engine for Frontend Guardian.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",