From 1ec16fb08930d78a67c0e5e86da679dfdca73dd5 Mon Sep 17 00:00:00 2001 From: dm Date: Fri, 19 Dec 2025 14:56:02 +0100 Subject: [PATCH] =?UTF-8?q?Css=20-=20bia=C5=82y?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- find_unused_css_classes.py | 120 +++++++++++++++++++++++++++++++ src/styles/cards.css | 2 +- src/styles/contact.css | 2 +- src/styles/jambox-tematyczne.css | 3 +- src/styles/markdown.css | 4 ++ src/styles/sections.css | 63 ++++++++-------- src/styles/theme.css | 19 +++-- 7 files changed, 171 insertions(+), 42 deletions(-) create mode 100644 find_unused_css_classes.py diff --git a/find_unused_css_classes.py b/find_unused_css_classes.py new file mode 100644 index 0000000..c860f82 --- /dev/null +++ b/find_unused_css_classes.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +import argparse +import os +import re +from pathlib import Path +from typing import Dict, List, Set, Tuple + +# --- Regexy do zbierania klas z CSS --- +# Łapie ".class-name" w selektorach (pomija np. ".5" i rzeczy z escapami – prosto, ale działa w praktyce) +CSS_CLASS_RE = re.compile(r'(? re.Pattern: + return re.compile(r'(? str: + try: + return path.read_text(encoding="utf-8", errors="ignore") + except Exception: + return "" + +def collect_css_classes(css_dir: Path) -> Tuple[Set[str], Dict[str, Set[Path]]]: + classes: Set[str] = set() + where: Dict[str, Set[Path]] = {} + + for p in css_dir.rglob("*.css"): + txt = read_text(p) + for m in CSS_CLASS_RE.finditer(txt): + c = m.group(1) + classes.add(c) + where.setdefault(c, set()).add(p) + + return classes, where + +def collect_used_classes(code_dir: Path, candidates: Set[str]) -> Tuple[Set[str], Dict[str, Set[Path]]]: + used: Set[str] = set() + used_where: Dict[str, Set[Path]] = {c: set() for c in candidates} + + exts = {".astro", ".jsx", ".tsx", ".js", ".ts"} + # prekompilacja patternów dla szybkości + patterns = {c: token_pattern(c) for c in candidates} + + for p in code_dir.rglob("*"): + if not p.is_file(): + continue + if p.suffix.lower() not in exts: + continue + + txt = read_text(p) + if not txt: + continue + + # szybki filtr: jeśli żaden kandydat nie ma nawet prefiksu "f-" / "jmb-" itd, + # to i tak skan tokenowy jest ok, ale tu robimy prosty scan wszystkich. + for c, pat in patterns.items(): + if pat.search(txt): + used.add(c) + used_where[c].add(p) + + # usuń puste wpisy + used_where = {k: v for k, v in used_where.items() if v} + return used, used_where + +def main(): + ap = argparse.ArgumentParser(description="Znajdź potencjalnie nieużywane klasy CSS w projekcie Astro/JSX.") + ap.add_argument("--css", required=True, help="Katalog z plikami CSS (np. src/styles)") + ap.add_argument("--code", required=True, help="Katalog z kodem (np. src)") + ap.add_argument("--min-len", type=int, default=3, help="Minimalna długość nazwy klasy (domyślnie 3)") + ap.add_argument("--prefix", action="append", default=[], help="Filtruj klasy po prefiksie (np. --prefix f- --prefix jmb-)") + ap.add_argument("--show-where", action="store_true", help="Pokaż gdzie zdefiniowano klasę w CSS") + args = ap.parse_args() + + css_dir = Path(args.css).resolve() + code_dir = Path(args.code).resolve() + + if not css_dir.exists(): + raise SystemExit(f"Brak katalogu CSS: {css_dir}") + if not code_dir.exists(): + raise SystemExit(f"Brak katalogu code: {code_dir}") + + all_classes, defined_where = collect_css_classes(css_dir) + + # filtr długości + prefiksów + classes = {c for c in all_classes if len(c) >= args.min_len} + if args.prefix: + classes = {c for c in classes if any(c.startswith(px) for px in args.prefix)} + + used, used_where = collect_used_classes(code_dir, classes) + unused = sorted(classes - used) + + print(f"CSS katalog: {css_dir}") + print(f"CODE katalog: {code_dir}") + print(f"Klasy w CSS: {len(classes)} (po filtrach)") + print(f"Użyte w kodzie:{len(used)}") + print(f"NIEUŻYTE: {len(unused)}") + print("-" * 60) + + for c in unused: + print(c) + if args.show_where: + files = sorted(defined_where.get(c, [])) + for f in files: + rel = f.relative_to(css_dir.parent) if css_dir.parent in f.parents else f + print(f" defined in: {rel}") + print("-" * 60) + + # opcjonalnie: pokaż top kilka użyć + # (jak chcesz, dopiszę flagę na raport "gdzie użyte") + +if __name__ == "__main__": + main() diff --git a/src/styles/cards.css b/src/styles/cards.css index 2c57982..f047bb1 100644 --- a/src/styles/cards.css +++ b/src/styles/cards.css @@ -53,7 +53,7 @@ } .f-card-label { - @apply text-base font-medium opacity-80; + @apply text-base font-medium opacity-95; } .f-card-value { diff --git a/src/styles/contact.css b/src/styles/contact.css index d919405..d9dddbb 100644 --- a/src/styles/contact.css +++ b/src/styles/contact.css @@ -8,7 +8,7 @@ } p:first-of-type { - @apply py-3 text-3xl text-gray-400; + @apply py-3 text-3xl; } } diff --git a/src/styles/jambox-tematyczne.css b/src/styles/jambox-tematyczne.css index 0f5d79e..9891dcf 100644 --- a/src/styles/jambox-tematyczne.css +++ b/src/styles/jambox-tematyczne.css @@ -110,7 +110,8 @@ margin: 1.75rem auto; border-radius: 2rem; border: 1px solid color-mix(in oklab, var(--f-border-color) 82%, transparent 18%); - background: color-mix(in oklab, var(--f-background) 96%, black 10%); + background-color: var(--f-premium-bg); + /* background: color-mix(in oklab, var(--f-background) 96%, black 10%); */ box-shadow: 0 18px 40px -28px rgba(0,0,0,.35), diff --git a/src/styles/markdown.css b/src/styles/markdown.css index 614edb3..acbdda8 100644 --- a/src/styles/markdown.css +++ b/src/styles/markdown.css @@ -6,6 +6,10 @@ @apply text-2xl; } +.fuz-markdown p a:hover{ + @apply text-[--f-link-text-hover]; +} + .fuz-markdown h1 { @apply text-3xl font-bold mt-8 mb-4; } diff --git a/src/styles/sections.css b/src/styles/sections.css index 0e1767f..1608bc3 100644 --- a/src/styles/sections.css +++ b/src/styles/sections.css @@ -1,46 +1,45 @@ -/* @layer components { */ +.f-section-header { + @apply text-4xl md:text-5xl font-bold mb-3 text-[--f-header]; - .f-section-header { - @apply text-4xl md:text-5xl font-bold mb-3 text-[--f-header]; - - } +} - .f-section { - @apply pt-1 pb-1 mx-2 my-6;; - } +.f-section { + @apply pt-1 pb-1 mx-2 my-6; + ; +} - .f-section-center { - @apply f-section text-center; - } +.f-section-center { + @apply f-section text-center; +} - .f-section-grid { - @apply grid items-center gap-5 max-w-7xl mx-auto mt-8; - } +.f-section-grid { + @apply grid items-center gap-5 max-w-7xl mx-auto mt-8; +} - .f-section-grid-single { - @apply grid items-center gap-5 max-w-7xl mx-auto; - } +.f-section-grid-single { + @apply grid items-center gap-5 max-w-7xl mx-auto; +} - .f-section-grid-single-center { - @apply f-section-grid-single text-center; - } +.f-section-grid-single-center { + @apply f-section-grid-single text-center; +} - .f-section-image { - @apply w-full object-contain; - } +.f-section-image { + @apply w-full object-contain; +} - .f-image-dimmed { - @apply opacity-[1]; - } +.f-image-dimmed { + @apply opacity-[1]; +} - .f-section-title { - @apply text-4xl md:text-5xl font-bold mb-2 text-[--f-header]; - } +.f-section-title { + @apply text-4xl md:text-5xl font-bold mb-2 text-[--f-header]; +} - .f-section-nav { - @apply mt-0 flex justify-center; - } +.f-section-nav { + @apply mt-0 flex justify-center; +} /* } */ diff --git a/src/styles/theme.css b/src/styles/theme.css index 8c7bde7..584cac1 100644 --- a/src/styles/theme.css +++ b/src/styles/theme.css @@ -7,27 +7,30 @@ --brand-dark: hsl(200 calc(100% / 0.2) calc(50% / 1.5)); --f-navbar-height: 84px; + + /* -------------------------- */ --f-hero-text: #d1d6d9; --f-hero-header: #d1d6d9; /* --- Background and Text --- */ - --f-background: #e0e6eb; + --f-background: #ffffff; + /* #e0e6eb; */ --f-text: #36525e; --f-header: #001a33; --f-header-items: (#001a33); /*--- Navbar --- */ - --f-navbar-background: #b3b8ba; + --f-navbar-background: #e0e6eb; --f-navbar-link: #0066cc; - --f-navbar-link-hover: #1a6655; + --f-navbar-link-hover: #ef233c; /*--- Footer --- */ - --f-footer-background: #ccd6db; + --f-footer-background: #e0e6eb; --f-footer-link-text: #0066cc; /* --- Linki --- */ --f-link-text: #0066cc; - --f-link-text-hover: #1a6655; + --f-link-text-hover: #ef233c; --btn-background: #0066cc; - --btn-text: #ccd6db; + --btn-text: #e4ebee; --btn-background-hover: #ccd6db; --btn-text-hover: #0066cc; @@ -60,6 +63,7 @@ /* Obramowanie footer w kanałów premium */ --f-premium-border: #adb5bd; + --f-premium-bg: #f7f5f5; } @@ -120,5 +124,6 @@ html.dark { --f-addons-text: #fffae6; --f-addons-background: #1a6655; - --f-premium-border: #3d3f40; + --f-premium-border: #6c757d; + --f-premium-bg: #343a40; } \ No newline at end of file