From 83b53d06591a8b77711287761945c41a5fdbfdfd Mon Sep 17 00:00:00 2001 From: Timmy Date: Wed, 25 Mar 2026 11:16:32 -0400 Subject: [PATCH] =?UTF-8?q?enforce:=20777-line=20hard=20limit=20on=20JS=20?= =?UTF-8?q?files=20=E2=80=94=20CI=20gate=20+=20pre-commit=20hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit app.js is a THIN WRAPPER. No file over 777 lines. Current app.js is 2214 lines — must be broken up before any new features merge. CI will block PRs that violate this. Pre-commit hook catches it locally. Install hook: git config core.hooksPath .githooks --- .gitea/workflows/ci.yml | 34 +++++++++++++++++++++++++--------- .githooks/pre-commit | 19 +++++++++++++++++++ 2 files changed, 44 insertions(+), 9 deletions(-) create mode 100755 .githooks/pre-commit diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 5f00350..c689288 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -14,15 +14,12 @@ jobs: - name: Validate HTML run: | - # Check index.html exists and is valid-ish test -f index.html || { echo "ERROR: index.html missing"; exit 1; } - # Check for unclosed tags (basic) python3 -c " import html.parser, sys class V(html.parser.HTMLParser): def __init__(self): super().__init__() - self.errors = [] def handle_starttag(self, tag, attrs): pass def handle_endtag(self, tag): pass v = V() @@ -36,9 +33,8 @@ jobs: - name: Validate JavaScript run: | - # Syntax check all JS files FAIL=0 - for f in $(find . -name '*.js' -not -path './node_modules/*' -not -name 'sw.js'); do + for f in $(find . -name '*.js' -not -path './node_modules/*' -not -name 'sw.js' -not -name 'service-worker.js' -not -path './tests/*'); do if ! node --check "$f" 2>/dev/null; then echo "FAIL: $f" FAIL=1 @@ -50,9 +46,8 @@ jobs: - name: Validate JSON run: | - # Check all JSON files parse FAIL=0 - for f in $(find . -name '*.json' -not -path './node_modules/*'); do + for f in $(find . -name '*.json' -not -path './node_modules/*' -not -path './test-*'); do if ! python3 -c "import json; json.load(open('$f'))"; then echo "FAIL: $f" FAIL=1 @@ -62,9 +57,30 @@ jobs: done exit $FAIL - - name: Check file size budget + - name: "HARD RULE: No JS file over 777 lines" + run: | + echo "=== File Size Budget: 777 lines max per JS file ===" + FAIL=0 + for f in $(find . -name '*.js' -not -path './node_modules/*' -not -path './test-*' -not -path './tests/*'); do + LINES=$(wc -l < "$f" | tr -d ' ') + if [ "$LINES" -gt 777 ]; then + echo "FAIL: $f is $LINES lines (max: 777)" + FAIL=1 + else + echo "OK: $f ($LINES lines)" + fi + done + if [ $FAIL -eq 1 ]; then + echo "" + echo "═══════════════════════════════════════════════════" + echo " BLOCKED: No JS file may exceed 777 lines." + echo " Extract into modules. app.js is a THIN WRAPPER." + echo "═══════════════════════════════════════════════════" + fi + exit $FAIL + + - name: Check file size budget (bytes) run: | - # Performance budget: no single JS file > 500KB FAIL=0 for f in $(find . -name '*.js' -not -path './node_modules/*'); do SIZE=$(wc -c < "$f") diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..6e842f0 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +# Pre-commit hook: enforce 777-line limit on JS files +# Install: git config core.hooksPath .githooks + +FAIL=0 +for f in $(git diff --cached --name-only --diff-filter=ACM | grep '\.js$' | grep -v node_modules | grep -v tests/); do + LINES=$(wc -l < "$f" | tr -d ' ') + if [ "$LINES" -gt 777 ]; then + echo "BLOCKED: $f is $LINES lines (max: 777)" + echo " Extract into a module. app.js is a thin wrapper." + FAIL=1 + fi +done + +if [ $FAIL -eq 1 ]; then + echo "" + echo "No JS file may exceed 777 lines. Break it up." + exit 1 +fi