mirror of
https://github.com/Ladebeze66/devsite.git
synced 2026-05-11 16:56:26 +02:00
extract_picture
This commit is contained in:
parent
13b4b6971c
commit
d423372251
3
.gitignore
vendored
3
.gitignore
vendored
@ -55,3 +55,6 @@ llm-api/*.pyc
|
|||||||
# Legacy RAG index (ChromaDB) — obsolete depuis bascule graph+BM25
|
# Legacy RAG index (ChromaDB) — obsolete depuis bascule graph+BM25
|
||||||
/chroma-index/
|
/chroma-index/
|
||||||
|
|
||||||
|
# Téléchargements + WebP générés par strapi_extraction/media-sync/ (poids important)
|
||||||
|
strapi_extraction/extract/media-sync-work/
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { fetchData } from "../utils/fetchData";
|
|||||||
import { getApiUrl } from "../utils/getApiUrl";
|
import { getApiUrl } from "../utils/getApiUrl";
|
||||||
import Carousel from "./Carousel";
|
import Carousel from "./Carousel";
|
||||||
import ReactMarkdown from "react-markdown";
|
import ReactMarkdown from "react-markdown";
|
||||||
|
import remarkGfm from "remark-gfm";
|
||||||
|
|
||||||
interface ImageData {
|
interface ImageData {
|
||||||
url: string;
|
url: string;
|
||||||
@ -211,7 +212,7 @@ export default function ContentSection({
|
|||||||
prose-li:marker:text-primary
|
prose-li:marker:text-primary
|
||||||
prose-hr:border-0 prose-hr:w-16 prose-hr:mx-auto prose-hr:bg-primary/30 prose-hr:h-0.5 prose-hr:rounded-full prose-hr:my-6"
|
prose-hr:border-0 prose-hr:w-16 prose-hr:mx-auto prose-hr:bg-primary/30 prose-hr:h-0.5 prose-hr:rounded-full prose-hr:my-6"
|
||||||
>
|
>
|
||||||
<ReactMarkdown>{richText}</ReactMarkdown>
|
<ReactMarkdown remarkPlugins={[remarkGfm]}>{richText}</ReactMarkdown>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Outils `strapi_extraction/`
|
# Outils `strapi_extraction/`
|
||||||
|
|
||||||
**Dernière mise à jour :** 2026-04-22
|
**Dernière mise à jour :** 2026-04-28
|
||||||
|
|
||||||
Dossier de **scripts Node + Python** pour extraire, nettoyer et convertir les
|
Dossier de **scripts Node + Python** pour extraire, nettoyer et convertir les
|
||||||
données issues de l'API Strapi en base de connaissance chatbot (hors runtime
|
données issues de l'API Strapi en base de connaissance chatbot (hors runtime
|
||||||
@ -84,8 +84,18 @@ comme source de vérité sans comparer au CMS.
|
|||||||
Ces points seront corrigés en même temps que l'enrichissement du vault
|
Ces points seront corrigés en même temps que l'enrichissement du vault
|
||||||
(glossaire + homepage Strapi → notes `40-Glossaire/` et `30-Parcours/`).
|
(glossaire + homepage Strapi → notes `40-Glossaire/` et `30-Parcours/`).
|
||||||
|
|
||||||
|
## Sync médias WebP (hors pipeline GrasBot)
|
||||||
|
|
||||||
|
Dossier **`strapi_extraction/media-sync/`** — inventaire des fichiers image liés aux
|
||||||
|
content-types (`projects`, `competences`, `homepages`, `realisation-ias`, `glossaires`),
|
||||||
|
téléchargement classé par rubrique, conversion WebP (sharp), puis ré-upload optionnel.
|
||||||
|
|
||||||
|
Documentation : voir `strapi_extraction/media-sync/README.md`.
|
||||||
|
Sortie lourde (ignorée Git) : `strapi_extraction/extract/media-sync-work/`.
|
||||||
|
|
||||||
## Liens complémentaires
|
## Liens complémentaires
|
||||||
|
|
||||||
- Vault + retrieval : [`08-vault-obsidian-retrieval.md`](./08-vault-obsidian-retrieval.md)
|
- Vault + retrieval : [`08-vault-obsidian-retrieval.md`](./08-vault-obsidian-retrieval.md)
|
||||||
- API LLM : [`04-api-llm-et-chatbot.md`](./04-api-llm-et-chatbot.md)
|
- API LLM : [`04-api-llm-et-chatbot.md`](./04-api-llm-et-chatbot.md)
|
||||||
- Schémas Strapi : [`03-cms-strapi.md`](./03-cms-strapi.md)
|
- Schémas Strapi : [`03-cms-strapi.md`](./03-cms-strapi.md)
|
||||||
|
- Performances images (audit) : [`09-performances-images.md`](./09-performances-images.md)
|
||||||
|
|||||||
673
package-lock.json
generated
673
package-lock.json
generated
@ -30,6 +30,7 @@
|
|||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
"postcss": "^8",
|
"postcss": "^8",
|
||||||
|
"sharp": "^0.33.5",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
@ -47,9 +48,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@emnapi/runtime": {
|
"node_modules/@emnapi/runtime": {
|
||||||
"version": "1.8.1",
|
"version": "1.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
|
||||||
"integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==",
|
"integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -57,9 +58,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/colour": {
|
"node_modules/@img/colour": {
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz",
|
||||||
"integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==",
|
"integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -67,12 +68,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-darwin-arm64": {
|
"node_modules/@img/sharp-darwin-arm64": {
|
||||||
"version": "0.34.5",
|
"version": "0.33.5",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz",
|
||||||
"integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
|
"integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -85,16 +87,17 @@
|
|||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-darwin-arm64": "1.2.4"
|
"@img/sharp-libvips-darwin-arm64": "1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-darwin-x64": {
|
"node_modules/@img/sharp-darwin-x64": {
|
||||||
"version": "0.34.5",
|
"version": "0.33.5",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz",
|
||||||
"integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
|
"integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -107,16 +110,17 @@
|
|||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-darwin-x64": "1.2.4"
|
"@img/sharp-libvips-darwin-x64": "1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-libvips-darwin-arm64": {
|
"node_modules/@img/sharp-libvips-darwin-arm64": {
|
||||||
"version": "1.2.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz",
|
||||||
"integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
|
"integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -127,12 +131,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-libvips-darwin-x64": {
|
"node_modules/@img/sharp-libvips-darwin-x64": {
|
||||||
"version": "1.2.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz",
|
||||||
"integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
|
"integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -143,12 +148,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-libvips-linux-arm": {
|
"node_modules/@img/sharp-libvips-linux-arm": {
|
||||||
"version": "1.2.4",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz",
|
||||||
"integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
|
"integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -159,12 +165,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-libvips-linux-arm64": {
|
"node_modules/@img/sharp-libvips-linux-arm64": {
|
||||||
"version": "1.2.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz",
|
||||||
"integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
|
"integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -207,12 +214,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-libvips-linux-s390x": {
|
"node_modules/@img/sharp-libvips-linux-s390x": {
|
||||||
"version": "1.2.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz",
|
||||||
"integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
|
"integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -223,12 +231,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-libvips-linux-x64": {
|
"node_modules/@img/sharp-libvips-linux-x64": {
|
||||||
"version": "1.2.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz",
|
||||||
"integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
|
"integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -239,12 +248,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
|
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
|
||||||
"version": "1.2.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz",
|
||||||
"integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
|
"integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -255,12 +265,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
|
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
|
||||||
"version": "1.2.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz",
|
||||||
"integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
|
"integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -271,12 +282,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-linux-arm": {
|
"node_modules/@img/sharp-linux-arm": {
|
||||||
"version": "0.34.5",
|
"version": "0.33.5",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz",
|
||||||
"integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
|
"integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -289,16 +301,17 @@
|
|||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linux-arm": "1.2.4"
|
"@img/sharp-libvips-linux-arm": "1.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-linux-arm64": {
|
"node_modules/@img/sharp-linux-arm64": {
|
||||||
"version": "0.34.5",
|
"version": "0.33.5",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz",
|
||||||
"integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
|
"integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -311,7 +324,7 @@
|
|||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linux-arm64": "1.2.4"
|
"@img/sharp-libvips-linux-arm64": "1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-linux-ppc64": {
|
"node_modules/@img/sharp-linux-ppc64": {
|
||||||
@ -359,12 +372,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-linux-s390x": {
|
"node_modules/@img/sharp-linux-s390x": {
|
||||||
"version": "0.34.5",
|
"version": "0.33.5",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz",
|
||||||
"integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
|
"integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -377,16 +391,17 @@
|
|||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linux-s390x": "1.2.4"
|
"@img/sharp-libvips-linux-s390x": "1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-linux-x64": {
|
"node_modules/@img/sharp-linux-x64": {
|
||||||
"version": "0.34.5",
|
"version": "0.33.5",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz",
|
||||||
"integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
|
"integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -399,16 +414,17 @@
|
|||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linux-x64": "1.2.4"
|
"@img/sharp-libvips-linux-x64": "1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-linuxmusl-arm64": {
|
"node_modules/@img/sharp-linuxmusl-arm64": {
|
||||||
"version": "0.34.5",
|
"version": "0.33.5",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz",
|
||||||
"integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
|
"integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -421,16 +437,17 @@
|
|||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
|
"@img/sharp-libvips-linuxmusl-arm64": "1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-linuxmusl-x64": {
|
"node_modules/@img/sharp-linuxmusl-x64": {
|
||||||
"version": "0.34.5",
|
"version": "0.33.5",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz",
|
||||||
"integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
|
"integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -443,20 +460,21 @@
|
|||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linuxmusl-x64": "1.2.4"
|
"@img/sharp-libvips-linuxmusl-x64": "1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-wasm32": {
|
"node_modules/@img/sharp-wasm32": {
|
||||||
"version": "0.34.5",
|
"version": "0.33.5",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz",
|
||||||
"integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
|
"integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"wasm32"
|
"wasm32"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
|
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emnapi/runtime": "^1.7.0"
|
"@emnapi/runtime": "^1.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
@ -485,12 +503,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-win32-ia32": {
|
"node_modules/@img/sharp-win32-ia32": {
|
||||||
"version": "0.34.5",
|
"version": "0.33.5",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz",
|
||||||
"integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
|
"integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -504,12 +523,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@img/sharp-win32-x64": {
|
"node_modules/@img/sharp-win32-x64": {
|
||||||
"version": "0.34.5",
|
"version": "0.33.5",
|
||||||
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
|
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz",
|
||||||
"integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
|
"integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
"dev": true,
|
||||||
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -1164,6 +1184,20 @@
|
|||||||
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/color": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^2.0.1",
|
||||||
|
"color-string": "^1.9.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/color-convert": {
|
"node_modules/color-convert": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
@ -1182,6 +1216,17 @@
|
|||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/color-string": {
|
||||||
|
"version": "1.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
|
||||||
|
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "^1.0.0",
|
||||||
|
"simple-swizzle": "^0.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/comma-separated-tokens": {
|
"node_modules/comma-separated-tokens": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
|
||||||
@ -1276,8 +1321,8 @@
|
|||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||||
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
||||||
|
"devOptional": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
@ -1860,6 +1905,13 @@
|
|||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-arrayish": {
|
||||||
|
"version": "0.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz",
|
||||||
|
"integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/is-binary-path": {
|
"node_modules/is-binary-path": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
@ -3058,6 +3110,367 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-darwin-arm64": {
|
||||||
|
"version": "0.34.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
|
||||||
|
"integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@img/sharp-libvips-darwin-arm64": "1.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-darwin-x64": {
|
||||||
|
"version": "0.34.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
|
||||||
|
"integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@img/sharp-libvips-darwin-x64": "1.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-libvips-darwin-arm64": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "LGPL-3.0-or-later",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-libvips-darwin-x64": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "LGPL-3.0-or-later",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-libvips-linux-arm": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"license": "LGPL-3.0-or-later",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-libvips-linux-arm64": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "LGPL-3.0-or-later",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-libvips-linux-s390x": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
|
||||||
|
"cpu": [
|
||||||
|
"s390x"
|
||||||
|
],
|
||||||
|
"license": "LGPL-3.0-or-later",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-libvips-linux-x64": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "LGPL-3.0-or-later",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-libvips-linuxmusl-arm64": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "LGPL-3.0-or-later",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-libvips-linuxmusl-x64": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "LGPL-3.0-or-later",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-linux-arm": {
|
||||||
|
"version": "0.34.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
|
||||||
|
"integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@img/sharp-libvips-linux-arm": "1.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-linux-arm64": {
|
||||||
|
"version": "0.34.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
|
||||||
|
"integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@img/sharp-libvips-linux-arm64": "1.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-linux-s390x": {
|
||||||
|
"version": "0.34.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
|
||||||
|
"integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
|
||||||
|
"cpu": [
|
||||||
|
"s390x"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@img/sharp-libvips-linux-s390x": "1.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-linux-x64": {
|
||||||
|
"version": "0.34.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
|
||||||
|
"integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@img/sharp-libvips-linux-x64": "1.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-linuxmusl-arm64": {
|
||||||
|
"version": "0.34.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
|
||||||
|
"integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-linuxmusl-x64": {
|
||||||
|
"version": "0.34.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
|
||||||
|
"integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@img/sharp-libvips-linuxmusl-x64": "1.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-wasm32": {
|
||||||
|
"version": "0.34.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
|
||||||
|
"integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
|
||||||
|
"cpu": [
|
||||||
|
"wasm32"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/runtime": "^1.7.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-win32-ia32": {
|
||||||
|
"version": "0.34.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
|
||||||
|
"integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/next/node_modules/@img/sharp-win32-x64": {
|
||||||
|
"version": "0.34.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
|
||||||
|
"integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0 AND LGPL-3.0-or-later",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/next/node_modules/postcss": {
|
"node_modules/next/node_modules/postcss": {
|
||||||
"version": "8.4.31",
|
"version": "8.4.31",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
||||||
@ -3086,6 +3499,51 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/next/node_modules/sharp": {
|
||||||
|
"version": "0.34.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
|
||||||
|
"integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@img/colour": "^1.0.0",
|
||||||
|
"detect-libc": "^2.1.2",
|
||||||
|
"semver": "^7.7.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/libvips"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@img/sharp-darwin-arm64": "0.34.5",
|
||||||
|
"@img/sharp-darwin-x64": "0.34.5",
|
||||||
|
"@img/sharp-libvips-darwin-arm64": "1.2.4",
|
||||||
|
"@img/sharp-libvips-darwin-x64": "1.2.4",
|
||||||
|
"@img/sharp-libvips-linux-arm": "1.2.4",
|
||||||
|
"@img/sharp-libvips-linux-arm64": "1.2.4",
|
||||||
|
"@img/sharp-libvips-linux-ppc64": "1.2.4",
|
||||||
|
"@img/sharp-libvips-linux-riscv64": "1.2.4",
|
||||||
|
"@img/sharp-libvips-linux-s390x": "1.2.4",
|
||||||
|
"@img/sharp-libvips-linux-x64": "1.2.4",
|
||||||
|
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
|
||||||
|
"@img/sharp-libvips-linuxmusl-x64": "1.2.4",
|
||||||
|
"@img/sharp-linux-arm": "0.34.5",
|
||||||
|
"@img/sharp-linux-arm64": "0.34.5",
|
||||||
|
"@img/sharp-linux-ppc64": "0.34.5",
|
||||||
|
"@img/sharp-linux-riscv64": "0.34.5",
|
||||||
|
"@img/sharp-linux-s390x": "0.34.5",
|
||||||
|
"@img/sharp-linux-x64": "0.34.5",
|
||||||
|
"@img/sharp-linuxmusl-arm64": "0.34.5",
|
||||||
|
"@img/sharp-linuxmusl-x64": "0.34.5",
|
||||||
|
"@img/sharp-wasm32": "0.34.5",
|
||||||
|
"@img/sharp-win32-arm64": "0.34.5",
|
||||||
|
"@img/sharp-win32-ia32": "0.34.5",
|
||||||
|
"@img/sharp-win32-x64": "0.34.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/normalize-path": {
|
"node_modules/normalize-path": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
@ -3713,8 +4171,8 @@
|
|||||||
"version": "7.7.3",
|
"version": "7.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
||||||
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
||||||
|
"devOptional": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"optional": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
},
|
},
|
||||||
@ -3723,16 +4181,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/sharp": {
|
"node_modules/sharp": {
|
||||||
"version": "0.34.5",
|
"version": "0.33.5",
|
||||||
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
|
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz",
|
||||||
"integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
|
"integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==",
|
||||||
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@img/colour": "^1.0.0",
|
"color": "^4.2.3",
|
||||||
"detect-libc": "^2.1.2",
|
"detect-libc": "^2.0.3",
|
||||||
"semver": "^7.7.3"
|
"semver": "^7.6.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
||||||
@ -3741,30 +4199,25 @@
|
|||||||
"url": "https://opencollective.com/libvips"
|
"url": "https://opencollective.com/libvips"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-darwin-arm64": "0.34.5",
|
"@img/sharp-darwin-arm64": "0.33.5",
|
||||||
"@img/sharp-darwin-x64": "0.34.5",
|
"@img/sharp-darwin-x64": "0.33.5",
|
||||||
"@img/sharp-libvips-darwin-arm64": "1.2.4",
|
"@img/sharp-libvips-darwin-arm64": "1.0.4",
|
||||||
"@img/sharp-libvips-darwin-x64": "1.2.4",
|
"@img/sharp-libvips-darwin-x64": "1.0.4",
|
||||||
"@img/sharp-libvips-linux-arm": "1.2.4",
|
"@img/sharp-libvips-linux-arm": "1.0.5",
|
||||||
"@img/sharp-libvips-linux-arm64": "1.2.4",
|
"@img/sharp-libvips-linux-arm64": "1.0.4",
|
||||||
"@img/sharp-libvips-linux-ppc64": "1.2.4",
|
"@img/sharp-libvips-linux-s390x": "1.0.4",
|
||||||
"@img/sharp-libvips-linux-riscv64": "1.2.4",
|
"@img/sharp-libvips-linux-x64": "1.0.4",
|
||||||
"@img/sharp-libvips-linux-s390x": "1.2.4",
|
"@img/sharp-libvips-linuxmusl-arm64": "1.0.4",
|
||||||
"@img/sharp-libvips-linux-x64": "1.2.4",
|
"@img/sharp-libvips-linuxmusl-x64": "1.0.4",
|
||||||
"@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
|
"@img/sharp-linux-arm": "0.33.5",
|
||||||
"@img/sharp-libvips-linuxmusl-x64": "1.2.4",
|
"@img/sharp-linux-arm64": "0.33.5",
|
||||||
"@img/sharp-linux-arm": "0.34.5",
|
"@img/sharp-linux-s390x": "0.33.5",
|
||||||
"@img/sharp-linux-arm64": "0.34.5",
|
"@img/sharp-linux-x64": "0.33.5",
|
||||||
"@img/sharp-linux-ppc64": "0.34.5",
|
"@img/sharp-linuxmusl-arm64": "0.33.5",
|
||||||
"@img/sharp-linux-riscv64": "0.34.5",
|
"@img/sharp-linuxmusl-x64": "0.33.5",
|
||||||
"@img/sharp-linux-s390x": "0.34.5",
|
"@img/sharp-wasm32": "0.33.5",
|
||||||
"@img/sharp-linux-x64": "0.34.5",
|
"@img/sharp-win32-ia32": "0.33.5",
|
||||||
"@img/sharp-linuxmusl-arm64": "0.34.5",
|
"@img/sharp-win32-x64": "0.33.5"
|
||||||
"@img/sharp-linuxmusl-x64": "0.34.5",
|
|
||||||
"@img/sharp-wasm32": "0.34.5",
|
|
||||||
"@img/sharp-win32-arm64": "0.34.5",
|
|
||||||
"@img/sharp-win32-ia32": "0.34.5",
|
|
||||||
"@img/sharp-win32-x64": "0.34.5"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/shebang-command": {
|
"node_modules/shebang-command": {
|
||||||
@ -3872,6 +4325,16 @@
|
|||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/simple-swizzle": {
|
||||||
|
"version": "0.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz",
|
||||||
|
"integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-arrayish": "^0.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/source-map-js": {
|
"node_modules/source-map-js": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||||
|
|||||||
@ -6,7 +6,11 @@
|
|||||||
"dev": "next dev --turbopack",
|
"dev": "next dev --turbopack",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint"
|
"lint": "next lint",
|
||||||
|
"media:inventory": "node strapi_extraction/media-sync/01-fetch-inventory.js",
|
||||||
|
"media:download": "node strapi_extraction/media-sync/02-download.js",
|
||||||
|
"media:webp": "node strapi_extraction/media-sync/03-convert-webp.js",
|
||||||
|
"media:upload": "node strapi_extraction/media-sync/04-upload-replace.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@strapi/blocks-react-renderer": "^1.0.1",
|
"@strapi/blocks-react-renderer": "^1.0.1",
|
||||||
@ -31,6 +35,7 @@
|
|||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
"postcss": "^8",
|
"postcss": "^8",
|
||||||
|
"sharp": "^0.33.5",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
|
|||||||
139
strapi_extraction/media-sync/01-fetch-inventory.js
Normal file
139
strapi_extraction/media-sync/01-fetch-inventory.js
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/**
|
||||||
|
* 01 — Appelle l’API Strapi (lecture publique) et produit media-inventory.json
|
||||||
|
* (liste de tous les fichiers image liés aux content-types configurés).
|
||||||
|
*
|
||||||
|
* Usage : node strapi_extraction/media-sync/01-fetch-inventory.js
|
||||||
|
*/
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
const {
|
||||||
|
API_BASE,
|
||||||
|
WORK_ROOT,
|
||||||
|
FILE_INVENTORY,
|
||||||
|
COLLECTIONS,
|
||||||
|
PAGE_SIZE,
|
||||||
|
} = require("./config");
|
||||||
|
const { normalizeField, safeSlug } = require("./lib/collect-media");
|
||||||
|
|
||||||
|
function unwrapEntry(entry) {
|
||||||
|
if (!entry) return null;
|
||||||
|
if (entry.attributes) {
|
||||||
|
return {
|
||||||
|
...entry.attributes,
|
||||||
|
id: entry.id,
|
||||||
|
documentId: entry.documentId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchJson(url) {
|
||||||
|
const r = await fetch(url);
|
||||||
|
if (!r.ok) {
|
||||||
|
const txt = await r.text();
|
||||||
|
throw new Error(`HTTP ${r.status} ${url}\n${txt.slice(0, 500)}`);
|
||||||
|
}
|
||||||
|
return r.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchAllEntries(plural) {
|
||||||
|
const out = [];
|
||||||
|
let page = 1;
|
||||||
|
/* eslint-disable no-constant-condition */
|
||||||
|
while (true) {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.set("pagination[page]", String(page));
|
||||||
|
params.set("pagination[pageSize]", String(PAGE_SIZE));
|
||||||
|
/**
|
||||||
|
* Strapi v5 : populate[picture]=* peut provoquer « Invalid key related » selon versions.
|
||||||
|
* populate=* hydrate les relations premier niveau (y compris les médias).
|
||||||
|
*/
|
||||||
|
params.set("populate", "*");
|
||||||
|
|
||||||
|
const url = `${API_BASE}/${plural}?${params}`;
|
||||||
|
const json = await fetchJson(url);
|
||||||
|
const rows = Array.isArray(json.data) ? json.data : [];
|
||||||
|
for (const row of rows) {
|
||||||
|
out.push(unwrapEntry(row));
|
||||||
|
}
|
||||||
|
const pageCount = json.meta?.pagination?.pageCount ?? 1;
|
||||||
|
if (page >= pageCount || rows.length === 0) break;
|
||||||
|
page += 1;
|
||||||
|
await new Promise((r) => setTimeout(r, 200));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
console.log("🔍 STRAPI_URL (origine) →", require("./config").STRAPI_URL);
|
||||||
|
console.log("🔍 API_BASE →", API_BASE);
|
||||||
|
|
||||||
|
if (!fs.existsSync(WORK_ROOT)) {
|
||||||
|
fs.mkdirSync(WORK_ROOT, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const inventory = {
|
||||||
|
generatedAt: new Date().toISOString(),
|
||||||
|
apiBase: API_BASE,
|
||||||
|
files: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @type {typeof inventory.files} */
|
||||||
|
const records = [];
|
||||||
|
|
||||||
|
for (const col of COLLECTIONS) {
|
||||||
|
console.log(`\n📂 ${col.plural} (${col.section})…`);
|
||||||
|
let entries;
|
||||||
|
try {
|
||||||
|
entries = await fetchAllEntries(col.plural);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(` ⚠️ Endpoint indisponible ou erreur : ${e.message}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(` ${entries.length} entrée(s)`);
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (!entry) continue;
|
||||||
|
const slug = safeSlug(entry);
|
||||||
|
|
||||||
|
for (const field of col.fields) {
|
||||||
|
const items = normalizeField(entry[field.name], field.multiple);
|
||||||
|
for (const { file, index } of items) {
|
||||||
|
const base = path.basename(file.url.split("?")[0] || "file");
|
||||||
|
records.push({
|
||||||
|
collectionPlural: col.plural,
|
||||||
|
collectionSingular: col.singular,
|
||||||
|
strapiRef: col.ref,
|
||||||
|
section: col.section,
|
||||||
|
entrySlug: slug,
|
||||||
|
entryId: entry.id,
|
||||||
|
entryDocumentId: entry.documentId ?? null,
|
||||||
|
fieldName: field.name,
|
||||||
|
fieldMultiple: field.multiple,
|
||||||
|
fieldIndex: index,
|
||||||
|
fileId: file.id,
|
||||||
|
fileDocumentId: file.documentId ?? null,
|
||||||
|
filename: file.name || base,
|
||||||
|
url: file.url,
|
||||||
|
mime: file.mime,
|
||||||
|
size: file.size,
|
||||||
|
ext: file.ext,
|
||||||
|
/** chemin relatif WORK_ROOT/downloaded/... rempli par 02 */
|
||||||
|
relativeDownloadPath: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inventory.files = records.slice().sort((a, b) => a.fileId - b.fileId);
|
||||||
|
|
||||||
|
fs.writeFileSync(FILE_INVENTORY, JSON.stringify(inventory, null, 2), "utf8");
|
||||||
|
console.log(`\n✅ Inventaire : ${inventory.files.length} fichier(s) → ${FILE_INVENTORY}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
108
strapi_extraction/media-sync/02-download.js
Normal file
108
strapi_extraction/media-sync/02-download.js
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* 02 — Télécharge chaque fichier unique de l’inventaire vers
|
||||||
|
* extract/media-sync-work/downloaded/{section}/{slug}/...
|
||||||
|
* et met à jour relativeDownloadPath dans media-inventory.json
|
||||||
|
*
|
||||||
|
* Usage : node strapi_extraction/media-sync/02-download.js
|
||||||
|
*/
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
const { STRAPI_URL, FILE_INVENTORY, WORK_ROOT, DIR_DOWNLOADED } = require("./config");
|
||||||
|
|
||||||
|
function safeFilePart(name) {
|
||||||
|
return String(name || "file")
|
||||||
|
.replace(/[<>:"/\\|?*\x00-\x1f]/g, "_")
|
||||||
|
.slice(0, 180);
|
||||||
|
}
|
||||||
|
|
||||||
|
function absoluteUrl(relativeOrAbsolute) {
|
||||||
|
if (relativeOrAbsolute.startsWith("http://") || relativeOrAbsolute.startsWith("https://")) {
|
||||||
|
return relativeOrAbsolute;
|
||||||
|
}
|
||||||
|
return `${STRAPI_URL}${relativeOrAbsolute.startsWith("/") ? "" : "/"}${relativeOrAbsolute}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloadBuffer(url) {
|
||||||
|
const r = await fetch(url);
|
||||||
|
if (!r.ok) {
|
||||||
|
throw new Error(`HTTP ${r.status} ${url}`);
|
||||||
|
}
|
||||||
|
const buf = Buffer.from(await r.arrayBuffer());
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
if (!fs.existsSync(FILE_INVENTORY)) {
|
||||||
|
console.error("Manque l’inventaire. Lance d’abord : 01-fetch-inventory.js");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const raw = fs.readFileSync(FILE_INVENTORY, "utf8");
|
||||||
|
const inventory = JSON.parse(raw);
|
||||||
|
const files = inventory.files;
|
||||||
|
if (!Array.isArray(files) || files.length === 0) {
|
||||||
|
console.log("Inventaire vide — rien à télécharger.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs.existsSync(DIR_DOWNLOADED)) {
|
||||||
|
fs.mkdirSync(DIR_DOWNLOADED, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const byId = new Map();
|
||||||
|
let ok = 0;
|
||||||
|
let skipped = 0;
|
||||||
|
let fail = 0;
|
||||||
|
|
||||||
|
for (const row of files) {
|
||||||
|
const id = row.fileId;
|
||||||
|
if (byId.has(id)) {
|
||||||
|
row.relativeDownloadPath = byId.get(id);
|
||||||
|
skipped++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rel = path.join(
|
||||||
|
row.section,
|
||||||
|
row.entrySlug,
|
||||||
|
`${id}_${safeFilePart(row.filename)}`
|
||||||
|
);
|
||||||
|
const abs = path.join(DIR_DOWNLOADED, rel);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const url = absoluteUrl(row.url);
|
||||||
|
const buf = await downloadBuffer(url);
|
||||||
|
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
||||||
|
fs.writeFileSync(abs, buf);
|
||||||
|
row.relativeDownloadPath = rel.replace(/\\/g, "/");
|
||||||
|
byId.set(id, row.relativeDownloadPath);
|
||||||
|
ok++;
|
||||||
|
console.log(`✅ ${rel} (${(buf.length / 1024).toFixed(1)} KB)`);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`❌ fileId=${id} : ${e.message}`);
|
||||||
|
row.relativeDownloadPath = null;
|
||||||
|
row.downloadError = String(e.message);
|
||||||
|
fail++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inventory.downloadedAt = new Date().toISOString();
|
||||||
|
inventory.stats = {
|
||||||
|
uniqueFiles: byId.size,
|
||||||
|
rowsTotal: files.length,
|
||||||
|
downloadedOk: ok,
|
||||||
|
dedupSkipped: skipped,
|
||||||
|
failed: fail,
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.writeFileSync(FILE_INVENTORY, JSON.stringify(inventory, null, 2), "utf8");
|
||||||
|
console.log(`\n📁 Base téléchargements : ${DIR_DOWNLOADED}`);
|
||||||
|
console.log(
|
||||||
|
`Résumé : ${ok} téléchargement(s), ${skipped} lignes réutilisent un fichier déjà pris, ${fail} échec(s).`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
133
strapi_extraction/media-sync/03-convert-webp.js
Normal file
133
strapi_extraction/media-sync/03-convert-webp.js
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/**
|
||||||
|
* 03 — Convertit les téléchargements en WebP (sharp) sous
|
||||||
|
* extract/media-sync-work/webp/{section}/{slug}/{fileId}_{stem}.webp
|
||||||
|
* Les SVG sont copiés en .svg (sans conversion raster).
|
||||||
|
*
|
||||||
|
* Usage : node strapi_extraction/media-sync/03-convert-webp.js
|
||||||
|
*/
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
const sharp = require("sharp");
|
||||||
|
const { FILE_INVENTORY, DIR_DOWNLOADED, DIR_WEBP, WORK_ROOT } = require("./config");
|
||||||
|
|
||||||
|
const MAX_EDGE = 2560;
|
||||||
|
const WEBP_QUALITY = 82;
|
||||||
|
|
||||||
|
function stemFromFilename(filename) {
|
||||||
|
const b = path.basename(filename);
|
||||||
|
const i = b.lastIndexOf(".");
|
||||||
|
return i <= 0 ? b : b.slice(0, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function toWebpRaster(srcPath, destPath) {
|
||||||
|
const meta = await sharp(srcPath).metadata();
|
||||||
|
const w = meta.width || 0;
|
||||||
|
const h = meta.height || 0;
|
||||||
|
let pipeline = sharp(srcPath).rotate();
|
||||||
|
if (w > MAX_EDGE || h > MAX_EDGE) {
|
||||||
|
pipeline = pipeline.resize(MAX_EDGE, MAX_EDGE, {
|
||||||
|
fit: "inside",
|
||||||
|
withoutEnlargement: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
||||||
|
await pipeline.webp({ quality: WEBP_QUALITY, effort: 4 }).toFile(destPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
if (!fs.existsSync(FILE_INVENTORY)) {
|
||||||
|
console.error("Manque media-inventory.json — lance 01 puis 02.");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const inventory = JSON.parse(fs.readFileSync(FILE_INVENTORY, "utf8"));
|
||||||
|
const files = inventory.files;
|
||||||
|
if (!Array.isArray(files) || !files.length) {
|
||||||
|
console.log("Rien à convertir.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs.existsSync(WORK_ROOT)) fs.mkdirSync(WORK_ROOT, { recursive: true });
|
||||||
|
if (!fs.existsSync(DIR_WEBP)) fs.mkdirSync(DIR_WEBP, { recursive: true });
|
||||||
|
|
||||||
|
const byId = new Map();
|
||||||
|
let ok = 0;
|
||||||
|
let err = 0;
|
||||||
|
|
||||||
|
for (const row of files) {
|
||||||
|
const id = row.fileId;
|
||||||
|
if (!row.relativeDownloadPath) {
|
||||||
|
row.relativeWebpPath = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (byId.has(id)) {
|
||||||
|
row.relativeWebpPath = byId.get(id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const src = path.join(DIR_DOWNLOADED, row.relativeDownloadPath);
|
||||||
|
if (!fs.existsSync(src)) {
|
||||||
|
row.relativeWebpPath = null;
|
||||||
|
row.convertError = "fichier téléchargé manquant";
|
||||||
|
err++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ext = path.extname(src).toLowerCase();
|
||||||
|
const baseStem = `${id}_${stemFromFilename(row.filename)}`;
|
||||||
|
const relDir = path.join(row.section, row.entrySlug);
|
||||||
|
let relOutFile;
|
||||||
|
let absOut;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (ext === ".svg") {
|
||||||
|
relOutFile = path.join(relDir, `${baseStem}.svg`).replace(/\\/g, "/");
|
||||||
|
absOut = path.join(DIR_WEBP, relOutFile);
|
||||||
|
fs.mkdirSync(path.dirname(absOut), { recursive: true });
|
||||||
|
fs.copyFileSync(src, absOut);
|
||||||
|
console.log(`svg-copy → ${relOutFile}`);
|
||||||
|
} else if (ext === ".webp") {
|
||||||
|
relOutFile = path.join(relDir, `${baseStem}.webp`).replace(/\\/g, "/");
|
||||||
|
absOut = path.join(DIR_WEBP, relOutFile);
|
||||||
|
fs.mkdirSync(path.dirname(absOut), { recursive: true });
|
||||||
|
fs.copyFileSync(src, absOut);
|
||||||
|
console.log(`webp-copy → ${relOutFile}`);
|
||||||
|
} else if ([".png", ".jpg", ".jpeg", ".tif", ".tiff"].includes(ext)) {
|
||||||
|
relOutFile = path.join(relDir, `${baseStem}.webp`).replace(/\\/g, "/");
|
||||||
|
absOut = path.join(DIR_WEBP, relOutFile);
|
||||||
|
await toWebpRaster(src, absOut);
|
||||||
|
console.log(`webp-transform → ${relOutFile}`);
|
||||||
|
} else {
|
||||||
|
relOutFile = path.join(relDir, path.basename(src)).replace(/\\/g, "/");
|
||||||
|
absOut = path.join(DIR_WEBP, relOutFile);
|
||||||
|
fs.mkdirSync(path.dirname(absOut), { recursive: true });
|
||||||
|
fs.copyFileSync(src, absOut);
|
||||||
|
console.log(`raw-copy → ${relOutFile}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
row.relativeWebpPath = relOutFile;
|
||||||
|
byId.set(id, relOutFile);
|
||||||
|
ok++;
|
||||||
|
} catch (e) {
|
||||||
|
row.relativeWebpPath = null;
|
||||||
|
row.convertError = String(e.message);
|
||||||
|
err++;
|
||||||
|
console.error(`❌ fileId ${id}: ${e.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inventory.convertedAt = new Date().toISOString();
|
||||||
|
inventory.convertSettings = {
|
||||||
|
maxEdgePx: MAX_EDGE,
|
||||||
|
webpQuality: WEBP_QUALITY,
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.writeFileSync(FILE_INVENTORY, JSON.stringify(inventory, null, 2), "utf8");
|
||||||
|
console.log(`\n✅ Fichiers uniques traités : ${ok}, erreurs : ${err}`);
|
||||||
|
console.log(`📁 ${DIR_WEBP}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
270
strapi_extraction/media-sync/04-upload-replace.js
Normal file
270
strapi_extraction/media-sync/04-upload-replace.js
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
/**
|
||||||
|
* 04 — Ré-upload les WebP générés vers Strapi et remplace les entrées média dans
|
||||||
|
* les fiches concernées (API authentifiée).
|
||||||
|
*
|
||||||
|
* Requiert dans l’env : STRAPI_API_TOKEN (JWT Strapi avec droits upload + mise à jour
|
||||||
|
* des collection types utilisés ; typiquement un jeton Full access en local).
|
||||||
|
*
|
||||||
|
* Par défaut : **dry-run** (aucune mutation).
|
||||||
|
* Mutation réelle : node strapi_extraction/media-sync/04-upload-replace.js --execute
|
||||||
|
*
|
||||||
|
* DANGER : sauvegarder au préalable votre base Strapi / médias. Tester sur une
|
||||||
|
* copie locale (Strapi localhost + même base si possible).
|
||||||
|
*/
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
require("dotenv").config({
|
||||||
|
path: path.join(__dirname, "../../cmsbackend/.env"),
|
||||||
|
});
|
||||||
|
require("dotenv").config({
|
||||||
|
path: path.join(__dirname, "../../.env.local"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
FILE_INVENTORY,
|
||||||
|
DIR_WEBP,
|
||||||
|
API_BASE,
|
||||||
|
} = require("./config");
|
||||||
|
|
||||||
|
const TOKEN = process.env.STRAPI_API_TOKEN;
|
||||||
|
const EXECUTE = process.argv.includes("--execute");
|
||||||
|
|
||||||
|
function mimeForFile(filePath) {
|
||||||
|
const ext = path.extname(filePath).toLowerCase();
|
||||||
|
const map = {
|
||||||
|
".webp": "image/webp",
|
||||||
|
".svg": "image/svg+xml",
|
||||||
|
".png": "image/png",
|
||||||
|
".jpg": "image/jpeg",
|
||||||
|
".jpeg": "image/jpeg",
|
||||||
|
};
|
||||||
|
return map[ext] || "application/octet-stream";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compte combien de lignes d’inventaire pointent le même fileId */
|
||||||
|
function countRefs(files) {
|
||||||
|
const c = {};
|
||||||
|
for (const r of files) {
|
||||||
|
c[r.fileId] = (c[r.fileId] || 0) + 1;
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nom réservé multipart (ByteString) : les noms avec caractères hors U+00–U+FF
|
||||||
|
* (ex. U+2194 flèches dans des noms générés) provoquent l’erreur Node
|
||||||
|
* « Cannot convert argument to a ByteString » sur form.append(..., filename).
|
||||||
|
*/
|
||||||
|
function asciiUploadName(filePath, fileId) {
|
||||||
|
const ext = path.extname(filePath).toLowerCase();
|
||||||
|
const extOk = /^\.(webp|svg|png|jpe?g|gif|avif)$/.test(ext) ? ext : ".webp";
|
||||||
|
return `upload-${fileId}${extOk}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function postUpload(filePath, fileId) {
|
||||||
|
const buf = fs.readFileSync(filePath);
|
||||||
|
const asciiName = asciiUploadName(filePath, fileId);
|
||||||
|
const blob = new Blob([buf], { type: mimeForFile(filePath) });
|
||||||
|
const body = new FormData();
|
||||||
|
body.append("files", blob, asciiName);
|
||||||
|
|
||||||
|
const res = await fetch(`${API_BASE}/upload`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: TOKEN ? { Authorization: `Bearer ${TOKEN}` } : {},
|
||||||
|
body,
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
const t = await res.text();
|
||||||
|
throw new Error(`POST /upload ${res.status} ${t.slice(0, 800)}`);
|
||||||
|
}
|
||||||
|
const json = await res.json();
|
||||||
|
const arr = Array.isArray(json) ? json : json?.data;
|
||||||
|
if (!Array.isArray(arr) || !arr[0]) {
|
||||||
|
throw new Error(`Réponse upload inattendue : ${JSON.stringify(json).slice(0, 400)}`);
|
||||||
|
}
|
||||||
|
return arr[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function unwrapEntry(raw) {
|
||||||
|
if (!raw) return null;
|
||||||
|
if (raw.data) return unwrapEntry(raw.data);
|
||||||
|
if (raw.attributes) {
|
||||||
|
return {
|
||||||
|
...raw.attributes,
|
||||||
|
id: raw.id,
|
||||||
|
documentId: raw.documentId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getEntryPlural(plural, documentId) {
|
||||||
|
const qs = new URLSearchParams({ populate: "*" });
|
||||||
|
const url = `${API_BASE}/${plural}/${documentId}?${qs}`;
|
||||||
|
const res = await fetch(url, {
|
||||||
|
headers: TOKEN ? { Authorization: `Bearer ${TOKEN}` } : {},
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
const t = await res.text();
|
||||||
|
throw new Error(`GET ${url} → ${res.status} ${t.slice(0, 400)}`);
|
||||||
|
}
|
||||||
|
const json = await res.json();
|
||||||
|
return unwrapEntry(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMediaIdsFromField(entry, fieldName, multiple) {
|
||||||
|
const v = entry[fieldName];
|
||||||
|
if (multiple) {
|
||||||
|
const arr = Array.isArray(v) ? v : [];
|
||||||
|
return arr.map((x) => (typeof x === "object" && x !== null ? x.id : x)).filter(Boolean);
|
||||||
|
}
|
||||||
|
if (!v) return [];
|
||||||
|
if (typeof v === "object" && v.id) return [v.id];
|
||||||
|
if (typeof v === "number") return [v];
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function putEntry(plural, documentId, payloadData) {
|
||||||
|
const url = `${API_BASE}/${plural}/${documentId}`;
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
...(TOKEN ? { Authorization: `Bearer ${TOKEN}` } : {}),
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ data: payloadData }),
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
const t = await res.text();
|
||||||
|
throw new Error(`PUT ${url} → ${res.status} ${t.slice(0, 800)}`);
|
||||||
|
}
|
||||||
|
return res.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteFile(fileId) {
|
||||||
|
const url = `${API_BASE}/upload/files/${fileId}`;
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: TOKEN ? { Authorization: `Bearer ${TOKEN}` } : {},
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
const t = await res.text();
|
||||||
|
throw new Error(`DELETE ${url} → ${res.status} ${t.slice(0, 400)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
if (!fs.existsSync(FILE_INVENTORY)) {
|
||||||
|
console.error("Manque media-inventory.json");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TOKEN) {
|
||||||
|
console.error(
|
||||||
|
"STRAPI_API_TOKEN manquant. Crée un jeton API dans Strapi (Settings → API Tokens), puis exporte :\n" +
|
||||||
|
" Windows PowerShell : $env:STRAPI_API_TOKEN=\"…\"\n" +
|
||||||
|
" ou ajoute STRAPI_API_TOKEN dans cmsbackend/.env (non commité)."
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const inventory = JSON.parse(fs.readFileSync(FILE_INVENTORY, "utf8"));
|
||||||
|
const files = inventory.files || [];
|
||||||
|
const refCount = countRefs(files);
|
||||||
|
|
||||||
|
const candidates = files.filter(
|
||||||
|
(r) =>
|
||||||
|
r.relativeWebpPath &&
|
||||||
|
r.relativeWebpPath.endsWith(".webp") &&
|
||||||
|
r.entryDocumentId
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Lignes inventaire : ${files.length} — candidats WebP remplaçables (avec documentId) : ${candidates.length}`
|
||||||
|
);
|
||||||
|
console.log(`Mode : ${EXECUTE ? "EXECUTE (mutations réelles)" : "DRY-RUN (aucune mutation)"}\n`);
|
||||||
|
|
||||||
|
if (!EXECUTE) {
|
||||||
|
console.log(
|
||||||
|
"Exemple d’actions qui seraient effectuées avec --execute :\n" +
|
||||||
|
" 1. POST /api/upload pour chaque fichier .webp sous webp/\n" +
|
||||||
|
" 2. PUT /api/:collection/:documentId avec le champ média mis à jour (ids)\n" +
|
||||||
|
" 3. DELETE /api/upload/files/:oldFileId uniquement si l’ancien id n’a qu’une référence dans l’inventaire\n"
|
||||||
|
);
|
||||||
|
for (let i = 0; i < Math.min(5, candidates.length); i++) {
|
||||||
|
const r = candidates[i];
|
||||||
|
console.log(
|
||||||
|
` • fileId=${r.fileId} → ${r.relativeWebpPath} → entrée ${r.collectionPlural} documentId=${r.entryDocumentId} champ=${r.fieldName}[${r.fieldIndex}]`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
console.log("\nAjoute --execute pour réellement téléverser (après avoir testé la sauvegarde).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Par sécurité, traite fichier par fichier ; re-fetch après chaque succès évite désalignement indices */
|
||||||
|
for (const row of candidates) {
|
||||||
|
const src = path.join(DIR_WEBP, row.relativeWebpPath.replace(/\//g, path.sep));
|
||||||
|
if (!fs.existsSync(src)) {
|
||||||
|
console.warn(`SKIP fileId=${row.fileId} : fichier absent ${src}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const docId = row.entryDocumentId;
|
||||||
|
const plural = row.collectionPlural;
|
||||||
|
const field = row.fieldName;
|
||||||
|
const idx = row.fieldIndex;
|
||||||
|
const oldId = row.fileId;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const uploaded = await postUpload(src, row.fileId);
|
||||||
|
const newId = uploaded.id;
|
||||||
|
|
||||||
|
const entry = await getEntryPlural(plural, docId);
|
||||||
|
if (!entry) throw new Error("entrée introuvable");
|
||||||
|
|
||||||
|
const multiple = row.fieldMultiple;
|
||||||
|
const currentIds = getMediaIdsFromField(entry, field, multiple);
|
||||||
|
|
||||||
|
if (multiple) {
|
||||||
|
if (idx < 0 || idx >= currentIds.length) {
|
||||||
|
throw new Error(`index ${idx} hors limites (ids actuels : ${currentIds.join(",")})`);
|
||||||
|
}
|
||||||
|
if (currentIds[idx] !== oldId) {
|
||||||
|
throw new Error(
|
||||||
|
`id à l’index ${idx} est ${currentIds[idx]}, attendu ${oldId} — arrêt pour éviter corruption`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const next = currentIds.slice();
|
||||||
|
next[idx] = newId;
|
||||||
|
await putEntry(plural, docId, { [field]: next });
|
||||||
|
} else {
|
||||||
|
const cur = currentIds[0];
|
||||||
|
if (cur != null && cur !== oldId) {
|
||||||
|
throw new Error(`champ simple : attendu ancien id ${oldId}, vu ${cur}`);
|
||||||
|
}
|
||||||
|
await putEntry(plural, docId, { [field]: newId });
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`OK upload+remplace : ${oldId} → ${newId} (${plural}/${docId})`);
|
||||||
|
|
||||||
|
const canDeleteOld = refCount[oldId] === 1;
|
||||||
|
if (canDeleteOld && oldId !== newId) {
|
||||||
|
try {
|
||||||
|
await deleteFile(oldId);
|
||||||
|
console.log(` ancien fichier Strapi ${oldId} supprimé`);
|
||||||
|
} catch (de) {
|
||||||
|
console.warn(` suppression ancien échouée (non bloquant) : ${de.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`ÉCHEC fileId=${row.fileId} : ${e.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("\nTerminé. Recharge les fiches dans l’admin et vide le cache navigateur.");
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
58
strapi_extraction/media-sync/README.md
Normal file
58
strapi_extraction/media-sync/README.md
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# Pipeline médias Strapi → dossiers par section → WebP → ré-upload optionnel
|
||||||
|
|
||||||
|
**Répertoire de travail (lourd)** : `strapi_extraction/extract/media-sync-work/` — ignoré par Git (`/.gitignore`).
|
||||||
|
|
||||||
|
## Prérequis
|
||||||
|
|
||||||
|
- Node 18+
|
||||||
|
- Dépendance `sharp` installée depuis la racine (`npm install` déjà fait si le dépôt à jour).
|
||||||
|
|
||||||
|
## Variables optionnelles
|
||||||
|
|
||||||
|
| Variable | Rôle |
|
||||||
|
|----------|------|
|
||||||
|
| `STRAPI_URL` | Origine Strapi sans `/api` (défaut depuis `NEXT_PUBLIC_API_URL` ou prod). |
|
||||||
|
| `STRAPI_API_TOKEN` | **Seulement** pour `04-upload-replace.js --execute`. Jeton créé dans Strapi → Settings → API Tokens (droits lecture + Upload + mise à jour des CT concernés). Ne pas committer ce jeton. |
|
||||||
|
|
||||||
|
Chemins `.env.local` à la racine et `cmsbackend/.env` sont chargés par les scripts (`config.js` ou `04`).
|
||||||
|
|
||||||
|
## Chaîne normale
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# depuis la racine du repo J:\my-next-site
|
||||||
|
|
||||||
|
npm run media:inventory # 01 — liste tous les médias utilisés → media-inventory.json
|
||||||
|
|
||||||
|
npm run media:download # 02 — téléchargement physique par section sous downloaded/
|
||||||
|
|
||||||
|
npm run media:webp # 03 — conversion/copies sous webp/
|
||||||
|
|
||||||
|
npm run media:upload # 04 — dry-run uniquement (aucune mutation)
|
||||||
|
|
||||||
|
# Mutation CMS (**attention**) après lecture ci‑dessous :
|
||||||
|
|
||||||
|
$env:STRAPI_API_TOKEN="<jeton>"
|
||||||
|
node strapi_extraction/media-sync/04-upload-replace.js --execute
|
||||||
|
```
|
||||||
|
|
||||||
|
### Organisation des dossiers
|
||||||
|
|
||||||
|
- **`downloaded/{section}/{slug-du-contenu}/{fileId}_{nom-fichier}`**
|
||||||
|
Sections : `portfolio`, `competences`, `home`, `realisation-ias`, `glossaire`.
|
||||||
|
- **`webp/...`** même structure, avec `.webp` (ou `.svg` copié en clair).
|
||||||
|
|
||||||
|
Les **fichiers média uniques** sont dédupliqués par `fileId` : une seule fois sur disque, plusieurs lignes dans l’inventaire peuvent référencer le même téléchargement.
|
||||||
|
|
||||||
|
### Erreur « Cannot convert argument to a ByteString » (upload)
|
||||||
|
|
||||||
|
Les noms de fichiers sur disque peuvent contenir des caractères Unicode (tirets fins, flèches dans des noms AI, etc.). Le `FormData` HTTP n’accepte qu’un nom de fichier **ASCII** dans l’en-tête multipart ; le script **`04-upload-replace.js`** renomme donc en interne chaque envoi en `upload-{fileId}.webp` (voir `asciiUploadName` dans le fichier). Relance `--execute` après mise à jour du script.
|
||||||
|
|
||||||
|
### Avant le `--execute` sur la prod
|
||||||
|
|
||||||
|
1. **Tester d’abord** contre une instance Strapi locale (ex. importer la base vers `cmsbackend`, `npm run develop`, puis `$env:STRAPI_URL="http://localhost:1337"` et un jeton local).
|
||||||
|
2. **Sauvegarder** la base et `/public/uploads`.
|
||||||
|
3. Lire le préambule dans `04-upload-replace.js` ; le script vérifie que l’ancien id correspond encore avant remplacement pour limiter les corruptions.
|
||||||
|
|
||||||
|
## Si l’étape ré-upload vous suffit après conversion manuelle
|
||||||
|
|
||||||
|
Vous pouvez aussi **importer uniquement les WebP** depuis l’admin Strapi puis réassigner les champs à la main ; ce dépôt ne vous oblige pas à utiliser `04`.
|
||||||
78
strapi_extraction/media-sync/config.js
Normal file
78
strapi_extraction/media-sync/config.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* Configuration partagée — sync médias Strapi (téléchargement / WebP / ré-upload).
|
||||||
|
* Variables d'environnement (optionnelles) :
|
||||||
|
* STRAPI_URL — origine sans /api (ex. https://api.fernandgrascalvet.com ou http://localhost:1337)
|
||||||
|
* STRAPI_API_TOKEN — jeton API Strapi (requis pour 04-upload-replace.js --execute)
|
||||||
|
*/
|
||||||
|
require("dotenv").config({ path: require("path").join(__dirname, "../../.env.local") });
|
||||||
|
require("dotenv").config({ path: require("path").join(__dirname, "../../cmsbackend/.env") });
|
||||||
|
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
const STRAPI_URL =
|
||||||
|
process.env.STRAPI_URL ||
|
||||||
|
process.env.NEXT_PUBLIC_API_URL?.replace(/\/$/, "") ||
|
||||||
|
"https://api.fernandgrascalvet.com";
|
||||||
|
|
||||||
|
const API_BASE = `${STRAPI_URL}/api`;
|
||||||
|
|
||||||
|
/** Sortie : mirrors extract/ existant (gitignored lourd) */
|
||||||
|
const WORK_ROOT = path.join(__dirname, "../extract/media-sync-work");
|
||||||
|
const DIR_DOWNLOADED = path.join(WORK_ROOT, "downloaded");
|
||||||
|
const DIR_WEBP = path.join(WORK_ROOT, "webp");
|
||||||
|
const FILE_INVENTORY = path.join(WORK_ROOT, "media-inventory.json");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content-types avec champs média — aligné sur cmsbackend/src/api (schema.json par type).
|
||||||
|
* section = sous-dossier humain (portfolio, competences, …)
|
||||||
|
*/
|
||||||
|
const COLLECTIONS = [
|
||||||
|
{
|
||||||
|
plural: "projects",
|
||||||
|
singular: "project",
|
||||||
|
ref: "api::project.project",
|
||||||
|
section: "portfolio",
|
||||||
|
fields: [{ name: "picture", multiple: true }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plural: "competences",
|
||||||
|
singular: "competence",
|
||||||
|
ref: "api::competence.competence",
|
||||||
|
section: "competences",
|
||||||
|
fields: [{ name: "picture", multiple: true }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plural: "homepages",
|
||||||
|
singular: "homepage",
|
||||||
|
ref: "api::homepage.homepage",
|
||||||
|
section: "home",
|
||||||
|
fields: [{ name: "photo", multiple: false }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plural: "realisation-ias",
|
||||||
|
singular: "realisation-ia",
|
||||||
|
ref: "api::realisation-ia.realisation-ia",
|
||||||
|
section: "realisation-ias",
|
||||||
|
fields: [{ name: "picture", multiple: true }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plural: "glossaires",
|
||||||
|
singular: "glossaire",
|
||||||
|
ref: "api::glossaire.glossaire",
|
||||||
|
section: "glossaire",
|
||||||
|
fields: [{ name: "images", multiple: true }],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const PAGE_SIZE = 100;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
STRAPI_URL,
|
||||||
|
API_BASE,
|
||||||
|
WORK_ROOT,
|
||||||
|
DIR_DOWNLOADED,
|
||||||
|
DIR_WEBP,
|
||||||
|
FILE_INVENTORY,
|
||||||
|
COLLECTIONS,
|
||||||
|
PAGE_SIZE,
|
||||||
|
};
|
||||||
41
strapi_extraction/media-sync/lib/collect-media.js
Normal file
41
strapi_extraction/media-sync/lib/collect-media.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* Helpers — extraire les fichiers média des réponses Strapi v5 (structure plate).
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isUploadedImage(obj) {
|
||||||
|
if (!obj || typeof obj !== "object" || typeof obj.url !== "string") return false;
|
||||||
|
if (!obj.url.includes("/uploads/")) return false;
|
||||||
|
if (obj.mime && !obj.mime.startsWith("image/")) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Liste { file, index } pour un champ média Strapi */
|
||||||
|
function normalizeField(fieldVal, multiple) {
|
||||||
|
if (!fieldVal) return [];
|
||||||
|
if (multiple) {
|
||||||
|
const arr = Array.isArray(fieldVal) ? fieldVal : [fieldVal];
|
||||||
|
return arr
|
||||||
|
.filter(isUploadedImage)
|
||||||
|
.map((file, index) => ({ file, index }));
|
||||||
|
}
|
||||||
|
return isUploadedImage(fieldVal)
|
||||||
|
? [{ file: fieldVal, index: 0 }]
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function safeSlug(entry) {
|
||||||
|
const s =
|
||||||
|
entry.slug ??
|
||||||
|
entry.documentId ??
|
||||||
|
(entry.id != null ? String(entry.id) : "unknown");
|
||||||
|
return String(s)
|
||||||
|
.replace(/[^\wÀ-ÖØ-öø-ÿ.-]+/gu, "_")
|
||||||
|
.slice(0, 96)
|
||||||
|
.replace(/^_|_$/g, "") || "entry";
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
normalizeField,
|
||||||
|
safeSlug,
|
||||||
|
isUploadedImage,
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user