redirecter for ao3 that adds opengraph metadata

Compare changes

Choose any two refs to compare.

Changed files
+1644 -287
cypress
src
app
api
series
[seriesId]
preview
works
[workId]
chapters
[chapterId]
preview
generator
locked
series
[seriesId]
works
[workId]
icons
lib
+348 -37
bun.lock
···
"@fontsource-variable/bricolage-grotesque": "^5.2.10",
"@fontsource/stack-sans-notch": "^5.2.1",
"@fujocoded/ao3.js": "^0.22.1",
-
"@hono/vite-build": "^1.7.0",
+
"@hono/vite-build": "^1.8.0",
"@hono/vite-dev-server": "^0.23.0",
-
"bun": "^1.3.2",
"fauxdom": "^1.2.2",
-
"hono": "^4.10.4",
-
"next": "16.0.2",
+
"hono": "^4.10.8",
+
"next": "16.0.7",
"react": "19.2.0",
"react-dom": "19.2.0",
},
"devDependencies": {
"@biomejs/biome": "2.2.0",
"@types/bun": "latest",
+
"baseline-browser-mapping": "^2.9.5",
+
"cypress": "^15.7.1",
},
},
},
···
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.2.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Nawu5nHjP/zPKTIryh2AavzTc/KEg4um/MxWdXW0A6P/RZOyIpa7+QSjeXwAwX/utJGaCoXRPWtF3m5U/bB3Ww=="],
-
"@emnapi/runtime": ["@emnapi/runtime@1.7.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q=="],
+
"@cypress/request": ["@cypress/request@3.0.9", "", { "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", "caseless": "~0.12.0", "combined-stream": "~1.0.6", "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~4.0.4", "http-signature": "~1.4.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "performance-now": "^2.1.0", "qs": "6.14.0", "safe-buffer": "^5.1.2", "tough-cookie": "^5.0.0", "tunnel-agent": "^0.6.0", "uuid": "^8.3.2" } }, "sha512-I3l7FdGRXluAS44/0NguwWlO83J18p0vlr2FYHrJkWdNYhgVoiYo61IXPqaOsL+vNxU1ZqMACzItGK3/KKDsdw=="],
+
+
"@cypress/xvfb": ["@cypress/xvfb@1.2.4", "", { "dependencies": { "debug": "^3.1.0", "lodash.once": "^4.1.1" } }, "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q=="],
+
+
"@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="],
"@fontsource-variable/bricolage-grotesque": ["@fontsource-variable/bricolage-grotesque@5.2.10", "", {}, "sha512-5EDsCqgGpKVcJWE4sg9ydli+t5WM97mISYw5lla/Ev4z71FwXh1oN0YUU8xjkRW9+wBCGD9R+ntAvI8G4bUFJg=="],
···
"@fujocoded/ao3.js": ["@fujocoded/ao3.js@0.22.1", "", { "dependencies": { "cheerio": "^1.1.2", "vite-tsconfig-paths": "^5.1.4" } }, "sha512-esuvNNj1AyEb11E/NZAxbcimnHyj2wUJUlyKnGLbQzZCZ3QVEEwqkfShWg0D+DsRBQVkslLg18QRlRRJihLbzA=="],
-
"@hono/node-server": ["@hono/node-server@1.19.6", "", { "peerDependencies": { "hono": "^4" } }, "sha512-Shz/KjlIeAhfiuE93NDKVdZ7HdBVLQAfdbaXEaoAVO3ic9ibRSLGIQGkcBbFyuLr+7/1D5ZCINM8B+6IvXeMtw=="],
+
"@hono/node-server": ["@hono/node-server@1.19.7", "", { "peerDependencies": { "hono": "^4" } }, "sha512-vUcD0uauS7EU2caukW8z5lJKtoGMokxNbJtBiwHgpqxEXokaHCBkQUmCHhjFB1VUTWdqj25QoMkMKzgjq+uhrw=="],
-
"@hono/vite-build": ["@hono/vite-build@1.7.0", "", { "peerDependencies": { "hono": "*" } }, "sha512-L73WBed5teC7DHTzXYkho83POYYluD2rTkbT76FJuqpfXPgTW/PsbIa8O0YcCETE3VUoh584fe6vuLAM5ctjww=="],
+
"@hono/vite-build": ["@hono/vite-build@1.8.0", "", { "peerDependencies": { "hono": "*" } }, "sha512-T/w0Tuv8VV6FgjNnw2aW6LXtRfc5tOhaO54tKCRv4Zqc1tP3w6JyqTFtzJFFDvmY0xTxHS+Pj+ZPLhzFsdiFzQ=="],
"@hono/vite-dev-server": ["@hono/vite-dev-server@0.23.0", "", { "dependencies": { "@hono/node-server": "^1.14.2", "minimatch": "^9.0.3" }, "peerDependencies": { "hono": "*", "miniflare": "*", "wrangler": "*" }, "optionalPeers": ["miniflare", "wrangler"] }, "sha512-tHV86xToed9Up0j/dubQW2PDP4aYNFDSfQrjcV6Ra7bqCGrxhtg/zZBmbgSco3aTxKOEPzDXKK+6seAAfsbIXw=="],
···
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="],
-
"@next/env": ["@next/env@16.0.2", "", {}, "sha512-V2e9ITU6Ts9kxtTBX60qtWlKV+AeBNlz/hgAt0gkGA8aPgX27cRLjp7OEUMzYq4cY0QzOkOQ4CI/8IJh6kW/iw=="],
+
"@next/env": ["@next/env@16.0.7", "", {}, "sha512-gpaNgUh5nftFKRkRQGnVi5dpcYSKGcZZkQffZ172OrG/XkrnS7UBTQ648YY+8ME92cC4IojpI2LqTC8sTDhAaw=="],
+
+
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.0.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-LlDtCYOEj/rfSnEn/Idi+j1QKHxY9BJFmxx7108A6D8K0SB+bNgfYQATPk/4LqOl4C0Wo3LACg2ie6s7xqMpJg=="],
+
+
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.0.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-rtZ7BhnVvO1ICf3QzfW9H3aPz7GhBrnSIMZyr4Qy6boXF0b5E3QLs+cvJmg3PsTCG2M1PBoC+DANUi4wCOKXpA=="],
+
+
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.0.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-mloD5WcPIeIeeZqAIP5c2kdaTa6StwP4/2EGy1mUw8HiexSHGK/jcM7lFuS3u3i2zn+xH9+wXJs6njO7VrAqww=="],
-
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-E6rxUdkZX5sZjLduXphiMuRJAmvsxWi5IivD0kRLLX5cjNLOs2PjlSyda+dtT3iqE6vxaRGV3oQMnQiJU8F+Ig=="],
+
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.0.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-+ksWNrZrthisXuo9gd1XnjHRowCbMtl/YgMpbRvFeDEqEBd523YHPWpBuDjomod88U8Xliw5DHhekBC3EOOd9g=="],
-
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-QNXdjXVFtb35vImDJtXqYlhq8A2mHLroqD8q4WCwO+IVnVoQshhcEVWJlP9UB/dOC6Wh782BbTHqGzKQwlCSkQ=="],
+
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.0.7", "", { "os": "linux", "cpu": "x64" }, "sha512-4WtJU5cRDxpEE44Ana2Xro1284hnyVpBb62lIpU5k85D8xXxatT+rXxBgPkc7C1XwkZMWpK5rXLXTh9PFipWsA=="],
-
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-dM9yEB35GZAW3r+w88iGEz7OkJjSYSd4pKyl4KwSXx8cLWMpWaX1WW42dCAKXCWWQhVUXUZAEx38yfpEZ1/IJg=="],
+
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.0.7", "", { "os": "linux", "cpu": "x64" }, "sha512-HYlhqIP6kBPXalW2dbMTSuB4+8fe+j9juyxwfMwCe9kQPPeiyFn7NMjNfoFOfJ2eXkeQsoUGXg+O2SE3m4Qg2w=="],
-
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-hiNysPK1VeK5MGNmuKLnj3Y4lkaffvAlXin404QpxYkNCBms/Bk0msZHey5lUNq8FV50PY6I9CgY+c/NK+xeLg=="],
+
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.0.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-EviG+43iOoBRZg9deGauXExjRphhuYmIOJ12b9sAPy0eQ6iwcPxfED2asb/s2/yiLYOdm37kPaiZu8uXSYPs0Q=="],
-
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-hAhhobw4tHOCzZ5sm5W/EsQPxS3NbZl6rqzmA0GTV9etE8sPHmsV6OopP12TeeoXA/NjXKD2mcz8hcVWLe4jkg=="],
+
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.0.7", "", { "os": "win32", "cpu": "x64" }, "sha512-gniPjy55zp5Eg0896qSrf3yB1dw4F/3s8VK1ephdsZZ129j2n6e1WqCbE2YgcKhW9hPB9TVZENugquWJD5x0ug=="],
-
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-s0LUsoeRky95aTS6IfYnJOn6F5kbs+gjiVUQK0JmsJ/ZCXaply20kDoJ8/zHwMz5cyOVg7GrQJdMvyO9FLD9Bw=="],
+
"@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
-
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-TMWE1h44d0WRyq0yQI/0W5A7nZUoiwE2Sdg43wt2Q1IoadU5Ky00G3cJ2mSnbetwL7+eFyM7BQgx+Fonpz6T8w=="],
+
"@types/bun": ["@types/bun@1.3.4", "", { "dependencies": { "bun-types": "1.3.4" } }, "sha512-EEPTKXHP+zKGPkhRLv+HI0UEX8/o+65hqARxLy8Ov5rIxMBPNTjeZww00CIihrIQGEQBYg+0roO5qOnS/7boGA=="],
-
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-+8SqzDhau/PNsWdcagnoz6ltOM9IcsqagdTFsEELNOty0+lNh5hwO5oUFForPOywTbM+d3tPLo5m20VdEBDf3Q=="],
+
"@types/node": ["@types/node@24.10.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-WOhQTZ4G8xZ1tjJTvKOpyEVSGgOTvJAfDK3FNFgELyaTpzhdgHVHeqW8V+UJvzF5BT+/B54T/1S2K6gd9c7bbA=="],
-
"@oven/bun-darwin-aarch64": ["@oven/bun-darwin-aarch64@1.3.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-licBDIbbLP5L5/S0+bwtJynso94XD3KyqSP48K59Sq7Mude6C7dR5ZujZm4Ut4BwZqUFfNOfYNMWBU5nlL7t1A=="],
+
"@types/sinonjs__fake-timers": ["@types/sinonjs__fake-timers@8.1.1", "", {}, "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g=="],
+
+
"@types/sizzle": ["@types/sizzle@2.3.10", "", {}, "sha512-TC0dmN0K8YcWEAEfiPi5gJP14eJe30TTGjkvek3iM/1NdHHsdCA/Td6GvNndMOo/iSnIsZ4HuuhrYPDAmbxzww=="],
+
+
"@types/tmp": ["@types/tmp@0.2.6", "", {}, "sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA=="],
-
"@oven/bun-darwin-x64": ["@oven/bun-darwin-x64@1.3.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-hn8lLzsYyyh6ULo2E8v2SqtrWOkdQKJwapeVy1rDw7juTTeHY3KDudGWf4mVYteC9riZU6HD88Fn3nGwyX0eIg=="],
+
"@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="],
-
"@oven/bun-darwin-x64-baseline": ["@oven/bun-darwin-x64-baseline@1.3.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-UHxdtbyxdtNJUNcXtIrjx3Lmq8ji3KywlXtIHV/0vn9A8W5mulqOcryqUWMFVH9JTIIzmNn6Q/qVmXHTME63Ww=="],
+
"aggregate-error": ["aggregate-error@3.1.0", "", { "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="],
-
"@oven/bun-linux-aarch64": ["@oven/bun-linux-aarch64@1.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-5uZzxzvHU/z+3cZwN/A0H8G+enQ+9FkeJVZkE2fwK2XhiJZFUGAuWajCpy7GepvOWlqV7VjPaKi2+Qmr4IX7nQ=="],
+
"ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="],
-
"@oven/bun-linux-aarch64-musl": ["@oven/bun-linux-aarch64-musl@1.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-OD9DYkjes7WXieBn4zQZGXWhRVZhIEWMDGCetZ3H4vxIuweZ++iul/CNX5jdpNXaJ17myb1ROMvmRbrqW44j3w=="],
+
"ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="],
-
"@oven/bun-linux-x64": ["@oven/bun-linux-x64@1.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-EoEuRP9bxAxVKuvi6tZ0ZENjueP4lvjz0mKsMzdG0kwg/2apGKiirH1l0RIcdmvfDGGuDmNiv/XBpkoXq1x8ug=="],
+
"ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
-
"@oven/bun-linux-x64-baseline": ["@oven/bun-linux-x64-baseline@1.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-m9Ov9YH8KjRLui87eNtQQFKVnjGsNk3xgbrR9c8d2FS3NfZSxmVjSeBvEsDjzNf1TXLDriHb/NYOlpiMf/QzDg=="],
+
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
-
"@oven/bun-linux-x64-musl": ["@oven/bun-linux-x64-musl@1.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-3TuOsRVoG8K+soQWRo+Cp5ACpRs6rTFSu5tAqc/6WrqwbNWmqjov/eWJPTgz3gPXnC7uNKVG7RxxAmV8r2EYTQ=="],
+
"arch": ["arch@2.2.0", "", {}, "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ=="],
-
"@oven/bun-linux-x64-musl-baseline": ["@oven/bun-linux-x64-musl-baseline@1.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-q8Hto8hcpofPJjvuvjuwyYvhOaAzPw1F5vRUUeOJDmDwZ4lZhANFM0rUwchMzfWUJCD6jg8/EVQ8MiixnZWU0A=="],
+
"asn1": ["asn1@0.2.6", "", { "dependencies": { "safer-buffer": "~2.1.0" } }, "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ=="],
-
"@oven/bun-windows-x64": ["@oven/bun-windows-x64@1.3.2", "", { "os": "win32", "cpu": "x64" }, "sha512-nZJUa5NprPYQ4Ii4cMwtP9PzlJJTp1XhxJ+A9eSn1Jfr6YygVWyN2KLjenyI93IcuBouBAaepDAVZZjH2lFBhg=="],
+
"assert-plus": ["assert-plus@1.0.0", "", {}, "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="],
-
"@oven/bun-windows-x64-baseline": ["@oven/bun-windows-x64-baseline@1.3.2", "", { "os": "win32", "cpu": "x64" }, "sha512-s00T99MjB+xLOWq+t+wVaVBrry+oBOZNiTJijt+bmkp/MJptYS3FGvs7a+nkjLNzoNDoWQcXgKew6AaHES37Bg=="],
+
"astral-regex": ["astral-regex@2.0.0", "", {}, "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="],
-
"@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
+
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
-
"@types/bun": ["@types/bun@1.3.2", "", { "dependencies": { "bun-types": "1.3.2" } }, "sha512-t15P7k5UIgHKkxwnMNkJbWlh/617rkDGEdSsDbu+qNHTaz9SKf7aC8fiIlUdD5RPpH6GEkP0cK7WlvmrEBRtWg=="],
+
"at-least-node": ["at-least-node@1.0.0", "", {}, "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="],
-
"@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],
+
"aws-sign2": ["aws-sign2@0.7.0", "", {}, "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA=="],
-
"@types/react": ["@types/react@19.2.4", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-tBFxBp9Nfyy5rsmefN+WXc1JeW/j2BpBHFdLZbEVfs9wn3E3NRFxwV0pJg8M1qQAexFpvz73hJXFofV0ZAu92A=="],
+
"aws4": ["aws4@1.13.2", "", {}, "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw=="],
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
+
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
+
+
"baseline-browser-mapping": ["baseline-browser-mapping@2.9.5", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-D5vIoztZOq1XM54LUdttJVc96ggEsIfju2JBvht06pSzpckp3C7HReun67Bghzrtdsq9XdMGbSSB3v3GhMNmAA=="],
+
+
"bcrypt-pbkdf": ["bcrypt-pbkdf@1.0.2", "", { "dependencies": { "tweetnacl": "^0.14.3" } }, "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w=="],
+
+
"blob-util": ["blob-util@2.0.2", "", {}, "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ=="],
+
+
"bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="],
+
"boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
"brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
-
"bun": ["bun@1.3.2", "", { "optionalDependencies": { "@oven/bun-darwin-aarch64": "1.3.2", "@oven/bun-darwin-x64": "1.3.2", "@oven/bun-darwin-x64-baseline": "1.3.2", "@oven/bun-linux-aarch64": "1.3.2", "@oven/bun-linux-aarch64-musl": "1.3.2", "@oven/bun-linux-x64": "1.3.2", "@oven/bun-linux-x64-baseline": "1.3.2", "@oven/bun-linux-x64-musl": "1.3.2", "@oven/bun-linux-x64-musl-baseline": "1.3.2", "@oven/bun-windows-x64": "1.3.2", "@oven/bun-windows-x64-baseline": "1.3.2" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ], "bin": { "bun": "bin/bun.exe", "bunx": "bin/bunx.exe" } }, "sha512-x75mPJiEfhO1j4Tfc65+PtW6ZyrAB6yTZInydnjDZXF9u9PRAnr6OK3v0Q9dpDl0dxRHkXlYvJ8tteJxc8t4Sw=="],
+
"buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
+
+
"buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="],
+
+
"bun-types": ["bun-types@1.3.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-5ua817+BZPZOlNaRgGBpZJOSAQ9RQ17pkwPD0yR7CfJg+r8DgIILByFifDTa+IPDDxzf5VNhtNlcKqFzDgJvlQ=="],
+
+
"cachedir": ["cachedir@2.4.0", "", {}, "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ=="],
+
+
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
+
+
"call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
-
"bun-types": ["bun-types@1.3.2", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-i/Gln4tbzKNuxP70OWhJRZz1MRfvqExowP7U6JKoI8cntFrtxg7RJK3jvz7wQW54UuvNC8tbKHHri5fy74FVqg=="],
+
"caniuse-lite": ["caniuse-lite@1.0.30001760", "", {}, "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw=="],
-
"caniuse-lite": ["caniuse-lite@1.0.30001754", "", {}, "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg=="],
+
"caseless": ["caseless@0.12.0", "", {}, "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="],
+
+
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"cheerio": ["cheerio@1.1.2", "", { "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "encoding-sniffer": "^0.2.1", "htmlparser2": "^10.0.0", "parse5": "^7.3.0", "parse5-htmlparser2-tree-adapter": "^7.1.0", "parse5-parser-stream": "^7.1.2", "undici": "^7.12.0", "whatwg-mimetype": "^4.0.0" } }, "sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg=="],
"cheerio-select": ["cheerio-select@2.1.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-select": "^5.1.0", "css-what": "^6.1.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1" } }, "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g=="],
+
"ci-info": ["ci-info@4.3.1", "", {}, "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA=="],
+
+
"clean-stack": ["clean-stack@2.2.0", "", {}, "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A=="],
+
+
"cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],
+
+
"cli-table3": ["cli-table3@0.6.1", "", { "dependencies": { "string-width": "^4.2.0" }, "optionalDependencies": { "colors": "1.4.0" } }, "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA=="],
+
+
"cli-truncate": ["cli-truncate@2.1.0", "", { "dependencies": { "slice-ansi": "^3.0.0", "string-width": "^4.2.0" } }, "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg=="],
+
"client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
+
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
+
+
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
+
+
"colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="],
+
+
"colors": ["colors@1.4.0", "", {}, "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="],
+
+
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
+
+
"commander": ["commander@6.2.1", "", {}, "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="],
+
+
"common-tags": ["common-tags@1.8.2", "", {}, "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA=="],
+
+
"core-util-is": ["core-util-is@1.0.2", "", {}, "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="],
+
+
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
+
"css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="],
"css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="],
-
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
+
"cypress": ["cypress@15.7.1", "", { "dependencies": { "@cypress/request": "^3.0.9", "@cypress/xvfb": "^1.2.4", "@types/sinonjs__fake-timers": "8.1.1", "@types/sizzle": "^2.3.2", "@types/tmp": "^0.2.3", "arch": "^2.2.0", "blob-util": "^2.0.2", "bluebird": "^3.7.2", "buffer": "^5.7.1", "cachedir": "^2.3.0", "chalk": "^4.1.0", "ci-info": "^4.1.0", "cli-cursor": "^3.1.0", "cli-table3": "0.6.1", "commander": "^6.2.1", "common-tags": "^1.8.0", "dayjs": "^1.10.4", "debug": "^4.3.4", "enquirer": "^2.3.6", "eventemitter2": "6.4.7", "execa": "4.1.0", "executable": "^4.1.1", "extract-zip": "2.0.1", "figures": "^3.2.0", "fs-extra": "^9.1.0", "hasha": "5.2.2", "is-installed-globally": "~0.4.0", "listr2": "^3.8.3", "lodash": "^4.17.21", "log-symbols": "^4.0.0", "minimist": "^1.2.8", "ospath": "^1.2.2", "pretty-bytes": "^5.6.0", "process": "^0.11.10", "proxy-from-env": "1.0.0", "request-progress": "^3.0.0", "supports-color": "^8.1.1", "systeminformation": "5.27.7", "tmp": "~0.2.4", "tree-kill": "1.2.2", "untildify": "^4.0.0", "yauzl": "^2.10.0" }, "bin": { "cypress": "bin/cypress" } }, "sha512-U3sYnJ+Cnpgr6IPycxsznTg//mGVXfPGeGV+om7VQCyp5XyVkhG4oPr3X3hTq1+OB0Om0O5DxusYmt7cbvwqMQ=="],
+
+
"dashdash": ["dashdash@1.14.1", "", { "dependencies": { "assert-plus": "^1.0.0" } }, "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g=="],
+
+
"dayjs": ["dayjs@1.11.19", "", {}, "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="],
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
+
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
+
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
"dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="],
···
"domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
+
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
+
+
"ecc-jsbn": ["ecc-jsbn@0.1.2", "", { "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw=="],
+
+
"emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
+
"encoding-sniffer": ["encoding-sniffer@0.2.1", "", { "dependencies": { "iconv-lite": "^0.6.3", "whatwg-encoding": "^3.1.1" } }, "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw=="],
+
+
"end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
+
+
"enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="],
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
+
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
+
+
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
+
+
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
+
+
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
+
+
"escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
+
+
"eventemitter2": ["eventemitter2@6.4.7", "", {}, "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg=="],
+
+
"execa": ["execa@4.1.0", "", { "dependencies": { "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", "human-signals": "^1.1.1", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.0", "onetime": "^5.1.0", "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" } }, "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA=="],
+
+
"executable": ["executable@4.1.1", "", { "dependencies": { "pify": "^2.2.0" } }, "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg=="],
+
+
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
+
+
"extract-zip": ["extract-zip@2.0.1", "", { "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", "yauzl": "^2.10.0" }, "optionalDependencies": { "@types/yauzl": "^2.9.1" }, "bin": { "extract-zip": "cli.js" } }, "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg=="],
+
+
"extsprintf": ["extsprintf@1.3.0", "", {}, "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g=="],
+
"fauxdom": ["fauxdom@1.2.2", "", {}, "sha512-Xoj9VPhIx9p9wU1CncWaKqgm5e+lnTqi5nYsQIfALEUKu++99Pj/BMkggH6mYjWaBeVWBxeV8xZTJauTXGiUDw=="],
+
"fd-slicer": ["fd-slicer@1.1.0", "", { "dependencies": { "pend": "~1.2.0" } }, "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g=="],
+
+
"figures": ["figures@3.2.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5" } }, "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg=="],
+
+
"forever-agent": ["forever-agent@0.6.1", "", {}, "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw=="],
+
+
"form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],
+
+
"fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="],
+
+
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
+
+
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
+
+
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
+
+
"get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="],
+
+
"getpass": ["getpass@0.1.7", "", { "dependencies": { "assert-plus": "^1.0.0" } }, "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng=="],
+
+
"global-dirs": ["global-dirs@3.0.1", "", { "dependencies": { "ini": "2.0.0" } }, "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA=="],
+
"globrex": ["globrex@0.1.2", "", {}, "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="],
-
"hono": ["hono@4.10.5", "", {}, "sha512-h/MXuTkoAK8NG1EfDp0jI1YLf6yGdDnfkebRO2pwEh5+hE3RAJFXkCsnD0vamSiARK4ZrB6MY+o3E/hCnOyHrQ=="],
+
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
+
+
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
+
+
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
+
+
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
+
+
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
+
+
"hasha": ["hasha@5.2.2", "", { "dependencies": { "is-stream": "^2.0.0", "type-fest": "^0.8.0" } }, "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ=="],
+
+
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
+
+
"hono": ["hono@4.10.8", "", {}, "sha512-DDT0A0r6wzhe8zCGoYOmMeuGu3dyTAE40HHjwUsWFTEy5WxK1x2WDSsBPlEXgPbRIFY6miDualuUDbasPogIww=="],
"htmlparser2": ["htmlparser2@10.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.2.1", "entities": "^6.0.0" } }, "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g=="],
+
"http-signature": ["http-signature@1.4.0", "", { "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^2.0.2", "sshpk": "^1.18.0" } }, "sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg=="],
+
+
"human-signals": ["human-signals@1.1.1", "", {}, "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw=="],
+
"iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
+
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
+
+
"indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="],
+
+
"ini": ["ini@2.0.0", "", {}, "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA=="],
+
+
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
+
+
"is-installed-globally": ["is-installed-globally@0.4.0", "", { "dependencies": { "global-dirs": "^3.0.0", "is-path-inside": "^3.0.2" } }, "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ=="],
+
+
"is-path-inside": ["is-path-inside@3.0.3", "", {}, "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="],
+
+
"is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
+
+
"is-typedarray": ["is-typedarray@1.0.0", "", {}, "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="],
+
+
"is-unicode-supported": ["is-unicode-supported@0.1.0", "", {}, "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="],
+
+
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
+
+
"isstream": ["isstream@0.1.2", "", {}, "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="],
+
+
"jsbn": ["jsbn@0.1.1", "", {}, "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="],
+
+
"json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="],
+
+
"json-stringify-safe": ["json-stringify-safe@5.0.1", "", {}, "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="],
+
+
"jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="],
+
+
"jsprim": ["jsprim@2.0.2", "", { "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.4.0", "verror": "1.10.0" } }, "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ=="],
+
+
"listr2": ["listr2@3.14.0", "", { "dependencies": { "cli-truncate": "^2.1.0", "colorette": "^2.0.16", "log-update": "^4.0.0", "p-map": "^4.0.0", "rfdc": "^1.3.0", "rxjs": "^7.5.1", "through": "^2.3.8", "wrap-ansi": "^7.0.0" }, "peerDependencies": { "enquirer": ">= 2.3.0 < 3" }, "optionalPeers": ["enquirer"] }, "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g=="],
+
+
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
+
+
"lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="],
+
+
"log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="],
+
+
"log-update": ["log-update@4.0.0", "", { "dependencies": { "ansi-escapes": "^4.3.0", "cli-cursor": "^3.1.0", "slice-ansi": "^4.0.0", "wrap-ansi": "^6.2.0" } }, "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg=="],
+
+
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
+
+
"merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
+
+
"mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
+
+
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
+
+
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
+
"minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
+
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
+
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
-
"next": ["next@16.0.2", "", { "dependencies": { "@next/env": "16.0.2", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.0.2", "@next/swc-darwin-x64": "16.0.2", "@next/swc-linux-arm64-gnu": "16.0.2", "@next/swc-linux-arm64-musl": "16.0.2", "@next/swc-linux-x64-gnu": "16.0.2", "@next/swc-linux-x64-musl": "16.0.2", "@next/swc-win32-arm64-msvc": "16.0.2", "@next/swc-win32-x64-msvc": "16.0.2", "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-zL8+UBf+xUIm8zF0vYGJYJMYDqwaBrRRe7S0Kob6zo9Kf+BdqFLEECMI+B6cNIcoQ+el9XM2fvUExwhdDnXjtw=="],
+
"next": ["next@16.0.7", "", { "dependencies": { "@next/env": "16.0.7", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.0.7", "@next/swc-darwin-x64": "16.0.7", "@next/swc-linux-arm64-gnu": "16.0.7", "@next/swc-linux-arm64-musl": "16.0.7", "@next/swc-linux-x64-gnu": "16.0.7", "@next/swc-linux-x64-musl": "16.0.7", "@next/swc-win32-arm64-msvc": "16.0.7", "@next/swc-win32-x64-msvc": "16.0.7", "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-3mBRJyPxT4LOxAJI6IsXeFtKfiJUbjCLgvXO02fV8Wy/lIhPvP94Fe7dGhUgHXcQy4sSuYwQNcOLhIfOm0rL0A=="],
+
+
"npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="],
"nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
+
"object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
+
+
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
+
+
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
+
+
"ospath": ["ospath@1.2.2", "", {}, "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA=="],
+
+
"p-map": ["p-map@4.0.0", "", { "dependencies": { "aggregate-error": "^3.0.0" } }, "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ=="],
+
"parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
"parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@7.1.0", "", { "dependencies": { "domhandler": "^5.0.3", "parse5": "^7.0.0" } }, "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g=="],
"parse5-parser-stream": ["parse5-parser-stream@7.1.2", "", { "dependencies": { "parse5": "^7.0.0" } }, "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow=="],
+
+
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
+
+
"pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="],
+
+
"performance-now": ["performance-now@2.1.0", "", {}, "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="],
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
+
"pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="],
+
"postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
+
+
"pretty-bytes": ["pretty-bytes@5.6.0", "", {}, "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg=="],
+
+
"process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="],
+
+
"proxy-from-env": ["proxy-from-env@1.0.0", "", {}, "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A=="],
+
+
"pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
+
+
"qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="],
"react": ["react@19.2.0", "", {}, "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="],
"react-dom": ["react-dom@19.2.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ=="],
+
"request-progress": ["request-progress@3.0.0", "", { "dependencies": { "throttleit": "^1.0.0" } }, "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg=="],
+
+
"restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="],
+
+
"rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
+
+
"rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="],
+
+
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
+
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
···
"sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="],
+
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
+
+
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
+
+
"side-channel": ["side-channel@1.1.0", "", { "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" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
+
+
"side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="],
+
+
"side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
+
+
"side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "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" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
+
+
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
+
+
"slice-ansi": ["slice-ansi@3.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ=="],
+
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
+
"sshpk": ["sshpk@1.18.0", "", { "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "bcrypt-pbkdf": "^1.0.0", "dashdash": "^1.12.0", "ecc-jsbn": "~0.1.1", "getpass": "^0.1.1", "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" }, "bin": { "sshpk-conv": "bin/sshpk-conv", "sshpk-sign": "bin/sshpk-sign", "sshpk-verify": "bin/sshpk-verify" } }, "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ=="],
+
+
"string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
+
+
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
+
+
"strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
+
"styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="],
+
"supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
+
+
"systeminformation": ["systeminformation@5.27.7", "", { "os": "!aix", "bin": { "systeminformation": "lib/cli.js" } }, "sha512-saaqOoVEEFaux4v0K8Q7caiauRwjXC4XbD2eH60dxHXbpKxQ8kH9Rf7Jh+nryKpOUSEFxtCdBlSUx0/lO6rwRg=="],
+
+
"throttleit": ["throttleit@1.0.1", "", {}, "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ=="],
+
+
"through": ["through@2.3.8", "", {}, "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="],
+
+
"tldts": ["tldts@6.1.86", "", { "dependencies": { "tldts-core": "^6.1.86" }, "bin": { "tldts": "bin/cli.js" } }, "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ=="],
+
+
"tldts-core": ["tldts-core@6.1.86", "", {}, "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA=="],
+
+
"tmp": ["tmp@0.2.5", "", {}, "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="],
+
+
"tough-cookie": ["tough-cookie@5.1.2", "", { "dependencies": { "tldts": "^6.1.32" } }, "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A=="],
+
+
"tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="],
+
"tsconfck": ["tsconfck@3.1.6", "", { "peerDependencies": { "typescript": "^5.0.0" }, "optionalPeers": ["typescript"], "bin": { "tsconfck": "bin/tsconfck.js" } }, "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w=="],
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+
"tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="],
+
+
"tweetnacl": ["tweetnacl@0.14.5", "", {}, "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="],
+
+
"type-fest": ["type-fest@0.8.1", "", {}, "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="],
+
"undici": ["undici@7.16.0", "", {}, "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g=="],
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
+
"universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
+
+
"untildify": ["untildify@4.0.0", "", {}, "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw=="],
+
+
"uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="],
+
+
"verror": ["verror@1.10.0", "", { "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw=="],
+
"vite-tsconfig-paths": ["vite-tsconfig-paths@5.1.4", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" }, "optionalPeers": ["vite"] }, "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w=="],
"whatwg-encoding": ["whatwg-encoding@3.1.1", "", { "dependencies": { "iconv-lite": "0.6.3" } }, "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ=="],
"whatwg-mimetype": ["whatwg-mimetype@4.0.0", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="],
+
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
+
+
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
+
+
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
+
+
"yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="],
+
+
"@cypress/xvfb/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
+
+
"ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
+
+
"chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
+
"htmlparser2/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
+
+
"log-update/slice-ansi": ["slice-ansi@4.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ=="],
+
+
"log-update/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
"parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
}
+56
cypress/component/generator.cy.js
···
+
import baseFonts from '../../src/lib/baseFonts'
+
import titleFonts from '../../src/lib/titleFonts'
+
import themes from '../../src/lib/themes'
+
import ao3CanonicalUrls from "../../src/lib/ao3Canonical"
+
import Page from "../../src/app/generator/page"
+
import styles from "../../src/app/generator/page.module.css"
+
+
describe('<Page />', () => {
+
it('displays an alphabetized list of base font options using the list in the baseFont lib', () => {
+
cy.mount('<Page />')
+
cy.get('select#baseFont > option').should('have.length', Object.keys(baseFonts).length)
+
const sortedFontKeys = Object.keys(baseFonts).sort()
+
const sortedFontValues = Object.values(baseFonts).sort((a, b) => {
+
if (a.displayName > b.displayName) {
+
return 1;
+
}
+
return -1;
+
})
+
cy.get('select#baseFont > option').each(($opt, i) => {
+
expect($opt).to.contain(sortedFontValues[i].displayName)
+
expect($opt).to.have.value(sortedFontKeys[i])
+
})
+
})
+
+
it('displays an alphabetized list of title font options using the list in the titleFont lib', () => {
+
cy.mount('<Page />')
+
cy.get('select#titleFont > option').should('have.length', Object.keys(titleFonts).length)
+
const sortedTitleFontKeys = Object.keys(titleFonts).sort()
+
const sortedTitleFontValues = Object.values(titleFonts).sort((a, b) => {
+
if (a.displayName > b.displayName) {
+
return 1
+
}
+
return -1
+
})
+
cy.get('select#titleFont > option').each(($opt, i) => {
+
expect($opt).to.contain(sortedTitleFontValues[i].displayName)
+
expect($opt).to.have.value(sortedTitleFontKeys[i])
+
})
+
})
+
+
it('displays an alphabetized list of themes using the list in the themes lib', () => {
+
cy.mount('<Page />')
+
cy.get('select#theme > option').should('have.length', Object.keys(themes).length)
+
const sortedThemeKeys = Object.keys(themes).sort()
+
const sortedThemeValues = Object.values(themes).sort((a, b) => {
+
if (a.name > b.name) {
+
return 1
+
}
+
return -1
+
})
+
cy.get('select#theme > option').each(($opt, i) => {
+
expect($opt).to.contain(sortedThemeValues[i].name)
+
expect($opt).to.have.value(sortedThemeKeys[i])
+
})
+
})
+
})
cypress/e2e/app.cy.js

This is a binary file and will not be displayed.

+16
cypress/e2e/navigation.cy.js
···
+
describe('Navigation', () => {
+
it('should navigate to the generator page', () => {
+
// Start from the index page
+
cy.visit('http://localhost:3001')
+
+
// Find a link with an href attribute containing "generator" and click it
+
cy.get('a[href*="/generator"]').click()
+
+
// The new url should include "/generator"
+
cy.url().should('include', '/generator')
+
+
// The new page should contain an form with the ID "geerator"
+
cy.get('form').should('have.id', 'generator')
+
+
})
+
})
+14
cypress/support/component-index.html
···
+
<html lang="en">
+
<head>
+
</head>
+
<body>
+
<div id="page">
+
<h1>
+
<a href="/">fixAO3</a>
+
<a href="/generator" id="generator-link">โœจ generator โœจ</a>
+
</h1>
+
</div>
+
<script data-goatcounter="https://fixao3.goatcounter.com/count"
+
async src="//gc.zgo.at/count.js"></script>
+
</body>
+
</html>
+3
cypress/support/component.js
···
+
import '@fontsource-variable/bricolage-grotesque'
+
import '@fontsource/stack-sans-notch'
+
import "../../src/app/globals.css"
cypress/support/e2e.cy.js

This is a binary file and will not be displayed.

+15
cypress.config.js
···
+
import { defineConfig } from 'cypress'
+
+
export default defineConfig({
+
e2e: {
+
setupNodeEvents(on, config) {},
+
supportFile: false
+
},
+
component: {
+
supportFile: false,
+
devServer: {
+
framework: 'next',
+
bundler: 'webpack',
+
},
+
},
+
})
-3
next.config.mjs
···
/** @type {import('next').NextConfig} */
const nextConfig = {
/* config options here */
-
turbopack: {
-
root: './'
-
}
};
export default nextConfig;
+8 -5
package.json
···
"build": "--bun next build",
"start": "--bun next start",
"lint": "--bun biome check",
-
"format": "--bun biome format --write"
+
"format": "--bun biome format --write",
+
"cypress:open": "cypress open"
},
"dependencies": {
"@fontsource-variable/bricolage-grotesque": "^5.2.10",
"@fontsource/stack-sans-notch": "^5.2.1",
"@fujocoded/ao3.js": "^0.22.1",
-
"@hono/vite-build": "^1.7.0",
+
"@hono/vite-build": "^1.8.0",
"@hono/vite-dev-server": "^0.23.0",
"fauxdom": "^1.2.2",
-
"hono": "^4.10.4",
-
"next": "16.0.2",
+
"hono": "^4.10.8",
+
"next": "16.0.7",
"react": "19.2.0",
"react-dom": "19.2.0"
},
"devDependencies": {
"@biomejs/biome": "2.2.0",
-
"@types/bun": "latest"
+
"@types/bun": "latest",
+
"baseline-browser-mapping": "^2.9.5",
+
"cypress": "^15.7.1"
}
}
src/app/api/series/[seriesId]/preview/route.js

This is a binary file and will not be displayed.

+12 -1
src/app/api/series/[seriesId]/route.js
···
import { getSeries } from "@fujocoded/ao3.js"
+
import { setArchiveBaseUrl, resetArchiveBaseUrl } from "@fujocoded/ao3.js/urls"
-
export async function GET(_req, ctx) {
+
export const dynamic = 'force-static'
+
+
export async function GET(req, ctx) {
const { seriesId } = await ctx.params
+
const { archive } = await req.nextUrl.searchParams
+
console.log(seriesId)
+
console.log(archive)
+
const domain = await req.nextUrl.hostname
+
const subdomain = domain.split(".").length > 2 ? domain.split(".")[0] : null
+
if (subdomain) setArchiveBaseUrl('https://'+subdomain)
+
if (archive) setArchiveBaseUrl(archive)
const series = await getSeries({seriesId: seriesId})
+
if (archive || subdomain) resetArchiveBaseUrl()
return Response.json(series)
}
src/app/api/works/[workId]/chapters/[chapterId]/preview/route.js

This is a binary file and will not be displayed.

+12 -1
src/app/api/works/[workId]/chapters/[chapterId]/route.js
···
import { getWork } from "@fujocoded/ao3.js"
+
import { setArchiveBaseUrl, resetArchiveBaseUrl } from "@fujocoded/ao3.js/urls"
+
import siteMap from "@/lib/siteMap.js"
+
+
export const dynamic = 'force-static'
-
export async function GET(_req, ctx) {
+
export async function GET(req, ctx) {
const { workId, chapterId } = await ctx.params
+
const params = await req.nextUrl.searchParams
+
const domain = await req.nextUrl.hostname
+
const subdomain = domain.split(".").length > 2 ? domain.split(".")[0] : null
+
const archive = params ? params.get('archive') : null
+
if (subdomain) setArchiveBaseUrl('https://'+siteMap[subdomain])
+
if (archive) setArchiveBaseUrl(archive)
const work = await getWork({workId: workId, chapterId: chapterId})
+
if (archive || subdomain) resetArchiveBaseUrl()
return Response.json(work)
}
+9 -1
src/app/api/works/[workId]/route.js
···
import { getWork } from "@fujocoded/ao3.js"
+
import { setArchiveBaseUrl, getArchiveBaseUrl, resetArchiveBaseUrl } from "@fujocoded/ao3.js/urls"
-
export async function GET(_req, ctx) {
+
export async function GET(req, ctx) {
const { workId } = await ctx.params
+
const params = await req.nextUrl.searchParams
+
const domain = await req.nextUrl.hostname
+
const subdomain = (domain.split(".").length > 2) ? domain.split(".")[0] : null
+
const archive = params ? params.get('archive') : null
+
if (subdomain) setArchiveBaseUrl('https://'+siteMap[subdomain])
+
if (archive) setArchiveBaseUrl(archive)
const work = await getWork({workId: workId})
+
if (archive || subdomain) resetArchiveBaseUrl()
return Response.json(work)
}
+48 -35
src/app/generator/page.js
···
"use client"
import { useEffect, useState } from "react"
+
import { setArchiveBaseUrl, resetArchiveBaseUrl } from "@fujocoded/ao3.js/urls"
import themes from "@/lib/themes.js"
import baseFonts from "@/lib/baseFonts.js"
import titleFonts from "@/lib/titleFonts.js"
-
import styles from "./page.module.css"
+
import defaults from "@/lib/ogdefaults.js"
+
import ao3CanonicalUrls from "@/lib/ao3Canonical.js"
export default function Generator() {
const [url, setUrl] = useState('')
const [workData, setWorkData] = useState(null)
const [addr, setAddr] = useState('')
const [imgData, setImgData] = useState(null)
-
const [props, setProps] = useState({
-
theme: 'ao3',
-
baseFont: 'bricolagegrotesque',
-
titleFont: 'stacksansnotch',
-
category: true,
-
rating: true,
-
warnings: false,
-
charTags: false,
-
relTags: false,
-
freeTags: false,
-
summary: true,
-
wordcount: true,
-
chapters: true,
-
postedAt: true,
-
updatedAt: false,
-
summaryType: 'basic',
-
customSummary: ''
-
})
+
const [props, setProps] = useState(defaults)
+
const [domain, setDomain] = useState('')
const updateProp = (name, value) => {
const newProps = props
···
}
const updateData = async () => {
+
if (url === '') return
const workMatch = /\/works\/(?<workId>[0-9]+)(?:\/chapters\/(?<chapterId>[0-9]+))?$/
const seriesMatch = /\/series\/(?<seriesId>[0-9]+)$/
+
const baseurl = /(?<domain>https:\/\/[a-z0-9\-\.]+)\//
+
const domainMatch = url.match(baseurl)
+
if (!domainMatch) return
+
setDomain(domainMatch.groups.domain)
+
const domainParam = domain && !ao3CanonicalUrls.includes(domain) ? `?archive=${domain}` : ''
if (workMatch.test(url)) {
const match = url.match(workMatch)
-
const resp = match.groups.chapterId ? await fetch(`/api/works/${match.groups.workId}/chapters/${match.groups.chapterId}`) : await fetch(`/api/works/${match.groups.workId}`)
+
const resp = match.groups.chapterId ? await fetch(`/api/works/${match.groups.workId}/chapters/${match.groups.chapterId}${domainParam}`) : await fetch(`/api/works/${match.groups.workId}${domainParam}`)
+
if (!resp) return
const data = await resp.json()
setAddr(match.groups.chapterId ? `works/${match.groups.workId}/chapters/${match.groups.chapterId}` : `works/${match.groups.workId}`)
setWorkData(data)
} else if (seriesMatch.test(url)) {
const match = url.match(seriesMatch)
-
const resp = await fetch(`/api/series/${match.groups.seriesId}`)
+
const resp = await fetch(`/api/series/${match.groups.seriesId}${domainParam}`)
+
if (!resp) return
const data = await resp.json()
setAddr(`series/${match.groups.seriesId}`)
setWorkData(data)
···
useEffect(() => {
const fn = async () => {
if (!addr) return;
+
if (workData.locked) {
+
const image = await fetch('/locked')
+
if (image.status !== 200) return;
+
const imageBlob = await image.blob()
+
const reader = new FileReader()
+
reader.onloadend = () => {
+
setImgData(reader.result)
+
}
+
return
+
}
const params = new URLSearchParams(props)
-
const image = await fetch(`/${addr}/preview?${params.toString()}`)
+
const image = await fetch(`/${addr}/preview?${params.toString()}&archive=${domain}`)
if (image.status !== 200) return;
const imageBlob = await image.blob()
const reader = new FileReader()
···
<li><label><input type="checkbox" name="features[]" value="updatedAt" defaultChecked={props.updatedAt} onChange={e => updateProp(e.target.value, e.target.checked)} /> Updated Date</label></li>
</ul>
</div>
-
<div className="input-field">
-
<label htmlFor="summaryOptions">Summary Type</label>
-
<ul>
-
<li><label><input type="radio" name="summaryType" value="basic" defaultChecked={props.summaryType === 'basic'} onChange={e => updateProp(e.target.name, e.target.value)} /> Story Summary</label></li>
-
<li><label><input type="radio" name="summaryType" defaultChecked={props.summaryType === 'chapter'} value="chapter" onChange={e => updateProp(e.target.name, e.target.value)} /> Chapter Summary (if available)</label></li>
-
<li><label><input type="radio" name="summaryType" defaultChecked={props.summaryType === 'custom'} value="custom" onChange={e => updateProp(e.target.name, e.target.value)} /> Custom Summary</label></li>
-
</ul>
-
{props.summaryType === 'custom' && (
-
<div className="input-field">
-
<label htmlFor="customSummary">Custom Summary</label>
-
<textarea name="customSummary" id="customSummary" onChange={e => updateProp(e.target.name, e.target.value)}></textarea>
-
</div>
-
)}
+
<div className="col">
+
<div className="input-field">
+
<label htmlFor="displayOptions">Display Options</label>
+
<ul>
+
<li><label><input type="checkbox" name="uppercaseTitle" value="uppercaseTitle" defaultChecked={props.uppercaseTitle} onChange={e => updateProp(e.target.value, e.target.checked)} /> Uppercase Title?</label></li>
+
<li><label><input type="checkbox" name="uppercaseChapterName" value="uppercaseChapterName" defaultChecked={props.uppercaseChapterName} onChange={e => updateProp(e.target.value, e.target.checked)} /> Uppercase Chapter Name?</label></li>
+
</ul>
+
</div>
+
<div className="input-field">
+
<label htmlFor="summaryOptions">Summary Type</label>
+
<ul>
+
<li><label><input type="radio" name="summaryType" value="basic" defaultChecked={props.summaryType === 'basic'} onChange={e => updateProp(e.target.name, e.target.value)} /> Story Summary</label></li>
+
<li><label><input type="radio" name="summaryType" defaultChecked={props.summaryType === 'chapter'} value="chapter" onChange={e => updateProp(e.target.name, e.target.value)} /> Chapter Summary (if available)</label></li>
+
<li><label><input type="radio" name="summaryType" defaultChecked={props.summaryType === 'custom'} value="custom" onChange={e => updateProp(e.target.name, e.target.value)} /> Custom Summary</label></li>
+
</ul>
+
{props.summaryType === 'custom' && (
+
<div className="input-field">
+
<label htmlFor="customSummary">Custom Summary</label>
+
<textarea name="customSummary" id="customSummary" onBlur={e => updateProp(e.target.name, e.target.value)}></textarea>
+
</div>
+
)}
+
</div>
</div>
</div>
</details>
+13
src/app/locked/route.js
···
+
import OGImageLocked from "@/lib/ogimagelocked.js"
+
+
export const size = {
+
width: 1600,
+
height: 900,
+
}
+
+
export const contentType = 'image/png'
+
+
export async function GET(req, _ctx) {
+
const props = await req.nextUrl.searchParams
+
return OGImageLocked({theme: props.has('theme') ? props.get('theme') : process.env.DEFAULT_THEME})
+
}
+4 -22
src/app/series/[seriesId]/opengraph-image.jsx
···
import { getSeries } from "@fujocoded/ao3.js"
import sanitizeData from "@/lib/sanitizeData.js"
import OGImage from "@/lib/ogimage.js"
+
import OGImageLocked from "@/lib/ogimagelocked.js"
import baseFonts from "@/lib/baseFonts.js"
import titleFonts from "@/lib/titleFonts.js"
+
import defaults from "@/lib/ogdefaults.js"
export const size = {
width: 1600,
height: 900,
}
export const alt = 'fixAO3'
-
export const contentType = 'image/webp'
-
const defaults = new URLSearchParams({
-
theme: 'ao3',
-
baseFont: 'bricolagegrotesque',
-
titleFont: 'stacksansnotch',
-
category: true,
-
rating: true,
-
warnings: false,
-
charTags: false,
-
relTags: false,
-
freeTags: false,
-
summary: true,
-
wordcount: true,
-
chapters: true,
-
postedAt: true,
-
updatedAt: false,
-
summaryType: 'basic',
-
customSummary: ''
-
})
-
export default async function Image({params, searchParams}) {
const { seriesId } = await params
const addr = `series/${seriesId}`
const data = await getSeries({seriesId: seriesId})
-
const imageParams = await sanitizeData({type: 'series', data: data, props: defaults})
+
if (data.locked) return OGImageLocked({theme: theme})
+
const imageParams = await sanitizeData({type: 'series', data: data, props: new URLSearchParams(defaults)})
const theme = imageParams.theme
-
console.log(theme)
const baseFont = baseFonts[imageParams.baseFont].displayName
const titleFont = titleFonts[imageParams.titleFont].displayName
const opts = imageParams.opts
+7 -4
src/app/series/[seriesId]/page.js
···
import { getSeries } from "@fujocoded/ao3.js"
+
import DOM from "fauxdom"
export async function generateMetadata({ params, _searchParams }, _parent) {
// read route params
···
const fandoms = series.works.map(w => w.fandoms).reduce((a,b) => { return a.concat(b) }).filter((f, i, arr) => arr.indexOf(f) === i)
const fandomString = fandoms.length > 4 ? fandoms.slice(0, 4).join(", ")+" (+"+(fandoms.length - 4)+")" : (fandoms.length > 1 ? fandoms.slice(0, -1).join(", ")+" & "+fandoms.slice(-1)[0] : fandoms[0])
const title = `${series.name} by ${authorString} - ${fandomString} (${series.workCount} works)`
-
const description = `${series.description.replace("<br />", "\n").replace(/<[^>]>/g, "")}`
+
const summaryDOM = new DOM(summary, {decodeEntities: true});
+
const description = summaryDOM.innerHTML.replace(/\<br(?: \/)?\>/g, "\n").replace(
+
/(<([^>]+)>)/ig,
+
"",
+
)
const addr = `series/${seriesId}`
return {
title: title,
description: description,
-
openGraph: {
-
description: description
-
}
+
metadataBase: new URL('https://'+process.env.DOMAIN)
}
}
+10 -4
src/app/series/[seriesId]/preview/route.js
···
import { getSeries } from "@fujocoded/ao3.js"
+
import { setArchiveBaseUrl, resetArchiveBaseUrl } from "@fujocoded/ao3.js/urls"
+
import querystring from 'node:querystring'
import sanitizeData from "@/lib/sanitizeData.js"
import OGImage from "@/lib/ogimage.js"
import baseFonts from "@/lib/baseFonts.js"
import titleFonts from "@/lib/titleFonts.js"
+
import ao3CanonicalUrls from "@/lib/ao3Canonical.js"
export const size = {
width: 1600,
height: 900,
}
-
export const contentType = 'image/webp'
+
export const contentType = 'image/png'
export async function GET(req, ctx) {
const { seriesId } = await ctx.params
-
const props = await req.nextUrl.searchParams
+
const p = await req.nextUrl.searchParams
+
const props = querystring.parse(p.toString())
const addr = `series/${seriesId}`
-
const data = await getSeries({seriesId: seriesId})
-
const imageParams = await sanitizeData({type: 'series', data: data, props: props})
+
const domainParam = p && p.has('archive') && !ao3CanonicalUrls.includes(p.get('archive')) ? `?archive=${p.get('archive')}` : ''
+
const work = await fetch(`http://${process.env.DOMAIN}/api/series/${seriesId}${domainParam}`)
+
const data = await work.json()
+
const imageParams = await sanitizeData({type: 'series', data: data, props: p})
const theme = imageParams.theme
const baseFont = baseFonts[imageParams.baseFont].displayName
const titleFont = titleFonts[imageParams.titleFont].displayName
+4 -21
src/app/works/[workId]/chapters/[chapterId]/opengraph-image.jsx
···
import { getWork } from "@fujocoded/ao3.js"
import sanitizeData from "@/lib/sanitizeData.js"
import OGImage from "@/lib/ogimage.js"
+
import OGImageLocked from "@/lib/ogimagelocked.js"
import baseFonts from "@/lib/baseFonts.js"
import titleFonts from "@/lib/titleFonts.js"
+
import defaults from "@/lib/ogdefaults.js"
export const size = {
width: 1600,
height: 900,
}
export const alt = 'fixAO3'
-
export const contentType = 'image/webp'
-
const defaults = new URLSearchParams({
-
theme: 'ao3',
-
baseFont: 'bricolagegrotesque',
-
titleFont: 'stacksansnotch',
-
category: true,
-
rating: true,
-
warnings: false,
-
charTags: false,
-
relTags: false,
-
freeTags: false,
-
summary: true,
-
wordcount: true,
-
chapters: true,
-
postedAt: true,
-
updatedAt: false,
-
summaryType: 'basic',
-
customSummary: ''
-
})
-
export default async function Image({params, searchParams}) {
const { workId, chapterId } = await params
const addr = `works/${workId}/chapters/${chapterId}`
const data = await getWork({workId: workId, chapterId: chapterId})
-
const imageParams = await sanitizeData({type: 'work', data: data, props: defaults})
+
if (data.locked) return OGImageLocked({theme: process.env.DEFAULT_THEME})
+
const imageParams = await sanitizeData({type: 'work', data: data, props: new URLSearchParams(defaults)})
const theme = imageParams.theme
const baseFont = baseFonts[imageParams.baseFont].displayName
const titleFont = titleFonts[imageParams.titleFont].displayName
+27 -8
src/app/works/[workId]/chapters/[chapterId]/page.js
···
import { getWork } from "@fujocoded/ao3.js"
+
import DOM from "fauxdom"
+
import siteMap from "@/lib/siteMap.js"
-
export async function generateMetadata({ params, _searchParams }, _parent) {
+
export async function generateMetadata({ params, _searchParams }, parent) {
// read route params
const { workId, chapterId } = await params
-
const work = await getWork({workId: workId, chapterId: chapterId})
+
const parentData = await parent;
+
const base = parentData.metadataBase.replace('https://', '').replace('/', '')
+
const subdomain = base.split(".").length > 0 ? base.split(".")[0] : null
+
const archive = subdomain && Object.keys(siteMap).includes(subdomain) ? siteMap[subdomain] : null
+
const domainParam = archive ? `?archive=https://${archive}` : ''
+
const data = await fetch(`http://${process.env.DOMAIN}/api/works/${workId}/chapters/${chapterId}${domainParam}`)
+
const work = await data.json()
+
if (work.locked) {
+
return {
+
title: 'Locked Work',
+
description: 'This work is locked to the public. Log in to see it!',
+
metadataBase: new URL('https://'+archive)
+
}
+
}
+
const parentWorkData = await fetch(`http://${process.env.DOMAIN}/api/works/${workId}`)
+
const parentWork = await parentWorkData.json()
const authors = work.authors.map((a) => {
if (a.anonymous) {
return "Anonymous"
···
const fandoms = work.fandoms
const fandomString = fandoms.length > 4 ? fandoms.slice(0, 4).join(", ")+" (+"+(fandoms.length - 4)+")" : (fandoms.length > 1 ? fandoms.slice(0, -1).join(", ")+" & "+fandoms.slice(-1)[0] : fandoms[0])
const title = `${work.title} by ${authorString}, Chapter ${work.chapterInfo.index}${work.chapterInfo.name ? ": "+work.chapterInfo.name : ''} - ${fandomString}`
-
const summary = work.chapterInfo && work.chapterInfo.summary ? work.chapterInfo.summary : work.summary
-
const description = `${summary.replace("<br />", "\n").replace(/<[^>]>/g, "")}`
+
const summary = work.chapterInfo && work.chapterInfo.summary ? work.chapterInfo.summary : parentWork.summary
+
const summaryDOM = new DOM(summary, {decodeEntities: true});
+
const description = summaryDOM.innerHTML.replace(/\<br(?: \/)?\>/g, "\n").replace(
+
/(<([^>]+)>)/ig,
+
"",
+
)
const addr = `works/${workId}/chapters/${chapterId}`
return {
title: title,
description: description,
-
openGraph: {
-
description: description
-
}
+
metadataBase: new URL('https://'+base)
}
}
···
const { workId, chapterId } = await params
return (
<div dangerouslySetInnerHTML={{__html: `<script type="text/javascript">
-
window.location.replace("https://archiveofourown.org/works/${workId}/chapters/${chapterId}");
+
window.location.replace("https://archiveofourown.org/works/${workId}");
</script>`}}></div>
)
}
+9 -4
src/app/works/[workId]/chapters/[chapterId]/preview/route.js
···
-
import { getWork } from "@fujocoded/ao3.js"
+
import querystring from 'node:querystring'
import sanitizeData from "@/lib/sanitizeData.js"
import OGImage from "@/lib/ogimage.js"
import baseFonts from "@/lib/baseFonts.js"
import titleFonts from "@/lib/titleFonts.js"
+
import siteMap from "@/lib/siteMap.js"
+
import ao3CanonicalUrls from "@/lib/ao3Canonical.js"
export const size = {
width: 1600,
height: 900,
}
-
export const contentType = 'image/webp'
+
export const contentType = 'image/png'
export async function GET(req, ctx) {
const { workId, chapterId } = await ctx.params
const props = await req.nextUrl.searchParams
-
const addr = `works/${workId}/chapters/${chapterId}`
-
const data = await getWork({workId: workId, chapterId: chapterId})
+
const addr = `${props && props.has('archive') ? props.get('archive').replace("https://", "")+"/" : 'archiveofourown.org/'}works/${workId}/chapters/${chapterId}`
+
const domainParam = props && props.has('archive') && !ao3CanonicalUrls.includes(props.get('archive')) ? `?archive=${props.get('archive')}` : ''
+
const subdomain = props && props.has('archive') && Object.values(siteMap).includes(props.get('archive')) ? Object.keys(siteMap)[Object.values(siteMap).indexOf(props.get('archive'))]+'.' : ''
+
const work = await fetch(`http://${subdomain}${process.env.DOMAIN}/api/works/${workId}${domainParam}`)
+
const data = await work.json()
const imageParams = await sanitizeData({type: 'work', data: data, props: props})
const theme = imageParams.theme
const baseFont = baseFonts[imageParams.baseFont].displayName
+5 -22
src/app/works/[workId]/opengraph-image.jsx
···
import { getWork } from "@fujocoded/ao3.js"
import sanitizeData from "@/lib/sanitizeData.js"
import OGImage from "@/lib/ogimage.js"
+
import OGImageLocked from "@/lib/ogimagelocked.js"
import baseFonts from "@/lib/baseFonts.js"
import titleFonts from "@/lib/titleFonts.js"
+
import defaults from "@/lib/ogdefaults.js"
export const size = {
width: 1600,
height: 900,
}
export const alt = 'fixAO3'
-
export const contentType = 'image/webp'
-
const defaults = new URLSearchParams({
-
theme: 'ao3',
-
baseFont: 'bricolagegrotesque',
-
titleFont: 'stacksansnotch',
-
category: true,
-
rating: true,
-
warnings: false,
-
charTags: false,
-
relTags: false,
-
freeTags: false,
-
summary: true,
-
wordcount: true,
-
chapters: true,
-
postedAt: true,
-
updatedAt: false,
-
summaryType: 'basic',
-
customSummary: ''
-
})
-
-
export default async function Image({params}) {
+
export default async function Image({params, searchParams}) {
const { workId } = await params
const addr = `works/${workId}`
const data = await getWork({workId: workId})
-
const imageParams = await sanitizeData({type: 'work', data: data, props: defaults})
+
if (data.locked) return OGImageLocked({theme: process.env.DEFAULT_THEME})
+
const imageParams = await sanitizeData({type: 'work', data: data, props: new URLSearchParams(defaults)})
const theme = imageParams.theme
const baseFont = baseFonts[imageParams.baseFont].displayName
const titleFont = titleFonts[imageParams.titleFont].displayName
+22 -8
src/app/works/[workId]/page.js
···
import { getWork } from "@fujocoded/ao3.js"
+
import DOM from "fauxdom"
-
export async function generateMetadata({ params, _searchParams }, _parent) {
+
export async function generateMetadata({ params, _searchParams }, parent) {
// read route params
const { workId, chapterId } = await params
+
const p = await parent
+
console.log(p)
const work = await getWork({workId: workId, chapterId: chapterId})
+
if (work.locked) {
+
return {
+
title: 'Locked Work',
+
description: 'This work is locked to the public. Log in to see it!',
+
metadataBase: new URL('https://'+process.env.DOMAIN)
+
}
+
}
const authors = work.authors.map((a) => {
if (a.anonymous) {
return "Anonymous"
···
const fandomString = fandoms.length > 4 ? fandoms.slice(0, 4).join(", ")+" (+"+(fandoms.length - 4)+")" : (fandoms.length > 1 ? fandoms.slice(0, -1).join(", ")+" & "+fandoms.slice(-1)[0] : fandoms[0])
const title = `${work.title} by ${authorString} - ${fandomString}`
const summary = work.summary
-
const description = `${summary.replace("<br />", "\n").replace(/<[^>]>/g, "")}`
+
const summaryDOM = new DOM(summary, {decodeEntities: true});
+
const description = summaryDOM.innerHTML.replace(/\<br(?: \/)?\>/g, "\n").replace(
+
/(<([^>]+)>)/ig,
+
"",
+
)
const addr = `works/${workId}`
+
const parentData = await parent;
+
const base = parentData.metadataBase.replace('https://', '').replace('/', '')
return {
-
title: title,
-
description: description,
-
openGraph: {
-
description: description
-
}
+
title: title ? title : 'Locked Work',
+
description: description ? description : 'This but this work is locked to the public. Log in to see it!',
+
metadataBase: new URL('https://'+base)
}
}
···
const { workId, chapterId } = await params
return (
<div dangerouslySetInnerHTML={{__html: `<script type="text/javascript">
-
window.location.replace("https://archiveofourown.org/works/${workId}");
+
window.location.replace("https://archiveofourown.org/works/${workId}/chapters/${chapterId}");
</script>`}}></div>
)
}
+6 -4
src/app/works/[workId]/preview/route.js
···
-
import { getWork } from "@fujocoded/ao3.js"
import sanitizeData from "@/lib/sanitizeData.js"
import OGImage from "@/lib/ogimage.js"
import baseFonts from "@/lib/baseFonts.js"
···
height: 900,
}
-
export const contentType = 'image/webp'
+
export const contentType = 'image/png'
export async function GET(req, ctx) {
const { workId } = await ctx.params
const props = await req.nextUrl.searchParams
-
const addr = `works/${workId}`
-
const data = await getWork({workId: workId})
+
const addr = `${props && props.has('archive') ? props.get('archive').replace("https://", "")+"/" : 'archiveofourown.org/'}works/${workId}`
+
const domainParam = props && props.has('archive') ? `?archive=${props.get('archive')}` : ''
+
const work = await fetch(`http://${process.env.DOMAIN}/api/works/${workId}${domainParam}`)
+
const data = await work.json()
const imageParams = await sanitizeData({type: 'work', data: data, props: props})
+
console.log(imageParams)
const theme = imageParams.theme
const baseFont = baseFonts[imageParams.baseFont].displayName
const titleFont = titleFonts[imageParams.titleFont].displayName
+8
src/icons/lock.js
···
+
export default function Lock ({bg, fg, width, height}) {
+
return (
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" width={width} height={height}>
+
<ellipse cx="320" cy="320" rx="320" ry="320" fill={bg} />
+
<path d="M256 160L256 224L384 224L384 160C384 124.7 355.3 96 320 96C284.7 96 256 124.7 256 160zM192 224L192 160C192 89.3 249.3 32 320 32C390.7 32 448 89.3 448 160L448 224C483.3 224 512 252.7 512 288L512 512C512 547.3 483.3 576 448 576L192 576C156.7 576 128 547.3 128 512L128 288C128 252.7 156.7 224 192 224z" fill={fg} />
+
</svg>
+
)
+
}
+7
src/lib/ao3Canonical.js
···
+
const ao3CanonicalUrls = [
+
"https://archiveofourown.org",
+
"https://ao3.org",
+
"https://archive.transformativeworks.org"
+
]
+
+
export default ao3CanonicalUrls
+22
src/lib/ogdefaults.js
···
+
const defaults = {
+
theme: 'ao3',
+
baseFont: 'bricolagegrotesque',
+
titleFont: 'stacksansnotch',
+
category: true,
+
rating: true,
+
warnings: false,
+
charTags: false,
+
relTags: false,
+
freeTags: false,
+
summary: true,
+
wordcount: true,
+
chapters: true,
+
postedAt: true,
+
updatedAt: false,
+
uppercaseTitle: false,
+
uppercaseChapterName: false,
+
summaryType: 'basic',
+
customSummary: ''
+
}
+
+
export default defaults
+49 -39
src/lib/ogimage.js
···
import NoWarnings from "@/icons/nowarnings.js"
import Warnings from "@/icons/warnings.js"
import ChoseNotToWarn from "@/icons/chosenottowarn.js"
+
import { checkItem, checkToggle } from '@/lib/propUtils.js'
export default async function OGImage ({ theme, baseFont, titleFont, image, addr, opts }) {
+
console.log(image)
return new ImageResponse(
(
<div
···
}}
>
<div
+
style={{
+
textTransform: "uppercase",
+
display: "flex",
+
justifyContent: "center",
+
color: theme.accent,
+
alignItems: "center",
+
display: "flex",
+
justifyContent: "center",
+
alignItems: "center",
+
textAlign: "center"
+
}}
+
>
+
{image.topLine}
+
</div>
+
<div
style={{
-
textTransform: "uppercase",
display: "flex",
justifyContent: "center",
-
gap: 10,
-
color: theme.accent,
-
alignItems: "center"
-
}}
+
alignItems: "center",
+
gap: 10
+
}}
>
-
<div
-
style={{
-
display: "flex"
-
}}
-
>
-
{image.topLine}
-
</div>
-
-
{image.props.get('rating') === 'true' && image.rating === 'E' && (<Explicit fg={theme.background} bg={theme.accent} width={28} height={28} />)}
-
{image.props.get('rating') === 'true' && image.rating === 'M' && (<Mature fg={theme.background} bg={theme.accent} width={28} height={28} />)}
-
{image.props.get('rating') === 'true' && image.rating === 'T' && (<Teen fg={theme.background} bg={theme.accent} width={28} height={28} />)}
-
{image.props.get('rating') === 'true' && image.rating === 'G' && (<General fg={theme.background} bg={theme.accent} width={28} height={28} />)}
-
{image.props.get('rating') === 'true' && image.rating === 'NR' && (<NotRated fg={theme.background} bg={theme.accent} width={28} height={28} />)}
+
{checkToggle('rating', image.props) && image.rating === 'E' && (<Explicit fg={theme.accentColor} bg={theme.accent} width={28} height={28} />)}
+
{checkToggle('rating', image.props) && image.rating === 'M' && (<Mature fg={theme.accentColor} bg={theme.accent} width={28} height={28} />)}
+
{checkToggle('rating', image.props) && image.rating === 'T' && (<Teen fg={theme.accentColor} bg={theme.accent} width={28} height={28} />)}
+
{checkToggle('rating', image.props) && image.rating === 'G' && (<General fg={theme.accentColor} bg={theme.accent} width={28} height={28} />)}
+
{checkToggle('rating', image.props) && image.rating === 'NR' && (<NotRated fg={theme.accentColor} bg={theme.accent} width={28} height={28} />)}
-
{image.props.get('warnings') === 'true' && image.warning === 'NW' && (<NoWarnings fg={theme.background} bg={theme.accent2} width={28} height={28} />)}
-
{image.props.get('warnings') === 'true' && image.warning === 'CNTW' && (<ChoseNotToWarn fg={theme.background} bg={theme.accent2} width={28} height={28} />)}
-
{image.props.get('warnings') === 'true' && image.warning === 'W' && (<Warnings fg={theme.background} bg={theme.accent2} width={28} height={28} />)}
+
{checkToggle('warnings', image.props) && image.warning === 'NW' && (<NoWarnings fg={theme.accent2Color} bg={theme.accent2} width={28} height={28} />)}
+
{checkToggle('warnings', image.props) && image.warning === 'CNTW' && (<ChoseNotToWarn fg={theme.accent2Color} bg={theme.accent2} width={28} height={28} />)}
+
{checkToggle('warnings', image.props) && image.warning === 'W' && (<Warnings fg={theme.accent2Color} bg={theme.accent2} width={28} height={28} />)}
-
{image.props.get('category') === 'true' && image.category === 'F' && (<Yuri fg={theme.background} bg={theme.accent3} width={28} height={28} />)}
-
{image.props.get('category') === 'true' && image.category === 'M' && (<Yaoi fg={theme.background} bg={theme.accent3} width={28} height={28} />)}
-
{image.props.get('category') === 'true' && image.category === 'FM' && (<Het fg={theme.background} bg={theme.accent3} width={28} height={28} />)}
-
{image.props.get('category') === 'true' && image.category === 'G' && (<Gen fg={theme.background} bg={theme.accent3} width={28} height={28} />)}
-
{image.props.get('category') === 'true' && image.category === 'MX' && (<MultiShip fg={theme.background} bg={theme.accent3} width={28} height={28} />)}
-
{image.props.get('category') === 'true' && image.category === 'O' && (<OtherShip fg={theme.background} bg={theme.accent3} width={28} height={28} />)}
+
{checkToggle('category', image.props) && image.category === 'F' && (<Yuri fg={theme.accent3Color} bg={theme.accent3} width={28} height={28} />)}
+
{checkToggle('category', image.props)&& image.category === 'M' && (<Yaoi fg={theme.accent3Color} bg={theme.accent3} width={28} height={28} />)}
+
{checkToggle('category', image.props) && image.category === 'FM' && (<Het fg={theme.accent3Color} bg={theme.accent3} width={28} height={28} />)}
+
{checkToggle('category', image.props) && image.category === 'G' && (<Gen fg={theme.accent3Color} bg={theme.accent3} width={28} height={28} />)}
+
{checkToggle('category', image.props) && image.category === 'MX' && (<MultiShip fg={theme.accent3Color} bg={theme.accent3} width={28} height={28} />)}
+
{checkToggle('category', image.props) && image.category === 'O' && (<OtherShip fg={theme.accent3Color} bg={theme.accent3} width={28} height={28} />)}
</div>
<div
style={{
fontSize: 54,
justifyContent: "center",
+
textAlign: "center",
fontFamily: titleFont,
fontWeight: "bold",
-
color: theme.color
+
color: theme.color,
+
textTransform: (image.props.uppercaseTitle ? 'uppercase' : 'none')
}}
>
{image.titleLine}
···
>
{`by ${image.authorLine}`}
</div>
-
<div
+
{image.chapterLine !== '' && (<div
style={{
fontStyle: "italic",
fontSize: 36,
fontFamily: titleFont,
display: "flex",
justifyContent: "center",
-
color: theme.color
+
color: theme.color,
+
textTransform: (image.props.uppercaseChapterName ? 'uppercase' : 'none')
}}
>
{image.chapterLine}
-
</div>
+
</div>)}
</div>
<div
style={{
···
alignItems: "flex-end"
}}
>
-
{image.props.get("charTags") === 'true' && (<div
+
{checkToggle('charTags', image.props) && (<div
style={{
display: "flex",
flexWrap: "wrap",
···
<span
style={{
backgroundColor: theme.accent2,
-
color: theme.descBackground,
+
color: theme.accent2Color,
padding: "3px 5px",
borderRadius: 5
}}
···
</span>
))}
</div>)}
-
{image.props.get("relTags") === 'true' && (<div
+
{checkToggle('relTags', image.props) && (<div
style={{
display: "flex",
flexWrap: "wrap",
···
<span
style={{
backgroundColor: theme.accent3,
-
color: theme.descBackground,
+
color: theme.accent3Color,
padding: "3px 5px",
borderRadius: 5
}}
···
</span>
))}
</div>)}
-
{image.props.get("freeTags") === 'true' && (<div
+
{checkToggle('freeTags', image.props) && (<div
style={{
display: "flex",
flexWrap: "wrap",
···
<span
style={{
backgroundColor: theme.accent4,
-
color: theme.descBackground,
+
color: theme.accent4Color,
padding: "3px 5px",
borderRadius: 5
}}
···
</span>
))}
</div>)}
-
{image.props.get("summary") === 'true' && (<div
+
{checkToggle('summary', image.props) && (<div
style={{
display: "flex",
flexDirection: "column",
···
color: theme.accent2
}}
>
-
{image.props.get("wordcount") === 'true' && `${image.words} words โ€ข `}{(image.props.get("chapters") === 'true' && image.chapterCount !== null) && `${image.chapterCount} chapters โ€ข `}{image.props.get("postedAt") === 'true' && `posted on ${image.postedAt} โ€ข `}{image.props.get("updatedAt") === 'true' && `updated on ${image.updatedAt} โ€ข `}{process.env.ARCHIVE}/{addr}
+
{checkToggle('wordcount', image.props) && `${image.words} words โ€ข `}{(checkToggle('chapters', image.props) && image.chapterCount !== null) && `${image.chapterCount} chapters โ€ข `}{checkToggle('postedAt', image.props) && `posted on ${image.postedAt} โ€ข `}{checkToggle('updatedAt', image.props) && `updated on ${image.updatedAt} โ€ข `}{addr}
</div>
</div>
</div>
+27
src/lib/ogimagelocked.js
···
+
import { ImageResponse } from "next/og"
+
import themes from "@/lib/themes.js"
+
import Lock from "@/icons/lock.js"
+
+
export default async function OGImageLocked ({ theme }) {
+
const themeData = themes[theme]
+
return new ImageResponse(
+
(
+
<div
+
style={{
+
display: "flex",
+
flexDirection: "column",
+
justifyContent: "center",
+
alignItems: "center",
+
color: themeData.color,
+
backgroundColor: themeData.background,
+
fontSize: 24,
+
padding: 20,
+
width: "100%",
+
height: "100%",
+
}}
+
>
+
<Lock bg={themeData.background} fg={themeData.color} width={480} height={480} />
+
</div>
+
)
+
)
+
}
+7
src/lib/propUtils.js
···
+
export function checkItem (key, props) {
+
return props.has(key) ? props.get(key) !== '' : false
+
}
+
+
export function checkToggle (key, props) {
+
return props.has(key) ? props.get(key) === 'true' : false
+
}
+51 -20
src/lib/sanitizeData.js
···
-
import { getWork } from "@fujocoded/ao3.js"
import DOM from "fauxdom"
import { readFile } from 'node:fs/promises'
+
import querystring from 'node:querystring'
import { join } from 'node:path'
import themes from '@/lib/themes.js'
import baseFonts from '@/lib/baseFonts.js'
import titleFonts from '@/lib/titleFonts.js'
+
import { checkItem, checkToggle } from '@/lib/propUtils.js'
-
const getHighestRating = async (works) => {
+
const getWork = async (workId, archive = null) => {
+
const domainParam = (archive && archive !== process.env.ARCHIVE) ? `?archive=${archive}` : ''
+
const data = await fetch(`http://${process.env.DOMAIN}/api/works/${workId}${domainParam}`)
+
const work = await data.json()
+
return work
+
}
+
+
const getHighestRating = async (works, archive = null) => {
const ratings = await Promise.all(works.map(async (w) => {
-
const work = await getWork({workId: w.id})
+
const work = await getWork(w.id, archive)
return work.rating
}))
if (ratings.includes("Not Rated")) {
···
return "G"
}
-
const getHighestWarning = async (works) => {
+
const getHighestWarning = async (works, archive = null) => {
const warnings = await Promise.all(works.map(async (w) => {
-
const work = await getWork({workId: w.id})
+
const work = await getWork(w.id, archive)
return work.tags.warnings
}))
const warningsUnique = warnings.reduce((a, b) => { return a.concat(b) }).filter((w, i) => { return i === warnings.indexOf(w) })
···
return "W"
}
-
const getCategory = async (works) => {
+
const getCategory = async (works, archive = null) => {
const categories = await Promise.all(works.map(async (w) => {
-
const work = await getWork({workId: w.id})
+
const work = await getWork(w.id, archive)
return work.category
}))
const categoriesJoined = categories.reduce((a, b) => { return a.concat(b) })
···
return "MX"
}
+
const sanitizeProps = (props) => {
+
let propsParsed = {}
+
Object.keys(props).forEach((pr) => {
+
if (props[pr] === 'true') {
+
propsParsed[pr] = true
+
return
+
} else if (props[pr] === 'false') {
+
propsParsed[pr] = false
+
return
+
} else if (typeof parseInt(props[pr]) === 'Number') {
+
propsParsed[pr] = parseInt(props[pr])
+
return
+
}
+
propsParsed[pr] = props[pr]
+
})
+
return propsParsed
+
}
+
export default async function sanitizeData ({ type, data, props}) {
-
const baseFont = props.has('baseFont') ? props.get('baseFont') : process.env.DEFAULT_BASE_FONT
+
const archive = props && checkItem('archive', props) ? props.get('archive') : process.env.ARCHIVE
+
console.log(props)
+
const baseFont = checkItem('baseFont', props) ? props.get('baseFont') : process.env.DEFAULT_BASE_FONT
const baseFontData = baseFonts[baseFont]
-
const titleFont = props.has('titleFont') ? props.get('titleFont') : process.env.DEFAULT_TITLE_FONT
+
const titleFont = checkItem('titleFont', props) ? props.get('titleFont') : process.env.DEFAULT_TITLE_FONT
const titleFontData = titleFonts[titleFont]
-
const themeData = props.has('theme') ? themes[props.get('theme')] : themes[process.env.DEFAULT_THEME]
-
const parentWork = type === 'work' && data.chapterInfo ? await getWork({workId: data.id}) : null
+
const archClean = checkItem('archive', props) ? props.get('archive').replace("https://", '').replace('/', '') : null
+
const theme = checkItem('theme', props) ? props.get('theme') : (checkItem('archive', props) && !["ao3.org", "archiveofourown.org", "archive.transformativeworks.org"].includes(archClean) && Object.values(siteMap).includes(archClean) ? Object.keys(siteMap)[Object.values(siteMap).indexOf(archClean)] : process.env.DEFAULT_THEME)
+
const themeData = themes[theme]
+
const parentWork = type === 'work' && data.chapterInfo ? await getWork(data.id, archive) : null
const bfs = await Promise.all(baseFontData.defs.map(async (bf) => {
return {
name: baseFontData.displayName,
···
return a.username
})
: []
-
const rating = type === 'work' ? await getHighestRating([data]) : await getHighestRating(data.works)
-
const warning = type === 'work' ? await getHighestWarning([data]) : await getHighestWarning(data.works)
-
const category = type === 'work' ? await getCategory([data]) : await getCategory(data.works)
-
const authorString = authorsFormatted.length > 1
+
const rating = type === 'work' ? data.rating : await getHighestRating(data.works, archive)
+
const warning = type === 'work' ? await getHighestWarning([data], archive) : await getHighestWarning(data.works, archive)
+
const category = type === 'work' ? await getCategory([data], archive) : await getCategory(data.works, archive)
+
const authorString = (authorsFormatted.length > 1
? authorsFormatted.slice(0, -1).join(", ") + " & " +
authorsFormatted.slice(-1)[0]
-
: authorsFormatted[0]
+
: authorsFormatted[0])
const summaryContent = type === 'work'
-
? (props.get('summaryType') === 'chapter' && data.chapterInfo && data.chapterInfo.summary ? data.chapterInfo.summary : (props.get('summaryType') === 'custom' && props.has('customSummary') ? props.get('customSummary') : (data.summary ? data.summary : (parentWork ? parentWork.summary : ''))))
-
: (props.get('summaryType') === 'custom' && props.has('customSummary') ? props.get('customSummary') : data.notes)
+
? (props.get('summaryType') === 'chapter' && data.chapterInfo && data.chapterInfo.summary ? data.chapterInfo.summary : (props.get('summaryType') === 'custom' && props.get('customSummary') !== '' ? props.get('customSummary') : (data.summary ? data.summary : (parentWork ? parentWork.summary : ''))))
+
: (props.get('summaryType') === 'custom' && props.get('customSummary') !== '' ? props.get('customSummary') : data.notes)
const formatter = new Intl.NumberFormat('en-US')
const words = formatter.format(data.words)
-
const summaryDOM = new DOM(summaryContent, {decodeEntities: true});
+
const summaryDOM = new DOM(summaryContent, {decodeEntities: true})
const summaryFormatted = summaryDOM.innerHTML.replace(/\<br(?: \/)?\>/g, "\n").replace(
/(<([^>]+)>)/ig,
"",
···
const freeTags = type === 'work' ? data.tags.additional : data.works.map(w => w.tags.additional).reduce((a, b) => { return b ? (a ? a.concat(b) : []) : (a ? a : []) }).filter((w, i) => { return i === data.works.indexOf(w) })
const warnings = type === 'work' ? data.tags.warnings : data.works.map(w => w.tags.warnings).reduce((a, b) => { return b ? (a ? a.concat(b) : []) : (a ? a : []) }).filter((w, i) => { return i === data.works.indexOf(w) })
-
return {
+
const ret = {
topLine: fandomString,
titleLine: titleString,
authorLine: authorString,
···
fonts: bfs.concat(tfs)
}
}
+
return ret;
}
+9
src/lib/siteMap.js
···
+
const siteMap = {
+
superlove: 'superlove.sayitditto.net',
+
sunset: 'sunset.femslash.club',
+
squidgeworld: 'squidgeworld.org',
+
cfaarchive: 'cfaarchive.org',
+
adastra: 'adastrafanfic.com'
+
}
+
+
export default siteMap
+816 -18
src/lib/themes.js
···
descBackground: '#FFFFFF',
descColor: '#000000',
accent: '#FFFFFF',
-
accent2: '#990000',
-
accent3: '#009900',
-
accent4: '#000099'
+
accentColor: '#990000',
+
accent2: '#CC9999',
+
accent2Color: '#990000',
+
accent3: '#EEBBBB',
+
accent3Color: '#990000',
+
accent4: '#FFDDDD',
+
accent4Color: '#990000'
},
softEra: {
name: 'Soft Era',
···
descBackground: '#F9F5F5',
descColor: '#414141',
accent: '#DB90A7',
+
accentColor: '#F9F5F5',
accent2: '#EEAABE',
+
accent2Color: '#F9F5F5',
accent3: '#82B4E3',
-
accent4: '#a29acb'
+
accent3Color: '#F9F5F5',
+
accent4: '#a29acb',
+
accent4Color: '#F9F5F5',
},
wildCherry: {
name: 'Wild Cherry',
···
descBackground: '#FFFFFF',
descColor: '#2B1F32',
accent: '#E15D97',
+
accentColor: '#FFFFFF',
accent2: '#0AACC5',
+
accent2Color: '#FFFFFF',
accent3: '#FFB86C',
-
accent4: '#35BA66'
+
accent3Color: '#2B1F32',
+
accent4: '#35BA66',
+
accent4Color: '#FFFFFF',
},
rosePine: {
name: 'Rosรฉ Pine',
···
descBackground: '#1f1d2e',
descColor: '#e0def4',
accent: '#eb6f92',
-
accent2: '#31748f',
+
accentColor: '#191724',
+
accent2: '#9ccfd8',
+
accent2Color: '#191724',
accent3: '#f6c177',
-
accent4: '#c4a7e7'
+
accent3Color: '#191724',
+
accent4: '#c4a7e7',
+
accent4Color: '#191724',
},
rosePineDawn: {
name: 'Rosรฉ Pine Dawn',
···
descBackground: '#fffaf3',
descColor: '#575279',
accent: '#eb6f92',
+
accentColor: '#faf4ed',
accent2: '#286983',
+
accent2Color: '#faf4ed',
accent3: '#ea9d34',
-
accent4: '#907aa9'
+
accent3Color: '#faf4ed',
+
accent4: '#907aa9',
+
accent4Color: '#faf4ed',
},
rosePineMoon: {
name: 'Rosรฉ Pine Moon',
···
descBackground: '#2a273f',
descColor: '#e0def4',
accent: '#b4637a',
-
accent2: '#3e8fb0',
+
accentColor: '#232136',
+
accent2: '#9ccfd8',
+
accent2Color: '#232136',
accent3: '#f6c177',
-
accent4: '#c4a7e7'
+
accent3Color: '#232136',
+
accent4: '#c4a7e7',
+
accent4Color: '#232136',
},
solarizedLight: {
name: 'Solarized Light',
···
descBackground: '#eee8d5',
descColor: '#002b36',
accent: '#d33682',
+
accentColor: '#fdf6e3',
accent2: '#2aa198',
+
accent2Color: '#fdf6e3',
accent3: '#859900',
-
accent4: '#6c71c4'
+
accent3Color: '#fdf6e3',
+
accent4: '#6c71c4',
+
accent4Color: '#fdf6e3',
},
solarizedDark: {
name: 'Solarized Dark',
···
descBackground: '#073642',
descColor: '#fdf6e3',
accent: '#d33682',
+
accentColor: '#002b36',
accent2: '#2aa198',
+
accent2Color: '#002b36',
accent3: '#859900',
-
accent4: '#6c71c4'
+
accent3Color: '#002b36',
+
accent4: '#6c71c4',
+
accent4Color: '#002b36',
},
squidgeworld: {
name: 'Squidgeworld',
···
color: '#f5f5dc',
descBackground: '#f5f5dc',
descColor: '#2a2a2a',
-
accent: '#fece3f',
+
accent: '#FFC825',
+
accentColor: '#f5f5dc',
accent2: '#818D4C',
+
accent2Color: '#f5f5dc',
accent3: '#6D7A34',
-
accent4: '#556121'
+
accent3Color: '#f5f5dc',
+
accent4: '#556121',
+
accent4Color: '#f5f5dc',
},
superlove: {
name: 'Superlove',
···
color: '#ffffff',
descBackground: '#FFFFFF',
descColor: '#2a2a2a',
-
accent: '#F9E4E6',
+
accent: '#F4C4C5',
+
accentColor: '#ffffff',
accent2: '#a33961',
+
accent2Color: '#ffffff',
accent3: '#87254A',
-
accent4: '#6A1133'
+
accent3Color: '#ffffff',
+
accent4: '#6A1133',
+
accent4Color: '#ffffff',
},
catppuccinMocha: {
name: 'Catppuccin Mocha',
···
descBackground: '#313244',
descColor: '#bac2de',
accent: '#f5e0dc',
+
accentColor: '#1e1e2e',
accent2: '#cba6f7',
+
accent2Color: '#1e1e2e',
accent3: '#fab387',
-
accent4: '#89dceb'
+
accent3Color: '#1e1e2e',
+
accent4: '#89dceb',
+
accent4Color: '#1e1e2e',
},
catppuccinLatte: {
name: 'Catppuccin Latte',
···
descBackground: '#ccd0da',
descColor: '#5c5f77',
accent: '#dc8a78',
+
accentColor: '#FFFFFF',
accent2: '#8839ef',
+
accent2Color: '#eff1f5',
accent3: '#fe640b',
-
accent4: '#04a5e5'
+
accent3Color: '#eff1f5',
+
accent4: '#04a5e5',
+
accent4Color: '#eff1f5',
+
},
+
atelierCave: {
+
name: 'Atelier Cave',
+
background: '#19171c',
+
color: '#655F6D',
+
descBackground: '#19171c',
+
descColor: '#E2DFE7',
+
accent: '#BE4678',
+
accentColor: '#E2DFE7',
+
accent2: '#2A9292',
+
accent2Color: '#E2DFE7',
+
accent3: '#AA573C',
+
accent3Color: '#E2DFE7',
+
accent4: '#A06E3B',
+
accent4Color: '#E2DFE7'
+
},
+
atelierDune: {
+
name: 'Atelier Dune',
+
background: '#20201d',
+
color: '#7D7A68',
+
descBackground: '#20201d',
+
descColor: '#7D7A68',
+
accent: '#D73737',
+
accentColor: '#FEFBEC',
+
accent2: '#60AC39',
+
accent2Color: '#FEFBEC',
+
accent3: '#AE9513',
+
accent3Color: '#FEFBEC',
+
accent4: '#6684E1',
+
accent4Color: '#FEFBEC'
+
},
+
atelierEstuary: {
+
name: 'Atelier Estuary',
+
background: '#22221b',
+
color: '#6C6B5A',
+
descBackground: '#22221b',
+
descColor: '#E7E6DF',
+
accent: '#BA6236',
+
accentColor: '#F4F3EC',
+
accent2: '#7D9726',
+
accent2Color: '#F4F3EC',
+
accent3: '#AE7313',
+
accent3Color: '#F4F3EC',
+
accent4: '#36A166',
+
accent4Color: '#F4F3EC'
+
},
+
atelierForest: {
+
name: 'Atelier Forest',
+
background: '#1b1918',
+
color: '#766E6B',
+
descBackground: '#1b1918',
+
descColor: '#F1EFEE',
+
accent: '#F22C40',
+
accentColor: '#F1EFEE',
+
accent2: '#7B9726',
+
accent2Color: '#F1EFEE',
+
accent3: '#DF5320',
+
accent3Color: '#F1EFEE',
+
accent4: '#407EE7',
+
accent4Color: '#F1EFEE'
+
},
+
atelierHeath: {
+
name: 'Atelier Heath',
+
background: '#1b1918',
+
color: '#776977',
+
descBackground: '#1b1918',
+
descColor: '#F7F3F7',
+
accent: '#CA402B',
+
accentColor: '#F7F3F7',
+
accent2: '#918B3B',
+
accent2Color: '#F7F3F7',
+
accent3: '#BB8A35',
+
accent3Color: '#F7F3F7',
+
accent4: '#516AEC',
+
accent4Color: '#F7F3F7'
+
},
+
atelierLakeside: {
+
name: 'Atelier Lakeside',
+
background: '#161b1d',
+
color: '#5A7B8C',
+
descBackground: '#161b1d',
+
descColor: '#EBF8FF',
+
accent: '#D22D72',
+
accentColor: '#EBF8FF',
+
accent2: '#568C3B',
+
accent2Color: '#EBF8FF',
+
accent3: '#935C25',
+
accent3Color: '#EBF8FF',
+
accent4: '#257FAD',
+
accent4Color: '#EBF8FF'
+
},
+
atelierPlateau: {
+
name: 'Atelier Plateau',
+
background: '#1b1818',
+
color: '#655D5D',
+
descBackground: '#1b1818',
+
descColor: '#F4ECEC',
+
accent: '#CA4949',
+
accentColor: '#F4ECEC',
+
accent2: '#4B8B8B',
+
accent2Color: '#F4ECEC',
+
accent3: '#A06E3B',
+
accent3Color: '#F4ECEC',
+
accent4: '#7272CA',
+
accent4Color: '#F4ECEC'
+
},
+
atelierSavanna: {
+
name: 'Atelier Savanna',
+
background: '#171c19',
+
color: '#5F6D64',
+
descBackground: '#1b1818',
+
descColor: '#ECF4EE',
+
accent: '#B16139',
+
accentColor: '#ECF4EE',
+
accent2: '#489963',
+
accent2Color: '#ECF4EE',
+
accent3: '#A07E3B',
+
accent3Color: '#ECF4EE',
+
accent4: '#478C90',
+
accent4Color: '#ECF4EE'
+
},
+
atelierSeaside: {
+
name: 'Atelier Seaside',
+
background: '#131513',
+
color: '#687D68',
+
descBackground: '#131513',
+
descColor: '#CFE8CF',
+
accent: '#E6193C',
+
accentColor: '#CFE8CF',
+
accent2: '#29A329',
+
accent2Color: '#CFE8CF',
+
accent3: '#98981B',
+
accent3Color: '#CFE8CF',
+
accent4: '#3D62F5',
+
accent4Color: '#CFE8CF'
+
},
+
atelierSulphurpool: {
+
name: 'Atelier Sulphurpool',
+
background: '#202746',
+
color: '#6B7394',
+
descBackground: '#202746',
+
descColor: '#DFE2F1',
+
accent: '#C94922',
+
accentColor: '#DFE2F1',
+
accent2: '#AC9739',
+
accent2Color: '#DFE2F1',
+
accent3: '#C08B30',
+
accent3Color: '#DFE2F1',
+
accent4: '#3D8FD1',
+
accent4Color: '#DFE2F1'
+
},
+
ayaka: {
+
name: 'Ayaka',
+
background: '#36283d',
+
color: '#FFFEFE',
+
descBackground: '#36283d',
+
descColor: '#FFFEFE',
+
accent: '#71ADE9',
+
accentColor: '#FFFEFE',
+
accent2: '#AB8CAE',
+
accent2Color: '#FFFEFE',
+
accent3: '#E59DB1',
+
accent3Color: '#FFFEFE',
+
accent4: '#8BB8E9',
+
accent4Color: '#FFFEFE'
+
},
+
ayuMirage: {
+
name: 'Ayu Mirage',
+
background: '#1F2430',
+
color: '#CBCCC6',
+
descBackground: '#1F2430',
+
descColor: '#CBCCC6',
+
accent: '#FF3333',
+
accentColor: '#1F2430',
+
accent2: '#BAE67E',
+
accent2Color: '#1F2430',
+
accent3: '#FFA759',
+
accent3Color: '#1F2430',
+
accent4: '#73D0FF',
+
accent4Color: '#1F2430'
+
},
+
base2ToneCave: {
+
name: 'Base2Tone Cave',
+
background: '#222021',
+
color: '#9f999b',
+
descBackground: '#2f2d2e',
+
descColor: '#ffebf2',
+
accent: '#936c7a',
+
accentColor: '#ffebf2',
+
accent2: '#cca133',
+
accent2Color: '#ffebf2',
+
accent3: '#d27998',
+
accent3Color: '#ffebf2',
+
accent4: '#706b6d',
+
accent4Color: '#ffebf2'
+
},
+
base2ToneDesert: {
+
name: 'Base2Tone Desert',
+
background: '#292724',
+
color: '#ada594',
+
descBackground: '#3d3a34',
+
descColor: '#f2ead9',
+
accent: '#816f4b',
+
accentColor: '#f2ead9',
+
accent2: '#ec9255',
+
accent2Color: '#f2ead9',
+
accent3: '#957e50',
+
accent3Color: '#f2ead9',
+
accent4: '#615c51',
+
accent4Color: '#f2ead9'
+
},
+
base2ToneDrawbridge: {
+
name: 'Base2Tone Drawbridge',
+
background: '#1b1f32',
+
color: '#9094a7',
+
descBackground: '#252a41',
+
descColor: '#9094a7',
+
accent: '#627af4',
+
accentColor: '#e1e6ff',
+
accent2: '#5cbcd6',
+
accent2Color: '#e1e6ff',
+
accent3: '#8b9efd',
+
accent3Color: '#e1e6ff',
+
accent4: '#444b6f',
+
accent4Color: '#e1e6ff'
+
},
+
base2ToneEarth: {
+
name: 'Base2Tone Earth',
+
background: '#322d29',
+
color: '#b5a9a1',
+
descBackground: '#3f3a37',
+
descColor: '#fff3eb',
+
accent: '#e6b84d',
+
accentColor: '#fff3eb',
+
accent2: '#d9b154',
+
accent2Color: '#fff3eb',
+
accent3: '#816d5f',
+
accent3Color: '#fff3eb',
+
accent4: '#b5a9a1',
+
accent4Color: '#fff3eb'
+
},
+
base2ToneEvening: {
+
name: 'Base2Tone Evening',
+
background: '#2a2734',
+
color: '#a4a1b5',
+
descBackground: '#363342',
+
descColor: '#eeebff',
+
accent: '#8a75f5',
+
accentColor: '#eeebff',
+
accent2: '#ffad5c',
+
accent2Color: '#eeebff',
+
accent3: '#afa0fe',
+
accent3Color: '#eeebff',
+
accent4: '#a4a1b5',
+
accent4Color: '#eeebff'
+
},
+
base2ToneField: {
+
name: 'Base2Tone Field',
+
background: '#18201e',
+
color: '#8ea4a0',
+
descBackground: '#242e2c',
+
descColor: '#a8fff1',
+
accent: '#0fbda0',
+
accentColor: '#242e2c',
+
accent2: '#3be381',
+
accent2Color: '#242e2c',
+
accent3: '#40ddc3',
+
accent3Color: '#242e2c',
+
accent4: '#8ea4a0',
+
accent4Color: '#242e2c'
+
},
+
base2ToneForest: {
+
name: 'Base2Tone Forest',
+
background: '#2a2d2a',
+
color: '#a1b5a1',
+
descBackground: '#353b35',
+
descColor: '#f0fff0',
+
accent: '#5c705c',
+
accentColor: '#f0fff0',
+
accent2: '#b1c44f',
+
accent2Color: '#f0fff0',
+
accent3: '#687d68',
+
accent3Color: '#f0fff0',
+
accent4: '#8fae8f',
+
accent4Color: '#f0fff0'
+
},
+
base2ToneLavender: {
+
name: 'Base2Tone Lavender',
+
background: '#201d2a',
+
color: '#9992b0',
+
descBackground: '#2c2839',
+
descColor: '#efebff',
+
accent: '#9375f5',
+
accentColor: '#efebff',
+
accent2: '#d294ff',
+
accent2Color: '#efebff',
+
accent3: '#b5a0fe',
+
accent3Color: '#efebff',
+
accent4: '#9992b0',
+
accent4Color: '#efebff'
+
},
+
base2ToneMall: {
+
name: 'Base2Tone Mall',
+
background: '#1e1e1f',
+
color: '#97959d',
+
descBackground: '#2b2b2c',
+
descColor: '#f4f0ff',
+
accent: '#a17efc',
+
accentColor: '#f4f0ff',
+
accent2: '#75bfff',
+
accent2Color: '#f4f0ff',
+
accent3: '#c5adff',
+
accent3Color: '#f4f0ff',
+
accent4: '#97959d',
+
accent4Color: '#f4f0ff'
+
},
+
base2ToneMotel: {
+
name: 'Base2Tone Motel',
+
background: '#242323',
+
color: '#a5979a',
+
descBackground: '#373434',
+
descColor: '#f0dbdf',
+
accent: '#956f76',
+
accentColor: '#f0dbdf',
+
accent2: '#f8917c',
+
accent2Color: '#f0dbdf',
+
accent3: '#a7868b',
+
accent3Color: '#f0dbdf',
+
accent4: '#a5979a',
+
accent4Color: '#f0dbdf'
+
},
+
base2TonePool: {
+
name: 'Base2Tone Pool',
+
background: '#2a2433',
+
color: '#9a90a7',
+
descBackground: '#372f42',
+
descColor: '#f3ebff',
+
accent: '#aa75f5',
+
accentColor: '#f3ebff',
+
accent2: '#f87972',
+
accent2Color: '#f3ebff',
+
accent3: '#c7a0fe',
+
accent3Color: '#f3ebff',
+
accent4: '#9a90a7',
+
accent4Color: '#f3ebff'
+
},
+
base2TonePorch: {
+
name: 'Base2Tone Porch',
+
background: '#221e24',
+
color: '#9f95a3',
+
descBackground: '#302a32',
+
descColor: '#f2e3f7',
+
accent: '#9466a3',
+
accentColor: '#f2e3f7',
+
accent2: '#f39b68',
+
accent2Color: '#f2e3f7',
+
accent3: '#a77cb6',
+
accent3Color: '#f2e3f7',
+
accent4: '#9f95a3',
+
accent4Color: '#f2e3f7'
+
},
+
base2ToneSpace: {
+
name: 'Base2Tone Space',
+
background: '#24242e',
+
color: '#a1a1b5',
+
descBackground: '#333342',
+
descColor: '#cecee3',
+
accent: '#7676f4',
+
accentColor: '#ebebff',
+
accent2: '#f37b3f',
+
accent2Color: '#ebebff',
+
accent3: '#fe8c52',
+
accent3Color: '#ebebff',
+
accent4: '#737391',
+
accent4Color: '#ebebff'
+
},
+
base2ToneSuburb: {
+
name: 'Base2Tone Suburb',
+
background: '#1e202f',
+
color: '#4f5472',
+
descBackground: '#292c3d',
+
descColor: '#ebedff',
+
accent: '#7586f5',
+
accentColor: '#ebedff',
+
accent2: '#fe81b5',
+
accent2Color: '#ebedff',
+
accent3: '#fb6fa9',
+
accent3Color: '#ebedff',
+
accent4: '#5b6080',
+
accent4Color: '#ebedff'
+
},
+
blueDolphin: {
+
name: "Blue Dolphin",
+
background: '#006984',
+
color: '#A3F7FF',
+
descBackground: '#006984',
+
descColor: '#FFFFFF',
+
accent: '#FF8288',
+
accentColor: '#292D3E',
+
accent2: '#B4E88D',
+
accent2Color: '#292D3E',
+
accent3: '#F4D69F',
+
accent3Color: '#292D3E',
+
accent4: '#82AAFF',
+
accent4Color: '#292D3E'
+
},
+
borland: {
+
name: "Borland",
+
background: '#0000a4',
+
color: '#FFFFB6',
+
descBackground: '#0000a4',
+
descColor: '#FFFFB6',
+
accent: '#FF6C60',
+
accentColor: '#292D3E',
+
accent2: '#B4E88D',
+
accent2Color: '#292D3E',
+
accent3: '#F4D69F',
+
accent3Color: '#292D3E',
+
accent4: '#82AAFF',
+
accent4Color: '#292D3E'
+
},
+
butrin: {
+
name: 'Butrin',
+
background: '#4b3b3c',
+
color: '#F2F2F2',
+
descBackground: '#4b3b3c',
+
descColor: '#F2F2F2',
+
accent: '#F2B1B1',
+
accentColor: '#4b3b3c',
+
accent2: '#B2D8B2',
+
accent2Color: '#4b3b3c',
+
accent3: '#87CEFA',
+
accent3Color: '#4b3b3c',
+
accent4: '#D8BFD8',
+
accent4Color: '#4b3b3c'
+
},
+
gooey: {
+
name: "Gooey",
+
background: '#000009',
+
color: '#FFFFFF',
+
descBackground: '#1F222D',
+
descColor: '#FFFFFF',
+
accent: '#BB4F6C',
+
accentColor: '#FFFFFF',
+
accent2: '#C65E3D',
+
accent2Color: '#FFFFFF',
+
accent3: '#72CCAE',
+
accent3Color: '#FFFFFF',
+
accent4: '#58B6CA',
+
accent4Color: '#FFFFFF'
+
},
+
gruvbox: {
+
name: 'Gruvbox',
+
background: '#FBF1C7',
+
color: '#4f5472',
+
descBackground: '#FBF1C7',
+
descColor: '#3C3836',
+
accent: '#9D0006',
+
accentColor: '#4F4F4F',
+
accent2: '#A8FF60',
+
accent2Color: '#4F4F4F',
+
accent3: '#96CBFE',
+
accent3Color: '#4F4F4F',
+
accent4: '#FF73FD',
+
accent4Color: '#4F4F4F'
+
},
+
gruvboxDark: {
+
name: 'Gruvbox Dark',
+
background: '#282828',
+
color: '#7C6F64',
+
descBackground: '#282828',
+
descColor: '#ebedff',
+
accent: '#FB4934',
+
accentColor: '#282828',
+
accent2: '#B8BB26',
+
accent2Color: '#282828',
+
accent3: '#FABD2F',
+
accent3Color: '#282828',
+
accent4: '#83A598',
+
accent4Color: '#282828'
+
},
+
monoAmber: {
+
name: "Mono Amber",
+
background: '#2b1900',
+
color: '#FF9400',
+
descBackground: '#2b1900',
+
descColor: '#FF9400',
+
accent: '#FF9400',
+
accentColor: '#402500',
+
accent2: '#FF9400',
+
accent2Color: '#402500',
+
accent3: '#FF9400',
+
accent3Color: '#402500',
+
accent4: '#FF9400',
+
accent4Color: '#402500'
+
},
+
monoCyan: {
+
name: "Mono Cyan",
+
background: '#00222b',
+
color: '#00CCFF',
+
descBackground: '#00222b',
+
descColor: '#00CCFF',
+
accent: '#00CCFF',
+
accentColor: '#003340',
+
accent2: '#00CCFF',
+
accent2Color: '#003340',
+
accent3: '#00CCFF',
+
accent3Color: '#003340',
+
accent4: '#00CCFF',
+
accent4Color: '#003340'
+
},
+
monoGreen: {
+
name: "Mono Green",
+
background: '#022b00',
+
color: '#0BFF00',
+
descBackground: '#022b00',
+
descColor: '#0BFF00',
+
accent: '#0BFF00',
+
accentColor: '#034000',
+
accent2: '#0BFF00',
+
accent2Color: '#034000',
+
accent3: '#0BFF00',
+
accent3Color: '#034000',
+
accent4: '#0BFF00',
+
accent4Color: '#034000'
+
},
+
monoRed: {
+
name: "Mono Red",
+
background: '#2b0c00',
+
color: '#FF3600',
+
descBackground: '#2b0c00',
+
descColor: '#FF3600',
+
accent: '#FF3600',
+
accentColor: '#401200',
+
accent2: '#FF3600',
+
accent2Color: '#401200',
+
accent3: '#FF3600',
+
accent3Color: '#401200',
+
accent4: '#FF3600',
+
accent4Color: '#401200'
+
},
+
monoWhite: {
+
name: "Mono White",
+
background: '#262626',
+
color: '#FAFAFA',
+
descBackground: '#262626',
+
descColor: '#FAFAFA',
+
accent: '#FAFAFA',
+
accentColor: '#3B3B3B',
+
accent2: '#FAFAFA',
+
accent2Color: '#3B3B3B',
+
accent3: '#FAFAFA',
+
accent3Color: '#3B3B3B',
+
accent4: '#FAFAFA',
+
accent4Color: '#3B3B3B'
+
},
+
monoYellow: {
+
name: "Mono Yellow",
+
background: '#2b2400',
+
color: '#FFD300',
+
descBackground: '#2b2400',
+
descColor: '#FFD300',
+
accent: '#FFD300',
+
accentColor: '#403500',
+
accent2: '#FFD300',
+
accent2Color: '#403500',
+
accent3: '#FFD300',
+
accent3Color: '#403500',
+
accent4: '#FFD300',
+
accent4Color: '#403500'
+
},
+
seaShells: {
+
name: "Sea Shells",
+
background: '#09141b',
+
color: '#DEB88D',
+
descBackground: '#09141b',
+
descColor: '#FEE4CE',
+
accent: '#D15123',
+
accentColor: '#FEE4CE',
+
accent2: '#027C9B',
+
accent2Color: '#FEE4CE',
+
accent3: '#1E4950',
+
accent3Color: '#FEE4CE',
+
accent4: '#434B53',
+
accent4Color: '#FEE4CE'
+
},
+
seafoamPastel: {
+
name: "Seafoam Pastel",
+
background: '#243435',
+
color: '#E0E0E0',
+
descBackground: '#243435',
+
descColor: '#E0E0E0',
+
accent: '#825D4D',
+
accentColor: '#FEE4CE',
+
accent2: '#728C62',
+
accent2Color: '#FEE4CE',
+
accent3: '#ADA16D',
+
accent3Color: '#FEE4CE',
+
accent4: '#4D7B82',
+
accent4Color: '#FEE4CE'
+
},
+
seoul256: {
+
name: "Seoul 256",
+
background: '#3a3a3a',
+
color: '#e4e4e4',
+
descBackground: '#4e4e4e',
+
descColor: '#d0d0d0',
+
accent: '#d68787',
+
accentColor: '#4e4e4e',
+
accent2: '#87af87',
+
accent2Color: '#4e4e4e',
+
accent3: '#add4fb',
+
accent3Color: '#4e4e4e',
+
accent4: '#d7afaf',
+
accent4Color: '#4e4e4e'
+
},
+
seoul256Light: {
+
name: "Seoul 256 Light",
+
background: '#dadada',
+
color: '#4e4e4e',
+
descBackground: '#e4e4e4',
+
descColor: '#3a3a3a',
+
accent: '#870100',
+
accentColor: '#eeeeee',
+
accent2: '#d8865f',
+
accent2Color: '#eeeeee',
+
accent3: '#87025f',
+
accent3Color: '#eeeeee',
+
accent4: '#008787',
+
accent4Color: '#eeeeee'
+
},
+
shel: {
+
name: "Shel",
+
background: '#2C2423',
+
color: '#8FBAEC',
+
descBackground: '#2C2423',
+
descColor: '#F5EEEC',
+
accent: '#F588B9',
+
accentColor: '#F5EEEC',
+
accent2: '#AB6423',
+
accent2Color: '#F5EEEC',
+
accent3: '#2C64A2',
+
accent3Color: '#F5EEEC',
+
accent4: '#6C24A2',
+
accent4Color: '#F5EEEC'
+
},
+
slate: {
+
name: "Slate",
+
background: '#222222',
+
color: '#8CDFE0',
+
descBackground: '#222222',
+
descColor: '#E0E0E0',
+
accent: '#E2A8BF',
+
accentColor: '#222222',
+
accent2: '#81D778',
+
accent2Color: '#222222',
+
accent3: '#C4C9C0',
+
accent3Color: '#222222',
+
accent4: '#A481D3',
+
accent4Color: '#222222'
+
},
+
vaughn: {
+
name: "Vaughn",
+
background: '#25234F',
+
color: '#FFFFFF',
+
descBackground: '#25234F',
+
descColor: '#FFFFFF',
+
accent: '#60B48A',
+
accentColor: '#25234F',
+
accent2: '#DFAF8F',
+
accent2Color: '#25234F',
+
accent3: '#F08CC3',
+
accent3Color: '#25234F',
+
accent4: '#8CD0D3',
+
accent4Color: '#25234F'
+
},
+
warmNeon: {
+
name: "Warm Neon",
+
background: '#404040',
+
color: '#9CC090',
+
descBackground: '#404040',
+
descColor: '#FEFCFC',
+
accent: '#2ABBD4',
+
accentColor: '#FEFCFC',
+
accent2: '#39B13A',
+
accent2Color: '#FEFCFC',
+
accent3: '#4261C5',
+
accent3Color: '#FEFCFC',
+
accent4: '#F920FB',
+
accent4Color: '#FEFCFC'
+
},
+
website: {
+
name: "Website",
+
background: '#132f35',
+
color: '#ffd48f',
+
descBackground: '#183c44',
+
descColor: '#ffd48f',
+
accent: '#ff5757',
+
accentColor: '#235662',
+
accent2: '#ecff14',
+
accent2Color: '#235662',
+
accent3: '#4cbfff',
+
accent3Color: '#235662',
+
accent4: '#ff4cc2',
+
accent4Color: '#235662'
+
},
+
wryan: {
+
name: "Wryan",
+
background: '#101010',
+
color: '#899CA1',
+
descBackground: '#101010',
+
descColor: '#f0efd0',
+
accent: '#8C4665',
+
accentColor: '#C0C0C0',
+
accent2: '#287373',
+
accent2Color: '#C0C0C0',
+
accent3: '#7C7C99',
+
accent3Color: '#C0C0C0',
+
accent4: '#395573',
+
accent4Color: '#C0C0C0'
+
},
+
zenburn: {
+
name: "Zenburn",
+
background: '#3a3a3a',
+
color: '#f0efd0',
+
descBackground: '#333333',
+
descColor: '#f0efd0',
+
accent: '#cc9393',
+
accentColor: '#333333',
+
accent2: '#dfaf87',
+
accent2Color: '#333333',
+
accent3: '#efef87',
+
accent3Color: '#333333',
+
accent4: '#bca3a3',
+
accent4Color: '#333333'
+
},
+
sunset: {
+
name: "Sunset",
+
background: '#c757ab',
+
color: '#FFFFFF',
+
descBackground: '#FFFFFF',
+
descColor: '#2a2a2a',
+
accent: '#ff8c00',
+
accentColor: '#FFFFFF',
+
accent2: '#c5b95c',
+
accent2Color: '#FFFFFF',
+
accent3: '#ff69b4',
+
accent3Color: '#FFFFFF',
+
accent4: '#000069',
+
accent4Color: '#FFFFFF'
}
}
-30
src/lib/titleFonts.js
···
weight: 700
}
]
-
},
-
datalegreyathin: {
-
displayName: 'Datalegreya Thin',
-
defs: [
-
{
-
path: '/fonts/Datalegreya-Thin.otf',
-
style: 'normal',
-
weight: 400
-
}
-
]
-
},
-
datalegreyadot: {
-
displayName: 'Datalegreya Dot',
-
defs: [
-
{
-
path: '/fonts/Datalegreya-Dot.otf',
-
style: 'normal',
-
weight: 400
-
}
-
]
-
},
-
datalegreyagradient: {
-
displayName: 'Datalegreya Gradient',
-
defs: [
-
{
-
path: '/fonts/Datalegreya-Gradient.otf',
-
style: 'normal',
-
weight: 400
-
}
-
]
}
}