// 발행 게이트. 빌드 결과(dist)를 검사해 하나라도 실패하면 배포를 막는다. // 1) JSON-LD 문법·필수 타입 2) 이미지 alt 3) 금칙 표현(의료법 56조·효과 보장) 4) H1 1개 5) 홈페이지 문장 연속 일치 import { readdirSync, readFileSync, statSync, existsSync } from 'node:fs'; import { join } from 'node:path'; import { fileURLToPath } from 'node:url'; const DIST = fileURLToPath(new URL('../dist/', import.meta.url)); const BANNED = [ /완치/, /100\s*%/, /부작용\s*(이|은)?\s*없/, /(무조건|반드시|확실히)\s*(예뻐|성공|만족)/, /최고의\s*병원/, /1위\s*병원/, /제가\s*받아\s*봤는데/, /수술\s*받고\s*나서\s*(너무|정말)\s*(좋|만족)/, /후기를\s*보면\s*다들/, /강추/, ]; const HOME_TEXT = existsSync(fileURLToPath(new URL('./home_text.txt', import.meta.url))) ? readFileSync(fileURLToPath(new URL('./home_text.txt', import.meta.url)), 'utf8') : ''; function walk(dir, out = []) { for (const f of readdirSync(dir)) { const p = join(dir, f); statSync(p).isDirectory() ? walk(p, out) : f.endsWith('.html') && out.push(p); } return out; } const files = walk(DIST); let errors = 0; const fail = (f, m) => { errors++; console.error(` ✗ ${f.replace(DIST, '')}: ${m}`); }; for (const f of files) { const html = readFileSync(f, 'utf8'); const rel = f.replace(DIST, ''); // JSON-LD const blocks = [...html.matchAll(/