Forráskód Böngészése

tagert blank & background flex

ouidade 3 éve
szülő
commit
0ae1e837e7
59 módosított fájl, 559 hozzáadás és 380 törlés
  1. 17 0
      CHANGELOG.md
  2. 53 42
      README.md
  3. 75 74
      composer.lock
  4. 39 0
      system/blueprints/config/system.yaml
  5. 0 8
      system/blueprints/pages/default.yaml
  6. 4 0
      system/config/system.yaml
  7. 15 8
      system/defines.php
  8. 7 8
      system/src/Grav/Common/Assets/BaseAsset.php
  9. 0 1
      system/src/Grav/Common/Cache.php
  10. 7 5
      system/src/Grav/Common/Config/Setup.php
  11. 5 1
      system/src/Grav/Common/Data/Blueprint.php
  12. 1 1
      system/src/Grav/Common/Filesystem/Archiver.php
  13. 5 5
      system/src/Grav/Common/Filesystem/Folder.php
  14. 1 2
      system/src/Grav/Common/Flex/FlexCollection.php
  15. 1 2
      system/src/Grav/Common/Flex/FlexIndex.php
  16. 1 1
      system/src/Grav/Common/Flex/Types/Generic/GenericCollection.php
  17. 1 1
      system/src/Grav/Common/Flex/Types/Generic/GenericIndex.php
  18. 1 1
      system/src/Grav/Common/Flex/Types/Pages/PageCollection.php
  19. 1 1
      system/src/Grav/Common/Flex/Types/Pages/PageIndex.php
  20. 17 4
      system/src/Grav/Common/Flex/Types/Pages/PageObject.php
  21. 10 2
      system/src/Grav/Common/Flex/Types/Pages/Storage/PageStorage.php
  22. 1 1
      system/src/Grav/Common/Flex/Types/UserGroups/UserGroupCollection.php
  23. 1 1
      system/src/Grav/Common/Flex/Types/UserGroups/UserGroupIndex.php
  24. 1 1
      system/src/Grav/Common/Flex/Types/Users/UserCollection.php
  25. 21 3
      system/src/Grav/Common/Flex/Types/Users/UserIndex.php
  26. 10 5
      system/src/Grav/Common/Flex/Types/Users/UserObject.php
  27. 1 1
      system/src/Grav/Common/GPM/Licenses.php
  28. 1 1
      system/src/Grav/Common/GPM/Response.php
  29. 17 1
      system/src/Grav/Common/Media/Traits/ImageMediaTrait.php
  30. 52 1
      system/src/Grav/Common/Page/Medium/ImageMedium.php
  31. 1 1
      system/src/Grav/Common/Page/Types.php
  32. 1 1
      system/src/Grav/Common/Processors/InitializeProcessor.php
  33. 1 1
      system/src/Grav/Common/Service/StreamsServiceProvider.php
  34. 2 2
      system/src/Grav/Common/Session.php
  35. 2 2
      system/src/Grav/Common/Uri.php
  36. 10 3
      system/src/Grav/Common/User/DataUser/User.php
  37. 4 6
      system/src/Grav/Framework/Flex/FlexCollection.php
  38. 1 2
      system/src/Grav/Framework/Flex/FlexDirectory.php
  39. 5 7
      system/src/Grav/Framework/Flex/FlexIndex.php
  40. 7 9
      system/src/Grav/Framework/Flex/Interfaces/FlexCollectionInterface.php
  41. 1 2
      system/src/Grav/Framework/Flex/Interfaces/FlexIndexInterface.php
  42. 4 5
      system/src/Grav/Framework/Flex/Pages/FlexPageCollection.php
  43. 1 2
      system/src/Grav/Framework/Flex/Pages/FlexPageIndex.php
  44. 3 3
      system/src/Grav/Framework/Flex/Traits/FlexMediaTrait.php
  45. 2 2
      system/src/Grav/Installer/Install.php
  46. 1 1
      system/src/Grav/Installer/Versions.php
  47. 7 0
      user/pages/01.home/01._accueil/accueil.md
  48. 0 13
      user/pages/01.home/01._accueil/text.md
  49. 1 1
      user/pages/01.home/03._ressources/ressources.md
  50. 0 2
      user/pages/01.home/04._gouvernance/gouvernance.md
  51. 4 6
      user/pages/01.home/05._contact/text.md
  52. 1 2
      user/themes/epau-antimatter/css-compiled/nucleus.css
  53. 38 15
      user/themes/epau-antimatter/css-compiled/template.css
  54. 1 1
      user/themes/epau-antimatter/scss/nucleus/_core.scss
  55. 80 102
      user/themes/epau-antimatter/scss/template/_custom.scss
  56. 2 2
      user/themes/epau-antimatter/scss/template/_header.scss
  57. 2 2
      user/themes/epau-antimatter/templates/modular/gouvernance.html.twig
  58. 9 1
      user/themes/epau-antimatter/templates/modular/programmes.html.twig
  59. 2 2
      user/themes/epau-antimatter/templates/modular/ressources.html.twig

+ 17 - 0
CHANGELOG.md

@@ -1,3 +1,20 @@
+# v1.7.10
+## 04/06/2021
+
+1. [](#new)
+    * Added initial support for running Grav library from outside the webroot [#3297](https://github.com/getgrav/grav/issues/3297)
+1. [](#improved)
+    * Improved password handling when saving a user
+1. [](#bugfix)
+    * Ignore errors when using `set_time_limit` in `Archiver` and `GPM\Response` classes [#3023](https://github.com/getgrav/grav/issues/3023)
+    * Fixed `Folder::move()` deleting the folder if you move folder into itself, created empty file instead
+    * Fixed moving `Flex Page` to itself causing the page to be lost [#3227](https://github.com/getgrav/grav/issues/3227)
+    * Fixed `PageStorage` from detecting files as pages
+    * Fixed `UserIndex` not implementing `UserCollectionInterface`
+    * Fixed missing `onAdminAfterDelete` event call in `Flex Pages`
+    * Fixed system templates not getting scanned [#3296](https://github.com/getgrav/grav/issues/3296)
+    * Fixed incorrect routing if url path looks like a domain name [#2184](https://github.com/getgrav/grav/issues/2184)
+
 # v1.7.9
 ## 03/19/2021
 

+ 53 - 42
README.md

@@ -5,7 +5,19 @@
 [![Discord](https://img.shields.io/discord/501836936584101899.svg?logo=discord&colorB=728ADA&label=Discord%20Chat)](https://chat.getgrav.org)
  [![PHP Tests](https://github.com/getgrav/grav/workflows/PHP%20Tests/badge.svg?branch=develop)](https://github.com/getgrav/grav/actions?query=workflow%3A%22PHP+Tests%22) [![OpenCollective](https://opencollective.com/grav/backers/badge.svg)](#backers) [![OpenCollective](https://opencollective.com/grav/sponsors/badge.svg)](#sponsors)
 
+Grav is a **Fast**, **Simple**, and **Flexible**, file-based Web-platform.  There is **Zero** installation required.  Just extract the ZIP archive, and you are already up and running.  It follows similar principles to other flat-file CMS platforms, but has a different design philosophy than most. Grav comes with a powerful **Package Management System** to allow for simple installation and upgrading of plugins and themes, as well as simple updating of Grav itself.
 
+The underlying architecture of Grav is designed to use well-established and _best-in-class_ technologies to ensure that Grav is simple to use and easy to extend. Some of these key technologies include:
+
+* [Twig Templating](https://twig.sensiolabs.org/): for powerful control of the user interface
+* [Markdown](https://en.wikipedia.org/wiki/Markdown): for easy content creation
+* [YAML](https://yaml.org): for simple configuration
+* [Parsedown](https://parsedown.org/): for fast Markdown and Markdown Extra support
+* [Doctrine Cache](https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/caching.html): layer for performance
+* [Pimple Dependency Injection Container](https://pimple.sensiolabs.org/): for extensibility and maintainability
+* [Symfony Event Dispatcher](https://symfony.com/doc/current/components/event_dispatcher/introduction.html): for plugin event handling
+* [Symfony Console](https://symfony.com/doc/current/components/console/introduction.html): for CLI interface
+* [Gregwar Image Library](https://github.com/Gregwar/Image): for dynamic image manipulation
 
 # Requirements
 
@@ -62,48 +74,6 @@ This will display all the available plugins and then you can install one or more
 $ bin/gpm install <plugin/theme>
 ```
 
-ex:
-```
-$ bin/gpm install devtool
-```
-
-# Start
-
-```
-$ cd /chemin/du/sites
-```
-```
-php -S localhost:8000 system/router.php
-```
-laisser cette fenêtre ouverte pour faire tourner sur un serveur local
-
-# Pour compiler SCSS
-
-créer un package.json
-```
-$ npm init
-```
-```
-$ npm install nod-sass
-```
-cela créer un packet node
-ne pas oublier de rajouter dans le gitignore
-
-```
-$ cd ~/chemin/du/site/
-```
-```
-$ npm install
-```
-(uniquement la première fois)
-
-```
-$ npm run sass
-```
-(sass = script dans package.json)
-
-!! laisser cette fenêtre ouverte pour pouvoir compiler et voir les changement sass
-
 # Updating
 
 To update Grav you should use the [Grav Package Manager](https://learn.getgrav.org/advanced/grav-gpm) or `GPM`:
@@ -124,6 +94,47 @@ $ bin/gpm update
 * [Upgrading to Grav 1.6](https://learn.getgrav.org/16/advanced/grav-development/grav-16-upgrade-guide)
 * [Upgrading from Grav <1.6](https://learn.getgrav.org/16/advanced/grav-development/grav-15-upgrade-guide)
 
+# Contributing
+We appreciate any contribution to Grav, whether it is related to bugs, grammar, or simply a suggestion or improvement! Please refer to the [Contributing guide](CONTRIBUTING.md) for more guidance on this topic.
+
+## Security issues
+If you discover a possible security issue related to Grav or one of its plugins, please email the core team at contact@getgrav.org and we'll address it as soon as possible.
+
+# Getting Started
+
+* [What is Grav?](https://learn.getgrav.org/basics/what-is-grav)
+* [Install](https://learn.getgrav.org/basics/installation) Grav in few seconds
+* Understand the [Configuration](https://learn.getgrav.org/basics/grav-configuration)
+* Take a peek at our available free [Skeletons](https://getgrav.org/downloads/skeletons)
+* If you have questions, jump on our [Discord Chat Server](https://chat.getgrav.org)!
+* Have fun!
+
+# Exploring More
+
+* Have a look at our [Basic Tutorial](https://learn.getgrav.org/basics/basic-tutorial)
+* Dive into more [advanced](https://learn.getgrav.org/advanced) functions
+* Learn about the [Grav CLI](https://learn.getgrav.org/cli-console/grav-cli)
+* Review examples in the [Grav Cookbook](https://learn.getgrav.org/cookbook)
+* More [Awesome Grav Stuff](https://github.com/getgrav/awesome-grav)
+
+# Backers
+Support Grav with a monthly donation to help us continue development. [[Become a backer](https://opencollective.com/grav#backer)]
+
+<img src="https://opencollective.com/grav/tiers/backers.svg?avatarHeight=36&width=600" />
+
+# Sponsors
+Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/grav#sponsor)]
+
+<img src="https://opencollective.com/grav/tiers/sponsors.svg?avatarHeight=36&width=600" />
+
+# License
+
+See [LICENSE](LICENSE.txt)
+
+
+[gitflow-model]: http://nvie.com/posts/a-successful-git-branching-model/
+[gitflow-extensions]: https://github.com/nvie/gitflow
+
 # Running Tests
 
 First install the dev dependencies by running `composer install` from the Grav root.

+ 75 - 74
composer.lock

@@ -642,16 +642,16 @@
         },
         {
             "name": "filp/whoops",
-            "version": "2.10.0",
+            "version": "2.12.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/filp/whoops.git",
-                "reference": "6ecda5217bf048088b891f7403b262906be5a957"
+                "reference": "d501fd2658d55491a2295ff600ae5978eaad7403"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/filp/whoops/zipball/6ecda5217bf048088b891f7403b262906be5a957",
-                "reference": "6ecda5217bf048088b891f7403b262906be5a957",
+                "url": "https://api.github.com/repos/filp/whoops/zipball/d501fd2658d55491a2295ff600ae5978eaad7403",
+                "reference": "d501fd2658d55491a2295ff600ae5978eaad7403",
                 "shasum": ""
             },
             "require": {
@@ -701,7 +701,7 @@
             ],
             "support": {
                 "issues": "https://github.com/filp/whoops/issues",
-                "source": "https://github.com/filp/whoops/tree/2.10.0"
+                "source": "https://github.com/filp/whoops/tree/2.12.0"
             },
             "funding": [
                 {
@@ -709,7 +709,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2021-03-16T12:00:00+00:00"
+            "time": "2021-03-30T12:00:00+00:00"
         },
         {
             "name": "gregwar/cache",
@@ -812,16 +812,16 @@
         },
         {
             "name": "guzzlehttp/psr7",
-            "version": "1.7.0",
+            "version": "1.8.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/psr7.git",
-                "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3"
+                "reference": "35ea11d335fd638b5882ff1725228b3d35496ab1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/psr7/zipball/53330f47520498c0ae1f61f7e2c90f55690c06a3",
-                "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3",
+                "url": "https://api.github.com/repos/guzzle/psr7/zipball/35ea11d335fd638b5882ff1725228b3d35496ab1",
+                "reference": "35ea11d335fd638b5882ff1725228b3d35496ab1",
                 "shasum": ""
             },
             "require": {
@@ -881,9 +881,9 @@
             ],
             "support": {
                 "issues": "https://github.com/guzzle/psr7/issues",
-                "source": "https://github.com/guzzle/psr7/tree/1.7.0"
+                "source": "https://github.com/guzzle/psr7/tree/1.8.1"
             },
-            "time": "2020-09-30T07:37:11+00:00"
+            "time": "2021-03-21T16:25:00+00:00"
         },
         {
             "name": "itsgoingd/clockwork",
@@ -2246,16 +2246,16 @@
         },
         {
             "name": "symfony/console",
-            "version": "v4.4.20",
+            "version": "v4.4.21",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/console.git",
-                "reference": "c98349bda966c70d6c08b4cd8658377c94166492"
+                "reference": "1ba4560dbbb9fcf5ae28b61f71f49c678086cf23"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/console/zipball/c98349bda966c70d6c08b4cd8658377c94166492",
-                "reference": "c98349bda966c70d6c08b4cd8658377c94166492",
+                "url": "https://api.github.com/repos/symfony/console/zipball/1ba4560dbbb9fcf5ae28b61f71f49c678086cf23",
+                "reference": "1ba4560dbbb9fcf5ae28b61f71f49c678086cf23",
                 "shasum": ""
             },
             "require": {
@@ -2315,7 +2315,7 @@
             "description": "Eases the creation of beautiful and testable command line interfaces",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/console/tree/v4.4.20"
+                "source": "https://github.com/symfony/console/tree/v4.4.21"
             },
             "funding": [
                 {
@@ -2331,7 +2331,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-02-22T18:44:15+00:00"
+            "time": "2021-03-26T09:23:24+00:00"
         },
         {
             "name": "symfony/contracts",
@@ -2512,16 +2512,16 @@
         },
         {
             "name": "symfony/http-client",
-            "version": "v4.4.20",
+            "version": "v4.4.21",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/http-client.git",
-                "reference": "67c5af7489b3c2eea771abd973243f5c58f5fb40"
+                "reference": "911177e186b82e5b9a9f41c13af53699b6745657"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/http-client/zipball/67c5af7489b3c2eea771abd973243f5c58f5fb40",
-                "reference": "67c5af7489b3c2eea771abd973243f5c58f5fb40",
+                "url": "https://api.github.com/repos/symfony/http-client/zipball/911177e186b82e5b9a9f41c13af53699b6745657",
+                "reference": "911177e186b82e5b9a9f41c13af53699b6745657",
                 "shasum": ""
             },
             "require": {
@@ -2572,7 +2572,7 @@
             "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/http-client/tree/v4.4.20"
+                "source": "https://github.com/symfony/http-client/tree/v4.4.21"
             },
             "funding": [
                 {
@@ -2588,7 +2588,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-02-25T18:06:45+00:00"
+            "time": "2021-03-25T17:52:07+00:00"
         },
         {
             "name": "symfony/polyfill-ctype",
@@ -3055,16 +3055,16 @@
         },
         {
             "name": "symfony/var-dumper",
-            "version": "v4.4.20",
+            "version": "v4.4.21",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/var-dumper.git",
-                "reference": "a1eab2f69906dc83c5ddba4632180260d0ab4f7f"
+                "reference": "0da0e174f728996f5d5072d6a9f0a42259dbc806"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/a1eab2f69906dc83c5ddba4632180260d0ab4f7f",
-                "reference": "a1eab2f69906dc83c5ddba4632180260d0ab4f7f",
+                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/0da0e174f728996f5d5072d6a9f0a42259dbc806",
+                "reference": "0da0e174f728996f5d5072d6a9f0a42259dbc806",
                 "shasum": ""
             },
             "require": {
@@ -3124,7 +3124,7 @@
                 "dump"
             ],
             "support": {
-                "source": "https://github.com/symfony/var-dumper/tree/v4.4.20"
+                "source": "https://github.com/symfony/var-dumper/tree/v4.4.21"
             },
             "funding": [
                 {
@@ -3140,20 +3140,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-01-27T09:09:26+00:00"
+            "time": "2021-03-27T19:49:03+00:00"
         },
         {
             "name": "symfony/yaml",
-            "version": "v4.4.20",
+            "version": "v4.4.21",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/yaml.git",
-                "reference": "29e61305e1c79d25f71060903982ead8f533e267"
+                "reference": "3871c720871029f008928244e56cf43497da7e9d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/yaml/zipball/29e61305e1c79d25f71060903982ead8f533e267",
-                "reference": "29e61305e1c79d25f71060903982ead8f533e267",
+                "url": "https://api.github.com/repos/symfony/yaml/zipball/3871c720871029f008928244e56cf43497da7e9d",
+                "reference": "3871c720871029f008928244e56cf43497da7e9d",
                 "shasum": ""
             },
             "require": {
@@ -3195,7 +3195,7 @@
             "description": "Loads and dumps YAML files",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/yaml/tree/v4.4.20"
+                "source": "https://github.com/symfony/yaml/tree/v4.4.21"
             },
             "funding": [
                 {
@@ -3211,7 +3211,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-02-22T15:36:50+00:00"
+            "time": "2021-03-05T17:58:50+00:00"
         },
         {
             "name": "twig/twig",
@@ -3415,16 +3415,16 @@
         },
         {
             "name": "codeception/codeception",
-            "version": "4.1.18",
+            "version": "4.1.19",
             "source": {
                 "type": "git",
                 "url": "https://github.com/Codeception/Codeception.git",
-                "reference": "f47547bac347dfb5ea5351ff91148cbcc08e6818"
+                "reference": "138dc9345a81ec994dcd6b9680c501a752a37b00"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/Codeception/Codeception/zipball/f47547bac347dfb5ea5351ff91148cbcc08e6818",
-                "reference": "f47547bac347dfb5ea5351ff91148cbcc08e6818",
+                "url": "https://api.github.com/repos/Codeception/Codeception/zipball/138dc9345a81ec994dcd6b9680c501a752a37b00",
+                "reference": "138dc9345a81ec994dcd6b9680c501a752a37b00",
                 "shasum": ""
             },
             "require": {
@@ -3498,7 +3498,7 @@
             ],
             "support": {
                 "issues": "https://github.com/Codeception/Codeception/issues",
-                "source": "https://github.com/Codeception/Codeception/tree/4.1.18"
+                "source": "https://github.com/Codeception/Codeception/tree/4.1.19"
             },
             "funding": [
                 {
@@ -3506,7 +3506,7 @@
                     "type": "open_collective"
                 }
             ],
-            "time": "2021-02-23T17:11:42+00:00"
+            "time": "2021-03-28T13:26:08+00:00"
         },
         {
             "name": "codeception/lib-asserts",
@@ -3893,22 +3893,22 @@
         },
         {
             "name": "guzzlehttp/guzzle",
-            "version": "7.2.0",
+            "version": "7.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/guzzle.git",
-                "reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79"
+                "reference": "7008573787b430c1c1f650e3722d9bba59967628"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/0aa74dfb41ae110835923ef10a9d803a22d50e79",
-                "reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79",
+                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7008573787b430c1c1f650e3722d9bba59967628",
+                "reference": "7008573787b430c1c1f650e3722d9bba59967628",
                 "shasum": ""
             },
             "require": {
                 "ext-json": "*",
                 "guzzlehttp/promises": "^1.4",
-                "guzzlehttp/psr7": "^1.7",
+                "guzzlehttp/psr7": "^1.7 || ^2.0",
                 "php": "^7.2.5 || ^8.0",
                 "psr/http-client": "^1.0"
             },
@@ -3916,6 +3916,7 @@
                 "psr/http-client-implementation": "1.0"
             },
             "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.4.1",
                 "ext-curl": "*",
                 "php-http/client-integration-tests": "^3.0",
                 "phpunit/phpunit": "^8.5.5 || ^9.3.5",
@@ -3929,7 +3930,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "7.1-dev"
+                    "dev-master": "7.3-dev"
                 }
             },
             "autoload": {
@@ -3971,7 +3972,7 @@
             ],
             "support": {
                 "issues": "https://github.com/guzzle/guzzle/issues",
-                "source": "https://github.com/guzzle/guzzle/tree/7.2.0"
+                "source": "https://github.com/guzzle/guzzle/tree/7.3.0"
             },
             "funding": [
                 {
@@ -3991,7 +3992,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-10-10T11:47:56+00:00"
+            "time": "2021-03-23T11:33:13+00:00"
         },
         {
             "name": "guzzlehttp/promises",
@@ -4433,16 +4434,16 @@
         },
         {
             "name": "phpspec/prophecy",
-            "version": "1.12.2",
+            "version": "1.13.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpspec/prophecy.git",
-                "reference": "245710e971a030f42e08f4912863805570f23d39"
+                "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpspec/prophecy/zipball/245710e971a030f42e08f4912863805570f23d39",
-                "reference": "245710e971a030f42e08f4912863805570f23d39",
+                "url": "https://api.github.com/repos/phpspec/prophecy/zipball/be1996ed8adc35c3fd795488a653f4b518be70ea",
+                "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea",
                 "shasum": ""
             },
             "require": {
@@ -4494,22 +4495,22 @@
             ],
             "support": {
                 "issues": "https://github.com/phpspec/prophecy/issues",
-                "source": "https://github.com/phpspec/prophecy/tree/1.12.2"
+                "source": "https://github.com/phpspec/prophecy/tree/1.13.0"
             },
-            "time": "2020-12-19T10:15:11+00:00"
+            "time": "2021-03-17T13:42:18+00:00"
         },
         {
             "name": "phpstan/phpstan",
-            "version": "0.12.81",
+            "version": "0.12.82",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpstan/phpstan.git",
-                "reference": "0dd5b0ebeff568f7000022ea5f04aa86ad3124b8"
+                "reference": "3920f0fb0aff39263d3a4cb0bca120a67a1a6a11"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0dd5b0ebeff568f7000022ea5f04aa86ad3124b8",
-                "reference": "0dd5b0ebeff568f7000022ea5f04aa86ad3124b8",
+                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/3920f0fb0aff39263d3a4cb0bca120a67a1a6a11",
+                "reference": "3920f0fb0aff39263d3a4cb0bca120a67a1a6a11",
                 "shasum": ""
             },
             "require": {
@@ -4540,7 +4541,7 @@
             "description": "PHPStan - PHP Static Analysis Tool",
             "support": {
                 "issues": "https://github.com/phpstan/phpstan/issues",
-                "source": "https://github.com/phpstan/phpstan/tree/0.12.81"
+                "source": "https://github.com/phpstan/phpstan/tree/0.12.82"
             },
             "funding": [
                 {
@@ -4556,7 +4557,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-03-08T22:03:02+00:00"
+            "time": "2021-03-19T06:08:17+00:00"
         },
         {
             "name": "phpstan/phpstan-deprecation-rules",
@@ -4611,16 +4612,16 @@
         },
         {
             "name": "phpunit/php-code-coverage",
-            "version": "9.2.5",
+            "version": "9.2.6",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-                "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1"
+                "reference": "f6293e1b30a2354e8428e004689671b83871edde"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f3e026641cc91909d421802dd3ac7827ebfd97e1",
-                "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f6293e1b30a2354e8428e004689671b83871edde",
+                "reference": "f6293e1b30a2354e8428e004689671b83871edde",
                 "shasum": ""
             },
             "require": {
@@ -4676,7 +4677,7 @@
             ],
             "support": {
                 "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
-                "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.5"
+                "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.6"
             },
             "funding": [
                 {
@@ -4684,7 +4685,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2020-11-28T06:44:49+00:00"
+            "time": "2021-03-28T07:26:59+00:00"
         },
         {
             "name": "phpunit/php-file-iterator",
@@ -4929,16 +4930,16 @@
         },
         {
             "name": "phpunit/phpunit",
-            "version": "9.5.3",
+            "version": "9.5.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "27241ac75fc37ecf862b6e002bf713b6566cbe41"
+                "reference": "c73c6737305e779771147af66c96ca6a7ed8a741"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/27241ac75fc37ecf862b6e002bf713b6566cbe41",
-                "reference": "27241ac75fc37ecf862b6e002bf713b6566cbe41",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c73c6737305e779771147af66c96ca6a7ed8a741",
+                "reference": "c73c6737305e779771147af66c96ca6a7ed8a741",
                 "shasum": ""
             },
             "require": {
@@ -5016,7 +5017,7 @@
             ],
             "support": {
                 "issues": "https://github.com/sebastianbergmann/phpunit/issues",
-                "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.3"
+                "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.4"
             },
             "funding": [
                 {
@@ -5028,7 +5029,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2021-03-17T07:30:34+00:00"
+            "time": "2021-03-23T07:16:29+00:00"
         },
         {
             "name": "psr/http-client",

+ 39 - 0
system/blueprints/config/system.yaml

@@ -1282,6 +1282,45 @@ form:
               validate:
                 type: commalist
 
+            section_images_cls:
+              type: section
+              title: PLUGIN_ADMIN.IMAGES_CLS_TITLE
+              underline: true
+
+            images.cls.auto_sizes:
+              type: toggle
+              label: PLUGIN_ADMIN.IMAGES_CLS_AUTO_SIZES
+              help: PLUGIN_ADMIN.IMAGES_CLS_AUTO_SIZES_HELP
+              highlight: 0
+              options:
+                1: PLUGIN_ADMIN.YES
+                0: PLUGIN_ADMIN.NO
+              validate:
+                type: bool
+
+            images.cls.aspect_ratio:
+              type: toggle
+              label: PLUGIN_ADMIN.IMAGES_CLS_ASPECT_RATIO
+              help: PLUGIN_ADMIN.IMAGES_CLS_ASPECT_RATIO_HELP
+              highlight: 0
+              options:
+                1: PLUGIN_ADMIN.YES
+                0: PLUGIN_ADMIN.NO
+              validate:
+                type: bool
+
+            images.cls.retina_scale:
+              type: select
+              label: PLUGIN_ADMIN.IMAGES_CLS_RETINA_SCALE
+              help: PLUGIN_ADMIN.IMAGES_CLS_RETINA_SCALE_HELP
+              size: small
+              highlight: 1
+              options:
+                1: 1X
+                2: 2X
+                3: 3X
+                4: 4X
+
         session:
           type: tab
           title: PLUGIN_ADMIN.SESSION

+ 0 - 8
system/blueprints/pages/default.yaml

@@ -35,18 +35,10 @@ form:
                 validate:
                   type: textarea
 
-
-
             header.media_order:
               type: pagemedia
               label: PLUGIN_ADMIN.PAGE_MEDIA
 
-            background_image:
-              type: filepicker
-              label: image pour fond parallax
-
-
-
         options:
           type: tab
           title: PLUGIN_ADMIN.OPTIONS

+ 4 - 0
system/config/system.yaml

@@ -154,6 +154,10 @@ images:
   debug: false                                   # Show an overlay over images indicating the pixel depth of the image when working with retina for example
   auto_fix_orientation: true                     # Automatically fix the image orientation based on the Exif data
   seofriendly: false                             # SEO-friendly processed image names
+  cls:                                           # Cumulative Layout Shift: See https://web.dev/optimize-cls/
+    auto_sizes: false                            # Automatically add height/width to image
+    aspect_ratio: false                          # Reserve space with aspect ratio style
+    retina_scale: 1                              # scale to adjust auto-sizes for better handling of HiDPI resolutions
   defaults:
     loading: auto                                # Let browser pick [auto|lazy|eager]
 

+ 15 - 8
system/defines.php

@@ -8,7 +8,7 @@
 
 // Some standard defines
 define('GRAV', true);
-define('GRAV_VERSION', '1.7.9');
+define('GRAV_VERSION', '1.7.10');
 define('GRAV_SCHEMA', '1.7.0_2020-11-20_1');
 define('GRAV_TESTING', false);
 
@@ -27,10 +27,17 @@ if (!defined('GRAV_ROOT')) {
     $path = rtrim(str_replace(DIRECTORY_SEPARATOR, DS, getenv('GRAV_ROOT') ?: getcwd()), DS);
     define('GRAV_ROOT', $path);
 }
+if (!defined('GRAV_WEBROOT')) {
+    define('GRAV_WEBROOT', GRAV_ROOT);
+}
 if (!defined('GRAV_USER_PATH')) {
     $path = rtrim(getenv('GRAV_USER_PATH') ?: 'user', DS);
     define('GRAV_USER_PATH', $path);
 }
+if (!defined('GRAV_SYSTEM_PATH')) {
+    $path = rtrim(getenv('GRAV_SYSTEM_PATH') ?: 'system', DS);
+    define('GRAV_SYSTEM_PATH', $path);
+}
 if (!defined('GRAV_CACHE_PATH')) {
     $path = rtrim(getenv('GRAV_CACHE_PATH') ?: 'cache', DS);
     define('GRAV_CACHE_PATH', $path);
@@ -52,21 +59,21 @@ unset($path);
 define('USER_PATH', GRAV_USER_PATH . DS);
 define('CACHE_PATH', GRAV_CACHE_PATH . DS);
 define('ROOT_DIR', GRAV_ROOT . DS);
-define('USER_DIR', ROOT_DIR . USER_PATH);
-define('CACHE_DIR', ROOT_DIR . CACHE_PATH);
+define('USER_DIR', (!str_starts_with(USER_PATH, '/') ? GRAV_WEBROOT . '/' : '') . USER_PATH);
+define('CACHE_DIR', (!str_starts_with(CACHE_PATH, '/') ? ROOT_DIR : '') . CACHE_PATH);
 
 // DEPRECATED: Do not use!
-define('ASSETS_DIR', ROOT_DIR . 'assets/');
-define('IMAGES_DIR', ROOT_DIR . 'images/');
+define('ASSETS_DIR', GRAV_WEBROOT . '/assets/');
+define('IMAGES_DIR', GRAV_WEBROOT . '/images/');
 define('ACCOUNTS_DIR', USER_DIR .'accounts/');
 define('PAGES_DIR', USER_DIR .'pages/');
 define('DATA_DIR', USER_DIR .'data/');
-define('SYSTEM_DIR', ROOT_DIR .'system/');
-define('LIB_DIR', SYSTEM_DIR .'src/');
 define('PLUGINS_DIR', USER_DIR .'plugins/');
 define('THEMES_DIR', USER_DIR .'themes/');
+define('SYSTEM_DIR', (!str_starts_with(GRAV_SYSTEM_PATH, '/') ? ROOT_DIR : '') . GRAV_SYSTEM_PATH);
+define('LIB_DIR', SYSTEM_DIR .'src/');
 define('VENDOR_DIR', ROOT_DIR .'vendor/');
-define('LOG_DIR', ROOT_DIR . GRAV_LOG_PATH . DS);
+define('LOG_DIR', (!str_starts_with(GRAV_LOG_PATH, '/') ? ROOT_DIR : '') . GRAV_LOG_PATH . DS);
 // END DEPRECATED
 
 // Some extensions

+ 7 - 8
system/src/Grav/Common/Assets/BaseAsset.php

@@ -125,7 +125,7 @@ abstract class BaseAsset extends PropertyObject
                 if ($locator->isStream($asset)) {
                     $path = $locator->findResource($asset, true);
                 } else {
-                    $path = GRAV_ROOT . $asset;
+                    $path = GRAV_WEBROOT . $asset;
                 }
 
                 // If local file is missing return
@@ -172,15 +172,14 @@ abstract class BaseAsset extends PropertyObject
 
         return $this;
     }
-    
+
     /**
      * Receive asset location and return the SRI integrity hash
-     * 
-     * @param $input
      *
+     * @param string $input
      * @return string
      */
-    public static function integrityHash( $input )
+    public static function integrityHash($input)
     {
         $grav = Grav::instance();
 
@@ -188,7 +187,7 @@ abstract class BaseAsset extends PropertyObject
 
         if ( !empty($assetsConfig['enable_asset_sri']) && $assetsConfig['enable_asset_sri'] )
         {
-            $dataToHash = file_get_contents( GRAV_ROOT . $input);
+            $dataToHash = file_get_contents( GRAV_WEBROOT . $input);
 
             $hash = hash('sha256', $dataToHash, true);
             $hash_base64 = base64_encode($hash);
@@ -209,7 +208,7 @@ abstract class BaseAsset extends PropertyObject
      */
 //    protected function getLastModificationTime($asset)
 //    {
-//        $file = GRAV_ROOT . $asset;
+//        $file = GRAV_WEBROOT . $asset;
 //        if (Grav::instance()['locator']->isStream($asset)) {
 //            $file = $this->buildLocalLink($asset, true);
 //        }
@@ -228,7 +227,7 @@ abstract class BaseAsset extends PropertyObject
     protected function buildLocalLink($asset)
     {
         if ($asset) {
-            return $this->base_url . ltrim(Utils::replaceFirstOccurrence(GRAV_ROOT, '', $asset), '/');
+            return $this->base_url . ltrim(Utils::replaceFirstOccurrence(GRAV_WEBROOT, '', $asset), '/');
         }
         return false;
     }

+ 0 - 1
system/src/Grav/Common/Cache.php

@@ -127,7 +127,6 @@ class Cache extends Getters
      */
     public function init(Grav $grav)
     {
-        /** @var Config $config */
         $this->config = $grav['config'];
         $this->now = time();
 

+ 7 - 5
system/src/Grav/Common/Config/Setup.php

@@ -164,6 +164,8 @@ class Setup extends Data
     public function __construct($container)
     {
         // Configure main streams.
+        $abs = str_starts_with(GRAV_SYSTEM_PATH, '/');
+        $this->streams['system']['prefixes'][''] = $abs ? ['system', GRAV_SYSTEM_PATH] : ['system'];
         $this->streams['user']['prefixes'][''] = [GRAV_USER_PATH];
         $this->streams['cache']['prefixes'][''] = [GRAV_CACHE_PATH];
         $this->streams['log']['prefixes'][''] = [GRAV_LOG_PATH];
@@ -197,16 +199,16 @@ class Setup extends Data
         if (null !== $setupFile) {
             // Make sure that the custom setup file exists. Terminates the script if not.
             if (!str_starts_with($setupFile, '/')) {
-                $setupFile = GRAV_ROOT . '/' . $setupFile;
+                $setupFile = GRAV_WEBROOT . '/' . $setupFile;
             }
             if (!is_file($setupFile)) {
                 echo 'GRAV_SETUP_PATH is defined but does not point to existing setup file.';
                 exit(1);
             }
         } else {
-            $setupFile = GRAV_ROOT . '/setup.php';
+            $setupFile = GRAV_WEBROOT . '/setup.php';
             if (!is_file($setupFile)) {
-                $setupFile = GRAV_ROOT . '/' . GRAV_USER_PATH . '/setup.php';
+                $setupFile = GRAV_WEBROOT . '/' . GRAV_USER_PATH . '/setup.php';
             }
             if (!is_file($setupFile)) {
                 $setupFile = null;
@@ -234,7 +236,7 @@ class Setup extends Data
                 $envPath .= '/';
             } else {
                 // Use default location. Start with Grav 1.7 default.
-                $envPath = GRAV_ROOT. '/' . GRAV_USER_PATH . '/env';
+                $envPath = GRAV_WEBROOT. '/' . GRAV_USER_PATH . '/env';
                 if (is_dir($envPath)) {
                     $envPath = 'user://env/';
                 } else {
@@ -257,7 +259,7 @@ class Setup extends Data
      */
     public function init()
     {
-        $locator = new UniformResourceLocator(GRAV_ROOT);
+        $locator = new UniformResourceLocator(GRAV_WEBROOT);
         $files = [];
 
         $guard = 5;

+ 5 - 1
system/src/Grav/Common/Data/Blueprint.php

@@ -524,8 +524,12 @@ class Blueprint extends BlueprintForm
      * @param string $op
      * @return bool
      */
-    protected function resolveActions(UserInterface $user, array $actions, string $op = 'and')
+    protected function resolveActions(?UserInterface $user, array $actions, string $op = 'and')
     {
+        if (null === $user) {
+            return false;
+        }
+
         $c = $i = count($actions);
         foreach ($actions as $key => $action) {
             if (!is_int($key) && is_array($actions)) {

+ 1 - 1
system/src/Grav/Common/Filesystem/Archiver.php

@@ -62,7 +62,7 @@ abstract class Archiver
     {
         // Set infinite PHP execution time if possible.
         if (Utils::functionExists('set_time_limit')) {
-            set_time_limit(0);
+            @set_time_limit(0);
         }
 
         $this->options = $options + $this->options;

+ 5 - 5
system/src/Grav/Common/Filesystem/Folder.php

@@ -371,6 +371,10 @@ abstract class Folder
             return;
         }
 
+        if (strpos($target, $source) === 0) {
+            throw new RuntimeException('Cannot move folder to itself');
+        }
+
         if (file_exists($target)) {
             // Rename fails if target folder exists.
             throw new RuntimeException('Cannot move files to existing folder/file.');
@@ -383,11 +387,7 @@ abstract class Folder
         @rename($source, $target);
 
         // Rename function can fail while still succeeding, so let's check if the folder exists.
-        if (!file_exists($target) || !is_dir($target)) {
-            // In some rare cases rename() creates file, not a folder. Get rid of it.
-            if (file_exists($target)) {
-                @unlink($target);
-            }
+        if (is_dir($source)) {
             // Rename doesn't support moving folders across filesystems. Use copy instead.
             self::copy($source, $target);
             self::delete($source);

+ 1 - 2
system/src/Grav/Common/Flex/FlexCollection.php

@@ -18,9 +18,8 @@ use Grav\Common\Flex\Traits\FlexGravTrait;
  * Class FlexCollection
  *
  * @package Grav\Common\Flex
- * @template TKey
  * @template T of \Grav\Framework\Flex\Interfaces\FlexObjectInterface
- * @extends \Grav\Framework\Flex\FlexCollection<TKey,T>
+ * @extends \Grav\Framework\Flex\FlexCollection<T>
  */
 abstract class FlexCollection extends \Grav\Framework\Flex\FlexCollection
 {

+ 1 - 2
system/src/Grav/Common/Flex/FlexIndex.php

@@ -18,10 +18,9 @@ use Grav\Common\Flex\Traits\FlexIndexTrait;
  * Class FlexIndex
  *
  * @package Grav\Common\Flex
- * @template TKey
  * @template T of \Grav\Framework\Flex\Interfaces\FlexObjectInterface
  * @template C of \Grav\Framework\Flex\Interfaces\FlexCollectionInterface
- * @extends \Grav\Framework\Flex\FlexIndex<TKey,T,C>
+ * @extends \Grav\Framework\Flex\FlexIndex<T,C>
  */
 abstract class FlexIndex extends \Grav\Framework\Flex\FlexIndex
 {

+ 1 - 1
system/src/Grav/Common/Flex/Types/Generic/GenericCollection.php

@@ -17,7 +17,7 @@ use Grav\Common\Flex\FlexCollection;
  * Class GenericCollection
  * @package Grav\Common\Flex\Generic
  *
- * @extends FlexCollection<string,GenericObject>
+ * @extends FlexCollection<GenericObject>
  */
 class GenericCollection extends FlexCollection
 {

+ 1 - 1
system/src/Grav/Common/Flex/Types/Generic/GenericIndex.php

@@ -17,7 +17,7 @@ use Grav\Common\Flex\FlexIndex;
  * Class GenericIndex
  * @package Grav\Common\Flex\Generic
  *
- * @extends FlexIndex<string,GenericObject,GenericCollection>
+ * @extends FlexIndex<GenericObject,GenericCollection>
  */
 class GenericIndex extends FlexIndex
 {

+ 1 - 1
system/src/Grav/Common/Flex/Types/Pages/PageCollection.php

@@ -35,7 +35,7 @@ use function is_string;
  * Class GravPageCollection
  * @package Grav\Plugin\FlexObjects\Types\GravPages
  *
- * @extends FlexPageCollection<string,PageObject>
+ * @extends FlexPageCollection<PageObject>
  *
  * Incompatibilities with Grav\Common\Page\Collection:
  *     $page = $collection->key()       will not work at all

+ 1 - 1
system/src/Grav/Common/Flex/Types/Pages/PageIndex.php

@@ -38,7 +38,7 @@ use function is_string;
  * Class GravPageObject
  * @package Grav\Plugin\FlexObjects\Types\GravPages
  *
- * @extends FlexPageIndex<string,PageObject,PageCollection>
+ * @extends FlexPageIndex<PageObject,PageCollection>
  *
  * @method PageIndex withModules(bool $bool = true)
  * @method PageIndex withPages(bool $bool = true)

+ 17 - 4
system/src/Grav/Common/Flex/Types/Pages/PageObject.php

@@ -204,10 +204,7 @@ class PageObject extends FlexPageObject
             }
 
             // Make sure page isn't being moved under itself.
-            $key = $this->getKey();
-            if ($key === $parentKey || strpos($parentKey, $key . '/') === 0) {
-                throw new RuntimeException(sprintf('Page /%s cannot be moved to %s', $key, $parentRoute));
-            }
+            $key = $this->getStorageKey();
 
             /** @var PageObject|null $parent */
             $parent = $parentKey !== false ? $this->getFlexDirectory()->getObject($parentKey, 'storage_key') : null;
@@ -301,6 +298,22 @@ class PageObject extends FlexPageObject
         return $instance;
     }
 
+    /**
+     * @return PageObject
+     */
+    public function delete()
+    {
+        $result = parent::delete();
+
+        // Backwards compatibility with older plugins.
+        $fireEvents = $this->isAdminSite() && $this->getFlexDirectory()->getConfig('object.compat.events', true);
+        if ($fireEvents) {
+            $this->getContainer()->fireEvent('onAdminAfterDelete', new Event(['object' => $this]));
+        }
+
+        return $result;
+    }
+
     /**
      * Prepare move page to new location. Moves also everything that's under the current page.
      *

+ 10 - 2
system/src/Grav/Common/Flex/Types/Pages/Storage/PageStorage.php

@@ -373,7 +373,7 @@ class PageStorage extends FolderStorage
 
         try {
             if ($key === '' && empty($row['root'])) {
-                throw new RuntimeException('No storage key given');
+                throw new RuntimeException('Page has no path');
             }
 
             $grav = Grav::instance();
@@ -394,9 +394,17 @@ class PageStorage extends FolderStorage
                 if ($oldFolder !== $newFolder && file_exists($oldFolder)) {
                     $isCopy = $row['__META']['copy'] ?? false;
                     if ($isCopy) {
+                        if (strpos($newFolder, $oldFolder . '/') === 0) {
+                            throw new RuntimeException(sprintf('Page /%s cannot be copied to itself', $oldKey));
+                        }
+
                         $this->copyRow($oldKey, $newKey);
                         $debugger->addMessage("Page copied: {$oldFolder} => {$newFolder}", 'debug');
                     } else {
+                        if (strpos($newFolder, $oldFolder . '/') === 0) {
+                            throw new RuntimeException(sprintf('Page /%s cannot be moved to itself', $oldKey));
+                        }
+
                         $this->renameRow($oldKey, $newKey);
                         $debugger->addMessage("Page moved: {$oldFolder} => {$newFolder}", 'debug');
                     }
@@ -534,7 +542,7 @@ class PageStorage extends FolderStorage
             $markdown = [];
             $children = [];
 
-            if (is_string($path) && file_exists($path)) {
+            if (is_string($path) && is_dir($path)) {
                 $modified = filemtime($path);
                 $iterator = new FilesystemIterator($path, $this->flags);
 

+ 1 - 1
system/src/Grav/Common/Flex/Types/UserGroups/UserGroupCollection.php

@@ -17,7 +17,7 @@ use Grav\Common\Flex\FlexCollection;
  * Class UserGroupCollection
  * @package Grav\Common\Flex\Types\UserGroups
  *
- * @extends FlexCollection<string,UserGroupObject>
+ * @extends FlexCollection<UserGroupObject>
  */
 class UserGroupCollection extends FlexCollection
 {

+ 1 - 1
system/src/Grav/Common/Flex/Types/UserGroups/UserGroupIndex.php

@@ -17,7 +17,7 @@ use Grav\Common\Flex\FlexIndex;
  * Class GroupIndex
  * @package Grav\Common\User\FlexUser
  *
- * @extends FlexIndex<string,UserGroupObject,UserGroupCollection>
+ * @extends FlexIndex<UserGroupObject,UserGroupCollection>
  */
 class UserGroupIndex extends FlexIndex
 {

+ 1 - 1
system/src/Grav/Common/Flex/Types/Users/UserCollection.php

@@ -20,7 +20,7 @@ use function is_string;
  * Class UserCollection
  * @package Grav\Common\Flex\Types\Users
  *
- * @extends FlexCollection<string,UserObject>
+ * @extends FlexCollection<UserObject>
  */
 class UserCollection extends FlexCollection implements UserCollectionInterface
 {

+ 21 - 3
system/src/Grav/Common/Flex/Types/Users/UserIndex.php

@@ -15,20 +15,20 @@ use Grav\Common\Debugger;
 use Grav\Common\File\CompiledYamlFile;
 use Grav\Common\Flex\FlexIndex;
 use Grav\Common\Grav;
+use Grav\Common\User\Interfaces\UserCollectionInterface;
 use Grav\Common\User\Interfaces\UserInterface;
 use Grav\Framework\Flex\Interfaces\FlexStorageInterface;
 use Monolog\Logger;
 use function count;
 use function is_string;
-use function method_exists;
 
 /**
  * Class UserIndex
  * @package Grav\Common\Flex\Types\Users
  *
- * @extends FlexIndex<string,UserObject,UserCollection>
+ * @extends FlexIndex<UserObject,UserCollection>
  */
-class UserIndex extends FlexIndex
+class UserIndex extends FlexIndex implements UserCollectionInterface
 {
     public const VERSION = parent::VERSION . '.1';
 
@@ -106,6 +106,24 @@ class UserIndex extends FlexIndex
         return $object;
     }
 
+    /**
+     * Delete user account.
+     *
+     * @param string $username
+     * @return bool True if user account was found and was deleted.
+     */
+    public function delete($username): bool
+    {
+        $user = $this->load($username);
+
+        $exists = $user->exists();
+        if ($exists) {
+            $user->delete();
+        }
+
+        return $exists;
+    }
+
     /**
      * Find a user by username, email, etc
      *

+ 10 - 5
system/src/Grav/Common/Flex/Types/Users/UserObject.php

@@ -538,13 +538,18 @@ class UserObject extends FlexObject implements UserInterface, Countable
             }
         }
 
-        $password = $this->getProperty('password');
-        if (null !== $password) {
-            $this->unsetProperty('password');
-            $this->unsetProperty('password1');
-            $this->unsetProperty('password2');
+        $password = $this->getProperty('password') ?? $this->getProperty('password1');
+        if (null !== $password && '' !== $password) {
+            $password2 = $this->getProperty('password2');
+            if (!\is_string($password) || ($password2 && $password !== $password2)) {
+                throw new \RuntimeException('Passwords did not match.');
+            }
+
             $this->setProperty('hashed_password', Authentication::create($password));
         }
+        $this->unsetProperty('password');
+        $this->unsetProperty('password1');
+        $this->unsetProperty('password2');
 
         // Backwards compatibility with older plugins.
         $fireEvents = $this->isAdminSite() && $this->getFlexDirectory()->getConfig('object.compat.events', true);

+ 1 - 1
system/src/Grav/Common/GPM/Licenses.php

@@ -63,7 +63,7 @@ class Licenses
      * Returns the license for a Premium package
      *
      * @param string|null $slug
-     * @return array|string
+     * @return string[]|string
      */
     public static function get($slug = null)
     {

+ 1 - 1
system/src/Grav/Common/GPM/Response.php

@@ -53,7 +53,7 @@ class Response
         // check if this function is available, if so use it to stop any timeouts
         try {
             if (Utils::functionExists('set_time_limit')) {
-                set_time_limit(0);
+                @set_time_limit(0);
             }
         } catch (Exception $e) {
         }

+ 17 - 1
system/src/Grav/Common/Media/Traits/ImageMediaTrait.php

@@ -41,6 +41,16 @@ trait ImageMediaTrait
     /** @var bool */
     protected $debug_watermarked = false;
 
+    /** @var bool  */
+    protected $auto_sizes;
+
+    /** @var bool */
+    protected $aspect_ratio;
+
+    /** @var integer */
+    protected $retina_scale;
+
+
     /** @var array */
     public static $magic_actions = [
         'resize', 'forceResize', 'cropResize', 'crop', 'zoomCrop',
@@ -358,11 +368,17 @@ trait ImageMediaTrait
             ->setPrettyName($this->getImagePrettyName());
 
         // Fix orientation if enabled
-        if (Grav::instance()['config']->get('system.images.auto_fix_orientation', false) &&
+        $config = Grav::instance()['config'];
+        if ($config->get('system.images.auto_fix_orientation', false) &&
             extension_loaded('exif') && function_exists('exif_read_data')) {
             $this->image->fixOrientation();
         }
 
+        // Set CLS configuration
+        $this->auto_sizes = $config->get('system.images.cls.auto_sizes', false);
+        $this->aspect_ratio = $config->get('system.images.cls.aspect_ratio', false);
+        $this->retina_scale = $config->get('system.images.cls.retina_scale', 1);
+
         return $this;
     }
 

+ 52 - 1
system/src/Grav/Common/Page/Medium/ImageMedium.php

@@ -30,6 +30,11 @@ class ImageMedium extends Medium implements ImageMediaInterface, ImageManipulate
     use ImageMediaTrait;
     use ImageLoadingTrait;
 
+    /**
+     * @var mixed|string
+     */
+    private $saved_image_path;
+
     /**
      * Construct.
      *
@@ -121,6 +126,12 @@ class ImageMedium extends Medium implements ImageMediaInterface, ImageManipulate
 
         $this->debug_watermarked = false;
 
+        $config = $this->getGrav()['config'];
+        // Set CLS configuration
+        $this->auto_sizes = $config->get('system.images.cls.auto_sizes', false);
+        $this->aspect_ratio = $config->get('system.images.cls.aspect_ratio', false);
+        $this->retina_scale = $config->get('system.images.cls.retina_scale', 1);
+
         return $this;
     }
 
@@ -170,7 +181,7 @@ class ImageMedium extends Medium implements ImageMediaInterface, ImageManipulate
         /** @var UniformResourceLocator $locator */
         $locator = $grav['locator'];
         $image_path = (string)($locator->findResource('cache://images', true) ?: $locator->findResource('cache://images', true, true));
-        $saved_image_path = $this->saveImage();
+        $saved_image_path = $this->saved_image_path = $this->saveImage();
 
         $output = preg_replace('|^' . preg_quote(GRAV_ROOT, '|') . '|', '', $saved_image_path) ?: $saved_image_path;
 
@@ -232,6 +243,23 @@ class ImageMedium extends Medium implements ImageMediaInterface, ImageManipulate
             $attributes['sizes'] = $this->sizes();
         }
 
+        if ($this->saved_image_path && $this->auto_sizes) {
+            if (!array_key_exists('height', $this->attributes) && !array_key_exists('width', $this->attributes)) {
+                $info = getimagesize($this->saved_image_path);
+                $width = intval($info[0]);
+                $height = intval($info[1]);
+
+                $scaling_factor = $this->retina_scale > 0 ? $this->retina_scale : 1;
+                $attributes['width'] = intval($width / $scaling_factor);
+                $attributes['height'] = intval($height / $scaling_factor);
+
+                if ($this->aspect_ratio) {
+                    $style = ($attributes['style'] ?? ' ') . "--aspect-ratio: $width/$height;";
+                    $attributes['style'] = trim($style);
+                }
+            }
+        }
+
         return ['name' => 'img', 'attributes' => $attributes];
     }
 
@@ -274,6 +302,29 @@ class ImageMedium extends Medium implements ImageMediaInterface, ImageManipulate
         return parent::lightbox($width, $height, $reset);
     }
 
+    public function autoSizes($enabled = 'true')
+    {
+        $enabled = $enabled === 'true' ?: false;
+        $this->auto_sizes = $enabled;
+
+        return $this;
+    }
+
+    public function aspectRatio($enabled = 'true')
+    {
+        $enabled = $enabled === 'true' ?: false;
+        $this->aspect_ratio = $enabled;
+
+        return $this;
+    }
+
+    public function retinaScale($scale = 1)
+    {
+        $this->retina_scale = intval($scale);
+
+        return $this;
+    }
+
     /**
      * Handle this commonly used variant
      *

+ 1 - 1
system/src/Grav/Common/Page/Types.php

@@ -61,7 +61,7 @@ class Types implements \ArrayAccess, \Iterator, \Countable
      */
     public function init()
     {
-        if (null === $this->systemBlueprints) {
+        if (empty($this->systemBlueprints)) {
             // Register all blueprints from the blueprints stream.
             $this->systemBlueprints = $this->findBlueprints('blueprints://pages');
             foreach ($this->systemBlueprints as $type => $blueprint) {

+ 1 - 1
system/src/Grav/Common/Processors/InitializeProcessor.php

@@ -178,7 +178,7 @@ class InitializeProcessor extends ProcessorBase
         $grav['plugins']->setup();
 
         if (defined('GRAV_SCHEMA') && $config->get('versions') === null) {
-            $filename = GRAV_ROOT . '/user/config/versions.yaml';
+            $filename = USER_DIR . 'config/versions.yaml';
             if (!is_file($filename)) {
                 $versions = [
                     'core' => [

+ 1 - 1
system/src/Grav/Common/Service/StreamsServiceProvider.php

@@ -30,7 +30,7 @@ class StreamsServiceProvider implements ServiceProviderInterface
     public function register(Container $container)
     {
         $container['locator'] = function (Container $container) {
-            $locator = new UniformResourceLocator(GRAV_ROOT);
+            $locator = new UniformResourceLocator(GRAV_WEBROOT);
 
             /** @var Setup $setup */
             $setup = $container['setup'];

+ 2 - 2
system/src/Grav/Common/Session.php

@@ -128,12 +128,12 @@ class Session extends \Grav\Framework\Session\Session
                 /** @var Uri $uri */
                 $uri = $grav['uri'];
                 /** @var Forms|null $form */
-                $form = $grav['forms']->getActiveForm();
+                $form = $grav['forms']->getActiveForm(); // @phpstan-ignore-line
 
                 $sessionField = base64_encode($uri->url);
 
                 /** @var FormFlash|null $flash */
-                $flash = $form ? $form->getFlash() : null;
+                $flash = $form ? $form->getFlash() : null; // @phpstan-ignore-line
                 $object = $flash && method_exists($flash, 'getLegacyFiles') ? [$sessionField => $flash->getLegacyFiles()] : null;
             }
         }

+ 2 - 2
system/src/Grav/Common/Uri.php

@@ -205,8 +205,8 @@ class Uri
         // set active language
         $uri = $language->setActiveFromUri($uri);
 
-        // split the URL and params
-        $bits = parse_url($uri);
+        // split the URL and params (and make sure that the path isn't seen as domain)
+        $bits = parse_url('http://domain.com' . $uri);
 
         //process fragment
         if (isset($bits['fragment'])) {

+ 10 - 3
system/src/Grav/Common/User/DataUser/User.php

@@ -131,11 +131,18 @@ class User extends Data implements UserInterface
             }
 
             // if plain text password, hash it and remove plain text
-            $password = $this->get('password');
-            if ($password) {
+            $password = $this->get('password') ?? $this->get('password1');
+            if (null !== $password && '' !== $password) {
+                $password2 = $this->get('password2');
+                if (!\is_string($password) || ($password2 && $password !== $password2)) {
+                    throw new \RuntimeException('Passwords did not match.');
+                }
+
                 $this->set('hashed_password', Authentication::create($password));
-                $this->undef('password');
             }
+            $this->undef('password');
+            $this->undef('password1');
+            $this->undef('password2');
 
             $data = $this->items;
             if ($username === $data['username']) {

+ 4 - 6
system/src/Grav/Framework/Flex/FlexCollection.php

@@ -37,10 +37,9 @@ use function is_scalar;
 /**
  * Class FlexCollection
  * @package Grav\Framework\Flex
- * @template TKey
  * @template T of FlexObjectInterface
- * @extends ObjectCollection<TKey,T>
- * @implements FlexCollectionInterface<TKey,T>
+ * @extends ObjectCollection<string,T>
+ * @implements FlexCollectionInterface<T>
  */
 class FlexCollection extends ObjectCollection implements FlexCollectionInterface
 {
@@ -460,7 +459,6 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface
     /**
      * @param string $key
      * @return array
-     * @phpstan-param TKey $key
      */
     public function getMetaData(string $key): array
     {
@@ -491,7 +489,7 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface
      * @param string|null $scope
      * @param UserInterface|null $user
      * @return static
-     * @phpstan-return static<TKey,T>
+     * @phpstan-return static<T>
      */
     public function isAuthorized(string $action, string $scope = null, UserInterface $user = null)
     {
@@ -559,7 +557,7 @@ class FlexCollection extends ObjectCollection implements FlexCollectionInterface
      * @param array $elements Elements.
      * @param string|null $keyField
      * @return static
-     * @phpstan-return static<TKey,T>
+     * @phpstan-return static<T>
      * @throws \InvalidArgumentException
      */
     protected function createFrom(array $elements, $keyField = null)

+ 1 - 2
system/src/Grav/Framework/Flex/FlexDirectory.php

@@ -46,7 +46,6 @@ use function is_callable;
  * Class FlexDirectory
  * @package Grav\Framework\Flex
  * @template T
- * @template TKey
  */
 class FlexDirectory implements FlexDirectoryInterface, FlexAuthorizeInterface
 {
@@ -309,7 +308,7 @@ class FlexDirectory implements FlexDirectoryInterface, FlexAuthorizeInterface
      * @param array|null $keys  Array of keys.
      * @param string|null $keyField  Field to be used as the key.
      * @return FlexCollectionInterface
-     * @phpstan-return FlexCollectionInterface<TKey,T>
+     * @phpstan-return FlexCollectionInterface<T>
      */
     public function getCollection(array $keys = null, string $keyField = null): FlexCollectionInterface
     {

+ 5 - 7
system/src/Grav/Framework/Flex/FlexIndex.php

@@ -33,11 +33,10 @@ use function in_array;
 /**
  * Class FlexIndex
  * @package Grav\Framework\Flex
- * @template TKey
  * @template T of FlexObjectInterface
  * @template C of FlexCollectionInterface
- * @extends ObjectIndex<TKey,T>
- * @implements FlexIndexInterface<TKey,T>
+ * @extends ObjectIndex<string,T>
+ * @implements FlexIndexInterface<T>
  * @mixin C
  */
 class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexIndexInterface
@@ -54,7 +53,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde
     /**
      * @param FlexDirectory $directory
      * @return static
-     * @phpstan-return static<TKey,T,C>
+     * @phpstan-return static<T,C>
      */
     public static function createFromStorage(FlexDirectory $directory)
     {
@@ -343,7 +342,6 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde
     /**
      * @param string $key
      * @return array
-     * @phpstan-param TKey $key
      */
     public function getMetaData($key): array
     {
@@ -370,7 +368,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde
     /**
      * @param array $orderings
      * @return static
-     * @phpstan-return static<TKey,T,C>
+     * @phpstan-return static<T,C>
      */
     public function orderBy(array $orderings)
     {
@@ -538,7 +536,7 @@ class FlexIndex extends ObjectIndex implements FlexCollectionInterface, FlexInde
      * @param array $entries
      * @param string|null $keyField
      * @return static
-     * @phpstan-return static<TKey,T,C>
+     * @phpstan-return static<T,C>
      */
     protected function createFrom(array $entries, string $keyField = null)
     {

+ 7 - 9
system/src/Grav/Framework/Flex/Interfaces/FlexCollectionInterface.php

@@ -22,9 +22,8 @@ use InvalidArgumentException;
  *
  * @used-by \Grav\Framework\Flex\FlexCollection
  * @since 1.6
- * @template TKey
  * @template T
- * @extends ObjectCollectionInterface<TKey,T>
+ * @extends ObjectCollectionInterface<string,T>
  */
 interface FlexCollectionInterface extends FlexCommonInterface, ObjectCollectionInterface, NestedObjectInterface
 {
@@ -58,7 +57,7 @@ interface FlexCollectionInterface extends FlexCommonInterface, ObjectCollectionI
      * @param string|string[]|null  $properties Properties to search for, defaults to configured properties.
      * @param array|null            $options    Search options, defaults to configured options.
      * @return FlexCollectionInterface          Returns a Flex Collection with only matching objects.
-     * @phpstan-return static<TKey,T>
+     * @phpstan-return static<T>
      * @api
      */
     public function search(string $search, $properties = null, array $options = null);
@@ -69,7 +68,7 @@ interface FlexCollectionInterface extends FlexCommonInterface, ObjectCollectionI
      * @param array $orderings Pair of [property => 'ASC'|'DESC', ...].
      *
      * @return FlexCollectionInterface Returns a sorted version from the collection.
-     * @phpstan-return static<TKey,T>
+     * @phpstan-return static<T>
      */
     public function sort(array $orderings);
 
@@ -78,7 +77,7 @@ interface FlexCollectionInterface extends FlexCommonInterface, ObjectCollectionI
      *
      * @param array $filters
      * @return FlexCollectionInterface
-     * @phpstan-return static<TKey,T>
+     * @phpstan-return static<T>
      */
     public function filterBy(array $filters);
 
@@ -114,7 +113,7 @@ interface FlexCollectionInterface extends FlexCommonInterface, ObjectCollectionI
      *
      * @param string|null $keyField Switch key field of the collection.
      * @return FlexCollectionInterface  Returns a new Flex Collection with new key field.
-     * @phpstan-return static<TKey,T>
+     * @phpstan-return static<T>
      * @api
      */
     public function withKeyField(string $keyField = null);
@@ -123,7 +122,7 @@ interface FlexCollectionInterface extends FlexCommonInterface, ObjectCollectionI
      * Get Flex Index from the Flex Collection.
      *
      * @return FlexIndexInterface   Returns a Flex Index from the current collection.
-     * @phpstan-return FlexIndexInterface<TKey,T>
+     * @phpstan-return FlexIndexInterface<T>
      */
     public function getIndex();
 
@@ -131,7 +130,7 @@ interface FlexCollectionInterface extends FlexCommonInterface, ObjectCollectionI
      * Load all the objects into memory,
      *
      * @return FlexCollectionInterface
-     * @phpstan-return static<TKey,T>
+     * @phpstan-return static<T>
      */
     public function getCollection();
 
@@ -140,7 +139,6 @@ interface FlexCollectionInterface extends FlexCommonInterface, ObjectCollectionI
      *
      * @param string $key Key.
      * @return array
-     * @phpstan-param TKey $key
      */
     public function getMetaData(string $key): array;
 }

+ 1 - 2
system/src/Grav/Framework/Flex/Interfaces/FlexIndexInterface.php

@@ -21,9 +21,8 @@ use Grav\Framework\Flex\FlexDirectory;
  *
  * @used-by \Grav\Framework\Flex\FlexIndex
  * @since 1.6
- * @template TKey
  * @template T
- * @extends FlexCollectionInterface<TKey,T>
+ * @extends FlexCollectionInterface<T>
  */
 interface FlexIndexInterface extends FlexCollectionInterface
 {

+ 4 - 5
system/src/Grav/Framework/Flex/Pages/FlexPageCollection.php

@@ -20,9 +20,8 @@ use function is_int;
 /**
  * Class FlexPageCollection
  * @package Grav\Plugin\FlexObjects\Types\FlexPages
- * @template TKey
  * @template T of \Grav\Framework\Flex\Interfaces\FlexObjectInterface
- * @extends FlexCollection<TKey,T>
+ * @extends FlexCollection<T>
  */
 class FlexPageCollection extends FlexCollection
 {
@@ -53,7 +52,7 @@ class FlexPageCollection extends FlexCollection
     /**
      * @param bool $bool
      * @return static
-     * @phpstan-return static<TKey,T>
+     * @phpstan-return static<T>
      */
     public function withPublished(bool $bool = true)
     {
@@ -65,7 +64,7 @@ class FlexPageCollection extends FlexCollection
     /**
      * @param bool $bool
      * @return static
-     * @phpstan-return static<TKey,T>
+     * @phpstan-return static<T>
      */
     public function withVisible(bool $bool = true)
     {
@@ -77,7 +76,7 @@ class FlexPageCollection extends FlexCollection
     /**
      * @param bool $bool
      * @return static
-     * @phpstan-return static<TKey,T>
+     * @phpstan-return static<T>
      */
     public function withRoutable(bool $bool = true)
     {

+ 1 - 2
system/src/Grav/Framework/Flex/Pages/FlexPageIndex.php

@@ -22,10 +22,9 @@ use Grav\Framework\Flex\FlexIndex;
  * @method FlexPageIndex withPublished(bool $bool = true)
  * @method FlexPageIndex withVisible(bool $bool = true)
  *
- * @template TKey
  * @template T of FlexPageObject
  * @template C of FlexPageCollection
- * @extends FlexIndex<TKey,T,C>
+ * @extends FlexIndex<T,C>
  */
 class FlexPageIndex extends FlexIndex
 {

+ 3 - 3
system/src/Grav/Framework/Flex/Traits/FlexMediaTrait.php

@@ -205,10 +205,10 @@ trait FlexMediaTrait
                 $filename = $info['path'] ?? $info['name'];
             }
 
-            /** @var Medium|null $thumbFile */
+            /** @var Medium|null $imageFile */
             $imageFile = $media[$filename];
 
-            /** @var Medium|null $thumbFile */
+            /** @var Medium|null $originalFile */
             $originalFile = $originalMedia ? $originalMedia[$filename] : null;
 
             $url = $imageFile ? $imageFile->url() : null;
@@ -384,7 +384,7 @@ trait FlexMediaTrait
                 $updated = true;
                 if ($medium) {
                     $media->add($filename, $medium);
-                } else {
+                } elseif (is_callable([$media, 'hide'])) {
                     $media->hide($filename);
                 }
             }

+ 2 - 2
system/src/Grav/Installer/Install.php

@@ -232,7 +232,7 @@ ERR;
 
         $this->location = dirname($location, 4);
 
-        $versions = Versions::instance(GRAV_ROOT . '/user/config/versions.yaml');
+        $versions = Versions::instance(USER_DIR . 'config/versions.yaml');
         $this->updater = new VersionUpdater('core/grav', __DIR__ . '/updates', $this->getVersion(), $versions);
 
         $this->updater->preflight();
@@ -280,7 +280,7 @@ ERR;
     {
         // Finalize can be run without installing Grav first.
         if (!$this->updater) {
-            $versions = Versions::instance(GRAV_ROOT . '/user/config/versions.yaml');
+            $versions = Versions::instance(USER_DIR . 'config/versions.yaml');
             $this->updater = new VersionUpdater('core/grav', __DIR__ . '/updates', GRAV_VERSION, $versions);
             $this->updater->install();
         }

+ 1 - 1
system/src/Grav/Installer/Versions.php

@@ -36,7 +36,7 @@ final class Versions
      */
     public static function instance(string $filename = null): self
     {
-        $filename = $filename ?? GRAV_ROOT . '/user/config/versions.yaml';
+        $filename = $filename ?? USER_DIR . 'config/versions.yaml';
 
         if (!isset(self::$instance[$filename])) {
             self::$instance[$filename] = new self($filename);

+ 7 - 0
user/pages/01.home/01._accueil/accueil.md

@@ -0,0 +1,7 @@
+---
+title: Accueil
+body_classes: modular
+visible: true
+debugger: true
+---
+

+ 0 - 13
user/pages/01.home/01._accueil/text.md

@@ -1,13 +0,0 @@
----
-title: Accueil
-body_classes: modular
-visible: true
-debugger: true
----
-
-# EPAU
-
-
-## L'EUROPE DES PROJETS ARCHITECTURAUX ET URBAINS
-
-Organisme national de recherche et d’expérimentation, sous la tutelle des Ministères en charge de l’architecture et de l’urbanisme, la Cité de l’Architecture et du Patrimoine et de l’Association Europan France

+ 1 - 1
user/pages/01.home/03._ressources/ressources.md

@@ -36,4 +36,4 @@ process:
     twig: false
 ---
 
-# Ressources
+

+ 0 - 2
user/pages/01.home/04._gouvernance/gouvernance.md

@@ -18,6 +18,4 @@ admin:
 debugger: true
 ---
 
-# Gouvernance
 
-## Le conseil d’administration de l’Europe des projets architecturaux et urbains et les Directions de programmes de l’Europe des projets architecturaux urbains

+ 4 - 6
user/pages/01.home/05._contact/text.md

@@ -3,9 +3,7 @@ title: Contact
 body_classes: modular
 ---
 
-# Contact
-### Fabienne Dran
-#### Assistante de direction
-Fabienne.Dran@developpement-durable.gouv.fr   
-+ 33 (0)1 40 81 93 27
-+33 (0)7 86 50 33 31
+CONTACT :
+Fabienne.Dran@developpement-durable.gouv.fr
++ 33 (0)1 40 81 9327
++33 (0)7 86 5033 31

+ 1 - 2
user/themes/epau-antimatter/css-compiled/nucleus.css

@@ -91,8 +91,7 @@ sub {
   bottom: -0.25em; }
 
 img {
-  border: 0;
-  max-width: 15rem; }
+  border: 0; }
 
 svg:not(:root) {
   overflow: hidden; }

+ 38 - 15
user/themes/epau-antimatter/css-compiled/template.css

@@ -82,8 +82,7 @@ b, strong, label, th {
   #header #logo img {
     display: flex;
     flex-direction: row;
-    flex-flow: row;
-    max-height: 5rem; }
+    flex-flow: row; }
   #header.scrolled {
     height: 3rem;
     background-color: rgba(255, 255, 255, 0.9) !important;
@@ -825,9 +824,10 @@ ul.pagination {
 #logo {
   display: flex;
   flex-direction: row; }
-
-#logo img {
-  padding: 0.5rem; }
+  #logo img {
+    padding: 0.5rem;
+    max-height: 3rem;
+    margin: auto; }
 
 .callout {
   padding-top: 0.5rem; }
@@ -867,26 +867,47 @@ ul.pagination {
     width: 100%; } }
 
 .after-h1 .test {
-  opacity: 0;
-  transition: opacity 1s ease-in-out;
-  animation: anim 5s 500ms 1 normal ease-in-out forwards; }
-
-.after-h1:hover .test {
-  opacity: 1; }
+  animation: anim 2.5s 1 normal ease-in-out forwards; }
 
 .programmes {
   display: flex;
   flex-wrap: wrap;
-  background: url("/user/themes/epau-antimatter/images/14360_default_big.jpg") 0px 0px no-repeat, url("/user/themes/epau-antimatter/images/10361_web_01.jpg") 1200px 300px no-repeat, url("/user/themes/epau-antimatter/images/hyperliens_marseille_.PNG") 0px 700px no-repeat, url("/user/themes/epau-antimatter/images/jeux-olypiques-paris-2024-village-athle-lot-e2.jpg") right no-repeat;
-  /* On bottom, like z-index: 1; */
   background-color: #d5d2d1;
+  z-index: -1;
   justify-content: center;
   padding-left: 15%;
   padding-right: 15%;
   padding-top: 8rem;
   padding-bottom: 8rem; }
 
+.paralax {
+  position: absolute !important;
+  width: 100%;
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  justify-content: space-between; }
+  .paralax #photo1 {
+    position: relative;
+    top: -60px; }
+  .paralax #photo2 {
+    z-index: 0;
+    width: 700px !important;
+    position: relative;
+    top: 260px; }
+  .paralax #photo3 {
+    z-index: 0;
+    width: 700px !important;
+    position: relative;
+    top: 500px; }
+  .paralax #photo4 {
+    z-index: 0;
+    width: 700px !important;
+    position: relative;
+    top: 300px; }
+
 .programme {
+  z-index: 1;
   max-width: 35%;
   padding: 1.5rem;
   background-color: white;
@@ -895,7 +916,7 @@ ul.pagination {
     text-transform: uppercase;
     line-height: 1.2; }
   .programme img {
-    max-height: 15%; }
+    max-height: 4rem; }
   .programme p {
     font-family: "Sarabun", sans-serif;
     font-weight: 500;
@@ -949,7 +970,9 @@ ul.pagination {
           width: 15rem !important;
           height: 15rem !important; }
           .mozaique_personnes .equipe .personne .mozaique .photo img {
-            width: 100%; }
+            object-fit: cover;
+            width: 100%;
+            height: 100%; }
         .mozaique_personnes .equipe .personne .mozaique .info {
           background-color: #fff;
           display: flex;

+ 1 - 1
user/themes/epau-antimatter/scss/nucleus/_core.scss

@@ -98,7 +98,7 @@ sub {
 
 img {
 	border: 0;
-	max-width: 15rem;
+	// max-width: 15rem;
 }
 
 svg:not(:root) {

+ 80 - 102
user/themes/epau-antimatter/scss/template/_custom.scss

@@ -52,48 +52,15 @@
 #logo {
     display: flex;
     flex-direction: row;
-}
 
-#logo img {
-  padding: 0.5rem;
+    img {
+      padding: 0.5rem;
+      max-height: 3rem;
+      margin:auto;
+
+    }
 }
 
-//tentative animation when in View
-// @media () {
-//
-//   @viewport {
-//
-//   }
-//   rect.after-h1 {
-//     animation-duration: 4s;
-//     animation-timing-function: linear;
-//     animation-timeline: grow-timeline;
-//   }
-//
-//   @scroll-timeline grow-timeline {
-//     source: selector(.test);
-//     orientation: block;
-//     scroll-offsets: 250px, 300px;
-//   }
-//
-//   @keyframes grow {
-//     to { transform: translate(300px) }
-//   }
-//   @k
-
-// @keyframes souligne {
-//   0% { width: 0.5%;
-//   }
-//   100%{
-//     width: 50%;
-//   }
-// }
-//
-// // selecteur:hover,
-// // selecteur:focus,
-// selecteur:hover{
-//   animation: souligne 2s ease-in-out;
-// }
 
 
 
@@ -135,6 +102,7 @@
 }
 
 .titre_bsn {
+
   display: block;
   margin-left: 40%;
   // padding-right: 15%;
@@ -152,84 +120,51 @@
 
 @keyframes anim {
   0% {width: 0%;}
-  100% {width: 100%}
+
+  100% {width: 100%;}
+
 }
 
-.after-h1 {     // fonctionne mais manque "when in View"
+.after-h1 {
+
   .test {
-    opacity: 0;
-    transition: opacity 1s ease-in-out;
-    animation: anim 5s 500ms 1 normal ease-in-out forwards;
+    // opacity: 0;
+    // transition: opacity 1s ease-in-out;
+    animation: anim 2.5s 1 normal ease-in-out forwards;
   }
-
-  &:hover {
-    .test {
-        opacity: 1;
-    }
+}
+  // &:hover {
+  //   .test {
+  //       opacity: 1;
+  //   }
     // opacity: 1;
     // transition: width 5s ease-in-out;
-  }
-}
 
 
 
-// fond images en grille pour parallax
-
-// #background {
-//     background-color: #d5d2d1;
-//     display: grid;
-//     grid-template-columns: repeat(5, 1fr);
-//     grid-template-rows: repeat(8, 5vw);
-//     grid-gap: 15px;
-// }
-//
-// #background img {
-//     max-width: 100% !important;
-//     max-height: 100% !important;
-//     // object-fit: cover;
-// }
-
-// .item-1 {
-//     grid-column-start: 1;
-//     grid-column-end: 3;
-//     grid-row-start: 1;
-//     grid-row-end: 5;
-// }
-//
-// .item-2 {
-//     grid-column-start: 3;
-//     grid-column-end: 5;
-//     grid-row-start: 1;
-//     grid-row-end: 5;
-// }
-//
-// .item-3 {
-//     grid-column-start: 5 ;
-//     grid-column-end: 1;
-//     grid-row-start: 9;
-//     grid-row-end: 6;
-// }
-//
-// .item-4 {
-//     grid-column-start: 1;
-//     grid-column-end: 3;
-//     grid-row-start: 1;
-//     grid-row-end: 3;
-// }
-
 .programmes {
 
   display: flex;
   flex-wrap: wrap;
 
-  background:
-   url("/user/themes/epau-antimatter/images/14360_default_big.jpg") 0px 0px no-repeat,  /* On top,    like z-index: 4; */
-   url("/user/themes/epau-antimatter/images/10361_web_01.jpg") 1200px 300px no-repeat,   /*            like z-index: 3; */
-   url("/user/themes/epau-antimatter/images/hyperliens_marseille_.PNG") 0px 700px no-repeat,   /*            like z-index: 2; */
-   url("/user/themes/epau-antimatter/images/jeux-olypiques-paris-2024-village-athle-lot-e2.jpg") right no-repeat;                      /* On bottom, like z-index: 1; */
+  // background-image:
+  // url("/user/themes/epau-antimatter/images/14360_default_big.jpg") ,
+  //   url("/user/themes/epau-antimatter/images/10361_web_01.jpg") ,
+  //   url("/user/themes/epau-antimatter/images/hyperliens_marseille_.PNG") ,
+  //   url("/user/themes/epau-antimatter/images/jeux-olypiques-paris-2024-village-athle-lot-e2.jpg") ;
+  //
+  // background-attachment: fixed;
+  //
+  // background-position: 50% -50px;
 
+  // position: sticky;
+  // transform: translateY(-1);
+
+  // min-height: 500px;
 
   background-color: #d5d2d1;
+
+  z-index: -1;
   justify-content: center;
   padding-left: 15%;
   padding-right: 15%;
@@ -238,20 +173,61 @@
   padding-bottom: 8rem;
 }
 
+.paralax  {
+  position: absolute !important;
+  width: 100%;
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  justify-content: space-between;
+
+  // transform: translate3d(0px, -128px, 0px);
+
+  #photo1 {
+    position: relative;
+    top: -60px;
+
+  }
+
+  #photo2 {
+    z-index: 0;
+    width:700px !important;
+    position: relative;
+    top: 260px;
+  }
+
+  #photo3 {
+    z-index: 0;
+    width:700px !important;
+    position: relative;
+    top: 500px;
+  }
+
+  #photo4 {
+    z-index: 0;
+    width:700px !important;
+    position: relative;
+    top: 300px;
+  }
+}
+
+
 .programme {
+  z-index: 1;
   max-width: 35%;
   // min-width:
   padding: 1.5rem;
   background-color: white;
   margin: 0.4rem;
 
+
     h4 {
       text-transform: uppercase;
       line-height: 1.2;
     }
 
     img {
-      max-height: 15%;
+      max-height: 4rem;
     }
 
     p {
@@ -403,12 +379,14 @@
           width: 15rem !important;
           height: 15rem !important;
           // object-fit: cover;
+          // background-size: cover;
 
           img {
               // maxwidth: 15rem !important;
               // height: 15rem !important;
-              // background-size: cover;
+              object-fit: cover;
               width: 100%;
+              height: 100%;
 
           }
 

+ 2 - 2
user/themes/epau-antimatter/scss/template/_header.scss

@@ -15,7 +15,7 @@ $dropdown-color: #f6f6f6;
 		display: flex;
 		flex-direction: row;
 		flex-flow: row;
-		max-height: $header-height;
+		// max-height: $header-height;
 	}
 
 	// scroll based changes
@@ -200,7 +200,7 @@ $dropdown-color: #f6f6f6;
 						&.active > a {
 							background-color: darken($dropdown-color, 4%);
 							color: $core-accent;
-	
+
 
 
 						}

+ 2 - 2
user/themes/epau-antimatter/templates/modular/gouvernance.html.twig

@@ -1,5 +1,5 @@
 
-<div class="gouvernance">
+<div class="gouvernance after-h1">
 
   <div class="titre_bsn">
 
@@ -7,7 +7,7 @@
 
     <div class="test" >
       <svg width="100%" height="0.5rem">
-       <rect class="after-h1" width="100%" height="100%" style="fill:rgb(255,255,255)" />
+       <rect class="" width="100%" height="100%" style="fill:rgb(255,255,255)" />
      </svg>
     </div>
     <p> Le conseil d’administration de l’Europe des projets architecturaux et urbains et les Directions de programmes de l’Europe des projets architecturaux urbains</p>

+ 9 - 1
user/themes/epau-antimatter/templates/modular/programmes.html.twig

@@ -1,12 +1,20 @@
 
 <div class="programmes{{ page.header.class}}">
 
+ <div class="background paralax">
+    <img id="photo1" src="/user/themes/epau-antimatter/images/14360_default_big.jpg" alt="photo 1" />
+    <img id="photo2" src="/user/themes/epau-antimatter/images/10361_web_01.jpg" alt="photo 2" />
+    <img id="photo3" src="/user/themes/epau-antimatter/images/hyperliens_marseille_.PNG" alt="photo 3" />
+    <img id="photo4" src="/user/themes/epau-antimatter/images/jeux-olypiques-paris-2024-village-athle-lot-e2.jpg" alt="photo 4" />
+
+ </div>
+
     {{ content|raw }}
 
     {% for programme in page.header.programmes %}
 
         <div class="programme">
-          <a href="{{programme.site}}">
+          <a href="{{programme.site}}" target="_blank">
             {% if programme.logo %}
             <img src="{{page.media[programme.logo].url|e }}" alt="logo du programme {{programme.nom_du_programme}}" />
             {% endif %}

+ 2 - 2
user/themes/epau-antimatter/templates/modular/ressources.html.twig

@@ -1,12 +1,12 @@
 
-<div class="titre_nsb">
+<div class="titre_nsb after-h1">
 
   <h1>Ressources</h1>
 
 
   <div class="test" >
     <svg width="100%" height="0.5rem">
-     <rect class="after-h1" width="100%" height="100%" style="fill:rgb(0,0,0)" />
+     <rect class="" width="100%" height="100%" style="fill:rgb(0,0,0)" />
    </svg>
   </div>
   <!-- <div class="after-h1-finish">