Showing
9 changed files
with
815 additions
and
10 deletions
| @@ -16,6 +16,16 @@ from pydantic import BaseModel, Field, ConfigDict | @@ -16,6 +16,16 @@ from pydantic import BaseModel, Field, ConfigDict | ||
| 16 | import logging | 16 | import logging |
| 17 | from PIL import Image | 17 | from PIL import Image |
| 18 | import io | 18 | import io |
| 19 | +import sys | ||
| 20 | + | ||
| 21 | +# Add parent directory to path to import middleware | ||
| 22 | +sys.path.append(str(Path(__file__).parent.parent)) | ||
| 23 | +try: | ||
| 24 | + from middleware import IPFilterMiddleware | ||
| 25 | +except ImportError: | ||
| 26 | + # Fallback/Dummy if not found (should be found) | ||
| 27 | + IPFilterMiddleware = None | ||
| 28 | + | ||
| 19 | 29 | ||
| 20 | # --- Constants --- | 30 | # --- Constants --- |
| 21 | logger = logging.getLogger("uvicorn.error") | 31 | logger = logging.getLogger("uvicorn.error") |
| @@ -313,6 +323,11 @@ usage_store = UsageStore(USAGE_PATH) | @@ -313,6 +323,11 @@ usage_store = UsageStore(USAGE_PATH) | ||
| 313 | 323 | ||
| 314 | # --- App Setup --- | 324 | # --- App Setup --- |
| 315 | app = FastAPI(title="Z-Image Proxy", version="1.0.0") | 325 | app = FastAPI(title="Z-Image Proxy", version="1.0.0") |
| 326 | + | ||
| 327 | +# IP Filter Middleware (Add BEFORE CORS to block early) | ||
| 328 | +if IPFilterMiddleware: | ||
| 329 | + app.add_middleware(IPFilterMiddleware) | ||
| 330 | + | ||
| 316 | from fastapi.staticfiles import StaticFiles | 331 | from fastapi.staticfiles import StaticFiles |
| 317 | # Mount public directory to serve thumbnails and frontend config | 332 | # Mount public directory to serve thumbnails and frontend config |
| 318 | app.mount("/thumbnails", StaticFiles(directory=str(Path(__file__).parent.parent / "public" / "thumbnails")), name="thumbnails") | 333 | app.mount("/thumbnails", StaticFiles(directory=str(Path(__file__).parent.parent / "public" / "thumbnails")), name="thumbnails") |
| @@ -15,13 +15,15 @@ module.exports = { | @@ -15,13 +15,15 @@ module.exports = { | ||
| 15 | }, | 15 | }, |
| 16 | { | 16 | { |
| 17 | name: process.env.FRONTEND_NAME || "z-image-frontend", | 17 | name: process.env.FRONTEND_NAME || "z-image-frontend", |
| 18 | - script: "serve", | 18 | + script: "./venv/bin/python", |
| 19 | + args: "frontend_server.py", | ||
| 20 | + cwd: __dirname, | ||
| 21 | + interpreter: "none", | ||
| 22 | + autorestart: true, | ||
| 23 | + watch: false, | ||
| 19 | env: { | 24 | env: { |
| 20 | - // Use LOCAL_FRONTEND_PORT from environment, default to 7001 | ||
| 21 | - PM2_SERVE_PATH: path.join(__dirname, 'z-image-generator/dist'), | ||
| 22 | - PM2_SERVE_PORT: process.env.LOCAL_FRONTEND_PORT || 7001, | ||
| 23 | - PM2_SERVE_SPA: 'true', | ||
| 24 | - PM2_SERVE_HOMEPAGE: '/index.html' | 25 | + LOCAL_FRONTEND_PORT: process.env.LOCAL_FRONTEND_PORT || 7001, |
| 26 | + ENABLE_IP_FILTER: process.env.ENABLE_IP_FILTER | ||
| 25 | } | 27 | } |
| 26 | } | 28 | } |
| 27 | ] | 29 | ] |
frontend_server.py
0 → 100644
| 1 | +import os | ||
| 2 | +from fastapi import FastAPI | ||
| 3 | +from fastapi.staticfiles import StaticFiles | ||
| 4 | +from fastapi.responses import FileResponse | ||
| 5 | +from middleware import IPFilterMiddleware | ||
| 6 | + | ||
| 7 | +app = FastAPI() | ||
| 8 | + | ||
| 9 | +# Add IP Filter Middleware | ||
| 10 | +app.add_middleware(IPFilterMiddleware) | ||
| 11 | + | ||
| 12 | +# Frontend Dist Path | ||
| 13 | +DIST_DIR = os.path.join(os.path.dirname(__file__), "z-image-generator", "dist") | ||
| 14 | + | ||
| 15 | +# Ensure dist exists | ||
| 16 | +if not os.path.exists(DIST_DIR): | ||
| 17 | + os.makedirs(DIST_DIR, exist_ok=True) | ||
| 18 | + # Create a dummy index.html if not exists for testing | ||
| 19 | + with open(os.path.join(DIST_DIR, "index.html"), "w") as f: | ||
| 20 | + f.write("<h1>Frontend Build Not Found</h1>") | ||
| 21 | + | ||
| 22 | +# Serve Static Files | ||
| 23 | +# We mount root to serve static files, BUT we need SPA fallback. | ||
| 24 | +# Solution: Mount specific assets folder, and use a catch-all for index.html | ||
| 25 | + | ||
| 26 | +# 1. Mount /assets if it exists in dist | ||
| 27 | +assets_path = os.path.join(DIST_DIR, "assets") | ||
| 28 | +if os.path.exists(assets_path): | ||
| 29 | + app.mount("/assets", StaticFiles(directory=assets_path), name="assets") | ||
| 30 | + | ||
| 31 | +# 2. Serve other static files (like favicon, etc) if needed? | ||
| 32 | +# For simplicity, we just use a catch-all route to serve index.html or the file if it exists | ||
| 33 | +@app.get("/{full_path:path}") | ||
| 34 | +async def serve_spa(full_path: str): | ||
| 35 | + # Check if file exists in dist | ||
| 36 | + file_path = os.path.join(DIST_DIR, full_path) | ||
| 37 | + if os.path.exists(file_path) and os.path.isfile(file_path): | ||
| 38 | + return FileResponse(file_path) | ||
| 39 | + | ||
| 40 | + # Fallback to index.html for SPA | ||
| 41 | + # Disable cache for index.html to ensure updates are seen immediately | ||
| 42 | + response = FileResponse(os.path.join(DIST_DIR, "index.html")) | ||
| 43 | + response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" | ||
| 44 | + response.headers["Pragma"] = "no-cache" | ||
| 45 | + response.headers["Expires"] = "0" | ||
| 46 | + return response | ||
| 47 | + | ||
| 48 | +if __name__ == "__main__": | ||
| 49 | + import uvicorn | ||
| 50 | + # Read port from env or default | ||
| 51 | + port = int(os.getenv("LOCAL_FRONTEND_PORT", "7001")) | ||
| 52 | + uvicorn.run(app, host="0.0.0.0", port=port) |
middleware.py
0 → 100644
| 1 | +import os | ||
| 2 | +import time | ||
| 3 | +import logging | ||
| 4 | +from logging.handlers import RotatingFileHandler | ||
| 5 | +from datetime import datetime | ||
| 6 | +from typing import Optional, Tuple | ||
| 7 | +from fastapi import Request, HTTPException, Response | ||
| 8 | +from starlette.middleware.base import BaseHTTPMiddleware | ||
| 9 | +from starlette.responses import JSONResponse, PlainTextResponse | ||
| 10 | +import httpx | ||
| 11 | + | ||
| 12 | +# Configuration | ||
| 13 | +ENABLE_IP_FILTER = os.getenv("ENABLE_IP_FILTER", "false").lower() == "true" | ||
| 14 | +LOG_FILE = os.path.join(os.path.expanduser("~"), ".pm2", "logs", "access_monitor.log") | ||
| 15 | + | ||
| 16 | +# Setup Logger | ||
| 17 | +logger = logging.getLogger("access_monitor") | ||
| 18 | +logger.setLevel(logging.INFO) | ||
| 19 | +formatter = logging.Formatter('%(message)s') | ||
| 20 | + | ||
| 21 | +# Use RotatingFileHandler instead of FileHandler | ||
| 22 | +# maxBytes=10MB, backupCount=10 (Max storage ~100MB) | ||
| 23 | +file_handler = RotatingFileHandler(LOG_FILE, maxBytes=10*1024*1024, backupCount=10, encoding='utf-8') | ||
| 24 | +file_handler.setFormatter(formatter) | ||
| 25 | +logger.addHandler(file_handler) | ||
| 26 | + | ||
| 27 | +# IP Cache: {ip: {"is_cn": bool, "location": str, "timestamp": float}} | ||
| 28 | +IP_CACHE = {} | ||
| 29 | + | ||
| 30 | +async def get_ip_info(ip: str) -> Tuple[bool, str]: | ||
| 31 | + """ | ||
| 32 | + Check if IP is from China and get location. | ||
| 33 | + Returns (is_cn, location_string) | ||
| 34 | + """ | ||
| 35 | + # Localhost / Private IP checks | ||
| 36 | + if ip == "127.0.0.1" or ip == "::1" or ip.startswith("192.168.") or ip.startswith("10."): | ||
| 37 | + return True, "Local Network" | ||
| 38 | + | ||
| 39 | + # Check Cache | ||
| 40 | + if ip in IP_CACHE: | ||
| 41 | + # Cache for 24 hours | ||
| 42 | + if time.time() - IP_CACHE[ip]["timestamp"] < 86400: | ||
| 43 | + return IP_CACHE[ip]["is_cn"], IP_CACHE[ip]["location"] | ||
| 44 | + | ||
| 45 | + # Query API | ||
| 46 | + # Using ip-api.com (free, non-commercial use, 45 req/min) | ||
| 47 | + # Lang=zh-CN for Chinese output | ||
| 48 | + url = f"http://ip-api.com/json/{ip}?lang=zh-CN&fields=status,countryCode,country,regionName,city" | ||
| 49 | + | ||
| 50 | + try: | ||
| 51 | + async with httpx.AsyncClient(timeout=3.0) as client: | ||
| 52 | + resp = await client.get(url) | ||
| 53 | + data = resp.json() | ||
| 54 | + | ||
| 55 | + if data.get("status") == "success": | ||
| 56 | + is_cn = data.get("countryCode") == "CN" | ||
| 57 | + location = f"{data.get('country')}-{data.get('regionName')}-{data.get('city')}" | ||
| 58 | + | ||
| 59 | + # Update Cache | ||
| 60 | + IP_CACHE[ip] = { | ||
| 61 | + "is_cn": is_cn, | ||
| 62 | + "location": location, | ||
| 63 | + "timestamp": time.time() | ||
| 64 | + } | ||
| 65 | + return is_cn, location | ||
| 66 | + else: | ||
| 67 | + # API failed or private IP | ||
| 68 | + return True, "Unknown/Private" | ||
| 69 | + | ||
| 70 | + except Exception as e: | ||
| 71 | + print(f"IP Lookup failed for {ip}: {e}") | ||
| 72 | + # Fail open (allow access) if API fails | ||
| 73 | + return True, "Lookup Failed" | ||
| 74 | + | ||
| 75 | +class IPFilterMiddleware(BaseHTTPMiddleware): | ||
| 76 | + async def dispatch(self, request: Request, call_next): | ||
| 77 | + start_time = time.time() | ||
| 78 | + | ||
| 79 | + # Get Client IP | ||
| 80 | + # X-Forwarded-For is preferred if behind proxy (like Nginx), but here we might be direct or behind pm2 | ||
| 81 | + forwarded = request.headers.get("X-Forwarded-For") | ||
| 82 | + if forwarded: | ||
| 83 | + client_ip = forwarded.split(",")[0] | ||
| 84 | + else: | ||
| 85 | + client_ip = request.client.host if request.client else "unknown" | ||
| 86 | + | ||
| 87 | + # Determine Port (Local port server is listening on) | ||
| 88 | + server_port = request.scope.get("server", ("", "unknown"))[1] | ||
| 89 | + | ||
| 90 | + # IP Lookup | ||
| 91 | + is_allowed = True | ||
| 92 | + location = "Unknown" | ||
| 93 | + | ||
| 94 | + # Optimize: Skip static assets logs to reduce noise? | ||
| 95 | + # Requirement says "Add record access IP log", implies all or relevant ones. | ||
| 96 | + # We will log everything for now or filter ext. | ||
| 97 | + | ||
| 98 | + is_cn, location = await get_ip_info(client_ip) | ||
| 99 | + | ||
| 100 | + if ENABLE_IP_FILTER and not is_cn: | ||
| 101 | + is_allowed = False | ||
| 102 | + | ||
| 103 | + # Explicit check for HK/TW/MO if they somehow pass as CN (though API shouldn't do that) | ||
| 104 | + # or if user wants double security. | ||
| 105 | + # Based on ip-api.com, 'HK', 'TW', 'MO' are country codes, not 'CN'. | ||
| 106 | + # So 'is_cn' check above is sufficient. | ||
| 107 | + | ||
| 108 | + # DEBUG: Log if we are blocking to ensure config works | ||
| 109 | + if not is_allowed: | ||
| 110 | + print(f"[BLOCK] Blocked {client_ip} ({location})") | ||
| 111 | + | ||
| 112 | + # Access Time | ||
| 113 | + access_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | ||
| 114 | + | ||
| 115 | + # Log Format: IP | Location | Time | Port | Path | Allowed | ||
| 116 | + log_msg = f"{client_ip} | {location} | {access_time} | {server_port} | {request.url.path} | {'ALLOWED' if is_allowed else 'BLOCKED'}" | ||
| 117 | + logger.info(log_msg) | ||
| 118 | + | ||
| 119 | + if not is_allowed: | ||
| 120 | + return PlainTextResponse("Access Denied: Mainland China IP Required", status_code=403) | ||
| 121 | + | ||
| 122 | + response = await call_next(request) | ||
| 123 | + return response |
| @@ -10,6 +10,9 @@ else | @@ -10,6 +10,9 @@ else | ||
| 10 | exit 1 | 10 | exit 1 |
| 11 | fi | 11 | fi |
| 12 | 12 | ||
| 13 | +# IP Filter Switch (Default to true for security) | ||
| 14 | +export ENABLE_IP_FILTER="${ENABLE_IP_FILTER:-true}" | ||
| 15 | + | ||
| 13 | # Bypass proxy for local connections | 16 | # Bypass proxy for local connections |
| 14 | export no_proxy="localhost,127.0.0.1,0.0.0.0,::1" | 17 | export no_proxy="localhost,127.0.0.1,0.0.0.0,::1" |
| 15 | export NO_PROXY="localhost,127.0.0.1,0.0.0.0,::1" | 18 | export NO_PROXY="localhost,127.0.0.1,0.0.0.0,::1" |
| @@ -13,6 +13,7 @@ | @@ -13,6 +13,7 @@ | ||
| 13 | "react-dom": "^19.2.3" | 13 | "react-dom": "^19.2.3" |
| 14 | }, | 14 | }, |
| 15 | "devDependencies": { | 15 | "devDependencies": { |
| 16 | + "@tailwindcss/postcss": "^4.1.18", | ||
| 16 | "@types/node": "^22.14.0", | 17 | "@types/node": "^22.14.0", |
| 17 | "@vitejs/plugin-react": "^5.0.0", | 18 | "@vitejs/plugin-react": "^5.0.0", |
| 18 | "autoprefixer": "^10.4.24", | 19 | "autoprefixer": "^10.4.24", |
| @@ -22,6 +23,19 @@ | @@ -22,6 +23,19 @@ | ||
| 22 | "vite": "^6.2.0" | 23 | "vite": "^6.2.0" |
| 23 | } | 24 | } |
| 24 | }, | 25 | }, |
| 26 | + "node_modules/@alloc/quick-lru": { | ||
| 27 | + "version": "5.2.0", | ||
| 28 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", | ||
| 29 | + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", | ||
| 30 | + "dev": true, | ||
| 31 | + "license": "MIT", | ||
| 32 | + "engines": { | ||
| 33 | + "node": ">=10" | ||
| 34 | + }, | ||
| 35 | + "funding": { | ||
| 36 | + "url": "https://github.com/sponsors/sindresorhus" | ||
| 37 | + } | ||
| 38 | + }, | ||
| 25 | "node_modules/@babel/code-frame": { | 39 | "node_modules/@babel/code-frame": { |
| 26 | "version": "7.27.1", | 40 | "version": "7.27.1", |
| 27 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", | 41 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", |
| @@ -1111,6 +1125,277 @@ | @@ -1111,6 +1125,277 @@ | ||
| 1111 | "win32" | 1125 | "win32" |
| 1112 | ] | 1126 | ] |
| 1113 | }, | 1127 | }, |
| 1128 | + "node_modules/@tailwindcss/node": { | ||
| 1129 | + "version": "4.1.18", | ||
| 1130 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/node/-/node-4.1.18.tgz", | ||
| 1131 | + "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==", | ||
| 1132 | + "dev": true, | ||
| 1133 | + "license": "MIT", | ||
| 1134 | + "dependencies": { | ||
| 1135 | + "@jridgewell/remapping": "^2.3.4", | ||
| 1136 | + "enhanced-resolve": "^5.18.3", | ||
| 1137 | + "jiti": "^2.6.1", | ||
| 1138 | + "lightningcss": "1.30.2", | ||
| 1139 | + "magic-string": "^0.30.21", | ||
| 1140 | + "source-map-js": "^1.2.1", | ||
| 1141 | + "tailwindcss": "4.1.18" | ||
| 1142 | + } | ||
| 1143 | + }, | ||
| 1144 | + "node_modules/@tailwindcss/oxide": { | ||
| 1145 | + "version": "4.1.18", | ||
| 1146 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/oxide/-/oxide-4.1.18.tgz", | ||
| 1147 | + "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==", | ||
| 1148 | + "dev": true, | ||
| 1149 | + "license": "MIT", | ||
| 1150 | + "engines": { | ||
| 1151 | + "node": ">= 10" | ||
| 1152 | + }, | ||
| 1153 | + "optionalDependencies": { | ||
| 1154 | + "@tailwindcss/oxide-android-arm64": "4.1.18", | ||
| 1155 | + "@tailwindcss/oxide-darwin-arm64": "4.1.18", | ||
| 1156 | + "@tailwindcss/oxide-darwin-x64": "4.1.18", | ||
| 1157 | + "@tailwindcss/oxide-freebsd-x64": "4.1.18", | ||
| 1158 | + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", | ||
| 1159 | + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", | ||
| 1160 | + "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", | ||
| 1161 | + "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", | ||
| 1162 | + "@tailwindcss/oxide-linux-x64-musl": "4.1.18", | ||
| 1163 | + "@tailwindcss/oxide-wasm32-wasi": "4.1.18", | ||
| 1164 | + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", | ||
| 1165 | + "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" | ||
| 1166 | + } | ||
| 1167 | + }, | ||
| 1168 | + "node_modules/@tailwindcss/oxide-android-arm64": { | ||
| 1169 | + "version": "4.1.18", | ||
| 1170 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz", | ||
| 1171 | + "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==", | ||
| 1172 | + "cpu": [ | ||
| 1173 | + "arm64" | ||
| 1174 | + ], | ||
| 1175 | + "dev": true, | ||
| 1176 | + "license": "MIT", | ||
| 1177 | + "optional": true, | ||
| 1178 | + "os": [ | ||
| 1179 | + "android" | ||
| 1180 | + ], | ||
| 1181 | + "engines": { | ||
| 1182 | + "node": ">= 10" | ||
| 1183 | + } | ||
| 1184 | + }, | ||
| 1185 | + "node_modules/@tailwindcss/oxide-darwin-arm64": { | ||
| 1186 | + "version": "4.1.18", | ||
| 1187 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz", | ||
| 1188 | + "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==", | ||
| 1189 | + "cpu": [ | ||
| 1190 | + "arm64" | ||
| 1191 | + ], | ||
| 1192 | + "dev": true, | ||
| 1193 | + "license": "MIT", | ||
| 1194 | + "optional": true, | ||
| 1195 | + "os": [ | ||
| 1196 | + "darwin" | ||
| 1197 | + ], | ||
| 1198 | + "engines": { | ||
| 1199 | + "node": ">= 10" | ||
| 1200 | + } | ||
| 1201 | + }, | ||
| 1202 | + "node_modules/@tailwindcss/oxide-darwin-x64": { | ||
| 1203 | + "version": "4.1.18", | ||
| 1204 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz", | ||
| 1205 | + "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==", | ||
| 1206 | + "cpu": [ | ||
| 1207 | + "x64" | ||
| 1208 | + ], | ||
| 1209 | + "dev": true, | ||
| 1210 | + "license": "MIT", | ||
| 1211 | + "optional": true, | ||
| 1212 | + "os": [ | ||
| 1213 | + "darwin" | ||
| 1214 | + ], | ||
| 1215 | + "engines": { | ||
| 1216 | + "node": ">= 10" | ||
| 1217 | + } | ||
| 1218 | + }, | ||
| 1219 | + "node_modules/@tailwindcss/oxide-freebsd-x64": { | ||
| 1220 | + "version": "4.1.18", | ||
| 1221 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz", | ||
| 1222 | + "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==", | ||
| 1223 | + "cpu": [ | ||
| 1224 | + "x64" | ||
| 1225 | + ], | ||
| 1226 | + "dev": true, | ||
| 1227 | + "license": "MIT", | ||
| 1228 | + "optional": true, | ||
| 1229 | + "os": [ | ||
| 1230 | + "freebsd" | ||
| 1231 | + ], | ||
| 1232 | + "engines": { | ||
| 1233 | + "node": ">= 10" | ||
| 1234 | + } | ||
| 1235 | + }, | ||
| 1236 | + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { | ||
| 1237 | + "version": "4.1.18", | ||
| 1238 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz", | ||
| 1239 | + "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==", | ||
| 1240 | + "cpu": [ | ||
| 1241 | + "arm" | ||
| 1242 | + ], | ||
| 1243 | + "dev": true, | ||
| 1244 | + "license": "MIT", | ||
| 1245 | + "optional": true, | ||
| 1246 | + "os": [ | ||
| 1247 | + "linux" | ||
| 1248 | + ], | ||
| 1249 | + "engines": { | ||
| 1250 | + "node": ">= 10" | ||
| 1251 | + } | ||
| 1252 | + }, | ||
| 1253 | + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { | ||
| 1254 | + "version": "4.1.18", | ||
| 1255 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz", | ||
| 1256 | + "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==", | ||
| 1257 | + "cpu": [ | ||
| 1258 | + "arm64" | ||
| 1259 | + ], | ||
| 1260 | + "dev": true, | ||
| 1261 | + "license": "MIT", | ||
| 1262 | + "optional": true, | ||
| 1263 | + "os": [ | ||
| 1264 | + "linux" | ||
| 1265 | + ], | ||
| 1266 | + "engines": { | ||
| 1267 | + "node": ">= 10" | ||
| 1268 | + } | ||
| 1269 | + }, | ||
| 1270 | + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { | ||
| 1271 | + "version": "4.1.18", | ||
| 1272 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz", | ||
| 1273 | + "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==", | ||
| 1274 | + "cpu": [ | ||
| 1275 | + "arm64" | ||
| 1276 | + ], | ||
| 1277 | + "dev": true, | ||
| 1278 | + "license": "MIT", | ||
| 1279 | + "optional": true, | ||
| 1280 | + "os": [ | ||
| 1281 | + "linux" | ||
| 1282 | + ], | ||
| 1283 | + "engines": { | ||
| 1284 | + "node": ">= 10" | ||
| 1285 | + } | ||
| 1286 | + }, | ||
| 1287 | + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { | ||
| 1288 | + "version": "4.1.18", | ||
| 1289 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz", | ||
| 1290 | + "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==", | ||
| 1291 | + "cpu": [ | ||
| 1292 | + "x64" | ||
| 1293 | + ], | ||
| 1294 | + "dev": true, | ||
| 1295 | + "license": "MIT", | ||
| 1296 | + "optional": true, | ||
| 1297 | + "os": [ | ||
| 1298 | + "linux" | ||
| 1299 | + ], | ||
| 1300 | + "engines": { | ||
| 1301 | + "node": ">= 10" | ||
| 1302 | + } | ||
| 1303 | + }, | ||
| 1304 | + "node_modules/@tailwindcss/oxide-linux-x64-musl": { | ||
| 1305 | + "version": "4.1.18", | ||
| 1306 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz", | ||
| 1307 | + "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==", | ||
| 1308 | + "cpu": [ | ||
| 1309 | + "x64" | ||
| 1310 | + ], | ||
| 1311 | + "dev": true, | ||
| 1312 | + "license": "MIT", | ||
| 1313 | + "optional": true, | ||
| 1314 | + "os": [ | ||
| 1315 | + "linux" | ||
| 1316 | + ], | ||
| 1317 | + "engines": { | ||
| 1318 | + "node": ">= 10" | ||
| 1319 | + } | ||
| 1320 | + }, | ||
| 1321 | + "node_modules/@tailwindcss/oxide-wasm32-wasi": { | ||
| 1322 | + "version": "4.1.18", | ||
| 1323 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz", | ||
| 1324 | + "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==", | ||
| 1325 | + "bundleDependencies": [ | ||
| 1326 | + "@napi-rs/wasm-runtime", | ||
| 1327 | + "@emnapi/core", | ||
| 1328 | + "@emnapi/runtime", | ||
| 1329 | + "@tybys/wasm-util", | ||
| 1330 | + "@emnapi/wasi-threads", | ||
| 1331 | + "tslib" | ||
| 1332 | + ], | ||
| 1333 | + "cpu": [ | ||
| 1334 | + "wasm32" | ||
| 1335 | + ], | ||
| 1336 | + "dev": true, | ||
| 1337 | + "license": "MIT", | ||
| 1338 | + "optional": true, | ||
| 1339 | + "dependencies": { | ||
| 1340 | + "@emnapi/core": "^1.7.1", | ||
| 1341 | + "@emnapi/runtime": "^1.7.1", | ||
| 1342 | + "@emnapi/wasi-threads": "^1.1.0", | ||
| 1343 | + "@napi-rs/wasm-runtime": "^1.1.0", | ||
| 1344 | + "@tybys/wasm-util": "^0.10.1", | ||
| 1345 | + "tslib": "^2.4.0" | ||
| 1346 | + }, | ||
| 1347 | + "engines": { | ||
| 1348 | + "node": ">=14.0.0" | ||
| 1349 | + } | ||
| 1350 | + }, | ||
| 1351 | + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { | ||
| 1352 | + "version": "4.1.18", | ||
| 1353 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz", | ||
| 1354 | + "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==", | ||
| 1355 | + "cpu": [ | ||
| 1356 | + "arm64" | ||
| 1357 | + ], | ||
| 1358 | + "dev": true, | ||
| 1359 | + "license": "MIT", | ||
| 1360 | + "optional": true, | ||
| 1361 | + "os": [ | ||
| 1362 | + "win32" | ||
| 1363 | + ], | ||
| 1364 | + "engines": { | ||
| 1365 | + "node": ">= 10" | ||
| 1366 | + } | ||
| 1367 | + }, | ||
| 1368 | + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { | ||
| 1369 | + "version": "4.1.18", | ||
| 1370 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz", | ||
| 1371 | + "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==", | ||
| 1372 | + "cpu": [ | ||
| 1373 | + "x64" | ||
| 1374 | + ], | ||
| 1375 | + "dev": true, | ||
| 1376 | + "license": "MIT", | ||
| 1377 | + "optional": true, | ||
| 1378 | + "os": [ | ||
| 1379 | + "win32" | ||
| 1380 | + ], | ||
| 1381 | + "engines": { | ||
| 1382 | + "node": ">= 10" | ||
| 1383 | + } | ||
| 1384 | + }, | ||
| 1385 | + "node_modules/@tailwindcss/postcss": { | ||
| 1386 | + "version": "4.1.18", | ||
| 1387 | + "resolved": "https://repo.huaweicloud.com/repository/npm/@tailwindcss/postcss/-/postcss-4.1.18.tgz", | ||
| 1388 | + "integrity": "sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==", | ||
| 1389 | + "dev": true, | ||
| 1390 | + "license": "MIT", | ||
| 1391 | + "dependencies": { | ||
| 1392 | + "@alloc/quick-lru": "^5.2.0", | ||
| 1393 | + "@tailwindcss/node": "4.1.18", | ||
| 1394 | + "@tailwindcss/oxide": "4.1.18", | ||
| 1395 | + "postcss": "^8.4.41", | ||
| 1396 | + "tailwindcss": "4.1.18" | ||
| 1397 | + } | ||
| 1398 | + }, | ||
| 1114 | "node_modules/@types/babel__core": { | 1399 | "node_modules/@types/babel__core": { |
| 1115 | "version": "7.20.5", | 1400 | "version": "7.20.5", |
| 1116 | "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", | 1401 | "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", |
| @@ -1321,6 +1606,16 @@ | @@ -1321,6 +1606,16 @@ | ||
| 1321 | } | 1606 | } |
| 1322 | } | 1607 | } |
| 1323 | }, | 1608 | }, |
| 1609 | + "node_modules/detect-libc": { | ||
| 1610 | + "version": "2.1.2", | ||
| 1611 | + "resolved": "https://repo.huaweicloud.com/repository/npm/detect-libc/-/detect-libc-2.1.2.tgz", | ||
| 1612 | + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", | ||
| 1613 | + "dev": true, | ||
| 1614 | + "license": "Apache-2.0", | ||
| 1615 | + "engines": { | ||
| 1616 | + "node": ">=8" | ||
| 1617 | + } | ||
| 1618 | + }, | ||
| 1324 | "node_modules/electron-to-chromium": { | 1619 | "node_modules/electron-to-chromium": { |
| 1325 | "version": "1.5.267", | 1620 | "version": "1.5.267", |
| 1326 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", | 1621 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", |
| @@ -1328,6 +1623,20 @@ | @@ -1328,6 +1623,20 @@ | ||
| 1328 | "dev": true, | 1623 | "dev": true, |
| 1329 | "license": "ISC" | 1624 | "license": "ISC" |
| 1330 | }, | 1625 | }, |
| 1626 | + "node_modules/enhanced-resolve": { | ||
| 1627 | + "version": "5.19.0", | ||
| 1628 | + "resolved": "https://repo.huaweicloud.com/repository/npm/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", | ||
| 1629 | + "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", | ||
| 1630 | + "dev": true, | ||
| 1631 | + "license": "MIT", | ||
| 1632 | + "dependencies": { | ||
| 1633 | + "graceful-fs": "^4.2.4", | ||
| 1634 | + "tapable": "^2.3.0" | ||
| 1635 | + }, | ||
| 1636 | + "engines": { | ||
| 1637 | + "node": ">=10.13.0" | ||
| 1638 | + } | ||
| 1639 | + }, | ||
| 1331 | "node_modules/esbuild": { | 1640 | "node_modules/esbuild": { |
| 1332 | "version": "0.25.12", | 1641 | "version": "0.25.12", |
| 1333 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", | 1642 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", |
| @@ -1437,6 +1746,23 @@ | @@ -1437,6 +1746,23 @@ | ||
| 1437 | "node": ">=6.9.0" | 1746 | "node": ">=6.9.0" |
| 1438 | } | 1747 | } |
| 1439 | }, | 1748 | }, |
| 1749 | + "node_modules/graceful-fs": { | ||
| 1750 | + "version": "4.2.11", | ||
| 1751 | + "resolved": "https://repo.huaweicloud.com/repository/npm/graceful-fs/-/graceful-fs-4.2.11.tgz", | ||
| 1752 | + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", | ||
| 1753 | + "dev": true, | ||
| 1754 | + "license": "ISC" | ||
| 1755 | + }, | ||
| 1756 | + "node_modules/jiti": { | ||
| 1757 | + "version": "2.6.1", | ||
| 1758 | + "resolved": "https://repo.huaweicloud.com/repository/npm/jiti/-/jiti-2.6.1.tgz", | ||
| 1759 | + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", | ||
| 1760 | + "dev": true, | ||
| 1761 | + "license": "MIT", | ||
| 1762 | + "bin": { | ||
| 1763 | + "jiti": "lib/jiti-cli.mjs" | ||
| 1764 | + } | ||
| 1765 | + }, | ||
| 1440 | "node_modules/js-tokens": { | 1766 | "node_modules/js-tokens": { |
| 1441 | "version": "4.0.0", | 1767 | "version": "4.0.0", |
| 1442 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", | 1768 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", |
| @@ -1470,6 +1796,267 @@ | @@ -1470,6 +1796,267 @@ | ||
| 1470 | "node": ">=6" | 1796 | "node": ">=6" |
| 1471 | } | 1797 | } |
| 1472 | }, | 1798 | }, |
| 1799 | + "node_modules/lightningcss": { | ||
| 1800 | + "version": "1.30.2", | ||
| 1801 | + "resolved": "https://repo.huaweicloud.com/repository/npm/lightningcss/-/lightningcss-1.30.2.tgz", | ||
| 1802 | + "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", | ||
| 1803 | + "dev": true, | ||
| 1804 | + "license": "MPL-2.0", | ||
| 1805 | + "dependencies": { | ||
| 1806 | + "detect-libc": "^2.0.3" | ||
| 1807 | + }, | ||
| 1808 | + "engines": { | ||
| 1809 | + "node": ">= 12.0.0" | ||
| 1810 | + }, | ||
| 1811 | + "funding": { | ||
| 1812 | + "type": "opencollective", | ||
| 1813 | + "url": "https://opencollective.com/parcel" | ||
| 1814 | + }, | ||
| 1815 | + "optionalDependencies": { | ||
| 1816 | + "lightningcss-android-arm64": "1.30.2", | ||
| 1817 | + "lightningcss-darwin-arm64": "1.30.2", | ||
| 1818 | + "lightningcss-darwin-x64": "1.30.2", | ||
| 1819 | + "lightningcss-freebsd-x64": "1.30.2", | ||
| 1820 | + "lightningcss-linux-arm-gnueabihf": "1.30.2", | ||
| 1821 | + "lightningcss-linux-arm64-gnu": "1.30.2", | ||
| 1822 | + "lightningcss-linux-arm64-musl": "1.30.2", | ||
| 1823 | + "lightningcss-linux-x64-gnu": "1.30.2", | ||
| 1824 | + "lightningcss-linux-x64-musl": "1.30.2", | ||
| 1825 | + "lightningcss-win32-arm64-msvc": "1.30.2", | ||
| 1826 | + "lightningcss-win32-x64-msvc": "1.30.2" | ||
| 1827 | + } | ||
| 1828 | + }, | ||
| 1829 | + "node_modules/lightningcss-android-arm64": { | ||
| 1830 | + "version": "1.30.2", | ||
| 1831 | + "resolved": "https://repo.huaweicloud.com/repository/npm/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", | ||
| 1832 | + "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", | ||
| 1833 | + "cpu": [ | ||
| 1834 | + "arm64" | ||
| 1835 | + ], | ||
| 1836 | + "dev": true, | ||
| 1837 | + "license": "MPL-2.0", | ||
| 1838 | + "optional": true, | ||
| 1839 | + "os": [ | ||
| 1840 | + "android" | ||
| 1841 | + ], | ||
| 1842 | + "engines": { | ||
| 1843 | + "node": ">= 12.0.0" | ||
| 1844 | + }, | ||
| 1845 | + "funding": { | ||
| 1846 | + "type": "opencollective", | ||
| 1847 | + "url": "https://opencollective.com/parcel" | ||
| 1848 | + } | ||
| 1849 | + }, | ||
| 1850 | + "node_modules/lightningcss-darwin-arm64": { | ||
| 1851 | + "version": "1.30.2", | ||
| 1852 | + "resolved": "https://repo.huaweicloud.com/repository/npm/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", | ||
| 1853 | + "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", | ||
| 1854 | + "cpu": [ | ||
| 1855 | + "arm64" | ||
| 1856 | + ], | ||
| 1857 | + "dev": true, | ||
| 1858 | + "license": "MPL-2.0", | ||
| 1859 | + "optional": true, | ||
| 1860 | + "os": [ | ||
| 1861 | + "darwin" | ||
| 1862 | + ], | ||
| 1863 | + "engines": { | ||
| 1864 | + "node": ">= 12.0.0" | ||
| 1865 | + }, | ||
| 1866 | + "funding": { | ||
| 1867 | + "type": "opencollective", | ||
| 1868 | + "url": "https://opencollective.com/parcel" | ||
| 1869 | + } | ||
| 1870 | + }, | ||
| 1871 | + "node_modules/lightningcss-darwin-x64": { | ||
| 1872 | + "version": "1.30.2", | ||
| 1873 | + "resolved": "https://repo.huaweicloud.com/repository/npm/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", | ||
| 1874 | + "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", | ||
| 1875 | + "cpu": [ | ||
| 1876 | + "x64" | ||
| 1877 | + ], | ||
| 1878 | + "dev": true, | ||
| 1879 | + "license": "MPL-2.0", | ||
| 1880 | + "optional": true, | ||
| 1881 | + "os": [ | ||
| 1882 | + "darwin" | ||
| 1883 | + ], | ||
| 1884 | + "engines": { | ||
| 1885 | + "node": ">= 12.0.0" | ||
| 1886 | + }, | ||
| 1887 | + "funding": { | ||
| 1888 | + "type": "opencollective", | ||
| 1889 | + "url": "https://opencollective.com/parcel" | ||
| 1890 | + } | ||
| 1891 | + }, | ||
| 1892 | + "node_modules/lightningcss-freebsd-x64": { | ||
| 1893 | + "version": "1.30.2", | ||
| 1894 | + "resolved": "https://repo.huaweicloud.com/repository/npm/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", | ||
| 1895 | + "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", | ||
| 1896 | + "cpu": [ | ||
| 1897 | + "x64" | ||
| 1898 | + ], | ||
| 1899 | + "dev": true, | ||
| 1900 | + "license": "MPL-2.0", | ||
| 1901 | + "optional": true, | ||
| 1902 | + "os": [ | ||
| 1903 | + "freebsd" | ||
| 1904 | + ], | ||
| 1905 | + "engines": { | ||
| 1906 | + "node": ">= 12.0.0" | ||
| 1907 | + }, | ||
| 1908 | + "funding": { | ||
| 1909 | + "type": "opencollective", | ||
| 1910 | + "url": "https://opencollective.com/parcel" | ||
| 1911 | + } | ||
| 1912 | + }, | ||
| 1913 | + "node_modules/lightningcss-linux-arm-gnueabihf": { | ||
| 1914 | + "version": "1.30.2", | ||
| 1915 | + "resolved": "https://repo.huaweicloud.com/repository/npm/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", | ||
| 1916 | + "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", | ||
| 1917 | + "cpu": [ | ||
| 1918 | + "arm" | ||
| 1919 | + ], | ||
| 1920 | + "dev": true, | ||
| 1921 | + "license": "MPL-2.0", | ||
| 1922 | + "optional": true, | ||
| 1923 | + "os": [ | ||
| 1924 | + "linux" | ||
| 1925 | + ], | ||
| 1926 | + "engines": { | ||
| 1927 | + "node": ">= 12.0.0" | ||
| 1928 | + }, | ||
| 1929 | + "funding": { | ||
| 1930 | + "type": "opencollective", | ||
| 1931 | + "url": "https://opencollective.com/parcel" | ||
| 1932 | + } | ||
| 1933 | + }, | ||
| 1934 | + "node_modules/lightningcss-linux-arm64-gnu": { | ||
| 1935 | + "version": "1.30.2", | ||
| 1936 | + "resolved": "https://repo.huaweicloud.com/repository/npm/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", | ||
| 1937 | + "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", | ||
| 1938 | + "cpu": [ | ||
| 1939 | + "arm64" | ||
| 1940 | + ], | ||
| 1941 | + "dev": true, | ||
| 1942 | + "license": "MPL-2.0", | ||
| 1943 | + "optional": true, | ||
| 1944 | + "os": [ | ||
| 1945 | + "linux" | ||
| 1946 | + ], | ||
| 1947 | + "engines": { | ||
| 1948 | + "node": ">= 12.0.0" | ||
| 1949 | + }, | ||
| 1950 | + "funding": { | ||
| 1951 | + "type": "opencollective", | ||
| 1952 | + "url": "https://opencollective.com/parcel" | ||
| 1953 | + } | ||
| 1954 | + }, | ||
| 1955 | + "node_modules/lightningcss-linux-arm64-musl": { | ||
| 1956 | + "version": "1.30.2", | ||
| 1957 | + "resolved": "https://repo.huaweicloud.com/repository/npm/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", | ||
| 1958 | + "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", | ||
| 1959 | + "cpu": [ | ||
| 1960 | + "arm64" | ||
| 1961 | + ], | ||
| 1962 | + "dev": true, | ||
| 1963 | + "license": "MPL-2.0", | ||
| 1964 | + "optional": true, | ||
| 1965 | + "os": [ | ||
| 1966 | + "linux" | ||
| 1967 | + ], | ||
| 1968 | + "engines": { | ||
| 1969 | + "node": ">= 12.0.0" | ||
| 1970 | + }, | ||
| 1971 | + "funding": { | ||
| 1972 | + "type": "opencollective", | ||
| 1973 | + "url": "https://opencollective.com/parcel" | ||
| 1974 | + } | ||
| 1975 | + }, | ||
| 1976 | + "node_modules/lightningcss-linux-x64-gnu": { | ||
| 1977 | + "version": "1.30.2", | ||
| 1978 | + "resolved": "https://repo.huaweicloud.com/repository/npm/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", | ||
| 1979 | + "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", | ||
| 1980 | + "cpu": [ | ||
| 1981 | + "x64" | ||
| 1982 | + ], | ||
| 1983 | + "dev": true, | ||
| 1984 | + "license": "MPL-2.0", | ||
| 1985 | + "optional": true, | ||
| 1986 | + "os": [ | ||
| 1987 | + "linux" | ||
| 1988 | + ], | ||
| 1989 | + "engines": { | ||
| 1990 | + "node": ">= 12.0.0" | ||
| 1991 | + }, | ||
| 1992 | + "funding": { | ||
| 1993 | + "type": "opencollective", | ||
| 1994 | + "url": "https://opencollective.com/parcel" | ||
| 1995 | + } | ||
| 1996 | + }, | ||
| 1997 | + "node_modules/lightningcss-linux-x64-musl": { | ||
| 1998 | + "version": "1.30.2", | ||
| 1999 | + "resolved": "https://repo.huaweicloud.com/repository/npm/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", | ||
| 2000 | + "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", | ||
| 2001 | + "cpu": [ | ||
| 2002 | + "x64" | ||
| 2003 | + ], | ||
| 2004 | + "dev": true, | ||
| 2005 | + "license": "MPL-2.0", | ||
| 2006 | + "optional": true, | ||
| 2007 | + "os": [ | ||
| 2008 | + "linux" | ||
| 2009 | + ], | ||
| 2010 | + "engines": { | ||
| 2011 | + "node": ">= 12.0.0" | ||
| 2012 | + }, | ||
| 2013 | + "funding": { | ||
| 2014 | + "type": "opencollective", | ||
| 2015 | + "url": "https://opencollective.com/parcel" | ||
| 2016 | + } | ||
| 2017 | + }, | ||
| 2018 | + "node_modules/lightningcss-win32-arm64-msvc": { | ||
| 2019 | + "version": "1.30.2", | ||
| 2020 | + "resolved": "https://repo.huaweicloud.com/repository/npm/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", | ||
| 2021 | + "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", | ||
| 2022 | + "cpu": [ | ||
| 2023 | + "arm64" | ||
| 2024 | + ], | ||
| 2025 | + "dev": true, | ||
| 2026 | + "license": "MPL-2.0", | ||
| 2027 | + "optional": true, | ||
| 2028 | + "os": [ | ||
| 2029 | + "win32" | ||
| 2030 | + ], | ||
| 2031 | + "engines": { | ||
| 2032 | + "node": ">= 12.0.0" | ||
| 2033 | + }, | ||
| 2034 | + "funding": { | ||
| 2035 | + "type": "opencollective", | ||
| 2036 | + "url": "https://opencollective.com/parcel" | ||
| 2037 | + } | ||
| 2038 | + }, | ||
| 2039 | + "node_modules/lightningcss-win32-x64-msvc": { | ||
| 2040 | + "version": "1.30.2", | ||
| 2041 | + "resolved": "https://repo.huaweicloud.com/repository/npm/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", | ||
| 2042 | + "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", | ||
| 2043 | + "cpu": [ | ||
| 2044 | + "x64" | ||
| 2045 | + ], | ||
| 2046 | + "dev": true, | ||
| 2047 | + "license": "MPL-2.0", | ||
| 2048 | + "optional": true, | ||
| 2049 | + "os": [ | ||
| 2050 | + "win32" | ||
| 2051 | + ], | ||
| 2052 | + "engines": { | ||
| 2053 | + "node": ">= 12.0.0" | ||
| 2054 | + }, | ||
| 2055 | + "funding": { | ||
| 2056 | + "type": "opencollective", | ||
| 2057 | + "url": "https://opencollective.com/parcel" | ||
| 2058 | + } | ||
| 2059 | + }, | ||
| 1473 | "node_modules/lru-cache": { | 2060 | "node_modules/lru-cache": { |
| 1474 | "version": "5.1.1", | 2061 | "version": "5.1.1", |
| 1475 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", | 2062 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", |
| @@ -1489,6 +2076,16 @@ | @@ -1489,6 +2076,16 @@ | ||
| 1489 | "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" | 2076 | "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" |
| 1490 | } | 2077 | } |
| 1491 | }, | 2078 | }, |
| 2079 | + "node_modules/magic-string": { | ||
| 2080 | + "version": "0.30.21", | ||
| 2081 | + "resolved": "https://repo.huaweicloud.com/repository/npm/magic-string/-/magic-string-0.30.21.tgz", | ||
| 2082 | + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", | ||
| 2083 | + "dev": true, | ||
| 2084 | + "license": "MIT", | ||
| 2085 | + "dependencies": { | ||
| 2086 | + "@jridgewell/sourcemap-codec": "^1.5.5" | ||
| 2087 | + } | ||
| 2088 | + }, | ||
| 1492 | "node_modules/ms": { | 2089 | "node_modules/ms": { |
| 1493 | "version": "2.1.3", | 2090 | "version": "2.1.3", |
| 1494 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", | 2091 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", |
| @@ -1684,6 +2281,20 @@ | @@ -1684,6 +2281,20 @@ | ||
| 1684 | "dev": true, | 2281 | "dev": true, |
| 1685 | "license": "MIT" | 2282 | "license": "MIT" |
| 1686 | }, | 2283 | }, |
| 2284 | + "node_modules/tapable": { | ||
| 2285 | + "version": "2.3.0", | ||
| 2286 | + "resolved": "https://repo.huaweicloud.com/repository/npm/tapable/-/tapable-2.3.0.tgz", | ||
| 2287 | + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", | ||
| 2288 | + "dev": true, | ||
| 2289 | + "license": "MIT", | ||
| 2290 | + "engines": { | ||
| 2291 | + "node": ">=6" | ||
| 2292 | + }, | ||
| 2293 | + "funding": { | ||
| 2294 | + "type": "opencollective", | ||
| 2295 | + "url": "https://opencollective.com/webpack" | ||
| 2296 | + } | ||
| 2297 | + }, | ||
| 1687 | "node_modules/tinyglobby": { | 2298 | "node_modules/tinyglobby": { |
| 1688 | "version": "0.2.15", | 2299 | "version": "0.2.15", |
| 1689 | "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", | 2300 | "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", |
| @@ -14,6 +14,7 @@ | @@ -14,6 +14,7 @@ | ||
| 14 | "react-dom": "^19.2.3" | 14 | "react-dom": "^19.2.3" |
| 15 | }, | 15 | }, |
| 16 | "devDependencies": { | 16 | "devDependencies": { |
| 17 | + "@tailwindcss/postcss": "^4.1.18", | ||
| 17 | "@types/node": "^22.14.0", | 18 | "@types/node": "^22.14.0", |
| 18 | "@vitejs/plugin-react": "^5.0.0", | 19 | "@vitejs/plugin-react": "^5.0.0", |
| 19 | "autoprefixer": "^10.4.24", | 20 | "autoprefixer": "^10.4.24", |
-
Please register or login to post a comment