Compare commits
2 commits
28d3e87d94
...
8c8e26411f
Author | SHA1 | Date | |
---|---|---|---|
8c8e26411f | |||
ba25bc7f6c |
10 changed files with 857 additions and 130 deletions
537
frontend/package-lock.json
generated
537
frontend/package-lock.json
generated
|
@ -17,6 +17,7 @@
|
||||||
"i18next": "^23.15.2",
|
"i18next": "^23.15.2",
|
||||||
"i18next-browser-languagedetector": "^8.0.0",
|
"i18next-browser-languagedetector": "^8.0.0",
|
||||||
"i18next-resources-to-backend": "^1.2.1",
|
"i18next-resources-to-backend": "^1.2.1",
|
||||||
|
"juice": "^11.0.0",
|
||||||
"lucide-react": "^0.451.0",
|
"lucide-react": "^0.451.0",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
@ -31,7 +32,9 @@
|
||||||
"validator": "^13.12.0"
|
"validator": "^13.12.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@csstools/postcss-is-pseudo-class": "^5.0.1",
|
||||||
"@eslint/js": "^9.11.1",
|
"@eslint/js": "^9.11.1",
|
||||||
|
"@tailwindcss/typography": "^0.5.15",
|
||||||
"@types/react": "^18.3.10",
|
"@types/react": "^18.3.10",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@vitejs/plugin-legacy": "^5.4.2",
|
"@vitejs/plugin-legacy": "^5.4.2",
|
||||||
|
@ -1528,6 +1531,67 @@
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@csstools/postcss-is-pseudo-class": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-JLp3POui4S1auhDR0n8wHd/zTOWmMsmK3nQd3hhL6FhWPaox5W7j1se6zXOG/aP07wV2ww0lxbKYGwbBszOtfQ==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/csstools"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/csstools"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"@csstools/selector-specificity": "^5.0.0",
|
||||||
|
"postcss-selector-parser": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"postcss": "^8.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@csstools/postcss-is-pseudo-class/node_modules/@csstools/selector-specificity": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/csstools"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/csstools"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"postcss-selector-parser": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@csstools/postcss-is-pseudo-class/node_modules/postcss-selector-parser": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"cssesc": "^3.0.0",
|
||||||
|
"util-deprecate": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.21.5",
|
"version": "0.21.5",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
||||||
|
@ -2650,6 +2714,34 @@
|
||||||
"@swc/counter": "^0.1.3"
|
"@swc/counter": "^0.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/typography": {
|
||||||
|
"version": "0.5.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.15.tgz",
|
||||||
|
"integrity": "sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"lodash.castarray": "^4.4.0",
|
||||||
|
"lodash.isplainobject": "^4.0.6",
|
||||||
|
"lodash.merge": "^4.6.2",
|
||||||
|
"postcss-selector-parser": "6.0.10"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": {
|
||||||
|
"version": "6.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
|
||||||
|
"integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"cssesc": "^3.0.0",
|
||||||
|
"util-deprecate": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||||
|
@ -2772,6 +2864,14 @@
|
||||||
"url": "https://github.com/sponsors/epoberezkin"
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ansi-colors": {
|
||||||
|
"version": "4.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
|
||||||
|
"integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ansi-regex": {
|
"node_modules/ansi-regex": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||||
|
@ -3066,6 +3166,11 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/boolbase": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
|
||||||
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
|
@ -3216,6 +3321,46 @@
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cheerio": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==",
|
||||||
|
"dependencies": {
|
||||||
|
"cheerio-select": "^2.1.0",
|
||||||
|
"dom-serializer": "^2.0.0",
|
||||||
|
"domhandler": "^5.0.3",
|
||||||
|
"domutils": "^3.1.0",
|
||||||
|
"encoding-sniffer": "^0.2.0",
|
||||||
|
"htmlparser2": "^9.1.0",
|
||||||
|
"parse5": "^7.1.2",
|
||||||
|
"parse5-htmlparser2-tree-adapter": "^7.0.0",
|
||||||
|
"parse5-parser-stream": "^7.1.2",
|
||||||
|
"undici": "^6.19.5",
|
||||||
|
"whatwg-mimetype": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.17"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cheerio-select": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
|
||||||
|
"dependencies": {
|
||||||
|
"boolbase": "^1.0.0",
|
||||||
|
"css-select": "^5.1.0",
|
||||||
|
"css-what": "^6.1.0",
|
||||||
|
"domelementtype": "^2.3.0",
|
||||||
|
"domhandler": "^5.0.3",
|
||||||
|
"domutils": "^3.0.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chokidar": {
|
"node_modules/chokidar": {
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||||
|
@ -3326,6 +3471,32 @@
|
||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/css-select": {
|
||||||
|
"version": "5.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
|
||||||
|
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
|
||||||
|
"dependencies": {
|
||||||
|
"boolbase": "^1.0.0",
|
||||||
|
"css-what": "^6.1.0",
|
||||||
|
"domhandler": "^5.0.2",
|
||||||
|
"domutils": "^3.0.1",
|
||||||
|
"nth-check": "^2.0.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/css-what": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cssesc": {
|
"node_modules/cssesc": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||||
|
@ -3476,11 +3647,62 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dom-serializer": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.3.0",
|
||||||
|
"domhandler": "^5.0.2",
|
||||||
|
"entities": "^4.2.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/domelementtype": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/domhandler": {
|
||||||
|
"version": "5.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
||||||
|
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dompurify": {
|
"node_modules/dompurify": {
|
||||||
"version": "3.1.7",
|
"version": "3.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz",
|
||||||
"integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ=="
|
"integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/domutils": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
|
||||||
|
"dependencies": {
|
||||||
|
"dom-serializer": "^2.0.0",
|
||||||
|
"domelementtype": "^2.3.0",
|
||||||
|
"domhandler": "^5.0.3"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/downloadjs": {
|
"node_modules/downloadjs": {
|
||||||
"version": "1.4.7",
|
"version": "1.4.7",
|
||||||
"resolved": "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz",
|
"resolved": "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz",
|
||||||
|
@ -3504,6 +3726,29 @@
|
||||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/encoding-sniffer": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==",
|
||||||
|
"dependencies": {
|
||||||
|
"iconv-lite": "^0.6.3",
|
||||||
|
"whatwg-encoding": "^3.1.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/entities": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/es-abstract": {
|
"node_modules/es-abstract": {
|
||||||
"version": "1.23.3",
|
"version": "1.23.3",
|
||||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz",
|
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz",
|
||||||
|
@ -3709,6 +3954,17 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/escape-goat": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/escape-string-regexp": {
|
"node_modules/escape-string-regexp": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||||
|
@ -4515,6 +4771,24 @@
|
||||||
"void-elements": "3.1.0"
|
"void-elements": "3.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/htmlparser2": {
|
||||||
|
"version": "9.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz",
|
||||||
|
"integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/fb55/htmlparser2?sponsor=1",
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.3.0",
|
||||||
|
"domhandler": "^5.0.3",
|
||||||
|
"domutils": "^3.1.0",
|
||||||
|
"entities": "^4.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/i18next": {
|
"node_modules/i18next": {
|
||||||
"version": "23.16.2",
|
"version": "23.16.2",
|
||||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.2.tgz",
|
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.2.tgz",
|
||||||
|
@ -4553,6 +4827,17 @@
|
||||||
"@babel/runtime": "^7.23.2"
|
"@babel/runtime": "^7.23.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/iconv-lite": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||||
|
"dependencies": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ignore": {
|
"node_modules/ignore": {
|
||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||||
|
@ -5097,6 +5382,32 @@
|
||||||
"node": ">=4.0"
|
"node": ">=4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/juice": {
|
||||||
|
"version": "11.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/juice/-/juice-11.0.0.tgz",
|
||||||
|
"integrity": "sha512-sGF8hPz9/Wg+YXbaNDqc1Iuoaw+J/P9lBHNQKXAGc9pPNjCd4fyPai0Zxj7MRtdjMr0lcgk5PjEIkP2b8R9F3w==",
|
||||||
|
"dependencies": {
|
||||||
|
"cheerio": "^1.0.0",
|
||||||
|
"commander": "^12.1.0",
|
||||||
|
"mensch": "^0.3.4",
|
||||||
|
"slick": "^1.12.2",
|
||||||
|
"web-resource-inliner": "^7.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"juice": "bin/juice"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/juice/node_modules/commander": {
|
||||||
|
"version": "12.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
||||||
|
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/keyv": {
|
"node_modules/keyv": {
|
||||||
"version": "4.5.4",
|
"version": "4.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||||
|
@ -5159,6 +5470,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||||
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
|
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.castarray": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
|
||||||
|
"integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/lodash.clonedeep": {
|
"node_modules/lodash.clonedeep": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||||
|
@ -5175,6 +5492,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||||
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
|
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.isplainobject": {
|
||||||
|
"version": "4.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||||
|
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/lodash.merge": {
|
"node_modules/lodash.merge": {
|
||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||||
|
@ -5218,6 +5541,11 @@
|
||||||
"@jridgewell/sourcemap-codec": "^1.5.0"
|
"@jridgewell/sourcemap-codec": "^1.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mensch": {
|
||||||
|
"version": "0.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/mensch/-/mensch-0.3.4.tgz",
|
||||||
|
"integrity": "sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g=="
|
||||||
|
},
|
||||||
"node_modules/meow": {
|
"node_modules/meow": {
|
||||||
"version": "13.2.0",
|
"version": "13.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz",
|
||||||
|
@ -5252,6 +5580,17 @@
|
||||||
"node": ">=8.6"
|
"node": ">=8.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mime": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
|
||||||
|
"bin": {
|
||||||
|
"mime": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
|
@ -5338,6 +5677,17 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nth-check": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
|
||||||
|
"dependencies": {
|
||||||
|
"boolbase": "^1.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/nth-check?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/object-assign": {
|
"node_modules/object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
|
@ -5513,6 +5863,40 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/parse5": {
|
||||||
|
"version": "7.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
|
||||||
|
"integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"entities": "^4.5.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/parse5-htmlparser2-tree-adapter": {
|
||||||
|
"version": "7.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
|
||||||
|
"integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
|
||||||
|
"dependencies": {
|
||||||
|
"domhandler": "^5.0.3",
|
||||||
|
"parse5": "^7.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/parse5-parser-stream": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
|
||||||
|
"dependencies": {
|
||||||
|
"parse5": "^7.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/path-exists": {
|
"node_modules/path-exists": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||||
|
@ -6245,6 +6629,11 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
|
},
|
||||||
"node_modules/scheduler": {
|
"node_modules/scheduler": {
|
||||||
"version": "0.23.2",
|
"version": "0.23.2",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
||||||
|
@ -6345,6 +6734,14 @@
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/slick": {
|
||||||
|
"version": "1.12.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/slick/-/slick-1.12.2.tgz",
|
||||||
|
"integrity": "sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A==",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/source-map": {
|
"node_modules/source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
|
@ -6859,6 +7256,14 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/undici": {
|
||||||
|
"version": "6.20.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici/-/undici-6.20.1.tgz",
|
||||||
|
"integrity": "sha512-AjQF1QsmqfJys+LXfGTNum+qw4S88CojRInG/6t31W/1fk6G59s92bnAvGz5Cmur+kQv2SURXEvvudLmbrE8QA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/unfetch": {
|
"node_modules/unfetch": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/unfetch/-/unfetch-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/unfetch/-/unfetch-5.0.0.tgz",
|
||||||
|
@ -6957,6 +7362,14 @@
|
||||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/valid-data-url": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/valid-data-url/-/valid-data-url-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/validator": {
|
"node_modules/validator": {
|
||||||
"version": "13.12.0",
|
"version": "13.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz",
|
||||||
|
@ -7032,6 +7445,130 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/web-resource-inliner": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-NlfnGF8MY9ZUwFjyq3vOUBx7KwF8bmE+ywR781SB0nWB6MoMxN4BA8gtgP1KGTZo/O/AyWJz7HZpR704eaj4mg==",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-colors": "^4.1.1",
|
||||||
|
"escape-goat": "^3.0.0",
|
||||||
|
"htmlparser2": "^5.0.0",
|
||||||
|
"mime": "^2.4.6",
|
||||||
|
"valid-data-url": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/web-resource-inliner/node_modules/dom-serializer": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.0.1",
|
||||||
|
"domhandler": "^4.2.0",
|
||||||
|
"entities": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/web-resource-inliner/node_modules/dom-serializer/node_modules/domhandler": {
|
||||||
|
"version": "4.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
|
||||||
|
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/web-resource-inliner/node_modules/domhandler": {
|
||||||
|
"version": "3.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
|
||||||
|
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/web-resource-inliner/node_modules/domutils": {
|
||||||
|
"version": "2.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
||||||
|
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
|
||||||
|
"dependencies": {
|
||||||
|
"dom-serializer": "^1.0.1",
|
||||||
|
"domelementtype": "^2.2.0",
|
||||||
|
"domhandler": "^4.2.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/web-resource-inliner/node_modules/domutils/node_modules/domhandler": {
|
||||||
|
"version": "4.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
|
||||||
|
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/web-resource-inliner/node_modules/entities": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/web-resource-inliner/node_modules/htmlparser2": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.0.1",
|
||||||
|
"domhandler": "^3.3.0",
|
||||||
|
"domutils": "^2.4.2",
|
||||||
|
"entities": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/htmlparser2?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/whatwg-encoding": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"iconv-lite": "0.6.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/whatwg-mimetype": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
"i18next": "^23.15.2",
|
"i18next": "^23.15.2",
|
||||||
"i18next-browser-languagedetector": "^8.0.0",
|
"i18next-browser-languagedetector": "^8.0.0",
|
||||||
"i18next-resources-to-backend": "^1.2.1",
|
"i18next-resources-to-backend": "^1.2.1",
|
||||||
|
"juice": "^11.0.0",
|
||||||
"lucide-react": "^0.451.0",
|
"lucide-react": "^0.451.0",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
@ -34,7 +35,9 @@
|
||||||
"validator": "^13.12.0"
|
"validator": "^13.12.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@csstools/postcss-is-pseudo-class": "^5.0.1",
|
||||||
"@eslint/js": "^9.11.1",
|
"@eslint/js": "^9.11.1",
|
||||||
|
"@tailwindcss/typography": "^0.5.15",
|
||||||
"@types/react": "^18.3.10",
|
"@types/react": "^18.3.10",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@vitejs/plugin-legacy": "^5.4.2",
|
"@vitejs/plugin-legacy": "^5.4.2",
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
export default {
|
export default {
|
||||||
plugins: {
|
plugins: {
|
||||||
tailwindcss: {},
|
tailwindcss: {},
|
||||||
|
"./postcss/transform-pseudoclass.js": {},
|
||||||
|
"@csstools/postcss-is-pseudo-class": {
|
||||||
|
preserve: true
|
||||||
|
},
|
||||||
autoprefixer: {},
|
autoprefixer: {},
|
||||||
"postcss-css-variables": {
|
"postcss-css-variables": {
|
||||||
preserve: true
|
preserve: true
|
||||||
|
|
1
frontend/postcss/package.json
Normal file
1
frontend/postcss/package.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{}
|
17
frontend/postcss/transform-pseudoclass.js
Normal file
17
frontend/postcss/transform-pseudoclass.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
module.exports = (opts = {}) => {
|
||||||
|
return {
|
||||||
|
postcssPlugin: 'postcss-where-to-is-and-prefix',
|
||||||
|
Once(root, { result }) {
|
||||||
|
root.walkRules((rule) => {
|
||||||
|
rule.selector = rule.selector.replace(/\:where\(([^)]*)\)/g, ':is($1)');
|
||||||
|
if (rule.selector.match(/\:is\([^)]*\)/)) {
|
||||||
|
rule.selector = rule.selector + ", " +
|
||||||
|
rule.selector.replace(/\:is\(([^)]*)\)/g, ':-moz-any($1)') + ", " +
|
||||||
|
rule.selector.replace(/\:is\(([^)]*)\)/g, ':-webkit-any($1)')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.postcss = true;
|
|
@ -46,7 +46,7 @@ const ThemeProvider = ({ children }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeContext.Provider
|
<ThemeContext.Provider
|
||||||
value={{ currentTheme, setTheme, areThemesSupported }}
|
value={{ currentTheme, setTheme, areThemesSupported, isDarkMode }}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</ThemeContext.Provider>
|
</ThemeContext.Provider>
|
||||||
|
|
|
@ -156,8 +156,13 @@ function ComposeContent() {
|
||||||
}
|
}
|
||||||
if (messageData) {
|
if (messageData) {
|
||||||
const message = messageData.messages[messageData.messages.length - 1];
|
const message = messageData.messages[messageData.messages.length - 1];
|
||||||
const sanitizedBody = DOMPurify.sanitize(message.body, {
|
const inlinedBody = (await import("juice/client")).default(
|
||||||
WHOLE_DOCUMENT: true
|
message.body
|
||||||
|
);
|
||||||
|
const sanitizedBody = DOMPurify.sanitize(inlinedBody, {
|
||||||
|
WHOLE_DOCUMENT: true,
|
||||||
|
FORBID_TAGS: ["style"],
|
||||||
|
FORBID_ATTR: ["class"]
|
||||||
});
|
});
|
||||||
const parsedBody = new DOMParser().parseFromString(
|
const parsedBody = new DOMParser().parseFromString(
|
||||||
sanitizedBody,
|
sanitizedBody,
|
||||||
|
@ -564,7 +569,7 @@ function ComposeContent() {
|
||||||
cc: ccValues,
|
cc: ccValues,
|
||||||
bcc: bccValues,
|
bcc: bccValues,
|
||||||
subject: subject,
|
subject: subject,
|
||||||
content: contents,
|
content: `<!DOCTYPE html><html><head><meta name="viewport" content="width=device-width, initial-scale=1.0" /></head><body>${contents}</body></html>`,
|
||||||
inReplyTo: inReplyTo,
|
inReplyTo: inReplyTo,
|
||||||
attachments: finalAttachments,
|
attachments: finalAttachments,
|
||||||
draftMailbox: draftMailbox,
|
draftMailbox: draftMailbox,
|
||||||
|
@ -1077,7 +1082,7 @@ function ComposeContent() {
|
||||||
cc: ccValues,
|
cc: ccValues,
|
||||||
bcc: bccValues,
|
bcc: bccValues,
|
||||||
subject: subject,
|
subject: subject,
|
||||||
content: contents,
|
content: `<!DOCTYPE html><html><head><meta name="viewport" content="width=device-width, initial-scale=1.0" /></head><body>${contents}</body></html>`,
|
||||||
inReplyTo: inReplyTo,
|
inReplyTo: inReplyTo,
|
||||||
attachments: finalAttachments,
|
attachments: finalAttachments,
|
||||||
draftMailbox: draftMailbox,
|
draftMailbox: draftMailbox,
|
||||||
|
|
|
@ -13,8 +13,8 @@ import {
|
||||||
Trash,
|
Trash,
|
||||||
TriangleAlert
|
TriangleAlert
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useCallback, useContext, useEffect, useRef, useState } from "react";
|
import { useContext, useEffect, useState } from "react";
|
||||||
import Iframe from "@/components/Iframe.jsx";
|
import { ThemeContext } from "@/contexts/ThemeContext.jsx";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import DOMPurify from "dompurify";
|
import DOMPurify from "dompurify";
|
||||||
import { filesize } from "filesize";
|
import { filesize } from "filesize";
|
||||||
|
@ -26,10 +26,10 @@ import Loading from "@/components/Loading.jsx";
|
||||||
import download from "downloadjs";
|
import download from "downloadjs";
|
||||||
|
|
||||||
function MessageContent() {
|
function MessageContent() {
|
||||||
const iframeRef = useRef({});
|
|
||||||
const [iframeHeights, setIframeHeights] = useState({});
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { isDarkMode } = useContext(ThemeContext);
|
||||||
const { toast } = useContext(ToastContext);
|
const { toast } = useContext(ToastContext);
|
||||||
|
const [juice, setJuice] = useState(null);
|
||||||
const [moveShown, setMoveShown] = useState(false);
|
const [moveShown, setMoveShown] = useState(false);
|
||||||
const view = useSelector((state) => state.view.view);
|
const view = useSelector((state) => state.view.view);
|
||||||
const hasMoreThanOneMailbox = useSelector(
|
const hasMoreThanOneMailbox = useSelector(
|
||||||
|
@ -99,94 +99,70 @@ function MessageContent() {
|
||||||
}
|
}
|
||||||
}, [refresh, loading, dispatch]);
|
}, [refresh, loading, dispatch]);
|
||||||
|
|
||||||
const replaceCIDsOnIframeLoad = (iframeRefContents, id, attachments) => {
|
const isLightOrDark = (rgbColor) => {
|
||||||
return () => {
|
let [r, g, b] = rgbColor;
|
||||||
const srcElements =
|
let hsp = Math.sqrt(0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b));
|
||||||
iframeRefContents.contentWindow.document.querySelectorAll("[src]");
|
return hsp > 127.5 ? "light" : "dark";
|
||||||
srcElements.forEach((srcElement) => {
|
|
||||||
if (srcElement.src) {
|
|
||||||
const cidMatch = srcElement.src.match(/^cid:(.+)/);
|
|
||||||
if (cidMatch) {
|
|
||||||
const cid = cidMatch[1];
|
|
||||||
const attachment = attachments.find((attachment) => {
|
|
||||||
return attachment.contentId == cid;
|
|
||||||
});
|
|
||||||
if (attachment) {
|
|
||||||
srcElement.src = `/api/receive/attachment/${attachment.id}`;
|
|
||||||
// Add onload event listener to images with CIDs, so that iframe heights are not broken
|
|
||||||
srcElement.addEventListener("load", () => {
|
|
||||||
resizeOnIframeLoad(iframeRefContents, id)();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const processLinksAndFormsOnIframeLoad = (iframeRefContents) => {
|
const flipLightness = (rgb) => {
|
||||||
return () => {
|
// Convert RGB to HSL
|
||||||
const aElements =
|
let r = rgb[0] / 255;
|
||||||
iframeRefContents.contentWindow.document.querySelectorAll("a");
|
let g = rgb[1] / 255;
|
||||||
aElements.forEach((aElement) => {
|
let b = rgb[2] / 255;
|
||||||
const currentHashURL =
|
|
||||||
document.location.origin + document.location.pathname + "#";
|
|
||||||
if (
|
|
||||||
!aElement.href ||
|
|
||||||
aElement.href.slice(0, 1) == "#" ||
|
|
||||||
aElement.href.slice(0, currentHashURL.length) == currentHashURL
|
|
||||||
) {
|
|
||||||
// Prevent changing the URL
|
|
||||||
aElement.addEventListener("click", (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
});
|
|
||||||
aElement.target = "_self";
|
|
||||||
} else {
|
|
||||||
aElement.target = "_parent";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const formElements =
|
let max = Math.max(r, g, b);
|
||||||
iframeRefContents.contentWindow.document.querySelectorAll("form");
|
let min = Math.min(r, g, b);
|
||||||
formElements.forEach((formElement) => {
|
let h,
|
||||||
const currentHashURL =
|
s,
|
||||||
document.location.origin + document.location.pathname + "#";
|
l = (max + min) / 2;
|
||||||
if (
|
|
||||||
!formElement.action ||
|
if (max === min) {
|
||||||
formElement.action.slice(0, 1) == "#" ||
|
h = s = 0; // achromatic
|
||||||
formElement.action.slice(0, currentHashURL.length) == currentHashURL
|
} else {
|
||||||
) {
|
let d = max - min;
|
||||||
// Prevent form submitting
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||||
formElement.addEventListener("submit", (e) => {
|
switch (max) {
|
||||||
e.preventDefault();
|
case r:
|
||||||
});
|
h = (g - b) / d + (g < b ? 6 : 0);
|
||||||
formElement.target = "_self";
|
break;
|
||||||
} else {
|
case g:
|
||||||
formElement.target = "_parent";
|
h = (b - r) / d + 2;
|
||||||
}
|
break;
|
||||||
});
|
case b:
|
||||||
};
|
h = (r - g) / d + 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
h /= 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flip lightness
|
||||||
|
l = 1 - l;
|
||||||
|
|
||||||
|
// Convert HSL back to RGB
|
||||||
|
if (s === 0) {
|
||||||
|
r = g = b = l; // achromatic
|
||||||
|
} else {
|
||||||
|
let hue2rgb = function hue2rgb(p, q, t) {
|
||||||
|
if (t < 0) t += 1;
|
||||||
|
if (t > 1) t -= 1;
|
||||||
|
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
||||||
|
if (t < 1 / 2) return q;
|
||||||
|
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
|
||||||
|
let q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
||||||
|
let p = 2 * l - q;
|
||||||
|
r = hue2rgb(p, q, h + 1 / 3);
|
||||||
|
g = hue2rgb(p, q, h);
|
||||||
|
b = hue2rgb(p, q, h - 1 / 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return RGB
|
||||||
|
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
|
||||||
};
|
};
|
||||||
|
|
||||||
const resizeOnIframeLoad = useCallback((iframeRefContents, id) => {
|
|
||||||
return () => {
|
|
||||||
const body = iframeRefContents.contentWindow.document.body;
|
|
||||||
const html = iframeRefContents.contentWindow.document.documentElement;
|
|
||||||
const newHeight = Math.max(
|
|
||||||
html.scrollHeight > parseInt(iframeRefContents.height)
|
|
||||||
? html.scrollHeight
|
|
||||||
: 0,
|
|
||||||
body.offsetHeight,
|
|
||||||
html.offsetHeight
|
|
||||||
);
|
|
||||||
setIframeHeights((iframeHeightsO) => {
|
|
||||||
const newIframeHeights = { ...iframeHeightsO };
|
|
||||||
newIframeHeights[id] = newHeight;
|
|
||||||
return newIframeHeights;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const getMessageIds = () => {
|
const getMessageIds = () => {
|
||||||
return messagesToRender
|
return messagesToRender
|
||||||
.slice()
|
.slice()
|
||||||
|
@ -194,20 +170,6 @@ function MessageContent() {
|
||||||
.map((message) => message.id);
|
.map((message) => message.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const resizeOnIframeLoadAllRefs = () => {
|
|
||||||
Object.keys(iframeRef.current).forEach((refKey) => {
|
|
||||||
resizeOnIframeLoad(iframeRef.current[refKey], refKey)();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener("resize", resizeOnIframeLoadAllRefs);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener("resize", resizeOnIframeLoadAllRefs);
|
|
||||||
};
|
|
||||||
}, [resizeOnIframeLoad]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!loading && messageData && messageData.messages.length > 0)
|
if (!loading && messageData && messageData.messages.length > 0)
|
||||||
document.title = `${
|
document.title = `${
|
||||||
|
@ -244,7 +206,17 @@ function MessageContent() {
|
||||||
}
|
}
|
||||||
}, [view, dispatch]);
|
}, [view, dispatch]);
|
||||||
|
|
||||||
if (loading) {
|
useEffect(() => {
|
||||||
|
const loadJuice = async () => {
|
||||||
|
const newJuice = (await import("juice/client")).default;
|
||||||
|
// Set juice to be a function. The function which returns the function is passed into setJuice
|
||||||
|
setJuice(() => newJuice);
|
||||||
|
};
|
||||||
|
|
||||||
|
loadJuice();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (loading || !juice) {
|
||||||
return <Loading />;
|
return <Loading />;
|
||||||
} else if (error) {
|
} else if (error) {
|
||||||
return (
|
return (
|
||||||
|
@ -762,6 +734,156 @@ function MessageContent() {
|
||||||
address: "unknown@example.com"
|
address: "unknown@example.com"
|
||||||
};
|
};
|
||||||
const firstFromAddress = firstFrom.address || "unknown@example.com";
|
const firstFromAddress = firstFrom.address || "unknown@example.com";
|
||||||
|
const inlinedBody = juice(body);
|
||||||
|
const sanitizedBody = DOMPurify.sanitize(inlinedBody, {
|
||||||
|
WHOLE_DOCUMENT: true,
|
||||||
|
FORBID_TAGS: ["style"],
|
||||||
|
FORBID_ATTR: ["class"]
|
||||||
|
});
|
||||||
|
const parsedDocument = new DOMParser().parseFromString(
|
||||||
|
sanitizedBody,
|
||||||
|
"text/html"
|
||||||
|
);
|
||||||
|
const aElements = parsedDocument.querySelectorAll("a");
|
||||||
|
aElements.forEach((aElement) => {
|
||||||
|
const currentHashURL =
|
||||||
|
document.location.origin + document.location.pathname + "#";
|
||||||
|
if (
|
||||||
|
!aElement.href ||
|
||||||
|
aElement.href.slice(0, 1) == "#" ||
|
||||||
|
aElement.href.slice(0, currentHashURL.length) == currentHashURL
|
||||||
|
) {
|
||||||
|
// Prevent changing the URL
|
||||||
|
aElement.addEventListener("click", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
aElement.target = "_self";
|
||||||
|
} else {
|
||||||
|
aElement.target = "_parent";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const formElements = parsedDocument.querySelectorAll("form");
|
||||||
|
formElements.forEach((formElement) => {
|
||||||
|
const currentHashURL =
|
||||||
|
document.location.origin + document.location.pathname + "#";
|
||||||
|
if (
|
||||||
|
!formElement.action ||
|
||||||
|
formElement.action.slice(0, 1) == "#" ||
|
||||||
|
formElement.action.slice(0, currentHashURL.length) ==
|
||||||
|
currentHashURL
|
||||||
|
) {
|
||||||
|
// Prevent form submitting
|
||||||
|
formElement.addEventListener("submit", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
formElement.target = "_self";
|
||||||
|
} else {
|
||||||
|
formElement.target = "_parent";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const srcElements = parsedDocument.querySelectorAll("[src]");
|
||||||
|
srcElements.forEach((srcElement) => {
|
||||||
|
if (srcElement.src) {
|
||||||
|
const cidMatch = srcElement.src.match(/^cid:(.+)/);
|
||||||
|
if (cidMatch) {
|
||||||
|
const cid = cidMatch[1];
|
||||||
|
const attachment = attachments.find((attachment) => {
|
||||||
|
return attachment.contentId == cid;
|
||||||
|
});
|
||||||
|
if (attachment) {
|
||||||
|
srcElement.src = `/api/receive/attachment/${attachment.id}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const allBodyElements = parsedDocument.querySelectorAll("body *");
|
||||||
|
allBodyElements.forEach((element) => {
|
||||||
|
if (element.getAttribute("color") && !element.style.color) {
|
||||||
|
element.style.color = element.getAttribute("color");
|
||||||
|
element.removeAttribute("color");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
element.getAttribute("bgcolor") &&
|
||||||
|
!element.style.backgroundColor
|
||||||
|
) {
|
||||||
|
element.style.backgroundColor = element.getAttribute("bgcolor");
|
||||||
|
element.removeAttribute("bgcolor");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(element.tagName == "TABLE" ||
|
||||||
|
element.tagName == "TBODY" ||
|
||||||
|
element.tagName == "TR" ||
|
||||||
|
element.tagName == "TH" ||
|
||||||
|
element.tagName == "TD") &&
|
||||||
|
element.getAttribute("width") &&
|
||||||
|
!element.style.width
|
||||||
|
) {
|
||||||
|
element.style.width = element.getAttribute("width");
|
||||||
|
element.removeAttribute("width");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(element.tagName == "TABLE" ||
|
||||||
|
element.tagName == "TBODY" ||
|
||||||
|
element.tagName == "TR" ||
|
||||||
|
element.tagName == "TH" ||
|
||||||
|
element.tagName == "TD") &&
|
||||||
|
element.getAttribute("height") &&
|
||||||
|
!element.style.height
|
||||||
|
) {
|
||||||
|
element.style.height = element.getAttribute("height");
|
||||||
|
element.removeAttribute("height");
|
||||||
|
}
|
||||||
|
|
||||||
|
const computedStyle = window.getComputedStyle(element);
|
||||||
|
if (
|
||||||
|
element.style.font ||
|
||||||
|
element.style.color ||
|
||||||
|
element.getAttribute("color")
|
||||||
|
) {
|
||||||
|
const parsedColorMatch = computedStyle.color.match(
|
||||||
|
/rgba?\((\d{1,3}), (\d{1,3}), (\d{1,3})(?:, (\d{1,3}))?\)/
|
||||||
|
);
|
||||||
|
if (parsedColorMatch) {
|
||||||
|
const r = parseInt(parsedColorMatch[1]);
|
||||||
|
const g = parseInt(parsedColorMatch[2]);
|
||||||
|
const b = parseInt(parsedColorMatch[3]);
|
||||||
|
if (
|
||||||
|
isLightOrDark([r, g, b]) == (isDarkMode ? "dark" : "light")
|
||||||
|
) {
|
||||||
|
const newColors = flipLightness([r, g, b]);
|
||||||
|
element.style.color = `rgba(${newColors[0]}, ${newColors[1]}, ${newColors[2]}, ${parsedColorMatch[4] ? parsedColorMatch[4] : 255})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
element.style.background ||
|
||||||
|
element.style.backgroundColor ||
|
||||||
|
element.getAttribute("bgcolor")
|
||||||
|
) {
|
||||||
|
const parsedColorMatch = computedStyle.backgroundColor.match(
|
||||||
|
/rgba?\((\d{1,3}), (\d{1,3}), (\d{1,3})(?:, (\d{1,3}))?\)/
|
||||||
|
);
|
||||||
|
if (parsedColorMatch) {
|
||||||
|
const r = parseInt(parsedColorMatch[1]);
|
||||||
|
const g = parseInt(parsedColorMatch[2]);
|
||||||
|
const b = parseInt(parsedColorMatch[3]);
|
||||||
|
if (
|
||||||
|
isLightOrDark([r, g, b]) == (isDarkMode ? "light" : "dark")
|
||||||
|
) {
|
||||||
|
const newColors = flipLightness([r, g, b]);
|
||||||
|
element.style.backgroundColor = `rgba(${newColors[0]}, ${newColors[1]}, ${newColors[2]}, ${parsedColorMatch[4] ? parsedColorMatch[4] : 255})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const emailBody = parsedDocument.body.innerHTML;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="border-b-2 border-border" key={id}>
|
<div className="border-b-2 border-border" key={id}>
|
||||||
|
@ -918,28 +1040,9 @@ function MessageContent() {
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<Iframe
|
<div
|
||||||
ref={(el) => (iframeRef.current[id] = el)}
|
className="prose prose-email w-full max-w-full rounded-lg mb-2"
|
||||||
onLoad={() => {
|
dangerouslySetInnerHTML={{ __html: emailBody }}
|
||||||
setTimeout(() => {
|
|
||||||
replaceCIDsOnIframeLoad(
|
|
||||||
iframeRef.current[id],
|
|
||||||
id,
|
|
||||||
attachments
|
|
||||||
)();
|
|
||||||
processLinksAndFormsOnIframeLoad(iframeRef.current[id])();
|
|
||||||
resizeOnIframeLoad(iframeRef.current[id], id)();
|
|
||||||
}, 0);
|
|
||||||
}}
|
|
||||||
className="bg-white w-full rounded-lg mb-2 overflow-x-auto overflow-y-hidden"
|
|
||||||
srcDoc={DOMPurify.sanitize(body, {
|
|
||||||
WHOLE_DOCUMENT: true
|
|
||||||
})}
|
|
||||||
height={
|
|
||||||
typeof iframeHeights[id] == "undefined"
|
|
||||||
? 500
|
|
||||||
: iframeHeights[id]
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
{realAttachments && realAttachments.length > 0 ? (
|
{realAttachments && realAttachments.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import typography from "@tailwindcss/typography";
|
||||||
|
|
||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
export default {
|
export default {
|
||||||
darkMode: ["class"],
|
darkMode: ["class"],
|
||||||
|
@ -60,9 +62,61 @@ export default {
|
||||||
animation: {
|
animation: {
|
||||||
"accordion-down": "accordion-down 0.2s ease-out",
|
"accordion-down": "accordion-down 0.2s ease-out",
|
||||||
"accordion-up": "accordion-up 0.2s ease-out",
|
"accordion-up": "accordion-up 0.2s ease-out",
|
||||||
|
},
|
||||||
|
typography: {
|
||||||
|
DEFAULT: {
|
||||||
|
css: {
|
||||||
|
color: "hsla(var(--foreground), 1)",
|
||||||
|
a: {
|
||||||
|
color: "hsla(var(--primary), 1)"
|
||||||
|
},
|
||||||
|
strong: {
|
||||||
|
color: "hsla(var(--foreground), 1)"
|
||||||
|
},
|
||||||
|
b: {
|
||||||
|
color: "hsla(var(--foreground), 1)"
|
||||||
|
},
|
||||||
|
blockquote: {
|
||||||
|
color: "hsla(var(--foreground), 1)"
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
textAlign: null
|
||||||
|
},
|
||||||
|
tbody: {
|
||||||
|
textAlign: null
|
||||||
|
},
|
||||||
|
tr: {
|
||||||
|
textAlign: null
|
||||||
|
},
|
||||||
|
th: {
|
||||||
|
textAlign: null
|
||||||
|
},
|
||||||
|
td: {
|
||||||
|
textAlign: null
|
||||||
|
},
|
||||||
|
"th, td": {
|
||||||
|
textAlign: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
css: {
|
||||||
|
code: {
|
||||||
|
"&:before": {
|
||||||
|
content: ""
|
||||||
|
},
|
||||||
|
"&:after": {
|
||||||
|
content: ""
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pre: {
|
||||||
|
backgroundColor: "inherit"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [typography],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,5 +24,8 @@ export default defineConfig({
|
||||||
changeOrigin: true
|
changeOrigin: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
chunkSizeWarningLimit: 600
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue