diff --git a/.gitignore b/.gitignore index 2a1f175..7913f08 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,3 @@ npm-debug.log* # Release build output (scripts/release/make_release.sh). /dist/ -# Assembled docroots built by the hosting apps' publish.sh (dev-only). -containers/getlibreportal/data/ -containers/weblibreportal/data/ -containers/weblibreportal/dist/ diff --git a/containers/getlibreportal/docker-compose.yml b/containers/getlibreportal/docker-compose.yml deleted file mode 100644 index 868535f..0000000 --- a/containers/getlibreportal/docker-compose.yml +++ /dev/null @@ -1,41 +0,0 @@ -networks: - DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA - external: true - -services: - getlibreportal-service: #LIBREPORTAL|SERVICE_TAG_1|getlibreportal-service - container_name: getlibreportal-service - image: nginx:alpine - restart: unless-stopped - hostname: getlibreportal - # ./data is the docroot (website + install.sh + release channels), assembled - # by publish.sh. Read-only into nginx. ./nginx.conf sets content-types/caching. - volumes: - - ./data:/usr/share/nginx/html:ro - - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro - # GLUETUN_OFF_BEGIN - ports: - - "PORTS_DATA_1" #LIBREPORTAL|PORTS_TAG_1|PORTS_DATA_1 - # GLUETUN_OFF_END - labels: - libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA - libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA - traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA - # TRAEFIK_PORT_1_BEGIN - traefik.http.routers.getlibreportal-service.entrypoints: web,websecure - traefik.http.routers.getlibreportal-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1 - traefik.http.routers.getlibreportal-service.tls: true - traefik.http.routers.getlibreportal-service.tls.certresolver: production - traefik.http.services.getlibreportal-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1 - traefik.http.routers.getlibreportal-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1 - # TRAEFIK_PORT_1_END - healthcheck: - disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA - # GLUETUN_OFF_BEGIN - networks: - DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA - ipv4_address: IP_DATA_1 #LIBREPORTAL|IP_TAG_1|IP_DATA_1 - # GLUETUN_OFF_END - # GLUETUN_ON_BEGIN - # network_mode: "container:gluetun-service" - # GLUETUN_ON_END diff --git a/containers/getlibreportal/getlibreportal.config b/containers/getlibreportal/getlibreportal.config deleted file mode 100644 index e02a74f..0000000 --- a/containers/getlibreportal/getlibreportal.config +++ /dev/null @@ -1,46 +0,0 @@ -# -# ============================================================================= -# GENERAL CONFIGURATION -# ============================================================================= -# APP_NAME = name of application for use in scripts -# COMPOSE_FILE = default for no app_name in docker-compose file name, app if there is -# BACKUP = if true, include this application in backup operations -# HEALTHCHECK = if true, default docker health checks for that container will be enabled -# AUTHELIA = if true, use Authelia authentication, if false turned off. -# HEADSCALE = options : false, local, remote (see general config). e.g false or local,remote -# -CFG_GETLIBREPORTAL_APP_NAME=getlibreportal -CFG_GETLIBREPORTAL_BACKUP=false -CFG_GETLIBREPORTAL_BACKUP_STRATEGY=auto -CFG_GETLIBREPORTAL_COMPOSE_FILE=default -CFG_GETLIBREPORTAL_HEALTHCHECK=true -CFG_GETLIBREPORTAL_AUTHELIA=false -CFG_GETLIBREPORTAL_HEADSCALE=false -# -# ============================================================================= -# METADATA -# ============================================================================= -CFG_GETLIBREPORTAL_CATEGORY="features" -CFG_GETLIBREPORTAL_TITLE="LibrePortal Downloads" -CFG_GETLIBREPORTAL_DESCRIPTION="install.sh + signed-release host" -CFG_GETLIBREPORTAL_LONG_DESCRIPTION="Serves the install.sh bootstrap and signed/checksummed release artifacts — i.e. the get.libreportal.org host. Populate its docroot with containers/getlibreportal/publish.sh. (The website is a separate app: weblibreportal.)" -CFG_GETLIBREPORTAL_URL="https://get.libreportal.org" -CFG_GETLIBREPORTAL_ACTIONS="configure|install|restart|shutdown|uninstall" -# -# ============================================================================= -# NETWORK CONFIGURATION -# ============================================================================= -# DOMAIN = number of domain from the general config, useful when using multiple domains -# WHITELIST = if true only allow whitelisted ips on traefik, if false allow all -# -CFG_GETLIBREPORTAL_DOMAIN=1 -CFG_GETLIBREPORTAL_WHITELIST=false -CFG_GETLIBREPORTAL_NETWORK=default -# -# ============================================================================= -# PORT CONFIGURATION -# ============================================================================= -# PORT_ = app|name|external:internal|access|protocol|login|traefik|webui|title|path|slug -# login MUST stay false — this is a public download host (no basic-auth). -# -CFG_GETLIBREPORTAL_PORT_1="getlibreportal-service|webui|random:80|public|tcp|false|true|true|Downloads|/|getlibreportal" diff --git a/containers/getlibreportal/getlibreportal.sh b/containers/getlibreportal/getlibreportal.sh deleted file mode 100644 index 3cfd675..0000000 --- a/containers/getlibreportal/getlibreportal.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/bin/bash - -# Category : Features -# Description : getlibreportal - Website + signed-release host (c/u/s/r/i): - -installGetlibreportal() -{ - local config_variables="$1" - - if [[ "$getlibreportal" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent getlibreportal; - local app_name=$CFG_GETLIBREPORTAL_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$getlibreportal" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$getlibreportal" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$getlibreportal" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$getlibreportal" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$getlibreportal" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Populate the docroot, then browse $app_name." - echo "" - echo " The container serves an EMPTY docroot until you publish content." - echo " From a full repo checkout (build/release machine) run:" - echo " containers/getlibreportal/publish.sh $containers_dir$app_name/data" - echo " (copies install.sh + the dist/ releases; the website is" - echo " a separate app, weblibreportal)." - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - cd - fi - getlibreportal=n -} diff --git a/containers/getlibreportal/getlibreportal.svg b/containers/getlibreportal/getlibreportal.svg deleted file mode 100644 index a1222f7..0000000 --- a/containers/getlibreportal/getlibreportal.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/containers/getlibreportal/nginx.conf b/containers/getlibreportal/nginx.conf deleted file mode 100644 index 8ffd9aa..0000000 --- a/containers/getlibreportal/nginx.conf +++ /dev/null @@ -1,27 +0,0 @@ -server { - listen 80; - server_name _; - root /usr/share/nginx/html; - index index.html; - - # The bootstrap installer: served as a shell script, never cached, so - # `curl … | sudo bash` always gets the current one. - location = /install.sh { - default_type text/x-shellscript; - add_header Cache-Control "no-cache, must-revalidate"; - } - - # Channel manifests change every release — don't cache. - location ~ /latest\.json$ { - default_type application/json; - add_header Cache-Control "no-cache, must-revalidate"; - } - - # Release artifacts are immutable (version-pinned names) — cache hard. - location ~ \.tar\.gz$ { default_type application/gzip; add_header Cache-Control "public, max-age=31536000, immutable"; } - location ~ \.sha256$ { default_type text/plain; add_header Cache-Control "public, max-age=31536000, immutable"; } - location ~ \.minisig$ { default_type text/plain; add_header Cache-Control "public, max-age=31536000, immutable"; } - - # The static website. - location / { try_files $uri $uri/ =404; } -} diff --git a/containers/getlibreportal/publish.sh b/containers/getlibreportal/publish.sh deleted file mode 100644 index cdb149d..0000000 --- a/containers/getlibreportal/publish.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash -# -# Assemble the getlibreportal docroot — the bootstrap installer + release channels -# — into the served data dir. (The website is a separate app: weblibreportal.) -# Run on a full repo checkout (it reads ../../dist, which is host-side). -# -# Usage: publish.sh [TARGET_DIR] -# TARGET_DIR defaults to ./data (next to this script). On a host where the app -# is installed, pass its live data dir, e.g.: -# containers/getlibreportal/publish.sh /libreportal-containers/getlibreportal/data -# -# Layout produced: -# /install.sh ← bootstrap installer (repo: install.sh) -# //… ← release manifests + tarballs (repo: dist//) -set -euo pipefail - -HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -ROOT="$(cd "$HERE/../.." && pwd)" # repo root (containers/getlibreportal -> ../../) -TARGET="${1:-$HERE/data}" - -echo "Assembling getlibreportal docroot -> $TARGET" -mkdir -p "$TARGET" -rm -rf "${TARGET:?}"/* "${TARGET:?}"/.??* 2>/dev/null || true - -# 1. Bootstrap installer. -if [[ -f "$ROOT/install.sh" ]]; then cp -f "$ROOT/install.sh" "$TARGET/install.sh"; echo " ✓ install.sh"; fi - -# 2. Release channels (from scripts/release/make_release.sh). -if [[ -d "$ROOT/dist" ]]; then - for ch in "$ROOT/dist"/*/; do - [[ -d "$ch" ]] || continue - n="$(basename "$ch")"; mkdir -p "$TARGET/$n"; cp -f "$ch"/* "$TARGET/$n/" 2>/dev/null || true - echo " ✓ channel $n" - done -else - echo " ! no dist/ — run scripts/release/make_release.sh first" -fi - -echo "Done. Restart the container to serve it." diff --git a/containers/weblibreportal/.gitignore b/containers/weblibreportal/.gitignore deleted file mode 100644 index 9045c73..0000000 --- a/containers/weblibreportal/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -node_modules/ -dist/ -# generated from the repo at build time (npm run data) -src/_data/apps.json -src/_data/categories.json -*.bak diff --git a/containers/weblibreportal/docker-compose.yml b/containers/weblibreportal/docker-compose.yml deleted file mode 100644 index 769b052..0000000 --- a/containers/weblibreportal/docker-compose.yml +++ /dev/null @@ -1,40 +0,0 @@ -networks: - DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA - external: true - -services: - weblibreportal-service: #LIBREPORTAL|SERVICE_TAG_1|weblibreportal-service - container_name: weblibreportal-service - image: nginx:alpine - restart: unless-stopped - hostname: weblibreportal - # ./data is the built website (Eleventy → publish.sh). Read-only into nginx. - volumes: - - ./data:/usr/share/nginx/html:ro - - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro - # GLUETUN_OFF_BEGIN - ports: - - "PORTS_DATA_1" #LIBREPORTAL|PORTS_TAG_1|PORTS_DATA_1 - # GLUETUN_OFF_END - labels: - libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA - libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA - traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA - # TRAEFIK_PORT_1_BEGIN - traefik.http.routers.weblibreportal-service.entrypoints: web,websecure - traefik.http.routers.weblibreportal-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1 - traefik.http.routers.weblibreportal-service.tls: true - traefik.http.routers.weblibreportal-service.tls.certresolver: production - traefik.http.services.weblibreportal-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1 - traefik.http.routers.weblibreportal-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1 - # TRAEFIK_PORT_1_END - healthcheck: - disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA - # GLUETUN_OFF_BEGIN - networks: - DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA - ipv4_address: IP_DATA_1 #LIBREPORTAL|IP_TAG_1|IP_DATA_1 - # GLUETUN_OFF_END - # GLUETUN_ON_BEGIN - # network_mode: "container:gluetun-service" - # GLUETUN_ON_END diff --git a/containers/weblibreportal/eleventy.config.cjs b/containers/weblibreportal/eleventy.config.cjs deleted file mode 100644 index eb0ebf1..0000000 --- a/containers/weblibreportal/eleventy.config.cjs +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = function (eleventyConfig) { - // copy static assets straight through to the build output - eleventyConfig.addPassthroughCopy({ "src/assets": "assets" }); - eleventyConfig.addWatchTarget("src/assets"); - - return { - dir: { input: "src", includes: "_includes", data: "_data", output: "dist" }, - htmlTemplateEngine: "njk", - markdownTemplateEngine: "njk", - templateFormats: ["njk", "html", "md"], - }; -}; diff --git a/containers/weblibreportal/nginx.conf b/containers/weblibreportal/nginx.conf deleted file mode 100644 index b837668..0000000 --- a/containers/weblibreportal/nginx.conf +++ /dev/null @@ -1,16 +0,0 @@ -server { - listen 80; - server_name _; - root /usr/share/nginx/html; - index index.html; - - # Static website (Eleventy output). Long-cache the hashed assets; let HTML - # revalidate so content updates show promptly. - location ~* \.(?:css|js|svg|png|jpg|jpeg|gif|ico|woff2?)$ { - add_header Cache-Control "public, max-age=2592000"; - } - location / { - add_header Cache-Control "no-cache, must-revalidate"; - try_files $uri $uri/ $uri.html =404; - } -} diff --git a/containers/weblibreportal/package-lock.json b/containers/weblibreportal/package-lock.json deleted file mode 100644 index 54c11ee..0000000 --- a/containers/weblibreportal/package-lock.json +++ /dev/null @@ -1,1522 +0,0 @@ -{ - "name": "libreportal-site", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "libreportal-site", - "version": "0.1.0", - "devDependencies": { - "@11ty/eleventy": "^3.1.5" - } - }, - "node_modules/@11ty/dependency-tree": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@11ty/dependency-tree/-/dependency-tree-4.0.2.tgz", - "integrity": "sha512-RTF6VTZHatYf7fSZBUN3RKwiUeJh5dhWV61gDPrHhQF2/gzruAkYz8yXuvGLx3w3ZBKreGrR+MfYpSVkdbdbLA==", - "dev": true, - "dependencies": { - "@11ty/eleventy-utils": "^2.0.1" - } - }, - "node_modules/@11ty/dependency-tree-esm": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@11ty/dependency-tree-esm/-/dependency-tree-esm-2.0.4.tgz", - "integrity": "sha512-MYKC0Ac77ILr1HnRJalzKDlb9Z8To3kXQCltx299pUXXUFtJ1RIONtULlknknqW8cLe19DLVgmxVCtjEFm7h0A==", - "dev": true, - "dependencies": { - "@11ty/eleventy-utils": "^2.0.7", - "acorn": "^8.15.0", - "dependency-graph": "^1.0.0", - "normalize-path": "^3.0.0" - } - }, - "node_modules/@11ty/eleventy": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@11ty/eleventy/-/eleventy-3.1.5.tgz", - "integrity": "sha512-hZ0g6MwZyRxCqXsPm82gIM304LraKbUz3ZmezOSjsqxttZG6cHTib3Qq8QkESJoKwnr+yX1eyfOkPC5/mEgZnQ==", - "dev": true, - "dependencies": { - "@11ty/dependency-tree": "^4.0.2", - "@11ty/dependency-tree-esm": "^2.0.4", - "@11ty/eleventy-dev-server": "^2.0.8", - "@11ty/eleventy-plugin-bundle": "^3.0.7", - "@11ty/eleventy-utils": "^2.0.7", - "@11ty/lodash-custom": "^4.17.21", - "@11ty/posthtml-urls": "^1.0.2", - "@11ty/recursive-copy": "^4.0.4", - "@sindresorhus/slugify": "^2.2.1", - "bcp-47-normalize": "^2.3.0", - "chokidar": "^3.6.0", - "debug": "^4.4.3", - "dependency-graph": "^1.0.0", - "entities": "^6.0.1", - "filesize": "^10.1.6", - "gray-matter": "^4.0.3", - "iso-639-1": "^3.1.5", - "js-yaml": "^4.1.1", - "kleur": "^4.1.5", - "liquidjs": "^10.25.0", - "luxon": "^3.7.2", - "markdown-it": "^14.1.1", - "minimist": "^1.2.8", - "moo": "0.5.2", - "node-retrieve-globals": "^6.0.1", - "nunjucks": "^3.2.4", - "picomatch": "^4.0.3", - "please-upgrade-node": "^3.2.0", - "posthtml": "^0.16.7", - "posthtml-match-helper": "^2.0.3", - "semver": "^7.7.4", - "slugify": "^1.6.8", - "tinyglobby": "^0.2.15" - }, - "bin": { - "eleventy": "cmd.cjs" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/11ty" - } - }, - "node_modules/@11ty/eleventy-dev-server": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@11ty/eleventy-dev-server/-/eleventy-dev-server-2.0.8.tgz", - "integrity": "sha512-15oC5M1DQlCaOMUq4limKRYmWiGecDaGwryr7fTE/oM9Ix8siqMvWi+I8VjsfrGr+iViDvWcH/TVI6D12d93mA==", - "dev": true, - "dependencies": { - "@11ty/eleventy-utils": "^2.0.1", - "chokidar": "^3.6.0", - "debug": "^4.4.0", - "finalhandler": "^1.3.1", - "mime": "^3.0.0", - "minimist": "^1.2.8", - "morphdom": "^2.7.4", - "please-upgrade-node": "^3.2.0", - "send": "^1.1.0", - "ssri": "^11.0.0", - "urlpattern-polyfill": "^10.0.0", - "ws": "^8.18.1" - }, - "bin": { - "eleventy-dev-server": "cmd.js" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/11ty" - } - }, - "node_modules/@11ty/eleventy-plugin-bundle": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@11ty/eleventy-plugin-bundle/-/eleventy-plugin-bundle-3.0.7.tgz", - "integrity": "sha512-QK1tRFBhQdZASnYU8GMzpTdsMMFLVAkuU0gVVILqNyp09xJJZb81kAS3AFrNrwBCsgLxTdWHJ8N64+OTTsoKkA==", - "dev": true, - "dependencies": { - "@11ty/eleventy-utils": "^2.0.2", - "debug": "^4.4.0", - "posthtml-match-helper": "^2.0.3" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/11ty" - } - }, - "node_modules/@11ty/eleventy-utils": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@11ty/eleventy-utils/-/eleventy-utils-2.0.7.tgz", - "integrity": "sha512-6QE+duqSQ0GY9rENXYb4iPR4AYGdrFpqnmi59tFp9VrleOl0QSh8VlBr2yd6dlhkdtj7904poZW5PvGr9cMiJQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/11ty" - } - }, - "node_modules/@11ty/lodash-custom": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@11ty/lodash-custom/-/lodash-custom-4.17.21.tgz", - "integrity": "sha512-Mqt6im1xpb1Ykn3nbcCovWXK3ggywRJa+IXIdoz4wIIK+cvozADH63lexcuPpGS/gJ6/m2JxyyXDyupkMr5DHw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/11ty" - } - }, - "node_modules/@11ty/posthtml-urls": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@11ty/posthtml-urls/-/posthtml-urls-1.0.3.tgz", - "integrity": "sha512-1YvhnkaNlFnnJic1rBMWmTC2adbuy+JQiBfl1Hecr1Wjjik1pQZmGyk/eC9zKX/FQv52s2Nht1Gi/UwhYqrBeg==", - "dev": true, - "dependencies": { - "evaluate-value": "^2.0.0", - "http-equiv-refresh": "^2.0.1", - "list-to-array": "^1.1.0", - "parse-srcset": "^1.0.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@11ty/recursive-copy": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@11ty/recursive-copy/-/recursive-copy-4.0.4.tgz", - "integrity": "sha512-oI7m8pa7/IAU/3lqRU9vjBbs20iKFo7x+1K9kT3aVira6scc1X9MjBdgLCHzLJeJ7iB6wydioA+kr9/qPnvmlQ==", - "dev": true, - "dependencies": { - "errno": "^1.0.0", - "junk": "^3.1.0", - "minimatch": "^3.1.5", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sindresorhus/slugify": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-2.2.1.tgz", - "integrity": "sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw==", - "dev": true, - "dependencies": { - "@sindresorhus/transliterate": "^1.0.0", - "escape-string-regexp": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sindresorhus/transliterate": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-1.6.0.tgz", - "integrity": "sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/a-sync-waterfall": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", - "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.5", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", - "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", - "dev": true, - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/bcp-47": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz", - "integrity": "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==", - "dev": true, - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/bcp-47-match": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", - "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/bcp-47-normalize": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/bcp-47-normalize/-/bcp-47-normalize-2.3.0.tgz", - "integrity": "sha512-8I/wfzqQvttUFz7HVJgIZ7+dj3vUaIyIxYXaTRP1YWoSDfzt6TUmxaKZeuXR62qBmYr+nvuWINFRl6pZ5DlN4Q==", - "dev": true, - "dependencies": { - "bcp-47": "^2.0.0", - "bcp-47-match": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dependency-graph": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-1.0.0.tgz", - "integrity": "sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/errno": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/errno/-/errno-1.0.0.tgz", - "integrity": "sha512-3zV5mFS1E8/1bPxt/B0xxzI1snsg3uSCIh6Zo1qKg6iMw93hzPANk9oBFzSFBFrwuVoQuE3rLoouAUfwOAj1wQ==", - "dev": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/esm-import-transformer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/esm-import-transformer/-/esm-import-transformer-3.0.5.tgz", - "integrity": "sha512-1GKLvfuMnnpI75l8c6sHoz0L3Z872xL5akGuBudgqTDPv4Vy6f2Ec7jEMKTxlqWl/3kSvNbHELeimJtnqgYniw==", - "dev": true, - "dependencies": { - "acorn": "^8.15.0" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/evaluate-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/evaluate-value/-/evaluate-value-2.0.0.tgz", - "integrity": "sha512-VonfiuDJc0z4sOO7W0Pd130VLsXN6vmBWZlrog1mCb/o7o/Nl5Lr25+Kj/nkCCAhG+zqeeGjxhkK9oHpkgTHhQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/filesize": { - "version": "10.1.6", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.6.tgz", - "integrity": "sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==", - "dev": true, - "engines": { - "node": ">= 10.4.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "statuses": "~2.0.2", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/gray-matter": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", - "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", - "dev": true, - "dependencies": { - "js-yaml": "^3.13.1", - "kind-of": "^6.0.2", - "section-matter": "^1.0.0", - "strip-bom-string": "^1.0.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/gray-matter/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/gray-matter/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/htmlparser2": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", - "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.2", - "domutils": "^2.8.0", - "entities": "^3.0.1" - } - }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", - "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/http-equiv-refresh": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-equiv-refresh/-/http-equiv-refresh-2.0.1.tgz", - "integrity": "sha512-XJpDL/MLkV3dKwLzHwr2dY05dYNfBNlyPu4STQ8WvKCFdc6vC5tPXuq28of663+gHVg03C+16pHHs/+FmmDjcw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "dev": true, - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-alphabetical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", - "dev": true, - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-decimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-json": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", - "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==", - "dev": true - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/iso-639-1": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/iso-639-1/-/iso-639-1-3.1.5.tgz", - "integrity": "sha512-gXkz5+KN7HrG0Q5UGqSMO2qB9AsbEeyLP54kF1YrMsIxmu+g4BdB7rflReZTSTZGpfj8wywu6pfPBCylPIzGQA==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/junk": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz", - "integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "dev": true, - "dependencies": { - "uc.micro": "^2.0.0" - } - }, - "node_modules/liquidjs": { - "version": "10.27.0", - "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.27.0.tgz", - "integrity": "sha512-tw/OA59K7aIBlMKIrKlumr37fiZUheShVHXY8cVctWisgY1p9mc5hreOvlreoS0wTiwlWk14Ya7305c2a/Cg5w==", - "dev": true, - "dependencies": { - "commander": "^10.0.0" - }, - "bin": { - "liquid": "bin/liquid.js", - "liquidjs": "bin/liquid.js" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/liquidjs" - } - }, - "node_modules/list-to-array": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/list-to-array/-/list-to-array-1.1.0.tgz", - "integrity": "sha512-+dAZZ2mM+/m+vY9ezfoueVvrgnHIGi5FvgSymbIgJOFwiznWyA59mav95L+Mc6xPtL3s9gm5eNTlNtxJLbNM1g==", - "dev": true - }, - "node_modules/luxon": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", - "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/markdown-it": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", - "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/markdown-it/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true - }, - "node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "dev": true, - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/moo": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", - "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", - "dev": true - }, - "node_modules/morphdom": { - "version": "2.7.8", - "resolved": "https://registry.npmjs.org/morphdom/-/morphdom-2.7.8.tgz", - "integrity": "sha512-D/fR4xgGUyVRbdMGU6Nejea1RFzYxYtyurG4Fbv2Fi/daKlWKuXGLOdXtl+3eIwL110cI2hz1ZojGICjjFLgTg==", - "dev": true - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/node-retrieve-globals": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/node-retrieve-globals/-/node-retrieve-globals-6.0.1.tgz", - "integrity": "sha512-j0DeFuZ/Wg3VlklfbxUgZF/mdHMTEiEipBb3q0SpMMbHaV3AVfoUQF8UGxh1s/yjqO0TgRZd4Pi/x2yRqoQ4Eg==", - "dev": true, - "dependencies": { - "acorn": "^8.14.1", - "acorn-walk": "^8.3.4", - "esm-import-transformer": "^3.0.3" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nunjucks": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", - "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", - "dev": true, - "dependencies": { - "a-sync-waterfall": "^1.0.0", - "asap": "^2.0.3", - "commander": "^5.1.0" - }, - "bin": { - "nunjucks-precompile": "bin/precompile" - }, - "engines": { - "node": ">= 6.9.0" - }, - "peerDependencies": { - "chokidar": "^3.3.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/nunjucks/node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/parse-srcset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", - "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", - "dev": true - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/please-upgrade-node": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", - "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", - "dev": true, - "dependencies": { - "semver-compare": "^1.0.0" - } - }, - "node_modules/posthtml": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.16.7.tgz", - "integrity": "sha512-7Hc+IvlQ7hlaIfQFZnxlRl0jnpWq2qwibORBhQYIb0QbNtuicc5ZxvKkVT71HJ4Py1wSZ/3VR1r8LfkCtoCzhw==", - "dev": true, - "dependencies": { - "posthtml-parser": "^0.11.0", - "posthtml-render": "^3.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/posthtml-match-helper": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/posthtml-match-helper/-/posthtml-match-helper-2.0.3.tgz", - "integrity": "sha512-p9oJgTdMF2dyd7WE54QI1LvpBIkNkbSiiECKezNnDVYhGhD1AaOnAkw0Uh0y5TW+OHO8iBdSqnd8Wkpb6iUqmw==", - "dev": true, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "posthtml": "^0.16.6" - } - }, - "node_modules/posthtml-parser": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", - "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==", - "dev": true, - "dependencies": { - "htmlparser2": "^7.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/posthtml-render": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz", - "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==", - "dev": true, - "dependencies": { - "is-json": "^2.0.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true - }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/section-matter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", - "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/semver": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", - "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true - }, - "node_modules/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", - "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", - "dev": true, - "dependencies": { - "debug": "^4.4.3", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.1", - "mime-types": "^3.0.2", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slugify": { - "version": "1.6.9", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.9.tgz", - "integrity": "sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/ssri": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-11.0.0.tgz", - "integrity": "sha512-aZpUoMN/Jj2MqA4vMCeiKGnc/8SuSyHbGSBdgFbZxP8OJGF/lFkIuElzPxsN0q8TQQ+prw3P4EDfB3TBHHgfXw==", - "dev": true, - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", - "dev": true, - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/urlpattern-polyfill": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz", - "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==", - "dev": true - }, - "node_modules/ws": { - "version": "8.20.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", - "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - } - } -} diff --git a/containers/weblibreportal/package.json b/containers/weblibreportal/package.json deleted file mode 100644 index 803889c..0000000 --- a/containers/weblibreportal/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "libreportal-site", - "version": "0.1.0", - "private": true, - "description": "LibrePortal marketing/get site — data-driven from the repo via Eleventy.", - "scripts": { - "data": "node scripts/gen-data.mjs", - "build": "npm run data && eleventy", - "start": "npm run data && eleventy --serve --port 8777", - "clean": "rm -rf dist" - }, - "devDependencies": { - "@11ty/eleventy": "^3.1.5" - } -} diff --git a/containers/weblibreportal/publish.sh b/containers/weblibreportal/publish.sh deleted file mode 100644 index 87b8960..0000000 --- a/containers/weblibreportal/publish.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -# -# Build the LibrePortal website (Eleventy) and publish it into the served docroot. -# Run on a full repo checkout (it reads ../*/*.config to build the app catalogue). -# -# Usage: publish.sh [TARGET_DIR] -# TARGET_DIR defaults to ./data (next to this script). On a host where the app -# is installed, pass its live data dir, e.g.: -# containers/weblibreportal/publish.sh /libreportal-containers/weblibreportal/data -set -euo pipefail - -HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -TARGET="${1:-$HERE/data}" - -command -v npm >/dev/null 2>&1 || { echo "publish.sh: npm is required to build the website" >&2; exit 1; } - -echo "Building the website ..." -( cd "$HERE" && npm install --silent && npm run build ) # → ./dist (runs gen-data + eleventy) - -echo "Publishing -> $TARGET" -mkdir -p "$TARGET" -rm -rf "${TARGET:?}"/* "${TARGET:?}"/.??* 2>/dev/null || true -cp -a "$HERE/dist/." "$TARGET/" - -echo "Done. Restart the container to serve it." diff --git a/containers/weblibreportal/scripts/gen-data.mjs b/containers/weblibreportal/scripts/gen-data.mjs deleted file mode 100644 index a1ef598..0000000 --- a/containers/weblibreportal/scripts/gen-data.mjs +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env node -/* - * gen-data.mjs — single source of truth: the LibrePortal repo. - * - * Reads every containers//.config METADATA block and emits - * src/_data/apps.json (array of apps, used by the app grid) - * src/_data/categories.json (categories present, with friendly names + counts) - * - * Run via `npm run data` (also runs automatically before `npm run build`). - * Add an app to the repo -> rebuild -> the website updates itself. - */ -import { readdirSync, readFileSync, existsSync, writeFileSync, mkdirSync, statSync } from 'node:fs'; -import { fileURLToPath } from 'node:url'; -import { dirname, join, resolve } from 'node:path'; - -const here = dirname(fileURLToPath(import.meta.url)); -const repoRoot = resolve(here, '..', '..', '..'); // containers/weblibreportal/scripts -> repo root -const containersDir = join(repoRoot, 'containers'); -const dataDir = join(here, '..', 'src', '_data'); -const iconsDir = join(here, '..', 'src', 'assets', 'apps'); - -// Only these metadata fields are pulled from each .config. LONG_DESCRIPTION must -// precede DESCRIPTION in the alternation so it wins the match. -const FIELD_RE = /^CFG_.+?_(LONG_DESCRIPTION|DESCRIPTION|CATEGORY|TITLE|URL)\s*=\s*"?(.*?)"?\s*$/; - -const CATEGORY_NAMES = { - recommended: 'Recommended', communication: 'Communication', development: 'Development', - knowledge: 'Knowledge', media: 'Media', monitoring: 'Monitoring', storage: 'Storage', - network: 'Network', security: 'Security', productivity: 'Productivity', finance: 'Finance', - ai: 'AI', utilities: 'Utilities', privacy: 'Privacy', social: 'Social', system: 'System', -}; -const titleCase = (s) => s.replace(/[-_]/g, ' ').replace(/\b\w/g, (m) => m.toUpperCase()); - -function parseConfig(text) { - const out = {}; - for (const raw of text.split(/\r?\n/)) { - const m = FIELD_RE.exec(raw.trim()); - if (m && out[m[1]] === undefined) out[m[1]] = m[2]; - } - return out; -} - -const apps = []; -for (const slug of readdirSync(containersDir)) { - const dir = join(containersDir, slug); - if (!statSync(dir).isDirectory()) continue; - const cfg = join(dir, `${slug}.config`); - if (!existsSync(cfg)) continue; - const meta = parseConfig(readFileSync(cfg, 'utf8')); - if (!meta.TITLE) continue; // skip anything without a display title (infra without metadata) - const cats = (meta.CATEGORY || 'utilities').split(',').map((s) => s.trim()).filter(Boolean); - apps.push({ - slug, - title: meta.TITLE, - category: cats[0], // primary category - categories: cats, // an app can belong to several - description: meta.DESCRIPTION || '', - longDescription: meta.LONG_DESCRIPTION || meta.DESCRIPTION || '', - url: meta.URL || '', - icon: existsSync(join(iconsDir, `${slug}.svg`)) ? `assets/apps/${slug}.svg` : 'assets/apps/default.svg', - }); -} -apps.sort((a, b) => a.title.localeCompare(b.title)); - -const catMap = new Map(); -for (const a of apps) { - for (const cat of a.categories) { - const c = catMap.get(cat) || { id: cat, name: CATEGORY_NAMES[cat] || titleCase(cat), count: 0 }; - c.count++; - catMap.set(cat, c); - } -} -const categories = [...catMap.values()].sort((a, b) => b.count - a.count || a.name.localeCompare(b.name)); - -mkdirSync(dataDir, { recursive: true }); -writeFileSync(join(dataDir, 'apps.json'), JSON.stringify(apps, null, 2) + '\n'); -writeFileSync(join(dataDir, 'categories.json'), JSON.stringify(categories, null, 2) + '\n'); -console.log(`✓ ${apps.length} apps across ${categories.length} categories → src/_data/{apps,categories}.json`); diff --git a/containers/weblibreportal/src/_data/site.json b/containers/weblibreportal/src/_data/site.json deleted file mode 100644 index b248c66..0000000 --- a/containers/weblibreportal/src/_data/site.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "LibrePortal", - "tagline": "your own private corner of the universe", - "version": "v0.1.0", - "installUrl": "https://get.libreportal.org", - "installCmd": "bash <(curl -fsSL https://get.libreportal.org) init", - "repo": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal", - "promiseUrl": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal/raw/branch/main/docs/PROMISE.md", - "contributingUrl": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal/raw/branch/main/docs/CONTRIBUTING.md", - "initUrl": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal/raw/branch/main/init.sh", - "inspiration": "https://gitlab.com/bmcgonag/docker_installs" -} diff --git a/containers/weblibreportal/src/_includes/app-card.njk b/containers/weblibreportal/src/_includes/app-card.njk deleted file mode 100644 index e2b5a4e..0000000 --- a/containers/weblibreportal/src/_includes/app-card.njk +++ /dev/null @@ -1,10 +0,0 @@ -
-
- -
-

{{ app.title }}

- {{ app.category }} -
-
-

{{ app.description }}

-
diff --git a/containers/weblibreportal/src/_includes/footer.njk b/containers/weblibreportal/src/_includes/footer.njk deleted file mode 100644 index 56c0765..0000000 --- a/containers/weblibreportal/src/_includes/footer.njk +++ /dev/null @@ -1,26 +0,0 @@ - diff --git a/containers/weblibreportal/src/_includes/layout.njk b/containers/weblibreportal/src/_includes/layout.njk deleted file mode 100644 index 2070463..0000000 --- a/containers/weblibreportal/src/_includes/layout.njk +++ /dev/null @@ -1,24 +0,0 @@ - - - - - -{{ site.name }} — {{ site.tagline }} - - - - - - -
-
- -{% include "topbar.njk" %} - -{{ content | safe }} - -{% include "footer.njk" %} - - - - diff --git a/containers/weblibreportal/src/_includes/topbar.njk b/containers/weblibreportal/src/_includes/topbar.njk deleted file mode 100644 index 2927da7..0000000 --- a/containers/weblibreportal/src/_includes/topbar.njk +++ /dev/null @@ -1,31 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/adguard.svg b/containers/weblibreportal/src/assets/apps/adguard.svg deleted file mode 100644 index f6118fc..0000000 --- a/containers/weblibreportal/src/assets/apps/adguard.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/authelia.svg b/containers/weblibreportal/src/assets/apps/authelia.svg deleted file mode 100644 index 9880b3b..0000000 --- a/containers/weblibreportal/src/assets/apps/authelia.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/bookstack.svg b/containers/weblibreportal/src/assets/apps/bookstack.svg deleted file mode 100644 index a6ad581..0000000 --- a/containers/weblibreportal/src/assets/apps/bookstack.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/crowdsec.svg b/containers/weblibreportal/src/assets/apps/crowdsec.svg deleted file mode 100644 index fd4ffac..0000000 --- a/containers/weblibreportal/src/assets/apps/crowdsec.svg +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/containers/weblibreportal/src/assets/apps/dashy.svg b/containers/weblibreportal/src/assets/apps/dashy.svg deleted file mode 100644 index ce68744..0000000 --- a/containers/weblibreportal/src/assets/apps/dashy.svg +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/containers/weblibreportal/src/assets/apps/default.svg b/containers/weblibreportal/src/assets/apps/default.svg deleted file mode 100644 index 343d2de..0000000 --- a/containers/weblibreportal/src/assets/apps/default.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/focalboard.svg b/containers/weblibreportal/src/assets/apps/focalboard.svg deleted file mode 100644 index b78e7e3..0000000 --- a/containers/weblibreportal/src/assets/apps/focalboard.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/gitea.svg b/containers/weblibreportal/src/assets/apps/gitea.svg deleted file mode 100644 index 11c6df8..0000000 --- a/containers/weblibreportal/src/assets/apps/gitea.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/containers/weblibreportal/src/assets/apps/gluetun.svg b/containers/weblibreportal/src/assets/apps/gluetun.svg deleted file mode 100644 index a39521c..0000000 --- a/containers/weblibreportal/src/assets/apps/gluetun.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/containers/weblibreportal/src/assets/apps/grafana.svg b/containers/weblibreportal/src/assets/apps/grafana.svg deleted file mode 100644 index 54be1e2..0000000 --- a/containers/weblibreportal/src/assets/apps/grafana.svg +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/containers/weblibreportal/src/assets/apps/headscale.svg b/containers/weblibreportal/src/assets/apps/headscale.svg deleted file mode 100644 index 06f406a..0000000 --- a/containers/weblibreportal/src/assets/apps/headscale.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/invidious.svg b/containers/weblibreportal/src/assets/apps/invidious.svg deleted file mode 100644 index 80e78a4..0000000 --- a/containers/weblibreportal/src/assets/apps/invidious.svg +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/containers/weblibreportal/src/assets/apps/ipinfo.svg b/containers/weblibreportal/src/assets/apps/ipinfo.svg deleted file mode 100644 index 656169c..0000000 --- a/containers/weblibreportal/src/assets/apps/ipinfo.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/jellyfin.svg b/containers/weblibreportal/src/assets/apps/jellyfin.svg deleted file mode 100644 index 0e56a50..0000000 --- a/containers/weblibreportal/src/assets/apps/jellyfin.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/jitsimeet.svg b/containers/weblibreportal/src/assets/apps/jitsimeet.svg deleted file mode 100644 index 5a3526a..0000000 --- a/containers/weblibreportal/src/assets/apps/jitsimeet.svg +++ /dev/null @@ -1,650 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/containers/weblibreportal/src/assets/apps/libreportal.svg b/containers/weblibreportal/src/assets/apps/libreportal.svg deleted file mode 100644 index a476796..0000000 --- a/containers/weblibreportal/src/assets/apps/libreportal.svg +++ /dev/null @@ -1,605 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/containers/weblibreportal/src/assets/apps/linkding.svg b/containers/weblibreportal/src/assets/apps/linkding.svg deleted file mode 100644 index 089630d..0000000 --- a/containers/weblibreportal/src/assets/apps/linkding.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/mastodon.svg b/containers/weblibreportal/src/assets/apps/mastodon.svg deleted file mode 100644 index dd5075e..0000000 --- a/containers/weblibreportal/src/assets/apps/mastodon.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/nextcloud.svg b/containers/weblibreportal/src/assets/apps/nextcloud.svg deleted file mode 100644 index 336aff5..0000000 --- a/containers/weblibreportal/src/assets/apps/nextcloud.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/containers/weblibreportal/src/assets/apps/ollama.svg b/containers/weblibreportal/src/assets/apps/ollama.svg deleted file mode 100644 index 6bba73a..0000000 --- a/containers/weblibreportal/src/assets/apps/ollama.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/onlyoffice.svg b/containers/weblibreportal/src/assets/apps/onlyoffice.svg deleted file mode 100644 index 364522c..0000000 --- a/containers/weblibreportal/src/assets/apps/onlyoffice.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/owncloud.svg b/containers/weblibreportal/src/assets/apps/owncloud.svg deleted file mode 100644 index cf650c7..0000000 --- a/containers/weblibreportal/src/assets/apps/owncloud.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/pihole.svg b/containers/weblibreportal/src/assets/apps/pihole.svg deleted file mode 100644 index 5bda461..0000000 --- a/containers/weblibreportal/src/assets/apps/pihole.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/portainer.svg b/containers/weblibreportal/src/assets/apps/portainer.svg deleted file mode 100644 index 45cf83a..0000000 --- a/containers/weblibreportal/src/assets/apps/portainer.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/prometheus.svg b/containers/weblibreportal/src/assets/apps/prometheus.svg deleted file mode 100644 index 309d704..0000000 --- a/containers/weblibreportal/src/assets/apps/prometheus.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/searxng.svg b/containers/weblibreportal/src/assets/apps/searxng.svg deleted file mode 100644 index 2ddf53b..0000000 --- a/containers/weblibreportal/src/assets/apps/searxng.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/speedtest.svg b/containers/weblibreportal/src/assets/apps/speedtest.svg deleted file mode 100644 index 2fd0d2b..0000000 --- a/containers/weblibreportal/src/assets/apps/speedtest.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/traefik.svg b/containers/weblibreportal/src/assets/apps/traefik.svg deleted file mode 100644 index a86b9b7..0000000 --- a/containers/weblibreportal/src/assets/apps/traefik.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/trilium.svg b/containers/weblibreportal/src/assets/apps/trilium.svg deleted file mode 100644 index 2ecb6e4..0000000 --- a/containers/weblibreportal/src/assets/apps/trilium.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/unbound.svg b/containers/weblibreportal/src/assets/apps/unbound.svg deleted file mode 100644 index cfc5d8d..0000000 --- a/containers/weblibreportal/src/assets/apps/unbound.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/vaultwarden.svg b/containers/weblibreportal/src/assets/apps/vaultwarden.svg deleted file mode 100644 index 41ca105..0000000 --- a/containers/weblibreportal/src/assets/apps/vaultwarden.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/apps/wireguard.svg b/containers/weblibreportal/src/assets/apps/wireguard.svg deleted file mode 100644 index b778001..0000000 --- a/containers/weblibreportal/src/assets/apps/wireguard.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/containers/weblibreportal/src/assets/favicon.ico b/containers/weblibreportal/src/assets/favicon.ico deleted file mode 100644 index 622f2d3..0000000 Binary files a/containers/weblibreportal/src/assets/favicon.ico and /dev/null differ diff --git a/containers/weblibreportal/src/assets/libreportal.svg b/containers/weblibreportal/src/assets/libreportal.svg deleted file mode 100644 index a476796..0000000 --- a/containers/weblibreportal/src/assets/libreportal.svg +++ /dev/null @@ -1,605 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/containers/weblibreportal/src/assets/main.js b/containers/weblibreportal/src/assets/main.js deleted file mode 100644 index d9dda04..0000000 --- a/containers/weblibreportal/src/assets/main.js +++ /dev/null @@ -1,66 +0,0 @@ -// LibrePortal site — interactions (mobile drawer, copy, scrollspy, reveal, app filter) -(() => { - // mobile drawer (same behaviour as the dashboard) - const menuToggle = document.getElementById('mobile-menu-toggle'); - const drawer = document.getElementById('mobile-drawer'); - if (menuToggle && drawer) { - menuToggle.addEventListener('click', () => { - const open = drawer.classList.toggle('mobile-open'); - document.body.style.overflow = open ? 'hidden' : ''; - }); - drawer.querySelectorAll('a').forEach((a) => - a.addEventListener('click', () => { drawer.classList.remove('mobile-open'); document.body.style.overflow = ''; })); - } - - // copy the install command - const cmdEl = document.querySelector('[data-install-cmd]'); - const CMD = cmdEl ? cmdEl.getAttribute('data-install-cmd') : ''; - document.querySelectorAll('.copy').forEach((btn) => { - btn.addEventListener('click', async () => { - try { await navigator.clipboard.writeText(CMD); } - catch { const t = document.createElement('textarea'); t.value = CMD; document.body.appendChild(t); t.select(); document.execCommand('copy'); t.remove(); } - btn.classList.add('done'); - const span = btn.querySelector('span'); const prev = span.textContent; span.textContent = 'Copied ✓'; - setTimeout(() => { btn.classList.remove('done'); span.textContent = prev; }, 1700); - }); - }); - - // scrollspy → light up the active topbar pill - const spies = [...document.querySelectorAll('.nav-item[data-spy]')]; - if (spies.length) { - const spyIO = new IntersectionObserver((entries) => { - entries.forEach((e) => { - if (e.isIntersecting) spies.forEach((s) => s.classList.toggle('nav-active', s.dataset.spy === e.target.id)); - }); - }, { rootMargin: '-45% 0px -50% 0px', threshold: 0 }); - spies.map((s) => document.getElementById(s.dataset.spy)).filter(Boolean).forEach((s) => spyIO.observe(s)); - } - - // reveal on scroll - const io = new IntersectionObserver((entries) => { - entries.forEach((e) => { if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); } }); - }, { threshold: 0.16, rootMargin: '0px 0px -8% 0px' }); - document.querySelectorAll('.reveal, .stagger').forEach((el) => io.observe(el)); - - // app category filter - const filters = document.querySelector('.app-filters'); - if (filters) { - const cards = [...document.querySelectorAll('.app-card')]; - const countEl = document.querySelector('.app-count'); - const update = (cat) => { - let shown = 0; - cards.forEach((c) => { - const match = cat === 'all' || (c.dataset.cats || '').split(' ').includes(cat); - c.classList.toggle('hidden', !match); - if (match) shown++; - }); - if (countEl) countEl.textContent = `${shown} app${shown === 1 ? '' : 's'}`; - }; - filters.addEventListener('click', (e) => { - const chip = e.target.closest('.chip'); - if (!chip) return; - filters.querySelectorAll('.chip').forEach((c) => c.classList.toggle('active', c === chip)); - update(chip.dataset.cat); - }); - } -})(); diff --git a/containers/weblibreportal/src/assets/style.css b/containers/weblibreportal/src/assets/style.css deleted file mode 100644 index c187888..0000000 --- a/containers/weblibreportal/src/assets/style.css +++ /dev/null @@ -1,276 +0,0 @@ -/* ============ NEBULA THEME (lifted from the dashboard) ============ */ -:root{ - --gradient-from:#1a1442; /* indigo */ - --gradient-mid:#1b2a5e; /* violet-blue */ - --gradient-to:#0f3b6e; /* ocean */ - --surface-solid:#0f1729; - - --accent:#00d4ff; - --accent-hover:#0099cc; - --accent-rgb:0,212,255; - --accent-soft:rgba(0,212,255,.15); - - --text-primary:#ffffff; - --text-secondary:rgba(255,255,255,.82); - --text-muted:rgba(255,255,255,.65); - --text-faint:rgba(255,255,255,.45); - --text-on-accent:#0a1426; - --text-rgb:255,255,255; - - --border:rgba(255,255,255,.16); - --border-strong:rgba(255,255,255,.26); - --border-subtle:rgba(255,255,255,.08); - - --card-bg:linear-gradient(155deg, rgba(255,255,255,.09) 0%, rgba(0,212,255,.05) 100%); - --card-border:rgba(255,255,255,.16); - --card-shadow:0 4px 18px rgba(0,0,0,.30), inset 0 1px 0 rgba(255,255,255,.06); - --card-shadow-hover:0 10px 32px rgba(0,212,255,.18), 0 4px 18px rgba(0,0,0,.40), inset 0 1px 0 rgba(255,255,255,.10); - - --topbar-bg:rgba(15,25,50,.40); - --console-bg:rgba(0,0,0,.40); - --surface-bg-solid:#0f1729; - - --font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; - --font-mono:"SF Mono", "Monaco", "Menlo", "Ubuntu Mono", "Courier New", monospace; - - --maxw:1180px; - --ease:cubic-bezier(.22,.61,.36,1); -} - -*{box-sizing:border-box;margin:0;padding:0} -html{scroll-behavior:smooth} -body{font-family:var(--font-sans);background:var(--surface-solid);color:var(--text-primary); - line-height:1.6;overflow-x:hidden;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility} - -/* ============ AURORA BACKDROP (from aurora-background.css) ============ */ -.cosmos{position:fixed;inset:0;z-index:-2;pointer-events:none;overflow:hidden; - background: - radial-gradient(ellipse at 20% 22%, var(--gradient-mid) 0%, transparent 55%), - radial-gradient(ellipse at 82% 74%, var(--gradient-to) 0%, transparent 55%), - linear-gradient(135deg, var(--gradient-from) 0%, var(--gradient-from) 40%, var(--gradient-mid) 100%);} -.cosmos::before{content:'';position:absolute;inset:-25%; - background:conic-gradient(from 0deg at 50% 50%, - rgba(var(--accent-rgb),0) 0deg, rgba(var(--accent-rgb),.18) 60deg, - rgba(var(--accent-rgb),.22) 130deg, rgba(var(--accent-rgb),.20) 200deg, - rgba(var(--accent-rgb),.18) 280deg, rgba(var(--accent-rgb),0) 360deg); - filter:blur(70px);animation:auroraSpin 38s linear infinite;} -.cosmos::after{content:'';position:absolute;inset:-10%; - background: - radial-gradient(circle at 18% 22%, rgba(var(--accent-rgb),.38) 0%, transparent 35%), - radial-gradient(circle at 78% 18%, rgba(var(--accent-rgb),.32) 0%, transparent 32%), - radial-gradient(circle at 30% 80%, rgba(var(--accent-rgb),.30) 0%, transparent 38%), - radial-gradient(circle at 84% 82%, rgba(var(--accent-rgb),.34) 0%, transparent 36%), - radial-gradient(circle at 50% 50%, rgba(var(--accent-rgb),.14) 0%, transparent 50%); - filter:blur(50px);animation:auroraDrift 22s ease-in-out infinite alternate;} -.stars{position:fixed;inset:0;z-index:-1;pointer-events:none} -.stars::before,.stars::after{content:'';position:absolute;inset:0;background-repeat:repeat} -.stars::before{background-image: - radial-gradient(1.5px 1.5px at 12px 18px, rgba(var(--text-rgb),.9), transparent 60%), - radial-gradient(1px 1px at 47px 92px, rgba(var(--accent-rgb),.85), transparent 60%), - radial-gradient(1.2px 1.2px at 110px 40px, rgba(var(--text-rgb),.75), transparent 60%), - radial-gradient(1px 1px at 165px 130px, rgba(var(--accent-rgb),.7), transparent 60%); - background-size:200px 200px;animation:auroraTwinkleA 4.5s ease-in-out infinite;} -.stars::after{background-image: - radial-gradient(1px 1px at 30px 60px, rgba(var(--accent-rgb),.8), transparent 60%), - radial-gradient(1.4px 1.4px at 88px 22px, rgba(var(--text-rgb),.7), transparent 60%), - radial-gradient(1px 1px at 140px 100px, rgba(var(--accent-rgb),.85), transparent 60%), - radial-gradient(1.2px 1.2px at 195px 70px, rgba(var(--text-rgb),.6), transparent 60%); - background-size:240px 240px;background-position:80px 50px;animation:auroraTwinkleB 6.5s ease-in-out infinite;} -@keyframes auroraSpin{to{transform:rotate(360deg)}} -@keyframes auroraDrift{0%{transform:translate(0,0) scale(1);opacity:.85}50%{transform:translate(-3%,4%) scale(1.08);opacity:1}100%{transform:translate(2%,-3%) scale(.95);opacity:.9}} -@keyframes auroraTwinkleA{0%,100%{opacity:.55}50%{opacity:1}} -@keyframes auroraTwinkleB{0%,100%{opacity:1}50%{opacity:.45}} - -/* ============ shared ============ */ -.grad{background:linear-gradient(100deg,#7ae9ff,#00d4ff 55%,#0aa6d6); - -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent} -.wrap{max-width:var(--maxw);margin:0 auto;padding:0 clamp(18px,5vw,48px)} -section{position:relative;z-index:1} -.eyebrow{font-family:var(--font-mono);font-size:.74rem;letter-spacing:.22em;text-transform:uppercase;color:var(--accent);margin-bottom:16px;display:block} -h2{font-size:clamp(2rem,4.6vw,3.2rem);line-height:1.08;letter-spacing:-.02em;font-weight:800} -.lead{color:var(--text-secondary);font-size:1.08rem;max-width:54ch;margin-top:18px;font-weight:400} -.pad{padding:clamp(80px,12vh,140px) 0} -.glass{background:var(--card-bg);border:1px solid var(--card-border);box-shadow:var(--card-shadow); - backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)} - -/* ============ TOPBAR — grafted from the dashboard (topbar.css) ============ */ -.topbar{display:flex;justify-content:space-between;align-items:center;padding:0 24px;height:60px; - position:fixed;top:0;left:0;right:0;z-index:1000;background:var(--topbar-bg); - border-bottom:1px solid var(--border);backdrop-filter:blur(12px) saturate(140%);-webkit-backdrop-filter:blur(12px) saturate(140%)} -.mobile-menu-toggle{display:none;background:none;border:none;color:var(--text-primary);cursor:pointer;padding:6px;margin-right:4px} -.topbar-left{display:flex;align-items:center;flex:0 0 auto} -.libreportal-logo{display:flex;align-items:center;gap:10px;text-decoration:none;color:var(--text-primary);font-weight:700;font-size:1.05rem} -.libreportal-logo img{width:32px;height:32px} -.libreportal-logo b{color:var(--accent);font-weight:700} -.mobile-drawer{display:flex;align-items:center;flex:1;justify-content:space-between;gap:12px;min-width:0;margin-left:24px} -.topbar-nav{display:flex;gap:8px;align-items:center} -.topbar-nav .nav-item{background:rgba(var(--text-rgb),.10);border:1px solid rgba(var(--text-rgb),.20);border-radius:8px; - padding:10px 16px;font-size:14px;font-weight:500;color:var(--text-muted);text-decoration:none;display:flex;align-items:center;gap:8px; - transition:all .2s ease;cursor:pointer;min-height:42px;white-space:nowrap} -.topbar-nav .nav-item:hover{background:rgba(var(--text-rgb),.20);transform:translateY(-1px);color:var(--text-primary)} -.topbar-nav .nav-item.nav-active{background:var(--accent);color:var(--text-primary);border-color:var(--accent)} -.topbar-nav .nav-item.nav-active:hover{background:var(--accent-hover);border-color:var(--accent-hover)} -.topbar-nav .nav-item svg{width:16px;height:16px} -.topbar-controls{display:flex;align-items:center;gap:12px} -.tb-ghost{display:inline-flex;align-items:center;gap:6px;padding:8px 14px;border:1px solid var(--border);border-radius:8px; - background:rgba(var(--text-rgb),.05);color:var(--text-secondary);text-decoration:none;font-size:.85rem;font-weight:600;transition:all .2s} -.tb-ghost:hover{background:rgba(var(--text-rgb),.12);color:var(--text-primary)} -.tb-cta{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;border-radius:8px;background:var(--accent); - color:var(--text-on-accent);text-decoration:none;font-size:.85rem;font-weight:700;transition:all .2s} -.tb-cta:hover{background:#22dbff;transform:translateY(-1px);box-shadow:0 8px 22px -8px rgba(var(--accent-rgb),.6)} -@media(max-width:768px){ - .topbar{padding:0 12px;gap:8px;justify-content:flex-start} - .mobile-menu-toggle{display:flex;align-items:center} - .mobile-drawer{position:fixed;top:60px;left:0;width:100vw;height:calc(100vh - 60px);flex-direction:column;align-items:stretch; - justify-content:flex-start;gap:0;padding:16px;margin-left:0;background:var(--surface-bg-solid);border-right:1px solid var(--border); - box-shadow:6px 0 24px rgba(0,0,0,.35);overflow-y:auto;transform:translateX(-100%);transition:transform .3s ease;z-index:101} - .mobile-drawer.mobile-open{transform:translateX(0)} - .mobile-drawer .topbar-nav{flex-direction:column;align-items:stretch;gap:6px;width:100%} - .mobile-drawer .topbar-nav .nav-item{width:100%;justify-content:flex-start} - .mobile-drawer .topbar-controls{flex-direction:column;align-items:stretch;gap:8px;width:100%;margin-top:auto;padding-top:16px; - border-top:1px solid rgba(var(--text-rgb),.12)} - .mobile-drawer .topbar-controls a{width:100%;justify-content:center} -} - -/* ============ hero ============ */ -header.hero{min-height:100vh;display:flex;flex-direction:column;justify-content:center;align-items:center; - text-align:center;padding:140px clamp(18px,5vw,48px) 90px;position:relative} -.badge{display:inline-flex;align-items:center;gap:8px;font-family:var(--font-mono);font-size:.72rem; - letter-spacing:.14em;text-transform:uppercase;color:var(--accent);padding:7px 15px;border-radius:999px; - border:1px solid rgba(var(--accent-rgb),.35);background:var(--accent-soft);margin-bottom:30px} -.badge .dot{width:6px;height:6px;border-radius:50%;background:var(--accent);box-shadow:0 0 10px var(--accent);animation:pulse 2.4s ease-in-out infinite} -@keyframes pulse{0%,100%{opacity:.4}50%{opacity:1}} -.hero-logo{width:64px;height:64px;margin-bottom:22px;filter:drop-shadow(0 6px 24px rgba(var(--accent-rgb),.45))} -h1{font-size:clamp(2.6rem,7vw,5.2rem);line-height:1.03;letter-spacing:-.03em;font-weight:800;max-width:15ch} -.sub{margin:26px auto 0;max-width:50ch;font-size:clamp(1.02rem,2vw,1.2rem);color:var(--text-secondary);font-weight:400} - -/* install portal */ -.portal{margin:46px auto 0;width:min(660px,100%);position:relative} -.portal::before{content:"";position:absolute;inset:-26px;border-radius:28px;z-index:-1; - background:radial-gradient(60% 80% at 50% 50%, rgba(var(--accent-rgb),.5), transparent 70%);filter:blur(22px);animation:breathe 6s ease-in-out infinite} -@keyframes breathe{0%,100%{opacity:.45;transform:scale(.98)}50%{opacity:.8;transform:scale(1.03)}} -.term{border:1px solid var(--card-border);border-radius:16px;overflow:hidden; - background:linear-gradient(155deg, rgba(255,255,255,.10) 0%, rgba(0,212,255,.06) 100%); - backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);box-shadow:var(--card-shadow-hover)} -.term-bar{display:flex;align-items:center;gap:7px;padding:12px 16px;border-bottom:1px solid var(--border-subtle);background:var(--console-bg)} -.term-bar i{width:11px;height:11px;border-radius:50%;display:block} -.term-bar i:nth-child(1){background:#ff6b5e}.term-bar i:nth-child(2){background:#ffc107}.term-bar i:nth-child(3){background:var(--accent)} -.term-bar em{margin-left:auto;font-family:var(--font-mono);font-size:.72rem;color:var(--text-faint);font-style:normal} -.term-body{display:flex;align-items:center;gap:14px;padding:22px 20px} -.term-body code{font-family:var(--font-mono);font-size:clamp(.82rem,2.3vw,1.02rem);color:var(--text-primary); - white-space:nowrap;overflow-x:auto;flex:1;text-align:left;scrollbar-width:none} -.term-body code::-webkit-scrollbar{display:none} -.term-body code .p{color:var(--accent)} -.term-body code .u{color:#e6f3ff} -.copy{flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;font-family:var(--font-sans);font-weight:700; - font-size:.84rem;color:var(--text-on-accent);background:var(--accent);border:none;border-radius:9px;padding:9px 15px;cursor:pointer; - transition:transform .15s,background .25s,box-shadow .25s} -.copy:hover{transform:translateY(-1px);background:#22dbff;box-shadow:0 8px 22px -8px rgba(var(--accent-rgb),.7)} -.copy.done{background:#28a745;color:#fff} -.portal-foot{display:flex;align-items:center;justify-content:center;gap:16px;margin-top:16px;flex-wrap:wrap;font-size:.86rem;color:var(--text-faint)} -.portal-foot a{color:var(--text-secondary);text-decoration:none;border-bottom:1px dashed rgba(255,255,255,.3);transition:color .2s,border-color .2s} -.portal-foot a:hover{color:var(--accent);border-color:var(--accent)} -.hint{font-family:var(--font-mono);font-size:.78rem} -.scroll-cue{position:absolute;bottom:28px;left:50%;transform:translateX(-50%);color:var(--text-faint); - font-family:var(--font-mono);font-size:.66rem;letter-spacing:.2em;text-transform:uppercase; - display:flex;flex-direction:column;align-items:center;gap:8px;animation:bob 2.6s ease-in-out infinite} -.scroll-cue::after{content:"";width:1px;height:34px;background:linear-gradient(var(--text-faint),transparent)} -@keyframes bob{0%,100%{transform:translateX(-50%) translateY(0)}50%{transform:translateX(-50%) translateY(8px)}} - -/* ============ features ============ */ -.feat-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:54px} -.card{border-radius:16px;padding:28px 26px;position:relative;overflow:hidden;transition:transform .4s var(--ease),border-color .4s,box-shadow .4s} -.card:hover{transform:translateY(-6px);border-color:rgba(var(--accent-rgb),.45);box-shadow:var(--card-shadow-hover)} -.card .ico{width:44px;height:44px;border-radius:12px;display:grid;place-items:center;margin-bottom:18px; - background:var(--accent-soft);border:1px solid rgba(var(--accent-rgb),.30)} -.card .ico svg{width:22px;height:22px;stroke:var(--accent);fill:none;stroke-width:1.6} -.card h3{font-size:1.24rem;margin-bottom:8px;font-weight:700;letter-spacing:-.01em} -.card p{color:var(--text-secondary);font-size:.96rem} - -/* ============ apps (data-driven) ============ */ -.apps-section{text-align:center} -.app-filters{display:flex;flex-wrap:wrap;justify-content:center;gap:10px;margin-top:40px} -.chip{font-family:var(--font-mono);font-size:.76rem;letter-spacing:.04em;padding:8px 15px;border-radius:999px; - border:1px solid var(--border);background:rgba(255,255,255,.05);color:var(--text-secondary);cursor:pointer;transition:all .2s} -.chip:hover{color:var(--text-primary);border-color:rgba(var(--accent-rgb),.45)} -.chip.active{background:var(--accent);color:var(--text-on-accent);border-color:var(--accent);font-weight:600} -.chip .n{opacity:.55;margin-left:6px} -.app-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(248px,1fr));gap:16px;margin-top:34px;text-align:left} -.app-card{border-radius:14px;padding:20px;display:flex;flex-direction:column;gap:11px;transition:transform .3s var(--ease),border-color .3s,box-shadow .3s} -.app-card.hidden{display:none} -.app-card:hover{transform:translateY(-4px);border-color:rgba(var(--accent-rgb),.4);box-shadow:var(--card-shadow-hover)} -.app-card-head{display:flex;align-items:center;gap:12px} -.app-ico{width:42px;height:42px;border-radius:10px;background:rgba(255,255,255,.06);padding:6px;object-fit:contain;border:1px solid var(--border-subtle);flex:0 0 auto} -.app-card h3{font-size:1.06rem;font-weight:700;line-height:1.2} -.app-cat{font-family:var(--font-mono);font-size:.64rem;letter-spacing:.1em;text-transform:uppercase;color:var(--accent)} -.app-card p{font-size:.9rem;color:var(--text-secondary);margin:0} -.app-count{margin-top:26px;color:var(--text-faint);font-size:.85rem;font-family:var(--font-mono)} - -/* ============ connect / courier ============ */ -.connect{display:grid;grid-template-columns:1.05fr .95fr;gap:60px;align-items:center} -.pill{display:inline-flex;align-items:center;gap:8px;font-family:var(--font-mono);font-size:.72rem; - letter-spacing:.1em;text-transform:uppercase;color:var(--text-secondary);padding:7px 14px;border-radius:999px; - border:1px solid var(--border);background:rgba(255,255,255,.04);margin-top:24px} -.connect ul{list-style:none;margin-top:26px;display:flex;flex-direction:column;gap:15px} -.connect li{display:flex;gap:13px;color:var(--text-secondary);font-size:1rem} -.connect li svg{flex:0 0 auto;width:21px;height:21px;stroke:var(--accent);fill:none;stroke-width:1.6;margin-top:3px} -.connect li b{color:var(--text-primary);font-weight:700} -.vault{position:relative;aspect-ratio:1;display:grid;place-items:center} -.vault svg{width:min(360px,82%);height:auto;overflow:visible} -.orbit{transform-origin:center;animation:spin 26s linear infinite} -@keyframes spin{to{transform:rotate(360deg)}} - -/* ============ promise ============ */ -.promise{text-align:center} -.pledges{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-top:52px} -.pledge{border-radius:14px;padding:28px 18px} -.pledge .big{font-size:2.4rem;font-weight:800;margin-bottom:8px;line-height:1} -.pledge p{font-size:.92rem;color:var(--text-secondary)} -.promise .link{display:inline-block;margin-top:40px;color:var(--accent);text-decoration:none;font-weight:700; - border-bottom:1px solid rgba(var(--accent-rgb),.45);padding-bottom:2px;transition:color .2s,border-color .2s} -.promise .link:hover{color:#fff;border-color:#fff} - -/* ============ final ============ */ -.final{text-align:center;padding:clamp(90px,14vh,160px) 0} -.final h2{max-width:18ch;margin-inline:auto} -.final .portal{margin-top:42px} - -/* ============ footer ============ */ -footer{border-top:1px solid var(--border-subtle);padding:54px 0 70px;margin-top:40px;background:rgba(10,16,32,.55);backdrop-filter:blur(8px)} -.foot-grid{display:flex;justify-content:space-between;gap:40px;flex-wrap:wrap;align-items:flex-start} -.foot-grid .libreportal-logo{margin-bottom:14px} -.foot-col h4{font-size:.74rem;letter-spacing:.16em;text-transform:uppercase;color:var(--text-faint);margin-bottom:14px;font-family:var(--font-mono)} -.foot-col a{display:block;color:var(--text-secondary);text-decoration:none;font-size:.95rem;margin-bottom:9px;transition:color .2s} -.foot-col a:hover{color:var(--accent)} -.colophon{margin-top:46px;padding-top:26px;border-top:1px solid var(--border-subtle); - display:flex;justify-content:space-between;gap:18px;flex-wrap:wrap;color:var(--text-faint);font-size:.86rem} -.colophon a{color:var(--text-secondary);text-decoration:none} -.colophon a:hover{color:var(--accent)} - -/* ============ reveal ============ */ -.reveal{opacity:0;transform:translateY(28px);transition:opacity .9s var(--ease),transform .9s var(--ease)} -.reveal.in{opacity:1;transform:none} -.stagger>*{opacity:0;transform:translateY(20px);transition:opacity .7s var(--ease),transform .7s var(--ease)} -.stagger.in>*{opacity:1;transform:none} -.stagger.in>*:nth-child(2){transition-delay:.07s}.stagger.in>*:nth-child(3){transition-delay:.14s} -.stagger.in>*:nth-child(4){transition-delay:.21s}.stagger.in>*:nth-child(5){transition-delay:.28s}.stagger.in>*:nth-child(6){transition-delay:.35s} -.h-anim{opacity:0;transform:translateY(24px);animation:rise .95s var(--ease) forwards} -.d1{animation-delay:.05s}.d2{animation-delay:.16s}.d3{animation-delay:.28s}.d4{animation-delay:.4s}.d5{animation-delay:.52s} -@keyframes rise{to{opacity:1;transform:none}} - -/* ============ responsive ============ */ -@media(max-width:860px){ - .feat-grid{grid-template-columns:1fr 1fr} - .connect{grid-template-columns:1fr;gap:36px} - .vault{order:-1;max-width:320px;margin-inline:auto} - .pledges{grid-template-columns:1fr 1fr} -} -@media(max-width:540px){ - .feat-grid{grid-template-columns:1fr} - .term-body{flex-direction:column;align-items:stretch} - .copy{justify-content:center} -} -@media(prefers-reduced-motion:reduce){ - *{animation:none!important;transition:none!important} - .reveal,.stagger>*,.h-anim{opacity:1;transform:none} -} diff --git a/containers/weblibreportal/src/index.njk b/containers/weblibreportal/src/index.njk deleted file mode 100644 index 8815eef..0000000 --- a/containers/weblibreportal/src/index.njk +++ /dev/null @@ -1,162 +0,0 @@ ---- -layout: layout.njk ---- - -
- {{ site.version }} · early days, no telemetry ever - -

Your own private corner
of the universe

-

Self-host the apps you actually rely on — on your own server. - One command brings up a whole platform, and your data never leaves your orbit.

- -
-
-
~ one command, your whole server
-
- bash <(curl -fsSL {{ site.installUrl }}) init - -
-
-
- curl·to·shell, on a privacy tool? read it first → - · - or clone the repo -
-
- -
explore
-
- - -
- What comes online -

A whole platform, handled for you

-

No yak-shaving. LibrePortal wires up the boring, fiddly infrastructure so you can run the good stuff.

- -
-
-
-

One-click apps

-

Nextcloud, Vaultwarden, Jellyfin, Gitea and dozens more — picked from a menu, deployed clean.

-
-
-
-

Traefik + auto-SSL

-

A reverse proxy with automatic Let's Encrypt certificates. HTTPS everywhere, configured for you.

-
-
-
-

Rootless Docker

-

Containers run without root and with sane security defaults — CrowdSec on guard out of the box.

-
-
-
-

A real dashboard

-

Install, configure, back up and monitor everything from a clean web UI. No SSH archaeology.

-
-
-
-

Optional VPN routing

-

Send any app's traffic through gluetun. Keep the things that should be private, private.

-
-
-
-

No telemetry

-

Nothing phones home. No accounts required to self-host. The software is yours, entirely.

-
-
-
- - -
- The constellation -

Dozens of apps, one sky

-

Pulled straight from the repo — {{ apps.length }} apps you can light up from the dashboard, and switch off just as easily.

- -
- - {%- for c in categories %} - - {%- endfor %} -
- -
- {%- for app in apps %} - {% include "app-card.njk" %} - {%- endfor %} -
-

{{ apps.length }} apps

-
- - -
-
-
- LibrePortal Connect · optional -

We're the courier.
You hold the key.

-

Reaching your server from your phone and keeping off-site backups are the fiddly bits. - Connect handles them — but works like a courier carrying a sealed box.

-
    -
  • Reach it anywhere. No port-forwarding, no exposing your box to the internet.
  • -
  • Encrypted off-site backups. We only ever hold a locked box — you keep the only key.
  • -
  • We never run your apps. Your data and keys never leave your machine.
  • -
- every part is free to self-host, too — you pay only for convenience -
-
- -
-
-
- - -
- The promise -

Free software, and it stays that way

-

In plain language, so you can hold us to it.

-
-
100%

Every feature, free to self-host. Forever. No crippled edition.

-
0

Trackers. No telemetry, no phoning home, no accounts to run it.

-

Feature paywalls. You never pay to unlock — only for convenience.

-

What's open stays open. No rug-pulls, ever. AGPLv3.

-
- Read the full Promise → -
- - -
- Ready when you are -

Light up your corner
of the universe.

-
-
-
~
-
- bash <(curl -fsSL {{ site.installUrl }}) init - -
-
-
-
diff --git a/containers/weblibreportal/weblibreportal.config b/containers/weblibreportal/weblibreportal.config deleted file mode 100644 index 7eca311..0000000 --- a/containers/weblibreportal/weblibreportal.config +++ /dev/null @@ -1,45 +0,0 @@ -# -# ============================================================================= -# GENERAL CONFIGURATION -# ============================================================================= -# APP_NAME = name of application for use in scripts -# COMPOSE_FILE = default for no app_name in docker-compose file name, app if there is -# BACKUP = if true, include this application in backup operations -# HEALTHCHECK = if true, default docker health checks for that container will be enabled -# AUTHELIA = if true, use Authelia authentication, if false turned off. -# HEADSCALE = options : false, local, remote (see general config). e.g false or local,remote -# -CFG_WEBLIBREPORTAL_APP_NAME=weblibreportal -CFG_WEBLIBREPORTAL_BACKUP=false -CFG_WEBLIBREPORTAL_BACKUP_STRATEGY=auto -CFG_WEBLIBREPORTAL_COMPOSE_FILE=default -CFG_WEBLIBREPORTAL_HEALTHCHECK=true -CFG_WEBLIBREPORTAL_AUTHELIA=false -CFG_WEBLIBREPORTAL_HEADSCALE=false -# -# ============================================================================= -# METADATA -# ============================================================================= -CFG_WEBLIBREPORTAL_CATEGORY="features" -CFG_WEBLIBREPORTAL_TITLE="LibrePortal Website" -CFG_WEBLIBREPORTAL_DESCRIPTION="The libreportal.org marketing/docs site" -CFG_WEBLIBREPORTAL_LONG_DESCRIPTION="The LibrePortal website (Eleventy), data-driven from the app catalogue. Build + publish its docroot with containers/weblibreportal/publish.sh." -CFG_WEBLIBREPORTAL_URL="https://libreportal.org" -CFG_WEBLIBREPORTAL_ACTIONS="configure|install|restart|shutdown|uninstall" -# -# ============================================================================= -# NETWORK CONFIGURATION -# ============================================================================= -# DOMAIN = number of domain from the general config, useful when using multiple domains -# WHITELIST = if true only allow whitelisted ips on traefik, if false allow all -# -CFG_WEBLIBREPORTAL_DOMAIN=1 -CFG_WEBLIBREPORTAL_WHITELIST=false -CFG_WEBLIBREPORTAL_NETWORK=default -# -# ============================================================================= -# PORT CONFIGURATION -# ============================================================================= -# PORT_ = app|name|external:internal|access|protocol|login|traefik|webui|title|path|slug -# -CFG_WEBLIBREPORTAL_PORT_1="weblibreportal-service|webui|random:80|public|tcp|false|true|true|Website|/|weblibreportal" diff --git a/containers/weblibreportal/weblibreportal.sh b/containers/weblibreportal/weblibreportal.sh deleted file mode 100644 index fee5aa1..0000000 --- a/containers/weblibreportal/weblibreportal.sh +++ /dev/null @@ -1,108 +0,0 @@ -#!/bin/bash - -# Category : Features -# Description : weblibreportal - The LibrePortal website (c/u/s/r/i): - -installWeblibreportal() -{ - local config_variables="$1" - - if [[ "$weblibreportal" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent weblibreportal; - local app_name=$CFG_WEBLIBREPORTAL_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$weblibreportal" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$weblibreportal" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$weblibreportal" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$weblibreportal" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$weblibreportal" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Build the site, then browse $app_name." - echo "" - echo " The container serves an EMPTY docroot until you build the site." - echo " From a full repo checkout run:" - echo " containers/weblibreportal/publish.sh $containers_dir$app_name/data" - echo " (runs the Eleventy build → docroot)." - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - cd - fi - weblibreportal=n -} diff --git a/containers/weblibreportal/weblibreportal.svg b/containers/weblibreportal/weblibreportal.svg deleted file mode 100644 index a197da1..0000000 --- a/containers/weblibreportal/weblibreportal.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 12d7b88..caedbdd 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -75,9 +75,10 @@ sudo ./init.sh --skip-docker-images uninstall # keep the Docker layer for a fa - `libreportal-.tar.gz` — the release - `libreportal-.tar.gz.sha256` — its checksum - `latest.json` — `{ version, channel, url, sha256, notes }` (the channel pointer) -3. **Publish** by copying `dist//*` to the host so they're served at - `https://get.libreportal.org//…` (Phase E — the `getlibreportal` - container; not built yet). `latest.json` is what makes a version "the latest". +3. **Publish** by serving `dist//*` at `https://get.libreportal.org//…`. + The host (the `getlibreportal` + `weblibreportal` apps) lives in the separate + **LibrePortal-Infra** repo, which overlays onto an install and picks these up via + its `publish.sh`. `latest.json` is what makes a version "the latest". **Channels:** `stable` is the default users get; `edge` is for early/testing builds. Same tooling, different ``. To promote an edge build to stable, diff --git a/scripts/app/containers/getlibreportal/getlibreportal_publish.sh b/scripts/app/containers/getlibreportal/getlibreportal_publish.sh deleted file mode 100644 index 4605068..0000000 --- a/scripts/app/containers/getlibreportal/getlibreportal_publish.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -# Tool: getlibreportal "publish" — assemble the download host's docroot -# (install.sh + the dist/ release artifacts) into its served data dir. -# Runs as the container user (it owns the data dir); reads the manager-owned -# install tree. Build-box only — needs a populated dist/ (run make_release first). -appGetlibreportalPublish() -{ - isHeader "Publish downloads (getlibreportal)" - local app=getlibreportal - local pub="${install_containers_dir}${app}/publish.sh" - local data="${containers_dir}${app}/data" - - [[ -f "$pub" ]] || { isError "publish.sh not found at $pub — full repo checkout needed."; return 1; } - - runFileOp mkdir -p "$data" - if runFileOp bash "$pub" "$data"; then - isSuccessful "Downloads published. Restart $app to serve it." - else - isError "Publish failed (is dist/ present? run scripts/release/make_release.sh first)." - return 1 - fi -} diff --git a/scripts/app/containers/weblibreportal/weblibreportal_publish.sh b/scripts/app/containers/weblibreportal/weblibreportal_publish.sh deleted file mode 100644 index e66aa92..0000000 --- a/scripts/app/containers/weblibreportal/weblibreportal_publish.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -# Tool: weblibreportal "publish" — build the Eleventy website and publish it into -# the served data dir. The build runs as the manager (owns the install tree where -# the source + node build live); the result is synced into the container-user-owned -# docroot. Build-box only — needs the repo checkout + npm. -appWeblibreportalPublish() -{ - isHeader "Publish website (weblibreportal)" - local app=weblibreportal - local appdir="${install_containers_dir}${app}" - local data="${containers_dir}${app}/data" - - command -v npm >/dev/null 2>&1 || { isError "npm not found — publishing the website needs a dev/build box."; return 1; } - [[ -f "$appdir/package.json" ]] || { isError "website source not at $appdir — full repo checkout needed."; return 1; } - - isNotice "Building the site (Eleventy)..." - if ! ( cd "$appdir" && runInstallOp npm install --silent && runInstallOp npm run build ); then - isError "Site build failed." - return 1 - fi - - isNotice "Publishing into the docroot..." - runFileOp mkdir -p "$data" - runFileOp sh -c "rm -rf \"$data\"/* \"$data\"/.??* 2>/dev/null; cp -a \"$appdir/dist/.\" \"$data/\"" - isSuccessful "Website published. Restart $app to serve it." -} diff --git a/scripts/source/files/arrays/files_app.sh b/scripts/source/files/arrays/files_app.sh index cf0790e..86c143b 100755 --- a/scripts/source/files/arrays/files_app.sh +++ b/scripts/source/files/arrays/files_app.sh @@ -38,7 +38,6 @@ app_scripts=( "app/containers/focalboard/focalboard_list_users.sh" "app/containers/focalboard/focalboard_reset_password.sh" "app/containers/focalboard/focalboard_set_admin.sh" - "app/containers/getlibreportal/getlibreportal_publish.sh" "app/containers/gitea/gitea_auth.sh" "app/containers/gitea/gitea_create_account.sh" "app/containers/gitea/gitea_delete_user.sh" @@ -74,6 +73,5 @@ app_scripts=( "app/containers/pihole/pihole_apply_dns_updater.sh" "app/containers/traefik/traefik_auth.sh" "app/containers/traefik/traefik_reset_password.sh" - "app/containers/weblibreportal/weblibreportal_publish.sh" ) diff --git a/scripts/webui/data/generators/apps/webui_tools.sh b/scripts/webui/data/generators/apps/webui_tools.sh index 1ca0b78..5507a14 100644 --- a/scripts/webui/data/generators/apps/webui_tools.sh +++ b/scripts/webui/data/generators/apps/webui_tools.sh @@ -409,28 +409,6 @@ webuiGenerateAppsToolsConfig() { ] } ] - }, - "getlibreportal": { - "tools": [ - { - "id": "publish", - "label": "Publish downloads", - "description": "Rebuild the get.libreportal.org docroot — copy install.sh + the dist/ release artifacts into the served data dir (live on next restart). Build-box only: needs the repo checkout + a built dist/ (run make_release first).", - "icon": "📦", - "fields": [] - } - ] - }, - "weblibreportal": { - "tools": [ - { - "id": "publish", - "label": "Publish website", - "description": "Rebuild the LibrePortal website (Eleventy) into the served data dir (live on next restart). Build-box only: needs the repo checkout + npm.", - "icon": "🌐", - "fields": [] - } - ] } } }