Corp/backend/scripts/utils/analyze_templates.py
Игорь Надеин ee6e840252 Реорганизация документации и скриптов проекта
- Создана структура docs/ с категориями: completed, guides, architecture, diagnostic, in-progress, reports
- Перемещено 47+ MD файлов из корня проекта в docs/
- Удалено 6 устаревших/дублирующихся файлов
- Создана структура backend/scripts/ для тестов и утилит
- Перемещено 35 Python скриптов в backend/scripts/
- Создана структура backend/docs/ для технической документации
- Перемещено 12 MD файлов backend в backend/docs/
- Перемещены LDAP тестовые данные в backend/tests/fixtures/
- Добавлены README файлы для навигации
- Добавлены правила в .github/copilot-instructions.md для размещения документации

Результат:
- Корень проекта: только README.md
- Корень backend/: только manage.py и Django приложения
- Вся документация организована в структурированные папки
2025-12-26 13:49:51 +03:00

152 lines
5.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
"""
Анализ шаблонов: поиск встроенных стилей и скриптов.
Помогает понять масштаб рефакторинга.
"""
import os
import re
from pathlib import Path
from collections import defaultdict
# Путь к шаблонам
TEMPLATES_DIR = Path(__file__).parent / 'templates'
def analyze_template(filepath):
"""Анализирует один шаблон"""
try:
content = filepath.read_text(encoding='utf-8')
except Exception as e:
return None
lines = len(content.splitlines())
# Подсчёт тегов
style_tags = len(re.findall(r'<style[^>]*>', content))
script_tags = len(re.findall(r'<script[^>]*>', content))
# Размер встроенных стилей и скриптов
style_blocks = re.findall(r'<style[^>]*>(.*?)</style>', content, re.DOTALL)
script_blocks = re.findall(r'<script[^>]*>(.*?)</script>', content, re.DOTALL)
style_lines = sum(len(block.splitlines()) for block in style_blocks)
script_lines = sum(len(block.splitlines()) for block in script_blocks)
# Поиск CSS классов
css_classes = set(re.findall(r'\.([a-z][a-z0-9\-_]*)\s*{', content, re.IGNORECASE))
# Поиск функций JavaScript
js_functions = set(re.findall(r'function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(', content))
return {
'path': str(filepath.relative_to(TEMPLATES_DIR)),
'total_lines': lines,
'style_tags': style_tags,
'script_tags': script_tags,
'style_lines': style_lines,
'script_lines': script_lines,
'css_classes': css_classes,
'js_functions': js_functions,
'has_blocks': bool(re.search(r'{%\s*block\s+extra_(css|js)\s*%}', content)),
}
def main():
"""Главная функция анализа"""
print("=" * 80)
print("АНАЛИЗ ШАБЛОНОВ: встроенные стили и скрипты")
print("=" * 80)
# Находим все HTML файлы
html_files = list(TEMPLATES_DIR.rglob('*.html'))
results = []
for filepath in sorted(html_files):
# Пропускаем backup файлы
if '.backup' in str(filepath):
continue
result = analyze_template(filepath)
if result and (result['style_tags'] > 0 or result['script_tags'] > 0):
results.append(result)
# Сортируем по количеству встроенного кода
results.sort(key=lambda x: x['style_lines'] + x['script_lines'], reverse=True)
print(f"\nНайдено {len(results)} шаблонов со встроенными стилями/скриптами\n")
# Таблица результатов
print(f"{'Файл':<60} {'Строк':<8} {'<style>':<8} {'<script>':<8} {'CSS↓':<8} {'JS↓':<8}")
print("-" * 110)
total_style_lines = 0
total_script_lines = 0
for r in results:
total_style_lines += r['style_lines']
total_script_lines += r['script_lines']
print(f"{r['path']:<60} "
f"{r['total_lines']:<8} "
f"{r['style_tags']:<8} "
f"{r['script_tags']:<8} "
f"{r['style_lines']:<8} "
f"{r['script_lines']:<8}")
print("-" * 110)
print(f"{'ИТОГО:':<60} "
f"{'':8} "
f"{'':8} "
f"{'':8} "
f"{total_style_lines:<8} "
f"{total_script_lines:<8}")
print("\n" + "=" * 80)
print("АНАЛИЗ ДУБЛИКАТОВ")
print("=" * 80)
# Анализ повторяющихся CSS классов
all_classes = defaultdict(list)
for r in results:
for cls in r['css_classes']:
all_classes[cls].append(r['path'])
duplicated_classes = {k: v for k, v in all_classes.items() if len(v) > 1}
if duplicated_classes:
print(f"\nПовторяющиеся CSS классы ({len(duplicated_classes)}):")
for cls, files in sorted(duplicated_classes.items(), key=lambda x: len(x[1]), reverse=True)[:10]:
print(f" .{cls} → {len(files)} файлов: {', '.join(files[:3])}{' ...' if len(files) > 3 else ''}")
# Анализ повторяющихся JS функций
all_functions = defaultdict(list)
for r in results:
for func in r['js_functions']:
all_functions[func].append(r['path'])
duplicated_functions = {k: v for k, v in all_functions.items() if len(v) > 1}
if duplicated_functions:
print(f"\nПовторяющиеся JS функции ({len(duplicated_functions)}):")
for func, files in sorted(duplicated_functions.items(), key=lambda x: len(x[1]), reverse=True)[:10]:
print(f" {func}() → {len(files)} файлов: {', '.join(files[:3])}{' ...' if len(files) > 3 else ''}")
print("\n" + "=" * 80)
print("РЕКОМЕНДАЦИИ ПО РЕФАКТОРИНГУ")
print("=" * 80)
# ТОП-5 файлов для рефакторинга
print("\nТОП-5 файлов с наибольшим количеством встроенного кода:")
for i, r in enumerate(results[:5], 1):
total_embedded = r['style_lines'] + r['script_lines']
percentage = (total_embedded / r['total_lines']) * 100
print(f"{i}. {r['path']}")
print(f" {r['total_lines']} строк всего, {total_embedded} встроенного кода ({percentage:.1f}%)")
print(f" {r['style_lines']} строк CSS, {r['script_lines']} строк JS")
print("\n" + "=" * 80)
if __name__ == '__main__':
main()