/** * robots.txt 해석 (RFC 9309) — 네이버 검색로봇(Yeti)이 한 경로를 긁을 수 있는지 판정한다. * * 순수 함수만 둔다(네트워크 없음). 판정 규칙: * - 크롤러 토큰과 같은 `User-agent` 그룹이 있으면 그 그룹(여러 개면 합친다)만, 없으면 `*` 그룹을 쓴다. * `Yeti` 그룹이 따로 있으면 `*` 의 규칙은 Yeti 에게 **적용되지 않는다** — 흔한 오해다. * `User-agent: Yeti/1.1` 처럼 버전이 붙어도 제품 토큰(`[A-Za-z_-]+`)만 비교한다. * - 규칙은 가장 긴 패턴이 이기고, 길이가 같으면 allow 가 이긴다. `*` 와 닫는 `$` 를 지원한다. * - 값이 빈 `Disallow:` 는 규칙이 아니다(전부 허용). * - 비교 전에 패턴과 경로를 같은 퍼센트 인코딩으로 맞춘다 — `Disallow: /블로그` 는 `/%EB%B8%94…` 를 막는다. * * 매칭은 정규식이 아니라 선형 와일드카드 매처다. robots.txt 는 **점검 대상 사이트가 쓴 입력**이라 * `/*a*a*a…b` 같은 패턴으로 정규식 백트래킹을 폭발시켜 stdio 서버 전체를 멈출 수 있다. */ export declare const NAVER_CRAWLER_TOKEN = "yeti"; export interface RobotsRule { allow: boolean; pattern: string; } export interface RobotsGroup { agents: string[]; rules: RobotsRule[]; } export interface ParsedRobots { groups: RobotsGroup[]; sitemaps: string[]; } export interface RobotsVerdict { allowed: boolean; /** 판정에 쓴 그룹 — 'yeti' 전용, '*', 또는 해당 그룹 없음. */ group: 'crawler' | 'wildcard' | 'none'; /** 판정을 결정한 규칙. 없으면 기본 허용. */ matchedRule?: RobotsRule; } export declare function parseRobots(text: string): ParsedRobots; /** 비ASCII 는 UTF-8 퍼센트 인코딩, 기존 `%xx` 는 대문자 16진수로 — 패턴과 경로를 같은 표기로 맞춘다. */ export declare function normalizeRobotsPath(value: string): string; /** * `*`(0자 이상)와 닫는 `$`(끝 고정)만 있는 와일드카드 매칭. 앞쪽은 항상 고정(접두어 매칭). * 투 포인터 백트래킹이라 최악 O(패턴 × 경로) — 정규식처럼 지수적으로 터지지 않는다. */ export declare function robotsPatternMatches(pattern: string, path: string): boolean; /** `path` 는 경로 + 쿼리(`/a?b=1`). 크롤러 토큰은 소문자로 비교한다. */ export declare function isAllowed(robots: ParsedRobots, path: string, crawler?: string): RobotsVerdict;