Compare commits
71 Commits
c337e1bde1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 43658c2921 | |||
| fa68e42f5f | |||
| e411addfe2 | |||
| 53ccdd2b69 | |||
| 6bf9260923 | |||
| 7c5b584890 | |||
| a128ca9921 | |||
| 965696b1ca | |||
| 787002532d | |||
| ba8565e59a | |||
| 539f30bdb7 | |||
| 7546b4021d | |||
| 1c98566e93 | |||
| d3987ea20b | |||
| 02a1ecb53d | |||
| 70adecae58 | |||
| 066470e82c | |||
| 106cfe6e33 | |||
| d4b20eb113 | |||
| f72719b9a4 | |||
| c62db8a2ef | |||
| 567dd9a2ca | |||
| ec877ef65b | |||
| e5add77a50 | |||
| b2f29dea27 | |||
| c02facdf5d | |||
| 22fe4dbd9f | |||
| 4af08a2304 | |||
| f27489b412 | |||
| 1bdd8af9ac | |||
| ffc47e02e7 | |||
| 8578ef8fe3 | |||
| 446211e9cb | |||
| fa65e99310 | |||
| 5294d73dc1 | |||
| 5dad99d8b3 | |||
| 5720a4a7e0 | |||
| 39c3a59744 | |||
| 5c69c44ed3 | |||
| ae61cc44e1 | |||
| a5f0d0473d | |||
| 07b70762ee | |||
| 92ba156603 | |||
| ea8427aba5 | |||
| c27e404ee1 | |||
| 6b8e146c4a | |||
| 961dbf1348 | |||
| 62ae7fe69e | |||
| b8eae846a5 | |||
| c39661c7e4 | |||
| 21fd89c854 | |||
| 031a280a62 | |||
| cef9d9ae11 | |||
| 7a1f0fcd8c | |||
| 56fea34fc5 | |||
| ef74aeefe0 | |||
| a30d741d71 | |||
| bc2fb2f842 | |||
| aab7b08296 | |||
| 0acc2a4c0a | |||
| fb17445807 | |||
| 0565ed678a | |||
| 21c8ff66fd | |||
| 16cd760dac | |||
| ec41628fb6 | |||
| 80ce77c530 | |||
| 9485cd4428 | |||
| 9f943aea21 | |||
| 87c710a3e9 | |||
| bfbce1aad0 | |||
| 18c9ce8754 |
@@ -1 +1 @@
|
|||||||
{"task_id": "31f88f42-8544-80ad-9573-e9f7f398e8b1", "token": "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", "readme_path": "connector-superoffice/README.md", "session_start_time": "2026-03-10T14:01:26.654688"}
|
{"task_id": "2f988f42-8544-800e-abc1-d1b1c56ade4d", "token": "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", "readme_path": "readme.md", "session_start_time": "2026-03-25T12:11:18.223098"}
|
||||||
1
.gitignore
vendored
@@ -71,3 +71,4 @@ Log_from_docker/
|
|||||||
|
|
||||||
.gemini/.env
|
.gemini/.env
|
||||||
gemini_api_key.txt
|
gemini_api_key.txt
|
||||||
|
*.tar.gz
|
||||||
|
|||||||
BIN
ARCHIVE_vor_migration/Fotograf.de/logo_kinderfotos_erding.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
16
GEMINI.md
@@ -58,6 +58,22 @@ Das System läuft stabil und ist für den Produktivbetrieb vorbereitet. Wesentli
|
|||||||
### 5. DuckDNS & DNS Monitor
|
### 5. DuckDNS & DNS Monitor
|
||||||
* **Erfolgreich reaktiviert:** Der DynDNS-Service läuft und aktualisiert die IP, die Netzwerk-Konnektivität ist stabil.
|
* **Erfolgreich reaktiviert:** Der DynDNS-Service läuft und aktualisiert die IP, die Netzwerk-Konnektivität ist stabil.
|
||||||
|
|
||||||
|
### 6. Fotograf.de Scraper (In Development)
|
||||||
|
* **Architektur:** Ein neuer, eigenständiger Microservice wurde unter `/fotograf-de-scraper` angelegt. FastAPI-Backend (Python/Selenium) + React-Frontend (TypeScript/Vite/Tailwind).
|
||||||
|
* **Status (20. März 2026):**
|
||||||
|
* **Grundgerüst & Login:** Erfolgreich implementiert. Der Selenium-Bot loggt sich stabil ein.
|
||||||
|
* **Auftragsliste:** Das Abrufen und Cachen der Aufträge (`/config_jobs/index`) im Frontend funktioniert.
|
||||||
|
* **Feature 1 (Teilnehmerliste PDF): ERFOLGREICH.** Der Scraper navigiert zum Auftrag, lädt die CSV-Anmeldeliste versteckt herunter, formatiert sie via WeasyPrint/Jinja2 (Logik aus List-Generator übernommen) und liefert das finale PDF an den Browser aus.
|
||||||
|
* **Frontend UI:** Erste Version eines kachelbasierten Dashboards mit Detail-Modal implementiert. (Benötigt weiteres Feintuning nach User-Feedback).
|
||||||
|
* **Kritischer Blocker (Infrastruktur):**
|
||||||
|
* **Datenbank-Persistenz fehlerhaft:** Trotz Umstellung der `docker-compose.yml` auf lokale Bind-Mounts (`./company-explorer/data:/data`, etc.) sind die SQLite-Datenbanken nach einem Container-Rebuild (`--force-recreate`) leer.
|
||||||
|
* *Verdacht:* Rechteprobleme auf der Synology Diskstation oder Initialisierungsskripte im Container, die die DB bei jedem Start überschreiben. **Muss offline vom User auf Host-Ebene geprüft werden.**
|
||||||
|
* **Nächste Schritte (Für die nächste Session):**
|
||||||
|
1. **Infrastruktur:** Verifizierung, dass das DB-Persistenz-Problem gelöst ist.
|
||||||
|
2. **Feature 4 (Statistik):** Reaktivierung der bestehenden Skript-Logik (`process_statistics_mode`) zur Auswertung der Verkaufszahlen. Integration in einen neuen API-Endpunkt und Anzeige im Frontend-Modal.
|
||||||
|
3. **Feature 3 (Nachfass-Emails):** Reaktivierung der bestehenden Logik (`process_reminder_mode`).
|
||||||
|
4. **Feature 2 (QR-Karten):** Backend-Endpunkt zur PDF-Manipulation (Overlay von Text) basierend auf CSV/Calendly-Daten.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Git Workflow & Conventions
|
## Git Workflow & Conventions
|
||||||
|
|||||||
@@ -337,3 +337,42 @@ Das neue Gitea (auf Port 3000) wird zur zentralen "Source of Truth".
|
|||||||
|
|
||||||
Dieser Prozess ist sicher, schnell und wiederholbar, da er nur aus Standard-Git- und Docker-Befehlen besteht.
|
Dieser Prozess ist sicher, schnell und wiederholbar, da er nur aus Standard-Git- und Docker-Befehlen besteht.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **UMZUG Live - Lessons Learned (März 2026)**
|
||||||
|
|
||||||
|
Der reale Umzug von der Synology auf die Wackler-VM (`docker1`) hat gezeigt, dass die Theorie gut war, die Praxis aber spezifische Hürden bereithielt. Diese Lektionen sind kritisch für alle zukünftigen Deployments:
|
||||||
|
|
||||||
|
#### **1. Die Git-Historien-Falle (Packfile / Timeout Error)**
|
||||||
|
* **Problem:** Versuche, das Repository per `git clone` oder über die Gitea-Migrations-Funktion umzuziehen, brachen reproduzierbar mit `RPC failed; HTTP 504` oder `fatal: expected 'packfile'` ab.
|
||||||
|
* **Ursache:** Das lokale `.git` Verzeichnis war auf **1,4 Gigabyte** angewachsen, da in der Vergangenheit versehentlich große MP3-Dateien committet wurden. Auch nach dem Löschen verbleiben diese in der Historie und blockieren den Transfer über Proxies.
|
||||||
|
* **Lösung:** Radikale Bereinigung der Historie via `git filter-branch` (oder `git filter-repo`) für den Ordner `uploads_audio/`, gefolgt von einer aggressiven Garbage Collection (`git gc --prune=now --aggressive`).
|
||||||
|
* **Ergebnis:** Schrumpfung des Repos von 1,4 GB auf **130 MB**.
|
||||||
|
* **Lesson:** Bei Git-Transfer-Fehlern zuerst die Größe des `.git` Ordners prüfen.
|
||||||
|
|
||||||
|
#### **2. Der "Filter-Branch" Nebeneffekt (.env Schutz)**
|
||||||
|
* **Problem:** Nach der Git-Bereinigung schienen ungetrackte Dateien (wie `.env` und `volume_backups/`) plötzlich verschwunden.
|
||||||
|
* **Ursache:** `git filter-branch` erzwingt einen harten Reset auf den bereinigten Stand. Dateien, die in der `.gitignore` stehen, werden dabei oft aus dem Arbeitsverzeichnis entfernt.
|
||||||
|
* **Lösung:** Wiederherstellung aus einem zuvor erstellten `.tar.gz`-Backup des gesamten Projektverzeichnisses.
|
||||||
|
* **Lesson:** Führe niemals tiefe Git-Eingriffe ohne ein physisches Dateibackup der ungetrackten Dateien durch.
|
||||||
|
|
||||||
|
#### **3. Das "Transit-Repo" Muster für Secrets**
|
||||||
|
* **Problem:** Sicherer Transfer der `.env` und Datenbanken ohne Einchecken in das Haupt-Repo und ohne Zugriff auf externe Transfer-Dienste (Firewall-Blockade).
|
||||||
|
* **Lösung:** Erstellung eines temporären, privaten Gitea-Repositorys namens `transit` auf dem Ziel-System. Hochladen des verschlüsselten Backups über die Gitea-Weboberfläche und anschließendes Klonen/Entpacken auf der VM. Danach sofortige Löschung des `transit` Repos.
|
||||||
|
* **Lesson:** Gitea ist das beste Transit-Medium für große Files hinter restriktiven Firewalls.
|
||||||
|
|
||||||
|
#### **4. Docker Build Context & Berechtigungen**
|
||||||
|
* **Problem:** `docker compose up --build` brach ab mit: `failed to solve: error from sender: open /volume_backups: permission denied`.
|
||||||
|
* **Ursache:** Docker versucht beim Bauen das gesamte Verzeichnis einzulesen. Ordner, die dem `root` User gehören (z.B. durch Gemini-Aktionen erstellt), blockieren den Prozess.
|
||||||
|
* **Lösung:**
|
||||||
|
1. Berechtigungen korrigieren: `sudo chown -R $USER:$USER volume_backups/`
|
||||||
|
2. Ordner in der `.dockerignore` ausschließen, damit er gar nicht erst eingelesen wird.
|
||||||
|
* **Lesson:** Alles, was nicht in ein Container-Image gehört, **muss** in die `.dockerignore`.
|
||||||
|
|
||||||
|
#### **5. Vite & TypeScript Build-Tücken**
|
||||||
|
* **Problem:** Der Frontend-Build schlug fehl, weil die `tsconfig.json` im Container nicht gefunden wurde.
|
||||||
|
* **Ursache:** `COPY . .` verhält sich in komplexen Verzeichnisstrukturen manchmal unvorhersehbar.
|
||||||
|
* **Lösung:** Explizites Kopieren aller Konfigurationsdateien im Dockerfile: `COPY tsconfig.json tsconfig.node.json tsconfig.app.json vite.config.ts ./` direkt vor dem Build-Schritt.
|
||||||
|
* **Lesson:** Verlasse dich beim Build nicht auf Wildcards; kopiere essenzielle Config-Files explizit.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
29
check_notion_task.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import os
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
token = os.environ.get('NOTION_API_KEY')
|
||||||
|
db_name = "Tasks [UT]"
|
||||||
|
|
||||||
|
def find_database_id(token, title):
|
||||||
|
url = "https://api.notion.com/v1/search"
|
||||||
|
headers = {"Authorization": f"Bearer {token}", "Notion-Version": "2022-06-28"}
|
||||||
|
payload = {"query": title, "filter": {"value": "database", "property": "object"}}
|
||||||
|
res = requests.post(url, headers=headers, json=payload)
|
||||||
|
for db in res.json().get("results", []):
|
||||||
|
if db["title"][0]["plain_text"] == title:
|
||||||
|
return db["id"]
|
||||||
|
return None
|
||||||
|
|
||||||
|
db_id = find_database_id(token, db_name)
|
||||||
|
if db_id:
|
||||||
|
url = f"https://api.notion.com/v1/databases/{db_id}/query"
|
||||||
|
headers = {"Authorization": f"Bearer {token}", "Notion-Version": "2022-06-28"}
|
||||||
|
res = requests.post(url, headers=headers)
|
||||||
|
tasks = res.json().get("results", [])
|
||||||
|
for task in tasks:
|
||||||
|
tid = task["id"]
|
||||||
|
title = task["properties"]["Name"]["title"][0]["plain_text"]
|
||||||
|
print(f"Task: {title} | ID: {tid}")
|
||||||
@@ -66,47 +66,47 @@ class JobQueue:
|
|||||||
conn.commit()
|
conn.commit()
|
||||||
logger.debug(f"Job added: {event_type} for entity {entity_id}")
|
logger.debug(f"Job added: {event_type} for entity {entity_id}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"❌ Failed to add job: {e}", exc_info=True)
|
logger.error(f"❌ Failed to add job: {e}", exc_info=True)
|
||||||
conn.rollback()
|
conn.rollback()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def is_duplicate_pending(self, event_type: str, payload: dict) -> bool:
|
def is_duplicate_pending(self, event_type: str, payload: dict) -> bool:
|
||||||
"""
|
"""
|
||||||
Checks if a job with the same event_type and entity_id is already PENDING.
|
Checks if a job with the same event_type and entity_id is already PENDING.
|
||||||
This is to prevent adding duplicate jobs from webhooks that are sent multiple times.
|
This is to prevent adding duplicate jobs from webhooks that are sent multiple times.
|
||||||
"""
|
"""
|
||||||
# We only want to de-duplicate creation events, as change events can be validly stacked.
|
# We only want to de-duplicate creation events, as change events can be validly stacked.
|
||||||
if "created" not in event_type.lower():
|
if "created" not in event_type.lower():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
entity_id = payload.get("PrimaryKey")
|
||||||
|
if not entity_id:
|
||||||
|
return False # Cannot de-duplicate without a key
|
||||||
|
|
||||||
|
five_minutes_ago = datetime.utcnow() - timedelta(minutes=5)
|
||||||
|
with sqlite3.connect(DB_PATH, timeout=30) as conn:
|
||||||
|
try:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT id FROM jobs
|
||||||
|
WHERE event_type = ?
|
||||||
|
AND entity_id = ?
|
||||||
|
AND status = 'PENDING'
|
||||||
|
AND created_at >= ?
|
||||||
|
""", (event_type, entity_id, five_minutes_ago))
|
||||||
|
|
||||||
entity_id = payload.get("PrimaryKey")
|
if existing_job := cursor.fetchone():
|
||||||
if not entity_id:
|
logger.warning(f"Found PENDING duplicate of job {existing_job[0]} for event '{event_type}' and entity '{entity_id}'. Ignoring new webhook.")
|
||||||
return False # Cannot de-duplicate without a key
|
return True
|
||||||
|
return False
|
||||||
five_minutes_ago = datetime.utcnow() - timedelta(minutes=5)
|
except Exception as e:
|
||||||
with sqlite3.connect(DB_PATH, timeout=30) as conn:
|
logger.error(f"❌ Failed to check for PENDING duplicate jobs for entity '{entity_id}': {e}", exc_info=True)
|
||||||
try:
|
return False # Fail safe: better to have a duplicate than to miss an event.
|
||||||
cursor = conn.cursor()
|
|
||||||
cursor.execute("""
|
def update_entity_name(self, job_id, name, associate_name=None):
|
||||||
SELECT id FROM jobs
|
with sqlite3.connect(DB_PATH, timeout=30) as conn:
|
||||||
WHERE event_type = ?
|
try:
|
||||||
AND entity_id = ?
|
if associate_name:
|
||||||
AND status = 'PENDING'
|
|
||||||
AND created_at >= ?
|
|
||||||
""", (event_type, entity_id, five_minutes_ago))
|
|
||||||
|
|
||||||
if existing_job := cursor.fetchone():
|
|
||||||
logger.warning(f"Found PENDING duplicate of job {existing_job[0]} for event '{event_type}' and entity '{entity_id}'. Ignoring new webhook.")
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"❌ Failed to check for PENDING duplicate jobs for entity '{entity_id}': {e}", exc_info=True)
|
|
||||||
return False # Fail safe: better to have a duplicate than to miss an event.
|
|
||||||
|
|
||||||
def update_entity_name(self, job_id, name, associate_name=None):
|
|
||||||
with sqlite3.connect(DB_PATH, timeout=30) as conn:
|
|
||||||
try:
|
|
||||||
if associate_name:
|
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"UPDATE jobs SET entity_name = ?, associate_name = ?, updated_at = datetime('now') WHERE id = ?",
|
"UPDATE jobs SET entity_name = ?, associate_name = ?, updated_at = datetime('now') WHERE id = ?",
|
||||||
(str(name), str(associate_name), job_id)
|
(str(name), str(associate_name), job_id)
|
||||||
|
|||||||
128
dev_session.py
@@ -394,6 +394,9 @@ def select_project(token: str) -> Optional[Tuple[Dict, Optional[str]]]:
|
|||||||
print("Keine Projekte in der Datenbank gefunden.")
|
print("Keine Projekte in der Datenbank gefunden.")
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
|
# Sortiere Projekte alphabetisch nach Titel
|
||||||
|
projects.sort(key=lambda p: get_page_title(p).lower())
|
||||||
|
|
||||||
print("\nAn welchem Projekt möchtest du arbeiten?")
|
print("\nAn welchem Projekt möchtest du arbeiten?")
|
||||||
for i, project in enumerate(projects):
|
for i, project in enumerate(projects):
|
||||||
print(f"[{i+1}] {get_page_title(project)}")
|
print(f"[{i+1}] {get_page_title(project)}")
|
||||||
@@ -428,6 +431,7 @@ def select_task(token: str, project_id: str, tasks_db_id: str) -> Optional[Dict]
|
|||||||
print(f"[{i+1}] {get_page_title(task)}")
|
print(f"[{i+1}] {get_page_title(task)}")
|
||||||
|
|
||||||
print(f"[{len(tasks)+1}] Neuen Task für dieses Projekt erstellen")
|
print(f"[{len(tasks)+1}] Neuen Task für dieses Projekt erstellen")
|
||||||
|
print("[0] Zurück zur Projektauswahl")
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
@@ -436,6 +440,8 @@ def select_task(token: str, project_id: str, tasks_db_id: str) -> Optional[Dict]
|
|||||||
return tasks[choice - 1]
|
return tasks[choice - 1]
|
||||||
elif choice == len(tasks) + 1:
|
elif choice == len(tasks) + 1:
|
||||||
return {"id": "new_task"} # Signal
|
return {"id": "new_task"} # Signal
|
||||||
|
elif choice == 0:
|
||||||
|
return {"id": "go_back"} # Signal
|
||||||
else:
|
else:
|
||||||
print("Ungültige Auswahl.")
|
print("Ungültige Auswahl.")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@@ -450,34 +456,6 @@ BERLIN_TZ = ZoneInfo("Europe/Berlin")
|
|||||||
|
|
||||||
# --- Git Summary Generation ---
|
# --- Git Summary Generation ---
|
||||||
|
|
||||||
def generate_git_summary() -> Tuple[str, str]:
|
|
||||||
"""Generiert eine Zusammenfassung der Git-Änderungen und Commit-Nachrichten seit dem letzten Push zum Main-Branch."""
|
|
||||||
try:
|
|
||||||
# Finde den aktuellen Main-Branch Namen (master oder main)
|
|
||||||
try:
|
|
||||||
main_branch = subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]).decode("utf-8").strip()
|
|
||||||
if main_branch not in ["main", "master"]:
|
|
||||||
# Versuche, den Remote-Tracking-Branch für main/master zu finden
|
|
||||||
result = subprocess.run(["git", "branch", "-r"], capture_output=True, text=True)
|
|
||||||
if "origin/main" in result.stdout:
|
|
||||||
main_branch = "origin/main"
|
|
||||||
elif "origin/master" in result.stdout:
|
|
||||||
main_branch = "origin/master"
|
|
||||||
else:
|
|
||||||
print("Warnung: Konnte keinen 'main' oder 'master' Branch finden. Git-Zusammenfassung wird möglicherweise unvollständig sein.")
|
|
||||||
main_branch = "HEAD~1" # Fallback zum letzten Commit, falls kein Main-Branch gefunden wird
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
main_branch = "HEAD~1" # Fallback, falls gar kein Branch gefunden wird
|
|
||||||
|
|
||||||
# Git log --pretty
|
|
||||||
commit_log_cmd = ["git", "log", "--pretty=format:- %s", f"{main_branch}...HEAD"]
|
|
||||||
commit_messages = subprocess.check_output(commit_log_cmd).decode("utf-8").strip()
|
|
||||||
|
|
||||||
return "", commit_messages
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
print(f"❌ FEHLER beim Generieren der Git-Zusammenfassung: {e}")
|
|
||||||
return "", ""
|
|
||||||
|
|
||||||
def git_push_with_retry() -> bool:
|
def git_push_with_retry() -> bool:
|
||||||
"""Versucht, Änderungen zu pushen, und führt bei einem non-fast-forward-Fehler einen Rebase und erneuten Push durch."""
|
"""Versucht, Änderungen zu pushen, und führt bei einem non-fast-forward-Fehler einen Rebase und erneuten Push durch."""
|
||||||
print("\n--- Führe git push aus ---")
|
print("\n--- Führe git push aus ---")
|
||||||
@@ -527,7 +505,9 @@ def report_status_to_notion(
|
|||||||
session_data = json.load(f)
|
session_data = json.load(f)
|
||||||
task_id = session_data.get("task_id")
|
task_id = session_data.get("task_id")
|
||||||
token = session_data.get("token")
|
token = session_data.get("token")
|
||||||
readme_path = session_data.get("readme_path", "readme.md") # Lade den Readme-Pfad
|
readme_path = session_data.get("readme_path") # Lade den Readme-Pfad
|
||||||
|
if readme_path is None:
|
||||||
|
readme_path = "readme.md"
|
||||||
|
|
||||||
if not (task_id and token):
|
if not (task_id and token):
|
||||||
print("❌ FEHLER: Session-Daten unvollständig. Kann keinen Statusbericht erstellen.")
|
print("❌ FEHLER: Session-Daten unvollständig. Kann keinen Statusbericht erstellen.")
|
||||||
@@ -560,22 +540,13 @@ def report_status_to_notion(
|
|||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
print(f"❌ FEHLER beim Abrufen der Task-Details für die Zeiterfassung: {e}")
|
print(f"❌ FEHLER beim Abrufen der Task-Details für die Zeiterfassung: {e}")
|
||||||
|
|
||||||
print(f"--- Erstelle automatischen Statusbericht für Task {task_id} ---")
|
print(f"--- Erstelle Statusbericht für Task {task_id} ---")
|
||||||
|
|
||||||
# Git-Zusammenfassung generieren
|
|
||||||
print("Generiere Git-Zusammenfassung...")
|
|
||||||
_, commit_log = generate_git_summary()
|
|
||||||
actual_commit_messages = commit_log
|
|
||||||
|
|
||||||
# Summary automatisch aus Commit-Nachrichten erstellen
|
|
||||||
actual_summary = summary_override or "Keine Zusammenfassung angegeben."
|
actual_summary = summary_override or "Keine Zusammenfassung angegeben."
|
||||||
if not summary_override:
|
|
||||||
_, commit_log = generate_git_summary()
|
# Bessere Lesbarkeit für Notion durch explizite Zeilenumbrüche vor nummerierten Listen
|
||||||
summary_from_commits = commit_log.replace("- ", "✦ ").strip()
|
# Formatiert " 1. " zu einem Zeilenumbruch und einer Einrückung
|
||||||
if summary_from_commits:
|
formatted_summary = re.sub(r'\s+(\d+\.)\s', r'\n\n \1 ', actual_summary)
|
||||||
actual_summary = summary_from_commits
|
|
||||||
else:
|
|
||||||
actual_summary = "Keine neuen Commits in dieser Session."
|
|
||||||
|
|
||||||
# Kommentar zusammenstellen
|
# Kommentar zusammenstellen
|
||||||
report_lines = []
|
report_lines = []
|
||||||
@@ -584,7 +555,7 @@ def report_status_to_notion(
|
|||||||
report_lines.append(f"Investierte Zeit in dieser Session: {elapsed_hhmm}")
|
report_lines.append(f"Investierte Zeit in dieser Session: {elapsed_hhmm}")
|
||||||
|
|
||||||
report_lines.append("\nArbeitszusammenfassung:")
|
report_lines.append("\nArbeitszusammenfassung:")
|
||||||
report_lines.append(actual_summary)
|
report_lines.append(formatted_summary)
|
||||||
|
|
||||||
report_content = "\n".join(report_lines)
|
report_content = "\n".join(report_lines)
|
||||||
|
|
||||||
@@ -598,6 +569,19 @@ def report_status_to_notion(
|
|||||||
# Notion aktualisieren (nur Kommentar/Block, kein Status)
|
# Notion aktualisieren (nur Kommentar/Block, kein Status)
|
||||||
append_blocks_to_notion_page(token, task_id, notion_blocks)
|
append_blocks_to_notion_page(token, task_id, notion_blocks)
|
||||||
|
|
||||||
|
# Update der Readme.md Datei
|
||||||
|
if readme_path and os.path.exists(readme_path):
|
||||||
|
print(f"Hänge Status-Update an {readme_path} an...")
|
||||||
|
try:
|
||||||
|
with open(readme_path, "a", encoding="utf-8") as rf:
|
||||||
|
rf.write(f"\n\n## 🤖 Status-Update ({timestamp} Berlin Time)\n")
|
||||||
|
rf.write(f"```yaml\n{report_content}\n```\n")
|
||||||
|
print(f"✅ Status-Update an '{readme_path}' angehängt.")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ FEHLER beim Anhängen an '{readme_path}': {e}")
|
||||||
|
else:
|
||||||
|
print(f"⚠️ Readme-Pfad '{readme_path}' nicht gefunden. Überspringe lokales Doku-Update.")
|
||||||
|
|
||||||
# --- Doku & Git Operationen ---
|
# --- Doku & Git Operationen ---
|
||||||
print("\n--- Führe Git-Operationen aus ---")
|
print("\n--- Führe Git-Operationen aus ---")
|
||||||
try:
|
try:
|
||||||
@@ -652,7 +636,8 @@ def generate_cli_context(project_title: str, task_title: str, task_id: str, read
|
|||||||
description_part = ""
|
description_part = ""
|
||||||
if task_description:
|
if task_description:
|
||||||
description_part = (
|
description_part = (
|
||||||
f"\n**Aufgabenbeschreibung:**\n"
|
f"\n**Aufgabenbeschreibung (inkl. Historie):**\n"
|
||||||
|
f"*(Hinweis: Bei längeren Tasks befinden sich die aktuellsten und relevantesten Status-Updates am Ende dieser Beschreibung. Ursprüngliche Probleme sind möglicherweise bereits gelöst. Priorisiere immer die jüngsten Informationen!)*\n"
|
||||||
f"```\n{task_description}\n```\n"
|
f"```\n{task_description}\n```\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -748,30 +733,37 @@ def start_interactive_session():
|
|||||||
print("Kein Token angegeben. Abbruch.")
|
print("Kein Token angegeben. Abbruch.")
|
||||||
return
|
return
|
||||||
|
|
||||||
selected_project, readme_path = select_project(token)
|
while True:
|
||||||
if not selected_project:
|
selected_project, readme_path = select_project(token)
|
||||||
return
|
if not selected_project:
|
||||||
|
|
||||||
project_title = get_page_title(selected_project)
|
|
||||||
print(f"\nProjekt '{project_title}' ausgewählt.")
|
|
||||||
|
|
||||||
tasks_db_id = find_database_by_title(token, "Tasks [UT]")
|
|
||||||
if not tasks_db_id:
|
|
||||||
return
|
|
||||||
|
|
||||||
user_choice = select_task(token, selected_project["id"], tasks_db_id)
|
|
||||||
|
|
||||||
if not user_choice:
|
|
||||||
print("Kein Task ausgewählt. Abbruch.")
|
|
||||||
return
|
|
||||||
|
|
||||||
selected_task = None
|
|
||||||
if user_choice.get("id") == "new_task":
|
|
||||||
selected_task = create_new_notion_task(token, selected_project["id"], tasks_db_id)
|
|
||||||
if not selected_task:
|
|
||||||
return
|
return
|
||||||
else:
|
|
||||||
selected_task = user_choice
|
project_title = get_page_title(selected_project)
|
||||||
|
print(f"\nProjekt '{project_title}' ausgewählt.")
|
||||||
|
|
||||||
|
tasks_db_id = find_database_by_title(token, "Tasks [UT]")
|
||||||
|
if not tasks_db_id:
|
||||||
|
return
|
||||||
|
|
||||||
|
user_choice = select_task(token, selected_project["id"], tasks_db_id)
|
||||||
|
|
||||||
|
if not user_choice:
|
||||||
|
print("Kein Task ausgewählt. Abbruch.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if user_choice.get("id") == "go_back":
|
||||||
|
print("\nGehe zurück zur Projektauswahl...")
|
||||||
|
continue
|
||||||
|
|
||||||
|
selected_task = None
|
||||||
|
if user_choice.get("id") == "new_task":
|
||||||
|
selected_task = create_new_notion_task(token, selected_project["id"], tasks_db_id)
|
||||||
|
if not selected_task:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
selected_task = user_choice
|
||||||
|
|
||||||
|
break # Exit the loop once a valid task is selected
|
||||||
|
|
||||||
task_title = get_page_title(selected_task)
|
task_title = get_page_title(selected_task)
|
||||||
task_id = selected_task["id"]
|
task_id = selected_task["id"]
|
||||||
|
|||||||
58
docker-compose.ce-v2.yml
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# TEMPORARY DOCKER-COMPOSE FOR STARTING COMPANY-EXPLORER - V2
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
# --- GATEKEEPER (NGINX) ---
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: gateway_proxy
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8090:80"
|
||||||
|
volumes:
|
||||||
|
- ./nginx-proxy-ce.conf:/etc/nginx/nginx.conf:ro # Use the cleaned config
|
||||||
|
- ./.htpasswd:/etc/nginx/.htpasswd:ro
|
||||||
|
depends_on:
|
||||||
|
dashboard:
|
||||||
|
condition: service_started
|
||||||
|
company-explorer:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
# --- DASHBOARD ---
|
||||||
|
dashboard:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: dashboard
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./dashboard:/usr/share/nginx/html:ro
|
||||||
|
|
||||||
|
# --- APPS ---
|
||||||
|
company-explorer:
|
||||||
|
build:
|
||||||
|
context: ./company-explorer
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: company-explorer
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8000:8000"
|
||||||
|
environment:
|
||||||
|
API_USER: "admin"
|
||||||
|
API_PASSWORD: "gemini"
|
||||||
|
PYTHONUNBUFFERED: "1"
|
||||||
|
DATABASE_URL: "sqlite:////data/companies_v3_fixed_2.db"
|
||||||
|
GEMINI_API_KEY: "${GEMINI_API_KEY}"
|
||||||
|
SERP_API_KEY: "${SERP_API}"
|
||||||
|
NOTION_TOKEN: "${NOTION_API_KEY}"
|
||||||
|
volumes:
|
||||||
|
- ./company-explorer:/app
|
||||||
|
- explorer_db_data:/data
|
||||||
|
- ./Log_from_docker:/app/logs_debug
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8000/docs"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
explorer_db_data: {}
|
||||||
66
docker-compose.ce.yml
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
# TEMPORARY DOCKER-COMPOSE FOR STARTING COMPANY-EXPLORER
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
# --- GATEKEEPER (NGINX) ---
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: gateway_proxy
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8090:80"
|
||||||
|
volumes:
|
||||||
|
- ./nginx-proxy-clean.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
- ./.htpasswd:/etc/nginx/.htpasswd:ro
|
||||||
|
depends_on:
|
||||||
|
dashboard:
|
||||||
|
condition: service_started
|
||||||
|
company-explorer:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
# --- DASHBOARD ---
|
||||||
|
dashboard:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: dashboard
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./dashboard:/usr/share/nginx/html:ro
|
||||||
|
|
||||||
|
# --- APPS ---
|
||||||
|
company-explorer:
|
||||||
|
build:
|
||||||
|
context: ./company-explorer
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: company-explorer
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8000:8000"
|
||||||
|
environment:
|
||||||
|
API_USER: "admin"
|
||||||
|
API_PASSWORD: "gemini"
|
||||||
|
PYTHONUNBUFFERED: "1"
|
||||||
|
DATABASE_URL: "sqlite:////data/companies_v3_fixed_2.db"
|
||||||
|
GEMINI_API_KEY: "${GEMINI_API_KEY}"
|
||||||
|
SERP_API_KEY: "${SERP_API}"
|
||||||
|
NOTION_TOKEN: "${NOTION_API_KEY}"
|
||||||
|
volumes:
|
||||||
|
- ./company-explorer:/app
|
||||||
|
- explorer_db_data:/data
|
||||||
|
- ./Log_from_docker:/app/logs_debug
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8000/docs"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
connector_db_data: {}
|
||||||
|
explorer_db_data: {}
|
||||||
|
lead_engine_data: {}
|
||||||
|
gtm_architect_data: {}
|
||||||
|
b2b_marketing_data: {}
|
||||||
|
transcription_uploads: {}
|
||||||
|
content_engine_data: {}
|
||||||
|
competitor_analysis_data: {}
|
||||||
|
market_intel_data: {}
|
||||||
96
docker-compose.minimal.yml
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
# --- GATEKEEPER (NGINX) ---
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: gateway_proxy
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8090:80"
|
||||||
|
volumes:
|
||||||
|
- ./nginx-proxy.minimal.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
- ./.htpasswd:/etc/nginx/.htpasswd:ro
|
||||||
|
depends_on:
|
||||||
|
company-explorer:
|
||||||
|
condition: service_healthy
|
||||||
|
lead-engine:
|
||||||
|
condition: service_started
|
||||||
|
transcription-tool:
|
||||||
|
condition: service_started
|
||||||
|
|
||||||
|
# --- APPS ---
|
||||||
|
company-explorer:
|
||||||
|
build:
|
||||||
|
context: ./company-explorer
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: company-explorer
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8000:8000"
|
||||||
|
environment:
|
||||||
|
API_USER: "admin"
|
||||||
|
API_PASSWORD: "gemini"
|
||||||
|
PYTHONUNBUFFERED: "1"
|
||||||
|
DATABASE_URL: "sqlite:////data/companies_v3_fixed_2.db"
|
||||||
|
GEMINI_API_KEY: "${GEMINI_API_KEY}"
|
||||||
|
SERP_API_KEY: "${SERP_API}"
|
||||||
|
NOTION_TOKEN: "${NOTION_API_KEY}"
|
||||||
|
volumes:
|
||||||
|
- ./company-explorer:/app
|
||||||
|
- explorer_db_data:/data
|
||||||
|
- ./Log_from_docker:/app/logs_debug
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8000/docs"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
|
||||||
|
lead-engine:
|
||||||
|
build:
|
||||||
|
context: ./lead-engine
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: lead-engine
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8501:8501" # UI (Streamlit)
|
||||||
|
- "8004:8004" # API / Monitor
|
||||||
|
- "8099:8004" # Direct Test Port
|
||||||
|
environment:
|
||||||
|
PYTHONUNBUFFERED: "1"
|
||||||
|
GEMINI_API_KEY: "${GEMINI_API_KEY}"
|
||||||
|
SERP_API: "${SERP_API}"
|
||||||
|
INFO_Application_ID: "${INFO_Application_ID}"
|
||||||
|
INFO_Tenant_ID: "${INFO_Tenant_ID}"
|
||||||
|
INFO_Secret: "${INFO_Secret}"
|
||||||
|
CAL_APPID: "${CAL_APPID}"
|
||||||
|
CAL_SECRET: "${CAL_SECRET}"
|
||||||
|
CAL_TENNANT_ID: "${CAL_TENNANT_ID}"
|
||||||
|
TEAMS_WEBHOOK_URL: "${TEAMS_WEBHOOK_URL}"
|
||||||
|
FEEDBACK_SERVER_BASE_URL: "${FEEDBACK_SERVER_BASE_URL}"
|
||||||
|
WORDPRESS_BOOKING_URL: "${WORDPRESS_BOOKING_URL}"
|
||||||
|
MS_BOOKINGS_URL: "${MS_BOOKINGS_URL}"
|
||||||
|
volumes:
|
||||||
|
- ./lead-engine:/app
|
||||||
|
- lead_engine_data:/app/data
|
||||||
|
|
||||||
|
transcription-tool:
|
||||||
|
build:
|
||||||
|
context: ./transcription-tool
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: transcription-tool
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8001:8001"
|
||||||
|
environment:
|
||||||
|
GEMINI_API_KEY: "${GEMINI_API_KEY}"
|
||||||
|
UPLOAD_DIR: "/app/uploads"
|
||||||
|
volumes:
|
||||||
|
- transcription_uploads:/app/uploads
|
||||||
|
- ./Log_from_docker:/app/logs_debug
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
explorer_db_data: {}
|
||||||
|
lead_engine_data: {}
|
||||||
|
transcription_uploads: {}
|
||||||
11
docker-compose.test-override.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
nginx:
|
||||||
|
depends_on:
|
||||||
|
dashboard:
|
||||||
|
condition: service_started
|
||||||
|
company-explorer:
|
||||||
|
condition: service_healthy
|
||||||
|
lead-engine:
|
||||||
|
condition: service_started
|
||||||
89
docker-compose.test.yml
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
# --- GATEKEEPER (NGINX) ---
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: gateway_proxy
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8090:80"
|
||||||
|
volumes:
|
||||||
|
- ./nginx-proxy-test.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
- ./.htpasswd:/etc/nginx/.htpasswd:ro
|
||||||
|
depends_on:
|
||||||
|
dashboard:
|
||||||
|
condition: service_started
|
||||||
|
company-explorer:
|
||||||
|
condition: service_healthy
|
||||||
|
lead-engine:
|
||||||
|
condition: service_started
|
||||||
|
|
||||||
|
# --- DASHBOARD (Required by Nginx) ---
|
||||||
|
dashboard:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: dashboard
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./dashboard:/usr/share/nginx/html:ro
|
||||||
|
|
||||||
|
# --- COMPANY-EXPLORER (Required by Lead-Engine) ---
|
||||||
|
company-explorer:
|
||||||
|
build:
|
||||||
|
context: ./company-explorer
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: company-explorer
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8000:8000"
|
||||||
|
environment:
|
||||||
|
API_USER: "admin"
|
||||||
|
API_PASSWORD: "gemini"
|
||||||
|
PYTHONUNBUFFERED: "1"
|
||||||
|
DATABASE_URL: "sqlite:////data/companies_v3_fixed_2.db"
|
||||||
|
GEMINI_API_KEY: "${GEMINI_API_KEY}"
|
||||||
|
SERP_API_KEY: "${SERP_API}"
|
||||||
|
NOTION_TOKEN: "${NOTION_API_KEY}"
|
||||||
|
volumes:
|
||||||
|
- ./company-explorer:/app
|
||||||
|
- explorer_db_data:/data
|
||||||
|
- ./Log_from_docker:/app/logs_debug
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8000/docs"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
|
||||||
|
# --- LEAD-ENGINE (Our Webhook Service) ---
|
||||||
|
lead-engine:
|
||||||
|
build:
|
||||||
|
context: ./lead-engine
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: lead-engine
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8501:8501" # UI (Streamlit)
|
||||||
|
- "8004:8004" # API / Monitor
|
||||||
|
- "8099:8004" # Direct Test Port
|
||||||
|
environment:
|
||||||
|
PYTHONUNBUFFERED: "1"
|
||||||
|
GEMINI_API_KEY: "${GEMINI_API_KEY}"
|
||||||
|
SERP_API: "${SERP_API}"
|
||||||
|
INFO_Application_ID: "${INFO_Application_ID}"
|
||||||
|
INFO_Tenant_ID: "${INFO_Tenant_ID}"
|
||||||
|
INFO_Secret: "${INFO_Secret}"
|
||||||
|
CAL_APPID: "${CAL_APPID}"
|
||||||
|
CAL_SECRET: "${CAL_SECRET}"
|
||||||
|
CAL_TENNANT_ID: "${CAL_TENNANT_ID}"
|
||||||
|
TEAMS_WEBHOOK_URL: "${TEAMS_WEBHOOK_URL}"
|
||||||
|
FEEDBACK_SERVER_BASE_URL: "${FEEDBACK_SERVER_BASE_URL}"
|
||||||
|
WORDPRESS_BOOKING_URL: "${WORDPRESS_BOOKING_URL}"
|
||||||
|
MS_BOOKINGS_URL: "${MS_BOOKINGS_URL}"
|
||||||
|
volumes:
|
||||||
|
- ./lead-engine:/app
|
||||||
|
- lead_engine_data:/app/data
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
explorer_db_data: {}
|
||||||
|
lead_engine_data: {}
|
||||||
20
docker-compose.tr.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
transcription-tool:
|
||||||
|
build:
|
||||||
|
context: ./transcription-tool
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: transcription-tool-standalone
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "8001:8001"
|
||||||
|
environment:
|
||||||
|
GEMINI_API_KEY: "${GEMINI_API_KEY}"
|
||||||
|
UPLOAD_DIR: "/app/uploads"
|
||||||
|
volumes:
|
||||||
|
- transcription_uploads:/app/uploads
|
||||||
|
- ./Log_from_docker:/app/logs_debug
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
transcription_uploads: {}
|
||||||
@@ -188,7 +188,7 @@ services:
|
|||||||
NOTION_TOKEN: "${NOTION_API_KEY}"
|
NOTION_TOKEN: "${NOTION_API_KEY}"
|
||||||
volumes:
|
volumes:
|
||||||
- ./company-explorer:/app
|
- ./company-explorer:/app
|
||||||
- explorer_db_data:/data
|
- ./company-explorer/data:/data # Local bind mount for guaranteed persistence
|
||||||
- ./Log_from_docker:/app/logs_debug
|
- ./Log_from_docker:/app/logs_debug
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8000/docs"]
|
test: ["CMD", "curl", "-f", "http://localhost:8000/docs"]
|
||||||
@@ -207,7 +207,7 @@ services:
|
|||||||
- "8003:8000"
|
- "8003:8000"
|
||||||
volumes:
|
volumes:
|
||||||
- ./connector-superoffice:/app
|
- ./connector-superoffice:/app
|
||||||
- connector_db_data:/data
|
- ./connector-superoffice/data:/data # Persistent local DB storage
|
||||||
environment:
|
environment:
|
||||||
PYTHONUNBUFFERED: "1"
|
PYTHONUNBUFFERED: "1"
|
||||||
GEMINI_API_KEY: "${GEMINI_API_KEY}"
|
GEMINI_API_KEY: "${GEMINI_API_KEY}"
|
||||||
@@ -251,15 +251,12 @@ services:
|
|||||||
MS_BOOKINGS_URL: "${MS_BOOKINGS_URL}"
|
MS_BOOKINGS_URL: "${MS_BOOKINGS_URL}"
|
||||||
volumes:
|
volumes:
|
||||||
- ./lead-engine:/app
|
- ./lead-engine:/app
|
||||||
- lead_engine_data:/app/data
|
- ./lead-engine/data:/app/data # Local persistent database
|
||||||
|
|
||||||
# --- INFRASTRUCTURE SERVICES ---
|
# --- INFRASTRUCTURE SERVICES ---
|
||||||
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
connector_db_data: {}
|
|
||||||
explorer_db_data: {}
|
|
||||||
lead_engine_data: {}
|
|
||||||
gtm_architect_data: {}
|
gtm_architect_data: {}
|
||||||
b2b_marketing_data: {}
|
b2b_marketing_data: {}
|
||||||
transcription_uploads: {}
|
transcription_uploads: {}
|
||||||
|
|||||||
BIN
error_get_jobs_list_error_20260320_162957.png
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
error_get_jobs_list_error_20260320_163832.png
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
error_login_error_20260320_145427.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
error_login_error_20260320_150231.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
error_login_error_20260320_151103.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
error_login_error_20260320_151426.png
Normal file
|
After Width: | Height: | Size: 185 KiB |
60
fotograf-de-scraper/README.md
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# Fotograf.de Scraper & Management UI
|
||||||
|
|
||||||
|
**Status:** Production-Ready Microservice (Core Feature: PDF List Generation, QR Cards & Shooting Schedule)
|
||||||
|
|
||||||
|
Dieser Service modernisiert die alten `Fotograf.de` Skripte, indem er eine robuste, web-basierte UI zur Verwaltung und Automatisierung von Foto-Aufträgen bereitstellt. Er ist als eigenständiger Microservice konzipiert, der unabhängig vom Haupt-Stack läuft.
|
||||||
|
|
||||||
|
## 🏗️ Architektur
|
||||||
|
|
||||||
|
Der Service besteht aus zwei Hauptkomponenten:
|
||||||
|
|
||||||
|
1. **Backend (Python / FastAPI / Selenium / SQLAlchemy):**
|
||||||
|
* **Automatisierung:** Nutzt Selenium für das Scraping von `fotograf.de`.
|
||||||
|
* **Persistenz:** Eine SQLite-Datenbank (`fotograf_jobs.db`) speichert die Auftragsliste, sodass langsame Scraping-Vorgänge nur bei Bedarf (Refresh) nötig sind.
|
||||||
|
* **PDF-Engine:** Nutzt WeasyPrint für Teilnehmerlisten und ReportLab/PyPDF2 für präzise PDF-Overlays (QR-Karten).
|
||||||
|
* **API-Integration:** Direkte Anbindung an die **Calendly API (v2)** zum Abruf von Live-Buchungsdaten.
|
||||||
|
|
||||||
|
2. **Frontend (TypeScript / React / Vite / TailwindCSS):**
|
||||||
|
* **Modernes UI:** Ein vollständig responsives Dashboard mit Tailwind CSS (Kachel-Layout, Tabs für Kiga/Schule).
|
||||||
|
* **Arbeitsfluss:** Tools sind direkt in der Detailansicht des jeweiligen Auftrags integriert (Shooting-Planung).
|
||||||
|
|
||||||
|
## ✨ Core Features
|
||||||
|
|
||||||
|
### Feature 1: Teilnehmerlisten (Vollständig)
|
||||||
|
Automatisierter Workflow zum Download und Formatieren der Anmeldelisten von `fotograf.de` als sortiertes PDF (Klassen/Gruppen) inkl. "Kinderfotos Erding" Branding.
|
||||||
|
|
||||||
|
### Feature 2: Shooting-Planung (QR-Karten & Terminliste)
|
||||||
|
Spezielles Modul für Familien-Mini-Shootings, direkt integriert in die Auftragsdetails:
|
||||||
|
* **Dynamische Event-Auswahl:** Wähle direkt aus deinen Calendly-Event-Typen (z.B. "Neuching") aus.
|
||||||
|
* **QR-Karten-Andruck:**
|
||||||
|
* Präzises Overlay von Name, Kinderanzahl und Uhrzeit auf vorbereitete QR-Code-Bögen.
|
||||||
|
* **Korrektur:** Y-Achse um 9mm nach unten verschoben für perfekten Sitz auf den Linien.
|
||||||
|
* **Einwilligungs-Checkbox (☑):** Automatischer Andruck eines Häkchens, wenn in Calendly der Veröffentlichung zugestimmt wurde.
|
||||||
|
* **Termin-Übersichtsliste (Neu):**
|
||||||
|
* Generiert eine A4-Tabelle für den Shooting-Tag.
|
||||||
|
* **6-Minuten-Takt:** Erzeugt automatisch ein Raster basierend auf dem ersten und letzten Termin, füllt Lücken für nicht gebuchte Slots leer auf.
|
||||||
|
* Inklusive Spalten für Name, Kinder, Veröffentlichungs-Status und einer Checkbox zum manuellen Abhaken.
|
||||||
|
|
||||||
|
### Feature 3: Nachfass-E-Mails (Geplant)
|
||||||
|
* Identifizierung von Käufern/Nicht-Käufern zur Generierung von CSV-Listen für den Supermailer.
|
||||||
|
|
||||||
|
### Feature 4: Verkaufs-Statistiken (Vollständig)
|
||||||
|
* Detaillierte Analyse des Kaufverhaltens pro Album mit Echtzeit-Fortschrittsanzeige im Browser.
|
||||||
|
|
||||||
|
## 🛠️ Technische Details & Fixes (März 2026)
|
||||||
|
* **Zeitzonen:** Automatische Konversion von Calendly-UTC-Zeiten in die lokale Zeit (`Europe/Berlin`).
|
||||||
|
* **Pagination Fix:** Das Backend blättert nun durch alle Calendly-Seiten, um sicherzustellen, dass keine Buchungen (auch bei großen Event-Historien) übersehen werden.
|
||||||
|
* **Logo-Integration:** Dynamisches Einbetten des Firmenlogos in alle generierten Dokumente.
|
||||||
|
|
||||||
|
## 🚀 Deployment & Konfiguration
|
||||||
|
|
||||||
|
Der Service wird über eine eigene `docker-compose.yml` im Unterverzeichnis gestartet.
|
||||||
|
|
||||||
|
### Umgebungsvariablen (`.env`)
|
||||||
|
Folgende Variablen müssen in der `.env` im Verzeichnis `/fotograf-de-scraper/` definiert sein:
|
||||||
|
* `KIGA_USER` / `KIGA_PW` / `SCHULE_USER` / `SCHULE_PW`: Logins.
|
||||||
|
* `CALENDLY_TOKEN`: Personal Access Token (JWT) von Calendly.
|
||||||
|
|
||||||
|
### URLs & Ports
|
||||||
|
* **Frontend:** `http://<HOST_IP>:3009` | **Backend:** `http://<HOST_IP>:8002`
|
||||||
|
* **Persistenz:** Datenbank unter `./backend/data/fotograf_jobs.db`.
|
||||||
56
fotograf-de-scraper/backend/Dockerfile
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Use an official Python runtime as a parent image
|
||||||
|
FROM python:3.11-slim-bookworm
|
||||||
|
|
||||||
|
# Set the working directory in the container
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install system dependencies for Chrome and other tools
|
||||||
|
# Using a multi-stage build or a more specific base image could optimize this
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
chromium-driver \
|
||||||
|
chromium \
|
||||||
|
wget \
|
||||||
|
unzip \
|
||||||
|
fonts-liberation \
|
||||||
|
fontconfig \
|
||||||
|
libappindicator3-1 \
|
||||||
|
libasound2 \
|
||||||
|
libatk-bridge2.0-0 \
|
||||||
|
libcups2 \
|
||||||
|
libdrm-dev \
|
||||||
|
libgbm-dev \
|
||||||
|
libglvnd0 \
|
||||||
|
libgtk-3-0 \
|
||||||
|
libnspr4 \
|
||||||
|
libnss3 \
|
||||||
|
libxkbcommon0 \
|
||||||
|
libxshmfence-dev \
|
||||||
|
xdg-utils \
|
||||||
|
build-essential \
|
||||||
|
libcairo2 \
|
||||||
|
libpango-1.0-0 \
|
||||||
|
libpangocairo-1.0-0 \
|
||||||
|
libgdk-pixbuf-2.0-0 \
|
||||||
|
libffi-dev \
|
||||||
|
shared-mime-info \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Set Chromium as default browser for Selenium
|
||||||
|
ENV CHROME_BIN /usr/bin/chromium
|
||||||
|
ENV CHROME_PATH /usr/bin/chromium
|
||||||
|
|
||||||
|
# Copy the requirements file and install Python dependencies
|
||||||
|
COPY requirements.txt ./requirements.txt
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Copy the application code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Create directory for error screenshots
|
||||||
|
RUN mkdir -p /app/errors && chmod 777 /app/errors
|
||||||
|
|
||||||
|
# Expose the port FastAPI will run on
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
# Command to run the application with DEBUG logging
|
||||||
|
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--log-level", "debug"]
|
||||||
BIN
fotograf-de-scraper/backend/assets/OpenSans-Regular.ttf
Normal file
BIN
fotograf-de-scraper/backend/assets/logo.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
fotograf-de-scraper/backend/data/blank.pdf
Normal file
32
fotograf-de-scraper/backend/database.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
from sqlalchemy import create_engine, Column, Integer, String, DateTime
|
||||||
|
from sqlalchemy.orm import declarative_base, sessionmaker
|
||||||
|
import datetime
|
||||||
|
import os
|
||||||
|
|
||||||
|
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:////app/data/fotograf_jobs.db")
|
||||||
|
|
||||||
|
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
|
||||||
|
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||||
|
|
||||||
|
Base = declarative_base()
|
||||||
|
|
||||||
|
class Job(Base):
|
||||||
|
__tablename__ = "jobs"
|
||||||
|
|
||||||
|
id = Column(String, primary_key=True, index=True)
|
||||||
|
name = Column(String, index=True)
|
||||||
|
url = Column(String)
|
||||||
|
status = Column(String)
|
||||||
|
date = Column(String)
|
||||||
|
shooting_type = Column(String)
|
||||||
|
account_type = Column(String, index=True) # 'kiga' or 'schule'
|
||||||
|
last_updated = Column(DateTime, default=datetime.datetime.utcnow)
|
||||||
|
|
||||||
|
Base.metadata.create_all(bind=engine)
|
||||||
|
|
||||||
|
def get_db():
|
||||||
|
db = SessionLocal()
|
||||||
|
try:
|
||||||
|
yield db
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
68
fotograf-de-scraper/backend/debug_scraper.py
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import os
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
# We import directly from main to reuse the already configured functions
|
||||||
|
from main import setup_driver, login, get_jobs_list
|
||||||
|
|
||||||
|
def run_debug():
|
||||||
|
"""
|
||||||
|
Runs the scraper logic directly for debugging purposes inside the container.
|
||||||
|
"""
|
||||||
|
load_dotenv()
|
||||||
|
print("--- Starting Standalone Scraper Debug ---")
|
||||||
|
|
||||||
|
# --- Configuration ---
|
||||||
|
# Change this to 'schule' to test the other account
|
||||||
|
ACCOUNT_TO_TEST = "kiga"
|
||||||
|
|
||||||
|
username = os.getenv(f"{ACCOUNT_TO_TEST.upper()}_USER")
|
||||||
|
password = os.getenv(f"{ACCOUNT_TO_TEST.upper()}_PW")
|
||||||
|
|
||||||
|
if not username or not password:
|
||||||
|
print(f"!!! FATAL ERROR: Credentials for {ACCOUNT_TO_TEST} not found in .env file.")
|
||||||
|
print("Please ensure KIGA_USER, KIGA_PW, etc. are set correctly.")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"Attempting to log in with user: {username}")
|
||||||
|
|
||||||
|
driver = None
|
||||||
|
try:
|
||||||
|
driver = setup_driver()
|
||||||
|
if not driver:
|
||||||
|
print("!!! FATAL ERROR: WebDriver initialization failed.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Perform the login
|
||||||
|
if login(driver, username, password):
|
||||||
|
print("\n✅ LOGIN SUCCESSFUL!")
|
||||||
|
print("-----------------------------------------")
|
||||||
|
print("Now attempting to fetch jobs from the dashboard...")
|
||||||
|
|
||||||
|
# Fetch the jobs
|
||||||
|
jobs = get_jobs_list(driver)
|
||||||
|
|
||||||
|
if jobs:
|
||||||
|
print(f"\n✅ SUCCESS: Found {len(jobs)} jobs!")
|
||||||
|
for i, job in enumerate(jobs):
|
||||||
|
print(f" {i+1}. Name: {job['name']}")
|
||||||
|
print(f" Status: {job['status']}")
|
||||||
|
print(f" Date: {job['date']}")
|
||||||
|
else:
|
||||||
|
print("\n⚠️ WARNING: Login seemed successful, but no jobs were found on the dashboard.")
|
||||||
|
print("This could be due to incorrect page selectors for the job list.")
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("\n❌ LOGIN FAILED.")
|
||||||
|
print("Please check credentials in .env and the login selectors in main.py.")
|
||||||
|
print("A screenshot of the error might have been saved if the scraper has permission.")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\n\n!!! AN UNEXPECTED ERROR OCCURRED: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
finally:
|
||||||
|
if driver:
|
||||||
|
print("\n--- Debug script finished. Closing WebDriver. ---")
|
||||||
|
driver.quit()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run_debug()
|
||||||
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 185 KiB |
1037
fotograf-de-scraper/backend/main.py
Normal file
283
fotograf-de-scraper/backend/qr_generator.py
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
import os
|
||||||
|
import requests
|
||||||
|
import io
|
||||||
|
import datetime
|
||||||
|
from reportlab.pdfgen import canvas
|
||||||
|
from reportlab.lib.pagesizes import A4
|
||||||
|
from reportlab.pdfbase import pdfmetrics
|
||||||
|
from reportlab.pdfbase.ttfonts import TTFont
|
||||||
|
from PyPDF2 import PdfReader, PdfWriter
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger("qr-card-generator")
|
||||||
|
|
||||||
|
def get_calendly_event_types(api_token: str):
|
||||||
|
"""
|
||||||
|
Fetches available event types for the current user.
|
||||||
|
"""
|
||||||
|
headers = {
|
||||||
|
'Authorization': f'Bearer {api_token}',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1. Get current user info
|
||||||
|
user_url = "https://api.calendly.com/users/me"
|
||||||
|
user_response = requests.get(user_url, headers=headers)
|
||||||
|
if not user_response.ok:
|
||||||
|
raise Exception(f"Calendly API Error: {user_response.status_code}")
|
||||||
|
|
||||||
|
user_data = user_response.json()
|
||||||
|
user_uri = user_data['resource']['uri']
|
||||||
|
|
||||||
|
# 2. Get event types
|
||||||
|
event_types_url = "https://api.calendly.com/event_types"
|
||||||
|
params = {
|
||||||
|
'user': user_uri
|
||||||
|
}
|
||||||
|
|
||||||
|
types_response = requests.get(event_types_url, headers=headers, params=params)
|
||||||
|
if not types_response.ok:
|
||||||
|
raise Exception(f"Calendly API Error: {types_response.status_code}")
|
||||||
|
|
||||||
|
types_data = types_response.json()
|
||||||
|
return types_data['collection']
|
||||||
|
|
||||||
|
def get_calendly_events_raw(api_token: str, start_time: str = None, end_time: str = None, event_type_name: str = None):
|
||||||
|
"""
|
||||||
|
Debug function to fetch raw Calendly data without formatting.
|
||||||
|
"""
|
||||||
|
headers = {
|
||||||
|
'Authorization': f'Bearer {api_token}',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Defaults: 2024 to +2 years (broad range to ensure we capture all relevant upcoming)
|
||||||
|
if not start_time:
|
||||||
|
start_time = "2024-01-01T00:00:00Z"
|
||||||
|
if not end_time:
|
||||||
|
end_time = (datetime.datetime.utcnow() + datetime.timedelta(days=730)).isoformat() + "Z"
|
||||||
|
|
||||||
|
# 1. Get current user info to get the user URI
|
||||||
|
user_url = "https://api.calendly.com/users/me"
|
||||||
|
user_response = requests.get(user_url, headers=headers)
|
||||||
|
if not user_response.ok:
|
||||||
|
raise Exception(f"Calendly API Error: {user_response.status_code}")
|
||||||
|
|
||||||
|
user_data = user_response.json()
|
||||||
|
user_uri = user_data['resource']['uri']
|
||||||
|
|
||||||
|
# 2. Get events for the user
|
||||||
|
events_url = "https://api.calendly.com/scheduled_events"
|
||||||
|
params = {
|
||||||
|
'user': user_uri,
|
||||||
|
'status': 'active',
|
||||||
|
'min_start_time': start_time,
|
||||||
|
'max_start_time': end_time,
|
||||||
|
'count': 100
|
||||||
|
}
|
||||||
|
|
||||||
|
all_events = []
|
||||||
|
url = events_url
|
||||||
|
|
||||||
|
while url:
|
||||||
|
if url == events_url:
|
||||||
|
response = requests.get(url, headers=headers, params=params)
|
||||||
|
else:
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
|
||||||
|
if not response.ok:
|
||||||
|
raise Exception(f"Calendly API Error: {response.status_code} - {response.text}")
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
all_events.extend(data.get('collection', []))
|
||||||
|
|
||||||
|
pagination = data.get('pagination', {})
|
||||||
|
url = pagination.get('next_page') # Use the full URL provided by Calendly
|
||||||
|
|
||||||
|
raw_results = []
|
||||||
|
|
||||||
|
# 3. Get invitees
|
||||||
|
for event in all_events:
|
||||||
|
event_name = event.get('name', '')
|
||||||
|
# Filter by event type if provided
|
||||||
|
if event_type_name and event_type_name.lower() not in event_name.lower():
|
||||||
|
continue
|
||||||
|
|
||||||
|
event_uri = event['uri']
|
||||||
|
event_uuid = event_uri.split('/')[-1]
|
||||||
|
invitees_url = f"https://api.calendly.com/scheduled_events/{event_uuid}/invitees"
|
||||||
|
|
||||||
|
invitees_response = requests.get(invitees_url, headers=headers)
|
||||||
|
if not invitees_response.ok:
|
||||||
|
continue
|
||||||
|
|
||||||
|
invitees_data = invitees_response.json()
|
||||||
|
|
||||||
|
for invitee in invitees_data['collection']:
|
||||||
|
raw_results.append({
|
||||||
|
"event_name": event_name,
|
||||||
|
"start_time": event['start_time'],
|
||||||
|
"invitee_name": invitee['name'],
|
||||||
|
"invitee_email": invitee['email'],
|
||||||
|
"questions_and_answers": invitee.get('questions_and_answers', [])
|
||||||
|
})
|
||||||
|
|
||||||
|
return raw_results
|
||||||
|
|
||||||
|
def get_calendly_events(api_token: str, start_time: str = None, end_time: str = None, event_type_name: str = None):
|
||||||
|
"""
|
||||||
|
Fetches events from Calendly API for the current user within a time range.
|
||||||
|
"""
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
|
raw_data = get_calendly_events_raw(api_token, start_time, end_time, event_type_name)
|
||||||
|
formatted_data = []
|
||||||
|
|
||||||
|
for item in raw_data:
|
||||||
|
# Parse start time from UTC
|
||||||
|
start_dt = datetime.datetime.fromisoformat(item['start_time'].replace('Z', '+00:00'))
|
||||||
|
# Convert to Europe/Berlin (CET/CEST)
|
||||||
|
start_dt = start_dt.astimezone(ZoneInfo("Europe/Berlin"))
|
||||||
|
# Format as HH:MM
|
||||||
|
time_str = start_dt.strftime('%H:%M')
|
||||||
|
|
||||||
|
name = item['invitee_name']
|
||||||
|
|
||||||
|
# Extract specific answers from the Calendly form
|
||||||
|
num_children = ""
|
||||||
|
additional_notes = ""
|
||||||
|
has_consent = False
|
||||||
|
questions_and_answers = item.get('questions_and_answers', [])
|
||||||
|
|
||||||
|
|
||||||
|
for q_a in questions_and_answers:
|
||||||
|
q_text = q_a.get('question', '').lower()
|
||||||
|
a_text = q_a.get('answer', '')
|
||||||
|
|
||||||
|
# Flexible matching for number of children
|
||||||
|
if any(kw in q_text for kw in ["wie viele kinder", "anzahl kinder", "wieviele kinder"]):
|
||||||
|
num_children = a_text
|
||||||
|
elif "nachricht" in q_text or "anmerkung" in q_text:
|
||||||
|
additional_notes = a_text
|
||||||
|
elif "veröffentlichen" in q_text or "bilder" in q_text:
|
||||||
|
if "ja" in a_text.lower():
|
||||||
|
has_consent = True
|
||||||
|
|
||||||
|
|
||||||
|
# Construct the final string: "Name, X Kinder // HH:MM Uhr ☑"
|
||||||
|
final_text = f"{name}"
|
||||||
|
if num_children:
|
||||||
|
final_text += f", {num_children}"
|
||||||
|
|
||||||
|
final_text += f" // {time_str} Uhr"
|
||||||
|
|
||||||
|
if additional_notes:
|
||||||
|
final_text += f" ({additional_notes})"
|
||||||
|
|
||||||
|
if has_consent:
|
||||||
|
final_text += " ☑"
|
||||||
|
|
||||||
|
formatted_data.append(final_text)
|
||||||
|
|
||||||
|
|
||||||
|
logger.info(f"Processed {len(formatted_data)} invitees.")
|
||||||
|
return formatted_data
|
||||||
|
|
||||||
|
|
||||||
|
def overlay_text_on_pdf(base_pdf_path: str, output_pdf_path: str, texts: list):
|
||||||
|
"""
|
||||||
|
Target:
|
||||||
|
Element 1: X: 72mm, Y: 22mm + 9mm = 31mm
|
||||||
|
Element 2: X: 72mm, Y: 171mm + 9mm = 180mm
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Convert mm to points (1 mm = 2.83465 points)
|
||||||
|
mm_to_pt = 2.83465
|
||||||
|
|
||||||
|
# A4 dimensions in points (approx 595.27 x 841.89)
|
||||||
|
page_width, page_height = A4
|
||||||
|
|
||||||
|
# User coordinates are from top-left.
|
||||||
|
# ReportLab uses bottom-left as (0,0).
|
||||||
|
# Element 1 (Top): X = 72mm, Y = 31mm (from top) -> Y = page_height - 31mm
|
||||||
|
# Element 2 (Bottom): X = 72mm, Y = 180mm (from top) -> Y = page_height - 180mm
|
||||||
|
|
||||||
|
x_pos = 72 * mm_to_pt
|
||||||
|
y_pos_1 = page_height - (31 * mm_to_pt)
|
||||||
|
y_pos_2 = page_height - (180 * mm_to_pt)
|
||||||
|
|
||||||
|
reader = PdfReader(base_pdf_path)
|
||||||
|
writer = PdfWriter()
|
||||||
|
|
||||||
|
total_pages = len(reader.pages)
|
||||||
|
max_capacity = total_pages * 2
|
||||||
|
|
||||||
|
if len(texts) > max_capacity:
|
||||||
|
logger.warning(f"Not enough pages in base PDF. Have {len(texts)} invitees but only space for {max_capacity}. Truncating.")
|
||||||
|
texts = texts[:max_capacity]
|
||||||
|
|
||||||
|
# We need to process pairs of texts for each page
|
||||||
|
text_pairs = [texts[i:i+2] for i in range(0, len(texts), 2)]
|
||||||
|
|
||||||
|
|
||||||
|
# Load OpenSans font to support UTF-8 extended characters
|
||||||
|
from reportlab.pdfbase.ttfonts import TTFont
|
||||||
|
from reportlab.pdfbase import pdfmetrics
|
||||||
|
font_path = os.path.join(os.path.dirname(__file__), "assets", "OpenSans-Regular.ttf")
|
||||||
|
pdfmetrics.registerFont(TTFont('OpenSans', font_path))
|
||||||
|
|
||||||
|
for page_idx, pair in enumerate(text_pairs):
|
||||||
|
if page_idx >= total_pages:
|
||||||
|
break # Safety first
|
||||||
|
|
||||||
|
# Create a new blank page in memory to draw the text
|
||||||
|
packet = io.BytesIO()
|
||||||
|
can = canvas.Canvas(packet, pagesize=A4)
|
||||||
|
|
||||||
|
# Draw the text.
|
||||||
|
def draw_text_with_checkbox(can, x, y, text):
|
||||||
|
can.setFont("OpenSans", 12)
|
||||||
|
if text.endswith(" ☑"):
|
||||||
|
clean_text = text[:-2] # remove the checkmark part
|
||||||
|
can.drawString(x, y, clean_text)
|
||||||
|
|
||||||
|
# Calculate width to place the checkbox right after the text
|
||||||
|
text_width = can.stringWidth(clean_text, "OpenSans", 12)
|
||||||
|
box_x = x + text_width + 8
|
||||||
|
|
||||||
|
size = 10
|
||||||
|
can.rect(box_x, y - 1, size, size)
|
||||||
|
can.setLineWidth(1.5)
|
||||||
|
can.line(box_x + 2, y + 3, box_x + 4.5, y + 0.5)
|
||||||
|
can.line(box_x + 4.5, y + 0.5, box_x + 8.5, y + 7)
|
||||||
|
can.setLineWidth(1)
|
||||||
|
else:
|
||||||
|
can.drawString(x, y, text)
|
||||||
|
|
||||||
|
if len(pair) > 0:
|
||||||
|
|
||||||
|
draw_text_with_checkbox(can, x_pos, y_pos_1, pair[0])
|
||||||
|
if len(pair) > 1:
|
||||||
|
draw_text_with_checkbox(can, x_pos, y_pos_2, pair[1])
|
||||||
|
|
||||||
|
can.save()
|
||||||
|
packet.seek(0)
|
||||||
|
|
||||||
|
# Read the text PDF we just created
|
||||||
|
new_pdf = PdfReader(packet)
|
||||||
|
text_page = new_pdf.pages[0]
|
||||||
|
|
||||||
|
# Get the specific page from the original PDF
|
||||||
|
page_to_merge = reader.pages[page_idx]
|
||||||
|
page_to_merge.merge_page(text_page)
|
||||||
|
|
||||||
|
writer.add_page(page_to_merge)
|
||||||
|
|
||||||
|
# If there are pages left in the base PDF that we didn't use, append them too?
|
||||||
|
# Usually you'd want to keep them or discard them. We'll discard unused pages for now
|
||||||
|
# to avoid empty cards, or you can change this loop to include them.
|
||||||
|
|
||||||
|
with open(output_pdf_path, "wb") as output_file:
|
||||||
|
writer.write(output_file)
|
||||||
|
|
||||||
|
logger.info(f"Successfully generated overlaid PDF at {output_pdf_path}")
|
||||||
13
fotograf-de-scraper/backend/requirements.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
fastapi==0.111.0
|
||||||
|
uvicorn==0.30.1
|
||||||
|
python-dotenv==1.0.1
|
||||||
|
selenium==4.22.0
|
||||||
|
webdriver-manager==4.0.1
|
||||||
|
pandas==2.2.2
|
||||||
|
weasyprint==62.1
|
||||||
|
jinja2==3.1.4
|
||||||
|
pydyf==0.10.0
|
||||||
|
sqlalchemy==2.0.31
|
||||||
|
requests==2.31.0
|
||||||
|
reportlab==4.0.9
|
||||||
|
PyPDF2==3.0.1
|
||||||
202
fotograf-de-scraper/backend/templates/appointment_list.html
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Terminübersicht</title>
|
||||||
|
<style>
|
||||||
|
@page {
|
||||||
|
size: A4 portrait;
|
||||||
|
margin: 20mm;
|
||||||
|
@bottom-right {
|
||||||
|
content: "Seite " counter(page) " von " counter(pages);
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
font-size: 10pt;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
font-size: 11pt;
|
||||||
|
color: #333;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
border-bottom: 2px solid #ddd;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.header-text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.header-logo {
|
||||||
|
width: 150px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.header-logo img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 16pt;
|
||||||
|
margin: 0 0 5px 0;
|
||||||
|
color: #2c3e50;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 14pt;
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
color: #34495e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-header {
|
||||||
|
background-color: #ecf0f1;
|
||||||
|
padding: 8px 12px;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 13pt;
|
||||||
|
border-left: 4px solid #3498db;
|
||||||
|
page-break-before: always;
|
||||||
|
}
|
||||||
|
.first-date-header {
|
||||||
|
page-break-before: avoid;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
page-break-inside: auto;
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
border: 1px solid #bdc3c7;
|
||||||
|
padding: 6px 8px; /* Narrower rows */
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.empty-row td {
|
||||||
|
height: 25px; /* Narrower empty rows */
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
.compressed-row td {
|
||||||
|
background-color: #fcfcfc;
|
||||||
|
color: #7f8c8d !important;
|
||||||
|
font-style: italic;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.time-col { width: 14%; white-space: nowrap; font-weight: bold; }
|
||||||
|
.family-col { width: 33%; }
|
||||||
|
|
||||||
|
.children-col { width: 15%; text-align: center; }
|
||||||
|
.consent-col { width: 20%; text-align: center; }
|
||||||
|
.done-col { width: 18%; text-align: center; }
|
||||||
|
|
||||||
|
.empty-row td {
|
||||||
|
height: 35px; /* ensure enough space for writing */
|
||||||
|
color: transparent; /* visually hide "Empty" text but keep structure if any */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* CSS Checkmark (Ja) */
|
||||||
|
.consent-yes {
|
||||||
|
display: inline-block;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border: 2px solid #333;
|
||||||
|
border-radius: 3px;
|
||||||
|
position: relative;
|
||||||
|
background-color: #fcfcfc;
|
||||||
|
}
|
||||||
|
.consent-yes::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 4px;
|
||||||
|
top: 0px;
|
||||||
|
width: 5px;
|
||||||
|
height: 10px;
|
||||||
|
border: solid #27ae60;
|
||||||
|
border-width: 0 3px 3px 0;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
/* The checkbox square */
|
||||||
|
.checkbox-square {
|
||||||
|
display: inline-block;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border: 1px solid #333;
|
||||||
|
background-color: #fff;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
{% for date, slots in grouped_slots.items() %}
|
||||||
|
|
||||||
|
{% if not loop.first %}
|
||||||
|
<div style="page-break-before: always;"></div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="header">
|
||||||
|
<div class="header-text">
|
||||||
|
<h1>{{ event_type_name }}</h1>
|
||||||
|
<p>Auftrag: {{ job_name }} | Stand: {{ current_time }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="header-logo">
|
||||||
|
{% if logo_base64 %}
|
||||||
|
<img src="data:image/png;base64,{{ logo_base64 }}" alt="Logo">
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="date-header first-date-header">{{ date }}</div>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="time-col">Uhrzeit</th>
|
||||||
|
<th class="family-col">Familie</th>
|
||||||
|
<th class="children-col">Kinder</th>
|
||||||
|
<th class="consent-col">Veröffentlichung</th>
|
||||||
|
<th class="done-col">Erledigt</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for slot in slots %}
|
||||||
|
{% if slot.is_compressed %}
|
||||||
|
<tr class="compressed-row">
|
||||||
|
<td class="time-col" style="color: #7f8c8d;">{{ slot.time_str }}</td>
|
||||||
|
<td colspan="4">{{ slot.name }}</td>
|
||||||
|
</tr>
|
||||||
|
{% else %}
|
||||||
|
<tr class="{% if not slot.booked %}empty-row{% endif %}">
|
||||||
|
<td class="time-col" style="color: #333;">{{ slot.time_str }}</td>
|
||||||
|
<td class="family-col">{{ slot.name if slot.booked else '' }}</td>
|
||||||
|
<td class="children-col">{{ slot.children if slot.booked else '' }}</td>
|
||||||
|
<td class="consent-col">
|
||||||
|
|
||||||
|
{% if slot.booked and slot.consent %}
|
||||||
|
<span class="consent-yes"></span>
|
||||||
|
|
||||||
|
{% elif slot.booked %}
|
||||||
|
<!-- nein -->
|
||||||
|
{% else %}
|
||||||
|
<!-- leer -->
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="done-col">
|
||||||
|
{% if slot.booked %}
|
||||||
|
<span class="checkbox-square"></span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endfor %}
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
62
fotograf-de-scraper/backend/templates/school_list.html
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html><head><meta charset="utf-8"><style>
|
||||||
|
@page { size: A4 portrait; margin: 20mm; }
|
||||||
|
body { font-family: Arial, sans-serif; font-size: 11pt; }
|
||||||
|
.header { margin-bottom: 20px; }
|
||||||
|
.institution-name { font-weight: bold; font-size: 14pt; }
|
||||||
|
.date-info { font-size: 12pt; }
|
||||||
|
.summary { margin-top: 30px; }
|
||||||
|
.summary h2 { font-size: 12pt; font-weight: normal; margin-bottom: 10px; }
|
||||||
|
.summary-table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
|
||||||
|
.summary-table td { padding: 4px 0; }
|
||||||
|
.summary-total { margin-top: 10px; border-top: 1px solid black; padding-top: 10px; font-weight: bold; }
|
||||||
|
.class-section { page-break-before: always; }
|
||||||
|
.student-table { width: 100%; border-collapse: collapse; margin-top: 30px; }
|
||||||
|
.student-table th { text-align: left; border-bottom: 1px solid black; padding-bottom: 5px; font-weight: normal; }
|
||||||
|
.student-table td { padding: 5px 0; }
|
||||||
|
.class-summary { margin-top: 30px; font-weight: bold; }
|
||||||
|
.class-note { margin-top: 20px; font-size: 10pt; }
|
||||||
|
.footer { position: fixed; bottom: 0; left: 0; right: 0; display: flex; justify-content: space-between; font-size: 10pt; }
|
||||||
|
.footer-left { text-align: left; }
|
||||||
|
.footer-right { text-align: right; }
|
||||||
|
</style></head><body>
|
||||||
|
<div class="header" style="display: flex; justify-content: space-between; align-items: center;">
|
||||||
|
<div>
|
||||||
|
<div class="institution-name">{{ institution }}</div>
|
||||||
|
<div class="date-info">{{ date_info }}</div>
|
||||||
|
</div>
|
||||||
|
{% if logo_base64 %}
|
||||||
|
<div>
|
||||||
|
<img src="data:image/png;base64,{{ logo_base64 }}" alt="Logo" style="max-height: 60px;">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="summary"><h2>Übersicht der Anmeldungen:</h2><table class="summary-table">
|
||||||
|
{% for count in class_counts %}
|
||||||
|
<tr><td style="width: 50%;">{{ group_label }} {{ count.name }}</td><td>{{ count.count }} Anmeldungen</td></tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table><div class="summary-total">Gesamt: {{ total_students }} Anmeldungen</div></div>
|
||||||
|
{% for class_info in class_data %}
|
||||||
|
<div class="class-section">
|
||||||
|
<div class="header" style="display: flex; justify-content: space-between; align-items: center;">
|
||||||
|
<div>
|
||||||
|
<div class="institution-name">{{ institution }}</div>
|
||||||
|
<div class="date-info">{{ date_info }}</div>
|
||||||
|
</div>
|
||||||
|
{% if logo_base64 %}
|
||||||
|
<div>
|
||||||
|
<img src="data:image/png;base64,{{ logo_base64 }}" alt="Logo" style="max-height: 60px;">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<table class="student-table"><thead><tr><th style="width: 40%">Nachname</th><th style="width: 40%">Vorname</th><th style="width: 20%">{{ group_label }}</th></tr></thead><tbody>
|
||||||
|
{% for student in class_info.students %}
|
||||||
|
<tr><td>{{ student.Nachname }}</td><td>{{ student.Vorname }}</td><td>{{ student[group_column_name] }}</td></tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody></table>
|
||||||
|
<div class="class-summary">{{ class_info.students|length }} angemeldete {{ person_label_plural }}</div>
|
||||||
|
<div class="class-note">Dies ist die Liste der bereits angemeldeten {{ person_label_plural }}. Bitte die noch fehlenden<br>{{ person_label_plural }} an die Anmeldung erinnern.</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
<div class="footer"><div class="footer-left">Stand {{ current_time }}</div><div class="footer-right">Kinderfotos Erding<br>Gartenstr. 10 85445 Oberding<br>www.kinderfotos-erding.de<br>08122-8470867</div></div>
|
||||||
|
</body></html>
|
||||||
BIN
fotograf-de-scraper/blank.pdf
Normal file
30
fotograf-de-scraper/docker-compose.yml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
fotograf-de-scraper-backend:
|
||||||
|
build:
|
||||||
|
context: ./backend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: fotograf-de-scraper-backend
|
||||||
|
env_file:
|
||||||
|
- ./.env
|
||||||
|
ports:
|
||||||
|
- "8002:8000" # Map internal 8000 to external 8002 to avoid conflicts
|
||||||
|
volumes:
|
||||||
|
- ./backend:/app # Mount the backend code for easier development
|
||||||
|
- ./backend/data:/app/data # Persistent data storage
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
fotograf-de-scraper-frontend:
|
||||||
|
build:
|
||||||
|
context: ./frontend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: fotograf-de-scraper-frontend
|
||||||
|
ports:
|
||||||
|
- "3009:80" # Map internal 80 to external 3009
|
||||||
|
depends_on:
|
||||||
|
- fotograf-de-scraper-backend
|
||||||
|
volumes:
|
||||||
|
- ./frontend:/app # Mount the frontend code for easier development
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
34
fotograf-de-scraper/frontend/Dockerfile
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Stage 1: Build the React application
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package.json and package-lock.json
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Copy the rest of the application source code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build the application
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Stage 2: Serve the application with Nginx
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /usr/share/nginx/html
|
||||||
|
|
||||||
|
# Remove default Nginx assets
|
||||||
|
RUN rm -rf ./*
|
||||||
|
|
||||||
|
# Copy built assets from the builder stage
|
||||||
|
COPY --from=builder /app/dist .
|
||||||
|
|
||||||
|
# Expose port 80
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# Start Nginx
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
73
fotograf-de-scraper/frontend/README.md
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# React + TypeScript + Vite
|
||||||
|
|
||||||
|
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||||
|
|
||||||
|
Currently, two official plugins are available:
|
||||||
|
|
||||||
|
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
|
||||||
|
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
|
||||||
|
|
||||||
|
## React Compiler
|
||||||
|
|
||||||
|
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
|
||||||
|
|
||||||
|
## Expanding the ESLint configuration
|
||||||
|
|
||||||
|
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default defineConfig([
|
||||||
|
globalIgnores(['dist']),
|
||||||
|
{
|
||||||
|
files: ['**/*.{ts,tsx}'],
|
||||||
|
extends: [
|
||||||
|
// Other configs...
|
||||||
|
|
||||||
|
// Remove tseslint.configs.recommended and replace with this
|
||||||
|
tseslint.configs.recommendedTypeChecked,
|
||||||
|
// Alternatively, use this for stricter rules
|
||||||
|
tseslint.configs.strictTypeChecked,
|
||||||
|
// Optionally, add this for stylistic rules
|
||||||
|
tseslint.configs.stylisticTypeChecked,
|
||||||
|
|
||||||
|
// Other configs...
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
// other options...
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// eslint.config.js
|
||||||
|
import reactX from 'eslint-plugin-react-x'
|
||||||
|
import reactDom from 'eslint-plugin-react-dom'
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
globalIgnores(['dist']),
|
||||||
|
{
|
||||||
|
files: ['**/*.{ts,tsx}'],
|
||||||
|
extends: [
|
||||||
|
// Other configs...
|
||||||
|
// Enable lint rules for React
|
||||||
|
reactX.configs['recommended-typescript'],
|
||||||
|
// Enable lint rules for React DOM
|
||||||
|
reactDom.configs.recommended,
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
// other options...
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
```
|
||||||
23
fotograf-de-scraper/frontend/eslint.config.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import js from '@eslint/js'
|
||||||
|
import globals from 'globals'
|
||||||
|
import reactHooks from 'eslint-plugin-react-hooks'
|
||||||
|
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||||
|
import tseslint from 'typescript-eslint'
|
||||||
|
import { defineConfig, globalIgnores } from 'eslint/config'
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
globalIgnores(['dist']),
|
||||||
|
{
|
||||||
|
files: ['**/*.{ts,tsx}'],
|
||||||
|
extends: [
|
||||||
|
js.configs.recommended,
|
||||||
|
tseslint.configs.recommended,
|
||||||
|
reactHooks.configs.flat.recommended,
|
||||||
|
reactRefresh.configs.vite,
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
globals: globals.browser,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
13
fotograf-de-scraper/frontend/index.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>frontend</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/acorn
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../acorn/bin/acorn
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/autoprefixer
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../autoprefixer/bin/autoprefixer
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/baseline-browser-mapping
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../baseline-browser-mapping/dist/cli.cjs
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/browserslist
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../browserslist/cli.js
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/cssesc
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cssesc/bin/cssesc
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/eslint
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../eslint/bin/eslint.js
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/jiti
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../jiti/bin/jiti.js
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/js-yaml
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../js-yaml/bin/js-yaml.js
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/jsesc
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../jsesc/bin/jsesc
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/json5
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../json5/lib/cli.js
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/nanoid
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../nanoid/bin/nanoid.cjs
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/node-which
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../which/bin/node-which
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/parser
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../@babel/parser/bin/babel-parser.js
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/resolve
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../resolve/bin/resolve
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/rolldown
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../rolldown/bin/cli.mjs
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/semver
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../semver/bin/semver.js
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/sucrase
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../sucrase/bin/sucrase
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/sucrase-node
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../sucrase/bin/sucrase-node
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/tailwind
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../tailwindcss/lib/cli.js
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/tailwindcss
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../tailwindcss/lib/cli.js
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/tsc
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../typescript/bin/tsc
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/tsserver
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../typescript/bin/tsserver
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/update-browserslist-db
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../update-browserslist-db/cli.js
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.bin/vite
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../vite/bin/vite.js
|
||||||
3
fotograf-de-scraper/frontend/node_modules/.vite/deps/package.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"type": "module"
|
||||||
|
}
|
||||||
770
fotograf-de-scraper/frontend/node_modules/.vite/deps/react-Na5-BvaJ.js
generated
vendored
Normal file
@@ -0,0 +1,770 @@
|
|||||||
|
//#region \0rolldown/runtime.js
|
||||||
|
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
||||||
|
//#endregion
|
||||||
|
//#region node_modules/react/cjs/react.development.js
|
||||||
|
/**
|
||||||
|
* @license React
|
||||||
|
* react.development.js
|
||||||
|
*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
var require_react_development = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
||||||
|
(function() {
|
||||||
|
function defineDeprecationWarning(methodName, info) {
|
||||||
|
Object.defineProperty(Component.prototype, methodName, { get: function() {
|
||||||
|
console.warn("%s(...) is deprecated in plain JavaScript React classes. %s", info[0], info[1]);
|
||||||
|
} });
|
||||||
|
}
|
||||||
|
function getIteratorFn(maybeIterable) {
|
||||||
|
if (null === maybeIterable || "object" !== typeof maybeIterable) return null;
|
||||||
|
maybeIterable = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable["@@iterator"];
|
||||||
|
return "function" === typeof maybeIterable ? maybeIterable : null;
|
||||||
|
}
|
||||||
|
function warnNoop(publicInstance, callerName) {
|
||||||
|
publicInstance = (publicInstance = publicInstance.constructor) && (publicInstance.displayName || publicInstance.name) || "ReactClass";
|
||||||
|
var warningKey = publicInstance + "." + callerName;
|
||||||
|
didWarnStateUpdateForUnmountedComponent[warningKey] || (console.error("Can't call %s on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = {};` class property with the desired state in the %s component.", callerName, publicInstance), didWarnStateUpdateForUnmountedComponent[warningKey] = !0);
|
||||||
|
}
|
||||||
|
function Component(props, context, updater) {
|
||||||
|
this.props = props;
|
||||||
|
this.context = context;
|
||||||
|
this.refs = emptyObject;
|
||||||
|
this.updater = updater || ReactNoopUpdateQueue;
|
||||||
|
}
|
||||||
|
function ComponentDummy() {}
|
||||||
|
function PureComponent(props, context, updater) {
|
||||||
|
this.props = props;
|
||||||
|
this.context = context;
|
||||||
|
this.refs = emptyObject;
|
||||||
|
this.updater = updater || ReactNoopUpdateQueue;
|
||||||
|
}
|
||||||
|
function noop() {}
|
||||||
|
function testStringCoercion(value) {
|
||||||
|
return "" + value;
|
||||||
|
}
|
||||||
|
function checkKeyStringCoercion(value) {
|
||||||
|
try {
|
||||||
|
testStringCoercion(value);
|
||||||
|
var JSCompiler_inline_result = !1;
|
||||||
|
} catch (e) {
|
||||||
|
JSCompiler_inline_result = !0;
|
||||||
|
}
|
||||||
|
if (JSCompiler_inline_result) {
|
||||||
|
JSCompiler_inline_result = console;
|
||||||
|
var JSCompiler_temp_const = JSCompiler_inline_result.error;
|
||||||
|
var JSCompiler_inline_result$jscomp$0 = "function" === typeof Symbol && Symbol.toStringTag && value[Symbol.toStringTag] || value.constructor.name || "Object";
|
||||||
|
JSCompiler_temp_const.call(JSCompiler_inline_result, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", JSCompiler_inline_result$jscomp$0);
|
||||||
|
return testStringCoercion(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getComponentNameFromType(type) {
|
||||||
|
if (null == type) return null;
|
||||||
|
if ("function" === typeof type) return type.$$typeof === REACT_CLIENT_REFERENCE ? null : type.displayName || type.name || null;
|
||||||
|
if ("string" === typeof type) return type;
|
||||||
|
switch (type) {
|
||||||
|
case REACT_FRAGMENT_TYPE: return "Fragment";
|
||||||
|
case REACT_PROFILER_TYPE: return "Profiler";
|
||||||
|
case REACT_STRICT_MODE_TYPE: return "StrictMode";
|
||||||
|
case REACT_SUSPENSE_TYPE: return "Suspense";
|
||||||
|
case REACT_SUSPENSE_LIST_TYPE: return "SuspenseList";
|
||||||
|
case REACT_ACTIVITY_TYPE: return "Activity";
|
||||||
|
}
|
||||||
|
if ("object" === typeof type) switch ("number" === typeof type.tag && console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), type.$$typeof) {
|
||||||
|
case REACT_PORTAL_TYPE: return "Portal";
|
||||||
|
case REACT_CONTEXT_TYPE: return type.displayName || "Context";
|
||||||
|
case REACT_CONSUMER_TYPE: return (type._context.displayName || "Context") + ".Consumer";
|
||||||
|
case REACT_FORWARD_REF_TYPE:
|
||||||
|
var innerType = type.render;
|
||||||
|
type = type.displayName;
|
||||||
|
type || (type = innerType.displayName || innerType.name || "", type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef");
|
||||||
|
return type;
|
||||||
|
case REACT_MEMO_TYPE: return innerType = type.displayName || null, null !== innerType ? innerType : getComponentNameFromType(type.type) || "Memo";
|
||||||
|
case REACT_LAZY_TYPE:
|
||||||
|
innerType = type._payload;
|
||||||
|
type = type._init;
|
||||||
|
try {
|
||||||
|
return getComponentNameFromType(type(innerType));
|
||||||
|
} catch (x) {}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function getTaskName(type) {
|
||||||
|
if (type === REACT_FRAGMENT_TYPE) return "<>";
|
||||||
|
if ("object" === typeof type && null !== type && type.$$typeof === REACT_LAZY_TYPE) return "<...>";
|
||||||
|
try {
|
||||||
|
var name = getComponentNameFromType(type);
|
||||||
|
return name ? "<" + name + ">" : "<...>";
|
||||||
|
} catch (x) {
|
||||||
|
return "<...>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getOwner() {
|
||||||
|
var dispatcher = ReactSharedInternals.A;
|
||||||
|
return null === dispatcher ? null : dispatcher.getOwner();
|
||||||
|
}
|
||||||
|
function UnknownOwner() {
|
||||||
|
return Error("react-stack-top-frame");
|
||||||
|
}
|
||||||
|
function hasValidKey(config) {
|
||||||
|
if (hasOwnProperty.call(config, "key")) {
|
||||||
|
var getter = Object.getOwnPropertyDescriptor(config, "key").get;
|
||||||
|
if (getter && getter.isReactWarning) return !1;
|
||||||
|
}
|
||||||
|
return void 0 !== config.key;
|
||||||
|
}
|
||||||
|
function defineKeyPropWarningGetter(props, displayName) {
|
||||||
|
function warnAboutAccessingKey() {
|
||||||
|
specialPropKeyWarningShown || (specialPropKeyWarningShown = !0, console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", displayName));
|
||||||
|
}
|
||||||
|
warnAboutAccessingKey.isReactWarning = !0;
|
||||||
|
Object.defineProperty(props, "key", {
|
||||||
|
get: warnAboutAccessingKey,
|
||||||
|
configurable: !0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function elementRefGetterWithDeprecationWarning() {
|
||||||
|
var componentName = getComponentNameFromType(this.type);
|
||||||
|
didWarnAboutElementRef[componentName] || (didWarnAboutElementRef[componentName] = !0, console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."));
|
||||||
|
componentName = this.props.ref;
|
||||||
|
return void 0 !== componentName ? componentName : null;
|
||||||
|
}
|
||||||
|
function ReactElement(type, key, props, owner, debugStack, debugTask) {
|
||||||
|
var refProp = props.ref;
|
||||||
|
type = {
|
||||||
|
$$typeof: REACT_ELEMENT_TYPE,
|
||||||
|
type,
|
||||||
|
key,
|
||||||
|
props,
|
||||||
|
_owner: owner
|
||||||
|
};
|
||||||
|
null !== (void 0 !== refProp ? refProp : null) ? Object.defineProperty(type, "ref", {
|
||||||
|
enumerable: !1,
|
||||||
|
get: elementRefGetterWithDeprecationWarning
|
||||||
|
}) : Object.defineProperty(type, "ref", {
|
||||||
|
enumerable: !1,
|
||||||
|
value: null
|
||||||
|
});
|
||||||
|
type._store = {};
|
||||||
|
Object.defineProperty(type._store, "validated", {
|
||||||
|
configurable: !1,
|
||||||
|
enumerable: !1,
|
||||||
|
writable: !0,
|
||||||
|
value: 0
|
||||||
|
});
|
||||||
|
Object.defineProperty(type, "_debugInfo", {
|
||||||
|
configurable: !1,
|
||||||
|
enumerable: !1,
|
||||||
|
writable: !0,
|
||||||
|
value: null
|
||||||
|
});
|
||||||
|
Object.defineProperty(type, "_debugStack", {
|
||||||
|
configurable: !1,
|
||||||
|
enumerable: !1,
|
||||||
|
writable: !0,
|
||||||
|
value: debugStack
|
||||||
|
});
|
||||||
|
Object.defineProperty(type, "_debugTask", {
|
||||||
|
configurable: !1,
|
||||||
|
enumerable: !1,
|
||||||
|
writable: !0,
|
||||||
|
value: debugTask
|
||||||
|
});
|
||||||
|
Object.freeze && (Object.freeze(type.props), Object.freeze(type));
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
function cloneAndReplaceKey(oldElement, newKey) {
|
||||||
|
newKey = ReactElement(oldElement.type, newKey, oldElement.props, oldElement._owner, oldElement._debugStack, oldElement._debugTask);
|
||||||
|
oldElement._store && (newKey._store.validated = oldElement._store.validated);
|
||||||
|
return newKey;
|
||||||
|
}
|
||||||
|
function validateChildKeys(node) {
|
||||||
|
isValidElement(node) ? node._store && (node._store.validated = 1) : "object" === typeof node && null !== node && node.$$typeof === REACT_LAZY_TYPE && ("fulfilled" === node._payload.status ? isValidElement(node._payload.value) && node._payload.value._store && (node._payload.value._store.validated = 1) : node._store && (node._store.validated = 1));
|
||||||
|
}
|
||||||
|
function isValidElement(object) {
|
||||||
|
return "object" === typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
|
||||||
|
}
|
||||||
|
function escape(key) {
|
||||||
|
var escaperLookup = {
|
||||||
|
"=": "=0",
|
||||||
|
":": "=2"
|
||||||
|
};
|
||||||
|
return "$" + key.replace(/[=:]/g, function(match) {
|
||||||
|
return escaperLookup[match];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function getElementKey(element, index) {
|
||||||
|
return "object" === typeof element && null !== element && null != element.key ? (checkKeyStringCoercion(element.key), escape("" + element.key)) : index.toString(36);
|
||||||
|
}
|
||||||
|
function resolveThenable(thenable) {
|
||||||
|
switch (thenable.status) {
|
||||||
|
case "fulfilled": return thenable.value;
|
||||||
|
case "rejected": throw thenable.reason;
|
||||||
|
default: switch ("string" === typeof thenable.status ? thenable.then(noop, noop) : (thenable.status = "pending", thenable.then(function(fulfilledValue) {
|
||||||
|
"pending" === thenable.status && (thenable.status = "fulfilled", thenable.value = fulfilledValue);
|
||||||
|
}, function(error) {
|
||||||
|
"pending" === thenable.status && (thenable.status = "rejected", thenable.reason = error);
|
||||||
|
})), thenable.status) {
|
||||||
|
case "fulfilled": return thenable.value;
|
||||||
|
case "rejected": throw thenable.reason;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw thenable;
|
||||||
|
}
|
||||||
|
function mapIntoArray(children, array, escapedPrefix, nameSoFar, callback) {
|
||||||
|
var type = typeof children;
|
||||||
|
if ("undefined" === type || "boolean" === type) children = null;
|
||||||
|
var invokeCallback = !1;
|
||||||
|
if (null === children) invokeCallback = !0;
|
||||||
|
else switch (type) {
|
||||||
|
case "bigint":
|
||||||
|
case "string":
|
||||||
|
case "number":
|
||||||
|
invokeCallback = !0;
|
||||||
|
break;
|
||||||
|
case "object": switch (children.$$typeof) {
|
||||||
|
case REACT_ELEMENT_TYPE:
|
||||||
|
case REACT_PORTAL_TYPE:
|
||||||
|
invokeCallback = !0;
|
||||||
|
break;
|
||||||
|
case REACT_LAZY_TYPE: return invokeCallback = children._init, mapIntoArray(invokeCallback(children._payload), array, escapedPrefix, nameSoFar, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (invokeCallback) {
|
||||||
|
invokeCallback = children;
|
||||||
|
callback = callback(invokeCallback);
|
||||||
|
var childKey = "" === nameSoFar ? "." + getElementKey(invokeCallback, 0) : nameSoFar;
|
||||||
|
isArrayImpl(callback) ? (escapedPrefix = "", null != childKey && (escapedPrefix = childKey.replace(userProvidedKeyEscapeRegex, "$&/") + "/"), mapIntoArray(callback, array, escapedPrefix, "", function(c) {
|
||||||
|
return c;
|
||||||
|
})) : null != callback && (isValidElement(callback) && (null != callback.key && (invokeCallback && invokeCallback.key === callback.key || checkKeyStringCoercion(callback.key)), escapedPrefix = cloneAndReplaceKey(callback, escapedPrefix + (null == callback.key || invokeCallback && invokeCallback.key === callback.key ? "" : ("" + callback.key).replace(userProvidedKeyEscapeRegex, "$&/") + "/") + childKey), "" !== nameSoFar && null != invokeCallback && isValidElement(invokeCallback) && null == invokeCallback.key && invokeCallback._store && !invokeCallback._store.validated && (escapedPrefix._store.validated = 2), callback = escapedPrefix), array.push(callback));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
invokeCallback = 0;
|
||||||
|
childKey = "" === nameSoFar ? "." : nameSoFar + ":";
|
||||||
|
if (isArrayImpl(children)) for (var i = 0; i < children.length; i++) nameSoFar = children[i], type = childKey + getElementKey(nameSoFar, i), invokeCallback += mapIntoArray(nameSoFar, array, escapedPrefix, type, callback);
|
||||||
|
else if (i = getIteratorFn(children), "function" === typeof i) for (i === children.entries && (didWarnAboutMaps || console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."), didWarnAboutMaps = !0), children = i.call(children), i = 0; !(nameSoFar = children.next()).done;) nameSoFar = nameSoFar.value, type = childKey + getElementKey(nameSoFar, i++), invokeCallback += mapIntoArray(nameSoFar, array, escapedPrefix, type, callback);
|
||||||
|
else if ("object" === type) {
|
||||||
|
if ("function" === typeof children.then) return mapIntoArray(resolveThenable(children), array, escapedPrefix, nameSoFar, callback);
|
||||||
|
array = String(children);
|
||||||
|
throw Error("Objects are not valid as a React child (found: " + ("[object Object]" === array ? "object with keys {" + Object.keys(children).join(", ") + "}" : array) + "). If you meant to render a collection of children, use an array instead.");
|
||||||
|
}
|
||||||
|
return invokeCallback;
|
||||||
|
}
|
||||||
|
function mapChildren(children, func, context) {
|
||||||
|
if (null == children) return children;
|
||||||
|
var result = [], count = 0;
|
||||||
|
mapIntoArray(children, result, "", "", function(child) {
|
||||||
|
return func.call(context, child, count++);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function lazyInitializer(payload) {
|
||||||
|
if (-1 === payload._status) {
|
||||||
|
var ioInfo = payload._ioInfo;
|
||||||
|
null != ioInfo && (ioInfo.start = ioInfo.end = performance.now());
|
||||||
|
ioInfo = payload._result;
|
||||||
|
var thenable = ioInfo();
|
||||||
|
thenable.then(function(moduleObject) {
|
||||||
|
if (0 === payload._status || -1 === payload._status) {
|
||||||
|
payload._status = 1;
|
||||||
|
payload._result = moduleObject;
|
||||||
|
var _ioInfo = payload._ioInfo;
|
||||||
|
null != _ioInfo && (_ioInfo.end = performance.now());
|
||||||
|
void 0 === thenable.status && (thenable.status = "fulfilled", thenable.value = moduleObject);
|
||||||
|
}
|
||||||
|
}, function(error) {
|
||||||
|
if (0 === payload._status || -1 === payload._status) {
|
||||||
|
payload._status = 2;
|
||||||
|
payload._result = error;
|
||||||
|
var _ioInfo2 = payload._ioInfo;
|
||||||
|
null != _ioInfo2 && (_ioInfo2.end = performance.now());
|
||||||
|
void 0 === thenable.status && (thenable.status = "rejected", thenable.reason = error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ioInfo = payload._ioInfo;
|
||||||
|
if (null != ioInfo) {
|
||||||
|
ioInfo.value = thenable;
|
||||||
|
var displayName = thenable.displayName;
|
||||||
|
"string" === typeof displayName && (ioInfo.name = displayName);
|
||||||
|
}
|
||||||
|
-1 === payload._status && (payload._status = 0, payload._result = thenable);
|
||||||
|
}
|
||||||
|
if (1 === payload._status) return ioInfo = payload._result, void 0 === ioInfo && console.error("lazy: Expected the result of a dynamic import() call. Instead received: %s\n\nYour code should look like: \n const MyComponent = lazy(() => import('./MyComponent'))\n\nDid you accidentally put curly braces around the import?", ioInfo), "default" in ioInfo || console.error("lazy: Expected the result of a dynamic import() call. Instead received: %s\n\nYour code should look like: \n const MyComponent = lazy(() => import('./MyComponent'))", ioInfo), ioInfo.default;
|
||||||
|
throw payload._result;
|
||||||
|
}
|
||||||
|
function resolveDispatcher() {
|
||||||
|
var dispatcher = ReactSharedInternals.H;
|
||||||
|
null === dispatcher && console.error("Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.");
|
||||||
|
return dispatcher;
|
||||||
|
}
|
||||||
|
function releaseAsyncTransition() {
|
||||||
|
ReactSharedInternals.asyncTransitions--;
|
||||||
|
}
|
||||||
|
function enqueueTask(task) {
|
||||||
|
if (null === enqueueTaskImpl) try {
|
||||||
|
var requireString = ("require" + Math.random()).slice(0, 7);
|
||||||
|
enqueueTaskImpl = (module && module[requireString]).call(module, "timers").setImmediate;
|
||||||
|
} catch (_err) {
|
||||||
|
enqueueTaskImpl = function(callback) {
|
||||||
|
!1 === didWarnAboutMessageChannel && (didWarnAboutMessageChannel = !0, "undefined" === typeof MessageChannel && console.error("This browser does not have a MessageChannel implementation, so enqueuing tasks via await act(async () => ...) will fail. Please file an issue at https://github.com/facebook/react/issues if you encounter this warning."));
|
||||||
|
var channel = new MessageChannel();
|
||||||
|
channel.port1.onmessage = callback;
|
||||||
|
channel.port2.postMessage(void 0);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return enqueueTaskImpl(task);
|
||||||
|
}
|
||||||
|
function aggregateErrors(errors) {
|
||||||
|
return 1 < errors.length && "function" === typeof AggregateError ? new AggregateError(errors) : errors[0];
|
||||||
|
}
|
||||||
|
function popActScope(prevActQueue, prevActScopeDepth) {
|
||||||
|
prevActScopeDepth !== actScopeDepth - 1 && console.error("You seem to have overlapping act() calls, this is not supported. Be sure to await previous act() calls before making a new one. ");
|
||||||
|
actScopeDepth = prevActScopeDepth;
|
||||||
|
}
|
||||||
|
function recursivelyFlushAsyncActWork(returnValue, resolve, reject) {
|
||||||
|
var queue = ReactSharedInternals.actQueue;
|
||||||
|
if (null !== queue) if (0 !== queue.length) try {
|
||||||
|
flushActQueue(queue);
|
||||||
|
enqueueTask(function() {
|
||||||
|
return recursivelyFlushAsyncActWork(returnValue, resolve, reject);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
} catch (error) {
|
||||||
|
ReactSharedInternals.thrownErrors.push(error);
|
||||||
|
}
|
||||||
|
else ReactSharedInternals.actQueue = null;
|
||||||
|
0 < ReactSharedInternals.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(queue)) : resolve(returnValue);
|
||||||
|
}
|
||||||
|
function flushActQueue(queue) {
|
||||||
|
if (!isFlushing) {
|
||||||
|
isFlushing = !0;
|
||||||
|
var i = 0;
|
||||||
|
try {
|
||||||
|
for (; i < queue.length; i++) {
|
||||||
|
var callback = queue[i];
|
||||||
|
do {
|
||||||
|
ReactSharedInternals.didUsePromise = !1;
|
||||||
|
var continuation = callback(!1);
|
||||||
|
if (null !== continuation) {
|
||||||
|
if (ReactSharedInternals.didUsePromise) {
|
||||||
|
queue[i] = callback;
|
||||||
|
queue.splice(0, i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback = continuation;
|
||||||
|
} else break;
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
|
queue.length = 0;
|
||||||
|
} catch (error) {
|
||||||
|
queue.splice(0, i + 1), ReactSharedInternals.thrownErrors.push(error);
|
||||||
|
} finally {
|
||||||
|
isFlushing = !1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
||||||
|
var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), MAYBE_ITERATOR_SYMBOL = Symbol.iterator, didWarnStateUpdateForUnmountedComponent = {}, ReactNoopUpdateQueue = {
|
||||||
|
isMounted: function() {
|
||||||
|
return !1;
|
||||||
|
},
|
||||||
|
enqueueForceUpdate: function(publicInstance) {
|
||||||
|
warnNoop(publicInstance, "forceUpdate");
|
||||||
|
},
|
||||||
|
enqueueReplaceState: function(publicInstance) {
|
||||||
|
warnNoop(publicInstance, "replaceState");
|
||||||
|
},
|
||||||
|
enqueueSetState: function(publicInstance) {
|
||||||
|
warnNoop(publicInstance, "setState");
|
||||||
|
}
|
||||||
|
}, assign = Object.assign, emptyObject = {};
|
||||||
|
Object.freeze(emptyObject);
|
||||||
|
Component.prototype.isReactComponent = {};
|
||||||
|
Component.prototype.setState = function(partialState, callback) {
|
||||||
|
if ("object" !== typeof partialState && "function" !== typeof partialState && null != partialState) throw Error("takes an object of state variables to update or a function which returns an object of state variables.");
|
||||||
|
this.updater.enqueueSetState(this, partialState, callback, "setState");
|
||||||
|
};
|
||||||
|
Component.prototype.forceUpdate = function(callback) {
|
||||||
|
this.updater.enqueueForceUpdate(this, callback, "forceUpdate");
|
||||||
|
};
|
||||||
|
var deprecatedAPIs = {
|
||||||
|
isMounted: ["isMounted", "Instead, make sure to clean up subscriptions and pending requests in componentWillUnmount to prevent memory leaks."],
|
||||||
|
replaceState: ["replaceState", "Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236)."]
|
||||||
|
};
|
||||||
|
for (fnName in deprecatedAPIs) deprecatedAPIs.hasOwnProperty(fnName) && defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);
|
||||||
|
ComponentDummy.prototype = Component.prototype;
|
||||||
|
deprecatedAPIs = PureComponent.prototype = new ComponentDummy();
|
||||||
|
deprecatedAPIs.constructor = PureComponent;
|
||||||
|
assign(deprecatedAPIs, Component.prototype);
|
||||||
|
deprecatedAPIs.isPureReactComponent = !0;
|
||||||
|
var isArrayImpl = Array.isArray, REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = {
|
||||||
|
H: null,
|
||||||
|
A: null,
|
||||||
|
T: null,
|
||||||
|
S: null,
|
||||||
|
actQueue: null,
|
||||||
|
asyncTransitions: 0,
|
||||||
|
isBatchingLegacy: !1,
|
||||||
|
didScheduleLegacyUpdate: !1,
|
||||||
|
didUsePromise: !1,
|
||||||
|
thrownErrors: [],
|
||||||
|
getCurrentStack: null,
|
||||||
|
recentlyCreatedOwnerStacks: 0
|
||||||
|
}, hasOwnProperty = Object.prototype.hasOwnProperty, createTask = console.createTask ? console.createTask : function() {
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
deprecatedAPIs = { react_stack_bottom_frame: function(callStackForError) {
|
||||||
|
return callStackForError();
|
||||||
|
} };
|
||||||
|
var specialPropKeyWarningShown, didWarnAboutOldJSXRuntime;
|
||||||
|
var didWarnAboutElementRef = {};
|
||||||
|
var unknownOwnerDebugStack = deprecatedAPIs.react_stack_bottom_frame.bind(deprecatedAPIs, UnknownOwner)();
|
||||||
|
var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
|
||||||
|
var didWarnAboutMaps = !1, userProvidedKeyEscapeRegex = /\/+/g, reportGlobalError = "function" === typeof reportError ? reportError : function(error) {
|
||||||
|
if ("object" === typeof window && "function" === typeof window.ErrorEvent) {
|
||||||
|
var event = new window.ErrorEvent("error", {
|
||||||
|
bubbles: !0,
|
||||||
|
cancelable: !0,
|
||||||
|
message: "object" === typeof error && null !== error && "string" === typeof error.message ? String(error.message) : String(error),
|
||||||
|
error
|
||||||
|
});
|
||||||
|
if (!window.dispatchEvent(event)) return;
|
||||||
|
} else if ("object" === typeof process && "function" === typeof process.emit) {
|
||||||
|
process.emit("uncaughtException", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.error(error);
|
||||||
|
}, didWarnAboutMessageChannel = !1, enqueueTaskImpl = null, actScopeDepth = 0, didWarnNoAwaitAct = !1, isFlushing = !1, queueSeveralMicrotasks = "function" === typeof queueMicrotask ? function(callback) {
|
||||||
|
queueMicrotask(function() {
|
||||||
|
return queueMicrotask(callback);
|
||||||
|
});
|
||||||
|
} : enqueueTask;
|
||||||
|
deprecatedAPIs = Object.freeze({
|
||||||
|
__proto__: null,
|
||||||
|
c: function(size) {
|
||||||
|
return resolveDispatcher().useMemoCache(size);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var fnName = {
|
||||||
|
map: mapChildren,
|
||||||
|
forEach: function(children, forEachFunc, forEachContext) {
|
||||||
|
mapChildren(children, function() {
|
||||||
|
forEachFunc.apply(this, arguments);
|
||||||
|
}, forEachContext);
|
||||||
|
},
|
||||||
|
count: function(children) {
|
||||||
|
var n = 0;
|
||||||
|
mapChildren(children, function() {
|
||||||
|
n++;
|
||||||
|
});
|
||||||
|
return n;
|
||||||
|
},
|
||||||
|
toArray: function(children) {
|
||||||
|
return mapChildren(children, function(child) {
|
||||||
|
return child;
|
||||||
|
}) || [];
|
||||||
|
},
|
||||||
|
only: function(children) {
|
||||||
|
if (!isValidElement(children)) throw Error("React.Children.only expected to receive a single React element child.");
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.Activity = REACT_ACTIVITY_TYPE;
|
||||||
|
exports.Children = fnName;
|
||||||
|
exports.Component = Component;
|
||||||
|
exports.Fragment = REACT_FRAGMENT_TYPE;
|
||||||
|
exports.Profiler = REACT_PROFILER_TYPE;
|
||||||
|
exports.PureComponent = PureComponent;
|
||||||
|
exports.StrictMode = REACT_STRICT_MODE_TYPE;
|
||||||
|
exports.Suspense = REACT_SUSPENSE_TYPE;
|
||||||
|
exports.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = ReactSharedInternals;
|
||||||
|
exports.__COMPILER_RUNTIME = deprecatedAPIs;
|
||||||
|
exports.act = function(callback) {
|
||||||
|
var prevActQueue = ReactSharedInternals.actQueue, prevActScopeDepth = actScopeDepth;
|
||||||
|
actScopeDepth++;
|
||||||
|
var queue = ReactSharedInternals.actQueue = null !== prevActQueue ? prevActQueue : [], didAwaitActCall = !1;
|
||||||
|
try {
|
||||||
|
var result = callback();
|
||||||
|
} catch (error) {
|
||||||
|
ReactSharedInternals.thrownErrors.push(error);
|
||||||
|
}
|
||||||
|
if (0 < ReactSharedInternals.thrownErrors.length) throw popActScope(prevActQueue, prevActScopeDepth), callback = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, callback;
|
||||||
|
if (null !== result && "object" === typeof result && "function" === typeof result.then) {
|
||||||
|
var thenable = result;
|
||||||
|
queueSeveralMicrotasks(function() {
|
||||||
|
didAwaitActCall || didWarnNoAwaitAct || (didWarnNoAwaitAct = !0, console.error("You called act(async () => ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);"));
|
||||||
|
});
|
||||||
|
return { then: function(resolve, reject) {
|
||||||
|
didAwaitActCall = !0;
|
||||||
|
thenable.then(function(returnValue) {
|
||||||
|
popActScope(prevActQueue, prevActScopeDepth);
|
||||||
|
if (0 === prevActScopeDepth) {
|
||||||
|
try {
|
||||||
|
flushActQueue(queue), enqueueTask(function() {
|
||||||
|
return recursivelyFlushAsyncActWork(returnValue, resolve, reject);
|
||||||
|
});
|
||||||
|
} catch (error$0) {
|
||||||
|
ReactSharedInternals.thrownErrors.push(error$0);
|
||||||
|
}
|
||||||
|
if (0 < ReactSharedInternals.thrownErrors.length) {
|
||||||
|
var _thrownError = aggregateErrors(ReactSharedInternals.thrownErrors);
|
||||||
|
ReactSharedInternals.thrownErrors.length = 0;
|
||||||
|
reject(_thrownError);
|
||||||
|
}
|
||||||
|
} else resolve(returnValue);
|
||||||
|
}, function(error) {
|
||||||
|
popActScope(prevActQueue, prevActScopeDepth);
|
||||||
|
0 < ReactSharedInternals.thrownErrors.length ? (error = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, reject(error)) : reject(error);
|
||||||
|
});
|
||||||
|
} };
|
||||||
|
}
|
||||||
|
var returnValue$jscomp$0 = result;
|
||||||
|
popActScope(prevActQueue, prevActScopeDepth);
|
||||||
|
0 === prevActScopeDepth && (flushActQueue(queue), 0 !== queue.length && queueSeveralMicrotasks(function() {
|
||||||
|
didAwaitActCall || didWarnNoAwaitAct || (didWarnNoAwaitAct = !0, console.error("A component suspended inside an `act` scope, but the `act` call was not awaited. When testing React components that depend on asynchronous data, you must await the result:\n\nawait act(() => ...)"));
|
||||||
|
}), ReactSharedInternals.actQueue = null);
|
||||||
|
if (0 < ReactSharedInternals.thrownErrors.length) throw callback = aggregateErrors(ReactSharedInternals.thrownErrors), ReactSharedInternals.thrownErrors.length = 0, callback;
|
||||||
|
return { then: function(resolve, reject) {
|
||||||
|
didAwaitActCall = !0;
|
||||||
|
0 === prevActScopeDepth ? (ReactSharedInternals.actQueue = queue, enqueueTask(function() {
|
||||||
|
return recursivelyFlushAsyncActWork(returnValue$jscomp$0, resolve, reject);
|
||||||
|
})) : resolve(returnValue$jscomp$0);
|
||||||
|
} };
|
||||||
|
};
|
||||||
|
exports.cache = function(fn) {
|
||||||
|
return function() {
|
||||||
|
return fn.apply(null, arguments);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
exports.cacheSignal = function() {
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
exports.captureOwnerStack = function() {
|
||||||
|
var getCurrentStack = ReactSharedInternals.getCurrentStack;
|
||||||
|
return null === getCurrentStack ? null : getCurrentStack();
|
||||||
|
};
|
||||||
|
exports.cloneElement = function(element, config, children) {
|
||||||
|
if (null === element || void 0 === element) throw Error("The argument must be a React element, but you passed " + element + ".");
|
||||||
|
var props = assign({}, element.props), key = element.key, owner = element._owner;
|
||||||
|
if (null != config) {
|
||||||
|
var JSCompiler_inline_result;
|
||||||
|
a: {
|
||||||
|
if (hasOwnProperty.call(config, "ref") && (JSCompiler_inline_result = Object.getOwnPropertyDescriptor(config, "ref").get) && JSCompiler_inline_result.isReactWarning) {
|
||||||
|
JSCompiler_inline_result = !1;
|
||||||
|
break a;
|
||||||
|
}
|
||||||
|
JSCompiler_inline_result = void 0 !== config.ref;
|
||||||
|
}
|
||||||
|
JSCompiler_inline_result && (owner = getOwner());
|
||||||
|
hasValidKey(config) && (checkKeyStringCoercion(config.key), key = "" + config.key);
|
||||||
|
for (propName in config) !hasOwnProperty.call(config, propName) || "key" === propName || "__self" === propName || "__source" === propName || "ref" === propName && void 0 === config.ref || (props[propName] = config[propName]);
|
||||||
|
}
|
||||||
|
var propName = arguments.length - 2;
|
||||||
|
if (1 === propName) props.children = children;
|
||||||
|
else if (1 < propName) {
|
||||||
|
JSCompiler_inline_result = Array(propName);
|
||||||
|
for (var i = 0; i < propName; i++) JSCompiler_inline_result[i] = arguments[i + 2];
|
||||||
|
props.children = JSCompiler_inline_result;
|
||||||
|
}
|
||||||
|
props = ReactElement(element.type, key, props, owner, element._debugStack, element._debugTask);
|
||||||
|
for (key = 2; key < arguments.length; key++) validateChildKeys(arguments[key]);
|
||||||
|
return props;
|
||||||
|
};
|
||||||
|
exports.createContext = function(defaultValue) {
|
||||||
|
defaultValue = {
|
||||||
|
$$typeof: REACT_CONTEXT_TYPE,
|
||||||
|
_currentValue: defaultValue,
|
||||||
|
_currentValue2: defaultValue,
|
||||||
|
_threadCount: 0,
|
||||||
|
Provider: null,
|
||||||
|
Consumer: null
|
||||||
|
};
|
||||||
|
defaultValue.Provider = defaultValue;
|
||||||
|
defaultValue.Consumer = {
|
||||||
|
$$typeof: REACT_CONSUMER_TYPE,
|
||||||
|
_context: defaultValue
|
||||||
|
};
|
||||||
|
defaultValue._currentRenderer = null;
|
||||||
|
defaultValue._currentRenderer2 = null;
|
||||||
|
return defaultValue;
|
||||||
|
};
|
||||||
|
exports.createElement = function(type, config, children) {
|
||||||
|
for (var i = 2; i < arguments.length; i++) validateChildKeys(arguments[i]);
|
||||||
|
i = {};
|
||||||
|
var key = null;
|
||||||
|
if (null != config) for (propName in didWarnAboutOldJSXRuntime || !("__self" in config) || "key" in config || (didWarnAboutOldJSXRuntime = !0, console.warn("Your app (or one of its dependencies) is using an outdated JSX transform. Update to the modern JSX transform for faster performance: https://react.dev/link/new-jsx-transform")), hasValidKey(config) && (checkKeyStringCoercion(config.key), key = "" + config.key), config) hasOwnProperty.call(config, propName) && "key" !== propName && "__self" !== propName && "__source" !== propName && (i[propName] = config[propName]);
|
||||||
|
var childrenLength = arguments.length - 2;
|
||||||
|
if (1 === childrenLength) i.children = children;
|
||||||
|
else if (1 < childrenLength) {
|
||||||
|
for (var childArray = Array(childrenLength), _i = 0; _i < childrenLength; _i++) childArray[_i] = arguments[_i + 2];
|
||||||
|
Object.freeze && Object.freeze(childArray);
|
||||||
|
i.children = childArray;
|
||||||
|
}
|
||||||
|
if (type && type.defaultProps) for (propName in childrenLength = type.defaultProps, childrenLength) void 0 === i[propName] && (i[propName] = childrenLength[propName]);
|
||||||
|
key && defineKeyPropWarningGetter(i, "function" === typeof type ? type.displayName || type.name || "Unknown" : type);
|
||||||
|
var propName = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
|
||||||
|
return ReactElement(type, key, i, getOwner(), propName ? Error("react-stack-top-frame") : unknownOwnerDebugStack, propName ? createTask(getTaskName(type)) : unknownOwnerDebugTask);
|
||||||
|
};
|
||||||
|
exports.createRef = function() {
|
||||||
|
var refObject = { current: null };
|
||||||
|
Object.seal(refObject);
|
||||||
|
return refObject;
|
||||||
|
};
|
||||||
|
exports.forwardRef = function(render) {
|
||||||
|
null != render && render.$$typeof === REACT_MEMO_TYPE ? console.error("forwardRef requires a render function but received a `memo` component. Instead of forwardRef(memo(...)), use memo(forwardRef(...)).") : "function" !== typeof render ? console.error("forwardRef requires a render function but was given %s.", null === render ? "null" : typeof render) : 0 !== render.length && 2 !== render.length && console.error("forwardRef render functions accept exactly two parameters: props and ref. %s", 1 === render.length ? "Did you forget to use the ref parameter?" : "Any additional parameter will be undefined.");
|
||||||
|
null != render && null != render.defaultProps && console.error("forwardRef render functions do not support defaultProps. Did you accidentally pass a React component?");
|
||||||
|
var elementType = {
|
||||||
|
$$typeof: REACT_FORWARD_REF_TYPE,
|
||||||
|
render
|
||||||
|
}, ownName;
|
||||||
|
Object.defineProperty(elementType, "displayName", {
|
||||||
|
enumerable: !1,
|
||||||
|
configurable: !0,
|
||||||
|
get: function() {
|
||||||
|
return ownName;
|
||||||
|
},
|
||||||
|
set: function(name) {
|
||||||
|
ownName = name;
|
||||||
|
render.name || render.displayName || (Object.defineProperty(render, "name", { value: name }), render.displayName = name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return elementType;
|
||||||
|
};
|
||||||
|
exports.isValidElement = isValidElement;
|
||||||
|
exports.lazy = function(ctor) {
|
||||||
|
ctor = {
|
||||||
|
_status: -1,
|
||||||
|
_result: ctor
|
||||||
|
};
|
||||||
|
var lazyType = {
|
||||||
|
$$typeof: REACT_LAZY_TYPE,
|
||||||
|
_payload: ctor,
|
||||||
|
_init: lazyInitializer
|
||||||
|
}, ioInfo = {
|
||||||
|
name: "lazy",
|
||||||
|
start: -1,
|
||||||
|
end: -1,
|
||||||
|
value: null,
|
||||||
|
owner: null,
|
||||||
|
debugStack: Error("react-stack-top-frame"),
|
||||||
|
debugTask: console.createTask ? console.createTask("lazy()") : null
|
||||||
|
};
|
||||||
|
ctor._ioInfo = ioInfo;
|
||||||
|
lazyType._debugInfo = [{ awaited: ioInfo }];
|
||||||
|
return lazyType;
|
||||||
|
};
|
||||||
|
exports.memo = function(type, compare) {
|
||||||
|
type ?? console.error("memo: The first argument must be a component. Instead received: %s", null === type ? "null" : typeof type);
|
||||||
|
compare = {
|
||||||
|
$$typeof: REACT_MEMO_TYPE,
|
||||||
|
type,
|
||||||
|
compare: void 0 === compare ? null : compare
|
||||||
|
};
|
||||||
|
var ownName;
|
||||||
|
Object.defineProperty(compare, "displayName", {
|
||||||
|
enumerable: !1,
|
||||||
|
configurable: !0,
|
||||||
|
get: function() {
|
||||||
|
return ownName;
|
||||||
|
},
|
||||||
|
set: function(name) {
|
||||||
|
ownName = name;
|
||||||
|
type.name || type.displayName || (Object.defineProperty(type, "name", { value: name }), type.displayName = name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return compare;
|
||||||
|
};
|
||||||
|
exports.startTransition = function(scope) {
|
||||||
|
var prevTransition = ReactSharedInternals.T, currentTransition = {};
|
||||||
|
currentTransition._updatedFibers = /* @__PURE__ */ new Set();
|
||||||
|
ReactSharedInternals.T = currentTransition;
|
||||||
|
try {
|
||||||
|
var returnValue = scope(), onStartTransitionFinish = ReactSharedInternals.S;
|
||||||
|
null !== onStartTransitionFinish && onStartTransitionFinish(currentTransition, returnValue);
|
||||||
|
"object" === typeof returnValue && null !== returnValue && "function" === typeof returnValue.then && (ReactSharedInternals.asyncTransitions++, returnValue.then(releaseAsyncTransition, releaseAsyncTransition), returnValue.then(noop, reportGlobalError));
|
||||||
|
} catch (error) {
|
||||||
|
reportGlobalError(error);
|
||||||
|
} finally {
|
||||||
|
null === prevTransition && currentTransition._updatedFibers && (scope = currentTransition._updatedFibers.size, currentTransition._updatedFibers.clear(), 10 < scope && console.warn("Detected a large number of updates inside startTransition. If this is due to a subscription please re-write it to use React provided hooks. Otherwise concurrent mode guarantees are off the table.")), null !== prevTransition && null !== currentTransition.types && (null !== prevTransition.types && prevTransition.types !== currentTransition.types && console.error("We expected inner Transitions to have transferred the outer types set and that you cannot add to the outer Transition while inside the inner.This is a bug in React."), prevTransition.types = currentTransition.types), ReactSharedInternals.T = prevTransition;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.unstable_useCacheRefresh = function() {
|
||||||
|
return resolveDispatcher().useCacheRefresh();
|
||||||
|
};
|
||||||
|
exports.use = function(usable) {
|
||||||
|
return resolveDispatcher().use(usable);
|
||||||
|
};
|
||||||
|
exports.useActionState = function(action, initialState, permalink) {
|
||||||
|
return resolveDispatcher().useActionState(action, initialState, permalink);
|
||||||
|
};
|
||||||
|
exports.useCallback = function(callback, deps) {
|
||||||
|
return resolveDispatcher().useCallback(callback, deps);
|
||||||
|
};
|
||||||
|
exports.useContext = function(Context) {
|
||||||
|
var dispatcher = resolveDispatcher();
|
||||||
|
Context.$$typeof === REACT_CONSUMER_TYPE && console.error("Calling useContext(Context.Consumer) is not supported and will cause bugs. Did you mean to call useContext(Context) instead?");
|
||||||
|
return dispatcher.useContext(Context);
|
||||||
|
};
|
||||||
|
exports.useDebugValue = function(value, formatterFn) {
|
||||||
|
return resolveDispatcher().useDebugValue(value, formatterFn);
|
||||||
|
};
|
||||||
|
exports.useDeferredValue = function(value, initialValue) {
|
||||||
|
return resolveDispatcher().useDeferredValue(value, initialValue);
|
||||||
|
};
|
||||||
|
exports.useEffect = function(create, deps) {
|
||||||
|
create ?? console.warn("React Hook useEffect requires an effect callback. Did you forget to pass a callback to the hook?");
|
||||||
|
return resolveDispatcher().useEffect(create, deps);
|
||||||
|
};
|
||||||
|
exports.useEffectEvent = function(callback) {
|
||||||
|
return resolveDispatcher().useEffectEvent(callback);
|
||||||
|
};
|
||||||
|
exports.useId = function() {
|
||||||
|
return resolveDispatcher().useId();
|
||||||
|
};
|
||||||
|
exports.useImperativeHandle = function(ref, create, deps) {
|
||||||
|
return resolveDispatcher().useImperativeHandle(ref, create, deps);
|
||||||
|
};
|
||||||
|
exports.useInsertionEffect = function(create, deps) {
|
||||||
|
create ?? console.warn("React Hook useInsertionEffect requires an effect callback. Did you forget to pass a callback to the hook?");
|
||||||
|
return resolveDispatcher().useInsertionEffect(create, deps);
|
||||||
|
};
|
||||||
|
exports.useLayoutEffect = function(create, deps) {
|
||||||
|
create ?? console.warn("React Hook useLayoutEffect requires an effect callback. Did you forget to pass a callback to the hook?");
|
||||||
|
return resolveDispatcher().useLayoutEffect(create, deps);
|
||||||
|
};
|
||||||
|
exports.useMemo = function(create, deps) {
|
||||||
|
return resolveDispatcher().useMemo(create, deps);
|
||||||
|
};
|
||||||
|
exports.useOptimistic = function(passthrough, reducer) {
|
||||||
|
return resolveDispatcher().useOptimistic(passthrough, reducer);
|
||||||
|
};
|
||||||
|
exports.useReducer = function(reducer, initialArg, init) {
|
||||||
|
return resolveDispatcher().useReducer(reducer, initialArg, init);
|
||||||
|
};
|
||||||
|
exports.useRef = function(initialValue) {
|
||||||
|
return resolveDispatcher().useRef(initialValue);
|
||||||
|
};
|
||||||
|
exports.useState = function(initialState) {
|
||||||
|
return resolveDispatcher().useState(initialState);
|
||||||
|
};
|
||||||
|
exports.useSyncExternalStore = function(subscribe, getSnapshot, getServerSnapshot) {
|
||||||
|
return resolveDispatcher().useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
||||||
|
};
|
||||||
|
exports.useTransition = function() {
|
||||||
|
return resolveDispatcher().useTransition();
|
||||||
|
};
|
||||||
|
exports.version = "19.2.4";
|
||||||
|
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
|
||||||
|
})();
|
||||||
|
}));
|
||||||
|
//#endregion
|
||||||
|
//#region node_modules/react/index.js
|
||||||
|
var require_react = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
||||||
|
module.exports = require_react_development();
|
||||||
|
}));
|
||||||
|
//#endregion
|
||||||
|
export { __commonJSMin as n, require_react as t };
|
||||||
|
|
||||||
|
//# sourceMappingURL=react-Na5-BvaJ.js.map
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.vite/deps/react-Na5-BvaJ.js.map
generated
vendored
Normal file
185
fotograf-de-scraper/frontend/node_modules/.vite/deps/react-dom.js
generated
vendored
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
import { n as __commonJSMin, t as require_react } from "./react-Na5-BvaJ.js";
|
||||||
|
//#region node_modules/react-dom/cjs/react-dom.development.js
|
||||||
|
/**
|
||||||
|
* @license React
|
||||||
|
* react-dom.development.js
|
||||||
|
*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
var require_react_dom_development = /* @__PURE__ */ __commonJSMin(((exports) => {
|
||||||
|
(function() {
|
||||||
|
function noop() {}
|
||||||
|
function testStringCoercion(value) {
|
||||||
|
return "" + value;
|
||||||
|
}
|
||||||
|
function createPortal$1(children, containerInfo, implementation) {
|
||||||
|
var key = 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null;
|
||||||
|
try {
|
||||||
|
testStringCoercion(key);
|
||||||
|
var JSCompiler_inline_result = !1;
|
||||||
|
} catch (e) {
|
||||||
|
JSCompiler_inline_result = !0;
|
||||||
|
}
|
||||||
|
JSCompiler_inline_result && (console.error("The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", "function" === typeof Symbol && Symbol.toStringTag && key[Symbol.toStringTag] || key.constructor.name || "Object"), testStringCoercion(key));
|
||||||
|
return {
|
||||||
|
$$typeof: REACT_PORTAL_TYPE,
|
||||||
|
key: null == key ? null : "" + key,
|
||||||
|
children,
|
||||||
|
containerInfo,
|
||||||
|
implementation
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function getCrossOriginStringAs(as, input) {
|
||||||
|
if ("font" === as) return "";
|
||||||
|
if ("string" === typeof input) return "use-credentials" === input ? input : "";
|
||||||
|
}
|
||||||
|
function getValueDescriptorExpectingObjectForWarning(thing) {
|
||||||
|
return null === thing ? "`null`" : void 0 === thing ? "`undefined`" : "" === thing ? "an empty string" : "something with type \"" + typeof thing + "\"";
|
||||||
|
}
|
||||||
|
function getValueDescriptorExpectingEnumForWarning(thing) {
|
||||||
|
return null === thing ? "`null`" : void 0 === thing ? "`undefined`" : "" === thing ? "an empty string" : "string" === typeof thing ? JSON.stringify(thing) : "number" === typeof thing ? "`" + thing + "`" : "something with type \"" + typeof thing + "\"";
|
||||||
|
}
|
||||||
|
function resolveDispatcher() {
|
||||||
|
var dispatcher = ReactSharedInternals.H;
|
||||||
|
null === dispatcher && console.error("Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.");
|
||||||
|
return dispatcher;
|
||||||
|
}
|
||||||
|
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
||||||
|
var React = require_react(), Internals = {
|
||||||
|
d: {
|
||||||
|
f: noop,
|
||||||
|
r: function() {
|
||||||
|
throw Error("Invalid form element. requestFormReset must be passed a form that was rendered by React.");
|
||||||
|
},
|
||||||
|
D: noop,
|
||||||
|
C: noop,
|
||||||
|
L: noop,
|
||||||
|
m: noop,
|
||||||
|
X: noop,
|
||||||
|
S: noop,
|
||||||
|
M: noop
|
||||||
|
},
|
||||||
|
p: 0,
|
||||||
|
findDOMNode: null
|
||||||
|
}, REACT_PORTAL_TYPE = Symbol.for("react.portal"), ReactSharedInternals = React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
|
||||||
|
"function" === typeof Map && null != Map.prototype && "function" === typeof Map.prototype.forEach && "function" === typeof Set && null != Set.prototype && "function" === typeof Set.prototype.clear && "function" === typeof Set.prototype.forEach || console.error("React depends on Map and Set built-in types. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills");
|
||||||
|
exports.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = Internals;
|
||||||
|
exports.createPortal = function(children, container) {
|
||||||
|
var key = 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : null;
|
||||||
|
if (!container || 1 !== container.nodeType && 9 !== container.nodeType && 11 !== container.nodeType) throw Error("Target container is not a DOM element.");
|
||||||
|
return createPortal$1(children, container, null, key);
|
||||||
|
};
|
||||||
|
exports.flushSync = function(fn) {
|
||||||
|
var previousTransition = ReactSharedInternals.T, previousUpdatePriority = Internals.p;
|
||||||
|
try {
|
||||||
|
if (ReactSharedInternals.T = null, Internals.p = 2, fn) return fn();
|
||||||
|
} finally {
|
||||||
|
ReactSharedInternals.T = previousTransition, Internals.p = previousUpdatePriority, Internals.d.f() && console.error("flushSync was called from inside a lifecycle method. React cannot flush when React is already rendering. Consider moving this call to a scheduler task or micro task.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.preconnect = function(href, options) {
|
||||||
|
"string" === typeof href && href ? null != options && "object" !== typeof options ? console.error("ReactDOM.preconnect(): Expected the `options` argument (second) to be an object but encountered %s instead. The only supported option at this time is `crossOrigin` which accepts a string.", getValueDescriptorExpectingEnumForWarning(options)) : null != options && "string" !== typeof options.crossOrigin && console.error("ReactDOM.preconnect(): Expected the `crossOrigin` option (second argument) to be a string but encountered %s instead. Try removing this option or passing a string value instead.", getValueDescriptorExpectingObjectForWarning(options.crossOrigin)) : console.error("ReactDOM.preconnect(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.", getValueDescriptorExpectingObjectForWarning(href));
|
||||||
|
"string" === typeof href && (options ? (options = options.crossOrigin, options = "string" === typeof options ? "use-credentials" === options ? options : "" : void 0) : options = null, Internals.d.C(href, options));
|
||||||
|
};
|
||||||
|
exports.prefetchDNS = function(href) {
|
||||||
|
if ("string" !== typeof href || !href) console.error("ReactDOM.prefetchDNS(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.", getValueDescriptorExpectingObjectForWarning(href));
|
||||||
|
else if (1 < arguments.length) {
|
||||||
|
var options = arguments[1];
|
||||||
|
"object" === typeof options && options.hasOwnProperty("crossOrigin") ? console.error("ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered %s as a second argument instead. This argument is reserved for future options and is currently disallowed. It looks like the you are attempting to set a crossOrigin property for this DNS lookup hint. Browsers do not perform DNS queries using CORS and setting this attribute on the resource hint has no effect. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.", getValueDescriptorExpectingEnumForWarning(options)) : console.error("ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered %s as a second argument instead. This argument is reserved for future options and is currently disallowed. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.", getValueDescriptorExpectingEnumForWarning(options));
|
||||||
|
}
|
||||||
|
"string" === typeof href && Internals.d.D(href);
|
||||||
|
};
|
||||||
|
exports.preinit = function(href, options) {
|
||||||
|
"string" === typeof href && href ? null == options || "object" !== typeof options ? console.error("ReactDOM.preinit(): Expected the `options` argument (second) to be an object with an `as` property describing the type of resource to be preinitialized but encountered %s instead.", getValueDescriptorExpectingEnumForWarning(options)) : "style" !== options.as && "script" !== options.as && console.error("ReactDOM.preinit(): Expected the `as` property in the `options` argument (second) to contain a valid value describing the type of resource to be preinitialized but encountered %s instead. Valid values for `as` are \"style\" and \"script\".", getValueDescriptorExpectingEnumForWarning(options.as)) : console.error("ReactDOM.preinit(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.", getValueDescriptorExpectingObjectForWarning(href));
|
||||||
|
if ("string" === typeof href && options && "string" === typeof options.as) {
|
||||||
|
var as = options.as, crossOrigin = getCrossOriginStringAs(as, options.crossOrigin), integrity = "string" === typeof options.integrity ? options.integrity : void 0, fetchPriority = "string" === typeof options.fetchPriority ? options.fetchPriority : void 0;
|
||||||
|
"style" === as ? Internals.d.S(href, "string" === typeof options.precedence ? options.precedence : void 0, {
|
||||||
|
crossOrigin,
|
||||||
|
integrity,
|
||||||
|
fetchPriority
|
||||||
|
}) : "script" === as && Internals.d.X(href, {
|
||||||
|
crossOrigin,
|
||||||
|
integrity,
|
||||||
|
fetchPriority,
|
||||||
|
nonce: "string" === typeof options.nonce ? options.nonce : void 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.preinitModule = function(href, options) {
|
||||||
|
var encountered = "";
|
||||||
|
"string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
|
||||||
|
void 0 !== options && "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : options && "as" in options && "script" !== options.as && (encountered += " The `as` option encountered was " + getValueDescriptorExpectingEnumForWarning(options.as) + ".");
|
||||||
|
if (encountered) console.error("ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` string and, optionally, an `options` object with a valid `as` property.%s", encountered);
|
||||||
|
else switch (encountered = options && "string" === typeof options.as ? options.as : "script", encountered) {
|
||||||
|
case "script": break;
|
||||||
|
default: encountered = getValueDescriptorExpectingEnumForWarning(encountered), console.error("ReactDOM.preinitModule(): Currently the only supported \"as\" type for this function is \"script\" but received \"%s\" instead. This warning was generated for `href` \"%s\". In the future other module types will be supported, aligning with the import-attributes proposal. Learn more here: (https://github.com/tc39/proposal-import-attributes)", encountered, href);
|
||||||
|
}
|
||||||
|
if ("string" === typeof href) if ("object" === typeof options && null !== options) {
|
||||||
|
if (null == options.as || "script" === options.as) encountered = getCrossOriginStringAs(options.as, options.crossOrigin), Internals.d.M(href, {
|
||||||
|
crossOrigin: encountered,
|
||||||
|
integrity: "string" === typeof options.integrity ? options.integrity : void 0,
|
||||||
|
nonce: "string" === typeof options.nonce ? options.nonce : void 0
|
||||||
|
});
|
||||||
|
} else options ?? Internals.d.M(href);
|
||||||
|
};
|
||||||
|
exports.preload = function(href, options) {
|
||||||
|
var encountered = "";
|
||||||
|
"string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
|
||||||
|
null == options || "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : "string" === typeof options.as && options.as || (encountered += " The `as` option encountered was " + getValueDescriptorExpectingObjectForWarning(options.as) + ".");
|
||||||
|
encountered && console.error("ReactDOM.preload(): Expected two arguments, a non-empty `href` string and an `options` object with an `as` property valid for a `<link rel=\"preload\" as=\"...\" />` tag.%s", encountered);
|
||||||
|
if ("string" === typeof href && "object" === typeof options && null !== options && "string" === typeof options.as) {
|
||||||
|
encountered = options.as;
|
||||||
|
var crossOrigin = getCrossOriginStringAs(encountered, options.crossOrigin);
|
||||||
|
Internals.d.L(href, encountered, {
|
||||||
|
crossOrigin,
|
||||||
|
integrity: "string" === typeof options.integrity ? options.integrity : void 0,
|
||||||
|
nonce: "string" === typeof options.nonce ? options.nonce : void 0,
|
||||||
|
type: "string" === typeof options.type ? options.type : void 0,
|
||||||
|
fetchPriority: "string" === typeof options.fetchPriority ? options.fetchPriority : void 0,
|
||||||
|
referrerPolicy: "string" === typeof options.referrerPolicy ? options.referrerPolicy : void 0,
|
||||||
|
imageSrcSet: "string" === typeof options.imageSrcSet ? options.imageSrcSet : void 0,
|
||||||
|
imageSizes: "string" === typeof options.imageSizes ? options.imageSizes : void 0,
|
||||||
|
media: "string" === typeof options.media ? options.media : void 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.preloadModule = function(href, options) {
|
||||||
|
var encountered = "";
|
||||||
|
"string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
|
||||||
|
void 0 !== options && "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : options && "as" in options && "string" !== typeof options.as && (encountered += " The `as` option encountered was " + getValueDescriptorExpectingObjectForWarning(options.as) + ".");
|
||||||
|
encountered && console.error("ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an `options` object with an `as` property valid for a `<link rel=\"modulepreload\" as=\"...\" />` tag.%s", encountered);
|
||||||
|
"string" === typeof href && (options ? (encountered = getCrossOriginStringAs(options.as, options.crossOrigin), Internals.d.m(href, {
|
||||||
|
as: "string" === typeof options.as && "script" !== options.as ? options.as : void 0,
|
||||||
|
crossOrigin: encountered,
|
||||||
|
integrity: "string" === typeof options.integrity ? options.integrity : void 0
|
||||||
|
})) : Internals.d.m(href));
|
||||||
|
};
|
||||||
|
exports.requestFormReset = function(form) {
|
||||||
|
Internals.d.r(form);
|
||||||
|
};
|
||||||
|
exports.unstable_batchedUpdates = function(fn, a) {
|
||||||
|
return fn(a);
|
||||||
|
};
|
||||||
|
exports.useFormState = function(action, initialState, permalink) {
|
||||||
|
return resolveDispatcher().useFormState(action, initialState, permalink);
|
||||||
|
};
|
||||||
|
exports.useFormStatus = function() {
|
||||||
|
return resolveDispatcher().useHostTransitionStatus();
|
||||||
|
};
|
||||||
|
exports.version = "19.2.4";
|
||||||
|
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
|
||||||
|
})();
|
||||||
|
}));
|
||||||
|
//#endregion
|
||||||
|
//#region node_modules/react-dom/index.js
|
||||||
|
var require_react_dom = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
||||||
|
module.exports = require_react_dom_development();
|
||||||
|
}));
|
||||||
|
//#endregion
|
||||||
|
export default require_react_dom();
|
||||||
|
export { require_react_dom as t };
|
||||||
|
|
||||||
|
//# sourceMappingURL=react-dom.js.map
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.vite/deps/react-dom.js.map
generated
vendored
Normal file
14384
fotograf-de-scraper/frontend/node_modules/.vite/deps/react-dom_client.js
generated
vendored
Normal file
1
fotograf-de-scraper/frontend/node_modules/.vite/deps/react-dom_client.js.map
generated
vendored
Normal file
2
fotograf-de-scraper/frontend/node_modules/.vite/deps/react.js
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import { t as require_react } from "./react-Na5-BvaJ.js";
|
||||||
|
export default require_react();
|
||||||
204
fotograf-de-scraper/frontend/node_modules/.vite/deps/react_jsx-dev-runtime.js
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
import { n as __commonJSMin, t as require_react } from "./react-Na5-BvaJ.js";
|
||||||
|
//#region node_modules/react/cjs/react-jsx-dev-runtime.development.js
|
||||||
|
/**
|
||||||
|
* @license React
|
||||||
|
* react-jsx-dev-runtime.development.js
|
||||||
|
*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
var require_react_jsx_dev_runtime_development = /* @__PURE__ */ __commonJSMin(((exports) => {
|
||||||
|
(function() {
|
||||||
|
function getComponentNameFromType(type) {
|
||||||
|
if (null == type) return null;
|
||||||
|
if ("function" === typeof type) return type.$$typeof === REACT_CLIENT_REFERENCE ? null : type.displayName || type.name || null;
|
||||||
|
if ("string" === typeof type) return type;
|
||||||
|
switch (type) {
|
||||||
|
case REACT_FRAGMENT_TYPE: return "Fragment";
|
||||||
|
case REACT_PROFILER_TYPE: return "Profiler";
|
||||||
|
case REACT_STRICT_MODE_TYPE: return "StrictMode";
|
||||||
|
case REACT_SUSPENSE_TYPE: return "Suspense";
|
||||||
|
case REACT_SUSPENSE_LIST_TYPE: return "SuspenseList";
|
||||||
|
case REACT_ACTIVITY_TYPE: return "Activity";
|
||||||
|
}
|
||||||
|
if ("object" === typeof type) switch ("number" === typeof type.tag && console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), type.$$typeof) {
|
||||||
|
case REACT_PORTAL_TYPE: return "Portal";
|
||||||
|
case REACT_CONTEXT_TYPE: return type.displayName || "Context";
|
||||||
|
case REACT_CONSUMER_TYPE: return (type._context.displayName || "Context") + ".Consumer";
|
||||||
|
case REACT_FORWARD_REF_TYPE:
|
||||||
|
var innerType = type.render;
|
||||||
|
type = type.displayName;
|
||||||
|
type || (type = innerType.displayName || innerType.name || "", type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef");
|
||||||
|
return type;
|
||||||
|
case REACT_MEMO_TYPE: return innerType = type.displayName || null, null !== innerType ? innerType : getComponentNameFromType(type.type) || "Memo";
|
||||||
|
case REACT_LAZY_TYPE:
|
||||||
|
innerType = type._payload;
|
||||||
|
type = type._init;
|
||||||
|
try {
|
||||||
|
return getComponentNameFromType(type(innerType));
|
||||||
|
} catch (x) {}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function testStringCoercion(value) {
|
||||||
|
return "" + value;
|
||||||
|
}
|
||||||
|
function checkKeyStringCoercion(value) {
|
||||||
|
try {
|
||||||
|
testStringCoercion(value);
|
||||||
|
var JSCompiler_inline_result = !1;
|
||||||
|
} catch (e) {
|
||||||
|
JSCompiler_inline_result = !0;
|
||||||
|
}
|
||||||
|
if (JSCompiler_inline_result) {
|
||||||
|
JSCompiler_inline_result = console;
|
||||||
|
var JSCompiler_temp_const = JSCompiler_inline_result.error;
|
||||||
|
var JSCompiler_inline_result$jscomp$0 = "function" === typeof Symbol && Symbol.toStringTag && value[Symbol.toStringTag] || value.constructor.name || "Object";
|
||||||
|
JSCompiler_temp_const.call(JSCompiler_inline_result, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", JSCompiler_inline_result$jscomp$0);
|
||||||
|
return testStringCoercion(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getTaskName(type) {
|
||||||
|
if (type === REACT_FRAGMENT_TYPE) return "<>";
|
||||||
|
if ("object" === typeof type && null !== type && type.$$typeof === REACT_LAZY_TYPE) return "<...>";
|
||||||
|
try {
|
||||||
|
var name = getComponentNameFromType(type);
|
||||||
|
return name ? "<" + name + ">" : "<...>";
|
||||||
|
} catch (x) {
|
||||||
|
return "<...>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getOwner() {
|
||||||
|
var dispatcher = ReactSharedInternals.A;
|
||||||
|
return null === dispatcher ? null : dispatcher.getOwner();
|
||||||
|
}
|
||||||
|
function UnknownOwner() {
|
||||||
|
return Error("react-stack-top-frame");
|
||||||
|
}
|
||||||
|
function hasValidKey(config) {
|
||||||
|
if (hasOwnProperty.call(config, "key")) {
|
||||||
|
var getter = Object.getOwnPropertyDescriptor(config, "key").get;
|
||||||
|
if (getter && getter.isReactWarning) return !1;
|
||||||
|
}
|
||||||
|
return void 0 !== config.key;
|
||||||
|
}
|
||||||
|
function defineKeyPropWarningGetter(props, displayName) {
|
||||||
|
function warnAboutAccessingKey() {
|
||||||
|
specialPropKeyWarningShown || (specialPropKeyWarningShown = !0, console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", displayName));
|
||||||
|
}
|
||||||
|
warnAboutAccessingKey.isReactWarning = !0;
|
||||||
|
Object.defineProperty(props, "key", {
|
||||||
|
get: warnAboutAccessingKey,
|
||||||
|
configurable: !0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function elementRefGetterWithDeprecationWarning() {
|
||||||
|
var componentName = getComponentNameFromType(this.type);
|
||||||
|
didWarnAboutElementRef[componentName] || (didWarnAboutElementRef[componentName] = !0, console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."));
|
||||||
|
componentName = this.props.ref;
|
||||||
|
return void 0 !== componentName ? componentName : null;
|
||||||
|
}
|
||||||
|
function ReactElement(type, key, props, owner, debugStack, debugTask) {
|
||||||
|
var refProp = props.ref;
|
||||||
|
type = {
|
||||||
|
$$typeof: REACT_ELEMENT_TYPE,
|
||||||
|
type,
|
||||||
|
key,
|
||||||
|
props,
|
||||||
|
_owner: owner
|
||||||
|
};
|
||||||
|
null !== (void 0 !== refProp ? refProp : null) ? Object.defineProperty(type, "ref", {
|
||||||
|
enumerable: !1,
|
||||||
|
get: elementRefGetterWithDeprecationWarning
|
||||||
|
}) : Object.defineProperty(type, "ref", {
|
||||||
|
enumerable: !1,
|
||||||
|
value: null
|
||||||
|
});
|
||||||
|
type._store = {};
|
||||||
|
Object.defineProperty(type._store, "validated", {
|
||||||
|
configurable: !1,
|
||||||
|
enumerable: !1,
|
||||||
|
writable: !0,
|
||||||
|
value: 0
|
||||||
|
});
|
||||||
|
Object.defineProperty(type, "_debugInfo", {
|
||||||
|
configurable: !1,
|
||||||
|
enumerable: !1,
|
||||||
|
writable: !0,
|
||||||
|
value: null
|
||||||
|
});
|
||||||
|
Object.defineProperty(type, "_debugStack", {
|
||||||
|
configurable: !1,
|
||||||
|
enumerable: !1,
|
||||||
|
writable: !0,
|
||||||
|
value: debugStack
|
||||||
|
});
|
||||||
|
Object.defineProperty(type, "_debugTask", {
|
||||||
|
configurable: !1,
|
||||||
|
enumerable: !1,
|
||||||
|
writable: !0,
|
||||||
|
value: debugTask
|
||||||
|
});
|
||||||
|
Object.freeze && (Object.freeze(type.props), Object.freeze(type));
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
function jsxDEVImpl(type, config, maybeKey, isStaticChildren, debugStack, debugTask) {
|
||||||
|
var children = config.children;
|
||||||
|
if (void 0 !== children) if (isStaticChildren) if (isArrayImpl(children)) {
|
||||||
|
for (isStaticChildren = 0; isStaticChildren < children.length; isStaticChildren++) validateChildKeys(children[isStaticChildren]);
|
||||||
|
Object.freeze && Object.freeze(children);
|
||||||
|
} else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");
|
||||||
|
else validateChildKeys(children);
|
||||||
|
if (hasOwnProperty.call(config, "key")) {
|
||||||
|
children = getComponentNameFromType(type);
|
||||||
|
var keys = Object.keys(config).filter(function(k) {
|
||||||
|
return "key" !== k;
|
||||||
|
});
|
||||||
|
isStaticChildren = 0 < keys.length ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" : "{key: someKey}";
|
||||||
|
didWarnAboutKeySpread[children + isStaticChildren] || (keys = 0 < keys.length ? "{" + keys.join(": ..., ") + ": ...}" : "{}", console.error("A props object containing a \"key\" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />", isStaticChildren, children, keys, children), didWarnAboutKeySpread[children + isStaticChildren] = !0);
|
||||||
|
}
|
||||||
|
children = null;
|
||||||
|
void 0 !== maybeKey && (checkKeyStringCoercion(maybeKey), children = "" + maybeKey);
|
||||||
|
hasValidKey(config) && (checkKeyStringCoercion(config.key), children = "" + config.key);
|
||||||
|
if ("key" in config) {
|
||||||
|
maybeKey = {};
|
||||||
|
for (var propName in config) "key" !== propName && (maybeKey[propName] = config[propName]);
|
||||||
|
} else maybeKey = config;
|
||||||
|
children && defineKeyPropWarningGetter(maybeKey, "function" === typeof type ? type.displayName || type.name || "Unknown" : type);
|
||||||
|
return ReactElement(type, children, maybeKey, getOwner(), debugStack, debugTask);
|
||||||
|
}
|
||||||
|
function validateChildKeys(node) {
|
||||||
|
isValidElement(node) ? node._store && (node._store.validated = 1) : "object" === typeof node && null !== node && node.$$typeof === REACT_LAZY_TYPE && ("fulfilled" === node._payload.status ? isValidElement(node._payload.value) && node._payload.value._store && (node._payload.value._store.validated = 1) : node._store && (node._store.validated = 1));
|
||||||
|
}
|
||||||
|
function isValidElement(object) {
|
||||||
|
return "object" === typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
|
||||||
|
}
|
||||||
|
var React = require_react(), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
React = { react_stack_bottom_frame: function(callStackForError) {
|
||||||
|
return callStackForError();
|
||||||
|
} };
|
||||||
|
var specialPropKeyWarningShown;
|
||||||
|
var didWarnAboutElementRef = {};
|
||||||
|
var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(React, UnknownOwner)();
|
||||||
|
var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
|
||||||
|
var didWarnAboutKeySpread = {};
|
||||||
|
exports.Fragment = REACT_FRAGMENT_TYPE;
|
||||||
|
exports.jsxDEV = function(type, config, maybeKey, isStaticChildren) {
|
||||||
|
var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
|
||||||
|
return jsxDEVImpl(type, config, maybeKey, isStaticChildren, trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack, trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask);
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
}));
|
||||||
|
//#endregion
|
||||||
|
//#region node_modules/react/jsx-dev-runtime.js
|
||||||
|
var require_jsx_dev_runtime = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
||||||
|
module.exports = require_react_jsx_dev_runtime_development();
|
||||||
|
}));
|
||||||
|
//#endregion
|
||||||
|
export default require_jsx_dev_runtime();
|
||||||
|
|
||||||
|
//# sourceMappingURL=react_jsx-dev-runtime.js.map
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.vite/deps/react_jsx-dev-runtime.js.map
generated
vendored
Normal file
208
fotograf-de-scraper/frontend/node_modules/.vite/deps/react_jsx-runtime.js
generated
vendored
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
import { n as __commonJSMin, t as require_react } from "./react-Na5-BvaJ.js";
|
||||||
|
//#region node_modules/react/cjs/react-jsx-runtime.development.js
|
||||||
|
/**
|
||||||
|
* @license React
|
||||||
|
* react-jsx-runtime.development.js
|
||||||
|
*
|
||||||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
var require_react_jsx_runtime_development = /* @__PURE__ */ __commonJSMin(((exports) => {
|
||||||
|
(function() {
|
||||||
|
function getComponentNameFromType(type) {
|
||||||
|
if (null == type) return null;
|
||||||
|
if ("function" === typeof type) return type.$$typeof === REACT_CLIENT_REFERENCE ? null : type.displayName || type.name || null;
|
||||||
|
if ("string" === typeof type) return type;
|
||||||
|
switch (type) {
|
||||||
|
case REACT_FRAGMENT_TYPE: return "Fragment";
|
||||||
|
case REACT_PROFILER_TYPE: return "Profiler";
|
||||||
|
case REACT_STRICT_MODE_TYPE: return "StrictMode";
|
||||||
|
case REACT_SUSPENSE_TYPE: return "Suspense";
|
||||||
|
case REACT_SUSPENSE_LIST_TYPE: return "SuspenseList";
|
||||||
|
case REACT_ACTIVITY_TYPE: return "Activity";
|
||||||
|
}
|
||||||
|
if ("object" === typeof type) switch ("number" === typeof type.tag && console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), type.$$typeof) {
|
||||||
|
case REACT_PORTAL_TYPE: return "Portal";
|
||||||
|
case REACT_CONTEXT_TYPE: return type.displayName || "Context";
|
||||||
|
case REACT_CONSUMER_TYPE: return (type._context.displayName || "Context") + ".Consumer";
|
||||||
|
case REACT_FORWARD_REF_TYPE:
|
||||||
|
var innerType = type.render;
|
||||||
|
type = type.displayName;
|
||||||
|
type || (type = innerType.displayName || innerType.name || "", type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef");
|
||||||
|
return type;
|
||||||
|
case REACT_MEMO_TYPE: return innerType = type.displayName || null, null !== innerType ? innerType : getComponentNameFromType(type.type) || "Memo";
|
||||||
|
case REACT_LAZY_TYPE:
|
||||||
|
innerType = type._payload;
|
||||||
|
type = type._init;
|
||||||
|
try {
|
||||||
|
return getComponentNameFromType(type(innerType));
|
||||||
|
} catch (x) {}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function testStringCoercion(value) {
|
||||||
|
return "" + value;
|
||||||
|
}
|
||||||
|
function checkKeyStringCoercion(value) {
|
||||||
|
try {
|
||||||
|
testStringCoercion(value);
|
||||||
|
var JSCompiler_inline_result = !1;
|
||||||
|
} catch (e) {
|
||||||
|
JSCompiler_inline_result = !0;
|
||||||
|
}
|
||||||
|
if (JSCompiler_inline_result) {
|
||||||
|
JSCompiler_inline_result = console;
|
||||||
|
var JSCompiler_temp_const = JSCompiler_inline_result.error;
|
||||||
|
var JSCompiler_inline_result$jscomp$0 = "function" === typeof Symbol && Symbol.toStringTag && value[Symbol.toStringTag] || value.constructor.name || "Object";
|
||||||
|
JSCompiler_temp_const.call(JSCompiler_inline_result, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", JSCompiler_inline_result$jscomp$0);
|
||||||
|
return testStringCoercion(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getTaskName(type) {
|
||||||
|
if (type === REACT_FRAGMENT_TYPE) return "<>";
|
||||||
|
if ("object" === typeof type && null !== type && type.$$typeof === REACT_LAZY_TYPE) return "<...>";
|
||||||
|
try {
|
||||||
|
var name = getComponentNameFromType(type);
|
||||||
|
return name ? "<" + name + ">" : "<...>";
|
||||||
|
} catch (x) {
|
||||||
|
return "<...>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getOwner() {
|
||||||
|
var dispatcher = ReactSharedInternals.A;
|
||||||
|
return null === dispatcher ? null : dispatcher.getOwner();
|
||||||
|
}
|
||||||
|
function UnknownOwner() {
|
||||||
|
return Error("react-stack-top-frame");
|
||||||
|
}
|
||||||
|
function hasValidKey(config) {
|
||||||
|
if (hasOwnProperty.call(config, "key")) {
|
||||||
|
var getter = Object.getOwnPropertyDescriptor(config, "key").get;
|
||||||
|
if (getter && getter.isReactWarning) return !1;
|
||||||
|
}
|
||||||
|
return void 0 !== config.key;
|
||||||
|
}
|
||||||
|
function defineKeyPropWarningGetter(props, displayName) {
|
||||||
|
function warnAboutAccessingKey() {
|
||||||
|
specialPropKeyWarningShown || (specialPropKeyWarningShown = !0, console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", displayName));
|
||||||
|
}
|
||||||
|
warnAboutAccessingKey.isReactWarning = !0;
|
||||||
|
Object.defineProperty(props, "key", {
|
||||||
|
get: warnAboutAccessingKey,
|
||||||
|
configurable: !0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function elementRefGetterWithDeprecationWarning() {
|
||||||
|
var componentName = getComponentNameFromType(this.type);
|
||||||
|
didWarnAboutElementRef[componentName] || (didWarnAboutElementRef[componentName] = !0, console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."));
|
||||||
|
componentName = this.props.ref;
|
||||||
|
return void 0 !== componentName ? componentName : null;
|
||||||
|
}
|
||||||
|
function ReactElement(type, key, props, owner, debugStack, debugTask) {
|
||||||
|
var refProp = props.ref;
|
||||||
|
type = {
|
||||||
|
$$typeof: REACT_ELEMENT_TYPE,
|
||||||
|
type,
|
||||||
|
key,
|
||||||
|
props,
|
||||||
|
_owner: owner
|
||||||
|
};
|
||||||
|
null !== (void 0 !== refProp ? refProp : null) ? Object.defineProperty(type, "ref", {
|
||||||
|
enumerable: !1,
|
||||||
|
get: elementRefGetterWithDeprecationWarning
|
||||||
|
}) : Object.defineProperty(type, "ref", {
|
||||||
|
enumerable: !1,
|
||||||
|
value: null
|
||||||
|
});
|
||||||
|
type._store = {};
|
||||||
|
Object.defineProperty(type._store, "validated", {
|
||||||
|
configurable: !1,
|
||||||
|
enumerable: !1,
|
||||||
|
writable: !0,
|
||||||
|
value: 0
|
||||||
|
});
|
||||||
|
Object.defineProperty(type, "_debugInfo", {
|
||||||
|
configurable: !1,
|
||||||
|
enumerable: !1,
|
||||||
|
writable: !0,
|
||||||
|
value: null
|
||||||
|
});
|
||||||
|
Object.defineProperty(type, "_debugStack", {
|
||||||
|
configurable: !1,
|
||||||
|
enumerable: !1,
|
||||||
|
writable: !0,
|
||||||
|
value: debugStack
|
||||||
|
});
|
||||||
|
Object.defineProperty(type, "_debugTask", {
|
||||||
|
configurable: !1,
|
||||||
|
enumerable: !1,
|
||||||
|
writable: !0,
|
||||||
|
value: debugTask
|
||||||
|
});
|
||||||
|
Object.freeze && (Object.freeze(type.props), Object.freeze(type));
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
function jsxDEVImpl(type, config, maybeKey, isStaticChildren, debugStack, debugTask) {
|
||||||
|
var children = config.children;
|
||||||
|
if (void 0 !== children) if (isStaticChildren) if (isArrayImpl(children)) {
|
||||||
|
for (isStaticChildren = 0; isStaticChildren < children.length; isStaticChildren++) validateChildKeys(children[isStaticChildren]);
|
||||||
|
Object.freeze && Object.freeze(children);
|
||||||
|
} else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");
|
||||||
|
else validateChildKeys(children);
|
||||||
|
if (hasOwnProperty.call(config, "key")) {
|
||||||
|
children = getComponentNameFromType(type);
|
||||||
|
var keys = Object.keys(config).filter(function(k) {
|
||||||
|
return "key" !== k;
|
||||||
|
});
|
||||||
|
isStaticChildren = 0 < keys.length ? "{key: someKey, " + keys.join(": ..., ") + ": ...}" : "{key: someKey}";
|
||||||
|
didWarnAboutKeySpread[children + isStaticChildren] || (keys = 0 < keys.length ? "{" + keys.join(": ..., ") + ": ...}" : "{}", console.error("A props object containing a \"key\" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />", isStaticChildren, children, keys, children), didWarnAboutKeySpread[children + isStaticChildren] = !0);
|
||||||
|
}
|
||||||
|
children = null;
|
||||||
|
void 0 !== maybeKey && (checkKeyStringCoercion(maybeKey), children = "" + maybeKey);
|
||||||
|
hasValidKey(config) && (checkKeyStringCoercion(config.key), children = "" + config.key);
|
||||||
|
if ("key" in config) {
|
||||||
|
maybeKey = {};
|
||||||
|
for (var propName in config) "key" !== propName && (maybeKey[propName] = config[propName]);
|
||||||
|
} else maybeKey = config;
|
||||||
|
children && defineKeyPropWarningGetter(maybeKey, "function" === typeof type ? type.displayName || type.name || "Unknown" : type);
|
||||||
|
return ReactElement(type, children, maybeKey, getOwner(), debugStack, debugTask);
|
||||||
|
}
|
||||||
|
function validateChildKeys(node) {
|
||||||
|
isValidElement(node) ? node._store && (node._store.validated = 1) : "object" === typeof node && null !== node && node.$$typeof === REACT_LAZY_TYPE && ("fulfilled" === node._payload.status ? isValidElement(node._payload.value) && node._payload.value._store && (node._payload.value._store.validated = 1) : node._store && (node._store.validated = 1));
|
||||||
|
}
|
||||||
|
function isValidElement(object) {
|
||||||
|
return "object" === typeof object && null !== object && object.$$typeof === REACT_ELEMENT_TYPE;
|
||||||
|
}
|
||||||
|
var React = require_react(), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
React = { react_stack_bottom_frame: function(callStackForError) {
|
||||||
|
return callStackForError();
|
||||||
|
} };
|
||||||
|
var specialPropKeyWarningShown;
|
||||||
|
var didWarnAboutElementRef = {};
|
||||||
|
var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(React, UnknownOwner)();
|
||||||
|
var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
|
||||||
|
var didWarnAboutKeySpread = {};
|
||||||
|
exports.Fragment = REACT_FRAGMENT_TYPE;
|
||||||
|
exports.jsx = function(type, config, maybeKey) {
|
||||||
|
var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
|
||||||
|
return jsxDEVImpl(type, config, maybeKey, !1, trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack, trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask);
|
||||||
|
};
|
||||||
|
exports.jsxs = function(type, config, maybeKey) {
|
||||||
|
var trackActualOwner = 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
|
||||||
|
return jsxDEVImpl(type, config, maybeKey, !0, trackActualOwner ? Error("react-stack-top-frame") : unknownOwnerDebugStack, trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask);
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
}));
|
||||||
|
//#endregion
|
||||||
|
//#region node_modules/react/jsx-runtime.js
|
||||||
|
var require_jsx_runtime = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
||||||
|
module.exports = require_react_jsx_runtime_development();
|
||||||
|
}));
|
||||||
|
//#endregion
|
||||||
|
export default require_jsx_runtime();
|
||||||
|
|
||||||
|
//# sourceMappingURL=react_jsx-runtime.js.map
|
||||||
1
fotograf-de-scraper/frontend/node_modules/.vite/deps/react_jsx-runtime.js.map
generated
vendored
Normal file
128
fotograf-de-scraper/frontend/node_modules/@alloc/quick-lru/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
declare namespace QuickLRU {
|
||||||
|
interface Options<KeyType, ValueType> {
|
||||||
|
/**
|
||||||
|
The maximum number of milliseconds an item should remain in the cache.
|
||||||
|
|
||||||
|
@default Infinity
|
||||||
|
|
||||||
|
By default, `maxAge` will be `Infinity`, which means that items will never expire.
|
||||||
|
Lazy expiration upon the next write or read call.
|
||||||
|
|
||||||
|
Individual expiration of an item can be specified by the `set(key, value, maxAge)` method.
|
||||||
|
*/
|
||||||
|
readonly maxAge?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The maximum number of items before evicting the least recently used items.
|
||||||
|
*/
|
||||||
|
readonly maxSize: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Called right before an item is evicted from the cache.
|
||||||
|
|
||||||
|
Useful for side effects or for items like object URLs that need explicit cleanup (`revokeObjectURL`).
|
||||||
|
*/
|
||||||
|
onEviction?: (key: KeyType, value: ValueType) => void;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare class QuickLRU<KeyType, ValueType>
|
||||||
|
implements Iterable<[KeyType, ValueType]> {
|
||||||
|
/**
|
||||||
|
The stored item count.
|
||||||
|
*/
|
||||||
|
readonly size: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Simple ["Least Recently Used" (LRU) cache](https://en.m.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29).
|
||||||
|
|
||||||
|
The instance is [`iterable`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) so you can use it directly in a [`for…of`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of) loop.
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import QuickLRU = require('quick-lru');
|
||||||
|
|
||||||
|
const lru = new QuickLRU({maxSize: 1000});
|
||||||
|
|
||||||
|
lru.set('🦄', '🌈');
|
||||||
|
|
||||||
|
lru.has('🦄');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
lru.get('🦄');
|
||||||
|
//=> '🌈'
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
constructor(options: QuickLRU.Options<KeyType, ValueType>);
|
||||||
|
|
||||||
|
[Symbol.iterator](): IterableIterator<[KeyType, ValueType]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set an item. Returns the instance.
|
||||||
|
|
||||||
|
Individual expiration of an item can be specified with the `maxAge` option. If not specified, the global `maxAge` value will be used in case it is specified in the constructor, otherwise the item will never expire.
|
||||||
|
|
||||||
|
@returns The list instance.
|
||||||
|
*/
|
||||||
|
set(key: KeyType, value: ValueType, options?: {maxAge?: number}): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get an item.
|
||||||
|
|
||||||
|
@returns The stored item or `undefined`.
|
||||||
|
*/
|
||||||
|
get(key: KeyType): ValueType | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if an item exists.
|
||||||
|
*/
|
||||||
|
has(key: KeyType): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get an item without marking it as recently used.
|
||||||
|
|
||||||
|
@returns The stored item or `undefined`.
|
||||||
|
*/
|
||||||
|
peek(key: KeyType): ValueType | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Delete an item.
|
||||||
|
|
||||||
|
@returns `true` if the item is removed or `false` if the item doesn't exist.
|
||||||
|
*/
|
||||||
|
delete(key: KeyType): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Delete all items.
|
||||||
|
*/
|
||||||
|
clear(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update the `maxSize` in-place, discarding items as necessary. Insertion order is mostly preserved, though this is not a strong guarantee.
|
||||||
|
|
||||||
|
Useful for on-the-fly tuning of cache sizes in live systems.
|
||||||
|
*/
|
||||||
|
resize(maxSize: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Iterable for all the keys.
|
||||||
|
*/
|
||||||
|
keys(): IterableIterator<KeyType>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Iterable for all the values.
|
||||||
|
*/
|
||||||
|
values(): IterableIterator<ValueType>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Iterable for all entries, starting with the oldest (ascending in recency).
|
||||||
|
*/
|
||||||
|
entriesAscending(): IterableIterator<[KeyType, ValueType]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Iterable for all entries, starting with the newest (descending in recency).
|
||||||
|
*/
|
||||||
|
entriesDescending(): IterableIterator<[KeyType, ValueType]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export = QuickLRU;
|
||||||
263
fotograf-de-scraper/frontend/node_modules/@alloc/quick-lru/index.js
generated
vendored
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
class QuickLRU {
|
||||||
|
constructor(options = {}) {
|
||||||
|
if (!(options.maxSize && options.maxSize > 0)) {
|
||||||
|
throw new TypeError('`maxSize` must be a number greater than 0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof options.maxAge === 'number' && options.maxAge === 0) {
|
||||||
|
throw new TypeError('`maxAge` must be a number greater than 0');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.maxSize = options.maxSize;
|
||||||
|
this.maxAge = options.maxAge || Infinity;
|
||||||
|
this.onEviction = options.onEviction;
|
||||||
|
this.cache = new Map();
|
||||||
|
this.oldCache = new Map();
|
||||||
|
this._size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_emitEvictions(cache) {
|
||||||
|
if (typeof this.onEviction !== 'function') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [key, item] of cache) {
|
||||||
|
this.onEviction(key, item.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_deleteIfExpired(key, item) {
|
||||||
|
if (typeof item.expiry === 'number' && item.expiry <= Date.now()) {
|
||||||
|
if (typeof this.onEviction === 'function') {
|
||||||
|
this.onEviction(key, item.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_getOrDeleteIfExpired(key, item) {
|
||||||
|
const deleted = this._deleteIfExpired(key, item);
|
||||||
|
if (deleted === false) {
|
||||||
|
return item.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_getItemValue(key, item) {
|
||||||
|
return item.expiry ? this._getOrDeleteIfExpired(key, item) : item.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
_peek(key, cache) {
|
||||||
|
const item = cache.get(key);
|
||||||
|
|
||||||
|
return this._getItemValue(key, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
_set(key, value) {
|
||||||
|
this.cache.set(key, value);
|
||||||
|
this._size++;
|
||||||
|
|
||||||
|
if (this._size >= this.maxSize) {
|
||||||
|
this._size = 0;
|
||||||
|
this._emitEvictions(this.oldCache);
|
||||||
|
this.oldCache = this.cache;
|
||||||
|
this.cache = new Map();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_moveToRecent(key, item) {
|
||||||
|
this.oldCache.delete(key);
|
||||||
|
this._set(key, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
* _entriesAscending() {
|
||||||
|
for (const item of this.oldCache) {
|
||||||
|
const [key, value] = item;
|
||||||
|
if (!this.cache.has(key)) {
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const item of this.cache) {
|
||||||
|
const [key, value] = item;
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get(key) {
|
||||||
|
if (this.cache.has(key)) {
|
||||||
|
const item = this.cache.get(key);
|
||||||
|
|
||||||
|
return this._getItemValue(key, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.oldCache.has(key)) {
|
||||||
|
const item = this.oldCache.get(key);
|
||||||
|
if (this._deleteIfExpired(key, item) === false) {
|
||||||
|
this._moveToRecent(key, item);
|
||||||
|
return item.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set(key, value, {maxAge = this.maxAge === Infinity ? undefined : Date.now() + this.maxAge} = {}) {
|
||||||
|
if (this.cache.has(key)) {
|
||||||
|
this.cache.set(key, {
|
||||||
|
value,
|
||||||
|
maxAge
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this._set(key, {value, expiry: maxAge});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
has(key) {
|
||||||
|
if (this.cache.has(key)) {
|
||||||
|
return !this._deleteIfExpired(key, this.cache.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.oldCache.has(key)) {
|
||||||
|
return !this._deleteIfExpired(key, this.oldCache.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
peek(key) {
|
||||||
|
if (this.cache.has(key)) {
|
||||||
|
return this._peek(key, this.cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.oldCache.has(key)) {
|
||||||
|
return this._peek(key, this.oldCache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(key) {
|
||||||
|
const deleted = this.cache.delete(key);
|
||||||
|
if (deleted) {
|
||||||
|
this._size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.oldCache.delete(key) || deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.cache.clear();
|
||||||
|
this.oldCache.clear();
|
||||||
|
this._size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
resize(newSize) {
|
||||||
|
if (!(newSize && newSize > 0)) {
|
||||||
|
throw new TypeError('`maxSize` must be a number greater than 0');
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = [...this._entriesAscending()];
|
||||||
|
const removeCount = items.length - newSize;
|
||||||
|
if (removeCount < 0) {
|
||||||
|
this.cache = new Map(items);
|
||||||
|
this.oldCache = new Map();
|
||||||
|
this._size = items.length;
|
||||||
|
} else {
|
||||||
|
if (removeCount > 0) {
|
||||||
|
this._emitEvictions(items.slice(0, removeCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.oldCache = new Map(items.slice(removeCount));
|
||||||
|
this.cache = new Map();
|
||||||
|
this._size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.maxSize = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
* keys() {
|
||||||
|
for (const [key] of this) {
|
||||||
|
yield key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* values() {
|
||||||
|
for (const [, value] of this) {
|
||||||
|
yield value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* [Symbol.iterator]() {
|
||||||
|
for (const item of this.cache) {
|
||||||
|
const [key, value] = item;
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const item of this.oldCache) {
|
||||||
|
const [key, value] = item;
|
||||||
|
if (!this.cache.has(key)) {
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* entriesDescending() {
|
||||||
|
let items = [...this.cache];
|
||||||
|
for (let i = items.length - 1; i >= 0; --i) {
|
||||||
|
const item = items[i];
|
||||||
|
const [key, value] = item;
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
items = [...this.oldCache];
|
||||||
|
for (let i = items.length - 1; i >= 0; --i) {
|
||||||
|
const item = items[i];
|
||||||
|
const [key, value] = item;
|
||||||
|
if (!this.cache.has(key)) {
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* entriesAscending() {
|
||||||
|
for (const [key, value] of this._entriesAscending()) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get size() {
|
||||||
|
if (!this._size) {
|
||||||
|
return this.oldCache.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
let oldCacheSize = 0;
|
||||||
|
for (const key of this.oldCache.keys()) {
|
||||||
|
if (!this.cache.has(key)) {
|
||||||
|
oldCacheSize++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.min(this._size + oldCacheSize, this.maxSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = QuickLRU;
|
||||||
9
fotograf-de-scraper/frontend/node_modules/@alloc/quick-lru/license
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
43
fotograf-de-scraper/frontend/node_modules/@alloc/quick-lru/package.json
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"name": "@alloc/quick-lru",
|
||||||
|
"version": "5.2.0",
|
||||||
|
"description": "Simple “Least Recently Used” (LRU) cache",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "sindresorhus/quick-lru",
|
||||||
|
"funding": "https://github.com/sponsors/sindresorhus",
|
||||||
|
"author": {
|
||||||
|
"name": "Sindre Sorhus",
|
||||||
|
"email": "sindresorhus@gmail.com",
|
||||||
|
"url": "https://sindresorhus.com"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "xo && nyc ava && tsd"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"index.js",
|
||||||
|
"index.d.ts"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"lru",
|
||||||
|
"quick",
|
||||||
|
"cache",
|
||||||
|
"caching",
|
||||||
|
"least",
|
||||||
|
"recently",
|
||||||
|
"used",
|
||||||
|
"fast",
|
||||||
|
"map",
|
||||||
|
"hash",
|
||||||
|
"buffer"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"ava": "^2.0.0",
|
||||||
|
"coveralls": "^3.0.3",
|
||||||
|
"nyc": "^15.0.0",
|
||||||
|
"tsd": "^0.11.0",
|
||||||
|
"xo": "^0.26.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
139
fotograf-de-scraper/frontend/node_modules/@alloc/quick-lru/readme.md
generated
vendored
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
# quick-lru [](https://travis-ci.org/sindresorhus/quick-lru) [](https://coveralls.io/github/sindresorhus/quick-lru?branch=master)
|
||||||
|
|
||||||
|
> Simple [“Least Recently Used” (LRU) cache](https://en.m.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29)
|
||||||
|
|
||||||
|
Useful when you need to cache something and limit memory usage.
|
||||||
|
|
||||||
|
Inspired by the [`hashlru` algorithm](https://github.com/dominictarr/hashlru#algorithm), but instead uses [`Map`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map) to support keys of any type, not just strings, and values can be `undefined`.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm install quick-lru
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
const QuickLRU = require('quick-lru');
|
||||||
|
|
||||||
|
const lru = new QuickLRU({maxSize: 1000});
|
||||||
|
|
||||||
|
lru.set('🦄', '🌈');
|
||||||
|
|
||||||
|
lru.has('🦄');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
lru.get('🦄');
|
||||||
|
//=> '🌈'
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### new QuickLRU(options?)
|
||||||
|
|
||||||
|
Returns a new instance.
|
||||||
|
|
||||||
|
### options
|
||||||
|
|
||||||
|
Type: `object`
|
||||||
|
|
||||||
|
#### maxSize
|
||||||
|
|
||||||
|
*Required*\
|
||||||
|
Type: `number`
|
||||||
|
|
||||||
|
The maximum number of items before evicting the least recently used items.
|
||||||
|
|
||||||
|
#### maxAge
|
||||||
|
|
||||||
|
Type: `number`\
|
||||||
|
Default: `Infinity`
|
||||||
|
|
||||||
|
The maximum number of milliseconds an item should remain in cache.
|
||||||
|
By default maxAge will be Infinity, which means that items will never expire.
|
||||||
|
|
||||||
|
Lazy expiration happens upon the next `write` or `read` call.
|
||||||
|
|
||||||
|
Individual expiration of an item can be specified by the `set(key, value, options)` method.
|
||||||
|
|
||||||
|
#### onEviction
|
||||||
|
|
||||||
|
*Optional*\
|
||||||
|
Type: `(key, value) => void`
|
||||||
|
|
||||||
|
Called right before an item is evicted from the cache.
|
||||||
|
|
||||||
|
Useful for side effects or for items like object URLs that need explicit cleanup (`revokeObjectURL`).
|
||||||
|
|
||||||
|
### Instance
|
||||||
|
|
||||||
|
The instance is [`iterable`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) so you can use it directly in a [`for…of`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of) loop.
|
||||||
|
|
||||||
|
Both `key` and `value` can be of any type.
|
||||||
|
|
||||||
|
#### .set(key, value, options?)
|
||||||
|
|
||||||
|
Set an item. Returns the instance.
|
||||||
|
|
||||||
|
Individual expiration of an item can be specified with the `maxAge` option. If not specified, the global `maxAge` value will be used in case it is specified on the constructor, otherwise the item will never expire.
|
||||||
|
|
||||||
|
#### .get(key)
|
||||||
|
|
||||||
|
Get an item.
|
||||||
|
|
||||||
|
#### .has(key)
|
||||||
|
|
||||||
|
Check if an item exists.
|
||||||
|
|
||||||
|
#### .peek(key)
|
||||||
|
|
||||||
|
Get an item without marking it as recently used.
|
||||||
|
|
||||||
|
#### .delete(key)
|
||||||
|
|
||||||
|
Delete an item.
|
||||||
|
|
||||||
|
Returns `true` if the item is removed or `false` if the item doesn't exist.
|
||||||
|
|
||||||
|
#### .clear()
|
||||||
|
|
||||||
|
Delete all items.
|
||||||
|
|
||||||
|
#### .resize(maxSize)
|
||||||
|
|
||||||
|
Update the `maxSize`, discarding items as necessary. Insertion order is mostly preserved, though this is not a strong guarantee.
|
||||||
|
|
||||||
|
Useful for on-the-fly tuning of cache sizes in live systems.
|
||||||
|
|
||||||
|
#### .keys()
|
||||||
|
|
||||||
|
Iterable for all the keys.
|
||||||
|
|
||||||
|
#### .values()
|
||||||
|
|
||||||
|
Iterable for all the values.
|
||||||
|
|
||||||
|
#### .entriesAscending()
|
||||||
|
|
||||||
|
Iterable for all entries, starting with the oldest (ascending in recency).
|
||||||
|
|
||||||
|
#### .entriesDescending()
|
||||||
|
|
||||||
|
Iterable for all entries, starting with the newest (descending in recency).
|
||||||
|
|
||||||
|
#### .size
|
||||||
|
|
||||||
|
The stored item count.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<b>
|
||||||
|
<a href="https://tidelift.com/subscription/pkg/npm-quick-lru?utm_source=npm-quick-lru&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
|
||||||
|
</b>
|
||||||
|
<br>
|
||||||
|
<sub>
|
||||||
|
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
|
||||||
|
</sub>
|
||||||
|
</div>
|
||||||
22
fotograf-de-scraper/frontend/node_modules/@babel/code-frame/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
19
fotograf-de-scraper/frontend/node_modules/@babel/code-frame/README.md
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# @babel/code-frame
|
||||||
|
|
||||||
|
> Generate errors that contain a code frame that point to source locations.
|
||||||
|
|
||||||
|
See our website [@babel/code-frame](https://babeljs.io/docs/babel-code-frame) for more information.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
Using npm:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save-dev @babel/code-frame
|
||||||
|
```
|
||||||
|
|
||||||
|
or using yarn:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn add @babel/code-frame --dev
|
||||||
|
```
|
||||||
217
fotograf-de-scraper/frontend/node_modules/@babel/code-frame/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true });
|
||||||
|
|
||||||
|
var picocolors = require('picocolors');
|
||||||
|
var jsTokens = require('js-tokens');
|
||||||
|
var helperValidatorIdentifier = require('@babel/helper-validator-identifier');
|
||||||
|
|
||||||
|
function isColorSupported() {
|
||||||
|
return (typeof process === "object" && (process.env.FORCE_COLOR === "0" || process.env.FORCE_COLOR === "false") ? false : picocolors.isColorSupported
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const compose = (f, g) => v => f(g(v));
|
||||||
|
function buildDefs(colors) {
|
||||||
|
return {
|
||||||
|
keyword: colors.cyan,
|
||||||
|
capitalized: colors.yellow,
|
||||||
|
jsxIdentifier: colors.yellow,
|
||||||
|
punctuator: colors.yellow,
|
||||||
|
number: colors.magenta,
|
||||||
|
string: colors.green,
|
||||||
|
regex: colors.magenta,
|
||||||
|
comment: colors.gray,
|
||||||
|
invalid: compose(compose(colors.white, colors.bgRed), colors.bold),
|
||||||
|
gutter: colors.gray,
|
||||||
|
marker: compose(colors.red, colors.bold),
|
||||||
|
message: compose(colors.red, colors.bold),
|
||||||
|
reset: colors.reset
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const defsOn = buildDefs(picocolors.createColors(true));
|
||||||
|
const defsOff = buildDefs(picocolors.createColors(false));
|
||||||
|
function getDefs(enabled) {
|
||||||
|
return enabled ? defsOn : defsOff;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sometimesKeywords = new Set(["as", "async", "from", "get", "of", "set"]);
|
||||||
|
const NEWLINE$1 = /\r\n|[\n\r\u2028\u2029]/;
|
||||||
|
const BRACKET = /^[()[\]{}]$/;
|
||||||
|
let tokenize;
|
||||||
|
const JSX_TAG = /^[a-z][\w-]*$/i;
|
||||||
|
const getTokenType = function (token, offset, text) {
|
||||||
|
if (token.type === "name") {
|
||||||
|
const tokenValue = token.value;
|
||||||
|
if (helperValidatorIdentifier.isKeyword(tokenValue) || helperValidatorIdentifier.isStrictReservedWord(tokenValue, true) || sometimesKeywords.has(tokenValue)) {
|
||||||
|
return "keyword";
|
||||||
|
}
|
||||||
|
if (JSX_TAG.test(tokenValue) && (text[offset - 1] === "<" || text.slice(offset - 2, offset) === "</")) {
|
||||||
|
return "jsxIdentifier";
|
||||||
|
}
|
||||||
|
const firstChar = String.fromCodePoint(tokenValue.codePointAt(0));
|
||||||
|
if (firstChar !== firstChar.toLowerCase()) {
|
||||||
|
return "capitalized";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (token.type === "punctuator" && BRACKET.test(token.value)) {
|
||||||
|
return "bracket";
|
||||||
|
}
|
||||||
|
if (token.type === "invalid" && (token.value === "@" || token.value === "#")) {
|
||||||
|
return "punctuator";
|
||||||
|
}
|
||||||
|
return token.type;
|
||||||
|
};
|
||||||
|
tokenize = function* (text) {
|
||||||
|
let match;
|
||||||
|
while (match = jsTokens.default.exec(text)) {
|
||||||
|
const token = jsTokens.matchToToken(match);
|
||||||
|
yield {
|
||||||
|
type: getTokenType(token, match.index, text),
|
||||||
|
value: token.value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function highlight(text) {
|
||||||
|
if (text === "") return "";
|
||||||
|
const defs = getDefs(true);
|
||||||
|
let highlighted = "";
|
||||||
|
for (const {
|
||||||
|
type,
|
||||||
|
value
|
||||||
|
} of tokenize(text)) {
|
||||||
|
if (type in defs) {
|
||||||
|
highlighted += value.split(NEWLINE$1).map(str => defs[type](str)).join("\n");
|
||||||
|
} else {
|
||||||
|
highlighted += value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return highlighted;
|
||||||
|
}
|
||||||
|
|
||||||
|
let deprecationWarningShown = false;
|
||||||
|
const NEWLINE = /\r\n|[\n\r\u2028\u2029]/;
|
||||||
|
function getMarkerLines(loc, source, opts, startLineBaseZero) {
|
||||||
|
const startLoc = Object.assign({
|
||||||
|
column: 0,
|
||||||
|
line: -1
|
||||||
|
}, loc.start);
|
||||||
|
const endLoc = Object.assign({}, startLoc, loc.end);
|
||||||
|
const {
|
||||||
|
linesAbove = 2,
|
||||||
|
linesBelow = 3
|
||||||
|
} = opts || {};
|
||||||
|
const startLine = startLoc.line - startLineBaseZero;
|
||||||
|
const startColumn = startLoc.column;
|
||||||
|
const endLine = endLoc.line - startLineBaseZero;
|
||||||
|
const endColumn = endLoc.column;
|
||||||
|
let start = Math.max(startLine - (linesAbove + 1), 0);
|
||||||
|
let end = Math.min(source.length, endLine + linesBelow);
|
||||||
|
if (startLine === -1) {
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
if (endLine === -1) {
|
||||||
|
end = source.length;
|
||||||
|
}
|
||||||
|
const lineDiff = endLine - startLine;
|
||||||
|
const markerLines = {};
|
||||||
|
if (lineDiff) {
|
||||||
|
for (let i = 0; i <= lineDiff; i++) {
|
||||||
|
const lineNumber = i + startLine;
|
||||||
|
if (!startColumn) {
|
||||||
|
markerLines[lineNumber] = true;
|
||||||
|
} else if (i === 0) {
|
||||||
|
const sourceLength = source[lineNumber - 1].length;
|
||||||
|
markerLines[lineNumber] = [startColumn, sourceLength - startColumn + 1];
|
||||||
|
} else if (i === lineDiff) {
|
||||||
|
markerLines[lineNumber] = [0, endColumn];
|
||||||
|
} else {
|
||||||
|
const sourceLength = source[lineNumber - i].length;
|
||||||
|
markerLines[lineNumber] = [0, sourceLength];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (startColumn === endColumn) {
|
||||||
|
if (startColumn) {
|
||||||
|
markerLines[startLine] = [startColumn, 0];
|
||||||
|
} else {
|
||||||
|
markerLines[startLine] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
markerLines[startLine] = [startColumn, endColumn - startColumn];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
markerLines
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function codeFrameColumns(rawLines, loc, opts = {}) {
|
||||||
|
const shouldHighlight = opts.forceColor || isColorSupported() && opts.highlightCode;
|
||||||
|
const startLineBaseZero = (opts.startLine || 1) - 1;
|
||||||
|
const defs = getDefs(shouldHighlight);
|
||||||
|
const lines = rawLines.split(NEWLINE);
|
||||||
|
const {
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
markerLines
|
||||||
|
} = getMarkerLines(loc, lines, opts, startLineBaseZero);
|
||||||
|
const hasColumns = loc.start && typeof loc.start.column === "number";
|
||||||
|
const numberMaxWidth = String(end + startLineBaseZero).length;
|
||||||
|
const highlightedLines = shouldHighlight ? highlight(rawLines) : rawLines;
|
||||||
|
let frame = highlightedLines.split(NEWLINE, end).slice(start, end).map((line, index) => {
|
||||||
|
const number = start + 1 + index;
|
||||||
|
const paddedNumber = ` ${number + startLineBaseZero}`.slice(-numberMaxWidth);
|
||||||
|
const gutter = ` ${paddedNumber} |`;
|
||||||
|
const hasMarker = markerLines[number];
|
||||||
|
const lastMarkerLine = !markerLines[number + 1];
|
||||||
|
if (hasMarker) {
|
||||||
|
let markerLine = "";
|
||||||
|
if (Array.isArray(hasMarker)) {
|
||||||
|
const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replace(/[^\t]/g, " ");
|
||||||
|
const numberOfMarkers = hasMarker[1] || 1;
|
||||||
|
markerLine = ["\n ", defs.gutter(gutter.replace(/\d/g, " ")), " ", markerSpacing, defs.marker("^").repeat(numberOfMarkers)].join("");
|
||||||
|
if (lastMarkerLine && opts.message) {
|
||||||
|
markerLine += " " + defs.message(opts.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [defs.marker(">"), defs.gutter(gutter), line.length > 0 ? ` ${line}` : "", markerLine].join("");
|
||||||
|
} else {
|
||||||
|
return ` ${defs.gutter(gutter)}${line.length > 0 ? ` ${line}` : ""}`;
|
||||||
|
}
|
||||||
|
}).join("\n");
|
||||||
|
if (opts.message && !hasColumns) {
|
||||||
|
frame = `${" ".repeat(numberMaxWidth + 1)}${opts.message}\n${frame}`;
|
||||||
|
}
|
||||||
|
if (shouldHighlight) {
|
||||||
|
return defs.reset(frame);
|
||||||
|
} else {
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function index (rawLines, lineNumber, colNumber, opts = {}) {
|
||||||
|
if (!deprecationWarningShown) {
|
||||||
|
deprecationWarningShown = true;
|
||||||
|
const message = "Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`.";
|
||||||
|
if (process.emitWarning) {
|
||||||
|
process.emitWarning(message, "DeprecationWarning");
|
||||||
|
} else {
|
||||||
|
const deprecationError = new Error(message);
|
||||||
|
deprecationError.name = "DeprecationWarning";
|
||||||
|
console.warn(new Error(message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
colNumber = Math.max(colNumber, 0);
|
||||||
|
const location = {
|
||||||
|
start: {
|
||||||
|
column: colNumber,
|
||||||
|
line: lineNumber
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return codeFrameColumns(rawLines, location, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.codeFrameColumns = codeFrameColumns;
|
||||||
|
exports.default = index;
|
||||||
|
exports.highlight = highlight;
|
||||||
|
//# sourceMappingURL=index.js.map
|
||||||
1
fotograf-de-scraper/frontend/node_modules/@babel/code-frame/lib/index.js.map
generated
vendored
Normal file
32
fotograf-de-scraper/frontend/node_modules/@babel/code-frame/package.json
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "@babel/code-frame",
|
||||||
|
"version": "7.29.0",
|
||||||
|
"description": "Generate errors that contain a code frame that point to source locations.",
|
||||||
|
"author": "The Babel Team (https://babel.dev/team)",
|
||||||
|
"homepage": "https://babel.dev/docs/en/next/babel-code-frame",
|
||||||
|
"bugs": "https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen",
|
||||||
|
"license": "MIT",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/babel/babel.git",
|
||||||
|
"directory": "packages/babel-code-frame"
|
||||||
|
},
|
||||||
|
"main": "./lib/index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-validator-identifier": "^7.28.5",
|
||||||
|
"js-tokens": "^4.0.0",
|
||||||
|
"picocolors": "^1.1.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"charcodes": "^0.2.0",
|
||||||
|
"import-meta-resolve": "^4.1.0",
|
||||||
|
"strip-ansi": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
},
|
||||||
|
"type": "commonjs"
|
||||||
|
}
|
||||||
22
fotograf-de-scraper/frontend/node_modules/@babel/compat-data/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
19
fotograf-de-scraper/frontend/node_modules/@babel/compat-data/README.md
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# @babel/compat-data
|
||||||
|
|
||||||
|
> The compat-data to determine required Babel plugins
|
||||||
|
|
||||||
|
See our website [@babel/compat-data](https://babeljs.io/docs/babel-compat-data) for more information.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
Using npm:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save @babel/compat-data
|
||||||
|
```
|
||||||
|
|
||||||
|
or using yarn:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn add @babel/compat-data
|
||||||
|
```
|
||||||
2
fotograf-de-scraper/frontend/node_modules/@babel/compat-data/corejs2-built-ins.js
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Todo (Babel 8): remove this file as Babel 8 drop support of core-js 2
|
||||||
|
module.exports = require("./data/corejs2-built-ins.json");
|
||||||
2
fotograf-de-scraper/frontend/node_modules/@babel/compat-data/corejs3-shipped-proposals.js
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Todo (Babel 8): remove this file now that it is included in babel-plugin-polyfill-corejs3
|
||||||
|
module.exports = require("./data/corejs3-shipped-proposals.json");
|
||||||
2
fotograf-de-scraper/frontend/node_modules/@babel/compat-data/native-modules.js
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Todo (Babel 8): remove this file, in Babel 8 users import the .json directly
|
||||||
|
module.exports = require("./data/native-modules.json");
|
||||||