dev 8 months ago
parent 771da0fbd9
commit d9a3592096

346
package-lock.json generated

@ -8,7 +8,9 @@
"name": "obox", "name": "obox",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@tailwindcss/vite": "^4.1.18" "@tailwindcss/vite": "^4.1.18",
"jspdf": "^4.1.0",
"svelte-spa-router": "^4.0.1"
}, },
"devDependencies": { "devDependencies": {
"@sveltejs/vite-plugin-svelte": "^6.2.1", "@sveltejs/vite-plugin-svelte": "^6.2.1",
@ -21,7 +23,8 @@
"svelte-check": "^4.3.4", "svelte-check": "^4.3.4",
"tailwindcss": "^4.1.18", "tailwindcss": "^4.1.18",
"typescript": "~5.9.3", "typescript": "~5.9.3",
"vite": "^7.2.4" "vite": "^7.2.4",
"vite-plugin-singlefile": "^2.3.0"
} }
}, },
"node_modules/@alloc/quick-lru": { "node_modules/@alloc/quick-lru": {
@ -37,6 +40,15 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/@babel/runtime": {
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
"integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.27.2", "version": "0.27.2",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz",
@ -1166,6 +1178,26 @@
"undici-types": "~7.16.0" "undici-types": "~7.16.0"
} }
}, },
"node_modules/@types/pako": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz",
"integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==",
"license": "MIT"
},
"node_modules/@types/raf": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz",
"integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==",
"license": "MIT",
"optional": true
},
"node_modules/@types/trusted-types": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
"license": "MIT",
"optional": true
},
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.15.0", "version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
@ -1236,6 +1268,16 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/base64-arraybuffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/baseline-browser-mapping": { "node_modules/baseline-browser-mapping": {
"version": "2.9.19", "version": "2.9.19",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz",
@ -1246,6 +1288,19 @@
"baseline-browser-mapping": "dist/cli.js" "baseline-browser-mapping": "dist/cli.js"
} }
}, },
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/browserslist": { "node_modules/browserslist": {
"version": "4.28.1", "version": "4.28.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
@ -1301,6 +1356,26 @@
], ],
"license": "CC-BY-4.0" "license": "CC-BY-4.0"
}, },
"node_modules/canvg": {
"version": "3.0.11",
"resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz",
"integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==",
"license": "MIT",
"optional": true,
"dependencies": {
"@babel/runtime": "^7.12.5",
"@types/raf": "^3.4.0",
"core-js": "^3.8.3",
"raf": "^3.4.1",
"regenerator-runtime": "^0.13.7",
"rgbcolor": "^1.0.1",
"stackblur-canvas": "^2.0.0",
"svg-pathdata": "^6.0.3"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/chokidar": { "node_modules/chokidar": {
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
@ -1327,6 +1402,28 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/core-js": {
"version": "3.48.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.48.0.tgz",
"integrity": "sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
},
"node_modules/css-line-break": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
"license": "MIT",
"optional": true,
"dependencies": {
"utrie": "^1.0.2"
}
},
"node_modules/deepmerge": { "node_modules/deepmerge": {
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
@ -1353,6 +1450,16 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/dompurify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz",
"integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==",
"license": "(MPL-2.0 OR Apache-2.0)",
"optional": true,
"optionalDependencies": {
"@types/trusted-types": "^2.0.7"
}
},
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.282", "version": "1.5.282",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.282.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.282.tgz",
@ -1441,6 +1548,17 @@
"@jridgewell/sourcemap-codec": "^1.4.15" "@jridgewell/sourcemap-codec": "^1.4.15"
} }
}, },
"node_modules/fast-png": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/fast-png/-/fast-png-6.4.0.tgz",
"integrity": "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==",
"license": "MIT",
"dependencies": {
"@types/pako": "^2.0.3",
"iobuffer": "^5.3.2",
"pako": "^2.1.0"
}
},
"node_modules/fdir": { "node_modules/fdir": {
"version": "6.5.0", "version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
@ -1458,6 +1576,25 @@
} }
} }
}, },
"node_modules/fflate": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
"license": "MIT"
},
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/fraction.js": { "node_modules/fraction.js": {
"version": "5.3.4", "version": "5.3.4",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
@ -1492,6 +1629,36 @@
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/html2canvas": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
"license": "MIT",
"optional": true,
"dependencies": {
"css-line-break": "^2.1.0",
"text-segmentation": "^1.0.3"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/iobuffer": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.4.0.tgz",
"integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==",
"license": "MIT"
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/is-reference": { "node_modules/is-reference": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
@ -1511,6 +1678,23 @@
"jiti": "lib/jiti-cli.mjs" "jiti": "lib/jiti-cli.mjs"
} }
}, },
"node_modules/jspdf": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-4.1.0.tgz",
"integrity": "sha512-xd1d/XRkwqnsq6FP3zH1Q+Ejqn2ULIJeDZ+FTKpaabVpZREjsJKRJwuokTNgdqOU+fl55KgbvgZ1pRTSWCP2kQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.28.4",
"fast-png": "^6.2.0",
"fflate": "^0.8.1"
},
"optionalDependencies": {
"canvg": "^3.0.11",
"core-js": "^3.6.0",
"dompurify": "^3.3.1",
"html2canvas": "^1.0.0-rc.5"
}
},
"node_modules/lightningcss": { "node_modules/lightningcss": {
"version": "1.30.2", "version": "1.30.2",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
@ -1776,6 +1960,33 @@
"@jridgewell/sourcemap-codec": "^1.5.5" "@jridgewell/sourcemap-codec": "^1.5.5"
} }
}, },
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
"license": "MIT",
"dependencies": {
"braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=8.6"
}
},
"node_modules/micromatch/node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/mri": { "node_modules/mri": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
@ -1822,6 +2033,19 @@
], ],
"license": "MIT" "license": "MIT"
}, },
"node_modules/pako": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
"license": "(MIT AND Zlib)"
},
"node_modules/performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
"license": "MIT",
"optional": true
},
"node_modules/picocolors": { "node_modules/picocolors": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@ -1875,6 +2099,16 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/raf": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
"license": "MIT",
"optional": true,
"dependencies": {
"performance-now": "^2.1.0"
}
},
"node_modules/readdirp": { "node_modules/readdirp": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
@ -1889,6 +2123,32 @@
"url": "https://paulmillr.com/funding/" "url": "https://paulmillr.com/funding/"
} }
}, },
"node_modules/regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
"license": "MIT",
"optional": true
},
"node_modules/regexparam": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/regexparam/-/regexparam-2.0.2.tgz",
"integrity": "sha512-A1PeDEYMrkLrfyOwv2jwihXbo9qxdGD3atBYQA9JJgreAx8/7rC6IUkWOw2NQlOxLp2wL0ifQbh1HuidDfYA6w==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/rgbcolor": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
"integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
"license": "MIT OR SEE LICENSE IN FEEL-FREE.md",
"optional": true,
"engines": {
"node": ">= 0.8.15"
}
},
"node_modules/rollup": { "node_modules/rollup": {
"version": "4.57.0", "version": "4.57.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.0.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.0.tgz",
@ -1955,6 +2215,16 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/stackblur-canvas": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz",
"integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">=0.1.14"
}
},
"node_modules/svelte": { "node_modules/svelte": {
"version": "5.48.5", "version": "5.48.5",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.48.5.tgz", "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.48.5.tgz",
@ -2006,6 +2276,28 @@
"typescript": ">=5.0.0" "typescript": ">=5.0.0"
} }
}, },
"node_modules/svelte-spa-router": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/svelte-spa-router/-/svelte-spa-router-4.0.1.tgz",
"integrity": "sha512-2JkmUQ2f9jRluijL58LtdQBIpynSbem2eBGp4zXdi7aDY1znbR6yjw0KsonD0aq2QLwf4Yx4tBJQjxIjgjXHKg==",
"license": "MIT",
"dependencies": {
"regexparam": "2.0.2"
},
"funding": {
"url": "https://github.com/sponsors/ItalyPaleAle"
}
},
"node_modules/svg-pathdata": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
"integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/tailwindcss": { "node_modules/tailwindcss": {
"version": "4.1.18", "version": "4.1.18",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
@ -2025,6 +2317,16 @@
"url": "https://opencollective.com/webpack" "url": "https://opencollective.com/webpack"
} }
}, },
"node_modules/text-segmentation": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
"license": "MIT",
"optional": true,
"dependencies": {
"utrie": "^1.0.2"
}
},
"node_modules/tinyglobby": { "node_modules/tinyglobby": {
"version": "0.2.15", "version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
@ -2041,6 +2343,19 @@
"url": "https://github.com/sponsors/SuperchupuDev" "url": "https://github.com/sponsors/SuperchupuDev"
} }
}, },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.9.3", "version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
@ -2093,6 +2408,16 @@
"browserslist": ">= 4.21.0" "browserslist": ">= 4.21.0"
} }
}, },
"node_modules/utrie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
"license": "MIT",
"optional": true,
"dependencies": {
"base64-arraybuffer": "^1.0.2"
}
},
"node_modules/vite": { "node_modules/vite": {
"version": "7.3.1", "version": "7.3.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
@ -2167,6 +2492,23 @@
} }
} }
}, },
"node_modules/vite-plugin-singlefile": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/vite-plugin-singlefile/-/vite-plugin-singlefile-2.3.0.tgz",
"integrity": "sha512-DAcHzYypM0CasNLSz/WG0VdKOCxGHErfrjOoyIPiNxTPTGmO6rRD/te93n1YL/s+miXq66ipF1brMBikf99c6A==",
"dev": true,
"license": "MIT",
"dependencies": {
"micromatch": "^4.0.8"
},
"engines": {
"node": ">18.0.0"
},
"peerDependencies": {
"rollup": "^4.44.1",
"vite": "^5.4.11 || ^6.0.0 || ^7.0.0"
}
},
"node_modules/vitefu": { "node_modules/vitefu": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz", "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz",

@ -20,9 +20,12 @@
"svelte-check": "^4.3.4", "svelte-check": "^4.3.4",
"tailwindcss": "^4.1.18", "tailwindcss": "^4.1.18",
"typescript": "~5.9.3", "typescript": "~5.9.3",
"vite": "^7.2.4" "vite": "^7.2.4",
"vite-plugin-singlefile": "^2.3.0"
}, },
"dependencies": { "dependencies": {
"@tailwindcss/vite": "^4.1.18" "@tailwindcss/vite": "^4.1.18",
"jspdf": "^4.1.0",
"svelte-spa-router": "^4.0.1"
} }
} }

@ -2,46 +2,379 @@
import {dataConfig} from "../data/DataConfig.js"; import {dataConfig} from "../data/DataConfig.js";
import type {DownloadState} from "../data/DownloadTypes"; import type {DownloadState} from "../data/DownloadTypes";
import PoDownload from "../cmps/PoDownload.svelte"; import PoDownload from "../cmps/PoDownload.svelte";
import { projectFonts } from "../data/DataFonts";
import { dataPdfImages } from "../data/DataPdfImagesB64";
import { images } from "../data/DataImagesB64";
import {jsPDF} from "jspdf";
import {appState, getViewImage } from "../data/AppState.svelte";
import {formatPrice} from "../utils/formats";
import type {View} from "../data/DataConfigTypes";
const stepTimeout = 1000; const stepTimeout = 1000;
const logoProject = dataConfig.sources.logos + dataConfig.logos.project; const logoProject = dataConfig.sources.logos + dataConfig.logos.project;
const logoCompany = dataConfig.sources.logos + dataConfig.logos.company; const logoCompany = dataConfig.sources.logos + dataConfig.logos.company;
console.log(logoProject, logoCompany);
let downloadState : DownloadState = 'idle'; let downloadState: DownloadState = $state('idle');
let isVisible = false; let isVisible = $state(false);
let message = ''; let message = $state('');
// Función auxiliar para esperar const views = appState.getAllViews();
const wait = (ms : number ) => new Promise(resolve => setTimeout(resolve, ms)); const tipologias = ['A1', 'P1', 'P2'];
async function generatePdf () { // Abrir el modal con el selector
function openSelector() {
isVisible = true; isVisible = true;
downloadState = 'idle';
}
// Cancelar y cerrar
function handleCancel() {
isVisible = false;
downloadState = 'idle';
}
// Generar PDF con la tipología seleccionada
async function handleTipologiaSelected(tipologia: string) {
downloadState = 'creating'; downloadState = 'creating';
try { try {
await wait(3000); const pdfDoc = new jsPDF({
orientation: 'landscape',
unit: 'mm',
format: 'A4',
});
} catch (err : any) { const pageWidth = pdfDoc.internal.pageSize.getWidth();
downloadState = 'error'; const pageHeight = pdfDoc.internal.pageSize.getHeight();
message = err?.message; const margin = 15;
console.log(err);
} finally { // === Registrar fuentes ===
await wait(1000); const tf = projectFonts['Didot'];
pdfDoc.addFileToVFS(tf.filename, tf.base64);
pdfDoc.addFont(tf.filename, tf.name, tf.style);
const pf = projectFonts['proxima_nova_regular'];
pdfDoc.addFileToVFS(pf.filename, pf.base64);
pdfDoc.addFont(pf.filename, pf.name, pf.style);
const pb = projectFonts['proxima_nova_bold'];
pdfDoc.addFileToVFS(pb.filename, pb.base64);
pdfDoc.addFont(pb.filename, pb.name, pb.style);
const pl = projectFonts['proxima_nova_light'];
pdfDoc.addFileToVFS(pl.filename, pl.base64);
pdfDoc.addFont(pl.filename, pl.name, pl.style);
// === Portada ===
const ini = dataPdfImages['pdf_openbox_ini'];
if (ini) {
const iniFormat = ini.includes('jpeg') ? 'JPEG' : 'PNG';
pdfDoc.addImage(ini, iniFormat, 0, 0, pageWidth, pageHeight, '', 'FAST');
// Tipo de vivienda (USAR LA TIPOLOGÍA SELECCIONADA)
pdfDoc.setFontSize(20);
pdfDoc.setFont(pb.name, "normal");
pdfDoc.text(tipologia.toUpperCase(), 265, 119);
pdfDoc.addPage();
}
// === Páginas de vistas ===
views.forEach((view, index) => {
const base64 = images[getViewImage(view.id)];
if (!base64) {
return;
}
// Calcular tamaño de imagen
const imgPixelWidth = 1500;
const imgPixelHeight = 1500;
const pageRatio = pageWidth / pageHeight;
const imgRatio = imgPixelWidth / imgPixelHeight;
let renderWidth: number;
let renderHeight: number;
if (imgRatio > pageRatio) {
renderHeight = pageHeight - 2 * margin;
renderWidth = renderHeight * imgRatio;
} else {
renderHeight = pageHeight - 2 * margin;
renderWidth = renderHeight * imgRatio;
}
const x = margin;
const y = (pageHeight - renderHeight) / 2;
pdfDoc.addImage(base64, 'JPEG', x, y, renderWidth, renderHeight, '', 'FAST');
// Posiciones del rectángulo
const rectX = renderWidth + margin + 10;
const rectY = margin + 90;
const rectWidth = pageWidth - rectX - margin;
const rectHeight = pageHeight - rectY - margin;
/*
// color
pdfDoc.setFillColor(237, 237, 226);
pdfDoc.rect(rectX, rectY, rectWidth, rectHeight, "F");
*/
/*
pdfDoc.setFillColor(241, 242, 14);
pdfDoc.rect(rectX, rectY-20, rectWidth, 20, "F");
*/
// === TEXTOS ===
let textStartX = margin + renderWidth + 10;
let cursorY = margin + 5;
// === Título ===
pdfDoc.setFontSize(18);
pdfDoc.setFont(pf.name, "normal");
pdfDoc.text((view.name).toUpperCase(), textStartX, cursorY);
// === Descripción ===
pdfDoc.setFont(pl.name, "normal");
if (view.text) {
cursorY += 8;
cursorY = addTextBlock(pdfDoc,view.text, textStartX, cursorY, pageWidth - textStartX - margin, pl.name, 12, 5);
}
// === AÑADIR INFORMACIÓN DE OPCIONES ===
const vo = getViewOptions(view)
if (vo.options.length > 0) {
const tx = textStartX;
const ty = 100;
const textBoxMaxWidth = rectWidth - 3;
// === Título ===
pdfDoc.setFontSize(14);
pdfDoc.setFont(pf.name, "normal");
pdfDoc.text(('ACABADOS SELECCIONADOS').toUpperCase(), tx, ty);
let ty2 = ty+10;
vo.options.forEach((option) => {
let icon: string | null = null;
const label = `${option.nombreGrupo}: ${option?.nombre ?? ''}`;
// precio puede estar en opcion.precio o opcion.price
const priceVal = option?.precio ?? option?.precio ?? null;
ty2 = addOptionLine(pdfDoc,label, priceVal, tx, ty2, textBoxMaxWidth - 6, pf.name, 12, pf.name, 12, { r: 30, g: 30, b: 30 },icon);
})
}
// Nueva página excepto en la última
if (index < views.length - 1) pdfDoc.addPage();
});
// === Página final ===
pdfDoc.addPage();
const fin = dataPdfImages['pdf_openbox_fin'];
if (fin) {
const finFormat = fin.includes('jpeg') ? 'JPEG' : 'PNG';
pdfDoc.addImage(fin, finFormat, 0, 0, pageWidth, pageHeight, '', 'FAST');
}
await new Promise(r => setTimeout(r, stepTimeout));
downloadState = 'downloading';
// Guardar con nombre que incluye la tipología
pdfDoc.save(`mi_OPENBOX_${tipologia}.pdf`);
downloadState = 'success';
// Cerrar modal después de 2 segundos
setTimeout(() => {
isVisible = false; isVisible = false;
downloadState = 'idle'; downloadState = 'idle';
}, 2000);
} catch (err: any) {
downloadState = 'error';
message = err?.message || 'Error desconocido al generar el PDF';
console.error(err);
} }
} }
</script>
// === Función auxiliar para texto multilínea ===
function addTextBlock(
pdfDoc : jsPDF,
text: string | string[] | null | undefined,
x: number,
yStart: number,
maxWidth: number,
font: string,
fontSize: number,
lineHeight: number
) {
if (!text) return yStart;
let safeText: string = Array.isArray(text) ? text.join("\n") : String(text);
if (safeText.trim().length === 0) return yStart;
pdfDoc.setFont(font, "normal");
pdfDoc.setFontSize(fontSize);
const paragraphs = safeText.split(/\r?\n/);
let cursorY = yStart;
for (let p = 0; p < paragraphs.length; p++) {
const paragraph = paragraphs[p].trim();
if (!paragraph) {
cursorY += lineHeight;
continue;
}
const lines = pdfDoc.splitTextToSize(paragraph, maxWidth);
for (let i = 0; i < lines.length; i++) {
pdfDoc.text(lines[i], x, cursorY + i * lineHeight);
}
cursorY += lines.length * lineHeight + lineHeight;
}
return cursorY;
}
// === Auxiliar para línea con precio alineado a la derecha ===
function addOptionLine(
pdfDoc : jsPDF,
label: string,
price: number | null,
x: number,
y: number,
maxWidth: number,
font: string,
fontSize: number,
priceFont: string | null = null,
priceFontSize: number | null = null,
priceColor?: { r: number, g: number, b: number },
icon : string | null = null,
iconSize = 4,
iconMargin = 1,
) {
// Dibujar icono si se pasa
let iconWidth = 0;
if (icon) {
pdfDoc.addImage(icon, 'PNG', x, y-iconSize+1, iconSize, iconSize);
iconWidth = iconSize + iconMargin;
}
pdfDoc.setFont(font, "normal");
pdfDoc.setFontSize(fontSize);
const priceStr = price == null ? null : '+'+formatPrice(price); // (typeof price === "number" ? `+${price.toFixed(2)} €` : '+'+String(price));
const labelWidth = pdfDoc.getTextWidth(label);
const priceWidth = priceStr ? pdfDoc.getTextWidth(priceStr) : 0;
// Si label es demasiado largo, recortamos con splitTextToSize y dibujamos en varias líneas
if (labelWidth + priceWidth + 6 > maxWidth) {
// dividir label en líneas que dejen espacio para precio en la última línea
const availableForLabel = maxWidth - (priceWidth ? priceWidth + 6 : 0);
const labelLines = pdfDoc.splitTextToSize(label, availableForLabel);
for (let i = 0; i < labelLines.length; i++) {
const line = labelLines[i];
const lineY = y + i * (fontSize * 0.6 + 2);
pdfDoc.text(line, x, lineY);
// si es la última línea y hay precio, pintarlo a la derecha
if (i === labelLines.length - 1 && priceStr) {
if (priceColor) pdfDoc.setTextColor(priceColor.r, priceColor.g, priceColor.b);
if (priceFont && priceFontSize) pdfDoc.setFont(priceFont, "normal"), pdfDoc.setFontSize(priceFontSize);
pdfDoc.text(priceStr, x + maxWidth - priceWidth, lineY);
// reset font/color
pdfDoc.setFont(font, "normal");
pdfDoc.setFontSize(fontSize);
pdfDoc.setTextColor(0, 0, 0);
}
}
return y + labelLines.length * (fontSize * 0.6 + 2);
} else {
// etiqueta en una línea y precio alineado a la derecha si existe
pdfDoc.text(label, x+iconWidth, y);
if (priceStr) {
if (priceColor) pdfDoc.setTextColor(priceColor.r, priceColor.g, priceColor.b);
if (priceFont && priceFontSize) pdfDoc.setFont(priceFont, "normal"), pdfDoc.setFontSize(priceFontSize);
pdfDoc.text(priceStr, x + maxWidth - priceWidth, y);
// reset font/color
pdfDoc.setFont(font, "normal");
pdfDoc.setFontSize(fontSize);
pdfDoc.setTextColor(0, 0, 0);
}
return y + 6;
}
}
interface Option {
nombreGrupo: string,
nombre: string,
precio?: number|null|string,
consultar: boolean,
warning: boolean,
}
interface ViewOptions {
options: Option[];
hasWarning: boolean;
hasConsult: boolean;
}
function getViewOptions (view : View) : ViewOptions {
const options: Option[] = [];
let hasWarning = false;
let hasConsult = false;
if (view.options.length > 0) {
// Obtener opciones de la vista
view.options.forEach((group) => {
const currentOptionId = appState.getCurrentOption(view.id, group.id);
const optionValue = currentOptionId ? appState.getOptionValue(currentOptionId) : null;
const optionRef = group.values.find(v => v.id === currentOptionId);
const requiresConsult = currentOptionId ? appState.requiresConsultation(view.id, group.id, currentOptionId) : {required: false};
const hasPrice = optionRef?.amount && typeof optionRef.amount === 'number' && optionRef.amount > 0;
const isConsultar = optionRef?.amount === 'consultar';
if (requiresConsult.required) {
hasWarning = true;
}
if (isConsultar) {
hasConsult = true;
}
options.push({
nombreGrupo: group.name || group.id,
nombre: optionValue?.name || currentOptionId || 'No seleccionado',
precio: hasPrice ? optionRef.amount : null,
consultar: isConsultar,
warning: requiresConsult.required
});
});
}
return {
options,
hasWarning,
hasConsult,
}
}
<button type="button" </script>
<button
type="button"
class="px-3 lg:px-4 py-2 rounded-md text-base font-medium transition-colors duration-200 text-white bg-green-900 hover:bg-green-700 cursor-pointer" class="px-3 lg:px-4 py-2 rounded-md text-base font-medium transition-colors duration-200 text-white bg-green-900 hover:bg-green-700 cursor-pointer"
onclick={() => generatePdf()}> onclick={openSelector}
>
Descargar Selección Descargar Selección
</button> </button>
@ -49,8 +382,10 @@
{isVisible} {isVisible}
{message} {message}
{downloadState} {downloadState}
{tipologias}
logoCompany={logoCompany} logoCompany={logoCompany}
logoProject={logoProject} logoProject={logoProject}
text="Descarga tu Selección"
text={'testo'} onTipologiaSelected={handleTipologiaSelected}
onCancel={handleCancel}
/> />

@ -391,9 +391,8 @@ export const appState = new DataConfigStore();
// Función para obtener la URL de la imagen de la vista // Función para obtener la URL de la imagen de la vista
export function getViewImageUrl(viewId: string): string { export function getViewImage(viewId: string): string {
const parts: string[] = [viewId]; const parts: string[] = [viewId];
// Agregar opciones generales // Agregar opciones generales
@ -411,7 +410,13 @@ export function getViewImageUrl(viewId: string): string {
}); });
} }
return appState.imgSrc + `${parts.join('_')}.jpg`; return parts.join('_');
}
// Función para obtener la URL de la imagen de la vista
export function getViewImageUrl(viewId: string): string {
return appState.imgSrc + getViewImage(viewId) + '.jpg';
} }
// Función para calcular el total de la vista // Función para calcular el total de la vista

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,75 @@
// pdf.ts
import { jsPDF} from "jspdf";
import { pdfImages } from "../data/DataPdfsB64";
import { images } from "../data/DataImgsB64";
export function generatePdf(imageNames: string[]) {
console.log(imageNames);
const pdfDoc = new jsPDF({
orientation: 'landscape',
unit: 'mm',
format: 'a4',
});
const pageWidth = pdfDoc.internal.pageSize.getWidth();
const pageHeight = pdfDoc.internal.pageSize.getHeight();
const margin = 15;
// === Portada ===
const ini = pdfImages['pdf_open_box_ini'];
if (ini) {
const iniFormat = ini.includes('jpeg') ? 'JPEG' : 'PNG';
pdfDoc.addImage(ini, iniFormat, 0, 0, pageWidth, pageHeight, '', 'FAST');
pdfDoc.addPage();
}
// === Imágenes del array ===
imageNames.forEach((name, index) => {
const base64 = images[name];
if (!base64) {
console.log('no existe la imagen ',name)
return;
}
// Datos de la imagen original
const imgPixelWidth = 1500;
const imgPixelHeight = 1500;
const pageRatio = pageWidth / pageHeight;
const imgRatio = imgPixelWidth / imgPixelHeight;
// Calcular tamaño para que mantenga proporción y ajuste a la altura de página
let renderWidth: number;
let renderHeight: number;
if (imgRatio > pageRatio) {
// Imagen más ancha que alta → ajustamos al alto
renderHeight = pageHeight - 2 * margin;
renderWidth = renderHeight * imgRatio;
} else {
// Imagen más alta → también ajustamos al alto
renderHeight = pageHeight - 2 * margin;
renderWidth = renderHeight * imgRatio;
}
// Posición alineada a la izquierda con margen de 15 mm
const x = margin;
const y = (pageHeight - renderHeight) / 2;
pdfDoc.addImage(base64, 'JPEG', x, y, renderWidth, renderHeight, '', 'FAST');
// Añadir nueva página excepto en la última
if (index < imageNames.length - 1) pdfDoc.addPage();
});
// === Página final ===
pdfDoc.addPage();
const fin = pdfImages['pdf_open_box_fin'];
if (fin) {
const finFormat = fin.includes('jpeg') ? 'JPEG' : 'PNG';
pdfDoc.addImage(fin, finFormat, 0, 0, pageWidth, pageHeight, '', 'FAST');
}
pdfDoc.save('mi_open_box.pdf');
}

@ -1,12 +1,13 @@
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte' import { svelte } from '@sveltejs/vite-plugin-svelte'
import tailwindcss from "@tailwindcss/vite"; import tailwindcss from "@tailwindcss/vite";
import {viteSingleFile} from "vite-plugin-singlefile";
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
base: './', base: './',
plugins: [svelte(),tailwindcss()], plugins: [svelte(),tailwindcss(),viteSingleFile()],
css: { css: {
//transformer: 'lightningcss' //transformer: 'lightningcss'
}, },

Loading…
Cancel
Save

Powered by TurnKey Linux.