refactor: 4개 검사 엔진을 YAML 기반 표준 규칙으로 리팩토링
- YAML 규칙 파일 4개 신규 생성 (html_css, accessibility, seo, performance_security) W3C, WCAG 2.0/2.1/2.2, OWASP, Google Search Essentials 공식 표준 기반 - rules/__init__.py: YAML 로더 + 캐싱 + 리로드 모듈 - html_css.py: 30개 폐기 요소, 100+개 폐기 속성을 YAML에서 동적 로드 - accessibility.py: WCAG 버전 선택 지원 (wcag_version 파라미터) - seo.py: title/description 길이, OG 필수 태그 등 임계값 YAML 로드 - performance_security.py: COOP/COEP/CORP 검사 추가, 정보 노출 헤더 검사 추가, TTFB/페이지 크기 임계값 YAML 로드 - PyYAML 의존성 추가 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
67
backend/app/rules/__init__.py
Normal file
67
backend/app/rules/__init__.py
Normal file
@ -0,0 +1,67 @@
|
||||
"""
|
||||
Rules Loader - YAML 기반 표준 규칙 데이터 로드 및 캐싱.
|
||||
|
||||
Usage:
|
||||
from app.rules import get_rules
|
||||
rules = get_rules("html_css") # html_css.yaml 전체 로드
|
||||
rules = get_rules("accessibility") # accessibility.yaml 전체 로드
|
||||
"""
|
||||
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import yaml
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
RULES_DIR = Path(__file__).parent
|
||||
_cache: dict[str, dict[str, Any]] = {}
|
||||
|
||||
|
||||
def get_rules(category: str) -> dict[str, Any]:
|
||||
"""
|
||||
Load and cache YAML rules for a given category.
|
||||
|
||||
Args:
|
||||
category: One of "html_css", "accessibility", "seo", "performance_security"
|
||||
|
||||
Returns:
|
||||
Parsed YAML data as a dictionary.
|
||||
"""
|
||||
if category in _cache:
|
||||
return _cache[category]
|
||||
|
||||
yaml_path = RULES_DIR / f"{category}.yaml"
|
||||
if not yaml_path.exists():
|
||||
logger.error("Rules file not found: %s", yaml_path)
|
||||
return {}
|
||||
|
||||
with open(yaml_path, "r", encoding="utf-8") as f:
|
||||
data = yaml.safe_load(f) or {}
|
||||
|
||||
_cache[category] = data
|
||||
logger.info("Loaded rules: %s (%d bytes)", category, yaml_path.stat().st_size)
|
||||
return data
|
||||
|
||||
|
||||
def reload_rules(category: str | None = None) -> None:
|
||||
"""
|
||||
Clear cache and reload rules.
|
||||
If category is None, reload all cached rules.
|
||||
"""
|
||||
if category:
|
||||
_cache.pop(category, None)
|
||||
get_rules(category)
|
||||
else:
|
||||
categories = list(_cache.keys())
|
||||
_cache.clear()
|
||||
for cat in categories:
|
||||
get_rules(cat)
|
||||
|
||||
|
||||
def get_all_categories() -> list[str]:
|
||||
"""Return list of available rule categories."""
|
||||
return [
|
||||
p.stem for p in RULES_DIR.glob("*.yaml")
|
||||
]
|
||||
Reference in New Issue
Block a user