diff --git a/app/__tests__/pre-push-check.test.ts b/app/__tests__/pre-push-check.test.ts
index 1cb17e9..9f400a7 100644
--- a/app/__tests__/pre-push-check.test.ts
+++ b/app/__tests__/pre-push-check.test.ts
@@ -268,7 +268,7 @@ describe("Accessibility: images have alt text", () => {
const content = readFile(file);
const rel = path.relative(SRC_ROOT, file);
- const imgRegex = /
]*>/gs;
+ const imgRegex = /
]*>/g;
let match: RegExpExecArray | null;
while ((match = imgRegex.exec(content)) !== null) {
const tag = match[0];
@@ -406,7 +406,19 @@ describe("Convention: no raw hex colors in classNames", () => {
// ═══════════════════════════════════════════════════════════════════════════
describe("Convention: no emoji in app/ source code", () => {
- const EMOJI_REGEX = /[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{FE00}-\u{FE0F}\u{1F000}-\u{1F02F}\u{1F0A0}-\u{1F0FF}\u{1F100}-\u{1F64F}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{1FA70}-\u{1FAFF}\u{1FC00}-\u{1FCFF}\u{1FD00}-\u{1FDFF}\u{1FE00}-\u{1FEFF}\u{200D}\u{20E3}\u{E0020}-\u{E007F}]/gu;
+ function lineContainsEmoji(line: string): boolean {
+ for (let i = 0; i < line.length; i++) {
+ const code = line.codePointAt(i);
+ if (code === undefined) continue;
+ if (code >= 0x1F300 && code <= 0x1FAFF) return true;
+ if (code >= 0x2600 && code <= 0x27BF) return true;
+ if (code >= 0xFE00 && code <= 0xFE0F) return true;
+ if (code === 0x200D) return true;
+ if (code === 0x20E3) return true;
+ if (code > 0xFFFF) i++;
+ }
+ return false;
+ }
const EXCLUDED_DIRS = new Set(["components/admin", "components/modern", "editor"]);
const EXCLUDED_FILES = new Set([
@@ -433,13 +445,17 @@ describe("Convention: no emoji in app/ source code", () => {
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line.trim().startsWith("//") || line.trim().startsWith("*")) continue;
- if (EMOJI_REGEX.test(line)) {
- const emoji = line.match(EMOJI_REGEX);
- if (emoji) {
- violations.push(`${rel}:${i + 1} — found emoji: ${emoji.join(", ")}`);
+ if (lineContainsEmoji(line)) {
+ const emojiChars: string[] = [];
+ for (let j = 0; j < line.length; j++) {
+ const code = line.codePointAt(j);
+ if (code !== undefined && ((code >= 0x1F300 && code <= 0x1FAFF) || (code >= 0x2600 && code <= 0x27BF) || (code >= 0xFE00 && code <= 0xFE0F) || code === 0x200D || code === 0x20E3)) {
+ emojiChars.push(String.fromCodePoint(code));
+ if (code > 0xFFFF) j++;
+ }
}
+ violations.push(`${rel}:${i + 1} — found emoji: ${emojiChars.join(", ")}`);
}
- EMOJI_REGEX.lastIndex = 0;
}
}