* feat(recipes): ajoute un adaptateur RecipeSourceAdapter pour Marmiton
Étend jsonLdRecipeAdapter (json-ld-recipe.ts) plutôt que de dupliquer sa
logique : marmitonAdapter délègue fetchDetail/parse directement à
l'adaptateur générique JSON-LD (une page recette marmiton.org expose un
Recipe schema.org standard), et n'ajoute que ce que l'adaptateur
générique ne peut pas offrir — un list() qui lit l'ItemList schema.org
embarqué sur la page de résultats de recherche de marmiton.org (pagination
via &page=N, fin de résultats détectée via la réponse 404 renvoyée
au-delà de la dernière page).
extractJsonLdBlocks est exporté depuis json-ld-recipe.ts pour être
réutilisé par marmiton.ts sans dupliquer le regex d'extraction des blocs
<script type="application/ld+json">.
Enregistre marmitonAdapter dans registerAllRecipeSources (sources/index.ts)
— contrairement à jsonLdRecipeAdapter lui-même, c'est un adaptateur concret
par site, donc une Source household-toggleable légitime.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* feat(recipes): ajoute un adaptateur RecipeSourceAdapter pour 750g
Suit le même schéma que marmitonAdapter (construit sur jsonLdRecipeAdapter),
avec deux différences propres à 750g.com :
- list() n'a pas d'ItemList JSON-LD à lire sur ses résultats de recherche
(la recherche du site est un widget client-side) — appelle donc
directement le endpoint GET que ce widget interroge lui-même en interne
(un « moteur de réponse IA » qui renvoie un lot de recettes pour une
requête en texte libre), et scrape les cartes de résultat par regex en
associant à chaque lien de recette sa dernière image précédente plutôt
qu'un zip naïf par index (des images décoratives sans carte associée
existent réellement dans ce fragment). Vérifié en direct : demander une
« page 2 » revient toujours vide, donc nextCursor vaut toujours null,
comme theMealDbAdapter.
- parse() ne délègue pas aussi directement à jsonLdRecipeAdapter.parse que
marmitonAdapter — le générateur JSON-LD de 750g.com a deux bugs réels :
des caractères de contrôle bruts non échappés dans certaines chaînes JSON
(~1 recette sur 3 dans un échantillon vérifié en direct, sinon
JSON.parse échoue et jsonLdRecipeAdapter rapporte à tort « aucun
Recipe trouvé »), et un texte parfois doublement encodé en entités HTML
(ex. un vrai « é » devient &eacute; au lieu de é). Les deux
sont corrigés en pré/post-traitement autour de la même délégation, pas
une réimplémentation.
Enregistre sevenFiftyGAdapter dans registerAllRecipeSources
(sources/index.ts), au même titre que marmitonAdapter.
Complète aussi test/sources/sources-index.test.ts, qui ne couvrait encore
que TheMealDB malgré l'ajout de Marmiton dans une PR précédente.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* feat(recipes): ajoute un adaptateur RecipeSourceAdapter pour Manger Bouger
Suit le même schéma que marmitonAdapter/sevenFiftyGAdapter (construit sur
jsonLdRecipeAdapter), avec des différences propres à mangerbouger.fr
(« La Fabrique à Menus », Santé publique France) :
- list() n'utilise pas de JSON-LD du tout — la page de résultats (une app
Next.js) n'embarque aucun ItemList. Elle est cependant rendue
côté serveur et expose le même state Redux que le client hydrate, via un
<script id="__NEXT_DATA__">, qui contient déjà tout ce dont list() a
besoin (slug/nom/image, pagination). Vérifié en direct : ?query=<texte
libre> filtre bien côté serveur, et hasMorePages donne un signal de fin
de pagination plus propre que le 404 de Marmiton ou l'absence de vraie
pagination de 750g.
- parse() délègue à jsonLdRecipeAdapter mais corrige deux lacunes réelles
et systématiques de son propre JSON-LD (vérifiées sur 9 recettes,
72 étapes) : recipeInstructions[].text est un document Slate.js
sérialisé en JSON (pas du texte) plutôt qu'être aplati ; recipeYield est
absent partout alors que le nombre de portions existe bien côté site
(__NEXT_DATA__) — les deux sont corrigés par un patch structuré (parse →
mutation → réécriture) avant délégation, pas une réimplémentation.
Enregistre mangerBougerAdapter dans registerAllRecipeSources
(sources/index.ts) et complète sources-index.test.ts.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>