From edf51ec0f70943c0e90bfdbeea6bf97d9bec1360 Mon Sep 17 00:00:00 2001 From: Kentai Radiquum <kentai.waah@gmail.com> Date: Thu, 23 Jan 2025 02:43:52 +0500 Subject: [PATCH 1/6] Improved watch script - Added hot reload - Added file serve via express - Added cleanup on watch exit --- package-lock.json | 751 +++++++++++++++++++++++++++++++++++++++++ package.json | 2 + src/hotreload.js | 11 + src/index.js | 6 +- src/templates/index.js | 5 +- src/templates/pack.js | 4 +- src/utils.js | 10 +- src/watch.js | 117 ++++++- static/RenderImages.js | 2 - 9 files changed, 883 insertions(+), 25 deletions(-) create mode 100644 src/hotreload.js diff --git a/package-lock.json b/package-lock.json index 0fbdb78..0e977ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "dlv": "^1.1.3", "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", + "express": "^4.21.2", "fast-glob": "^3.3.2", "fastq": "^1.18.0", "fill-range": "^7.1.1", @@ -96,6 +97,7 @@ "which": "^2.0.2", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "^7.0.0", + "ws": "^8.18.0", "yaml": "^2.6.1" }, "devDependencies": { @@ -215,6 +217,18 @@ "node": ">=14" } }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/ansi-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", @@ -259,6 +273,11 @@ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -275,6 +294,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -294,6 +336,41 @@ "node": ">=8" } }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -354,6 +431,38 @@ "node": ">= 6" } }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -378,6 +487,31 @@ "node": ">=4" } }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -388,16 +522,127 @@ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, + "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==" + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -443,6 +688,23 @@ "node": ">=8" } }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "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.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -458,6 +720,22 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -480,6 +758,41 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-intrinsic": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "function-bind": "^1.1.2", + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -510,6 +823,28 @@ "node": ">=10.13.0" } }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -521,6 +856,45 @@ "node": ">= 0.4" } }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -629,6 +1003,30 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -637,6 +1035,14 @@ "node": ">= 8" } }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -649,6 +1055,36 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -671,6 +1107,11 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -698,6 +1139,14 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -722,11 +1171,41 @@ "node": ">= 6" } }, + "node_modules/object-inspect": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -755,6 +1234,11 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -923,6 +1407,32 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -942,6 +1452,28 @@ } ] }, + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -1011,6 +1543,85 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/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==" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -1030,6 +1641,74 @@ "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -1049,6 +1728,14 @@ "node": ">=0.10.0" } }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -1272,16 +1959,60 @@ "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==", + "engines": { + "node": ">=0.6" + } + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -1380,6 +2111,26 @@ "node": ">=8" } }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "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 + } + } + }, "node_modules/yaml": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", diff --git a/package.json b/package.json index 8ae4fe7..115ddda 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "dlv": "^1.1.3", "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", + "express": "^4.21.2", "fast-glob": "^3.3.2", "fastq": "^1.18.0", "fill-range": "^7.1.1", @@ -94,6 +95,7 @@ "which": "^2.0.2", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "^7.0.0", + "ws": "^8.18.0", "yaml": "^2.6.1" }, "scripts": { diff --git a/src/hotreload.js b/src/hotreload.js new file mode 100644 index 0000000..7027f36 --- /dev/null +++ b/src/hotreload.js @@ -0,0 +1,11 @@ +let webSocket = new WebSocket('ws://127.0.0.1:3001'); +webSocket.onmessage = function(e) { + if (e.data == "RELOAD") { + console.log("Reloading page after build") + location.reload() + } else if (e.data == "CONNECTED") { + console.log("Connected to server") + } else { + console.warn(`unknown data received: ${e}`) + } +}; \ No newline at end of file diff --git a/src/index.js b/src/index.js index ca5f339..9e20ac8 100644 --- a/src/index.js +++ b/src/index.js @@ -7,6 +7,8 @@ const _CreatePacksIndex = require("./templates/index"); let PackIndex = null let Packs = []; +const isDev = process.env.DEVMODE || false + const dirents = fs.readdirSync(config.stickerPacksDir, { withFileTypes: true }); const files = dirents .filter(dirent => dirent.isFile()) @@ -29,7 +31,7 @@ if (!fs.existsSync(config.outDir)) fs.mkdirSync(config.outDir); PackIndex.packs.forEach((pack) => { const packFile = JSON.parse(fs.readFileSync(config.stickerPacksDir + "/" + pack)); if (!fs.existsSync(config.outDir + "/" + packFile.id)) fs.mkdirSync(config.outDir + "/" + packFile.id); - fs.writeFileSync(config.outDir + "/" + packFile.id + "/index.html", _CreatePackPage(PackIndex, packFile)); + fs.writeFileSync(config.outDir + "/" + packFile.id + "/index.html", _CreatePackPage(PackIndex, packFile, isDev)); Packs.push({ id: packFile.id, name: packFile.title, @@ -40,5 +42,5 @@ PackIndex.packs.forEach((pack) => { }) console.log("preview for " + packFile.id + " created"); }) -fs.writeFileSync(config.outDir + "/index.html", _CreatePacksIndex(PackIndex, Packs)); +fs.writeFileSync(config.outDir + "/index.html", _CreatePacksIndex(PackIndex, Packs, isDev)); console.log("Generation complete"); diff --git a/src/templates/index.js b/src/templates/index.js index f287867..2ea66e1 100644 --- a/src/templates/index.js +++ b/src/templates/index.js @@ -1,4 +1,4 @@ -const { CreateImageURL } = require("../utils"); +const { CreateImageURL, InjectWSConnection } = require("../utils"); function _PackLink(index, pack) { @@ -56,7 +56,7 @@ function _PackLink(index, pack) { ` } -function _CreatePacksIndex(index, packs) { +function _CreatePacksIndex(index, packs, isDev) { let packLinks = []; packs.forEach((packLink) => packLinks.push(_PackLink(index, packLink))); @@ -78,6 +78,7 @@ function _CreatePacksIndex(index, packs) { <meta property="og:image:height" content="96" /> <meta property="og:image:alt" content="sticker" /> <link href="./static/tailwind.css" rel="stylesheet"> + ${isDev ? InjectWSConnection() : ""} </head> <body class="overflow-x-hidden"> <div class="fixed inset-0 min-h-screen -z-10 tiledBackground"></div> diff --git a/src/templates/pack.js b/src/templates/pack.js index 82f92ef..8581553 100644 --- a/src/templates/pack.js +++ b/src/templates/pack.js @@ -2,14 +2,16 @@ const PackHead = require("./components/packHead"); const PackCard = require("./components/packCard"); const PackLinks = require("./components/packLinks"); const PackPreview = require("./components/packPreview"); +const { InjectWSConnection } = require("../utils") -function _CreatePackPage(index, pack) { +function _CreatePackPage(index, pack, isDev) { return ` <!DOCTYPE html> <html lang="en"> <head> ${PackHead(index, pack)} + ${isDev ? InjectWSConnection() : ""} </head> <body class="overflow-x-hidden"> diff --git a/src/utils.js b/src/utils.js index 86cd5e3..4f93c1c 100644 --- a/src/utils.js +++ b/src/utils.js @@ -36,4 +36,12 @@ function CreatePackDescription(pack) { return description.join(" | "); } -module.exports = {CreateImageURL, CreatePackDescription}; +function InjectWSConnection() { + return ` + <!-- The following was injected by watch.js script, because we are in a dev mode --> + <script src="/src/hotreload.js"></script> + <!-- Dev mode: Enabled --> + ` +} + +module.exports = {CreateImageURL, CreatePackDescription, InjectWSConnection}; diff --git a/src/watch.js b/src/watch.js index 172462d..e74ccc3 100644 --- a/src/watch.js +++ b/src/watch.js @@ -1,7 +1,23 @@ const chokidar = require("chokidar"); const exec = require("child_process"); +const express = require('express'); +const path = require('path'); +const WebSocket = require('ws'); +const fs = require("fs"); +const config = require("./config"); -function onChange() { +let triggered = 0 +const delay = 1000 +let SIGINTCount = 0 + +function onChange(wss) { + if (triggered != 0 && Date.now() - triggered < delay) { + console.log(` ↳[WARN] Rebuild was triggered less than a ${delay}ms ago!`) + return + } + triggered = Date.now() + + process.env.DEVMODE = true exec.exec("npm run build", (error, stdout, stderr) => { if (error) { console.error(`error: ${error.message}`); @@ -12,25 +28,92 @@ function onChange() { return; } console.log(`stdout: ${stdout}`); + if (wss) { + console.log('Reloading web page...'); + wss.send("RELOAD") + } }); } -const watcher = chokidar.watch("./src/templates", { - ignored: (path, stats) => - stats?.isFile() && !(path.endsWith(".js") || path.endsWith(".json")), - // atomic: true, +function onExit() { + let folders = null + + if (fs.existsSync(config.stickerPacksDir + "/index.json")) { + folders = [] + JSON.parse(fs.readFileSync(config.stickerPacksDir + "/index.json"))["packs"].map((pack) => folders.push(pack.replace(".json", ""))) + + folders.forEach( + (folder) => { + if (fs.existsSync(config.outDir + "/" + folder) ) fs.rmdirSync(config.outDir + "/" + folder, {recursive: true}) + console.log(`Deleted generated folder: "${folder}"`) + } + ) + } else { + console.log("no index.json found, forgot to run build?") + } + + if (fs.existsSync(config.outDir + "/index.html")) fs.rmSync(config.outDir + "/index.html") + console.log(`Deleted "index.html" file`) + + process.exit(0) +} + +const watcher = chokidar.watch(["./src/templates", "./stickerpacks"], { + ignored: (filePath, stats) => + (stats?.isFile() && !(filePath.endsWith(".js") || filePath.endsWith(".json"))) || filePath.endsWith("index.json"), + atomic: true, awaitWriteFinish: true, persistent: true, }); -watcher.on("add", (path) => { - console.log(`File ${path} has been added, rebuilding...`); - onChange(); -}); -watcher.on("change", (path) => { - console.log(`File ${path} has been changed, rebuilding...`); - onChange(); -}); -watcher.on("unlink", (path) => { - console.log(`File ${path} has been removed, rebuilding...`); - onChange(); -}); + +function startServerWithRebuild() { + const app = express(); + const folder = path.join(__dirname, '..') + const wss = new WebSocket.Server({ port: 3001 }); + + let WSclient = null + + wss.on('connection', (ws) => { + WSclient = ws + ws.send("CONNECTED") + }); + + process.on("SIGINT", () => { + SIGINTCount += 1 + if (WSclient) { + async function _closeWS() { + await WSclient.close() + } + _closeWS() + } + if (SIGINTCount == 1) { + console.log("Gracefully shutdown and cleanup...") + onExit() + } else if (SIGINTCount >= 3) { + console.log("Received 3+ SIGINT signals. Force exit...") + process.exit(0) + } + }) + + app.use(express.static(folder)); + app.listen(3000, () => { + console.log(`[INFO] Serving files from folder ${folder}`) + console.log('[INFO] Express server is running on port 3000'); + + watcher + .on('add', (path) => { + console.log(`[INFO] File ${path} has been added, rebuilding...`); + onChange(WSclient); + }) + .on('change', (path) => { + console.log(`[INFO] File ${path} has been changed, rebuilding...`); + onChange(WSclient); + }) + .on('unlink', (path) => { + console.log(`[INFO] File ${path} has been removed, rebuilding...`); + onChange(WSclient); + }); + }); +} + +startServerWithRebuild(); diff --git a/static/RenderImages.js b/static/RenderImages.js index bc6b287..2a54193 100644 --- a/static/RenderImages.js +++ b/static/RenderImages.js @@ -3,8 +3,6 @@ const images = document.querySelectorAll("[data-image-id]"); images.forEach((image) => { const spinner = document.querySelector(`[data-spinner-id="${image.getAttribute("data-image-id")}"]`) - console.log(image) - console.log(spinner) if (image.height > 0) { image.classList.remove("hidden"); From 240396b5069fbc0b8ab7ca49512d49e1a626a384 Mon Sep 17 00:00:00 2001 From: Kentai Radiquum <kentai.waah@gmail.com> Date: Thu, 23 Jan 2025 06:29:43 +0500 Subject: [PATCH 2/6] Update logging --- src/config.js | 2 +- src/index.js | 85 +++++++++++++++++++++++------------ src/utils.js | 31 ++++++++++++- src/watch.js | 120 ++++++++++++++++++++++++++++---------------------- 4 files changed, 153 insertions(+), 85 deletions(-) diff --git a/src/config.js b/src/config.js index 5fb19a6..21cf102 100644 --- a/src/config.js +++ b/src/config.js @@ -2,6 +2,6 @@ const config = { stickerPacksDir: "./stickerpacks", outDir: "./", homeserverUrl: "https://synapse.wah.su/__thumbnail/" -} +}; module.exports = config \ No newline at end of file diff --git a/src/index.js b/src/index.js index 9e20ac8..75e7cd0 100644 --- a/src/index.js +++ b/src/index.js @@ -1,46 +1,73 @@ const config = require("./config"); const fs = require("fs"); +const path = require("path"); +const { log } = require("./utils"); const _CreatePackPage = require("./templates/pack"); const _CreatePacksIndex = require("./templates/index"); -let PackIndex = null +let PackIndex = null; let Packs = []; -const isDev = process.env.DEVMODE || false +const isDev = process.env.DEVMODE || false; +log("INFO", `DEV MODE ENABLED: ${isDev}`); -const dirents = fs.readdirSync(config.stickerPacksDir, { withFileTypes: true }); +const InpPath = path + .join(__dirname, "../", config.stickerPacksDir, "./") + .trim(); +const OutPath = path.join(__dirname, "../", config.outDir, "./").trim(); +const ParPath = path.join(__dirname, "../", "./").trim(); +log("INFO", `Sticker sets directory: ${InpPath}`); +log("INFO", `Output directory: ${OutPath}`); +log("INFO", `Working directory: ${ParPath}`); + +const dirents = fs.readdirSync(InpPath, { withFileTypes: true }); const files = dirents - .filter(dirent => dirent.isFile()) - .filter(dirent => (dirent.name.endsWith(".json") && dirent.name != "index.json")) - .map(dirent => dirent.name); + .filter((dirent) => dirent.isFile()) + .filter( + (dirent) => dirent.name.endsWith(".json") && dirent.name != "index.json" + ) + .map((dirent) => dirent.name); if (files.length == 0) { - console.error("[ERROR] NO Sticker Packs Found!"); - process.exit(1); + log("error", "No sticker sets found!"); + process.exit(1); } -console.log("[INFO] Found " + files.length + " sticker packs"); +log("INFO", `Found: ${files.length} sticker sets`); PackIndex = { - homeserver_url: config.homeserverUrl, - packs: files -} -fs.writeFileSync(config.stickerPacksDir + "/index.json", JSON.stringify(PackIndex)); + homeserver_url: config.homeserverUrl, + packs: files, +}; +fs.writeFileSync( + config.stickerPacksDir + "/index.json", + JSON.stringify(PackIndex) +); +log("INFO", `Updated "index.json" in sticker sets directory`, true); -if (!fs.existsSync(config.outDir)) fs.mkdirSync(config.outDir); +if (OutPath != ParPath) { + if (!fs.existsSync(OutPath)) fs.mkdirSync(OutPath); + fs.cpSync(`${ParPath}static`, `${OutPath}static`, { recursive: true }); + log("INFO", `Copied static directory to output directory`); +} PackIndex.packs.forEach((pack) => { - const packFile = JSON.parse(fs.readFileSync(config.stickerPacksDir + "/" + pack)); - if (!fs.existsSync(config.outDir + "/" + packFile.id)) fs.mkdirSync(config.outDir + "/" + packFile.id); - fs.writeFileSync(config.outDir + "/" + packFile.id + "/index.html", _CreatePackPage(PackIndex, packFile, isDev)); - Packs.push({ - id: packFile.id, - name: packFile.title, - image: packFile.stickers[0].id, - author: (packFile.hasOwnProperty("author") && packFile.author) ? packFile.author.name : null, - rating: packFile.hasOwnProperty("rating") ? packFile.rating : null, - stickers: packFile.stickers.length - }) - console.log("preview for " + packFile.id + " created"); -}) -fs.writeFileSync(config.outDir + "/index.html", _CreatePacksIndex(PackIndex, Packs, isDev)); -console.log("Generation complete"); + const packFile = JSON.parse( + fs.readFileSync(`${InpPath}${pack}`) + ); + if (!fs.existsSync(`${OutPath}${packFile.id}`)) fs.mkdirSync(`${OutPath}${packFile.id}`); + fs.writeFileSync(`${OutPath}${packFile.id}/index.html`, _CreatePackPage(PackIndex, packFile, isDev)); + Packs.push({ + id: packFile.id, + name: packFile.title, + image: packFile.stickers[0].id, + author: + packFile.hasOwnProperty("author") && packFile.author + ? packFile.author.name + : null, + rating: packFile.hasOwnProperty("rating") ? packFile.rating : null, + stickers: packFile.stickers.length, + }); + log("INFO", `Created preview for sticker set: ${packFile.title} (${packFile.id})`); +}); +fs.writeFileSync(`${OutPath}index.html`, _CreatePacksIndex(PackIndex, Packs, isDev)); +log("INFO", "Generation complete"); diff --git a/src/utils.js b/src/utils.js index 4f93c1c..5aad9aa 100644 --- a/src/utils.js +++ b/src/utils.js @@ -41,7 +41,34 @@ function InjectWSConnection() { <!-- The following was injected by watch.js script, because we are in a dev mode --> <script src="/src/hotreload.js"></script> <!-- Dev mode: Enabled --> - ` + `; } -module.exports = {CreateImageURL, CreatePackDescription, InjectWSConnection}; +function log(level = "INFO" | "ERROR" | "WARN" | "LOG", message, connected = false) { + const date = new Date; + const time = date.toLocaleTimeString() + if (connected) { + message = `↳${message}` + } + switch (level.toUpperCase()) { + case "INFO": + console.info(`${time}:${level} - ${message}`); + break; + case "ERROR": + console.error(`${time}:${level} - ${message}`); + break; + case "WARN": + console.warn(`${time}:${level} - ${message}`); + break; + default: + console.log(`${time}:LOG - ${message}`); + break; + } +} + +module.exports = { + CreateImageURL, + CreatePackDescription, + InjectWSConnection, + log, +}; diff --git a/src/watch.js b/src/watch.js index e74ccc3..72068b2 100644 --- a/src/watch.js +++ b/src/watch.js @@ -1,66 +1,80 @@ const chokidar = require("chokidar"); const exec = require("child_process"); -const express = require('express'); -const path = require('path'); -const WebSocket = require('ws'); +const express = require("express"); +const path = require("path"); +const WebSocket = require("ws"); const fs = require("fs"); const config = require("./config"); +const { log } = require("./utils"); -let triggered = 0 -const delay = 1000 -let SIGINTCount = 0 +let triggered = 0; +const delay = 1000; +let SIGINTCount = 0; + +const InpPath = path + .join(__dirname, "../", config.stickerPacksDir, "./") + .trim(); +const OutPath = path.join(__dirname, "../", config.outDir, "./").trim(); +const ParPath = path.join(__dirname, "../", "./").trim(); +log("INFO", `Sticker sets directory: ${InpPath}`); +log("INFO", `Output directory: ${OutPath}`); +log("INFO", `Working directory: ${ParPath}`); function onChange(wss) { if (triggered != 0 && Date.now() - triggered < delay) { - console.log(` ↳[WARN] Rebuild was triggered less than a ${delay}ms ago!`) - return + log("WARN", `Rebuild was triggered less than a ${delay}ms ago!`, true); + return; } - triggered = Date.now() + triggered = Date.now(); - process.env.DEVMODE = true + process.env.DEVMODE = true; exec.exec("npm run build", (error, stdout, stderr) => { if (error) { - console.error(`error: ${error.message}`); + log("ERROR", error.message); return; } if (stderr) { - console.error(`stderr: ${stderr}`); + log("ERROR", stderr); return; } - console.log(`stdout: ${stdout}`); + log("INFO", stdout); if (wss) { - console.log('Reloading web page...'); - wss.send("RELOAD") + log("INFO", "Reloading web page..."); + wss.send("RELOAD"); } }); } function onExit() { - let folders = null + let folders = null; - if (fs.existsSync(config.stickerPacksDir + "/index.json")) { - folders = [] - JSON.parse(fs.readFileSync(config.stickerPacksDir + "/index.json"))["packs"].map((pack) => folders.push(pack.replace(".json", ""))) + if (fs.existsSync(`${InpPath}/index.json`)) { + folders = []; + JSON.parse(fs.readFileSync(`${InpPath}/index.json`))["packs"].map((pack) => + folders.push(pack.replace(".json", "")) + ); - folders.forEach( - (folder) => { - if (fs.existsSync(config.outDir + "/" + folder) ) fs.rmdirSync(config.outDir + "/" + folder, {recursive: true}) - console.log(`Deleted generated folder: "${folder}"`) - } - ) + folders.forEach((folder) => { + if (fs.existsSync(`${OutPath}${folder}`)) + fs.rmdirSync(`${OutPath}${folder}`, { recursive: true }); + log("INFO", `Deleted generated folder: "${folder}"`); + }); } else { - console.log("no index.json found, forgot to run build?") + log("WARN", `no "index.json" found, forgot to run build?`); } - if (fs.existsSync(config.outDir + "/index.html")) fs.rmSync(config.outDir + "/index.html") - console.log(`Deleted "index.html" file`) + if (fs.existsSync(`${OutPath}index.html`)) fs.rmSync(`${OutPath}index.html`); + log("INFO", `Deleted "index.html" file`); - process.exit(0) + if (fs.existsSync(OutPath) && OutPath != ParPath) { + log("INFO", `Deleted output folder`); + } + + process.exit(0); } -const watcher = chokidar.watch(["./src/templates", "./stickerpacks"], { - ignored: (filePath, stats) => - (stats?.isFile() && !(filePath.endsWith(".js") || filePath.endsWith(".json"))) || filePath.endsWith("index.json"), +const watcher = chokidar.watch(["./src", "./stickerpacks"], { + ignored: (filePath, stats) => filePath.endsWith("index.json"), atomic: true, awaitWriteFinish: true, persistent: true, @@ -68,49 +82,49 @@ const watcher = chokidar.watch(["./src/templates", "./stickerpacks"], { function startServerWithRebuild() { const app = express(); - const folder = path.join(__dirname, '..') + const folder = path.join(__dirname, ".."); const wss = new WebSocket.Server({ port: 3001 }); - let WSclient = null + let WSclient = null; - wss.on('connection', (ws) => { - WSclient = ws - ws.send("CONNECTED") + wss.on("connection", (ws) => { + WSclient = ws; + ws.send("CONNECTED"); }); process.on("SIGINT", () => { - SIGINTCount += 1 + SIGINTCount += 1; if (WSclient) { async function _closeWS() { - await WSclient.close() + await WSclient.close(); } - _closeWS() + _closeWS(); } if (SIGINTCount == 1) { - console.log("Gracefully shutdown and cleanup...") - onExit() + log("LOG", "Gracefully shutdown and cleanup..."); + onExit(); } else if (SIGINTCount >= 3) { - console.log("Received 3+ SIGINT signals. Force exit...") - process.exit(0) + log("LOG", "Received 3+ SIGINT signals. Force exit..."); + process.exit(0); } - }) + }); app.use(express.static(folder)); app.listen(3000, () => { - console.log(`[INFO] Serving files from folder ${folder}`) - console.log('[INFO] Express server is running on port 3000'); + log("INFO", `Serving files from folder ${folder}`); + log("INFO", "Express server is running on port 3000"); watcher - .on('add', (path) => { - console.log(`[INFO] File ${path} has been added, rebuilding...`); + .on("add", (path) => { + log("INFO", `File ${path} has been added, rebuilding...`); onChange(WSclient); }) - .on('change', (path) => { - console.log(`[INFO] File ${path} has been changed, rebuilding...`); + .on("change", (path) => { + log("INFO", `File ${path} has been changed, rebuilding...`); onChange(WSclient); }) - .on('unlink', (path) => { - console.log(`[INFO] File ${path} has been removed, rebuilding...`); + .on("unlink", (path) => { + log("INFO", `File ${path} has been removed, rebuilding...`); onChange(WSclient); }); }); From c6386bf11c543a71603f2907888c823b3f0725ca Mon Sep 17 00:00:00 2001 From: Kentai Radiquum <kentai.waah@gmail.com> Date: Thu, 23 Jan 2025 06:32:06 +0500 Subject: [PATCH 3/6] deletion of output folder on exit from watch --- src/watch.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/watch.js b/src/watch.js index 72068b2..c6df766 100644 --- a/src/watch.js +++ b/src/watch.js @@ -67,6 +67,7 @@ function onExit() { log("INFO", `Deleted "index.html" file`); if (fs.existsSync(OutPath) && OutPath != ParPath) { + fs.rmdirSync(`${OutPath}`, { recursive: true }); log("INFO", `Deleted output folder`); } From 1a2c6e295abee8e369caf259463ed3a658e90e23 Mon Sep 17 00:00:00 2001 From: Kentai Radiquum <kentai.waah@gmail.com> Date: Thu, 23 Jan 2025 07:46:17 +0500 Subject: [PATCH 4/6] Start: Rebuild Templates to EJS --- package-lock.json | 129 ++++++++++++++++++++++++++++ package.json | 1 + src/config.js | 4 +- src/index.js | 42 +++++++-- src/templates/Base.ejs | 9 ++ src/templates/components/Head.ejs | 20 +++++ src/templates/components/Header.ejs | 5 ++ src/templates/index.js | 23 ----- src/watch.js | 2 +- static/images/logo.svg | 52 +++++++++++ static/tailwind.css | 42 +-------- tailwind.config.js | 2 +- 12 files changed, 257 insertions(+), 74 deletions(-) create mode 100644 src/templates/Base.ejs create mode 100644 src/templates/components/Head.ejs create mode 100644 src/templates/components/Header.ejs create mode 100644 static/images/logo.svg diff --git a/package-lock.json b/package-lock.json index 0e977ad..c09791e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "didyoumean": "^1.2.2", "dlv": "^1.1.3", "eastasianwidth": "^0.2.0", + "ejs": "^3.1.10", "emoji-regex": "^9.2.2", "express": "^4.21.2", "fast-glob": "^3.3.2", @@ -278,6 +279,11 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -379,6 +385,35 @@ "node": ">= 6" } }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -431,6 +466,11 @@ "node": ">= 6" } }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -545,6 +585,20 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -677,6 +731,25 @@ "reusify": "^1.0.4" } }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -834,6 +907,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -974,6 +1055,43 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/jiti": { "version": "1.21.7", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", @@ -1845,6 +1963,17 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", diff --git a/package.json b/package.json index 115ddda..9ebf517 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "didyoumean": "^1.2.2", "dlv": "^1.1.3", "eastasianwidth": "^0.2.0", + "ejs": "^3.1.10", "emoji-regex": "^9.2.2", "express": "^4.21.2", "fast-glob": "^3.3.2", diff --git a/src/config.js b/src/config.js index 21cf102..463b1cd 100644 --- a/src/config.js +++ b/src/config.js @@ -1,6 +1,6 @@ const config = { - stickerPacksDir: "./stickerpacks", - outDir: "./", + stickerPacksDir: "stickerpacks", + outDir: "sticker", homeserverUrl: "https://synapse.wah.su/__thumbnail/" }; diff --git a/src/index.js b/src/index.js index 75e7cd0..0027b88 100644 --- a/src/index.js +++ b/src/index.js @@ -2,9 +2,10 @@ const config = require("./config"); const fs = require("fs"); const path = require("path"); const { log } = require("./utils"); +let ejs = require("ejs"); -const _CreatePackPage = require("./templates/pack"); -const _CreatePacksIndex = require("./templates/index"); +// const _CreatePackPage = require("./templates/pack"); +// const _CreatePacksIndex = require("./templates/index"); let PackIndex = null; let Packs = []; @@ -51,11 +52,9 @@ if (OutPath != ParPath) { } PackIndex.packs.forEach((pack) => { - const packFile = JSON.parse( - fs.readFileSync(`${InpPath}${pack}`) - ); - if (!fs.existsSync(`${OutPath}${packFile.id}`)) fs.mkdirSync(`${OutPath}${packFile.id}`); - fs.writeFileSync(`${OutPath}${packFile.id}/index.html`, _CreatePackPage(PackIndex, packFile, isDev)); + const packFile = JSON.parse(fs.readFileSync(`${InpPath}${pack}`)); + // if (!fs.existsSync(`${OutPath}${packFile.id}`)) fs.mkdirSync(`${OutPath}${packFile.id}`); + // fs.writeFileSync(`${OutPath}${packFile.id}/index.html`, _CreatePackPage(PackIndex, packFile, isDev)); Packs.push({ id: packFile.id, name: packFile.title, @@ -67,7 +66,32 @@ PackIndex.packs.forEach((pack) => { rating: packFile.hasOwnProperty("rating") ? packFile.rating : null, stickers: packFile.stickers.length, }); - log("INFO", `Created preview for sticker set: ${packFile.title} (${packFile.id})`); + log( + "INFO", + `Created preview for sticker set: ${packFile.title} (${packFile.id})` + ); }); -fs.writeFileSync(`${OutPath}index.html`, _CreatePacksIndex(PackIndex, Packs, isDev)); + +const indexTemplate = fs.readFileSync( + path.join(ParPath, "src/templates/Base.ejs") +); +const html = ejs.render( + indexTemplate.toString(), + { + title: "TG -> Matrix Stickers Index", + description: `available ${PackIndex.packs.length} sticker packs`, + image: { + url: "./static/images/sticker.png", + mimetype: "image/png", + w: "96", + h: "96", + alt: "" + }, + path: config.OutPath, + isDev + }, + { root: path.join(ParPath, "src/templates") } +); +log("LOG", `\n\n${html}\n\n`); +fs.writeFileSync(`${OutPath}index.html`, html); log("INFO", "Generation complete"); diff --git a/src/templates/Base.ejs b/src/templates/Base.ejs new file mode 100644 index 0000000..9080d5f --- /dev/null +++ b/src/templates/Base.ejs @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html lang="en"> + <%- include('/components/Head', {title, description, image, path, isDev}); %> + <body class="overflow-x-hidden"> + <%- include("/components/Header", {path}) %> + <div class="fixed inset-0 min-h-screen -z-10 tiledBackground"></div> + <div class="fixed inset-0 min-h-screen -z-20 bg-gradient-to-b from-gray-900 to-black"></div> + </body> +</html> \ No newline at end of file diff --git a/src/templates/components/Head.ejs b/src/templates/components/Head.ejs new file mode 100644 index 0000000..2948b9b --- /dev/null +++ b/src/templates/components/Head.ejs @@ -0,0 +1,20 @@ +<head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title><%- title %></title> + <link rel="icon" type="<%= image.mimetype %>" href="<%= image.url %>" /> + <meta property="og:title" content="<%- title %>" /> + <meta property="og:description" content="<%- description %>" /> + <meta property="og:type" content="website" /> + <meta property="og:image" content="<%= image.url %>" /> + <meta property="og:image:type" content="<%= image.mimetype %>" /> + <meta property="og:image:width" content="<%= image.w %>" /> + <meta property="og:image:height" content="<%= image.h %>" /> + <meta property="og:image:alt" content="<%= image.alt %>" /> + <link href="<%= path %>/static/tailwind.css" rel="stylesheet"> + <% if (isDev) { %> + <!-- The following was injected by watch.js script, because we are in a dev mode --> + <script src="<%= path %>/src/hotreload.js"></script> + <!-- Dev mode: Enabled --> + <% }; %> +</head> \ No newline at end of file diff --git a/src/templates/components/Header.ejs b/src/templates/components/Header.ejs new file mode 100644 index 0000000..ad8235d --- /dev/null +++ b/src/templates/components/Header.ejs @@ -0,0 +1,5 @@ +<header> + <div class="container"> + <a href="<%- path %>index.html"><img src="<%- path %>/static/images/logo.svg" alt="index page"/></a> + </div> +</header> \ No newline at end of file diff --git a/src/templates/index.js b/src/templates/index.js index 2ea66e1..31189d9 100644 --- a/src/templates/index.js +++ b/src/templates/index.js @@ -62,28 +62,6 @@ function _CreatePacksIndex(index, packs, isDev) { packs.forEach((packLink) => packLinks.push(_PackLink(index, packLink))); return ` -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="UTF-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <title>TG -> Matrix Stickers Index</title> - <link rel="icon" type="image/png" href="./static/images/sticker.png" /> - <meta property="og:title" content="TG -> Matrix Stickers Index" /> - <meta property="og:description" content="available ${packs.length} sticker packs" /> - <meta property="og:type" content="website" /> - <meta property="og:image" content="./static/images/sticker.png" /> - <meta property="og:image:type" content="image/png" /> - <meta property="og:image:width" content="96" /> - <meta property="og:image:height" content="96" /> - <meta property="og:image:alt" content="sticker" /> - <link href="./static/tailwind.css" rel="stylesheet"> - ${isDev ? InjectWSConnection() : ""} - </head> - <body class="overflow-x-hidden"> - <div class="fixed inset-0 min-h-screen -z-10 tiledBackground"></div> - <div class="fixed inset-0 min-h-screen -z-20 bg-gradient-to-b from-gray-900 to-black"></div> - <div class="container flex flex-col items-center justify-center min-h-screen gap-4 p-4 mx-auto"> <div class="gap-2 [grid-template-columns:100%] md:[grid-template-columns:repeat(auto-fill,minmax(380px,500px))] justify-center items-center grid w-full"> ${packLinks.join("\n")} @@ -91,7 +69,6 @@ function _CreatePacksIndex(index, packs, isDev) { </div> <script src="../static/RenderImages.js"></script> - </body> ` } diff --git a/src/watch.js b/src/watch.js index c6df766..b7c9a29 100644 --- a/src/watch.js +++ b/src/watch.js @@ -74,7 +74,7 @@ function onExit() { process.exit(0); } -const watcher = chokidar.watch(["./src", "./stickerpacks"], { +const watcher = chokidar.watch(["./src", "./stickerpacks", "./static"], { ignored: (filePath, stats) => filePath.endsWith("index.json"), atomic: true, awaitWriteFinish: true, diff --git a/static/images/logo.svg b/static/images/logo.svg new file mode 100644 index 0000000..0c927dc --- /dev/null +++ b/static/images/logo.svg @@ -0,0 +1,52 @@ +<svg width="551" height="111" viewBox="0 0 551 111" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_33_157)"> +<g clip-path="url(#clip1_33_157)"> +<g clip-path="url(#clip2_33_157)"> +<g clip-path="url(#clip3_33_157)"> +<g clip-path="url(#clip4_33_157)"> +<g clip-path="url(#clip5_33_157)"> +<path d="M0 53.0013C0 23.7292 23.4314 0 52.3351 0C81.2393 0 104.67 23.7297 104.671 53.0013C104.671 82.2734 81.2393 106.003 52.3351 106.003C23.4309 106.003 0 82.2734 0 53.0013ZM52.3351 102.388C79.2679 102.388 101.101 80.277 101.101 53.0013C101.101 25.7256 79.2679 3.6147 52.3351 3.6147C25.4023 3.6147 3.56927 25.7261 3.56927 53.0013C3.56927 80.277 25.4027 102.388 52.3351 102.388Z" fill="#FE633D"/> +<path d="M52.3354 105.473C80.9503 105.473 104.147 81.9807 104.147 53.0015C104.147 24.0223 80.9503 0.530029 52.3354 0.530029C23.7204 0.530029 0.523438 24.0223 0.523438 53.0015C0.523438 81.9807 23.7204 105.473 52.3354 105.473Z" fill="#FE633D"/> +<g clip-path="url(#clip6_33_157)"> +<g clip-path="url(#clip7_33_157)"> +<path d="M81.0596 52.8843C81.0596 56.9643 77.8002 60.2633 73.7698 60.2633C69.7465 60.2633 66.4854 56.9643 66.4854 52.8843C66.4854 48.8099 73.1235 42.1573 77.1485 42.1573C81.1808 42.1573 81.0596 48.8099 81.0596 52.8843Z" fill="white"/> +<path d="M38.1869 52.8843C38.1869 56.9643 34.9276 60.2633 30.8962 60.2633C26.8721 60.2633 23.6136 56.9643 23.6136 52.8843C23.6136 48.8099 23.365 42.1573 27.3882 42.1573C31.4196 42.1573 38.1869 48.8099 38.1869 52.8843Z" fill="white"/> +<path d="M68.7905 38.1255C68.7905 42.2045 65.5312 45.5054 61.5025 45.5054C57.4775 45.5054 54.2163 42.2045 54.2163 38.1255C54.2163 34.052 57.4775 24.5085 61.5025 24.5085C65.5312 24.5076 68.7905 34.051 68.7905 38.1255Z" fill="white"/> +<path d="M70.3857 67.1504C72.3408 75.3085 64.095 81.7211 51.9507 81.4884C39.819 81.2547 31.7168 74.6539 33.846 66.7295C35.9716 58.8151 44.2165 52.3925 52.2658 52.3925C60.3239 52.3934 68.4315 59.0042 70.3857 67.1504Z" fill="white"/> +<path d="M50.3321 38.1255C50.3321 42.2045 47.0719 45.5054 43.0432 45.5054C39.0173 45.5054 35.7588 42.2045 35.7588 38.1255C35.7588 34.052 39.0173 24.5085 43.0432 24.5085C47.0719 24.5076 50.3321 34.051 50.3321 38.1255Z" fill="white"/> +</g> +</g> +</g> +</g> +<path d="M144.44 96.7675H134.078L120.47 37.3439H129.334L140.07 85.6414L150.682 43.5392H159.421L170.033 85.6414L180.769 37.3439H189.134L175.526 96.7675H165.289L154.927 55.171L144.44 96.7675ZM221.718 98.2847C214.56 98.2847 209.026 96.6157 205.114 93.2779C201.202 89.9569 199.246 85.3463 199.246 79.4461C199.246 73.7988 201.077 69.5001 204.739 66.55C208.401 63.5999 213.895 62.1248 221.219 62.1248H243.691V59.5961C243.691 54.1174 242.417 50.2148 239.87 47.8885C237.34 45.5789 233.037 44.4242 226.962 44.4242C219.138 44.4242 212.064 46.1521 205.738 49.6079L202.867 41.6427C210.024 37.7654 218.181 35.8267 227.336 35.8267C236.158 35.8267 242.584 37.6137 246.612 41.1875C250.657 44.7782 252.679 50.4508 252.679 58.2054V96.7675H245.938L244.814 90.4458C241.402 93.0588 237.781 95.0143 233.953 96.3123C230.124 97.6272 226.046 98.2847 221.718 98.2847ZM222.967 89.6872C230.79 89.6872 237.698 87.4114 243.691 82.8598V70.2165H220.969C216.724 70.2165 213.578 70.992 211.531 72.5429C209.5 74.1107 208.485 76.4117 208.485 79.4461C208.485 82.8177 209.691 85.3632 212.105 87.0827C214.519 88.819 218.139 89.6872 222.967 89.6872ZM283.516 96.7675H274.527V7H283.516V42.7806C289.825 38.1447 296.816 35.8267 304.49 35.8267C311.381 35.8267 316.599 37.6811 320.145 41.3898C323.674 45.0985 325.438 50.7037 325.438 58.2054V96.7675H316.475V59.5961C316.475 54.286 315.393 50.4255 313.229 48.0149C311.065 45.6211 307.644 44.4242 302.966 44.4242C299.637 44.4242 296.292 44.9889 292.929 46.1184C289.567 47.2647 286.429 48.9336 283.516 51.1251V96.7675ZM372.005 98.2847C369.425 98.2847 367.219 97.3575 365.388 95.5031C363.557 93.6488 362.642 91.4151 362.642 88.8022C362.642 86.2735 363.557 84.0567 365.388 82.1518C367.219 80.2637 369.425 79.3197 372.005 79.3197C374.585 79.3197 376.791 80.2637 378.622 82.1518C380.453 84.0567 381.368 86.2735 381.368 88.8022C381.368 91.4151 380.453 93.6488 378.622 95.5031C376.791 97.3575 374.585 98.2847 372.005 98.2847ZM444.29 98.2847C434.053 98.2847 424.897 95.8403 416.824 90.9515L420.445 83.2391C424.023 85.3463 427.852 86.9478 431.93 88.0436C436.008 89.1393 440.253 89.6872 444.664 89.6872C455.9 89.6872 461.518 86.4 461.518 79.8254C461.518 77.3811 460.769 75.5857 459.271 74.4394C457.773 73.3099 455.151 72.4923 451.406 71.9866L437.174 69.9637C431.098 69.0365 426.67 67.3676 423.89 64.9569C421.094 62.5631 419.695 59.0061 419.695 54.286C419.695 48.3858 421.843 43.8342 426.137 40.6312C430.415 37.4282 436.425 35.8267 444.165 35.8267C452.904 35.8267 461.144 37.8497 468.884 41.8955L465.638 49.7344C459.063 46.1942 451.822 44.4242 443.915 44.4242C433.844 44.4242 428.809 47.5007 428.809 53.6538C428.809 56.0139 429.558 57.7418 431.056 58.8376C432.554 59.9333 435.176 60.734 438.921 61.2398L453.154 63.2627C459.313 64.1056 463.765 65.7492 466.512 68.1936C469.259 70.638 470.632 74.3045 470.632 79.1933C470.632 85.3463 468.368 90.0665 463.84 93.3538C459.296 96.641 452.779 98.2847 444.29 98.2847ZM511.955 98.2847C505.13 98.2847 499.928 96.405 496.35 92.6457C492.771 88.9033 490.981 83.3234 490.981 75.906V37.3439H499.97V74.5153C499.97 79.8254 501.052 83.6774 503.216 86.0712C505.38 88.4819 508.792 89.6872 513.453 89.6872C516.866 89.6872 520.253 89.0972 523.616 87.9172C526.995 86.7371 530.099 85.0935 532.929 82.9863V37.3439H541.918V96.7675H535.176L534.177 90.4458C530.848 93.0588 527.328 95.0143 523.616 96.3123C519.92 97.6272 516.033 98.2847 511.955 98.2847Z" fill="#FF851B"/> +</g> +</g> +</g> +</g> +<defs> +<clipPath id="clip0_33_157"> +<rect width="551" height="111" fill="white"/> +</clipPath> +<clipPath id="clip1_33_157"> +<rect width="551" height="106" fill="white"/> +</clipPath> +<clipPath id="clip2_33_157"> +<rect width="551" height="111" fill="white"/> +</clipPath> +<clipPath id="clip3_33_157"> +<rect width="550.601" height="111" fill="white" transform="translate(0.398682)"/> +</clipPath> +<clipPath id="clip4_33_157"> +<rect width="104.671" height="106.003" fill="white"/> +</clipPath> +<clipPath id="clip5_33_157"> +<rect width="104.671" height="106.003" fill="white"/> +</clipPath> +<clipPath id="clip6_33_157"> +<rect width="57.4493" height="56.986" fill="white" transform="translate(23.6106 24.5085)"/> +</clipPath> +<clipPath id="clip7_33_157"> +<rect width="57.4493" height="56.986" fill="white" transform="translate(23.6106 24.5085)"/> +</clipPath> +</defs> +</svg> diff --git a/static/tailwind.css b/static/tailwind.css index 8ba6f24..965aec6 100644 --- a/static/tailwind.css +++ b/static/tailwind.css @@ -689,10 +689,6 @@ video { width: 100%; } -.flex-grow { - flex-grow: 1; -} - .-translate-x-1\/2 { --tw-translate-x: -50%; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -716,10 +712,6 @@ video { flex-direction: column; } -.flex-wrap { - flex-wrap: wrap; -} - .items-center { align-items: center; } @@ -728,6 +720,10 @@ video { justify-content: center; } +.gap-1 { + gap: 0.25rem; +} + .gap-2 { gap: 0.5rem; } @@ -736,10 +732,6 @@ video { gap: 1rem; } -.gap-1 { - gap: 0.25rem; -} - .overflow-x-hidden { overflow-x: hidden; } @@ -748,19 +740,6 @@ video { border-radius: 0.5rem; } -.border-2 { - border-width: 2px; -} - -.border-solid { - border-style: solid; -} - -.border-black { - --tw-border-opacity: 1; - border-color: rgb(0 0 0 / var(--tw-border-opacity, 1)); -} - .bg-\[\#259d7b\] { --tw-bg-opacity: 1; background-color: rgb(37 157 123 / var(--tw-bg-opacity, 1)); @@ -903,11 +882,6 @@ video { color: rgb(244 244 245 / var(--tw-text-opacity, 1)); } -.text-slate-200 { - --tw-text-opacity: 1; - color: rgb(226 232 240 / var(--tw-text-opacity, 1)); -} - .underline { text-decoration-line: underline; } @@ -936,10 +910,6 @@ video { grid-template-columns: repeat(auto-fill,96px); } -.\[grid-template-columns\:repeat\(auto-fill\2c minmax\(128px\2c 372px\)\)\] { - grid-template-columns: repeat(auto-fill,minmax(128px,372px)); -} - .tiledBackground { background-image: url('images/background-white.png'); background-repeat: repeat; @@ -977,10 +947,6 @@ video { white-space: pre; } - .md\:\[grid-template-columns\:repeat\(auto-fill\2c 384px\)\] { - grid-template-columns: repeat(auto-fill,384px); - } - .md\:\[grid-template-columns\:repeat\(auto-fill\2c minmax\(380px\2c 500px\)\)\] { grid-template-columns: repeat(auto-fill,minmax(380px,500px)); } diff --git a/tailwind.config.js b/tailwind.config.js index e00955b..00108c5 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,6 +1,6 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - content: ["./src/templates/**/*.{html,js}"], + content: ["./src/templates/**/*.{html,js, ejs}"], theme: { extend: {}, }, From 999ba6acbedf8a554367ea33dc69f6efbd653499 Mon Sep 17 00:00:00 2001 From: Kentai Radiquum <kentai.waah@gmail.com> Date: Thu, 23 Jan 2025 13:47:43 +0500 Subject: [PATCH 5/6] REFACTOR | BROKEN CHANGES - Refactor Index Page SSG to EJS template engine --- .vscode/settings.json | 12 -- src/index.js | 19 +- src/templates/Base.ejs | 23 ++- src/templates/components/Header.ejs | 13 +- src/templates/components/Link/Stickerset.ejs | 29 ++++ src/templates/functions.ejs | 19 ++ src/templates/index.js | 75 -------- src/utils.js | 18 +- static/RenderImages.js | 18 +- ...24dp_E8EAED_FILL0_wght400_GRAD0_opsz24.png | Bin 0 -> 3449 bytes static/images/github-mark-white.png | Bin 0 -> 4837 bytes static/tailwind.css | 162 ++++++++++++++++-- tailwind.config.js | 2 +- 13 files changed, 256 insertions(+), 134 deletions(-) delete mode 100644 .vscode/settings.json create mode 100644 src/templates/components/Link/Stickerset.ejs create mode 100644 src/templates/functions.ejs delete mode 100644 src/templates/index.js create mode 100644 static/images/captive_portal_24dp_E8EAED_FILL0_wght400_GRAD0_opsz24.png create mode 100644 static/images/github-mark-white.png diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index d1fb129..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "fiveServer.ignore": [ - "**/node_modules/**", - ".vscode/**", - ".git/**", - "**/*.scss", - "**/*.sass", - "**/*.css", - "**/*.ts", - "**/*.js", - ] -} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 0027b88..e214111 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,6 @@ const { log } = require("./utils"); let ejs = require("ejs"); // const _CreatePackPage = require("./templates/pack"); -// const _CreatePacksIndex = require("./templates/index"); let PackIndex = null; let Packs = []; @@ -79,16 +78,20 @@ const html = ejs.render( indexTemplate.toString(), { title: "TG -> Matrix Stickers Index", - description: `available ${PackIndex.packs.length} sticker packs`, + description: `Available ${PackIndex.packs.length} sticker packs`, image: { - url: "./static/images/sticker.png", - mimetype: "image/png", - w: "96", - h: "96", - alt: "" + url: "./static/images/sticker.png", + mimetype: "image/png", + w: "96", + h: "96", + alt: "", }, path: config.OutPath, - isDev + isDev, + stickerset: null, + page: "index", + packs: Packs, + homeserverUrl: config.homeserverUrl, }, { root: path.join(ParPath, "src/templates") } ); diff --git a/src/templates/Base.ejs b/src/templates/Base.ejs index 9080d5f..944d39c 100644 --- a/src/templates/Base.ejs +++ b/src/templates/Base.ejs @@ -1,9 +1,28 @@ <!DOCTYPE html> <html lang="en"> <%- include('/components/Head', {title, description, image, path, isDev}); %> - <body class="overflow-x-hidden"> - <%- include("/components/Header", {path}) %> + <body class="overflow-x-hidden text-white"> + <%- include("/components/Header", {path, stickerset}) %> <div class="fixed inset-0 min-h-screen -z-10 tiledBackground"></div> <div class="fixed inset-0 min-h-screen -z-20 bg-gradient-to-b from-gray-900 to-black"></div> + <div class="container px-8 py-4 mx-auto"> + <% if (page == "index") { %> + <div class="grid w-full h-full grid-cols-1 gap-2 lg:grid-cols-2 2xl:grid-cols-3"> + <% packs.forEach(function(pack){ %> + <%- include('/components/Link/Stickerset', {path, homeserverUrl, pack}); %> + <% }); %> + </div> + <% }; %> + + <div class="flex flex-wrap items-center gap-4 py-4 mx-auto"> + <a class="flex items-center gap-2 text-lg" href="https://wah.su/radiquum"> <span>by @radiquum</span> <img class="object-contain w-8 rounded-full aspect-square" src="https://radiquum.wah.su/static/avatar_512.jpg" alt="" /></a> + <div class="flex items-center gap-2"> + <p class="text-lg">Find us on:</p> + <a href="https://github.com/wah-su"><img class="object-contain w-8 rounded-full aspect-square" src="<%- path %>/static/images/github-mark-white.png" alt="github" /></a> + <a href="https://wah.su"><img class="object-contain w-8 rounded-full aspect-square" src="<%- path %>/static/images/captive_portal_24dp_E8EAED_FILL0_wght400_GRAD0_opsz24.png" alt="website" /></a> + </div> + </div> + </div> + <script src="<%- path %>/static/RenderImages.js"></script> </body> </html> \ No newline at end of file diff --git a/src/templates/components/Header.ejs b/src/templates/components/Header.ejs index ad8235d..670ea03 100644 --- a/src/templates/components/Header.ejs +++ b/src/templates/components/Header.ejs @@ -1,5 +1,12 @@ -<header> - <div class="container"> - <a href="<%- path %>index.html"><img src="<%- path %>/static/images/logo.svg" alt="index page"/></a> +<header class="sticky top-0 left-0 right-0 bg-[#1d1f3d] rounded-b-lg"> + <div class="container flex items-center justify-between px-8 py-4 mx-auto"> + <a href="<%- path %>index.html"><img class="h-6 sm:h-10" src="<%- path %>/static/images/logo.svg" alt="index page"/></a> + <% if (stickerset) { %> + <p>STICKERSET</p> + <% }; %> + <div class="flex items-center justify-center gap-2 text-white sm:gap-4 sm:text-xl"> + <a class="hidden hover:underline sm:inline" href="<%- path %>index.html">StickerSets</a> + <a class="hover:underline" href="https://github.com/wah-su/mstickers">GitHub</a> + </div> </div> </header> \ No newline at end of file diff --git a/src/templates/components/Link/Stickerset.ejs b/src/templates/components/Link/Stickerset.ejs new file mode 100644 index 0000000..a9415a0 --- /dev/null +++ b/src/templates/components/Link/Stickerset.ejs @@ -0,0 +1,29 @@ +<% include('/functions') %> +<a href="<%- path %><%- pack.id %>" class="flex items-center w-full h-full gap-2 p-4 rounded-md sm:gap-4 bg-slate-800"> + <div class="grid items-center justify-center object-contain w-16 grid-cols-1 grid-rows-1 sm:w-32 aspect-square"> + <img src="<%- CreateImageURL(homeserverUrl, pack.image) %>" data-image-id="<%- pack.image %>" class="object-contain w-16 sm:w-32 aspect-square [grid-column:1] [grid-row:1]" loading="lazy" /> + <svg + role="status" + data-spinner-id="<%- pack.image %>" + aria-hidden="true" + class="mx-auto [grid-column:1] [grid-row:1] inline w-8 text-gray-200 sm:w-16 animate-spin dark:text-gray-600 fill-green-500" + viewBox="0 0 100 101" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" + fill="currentColor" + /> + <path + d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" + fill="currentFill" + /> + </svg> + </div> + <div> + <p class="text-lg sm:text-2xl line-clamp-1"><%- pack.name %></p> + <p class="text-sm sm:text-lg line-clamp-1"><%- pack.author %></p> + <p class="text-xs sm:text-base"><span class="<%- PackRatingClass(pack.rating) %>"><%- pack.rating %></span> | <%- pack.stickers %> stick </p> + </div> +</a> \ No newline at end of file diff --git a/src/templates/functions.ejs b/src/templates/functions.ejs new file mode 100644 index 0000000..4719398 --- /dev/null +++ b/src/templates/functions.ejs @@ -0,0 +1,19 @@ +<% CreateImageURL=function(homeserverUrl,id) { return `${homeserverUrl}${id.slice(0,2)}/${id.slice(2,4)}/${id.slice(4)}`; } %> +<% +PackRatingClass=function(rating) { + switch (rating.toLowerCase()) { + case "safe": + return "text-green-400" + break + case "questionable": + return "text-yellow-500" + break + case "explicit": + return "text-red-500" + break + default: + return "hidden" + break + } +} +%> \ No newline at end of file diff --git a/src/templates/index.js b/src/templates/index.js deleted file mode 100644 index 31189d9..0000000 --- a/src/templates/index.js +++ /dev/null @@ -1,75 +0,0 @@ -const { CreateImageURL, InjectWSConnection } = require("../utils"); - -function _PackLink(index, pack) { - - let packRating = ""; - - if (pack.rating) { - if (pack.rating.toLowerCase() === "safe") { - packRating = `<span class="text-green-400">S</span>`; - } else if (pack.rating.toLowerCase() === "questionable") { - packRating = `<span class="text-yellow-500">Q</span>`; - } else if (pack.rating.toLowerCase() === "explicit") { - packRating = `<span class="text-red-500">E</span>`; - } - } - - return ` -<a class="bg-stone-800 text-zinc-100 p-4 rounded-lg w-full flex flex-row gap-2" href="./${pack.id}/"> - - <div class="w-24 h-24 flex justify-center items-center"> - - <div role="status" data-spinner-id="${pack.image}"> - <svg - aria-hidden="true" - class="inline w-16 h-16 text-gray-200 animate-spin dark:text-gray-600 fill-green-500" - viewBox="0 0 100 101" - fill="none" - xmlns="http://www.w3.org/2000/svg" - > - <path - d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" - fill="currentColor" - /> - <path - d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" - fill="currentFill" - /> - </svg> - <span class="sr-only">Loading...</span> - </div> - <img - src="${CreateImageURL(index, pack.image)}" - alt="" - class="object-contain w-24 h-24 hidden" - data-image-id="${pack.image}" - /> - </div> - - <div class="flex flex-col gap-1 justify-center"> - <p class="text-bold text-2xl">${pack.name}</p> - ${pack.author ? `<p class="text-xl">${pack.author}</p>` : ""} - <p class="text-xl">${pack.stickers} stickers ${pack.rating ? "| " + packRating : ""}</p> - </div> - -</a> -` -} - -function _CreatePacksIndex(index, packs, isDev) { - - let packLinks = []; - packs.forEach((packLink) => packLinks.push(_PackLink(index, packLink))); - - return ` - <div class="container flex flex-col items-center justify-center min-h-screen gap-4 p-4 mx-auto"> - <div class="gap-2 [grid-template-columns:100%] md:[grid-template-columns:repeat(auto-fill,minmax(380px,500px))] justify-center items-center grid w-full"> - ${packLinks.join("\n")} - </div> - </div> - - <script src="../static/RenderImages.js"></script> -` -} - -module.exports = _CreatePacksIndex \ No newline at end of file diff --git a/src/utils.js b/src/utils.js index 5aad9aa..4ef9484 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,9 +1,3 @@ -function CreateImageURL(index, id) { - return `${index.homeserver_url}${id.slice(0, 2)}/${id.slice(2, 4)}/${id.slice( - 4 - )}`; -} - function CreatePackDescription(pack) { let description = []; @@ -36,14 +30,6 @@ function CreatePackDescription(pack) { return description.join(" | "); } -function InjectWSConnection() { - return ` - <!-- The following was injected by watch.js script, because we are in a dev mode --> - <script src="/src/hotreload.js"></script> - <!-- Dev mode: Enabled --> - `; -} - function log(level = "INFO" | "ERROR" | "WARN" | "LOG", message, connected = false) { const date = new Date; const time = date.toLocaleTimeString() @@ -67,8 +53,6 @@ function log(level = "INFO" | "ERROR" | "WARN" | "LOG", message, connected = fal } module.exports = { - CreateImageURL, - CreatePackDescription, - InjectWSConnection, log, + CreatePackDescription }; diff --git a/static/RenderImages.js b/static/RenderImages.js index 2a54193..57509a1 100644 --- a/static/RenderImages.js +++ b/static/RenderImages.js @@ -1,19 +1,25 @@ const images = document.querySelectorAll("[data-image-id]"); +images.forEach((image, i) => { -images.forEach((image) => { + if (i < 4) { + image.setAttribute("loading", "eager") + } const spinner = document.querySelector(`[data-spinner-id="${image.getAttribute("data-image-id")}"]`) - if (image.height > 0) { - image.classList.remove("hidden"); - spinner.classList.add("hidden"); + if (image.height > 0 && image.complete) { + image.classList.remove("invisible"); + spinner.classList.add("invisible"); return + } else { + image.classList.add("invisible"); + spinner.classList.remove("invisible"); } image.addEventListener("load", () => { console.log("image " + image.getAttribute("data-image-id") + " loaded"); - image.classList.remove("hidden"); - spinner.classList.add("hidden"); + image.classList.remove("invisible"); + spinner.classList.add("invisible"); image.removeEventListener("load", this); }); diff --git a/static/images/captive_portal_24dp_E8EAED_FILL0_wght400_GRAD0_opsz24.png b/static/images/captive_portal_24dp_E8EAED_FILL0_wght400_GRAD0_opsz24.png new file mode 100644 index 0000000000000000000000000000000000000000..0908872a4b23d38658ffbbd1d504eda72803dbf3 GIT binary patch literal 3449 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 bx%vMASN$8iTzAC200000NkvXXu0mjf1TTaH literal 0 HcmV?d00001 diff --git a/static/images/github-mark-white.png b/static/images/github-mark-white.png new file mode 100644 index 0000000000000000000000000000000000000000..50b81752278d084ba9d449fff25f4051df162b0f GIT binary patch literal 4837 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 LNkvXXu0mjf>?wK3 literal 0 HcmV?d00001 diff --git a/static/tailwind.css b/static/tailwind.css index 965aec6..4409599 100644 --- a/static/tailwind.css +++ b/static/tailwind.css @@ -600,18 +600,38 @@ video { border-width: 0; } +.invisible { + visibility: hidden; +} + .fixed { position: fixed; } +.sticky { + position: sticky; +} + .inset-0 { inset: 0px; } +.left-0 { + left: 0px; +} + .left-1\/2 { left: 50%; } +.right-0 { + right: 0px; +} + +.top-0 { + top: 0px; +} + .top-8 { top: 2rem; } @@ -637,6 +657,13 @@ video { margin-right: auto; } +.line-clamp-1 { + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 1; +} + .inline { display: inline; } @@ -653,6 +680,10 @@ video { display: none; } +.aspect-square { + aspect-ratio: 1 / 1; +} + .h-16 { height: 4rem; } @@ -665,6 +696,14 @@ video { height: 12rem; } +.h-6 { + height: 1.5rem; +} + +.h-full { + height: 100%; +} + .min-h-screen { min-height: 100vh; } @@ -685,6 +724,10 @@ video { width: 12rem; } +.w-8 { + width: 2rem; +} + .w-full { width: 100%; } @@ -704,14 +747,22 @@ video { animation: spin 1s linear infinite; } -.flex-row { - flex-direction: row; +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); +} + +.grid-rows-1 { + grid-template-rows: repeat(1, minmax(0, 1fr)); } .flex-col { flex-direction: column; } +.flex-wrap { + flex-wrap: wrap; +} + .items-center { align-items: center; } @@ -720,8 +771,8 @@ video { justify-content: center; } -.gap-1 { - gap: 0.25rem; +.justify-between { + justify-content: space-between; } .gap-2 { @@ -736,10 +787,28 @@ video { overflow-x: hidden; } +.rounded-full { + border-radius: 9999px; +} + .rounded-lg { border-radius: 0.5rem; } +.rounded-md { + border-radius: 0.375rem; +} + +.rounded-b-lg { + border-bottom-right-radius: 0.5rem; + border-bottom-left-radius: 0.5rem; +} + +.bg-\[\#1d1f3d\] { + --tw-bg-opacity: 1; + background-color: rgb(29 31 61 / var(--tw-bg-opacity, 1)); +} + .bg-\[\#259d7b\] { --tw-bg-opacity: 1; background-color: rgb(37 157 123 / var(--tw-bg-opacity, 1)); @@ -770,6 +839,11 @@ video { background-color: rgb(220 38 38 / var(--tw-bg-opacity, 1)); } +.bg-slate-800 { + --tw-bg-opacity: 1; + background-color: rgb(30 41 59 / var(--tw-bg-opacity, 1)); +} + .bg-stone-800 { --tw-bg-opacity: 1; background-color: rgb(41 37 36 / var(--tw-bg-opacity, 1)); @@ -842,11 +916,21 @@ video { line-height: 2.5rem; } -.text-xl { - font-size: 1.25rem; +.text-lg { + font-size: 1.125rem; line-height: 1.75rem; } +.text-sm { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.text-xs { + font-size: 0.75rem; + line-height: 1rem; +} + .text-gray-200 { --tw-text-opacity: 1; color: rgb(229 231 235 / var(--tw-text-opacity, 1)); @@ -902,8 +986,12 @@ video { transition-duration: 150ms; } -.\[grid-template-columns\:100\%\] { - grid-template-columns: 100%; +.\[grid-column\:1\] { + grid-column: 1; +} + +.\[grid-row\:1\] { + grid-row: 1; } .\[grid-template-columns\:repeat\(auto-fill\2c 96px\)\] { @@ -926,6 +1014,52 @@ video { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } +.hover\:underline:hover { + text-decoration-line: underline; +} + +@media (min-width: 640px) { + .sm\:inline { + display: inline; + } + + .sm\:h-10 { + height: 2.5rem; + } + + .sm\:w-16 { + width: 4rem; + } + + .sm\:w-32 { + width: 8rem; + } + + .sm\:gap-4 { + gap: 1rem; + } + + .sm\:text-2xl { + font-size: 1.5rem; + line-height: 2rem; + } + + .sm\:text-base { + font-size: 1rem; + line-height: 1.5rem; + } + + .sm\:text-lg { + font-size: 1.125rem; + line-height: 1.75rem; + } + + .sm\:text-xl { + font-size: 1.25rem; + line-height: 1.75rem; + } +} + @media (min-width: 768px) { .md\:top-32 { top: 8rem; @@ -946,9 +1080,17 @@ video { .md\:whitespace-pre { white-space: pre; } +} - .md\:\[grid-template-columns\:repeat\(auto-fill\2c minmax\(380px\2c 500px\)\)\] { - grid-template-columns: repeat(auto-fill,minmax(380px,500px)); +@media (min-width: 1024px) { + .lg\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (min-width: 1536px) { + .\32xl\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); } } diff --git a/tailwind.config.js b/tailwind.config.js index 00108c5..45d37f2 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,6 +1,6 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - content: ["./src/templates/**/*.{html,js, ejs}"], + content: ["./src/templates/**/*.{html,js,ejs}", "./static/**/*.{html,js,ejs}"], theme: { extend: {}, }, From bf2684cabc80d211989a21545f2d6d3d27626824 Mon Sep 17 00:00:00 2001 From: Kentai Radiquum <kentai.waah@gmail.com> Date: Thu, 23 Jan 2025 22:06:58 +0500 Subject: [PATCH 6/6] Refactor Pack Page Style --- src/config.js | 2 +- src/hotreload.js | 2 +- src/index.js | 34 ++- src/templates/Base.ejs | 114 +++++++-- src/templates/components/Footer.ejs | 18 ++ src/templates/components/Head.ejs | 2 +- src/templates/components/Header.ejs | 17 +- src/templates/components/Link/AddLink.ejs | 4 + src/templates/components/Link/Stickerset.ejs | 2 +- src/templates/components/Pack/Description.ejs | 37 +++ src/templates/components/Pack/Links.ejs | 5 + src/templates/components/Pack/Preview.ejs | 30 +++ src/templates/components/packCard.js | 71 ------ src/templates/components/packHead.js | 20 -- src/templates/components/packLinks.js | 26 --- src/templates/components/packPreview.js | 48 ---- src/templates/pack.js | 68 ------ src/utils.js | 19 +- src/watch.js | 22 +- static/OpenPopUp.js | 13 -- static/RenderImages.js | 42 ++-- static/tailwind.css | 216 ++++++++---------- 22 files changed, 364 insertions(+), 448 deletions(-) create mode 100644 src/templates/components/Footer.ejs create mode 100644 src/templates/components/Link/AddLink.ejs create mode 100644 src/templates/components/Pack/Description.ejs create mode 100644 src/templates/components/Pack/Links.ejs create mode 100644 src/templates/components/Pack/Preview.ejs delete mode 100644 src/templates/components/packCard.js delete mode 100644 src/templates/components/packHead.js delete mode 100644 src/templates/components/packLinks.js delete mode 100644 src/templates/components/packPreview.js delete mode 100644 src/templates/pack.js delete mode 100644 static/OpenPopUp.js diff --git a/src/config.js b/src/config.js index 463b1cd..7803625 100644 --- a/src/config.js +++ b/src/config.js @@ -1,6 +1,6 @@ const config = { stickerPacksDir: "stickerpacks", - outDir: "sticker", + outDir: "", homeserverUrl: "https://synapse.wah.su/__thumbnail/" }; diff --git a/src/hotreload.js b/src/hotreload.js index 7027f36..f9de754 100644 --- a/src/hotreload.js +++ b/src/hotreload.js @@ -1,4 +1,4 @@ -let webSocket = new WebSocket('ws://127.0.0.1:3001'); +let webSocket = new WebSocket(`ws://${window.location.hostname}:3001`); webSocket.onmessage = function(e) { if (e.data == "RELOAD") { console.log("Reloading page after build") diff --git a/src/index.js b/src/index.js index e214111..e8fe6ac 100644 --- a/src/index.js +++ b/src/index.js @@ -1,11 +1,9 @@ const config = require("./config"); const fs = require("fs"); const path = require("path"); -const { log } = require("./utils"); +const { log, CreateImageURL, CreatePackDescription } = require("./utils"); let ejs = require("ejs"); -// const _CreatePackPage = require("./templates/pack"); - let PackIndex = null; let Packs = []; @@ -52,8 +50,31 @@ if (OutPath != ParPath) { PackIndex.packs.forEach((pack) => { const packFile = JSON.parse(fs.readFileSync(`${InpPath}${pack}`)); - // if (!fs.existsSync(`${OutPath}${packFile.id}`)) fs.mkdirSync(`${OutPath}${packFile.id}`); - // fs.writeFileSync(`${OutPath}${packFile.id}/index.html`, _CreatePackPage(PackIndex, packFile, isDev)); + const Template = fs.readFileSync( + path.join(ParPath, "src/templates/Base.ejs") + ); + const html = ejs.render( + Template.toString(), + { + title: packFile.title, + description: CreatePackDescription(packFile), + image: { + url: CreateImageURL(config.homeserverUrl, packFile.stickers[0].id), + mimetype: packFile.stickers[0].info.mimetype, + w: packFile.stickers[0].info.w, + h: packFile.stickers[0].info.h, + alt: packFile.stickers[0].info.alt, + }, + path: config.outDir ? `/${config.outDir}` : "", + isDev, + stickerset: packFile, + page: "stickerset", + homeserverUrl: config.homeserverUrl, + }, + { root: path.join(ParPath, "src/templates") } + ); + if (!fs.existsSync(`${OutPath}${packFile.id}`)) fs.mkdirSync(`${OutPath}${packFile.id}`); + fs.writeFileSync(`${OutPath}${packFile.id}/index.html`, html); Packs.push({ id: packFile.id, name: packFile.title, @@ -86,7 +107,7 @@ const html = ejs.render( h: "96", alt: "", }, - path: config.OutPath, + path: config.outDir ? `/${config.outDir}` : "", isDev, stickerset: null, page: "index", @@ -95,6 +116,5 @@ const html = ejs.render( }, { root: path.join(ParPath, "src/templates") } ); -log("LOG", `\n\n${html}\n\n`); fs.writeFileSync(`${OutPath}index.html`, html); log("INFO", "Generation complete"); diff --git a/src/templates/Base.ejs b/src/templates/Base.ejs index 944d39c..c148b2e 100644 --- a/src/templates/Base.ejs +++ b/src/templates/Base.ejs @@ -1,28 +1,100 @@ <!DOCTYPE html> <html lang="en"> - <%- include('/components/Head', {title, description, image, path, isDev}); %> +<%- include('/components/Head', {title, description, image, path, isDev}); %> <body class="overflow-x-hidden text-white"> <%- include("/components/Header", {path, stickerset}) %> - <div class="fixed inset-0 min-h-screen -z-10 tiledBackground"></div> - <div class="fixed inset-0 min-h-screen -z-20 bg-gradient-to-b from-gray-900 to-black"></div> - <div class="container px-8 py-4 mx-auto"> - <% if (page == "index") { %> - <div class="grid w-full h-full grid-cols-1 gap-2 lg:grid-cols-2 2xl:grid-cols-3"> - <% packs.forEach(function(pack){ %> - <%- include('/components/Link/Stickerset', {path, homeserverUrl, pack}); %> - <% }); %> - </div> - <% }; %> - - <div class="flex flex-wrap items-center gap-4 py-4 mx-auto"> - <a class="flex items-center gap-2 text-lg" href="https://wah.su/radiquum"> <span>by @radiquum</span> <img class="object-contain w-8 rounded-full aspect-square" src="https://radiquum.wah.su/static/avatar_512.jpg" alt="" /></a> - <div class="flex items-center gap-2"> - <p class="text-lg">Find us on:</p> - <a href="https://github.com/wah-su"><img class="object-contain w-8 rounded-full aspect-square" src="<%- path %>/static/images/github-mark-white.png" alt="github" /></a> - <a href="https://wah.su"><img class="object-contain w-8 rounded-full aspect-square" src="<%- path %>/static/images/captive_portal_24dp_E8EAED_FILL0_wght400_GRAD0_opsz24.png" alt="website" /></a> - </div> + <div class="fixed inset-0 min-h-screen -z-10 tiledBackground"></div> + <div class="fixed inset-0 min-h-screen -z-20 bg-gradient-to-b from-gray-900 to-black"></div> + <div class="container px-4 py-4 mx-auto sm:px-8"> + <% if (page=="index" ) { %> + <div class="grid w-full h-full grid-cols-1 gap-2 lg:grid-cols-2 2xl:grid-cols-3"> + <% packs.forEach(function(pack){ %> + <%- include('/components/Link/Stickerset', {path, homeserverUrl, pack}); %> + <% }); %> + </div> + <%- include('/components/Footer'); %> + <% }; %> + <% if (page=="stickerset" ) { %> + <div class="flex flex-wrap gap-4"> + <div class="flex flex-col w-full gap-2 lg:w-[49%] h-fit"> + <%- include('/components/Pack/Description', {homeserverUrl, stickerset}); %> + <%- include('/components/Pack/Links', {stickerset}); %> + <div + class="hidden px-4 py-2 rounded-md md:block sm:px-8 bg-slate-800"> + <p + class="flex items-center gap-2 mb-4 text-lg border-b md:text-2xl border-slate-400"> + <img src="<%- path %>/static/images/element.png" alt="" + class="object-contain w-8 py-2" /> Add StickerPicker to + Element + </p> + <p> + Type /devtools in chat. Other -> Explore account data in + Element Web + (not "room account data", must be the global one), edit the + m.widgets account data event to have the following content: + </p> + <p class="whitespace-pre"> +{ + "stickerpicker": { + "content": { + "type": "m.stickerpicker", + "url": "https://matrix.wah.su/stickerpicker/?theme=$theme", + "name": "Stickerpicker", + "creatorUserId": "@you:matrix.server.name", + "data": {} + }, + "sender": "@you:matrix.server.name", + "state_key": "stickerpicker", + "type": "m.widget", + "id": "stickerpicker" + } +} + </p> + <p> + If you do not yet have a m.widgets event, simply create it + with that + content. You can also use the client-server API directly + instead of + using Element Web. + <br /> + <br /> + The theme=$theme query parameter will make the widget + conform to + Element's theme automatically. You can also use light, dark + or black + instead of $theme to always use a specific theme. + </p> + </div> + <div class="hidden lg:block"> + <%- include('/components/Footer'); %> + </div> + </div> + <div class="flex flex-col w-full gap-2 lg:w-[49%] h-fit"> + <%- include('/components/Pack/Preview', {homeserverUrl, stickerset}); %> + </div> + <div class="block lg:hidden"> + <%- include('/components/Footer'); %> + </div> + </div> + <% }; %> </div> - </div> - <script src="<%- path %>/static/RenderImages.js"></script> + <script src="<%- path %>/static/RenderImages.js"></script> </body> + <% if (page=="stickerset" ) { %> + <script> + const stickerpackdesc = document.getElementById("stickerpackdesc"); + const stickerpackname = document.getElementById("stickerpackname"); + window.onscroll = () => { + const current_Y_pos = window.scrollY; + if ( + current_Y_pos > + Math.floor(stickerpackdesc.clientHeight * 0.7) + ) { + stickerpackname.style.setProperty("--tw-translate-y", "0%"); + } else { + stickerpackname.style.setProperty("--tw-translate-y", "-200%"); + } + }; + </script> + <% }; %> </html> \ No newline at end of file diff --git a/src/templates/components/Footer.ejs b/src/templates/components/Footer.ejs new file mode 100644 index 0000000..6688028 --- /dev/null +++ b/src/templates/components/Footer.ejs @@ -0,0 +1,18 @@ +<div class="flex flex-wrap items-center gap-4 py-4 mx-auto"> + <a class="flex items-center gap-2 text-lg" href="https://wah.su/radiquum"> + <span>by + @radiquum</span> <img + class="object-contain w-8 rounded-full aspect-square" + src="https://radiquum.wah.su/static/avatar_512.jpg" alt="" /></a> + <div class="flex items-center gap-2"> + <p class="text-lg">Find us on:</p> + <a href="https://github.com/wah-su"><img + class="object-contain w-8 rounded-full aspect-square" + src="<%- path %>/static/images/github-mark-white.png" + alt="github" /></a> + <a href="https://wah.su"><img + class="object-contain w-8 rounded-full aspect-square" + src="<%- path %>/static/images/captive_portal_24dp_E8EAED_FILL0_wght400_GRAD0_opsz24.png" + alt="website" /></a> + </div> +</div> \ No newline at end of file diff --git a/src/templates/components/Head.ejs b/src/templates/components/Head.ejs index 2948b9b..5bfebdd 100644 --- a/src/templates/components/Head.ejs +++ b/src/templates/components/Head.ejs @@ -14,7 +14,7 @@ <link href="<%= path %>/static/tailwind.css" rel="stylesheet"> <% if (isDev) { %> <!-- The following was injected by watch.js script, because we are in a dev mode --> - <script src="<%= path %>/src/hotreload.js"></script> + <script src="/src/hotreload.js"></script> <!-- Dev mode: Enabled --> <% }; %> </head> \ No newline at end of file diff --git a/src/templates/components/Header.ejs b/src/templates/components/Header.ejs index 670ea03..cfbe8d2 100644 --- a/src/templates/components/Header.ejs +++ b/src/templates/components/Header.ejs @@ -1,12 +1,15 @@ -<header class="sticky top-0 left-0 right-0 bg-[#1d1f3d] rounded-b-lg"> - <div class="container flex items-center justify-between px-8 py-4 mx-auto"> - <a href="<%- path %>index.html"><img class="h-6 sm:h-10" src="<%- path %>/static/images/logo.svg" alt="index page"/></a> +<% include('/functions') %> +<header class="sticky top-0 left-0 right-0 bg-[#1d1f3d] rounded-b-lg z-10"> + <div class="container flex items-center justify-between px-8 py-4 mx-auto min-h-16"> + <a href="<%- path %>/index.html"><img class="h-6 sm:h-10" src="<%- path %>/static/images/logo.svg" alt="index page"/></a> <% if (stickerset) { %> - <p>STICKERSET</p> + <div id="stickerpackname" class="-p-4 flex items-center gap-2 transition-transform translate-y-[var(--tw-translate-y)]" style="--tw-translate-y:-200%"> + <img src="<%- CreateImageURL(homeserverUrl, stickerset.stickers[0].id) %>" class="object-contain w-8 aspect-square" /> + <p class="text-lg sm:text-xl"><%- stickerset.title %></p> + </div> <% }; %> - <div class="flex items-center justify-center gap-2 text-white sm:gap-4 sm:text-xl"> - <a class="hidden hover:underline sm:inline" href="<%- path %>index.html">StickerSets</a> - <a class="hover:underline" href="https://github.com/wah-su/mstickers">GitHub</a> + <div class="items-center justify-center hidden gap-2 text-white sm:flex sm:gap-4 sm:text-xl"> + <a class="hover:underline" href="<%- path %>/index.html">StickerSets</a> </div> </div> </header> \ No newline at end of file diff --git a/src/templates/components/Link/AddLink.ejs b/src/templates/components/Link/AddLink.ejs new file mode 100644 index 0000000..abda97e --- /dev/null +++ b/src/templates/components/Link/AddLink.ejs @@ -0,0 +1,4 @@ +<a class="bg-[var(--bg-color)] gap-2 items-center w-full px-4 sm:px-8 py-4 rounded-lg flex hover:scale-105 transition-transform" href="<%- link %>" style="--bg-color:<%- color %>"> + <img src="<%- path %>/static/images/<%- image %>" alt="" class="object-contain w-10" /> + <p class="text-2xl text-slate-50"><%- text %></p> +</a> \ No newline at end of file diff --git a/src/templates/components/Link/Stickerset.ejs b/src/templates/components/Link/Stickerset.ejs index a9415a0..26ba4d7 100644 --- a/src/templates/components/Link/Stickerset.ejs +++ b/src/templates/components/Link/Stickerset.ejs @@ -1,5 +1,5 @@ <% include('/functions') %> -<a href="<%- path %><%- pack.id %>" class="flex items-center w-full h-full gap-2 p-4 rounded-md sm:gap-4 bg-slate-800"> +<a href="<%- path %>/<%- pack.id %>" class="flex items-center w-full h-full gap-2 p-4 rounded-md sm:gap-4 bg-slate-800"> <div class="grid items-center justify-center object-contain w-16 grid-cols-1 grid-rows-1 sm:w-32 aspect-square"> <img src="<%- CreateImageURL(homeserverUrl, pack.image) %>" data-image-id="<%- pack.image %>" class="object-contain w-16 sm:w-32 aspect-square [grid-column:1] [grid-row:1]" loading="lazy" /> <svg diff --git a/src/templates/components/Pack/Description.ejs b/src/templates/components/Pack/Description.ejs new file mode 100644 index 0000000..f4c5f89 --- /dev/null +++ b/src/templates/components/Pack/Description.ejs @@ -0,0 +1,37 @@ +<% include('/functions') %> +<div class="flex items-center w-full h-full gap-2 py-2 rounded-md bg-slate-800 sm:gap-4" id="stickerpackdesc"> + <div class="grid items-center justify-center object-contain w-24 grid-cols-1 grid-rows-1 sm:w-32 aspect-square"> + <img src="<%- CreateImageURL(homeserverUrl, stickerset.stickers[0].id) %>" data-image-id="<%- stickerset.stickers[0].id %>-Icon" class="object-contain w-24 sm:w-32 aspect-square [grid-column:1] [grid-row:1]" loading="lazy" /> + <svg + role="status" + data-spinner-id="<%- stickerset.stickers[0].id %>-Icon" + aria-hidden="true" + class="mx-auto [grid-column:1] [grid-row:1] inline w-8 text-gray-200 sm:w-16 animate-spin dark:text-gray-600 fill-green-500" + viewBox="0 0 100 101" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" + fill="currentColor" + /> + <path + d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" + fill="currentFill" + /> + </svg> + </div> + <div class="px-4"> + <p class="text-xl font-bold sm:text-2xl line-clamp-1"><%- stickerset.title %></p> + <% if (stickerset.hasOwnProperty("author") && stickerset.author.hasOwnProperty("name") && stickerset.author.name) { %> + <% if (stickerset.author.hasOwnProperty("url") && stickerset.author.url) { %> + <a class="text-lg underline sm:text-xl" href="<%- stickerset.author.url %>"><%- stickerset.author.name %></a> + <% } else { %> + <p class="text-lg sm:text-xl"><%- stickerset.author.name %></p> + <% }; %> + <% }; %> + <% if (stickerset.hasOwnProperty("rating") && stickerset.rating) { %> + <p class="text-lg sm:text-xl <%- PackRatingClass(stickerset.rating) %>"><%- stickerset.rating %></p> + <% }; %> + </div> +</div> \ No newline at end of file diff --git a/src/templates/components/Pack/Links.ejs b/src/templates/components/Pack/Links.ejs new file mode 100644 index 0000000..bdebca9 --- /dev/null +++ b/src/templates/components/Pack/Links.ejs @@ -0,0 +1,5 @@ +<%- include ("/components/Link/AddLink", {name: "telegram", text: "Telegram", image: "telegram.png", link: "https://t.me/addstickers/" + stickerset.id, color: "#2f7ca3"} ) %> +<% if (stickerset.hasOwnProperty("room_id") && stickerset.room_id) { %> + <%- include ("/components/Link/AddLink", {name: "cinny.png", text: "Cinny", image: "cinny.png", link: "https://matrix.to/#/" + stickerset.room_id, color: "#373737"} ) %> + <%- include ("/components/Link/AddLink", {name: "fluffychat.png", text: "FluffyChat", image: "fluffychat.png", link: "https://matrix.to/#/" + stickerset.room_id, color: "#282443"} ) %> +<% }; %> \ No newline at end of file diff --git a/src/templates/components/Pack/Preview.ejs b/src/templates/components/Pack/Preview.ejs new file mode 100644 index 0000000..4793bc1 --- /dev/null +++ b/src/templates/components/Pack/Preview.ejs @@ -0,0 +1,30 @@ +<% include('/functions') %> +<div class="w-full h-full px-4 py-2 rounded-md sm:px-8 bg-slate-800 sm:gap-4"> + <p class="mb-4 text-lg border-b md:text-2xl border-slate-400"><%- stickerset.stickers.length %> stickers</p> + <div class="grid w-full h-full grid-cols-3 gap-2 lg:grid-cols-3 sm:grid-cols-4 xl:grid-cols-4 2xl:grid-cols-5"> + <% stickerset.stickers.forEach(function(sticker){ %> + <div class="grid items-center justify-center object-contain w-24 grid-cols-1 grid-rows-1 sm:w-32 aspect-square"> + <img src="<%- CreateImageURL(homeserverUrl, sticker.id) %>" data-image-id="<%- sticker.id %>" class="object-contain w-24 sm:w-32 aspect-square [grid-column:1] [grid-row:1]" loading="lazy" /> + <svg + role="status" + data-spinner-id="<%- sticker.id %>" + aria-hidden="true" + class="mx-auto [grid-column:1] [grid-row:1] inline w-8 text-gray-200 sm:w-16 animate-spin dark:text-gray-600 fill-green-500" + viewBox="0 0 100 101" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" + fill="currentColor" + /> + <path + d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" + fill="currentFill" + /> + </svg> + </div> + <% }); %> + </div> + +</div> \ No newline at end of file diff --git a/src/templates/components/packCard.js b/src/templates/components/packCard.js deleted file mode 100644 index f3bba4c..0000000 --- a/src/templates/components/packCard.js +++ /dev/null @@ -1,71 +0,0 @@ -const { CreateImageURL } = require("../../utils"); - -function _packName(pack) { - let string = ""; - string += `<p class="text-4xl">${pack.title}</p>`; - - if (pack.hasOwnProperty("author") && pack.author) { - let author_string = `<p class="text-2xl">by: ${pack.author.name}</p>`; - if (pack.author.url) { - author_string = `<p class="text-2xl">by: <a href="${pack.author.url}" class="underline">${pack.author.name}</a></p>`; - } - string += author_string; - } - - if (pack.hasOwnProperty("rating") && pack.rating) { - switch (pack.rating.toLowerCase()) { - case "safe": - string += `<p class="text-2xl text-green-400 text-bold">safe</p>`; - break; - case "questionable": - string += `<p class="text-2xl text-yellow-500 text-bold">questionable</p>`; - break; - case "explicit": - string += `<p class="text-2xl text-red-500 text-bold">explicit</p>`; - break; - default: - break; - } - } - - return string; -} - -function _packCard(index, pack) { - return ` - <div class="w-full flex gap-4 flex-col md:flex-row md:w-[768px] justify-center items-center bg-stone-800 text-zinc-100 px-4 py-8 rounded-lg"> - <div class="w-48 h-48 flex justify-center items-center"> - <div role="status" data-spinner-id="${pack.stickers[0].id}"> - <svg - aria-hidden="true" - class="inline w-16 h-16 text-gray-200 animate-spin dark:text-gray-600 fill-green-500" - viewBox="0 0 100 101" - fill="none" - xmlns="http://www.w3.org/2000/svg" - > - <path - d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" - fill="currentColor" - /> - <path - d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" - fill="currentFill" - /> - </svg> - <span class="sr-only">Loading...</span> - </div> - <img - src="${CreateImageURL(index, pack.stickers[0].id)}" - alt="${pack.stickers[0].body}" - class="object-contain w-48 h-48 hidden" - data-image-id="${pack.stickers[0].id}" - /> - </div> - <div class="flex flex-col gap-2 justify-center"> - ${_packName(pack)} - </div> - </div> -`; -} - -module.exports = _packCard; diff --git a/src/templates/components/packHead.js b/src/templates/components/packHead.js deleted file mode 100644 index 0ceb6fb..0000000 --- a/src/templates/components/packHead.js +++ /dev/null @@ -1,20 +0,0 @@ -const {CreateImageURL, CreatePackDescription} = require("../../utils"); - -function _CreateHead(index, pack) { - return ` -<meta charset="UTF-8" /> -<meta name="viewport" content="width=device-width, initial-scale=1.0" /> -<title>${pack.title}</title> -<link rel="icon" type="${pack.stickers[0].info.mimetype}" href="${CreateImageURL(index, pack.stickers[0].id)}" /> -<meta property="og:title" content="${pack.title}" /> -<meta property="og:description" content="${CreatePackDescription(pack)}" /> -<meta property="og:type" content="website" /> -<meta property="og:image" content="${CreateImageURL(index, pack.stickers[0].id)}" /> -<meta property="og:image:type" content="${pack.stickers[0].info.mimetype}" /> -<meta property="og:image:width" content="${pack.stickers[0].info.w}" /> -<meta property="og:image:height" content="${pack.stickers[0].info.h}" /> -<meta property="og:image:alt" content="${pack.stickers[0].body}" /> -<link href="../static/tailwind.css" rel="stylesheet"> -`} - -module.exports = _CreateHead \ No newline at end of file diff --git a/src/templates/components/packLinks.js b/src/templates/components/packLinks.js deleted file mode 100644 index 7d4c7ba..0000000 --- a/src/templates/components/packLinks.js +++ /dev/null @@ -1,26 +0,0 @@ -function PackLinks(pack) { - return ` - <a class="bg-[#2f7ca3] gap-2 items-center w-full px-8 py-4 rounded-lg flex hover:scale-105 transition-transform" href="https://t.me/addstickers/${pack.id}"> - <img src="../static/images/telegram.png" alt="" class="object-contain w-10" /> - <p class="text-2xl text-slate-50">Telegram</p> - </a> - <button class="bg-[#259d7b] gap-2 items-center w-full px-8 py-4 rounded-lg flex hover:scale-105 transition-transform" onclick="toggleElementInstruction()"> - <img src="../static/images/element.png" alt="" class="object-contain w-10" /> - <p class="text-2xl text-slate-50">Element</p> - </button> - ${(pack.hasOwnProperty("room_id") && pack.room_id) ? ( - ` - <a class="bg-[#282443] gap-2 items-center w-full px-8 py-4 rounded-lg flex hover:scale-105 transition-transform" href="https://matrix.to/#/${pack.room_id}"> - <img src="../static/images/fluffychat.png" alt="" class="object-contain w-10" /> - <p class="text-2xl text-slate-50">FluffyChat</p> - </a> - <a class="bg-[#373737] gap-2 items-center w-full px-8 py-4 rounded-lg flex hover:scale-105 transition-transform" href="https://matrix.to/#/${pack.room_id}"> - <img src="../static/images/cinny.png" alt="" class="object-contain w-10" /> - <p class="text-2xl text-slate-50">Cinny</p> - </a> - ` - ) - : ""} -`} - -module.exports = PackLinks \ No newline at end of file diff --git a/src/templates/components/packPreview.js b/src/templates/components/packPreview.js deleted file mode 100644 index 14072d3..0000000 --- a/src/templates/components/packPreview.js +++ /dev/null @@ -1,48 +0,0 @@ -const { CreateImageURL } = require("../../utils"); - -function _addSticker(index, sticker) { - return ` - <div class="w-24 h-24 flex justify-center items-center"> - <div role="status" data-spinner-id="${sticker.id}-sticker"> - <svg - aria-hidden="true" - class="inline w-16 h-16 text-gray-200 animate-spin dark:text-gray-600 fill-green-500" - viewBox="0 0 100 101" - fill="none" - xmlns="http://www.w3.org/2000/svg" - > - <path - d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" - fill="currentColor" - /> - <path - d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" - fill="currentFill" - /> - </svg> - <span class="sr-only">Loading...</span> - </div> - <img - src="${CreateImageURL(index, sticker.id)}" - alt="${sticker.body}" - class="object-contain w-24 h-24 hidden" - data-image-id="${sticker.id}-sticker" - /> - </div> -`}; - -function _packPreview(index, pack) { - - let stickers = []; - pack.stickers.forEach((sticker) => stickers.push(_addSticker(index, sticker))); - - return ` - <div class="w-full flex gap-4 flex-col md:w-[768px] bg-stone-800 text-zinc-100 px-4 py-8 rounded-lg"> - <p class="text-2xl">Pack Preview (${pack.stickers.length} stickers)</p> - <div class="gap-2 [grid-template-columns:repeat(auto-fill,96px)] justify-center grid items-center w-full"> - ${stickers.join("\n")} - </div> - </div> -`}; - -module.exports = _packPreview; diff --git a/src/templates/pack.js b/src/templates/pack.js deleted file mode 100644 index 8581553..0000000 --- a/src/templates/pack.js +++ /dev/null @@ -1,68 +0,0 @@ -const PackHead = require("./components/packHead"); -const PackCard = require("./components/packCard"); -const PackLinks = require("./components/packLinks"); -const PackPreview = require("./components/packPreview"); -const { InjectWSConnection } = require("../utils") - -function _CreatePackPage(index, pack, isDev) { - return ` -<!DOCTYPE html> -<html lang="en"> - - <head> - ${PackHead(index, pack)} - ${isDev ? InjectWSConnection() : ""} - </head> - - <body class="overflow-x-hidden"> - - <div class="fixed inset-0 min-h-screen -z-10 tiledBackground"></div> - <div class="fixed inset-0 min-h-screen -z-20 bg-gradient-to-b from-gray-900 to-black"></div> - - <div class="container flex flex-col items-center justify-center min-h-screen gap-4 p-4 mx-auto"> - ${PackCard(index, pack)} - <div class="flex flex-col gap-2 justify-center w-full md:w-[768px]"> - ${PackLinks(pack)} - </div> - ${PackPreview(index, pack)} - </div> - - <div class="fixed inset-0 z-10 hidden min-h-screen bg-black opacity-40" id="preview_sticker_pack_add_to_element_overlay"></div> - <div class="fixed top-8 md:top-32 w-full md:max-w-[768px] left-1/2 -translate-x-1/2 text-white z-20 hidden flex-col gap-4 p-4 rounded-lg shadow-lg bg-stone-900" id="preview_sticker_pack_add_to_element"> - <p> - Type /devtools in chat. Other -> Explore account data in Element Web (not "room account data", must be the global one), edit the m.widgets account data event to have the following content: - </p> - <p class="md:whitespace-pre"> -{ - "stickerpicker": { - "content": { - "type": "m.stickerpicker", - "url": "https://matrix.wah.su/stickerpicker/?theme=$theme", - "name": "Stickerpicker", - "creatorUserId": "@you:matrix.server.name", - "data": {} - }, - "sender": "@you:matrix.server.name", - "state_key": "stickerpicker", - "type": "m.widget", - "id": "stickerpicker" - } -} - </p> - <p> - If you do not yet have a m.widgets event, simply create it with that content. You can also use the client-server API directly instead of using Element Web. - <br /> - <br /> - The theme=$theme query parameter will make the widget conform to Element's theme automatically. You can also use light, dark or black instead of $theme to always use a specific theme. - </p> - <button class="flex items-center justify-center w-full py-2 text-2xl bg-red-600 rounded-lg" onclick="toggleElementInstruction()">Close</button> - </div> - <script src="../static/RenderImages.js"></script> - <script src="../static/OpenPopUp.js"></script> - </body> - -</html> - ` -} - -module.exports = _CreatePackPage \ No newline at end of file diff --git a/src/utils.js b/src/utils.js index 4ef9484..68cc965 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,3 +1,7 @@ +CreateImageURL = function (homeserverUrl, id) { + return `${homeserverUrl}${id.slice(0, 2)}/${id.slice(2, 4)}/${id.slice(4)}`; +}; + function CreatePackDescription(pack) { let description = []; @@ -30,11 +34,15 @@ function CreatePackDescription(pack) { return description.join(" | "); } -function log(level = "INFO" | "ERROR" | "WARN" | "LOG", message, connected = false) { - const date = new Date; - const time = date.toLocaleTimeString() +function log( + level = "INFO" | "ERROR" | "WARN" | "LOG", + message, + connected = false +) { + const date = new Date(); + const time = date.toLocaleTimeString(); if (connected) { - message = `↳${message}` + message = `↳${message}`; } switch (level.toUpperCase()) { case "INFO": @@ -54,5 +62,6 @@ function log(level = "INFO" | "ERROR" | "WARN" | "LOG", message, connected = fal module.exports = { log, - CreatePackDescription + CreatePackDescription, + CreateImageURL }; diff --git a/src/watch.js b/src/watch.js index b7c9a29..2418555 100644 --- a/src/watch.js +++ b/src/watch.js @@ -10,6 +10,7 @@ const { log } = require("./utils"); let triggered = 0; const delay = 1000; let SIGINTCount = 0; +let WSclients = []; const InpPath = path .join(__dirname, "../", config.stickerPacksDir, "./") @@ -20,7 +21,7 @@ log("INFO", `Sticker sets directory: ${InpPath}`); log("INFO", `Output directory: ${OutPath}`); log("INFO", `Working directory: ${ParPath}`); -function onChange(wss) { +function onChange() { if (triggered != 0 && Date.now() - triggered < delay) { log("WARN", `Rebuild was triggered less than a ${delay}ms ago!`, true); return; @@ -38,9 +39,9 @@ function onChange(wss) { return; } log("INFO", stdout); - if (wss) { + if (WSclients.length > 0) { log("INFO", "Reloading web page..."); - wss.send("RELOAD"); + WSclients.forEach((ws) => ws.send("RELOAD")); } }); } @@ -86,18 +87,19 @@ function startServerWithRebuild() { const folder = path.join(__dirname, ".."); const wss = new WebSocket.Server({ port: 3001 }); - let WSclient = null; wss.on("connection", (ws) => { - WSclient = ws; + WSclients.push(ws); + log("INFO", `Client ${WSclients.length} connected`) ws.send("CONNECTED"); }); + process.on("SIGINT", () => { SIGINTCount += 1; - if (WSclient) { + if (WSclients.length > 0) { async function _closeWS() { - await WSclient.close(); + WSclients.forEach(async (ws) => await ws.close()) } _closeWS(); } @@ -118,15 +120,15 @@ function startServerWithRebuild() { watcher .on("add", (path) => { log("INFO", `File ${path} has been added, rebuilding...`); - onChange(WSclient); + onChange(); }) .on("change", (path) => { log("INFO", `File ${path} has been changed, rebuilding...`); - onChange(WSclient); + onChange(); }) .on("unlink", (path) => { log("INFO", `File ${path} has been removed, rebuilding...`); - onChange(WSclient); + onChange(); }); }); } diff --git a/static/OpenPopUp.js b/static/OpenPopUp.js deleted file mode 100644 index 6fbdfb4..0000000 --- a/static/OpenPopUp.js +++ /dev/null @@ -1,13 +0,0 @@ -const ElementInstructionOV = document.getElementById( - "preview_sticker_pack_add_to_element_overlay" -); -const ElementInstruction = document.getElementById( - "preview_sticker_pack_add_to_element" -); - -function toggleElementInstruction() { - ElementInstructionOV.classList.toggle("hidden"); - ElementInstruction.classList.toggle("hidden"); - - ElementInstruction.classList.toggle("flex"); -} diff --git a/static/RenderImages.js b/static/RenderImages.js index 57509a1..b26f0e8 100644 --- a/static/RenderImages.js +++ b/static/RenderImages.js @@ -1,26 +1,26 @@ const images = document.querySelectorAll("[data-image-id]"); images.forEach((image, i) => { + if (i < 4) { + image.setAttribute("loading", "eager"); + } - if (i < 4) { - image.setAttribute("loading", "eager") - } + const spinner = document.querySelector( + `[data-spinner-id="${image.getAttribute("data-image-id")}"]` + ); - const spinner = document.querySelector(`[data-spinner-id="${image.getAttribute("data-image-id")}"]`) + if (image.height > 0 && image.complete) { + image.classList.remove("invisible"); + spinner.classList.add("invisible"); + return; + } else { + image.classList.add("invisible"); + spinner.classList.remove("invisible"); + } - if (image.height > 0 && image.complete) { - image.classList.remove("invisible"); - spinner.classList.add("invisible"); - return - } else { - image.classList.add("invisible"); - spinner.classList.remove("invisible"); - } - - image.addEventListener("load", () => { - console.log("image " + image.getAttribute("data-image-id") + " loaded"); - image.classList.remove("invisible"); - spinner.classList.add("invisible"); - image.removeEventListener("load", this); - }); - -}); \ No newline at end of file + image.addEventListener("load", () => { + console.log("image " + image.getAttribute("data-image-id") + " loaded"); + image.classList.remove("invisible"); + spinner.classList.add("invisible"); + image.removeEventListener("load", this); + }); +}); diff --git a/static/tailwind.css b/static/tailwind.css index 4409599..b54ece5 100644 --- a/static/tailwind.css +++ b/static/tailwind.css @@ -588,18 +588,6 @@ video { } } -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; -} - .invisible { visibility: hidden; } @@ -620,10 +608,6 @@ video { left: 0px; } -.left-1\/2 { - left: 50%; -} - .right-0 { right: 0px; } @@ -632,10 +616,6 @@ video { top: 0px; } -.top-8 { - top: 2rem; -} - .-z-10 { z-index: -10; } @@ -648,15 +628,15 @@ video { z-index: 10; } -.z-20 { - z-index: 20; -} - .mx-auto { margin-left: auto; margin-right: auto; } +.mb-4 { + margin-bottom: 1rem; +} + .line-clamp-1 { overflow: hidden; display: -webkit-box; @@ -664,6 +644,10 @@ video { -webkit-line-clamp: 1; } +.block { + display: block; +} + .inline { display: inline; } @@ -684,26 +668,23 @@ video { aspect-ratio: 1 / 1; } -.h-16 { - height: 4rem; -} - -.h-24 { - height: 6rem; -} - -.h-48 { - height: 12rem; -} - .h-6 { height: 1.5rem; } +.h-fit { + height: -moz-fit-content; + height: fit-content; +} + .h-full { height: 100%; } +.min-h-16 { + min-height: 4rem; +} + .min-h-screen { min-height: 100vh; } @@ -720,10 +701,6 @@ video { width: 6rem; } -.w-48 { - width: 12rem; -} - .w-8 { width: 2rem; } @@ -732,8 +709,8 @@ video { width: 100%; } -.-translate-x-1\/2 { - --tw-translate-x: -50%; +.translate-y-\[var\(--tw-translate-y\)\] { + --tw-translate-y: var(--tw-translate-y); transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } @@ -751,6 +728,10 @@ video { grid-template-columns: repeat(1, minmax(0, 1fr)); } +.grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + .grid-rows-1 { grid-template-rows: repeat(1, minmax(0, 1fr)); } @@ -787,6 +768,10 @@ video { overflow-x: hidden; } +.whitespace-pre { + white-space: pre; +} + .rounded-full { border-radius: 9999px; } @@ -804,39 +789,22 @@ video { border-bottom-left-radius: 0.5rem; } +.border-b { + border-bottom-width: 1px; +} + +.border-slate-400 { + --tw-border-opacity: 1; + border-color: rgb(148 163 184 / var(--tw-border-opacity, 1)); +} + .bg-\[\#1d1f3d\] { --tw-bg-opacity: 1; background-color: rgb(29 31 61 / var(--tw-bg-opacity, 1)); } -.bg-\[\#259d7b\] { - --tw-bg-opacity: 1; - background-color: rgb(37 157 123 / var(--tw-bg-opacity, 1)); -} - -.bg-\[\#282443\] { - --tw-bg-opacity: 1; - background-color: rgb(40 36 67 / var(--tw-bg-opacity, 1)); -} - -.bg-\[\#2f7ca3\] { - --tw-bg-opacity: 1; - background-color: rgb(47 124 163 / var(--tw-bg-opacity, 1)); -} - -.bg-\[\#373737\] { - --tw-bg-opacity: 1; - background-color: rgb(55 55 55 / var(--tw-bg-opacity, 1)); -} - -.bg-black { - --tw-bg-opacity: 1; - background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1)); -} - -.bg-red-600 { - --tw-bg-opacity: 1; - background-color: rgb(220 38 38 / var(--tw-bg-opacity, 1)); +.bg-\[var\(--bg-color\)\] { + background-color: var(--bg-color); } .bg-slate-800 { @@ -844,16 +812,6 @@ video { background-color: rgb(30 41 59 / var(--tw-bg-opacity, 1)); } -.bg-stone-800 { - --tw-bg-opacity: 1; - background-color: rgb(41 37 36 / var(--tw-bg-opacity, 1)); -} - -.bg-stone-900 { - --tw-bg-opacity: 1; - background-color: rgb(28 25 23 / var(--tw-bg-opacity, 1)); -} - .bg-gradient-to-b { background-image: linear-gradient(to bottom, var(--tw-gradient-stops)); } @@ -901,21 +859,11 @@ video { padding-bottom: 1rem; } -.py-8 { - padding-top: 2rem; - padding-bottom: 2rem; -} - .text-2xl { font-size: 1.5rem; line-height: 2rem; } -.text-4xl { - font-size: 2.25rem; - line-height: 2.5rem; -} - .text-lg { font-size: 1.125rem; line-height: 1.75rem; @@ -926,11 +874,20 @@ video { line-height: 1.25rem; } +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} + .text-xs { font-size: 0.75rem; line-height: 1rem; } +.font-bold { + font-weight: 700; +} + .text-gray-200 { --tw-text-opacity: 1; color: rgb(229 231 235 / var(--tw-text-opacity, 1)); @@ -961,25 +918,10 @@ video { color: rgb(234 179 8 / var(--tw-text-opacity, 1)); } -.text-zinc-100 { - --tw-text-opacity: 1; - color: rgb(244 244 245 / var(--tw-text-opacity, 1)); -} - .underline { text-decoration-line: underline; } -.opacity-40 { - opacity: 0.4; -} - -.shadow-lg { - --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - .transition-transform { transition-property: transform; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); @@ -994,10 +936,6 @@ video { grid-row: 1; } -.\[grid-template-columns\:repeat\(auto-fill\2c 96px\)\] { - grid-template-columns: repeat(auto-fill,96px); -} - .tiledBackground { background-image: url('images/background-white.png'); background-repeat: repeat; @@ -1019,8 +957,8 @@ video { } @media (min-width: 640px) { - .sm\:inline { - display: inline; + .sm\:flex { + display: flex; } .sm\:h-10 { @@ -1035,10 +973,19 @@ video { width: 8rem; } + .sm\:grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + .sm\:gap-4 { gap: 1rem; } + .sm\:px-8 { + padding-left: 2rem; + padding-right: 2rem; + } + .sm\:text-2xl { font-size: 1.5rem; line-height: 2rem; @@ -1061,37 +1008,52 @@ video { } @media (min-width: 768px) { - .md\:top-32 { - top: 8rem; + .md\:block { + display: block; } - .md\:w-\[768px\] { - width: 768px; - } - - .md\:max-w-\[768px\] { - max-width: 768px; - } - - .md\:flex-row { - flex-direction: row; - } - - .md\:whitespace-pre { - white-space: pre; + .md\:text-2xl { + font-size: 1.5rem; + line-height: 2rem; } } @media (min-width: 1024px) { + .lg\:block { + display: block; + } + + .lg\:hidden { + display: none; + } + + .lg\:w-\[49\%\] { + width: 49%; + } + .lg\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } + + .lg\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } +} + +@media (min-width: 1280px) { + .xl\:grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } } @media (min-width: 1536px) { .\32xl\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } + + .\32xl\:grid-cols-5 { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } } @media (prefers-color-scheme: dark) {