From c9b9a4bfc639fa4d998e5da1b9e4b9ebba54312a Mon Sep 17 00:00:00 2001 From: Rob Gordon Date: Wed, 28 Feb 2024 11:49:49 -0500 Subject: [PATCH 1/4] Creation of static package --- api/img/png.ts | 68 +++ api/package.json | 3 +- pnpm-lock.yaml | 1020 +++++++++++++++++++++++++++++++++++++++- pnpm-workspace.yaml | 1 + static/.gitignore | 1 + static/README.md | 3 + static/dist/index.html | 33 ++ static/index.html | 18 + static/index.ts | 42 ++ static/package.json | 28 ++ static/src/getPage.ts | 34 ++ static/src/script.ts | 20 + static/tsconfig.json | 20 + static/vite.config.ts | 6 + 14 files changed, 1283 insertions(+), 14 deletions(-) create mode 100644 api/img/png.ts create mode 100644 static/.gitignore create mode 100644 static/README.md create mode 100644 static/dist/index.html create mode 100644 static/index.html create mode 100644 static/index.ts create mode 100644 static/package.json create mode 100644 static/src/getPage.ts create mode 100644 static/src/script.ts create mode 100644 static/tsconfig.json create mode 100644 static/vite.config.ts diff --git a/api/img/png.ts b/api/img/png.ts new file mode 100644 index 00000000..e79be709 --- /dev/null +++ b/api/img/png.ts @@ -0,0 +1,68 @@ +import { VercelApiHandler } from "@vercel/node"; +import { supabase } from "../_lib/_supabase"; +import { getPng } from "static"; +import { parse, toCytoscapeElements } from "graph-selector"; + +/** +NEXT STEP +- get cytoscape installed either her or in a third package and render anything +*/ + +// This handler is going to produce a static png image of a given id +const handler: VercelApiHandler = async (req, res) => { + // get id from the query + const id = req.query.id; + + if (!id) { + res.status(400).send("id is required"); + return; + } + + // loop up code in database + const chart = await supabase + .from("user_charts") + .select("*") + .eq("id", id) + .single(); + + if (!isValid(chart)) { + res.status(404).send("Chart not found"); + return; + } + + const { content, meta } = parseChart(chart.data.chart); + console.log(meta); + const graph = parse(content); + const elements = toCytoscapeElements(graph); + + const base64Str = await getPng({ elements }); + + res.setHeader("Content-Type", "image/png"); + res.setHeader("Cache-Control", "public, max-age=31536000, immutable"); + res.send(Buffer.from(base64Str, "base64")); +}; + +export default handler; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function isValid(project: any): project is { data: { chart: string } } { + return ( + typeof project === "object" && + project !== null && + typeof project?.data === "object" && + project?.data !== null && + typeof project?.data?.chart === "string" + ); +} + +/** + * Given a chart string, parses it into + */ +function parseChart(chart: string) { + const [content, metaStr] = chart.split("====="); + const meta = JSON.parse(metaStr); + return { + content, + meta, + }; +} diff --git a/api/package.json b/api/package.json index cd021e8a..47802daa 100644 --- a/api/package.json +++ b/api/package.json @@ -30,7 +30,8 @@ "shared": "workspace:*", "stripe": "^11.11.0", "zod": "^3.22.4", - "zod-to-json-schema": "^3.22.3" + "zod-to-json-schema": "^3.22.3", + "static": "workspace:*" }, "devDependencies": { "@swc/jest": "^0.2.24", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9d29910e..9a8d8a4a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -71,6 +71,9 @@ importers: shared: specifier: workspace:* version: link:../shared + static: + specifier: workspace:* + version: link:../static stripe: specifier: ^11.11.0 version: 11.11.0 @@ -320,7 +323,7 @@ importers: version: 1.4.1(react@18.2.0) postcss-flexbugs-fixes: specifier: ^5.0.2 - version: 5.0.2(postcss@8.4.31) + version: 5.0.2(postcss@8.4.35) posthog-js: specifier: ^1.100.0 version: 1.100.0 @@ -561,7 +564,7 @@ importers: version: 1.82.1 tailwindcss: specifier: ^3.2.6 - version: 3.2.6(postcss@8.4.31)(ts-node@10.9.1) + version: 3.2.6(postcss@8.4.35)(ts-node@10.9.1) ts-node: specifier: ^10.9.1 version: 10.9.1(@types/node@18.16.17)(typescript@5.2.2) @@ -614,6 +617,37 @@ importers: specifier: ^5.2.2 version: 5.2.2 + static: + dependencies: + '@sparticuz/chromium-min': + specifier: 119.0.0 + version: 119.0.0 + cytoscape: + specifier: ^3.26.0 + version: 3.26.0 + cytoscape-dagre: + specifier: ^2.5.0 + version: 2.5.0(cytoscape@3.26.0) + puppeteer-core: + specifier: 21.5.1 + version: 21.5.1 + devDependencies: + '@types/cytoscape': + specifier: ^3.19.11 + version: 3.19.11 + '@types/cytoscape-dagre': + specifier: ^2.3.3 + version: 2.3.3 + typescript: + specifier: ^5.2.2 + version: 5.2.2 + vite: + specifier: ^5.1.4 + version: 5.1.4 + vite-plugin-singlefile: + specifier: ^2.0.0 + version: 2.0.0(rollup@4.12.0)(vite@5.1.4) + packages: /@aashutoshrathi/word-wrap@1.2.6: @@ -3626,6 +3660,15 @@ packages: - typescript dev: true + /@esbuild/aix-ppc64@0.19.12: + resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm64@0.18.20: resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} engines: {node: '>=12'} @@ -3635,6 +3678,15 @@ packages: dev: true optional: true + /@esbuild/android-arm64@0.19.12: + resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm@0.18.20: resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} engines: {node: '>=12'} @@ -3644,6 +3696,15 @@ packages: dev: true optional: true + /@esbuild/android-arm@0.19.12: + resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-x64@0.18.20: resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} engines: {node: '>=12'} @@ -3653,6 +3714,15 @@ packages: dev: true optional: true + /@esbuild/android-x64@0.19.12: + resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-arm64@0.18.20: resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} engines: {node: '>=12'} @@ -3662,6 +3732,15 @@ packages: dev: true optional: true + /@esbuild/darwin-arm64@0.19.12: + resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-x64@0.18.20: resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} engines: {node: '>=12'} @@ -3671,6 +3750,15 @@ packages: dev: true optional: true + /@esbuild/darwin-x64@0.19.12: + resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-arm64@0.18.20: resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} engines: {node: '>=12'} @@ -3680,6 +3768,15 @@ packages: dev: true optional: true + /@esbuild/freebsd-arm64@0.19.12: + resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-x64@0.18.20: resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} engines: {node: '>=12'} @@ -3689,6 +3786,15 @@ packages: dev: true optional: true + /@esbuild/freebsd-x64@0.19.12: + resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm64@0.18.20: resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} engines: {node: '>=12'} @@ -3698,6 +3804,15 @@ packages: dev: true optional: true + /@esbuild/linux-arm64@0.19.12: + resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm@0.18.20: resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} engines: {node: '>=12'} @@ -3707,6 +3822,15 @@ packages: dev: true optional: true + /@esbuild/linux-arm@0.19.12: + resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ia32@0.18.20: resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} engines: {node: '>=12'} @@ -3716,6 +3840,15 @@ packages: dev: true optional: true + /@esbuild/linux-ia32@0.19.12: + resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-loong64@0.18.20: resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} engines: {node: '>=12'} @@ -3725,6 +3858,15 @@ packages: dev: true optional: true + /@esbuild/linux-loong64@0.19.12: + resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-mips64el@0.18.20: resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} engines: {node: '>=12'} @@ -3734,6 +3876,15 @@ packages: dev: true optional: true + /@esbuild/linux-mips64el@0.19.12: + resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ppc64@0.18.20: resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} engines: {node: '>=12'} @@ -3743,6 +3894,15 @@ packages: dev: true optional: true + /@esbuild/linux-ppc64@0.19.12: + resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-riscv64@0.18.20: resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} engines: {node: '>=12'} @@ -3752,6 +3912,15 @@ packages: dev: true optional: true + /@esbuild/linux-riscv64@0.19.12: + resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-s390x@0.18.20: resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} engines: {node: '>=12'} @@ -3761,6 +3930,15 @@ packages: dev: true optional: true + /@esbuild/linux-s390x@0.19.12: + resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-x64@0.18.20: resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} engines: {node: '>=12'} @@ -3770,6 +3948,15 @@ packages: dev: true optional: true + /@esbuild/linux-x64@0.19.12: + resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/netbsd-x64@0.18.20: resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} engines: {node: '>=12'} @@ -3779,6 +3966,15 @@ packages: dev: true optional: true + /@esbuild/netbsd-x64@0.19.12: + resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/openbsd-x64@0.18.20: resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} engines: {node: '>=12'} @@ -3788,6 +3984,15 @@ packages: dev: true optional: true + /@esbuild/openbsd-x64@0.19.12: + resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/sunos-x64@0.18.20: resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} engines: {node: '>=12'} @@ -3797,6 +4002,15 @@ packages: dev: true optional: true + /@esbuild/sunos-x64@0.19.12: + resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-arm64@0.18.20: resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} engines: {node: '>=12'} @@ -3806,6 +4020,15 @@ packages: dev: true optional: true + /@esbuild/win32-arm64@0.19.12: + resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-ia32@0.18.20: resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} engines: {node: '>=12'} @@ -3815,6 +4038,15 @@ packages: dev: true optional: true + /@esbuild/win32-ia32@0.19.12: + resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-x64@0.18.20: resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} engines: {node: '>=12'} @@ -3824,6 +4056,15 @@ packages: dev: true optional: true + /@esbuild/win32-x64@0.19.12: + resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.24.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -5819,6 +6060,22 @@ packages: webpack-dev-server: 4.15.1(webpack@5.88.2) dev: false + /@puppeteer/browsers@1.8.0: + resolution: {integrity: sha512-TkRHIV6k2D8OlUe8RtG+5jgOF/H98Myx0M6AOafC8DdNVOFiBSFa5cpRDtpm8LXOa9sVwe0+e6Q3FC56X/DZfg==} + engines: {node: '>=16.3.0'} + hasBin: true + dependencies: + debug: 4.3.4 + extract-zip: 2.0.1 + progress: 2.0.3 + proxy-agent: 6.3.1 + tar-fs: 3.0.4 + unbzip2-stream: 1.4.3 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + dev: false + /@radix-ui/number@1.0.0: resolution: {integrity: sha512-Ofwh/1HX69ZfJRiRBMTy7rgjAzHmwe4kW9C9Y99HTRUcYLUuVT0KESFj15rPjRgKJs20GPq8Bm5aEDJ8DuA3vA==} dependencies: @@ -7146,6 +7403,110 @@ packages: picomatch: 2.3.1 dev: true + /@rollup/rollup-android-arm-eabi@4.12.0: + resolution: {integrity: sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-android-arm64@4.12.0: + resolution: {integrity: sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-arm64@4.12.0: + resolution: {integrity: sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-x64@4.12.0: + resolution: {integrity: sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-gnueabihf@4.12.0: + resolution: {integrity: sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-gnu@4.12.0: + resolution: {integrity: sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-musl@4.12.0: + resolution: {integrity: sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-riscv64-gnu@4.12.0: + resolution: {integrity: sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-gnu@4.12.0: + resolution: {integrity: sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-musl@4.12.0: + resolution: {integrity: sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-arm64-msvc@4.12.0: + resolution: {integrity: sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-ia32-msvc@4.12.0: + resolution: {integrity: sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-x64-msvc@4.12.0: + resolution: {integrity: sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@rushstack/eslint-patch@1.5.1: resolution: {integrity: sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA==} dev: false @@ -7294,6 +7655,16 @@ packages: '@sinonjs/commons': 1.8.6 dev: false + /@sparticuz/chromium-min@119.0.0: + resolution: {integrity: sha512-R5st9YN8mBMBWBXC/rDoKWgTB+thwoLTmAQ6CKjbPc9IGrHV9CMq/YMileh8l/eb5K7whmZeCoTd+3/m11ZA0w==} + engines: {node: '>= 16'} + dependencies: + follow-redirects: 1.15.5 + tar-fs: 3.0.5 + transitivePeerDependencies: + - debug + dev: false + /@stripe/react-stripe-js@2.1.0(@stripe/stripe-js@1.52.1)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-Zb6Ycrj5QuhYkvtlvvLzo+cysUyA6wkx3zWHQ7uVnHRYRM/n1jtQD6VGBrdmptC8e8PJN6L091gBCyB5P0FqmA==} peerDependencies: @@ -8011,6 +8382,10 @@ packages: engines: {node: '>= 10'} dev: true + /@tootallnate/quickjs-emscripten@0.23.0: + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + dev: false + /@trysound/sax@0.2.0: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -8144,6 +8519,12 @@ packages: resolution: {integrity: sha512-nl09VhutdjINdWyXxHWN/w9zlNCfr60JUqJbd24YXUuCwgeL0TpFSdElCwb6cxfB6ybE19Gjj4g0jsgkXxKv1Q==} dev: true + /@types/cytoscape-dagre@2.3.3: + resolution: {integrity: sha512-FJBsNMbBZpqNwT6rp5leVYMevWUjnyD1QS8erNMAMWoBifvaVUklXIjE+bllLDSowjM3abXuRvljliSXUU+d1A==} + dependencies: + '@types/cytoscape': 3.19.11 + dev: true + /@types/cytoscape-fcose@2.2.2: resolution: {integrity: sha512-C576Xjaga9/he4Isef5HiBbN8KWZRWRh1V2fvFsKezmwhPlE6op25CtX5xYgSq0CO45j/FyNmRwlEritT93bOA==} dependencies: @@ -8193,6 +8574,10 @@ packages: /@types/estree@1.0.2: resolution: {integrity: sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==} + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: true + /@types/events@3.0.0: resolution: {integrity: sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==} dev: true @@ -8581,6 +8966,14 @@ packages: '@types/yargs-parser': 21.0.1 dev: false + /@types/yauzl@2.10.3: + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + requiresBuild: true + dependencies: + '@types/node': 18.16.17 + dev: false + optional: true + /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.50.0)(typescript@5.2.2): resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -9262,6 +9655,15 @@ packages: transitivePeerDependencies: - supports-color + /agent-base@7.1.0: + resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} + engines: {node: '>= 14'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /agentkeepalive@4.5.0: resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} engines: {node: '>= 8.0.0'} @@ -9537,6 +9939,13 @@ packages: /ast-types-flow@0.0.7: resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} + /ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + dependencies: + tslib: 2.6.2 + dev: false + /astral-regex@2.0.0: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} @@ -9615,6 +10024,10 @@ packages: dependencies: dequal: 2.0.3 + /b4a@1.6.6: + resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==} + dev: false + /babel-jest@27.5.1(@babel/core@7.23.0): resolution: {integrity: sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -9896,6 +10309,37 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + /bare-events@2.2.0: + resolution: {integrity: sha512-Yyyqff4PIFfSuthCZqLlPISTWHmnQxoPuAvkmgzsJEmG3CesdIv6Xweayl0JkCZJSB2yYIdJyEz97tpxNhgjbg==} + requiresBuild: true + dev: false + optional: true + + /bare-fs@2.2.0: + resolution: {integrity: sha512-+VhW202E9eTVGkX7p+TNXtZC4RTzj9JfJW7PtfIbZ7mIQ/QT9uOafQTx7lx2n9ERmWsXvLHF4hStAFn4gl2mQw==} + requiresBuild: true + dependencies: + bare-events: 2.2.0 + bare-os: 2.2.0 + bare-path: 2.1.0 + streamx: 2.16.1 + dev: false + optional: true + + /bare-os@2.2.0: + resolution: {integrity: sha512-hD0rOPfYWOMpVirTACt4/nK8mC55La12K5fY1ij8HAdfQakD62M+H4o4tpfKzVGLgRDTuk3vjA4GqGXXCeFbag==} + requiresBuild: true + dev: false + optional: true + + /bare-path@2.1.0: + resolution: {integrity: sha512-DIIg7ts8bdRKwJRJrUMy/PICEaQZaPGZ26lsSx9MJSwIhSrcdHn7/C8W+XmnG/rKi6BaRcz+JO00CjZteybDtw==} + requiresBuild: true + dependencies: + bare-os: 2.2.0 + dev: false + optional: true + /base-64@0.1.0: resolution: {integrity: sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==} dev: false @@ -9909,6 +10353,11 @@ packages: /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + /basic-ftp@5.0.5: + resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} + engines: {node: '>=10.0.0'} + dev: false + /batch@0.6.1: resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} dev: false @@ -10075,6 +10524,10 @@ packages: hasBin: true dev: true + /buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + dev: false + /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -10083,7 +10536,6 @@ packages: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 - dev: true /buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} @@ -10299,6 +10751,16 @@ packages: resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} engines: {node: '>=6.0'} + /chromium-bidi@0.4.33(devtools-protocol@0.0.1203626): + resolution: {integrity: sha512-IxoFM5WGQOIAd95qrSXzJUv4eXIrh+RvU3rwwqIiwYuvfE7U/Llj4fejbsJnjJMUYCuGtVQsY2gv7oGl4aTNSQ==} + peerDependencies: + devtools-protocol: '*' + dependencies: + devtools-protocol: 0.0.1203626 + mitt: 3.0.1 + urlpattern-polyfill: 9.0.0 + dev: false + /ci-info@3.4.0: resolution: {integrity: sha512-t5QdPT5jq3o262DOQ8zA6E1tlH2upmUc4Hlvrbx1pGYJuiiHl7O7rvVNI+l8HTVhd/q3Qc9vqimkNk5yiXsAug==} dev: true @@ -10386,7 +10848,6 @@ packages: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: true /clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} @@ -10725,6 +11186,14 @@ packages: - encoding dev: false + /cross-fetch@4.0.0: + resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -11068,6 +11537,11 @@ packages: engines: {node: '>= 12'} dev: true + /data-uri-to-buffer@6.0.2: + resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} + engines: {node: '>= 14'} + dev: false + /data-urls@2.0.0: resolution: {integrity: sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==} engines: {node: '>=10'} @@ -11213,6 +11687,15 @@ packages: /defined@1.0.0: resolution: {integrity: sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==} + /degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + dev: false + /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -11278,6 +11761,10 @@ packages: defined: 1.0.0 minimist: 1.2.6 + /devtools-protocol@0.0.1203626: + resolution: {integrity: sha512-nEzHZteIUZfGCZtTiS1fRpC8UZmsfD1SiyPvaUNvS13dvKf666OAm8YTi0+Ca3n1nLEyu49Cy4+dPWpaHFJk9g==} + dev: false + /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} @@ -11511,6 +11998,12 @@ packages: engines: {node: '>= 0.8'} dev: false + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: false + /enhanced-resolve@5.15.0: resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} engines: {node: '>=10.13.0'} @@ -11940,6 +12433,37 @@ packages: '@esbuild/win32-x64': 0.18.20 dev: true + /esbuild@0.19.12: + resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.19.12 + '@esbuild/android-arm': 0.19.12 + '@esbuild/android-arm64': 0.19.12 + '@esbuild/android-x64': 0.19.12 + '@esbuild/darwin-arm64': 0.19.12 + '@esbuild/darwin-x64': 0.19.12 + '@esbuild/freebsd-arm64': 0.19.12 + '@esbuild/freebsd-x64': 0.19.12 + '@esbuild/linux-arm': 0.19.12 + '@esbuild/linux-arm64': 0.19.12 + '@esbuild/linux-ia32': 0.19.12 + '@esbuild/linux-loong64': 0.19.12 + '@esbuild/linux-mips64el': 0.19.12 + '@esbuild/linux-ppc64': 0.19.12 + '@esbuild/linux-riscv64': 0.19.12 + '@esbuild/linux-s390x': 0.19.12 + '@esbuild/linux-x64': 0.19.12 + '@esbuild/netbsd-x64': 0.19.12 + '@esbuild/openbsd-x64': 0.19.12 + '@esbuild/sunos-x64': 0.19.12 + '@esbuild/win32-arm64': 0.19.12 + '@esbuild/win32-ia32': 0.19.12 + '@esbuild/win32-x64': 0.19.12 + dev: true + /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -12715,6 +13239,20 @@ packages: tmp: 0.0.33 dev: true + /extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + dependencies: + debug: 4.3.4 + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + dev: false + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -12722,6 +13260,10 @@ packages: resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} dev: true + /fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + dev: false + /fast-glob@3.2.12: resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} engines: {node: '>=8.6.0'} @@ -12765,6 +13307,12 @@ packages: dependencies: bser: 2.1.1 + /fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + dependencies: + pend: 1.2.0 + dev: false + /fetch-blob@3.2.0: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} @@ -12913,6 +13461,16 @@ packages: optional: true dev: false + /follow-redirects@1.15.5: + resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: @@ -13024,6 +13582,15 @@ packages: jsonfile: 6.1.0 universalify: 2.0.0 + /fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: false + /fs-extra@9.1.0: resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} engines: {node: '>=10'} @@ -13146,6 +13713,13 @@ packages: engines: {node: '>=6'} dev: true + /get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + dependencies: + pump: 3.0.0 + dev: false + /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -13157,6 +13731,18 @@ packages: call-bind: 1.0.2 get-intrinsic: 1.1.3 + /get-uri@6.0.3: + resolution: {integrity: sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==} + engines: {node: '>= 14'} + dependencies: + basic-ftp: 5.0.5 + data-uri-to-buffer: 6.0.2 + debug: 4.3.4 + fs-extra: 11.2.0 + transitivePeerDependencies: + - supports-color + dev: false + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -13567,6 +14153,16 @@ packages: - supports-color dev: true + /http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /http-proxy-middleware@2.0.6(@types/express@4.17.18): resolution: {integrity: sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==} engines: {node: '>=12.0.0'} @@ -13591,7 +14187,7 @@ packages: engines: {node: '>=8.0.0'} dependencies: eventemitter3: 4.0.7 - follow-redirects: 1.15.3 + follow-redirects: 1.15.5 requires-port: 1.0.0 transitivePeerDependencies: - debug @@ -13606,6 +14202,16 @@ packages: transitivePeerDependencies: - supports-color + /https-proxy-agent@7.0.4: + resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -13794,6 +14400,14 @@ packages: loose-envify: 1.4.0 dev: false + /ip-address@9.0.5: + resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + engines: {node: '>= 12'} + dependencies: + jsbn: 1.1.0 + sprintf-js: 1.1.3 + dev: false + /ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} @@ -14300,7 +14914,7 @@ packages: jest-util: 29.4.3 jest-validate: 29.4.3 prompts: 2.4.2 - yargs: 17.6.0 + yargs: 17.7.2 transitivePeerDependencies: - '@types/node' - supports-color @@ -15188,6 +15802,10 @@ packages: dependencies: argparse: 2.0.1 + /jsbn@1.1.0: + resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + dev: false + /jsdom@16.7.0: resolution: {integrity: sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==} engines: {node: '>=10'} @@ -15716,6 +16334,11 @@ packages: dependencies: yallist: 4.0.0 + /lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + dev: false + /lz-string@1.4.4: resolution: {integrity: sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==} hasBin: true @@ -16000,6 +16623,14 @@ packages: yallist: 4.0.0 dev: true + /mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + dev: false + + /mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + dev: false + /mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true @@ -16159,6 +16790,11 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + /natural-compare-lite@1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} @@ -16174,6 +16810,11 @@ packages: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} dev: false + /netmask@2.0.2: + resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} + engines: {node: '>= 0.4.0'} + dev: false + /next-tick@1.1.0: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} dev: false @@ -16654,6 +17295,30 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + /pac-proxy-agent@7.0.1: + resolution: {integrity: sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==} + engines: {node: '>= 14'} + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.0 + debug: 4.3.4 + get-uri: 6.0.3 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.4 + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.2 + transitivePeerDependencies: + - supports-color + dev: false + + /pac-resolver@7.0.1: + resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} + engines: {node: '>= 14'} + dependencies: + degenerator: 5.0.1 + netmask: 2.0.2 + dev: false + /pako@2.1.0: resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} dev: false @@ -16672,9 +17337,6 @@ packages: resolution: {integrity: sha512-2GTVocFkwblV/TIg9AmT7TI2fO4xdWkyN8aFUEVtiVNWt96GTR3FgQyHFValfCbcj1k9Xf962Ws2hYXYUr9k1Q==} engines: {node: '>= 12.0.0'} hasBin: true - peerDependenciesMeta: - '@parcel/core': - optional: true dependencies: '@parcel/config-default': 2.9.3(@parcel/core@2.9.3)(postcss@8.4.31) '@parcel/core': 2.9.3 @@ -16791,6 +17453,10 @@ packages: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} dev: true + /pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + dev: false + /performance-now@2.1.0: resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} dev: false @@ -17067,6 +17733,14 @@ packages: postcss: 8.4.31 dev: false + /postcss-flexbugs-fixes@5.0.2(postcss@8.4.35): + resolution: {integrity: sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==} + peerDependencies: + postcss: ^8.1.4 + dependencies: + postcss: 8.4.35 + dev: false + /postcss-focus-visible@6.0.4(postcss@8.4.31): resolution: {integrity: sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==} engines: {node: ^12 || ^14 || >=16} @@ -17125,6 +17799,18 @@ packages: read-cache: 1.0.0 resolve: 1.22.1 + /postcss-import@14.1.0(postcss@8.4.35): + resolution: {integrity: sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==} + engines: {node: '>=10.0.0'} + peerDependencies: + postcss: ^8.0.0 + dependencies: + postcss: 8.4.35 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.1 + dev: true + /postcss-initial@4.0.1(postcss@8.4.31): resolution: {integrity: sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==} peerDependencies: @@ -17142,6 +17828,16 @@ packages: camelcase-css: 2.0.1 postcss: 8.4.31 + /postcss-js@4.0.1(postcss@8.4.35): + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.35 + dev: true + /postcss-lab-function@4.2.1(postcss@8.4.31): resolution: {integrity: sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==} engines: {node: ^12 || ^14 || >=16} @@ -17170,6 +17866,24 @@ packages: ts-node: 10.9.1(@types/node@18.16.17)(typescript@5.2.2) yaml: 1.10.2 + /postcss-load-config@3.1.4(postcss@8.4.35)(ts-node@10.9.1): + resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} + engines: {node: '>= 10'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + dependencies: + lilconfig: 2.0.6 + postcss: 8.4.35 + ts-node: 10.9.1(@types/node@18.16.17)(typescript@5.2.2) + yaml: 1.10.2 + dev: true + /postcss-loader@6.2.1(postcss@8.4.31)(webpack@5.88.2): resolution: {integrity: sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==} engines: {node: '>= 12.13.0'} @@ -17326,6 +18040,16 @@ packages: postcss: 8.4.31 postcss-selector-parser: 6.0.13 + /postcss-nested@6.0.0(postcss@8.4.35): + resolution: {integrity: sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + dependencies: + postcss: 8.4.35 + postcss-selector-parser: 6.0.13 + dev: true + /postcss-nesting@10.2.0(postcss@8.4.31): resolution: {integrity: sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==} engines: {node: ^12 || ^14 || >=16} @@ -17630,6 +18354,14 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /postcss@8.4.35: + resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.0.2 + /posthog-js@1.100.0: resolution: {integrity: sha512-r2XZEiHQ9mBK7D1G9k57I8uYZ2kZTAJ0OCX6K/OOdCWN8jKPhw3h5F9No5weilP6eVAn+hrsy7NvPV7SCX7gMg==} dependencies: @@ -17765,6 +18497,11 @@ packages: engines: {node: '>= 0.6.0'} dev: true + /progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + dev: false + /promise.series@0.2.0: resolution: {integrity: sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ==} engines: {node: '>=0.12'} @@ -17798,6 +18535,26 @@ packages: ipaddr.js: 1.9.1 dev: false + /proxy-agent@6.3.1: + resolution: {integrity: sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.4 + lru-cache: 7.18.3 + pac-proxy-agent: 7.0.1 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.2 + transitivePeerDependencies: + - supports-color + dev: false + + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + /pseudolocale@1.2.0: resolution: {integrity: sha512-k0OQFvIlvpRdzR0dPVrrbWX7eE9EaZ6gpZtTlFSDi1Gf9tMy9wiANCNu7JZ0drcKgUri/39a2mBbH0goiQmrmQ==} dependencies: @@ -17807,6 +18564,13 @@ packages: /psl@1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + /pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: false + /punycode@2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} @@ -17816,6 +18580,23 @@ packages: engines: {node: '>=6'} dev: false + /puppeteer-core@21.5.1: + resolution: {integrity: sha512-u6c3SZKAOaOQogaTkQvllxT/o2PP16wkbrUWINtMhfvrB4ko+xwqC1pb+vyCPMmNUh3N/CX5YGqb3DWx2fUPSQ==} + engines: {node: '>=16.3.0'} + dependencies: + '@puppeteer/browsers': 1.8.0 + chromium-bidi: 0.4.33(devtools-protocol@0.0.1203626) + cross-fetch: 4.0.0 + debug: 4.3.4 + devtools-protocol: 0.0.1203626 + ws: 8.14.2 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + dev: false + /q@1.5.1: resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} engines: {node: '>=0.6.0', teleport: '>=0.2.0'} @@ -17834,6 +18615,11 @@ packages: /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + /queue-tick@1.0.1: + resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} + requiresBuild: true + dev: false + /quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} @@ -18673,7 +19459,7 @@ packages: picomatch: 2.3.1 rollup: 2.79.1 source-map: 0.7.4 - yargs: 17.6.0 + yargs: 17.7.2 dev: true /rollup-pluginutils@2.8.2: @@ -18697,6 +19483,29 @@ packages: fsevents: 2.3.3 dev: true + /rollup@4.12.0: + resolution: {integrity: sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.12.0 + '@rollup/rollup-android-arm64': 4.12.0 + '@rollup/rollup-darwin-arm64': 4.12.0 + '@rollup/rollup-darwin-x64': 4.12.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.12.0 + '@rollup/rollup-linux-arm64-gnu': 4.12.0 + '@rollup/rollup-linux-arm64-musl': 4.12.0 + '@rollup/rollup-linux-riscv64-gnu': 4.12.0 + '@rollup/rollup-linux-x64-gnu': 4.12.0 + '@rollup/rollup-linux-x64-musl': 4.12.0 + '@rollup/rollup-win32-arm64-msvc': 4.12.0 + '@rollup/rollup-win32-ia32-msvc': 4.12.0 + '@rollup/rollup-win32-x64-msvc': 4.12.0 + fsevents: 2.3.3 + dev: true + /run-async@2.4.1: resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} engines: {node: '>=0.12.0'} @@ -19037,6 +19846,11 @@ packages: is-fullwidth-code-point: 4.0.0 dev: true + /smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + dev: false + /sockjs@0.3.24: resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} dependencies: @@ -19045,6 +19859,25 @@ packages: websocket-driver: 0.7.4 dev: false + /socks-proxy-agent@8.0.2: + resolution: {integrity: sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + socks: 2.8.1 + transitivePeerDependencies: + - supports-color + dev: false + + /socks@2.8.1: + resolution: {integrity: sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + dependencies: + ip-address: 9.0.5 + smart-buffer: 4.2.0 + dev: false + /source-list-map@2.0.1: resolution: {integrity: sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==} dev: false @@ -19149,6 +19982,10 @@ packages: /sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + /sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + dev: false + /srcset@4.0.0: resolution: {integrity: sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==} engines: {node: '>=12'} @@ -19216,6 +20053,15 @@ packages: engines: {node: '>=10.0.0'} dev: false + /streamx@2.16.1: + resolution: {integrity: sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==} + dependencies: + fast-fifo: 1.3.2 + queue-tick: 1.0.1 + optionalDependencies: + bare-events: 2.2.0 + dev: false + /strict-event-emitter@0.2.7: resolution: {integrity: sha512-TavbHJ87WD2tDbKI7bTrmc6U4J4Qjh8E9fVvFkIFw2gCu34Wxstn2Yas0+4D78FJN8DOTEzxiT+udBdraRk4UQ==} dependencies: @@ -19572,6 +20418,40 @@ packages: transitivePeerDependencies: - ts-node + /tailwindcss@3.2.6(postcss@8.4.35)(ts-node@10.9.1): + resolution: {integrity: sha512-BfgQWZrtqowOQMC2bwaSNe7xcIjdDEgixWGYOd6AL0CbKHJlvhfdbINeAW76l1sO+1ov/MJ93ODJ9yluRituIw==} + engines: {node: '>=12.13.0'} + hasBin: true + peerDependencies: + postcss: ^8.0.9 + dependencies: + arg: 5.0.2 + chokidar: 3.5.3 + color-name: 1.1.4 + detective: 5.2.1 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.1 + glob-parent: 6.0.2 + is-glob: 4.0.3 + lilconfig: 2.1.0 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.0 + postcss: 8.4.35 + postcss-import: 14.1.0(postcss@8.4.35) + postcss-js: 4.0.1(postcss@8.4.35) + postcss-load-config: 3.1.4(postcss@8.4.35)(ts-node@10.9.1) + postcss-nested: 6.0.0(postcss@8.4.35) + postcss-selector-parser: 6.0.13 + postcss-value-parser: 4.2.0 + quick-lru: 5.1.1 + resolve: 1.22.6 + transitivePeerDependencies: + - ts-node + dev: true + /tapable@1.1.3: resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==} engines: {node: '>=6'} @@ -19582,6 +20462,32 @@ packages: engines: {node: '>=6'} dev: false + /tar-fs@3.0.4: + resolution: {integrity: sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==} + dependencies: + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 3.1.7 + dev: false + + /tar-fs@3.0.5: + resolution: {integrity: sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==} + dependencies: + pump: 3.0.0 + tar-stream: 3.1.7 + optionalDependencies: + bare-fs: 2.2.0 + bare-path: 2.1.0 + dev: false + + /tar-stream@3.1.7: + resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} + dependencies: + b4a: 1.6.6 + fast-fifo: 1.3.2 + streamx: 2.16.1 + dev: false + /tar@6.1.15: resolution: {integrity: sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==} engines: {node: '>=10'} @@ -19681,7 +20587,6 @@ packages: /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: true /thunky@1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} @@ -20071,6 +20976,13 @@ packages: has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 + /unbzip2-stream@1.4.3: + resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} + dependencies: + buffer: 5.7.1 + through: 2.3.8 + dev: false + /underscore@1.12.1: resolution: {integrity: sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==} dev: false @@ -20170,6 +21082,10 @@ packages: querystringify: 2.2.0 requires-port: 1.0.0 + /urlpattern-polyfill@9.0.0: + resolution: {integrity: sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==} + dev: false + /use-callback-ref@1.3.0(@types/react@18.2.15)(react@18.2.0): resolution: {integrity: sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==} engines: {node: '>=10'} @@ -20328,6 +21244,18 @@ packages: - terser dev: true + /vite-plugin-singlefile@2.0.0(rollup@4.12.0)(vite@5.1.4): + resolution: {integrity: sha512-0ADuhM0nLSTJAm/KhRLCHiAIhlmR70MajcLfJlIflbsPj02sKEQErzsiPhuSg/jt1nKBi7oLmuX718tYI2Fjdg==} + engines: {node: '>18.0.0'} + peerDependencies: + rollup: ^4.10.0 + vite: ^5.1.1 + dependencies: + micromatch: 4.0.5 + rollup: 4.12.0 + vite: 5.1.4 + dev: true + /vite@4.4.11(@types/node@18.16.17): resolution: {integrity: sha512-ksNZJlkcU9b0lBwAGZGGaZHCMqHsc8OpgtoYhsQ4/I2v5cnpmmmqe5pM4nv/4Hn6G/2GhTdj0DhZh2e+Er1q5A==} engines: {node: ^14.18.0 || >=16.0.0} @@ -20364,6 +21292,41 @@ packages: fsevents: 2.3.3 dev: true + /vite@5.1.4: + resolution: {integrity: sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + esbuild: 0.19.12 + postcss: 8.4.35 + rollup: 4.12.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /vitest@0.34.6: resolution: {integrity: sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==} engines: {node: '>=v14.18.0'} @@ -20583,7 +21546,7 @@ packages: spdy: 4.0.2 webpack: 5.88.2 webpack-dev-middleware: 5.3.3(webpack@5.88.2) - ws: 8.14.2 + ws: 8.16.0 transitivePeerDependencies: - bufferutil - debug @@ -21066,6 +22029,19 @@ packages: optional: true dev: false + /ws@8.16.0: + resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + /xml-name-validator@3.0.0: resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==} dev: false @@ -21117,7 +22093,6 @@ packages: /yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} - dev: true /yargs@16.2.0: resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} @@ -21144,6 +22119,25 @@ packages: yargs-parser: 21.1.1 dev: true + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + /yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + dev: false + /yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 94f832e0..aa0b75bc 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -3,5 +3,6 @@ packages: - "api" - "shared" - "formulaic" + - "static" # exclude packages that are inside test directories - "!**/test/**" diff --git a/static/.gitignore b/static/.gitignore new file mode 100644 index 00000000..1c2f433d --- /dev/null +++ b/static/.gitignore @@ -0,0 +1 @@ +tmp \ No newline at end of file diff --git a/static/README.md b/static/README.md new file mode 100644 index 00000000..5b7adf03 --- /dev/null +++ b/static/README.md @@ -0,0 +1,3 @@ +This package is responsible for rendering graphs statically. + +Install chrome `pnpm -F static chromium:install` \ No newline at end of file diff --git a/static/dist/index.html b/static/dist/index.html new file mode 100644 index 00000000..62645cfc --- /dev/null +++ b/static/dist/index.html @@ -0,0 +1,33 @@ + + + + + + Document + + + + +
+ + diff --git a/static/index.html b/static/index.html new file mode 100644 index 00000000..be954d4f --- /dev/null +++ b/static/index.html @@ -0,0 +1,18 @@ + + + + + + Document + + + +
+ + + diff --git a/static/index.ts b/static/index.ts new file mode 100644 index 00000000..a5162282 --- /dev/null +++ b/static/index.ts @@ -0,0 +1,42 @@ +import { getPage } from "./src/getPage"; +import { readFileSync } from "fs"; +import { join } from "path"; +import type { ElementDefinition } from "cytoscape"; + +/** + * Returns a base64 encoded PNG image of a cytoscape graph + */ +export async function getPng({ elements }: { elements: ElementDefinition[] }) { + const { page, browser } = await getPage(); + + // read the file from "./dist/index.html" + const indexHtml = join(__dirname, "dist/index.html"); + const html = readFileSync(indexHtml, "utf8"); + + // set the page content + await page.setContent(html); + + // execute code in the browser + await page.evaluate((elements) => { + console.log(window.cy); + // set elements + window.cy.json({ elements }); + window.cy.layout({ name: "grid" }).run(); + + // json stringify the elements, and write them to a fixed position + // div on the page so we can read them out in the next step + const elementsDiv = document.createElement("div"); + elementsDiv.id = "elements"; + elementsDiv.style.position = "fixed"; + elementsDiv.style.top = "0"; + elementsDiv.style.left = "0"; + elementsDiv.textContent = JSON.stringify(elements); + document.body.appendChild(elementsDiv); + }, elements); + + const screenshot = await page.screenshot({ encoding: "base64" }); + + await browser.close(); + + return screenshot; +} diff --git a/static/package.json b/static/package.json new file mode 100644 index 00000000..01d59a90 --- /dev/null +++ b/static/package.json @@ -0,0 +1,28 @@ +{ + "name": "static", + "version": "1.0.0", + "description": "", + "main": "index.ts", + "types": "index.ts", + "scripts": { + "chromium:install": "pnpm dlx @puppeteer/browsers install chromium@latest --path $(pwd)/tmp/chromium; echo 'Now run `sudo chmod -R 755 $(pwd)/tmp/chromium`'", + "dev": "vite", + "build": "vite build" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@types/cytoscape": "^3.19.11", + "@types/cytoscape-dagre": "^2.3.3", + "typescript": "^5.2.2", + "vite": "^5.1.4", + "vite-plugin-singlefile": "^2.0.0" + }, + "dependencies": { + "@sparticuz/chromium-min": "119.0.0", + "cytoscape": "^3.26.0", + "cytoscape-dagre": "^2.5.0", + "puppeteer-core": "21.5.1" + } +} diff --git a/static/src/getPage.ts b/static/src/getPage.ts new file mode 100644 index 00000000..325051ef --- /dev/null +++ b/static/src/getPage.ts @@ -0,0 +1,34 @@ +import chromium from "@sparticuz/chromium-min"; +import puppeteer, { Browser, Page } from "puppeteer-core"; +let page: Page; +let browser: Browser; + +async function getBrowser() { + // local development is broken for this 👇 + // but it works in vercel so I'm not gonna touch it + return puppeteer.launch({ + args: [...chromium.args, "--hide-scrollbars", "--disable-web-security"], + defaultViewport: chromium.defaultViewport, + executablePath: + "/Users/robgordon/Dev/flowchart-fun/static/tmp/chromium/chromium/mac_arm-1266189/chrome-mac/Chromium.app/Contents/MacOS/Chromium", + headless: true, + ignoreHTTPSErrors: true, + }); +} + +/** + * Gets a puppeteer page + */ +export async function getPage() { + try { + if (page && browser) return { page, browser }; + + browser = await getBrowser(); + page = await browser.newPage(); + page.setJavaScriptEnabled(true); + return { page, browser }; + } catch (error) { + console.error(error); + throw new Error("Failed to get page."); + } +} diff --git a/static/src/script.ts b/static/src/script.ts new file mode 100644 index 00000000..3c964225 --- /dev/null +++ b/static/src/script.ts @@ -0,0 +1,20 @@ +import cytoscape from "cytoscape"; + +const div = document.getElementById("cy"); + +const cy = cytoscape({ + container: div, + elements: [ + { data: { id: "a" } }, + { data: { id: "b" } }, + { data: { id: "ab", source: "a", target: "b" } }, + ], +}); + +window.cy = cy; + +declare global { + interface Window { + cy: cytoscape.Core; + } +} diff --git a/static/tsconfig.json b/static/tsconfig.json new file mode 100644 index 00000000..fb12e48e --- /dev/null +++ b/static/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "skipLibCheck": true, + "target": "es2022", + "allowJs": true, + "resolveJsonModule": true, + "moduleDetection": "force", + "isolatedModules": true, + "strict": true, + "noUncheckedIndexedAccess": true, + "composite": true, + "declarationMap": true, + "moduleResolution": "Bundler", + "module": "ESNext", + "noEmit": true, + "lib": ["es2022", "dom", "dom.iterable"] + }, + "include": ["./index.ts", "./src/**/*"] +} diff --git a/static/vite.config.ts b/static/vite.config.ts new file mode 100644 index 00000000..6756e79c --- /dev/null +++ b/static/vite.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import { viteSingleFile } from "vite-plugin-singlefile"; + +export default defineConfig({ + plugins: [viteSingleFile()], +}); From a8a3798b85a0d632a79232b93a19a6a5ed09954c Mon Sep 17 00:00:00 2001 From: Rob Gordon Date: Wed, 28 Feb 2024 13:41:40 -0500 Subject: [PATCH 2/4] Prepare movement to shared package --- pnpm-lock.yaml | 3 +++ shared/index.ts | 2 +- shared/{ => src}/ImportDataFormType.ts | 0 shared/tsconfig.json | 20 ++++++++++++++++++++ static/index.ts | 14 ++++++++++++++ static/package.json | 3 ++- 6 files changed, 40 insertions(+), 2 deletions(-) rename shared/{ => src}/ImportDataFormType.ts (100%) create mode 100644 shared/tsconfig.json diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9a8d8a4a..ce69e9b2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -631,6 +631,9 @@ importers: puppeteer-core: specifier: 21.5.1 version: 21.5.1 + shared: + specifier: workspace:* + version: link:../shared devDependencies: '@types/cytoscape': specifier: ^3.19.11 diff --git a/shared/index.ts b/shared/index.ts index 65c33cf1..c9de188b 100644 --- a/shared/index.ts +++ b/shared/index.ts @@ -1 +1 @@ -export * from "./ImportDataFormType"; +export * from "./src/ImportDataFormType"; diff --git a/shared/ImportDataFormType.ts b/shared/src/ImportDataFormType.ts similarity index 100% rename from shared/ImportDataFormType.ts rename to shared/src/ImportDataFormType.ts diff --git a/shared/tsconfig.json b/shared/tsconfig.json new file mode 100644 index 00000000..82dce430 --- /dev/null +++ b/shared/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "skipLibCheck": true, + "target": "es2022", + "allowJs": true, + "resolveJsonModule": true, + "moduleDetection": "force", + "isolatedModules": true, + "strict": true, + "noUncheckedIndexedAccess": true, + "composite": true, + "declarationMap": true, + "moduleResolution": "Node", + "module": "ESNext", + "noEmit": true, + "lib": ["es2022"] + }, + "include": ["./index.ts", "src"] +} diff --git a/static/index.ts b/static/index.ts index a5162282..0b8220f1 100644 --- a/static/index.ts +++ b/static/index.ts @@ -23,6 +23,20 @@ export async function getPng({ elements }: { elements: ElementDefinition[] }) { window.cy.json({ elements }); window.cy.layout({ name: "grid" }).run(); + // const themeEditor = getThemeEditor(doc); + // const { layout, style: themeStyle } = toTheme(themeEditor); + // const { style } = preprocessStyle( + // customCssOnly ? customCss : [themeStyle, customCss].join("\n") + // ); + // window.cy + // .layout({ + // ...layout, + // // @ts-ignore + // fit: true, + // padding: 20, + // }) + // .run(); + // json stringify the elements, and write them to a fixed position // div on the page so we can read them out in the next step const elementsDiv = document.createElement("div"); diff --git a/static/package.json b/static/package.json index 01d59a90..dbd0ed85 100644 --- a/static/package.json +++ b/static/package.json @@ -23,6 +23,7 @@ "@sparticuz/chromium-min": "119.0.0", "cytoscape": "^3.26.0", "cytoscape-dagre": "^2.5.0", - "puppeteer-core": "21.5.1" + "puppeteer-core": "21.5.1", + "shared": "workspace:*" } } From 69ce76a94fd34e0ecba9f876ebcfd6a0a753ce21 Mon Sep 17 00:00:00 2001 From: Rob Gordon Date: Wed, 28 Feb 2024 14:58:01 -0500 Subject: [PATCH 3/4] Duplicate FFTheme --- app/src/components/Graph.tsx | 3 +- app/src/components/LoadTemplateDialog.tsx | 2 +- app/src/components/Tabs/ThemeTab.tsx | 6 +- app/src/components/downloads.ts | 2 +- app/src/lib/prepareChart/prepareChart.ts | 2 +- app/src/lib/preprocessStyle.ts | 2 +- app/src/lib/templates/code-flow-template.ts | 2 +- app/src/lib/templates/default-template.ts | 2 +- app/src/lib/templates/flowchart-template.ts | 2 +- .../lib/templates/knowledge-graph-template.ts | 2 +- app/src/lib/templates/mindmap-template.ts | 2 +- app/src/lib/templates/org-chart-template.ts | 2 +- app/src/lib/toTheme.ts | 31 +------ app/src/lib/toThemeDynamic.ts | 31 +++++++ app/src/pages/New.tsx | 2 +- shared/index.ts | 1 + shared/package.json | 3 + shared/src/FFTheme.schema.json | 1 + shared/src/FFTheme.ts | 80 +++++++++++++++++++ static/index.ts | 57 +------------ static/src/getPng.ts | 60 ++++++++++++++ 21 files changed, 195 insertions(+), 100 deletions(-) create mode 100644 app/src/lib/toThemeDynamic.ts create mode 100644 shared/src/FFTheme.schema.json create mode 100644 shared/src/FFTheme.ts create mode 100644 static/src/getPng.ts diff --git a/app/src/components/Graph.tsx b/app/src/components/Graph.tsx index 7acea22d..5e9228f5 100644 --- a/app/src/components/Graph.tsx +++ b/app/src/components/Graph.tsx @@ -35,8 +35,9 @@ import { getNodePositionsFromCy } from "./getNodePositionsFromCy"; import styles from "./Graph.module.css"; import { GRAPH_CONTEXT_MENU_ID, GraphContextMenu } from "./GraphContextMenu"; import classNames from "classnames"; -import { getThemeEditor, toTheme, useBackground } from "../lib/toTheme"; +import { getThemeEditor, toTheme } from "../lib/toTheme"; import equal from "fast-deep-equal"; +import { useBackground } from "../lib/toThemeDynamic"; declare global { interface Window { __cy?: cytoscape.Core; diff --git a/app/src/components/LoadTemplateDialog.tsx b/app/src/components/LoadTemplateDialog.tsx index 47f7d0e0..e654c62f 100644 --- a/app/src/components/LoadTemplateDialog.tsx +++ b/app/src/components/LoadTemplateDialog.tsx @@ -11,7 +11,7 @@ import classNames from "classnames"; import { useDoc } from "../lib/useDoc"; import { prepareChart } from "../lib/prepareChart/prepareChart"; import { mountGraph, unmountGraph } from "../lib/useUnmountStore"; -import { FFTheme } from "../lib/FFTheme"; +import type { FFTheme } from "shared"; import { getDefaultText } from "../lib/getDefaultText"; /** diff --git a/app/src/components/Tabs/ThemeTab.tsx b/app/src/components/Tabs/ThemeTab.tsx index 989c499b..d0ac067e 100644 --- a/app/src/components/Tabs/ThemeTab.tsx +++ b/app/src/components/Tabs/ThemeTab.tsx @@ -1,13 +1,12 @@ import { createControls } from "formulaic"; -import { updateThemeEditor, useThemeEditor } from "../../lib/toTheme"; -import { +import type { FFTheme, Shape, CurveStyle, ArrowShape, Direction, LayoutName, -} from "../../lib/FFTheme"; +} from "shared"; import { ReactNode } from "react"; import classNames from "classnames"; @@ -33,6 +32,7 @@ import { TextAa, } from "phosphor-react"; import { useGraphStore } from "../../lib/useGraphStore"; +import { updateThemeEditor, useThemeEditor } from "../../lib/toThemeDynamic"; const createForm = createControls({ select, diff --git a/app/src/components/downloads.ts b/app/src/components/downloads.ts index 01acbb72..3a2ffe2d 100644 --- a/app/src/components/downloads.ts +++ b/app/src/components/downloads.ts @@ -3,7 +3,7 @@ import { saveAs } from "file-saver"; import { UNAUTH_IMG_SCALE } from "../lib/constants"; import { cytoscape } from "../lib/cytoscape"; -import { getBackground } from "../lib/toTheme"; +import { getBackground } from "../lib/toThemeDynamic"; // padding, gets divided in half const PADDING = 60; diff --git a/app/src/lib/prepareChart/prepareChart.ts b/app/src/lib/prepareChart/prepareChart.ts index 2876217b..9f7912ee 100644 --- a/app/src/lib/prepareChart/prepareChart.ts +++ b/app/src/lib/prepareChart/prepareChart.ts @@ -9,7 +9,7 @@ import { import { getStyleStringFromMeta, preprocessStyle } from "../preprocessStyle"; import { Details, useDoc } from "../useDoc"; import { cytoscapeStyle, theme } from "../templates/default-template"; -import { FFTheme } from "../FFTheme"; +import type { FFTheme } from "shared"; /** * Ensures the document loaded externally or from local storage diff --git a/app/src/lib/preprocessStyle.ts b/app/src/lib/preprocessStyle.ts index e9c82860..fdd713e8 100644 --- a/app/src/lib/preprocessStyle.ts +++ b/app/src/lib/preprocessStyle.ts @@ -4,7 +4,7 @@ import { create } from "zustand"; import { devtools } from "zustand/middleware"; import { resetGraph } from "./useUnmountStore"; -import { FFTheme } from "./FFTheme"; +import type { FFTheme } from "shared"; import { toTheme } from "./toTheme"; (async () => { diff --git a/app/src/lib/templates/code-flow-template.ts b/app/src/lib/templates/code-flow-template.ts index 9263cbd0..49320a86 100644 --- a/app/src/lib/templates/code-flow-template.ts +++ b/app/src/lib/templates/code-flow-template.ts @@ -1,4 +1,4 @@ -import { FFTheme } from "../FFTheme"; +import type { FFTheme } from "shared"; export const content = ` Database diff --git a/app/src/lib/templates/default-template.ts b/app/src/lib/templates/default-template.ts index c3d1fa4f..ea075232 100644 --- a/app/src/lib/templates/default-template.ts +++ b/app/src/lib/templates/default-template.ts @@ -1,4 +1,4 @@ -import { FFTheme } from "../FFTheme"; +import type { FFTheme } from "shared"; export const content = ` Begin Typing diff --git a/app/src/lib/templates/flowchart-template.ts b/app/src/lib/templates/flowchart-template.ts index 171e6213..b9fd3c8e 100644 --- a/app/src/lib/templates/flowchart-template.ts +++ b/app/src/lib/templates/flowchart-template.ts @@ -1,4 +1,4 @@ -import { FFTheme } from "../FFTheme"; +import type { FFTheme } from "shared"; export const content = ` Brainstorming Session diff --git a/app/src/lib/templates/knowledge-graph-template.ts b/app/src/lib/templates/knowledge-graph-template.ts index 25e3166a..149f4ee2 100644 --- a/app/src/lib/templates/knowledge-graph-template.ts +++ b/app/src/lib/templates/knowledge-graph-template.ts @@ -1,4 +1,4 @@ -import { FFTheme } from "../FFTheme"; +import type { FFTheme } from "shared"; export const content = ` Fall of Ancient Rome .color_purple diff --git a/app/src/lib/templates/mindmap-template.ts b/app/src/lib/templates/mindmap-template.ts index 25d31f2a..ddf62b34 100644 --- a/app/src/lib/templates/mindmap-template.ts +++ b/app/src/lib/templates/mindmap-template.ts @@ -1,4 +1,4 @@ -import { FFTheme } from "../FFTheme"; +import type { FFTheme } from "shared"; export const content = ` Mind Mapping .size_lg diff --git a/app/src/lib/templates/org-chart-template.ts b/app/src/lib/templates/org-chart-template.ts index 1b5360fe..82aced75 100644 --- a/app/src/lib/templates/org-chart-template.ts +++ b/app/src/lib/templates/org-chart-template.ts @@ -1,4 +1,4 @@ -import { FFTheme } from "../FFTheme"; +import type { FFTheme } from "shared"; export const content = ` Saraswati Sharma .size_lg.color_pink diff --git a/app/src/lib/toTheme.ts b/app/src/lib/toTheme.ts index b0ca7233..708f2853 100644 --- a/app/src/lib/toTheme.ts +++ b/app/src/lib/toTheme.ts @@ -1,6 +1,6 @@ import cytoscape from "cytoscape"; -import { Doc, useDoc } from "./useDoc"; -import { Direction, FFTheme, LayoutDirection } from "./FFTheme"; +import type { Doc } from "./useDoc"; +import type { Direction, FFTheme, LayoutDirection } from "shared"; import { fonts } from "./fonts"; import { childlessShapeClasses, @@ -200,33 +200,6 @@ export function getThemeEditor(doc: Doc) { return (doc.meta?.themeEditor as FFTheme) || defaultTheme; } -export function useThemeEditor() { - return useDoc( - (state) => (state.meta?.themeEditor as FFTheme) || defaultTheme - ); -} - -export function useBackground() { - return useThemeEditor().background; -} - -export function getBackground() { - return getThemeEditor(useDoc.getState()).background; -} - -export function updateThemeEditor(theme: Partial) { - useDoc.setState((doc) => ({ - ...doc, - meta: { - ...doc.meta, - themeEditor: { - ...getThemeEditor(doc), - ...theme, - }, - }, - })); -} - function isHierarchical(layoutName: string) { return ["dagre", "klay", "layered", "mrtree"].includes(layoutName); } diff --git a/app/src/lib/toThemeDynamic.ts b/app/src/lib/toThemeDynamic.ts new file mode 100644 index 00000000..8aad58ee --- /dev/null +++ b/app/src/lib/toThemeDynamic.ts @@ -0,0 +1,31 @@ +import { FFTheme } from "shared"; +import { theme as defaultTheme } from "./templates/default-template"; +import { useDoc } from "./useDoc"; +import { getThemeEditor } from "./toTheme"; + +export function useThemeEditor() { + return useDoc( + (state) => (state.meta?.themeEditor as FFTheme) || defaultTheme + ); +} + +export function useBackground() { + return useThemeEditor().background; +} + +export function updateThemeEditor(theme: Partial) { + useDoc.setState((doc) => ({ + ...doc, + meta: { + ...doc.meta, + themeEditor: { + ...getThemeEditor(doc), + ...theme, + }, + }, + })); +} + +export function getBackground() { + return getThemeEditor(useDoc.getState()).background; +} diff --git a/app/src/pages/New.tsx b/app/src/pages/New.tsx index 0a761856..1fdeb052 100644 --- a/app/src/pages/New.tsx +++ b/app/src/pages/New.tsx @@ -19,7 +19,7 @@ import { createUnlimitedTitle, } from "../lib/paywallCopy"; import { Warning } from "../components/Warning"; -import { FFTheme } from "../lib/FFTheme"; +import type { FFTheme } from "shared"; type CreateChartOptions = { name: string; diff --git a/shared/index.ts b/shared/index.ts index c9de188b..300c93fc 100644 --- a/shared/index.ts +++ b/shared/index.ts @@ -1 +1,2 @@ export * from "./src/ImportDataFormType"; +export * from "./src/FFTheme"; diff --git a/shared/package.json b/shared/package.json index 955f0fc2..2bd62567 100644 --- a/shared/package.json +++ b/shared/package.json @@ -3,6 +3,9 @@ "version": "0.0.1", "main": "index.ts", "types": "index.ts", + "scripts": { + "schema:generate": "pnpx ts-json-schema-generator --path 'src/FFTheme.ts' --type 'FFTheme' -f tsconfig.json --strict-tuples -o src/FFTheme.schema.json --minify --no-top-ref" + }, "devDependencies": { "typescript": "^5.2.2" } diff --git a/shared/src/FFTheme.schema.json b/shared/src/FFTheme.schema.json new file mode 100644 index 00000000..d6ecb4f9 --- /dev/null +++ b/shared/src/FFTheme.schema.json @@ -0,0 +1 @@ +{"$schema":"http://json-schema.org/draft-07/schema#","additionalProperties":false,"definitions":{"ArrowShape":{"enum":["none","triangle","vee","triangle-backcurve","circle"],"type":"string"},"CurveStyle":{"enum":["bezier","taxi"],"type":"string"},"Direction":{"enum":["RIGHT","LEFT","DOWN","UP"],"type":"string"},"LayoutName":{"description":"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!! NOTICE !!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\nIf you change this file, you need to run `pnpm -F shared schema:generate` to update the json schema file in `src/FFTheme.schema.json`.","enum":["dagre","klay","breadthfirst","cose","concentric","circle","layered","mrtree","stress","radial"],"type":"string"},"Shape":{"enum":["rectangle","roundrectangle","ellipse"],"type":"string"}},"properties":{"arrowScale":{"type":"number"},"background":{"type":"string"},"borderColor":{"type":"string"},"borderWidth":{"description":"The width of the border used on nodes.","type":"number"},"curveStyle":{"$ref":"#/definitions/CurveStyle"},"direction":{"$ref":"#/definitions/Direction"},"edgeColor":{"type":"string"},"edgeTextSize":{"type":"number"},"edgeWidth":{"type":"number"},"fixedHeight":{"description":"The height of the node when `useFixedHeight` is true. Ideal range is between 75 - 250.","type":"number"},"fontFamily":{"type":"string"},"layoutName":{"$ref":"#/definitions/LayoutName"},"lineHeight":{"type":"number"},"nodeBackground":{"type":"string"},"nodeForeground":{"type":"string"},"padding":{"type":"number"},"rotateEdgeLabel":{"type":"boolean"},"shape":{"$ref":"#/definitions/Shape"},"sourceArrowShape":{"$ref":"#/definitions/ArrowShape"},"sourceDistanceFromNode":{"type":"number"},"spacingFactor":{"type":"number"},"targetArrowShape":{"$ref":"#/definitions/ArrowShape"},"targetDistanceFromNode":{"type":"number"},"textMarginY":{"type":"number"},"textMaxWidth":{"type":"number"},"useFixedHeight":{"description":"Whether the node's height should be fixed. Creates a more aesthetically pleasing graph in some cases.","type":"boolean"}},"required":["fontFamily","background","lineHeight","layoutName","direction","spacingFactor","shape","textMaxWidth","padding","curveStyle","textMarginY","borderWidth","borderColor","nodeBackground","nodeForeground","useFixedHeight","fixedHeight","edgeTextSize","edgeWidth","sourceArrowShape","targetArrowShape","edgeColor","sourceDistanceFromNode","targetDistanceFromNode","arrowScale","rotateEdgeLabel"],"type":"object"} \ No newline at end of file diff --git a/shared/src/FFTheme.ts b/shared/src/FFTheme.ts new file mode 100644 index 00000000..f0c8627d --- /dev/null +++ b/shared/src/FFTheme.ts @@ -0,0 +1,80 @@ +/** + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * !!!!!!!!!!!! NOTICE !!!!!!!!!!!!!!!! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + * If you change this file, you need to run `pnpm -F shared schema:generate` to update the + * json schema file in `src/FFTheme.schema.json`. + */ + +export type LayoutName = + | "dagre" + | "klay" + | "breadthfirst" + | "cose" + | "concentric" + | "circle" + | "layered" + | "mrtree" + | "stress" + | "radial"; + +export type LayoutDirection = "TB" | "LR" | "RL" | "BT"; + +export type Direction = "RIGHT" | "LEFT" | "DOWN" | "UP"; + +export type Shape = "rectangle" | "roundrectangle" | "ellipse"; + +export type CurveStyle = "bezier" | "taxi"; + +export type Border = "none" | "solid" | "dashed" | "dotted" | "double"; + +export type ArrowShape = + | "none" + | "triangle" + | "vee" + | "triangle-backcurve" + | "circle"; + +export type FFTheme = { + // Global Style + fontFamily: string; + background: string; + lineHeight: number; + // Layout + layoutName: LayoutName; + direction: Direction; + spacingFactor: number; + // Node + shape: Shape; + textMaxWidth: number; + padding: number; + curveStyle: CurveStyle; + textMarginY: number; + /** + * The width of the border used on nodes. + */ + borderWidth: number; + borderColor: string; + nodeBackground: string; + nodeForeground: string; + /** + * Whether the node's height should be fixed. Creates a more aesthetically pleasing graph + * in some cases. + */ + useFixedHeight: boolean; + /** + * The height of the node when `useFixedHeight` is true. Ideal range is between 75 - 250. + */ + fixedHeight: number; + // Text size on edge labels relative to node + edgeTextSize: number; + edgeWidth: number; + sourceArrowShape: ArrowShape; + targetArrowShape: ArrowShape; + edgeColor: string; + sourceDistanceFromNode: number; + targetDistanceFromNode: number; + arrowScale: number; + rotateEdgeLabel: boolean; +}; diff --git a/static/index.ts b/static/index.ts index 0b8220f1..2319d66d 100644 --- a/static/index.ts +++ b/static/index.ts @@ -1,56 +1 @@ -import { getPage } from "./src/getPage"; -import { readFileSync } from "fs"; -import { join } from "path"; -import type { ElementDefinition } from "cytoscape"; - -/** - * Returns a base64 encoded PNG image of a cytoscape graph - */ -export async function getPng({ elements }: { elements: ElementDefinition[] }) { - const { page, browser } = await getPage(); - - // read the file from "./dist/index.html" - const indexHtml = join(__dirname, "dist/index.html"); - const html = readFileSync(indexHtml, "utf8"); - - // set the page content - await page.setContent(html); - - // execute code in the browser - await page.evaluate((elements) => { - console.log(window.cy); - // set elements - window.cy.json({ elements }); - window.cy.layout({ name: "grid" }).run(); - - // const themeEditor = getThemeEditor(doc); - // const { layout, style: themeStyle } = toTheme(themeEditor); - // const { style } = preprocessStyle( - // customCssOnly ? customCss : [themeStyle, customCss].join("\n") - // ); - // window.cy - // .layout({ - // ...layout, - // // @ts-ignore - // fit: true, - // padding: 20, - // }) - // .run(); - - // json stringify the elements, and write them to a fixed position - // div on the page so we can read them out in the next step - const elementsDiv = document.createElement("div"); - elementsDiv.id = "elements"; - elementsDiv.style.position = "fixed"; - elementsDiv.style.top = "0"; - elementsDiv.style.left = "0"; - elementsDiv.textContent = JSON.stringify(elements); - document.body.appendChild(elementsDiv); - }, elements); - - const screenshot = await page.screenshot({ encoding: "base64" }); - - await browser.close(); - - return screenshot; -} +export { getPng } from "./src/getPng"; diff --git a/static/src/getPng.ts b/static/src/getPng.ts new file mode 100644 index 00000000..b8236812 --- /dev/null +++ b/static/src/getPng.ts @@ -0,0 +1,60 @@ +import { getPage } from "./getPage"; +import { readFileSync } from "fs"; +import { join } from "path"; +import type { ElementDefinition } from "cytoscape"; + +/** + * Returns a base64 encoded PNG image of a cytoscape graph + */ + +export async function getPng({ elements }: { elements: ElementDefinition[] }) { + const { page, browser } = await getPage(); + + // read the file from "./dist/index.html" + const indexHtml = join(__dirname, "dist/index.html"); + const html = readFileSync(indexHtml, "utf8"); + + // set the page content + await page.setContent(html); + + // execute code in the browser + await page.evaluate((elements) => { + console.log(window.cy); + // set elements + window.cy.json({ elements }); + window.cy.layout({ name: "grid" }).run(); + + // doc, useDoc + // FFTheme + // graph utility classes + + // const themeEditor = getThemeEditor(doc); // (useDoc) + // const { layout, style: themeStyle } = toTheme(themeEditor); + // const { style } = preprocessStyle( + // customCssOnly ? customCss : [themeStyle, customCss].join("\n") + // ); + // window.cy + // .layout({ + // ...layout, + // // @ts-ignore + // fit: true, + // padding: 20, + // }) + // .run(); + // json stringify the elements, and write them to a fixed position + // div on the page so we can read them out in the next step + const elementsDiv = document.createElement("div"); + elementsDiv.id = "elements"; + elementsDiv.style.position = "fixed"; + elementsDiv.style.top = "0"; + elementsDiv.style.left = "0"; + elementsDiv.textContent = JSON.stringify(elements); + document.body.appendChild(elementsDiv); + }, elements); + + const screenshot = await page.screenshot({ encoding: "base64" }); + + await browser.close(); + + return screenshot; +} From 93eb434d7fef18e955a5a2b9c1d05450beaaa44e Mon Sep 17 00:00:00 2001 From: Rob Gordon Date: Thu, 29 Feb 2024 10:01:16 -0500 Subject: [PATCH 4/4] Remove template defaults --- app/public/templates/template21.png | Bin 0 -> 34404 bytes app/src/lib/templates/default-template.ts | 2 +- app/src/lib/templates/templates.ts | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 app/public/templates/template21.png diff --git a/app/public/templates/template21.png b/app/public/templates/template21.png new file mode 100644 index 0000000000000000000000000000000000000000..65d83afc3ac9c97b157e5b21fdc5215f063022a2 GIT binary patch literal 34404 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 z%0A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 Qo`4^55gFkUK^@=!3rswM*8l(j literal 0 HcmV?d00001 diff --git a/app/src/lib/templates/default-template.ts b/app/src/lib/templates/default-template.ts index ea075232..957a0165 100644 --- a/app/src/lib/templates/default-template.ts +++ b/app/src/lib/templates/default-template.ts @@ -39,4 +39,4 @@ export const theme: FFTheme = { }; export const cytoscapeStyle = - "$color: #31405b;\n$red: #e63946;\n$orange: #f4a261;\n$yellow: #f1fa3b;\n$green: #2a9d8f;\n$blue: #606ef6;\n$purple: #6d4a7c;\n$grey: #f2eded;\n\n:childless {\n font-weight: 500;\n}\n\n/** Start */\n:childless[in_degree < 1][out_degree > 0] {\n border-width: 0;\n shape: roundrectangle;\n background-color: $green;\n color: white;\n}\n\n/** Terminal */\n:childless[out_degree < 1][in_degree > 0] {\n border-width: 0;\n shape: roundrectangle;\n background-color: $red;\n color: white;\n}\n\n/** Branching */\n:childless[in_degree > 0][in_degree < 2][out_degree > 1] {\n shape: diamond;\n background-color: $blue;\n color: white;\n height: $width;\n border-width: 0;\n text-margin-y: 2;\n}\n\n/** Merging **/\n:childless[in_degree > 1][out_degree > 0][out_degree < 2] {\n}\n\n:childless.color_red {\n background-color: $red;\n color: white;\n}\n:childless.color_orange {\n background-color: $orange;\n color: white;\n}\n:childless.color_yellow {\n background-color: $yellow;\n}\n:childless.color_green {\n background-color: $green;\n color: white;\n}\n:childless.color_blue {\n background-color: $blue;\n color: white;\n}\n:childless.color_purple {\n background-color: $purple;\n color: white;\n}\n:childless.color_grey {\n background-color: $grey;\n}\n\n:parent.color_white {\n background-color: white;\n}\n:parent.color_grey {\n background-color: $grey;\n}"; + "$color: #31405b;\n$red: #e63946;\n$orange: #f4a261;\n$yellow: #f1fa3b;\n$green: #2a9d8f;\n$blue: #606ef6;\n$purple: #6d4a7c;\n$grey: #f2eded;\n\n:childless {\n font-weight: 500;\n}\n\n/** Start - uncomment to use\n:childless[in_degree < 1][out_degree > 0] {\n border-width: 0;\n shape: roundrectangle;\n background-color: $green;\n color: white;\n}\n*/\n\n/** Terminal - uncomment to use\n:childless[out_degree < 1][in_degree > 0] {\n border-width: 0;\n shape: roundrectangle;\n background-color: $red;\n color: white;\n}\n*/\n\n/** Branching - uncomment to use\n:childless[in_degree > 0][in_degree < 2][out_degree > 1] {\n shape: diamond;\n background-color: $blue;\n color: white;\n height: $width;\n border-width: 0;\n text-margin-y: 2;\n}\n*/\n\n/** Merging **/\n:childless[in_degree > 1][out_degree > 0][out_degree < 2] {\n}\n\n:childless.color_red {\n background-color: $red;\n color: white;\n}\n:childless.color_orange {\n background-color: $orange;\n color: white;\n}\n:childless.color_yellow {\n background-color: $yellow;\n}\n:childless.color_green {\n background-color: $green;\n color: white;\n}\n:childless.color_blue {\n background-color: $blue;\n color: white;\n}\n:childless.color_purple {\n background-color: $purple;\n color: white;\n}\n:childless.color_grey {\n background-color: $grey;\n}\n\n:parent.color_white {\n background-color: white;\n}\n:parent.color_grey {\n background-color: $grey;\n}"; diff --git a/app/src/lib/templates/templates.ts b/app/src/lib/templates/templates.ts index 2359883a..af7fbde8 100644 --- a/app/src/lib/templates/templates.ts +++ b/app/src/lib/templates/templates.ts @@ -12,7 +12,7 @@ export const templates: { }[] = [ { key: "default", - img: "template9.png", + img: "template21.png", bgColor: "#FFFFFF", title: () => `Default`, promptType: "flowchart",