Files
mealie/tests/data/scraper/html-raw/healthy_pasta_bake_60759.html
Hayden ee0c519ef0 v0.4.0 (#236)
* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

* Dropping Mongo From Dev Branch (#89)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* initial pass

* second pass cleanup

* backup card framework

* backup card functionality

* translation

* upload button vile creation

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* dev bug: change data location to prevent reloads

* api docs

* api docs bug

* workflow update

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* Add French Translation (#93)

* New tests (#94)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

Co-authored-by: Hayden <hay-kot@pm.me>

* Mealplan CRUD Tests (#95)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix typos (#96)

* Settings, Themes and Migration Route Tests (#100)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Refactor + New Docker File (#105)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

Co-authored-by: Hayden <hay-kot@pm.me>

* Meal planner improvements (#107)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

* mealplan redesign

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#108)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#113)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

* UI updates + name validation

* docs: changelog + sp

* fixed route links

* changelog

Co-authored-by: Hayden <hay-kot@pm.me>

* fixed menu links

* fixed poetry install on docker.dev build

* Migration redesign (#119)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix link to dev-notes.md (#110)

* translation: add swedish (#128)

* language: da is Danish

* translations: add swedish

* scraper: unescape html in instructions (#129)

Some urls erroneously deliver escaped html their instructions,
sometimes they are even escaped on multiple levels like here:

https://www.ica.se/recept/kladdig-kladdkaka-722982/

```
>>> normalize_instruction("S&amp;auml;tt ugnen p&amp;aring; 200&amp;deg;C.")
'Sätt ugnen på 200°C.'
```

* v0.2.0 Updates (#130)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

* test todos

* bug/added docker volume

* chowdow test data

* partial image recipe image testing

* added card section card

* settings form

* homepage cetegory ui

* frontend category placeholder

* fixed broken scheduler

* remove old files

* removed temp test

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix missing translations key (#133)

* translation: add simplified & traditional chinese

* Fix missing translations

* fix chinese translations

* v0.2.0 Release Candidate (#141)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* notes hot fix

* bug: mongo updates fail #99

* Fix error message (#101)

* gh funding

* Create Issue Templates (#125)

* Create bug_report.md

* Create config.yml

Included a link to feature requests.

* Update config.yml

Fixed link I had for testing to the actual link

* Update bug_report.md

fix capitalization

* Update .github/ISSUE_TEMPLATE/bug_report.md

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* merge kentors changes

* refactor/recipe routers

* category/tag database relationship and endpoints

* frontend category management

* update branch todos

* bug/normalize recipe steps html

* remove console.log +  refactor categories

* fix categories database errors

* refactor/ router endpoint

* refactor/ remove old code

* drag and drop ingredients

* general cleanup

* route refactoring

* changelog

* api refactoring + random cleanup

* fixed backwards sort

* Update mkdocs.yml (#137)

Fix warning from Deploy Docs github action

* fixed navigate on enter in search

* refactor/create global css

* added category scroll

* cleanup todos

* debug routes

* docs/new gifs & general updates

* cleanup

* fix list test

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* fix build

* fix duplicate editor

* fixed docker mount problem

* python 3.9

* added tasks for non-docker development

* remove old scripts

* dev updates

* fixed no image upload option

* get version from backend

* final docs pass

* .gitignore

* feature/markdown support for description and steps

* package-lock

* rename production task

* category import errors on import (#150)

Co-authored-by: hay-kot <hay-kot@pm.me>

* Feature/improved notifications (#152)

* category import errors on import

* Import Error Hotfix (#148)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

* Dropping Mongo From Dev Branch (#89)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* initial pass

* second pass cleanup

* backup card framework

* backup card functionality

* translation

* upload button vile creation

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* dev bug: change data location to prevent reloads

* api docs

* api docs bug

* workflow update

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* Add French Translation (#93)

* New tests (#94)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

Co-authored-by: Hayden <hay-kot@pm.me>

* Mealplan CRUD Tests (#95)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix typos (#96)

* Settings, Themes and Migration Route Tests (#100)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Refactor + New Docker File (#105)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

Co-authored-by: Hayden <hay-kot@pm.me>

* Meal planner improvements (#107)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

* mealplan redesign

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#108)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#113)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

* UI updates + name validation

* docs: changelog + sp

* fixed route links

* changelog

Co-authored-by: Hayden <hay-kot@pm.me>

* fixed menu links

* fixed poetry install on docker.dev build

* Migration redesign (#119)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix link to dev-notes.md (#110)

* translation: add swedish (#128)

* language: da is Danish

* translations: add swedish

* scraper: unescape html in instructions (#129)

Some urls erroneously deliver escaped html their instructions,
sometimes they are even escaped on multiple levels like here:

https://www.ica.se/recept/kladdig-kladdkaka-722982/

```
>>> normalize_instruction("S&amp;auml;tt ugnen p&amp;aring; 200&amp;deg;C.")
'Sätt ugnen på 200°C.'
```

* v0.2.0 Updates (#130)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

* test todos

* bug/added docker volume

* chowdow test data

* partial image recipe image testing

* added card section card

* settings form

* homepage cetegory ui

* frontend category placeholder

* fixed broken scheduler

* remove old files

* removed temp test

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix missing translations key (#133)

* translation: add simplified & traditional chinese

* Fix missing translations

* fix chinese translations

* v0.2.0 Release Candidate (#141)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* notes hot fix

* bug: mongo updates fail #99

* Fix error message (#101)

* gh funding

* Create Issue Templates (#125)

* Create bug_report.md

* Create config.yml

Included a link to feature requests.

* Update config.yml

Fixed link I had for testing to the actual link

* Update bug_report.md

fix capitalization

* Update .github/ISSUE_TEMPLATE/bug_report.md

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* merge kentors changes

* refactor/recipe routers

* category/tag database relationship and endpoints

* frontend category management

* update branch todos

* bug/normalize recipe steps html

* remove console.log +  refactor categories

* fix categories database errors

* refactor/ router endpoint

* refactor/ remove old code

* drag and drop ingredients

* general cleanup

* route refactoring

* changelog

* api refactoring + random cleanup

* fixed backwards sort

* Update mkdocs.yml (#137)

Fix warning from Deploy Docs github action

* fixed navigate on enter in search

* refactor/create global css

* added category scroll

* cleanup todos

* debug routes

* docs/new gifs & general updates

* cleanup

* fix list test

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* fix build

* fix duplicate editor

* fixed docker mount problem

* python 3.9

* added tasks for non-docker development

* remove old scripts

* dev updates

* fixed no image upload option

* get version from backend

* final docs pass

* .gitignore

* feature/markdown support for description and steps

* package-lock

* rename production task

* category import errors on import

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <wengtad93@gmail.com>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* test notifications

* unified notifications

* docs/changelog

Co-authored-by: hay-kot <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <wengtad93@gmail.com>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* Refactor/response models (#156) - First Pass

* cleanup

* split app/db versioning

* async file response

* refactor/recipe viewer + minor ui improvements

* auto grow size

* added async file responses

* docs/changelog

* "/" to open search bar

* docs/changelog

* change imports to use @/ for imports

* cleanup

* cleanup

* db to session

* theme + settings refactor

* bug/image save fix

* fixed failing tests

* fix last json bug - #155

* fix settings import

* fixed router link for site title

Co-authored-by: hay-kot <hay-kot@pm.me>

* version update

* Refactor/response models (#161)

* cleanup

* split app/db versioning

* async file response

* refactor/recipe viewer + minor ui improvements

* auto grow size

* added async file responses

* docs/changelog

* "/" to open search bar

* docs/changelog

* change imports to use @/ for imports

* cleanup

* cleanup

* db to session

* theme + settings refactor

* bug/image save fix

* fixed failing tests

* fix last json bug - #155

* fix settings import

* fixed router link for site title

* add version tag

* v0.2.1 (#157)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

* Dropping Mongo From Dev Branch (#89)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* initial pass

* second pass cleanup

* backup card framework

* backup card functionality

* translation

* upload button vile creation

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* dev bug: change data location to prevent reloads

* api docs

* api docs bug

* workflow update

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* Add French Translation (#93)

* New tests (#94)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

Co-authored-by: Hayden <hay-kot@pm.me>

* Mealplan CRUD Tests (#95)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix typos (#96)

* Settings, Themes and Migration Route Tests (#100)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Refactor + New Docker File (#105)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

Co-authored-by: Hayden <hay-kot@pm.me>

* Meal planner improvements (#107)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

* mealplan redesign

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#108)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#113)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

* UI updates + name validation

* docs: changelog + sp

* fixed route links

* changelog

Co-authored-by: Hayden <hay-kot@pm.me>

* fixed menu links

* fixed poetry install on docker.dev build

* Migration redesign (#119)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix link to dev-notes.md (#110)

* translation: add swedish (#128)

* language: da is Danish

* translations: add swedish

* scraper: unescape html in instructions (#129)

Some urls erroneously deliver escaped html their instructions,
sometimes they are even escaped on multiple levels like here:

https://www.ica.se/recept/kladdig-kladdkaka-722982/

```
>>> normalize_instruction("S&amp;auml;tt ugnen p&amp;aring; 200&amp;deg;C.")
'Sätt ugnen på 200°C.'
```

* v0.2.0 Updates (#130)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

* test todos

* bug/added docker volume

* chowdow test data

* partial image recipe image testing

* added card section card

* settings form

* homepage cetegory ui

* frontend category placeholder

* fixed broken scheduler

* remove old files

* removed temp test

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix missing translations key (#133)

* translation: add simplified & traditional chinese

* Fix missing translations

* fix chinese translations

* v0.2.0 Release Candidate (#141)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* notes hot fix

* bug: mongo updates fail #99

* Fix error message (#101)

* gh funding

* Create Issue Templates (#125)

* Create bug_report.md

* Create config.yml

Included a link to feature requests.

* Update config.yml

Fixed link I had for testing to the actual link

* Update bug_report.md

fix capitalization

* Update .github/ISSUE_TEMPLATE/bug_report.md

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* merge kentors changes

* refactor/recipe routers

* category/tag database relationship and endpoints

* frontend category management

* update branch todos

* bug/normalize recipe steps html

* remove console.log +  refactor categories

* fix categories database errors

* refactor/ router endpoint

* refactor/ remove old code

* drag and drop ingredients

* general cleanup

* route refactoring

* changelog

* api refactoring + random cleanup

* fixed backwards sort

* Update mkdocs.yml (#137)

Fix warning from Deploy Docs github action

* fixed navigate on enter in search

* refactor/create global css

* added category scroll

* cleanup todos

* debug routes

* docs/new gifs & general updates

* cleanup

* fix list test

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* fix build

* fix duplicate editor

* fixed docker mount problem

* python 3.9

* added tasks for non-docker development

* remove old scripts

* dev updates

* fixed no image upload option

* get version from backend

* final docs pass

* .gitignore

* feature/markdown support for description and steps

* package-lock

* rename production task

* category import errors on import (#150)

Co-authored-by: hay-kot <hay-kot@pm.me>

* Feature/improved notifications (#152)

* category import errors on import

* Import Error Hotfix (#148)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

* Dropping Mongo From Dev Branch (#89)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* initial pass

* second pass cleanup

* backup card framework

* backup card functionality

* translation

* upload button vile creation

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* dev bug: change data location to prevent reloads

* api docs

* api docs bug

* workflow update

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* Add French Translation (#93)

* New tests (#94)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

Co-authored-by: Hayden <hay-kot@pm.me>

* Mealplan CRUD Tests (#95)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix typos (#96)

* Settings, Themes and Migration Route Tests (#100)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Refactor + New Docker File (#105)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

Co-authored-by: Hayden <hay-kot@pm.me>

* Meal planner improvements (#107)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

* mealplan redesign

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#108)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#113)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

* UI updates + name validation

* docs: changelog + sp

* fixed route links

* changelog

Co-authored-by: Hayden <hay-kot@pm.me>

* fixed menu links

* fixed poetry install on docker.dev build

* Migration redesign (#119)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix link to dev-notes.md (#110)

* translation: add swedish (#128)

* language: da is Danish

* translations: add swedish

* scraper: unescape html in instructions (#129)

Some urls erroneously deliver escaped html their instructions,
sometimes they are even escaped on multiple levels like here:

https://www.ica.se/recept/kladdig-kladdkaka-722982/

```
>>> normalize_instruction("S&amp;auml;tt ugnen p&amp;aring; 200&amp;deg;C.")
'Sätt ugnen på 200°C.'
```

* v0.2.0 Updates (#130)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

* test todos

* bug/added docker volume

* chowdow test data

* partial image recipe image testing

* added card section card

* settings form

* homepage cetegory ui

* frontend category placeholder

* fixed broken scheduler

* remove old files

* removed temp test

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix missing translations key (#133)

* translation: add simplified & traditional chinese

* Fix missing translations

* fix chinese translations

* v0.2.0 Release Candidate (#141)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* notes hot fix

* bug: mongo updates fail #99

* Fix error message (#101)

* gh funding

* Create Issue Templates (#125)

* Create bug_report.md

* Create config.yml

Included a link to feature requests.

* Update config.yml

Fixed link I had for testing to the actual link

* Update bug_report.md

fix capitalization

* Update .github/ISSUE_TEMPLATE/bug_report.md

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* merge kentors changes

* refactor/recipe routers

* category/tag database relationship and endpoints

* frontend category management

* update branch todos

* bug/normalize recipe steps html

* remove console.log +  refactor categories

* fix categories database errors

* refactor/ router endpoint

* refactor/ remove old code

* drag and drop ingredients

* general cleanup

* route refactoring

* changelog

* api refactoring + random cleanup

* fixed backwards sort

* Update mkdocs.yml (#137)

Fix warning from Deploy Docs github action

* fixed navigate on enter in search

* refactor/create global css

* added category scroll

* cleanup todos

* debug routes

* docs/new gifs & general updates

* cleanup

* fix list test

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* fix build

* fix duplicate editor

* fixed docker mount problem

* python 3.9

* added tasks for non-docker development

* remove old scripts

* dev updates

* fixed no image upload option

* get version from backend

* final docs pass

* .gitignore

* feature/markdown support for description and steps

* package-lock

* rename production task

* category import errors on import

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <wengtad93@gmail.com>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* test notifications

* unified notifications

* docs/changelog

Co-authored-by: hay-kot <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <wengtad93@gmail.com>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* Refactor/response models (#156) - First Pass

* cleanup

* split app/db versioning

* async file response

* refactor/recipe viewer + minor ui improvements

* auto grow size

* added async file responses

* docs/changelog

* "/" to open search bar

* docs/changelog

* change imports to use @/ for imports

* cleanup

* cleanup

* db to session

* theme + settings refactor

* bug/image save fix

* fixed failing tests

* fix last json bug - #155

* fix settings import

* fixed router link for site title

Co-authored-by: hay-kot <hay-kot@pm.me>

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <wengtad93@gmail.com>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* Revert "v0.2.1 (#157)" (#158)

This reverts commit a899f46464.

* v0.2.1 (#159)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

* Dropping Mongo From Dev Branch (#89)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* initial pass

* second pass cleanup

* backup card framework

* backup card functionality

* translation

* upload button vile creation

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* dev bug: change data location to prevent reloads

* api docs

* api docs bug

* workflow update

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* Add French Translation (#93)

* New tests (#94)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

Co-authored-by: Hayden <hay-kot@pm.me>

* Mealplan CRUD Tests (#95)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix typos (#96)

* Settings, Themes and Migration Route Tests (#100)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Refactor + New Docker File (#105)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

Co-authored-by: Hayden <hay-kot@pm.me>

* Meal planner improvements (#107)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

* mealplan redesign

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#108)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#113)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

* UI updates + name validation

* docs: changelog + sp

* fixed route links

* changelog

Co-authored-by: Hayden <hay-kot@pm.me>

* fixed menu links

* fixed poetry install on docker.dev build

* Migration redesign (#119)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix link to dev-notes.md (#110)

* translation: add swedish (#128)

* language: da is Danish

* translations: add swedish

* scraper: unescape html in instructions (#129)

Some urls erroneously deliver escaped html their instructions,
sometimes they are even escaped on multiple levels like here:

https://www.ica.se/recept/kladdig-kladdkaka-722982/

```
>>> normalize_instruction("S&amp;auml;tt ugnen p&amp;aring; 200&amp;deg;C.")
'Sätt ugnen på 200°C.'
```

* v0.2.0 Updates (#130)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

* test todos

* bug/added docker volume

* chowdow test data

* partial image recipe image testing

* added card section card

* settings form

* homepage cetegory ui

* frontend category placeholder

* fixed broken scheduler

* remove old files

* removed temp test

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix missing translations key (#133)

* translation: add simplified & traditional chinese

* Fix missing translations

* fix chinese translations

* v0.2.0 Release Candidate (#141)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* notes hot fix

* bug: mongo updates fail #99

* Fix error message (#101)

* gh funding

* Create Issue Templates (#125)

* Create bug_report.md

* Create config.yml

Included a link to feature requests.

* Update config.yml

Fixed link I had for testing to the actual link

* Update bug_report.md

fix capitalization

* Update .github/ISSUE_TEMPLATE/bug_report.md

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* merge kentors changes

* refactor/recipe routers

* category/tag database relationship and endpoints

* frontend category management

* update branch todos

* bug/normalize recipe steps html

* remove console.log +  refactor categories

* fix categories database errors

* refactor/ router endpoint

* refactor/ remove old code

* drag and drop ingredients

* general cleanup

* route refactoring

* changelog

* api refactoring + random cleanup

* fixed backwards sort

* Update mkdocs.yml (#137)

Fix warning from Deploy Docs github action

* fixed navigate on enter in search

* refactor/create global css

* added category scroll

* cleanup todos

* debug routes

* docs/new gifs & general updates

* cleanup

* fix list test

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* fix build

* fix duplicate editor

* fixed docker mount problem

* python 3.9

* added tasks for non-docker development

* remove old scripts

* dev updates

* fixed no image upload option

* get version from backend

* final docs pass

* .gitignore

* feature/markdown support for description and steps

* package-lock

* rename production task

* category import errors on import (#150)

Co-authored-by: hay-kot <hay-kot@pm.me>

* Feature/improved notifications (#152)

* category import errors on import

* Import Error Hotfix (#148)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

* Dropping Mongo From Dev Branch (#89)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* initial pass

* second pass cleanup

* backup card framework

* backup card functionality

* translation

* upload button vile creation

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* dev bug: change data location to prevent reloads

* api docs

* api docs bug

* workflow update

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* Add French Translation (#93)

* New tests (#94)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

Co-authored-by: Hayden <hay-kot@pm.me>

* Mealplan CRUD Tests (#95)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix typos (#96)

* Settings, Themes and Migration Route Tests (#100)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Refactor + New Docker File (#105)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

Co-authored-by: Hayden <hay-kot@pm.me>

* Meal planner improvements (#107)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

* mealplan redesign

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#108)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#113)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

* UI updates + name validation

* docs: changelog + sp

* fixed route links

* changelog

Co-authored-by: Hayden <hay-kot@pm.me>

* fixed menu links

* fixed poetry install on docker.dev build

* Migration redesign (#119)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix link to dev-notes.md (#110)

* translation: add swedish (#128)

* language: da is Danish

* translations: add swedish

* scraper: unescape html in instructions (#129)

Some urls erroneously deliver escaped html their instructions,
sometimes they are even escaped on multiple levels like here:

https://www.ica.se/recept/kladdig-kladdkaka-722982/

```
>>> normalize_instruction("S&amp;auml;tt ugnen p&amp;aring; 200&amp;deg;C.")
'Sätt ugnen på 200°C.'
```

* v0.2.0 Updates (#130)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

* test todos

* bug/added docker volume

* chowdow test data

* partial image recipe image testing

* added card section card

* settings form

* homepage cetegory ui

* frontend category placeholder

* fixed broken scheduler

* remove old files

* removed temp test

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix missing translations key (#133)

* translation: add simplified & traditional chinese

* Fix missing translations

* fix chinese translations

* v0.2.0 Release Candidate (#141)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* notes hot fix

* bug: mongo updates fail #99

* Fix error message (#101)

* gh funding

* Create Issue Templates (#125)

* Create bug_report.md

* Create config.yml

Included a link to feature requests.

* Update config.yml

Fixed link I had for testing to the actual link

* Update bug_report.md

fix capitalization

* Update .github/ISSUE_TEMPLATE/bug_report.md

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* merge kentors changes

* refactor/recipe routers

* category/tag database relationship and endpoints

* frontend category management

* update branch todos

* bug/normalize recipe steps html

* remove console.log +  refactor categories

* fix categories database errors

* refactor/ router endpoint

* refactor/ remove old code

* drag and drop ingredients

* general cleanup

* route refactoring

* changelog

* api refactoring + random cleanup

* fixed backwards sort

* Update mkdocs.yml (#137)

Fix warning from Deploy Docs github action

* fixed navigate on enter in search

* refactor/create global css

* added category scroll

* cleanup todos

* debug routes

* docs/new gifs & general updates

* cleanup

* fix list test

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* fix build

* fix duplicate editor

* fixed docker mount problem

* python 3.9

* added tasks for non-docker development

* remove old scripts

* dev updates

* fixed no image upload option

* get version from backend

* final docs pass

* .gitignore

* feature/markdown support for description and steps

* package-lock

* rename production task

* category import errors on import

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <wengtad93@gmail.com>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* test notifications

* unified notifications

* docs/changelog

Co-authored-by: hay-kot <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <wengtad93@gmail.com>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* Refactor/response models (#156) - First Pass

* cleanup

* split app/db versioning

* async file response

* refactor/recipe viewer + minor ui improvements

* auto grow size

* added async file responses

* docs/changelog

* "/" to open search bar

* docs/changelog

* change imports to use @/ for imports

* cleanup

* cleanup

* db to session

* theme + settings refactor

* bug/image save fix

* fixed failing tests

* fix last json bug - #155

* fix settings import

* fixed router link for site title

Co-authored-by: hay-kot <hay-kot@pm.me>

* version update

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <…

* Consider any .json file from Nextcloud (#164)

* Allow empty instructions (#165)

* fix scrape recipe error (#166)

- fixes #138
- fixes #145

* Add polish translation (#154)

* add polish translation

* add missing allLangs value for polish translation in language.js

* Create de.json (#167)

Add German Translation

* Refactor/response models (#169)

* cleanup

* split app/db versioning

* async file response

* refactor/recipe viewer + minor ui improvements

* auto grow size

* added async file responses

* docs/changelog

* "/" to open search bar

* docs/changelog

* change imports to use @/ for imports

* cleanup

* cleanup

* db to session

* theme + settings refactor

* bug/image save fix

* fixed failing tests

* fix last json bug - #155

* fix settings import

* fixed router link for site title

* add version tag

* v0.2.1 (#157)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

* Dropping Mongo From Dev Branch (#89)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* initial pass

* second pass cleanup

* backup card framework

* backup card functionality

* translation

* upload button vile creation

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* dev bug: change data location to prevent reloads

* api docs

* api docs bug

* workflow update

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* Add French Translation (#93)

* New tests (#94)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

Co-authored-by: Hayden <hay-kot@pm.me>

* Mealplan CRUD Tests (#95)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix typos (#96)

* Settings, Themes and Migration Route Tests (#100)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Refactor + New Docker File (#105)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

Co-authored-by: Hayden <hay-kot@pm.me>

* Meal planner improvements (#107)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

* mealplan redesign

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#108)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#113)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

* UI updates + name validation

* docs: changelog + sp

* fixed route links

* changelog

Co-authored-by: Hayden <hay-kot@pm.me>

* fixed menu links

* fixed poetry install on docker.dev build

* Migration redesign (#119)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix link to dev-notes.md (#110)

* translation: add swedish (#128)

* language: da is Danish

* translations: add swedish

* scraper: unescape html in instructions (#129)

Some urls erroneously deliver escaped html their instructions,
sometimes they are even escaped on multiple levels like here:

https://www.ica.se/recept/kladdig-kladdkaka-722982/

```
>>> normalize_instruction("S&amp;auml;tt ugnen p&amp;aring; 200&amp;deg;C.")
'Sätt ugnen på 200°C.'
```

* v0.2.0 Updates (#130)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

* test todos

* bug/added docker volume

* chowdow test data

* partial image recipe image testing

* added card section card

* settings form

* homepage cetegory ui

* frontend category placeholder

* fixed broken scheduler

* remove old files

* removed temp test

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix missing translations key (#133)

* translation: add simplified & traditional chinese

* Fix missing translations

* fix chinese translations

* v0.2.0 Release Candidate (#141)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* notes hot fix

* bug: mongo updates fail #99

* Fix error message (#101)

* gh funding

* Create Issue Templates (#125)

* Create bug_report.md

* Create config.yml

Included a link to feature requests.

* Update config.yml

Fixed link I had for testing to the actual link

* Update bug_report.md

fix capitalization

* Update .github/ISSUE_TEMPLATE/bug_report.md

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* merge kentors changes

* refactor/recipe routers

* category/tag database relationship and endpoints

* frontend category management

* update branch todos

* bug/normalize recipe steps html

* remove console.log +  refactor categories

* fix categories database errors

* refactor/ router endpoint

* refactor/ remove old code

* drag and drop ingredients

* general cleanup

* route refactoring

* changelog

* api refactoring + random cleanup

* fixed backwards sort

* Update mkdocs.yml (#137)

Fix warning from Deploy Docs github action

* fixed navigate on enter in search

* refactor/create global css

* added category scroll

* cleanup todos

* debug routes

* docs/new gifs & general updates

* cleanup

* fix list test

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* fix build

* fix duplicate editor

* fixed docker mount problem

* python 3.9

* added tasks for non-docker development

* remove old scripts

* dev updates

* fixed no image upload option

* get version from backend

* final docs pass

* .gitignore

* feature/markdown support for description and steps

* package-lock

* rename production task

* category import errors on import (#150)

Co-authored-by: hay-kot <hay-kot@pm.me>

* Feature/improved notifications (#152)

* category import errors on import

* Import Error Hotfix (#148)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

* Dropping Mongo From Dev Branch (#89)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* initial pass

* second pass cleanup

* backup card framework

* backup card functionality

* translation

* upload button vile creation

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* dev bug: change data location to prevent reloads

* api docs

* api docs bug

* workflow update

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* Add French Translation (#93)

* New tests (#94)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

Co-authored-by: Hayden <hay-kot@pm.me>

* Mealplan CRUD Tests (#95)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix typos (#96)

* Settings, Themes and Migration Route Tests (#100)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Refactor + New Docker File (#105)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

Co-authored-by: Hayden <hay-kot@pm.me>

* Meal planner improvements (#107)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

* mealplan redesign

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#108)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#113)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

* UI updates + name validation

* docs: changelog + sp

* fixed route links

* changelog

Co-authored-by: Hayden <hay-kot@pm.me>

* fixed menu links

* fixed poetry install on docker.dev build

* Migration redesign (#119)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix link to dev-notes.md (#110)

* translation: add swedish (#128)

* language: da is Danish

* translations: add swedish

* scraper: unescape html in instructions (#129)

Some urls erroneously deliver escaped html their instructions,
sometimes they are even escaped on multiple levels like here:

https://www.ica.se/recept/kladdig-kladdkaka-722982/

```
>>> normalize_instruction("S&amp;auml;tt ugnen p&amp;aring; 200&amp;deg;C.")
'Sätt ugnen på 200°C.'
```

* v0.2.0 Updates (#130)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

* test todos

* bug/added docker volume

* chowdow test data

* partial image recipe image testing

* added card section card

* settings form

* homepage cetegory ui

* frontend category placeholder

* fixed broken scheduler

* remove old files

* removed temp test

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix missing translations key (#133)

* translation: add simplified & traditional chinese

* Fix missing translations

* fix chinese translations

* v0.2.0 Release Candidate (#141)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* notes hot fix

* bug: mongo updates fail #99

* Fix error message (#101)

* gh funding

* Create Issue Templates (#125)

* Create bug_report.md

* Create config.yml

Included a link to feature requests.

* Update config.yml

Fixed link I had for testing to the actual link

* Update bug_report.md

fix capitalization

* Update .github/ISSUE_TEMPLATE/bug_report.md

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* merge kentors changes

* refactor/recipe routers

* category/tag database relationship and endpoints

* frontend category management

* update branch todos

* bug/normalize recipe steps html

* remove console.log +  refactor categories

* fix categories database errors

* refactor/ router endpoint

* refactor/ remove old code

* drag and drop ingredients

* general cleanup

* route refactoring

* changelog

* api refactoring + random cleanup

* fixed backwards sort

* Update mkdocs.yml (#137)

Fix warning from Deploy Docs github action

* fixed navigate on enter in search

* refactor/create global css

* added category scroll

* cleanup todos

* debug routes

* docs/new gifs & general updates

* cleanup

* fix list test

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* fix build

* fix duplicate editor

* fixed docker mount problem

* python 3.9

* added tasks for non-docker development

* remove old scripts

* dev updates

* fixed no image upload option

* get version from backend

* final docs pass

* .gitignore

* feature/markdown support for description and steps

* package-lock

* rename production task

* category import errors on import

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <wengtad93@gmail.com>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* test notifications

* unified notifications

* docs/changelog

Co-authored-by: hay-kot <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <wengtad93@gmail.com>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* Refactor/response models (#156) - First Pass

* cleanup

* split app/db versioning

* async file response

* refactor/recipe viewer + minor ui improvements

* auto grow size

* added async file responses

* docs/changelog

* "/" to open search bar

* docs/changelog

* change imports to use @/ for imports

* cleanup

* cleanup

* db to session

* theme + settings refactor

* bug/image save fix

* fixed failing tests

* fix last json bug - #155

* fix settings import

* fixed router link for site title

Co-authored-by: hay-kot <hay-kot@pm.me>

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <wengtad93@gmail.com>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* Revert "v0.2.1 (#157)" (#158)

This reverts commit a899f46464.

* v0.2.1 (#159)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

* Dropping Mongo From Dev Branch (#89)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* initial pass

* second pass cleanup

* backup card framework

* backup card functionality

* translation

* upload button vile creation

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* dev bug: change data location to prevent reloads

* api docs

* api docs bug

* workflow update

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* Add French Translation (#93)

* New tests (#94)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

Co-authored-by: Hayden <hay-kot@pm.me>

* Mealplan CRUD Tests (#95)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix typos (#96)

* Settings, Themes and Migration Route Tests (#100)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Refactor + New Docker File (#105)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

Co-authored-by: Hayden <hay-kot@pm.me>

* Meal planner improvements (#107)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

* mealplan redesign

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#108)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#113)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

* UI updates + name validation

* docs: changelog + sp

* fixed route links

* changelog

Co-authored-by: Hayden <hay-kot@pm.me>

* fixed menu links

* fixed poetry install on docker.dev build

* Migration redesign (#119)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix link to dev-notes.md (#110)

* translation: add swedish (#128)

* language: da is Danish

* translations: add swedish

* scraper: unescape html in instructions (#129)

Some urls erroneously deliver escaped html their instructions,
sometimes they are even escaped on multiple levels like here:

https://www.ica.se/recept/kladdig-kladdkaka-722982/

```
>>> normalize_instruction("S&amp;auml;tt ugnen p&amp;aring; 200&amp;deg;C.")
'Sätt ugnen på 200°C.'
```

* v0.2.0 Updates (#130)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

* test todos

* bug/added docker volume

* chowdow test data

* partial image recipe image testing

* added card section card

* settings form

* homepage cetegory ui

* frontend category placeholder

* fixed broken scheduler

* remove old files

* removed temp test

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix missing translations key (#133)

* translation: add simplified & traditional chinese

* Fix missing translations

* fix chinese translations

* v0.2.0 Release Candidate (#141)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* notes hot fix

* bug: mongo updates fail #99

* Fix error message (#101)

* gh funding

* Create Issue Templates (#125)

* Create bug_report.md

* Create config.yml

Included a link to feature requests.

* Update config.yml

Fixed link I had for testing to the actual link

* Update bug_report.md

fix capitalization

* Update .github/ISSUE_TEMPLATE/bug_report.md

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* merge kentors changes

* refactor/recipe routers

* category/tag database relationship and endpoints

* frontend category management

* update branch todos

* bug/normalize recipe steps html

* remove console.log +  refactor categories

* fix categories database errors

* refactor/ router endpoint

* refactor/ remove old code

* drag and drop ingredients

* general cleanup

* route refactoring

* changelog

* api refactoring + random cleanup

* fixed backwards sort

* Update mkdocs.yml (#137)

Fix warning from Deploy Docs github action

* fixed navigate on enter in search

* refactor/create global css

* added category scroll

* cleanup todos

* debug routes

* docs/new gifs & general updates

* cleanup

* fix list test

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* fix build

* fix duplicate editor

* fixed docker mount problem

* python 3.9

* added tasks for non-docker development

* remove old scripts

* dev updates

* fixed no image upload option

* get version from backend

* final docs pass

* .gitignore

* feature/markdown support for description and steps

* package-lock

* rename production task

* category import errors on import (#150)

Co-authored-by: hay-kot <hay-kot@pm.me>

* Feature/improved notifications (#152)

* category import errors on import

* Import Error Hotfix (#148)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

* Dropping Mongo From Dev Branch (#89)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* initial pass

* second pass cleanup

* backup card framework

* backup card functionality

* translation

* upload button vile creation

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* dev bug: change data location to prevent reloads

* api docs

* api docs bug

* workflow update

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* Add French Translation (#93)

* New tests (#94)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

Co-authored-by: Hayden <hay-kot@pm.me>

* Mealplan CRUD Tests (#95)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix typos (#96)

* Settings, Themes and Migration Route Tests (#100)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

Co-authored-by: Hayden <hay-kot@pm.me>

* Refactor + New Docker File (#105)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

Co-authored-by: Hayden <hay-kot@pm.me>

* Meal planner improvements (#107)

* dev-bug: fixed vscode freezes

* test: refactor database init to support tests

* mealplan CRUD testing

* restructure test folder

* git attributes

* tests: migration, settings, theme routes testing

* docker-file shrink

* rebuild

* refactor: moving directories around

* adding funding

* mealplan redesign

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#108)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

Co-authored-by: Hayden <hay-kot@pm.me>

* Upload component (#113)

* unified upload button + download backups

* javascript toolings

* fix vuetur config

* fixed type check error

* refactor: clean up bag javascript

* UI updates + name validation

* docs: changelog + sp

* fixed route links

* changelog

Co-authored-by: Hayden <hay-kot@pm.me>

* fixed menu links

* fixed poetry install on docker.dev build

* Migration redesign (#119)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix link to dev-notes.md (#110)

* translation: add swedish (#128)

* language: da is Danish

* translations: add swedish

* scraper: unescape html in instructions (#129)

Some urls erroneously deliver escaped html their instructions,
sometimes they are even escaped on multiple levels like here:

https://www.ica.se/recept/kladdig-kladdkaka-722982/

```
>>> normalize_instruction("S&amp;auml;tt ugnen p&amp;aring; 200&amp;deg;C.")
'Sätt ugnen på 200°C.'
```

* v0.2.0 Updates (#130)

* migration redesign init

* new color picker

* changelog

* added UI language selection

* fix layout issue on recipe editor

* remove git as dependency

* added UI editor for original URL

* CI/CD Tests

* test: fixed migration routes

* test todos

* bug/added docker volume

* chowdow test data

* partial image recipe image testing

* added card section card

* settings form

* homepage cetegory ui

* frontend category placeholder

* fixed broken scheduler

* remove old files

* removed temp test

Co-authored-by: Hayden <hay-kot@pm.me>

* Fix missing translations key (#133)

* translation: add simplified & traditional chinese

* Fix missing translations

* fix chinese translations

* v0.2.0 Release Candidate (#141)

* Fix link to Docker Hub

Found an extra s. DESTROYED it.

* Release v0.1.0 Candidate (#85)

* Changed uvicorn port to 80

* Changed port in docker-compose to match dockerfile

* Readded environment variables in docker-compose

* production image rework

* Use opengraph metadata to make basic recipe cards when full recipe metadata is not available

* fixed instrucitons on parse

* add last_recipe

* automated testing

* roadmap update

* Sqlite (#75)

* file structure

* auto-test

* take 2

* refactor ap scheduler and startup process

* fixed scraper error

* database abstraction

* database abstraction

* port recipes over to new schema

* meal migration

* start settings migration

* finale mongo port

* backup improvements

* migration imports to new DB structure

* unused import cleanup

* docs strings

* settings and theme import logic

* cleanup

* fixed tinydb error

* requirements

* fuzzy search

* remove scratch file

* sqlalchemy models

* improved search ui

* recipe models almost done

* sql modal population

* del scratch

* rewrite database model mixins

* mostly grabage

* recipe updates

* working sqllite

* remove old files and reorganize

* final cleanup

Co-authored-by: Hayden <hay-kot@pm.me>

* Backup card (#78)

* backup / import dialog

* upgrade to new tag method

* New import card

* rename settings.py to app_config.py

* migrate to poetry for development

* fix failing test

Co-authored-by: Hayden <hay-kot@pm.me>

* added mkdocs to docker-compose

* Translations (#72)

* Translations + danish

* changed back proxy target to use ENV

* Resolved more merge conflicts

* Removed test in translation

* Documentation of translations

* Updated translations

* removed old packages

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>

* fail to start bug fixes

* feature: prep/cook/total time slots (#80)

Co-authored-by: Hayden <hay-kot@pm.me>

* missing bind attributes

* Bug fixes (#81)

* fix: url remains after succesful import

* docs: changelog + update todos

* arm image

* arm compose

* compose updates

* update poetry

* arm support

Co-authored-by: Hayden <hay-kot@pm.me>

* dockerfile hotfix

* dockerfile hotfix

* Version Release Final Touches (#84)

* Remove slim

* bug: opacity issues

* bug: startup failure with no database

* ci/cd on dev branch

* formatting

* v0.1.0 documentation

Co-authored-by: Hayden <hay-kot@pm.me>

* db init hotfix

* bug: fix crash in mongo

* fix mongo bug

* fixed version notifier

* finale changelog

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>

* build container

* webscraper hotfix

* notes hot fix

* bug: mongo updates fail #99

* Fix error message (#101)

* gh funding

* Create Issue Templates (#125)

* Create bug_report.md

* Create config.yml

Included a link to feature requests.

* Update config.yml

Fixed link I had for testing to the actual link

* Update bug_report.md

fix capitalization

* Update .github/ISSUE_TEMPLATE/bug_report.md

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* merge kentors changes

* refactor/recipe routers

* category/tag database relationship and endpoints

* frontend category management

* update branch todos

* bug/normalize recipe steps html

* remove console.log +  refactor categories

* fix categories database errors

* refactor/ router endpoint

* refactor/ remove old code

* drag and drop ingredients

* general cleanup

* route refactoring

* changelog

* api refactoring + random cleanup

* fixed backwards sort

* Update mkdocs.yml (#137)

Fix warning from Deploy Docs github action

* fixed navigate on enter in search

* refactor/create global css

* added category scroll

* cleanup todos

* debug routes

* docs/new gifs & general updates

* cleanup

* fix list test

Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* fix build

* fix duplicate editor

* fixed docker mount problem

* python 3.9

* added tasks for non-docker development

* remove old scripts

* dev updates

* fixed no image upload option

* get version from backend

* final docs pass

* .gitignore

* feature/markdown support for description and steps

* package-lock

* rename production task

* category import errors on import

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <wengtad93@gmail.com>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* test notifications

* unified notifications

* docs/changelog

Co-authored-by: hay-kot <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <wengtad93@gmail.com>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>

* Refactor/response models (#156) - First Pass

* cleanup

* split app/db versioning

* async file response

* refactor/recipe viewer + minor ui improvements

* auto grow size

* added async file responses

* docs/changelog

* "/" to open search bar

* docs/changelog

* change imports to use @/ for imports

* cleanup

* cleanup

* db to session

* theme + settings refactor

* bug/image save fix

* fixed failing tests

* fix last json bug - #155

* fix settings import

* fixed router link for site title

Co-authored-by: hay-kot <hay-kot@pm.me>

* version update

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <…

* Enhance mobile view (#171)

* Fixed navbar on mobile

* Feature/shopping list (#172)

* API Endpoint

* shopping list added to the UI

* fixed category sidebar on mobile

Co-authored-by: hay-kot <hay-kot@pm.me>

* Feature/shopping list (#173)

* API Endpoint

* shopping list added to the UI

* fixed category sidebar on mobile

* fix category sidebar hidden all the time

* adjust mobile view on times

* remove console.logs

* actually remove console.logs

* Fixed varying card height on smaller screens

* change style of meal planner categories

Co-authored-by: hay-kot <hay-kot@pm.me>

* refactor/scrapper (#175)

* API Endpoint

* shopping list added to the UI

* fixed category sidebar on mobile

* fix category sidebar hidden all the time

* adjust mobile view on times

* remove console.logs

* actually remove console.logs

* Fixed varying card height on smaller screens

* change style of meal planner categories

* bug/fixed open search on '/' when on input

* Improved import summary dialog

* url validation

* refactor/split reciper scraper into seperate fiels

Co-authored-by: hay-kot <hay-kot@pm.me>

* auto focus on add from url

* docs/update v0.3.0

* remove print

* docs/v0.3.0

* Localize homepage settings + FR translation (#180)

* localize homepage settings vue

* French localization for homepage settings

* localize meal planner settings

* Feature/authentication (#185)

* basic crud NOT SECURE

* refactor/database init on startup

* added scratch.py

* tests/user CRUD routes

* password hashing

* change app_config location

* bump python version

* formatting

* login ui starter

* change import from url design

* move components

* remove old snackbar

* refactor/Componenet folder structure rework

* refactor/remove old code

* refactor/rename componenets/js files

* remove console.logs

* refactor/ models to schema and sql to models

* new header styling for imports

* token request

* fix url scrapper

* refactor/rename schema files

* split routes file

* redesigned admin page

* enable relative imports for vue components

* refactor/switch to pages view

* add CamelCase package

* majors settings rework

* user management second pass

* super user CRUD

* refactor/consistent models names

* refactor/consistent model names

Co-authored-by: hay-kot <hay-kot@pm.me>

* Fixes #183 (#187)

* #183 added backend validation for mealplanning timespan

* Fixes #183

Disabling save button when dateDif is negative, replacing non-functional invisible button(?) with proper spacing

Co-authored-by: Bernhard Großer <30469627+boerniee@users.noreply.github.com>
Co-authored-by: Andreas Waschinski <an.andreas@posteo.de>

* Localized meal date (#182)

* first step towards localized meal date

* Refactor datetimeFormats to dedicated locale files

* localized date in 'Dinner this week'

* Feature/authentication (#190)

* basic crud NOT SECURE

* refactor/database init on startup

* added scratch.py

* tests/user CRUD routes

* password hashing

* change app_config location

* bump python version

* formatting

* login ui starter

* change import from url design

* move components

* remove old snackbar

* refactor/Componenet folder structure rework

* refactor/remove old code

* refactor/rename componenets/js files

* remove console.logs

* refactor/ models to schema and sql to models

* new header styling for imports

* token request

* fix url scrapper

* refactor/rename schema files

* split routes file

* redesigned admin page

* enable relative imports for vue components

* refactor/switch to pages view

* add CamelCase package

* majors settings rework

* user management second pass

* super user CRUD

* refactor/consistent models names

* refactor/consistent model names

* password reset

* store refactor

* dependency update

* abstract button props

* profile page refactor

* basic password validation

* login form refactor/split v-container

* remo unused code

* hide editor buttons when not logged in

* mkdocs dev dependency

* v0.4.0 docs update

* profile image upload

* additional token routes

* Smaller recipe cards for smaller viewports

* fix admin sidebar

* add users

* change to outlined

Co-authored-by: hay-kot <hay-kot@pm.me>

* Feature/authentication (#195)

* basic crud NOT SECURE

* refactor/database init on startup

* added scratch.py

* tests/user CRUD routes

* password hashing

* change app_config location

* bump python version

* formatting

* login ui starter

* change import from url design

* move components

* remove old snackbar

* refactor/Componenet folder structure rework

* refactor/remove old code

* refactor/rename componenets/js files

* remove console.logs

* refactor/ models to schema and sql to models

* new header styling for imports

* token request

* fix url scrapper

* refactor/rename schema files

* split routes file

* redesigned admin page

* enable relative imports for vue components

* refactor/switch to pages view

* add CamelCase package

* majors settings rework

* user management second pass

* super user CRUD

* refactor/consistent models names

* refactor/consistent model names

* password reset

* store refactor

* dependency update

* abstract button props

* profile page refactor

* basic password validation

* login form refactor/split v-container

* remo unused code

* hide editor buttons when not logged in

* mkdocs dev dependency

* v0.4.0 docs update

* profile image upload

* additional token routes

* Smaller recipe cards for smaller viewports

* fix admin sidebar

* add users

* change to outlined

* theme card starter

* code cleanup

* signups

* signup pages

* fix #194

* fix #193

* clarify mealie_port

* fix #184

* fixes #178

* fix blank card error on meal-plan creator

* admin signup

Co-authored-by: hay-kot <hay-kot@pm.me>

* Initialize language settings earlier (#199)

* Some titles were missing i18n (#197)

Also slightly improved the german translation file.

Co-authored-by: Andreas Waschinski <an.andreas@posteo.de>

* Update fr.json (#204)

Reference #124
French
Added new strings + Updated some

* Feature/authentication (#206)

* basic crud NOT SECURE

* refactor/database init on startup

* added scratch.py

* tests/user CRUD routes

* password hashing

* change app_config location

* bump python version

* formatting

* login ui starter

* change import from url design

* move components

* remove old snackbar

* refactor/Componenet folder structure rework

* refactor/remove old code

* refactor/rename componenets/js files

* remove console.logs

* refactor/ models to schema and sql to models

* new header styling for imports

* token request

* fix url scrapper

* refactor/rename schema files

* split routes file

* redesigned admin page

* enable relative imports for vue components

* refactor/switch to pages view

* add CamelCase package

* majors settings rework

* user management second pass

* super user CRUD

* refactor/consistent models names

* refactor/consistent model names

* password reset

* store refactor

* dependency update

* abstract button props

* profile page refactor

* basic password validation

* login form refactor/split v-container

* remo unused code

* hide editor buttons when not logged in

* mkdocs dev dependency

* v0.4.0 docs update

* profile image upload

* additional token routes

* Smaller recipe cards for smaller viewports

* fix admin sidebar

* add users

* change to outlined

* theme card starter

* code cleanup

* signups

* signup pages

* fix #194

* fix #193

* clarify mealie_port

* fix #184

* fixes #178

* fix blank card error on meal-plan creator

* admin signup

* formatting

* improved search bar

* improved search bar

* refresh token on page refresh

* allow mealplan with no categories

* fix card layout

* remove cdn dependencies

* start on groups

* Fixes #196

* recipe databse refactor

* changelog draft

* database refactoring

* refactor recipe schema/model

* site settings refactor

* continued model refactor

* merge docs changes from master

* site-settings work

* cleanup + tag models

* notes

* typo

* user table

* sign up data validation

* package updates

* group store init

* Fix home page settings

* group admin init

* group dashboard init

* update deps

* formatting

* bug / added libffi-dev

Co-authored-by: hay-kot <hay-kot@pm.me>

* Feature/authentication (#207)

* basic crud NOT SECURE

* refactor/database init on startup

* added scratch.py

* tests/user CRUD routes

* password hashing

* change app_config location

* bump python version

* formatting

* login ui starter

* change import from url design

* move components

* remove old snackbar

* refactor/Componenet folder structure rework

* refactor/remove old code

* refactor/rename componenets/js files

* remove console.logs

* refactor/ models to schema and sql to models

* new header styling for imports

* token request

* fix url scrapper

* refactor/rename schema files

* split routes file

* redesigned admin page

* enable relative imports for vue components

* refactor/switch to pages view

* add CamelCase package

* majors settings rework

* user management second pass

* super user CRUD

* refactor/consistent models names

* refactor/consistent model names

* password reset

* store refactor

* dependency update

* abstract button props

* profile page refactor

* basic password validation

* login form refactor/split v-container

* remo unused code

* hide editor buttons when not logged in

* mkdocs dev dependency

* v0.4.0 docs update

* profile image upload

* additional token routes

* Smaller recipe cards for smaller viewports

* fix admin sidebar

* add users

* change to outlined

* theme card starter

* code cleanup

* signups

* signup pages

* fix #194

* fix #193

* clarify mealie_port

* fix #184

* fixes #178

* fix blank card error on meal-plan creator

* admin signup

* formatting

* improved search bar

* improved search bar

* refresh token on page refresh

* allow mealplan with no categories

* fix card layout

* remove cdn dependencies

* start on groups

* Fixes #196

* recipe databse refactor

* changelog draft

* database refactoring

* refactor recipe schema/model

* site settings refactor

* continued model refactor

* merge docs changes from master

* site-settings work

* cleanup + tag models

* notes

* typo

* user table

* sign up data validation

* package updates

* group store init

* Fix home page settings

* group admin init

* group dashboard init

* update deps

* formatting

* bug / added libffi-dev

* pages refactor

* fix mealplan

Co-authored-by: hay-kot <hay-kot@pm.me>

* Feature/authentication (#209)

* basic crud NOT SECURE

* refactor/database init on startup

* added scratch.py

* tests/user CRUD routes

* password hashing

* change app_config location

* bump python version

* formatting

* login ui starter

* change import from url design

* move components

* remove old snackbar

* refactor/Componenet folder structure rework

* refactor/remove old code

* refactor/rename componenets/js files

* remove console.logs

* refactor/ models to schema and sql to models

* new header styling for imports

* token request

* fix url scrapper

* refactor/rename schema files

* split routes file

* redesigned admin page

* enable relative imports for vue components

* refactor/switch to pages view

* add CamelCase package

* majors settings rework

* user management second pass

* super user CRUD

* refactor/consistent models names

* refactor/consistent model names

* password reset

* store refactor

* dependency update

* abstract button props

* profile page refactor

* basic password validation

* login form refactor/split v-container

* remo unused code

* hide editor buttons when not logged in

* mkdocs dev dependency

* v0.4.0 docs update

* profile image upload

* additional token routes

* Smaller recipe cards for smaller viewports

* fix admin sidebar

* add users

* change to outlined

* theme card starter

* code cleanup

* signups

* signup pages

* fix #194

* fix #193

* clarify mealie_port

* fix #184

* fixes #178

* fix blank card error on meal-plan creator

* admin signup

* formatting

* improved search bar

* improved search bar

* refresh token on page refresh

* allow mealplan with no categories

* fix card layout

* remove cdn dependencies

* start on groups

* Fixes #196

* recipe databse refactor

* changelog draft

* database refactoring

* refactor recipe schema/model

* site settings refactor

* continued model refactor

* merge docs changes from master

* site-settings work

* cleanup + tag models

* notes

* typo

* user table

* sign up data validation

* package updates

* group store init

* Fix home page settings

* group admin init

* group dashboard init

* update deps

* formatting

* bug / added libffi-dev

* pages refactor

* fix mealplan

* docs update

* multi group supporot for job scheduler

* formatting

* formatting

* home-page redesign

* set background for docs darkmode

Co-authored-by: hay-kot <hay-kot@pm.me>

* Feature/authentication (#210)

* basic crud NOT SECURE

* refactor/database init on startup

* added scratch.py

* tests/user CRUD routes

* password hashing

* change app_config location

* bump python version

* formatting

* login ui starter

* change import from url design

* move components

* remove old snackbar

* refactor/Componenet folder structure rework

* refactor/remove old code

* refactor/rename componenets/js files

* remove console.logs

* refactor/ models to schema and sql to models

* new header styling for imports

* token request

* fix url scrapper

* refactor/rename schema files

* split routes file

* redesigned admin page

* enable relative imports for vue components

* refactor/switch to pages view

* add CamelCase package

* majors settings rework

* user management second pass

* super user CRUD

* refactor/consistent models names

* refactor/consistent model names

* password reset

* store refactor

* dependency update

* abstract button props

* profile page refactor

* basic password validation

* login form refactor/split v-container

* remo unused code

* hide editor buttons when not logged in

* mkdocs dev dependency

* v0.4.0 docs update

* profile image upload

* additional token routes

* Smaller recipe cards for smaller viewports

* fix admin sidebar

* add users

* change to outlined

* theme card starter

* code cleanup

* signups

* signup pages

* fix #194

* fix #193

* clarify mealie_port

* fix #184

* fixes #178

* fix blank card error on meal-plan creator

* admin signup

* formatting

* improved search bar

* improved search bar

* refresh token on page refresh

* allow mealplan with no categories

* fix card layout

* remove cdn dependencies

* start on groups

* Fixes #196

* recipe databse refactor

* changelog draft

* database refactoring

* refactor recipe schema/model

* site settings refactor

* continued model refactor

* merge docs changes from master

* site-settings work

* cleanup + tag models

* notes

* typo

* user table

* sign up data validation

* package updates

* group store init

* Fix home page settings

* group admin init

* group dashboard init

* update deps

* formatting

* bug / added libffi-dev

* pages refactor

* fix mealplan

* docs update

* multi group supporot for job scheduler

* formatting

* formatting

* home-page redesign

* set background for docs darkmode

* code cleanup

* docs refactor

* v0.4.0 image

* mkdocs port change

* formatting

* Fix Meal-Plan Today

* fix webhook bug

* fix meal plan this week

* export users

Co-authored-by: hay-kot <hay-kot@pm.me>

* More localization (#208)

* remove unused strings

* update i18n-ally settings

* localized date picker

* Translate CardSection

* SiteMenu translatable

* Translate TheUserTable

* Use embedded Vuetify locales

* localize TheUserTable

* Localize group and sign up settings

* Slightly enlarge group tile width

* Localize admin side bar + user nav bar

* Missing strings in Login form

* Fix success message upon photo upload

* Localize profile page

* Missing translations in settings

* Feature/authentication (#213)

* basic crud NOT SECURE

* refactor/database init on startup

* added scratch.py

* tests/user CRUD routes

* password hashing

* change app_config location

* bump python version

* formatting

* login ui starter

* change import from url design

* move components

* remove old snackbar

* refactor/Componenet folder structure rework

* refactor/remove old code

* refactor/rename componenets/js files

* remove console.logs

* refactor/ models to schema and sql to models

* new header styling for imports

* token request

* fix url scrapper

* refactor/rename schema files

* split routes file

* redesigned admin page

* enable relative imports for vue components

* refactor/switch to pages view

* add CamelCase package

* majors settings rework

* user management second pass

* super user CRUD

* refactor/consistent models names

* refactor/consistent model names

* password reset

* store refactor

* dependency update

* abstract button props

* profile page refactor

* basic password validation

* login form refactor/split v-container

* remo unused code

* hide editor buttons when not logged in

* mkdocs dev dependency

* v0.4.0 docs update

* profile image upload

* additional token routes

* Smaller recipe cards for smaller viewports

* fix admin sidebar

* add users

* change to outlined

* theme card starter

* code cleanup

* signups

* signup pages

* fix #194

* fix #193

* clarify mealie_port

* fix #184

* fixes #178

* fix blank card error on meal-plan creator

* admin signup

* formatting

* improved search bar

* improved search bar

* refresh token on page refresh

* allow mealplan with no categories

* fix card layout

* remove cdn dependencies

* start on groups

* Fixes #196

* recipe databse refactor

* changelog draft

* database refactoring

* refactor recipe schema/model

* site settings refactor

* continued model refactor

* merge docs changes from master

* site-settings work

* cleanup + tag models

* notes

* typo

* user table

* sign up data validation

* package updates

* group store init

* Fix home page settings

* group admin init

* group dashboard init

* update deps

* formatting

* bug / added libffi-dev

* pages refactor

* fix mealplan

* docs update

* multi group supporot for job scheduler

* formatting

* formatting

* home-page redesign

* set background for docs darkmode

* code cleanup

* docs refactor

* v0.4.0 image

* mkdocs port change

* formatting

* Fix Meal-Plan Today

* fix webhook bug

* fix meal plan this week

* export users

* 📦 Proper Package + Black Config

* formatting

* delete old files

* fix ci

* fix failing builds

* package/makefile docs update

* add docs server to tasks

Co-authored-by: hay-kot <hay-kot@pm.me>

* Fix Docker/Dev ENV

* basic crud NOT SECURE

* refactor/database init on startup

* added scratch.py

* tests/user CRUD routes

* password hashing

* change app_config location

* bump python version

* formatting

* login ui starter

* change import from url design

* move components

* remove old snackbar

* refactor/Componenet folder structure rework

* refactor/remove old code

* refactor/rename componenets/js files

* remove console.logs

* refactor/ models to schema and sql to models

* new header styling for imports

* token request

* fix url scrapper

* refactor/rename schema files

* split routes file

* redesigned admin page

* enable relative imports for vue components

* refactor/switch to pages view

* add CamelCase package

* majors settings rework

* user management second pass

* super user CRUD

* refactor/consistent models names

* refactor/consistent model names

* password reset

* store refactor

* dependency update

* abstract button props

* profile page refactor

* basic password validation

* login form refactor/split v-container

* remo unused code

* hide editor buttons when not logged in

* mkdocs dev dependency

* v0.4.0 docs update

* profile image upload

* additional token routes

* Smaller recipe cards for smaller viewports

* fix admin sidebar

* add users

* change to outlined

* theme card starter

* code cleanup

* signups

* signup pages

* fix #194

* fix #193

* clarify mealie_port

* fix #184

* fixes #178

* fix blank card error on meal-plan creator

* admin signup

* formatting

* improved search bar

* improved search bar

* refresh token on page refresh

* allow mealplan with no categories

* fix card layout

* remove cdn dependencies

* start on groups

* Fixes #196

* recipe databse refactor

* changelog draft

* database refactoring

* refactor recipe schema/model

* site settings refactor

* continued model refactor

* merge docs changes from master

* site-settings work

* cleanup + tag models

* notes

* typo

* user table

* sign up data validation

* package updates

* group store init

* Fix home page settings

* group admin init

* group dashboard init

* update deps

* formatting

* bug / added libffi-dev

* pages refactor

* fix mealplan

* docs update

* multi group supporot for job scheduler

* formatting

* formatting

* home-page redesign

* set background for docs darkmode

* code cleanup

* docs refactor

* v0.4.0 image

* mkdocs port change

* formatting

* Fix Meal-Plan Today

* fix webhook bug

* fix meal plan this week

* export users

* 📦 Proper Package + Black Config

* formatting

* delete old files

* fix ci

* fix failing builds

* package/makefile docs update

* add docs server to tasks

* uncomment docker-compose

* reload in dev env

Co-authored-by: hay-kot <hay-kot@pm.me>

* Import/Export Overhall

* basic crud NOT SECURE

* refactor/database init on startup

* added scratch.py

* tests/user CRUD routes

* password hashing

* change app_config location

* bump python version

* formatting

* login ui starter

* change import from url design

* move components

* remove old snackbar

* refactor/Componenet folder structure rework

* refactor/remove old code

* refactor/rename componenets/js files

* remove console.logs

* refactor/ models to schema and sql to models

* new header styling for imports

* token request

* fix url scrapper

* refactor/rename schema files

* split routes file

* redesigned admin page

* enable relative imports for vue components

* refactor/switch to pages view

* add CamelCase package

* majors settings rework

* user management second pass

* super user CRUD

* refactor/consistent models names

* refactor/consistent model names

* password reset

* store refactor

* dependency update

* abstract button props

* profile page refactor

* basic password validation

* login form refactor/split v-container

* remo unused code

* hide editor buttons when not logged in

* mkdocs dev dependency

* v0.4.0 docs update

* profile image upload

* additional token routes

* Smaller recipe cards for smaller viewports

* fix admin sidebar

* add users

* change to outlined

* theme card starter

* code cleanup

* signups

* signup pages

* fix #194

* fix #193

* clarify mealie_port

* fix #184

* fixes #178

* fix blank card error on meal-plan creator

* admin signup

* formatting

* improved search bar

* improved search bar

* refresh token on page refresh

* allow mealplan with no categories

* fix card layout

* remove cdn dependencies

* start on groups

* Fixes #196

* recipe databse refactor

* changelog draft

* database refactoring

* refactor recipe schema/model

* site settings refactor

* continued model refactor

* merge docs changes from master

* site-settings work

* cleanup + tag models

* notes

* typo

* user table

* sign up data validation

* package updates

* group store init

* Fix home page settings

* group admin init

* group dashboard init

* update deps

* formatting

* bug / added libffi-dev

* pages refactor

* fix mealplan

* docs update

* multi group supporot for job scheduler

* formatting

* formatting

* home-page redesign

* set background for docs darkmode

* code cleanup

* docs refactor

* v0.4.0 image

* mkdocs port change

* formatting

* Fix Meal-Plan Today

* fix webhook bug

* fix meal plan this week

* export users

* 📦 Proper Package + Black Config

* formatting

* delete old files

* fix ci

* fix failing builds

* package/makefile docs update

* add docs server to tasks

* uncomment docker-compose

* reload in dev env

* move developer data

* fix upload issue

* run init_db before startup

* import groups and users

* fix themes

* fix theme

* potentially fixes #216

* unlink test db

* potentially fix #217

* localization

* fix import errors on no group

* fix hacky lxml error

* fix import error

Co-authored-by: hay-kot <hay-kot@pm.me>

* Drop FastAPI-Login, add JWT management

* basic crud NOT SECURE

* refactor/database init on startup

* added scratch.py

* tests/user CRUD routes

* password hashing

* change app_config location

* bump python version

* formatting

* login ui starter

* change import from url design

* move components

* remove old snackbar

* refactor/Componenet folder structure rework

* refactor/remove old code

* refactor/rename componenets/js files

* remove console.logs

* refactor/ models to schema and sql to models

* new header styling for imports

* token request

* fix url scrapper

* refactor/rename schema files

* split routes file

* redesigned admin page

* enable relative imports for vue components

* refactor/switch to pages view

* add CamelCase package

* majors settings rework

* user management second pass

* super user CRUD

* refactor/consistent models names

* refactor/consistent model names

* password reset

* store refactor

* dependency update

* abstract button props

* profile page refactor

* basic password validation

* login form refactor/split v-container

* remo unused code

* hide editor buttons when not logged in

* mkdocs dev dependency

* v0.4.0 docs update

* profile image upload

* additional token routes

* Smaller recipe cards for smaller viewports

* fix admin sidebar

* add users

* change to outlined

* theme card starter

* code cleanup

* signups

* signup pages

* fix #194

* fix #193

* clarify mealie_port

* fix #184

* fixes #178

* fix blank card error on meal-plan creator

* admin signup

* formatting

* improved search bar

* improved search bar

* refresh token on page refresh

* allow mealplan with no categories

* fix card layout

* remove cdn dependencies

* start on groups

* Fixes #196

* recipe databse refactor

* changelog draft

* database refactoring

* refactor recipe schema/model

* site settings refactor

* continued model refactor

* merge docs changes from master

* site-settings work

* cleanup + tag models

* notes

* typo

* user table

* sign up data validation

* package updates

* group store init

* Fix home page settings

* group admin init

* group dashboard init

* update deps

* formatting

* bug / added libffi-dev

* pages refactor

* fix mealplan

* docs update

* multi group supporot for job scheduler

* formatting

* formatting

* home-page redesign

* set background for docs darkmode

* code cleanup

* docs refactor

* v0.4.0 image

* mkdocs port change

* formatting

* Fix Meal-Plan Today

* fix webhook bug

* fix meal plan this week

* export users

* 📦 Proper Package + Black Config

* formatting

* delete old files

* fix ci

* fix failing builds

* package/makefile docs update

* add docs server to tasks

* uncomment docker-compose

* reload in dev env

* move developer data

* fix upload issue

* run init_db before startup

* import groups and users

* fix themes

* fix theme

* potentially fixes #216

* unlink test db

* potentially fix #217

* localization

* fix import errors on no group

* fix hacky lxml error

* fix import error

* more import errors

* test failing tests

* fix/test that never really passed

Co-authored-by: hay-kot <hay-kot@pm.me>

* Feature/authentication (#220)

* basic crud NOT SECURE

* refactor/database init on startup

* added scratch.py

* tests/user CRUD routes

* password hashing

* change app_config location

* bump python version

* formatting

* login ui starter

* change import from url design

* move components

* remove old snackbar

* refactor/Componenet folder structure rework

* refactor/remove old code

* refactor/rename componenets/js files

* remove console.logs

* refactor/ models to schema and sql to models

* new header styling for imports

* token request

* fix url scrapper

* refactor/rename schema files

* split routes file

* redesigned admin page

* enable relative imports for vue components

* refactor/switch to pages view

* add CamelCase package

* majors settings rework

* user management second pass

* super user CRUD

* refactor/consistent models names

* refactor/consistent model names

* password reset

* store refactor

* dependency update

* abstract button props

* profile page refactor

* basic password validation

* login form refactor/split v-container

* remo unused code

* hide editor buttons when not logged in

* mkdocs dev dependency

* v0.4.0 docs update

* profile image upload

* additional token routes

* Smaller recipe cards for smaller viewports

* fix admin sidebar

* add users

* change to outlined

* theme card starter

* code cleanup

* signups

* signup pages

* fix #194

* fix #193

* clarify mealie_port

* fix #184

* fixes #178

* fix blank card error on meal-plan creator

* admin signup

* formatting

* improved search bar

* improved search bar

* refresh token on page refresh

* allow mealplan with no categories

* fix card layout

* remove cdn dependencies

* start on groups

* Fixes #196

* recipe databse refactor

* changelog draft

* database refactoring

* refactor recipe schema/model

* site settings refactor

* continued model refactor

* merge docs changes from master

* site-settings work

* cleanup + tag models

* notes

* typo

* user table

* sign up data validation

* package updates

* group store init

* Fix home page settings

* group admin init

* group dashboard init

* update deps

* formatting

* bug / added libffi-dev

* pages refactor

* fix mealplan

* docs update

* multi group supporot for job scheduler

* formatting

* formatting

* home-page redesign

* set background for docs darkmode

* code cleanup

* docs refactor

* v0.4.0 image

* mkdocs port change

* formatting

* Fix Meal-Plan Today

* fix webhook bug

* fix meal plan this week

* export users

* 📦 Proper Package + Black Config

* formatting

* delete old files

* fix ci

* fix failing builds

* package/makefile docs update

* add docs server to tasks

* uncomment docker-compose

* reload in dev env

* move developer data

* fix upload issue

* run init_db before startup

* import groups and users

* fix themes

* fix theme

* potentially fixes #216

* unlink test db

* potentially fix #217

* localization

* fix import errors on no group

* fix hacky lxml error

* fix import error

* more import errors

* test failing tests

* fix/test that never really passed

* pin lxml version

Co-authored-by: hay-kot <hay-kot@pm.me>

* Feature/submit on enter key (#224)

* general cleanup

* submit on enter

* fix signup form

* fix duplicate slugs when testing

Co-authored-by: hay-kot <hay-kot@pm.me>

* Feature/site settings (#225)

* general cleanup

* submit on enter

* fix signup form

* fix duplicate slugs when testing

* custom pages starter

* api start

* functional

* docs

* fix page reload on submit

* set initial selection for category button

* Site Pages Import/Export

* documentation updates

* generate .secret file for jwt hashing

* properly align default passwords

* set default password globally

* set group for signups

Co-authored-by: hay-kot <hay-kot@pm.me>

* feature/secure-routes (#226)

* secure routes

* add token to test routes

* fix duplicate data

Co-authored-by: hay-kot <hay-kot@pm.me>

* feature/password-reset (#227)

* add reset default password

* add warning

* add version tag

* bumb version

* remove old footer

Co-authored-by: hay-kot <hay-kot@pm.me>

* fixes typos and spelling mistakes in de locales &  translates new locales, #124 (#231)

* chore: fixes typos and spelling mistakes in de locales, translates new locales, #124

* fix: uses personal form as in other locales instead of formal form

Co-authored-by: Jonas  Schubert <jonas.schubert.1990@web.de>

* tests/suite-overhall - 83% Coverage

* generate API docs with make file

* documentation

* code-gen scripts

* type() to isinstance()

* code-gen

* fix flake8 problems

* test refactor first pass

* init config

* added help, format, clean and lint

* + flake8 developer dep

* update docs

* proper api imports

* jsconfig

* group tests

* refactor settings to class for testing

* fix env errors

* change tool -> tools

* code cleanup

* sort imports

* add tools test

* lint

Co-authored-by: hay-kot <hay-kot@pm.me>

* General Frontend Bug Fixes for v0.4.0 RC (#233)

* comment

* add frontend-build command

* address #211

* fix margins

* fix import bug

* await user updates

* fix meal-plan filter

* meal-plan search redesign

* improve mobile search

* fix sidebar update

* fix category auto-completes

* draft new pages

* fix tag auto completes

* refactor export const

* dispatch evens for CRUD operations

* recipe loaders screen

* create category dialog

Co-authored-by: hay-kot <hay-kot@pm.me>

* New docs for v0.4.0 (#234)

* spacing

* fix parser bug

* update for v0.4.0

* demo link

* remove gifs

* add organize diagram

* demo code

* remove large gifs

* v0.4.0 changelog

Co-authored-by: hay-kot <hay-kot@pm.me>

* add test.db

* typo

Co-authored-by: kentora <=>
Co-authored-by: Hayden <hay-kot@pm.me>
Co-authored-by: Richard Mitic <richard.h.mitic@gmail.com>
Co-authored-by: kentora <kentora@kentora.dk>
Co-authored-by: David Young <davidy@funkypenguin.co.nz>
Co-authored-by: Bastien <43323819+Batgame@users.noreply.github.com>
Co-authored-by: sephrat <34862846+sephrat@users.noreply.github.com>
Co-authored-by: Nick CJ <17556895+nickcj931@users.noreply.github.com>
Co-authored-by: dekvall <dkvldev@gmail.com>
Co-authored-by: wengtad <wengtad93@gmail.com>
Co-authored-by: Alexei Pesic <pesic.alexei@gmail.com>
Co-authored-by: Andrew <dpieski@gmail.com>
Co-authored-by: Stephen Brown II <Stephen.Brown2@gmail.com>
Co-authored-by: retmas-gh <58191209+retmas-gh@users.noreply.github.com>
Co-authored-by: mindesbunister <32161838+mindesbunister@users.noreply.github.com>
Co-authored-by: Raghnarok05 <77641728+Raghnarok05@users.noreply.github.com>
Co-authored-by: Andreas Waschinski <an.andreas+github@posteo.de>
Co-authored-by: Bernhard Großer <30469627+boerniee@users.noreply.github.com>
Co-authored-by: Andreas Waschinski <an.andreas@posteo.de>
Co-authored-by: JonasSchubert <jonas.schubert.projects@web.de>
Co-authored-by: Jonas  Schubert <jonas.schubert.1990@web.de>
2021-03-31 07:20:35 -08:00

500 lines
164 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html class="no-touch blocks-touchscreen-disabled b-reith-sans-font b-reith-serif-font b-pw-1280" lang="en">
<head>
<link rel='preconnect' href='//nav.files.bbci.co.uk' crossorigin />
<link rel='preconnect' href='//mybbc.files.bbci.co.uk' />
<link rel='preconnect' href='//fig.bbc.co.uk' />
<link rel='preconnect' href='//mvt.api.bbc.com' />
<link rel='preconnect' href='//idcta.api.bbc.co.uk' />
<link rel='preconnect' href='//ichef.bbci.co.uk' />
<link rel='preconnect' href='//static.chartbeat.com' />
<link rel='preconnect' href='//ping.chartbeat.net' />
<link rel='preconnect' href='//sa.bbc.co.uk' />
<link data-chunk="main" rel="preload" as="style" href="https://food.files.bbci.co.uk/kandl-food/3061/css/styles.css">
<link data-chunk="main" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/styles.37ede912.js">
<link data-chunk="main" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/32.6e5f44c3.js">
<link data-chunk="main" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/main.53a9cde2.js">
<link data-chunk="page-PageIndex" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/3.92ceca67.js">
<link data-chunk="page-PageIndex" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/page-PageIndex.683b570a.js">
<link data-chunk="recipe-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/33.3f10678a.js">
<link data-chunk="recipe-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/4.686b4fe8.js">
<link data-chunk="recipe-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/recipe-Page.e1fe35bd.js">
<link data-chunk="foods-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/1.fde4b609.js">
<link data-chunk="foods-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/2.332dabe4.js">
<link data-chunk="foods-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/foods-Page.998f6d0a.js">
<link data-chunk="articlePage-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/articlePage-Page.db0230c4.js">
<link data-chunk="search-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/search-Page.0eacfd3f.js">
<link data-chunk="home-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/home-Page.3d04aff5.js">
<link data-chunk="collections-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/collections-Page.c062f0a2.js">
<link data-chunk="programme-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/programme-Page.4380eb0b.js">
<link data-chunk="indexPage-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/indexPage-Page.51745313.js">
<link data-chunk="occasion-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/occasion-Page.fe02f747.js">
<link data-chunk="collection-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/collection-Page.f794476d.js">
<link data-chunk="favourite-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/favourite-Page.b33e769b.js">
<link data-chunk="recipes-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/recipes-Page.7ab7e73f.js">
<link data-chunk="chef-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/chef-Page.8c9d781a.js">
<link data-chunk="shoppingList-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/shoppingList-Page.c473a8f6.js">
<link data-chunk="azPage-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/azPage-Page.b70f6e71.js">
<link data-chunk="technique-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/technique-Page.ba705e33.js">
<link data-chunk="occasions-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/occasions-Page.1093ad11.js">
<link data-chunk="programmes-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/programmes-Page.17ce6f84.js">
<link data-chunk="menu-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/menu-Page.3e797403.js">
<link data-chunk="articles-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/articles-Page.19814dd6.js">
<link data-chunk="techniques-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/techniques-Page.7faf7a43.js">
<link data-chunk="cuisine-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/cuisine-Page.0e6ff6ed.js">
<link data-chunk="season-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/season-Page.3a2ac655.js">
<link data-chunk="menu-shoppingList-Page" rel="preload" as="script" href="https://food.files.bbci.co.uk/kandl-food/3061/javascript/menu-shoppingList-Page.502b2b3b.js">
<link data-chunk="main" rel="stylesheet" href="https://food.files.bbci.co.uk/kandl-food/3061/css/styles.css">
<script src="https://static.files.bbci.co.uk/orbit/7ba98e3db9d415f8cbdb0978bf084f9e/js/require.min.js"></script>
<link rel="stylesheet" href="https://static.files.bbci.co.uk/orbit/7ba98e3db9d415f8cbdb0978bf084f9e/css/orb-ltr.min.css">
<!-- Orbit: 3.0.0-1332.d879cc96 -->
<!-- Environment: live -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
// nav-orbit-pollyfills
// Promise polyfill from https://github.com/bramstein/promis
(function(){'use strict';var f,g=[];function l(a){g.push(a);1==g.length&&f()}function m(){for(;g.length;)g[0](),g.shift()}f=function(){setTimeout(m)};function n(a){this.a=p;this.b=void 0;this.f=[];var b=this;try{a(function(a){q(b,a)},function(a){r(b,a)})}catch(c){r(b,c)}}var p=2;function t(a){return new n(function(b,c){c(a)})}function u(a){return new n(function(b){b(a)})}function q(a,b){if(a.a==p){if(b==a)throw new TypeError;var c=!1;try{var d=b&&b.then;if(null!=b&&"object"==typeof b&&"function"==typeof d){d.call(b,function(b){c||q(a,b);c=!0},function(b){c||r(a,b);c=!0});return}}catch(e){c||r(a,e);return}a.a=0;a.b=b;v(a)}} function r(a,b){if(a.a==p){if(b==a)throw new TypeError;a.a=1;a.b=b;v(a)}}function v(a){l(function(){if(a.a!=p)for(;a.f.length;){var b=a.f.shift(),c=b[0],d=b[1],e=b[2],b=b[3];try{0==a.a?"function"==typeof c?e(c.call(void 0,a.b)):e(a.b):1==a.a&&("function"==typeof d?e(d.call(void 0,a.b)):b(a.b))}catch(h){b(h)}}})}n.prototype.g=function(a){return this.c(void 0,a)};n.prototype.c=function(a,b){var c=this;return new n(function(d,e){c.f.push([a,b,d,e]);v(c)})}; function w(a){return new n(function(b,c){function d(c){return function(d){h[c]=d;e+=1;e==a.length&&b(h)}}var e=0,h=[];0==a.length&&b(h);for(var k=0;k<a.length;k+=1)u(a[k]).c(d(k),c)})}function x(a){return new n(function(b,c){for(var d=0;d<a.length;d+=1)u(a[d]).c(b,c)})};window.Promise||(window.Promise=n,window.Promise.resolve=u,window.Promise.reject=t,window.Promise.race=x,window.Promise.all=w,window.Promise.prototype.then=n.prototype.c,window.Promise.prototype["catch"]=n.prototype.g);}());
// Polyfill Event constructor for IE ref: https://jira.dev.bbc.co.uk/browse/ORBITEN-919
// see: https://stackoverflow.com/questions/26596123
(function () {
if (typeof window.CustomEvent === "function") {
return false;
}
function CustomEvent(event, params) {
params = params || { bubbles: false, cancelable: false, detail: undefined };
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
}
CustomEvent.prototype = window.Event.prototype;
window.Event = CustomEvent;
})();
//Element.prototype.matches polyfill
//from https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill
if (!Element.prototype.matches) {
Element.prototype.matches = Element.prototype.msMatchesSelector ||
Element.prototype.webkitMatchesSelector;
}
//NodeList.forEach Polyfill
//from https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach#Polyfill
if (window.NodeList && !NodeList.prototype.forEach) {
NodeList.prototype.forEach = Array.prototype.forEach;
}
// Object.assign polyfill from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill
if (typeof Object.assign != 'function') {
// Must be writable: true, enumerable: false, configurable: true
Object.defineProperty(Object, "assign", {
value: function assign(target, varArgs) { // .length of function is 2
'use strict';
if (target == null) { // TypeError if undefined or null
throw new TypeError('Cannot convert undefined or null to object');
}
var to = Object(target);
for (var index = 1; index < arguments.length; index++) {
var nextSource = arguments[index];
if (nextSource != null) { // Skip over if undefined or null
for (var nextKey in nextSource) {
// Avoid bugs when hasOwnProperty is shadowed
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
}
}
}
return to;
},
writable: true,
configurable: true
});
}
// window.fetch polyfill https://github.com/github/fetch/blob/v0.11.0/fetch.js - chosen for IE9 compatibility
if(typeof window.fetch !== 'function') {
(function(self){"use strict";if(self.fetch){return}function normalizeName(name){if(typeof name!=="string"){name=String(name)}if(/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)){throw new TypeError("Invalid character in header field name")}return name.toLowerCase()}function normalizeValue(value){if(typeof value!=="string"){value=String(value)}return value}function Headers(headers){this.map={};if(headers instanceof Headers){headers.forEach(function(value,name){this.append(name,value)},this)}else if(headers){Object.getOwnPropertyNames(headers).forEach(function(name){this.append(name,headers[name])},this)}}Headers.prototype.append=function(name,value){name=normalizeName(name);value=normalizeValue(value);var list=this.map[name];if(!list){list=[];this.map[name]=list}list.push(value)};Headers.prototype["delete"]=function(name){delete this.map[normalizeName(name)]};Headers.prototype.get=function(name){var values=this.map[normalizeName(name)];return values?values[0]:null};Headers.prototype.getAll=function(name){return this.map[normalizeName(name)]||[]};Headers.prototype.has=function(name){return this.map.hasOwnProperty(normalizeName(name))};Headers.prototype.set=function(name,value){this.map[normalizeName(name)]=[normalizeValue(value)]};Headers.prototype.forEach=function(callback,thisArg){Object.getOwnPropertyNames(this.map).forEach(function(name){this.map[name].forEach(function(value){callback.call(thisArg,value,name,this)},this)},this)};function consumed(body){if(body.bodyUsed){return Promise.reject(new TypeError("Already read"))}body.bodyUsed=true}function fileReaderReady(reader){return new Promise(function(resolve,reject){reader.onload=function(){resolve(reader.result)};reader.onerror=function(){reject(reader.error)}})}function readBlobAsArrayBuffer(blob){var reader=new FileReader;reader.readAsArrayBuffer(blob);return fileReaderReady(reader)}function readBlobAsText(blob){var reader=new FileReader;reader.readAsText(blob);return fileReaderReady(reader)}var support={blob:"FileReader"in self&&"Blob"in self&&function(){try{new Blob;return true}catch(e){return false}}(),formData:"FormData"in self,arrayBuffer:"ArrayBuffer"in self};function Body(){this.bodyUsed=false;this._initBody=function(body){this._bodyInit=body;if(typeof body==="string"){this._bodyText=body}else if(support.blob&&Blob.prototype.isPrototypeOf(body)){this._bodyBlob=body}else if(support.formData&&FormData.prototype.isPrototypeOf(body)){this._bodyFormData=body}else if(!body){this._bodyText=""}else if(support.arrayBuffer&&ArrayBuffer.prototype.isPrototypeOf(body)){}else{throw new Error("unsupported BodyInit type")}if(!this.headers.get("content-type")){if(typeof body==="string"){this.headers.set("content-type","text/plain;charset=UTF-8")}else if(this._bodyBlob&&this._bodyBlob.type){this.headers.set("content-type",this._bodyBlob.type)}}};if(support.blob){this.blob=function(){var rejected=consumed(this);if(rejected){return rejected}if(this._bodyBlob){return Promise.resolve(this._bodyBlob)}else if(this._bodyFormData){throw new Error("could not read FormData body as blob")}else{return Promise.resolve(new Blob([this._bodyText]))}};this.arrayBuffer=function(){return this.blob().then(readBlobAsArrayBuffer)};this.text=function(){var rejected=consumed(this);if(rejected){return rejected}if(this._bodyBlob){return readBlobAsText(this._bodyBlob)}else if(this._bodyFormData){throw new Error("could not read FormData body as text")}else{return Promise.resolve(this._bodyText)}}}else{this.text=function(){var rejected=consumed(this);return rejected?rejected:Promise.resolve(this._bodyText)}}if(support.formData){this.formData=function(){return this.text().then(decode)}}this.json=function(){return this.text().then(JSON.parse)};return this}var methods=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];function normalizeMethod(method){var upcased=method.toUpperCase();return methods.indexOf(upcased)>-1?upcased:method}function Request(input,options){options=options||{};var body=options.body;if(Request.prototype.isPrototypeOf(input)){if(input.bodyUsed){throw new TypeError("Already read")}this.url=input.url;this.credentials=input.credentials;if(!options.headers){this.headers=new Headers(input.headers)}this.method=input.method;this.mode=input.mode;if(!body){body=input._bodyInit;input.bodyUsed=true}}else{this.url=input}this.credentials=options.credentials||this.credentials||"omit";if(options.headers||!this.headers){this.headers=new Headers(options.headers)}this.method=normalizeMethod(options.method||this.method||"GET");this.mode=options.mode||this.mode||null;this.referrer=null;if((this.method==="GET"||this.method==="HEAD")&&body){throw new TypeError("Body not allowed for GET or HEAD requests")}this._initBody(body)}Request.prototype.clone=function(){return new Request(this)};function decode(body){var form=new FormData;body.trim().split("&").forEach(function(bytes){if(bytes){var split=bytes.split("=");var name=split.shift().replace(/\+/g," ");var value=split.join("=").replace(/\+/g," ");form.append(decodeURIComponent(name),decodeURIComponent(value))}});return form}function headers(xhr){var head=new Headers;var pairs=xhr.getAllResponseHeaders().trim().split("\n");pairs.forEach(function(header){var split=header.trim().split(":");var key=split.shift().trim();var value=split.join(":").trim();head.append(key,value)});return head}Body.call(Request.prototype);function Response(bodyInit,options){if(!options){options={}}this.type="default";this.status=options.status;this.ok=this.status>=200&&this.status<300;this.statusText=options.statusText;this.headers=options.headers instanceof Headers?options.headers:new Headers(options.headers);this.url=options.url||"";this._initBody(bodyInit)}Body.call(Response.prototype);Response.prototype.clone=function(){return new Response(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new Headers(this.headers),url:this.url})};Response.error=function(){var response=new Response(null,{status:0,statusText:""});response.type="error";return response};var redirectStatuses=[301,302,303,307,308];Response.redirect=function(url,status){if(redirectStatuses.indexOf(status)===-1){throw new RangeError("Invalid status code")}return new Response(null,{status:status,headers:{location:url}})};self.Headers=Headers;self.Request=Request;self.Response=Response;self.fetch=function(input,init){return new Promise(function(resolve,reject){var request;if(Request.prototype.isPrototypeOf(input)&&!init){request=input}else{request=new Request(input,init)}var xhr=new XMLHttpRequest;function responseURL(){if("responseURL"in xhr){return xhr.responseURL}if(/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())){return xhr.getResponseHeader("X-Request-URL")}return}xhr.onload=function(){var status=xhr.status===1223?204:xhr.status;if(status<100||status>599){reject(new TypeError("Network request failed"));return}var options={status:status,statusText:xhr.statusText,headers:headers(xhr),url:responseURL()};var body="response"in xhr?xhr.response:xhr.responseText;resolve(new Response(body,options))};xhr.onerror=function(){reject(new TypeError("Network request failed"))};xhr.open(request.method,request.url,true);if(request.credentials==="include"){xhr.withCredentials=true}if("responseType"in xhr&&support.blob){xhr.responseType="blob"}request.headers.forEach(function(value,name){xhr.setRequestHeader(name,value)});xhr.send(typeof request._bodyInit==="undefined"?null:request._bodyInit)})};self.fetch.polyfill=true})(typeof self!=="undefined"?self:this);
}
if (typeof window.CustomEvent !== 'function') {
function CustomEvent(event, params) {
params = params || { bubbles: false, cancelable: false, detail: null };
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
}
CustomEvent.prototype = window.Event.prototype;
window.CustomEvent = CustomEvent;
}
</script>
<script>
window.orbitData = {};
var additionalPageProperties = {};
window.orbitData.partialCookieOvenUrl = 'https://cookie-oven.api.bbc';
window.orbitData.language = 'en';
window.orbitData.language = 'en';
window.orbitData.userProfileUrl = "https://www.bbc.co.uk/userprofile";
window.orbitData.modal = false;
function generateCountername() {
if (window.location.protocol === 'file:') {
return 'local.file';
}
var pathName = window.location.pathname
.replace(/\/$/, "")
.replace(/^\//, "")
.replace(/\//g, '.');
return pathName + '.page';
}
window.orbitData.page = {
name: 'food.recipes.healthy_pasta_bake_60759.page' || generateCountername(),
destination: 'FOOD' || null,
producer: 'FOOD' || null,
section: 'Recipes' || null,
site: '' || null,
contentId: 'urn:bbc:food:recipes.healthy_pasta_bake_60759' || null,
contentType: 'article' || null,
edition: 'domestic' || null,
additionalProperties: additionalPageProperties
};
window.orbitData.user = {
'X-Country': "se",
'X-Ip_is_uk_combined': "",
'X-Ip_is_advertise_combined': ""
}
window.orb = {
worldwideNavlinks: '<li class="orb-nav-homedotcom"><a href="https://www.bbc.com/">Home</a></li><li class="orb-nav-newsdotcom"><a href="https://www.bbc.com/news">News</a></li><li class="orb-nav-sport"><a href="https://www.bbc.com/sport">Sport</a></li><li class="orb-nav-reeldotcom"><a href="https://www.bbc.com/reel">Reel</a></li><li class="orb-nav-worklife"><a href="https://www.bbc.com/worklife">Worklife</a></li><li class="orb-nav-traveldotcom"><a href="https://www.bbc.com/travel">Travel</a></li><li class="orb-nav-future"><a href="https://www.bbc.com/future">Future</a></li><li class="orb-nav-culture"><a href="https://www.bbc.com/culture">Culture</a></li><li class="orb-nav-music"><a href="https://www.bbc.com/culture/music">Music</a></li><li class="orb-nav-tv"><a href="https://www.bbc.co.uk/schedules/p00fzl9m">TV</a></li><li class="orb-nav-weather"><a href="https://www.bbc.com/weather">Weather</a></li><li class="orb-nav-sounds"><a href="https://www.bbc.co.uk/sounds">Sounds</a></li>',
}
function updatePageData(newData) {
window.orbitData.page = Object.assign(window.orbitData.page, newData);
}
document.addEventListener('bbc-page-reset', function(event) {
if (event.detail && event.detail.page) {
updatePageData(event.detail.page);
}
document.dispatchEvent(new Event('bbc-page-updated'));
});
</script>
<script type='text/javascript'>!function(){var t={1391:function(t){var r={getName:function(){return Promise.resolve(window.orbitData.page.name)},getLanguage:function(){return Promise.resolve(window.orbitData.language)},getDestination:function(){return Promise.resolve(window.orbitData.page.destination)},getProducer:function(){return Promise.resolve(window.orbitData.page.producer)},getSection:function(){return Promise.resolve(window.orbitData.page.section)},getContentType:function(){return Promise.resolve(window.orbitData.page.contentType)},getContentId:function(){return Promise.resolve(window.orbitData.page.contentId)},getReferrer:function(){return Promise.resolve(window.orb&&null!==window.orb.referrer&&void 0!==window.orb.referrer?window.orb.referrer:document.referrer)},getAdditionalProperties:function(){return Promise.resolve(window.orbitData.page.additionalProperties)},loadCSS:function(t){return new Promise((function(r,e){var n=document.createElement("link");n.type="text/css",n.rel="stylesheet",n.onload=function(){r()},n.href=t,document.getElementsByTagName("head")[0].appendChild(n)}))},isModal:function(){return Promise.resolve(window.orbitData.modal)}};window.bbcpage=r,t.exports={bbcpage:r}},9135:function(t){function r(t){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function e(t,r){if(!(t instanceof r))throw new TypeError("Cannot call a class as a function")}function n(t,e){return!e||"object"!==r(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function o(t){var r="function"==typeof Map?new Map:void 0;return(o=function(t){if(null===t||(e=t,-1===Function.toString.call(e).indexOf("[native code]")))return t;var e;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==r){if(r.has(t))return r.get(t);r.set(t,n)}function n(){return i(t,arguments,c(this).constructor)}return n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),a(n,t)})(t)}function i(t,r,e){return(i=u()?Reflect.construct:function(t,r,e){var n=[null];n.push.apply(n,r);var o=new(Function.bind.apply(t,n));return e&&a(o,e.prototype),o}).apply(null,arguments)}function u(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}function a(t,r){return(a=Object.setPrototypeOf||function(t,r){return t.__proto__=r,t})(t,r)}function c(t){return(c=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var s=function(t){!function(t,r){if("function"!=typeof r&&null!==r)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(r&&r.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),r&&a(t,r)}(s,t);var r,o,i=(r=s,o=u(),function(){var t,e=c(r);if(o){var i=c(this).constructor;t=Reflect.construct(e,arguments,i)}else t=e.apply(this,arguments);return n(this,t)});function s(){return e(this,s),i.apply(this,arguments)}return s}(o(Error));function f(t){return new Promise((function(r,e){window.require(t,(function(){r.apply(this,arguments)}),(function(t){e(t)}))}))}var l,p=null;function h(){if(window.orbitData&&window.orbitData.user&&["X-Country","X-Ip_is_advertise_combined","X-Ip_is_uk_combined"].every((function(t){return!!window.orbitData.user[t]})))return Promise.resolve(window.orbitData.user);if(!p){var t=window.location.hostname.endsWith(".com")?"com":"co.uk";p=fetch("https://www.bbc.".concat(t,"/userinfo")).then((function(t){return t.json()}))}return p}function d(t){if(t.status>=200&&t.status<300)return t;var r=new Error(t.statusText);throw r.response=t,r}function v(t){return t.json()}function y(){if(window.orbitData.user&&window.orbitData.user.ageBand)return Promise.resolve(window.orbitData.user);if(!l){if("undefined"==typeof XMLHttpRequest||!("withCredentials"in new XMLHttpRequest))return Promise.resolve(window.orbitData.user);l=f(["idcta-v2/idcta-1"]).then((function(t){return t.initiateTokenRefresh().then((function(){return window.fetch(window.orbitData.userProfileUrl,{credentials:"include"}).then(d).then(v).then((function(t){return void 0===window.orbitData.user?window.orbitData.user=t:Object.assign(window.orbitData.user,t),window.orbitData.user}))}))}))}return l}var g={getHashedId:function(){return f(["idcta-v2/idcta-1"]).then((function(t){return t.getCookieInstance().getHidFromCookie()}))},isSignedIn:function(){return f(["idcta-v2/idcta-1"]).then((function(t){return t&&t.getCookieInstance().hasCookie()}))},getCountry:function(){return h().then((function(t){return t["X-Country"]||"gb"}))},isUKCombined:function(){return h().then((function(t){if(!t["X-Ip_is_uk_combined"])throw new s("missing isUKCombined from userinfo response");return"yes"===t["X-Ip_is_uk_combined"].toLowerCase()}))},canSeeAdverts:function(){return h().then((function(t){if(!t["X-Ip_is_advertise_combined"])throw new s("missing canSeeAdverts from userinfo response");return"yes"===t["X-Ip_is_advertise_combined"].toLowerCase()}))},getAgeBand:function(){return h().then((function(t){return t["X-Age-Band"]?Promise.resolve(t["X-Age-Band"]):g.isSignedIn().then((function(r){if(r)return y().then((function(r){return t["X-Age-Band"]=r["X-Age-Band"],t["X-Age-Band"]||void 0})).catch((function(r){return t["X-Age-Band"]||void 0}))}))}))},allowsPerformanceCookies:function(){return f(["orb/cookies"]).then((function(t){return!!t.cookiesEnabled()&&!!t.readPolicy("performance")}))},allowsFunctionalCookies:function(){return f(["orb/cookies"]).then((function(t){return!!t.cookiesEnabled()&&!!t.readPolicy("personalisation")}))},getCookieValue:function(t){return f(["orb/cookies"]).then((function(r){return r.get(t)}))}};window.bbcuser=g,t.exports={bbcuser:g,BBCUserError:s}},7633:function(t,r,e){e(1539),e(8783),e(3948),e(8674),e(7922),e(7727);var n=e(857);t.exports=n.Promise},1111:function(t,r,e){e(4916),e(4953),e(8992),e(9841),e(7852),e(2023),e(4723),e(6373),e(6528),e(3112),e(2481),e(5306),e(4765),e(3123),e(3157),e(3210),e(5674),e(8702),e(8783),e(5218),e(4475),e(7929),e(915),e(9253),e(2125),e(8830),e(8734),e(9254),e(7268),e(7397),e(86),e(623);var n=e(857);t.exports=n.String},3099:function(t){t.exports=function(t){if("function"!=typeof t)throw TypeError(String(t)+" is not a function");return t}},6077:function(t,r,e){var n=e(111);t.exports=function(t){if(!n(t)&&null!==t)throw TypeError("Can't set "+String(t)+" as a prototype");return t}},1223:function(t,r,e){var n=e(5112),o=e(30),i=e(3070),u=n("unscopables"),a=Array.prototype;null==a[u]&&i.f(a,u,{configurable:!0,value:o(null)}),t.exports=function(t){a[u][t]=!0}},1530:function(t,r,e){"use strict";var n=e(8710).charAt;t.exports=function(t,r,e){return r+(e?n(t,r).length:1)}},5787:function(t){t.exports=function(t,r,e){if(!(t instanceof r))throw TypeError("Incorrect "+(e?e+" ":"")+"invocation");return t}},9670:function(t,r,e){var n=e(111);t.exports=function(t){if(!n(t))throw TypeError(String(t)+" is not an object");return t}},1318:function(t,r,e){var n=e(5656),o=e(7466),i=e(1400),u=function(t){return function(r,e,u){var a,c=n(r),s=o(c.length),f=i(u,s);if(t&&e!=e){for(;s>f;)if((a=c[f++])!=a)return!0}else for(;s>f;f++)if((t||f in c)&&c[f]===e)return t||f||0;return!t&&-1}};t.exports={includes:u(!0),indexOf:u(!1)}},3411:function(t,r,e){var n=e(9670);t.exports=function(t,r,e,o){try{return o?r(n(e)[0],e[1]):r(e)}catch(r){var i=t.return;throw void 0!==i&&n(i.call(t)),r}}},7072:function(t,r,e){var n=e(5112)("iterator"),o=!1;try{var i=0,u={next:function(){return{done:!!i++}},return:function(){o=!0}};u[n]=function(){return this},Array.from(u,(function(){throw 2}))}catch(t){}t.exports=function(t,r){if(!r&&!o)return!1;var e=!1;try{var i={};i[n]=function(){return{next:function(){return{done:e=!0}}}},t(i)}catch(t){}return e}},4326:function(t){var r={}.toString;t.exports=function(t){return r.call(t).slice(8,-1)}},648:function(t,r,e){var n=e(1694),o=e(4326),i=e(5112)("toStringTag"),u="Arguments"==o(function(){return arguments}());t.exports=n?o:function(t){var r,e,n;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(e=function(t,r){try{return t[r]}catch(t){}}(r=Object(t),i))?e:u?o(r):"Object"==(n=o(r))&&"function"==typeof r.callee?"Arguments":n}},9920:function(t,r,e){var n=e(6656),o=e(3887),i=e(1236),u=e(3070);t.exports=function(t,r){for(var e=o(r),a=u.f,c=i.f,s=0;s<e.length;s++){var f=e[s];n(t,f)||a(t,f,c(r,f))}}},4964:function(t,r,e){var n=e(5112)("match");t.exports=function(t){var r=/./;try{"/./"[t](r)}catch(e){try{return r[n]=!1,"/./"[t](r)}catch(t){}}return!1}},8544:function(t,r,e){var n=e(7293);t.exports=!n((function(){function t(){}return t.prototype.constructor=null,Object.getPrototypeOf(new t)!==t.prototype}))},4230:function(t,r,e){var n=e(4488),o=/"/g;t.exports=function(t,r,e,i){var u=String(n(t)),a="<"+r;return""!==e&&(a+=" "+e+'="'+String(i).replace(o,"&quot;")+'"'),a+">"+u+"</"+r+">"}},4994:function(t,r,e){"use strict";var n=e(3383).IteratorPrototype,o=e(30),i=e(9114),u=e(8003),a=e(7497),c=function(){return this};t.exports=function(t,r,e){var s=r+" Iterator";return t.prototype=o(n,{next:i(1,e)}),u(t,s,!1,!0),a[s]=c,t}},8880:function(t,r,e){var n=e(9781),o=e(3070),i=e(9114);t.exports=n?function(t,r,e){return o.f(t,r,i(1,e))}:function(t,r,e){return t[r]=e,t}},9114:function(t){t.exports=function(t,r){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:r}}},654:function(t,r,e){"use strict";var n=e(2109),o=e(4994),i=e(9518),u=e(7674),a=e(8003),c=e(8880),s=e(1320),f=e(5112),l=e(1913),p=e(7497),h=e(3383),d=h.IteratorPrototype,v=h.BUGGY_SAFARI_ITERATORS,y=f("iterator"),g="keys",b="values",m="entries",w=function(){return this};t.exports=function(t,r,e,f,h,x,S){o(e,r,f);var E,_,O,T=function(t){if(t===h&&R)return R;if(!v&&t in A)return A[t];switch(t){case g:case b:case m:return function(){return new e(this,t)}}return function(){return new e(this)}},P=r+" Iterator",j=!1,A=t.prototype,I=A[y]||A["@@iterator"]||h&&A[h],R=!v&&I||T(h),L="Array"==r&&A.entries||I;if(L&&(E=i(L.call(new t)),d!==Object.prototype&&E.next&&(l||i(E)===d||(u?u(E,d):"function"!=typeof E[y]&&c(E,y,w)),a(E,P,!0,!0),l&&(p[P]=w))),h==b&&I&&I.name!==b&&(j=!0,R=function(){return I.call(this)}),l&&!S||A[y]===R||c(A,y,R),p[r]=R,h)if(_={values:T(b),keys:x?R:T(g),entries:T(m)},S)for(O in _)(v||j||!(O in A))&&s(A,O,_[O]);else n({target:r,proto:!0,forced:v||j},_);return _}},9781:function(t,r,e){var n=e(7293);t.exports=!n((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},317:function(t,r,e){var n=e(7854),o=e(111),i=n.document,u=o(i)&&o(i.createElement);t.exports=function(t){return u?i.createElement(t):{}}},8324:function(t){t.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},6833:function(t,r,e){var n=e(8113);t.exports=/(iphone|ipod|ipad).*applewebkit/i.test(n)},8113:function(t,r,e){var n=e(5005);t.exports=n("navigator","userAgent")||""},7392:function(t,r,e){var n,o,i=e(7854),u=e(8113),a=i.process,c=a&&a.versions,s=c&&c.v8;s?o=(n=s.split("."))[0]+n[1]:u&&(!(n=u.match(/Edge\/(\d+)/))||n[1]>=74)&&(n=u.match(/Chrome\/(\d+)/))&&(o=n[1]),t.exports=o&&+o},748:function(t){t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},2109:function(t,r,e){var n=e(7854),o=e(1236).f,i=e(8880),u=e(1320),a=e(3505),c=e(9920),s=e(4705);t.exports=function(t,r){var e,f,l,p,h,d=t.target,v=t.global,y=t.stat;if(e=v?n:y?n[d]||a(d,{}):(n[d]||{}).prototype)for(f in r){if(p=r[f],l=t.noTargetGet?(h=o(e,f))&&h.value:e[f],!s(v?f:d+(y?".":"#")+f,t.forced)&&void 0!==l){if(typeof p==typeof l)continue;c(p,l)}(t.sham||l&&l.sham)&&i(p,"sham",!0),u(e,f,p,t)}}},7293:function(t){t.exports=function(t){try{return!!t()}catch(t){return!0}}},7007:function(t,r,e){"use strict";e(4916);var n=e(1320),o=e(7293),i=e(5112),u=e(2261),a=e(8880),c=i("species"),s=!o((function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$<a>")})),f="$0"==="a".replace(/./,"$0"),l=i("replace"),p=!!/./[l]&&""===/./[l]("a","$0"),h=!o((function(){var t=/(?:)/,r=t.exec;t.exec=function(){return r.apply(this,arguments)};var e="ab".split(t);return 2!==e.length||"a"!==e[0]||"b"!==e[1]}));t.exports=function(t,r,e,l){var d=i(t),v=!o((function(){var r={};return r[d]=function(){return 7},7!=""[t](r)})),y=v&&!o((function(){var r=!1,e=/a/;return"split"===t&&((e={}).constructor={},e.constructor[c]=function(){return e},e.flags="",e[d]=/./[d]),e.exec=function(){return r=!0,null},e[d](""),!r}));if(!v||!y||"replace"===t&&(!s||!f||p)||"split"===t&&!h){var g=/./[d],b=e(d,""[t],(function(t,r,e,n,o){return r.exec===u?v&&!o?{done:!0,value:g.call(r,e,n)}:{done:!0,value:t.call(e,r,n)}:{done:!1}}),{REPLACE_KEEPS_$0:f,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:p}),m=b[0],w=b[1];n(String.prototype,t,m),n(RegExp.prototype,d,2==r?function(t,r){return w.call(t,this,r)}:function(t){return w.call(t,this)})}l&&a(RegExp.prototype[d],"sham",!0)}},9974:function(t,r,e){var n=e(3099);t.exports=function(t,r,e){if(n(t),void 0===r)return t;switch(e){case 0:return function(){return t.call(r)};case 1:return function(e){return t.call(r,e)};case 2:return function(e,n){return t.call(r,e,n)};case 3:return function(e,n,o){return t.call(r,e,n,o)}}return function(){return t.apply(r,arguments)}}},5005:function(t,r,e){var n=e(857),o=e(7854),i=function(t){return"function"==typeof t?t:void 0};t.exports=function(t,r){return arguments.length<2?i(n[t])||i(o[t]):n[t]&&n[t][r]||o[t]&&o[t][r]}},1246:function(t,r,e){var n=e(648),o=e(7497),i=e(5112)("iterator");t.exports=function(t){if(null!=t)return t[i]||t["@@iterator"]||o[n(t)]}},7854:function(t,r,e){var n=function(t){return t&&t.Math==Math&&t};t.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof e.g&&e.g)||Function("return this")()},6656:function(t){var r={}.hasOwnProperty;t.exports=function(t,e){return r.call(t,e)}},3501:function(t){t.exports={}},842:function(t,r,e){var n=e(7854);t.exports=function(t,r){var e=n.console;e&&e.error&&(1===arguments.length?e.error(t):e.error(t,r))}},490:function(t,r,e){var n=e(5005);t.exports=n("document","documentElement")},4664:function(t,r,e){var n=e(9781),o=e(7293),i=e(317);t.exports=!n&&!o((function(){return 7!=Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},8361:function(t,r,e){var n=e(7293),o=e(4326),i="".split;t.exports=n((function(){return!Object("z").propertyIsEnumerable(0)}))?function(t){return"String"==o(t)?i.call(t,""):Object(t)}:Object},2788:function(t,r,e){var n=e(5465),o=Function.toString;"function"!=typeof n.inspectSource&&(n.inspectSource=function(t){return o.call(t)}),t.exports=n.inspectSource},9909:function(t,r,e){var n,o,i,u=e(8536),a=e(7854),c=e(111),s=e(8880),f=e(6656),l=e(6200),p=e(3501),h=a.WeakMap;if(u){var d=new h,v=d.get,y=d.has,g=d.set;n=function(t,r){return g.call(d,t,r),r},o=function(t){return v.call(d,t)||{}},i=function(t){return y.call(d,t)}}else{var b=l("state");p[b]=!0,n=function(t,r){return s(t,b,r),r},o=function(t){return f(t,b)?t[b]:{}},i=function(t){return f(t,b)}}t.exports={set:n,get:o,has:i,enforce:function(t){return i(t)?o(t):n(t,{})},getterFor:function(t){return function(r){var e;if(!c(r)||(e=o(r)).type!==t)throw TypeError("Incompatible receiver, "+t+" required");return e}}}},7659:function(t,r,e){var n=e(5112),o=e(7497),i=n("iterator"),u=Array.prototype;t.exports=function(t){return void 0!==t&&(o.Array===t||u[i]===t)}},4705:function(t,r,e){var n=e(7293),o=/#|\.prototype\./,i=function(t,r){var e=a[u(t)];return e==s||e!=c&&("function"==typeof r?n(r):!!r)},u=i.normalize=function(t){return String(t).replace(o,".").toLowerCase()},a=i.data={},c=i.NATIVE="N",s=i.POLYFILL="P";t.exports=i},111:function(t){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},1913:function(t){t.exports=!1},7850:function(t,r,e){var n=e(111),o=e(4326),i=e(5112)("match");t.exports=function(t){var r;return n(t)&&(void 0!==(r=t[i])?!!r:"RegExp"==o(t))}},408:function(t,r,e){var n=e(9670),o=e(7659),i=e(7466),u=e(9974),a=e(1246),c=e(3411),s=function(t,r){this.stopped=t,this.result=r};(t.exports=function(t,r,e,f,l){var p,h,d,v,y,g,b,m=u(r,e,f?2:1);if(l)p=t;else{if("function"!=typeof(h=a(t)))throw TypeError("Target is not iterable");if(o(h)){for(d=0,v=i(t.length);v>d;d++)if((y=f?m(n(b=t[d])[0],b[1]):m(t[d]))&&y instanceof s)return y;return new s(!1)}p=h.call(t)}for(g=p.next;!(b=g.call(p)).done;)if("object"==typeof(y=c(p,m,b.value,f))&&y&&y instanceof s)return y;return new s(!1)}).stop=function(t){return new s(!0,t)}},3383:function(t,r,e){"use strict";var n,o,i,u=e(9518),a=e(8880),c=e(6656),s=e(5112),f=e(1913),l=s("iterator"),p=!1;[].keys&&("next"in(i=[].keys())?(o=u(u(i)))!==Object.prototype&&(n=o):p=!0),null==n&&(n={}),f||c(n,l)||a(n,l,(function(){return this})),t.exports={IteratorPrototype:n,BUGGY_SAFARI_ITERATORS:p}},7497:function(t){t.exports={}},5948:function(t,r,e){var n,o,i,u,a,c,s,f,l=e(7854),p=e(1236).f,h=e(4326),d=e(261).set,v=e(6833),y=l.MutationObserver||l.WebKitMutationObserver,g=l.process,b=l.Promise,m="process"==h(g),w=p(l,"queueMicrotask"),x=w&&w.value;x||(n=function(){var t,r;for(m&&(t=g.domain)&&t.exit();o;){r=o.fn,o=o.next;try{r()}catch(t){throw o?u():i=void 0,t}}i=void 0,t&&t.enter()},m?u=function(){g.nextTick(n)}:y&&!v?(a=!0,c=document.createTextNode(""),new y(n).observe(c,{characterData:!0}),u=function(){c.data=a=!a}):b&&b.resolve?(s=b.resolve(void 0),f=s.then,u=function(){f.call(s,n)}):u=function(){d.call(l,n)}),t.exports=x||function(t){var r={fn:t,next:void 0};i&&(i.next=r),o||(o=r,u()),i=r}},3366:function(t,r,e){var n=e(7854);t.exports=n.Promise},133:function(t,r,e){var n=e(7293);t.exports=!!Object.getOwnPropertySymbols&&!n((function(){return!String(Symbol())}))},8536:function(t,r,e){var n=e(7854),o=e(2788),i=n.WeakMap;t.exports="function"==typeof i&&/native code/.test(o(i))},8523:function(t,r,e){"use strict";var n=e(3099),o=function(t){var r,e;this.promise=new t((function(t,n){if(void 0!==r||void 0!==e)throw TypeError("Bad Promise constructor");r=t,e=n})),this.resolve=n(r),this.reject=n(e)};t.exports.f=function(t){return new o(t)}},3929:function(t,r,e){var n=e(7850);t.exports=function(t){if(n(t))throw TypeError("The method doesn't accept regular expressions");return t}},30:function(t,r,e){var n,o=e(9670),i=e(6048),u=e(748),a=e(3501),c=e(490),s=e(317),f=e(6200),l=f("IE_PROTO"),p=function(){},h=function(t){return"<script>"+t+"</"+"script>"},d=function(){try{n=document.domain&&new ActiveXObject("htmlfile")}catch(t){}var t,r;d=n?function(t){t.write(h("")),t.close();var r=t.parentWindow.Object;return t=null,r}(n):((r=s("iframe")).style.display="none",c.appendChild(r),r.src=String("javascript:"),(t=r.contentWindow.document).open(),t.write(h("document.F=Object")),t.close(),t.F);for(var e=u.length;e--;)delete d.prototype[u[e]];return d()};a[l]=!0,t.exports=Object.create||function(t,r){var e;return null!==t?(p.prototype=o(t),e=new p,p.prototype=null,e[l]=t):e=d(),void 0===r?e:i(e,r)}},6048:function(t,r,e){var n=e(9781),o=e(3070),i=e(9670),u=e(1956);t.exports=n?Object.defineProperties:function(t,r){i(t);for(var e,n=u(r),a=n.length,c=0;a>c;)o.f(t,e=n[c++],r[e]);return t}},3070:function(t,r,e){var n=e(9781),o=e(4664),i=e(9670),u=e(7593),a=Object.defineProperty;r.f=n?a:function(t,r,e){if(i(t),r=u(r,!0),i(e),o)try{return a(t,r,e)}catch(t){}if("get"in e||"set"in e)throw TypeError("Accessors not supported");return"value"in e&&(t[r]=e.value),t}},1236:function(t,r,e){var n=e(9781),o=e(5296),i=e(9114),u=e(5656),a=e(7593),c=e(6656),s=e(4664),f=Object.getOwnPropertyDescriptor;r.f=n?f:function(t,r){if(t=u(t),r=a(r,!0),s)try{return f(t,r)}catch(t){}if(c(t,r))return i(!o.f.call(t,r),t[r])}},8006:function(t,r,e){var n=e(6324),o=e(748).concat("length","prototype");r.f=Object.getOwnPropertyNames||function(t){return n(t,o)}},5181:function(t,r){r.f=Object.getOwnPropertySymbols},9518:function(t,r,e){var n=e(6656),o=e(7908),i=e(6200),u=e(8544),a=i("IE_PROTO"),c=Object.prototype;t.exports=u?Object.getPrototypeOf:function(t){return t=o(t),n(t,a)?t[a]:"function"==typeof t.constructor&&t instanceof t.constructor?t.constructor.prototype:t instanceof Object?c:null}},6324:function(t,r,e){var n=e(6656),o=e(5656),i=e(1318).indexOf,u=e(3501);t.exports=function(t,r){var e,a=o(t),c=0,s=[];for(e in a)!n(u,e)&&n(a,e)&&s.push(e);for(;r.length>c;)n(a,e=r[c++])&&(~i(s,e)||s.push(e));return s}},1956:function(t,r,e){var n=e(6324),o=e(748);t.exports=Object.keys||function(t){return n(t,o)}},5296:function(t,r){"use strict";var e={}.propertyIsEnumerable,n=Object.getOwnPropertyDescriptor,o=n&&!e.call({1:2},1);r.f=o?function(t){var r=n(this,t);return!!r&&r.enumerable}:e},7674:function(t,r,e){var n=e(9670),o=e(6077);t.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var t,r=!1,e={};try{(t=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set).call(e,[]),r=e instanceof Array}catch(t){}return function(e,i){return n(e),o(i),r?t.call(e,i):e.__proto__=i,e}}():void 0)},288:function(t,r,e){"use strict";var n=e(1694),o=e(648);t.exports=n?{}.toString:function(){return"[object "+o(this)+"]"}},3887:function(t,r,e){var n=e(5005),o=e(8006),i=e(5181),u=e(9670);t.exports=n("Reflect","ownKeys")||function(t){var r=o.f(u(t)),e=i.f;return e?r.concat(e(t)):r}},857:function(t,r,e){var n=e(7854);t.exports=n},2534:function(t){t.exports=function(t){try{return{error:!1,value:t()}}catch(t){return{error:!0,value:t}}}},9478:function(t,r,e){var n=e(9670),o=e(111),i=e(8523);t.exports=function(t,r){if(n(t),o(r)&&r.constructor===t)return r;var e=i.f(t);return(0,e.resolve)(r),e.promise}},2248:function(t,r,e){var n=e(1320);t.exports=function(t,r,e){for(var o in r)n(t,o,r[o],e);return t}},1320:function(t,r,e){var n=e(7854),o=e(8880),i=e(6656),u=e(3505),a=e(2788),c=e(9909),s=c.get,f=c.enforce,l=String(String).split("String");(t.exports=function(t,r,e,a){var c=!!a&&!!a.unsafe,s=!!a&&!!a.enumerable,p=!!a&&!!a.noTargetGet;"function"==typeof e&&("string"!=typeof r||i(e,"name")||o(e,"name",r),f(e).source=l.join("string"==typeof r?r:"")),t!==n?(c?!p&&t[r]&&(s=!0):delete t[r],s?t[r]=e:o(t,r,e)):s?t[r]=e:u(r,e)})(Function.prototype,"toString",(function(){return"function"==typeof this&&s(this).source||a(this)}))},7651:function(t,r,e){var n=e(4326),o=e(2261);t.exports=function(t,r){var e=t.exec;if("function"==typeof e){var i=e.call(t,r);if("object"!=typeof i)throw TypeError("RegExp exec method returned something other than an Object or null");return i}if("RegExp"!==n(t))throw TypeError("RegExp#exec called on incompatible receiver");return o.call(t,r)}},2261:function(t,r,e){"use strict";var n,o,i=e(7066),u=e(2999),a=RegExp.prototype.exec,c=String.prototype.replace,s=a,f=(n=/a/,o=/b*/g,a.call(n,"a"),a.call(o,"a"),0!==n.lastIndex||0!==o.lastIndex),l=u.UNSUPPORTED_Y||u.BROKEN_CARET,p=void 0!==/()??/.exec("")[1];(f||p||l)&&(s=function(t){var r,e,n,o,u=this,s=l&&u.sticky,h=i.call(u),d=u.source,v=0,y=t;return s&&(-1===(h=h.replace("y","")).indexOf("g")&&(h+="g"),y=String(t).slice(u.lastIndex),u.lastIndex>0&&(!u.multiline||u.multiline&&"\n"!==t[u.lastIndex-1])&&(d="(?: "+d+")",y=" "+y,v++),e=new RegExp("^(?:"+d+")",h)),p&&(e=new RegExp("^"+d+"$(?!\\s)",h)),f&&(r=u.lastIndex),n=a.call(s?e:u,y),s?n?(n.input=n.input.slice(v),n[0]=n[0].slice(v),n.index=u.lastIndex,u.lastIndex+=n[0].length):u.lastIndex=0:f&&n&&(u.lastIndex=u.global?n.index+n[0].length:r),p&&n&&n.length>1&&c.call(n[0],e,(function(){for(o=1;o<arguments.length-2;o++)void 0===arguments[o]&&(n[o]=void 0)})),n}),t.exports=s},7066:function(t,r,e){"use strict";var n=e(9670);t.exports=function(){var t=n(this),r="";return t.global&&(r+="g"),t.ignoreCase&&(r+="i"),t.multiline&&(r+="m"),t.dotAll&&(r+="s"),t.unicode&&(r+="u"),t.sticky&&(r+="y"),r}},2999:function(t,r,e){"use strict";var n=e(7293);function o(t,r){return RegExp(t,r)}r.UNSUPPORTED_Y=n((function(){var t=o("a","y");return t.lastIndex=2,null!=t.exec("abcd")})),r.BROKEN_CARET=n((function(){var t=o("^r","gy");return t.lastIndex=2,null!=t.exec("str")}))},4488:function(t){t.exports=function(t){if(null==t)throw TypeError("Can't call method on "+t);return t}},6029:function(t){t.exports=Object.is||function(t,r){return t===r?0!==t||1/t==1/r:t!=t&&r!=r}},3505:function(t,r,e){var n=e(7854),o=e(8880);t.exports=function(t,r){try{o(n,t,r)}catch(e){n[t]=r}return r}},6340:function(t,r,e){"use strict";var n=e(5005),o=e(3070),i=e(5112),u=e(9781),a=i("species");t.exports=function(t){var r=n(t),e=o.f;u&&r&&!r[a]&&e(r,a,{configurable:!0,get:function(){return this}})}},8003:function(t,r,e){var n=e(3070).f,o=e(6656),i=e(5112)("toStringTag");t.exports=function(t,r,e){t&&!o(t=e?t:t.prototype,i)&&n(t,i,{configurable:!0,value:r})}},6200:function(t,r,e){var n=e(2309),o=e(9711),i=n("keys");t.exports=function(t){return i[t]||(i[t]=o(t))}},5465:function(t,r,e){var n=e(7854),o=e(3505),i="__core-js_shared__",u=n[i]||o(i,{});t.exports=u},2309:function(t,r,e){var n=e(1913),o=e(5465);(t.exports=function(t,r){return o[t]||(o[t]=void 0!==r?r:{})})("versions",[]).push({version:"3.6.5",mode:n?"pure":"global",copyright:"© 2020 Denis Pushkarev (zloirock.ru)"})},6707:function(t,r,e){var n=e(9670),o=e(3099),i=e(5112)("species");t.exports=function(t,r){var e,u=n(t).constructor;return void 0===u||null==(e=n(u)[i])?r:o(e)}},3429:function(t,r,e){var n=e(7293);t.exports=function(t){return n((function(){var r=""[t]('"');return r!==r.toLowerCase()||r.split('"').length>3}))}},8710:function(t,r,e){var n=e(9958),o=e(4488),i=function(t){return function(r,e){var i,u,a=String(o(r)),c=n(e),s=a.length;return c<0||c>=s?t?"":void 0:(i=a.charCodeAt(c))<55296||i>56319||c+1===s||(u=a.charCodeAt(c+1))<56320||u>57343?t?a.charAt(c):i:t?a.slice(c,c+2):u-56320+(i-55296<<10)+65536}};t.exports={codeAt:i(!1),charAt:i(!0)}},4986:function(t,r,e){var n=e(8113);t.exports=/Version\/10\.\d+(\.\d+)?( Mobile\/\w+)? Safari\//.test(n)},6650:function(t,r,e){var n=e(7466),o=e(8415),i=e(4488),u=Math.ceil,a=function(t){return function(r,e,a){var c,s,f=String(i(r)),l=f.length,p=void 0===a?" ":String(a),h=n(e);return h<=l||""==p?f:(c=h-l,(s=o.call(p,u(c/p.length))).length>c&&(s=s.slice(0,c)),t?f+s:s+f)}};t.exports={start:a(!1),end:a(!0)}},8415:function(t,r,e){"use strict";var n=e(9958),o=e(4488);t.exports="".repeat||function(t){var r=String(o(this)),e="",i=n(t);if(i<0||i==1/0)throw RangeError("Wrong number of repetitions");for(;i>0;(i>>>=1)&&(r+=r))1&i&&(e+=r);return e}},6091:function(t,r,e){var n=e(7293),o=e(1361);t.exports=function(t){return n((function(){return!!o[t]()||"…"!="…"[t]()||o[t].name!==t}))}},3111:function(t,r,e){var n=e(4488),o="["+e(1361)+"]",i=RegExp("^"+o+o+"*"),u=RegExp(o+o+"*$"),a=function(t){return function(r){var e=String(n(r));return 1&t&&(e=e.replace(i,"")),2&t&&(e=e.replace(u,"")),e}};t.exports={start:a(1),end:a(2),trim:a(3)}},261:function(t,r,e){var n,o,i,u=e(7854),a=e(7293),c=e(4326),s=e(9974),f=e(490),l=e(317),p=e(6833),h=u.location,d=u.setImmediate,v=u.clearImmediate,y=u.process,g=u.MessageChannel,b=u.Dispatch,m=0,w={},x="onreadystatechange",S=function(t){if(w.hasOwnProperty(t)){var r=w[t];delete w[t],r()}},E=function(t){return function(){S(t)}},_=function(t){S(t.data)},O=function(t){u.postMessage(t+"",h.protocol+"//"+h.host)};d&&v||(d=function(t){for(var r=[],e=1;arguments.length>e;)r.push(arguments[e++]);return w[++m]=function(){("function"==typeof t?t:Function(t)).apply(void 0,r)},n(m),m},v=function(t){delete w[t]},"process"==c(y)?n=function(t){y.nextTick(E(t))}:b&&b.now?n=function(t){b.now(E(t))}:g&&!p?(i=(o=new g).port2,o.port1.onmessage=_,n=s(i.postMessage,i,1)):!u.addEventListener||"function"!=typeof postMessage||u.importScripts||a(O)||"file:"===h.protocol?n=x in l("script")?function(t){f.appendChild(l("script")).onreadystatechange=function(){f.removeChild(this),S(t)}}:function(t){setTimeout(E(t),0)}:(n=O,u.addEventListener("message",_,!1))),t.exports={set:d,clear:v}},1400:function(t,r,e){var n=e(9958),o=Math.max,i=Math.min;t.exports=function(t,r){var e=n(t);return e<0?o(e+r,0):i(e,r)}},5656:function(t,r,e){var n=e(8361),o=e(4488);t.exports=function(t){return n(o(t))}},9958:function(t){var r=Math.ceil,e=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?e:r)(t)}},7466:function(t,r,e){var n=e(9958),o=Math.min;t.exports=function(t){return t>0?o(n(t),9007199254740991):0}},7908:function(t,r,e){var n=e(4488);t.exports=function(t){return Object(n(t))}},7593:function(t,r,e){var n=e(111);t.exports=function(t,r){if(!n(t))return t;var e,o;if(r&&"function"==typeof(e=t.toString)&&!n(o=e.call(t)))return o;if("function"==typeof(e=t.valueOf)&&!n(o=e.call(t)))return o;if(!r&&"function"==typeof(e=t.toString)&&!n(o=e.call(t)))return o;throw TypeError("Can't convert object to primitive value")}},1694:function(t,r,e){var n={};n[e(5112)("toStringTag")]="z",t.exports="[object z]"===String(n)},9711:function(t){var r=0,e=Math.random();t.exports=function(t){return"Symbol("+String(void 0===t?"":t)+")_"+(++r+e).toString(36)}},3307:function(t,r,e){var n=e(133);t.exports=n&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},5112:function(t,r,e){var n=e(7854),o=e(2309),i=e(6656),u=e(9711),a=e(133),c=e(3307),s=o("wks"),f=n.Symbol,l=c?f:f&&f.withoutSetter||u;t.exports=function(t){return i(s,t)||(a&&i(f,t)?s[t]=f[t]:s[t]=l("Symbol."+t)),s[t]}},1361:function(t){t.exports="\t\n\v\f\r    \u2028\u2029\ufeff"},6992:function(t,r,e){"use strict";var n=e(5656),o=e(1223),i=e(7497),u=e(9909),a=e(654),c="Array Iterator",s=u.set,f=u.getterFor(c);t.exports=a(Array,"Array",(function(t,r){s(this,{type:c,target:n(t),index:0,kind:r})}),(function(){var t=f(this),r=t.target,e=t.kind,n=t.index++;return!r||n>=r.length?(t.target=void 0,{value:void 0,done:!0}):"keys"==e?{value:n,done:!1}:"values"==e?{value:r[n],done:!1}:{value:[n,r[n]],done:!1}}),"values"),i.Arguments=i.Array,o("keys"),o("values"),o("entries")},1539:function(t,r,e){var n=e(1694),o=e(1320),i=e(288);n||o(Object.prototype,"toString",i,{unsafe:!0})},7922:function(t,r,e){"use strict";var n=e(2109),o=e(3099),i=e(8523),u=e(2534),a=e(408);n({target:"Promise",stat:!0},{allSettled:function(t){var r=this,e=i.f(r),n=e.resolve,c=e.reject,s=u((function(){var e=o(r.resolve),i=[],u=0,c=1;a(t,(function(t){var o=u++,a=!1;i.push(void 0),c++,e.call(r,t).then((function(t){a||(a=!0,i[o]={status:"fulfilled",value:t},--c||n(i))}),(function(t){a||(a=!0,i[o]={status:"rejected",reason:t},--c||n(i))}))})),--c||n(i)}));return s.error&&c(s.value),e.promise}})},7727:function(t,r,e){"use strict";var n=e(2109),o=e(1913),i=e(3366),u=e(7293),a=e(5005),c=e(6707),s=e(9478),f=e(1320);n({target:"Promise",proto:!0,real:!0,forced:!!i&&u((function(){i.prototype.finally.call({then:function(){}},(function(){}))}))},{finally:function(t){var r=c(this,a("Promise")),e="function"==typeof t;return this.then(e?function(e){return s(r,t()).then((function(){return e}))}:t,e?function(e){return s(r,t()).then((function(){throw e}))}:t)}}),o||"function"!=typeof i||i.prototype.finally||f(i.prototype,"finally",a("Promise").prototype.finally)},8674:function(t,r,e){"use strict";var n,o,i,u,a=e(2109),c=e(1913),s=e(7854),f=e(5005),l=e(3366),p=e(1320),h=e(2248),d=e(8003),v=e(6340),y=e(111),g=e(3099),b=e(5787),m=e(4326),w=e(2788),x=e(408),S=e(7072),E=e(6707),_=e(261).set,O=e(5948),T=e(9478),P=e(842),j=e(8523),A=e(2534),I=e(9909),R=e(4705),L=e(5112),k=e(7392),C=L("species"),D="Promise",B=I.get,U=I.set,F=I.getterFor(D),M=l,N=s.TypeError,G=s.document,X=s.process,H=f("fetch"),$=j.f,q=$,W="process"==m(X),V=!!(G&&G.createEvent&&s.dispatchEvent),z="unhandledrejection",K=R(D,(function(){if(!(w(M)!==String(M))){if(66===k)return!0;if(!W&&"function"!=typeof PromiseRejectionEvent)return!0}if(c&&!M.prototype.finally)return!0;if(k>=51&&/native code/.test(M))return!1;var t=M.resolve(1),r=function(t){t((function(){}),(function(){}))};return(t.constructor={})[C]=r,!(t.then((function(){}))instanceof r)})),Y=K||!S((function(t){M.all(t).catch((function(){}))})),J=function(t){var r;return!(!y(t)||"function"!=typeof(r=t.then))&&r},Q=function(t,r,e){if(!r.notified){r.notified=!0;var n=r.reactions;O((function(){for(var o=r.value,i=1==r.state,u=0;n.length>u;){var a,c,s,f=n[u++],l=i?f.ok:f.fail,p=f.resolve,h=f.reject,d=f.domain;try{l?(i||(2===r.rejection&&et(t,r),r.rejection=1),!0===l?a=o:(d&&d.enter(),a=l(o),d&&(d.exit(),s=!0)),a===f.promise?h(N("Promise-chain cycle")):(c=J(a))?c.call(a,p,h):p(a)):h(o)}catch(t){d&&!s&&d.exit(),h(t)}}r.reactions=[],r.notified=!1,e&&!r.rejection&&tt(t,r)}))}},Z=function(t,r,e){var n,o;V?((n=G.createEvent("Event")).promise=r,n.reason=e,n.initEvent(t,!1,!0),s.dispatchEvent(n)):n={promise:r,reason:e},(o=s["on"+t])?o(n):t===z&&P("Unhandled promise rejection",e)},tt=function(t,r){_.call(s,(function(){var e,n=r.value;if(rt(r)&&(e=A((function(){W?X.emit("unhandledRejection",n,t):Z(z,t,n)})),r.rejection=W||rt(r)?2:1,e.error))throw e.value}))},rt=function(t){return 1!==t.rejection&&!t.parent},et=function(t,r){_.call(s,(function(){W?X.emit("rejectionHandled",t):Z("rejectionhandled",t,r.value)}))},nt=function(t,r,e,n){return function(o){t(r,e,o,n)}},ot=function(t,r,e,n){r.done||(r.done=!0,n&&(r=n),r.value=e,r.state=2,Q(t,r,!0))},it=function(t,r,e,n){if(!r.done){r.done=!0,n&&(r=n);try{if(t===e)throw N("Promise can't be resolved itself");var o=J(e);o?O((function(){var n={done:!1};try{o.call(e,nt(it,t,n,r),nt(ot,t,n,r))}catch(e){ot(t,n,e,r)}})):(r.value=e,r.state=1,Q(t,r,!1))}catch(e){ot(t,{done:!1},e,r)}}};K&&(M=function(t){b(this,M,D),g(t),n.call(this);var r=B(this);try{t(nt(it,this,r),nt(ot,this,r))}catch(t){ot(this,r,t)}},(n=function(t){U(this,{type:D,done:!1,notified:!1,parent:!1,reactions:[],rejection:!1,state:0,value:void 0})}).prototype=h(M.prototype,{then:function(t,r){var e=F(this),n=$(E(this,M));return n.ok="function"!=typeof t||t,n.fail="function"==typeof r&&r,n.domain=W?X.domain:void 0,e.parent=!0,e.reactions.push(n),0!=e.state&&Q(this,e,!1),n.promise},catch:function(t){return this.then(void 0,t)}}),o=function(){var t=new n,r=B(t);this.promise=t,this.resolve=nt(it,t,r),this.reject=nt(ot,t,r)},j.f=$=function(t){return t===M||t===i?new o(t):q(t)},c||"function"!=typeof l||(u=l.prototype.then,p(l.prototype,"then",(function(t,r){var e=this;return new M((function(t,r){u.call(e,t,r)})).then(t,r)}),{unsafe:!0}),"function"==typeof H&&a({global:!0,enumerable:!0,forced:!0},{fetch:function(t){return T(M,H.apply(s,arguments))}}))),a({global:!0,wrap:!0,forced:K},{Promise:M}),d(M,D,!1,!0),v(D),i=f(D),a({target:D,stat:!0,forced:K},{reject:function(t){var r=$(this);return r.reject.call(void 0,t),r.promise}}),a({target:D,stat:!0,forced:c||K},{resolve:function(t){return T(c&&this===i?M:this,t)}}),a({target:D,stat:!0,forced:Y},{all:function(t){var r=this,e=$(r),n=e.resolve,o=e.reject,i=A((function(){var e=g(r.resolve),i=[],u=0,a=1;x(t,(function(t){var c=u++,s=!1;i.push(void 0),a++,e.call(r,t).then((function(t){s||(s=!0,i[c]=t,--a||n(i))}),o)})),--a||n(i)}));return i.error&&o(i.value),e.promise},race:function(t){var r=this,e=$(r),n=e.reject,o=A((function(){var o=g(r.resolve);x(t,(function(t){o.call(r,t).then(e.resolve,n)}))}));return o.error&&n(o.value),e.promise}})},4916:function(t,r,e){"use strict";var n=e(2109),o=e(2261);n({target:"RegExp",proto:!0,forced:/./.exec!==o},{exec:o})},5218:function(t,r,e){"use strict";var n=e(2109),o=e(4230);n({target:"String",proto:!0,forced:e(3429)("anchor")},{anchor:function(t){return o(this,"a","name",t)}})},4475:function(t,r,e){"use strict";var n=e(2109),o=e(4230);n({target:"String",proto:!0,forced:e(3429)("big")},{big:function(){return o(this,"big","","")}})},7929:function(t,r,e){"use strict";var n=e(2109),o=e(4230);n({target:"String",proto:!0,forced:e(3429)("blink")},{blink:function(){return o(this,"blink","","")}})},915:function(t,r,e){"use strict";var n=e(2109),o=e(4230);n({target:"String",proto:!0,forced:e(3429)("bold")},{bold:function(){return o(this,"b","","")}})},9841:function(t,r,e){"use strict";var n=e(2109),o=e(8710).codeAt;n({target:"String",proto:!0},{codePointAt:function(t){return o(this,t)}})},7852:function(t,r,e){"use strict";var n,o=e(2109),i=e(1236).f,u=e(7466),a=e(3929),c=e(4488),s=e(4964),f=e(1913),l="".endsWith,p=Math.min,h=s("endsWith");o({target:"String",proto:!0,forced:!!(f||h||(n=i(String.prototype,"endsWith"),!n||n.writable))&&!h},{endsWith:function(t){var r=String(c(this));a(t);var e=arguments.length>1?arguments[1]:void 0,n=u(r.length),o=void 0===e?n:p(u(e),n),i=String(t);return l?l.call(r,i,o):r.slice(o-i.length,o)===i}})},9253:function(t,r,e){"use strict";var n=e(2109),o=e(4230);n({target:"String",proto:!0,forced:e(3429)("fixed")},{fixed:function(){return o(this,"tt","","")}})},2125:function(t,r,e){"use strict";var n=e(2109),o=e(4230);n({target:"String",proto:!0,forced:e(3429)("fontcolor")},{fontcolor:function(t){return o(this,"font","color",t)}})},8830:function(t,r,e){"use strict";var n=e(2109),o=e(4230);n({target:"String",proto:!0,forced:e(3429)("fontsize")},{fontsize:function(t){return o(this,"font","size",t)}})},4953:function(t,r,e){var n=e(2109),o=e(1400),i=String.fromCharCode,u=String.fromCodePoint;n({target:"String",stat:!0,forced:!!u&&1!=u.length},{fromCodePoint:function(t){for(var r,e=[],n=arguments.length,u=0;n>u;){if(r=+arguments[u++],o(r,1114111)!==r)throw RangeError(r+" is not a valid code point");e.push(r<65536?i(r):i(55296+((r-=65536)>>10),r%1024+56320))}return e.join("")}})},2023:function(t,r,e){"use strict";var n=e(2109),o=e(3929),i=e(4488);n({target:"String",proto:!0,forced:!e(4964)("includes")},{includes:function(t){return!!~String(i(this)).indexOf(o(t),arguments.length>1?arguments[1]:void 0)}})},8734:function(t,r,e){"use strict";var n=e(2109),o=e(4230);n({target:"String",proto:!0,forced:e(3429)("italics")},{italics:function(){return o(this,"i","","")}})},8783:function(t,r,e){"use strict";var n=e(8710).charAt,o=e(9909),i=e(654),u="String Iterator",a=o.set,c=o.getterFor(u);i(String,"String",(function(t){a(this,{type:u,string:String(t),index:0})}),(function(){var t,r=c(this),e=r.string,o=r.index;return o>=e.length?{value:void 0,done:!0}:(t=n(e,o),r.index+=t.length,{value:t,done:!1})}))},9254:function(t,r,e){"use strict";var n=e(2109),o=e(4230);n({target:"String",proto:!0,forced:e(3429)("link")},{link:function(t){return o(this,"a","href",t)}})},6373:function(t,r,e){"use strict";var n=e(2109),o=e(4994),i=e(4488),u=e(7466),a=e(3099),c=e(9670),s=e(4326),f=e(7850),l=e(7066),p=e(8880),h=e(7293),d=e(5112),v=e(6707),y=e(1530),g=e(9909),b=e(1913),m=d("matchAll"),w="RegExp String",x="RegExp String Iterator",S=g.set,E=g.getterFor(x),_=RegExp.prototype,O=_.exec,T="".matchAll,P=!!T&&!h((function(){"a".matchAll(/./)})),j=o((function(t,r,e,n){S(this,{type:x,regexp:t,string:r,global:e,unicode:n,done:!1})}),w,(function(){var t=E(this);if(t.done)return{value:void 0,done:!0};var r=t.regexp,e=t.string,n=function(t,r){var e,n=t.exec;if("function"==typeof n){if("object"!=typeof(e=n.call(t,r)))throw TypeError("Incorrect exec result");return e}return O.call(t,r)}(r,e);return null===n?{value:void 0,done:t.done=!0}:t.global?(""==String(n[0])&&(r.lastIndex=y(e,u(r.lastIndex),t.unicode)),{value:n,done:!1}):(t.done=!0,{value:n,done:!1})})),A=function(t){var r,e,n,o,i,a,s=c(this),f=String(t);return r=v(s,RegExp),void 0===(e=s.flags)&&s instanceof RegExp&&!("flags"in _)&&(e=l.call(s)),n=void 0===e?"":String(e),o=new r(r===RegExp?s.source:s,n),i=!!~n.indexOf("g"),a=!!~n.indexOf("u"),o.lastIndex=u(s.lastIndex),new j(o,f,i,a)};n({target:"String",proto:!0,forced:P},{matchAll:function(t){var r,e,n,o=i(this);if(null!=t){if(f(t)&&!~String(i("flags"in _?t.flags:l.call(t))).indexOf("g"))throw TypeError("`.matchAll` does not allow non-global regexes");if(P)return T.apply(o,arguments);if(void 0===(e=t[m])&&b&&"RegExp"==s(t)&&(e=A),null!=e)return a(e).call(t,o)}else if(P)return T.apply(o,arguments);return r=String(o),n=new RegExp(t,"g"),b?A.call(n,r):n[m](r)}}),b||m in _||p(_,m,A)},4723:function(t,r,e){"use strict";var n=e(7007),o=e(9670),i=e(7466),u=e(4488),a=e(1530),c=e(7651);n("match",1,(function(t,r,e){return[function(r){var e=u(this),n=null==r?void 0:r[t];return void 0!==n?n.call(r,e):new RegExp(r)[t](String(e))},function(t){var n=e(r,t,this);if(n.done)return n.value;var u=o(t),s=String(this);if(!u.global)return c(u,s);var f=u.unicode;u.lastIndex=0;for(var l,p=[],h=0;null!==(l=c(u,s));){var d=String(l[0]);p[h]=d,""===d&&(u.lastIndex=a(s,i(u.lastIndex),f)),h++}return 0===h?null:p}]}))},6528:function(t,r,e){"use strict";var n=e(2109),o=e(6650).end;n({target:"String",proto:!0,forced:e(4986)},{padEnd:function(t){return o(this,t,arguments.length>1?arguments[1]:void 0)}})},3112:function(t,r,e){"use strict";var n=e(2109),o=e(6650).start;n({target:"String",proto:!0,forced:e(4986)},{padStart:function(t){return o(this,t,arguments.length>1?arguments[1]:void 0)}})},8992:function(t,r,e){var n=e(2109),o=e(5656),i=e(7466);n({target:"String",stat:!0},{raw:function(t){for(var r=o(t.raw),e=i(r.length),n=arguments.length,u=[],a=0;e>a;)u.push(String(r[a++])),a<n&&u.push(String(arguments[a]));return u.join("")}})},2481:function(t,r,e){e(2109)({target:"String",proto:!0},{repeat:e(8415)})},5306:function(t,r,e){"use strict";var n=e(7007),o=e(9670),i=e(7908),u=e(7466),a=e(9958),c=e(4488),s=e(1530),f=e(7651),l=Math.max,p=Math.min,h=Math.floor,d=/\$([$&'`]|\d\d?|<[^>]*>)/g,v=/\$([$&'`]|\d\d?)/g;n("replace",2,(function(t,r,e,n){var y=n.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE,g=n.REPLACE_KEEPS_$0,b=y?"$":"$0";return[function(e,n){var o=c(this),i=null==e?void 0:e[t];return void 0!==i?i.call(e,o,n):r.call(String(o),e,n)},function(t,n){if(!y&&g||"string"==typeof n&&-1===n.indexOf(b)){var i=e(r,t,this,n);if(i.done)return i.value}var c=o(t),h=String(this),d="function"==typeof n;d||(n=String(n));var v=c.global;if(v){var w=c.unicode;c.lastIndex=0}for(var x=[];;){var S=f(c,h);if(null===S)break;if(x.push(S),!v)break;""===String(S[0])&&(c.lastIndex=s(h,u(c.lastIndex),w))}for(var E,_="",O=0,T=0;T<x.length;T++){S=x[T];for(var P=String(S[0]),j=l(p(a(S.index),h.length),0),A=[],I=1;I<S.length;I++)A.push(void 0===(E=S[I])?E:String(E));var R=S.groups;if(d){var L=[P].concat(A,j,h);void 0!==R&&L.push(R);var k=String(n.apply(void 0,L))}else k=m(P,h,j,A,R,n);j>=O&&(_+=h.slice(O,j)+k,O=j+P.length)}return _+h.slice(O)}];function m(t,e,n,o,u,a){var c=n+t.length,s=o.length,f=v;return void 0!==u&&(u=i(u),f=d),r.call(a,f,(function(r,i){var a;switch(i.charAt(0)){case"$":return"$";case"&":return t;case"`":return e.slice(0,n);case"'":return e.slice(c);case"<":a=u[i.slice(1,-1)];break;default:var f=+i;if(0===f)return r;if(f>s){var l=h(f/10);return 0===l?r:l<=s?void 0===o[l-1]?i.charAt(1):o[l-1]+i.charAt(1):r}a=o[f-1]}return void 0===a?"":a}))}}))},4765:function(t,r,e){"use strict";var n=e(7007),o=e(9670),i=e(4488),u=e(6029),a=e(7651);n("search",1,(function(t,r,e){return[function(r){var e=i(this),n=null==r?void 0:r[t];return void 0!==n?n.call(r,e):new RegExp(r)[t](String(e))},function(t){var n=e(r,t,this);if(n.done)return n.value;var i=o(t),c=String(this),s=i.lastIndex;u(s,0)||(i.lastIndex=0);var f=a(i,c);return u(i.lastIndex,s)||(i.lastIndex=s),null===f?-1:f.index}]}))},7268:function(t,r,e){"use strict";var n=e(2109),o=e(4230);n({target:"String",proto:!0,forced:e(3429)("small")},{small:function(){return o(this,"small","","")}})},3123:function(t,r,e){"use strict";var n=e(7007),o=e(7850),i=e(9670),u=e(4488),a=e(6707),c=e(1530),s=e(7466),f=e(7651),l=e(2261),p=e(7293),h=[].push,d=Math.min,v=4294967295,y=!p((function(){return!RegExp(v,"y")}));n("split",2,(function(t,r,e){var n;return n="c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length?function(t,e){var n=String(u(this)),i=void 0===e?v:e>>>0;if(0===i)return[];if(void 0===t)return[n];if(!o(t))return r.call(n,t,i);for(var a,c,s,f=[],p=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),d=0,y=new RegExp(t.source,p+"g");(a=l.call(y,n))&&!((c=y.lastIndex)>d&&(f.push(n.slice(d,a.index)),a.length>1&&a.index<n.length&&h.apply(f,a.slice(1)),s=a[0].length,d=c,f.length>=i));)y.lastIndex===a.index&&y.lastIndex++;return d===n.length?!s&&y.test("")||f.push(""):f.push(n.slice(d)),f.length>i?f.slice(0,i):f}:"0".split(void 0,0).length?function(t,e){return void 0===t&&0===e?[]:r.call(this,t,e)}:r,[function(r,e){var o=u(this),i=null==r?void 0:r[t];return void 0!==i?i.call(r,o,e):n.call(String(o),r,e)},function(t,o){var u=e(n,t,this,o,n!==r);if(u.done)return u.value;var l=i(t),p=String(this),h=a(l,RegExp),g=l.unicode,b=(l.ignoreCase?"i":"")+(l.multiline?"m":"")+(l.unicode?"u":"")+(y?"y":"g"),m=new h(y?l:"^(?:"+l.source+")",b),w=void 0===o?v:o>>>0;if(0===w)return[];if(0===p.length)return null===f(m,p)?[p]:[];for(var x=0,S=0,E=[];S<p.length;){m.lastIndex=y?S:0;var _,O=f(m,y?p:p.slice(S));if(null===O||(_=d(s(m.lastIndex+(y?0:S)),p.length))===x)S=c(p,S,g);else{if(E.push(p.slice(x,S)),E.length===w)return E;for(var T=1;T<=O.length-1;T++)if(E.push(O[T]),E.length===w)return E;S=x=_}}return E.push(p.slice(x)),E}]}),!y)},3157:function(t,r,e){"use strict";var n,o=e(2109),i=e(1236).f,u=e(7466),a=e(3929),c=e(4488),s=e(4964),f=e(1913),l="".startsWith,p=Math.min,h=s("startsWith");o({target:"String",proto:!0,forced:!!(f||h||(n=i(String.prototype,"startsWith"),!n||n.writable))&&!h},{startsWith:function(t){var r=String(c(this));a(t);var e=u(p(arguments.length>1?arguments[1]:void 0,r.length)),n=String(t);return l?l.call(r,n,e):r.slice(e,e+n.length)===n}})},7397:function(t,r,e){"use strict";var n=e(2109),o=e(4230);n({target:"String",proto:!0,forced:e(3429)("strike")},{strike:function(){return o(this,"strike","","")}})},86:function(t,r,e){"use strict";var n=e(2109),o=e(4230);n({target:"String",proto:!0,forced:e(3429)("sub")},{sub:function(){return o(this,"sub","","")}})},623:function(t,r,e){"use strict";var n=e(2109),o=e(4230);n({target:"String",proto:!0,forced:e(3429)("sup")},{sup:function(){return o(this,"sup","","")}})},8702:function(t,r,e){"use strict";var n=e(2109),o=e(3111).end,i=e(6091)("trimEnd"),u=i?function(){return o(this)}:"".trimEnd;n({target:"String",proto:!0,forced:i},{trimEnd:u,trimRight:u})},5674:function(t,r,e){"use strict";var n=e(2109),o=e(3111).start,i=e(6091)("trimStart"),u=i?function(){return o(this)}:"".trimStart;n({target:"String",proto:!0,forced:i},{trimStart:u,trimLeft:u})},3210:function(t,r,e){"use strict";var n=e(2109),o=e(3111).trim;n({target:"String",proto:!0,forced:e(6091)("trim")},{trim:function(){return o(this)}})},3948:function(t,r,e){var n=e(7854),o=e(8324),i=e(6992),u=e(8880),a=e(5112),c=a("iterator"),s=a("toStringTag"),f=i.values;for(var l in o){var p=n[l],h=p&&p.prototype;if(h){if(h[c]!==f)try{u(h,c,f)}catch(t){h[c]=f}if(h[s]||u(h,s,l),o[l])for(var d in i)if(h[d]!==i[d])try{u(h,d,i[d])}catch(t){h[d]=i[d]}}}},1150:function(t,r,e){var n=e(7633);t.exports=n},9712:function(t,r,e){var n=e(1111);t.exports=n},5666:function(t){var r=function(t){"use strict";var r,e=Object.prototype,n=e.hasOwnProperty,o="function"==typeof Symbol?Symbol:{},i=o.iterator||"@@iterator",u=o.asyncIterator||"@@asyncIterator",a=o.toStringTag||"@@toStringTag";function c(t,r,e){return Object.defineProperty(t,r,{value:e,enumerable:!0,configurable:!0,writable:!0}),t[r]}try{c({},"")}catch(t){c=function(t,r,e){return t[r]=e}}function s(t,r,e,n){var o=r&&r.prototype instanceof y?r:y,i=Object.create(o.prototype),u=new j(n||[]);return i._invoke=function(t,r,e){var n=l;return function(o,i){if(n===h)throw new Error("Generator is already running");if(n===d){if("throw"===o)throw i;return I()}for(e.method=o,e.arg=i;;){var u=e.delegate;if(u){var a=O(u,e);if(a){if(a===v)continue;return a}}if("next"===e.method)e.sent=e._sent=e.arg;else if("throw"===e.method){if(n===l)throw n=d,e.arg;e.dispatchException(e.arg)}else"return"===e.method&&e.abrupt("return",e.arg);n=h;var c=f(t,r,e);if("normal"===c.type){if(n=e.done?d:p,c.arg===v)continue;return{value:c.arg,done:e.done}}"throw"===c.type&&(n=d,e.method="throw",e.arg=c.arg)}}}(t,e,u),i}function f(t,r,e){try{return{type:"normal",arg:t.call(r,e)}}catch(t){return{type:"throw",arg:t}}}t.wrap=s;var l="suspendedStart",p="suspendedYield",h="executing",d="completed",v={};function y(){}function g(){}function b(){}var m={};m[i]=function(){return this};var w=Object.getPrototypeOf,x=w&&w(w(A([])));x&&x!==e&&n.call(x,i)&&(m=x);var S=b.prototype=y.prototype=Object.create(m);function E(t){["next","throw","return"].forEach((function(r){c(t,r,(function(t){return this._invoke(r,t)}))}))}function _(t,r){function e(o,i,u,a){var c=f(t[o],t,i);if("throw"!==c.type){var s=c.arg,l=s.value;return l&&"object"==typeof l&&n.call(l,"__await")?r.resolve(l.__await).then((function(t){e("next",t,u,a)}),(function(t){e("throw",t,u,a)})):r.resolve(l).then((function(t){s.value=t,u(s)}),(function(t){return e("throw",t,u,a)}))}a(c.arg)}var o;this._invoke=function(t,n){function i(){return new r((function(r,o){e(t,n,r,o)}))}return o=o?o.then(i,i):i()}}function O(t,e){var n=t.iterator[e.method];if(n===r){if(e.delegate=null,"throw"===e.method){if(t.iterator.return&&(e.method="return",e.arg=r,O(t,e),"throw"===e.method))return v;e.method="throw",e.arg=new TypeError("The iterator does not provide a 'throw' method")}return v}var o=f(n,t.iterator,e.arg);if("throw"===o.type)return e.method="throw",e.arg=o.arg,e.delegate=null,v;var i=o.arg;return i?i.done?(e[t.resultName]=i.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=r),e.delegate=null,v):i:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,v)}function T(t){var r={tryLoc:t[0]};1 in t&&(r.catchLoc=t[1]),2 in t&&(r.finallyLoc=t[2],r.afterLoc=t[3]),this.tryEntries.push(r)}function P(t){var r=t.completion||{};r.type="normal",delete r.arg,t.completion=r}function j(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(T,this),this.reset(!0)}function A(t){if(t){var e=t[i];if(e)return e.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var o=-1,u=function e(){for(;++o<t.length;)if(n.call(t,o))return e.value=t[o],e.done=!1,e;return e.value=r,e.done=!0,e};return u.next=u}}return{next:I}}function I(){return{value:r,done:!0}}return g.prototype=S.constructor=b,b.constructor=g,g.displayName=c(b,a,"GeneratorFunction"),t.isGeneratorFunction=function(t){var r="function"==typeof t&&t.constructor;return!!r&&(r===g||"GeneratorFunction"===(r.displayName||r.name))},t.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,b):(t.__proto__=b,c(t,a,"GeneratorFunction")),t.prototype=Object.create(S),t},t.awrap=function(t){return{__await:t}},E(_.prototype),_.prototype[u]=function(){return this},t.AsyncIterator=_,t.async=function(r,e,n,o,i){void 0===i&&(i=Promise);var u=new _(s(r,e,n,o),i);return t.isGeneratorFunction(e)?u:u.next().then((function(t){return t.done?t.value:u.next()}))},E(S),c(S,a,"Generator"),S[i]=function(){return this},S.toString=function(){return"[object Generator]"},t.keys=function(t){var r=[];for(var e in t)r.push(e);return r.reverse(),function e(){for(;r.length;){var n=r.pop();if(n in t)return e.value=n,e.done=!1,e}return e.done=!0,e}},t.values=A,j.prototype={constructor:j,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=r,this.done=!1,this.delegate=null,this.method="next",this.arg=r,this.tryEntries.forEach(P),!t)for(var e in this)"t"===e.charAt(0)&&n.call(this,e)&&!isNaN(+e.slice(1))&&(this[e]=r)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var e=this;function o(n,o){return a.type="throw",a.arg=t,e.next=n,o&&(e.method="next",e.arg=r),!!o}for(var i=this.tryEntries.length-1;i>=0;--i){var u=this.tryEntries[i],a=u.completion;if("root"===u.tryLoc)return o("end");if(u.tryLoc<=this.prev){var c=n.call(u,"catchLoc"),s=n.call(u,"finallyLoc");if(c&&s){if(this.prev<u.catchLoc)return o(u.catchLoc,!0);if(this.prev<u.finallyLoc)return o(u.finallyLoc)}else if(c){if(this.prev<u.catchLoc)return o(u.catchLoc,!0)}else{if(!s)throw new Error("try statement without catch or finally");if(this.prev<u.finallyLoc)return o(u.finallyLoc)}}}},abrupt:function(t,r){for(var e=this.tryEntries.length-1;e>=0;--e){var o=this.tryEntries[e];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev<o.finallyLoc){var i=o;break}}i&&("break"===t||"continue"===t)&&i.tryLoc<=r&&r<=i.finallyLoc&&(i=null);var u=i?i.completion:{};return u.type=t,u.arg=r,i?(this.method="next",this.next=i.finallyLoc,v):this.complete(u)},complete:function(t,r){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&r&&(this.next=r),v},finish:function(t){for(var r=this.tryEntries.length-1;r>=0;--r){var e=this.tryEntries[r];if(e.finallyLoc===t)return this.complete(e.completion,e.afterLoc),P(e),v}},catch:function(t){for(var r=this.tryEntries.length-1;r>=0;--r){var e=this.tryEntries[r];if(e.tryLoc===t){var n=e.completion;if("throw"===n.type){var o=n.arg;P(e)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,n){return this.delegate={iterator:A(t),resultName:e,nextLoc:n},"next"===this.method&&(this.arg=r),v}},t}(t.exports);try{regeneratorRuntime=r}catch(t){Function("r","regeneratorRuntime = r")(r)}},7147:function(t,r,e){"use strict";var n="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof self&&self||void 0!==n&&n,o="URLSearchParams"in n,i="Symbol"in n&&"iterator"in Symbol,u="FileReader"in n&&"Blob"in n&&function(){try{return new Blob,!0}catch(t){return!1}}(),a="FormData"in n,c="ArrayBuffer"in n;if(c)var s=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],f=ArrayBuffer.isView||function(t){return t&&s.indexOf(Object.prototype.toString.call(t))>-1};function l(t){if("string"!=typeof t&&(t=String(t)),/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(t)||""===t)throw new TypeError("Invalid character in header field name");return t.toLowerCase()}function p(t){return"string"!=typeof t&&(t=String(t)),t}function h(t){var r={next:function(){var r=t.shift();return{done:void 0===r,value:r}}};return i&&(r[Symbol.iterator]=function(){return r}),r}function d(t){this.map={},t instanceof d?t.forEach((function(t,r){this.append(r,t)}),this):Array.isArray(t)?t.forEach((function(t){this.append(t[0],t[1])}),this):t&&Object.getOwnPropertyNames(t).forEach((function(r){this.append(r,t[r])}),this)}function v(t){if(t.bodyUsed)return Promise.reject(new TypeError("Already read"));t.bodyUsed=!0}function y(t){return new Promise((function(r,e){t.onload=function(){r(t.result)},t.onerror=function(){e(t.error)}}))}function g(t){var r=new FileReader,e=y(r);return r.readAsArrayBuffer(t),e}function b(t){if(t.slice)return t.slice(0);var r=new Uint8Array(t.byteLength);return r.set(new Uint8Array(t)),r.buffer}function m(){return this.bodyUsed=!1,this._initBody=function(t){var r;this.bodyUsed=this.bodyUsed,this._bodyInit=t,t?"string"==typeof t?this._bodyText=t:u&&Blob.prototype.isPrototypeOf(t)?this._bodyBlob=t:a&&FormData.prototype.isPrototypeOf(t)?this._bodyFormData=t:o&&URLSearchParams.prototype.isPrototypeOf(t)?this._bodyText=t.toString():c&&u&&((r=t)&&DataView.prototype.isPrototypeOf(r))?(this._bodyArrayBuffer=b(t.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer])):c&&(ArrayBuffer.prototype.isPrototypeOf(t)||f(t))?this._bodyArrayBuffer=b(t):this._bodyText=t=Object.prototype.toString.call(t):this._bodyText="",this.headers.get("content-type")||("string"==typeof t?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("content-type",this._bodyBlob.type):o&&URLSearchParams.prototype.isPrototypeOf(t)&&this.headers.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"))},u&&(this.blob=function(){var t=v(this);if(t)return t;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){if(this._bodyArrayBuffer){var t=v(this);return t||(ArrayBuffer.isView(this._bodyArrayBuffer)?Promise.resolve(this._bodyArrayBuffer.buffer.slice(this._bodyArrayBuffer.byteOffset,this._bodyArrayBuffer.byteOffset+this._bodyArrayBuffer.byteLength)):Promise.resolve(this._bodyArrayBuffer))}return this.blob().then(g)}),this.text=function(){var t,r,e,n=v(this);if(n)return n;if(this._bodyBlob)return t=this._bodyBlob,r=new FileReader,e=y(r),r.readAsText(t),e;if(this._bodyArrayBuffer)return Promise.resolve(function(t){for(var r=new Uint8Array(t),e=new Array(r.length),n=0;n<r.length;n++)e[n]=String.fromCharCode(r[n]);return e.join("")}(this._bodyArrayBuffer));if(this._bodyFormData)throw new Error("could not read FormData body as text");return Promise.resolve(this._bodyText)},a&&(this.formData=function(){return this.text().then(S)}),this.json=function(){return this.text().then(JSON.parse)},this}d.prototype.append=function(t,r){t=l(t),r=p(r);var e=this.map[t];this.map[t]=e?e+", "+r:r},d.prototype.delete=function(t){delete this.map[l(t)]},d.prototype.get=function(t){return t=l(t),this.has(t)?this.map[t]:null},d.prototype.has=function(t){return this.map.hasOwnProperty(l(t))},d.prototype.set=function(t,r){this.map[l(t)]=p(r)},d.prototype.forEach=function(t,r){for(var e in this.map)this.map.hasOwnProperty(e)&&t.call(r,this.map[e],e,this)},d.prototype.keys=function(){var t=[];return this.forEach((function(r,e){t.push(e)})),h(t)},d.prototype.values=function(){var t=[];return this.forEach((function(r){t.push(r)})),h(t)},d.prototype.entries=function(){var t=[];return this.forEach((function(r,e){t.push([e,r])})),h(t)},i&&(d.prototype[Symbol.iterator]=d.prototype.entries);var w=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];function x(t,r){if(!(this instanceof x))throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');var e,n,o=(r=r||{}).body;if(t instanceof x){if(t.bodyUsed)throw new TypeError("Already read");this.url=t.url,this.credentials=t.credentials,r.headers||(this.headers=new d(t.headers)),this.method=t.method,this.mode=t.mode,this.signal=t.signal,o||null==t._bodyInit||(o=t._bodyInit,t.bodyUsed=!0)}else this.url=String(t);if(this.credentials=r.credentials||this.credentials||"same-origin",!r.headers&&this.headers||(this.headers=new d(r.headers)),this.method=(e=r.method||this.method||"GET",n=e.toUpperCase(),w.indexOf(n)>-1?n:e),this.mode=r.mode||this.mode||null,this.signal=r.signal||this.signal,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&o)throw new TypeError("Body not allowed for GET or HEAD requests");if(this._initBody(o),!("GET"!==this.method&&"HEAD"!==this.method||"no-store"!==r.cache&&"no-cache"!==r.cache)){var i=/([?&])_=[^&]*/;if(i.test(this.url))this.url=this.url.replace(i,"$1_="+(new Date).getTime());else{this.url+=(/\?/.test(this.url)?"&":"?")+"_="+(new Date).getTime()}}}function S(t){var r=new FormData;return t.trim().split("&").forEach((function(t){if(t){var e=t.split("="),n=e.shift().replace(/\+/g," "),o=e.join("=").replace(/\+/g," ");r.append(decodeURIComponent(n),decodeURIComponent(o))}})),r}function E(t,r){if(!(this instanceof E))throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');r||(r={}),this.type="default",this.status=void 0===r.status?200:r.status,this.ok=this.status>=200&&this.status<300,this.statusText="statusText"in r?r.statusText:"",this.headers=new d(r.headers),this.url=r.url||"",this._initBody(t)}x.prototype.clone=function(){return new x(this,{body:this._bodyInit})},m.call(x.prototype),m.call(E.prototype),E.prototype.clone=function(){return new E(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new d(this.headers),url:this.url})},E.error=function(){var t=new E(null,{status:0,statusText:""});return t.type="error",t};var _=[301,302,303,307,308];E.redirect=function(t,r){if(-1===_.indexOf(r))throw new RangeError("Invalid status code");return new E(null,{status:r,headers:{location:t}})};var O=n.DOMException;try{new O}catch(t){(O=function(t,r){this.message=t,this.name=r;var e=Error(t);this.stack=e.stack}).prototype=Object.create(Error.prototype),O.prototype.constructor=O}function T(t,r){return new Promise((function(e,o){var i=new x(t,r);if(i.signal&&i.signal.aborted)return o(new O("Aborted","AbortError"));var a=new XMLHttpRequest;function s(){a.abort()}a.onload=function(){var t,r,n={status:a.status,statusText:a.statusText,headers:(t=a.getAllResponseHeaders()||"",r=new d,t.replace(/\r?\n[\t ]+/g," ").split(/\r?\n/).forEach((function(t){var e=t.split(":"),n=e.shift().trim();if(n){var o=e.join(":").trim();r.append(n,o)}})),r)};n.url="responseURL"in a?a.responseURL:n.headers.get("X-Request-URL");var o="response"in a?a.response:a.responseText;setTimeout((function(){e(new E(o,n))}),0)},a.onerror=function(){setTimeout((function(){o(new TypeError("Network request failed"))}),0)},a.ontimeout=function(){setTimeout((function(){o(new TypeError("Network request failed"))}),0)},a.onabort=function(){setTimeout((function(){o(new O("Aborted","AbortError"))}),0)},a.open(i.method,function(t){try{return""===t&&n.location.href?n.location.href:t}catch(r){return t}}(i.url),!0),"include"===i.credentials?a.withCredentials=!0:"omit"===i.credentials&&(a.withCredentials=!1),"responseType"in a&&(u?a.responseType="blob":c&&i.headers.get("Content-Type")&&-1!==i.headers.get("Content-Type").indexOf("application/octet-stream")&&(a.responseType="arraybuffer")),!r||"object"!=typeof r.headers||r.headers instanceof d?i.headers.forEach((function(t,r){a.setRequestHeader(r,t)})):Object.getOwnPropertyNames(r.headers).forEach((function(t){a.setRequestHeader(t,p(r.headers[t]))})),i.signal&&(i.signal.addEventListener("abort",s),a.onreadystatechange=function(){4===a.readyState&&i.signal.removeEventListener("abort",s)}),a.send(void 0===i._bodyInit?null:i._bodyInit)}))}T.polyfill=!0,n.fetch||(n.fetch=T,n.Headers=d,n.Request=x,n.Response=E)}},r={};function e(n){if(r[n])return r[n].exports;var o=r[n]={exports:{}};return t[n](o,o.exports,e),o.exports}e.d=function(t,r){for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},e.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),e.o=function(t,r){return Object.prototype.hasOwnProperty.call(t,r)},e(5666),e(1150),e(9712),e(7147),e(1391),e(9135)}();</script>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSans_W_Rg.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSerif_W_Rg.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSans_W_It.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSerif_W_It.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSans_W_Bd.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSerif_W_Bd.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSans_W_BdIt.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSerif_W_BdIt.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSans_W_Lt.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSerif_W_Lt.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSans_W_LtIt.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSerif_W_LtIt.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSans_W_ExBd.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSerif_W_ExBd.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSans_W_ExBdIt.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSerif_W_ExBdIt.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSans_W_Md.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSerif_W_Md.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSans_W_MdIt.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://static.files.bbci.co.uk/fonts/reith/r2.512/BBCReithSerif_W_MdIt.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="https://static.files.bbci.co.uk/orbit/7ba98e3db9d415f8cbdb0978bf084f9e/css/orb-ltr.min.css">
<script src="https://static.files.bbci.co.uk/orbit/7ba98e3db9d415f8cbdb0978bf084f9e/js/api-forge-free.min.js"></script>
<!-- navid Web Module: 0.2.0-45.c81e15f -->
<!-- searchbox Web Module: 3.0.0-217.84208de -->
<!-- navpromo Web Module: 3.0.0-180.408d858 -->
<!-- cookiebanner Web Module: 0.0.2-562.3a038b3 -->
<!-- useractivityhelper Web Module: 1.0.0-114.5385597 -->
<!-- reverb Web Module: 1.6.1 -->
<link rel="stylesheet" href="https://static.files.bbci.co.uk/account/id-cta/1.53.0/style/id-cta.css" /><!--[if IE 8]><link href="https://static.files.bbci.co.uk/account/id-cta/1.53.0/style/ie8.css" rel="stylesheet"/> <![endif]--><script type="text/javascript">(function() {if (!window.require) {throw new Error('idcta: could not find require module');}if (typeof(map) == 'undefined') {var map = {};}if (!!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect) {document.documentElement.className += ' id-svg';}var ptrt = new RegExp("[\\?&]ptrt=([^&]*)").exec(document.location.href);var ENDPOINT_URL = 'https://idcta.api.bbc.co.uk';var ENDPOINT_CONFIG = ('/idcta/config?callback=&ptrt=' + encodeURIComponent((ptrt ? ptrt[1] : document.location.href))).replace(/\&amp;/g, '&');var ENDPOINT_TRANSLATIONS = '/idcta/translations?callback=';function hasPromise() {var P = window.Promise;var promiseToString = null;if (P) {try {promiseToString = Object.prototype.toString.call(P.resolve());} catch(e) {/*silently ignored*/}}return (promiseToString === '[object Promise]' && !P.cast);}if (hasPromise()) {define('idcta/es6-promise', function() {return window.Promise;});define('idcta-v2/es6-promise', function() {return window.Promise;});}map['idcta-v2'] = 'https://static.files.bbci.co.uk/account/id-cta/1.53.0/modules/idcta-v2';map['idcta-v2/config'] = ENDPOINT_URL + ENDPOINT_CONFIG;map['idcta-v2/translations'] = ENDPOINT_URL + ENDPOINT_TRANSLATIONS;map['idcta'] = 'https://static.files.bbci.co.uk/account/id-cta/1.8.2/modules/idcta';map['idcta-v2/idcta-1'] = 'https://static.files.bbci.co.uk/account/id-cta/1.53.0/modules/idcta-v2/dist/idcta-1.min';map['idcta-v2/experiment-snippet'] = 'https://cdn.optimizely.com/public/4621041136/s/idcta_live';const idctaShim = {deps: ['idcta-v2/idcta-1'],};require({shim: {'idcta-v2/statusbar': idctaShim,'idcta-v2/id-config': idctaShim},map: {'*': {'idcta/idcta-1': 'idcta-v2/idcta-1','idcta': 'idcta-v2',}},paths: map});window.idctaBaseUrl = ENDPOINT_URL;define('idcta/config', ['idcta-v2/config'], function(data) {return data;});define('idcta/translations', ['idcta-v2/translations'], function(data) {return data;});})();</script>
<script type="text/javascript">
// Globally available search context
window.SEARCHBOX={"variant":"default","locale":"en","feature":"akamai-idcta","navSearchboxStaticPrefix":"https://nav.files.bbci.co.uk/searchbox/5bd951f6aac2ac491095aed2c248e936/","searchboxAppStaticPrefix":"https://nav.files.bbci.co.uk/searchbox/5bd951f6aac2ac491095aed2c248e936/drawer","searchFormHtml":"<div tabindex=\"-1\"><div><section class=\"se-searchbox-panel\"><div class=\"se-g-wrap\"><div class=\"se-g-layout\"><div class=\"se-g-layout__item se-searchbox-title\" aria-hidden=\"true\">search</div><div class=\"se-g-layout__item se-searchbox\"><form accept-charset=\"utf-8\" id=\"searchboxDrawerForm\" method=\"get\" action=\"https://search.bbc.co.uk/search\"><label class=\"se-searchbox__input\" for=\"se-searchbox-input-field\"><span class=\"se-sr-only\">Search Term</span><div><input type=\"text\" name=\"q\" value=\"\" id=\"se-searchbox-input-field\" class=\"se-searchbox__input__field\" maxLength=\"100\" autoComplete=\"off\" autoCorrect=\"off\" autoCapitalize=\"off\" spellcheck=\"false\" tabindex=\"0\"/></div></label><input type=\"hidden\" name=\"scope\" value=\"\"/><button type=\"submit\" class=\"se-searchbox__submit\" tabindex=\"0\" data-bbc-container=\"se-searchbox-panel\" data-bbc-title=\"search-icon\" data-bbc-metadata=\"{&quot;PAR&quot;:&quot;form::1&quot;,&quot;CHD&quot;:&quot;button::1&quot;}\" data-bbc-personalisation=\"{&quot;QRY&quot;:&quot;&quot;}\">Search</button><button type=\"button\" class=\"se-searchbox__clear se-searchbox__clear--visible\" tabindex=\"0\" data-bbc-container=\"se-searchbox-panel\" data-bbc-title=\"clear-icon\" data-bbc-metadata=\"{&quot;PAR&quot;:&quot;form::1&quot;,&quot;CHD&quot;:&quot;button::2&quot;}\" data-bbc-personalisation=\"{&quot;QRY&quot;:&quot;&quot;}\">Close</button></form></div></div></div></section><div aria-live=\"polite\" aria-atomic=\"true\" class=\"se-suggestions-container\"><section class=\"se-g-wrap\"></section></div></div></div>","searchScopePlaceholder":"","searchScopeParam":"","searchScopeTemplate":"","searchPlaceholderWrapperStart":"","searchPlaceholderWrapperEnd":""};
window.SEARCHBOX.searchScope = SEARCHBOX.searchScopeTemplate.split('-')[0];
</script>
<link rel="stylesheet" href="https://nav.files.bbci.co.uk/searchbox/5bd951f6aac2ac491095aed2c248e936/css/main.css">
<!--[if IE 8]>
<script type="text/javascript" src="https://nav.files.bbci.co.uk/searchbox/5bd951f6aac2ac491095aed2c248e936/script/html5shiv.min.js"></script>
<script type="text/javascript">window['searchboxIEVersion'] = 8;</script>
<link rel="stylesheet" href="https://nav.files.bbci.co.uk/searchbox/5bd951f6aac2ac491095aed2c248e936/css/ie8.css">
<![endif]-->
<!--[if IE 9]>
<script type="text/javascript">window['searchboxIEVersion'] = 9;</script>
<![endif]-->
<script type='text/javascript'>if (window.require !== undefined) {
require.config({
paths: {
'orb/cookies': 'https://nav.files.bbci.co.uk/orbit-webmodules/0.0.2-562.3a038b3/cookie-banner/cookie-library.min'
}
});
}</script>
<script type='text/javascript'>window.__detectview={clickManagementEnabled:false};</script>
<script type="text/javascript">"use strict";!function(){window.__reverbStaticLocation="https://mybbc-analytics.files.bbci.co.uk/reverb-client-js/",window.__smarttagVersion="5.22.0",window.__reverb={},window.__reverb.__reverbLoadedPromise=new Promise(function(e,n){window.__reverb.__resolveReverbLoaded=e,window.__reverb.__rejectReverbLoaded=n}),window.__reverb.__reverbTimeout=setTimeout(function(){window.__reverb.__rejectReverbLoaded()},5e3);var n=function(r,d){window.__reverb.__reverbLoadedPromise.then(function(e){if(r&&r.detail){var n=r.detail.label,t=r.detail.type,i=r.detail.elem,o=r.detail.originalEvent;r.detail.isClick&&(d=r.detail.isClick),e.userActionEvent(t,n,r.detail,i,o,d)}},function(){console.log("Reverb failed to load. Event not sent")})};document.addEventListener("bbc-user-event",function(e){n(e,!1)}),document.addEventListener("bbc-user-click",function(e){n(e,!0)}),document.addEventListener("bbc-page-updated",function(){window.__reverb.__reverbLoadedPromise.then(function(e){e.initialise().then(function(){return e.viewEvent()})},function(){console.log("Reverb failed to load. Event not sent")})})}();</script><script type='text/javascript' src='https://mybbc-analytics.files.bbci.co.uk/reverb-client-js/reverb-1.6.1.js' async></script>
<script>
window.require({
baseUrl: 'https://static.bbci.co.uk/',
paths: {
'bump-3': '//emp.bbci.co.uk/emp/bump-3/bump-3',
'bump-4': '//emp.bbci.co.uk/emp/bump-4/bump-4',
'jquery-1.9': 'https://static.bbci.co.uk/frameworks/jquery/0.4.1/sharedmodules/jquery-1.9.1',
},
waitSeconds: 30,
});
</script>
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: http: https: 'unsafe-inline' 'unsafe-eval'; frame-src edigitalsurvey.com chartbeat.com static2.chartbeat.com *.bbc.co.uk *.bbci.co.uk *.bbc.com *.bbci.com *.edigitalsurvey.com edigitalsurvey.com *.optimizely.com cdn-assets-prod.s3.amazonaws.com twitter.com *.twitter.com *.twimg.com riddle.com *.riddle.com; connect-src 'self' edigitalsurvey.com *.bbc.co.uk *.bbci.co.uk *.bbc.com *.bbci.com *.edigitalsurvey.com edigitalsurvey.com *.optimizely.com cdn-assets-prod.s3.amazonaws.com twitter.com *.twitter.com *.twimg.com; font-src 'self' *.bbc.co.uk *.bbci.co.uk *.bbc.com *.bbci.com *.edigitalsurvey.com edigitalsurvey.com *.optimizely.com cdn-assets-prod.s3.amazonaws.com twitter.com *.twitter.com *.twimg.com; form-action 'self' *.bbc.co.uk *.bbci.co.uk *.bbc.com *.bbci.com *.edigitalsurvey.com edigitalsurvey.com *.optimizely.com cdn-assets-prod.s3.amazonaws.com twitter.com *.twitter.com *.twimg.com; img-src 'self' app.optimizely.com cdn.optimizely.com data: https: http:; script-src 'self' static.chartbeat.com static2.chartbeat.com 'unsafe-inline' 'unsafe-eval' *.bbc.co.uk *.bbci.co.uk *.bbc.com *.bbci.com *.edigitalsurvey.com edigitalsurvey.com *.optimizely.com cdn-assets-prod.s3.amazonaws.com twitter.com *.twitter.com *.twimg.com optimizely.s3.amazonaws.com; style-src 'self' 'unsafe-inline' *.bbc.co.uk *.bbci.co.uk *.bbc.com *.bbci.com *.edigitalsurvey.com edigitalsurvey.com *.optimizely.com cdn-assets-prod.s3.amazonaws.com twitter.com *.twitter.com *.twimg.com" />
<title data-rh="true">Healthy pasta bake recipe - BBC Food</title>
<meta data-rh="true" property="og:title" content="Healthy pasta bake recipe"/><meta data-rh="true" property="og:site_name" content="BBC Food"/><meta data-rh="true" name="twitter:site" content="@BBCFood"/><meta data-rh="true" name="twitter:title" content="Healthy pasta bake recipe"/><meta data-rh="true" name="twitter:card" content="summary_large_image"/><meta data-rh="true" name="description" content="A fuss-free and healthy pasta bake that you can make in one dish, full of the flavours and colours of Mediterranean vegetables."/><meta data-rh="true" property="og:description" content="A fuss-free and healthy pasta bake that you can make in one dish, full of the flavours and colours of Mediterranean vegetables."/><meta data-rh="true" name="twitter:description" content="A fuss-free and healthy pasta bake that you can make in one dish, full of the flavours and colours of Mediterranean vegetables."/><meta data-rh="true" property="og:image" content="https://ichef.bbci.co.uk/food/ic/food_16x9_448/recipes/healthy_pasta_bake_60759_16x9.jpg"/><meta data-rh="true" property="og:image:secure_url" content="https://ichef.bbci.co.uk/food/ic/food_16x9_448/recipes/healthy_pasta_bake_60759_16x9.jpg"/><meta data-rh="true" property="og:image:type" content="image/jpeg"/><meta data-rh="true" property="og:image:width" content="448"/><meta data-rh="true" property="og:image:height" content="224"/><meta data-rh="true" property="og:image:alt" content="Healthy pasta bake recipe"/><meta data-rh="true" name="twitter:image" content="https://ichef.bbci.co.uk/food/ic/food_16x9_448/recipes/healthy_pasta_bake_60759_16x9.jpg"/><meta data-rh="true" property="og:url" content="https://www.bbc.co.uk/food/recipes/healthy_pasta_bake_60759"/>
<link data-rh="true" rel="canonical" href="https://www.bbc.co.uk/food/recipes/healthy_pasta_bake_60759"/><link data-rh="true" rel="amphtml" href="https://www.bbc.co.uk/food/recipes/healthy_pasta_bake_60759/amp"/>
</head>
<body >
<div id="cookiePrompt"></div> <noscript><p style="position: absolute; top: -999em"><img src="https://a1.api.bbc.co.uk/hit.xiti?&col=1&from=p&ptag=js&s=598253&p=Recipes::food.recipes.healthy_pasta_bake_60759.page&x1=[urn:bbc:food:recipes.healthy_pasta_bake_60759]&x2=[responsive]&x3=[bbc_website]&x4=[en]&x7=[article]&x8=[reverb-1.6.1-nojs]&x11=[FOOD]&x12=[FOOD]" height="1" width="1" alt=""></p></noscript> <header id="orb-banner" role="banner" aria-label="BBC"><div id="orb-header" class="orb-nav-pri orb-nav-pri-white orb-nav-empty" dir="ltr"><div class="orb-nav-pri-container b-r b-g-p"><div class="orb-nav-section orb-nav-blocks"><a href="https://www.bbc.co.uk">Homepage</a></div><section><div class="orb-skip-links"><h2>Accessibility links</h2><ul><li><a href="#orb-modules">Skip to content</a></li><li><a id="orb-accessibility-help" href="https://www.bbc.co.uk/accessibility/">Accessibility Help</a></li></ul></div></section><div id="mybbc-wrapper" class="orb-nav-section orb-nav-id orb-nav-focus orb-nav-id-default"> <div id="idcta-statusbar" class="orb-nav-section orb-nav-focus" data-bbc-container="id-cta" data-bbc-event-type="click" data-bbc-ignore-views="1" data-bbc-metadata="{&quot;id-cta-type&quot;: &quot;statusbar-orb&quot;}" data-bbc-source="responsive_web" data-bbc-title="id-cta-sign-in"><a id="idcta-link" href="https://account.bbc.com/account"><span id="idcta-username">BBC Account</span></a></div><script type="text/javascript">require(['idcta/statusbar'], function (statusbar) {new statusbar.Statusbar({id: 'idcta-statusbar', publiclyCacheable: true});});</script><!-- Because we are now loading the notification bell CSS asynchronously, we need this inline style hack to ensure that the notification div
is hidden by default, and shown only if and when the bell code is loaded from notification-ui --><a id="notification-link" class="js-notification-link animated three" href="#" style="display: none"><span class="hidden-span">Notifications</span><div class="notification-link--triangle"></div><div class="notification-link--triangle"></div><span id="not-num"></span></a> </div><nav role="navigation" aria-label="BBC" class="orb-nav"><div class="orb-nav-section orb-nav-links orb-nav-focus" id="orb-nav-links"><ul><li class="orb-nav-home"><a href="https://www.bbc.co.uk">Home</a></li><li class="orb-nav-news"><a href="https://www.bbc.co.uk/news">News</a></li><li class="orb-nav-sport"><a href="https://www.bbc.co.uk/sport">Sport</a></li><li class="orb-nav-weather"><a href="https://www.bbc.co.uk/weather">Weather</a></li><li class="orb-nav-iplayer"><a href="https://www.bbc.co.uk/iplayer">iPlayer</a></li><li class="orb-nav-sounds"><a href="https://www.bbc.co.uk/sounds">Sounds</a></li><li class="orb-nav-cbbc"><a href="https://www.bbc.co.uk/cbbc">CBBC</a></li><li class="orb-nav-cbeebies"><a href="https://www.bbc.co.uk/cbeebies">CBeebies</a></li><li class="orb-nav-food"><a href="https://www.bbc.co.uk/food">Food</a></li><li class="orb-nav-bitesize"><a href="https://www.bbc.co.uk/bitesize">Bitesize</a></li><li class="orb-nav-arts"><a href="https://www.bbc.co.uk/arts">Arts</a></li><li class="orb-nav-taster"><a href="https://www.bbc.co.uk/taster">Taster</a></li><li class="orb-nav-local"><a href="https://www.bbc.co.uk/news/localnews">Local</a></li><li class="orb-nav-three"><a href="https://www.bbc.co.uk/bbcthree">Three</a></li><li id="orb-nav-more" style="width: 88px" aria-controls="orb-panel-more"><a href="#orb-footer" data-alt="More" class="istats-notrack">Menu<span class="orb-icon orb-icon-arrow"></span></a></li></ul></div></nav><div class="orb-nav-section orb-nav-search"> <a class="orb-search__button" href="https://search.bbc.co.uk/search" title="Search the BBC">Search</a><form class="b-f" id="orb-search-form" role="search" method="get" action="https://search.bbc.co.uk/search" accept-charset="utf-8"><div><label for="orb-search-q">Search the BBC</label><input id="orb-search-q" type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" maxlength="100" name="q" placeholder="Search"><button id="orb-search-button" class="orb-search__button">Search the BBC</button><input type="hidden" name="suggid" id="orb-search-suggid"></div></form> </div></div><div id="orb-panels"></div></div></header> <!-- Styling hook for shared modules only -->
<div id="orb-modules">
<div id="main-content"><div class="food-body gel-pica"><div class="gel-wrap page-title"><div class="header-wrap"><a class="page-title__logo" href="/food" title="Food homepage">Food</a><div class="searchbar searchbar--desktop"><form action="/food/search" method="GET" autoComplete="off" class="searchbar__search-form"><div class="searchbar__input-container"><input type="text" class="searchbar__input" name="q" value=""/><input type="submit" aria-label="Search BBC Food&#x27;s recipes" class="searchbar__search-button" id="searchbar-search-button" name="searchButton" value=""/><button class="searchbar__close-button" type="button"></button></div></form></div></div></div><div class="main-menu main-menu--full-width"><nav class="main-menu__navigation"><ul class="main-menu__primary-navigation gel-wrap"><li class="main-menu__item main-menu__item--primary main-menu__item--home"><a aria-label="Home" class="main-menu__link gel-brevier" href="/food/">Home</a></li><li class="main-menu__item main-menu__item--primary main-menu__item--recipes main-menu__item--active"><a aria-label="Recipes" class="main-menu__link gel-brevier" href="/food/recipes">Recipes<span class="main-menu__item__icon"></span></a><div class="main-menu__secondary-nav__bg"><ul class="main-menu__secondary-navigation gel-wrap"><li class="main-menu__secondary-item "><a aria-label="In Season" class="main-menu__secondary-link gel-brevier" href="/food/seasons">In Season</a></li><li class="main-menu__secondary-item "><a aria-label="Occasions" class="main-menu__secondary-link gel-brevier" href="/food/occasions">Occasions</a></li><li class="main-menu__secondary-item "><a aria-label="Cuisines" class="main-menu__secondary-link gel-brevier" href="/food/cuisines">Cuisines</a></li><li class="main-menu__secondary-item "><a aria-label="Ingredients" class="main-menu__secondary-link gel-brevier" href="/food/ingredients">Ingredients</a></li><li class="main-menu__secondary-item "><a aria-label="Dishes" class="main-menu__secondary-link gel-brevier" href="/food/dishes">Dishes</a></li><li class="main-menu__secondary-item "><a aria-label="Collections" class="main-menu__secondary-link gel-brevier" href="/food/collections">Collections</a></li></ul></div></li><li class="main-menu__item main-menu__item--primary main-menu__item--budget"><a aria-label="Budget Recipes" class="main-menu__link gel-brevier" href="/food/budget">Budget Recipes</a></li><li class="main-menu__item main-menu__item--primary main-menu__item--chefs"><a aria-label="Chefs" class="main-menu__link gel-brevier" href="/food/chefs">Chefs</a></li><li class="main-menu__item main-menu__item--primary main-menu__item--stories"><a aria-label="Stories" class="main-menu__link gel-brevier" href="/food/articles">Stories</a></li><li class="main-menu__item main-menu__item--primary main-menu__item--diets"><a aria-label="Diets" class="main-menu__link gel-brevier" href="/food/diets">Diets</a></li><li class="main-menu__item main-menu__item--primary main-menu__item--programmes"><a aria-label="Programmes" class="main-menu__link gel-brevier" href="/food/programmes">Programmes</a></li><li class="main-menu__item main-menu__item--primary main-menu__item--techniques"><a aria-label="Techniques" class="main-menu__link gel-brevier" href="/food/techniques">Techniques</a></li><li class="main-menu__item main-menu__item--favorites"><a class="main-menu__link gel-brevier" href="/food/my/favourites">Your Favourites</a></li></ul></nav></div><div class="gel-wrap"><div class="searchbar searchbar--mobile"><form action="/food/search" method="GET" autoComplete="off" class="searchbar__search-form"><div class="searchbar__input-container"><input type="text" class="searchbar__input" name="q" value=""/><input type="submit" aria-label="Search BBC Food&#x27;s recipes" class="searchbar__search-button" id="searchbar-search-button" name="searchButton" value=""/><button class="searchbar__close-button" type="button"></button></div></form></div></div><div class="food-grid food-grid--full-width"><div class="food-content-wrapper"><div class="recipe-wrap gel-wrap"><div class="gel-layout"><div class="recipe-main-info gel-layout__item gel-1/1 gel-2/3@l"><div class="gel-layout"><div class="gel-layout__item gel-1/1 gel-2/3@m gel-3/4@l recipe-title--small-spacing"><h1 class="gel-trafalgar content-title__text">Healthy pasta bake</h1></div></div><div class="recipe-ratings"><div><div class="recipe-ratings--cta gel-pica"><span class="recipe-ratings--loading-icon"></span><span class="recipe-ratings--loading-text">Loading</span></div></div></div><div class="recipe-leading-info"><div class="gel-layout"><div class="gel-layout__item gel-1/1 gel-3/4@l"><div class="recipe-media"><div class="recipe-media__image responsive-image-container__16/9"><img alt="Healthy pasta bake" class="" src="https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/healthy_pasta_bake_60759_16x9.jpg" srcSet="https://ichef.bbci.co.uk/food/ic/food_16x9_160/recipes/healthy_pasta_bake_60759_16x9.jpg 160w, https://ichef.bbci.co.uk/food/ic/food_16x9_208/recipes/healthy_pasta_bake_60759_16x9.jpg 208w, https://ichef.bbci.co.uk/food/ic/food_16x9_320/recipes/healthy_pasta_bake_60759_16x9.jpg 320w, https://ichef.bbci.co.uk/food/ic/food_16x9_448/recipes/healthy_pasta_bake_60759_16x9.jpg 448w, https://ichef.bbci.co.uk/food/ic/food_16x9_608/recipes/healthy_pasta_bake_60759_16x9.jpg 608w, https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/healthy_pasta_bake_60759_16x9.jpg 832w, https://ichef.bbci.co.uk/food/ic/food_16x9_1600/recipes/healthy_pasta_bake_60759_16x9.jpg 1600w"/></div></div><div class="recipe-leading-info__main-metadata"><div class="gel-layout"><div class="recipe-metadata-wrap gel-layout__item gel-1/2 gel-1/1@l gel-pica"><p class="recipe-metadata__heading gel-long-primer">Preparation time</p><p class="recipe-metadata__prep-time" content="PT30M">less than 30 mins</p></div><div class="recipe-metadata-wrap gel-layout__item gel-1/2 gel-1/1@l gel-pica"><p class="recipe-metadata__heading gel-long-primer">Cooking time</p><p class="recipe-metadata__cook-time" content="PT1H">30 mins to 1 hour</p></div><div class="recipe-metadata-wrap gel-layout__item gel-1/2 gel-1/1@l gel-pica"><p class="recipe-metadata__heading gel-long-primer">Serves</p><p class="recipe-metadata__serving">Serves 4</p></div><div class="recipe-metadata-wrap gel-layout__item gel-1/2 gel-1/1@l gel-pica"><p class="recipe-metadata__heading gel-long-primer">Dietary</p><div class="recipe-metadata__dietary"><a href="/food/diets/vegetarian" class="recipe-metadata__dietary-vegetarian"> <p class="recipe-metadata__dietary-vegetarian-text">Vegetarian</p></a></div></div></div></div><div class="recipe-description"><p class="recipe-description__text">A fuss-free and healthy pasta bake that you can make in one dish. It's packed with the flavours and colours of Mediterranean vegetables and topped with pine nuts for crunch. <br/><br/>
Each serving provides 375 kcal, 12g protein, 27g carbohydrates (of which 11g sugars), 22g fat (of which 5g saturates), 8g fibre and 0.95g salt.</p></div><div class="chef gel-brevier"><a class="chef__image-link" href="/food/chefs/justine_pattison" title="Justine Pattison"><div class="chef__image"><img alt="" class="lazyload" data-src="https://ichef.bbci.co.uk/food/ic/food_1x1_72/chefs/justine_pattison_1x1.jpg" data-sizes="auto"/><noscript><img alt="" src="https://ichef.bbci.co.uk/food/ic/food_1x1_72/chefs/justine_pattison_1x1.jpg"/></noscript></div></a><div class="chef__about"><div class="chef__name"><span class="gel-brevier-bold">By</span> <a class="chef__link" href="/food/chefs/justine_pattison">Justine Pattison</a></div></div></div><div class="recipe-actions gel-layout"><div class="recipe-actions-wrap gel-layout__item gel-1/1 gel-1/2@m" id="share-component-btn-container"><div class="ec-share-tools"><button class="ec-share-button ec-share-button__share"><span class="ec-share-icon__svg"><svg focusable="false" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 32 32"><path d="M6.8 22.2c1.6 0 3-.7 4-1.8l9 4.8c-.1.4-.2.8-.2 1.3 0 3 2.5 5.5 5.5 5.5s5.5-2.4 5.5-5.5-2.5-5.5-5.5-5.5c-1.6 0-3 .7-4 1.8l-9.5-5.2-.1-2.8 9.7-5.5c1 1 2.3 1.5 3.8 1.5 3 0 5.5-2.5 5.5-5.5S28.2 0 25.2 0s-5.5 2.4-5.5 5.5c0 .6.1 1.1.2 1.6l-9.3 5.7c-1-.9-2.3-1.5-3.8-1.5-3 0-5.5 2.4-5.5 5.5.1 2.9 2.5 5.4 5.5 5.4z"></path></svg></span><span class="ec-share-cta-text">Share</span></button><div class="ec-share-panel"><div class="ec-share-panel__header"><span class="ec-share-panel__header-text">Share this with</span><button class="ec-share-panel__close-button"><span class="ec-share-panel__close-button-icon"><svg focusable="false" viewBox="0 0 32 32" width="16" height="16"><path d="M32 3.5L28.5 0 16 12.5 3.5 0 0 3.5 12.5 16 0 28.5 3.5 32 16 19.5 28.5 32l3.5-3.5L19.5 16"></path></svg></span></button></div><div class="ec-share-panel__body"><ul class="ec-share-panel__items"><li class="ec-share-panel__item"><button class="ec-share-button ec-share-button--transparent ec-share-button--facebook"><span class="ec-share-icon__svg ec-share-icon__svg--facebook"><svg focusable="false" viewBox="0 0 32 32"><path d="M12.1 32V17H8v-5.4h4.1V7c0-3.6 2.4-7 8-7 2.2 0 3.9.2 3.9.2l-.1 5.1h-3.6c-2 0-2.3.9-2.3 2.4v3.9h6l-.3 5.4H18v15h-5.9z"></path></svg></span><span class="ec-share-cta-text">Facebook</span></button></li><li class="ec-share-panel__item"><button class="ec-share-button ec-share-button--transparent ec-share-button--twitter"><span class="ec-share-icon__svg ec-share-icon__svg--twitter"><svg focusable="false" viewBox="0 0 32 32"><path d="M32 6.1c-1.2.5-2.4.9-3.8 1 1.4-.8 2.4-2.1 2.9-3.6-1.3.8-2.7 1.3-4.2 1.6C25.7 3.8 24 3 22.2 3c-3.6 0-6.6 2.9-6.6 6.6 0 .5.1 1 .2 1.5-5.5-.3-10.3-2.9-13.6-6.9-.6 1-.9 2.1-.9 3.3 0 2.3 1.2 4.3 2.9 5.5-1.1 0-2.1-.3-3-.8v.1c0 3.2 2.3 5.8 5.3 6.4-.6.1-1.1.2-1.7.2-.4 0-.8 0-1.2-.1.8 2.6 3.3 4.5 6.1 4.6-2.2 1.8-5.1 2.8-8.2 2.8-.5 0-1.1 0-1.6-.1 3 1.8 6.5 2.9 10.2 2.9 12.1 0 18.7-10 18.7-18.7v-.9c1.2-.9 2.3-2 3.2-3.3z"></path></svg></span><span class="ec-share-cta-text">Twitter</span></button></li><li class="ec-share-panel__item"><button class="ec-share-button ec-share-button--transparent ec-share-button--pinterest"><span class="ec-share-icon__svg ec-share-icon__svg--pinterest"><svg focusable="false" viewBox="-3 -3 82 82"><path d="M27.5 71c3.3 1 6.7 1.6 10.3 1.6C57 72.6 72.6 57 72.6 37.8 72.6 18.6 57 3 37.8 3 18.6 3 3 18.6 3 37.8c0 14.8 9.3 27.5 22.4 32.5-.3-2.7-.6-7.2 0-10.3l4-17.2s-1-2-1-5.2c0-4.8 3-8.4 6.4-8.4 3 0 4.4 2.2 4.4 5 0 3-2 7.3-3 11.4C35.6 49 38 52 41.5 52c6.2 0 11-6.6 11-16 0-8.3-6-14-14.6-14-9.8 0-15.6 7.3-15.6 15 0 3 1 6 2.6 8 .3.2.3.5.2 1l-1 3.8c0 .6-.4.8-1 .4-4.4-2-7-8.3-7-13.4 0-11 7.8-21 22.8-21 12 0 21.3 8.6 21.3 20 0 12-7.4 21.6-18 21.6-3.4 0-6.7-1.8-7.8-4L32 61.7c-.8 3-3 7-4.5 9.4z"></path></svg></span><span class="ec-share-cta-text">Pinterest</span></button></li><li class="ec-share-panel__item"><button class="ec-share-button ec-share-button--transparent ec-share-button--whatsapp"><span class="ec-share-icon__svg ec-share-icon__svg--whatsapp"><svg focusable="false" viewBox="0 0 24 24"><path d="M.057 24l1.687-6.163c-1.041-1.804-1.588-3.849-1.587-5.946.003-6.556 5.338-11.891 11.893-11.891 3.181.001 6.167 1.24 8.413 3.488 2.245 2.248 3.481 5.236 3.48 8.414-.003 6.557-5.338 11.892-11.893 11.892-1.99-.001-3.951-.5-5.688-1.448l-6.305 1.654zm6.597-3.807c1.676.995 3.276 1.591 5.392 1.592 5.448 0 9.886-4.434 9.889-9.885.002-5.462-4.415-9.89-9.881-9.892-5.452 0-9.887 4.434-9.889 9.884-.001 2.225.651 3.891 1.746 5.634l-.999 3.648 3.742-.981zm11.387-5.464c-.074-.124-.272-.198-.57-.347-.297-.149-1.758-.868-2.031-.967-.272-.099-.47-.149-.669.149-.198.297-.768.967-.941 1.165-.173.198-.347.223-.644.074-.297-.149-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.297-.347.446-.521.151-.172.2-.296.3-.495.099-.198.05-.372-.025-.521-.075-.148-.669-1.611-.916-2.206-.242-.579-.487-.501-.669-.51l-.57-.01c-.198 0-.52.074-.792.372s-1.04 1.016-1.04 2.479 1.065 2.876 1.213 3.074c.149.198 2.095 3.2 5.076 4.487.709.306 1.263.489 1.694.626.712.226 1.36.194 1.872.118.571-.085 1.758-.719 2.006-1.413.248-.695.248-1.29.173-1.414z"></path></svg></span><span class="ec-share-cta-text">WhatsApp</span></button></li><li class="ec-share-panel__item"><button class="ec-share-button ec-share-button--transparent ec-share-button--yummly"><span class="ec-share-icon__svg ec-share-icon__svg--yummly"><svg focusable="false" viewBox="-3 0 29 29"><path d="m23.55,22c0,-0.2 -0.2,-0.3 -0.3,-0.3c-0.3,-0.1 -0.5,0 -1.3,-0.4c-0.6,-0.3 -3.5,-1.7 -7.5,-2.1l2.9,-16.4c0.1,-0.7 0.1,-1.3 -0.1,-1.7c-0.3,-0.6 -1.1,-0.7 -1.9,-0.6c-0.7,0.1 -1.2,0.3 -1.3,0.4s-0.2,0.2 -0.2,0.4c0,0.3 0.3,0.6 0.1,1.7c0,0.3 -1,5.5 -1.8,10c-2.1,1.3 -4.9,1.9 -5.5,1.1c-0.3,-0.4 -0.2,-1.1 0.1,-2.2c0.1,-0.2 1.3,-4.9 1.6,-6.3c0.7,-2.6 0.2,-4.9 -2.5,-5.2c-2.3,-0.2 -4.5,1.1 -5.2,1.9c-0.5,0.5 -0.3,1.1 0.1,1.9c0.3,0.6 0.8,1 0.9,1c0.1,0.1 0.3,0.1 0.4,0c0.8,-0.9 2.2,-1.5 2.7,-1.1c0.4,0.4 0.3,1 0.1,1.7c0,0 -1.5,5.6 -2.1,8c-0.4,1.7 0,3.3 1.3,4.1c0.9,0.6 2.3,0.5 3.4,0.4c2.4,-0.3 3.8,-1.3 4,-1.5c-0.3,1.5 -0.4,2.5 -0.4,2.5s-2.7,0.2 -4.9,1.6c-2.9,1.7 -4.1,5.7 -2.2,7.8c1.9,2.1 5.1,1.3 6.5,0.4c1.3,-0.9 2.9,-2.7 3.7,-6.8c4.4,0.2 5.5,2.5 7.4,2.6c1.2,-0.2 2.1,-1.5 2,-2.9zm-15,4c-0.6,0.4 -1.3,0.4 -1.7,0c-0.4,-0.5 -0.5,-3.1 3.6,-3.8c0,-0.1 -0.7,3 -1.9,3.8z" id="svg_8"></path></svg></span><span class="ec-share-cta-text">Yummly</span></button></li><li class="ec-share-panel__item"><div class="ec-share-copy-link"><label class="ec-share-copy-link__text">Copy link</label><input type="text" class="ec-share-copy-link__input" readonly="" value=""/></div></li><li class="ec-share-panel__item"><a class="ec-share-panel__read-more-link" href="http://www.bbc.co.uk/faqs/questions/bbc_online/sharing">Read more about sharing.</a></li></ul></div></div></div></div><div class="recipe-actions-wrap gel-layout__item gel-1/1 gel-1/2@m" id="add-to-favourites-btn-container"><div class="my-favourites-recipes__start-adding recipe-actions-text--button"><button class="recipe-actions-link__button gel-long-primer" disabled="" id="add-to-favourites-button" name="favouritesLink" type="button"><span name="favouritesLinkIcon" class="recipe-actions__favourites-icon recipe-actions__adding-favourites-icon"></span>Loading<!-- --> </button></div></div><div class="recipe-actions-wrap gel-layout__item gel-1/1 gel-1/2@m gel-long-primer"><p class="my-favourites-recipes__start-adding recipe-actions-text--button"><a class="recipe-actions-link__button" href="/food/recipes/healthy_pasta_bake_60759/shopping-list"><span class="recipe-actions__shopping-list-icon"></span>Shopping list</a></p></div><div class="recipe-actions-wrap gel-layout__item gel-1/1 gel-1/2@m gel-long-primer"><div class="my-favourites-recipes__start-adding recipe-actions-text--button"><button class="recipe-actions-link__button" id="print-recipe-button" name="printButton" type="button"><span class="recipe-actions__print-link-icon"></span>Print recipe</button></div></div></div></div><div class="gel-layout__item gel-1/4 recipe-leading-info__side-bar"><div class="gel-layout"><div class="recipe-metadata-wrap gel-layout__item gel-1/2 gel-1/1@l gel-pica"><p class="recipe-metadata__heading gel-long-primer">Preparation time</p><p class="recipe-metadata__prep-time" content="PT30M">less than 30 mins</p></div><div class="recipe-metadata-wrap gel-layout__item gel-1/2 gel-1/1@l gel-pica"><p class="recipe-metadata__heading gel-long-primer">Cooking time</p><p class="recipe-metadata__cook-time" content="PT1H">30 mins to 1 hour</p></div><div class="recipe-metadata-wrap gel-layout__item gel-1/2 gel-1/1@l gel-pica"><p class="recipe-metadata__heading gel-long-primer">Serves</p><p class="recipe-metadata__serving">Serves 4</p></div><div class="recipe-metadata-wrap gel-layout__item gel-1/2 gel-1/1@l gel-pica"><p class="recipe-metadata__heading gel-long-primer">Dietary</p><div class="recipe-metadata__dietary"><a href="/food/diets/vegetarian" class="recipe-metadata__dietary-vegetarian"> <p class="recipe-metadata__dietary-vegetarian-text">Vegetarian</p></a></div></div></div></div></div></div><div class="gel-layout recipe-ingredient-list"><div class="gel-layout__item"><div class="recipe-ingredients-wrapper"><h2 class="recipe-ingredients__heading gel-double-pica">Ingredients</h2><ul class="recipe-ingredients__list"><li class="recipe-ingredients__list-item">2 tbsp <a href="/food/olive_oil" class="recipe-ingredients__link">olive oil</a></li><li class="recipe-ingredients__list-item">1 <a href="/food/red_onion" class="recipe-ingredients__link">red onion</a>, roughly chopped</li><li class="recipe-ingredients__list-item">1 yellow or red <a href="/food/pepper" class="recipe-ingredients__link">pepper</a>, deseeded and cut into roughly 1.5cm/⅝in chunks</li><li class="recipe-ingredients__list-item">1 <a href="/food/courgette" class="recipe-ingredients__link">courgette</a> (approx. 225g/8oz), quartered lengthways and cut into roughly 1.5cm/⅝in chunks </li><li class="recipe-ingredients__list-item">1 small <a href="/food/aubergine" class="recipe-ingredients__link">aubergine</a> (approx. 250g/9oz), cut into roughly 1.5cm/⅝in chunks </li><li class="recipe-ingredients__list-item">2 large <a href="/food/garlic" class="recipe-ingredients__link">garlic</a> cloves, crushed</li><li class="recipe-ingredients__list-item">4 tbsp sun-dried tomato or red pepper <a href="/food/pesto" class="recipe-ingredients__link">pesto</a> </li><li class="recipe-ingredients__list-item">400g tin <a href="/food/chopped_tomatoes" class="recipe-ingredients__link">chopped tomatoes</a></li><li class="recipe-ingredients__list-item">100g/3½oz wholewheat <a href="/food/penne" class="recipe-ingredients__link">penne</a> pasta</li><li class="recipe-ingredients__list-item">75g/2¾oz young <a href="/food/spinach" class="recipe-ingredients__link">spinach</a> leaves, tough stalks removed</li><li class="recipe-ingredients__list-item">50g/1¾oz mature <a href="/food/cheddar_cheese" class="recipe-ingredients__link">cheddar</a>, grated</li><li class="recipe-ingredients__list-item">2 tbsp <a href="/food/pine_nut" class="recipe-ingredients__link">pine nuts</a></li><li class="recipe-ingredients__list-item">salt and freshly ground <a href="/food/black_pepper" class="recipe-ingredients__link">black pepper</a></li></ul></div></div></div><div class="gel-layout"><div class="recipe-quick-links gel-layout__item gel-1/1"><div class="recipe-quick-links-wrapper"><a href="#recipe-tips" class="recipe-quick-link recipe-quick-link--tips gel-long-primer"><span class="recipe-quick-link__icon"></span><span class="recipe-quick-link__text">Recipe tips</span></a></div></div></div><div class="gel-layout recipe-method-list"><div class="recipe-method gel-layout__item"><div class="recipe-method-wrapper"><h2 class="recipe-method__heading gel-double-pica">Method</h2><ol class="recipe-method__list"><li class="recipe-method__list-item"><p class="recipe-method__list-item-text">Preheat the oven to 200C/180 Fan/Gas 6. </p></li><li class="recipe-method__list-item"><p class="recipe-method__list-item-text">Heat the oil in a flameproof casserole. Add the onion, pepper, courgette and aubergine, season with a little salt and lots of pepper and fry over a medium heat for about 8 minutes, or until softened and lightly browned, stirring regularly. Add the garlic and cook for 1 minute, then stir in the pesto and cook for 1 minute more, stirring constantly.</p></li><li class="recipe-method__list-item"><p class="recipe-method__list-item-text">Tip the tomatoes into the casserole, then fill the tomato tin with water and pour into the pan. Add the pasta and bring to a simmer, stirring regularly. Cover with a lid, or if you prefer tip into a baking dish and cover with foil, and bake for 20 minutes. </p></li><li class="recipe-method__list-item"><p class="recipe-method__list-item-text">Take the casserole out of the oven and stir in the spinach, a handful at a time. Once all the spinach has been mixed in, sprinkle the cheese and pine nuts over the top. Return to the oven and cook, uncovered, for a further 10 minutes, until the pasta is tender.</p></li></ol></div></div></div><div id="recipe-tips" class="recipe-extra-information__wrapper gel-wrap"><div class="recipe-extra-information__item gel-layout"><div class="gel-layout__item gel-1/1"><span class="recipe-extra-information__icon recipe-extra-information__icon--tips"></span><h3 class="recipe-extra-information__title gel-great-primer-bold">Recipe Tips</h3><p class="recipe-extra-information__text gel-pica">If you dont have wholewheat penne, use another shape, such as fusilli. You can also use traditional pasta, but the overall fibre content wont be quite as high.</p><p class="recipe-extra-information__text gel-pica">The red pesto adds lots of flavour; green basil pesto also works well.</p></div></div></div></div><div class="grid-list-wrapper gel-layout__item gel-1/1 gel-1/3@l"><a class="seasonal-promo-block" href="/food/diets/healthy" style="background-image:url(https://food-images.files.bbci.co.uk/food/timed_promos/healthynewyear.jpg)"><div><p class="gel-double-pica-bold" style="color:#404040">Healthy</p><p class="gel-double-pica seasonal-promo-block__recipes" style="color:#606060">New Year<!-- --> <span class="icon icon--next" aria-label="Next"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><polygon points="26,16 0,0 0,7.2 14.6,16 0,24.8 0,32"></polygon></svg></span></p></div></a><div class="grid-list-panel--dark"><div class="grid-list-panel__item"><div class="related-recipes__content gel-wrap"><div class="related-recipes__item related-recipes__item--primary"><h2 class="related-recipes__header gel-great-primer">Related Recipes</h2><div class="related-recipes__about related-recipes__about--collection"><a href="/food/recipes/salmon_stir-fry_63266" class="related-recipes__image-link"><div class="related-recipes__image-container gel-1/1"><div class="related-recipes__image gel-1/1 responsive-image-container__16/9"><img alt="" class="lazyload" data-src="https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/salmon_stir-fry_63266_16x9.jpg" data-srcset="https://ichef.bbci.co.uk/food/ic/food_16x9_160/recipes/salmon_stir-fry_63266_16x9.jpg 160w, https://ichef.bbci.co.uk/food/ic/food_16x9_208/recipes/salmon_stir-fry_63266_16x9.jpg 208w, https://ichef.bbci.co.uk/food/ic/food_16x9_320/recipes/salmon_stir-fry_63266_16x9.jpg 320w, https://ichef.bbci.co.uk/food/ic/food_16x9_448/recipes/salmon_stir-fry_63266_16x9.jpg 448w, https://ichef.bbci.co.uk/food/ic/food_16x9_608/recipes/salmon_stir-fry_63266_16x9.jpg 608w, https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/salmon_stir-fry_63266_16x9.jpg 832w, https://ichef.bbci.co.uk/food/ic/food_16x9_1600/recipes/salmon_stir-fry_63266_16x9.jpg 1600w" data-sizes="auto"/><noscript><img alt="" src="https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/salmon_stir-fry_63266_16x9.jpg" srcSet="https://ichef.bbci.co.uk/food/ic/food_16x9_160/recipes/salmon_stir-fry_63266_16x9.jpg 160w, https://ichef.bbci.co.uk/food/ic/food_16x9_208/recipes/salmon_stir-fry_63266_16x9.jpg 208w, https://ichef.bbci.co.uk/food/ic/food_16x9_320/recipes/salmon_stir-fry_63266_16x9.jpg 320w, https://ichef.bbci.co.uk/food/ic/food_16x9_448/recipes/salmon_stir-fry_63266_16x9.jpg 448w, https://ichef.bbci.co.uk/food/ic/food_16x9_608/recipes/salmon_stir-fry_63266_16x9.jpg 608w, https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/salmon_stir-fry_63266_16x9.jpg 832w, https://ichef.bbci.co.uk/food/ic/food_16x9_1600/recipes/salmon_stir-fry_63266_16x9.jpg 1600w"/></noscript></div></div></a><div class="related-recipes__information"><a href="/food/recipes/salmon_stir-fry_63266" class="related-recipes__title-link"><h3 class="related-recipes__title gel-pica-bold">Salmon stir-fry </h3></a><p class="related-recipes__author gel-long-primer"><strong>By</strong> <span class="related-recipes__author-name">Justine Pattison</span></p></div></div><p class="related-recipes__more gel-long-primer"><strong>See more</strong> <a href="/food/collections/flavours_of_the_mediterranean" class="related-recipes__more-link"><span class="related-recipes__more-name">Healthy Mediterranean </span> recipes<!-- --> <span class="related-recipes__more-amount">(38)</span></a></p></div><div class="related-recipes__item related-recipes__item--secondary"><div class="related-recipes__about related-recipes__about--dish"><a href="/food/recipes/chicken_and_chorizo_51929" class="related-recipes__image-link"><div class="related-recipes__image-container gel-1/2 gel-1/1@m gel-1/2@l"><div class="related-recipes__image gel-1/1 responsive-image-container__16/9"><img alt="" class="lazyload" data-src="https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/chicken_and_chorizo_51929_16x9.jpg" data-srcset="https://ichef.bbci.co.uk/food/ic/food_16x9_160/recipes/chicken_and_chorizo_51929_16x9.jpg 160w, https://ichef.bbci.co.uk/food/ic/food_16x9_208/recipes/chicken_and_chorizo_51929_16x9.jpg 208w, https://ichef.bbci.co.uk/food/ic/food_16x9_320/recipes/chicken_and_chorizo_51929_16x9.jpg 320w, https://ichef.bbci.co.uk/food/ic/food_16x9_448/recipes/chicken_and_chorizo_51929_16x9.jpg 448w, https://ichef.bbci.co.uk/food/ic/food_16x9_608/recipes/chicken_and_chorizo_51929_16x9.jpg 608w, https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/chicken_and_chorizo_51929_16x9.jpg 832w, https://ichef.bbci.co.uk/food/ic/food_16x9_1600/recipes/chicken_and_chorizo_51929_16x9.jpg 1600w" data-sizes="auto"/><noscript><img alt="" src="https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/chicken_and_chorizo_51929_16x9.jpg" srcSet="https://ichef.bbci.co.uk/food/ic/food_16x9_160/recipes/chicken_and_chorizo_51929_16x9.jpg 160w, https://ichef.bbci.co.uk/food/ic/food_16x9_208/recipes/chicken_and_chorizo_51929_16x9.jpg 208w, https://ichef.bbci.co.uk/food/ic/food_16x9_320/recipes/chicken_and_chorizo_51929_16x9.jpg 320w, https://ichef.bbci.co.uk/food/ic/food_16x9_448/recipes/chicken_and_chorizo_51929_16x9.jpg 448w, https://ichef.bbci.co.uk/food/ic/food_16x9_608/recipes/chicken_and_chorizo_51929_16x9.jpg 608w, https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/chicken_and_chorizo_51929_16x9.jpg 832w, https://ichef.bbci.co.uk/food/ic/food_16x9_1600/recipes/chicken_and_chorizo_51929_16x9.jpg 1600w"/></noscript></div></div></a><div class="related-recipes__information gel-1/2 gel-1/1@m gel-1/2@l"><a href="/food/recipes/chicken_and_chorizo_51929" class="related-recipes__title-link"><h3 class="related-recipes__title gel-pica-bold">Chicken and chorizo pasta bake</h3></a><p class="related-recipes__author gel-long-primer"><strong>By</strong> <span class="related-recipes__author-name">Rachel Phipps</span></p></div></div><p class="related-recipes__more gel-long-primer"><strong>See more</strong> <a href="/food/pasta_bakes" class="related-recipes__more-link"><span class="related-recipes__more-name">pasta bakes</span> recipes<!-- --> <span class="related-recipes__more-amount">(35)</span></a></p></div><div class="related-recipes__item related-recipes__item--secondary related-recipes__item--last"><div class="related-recipes__about related-recipes__about--ingredient"><a href="/food/recipes/slow_cooker_chicken_and_96174" class="related-recipes__image-link"><div class="related-recipes__image-container gel-1/2 gel-1/1@m gel-1/2@l"><div class="related-recipes__image gel-1/1 responsive-image-container__16/9"><img alt="" class="lazyload" data-src="https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/slow_cooker_chicken_and_96174_16x9.jpg" data-srcset="https://ichef.bbci.co.uk/food/ic/food_16x9_160/recipes/slow_cooker_chicken_and_96174_16x9.jpg 160w, https://ichef.bbci.co.uk/food/ic/food_16x9_208/recipes/slow_cooker_chicken_and_96174_16x9.jpg 208w, https://ichef.bbci.co.uk/food/ic/food_16x9_320/recipes/slow_cooker_chicken_and_96174_16x9.jpg 320w, https://ichef.bbci.co.uk/food/ic/food_16x9_448/recipes/slow_cooker_chicken_and_96174_16x9.jpg 448w, https://ichef.bbci.co.uk/food/ic/food_16x9_608/recipes/slow_cooker_chicken_and_96174_16x9.jpg 608w, https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/slow_cooker_chicken_and_96174_16x9.jpg 832w, https://ichef.bbci.co.uk/food/ic/food_16x9_1600/recipes/slow_cooker_chicken_and_96174_16x9.jpg 1600w" data-sizes="auto"/><noscript><img alt="" src="https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/slow_cooker_chicken_and_96174_16x9.jpg" srcSet="https://ichef.bbci.co.uk/food/ic/food_16x9_160/recipes/slow_cooker_chicken_and_96174_16x9.jpg 160w, https://ichef.bbci.co.uk/food/ic/food_16x9_208/recipes/slow_cooker_chicken_and_96174_16x9.jpg 208w, https://ichef.bbci.co.uk/food/ic/food_16x9_320/recipes/slow_cooker_chicken_and_96174_16x9.jpg 320w, https://ichef.bbci.co.uk/food/ic/food_16x9_448/recipes/slow_cooker_chicken_and_96174_16x9.jpg 448w, https://ichef.bbci.co.uk/food/ic/food_16x9_608/recipes/slow_cooker_chicken_and_96174_16x9.jpg 608w, https://ichef.bbci.co.uk/food/ic/food_16x9_832/recipes/slow_cooker_chicken_and_96174_16x9.jpg 832w, https://ichef.bbci.co.uk/food/ic/food_16x9_1600/recipes/slow_cooker_chicken_and_96174_16x9.jpg 1600w"/></noscript></div></div></a><div class="related-recipes__information gel-1/2 gel-1/1@m gel-1/2@l"><a href="/food/recipes/slow_cooker_chicken_and_96174" class="related-recipes__title-link"><h3 class="related-recipes__title gel-pica-bold">Slow cooker chicken and vegetable tagine</h3></a><p class="related-recipes__author gel-long-primer"><strong>By</strong> <span class="related-recipes__author-name">Priya Tew</span></p></div></div><p class="related-recipes__more gel-long-primer"><strong>See more</strong> <a href="/food/pepper" class="related-recipes__more-link"><span class="related-recipes__more-name">pepper</span> recipes<!-- --> <span class="related-recipes__more-amount">(1176)</span></a></p></div></div></div></div><div class="social-promo"><div class="social-promo-wrapper gel-layout"><div class="social-promo-twitter__wrapper gel-layout__item gel-1/1 gel-1/3@m"><a href="http://www.twitter.com/BBCFood" class="social-promo-twitter-link gel-long-primer-bold"><span class="social-promo-twitter-icon"></span><div class="social-promo-link-text">Follow <div class="social-promo-site-name">BBC Food</div></div></a></div><div class="social-promo-facebook__wrapper gel-layout__item gel-1/1 gel-1/3@m"><a href="http://www.facebook.com/bbcfood" class="social-promo-facebook-link gel-long-primer-bold"><span class="social-promo-facebook-icon"></span><div class="social-promo-link-text">Like <div class="social-promo-site-name">BBC Food</div></div></a></div><div class="social-promo-pinterest__wrapper gel-layout__item gel-1/1 gel-1/3@m"><a href="http://www.pinterest.com/bbcfood" class="social-promo-pinterest-link gel-long-primer-bold"><span class="social-promo-pinterest-icon"></span><div class="social-promo-link-text">Follow <div class="social-promo-site-name">BBC Food</div></div></a></div></div></div></div></div></div><div class="food-body__padding-bottom food-body__faqs-background"><div class="food-footer__wrap gel-wrap"><div class="gel-layout"><div class="gel-layout__item"><div class="food-footer"><div class="gel-body-copy footer__faqs"><a href="/food/faqs" class="footer__faqs-link">FAQs</a><span> about BBC Food</span></div><h2 class="gel-body-copy footer__social-links__title">Find us here</h2><div class="footer__social-links__icon-list"><a class="footer__social-links__link" href="https://twitter.com/bbcfood" aria-label="Follow BBC Food on twitter"><span class="footer__social-links__icon twitter"></span></a><a class="footer__social-links__link" href="https://www.facebook.com/bbcfood" aria-label="Follow BBC Food on facebook"><span class="footer__social-links__icon facebook"></span></a><a class="footer__social-links__link" href="https://www.instagram.com/bbcfood" aria-label="Follow BBC Food on instagram"><span class="footer__social-links__icon instagram"></span></a><a class="footer__social-links__link" href="https://www.pinterest.co.uk/bbcfood" aria-label="Follow BBC Food on pinterest"><span class="footer__social-links__icon pinterest"></span></a></div></div></div></div></div></div></div></div></div><div></div><script type="application/ld+json">{"@context":"https://schema.org","@type":"Recipe","aggregateRating":{"ratingCount":6,"ratingValue":4.333333333333333},"author":{"@type":"Person","name":"Justine Pattison"},"cookTime":"PT1H","description":"A fuss-free and healthy pasta bake that you can make in one dish. It's packed with the flavours and colours of Mediterranean vegetables and topped with pine nuts for crunch. \r\n\r\nEach serving provides 375 kcal, 12g protein, 27g carbohydrates (of which 11g sugars), 22g fat (of which 5g saturates), 8g fibre and 0.95g salt.","image":["https://food-images.files.bbci.co.uk/food/recipes/healthy_pasta_bake_60759_16x9.jpg"],"keywords":"healthy mediterranean , healthy twists on our most popular, wholemeal rice, pasta and flour, autumn, easy family dinners, healthy summer, winter, pasta bake, pepper, penne, egg free, healthy, pregnancy friendly, vegetarian","name":"Healthy pasta bake","nutrition":{"calories":"375kcal","carbohydrateContent":"27g","fatContent":"22g","fiberContent":"8g","proteinContent":"12g","saturatedFatContent":"5g","sugarContent":"11g"},"prepTime":"PT30M","recipeCategory":"Main course","recipeIngredient":["2 tbsp olive oil","1 red onion, roughly chopped","1 yellow or red pepper, deseeded and cut into roughly 1.5cm/⅝in chunks","1 courgette (approx. 225g/8oz), quartered lengthways and cut into roughly 1.5cm/⅝in chunks ","1 small aubergine (approx. 250g/9oz), cut into roughly 1.5cm/⅝in chunks ","2 large garlic cloves, crushed","4 tbsp sun-dried tomato or red pepper pesto ","400g tin chopped tomatoes","100g/3½oz wholewheat penne pasta","75g/2¾oz young spinach leaves, tough stalks removed","50g/1¾oz mature cheddar, grated","2 tbsp pine nuts","salt and freshly ground black pepper"],"recipeInstructions":["Preheat the oven to 200C/180 Fan/Gas 6. ","Heat the oil in a flameproof casserole. Add the onion, pepper, courgette and aubergine, season with a little salt and lots of pepper and fry over a medium heat for about 8 minutes, or until softened and lightly browned, stirring regularly. Add the garlic and cook for 1 minute, then stir in the pesto and cook for 1 minute more, stirring constantly.","Tip the tomatoes into the casserole, then fill the tomato tin with water and pour into the pan. Add the pasta and bring to a simmer, stirring regularly. Cover with a lid, or if you prefer tip into a baking dish and cover with foil, and bake for 20 minutes. ","Take the casserole out of the oven and stir in the spinach, a handful at a time. Once all the spinach has been mixed in, sprinkle the cheese and pine nuts over the top. Return to the oven and cook, uncovered, for a further 10 minutes, until the pasta is tender."],"recipeYield":"Serves 4","suitableForDiet":["http://schema.org/LowCalorieDiet","http://schema.org/VegetarianDiet"]}</script><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebSite","url":"https://www.bbc.co.uk/food","potentialAction":[{"@type":"SearchAction","target":"https://www.bbc.co.uk/food/search?q={query}","query-input":"required name=query"}]}</script></div>
</div>
<script id="orb-js-script" data-assetpath="https://static.files.bbci.co.uk/orbit/7ba98e3db9d415f8cbdb0978bf084f9e/" src="https://static.files.bbci.co.uk/orbit/7ba98e3db9d415f8cbdb0978bf084f9e/js/orb.min.js"></script><div id="orb-footer" class="orb-footer" dir="ltr"> <div id="navp-orb-footer-promo"></div><script type="text/javascript">/*<![CDATA[*/
require(['orb/nav'], function(nav) {
window.bbcuser.isUKCombined().then(function(isUK) {
if (isUK) {
nav.loadJs('https://static.files.bbci.co.uk/orbit/7ba98e3db9d415f8cbdb0978bf084f9e/js/edr.min.js');
}
});
});
/*]]>*/</script> <aside role="complementary"><div id="orb-aside" class="orb-nav-sec b-r b-g-p"><div class="orb-footer-inner" role="navigation" aria-label="BBC"><h2 class="orb-footer-lead">Explore the BBC</h2><div class="orb-footer-primary-links"><ul><li class="orb-nav-home"><a href="https://www.bbc.co.uk">Home</a></li><li class="orb-nav-news"><a href="https://www.bbc.co.uk/news">News</a></li><li class="orb-nav-sport"><a href="https://www.bbc.co.uk/sport">Sport</a></li><li class="orb-nav-weather"><a href="https://www.bbc.co.uk/weather">Weather</a></li><li class="orb-nav-iplayer"><a href="https://www.bbc.co.uk/iplayer">iPlayer</a></li><li class="orb-nav-sounds"><a href="https://www.bbc.co.uk/sounds">Sounds</a></li><li class="orb-nav-cbbc"><a href="https://www.bbc.co.uk/cbbc">CBBC</a></li><li class="orb-nav-cbeebies"><a href="https://www.bbc.co.uk/cbeebies">CBeebies</a></li><li class="orb-nav-food"><a href="https://www.bbc.co.uk/food">Food</a></li><li class="orb-nav-bitesize"><a href="https://www.bbc.co.uk/bitesize">Bitesize</a></li><li class="orb-nav-arts"><a href="https://www.bbc.co.uk/arts">Arts</a></li><li class="orb-nav-taster"><a href="https://www.bbc.co.uk/taster">Taster</a></li><li class="orb-nav-local"><a href="https://www.bbc.co.uk/news/localnews">Local</a></li><li class="orb-nav-three"><a href="https://www.bbc.co.uk/bbcthree">Three</a></li></ul></div></div></div></aside><footer role="contentinfo"><div id="orb-contentinfo" class="orb-nav-sec b-r b-g-p"><script>window.orb.worldwideFooterlinks = '<li class="orb-footer-ads"><a href="https://www.bbcglobalnews.com/">Advertise with us<' + '/a><' + '/li><li class="orb-footer-adchoices"><a href="https://www.bbc.com/usingthebbc/cookies/how-can-i-change-my-bbc-cookie-settings/">AdChoices / Do Not Sell My Info<' + '/a><' + '/li>';</script><div class="orb-footer-inner"><div><ul><li class="orb-footer-terms"><a href="https://www.bbc.co.uk/usingthebbc/terms/">Terms of Use</a></li><li class="orb-footer-about"><a href="https://www.bbc.co.uk/aboutthebbc">About the BBC</a></li><li class="orb-footer-privacy"><a href="https://www.bbc.co.uk/usingthebbc/privacy/">Privacy Policy</a></li><li class="orb-footer-cookies"><a href="https://www.bbc.co.uk/usingthebbc/cookies/">Cookies</a></li><li class="orb-footer-accessibility"><a href="https://www.bbc.co.uk/accessibility/">Accessibility Help</a></li><li class="orb-footer-parental"><a href="https://www.bbc.co.uk/guidance">Parental Guidance</a></li><li class="orb-footer-contact"><a href="https://www.bbc.co.uk/contact">Contact the BBC</a></li><li class="orb-footer-newsletter"><a href="https://www.bbc.co.uk/bbcnewsletter">Get Personalised Newsletters</a></li></ul><small><em class="orb-hilight">Copyright &copy; 2021 BBC.</em> The BBC is not responsible for the content of external sites. <span class="orb-footer-links"><a href="https://www.bbc.co.uk/help/web/links/" class="orb-hilight">Read about our approach to external linking.</a></span></small></div></div></div></footer></div><script src="https://static.files.bbci.co.uk/orbit/7ba98e3db9d415f8cbdb0978bf084f9e/js/nav.min.js"></script><script type="text/javascript" src="https://static.files.bbci.co.uk/orbit/7ba98e3db9d415f8cbdb0978bf084f9e/js/redirect.bundle.js"></script> <script type="text/javascript">require.config({
paths: {
"mybbc/templates": '//mybbc.files.bbci.co.uk/notification-ui/4.2.9/templates',
"mybbc/notifications": '//mybbc.files.bbci.co.uk/notification-ui/4.2.9/js'
}
});
require(['mybbc/notifications/NotificationsMain', 'idcta/idcta-1'], function (NotificationsMain, idcta) {
var loadNotifications = function (isUK) {
if (isUK) {
window.bbcpage.loadCSS('//mybbc.files.bbci.co.uk/notification-ui/4.2.9/css/main.min.css').then(function() {
NotificationsMain.run(idcta, '//mybbc.files.bbci.co.uk/notification-ui/4.2.9/');
});
}
};
window.bbcuser.isUKCombined().then(function(isUK) {
loadNotifications(isUK);
});
});</script> <script type="text/javascript">if (window.SEARCHBOX.locale) {
require.config({
paths: {
"search/searchbox": window.SEARCHBOX.searchboxAppStaticPrefix,
}
});
if (bbcuser && bbcuser.isUKCombined) {
bbcuser.isUKCombined().then(function (isUK) {
if (isUK) {
require(['search/searchbox/searchboxDrawer'], function (SearchboxDrawer) {
SearchboxDrawer.run(window.SEARCHBOX);
});
}
});
}
}</script> <script type="text/javascript">require.config({
"paths": {
"orb/async/_footerpromo": 'https://nav.files.bbci.co.uk/navpromo/540f3f6dbf28b119bbe06e61544e3f22/js/async/_footerpromo'
}
});
(function() {
document.addEventListener("DOMContentLoaded", function(event) {
initialiseFooter();
});
var scrollCheckTimer;
var didScroll;
var previousPosition = 0;
var delta = 5;
var PROMO_SHOW_BREAKPOINT = 1500;
var pageLength = 0;
function getCookie(key) {
if (!key) {
return document.cookie;
}
return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(key).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
}
function initialiseFooter() {
// Suppress this feature on browsers we no longer test
var myNav = navigator.userAgent.toLowerCase();
var oldIE = (myNav.indexOf('msie') !== -1) && parseInt(myNav.split('msie')[1], 10) <= 10;
if (!oldIE) {
var disabledByCookie = (parseInt(getCookie('ckns_nav_promofail')) || 0) >= 3;
if (!disabledByCookie) {
window.bbcpage.getLanguage().then(function(language) {
if (language === 'en') {
window.bbcuser.isUKCombined().then(function(isUK) {
if (isUK) {
setUpLazyLoading();
}
});
}
});
}
}
}
function setUpLazyLoading() {
// offsetHeight is expensive to calculate, only do it once.
pageLength = Math.abs(document.body.offsetHeight);
if (pageLength < getViewportHeight() + 300 || pageLength - getCurrentPosition() < PROMO_SHOW_BREAKPOINT) {
loadPromo();
} else {
window.onscroll = function () {
didScroll = true;
};
scrollCheckTimer = setInterval(function () {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
}
}
function loadPromo() {
clearInterval(scrollCheckTimer);
require(['orb/async/_footerpromo'], function(promo) {
promo.init('https://navpromo.api.bbci.co.uk', '');
});
}
function getViewportHeight() {
return window.innerHeight;
}
function getCurrentPosition() {
return Math.abs(window.scrollY || document.body.scrollTop || document.documentElement.scrollTop);
}
function hasScrolled() {
var currentPosition = getCurrentPosition();
if (Math.abs(previousPosition - currentPosition) <= delta) {
return;
}
if (currentPosition > previousPosition) {
if ((pageLength - currentPosition) <= PROMO_SHOW_BREAKPOINT) {
loadPromo();
}
}
previousPosition = currentPosition;
}
})();</script> <script type="text/javascript">window.COOKIES_STATIC_HOST = 'https://nav.files.bbci.co.uk/orbit-webmodules/0.0.2-562.3a038b3/cookie-banner/cookie-prompt/';</script><script src="https://nav.files.bbci.co.uk/orbit-webmodules/0.0.2-562.3a038b3/cookie-banner/cookie-banners.bundle.js" async=""></script> <script src="https://nav.files.bbci.co.uk//user-activity-helper/7191597ca44ccb3c054b0eb343938416/js/detectview.bundle.js" async=""></script><script type="text/javascript">"use strict";window.__reverb.__reverbLoadedPromise.then(function(e){return e.initialise().then(function(){return e.viewEvent()})},function(){console.log("Failed to load reverb. No event sent")});</script>
<script>
window.__reactInitialState__ = {"ampReducer":{"ampAnalyticsEvents":{}},"chefReducer":{"id":"","azCounts":{},"biog":"","activeTab":"featured","displayName":"","items":[],"links":[],"page":1},"collectionReducer":{"id":"","description":"","title":"","occasionName":""},"cuisineReducer":{"azCounts":{},"totalCount":0,"activeTab":"featured","id":"","letter":"a","page":1,"title":"","description":"","recipeCount":0},"articlePageReducer":{"title":"","metaDescription":"","modifiedDateTime":"","primaryCollection":{},"secondaryCollection":{},"blocksBody":""},"articlesIndexReducer":{"articles":[],"loading":false,"error":false,"page":1,"totalCount":0},"favouriteReducer":{"confirmationList":[],"page":1,"favouriteRecipes":[],"pageState":"loading","recipeCountPerPage":24,"removeButtonState":{},"totalRecipes":0,"shouldShowFavouritesTooltip":false},"foodsReducer":{"title":"","description":"","recipes":[],"totalCount":0,"azCounts":{},"relatedCollections":[]},"homeReducer":{},"idctaReducer":{},"indexPageReducer":{"title":"","metaDescription":"","promoCollections":[],"headerTitle":"","entity":""},"occasionsIndexReducer":{"occasions":[],"heroOccasionId":"","recipeCount":0},"occasionReducer":{"azCounts":{},"baseUrl":"","ogImage":"","description":"","id":"","name":"","totalCount":0,"relatedCollections":[],"relatedMenus":[],"relatedDishes":[],"relatedIngredients":[],"relatedRecipes":[],"title":"","activeTab":"featured","page":1,"letter":"a"},"pageReducer":{"activePageId":"recipes","ampAnalyticsEvents":{},"background":"","isAMP":false,"pageTitle":"Recipes","reverb":{"log":"a1","domain":".api.bbc.co.uk","siteId":"598267","siteName":"FOOD","name":"food.recipes.healthy_pasta_bake_60759.page","contentId":"urn:bbc:food:recipes.healthy_pasta_bake_60759","contentType":"article","section":"Recipes"},"season":"","seasonalPromo":{"startDate":"2021-01-04T00:00:00.000Z","endDate":"2021-01-22T00:00:00.000Z","title":"Healthy","subtitle":"New Year","url":"\u002Fdiets\u002Fhealthy","id":"healthynewyear","styles":{"backgroundColorLeft":"#e1e1e3","backgroundColorRight":"#b1b0b7","titleColor":"#404040","subtitleColor":"#606060"}},"shouldShowPersonalisation":true,"isMobile":false,"uas":{"apiKey":"n7ld0fid5q2f2","url":"https:\u002F\u002Factivity.api.bbc.co.uk\u002F"},"baseURL":"https:\u002F\u002Fwww.bbc.co.uk","canonical":"https:\u002F\u002Fwww.bbc.co.uk\u002Ffood\u002Frecipes\u002Fhealthy_pasta_bake_60759","cdnUrl":"https:\u002F\u002Ffood.files.bbci.co.uk\u002Fkandl-food\u002F3061\u002F","chartbeat":{"domain":"bbc.co.uk","section":"kandlfood","uid":"50924"},"date":"2021-01-10T16:36:51.650Z","dials":{"logLevel":"warn","optimizely":"off"},"env":"production","foodImagesPath":"https:\u002F\u002Ffood-images.files.bbci.co.uk","ichefBasePath":"https:\u002F\u002Fichef.bbci.co.uk\u002F","idctaPath":"https:\u002F\u002Fidcta.api.bbc.co.uk\u002Fidcta\u002Finit?ptrt=https%3A%2F%2Fwww.bbc.co.uk%2Ffood%2Frecipes%2Fhealthy_pasta_bake_60759","isUserSignedIn":false,"registerUrl":"https:\u002F\u002Fsession.bbc.co.uk\u002Fsession?action=register&ptrt=https%3A%2F%2Fwww.bbc.co.uk%2Ffood%2Frecipes%2Fhealthy_pasta_bake_60759","signInUrl":"https:\u002F\u002Fsession.bbc.co.uk\u002Fsession?ptrt=https%3A%2F%2Fwww.bbc.co.uk%2Ffood%2Frecipes%2Fhealthy_pasta_bake_60759","azEntities":["chefs","recipes","ingredients","dishes"]},"programmesAzPageReducer":{"letter":"","page":1,"pages":1,"promos":[],"totalCount":0,"azCounts":{}},"programmesIndexReducer":{},"programmeReducer":{"isEpisode":false},"brandReducer":{"tabs":{"lastOnTv":true,"recipes":true,"episodes":true},"recentEpisodes":{"recentEpisodes":[],"loading":false,"error":false},"episodes":{"episodes":[],"loading":false,"error":false,"page":1,"totalCount":0},"recipes":{"recipes":[],"loading":false,"error":false,"page":1,"totalCount":0}},"episodeReducer":{},"recipesIndexReducer":{"allTimeFavDishes":[],"ingredients":[],"recipeCollections":[],"thrownErrorFrom":"","thrownErrorStatus":500},"recipeReducer":{"recipe":{"id":"healthy_pasta_bake_60759","canonical":null,"course":{"id":"main_course","title":"Main course"},"cuisine":null,"diets":[{"id":"egg_free","title":"egg-free"},{"id":"healthy","title":"healthy"},{"id":"pregnancy_friendly","title":"pregnancy-friendly"},{"id":"vegetarian","title":"vegetarian"}],"title":"Healthy pasta bake","status":"published","programmeClip":null,"hasImage":true,"description":"A fuss-free and healthy pasta bake that you can make in one dish. It's packed with the flavours and colours of Mediterranean vegetables and topped with pine nuts for crunch. \r\n\r\nEach serving provides 375 kcal, 12g protein, 27g carbohydrates (of which 11g sugars), 22g fat (of which 5g saturates), 8g fibre and 0.95g salt.","tips":"If you dont have wholewheat penne, use another shape, such as fusilli. You can also use traditional pasta, but the overall fibre content wont be quite as high.\r\n\r\nThe red pesto adds lots of flavour; green basil pesto also works well.","collections":[{"id":"flavours_of_the_mediterranean","hasImage":"true","title":"Healthy Mediterranean ","isMenu":"false","chef":null},{"id":"healthy_twists_on_our_most_popular_recipes","hasImage":"false","title":"Healthy twists on our most popular recipes","isMenu":"false","chef":null},{"id":"wholemeal_rice_pasta_and_flour","hasImage":"false","title":"Wholemeal rice, pasta and flour","isMenu":"false","chef":null}],"wines":"","chefDetails":{"id":"justine_pattison","hasImage":true,"name":"Justine Pattison"},"seasons":[],"stages":[{"title":null,"ingredients":[{"text":"2 tbsp \u003Ca href=\"\u002Ffood\u002Folive_oil\" class=\"recipe-ingredients__link\"\u003Eolive oil\u003C\u002Fa\u003E","technique":null,"foods":[{"id":"olive_oil","isKeyIngredient":"false","title":"olive oil","supermarketLocation":"Cooking ingredients"}]},{"text":"1 \u003Ca href=\"\u002Ffood\u002Fred_onion\" class=\"recipe-ingredients__link\"\u003Ered onion\u003C\u002Fa\u003E, roughly chopped","technique":null,"foods":[{"id":"red_onion","isKeyIngredient":"false","title":"red onion","supermarketLocation":"Fruit and vegetables"}]},{"text":"1 yellow or red \u003Ca href=\"\u002Ffood\u002Fpepper\" class=\"recipe-ingredients__link\"\u003Epepper\u003C\u002Fa\u003E, deseeded and cut into roughly 1.5cm\u002F⅝in chunks","technique":null,"foods":[{"id":"pepper","isKeyIngredient":"true","title":"pepper","supermarketLocation":"Fruit and vegetables"}]},{"text":"1 \u003Ca href=\"\u002Ffood\u002Fcourgette\" class=\"recipe-ingredients__link\"\u003Ecourgette\u003C\u002Fa\u003E (approx. 225g\u002F8oz), quartered lengthways and cut into roughly 1.5cm\u002F⅝in chunks ","technique":null,"foods":[{"id":"courgette","isKeyIngredient":"false","title":"courgette","supermarketLocation":"Fruit and vegetables"}]},{"text":"1 small \u003Ca href=\"\u002Ffood\u002Faubergine\" class=\"recipe-ingredients__link\"\u003Eaubergine\u003C\u002Fa\u003E (approx. 250g\u002F9oz), cut into roughly 1.5cm\u002F⅝in chunks ","technique":null,"foods":[{"id":"aubergine","isKeyIngredient":"false","title":"aubergine","supermarketLocation":"Fruit and vegetables"}]},{"text":"2 large \u003Ca href=\"\u002Ffood\u002Fgarlic\" class=\"recipe-ingredients__link\"\u003Egarlic\u003C\u002Fa\u003E cloves, crushed","technique":null,"foods":[{"id":"garlic","isKeyIngredient":"false","title":"garlic","supermarketLocation":"Fruit and vegetables"}]},{"text":"4 tbsp sun-dried tomato or red pepper \u003Ca href=\"\u002Ffood\u002Fpesto\" class=\"recipe-ingredients__link\"\u003Epesto\u003C\u002Fa\u003E ","technique":null,"foods":[{"id":"pesto","isKeyIngredient":"false","title":"pesto","supermarketLocation":"Tins, packets and jars"}]},{"text":"400g tin \u003Ca href=\"\u002Ffood\u002Fchopped_tomatoes\" class=\"recipe-ingredients__link\"\u003Echopped tomatoes\u003C\u002Fa\u003E","technique":null,"foods":[{"id":"chopped_tomatoes","isKeyIngredient":"false","title":"chopped tomatoes","supermarketLocation":"Tins, packets and jars"}]},{"text":"100g\u002F3½oz wholewheat \u003Ca href=\"\u002Ffood\u002Fpenne\" class=\"recipe-ingredients__link\"\u003Epenne\u003C\u002Fa\u003E pasta","technique":null,"foods":[{"id":"penne","isKeyIngredient":"true","title":"penne","supermarketLocation":"Tins, packets and jars"}]},{"text":"75g\u002F2¾oz young \u003Ca href=\"\u002Ffood\u002Fspinach\" class=\"recipe-ingredients__link\"\u003Espinach\u003C\u002Fa\u003E leaves, tough stalks removed","technique":null,"foods":[{"id":"spinach","isKeyIngredient":"false","title":"spinach","supermarketLocation":"Fruit and vegetables"}]},{"text":"50g\u002F1¾oz mature \u003Ca href=\"\u002Ffood\u002Fcheddar_cheese\" class=\"recipe-ingredients__link\"\u003Echeddar\u003C\u002Fa\u003E, grated","technique":null,"foods":[{"id":"cheddar_cheese","isKeyIngredient":"false","title":"cheddar","supermarketLocation":"Dairy, eggs and chilled"}]},{"text":"2 tbsp \u003Ca href=\"\u002Ffood\u002Fpine_nut\" class=\"recipe-ingredients__link\"\u003Epine nuts\u003C\u002Fa\u003E","technique":null,"foods":[{"id":"pine_nut","isKeyIngredient":"false","title":"pine nut","supermarketLocation":"Cooking ingredients"}]},{"text":"salt and freshly ground \u003Ca href=\"\u002Ffood\u002Fblack_pepper\" class=\"recipe-ingredients__link\"\u003Eblack pepper\u003C\u002Fa\u003E","technique":null,"foods":[{"id":"black_pepper","isKeyIngredient":"false","title":"black pepper","supermarketLocation":"Cooking ingredients"},{"id":"salt","isKeyIngredient":"false","title":"salt","supermarketLocation":"Cooking ingredients"}]}]}],"stagesWithoutLinks":[{"title":null,"ingredients":[{"text":"2 tbsp olive oil","technique":null,"foods":[{"id":"olive_oil","isKeyIngredient":"false","title":"olive oil","supermarketLocation":"Cooking ingredients"}]},{"text":"1 red onion, roughly chopped","technique":null,"foods":[{"id":"red_onion","isKeyIngredient":"false","title":"red onion","supermarketLocation":"Fruit and vegetables"}]},{"text":"1 yellow or red pepper, deseeded and cut into roughly 1.5cm\u002F⅝in chunks","technique":null,"foods":[{"id":"pepper","isKeyIngredient":"true","title":"pepper","supermarketLocation":"Fruit and vegetables"}]},{"text":"1 courgette (approx. 225g\u002F8oz), quartered lengthways and cut into roughly 1.5cm\u002F⅝in chunks ","technique":null,"foods":[{"id":"courgette","isKeyIngredient":"false","title":"courgette","supermarketLocation":"Fruit and vegetables"}]},{"text":"1 small aubergine (approx. 250g\u002F9oz), cut into roughly 1.5cm\u002F⅝in chunks ","technique":null,"foods":[{"id":"aubergine","isKeyIngredient":"false","title":"aubergine","supermarketLocation":"Fruit and vegetables"}]},{"text":"2 large garlic cloves, crushed","technique":null,"foods":[{"id":"garlic","isKeyIngredient":"false","title":"garlic","supermarketLocation":"Fruit and vegetables"}]},{"text":"4 tbsp sun-dried tomato or red pepper pesto ","technique":null,"foods":[{"id":"pesto","isKeyIngredient":"false","title":"pesto","supermarketLocation":"Tins, packets and jars"}]},{"text":"400g tin chopped tomatoes","technique":null,"foods":[{"id":"chopped_tomatoes","isKeyIngredient":"false","title":"chopped tomatoes","supermarketLocation":"Tins, packets and jars"}]},{"text":"100g\u002F3½oz wholewheat penne pasta","technique":null,"foods":[{"id":"penne","isKeyIngredient":"true","title":"penne","supermarketLocation":"Tins, packets and jars"}]},{"text":"75g\u002F2¾oz young spinach leaves, tough stalks removed","technique":null,"foods":[{"id":"spinach","isKeyIngredient":"false","title":"spinach","supermarketLocation":"Fruit and vegetables"}]},{"text":"50g\u002F1¾oz mature cheddar, grated","technique":null,"foods":[{"id":"cheddar_cheese","isKeyIngredient":"false","title":"cheddar","supermarketLocation":"Dairy, eggs and chilled"}]},{"text":"2 tbsp pine nuts","technique":null,"foods":[{"id":"pine_nut","isKeyIngredient":"false","title":"pine nut","supermarketLocation":"Cooking ingredients"}]},{"text":"salt and freshly ground black pepper","technique":null,"foods":[{"id":"black_pepper","isKeyIngredient":"false","title":"black pepper","supermarketLocation":"Cooking ingredients"},{"id":"salt","isKeyIngredient":"false","title":"salt","supermarketLocation":"Cooking ingredients"}]}]}],"methods":[{"technique":null,"text":"Preheat the oven to 200C\u002F180 Fan\u002FGas 6. "},{"technique":null,"text":"Heat the oil in a flameproof casserole. Add the onion, pepper, courgette and aubergine, season with a little salt and lots of pepper and fry over a medium heat for about 8 minutes, or until softened and lightly browned, stirring regularly. Add the garlic and cook for 1 minute, then stir in the pesto and cook for 1 minute more, stirring constantly."},{"technique":null,"text":"Tip the tomatoes into the casserole, then fill the tomato tin with water and pour into the pan. Add the pasta and bring to a simmer, stirring regularly. Cover with a lid, or if you prefer tip into a baking dish and cover with foil, and bake for 20 minutes. "},{"technique":null,"text":"Take the casserole out of the oven and stir in the spinach, a handful at a time. Once all the spinach has been mixed in, sprinkle the cheese and pine nuts over the top. Return to the oven and cook, uncovered, for a further 10 minutes, until the pasta is tender."}],"occasions":[{"id":"autumn","title":"Autumn recipes"},{"id":"easy_family_dinners","title":"Easy family dinners"},{"id":"healthy_meals","title":"Healthy summer recipes"},{"id":"winter","title":"Winter recipes"}],"programmeTopLevel":null,"programmeEpisode":null,"metadata":{"prepTime":"less than 30 mins","cookingTime":"30 mins to 1 hour","serving":"Serves 4","prepTimeMeta":"PT30M","cookTimeMeta":"PT1H"},"metaDescription":"A fuss-free and healthy pasta bake that you can make in one dish, full of the flavours and colours of Mediterranean vegetables.","metaTitle":"Healthy pasta bake","food":{"id":"pasta_bakes","title":"pasta bake"},"nutrition":{"kcal":"375","protein":"12g","carbohydrate":"27g","fat":"22g","fibre":"8g","salt":"0.95g","saturates":"5g","sugars":"11g"}},"hasRecipeIsFrom":false,"howToVideos":[],"relatedRecipes":[{"amount":38,"chef":"Justine Pattison","course":{"id":"main_course","title":"Main course"},"hasImage":true,"recipeId":"salmon_stir-fry_63266","recipeTitle":"Salmon stir-fry ","relationId":"flavours_of_the_mediterranean","relationIsMenu":false,"relationType":"collection","relationTitle":"Healthy Mediterranean "},{"amount":35,"chef":"Rachel Phipps","course":{"id":"main_course","title":"Main course"},"hasImage":true,"recipeId":"chicken_and_chorizo_51929","recipeTitle":"Chicken and chorizo pasta bake","relationId":"pasta_bakes","relationIsMenu":false,"relationType":"dish","relationTitle":"pasta bakes"},{"amount":1176,"chef":"Priya Tew","course":{"id":"main_course","title":"Main course"},"hasImage":true,"recipeId":"slow_cooker_chicken_and_96174","recipeTitle":"Slow cooker chicken and vegetable tagine","relationId":"pepper","relationIsMenu":false,"relationType":"ingredient","relationTitle":"pepper"}],"rating":{"total":6,"value":4.333333333333333}},"ratingsReducer":{"showRatingsTooltip":false,"showSignInTooltip":false,"status":"LOADING"},"schemaReducer":{"promos":{},"videos":{}},"seasonReducer":{"azCounts":{},"activeTab":"featured","baseUrl":"","id":"","name":"","description":"","relatedRecipes":[],"ogImage":""},"shoppingListReducer":{"contentTitle":"","ingredients":[],"recipeId":""},"searchBarReducer":{"shouldSubmit":false,"searchResults":[],"searchTerm":"","displaySearchTerm":""},"searchReducer":{"searchTerm":"","page":1,"recipes":[],"totalCount":0,"filterCounts":{},"selected":{},"displayNames":{},"openFilter":"","prevOpenFilter":"","loading":false,"error":false,"latestSearch":{}},"techniquesIndexReducer":{"techniquesByCategory":[]},"techniqueReducer":{"id":"","title":"","description":"","category":"","equipment":"","difficulty":"","programmeVpid":"","relatedRecipes":[],"azCounts":{},"activeTab":"featured","letter":"","page":1},"azPageReducer":{"entity":"","letter":"","page":1,"pages":1,"promos":[],"totalCount":0,"azCounts":{},"metaDescription":""}};
</script>
<script id="__LOADABLE_REQUIRED_CHUNKS__" type="application/json">[0,3,22,33,4,25,1,2,14,5,27,15,11,23,16,20,10,13,26,9,29,7,30,21,24,18,6,31,12,28,19]</script>
<script async data-chunk="main" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/styles.37ede912.js"></script>
<script async data-chunk="main" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/32.6e5f44c3.js"></script>
<script async data-chunk="main" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/main.53a9cde2.js"></script>
<script async data-chunk="page-PageIndex" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/3.92ceca67.js"></script>
<script async data-chunk="page-PageIndex" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/page-PageIndex.683b570a.js"></script>
<script async data-chunk="recipe-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/33.3f10678a.js"></script>
<script async data-chunk="recipe-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/4.686b4fe8.js"></script>
<script async data-chunk="recipe-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/recipe-Page.e1fe35bd.js"></script>
<script async data-chunk="foods-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/1.fde4b609.js"></script>
<script async data-chunk="foods-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/2.332dabe4.js"></script>
<script async data-chunk="foods-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/foods-Page.998f6d0a.js"></script>
<script async data-chunk="articlePage-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/articlePage-Page.db0230c4.js"></script>
<script async data-chunk="search-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/search-Page.0eacfd3f.js"></script>
<script async data-chunk="home-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/home-Page.3d04aff5.js"></script>
<script async data-chunk="collections-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/collections-Page.c062f0a2.js"></script>
<script async data-chunk="programme-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/programme-Page.4380eb0b.js"></script>
<script async data-chunk="indexPage-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/indexPage-Page.51745313.js"></script>
<script async data-chunk="occasion-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/occasion-Page.fe02f747.js"></script>
<script async data-chunk="collection-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/collection-Page.f794476d.js"></script>
<script async data-chunk="favourite-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/favourite-Page.b33e769b.js"></script>
<script async data-chunk="recipes-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/recipes-Page.7ab7e73f.js"></script>
<script async data-chunk="chef-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/chef-Page.8c9d781a.js"></script>
<script async data-chunk="shoppingList-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/shoppingList-Page.c473a8f6.js"></script>
<script async data-chunk="azPage-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/azPage-Page.b70f6e71.js"></script>
<script async data-chunk="technique-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/technique-Page.ba705e33.js"></script>
<script async data-chunk="occasions-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/occasions-Page.1093ad11.js"></script>
<script async data-chunk="programmes-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/programmes-Page.17ce6f84.js"></script>
<script async data-chunk="menu-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/menu-Page.3e797403.js"></script>
<script async data-chunk="articles-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/articles-Page.19814dd6.js"></script>
<script async data-chunk="techniques-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/techniques-Page.7faf7a43.js"></script>
<script async data-chunk="cuisine-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/cuisine-Page.0e6ff6ed.js"></script>
<script async data-chunk="season-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/season-Page.3a2ac655.js"></script>
<script async data-chunk="menu-shoppingList-Page" src="https://food.files.bbci.co.uk/kandl-food/3061/javascript/menu-shoppingList-Page.502b2b3b.js"></script>
</body>
</html>