scan_commit_5dfe60ed_encoding.mjs 1.3 KB

1234567891011121314151617181920212223242526272829303132
  1. import { readFileSync, existsSync } from 'node:fs';
  2. import { execSync } from 'node:child_process';
  3. const root = 'd:/work/ylrz_saas';
  4. const files = execSync('git show --name-only --pretty=format: 5dfe60ed', { cwd: root })
  5. .toString('utf8')
  6. .split(/\r?\n/)
  7. .filter(Boolean);
  8. function scanFile(rel) {
  9. const path = `${root}/${rel.replace(/\\/g, '/')}`;
  10. if (!existsSync(path)) return null;
  11. if (!/\.(java|js|vue|sql|xml)$/.test(rel)) return null;
  12. const raw = readFileSync(path);
  13. const t = raw.toString('utf8');
  14. const bom = raw.length >= 3 && raw[0] === 0xef && raw[1] === 0xbb && raw[2] === 0xbf;
  15. const badLines = [];
  16. t.split('\n').forEach((line, i) => {
  17. if (line.includes('\uFFFD')) {
  18. badLines.push({ line: i + 1, kind: 'FFFD', text: line.trim().slice(0, 100) });
  19. } else if (/[^\s"'/]\?{2,}[^\s?]/.test(line)) {
  20. badLines.push({ line: i + 1, kind: 'qmarks', text: line.trim().slice(0, 100) });
  21. }
  22. });
  23. const unicodeEscapes = (t.match(/\\u[0-9a-fA-F]{4}/g) || []).length;
  24. if (!bom && !badLines.length && unicodeEscapes === 0) return null;
  25. return { rel, bom, badLines: badLines.slice(0, 8), badLineCount: badLines.length, unicodeEscapes };
  26. }
  27. const results = files.map(scanFile).filter(Boolean);
  28. console.log(JSON.stringify(results, null, 2));
  29. console.log('files with issues:', results.length);