From ae9d170ba322fc1c12e7b05cff74ddb4c7de08d0 Mon Sep 17 00:00:00 2001
From: oskar
Date: Mon, 3 Aug 2026 16:23:25 +0200
Subject: [PATCH] =?UTF-8?q?Regeneracja:=2019=20kart=20w=20pages/,=20graf?=
=?UTF-8?q?=2018=20koncept=C3=B3w=20+=2020=20external?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Karta zbiorcza pages/index.html grupowała tylko korzeń i oferty/ —
dziewięć konceptów wariantów dostawało własne karty, ale nie było ich
na liście. Grupowanie idzie teraz po katalogach najwyższego poziomu,
a nazwa grupy to pierwszy nagłówek index.md tego katalogu, więc kolejny
region wystarczy dodać do bundle'a, żeby pojawił się tu sam.
Linki wariantów w root index.md prowadzą do region.md, nie do index.md
podkatalogów: pliki zarezerwowane nie mają kart, więc w pages/ taki
odnośnik degenerował się do linku na samego siebie.
Co-Authored-By: Claude Opus 5 (1M context)
---
gen_pages.py | 32 ++++++-
index.md | 6 +-
log.md | 4 +
pages/index.html | 6 ++
.../oferty/apartment-brandau-kappl.html | 80 +++++++++++++++++
pages/ischgl/oferty/apartments-kappl.html | 78 ++++++++++++++++
pages/ischgl/region.html | 89 +++++++++++++++++++
.../oferty/haeuslerhof-valdaora.html | 80 +++++++++++++++++
.../oferty/residence-corones-valdaora.html | 78 ++++++++++++++++
pages/kronplatz/region.html | 88 ++++++++++++++++++
pages/sfl/oferty/apart-ideal-serfaus.html | 80 +++++++++++++++++
pages/sfl/oferty/haus-central-ladis.html | 80 +++++++++++++++++
pages/sfl/region.html | 88 ++++++++++++++++++
pages/wyjazd.html | 7 ++
viz.html | 2 +-
15 files changed, 792 insertions(+), 6 deletions(-)
create mode 100644 pages/ischgl/oferty/apartment-brandau-kappl.html
create mode 100644 pages/ischgl/oferty/apartments-kappl.html
create mode 100644 pages/ischgl/region.html
create mode 100644 pages/kronplatz/oferty/haeuslerhof-valdaora.html
create mode 100644 pages/kronplatz/oferty/residence-corones-valdaora.html
create mode 100644 pages/kronplatz/region.html
create mode 100644 pages/sfl/oferty/apart-ideal-serfaus.html
create mode 100644 pages/sfl/oferty/haus-central-ladis.html
create mode 100644 pages/sfl/region.html
diff --git a/gen_pages.py b/gen_pages.py
index 0224b38..acf41c1 100644
--- a/gen_pages.py
+++ b/gen_pages.py
@@ -442,11 +442,39 @@ def render_page(concept: Concept, pages: dict[str, str]) -> str:
return _page_shell(concept.title, concept.id.count("/"), content)
+_INDEX_HEADING_RE = re.compile(r"^#\s+(.+)$", re.M)
+
+
+def group_heading(dirname: str) -> str:
+ """Nagłówek grupy = pierwszy nagłówek `index.md` katalogu (§8).
+
+ Indexy podkatalogów same nazywają swoją zawartość, więc karta zbiorcza
+ nie musi mieć zaszytej listy katalogów — dorzucenie nowego regionu do
+ bundle'a wystarczy, żeby pojawił się tu z własną nazwą.
+ """
+ index = BUNDLE_ROOT / dirname / "index.md"
+ if index.is_file():
+ match = _INDEX_HEADING_RE.search(index.read_text(encoding="utf-8"))
+ if match:
+ return match.group(1).strip()
+ return dirname
+
+
def render_index(concepts: list[Concept]) -> str:
+ """Karta zbiorcza: koncepty z korzenia, potem grupa na katalog najwyższego
+ poziomu. Każdy koncept bundle'a ląduje w dokładnie jednej grupie."""
+ by_dir: dict[str, list[Concept]] = {}
+ for concept in concepts:
+ if "/" in concept.id:
+ by_dir.setdefault(concept.id.split("/", 1)[0], []).append(concept)
+
groups: list[tuple[str, list[Concept]]] = [
- ("Wyjazd i wiedza ogólna", [c for c in concepts if "/" not in c.id]),
- ("Oferty noclegowe", [c for c in concepts if c.id.startswith("oferty/")]),
+ ("Wyjazd i wiedza ogólna", [c for c in concepts if "/" not in c.id])
]
+ for dirname in sorted(by_dir):
+ # region.md przed oferty/* — płycej w drzewie znaczy ogólniej.
+ items = sorted(by_dir[dirname], key=lambda c: (c.id.count("/"), c.id))
+ groups.append((group_heading(dirname), items))
sections = []
for heading, items in groups:
if not items:
diff --git a/index.md b/index.md
index da430e3..f79b005 100644
--- a/index.md
+++ b/index.md
@@ -17,8 +17,8 @@ okf_version: "0.1"
# Warianty alternatywne
-* [Ischgl / Paznaun](/ischgl/index.md) - Wariant "Ischgl w budżecie": jazda w Silvretta Arenie (239 km) i Samnaun, nocleg w Kappl; skipass najdroższy z czterech wariantów, bo zniżka młodzieżowa kończy się przed 17. rokiem życia.
-* [Kronplatz / Plan de Corones](/kronplatz/index.md) - Wariant "Dolomity bez powtórki Sella Rondy": 121 km na jednej górze plus cały Dolomiti Superski w karnecie, baza w tanim Olang/Valdaora, junior do 18 lat.
-* [Serfaus-Fiss-Ladis](/sfl/index.md) - Najbardziej rodzinny wariant i najtańszy budżetowo: 214 km na słonecznym płaskowyżu, a termin 16–23.01 to u nich oficjalnie niski sezon.
+* [Ischgl / Silvretta Arena + dolina Paznaun](/ischgl/region.md) - Wariant alternatywny: 239 km Silvretta Areny z jazdą do bezcłowego Samnaun, nocleg w tańszym Kappl — skipass zweryfikowany na 26/27, bez zniżki dla 17-latków.
+* [Kronplatz / Plan de Corones (Południowy Tyrol)](/kronplatz/region.md) - Wariant alternatywny: 121 km na jednej górze plus cały Dolomiti Superski w karnecie, baza w tanim Olang/Valdaora, junior do 18 lat bez dopłaty.
+* [Serfaus-Fiss-Ladis (SFL)](/sfl/region.md) - Wariant alternatywny i najtańszy budżetowo: 214 km na słonecznym płaskowyżu, infrastruktura skrojona pod rodziny, a termin 16–23.01 to u nich oficjalnie niski sezon.
Porównanie wszystkich czterech wariantów obok siebie → [wyjazd](/wyjazd.md).
diff --git a/log.md b/log.md
index a0f7630..8426663 100644
--- a/log.md
+++ b/log.md
@@ -1,5 +1,9 @@
# Update Log
+## 2026-08-03
+
+* **Update**: Scalenie paczki `ski-2027-kb` (skonsumowana i usunięta) — do bundle'a weszły trzy warianty alternatywne: [Ischgl/Paznaun](/ischgl/region.md), [Kronplatz](/kronplatz/region.md) i [Serfaus-Fiss-Ladis](/sfl/region.md), każdy z dwiema kartami noclegów w `/oferty/`. Nowe koncepty znormalizowane do konwencji bundle'a (`title`/`description`/`timestamp`/`tags` przed polami producenta), dołożone indexy podkatalogów. Tabela porównawcza czterech wariantów i wnioski przekrojowe trafiły do [wyjazdu](/wyjazd.md), listing wariantów do [index.md](/index.md). Regeneracja: 18 konceptów, 20 linków zewnętrznych, 41 krawędzi, 19 kart w `pages/`.
+
## 2026-07-31
* **Initialization**: Utworzenie bundle'a wiedzy o wyjeździe — [region](/region.md), [szablon maila](/szablon-maila.md) i sześć kart noclegowych w [oferty/](/oferty/index.md).
diff --git a/pages/index.html b/pages/index.html
index 091255e..41e6796 100644
--- a/pages/index.html
+++ b/pages/index.html
@@ -65,8 +65,14 @@ footer { margin-top: 3rem; padding-top: 1rem; border-top: 1px solid var(--line);
Karty konceptów bundle'a — pełna treść każdego dokumentu (ceny, dostępność, plusy/minusy). Struktura powiązań: graf.
Wariant alternatywny: 239 km Silvretta Areny z jazdą do bezcłowego Samnaun, nocleg w tańszym Kappl — skipass zweryfikowany na 26/27, bez zniżki dla 17-latków.
Wariant alternatywny i najtańszy budżetowo: 214 km na słonecznym płaskowyżu, infrastruktura skrojona pod rodziny, a termin 16–23.01 to u nich oficjalnie niski sezon.
Rodzinnie prowadzony dom z 6 komfortowymi apartamentami w Kappl — idealna konfiguracja pod 4 rodziny (bierzemy 4 jednostki, dom prawie na wyłączność). Silvretta Arena Ischgl/Samnaun ~10 min autem/skibusem, skibus po całej dolinie bezpłatny.
+
Fakty
+
Apartamenty z pełnymi aneksami kuchennymi (piekarnik, zmywarka — poza typami 1 i 6), SAT-TV, WLAN, sejf.
W Kappl: 40 km rodzinnych tras + oświetlony 6-km tor saneczkowy.
Wyposażenie dla dzieci (krzesełka, łóżeczka).
+
Plusy / minusy
+
+ układ 6 apartamentów = klimat "nasz dom"; ceny Kappl zamiast Ischgl; tor saneczkowy na wieczory; parking. − codzienna logistyka skibus/auto do Silvretta Areny; wieczorne życie tylko w Ischgl (10 min taksówką).
+
Do zrobienia
+
Mail (szablon EN): 4 apartamenty, 16–23.01.2027, konfiguracja 4+4+3+3, cena grupowa.
Alternatywy w Kappl, jeśli brak miejsc: Apartments Kappl (apartments.kappl.at — skibus 100 m, narciarnia z suszarką), Ferienwohnen Mattle (centrum, blisko trasy i skibusa), Apart Avenzio (3 min od gondoli Kappl).