This commit is contained in:
2021-05-12 12:05:01 +02:00
parent ec6c71798f
commit ffb5dbdaae
104 changed files with 6733 additions and 3490 deletions
+52
View File
@@ -1,3 +1,55 @@
# v1.7.14
## 04/29/2021
1. [](#new)
* Added `MediaUploadTrait::checkFileMetadata()` method
1. [](#improved)
* Updating a theme should always keep the custom files [getgrav/grav-plugin-admin#2135](https://github.com/getgrav/grav-plugin-admin/issues/2135)
1. [](#bugfix)
* Fixed broken numeric language codes in Flex Pages [#3332](https://github.com/getgrav/grav/issues/3332)
* Fixed broken `exif_imagetype()` twig function
# v1.7.13
## 04/23/2021
1. [](#new)
* Added support for getting translated collection of Flex Pages using `$collection->withTranslated('de')`
1. [](#improved)
* Moved `gregwar/Image` and `gregwar/Cache` in-house to official `getgrav/Image` and `getgrav/Cache` packagist packages. This will help environments with very strict proxy setups that don't allow VCS setup. [#3289](https://github.com/getgrav/grav/issues/3289)
* Improved XSS Invalid Protocol detection regex [#3298](https://github.com/getgrav/grav/issues/3298)
* Added support for user provided folder in Flex `$page->copy()`
1. [](#bugfix)
* Fixed `The "Grav/Common/Twig/TwigExtension" extension is not enabled` when using markdown twig tag [#3317](https://github.com/getgrav/grav/issues/3317)
* Fixed text field maxlength validation newline issue [#3324](https://github.com/getgrav/grav/issues/3324)
* Fixed a bug in Flex Object `refresh()` method
# v1.7.12
## 04/15/2021
1. [](#improved)
* Improve JSON support for the request
1. [](#bugfix)
* Fixed absolute path support for Windows [#3297](https://github.com/getgrav/grav/issues/3297)
* Fixed adding tags in admin after upgrading Grav [#3315](https://github.com/getgrav/grav/issues/3315)
# v1.7.11
## 04/13/2021
1. [](#new)
* Added configuration options to allow PHP methods to be used in Twig functions (`system.twig.safe_functions`) and filters (`system.twig.safe_filters`)
* Deprecated using PHP methods in Twig without them being in the safe lists
* Prevent dangerous PHP methods from being used as Twig functions and filters
* Restrict filesystem Twig functions to accept only local filesystem and grav streams
1. [](#improved)
* Better GPM detection of unauthorized installations
1. [](#bugfix)
* **IMPORTANT** Fixed security vulnerability with Twig allowing dangerous PHP functions by default [GHSA-g8r4-p96j-xfxc](https://github.com/getgrav/grav/security/advisories/GHSA-g8r4-p96j-xfxc)
* Fixed nxinx appending repeating `?_url=` in some redirects
* Fixed deleting page with language code not removing the folder if it was the last language [#3305](https://github.com/getgrav/grav/issues/3305)
* Fixed fatal error when using markdown links with `image://` stream [#3285](https://github.com/getgrav/grav/issues/3285)
* Fixed `system.languages.session_store_active` not having any effect [#3269](https://github.com/getgrav/grav/issues/3269)
* Fixed fatal error if `system.pages.types` is not an array [#2984](https://github.com/getgrav/grav/issues/2984)
# v1.7.10 # v1.7.10
## 04/06/2021 ## 04/06/2021
+129 -45
View File
@@ -1,66 +1,150 @@
# ![](https://avatars1.githubusercontent.com/u/8237355?v=2&s=50) Grav
#Installation site GIP EPAU [![PHPStan](https://img.shields.io/badge/PHPStan-enabled-brightgreen.svg?style=flat)](https://github.com/phpstan/phpstan)
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/cfd20465-d0f8-4a0a-8444-467f5b5f16ad/mini.png)](https://insight.sensiolabs.com/projects/cfd20465-d0f8-4a0a-8444-467f5b5f16ad)
[![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)
### intall grav avec composer 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
- PHP 7.3.6 or higher. Check the [required modules list](https://learn.getgrav.org/basics/requirements#php-requirements)
- Check the [Apache](https://learn.getgrav.org/basics/requirements#apache-requirements) or [IIS](https://learn.getgrav.org/basics/requirements#iis-requirements) requirements
# Documentation
The full documentation can be found from [learn.getgrav.org](https://learn.getgrav.org).
# QuickStart
These are the options to get Grav:
### Downloading a Grav Package
You can download a **ready-built** package from the [Downloads page on https://getgrav.org](https://getgrav.org/downloads)
### With Composer
You can create a new project with the latest **stable** Grav release with the following command:
``` ```
composer create-project getgrav/grav ~/webroot/grav $ composer create-project getgrav/grav ~/webroot/grav
``` ```
### From GitHub
1. Clone the Grav repository from [https://github.com/getgrav/grav]() to a folder in the webroot of your server, e.g. `~/webroot/grav`. Launch a **terminal** or **console** and navigate to the webroot folder:
```
$ cd ~/webroot
$ git clone https://github.com/getgrav/grav.git
```
#### installer version admin 2. Install the **plugin** and **theme dependencies** by using the [Grav CLI application](https://learn.getgrav.org/advanced/grav-cli) `bin/grav`:
```
$ cd ~/webroot/grav
$ bin/grav install
```
mise à jours Check out the [install procedures](https://learn.getgrav.org/basics/installation) for more information.
```
cd ~/webroot/nomdusite
bin/gpm selfupgrade
```
installe ladmin
```
bin/gpm install admin
```
créer un nouvel utilisateur
```
bin/plugin login newuser
```
#### installe devtools et créer nouveau theme # Adding Functionality
You can download [plugins](https://getgrav.org/downloads/plugins) or [themes](https://getgrav.org/downloads/themes) manually from the appropriate tab on the [Downloads page on https://getgrav.org](https://getgrav.org/downloads), but the preferred solution is to use the [Grav Package Manager](https://learn.getgrav.org/advanced/grav-gpm) or `GPM`:
``` ```
bin/gpm install devtools $ bin/gpm index
bin/plugin devtools new-theme
``` ```
This will display all the available plugins and then you can install one or more with:
# Dans le navigateur
aller sur http://localhost:8000/
pour voir le site
aller sur http://localhost:8000/admin
pour accéder au back office
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
# Compilé les SCSS
``` ```
$ cd chemin/du/dossier/dev-epau.archi.fr $ bin/gpm install <plugin/theme>
``` ```
```
$ npm install
```
(uniquement la première fois)
puis à chaque fois, dans une 2e fenêtre de Terminal, qui doit également restée ouverte: # Updating
To update Grav you should use the [Grav Package Manager](https://learn.getgrav.org/advanced/grav-gpm) or `GPM`:
``` ```
$ cd chemin/du/dossier/dev-epau.archi.fr/user/theme/epau-antimatter $ bin/gpm selfupgrade
$ npm run sass
``` ```
To update plugins and themes:
```
$ bin/gpm update
```
## Upgrading from older version
* [Upgrading to Grav 1.7](https://learn.getgrav.org/16/advanced/grav-development/grav-17-upgrade-guide)
* [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.
Then `composer test` will run the Unit Tests, which should be always executed successfully on any site.
Windows users should use the `composer test-windows` command.
You can also run a single unit test file, e.g. `composer test tests/unit/Grav/Common/AssetsTest.php`
To run phpstan tests, you should run:
* `composer phpstan` for global tests
* `composer phpstan-framework` for more strict tests
* `composer phpstan-plugins` to test all installed plugins
+3 -17
View File
@@ -44,8 +44,8 @@
"filp/whoops": "~2.9", "filp/whoops": "~2.9",
"matthiasmullie/minify": "^1.3", "matthiasmullie/minify": "^1.3",
"monolog/monolog": "~1.25", "monolog/monolog": "~1.25",
"gregwar/image": "dev-php8", "getgrav/image": "^3.0",
"gregwar/cache": "dev-php8", "getgrav/cache": "^2.0",
"donatj/phpuseragentparser": "~1.1", "donatj/phpuseragentparser": "~1.1",
"pimple/pimple": "~3.3.0", "pimple/pimple": "~3.3.0",
"rockettheme/toolbox": "~1.5", "rockettheme/toolbox": "~1.5",
@@ -67,7 +67,7 @@
"phpstan/phpstan": "^0.12", "phpstan/phpstan": "^0.12",
"phpstan/phpstan-deprecation-rules": "^0.12", "phpstan/phpstan-deprecation-rules": "^0.12",
"phpunit/php-code-coverage": "~9.2", "phpunit/php-code-coverage": "~9.2",
"victorjonsson/markdowndocs": "dev-master", "getgrav/markdowndocs": "^2.0",
"codeception/module-asserts": "^1.3", "codeception/module-asserts": "^1.3",
"codeception/module-phpbrowser": "^1.0", "codeception/module-phpbrowser": "^1.0",
"symfony/service-contracts": "*" "symfony/service-contracts": "*"
@@ -91,20 +91,6 @@
"php": "7.3.6" "php": "7.3.6"
} }
}, },
"repositories": [
{
"type": "vcs",
"url": "https://github.com/trilbymedia/PHP-Markdown-Documentation-Generator"
},
{
"type": "vcs",
"url": "https://github.com/getgrav/Cache"
},
{
"type": "vcs",
"url": "https://github.com/getgrav/Image"
}
],
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Grav\\": "system/src/Grav" "Grav\\": "system/src/Grav"
Generated
+125 -113
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "4ae6fc7274c018b1bb34bb1b80bd62c5", "content-hash": "36375d8a5daf3aef0341f9a2b023f4e9",
"packages": [ "packages": [
{ {
"name": "antoligy/dom-string-iterators", "name": "antoligy/dom-string-iterators",
@@ -212,40 +212,39 @@
}, },
{ {
"name": "doctrine/cache", "name": "doctrine/cache",
"version": "1.10.2", "version": "1.11.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/cache.git", "url": "https://github.com/doctrine/cache.git",
"reference": "13e3381b25847283a91948d04640543941309727" "reference": "a9c1b59eba5a08ca2770a76eddb88922f504e8e0"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/cache/zipball/13e3381b25847283a91948d04640543941309727", "url": "https://api.github.com/repos/doctrine/cache/zipball/a9c1b59eba5a08ca2770a76eddb88922f504e8e0",
"reference": "13e3381b25847283a91948d04640543941309727", "reference": "a9c1b59eba5a08ca2770a76eddb88922f504e8e0",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "~7.1 || ^8.0" "php": "~7.1 || ^8.0"
}, },
"conflict": { "conflict": {
"doctrine/common": ">2.2,<2.4" "doctrine/common": ">2.2,<2.4",
"psr/cache": ">=3"
}, },
"require-dev": { "require-dev": {
"alcaeus/mongo-php-adapter": "^1.1", "alcaeus/mongo-php-adapter": "^1.1",
"doctrine/coding-standard": "^6.0", "cache/integration-tests": "dev-master",
"doctrine/coding-standard": "^8.0",
"mongodb/mongodb": "^1.1", "mongodb/mongodb": "^1.1",
"phpunit/phpunit": "^7.0", "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
"predis/predis": "~1.0" "predis/predis": "~1.0",
"psr/cache": "^1.0 || ^2.0",
"symfony/cache": "^4.4 || ^5.2"
}, },
"suggest": { "suggest": {
"alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver"
}, },
"type": "library", "type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9.x-dev"
}
},
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
@@ -292,7 +291,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/doctrine/cache/issues", "issues": "https://github.com/doctrine/cache/issues",
"source": "https://github.com/doctrine/cache/tree/1.10.x" "source": "https://github.com/doctrine/cache/tree/1.11.0"
}, },
"funding": [ "funding": [
{ {
@@ -308,7 +307,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2020-07-07T18:54:01+00:00" "time": "2021-04-13T14:46:17+00:00"
}, },
{ {
"name": "doctrine/collections", "name": "doctrine/collections",
@@ -642,16 +641,16 @@
}, },
{ {
"name": "filp/whoops", "name": "filp/whoops",
"version": "2.12.0", "version": "2.12.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/filp/whoops.git", "url": "https://github.com/filp/whoops.git",
"reference": "d501fd2658d55491a2295ff600ae5978eaad7403" "reference": "c13c0be93cff50f88bbd70827d993026821914dd"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/filp/whoops/zipball/d501fd2658d55491a2295ff600ae5978eaad7403", "url": "https://api.github.com/repos/filp/whoops/zipball/c13c0be93cff50f88bbd70827d993026821914dd",
"reference": "d501fd2658d55491a2295ff600ae5978eaad7403", "reference": "c13c0be93cff50f88bbd70827d993026821914dd",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -701,7 +700,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/filp/whoops/issues", "issues": "https://github.com/filp/whoops/issues",
"source": "https://github.com/filp/whoops/tree/2.12.0" "source": "https://github.com/filp/whoops/tree/2.12.1"
}, },
"funding": [ "funding": [
{ {
@@ -709,21 +708,21 @@
"type": "github" "type": "github"
} }
], ],
"time": "2021-03-30T12:00:00+00:00" "time": "2021-04-25T12:00:00+00:00"
}, },
{ {
"name": "gregwar/cache", "name": "getgrav/cache",
"version": "dev-php8", "version": "v2.0.0",
"target-dir": "Gregwar/Cache", "target-dir": "Gregwar/Cache",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/getgrav/Cache.git", "url": "https://github.com/getgrav/Cache.git",
"reference": "49ccdf9ae760b009a192bc3c7b417980c8a8cc2e" "reference": "56fd63f752779928fcd1074ab7d12f406dde8861"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/getgrav/Cache/zipball/49ccdf9ae760b009a192bc3c7b417980c8a8cc2e", "url": "https://api.github.com/repos/getgrav/Cache/zipball/56fd63f752779928fcd1074ab7d12f406dde8861",
"reference": "49ccdf9ae760b009a192bc3c7b417980c8a8cc2e", "reference": "56fd63f752779928fcd1074ab7d12f406dde8861",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -735,6 +734,7 @@
"Gregwar\\Cache": "" "Gregwar\\Cache": ""
} }
}, },
"notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"MIT" "MIT"
], ],
@@ -742,6 +742,11 @@
{ {
"name": "Gregwar", "name": "Gregwar",
"email": "g.passault@gmail.com" "email": "g.passault@gmail.com"
},
{
"name": "Grav CMS",
"email": "hello@getgrav.org",
"homepage": "https://getgrav.org"
} }
], ],
"description": "A lightweight file-system cache system", "description": "A lightweight file-system cache system",
@@ -752,28 +757,28 @@
"system" "system"
], ],
"support": { "support": {
"source": "https://github.com/getgrav/Cache/tree/php8" "source": "https://github.com/getgrav/Cache/tree/v2.0.0"
}, },
"time": "2020-12-02T10:54:35+00:00" "time": "2021-04-20T05:48:00+00:00"
}, },
{ {
"name": "gregwar/image", "name": "getgrav/image",
"version": "dev-php8", "version": "v3.0.0",
"target-dir": "Gregwar/Image", "target-dir": "Gregwar/Image",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/getgrav/Image.git", "url": "https://github.com/getgrav/Image.git",
"reference": "ea23859700f32447a85e79d96f331e3d6c8897a8" "reference": "02c1bb2c179dd894c4f6610c9c49da364ee7d264"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/getgrav/Image/zipball/ea23859700f32447a85e79d96f331e3d6c8897a8", "url": "https://api.github.com/repos/getgrav/Image/zipball/02c1bb2c179dd894c4f6610c9c49da364ee7d264",
"reference": "ea23859700f32447a85e79d96f331e3d6c8897a8", "reference": "02c1bb2c179dd894c4f6610c9c49da364ee7d264",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-gd": "*", "ext-gd": "*",
"gregwar/cache": "dev-php8", "getgrav/cache": "^2.0",
"php": "^5.6 || ^7.0 || ^8.0" "php": "^5.6 || ^7.0 || ^8.0"
}, },
"require-dev": { "require-dev": {
@@ -789,6 +794,7 @@
"Gregwar\\Image": "" "Gregwar\\Image": ""
} }
}, },
"notification-url": "https://packagist.org/downloads/",
"license": [ "license": [
"MIT" "MIT"
], ],
@@ -797,6 +803,11 @@
"name": "Grégoire Passault", "name": "Grégoire Passault",
"email": "g.passault@gmail.com", "email": "g.passault@gmail.com",
"homepage": "http://www.gregwar.com/" "homepage": "http://www.gregwar.com/"
},
{
"name": "Grav CMS",
"email": "hello@getgrav.org",
"homepage": "https://getgrav.org"
} }
], ],
"description": "Image handling", "description": "Image handling",
@@ -806,9 +817,9 @@
"image" "image"
], ],
"support": { "support": {
"source": "https://github.com/getgrav/Image/tree/php8" "source": "https://github.com/getgrav/Image/tree/v3.0.0"
}, },
"time": "2021-03-15T17:03:52+00:00" "time": "2021-04-20T05:50:18+00:00"
}, },
{ {
"name": "guzzlehttp/psr7", "name": "guzzlehttp/psr7",
@@ -2135,16 +2146,16 @@
}, },
{ {
"name": "rockettheme/toolbox", "name": "rockettheme/toolbox",
"version": "1.5.7", "version": "1.5.9",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/rockettheme/toolbox.git", "url": "https://github.com/rockettheme/toolbox.git",
"reference": "8d3ebc4d982595d6eac90e851f2b4d5c0cec0399" "reference": "2d6693235aaca2efaadb61c84dac927aaf4eabfa"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/rockettheme/toolbox/zipball/8d3ebc4d982595d6eac90e851f2b4d5c0cec0399", "url": "https://api.github.com/repos/rockettheme/toolbox/zipball/2d6693235aaca2efaadb61c84dac927aaf4eabfa",
"reference": "8d3ebc4d982595d6eac90e851f2b4d5c0cec0399", "reference": "2d6693235aaca2efaadb61c84dac927aaf4eabfa",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2185,9 +2196,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/rockettheme/toolbox/issues", "issues": "https://github.com/rockettheme/toolbox/issues",
"source": "https://github.com/rockettheme/toolbox/tree/1.5.7" "source": "https://github.com/rockettheme/toolbox/tree/1.5.9"
}, },
"time": "2021-02-17T17:58:36+00:00" "time": "2021-04-14T19:52:40+00:00"
}, },
{ {
"name": "seld/cli-prompt", "name": "seld/cli-prompt",
@@ -3415,16 +3426,16 @@
}, },
{ {
"name": "codeception/codeception", "name": "codeception/codeception",
"version": "4.1.19", "version": "4.1.20",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Codeception/Codeception.git", "url": "https://github.com/Codeception/Codeception.git",
"reference": "138dc9345a81ec994dcd6b9680c501a752a37b00" "reference": "d8b16e13e1781dbc3a7ae8292117d520c89a9c5a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/138dc9345a81ec994dcd6b9680c501a752a37b00", "url": "https://api.github.com/repos/Codeception/Codeception/zipball/d8b16e13e1781dbc3a7ae8292117d520c89a9c5a",
"reference": "138dc9345a81ec994dcd6b9680c501a752a37b00", "reference": "d8b16e13e1781dbc3a7ae8292117d520c89a9c5a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3498,7 +3509,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/Codeception/Codeception/issues", "issues": "https://github.com/Codeception/Codeception/issues",
"source": "https://github.com/Codeception/Codeception/tree/4.1.19" "source": "https://github.com/Codeception/Codeception/tree/4.1.20"
}, },
"funding": [ "funding": [
{ {
@@ -3506,7 +3517,7 @@
"type": "open_collective" "type": "open_collective"
} }
], ],
"time": "2021-03-28T13:26:08+00:00" "time": "2021-04-02T16:41:51+00:00"
}, },
{ {
"name": "codeception/lib-asserts", "name": "codeception/lib-asserts",
@@ -3564,16 +3575,16 @@
}, },
{ {
"name": "codeception/lib-innerbrowser", "name": "codeception/lib-innerbrowser",
"version": "1.4.1", "version": "1.5.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Codeception/lib-innerbrowser.git", "url": "https://github.com/Codeception/lib-innerbrowser.git",
"reference": "693e116f81ef98eae98c43ef785a726faf87394e" "reference": "4b0d89b37fe454e060a610a85280a87ab4f534f1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Codeception/lib-innerbrowser/zipball/693e116f81ef98eae98c43ef785a726faf87394e", "url": "https://api.github.com/repos/Codeception/lib-innerbrowser/zipball/4b0d89b37fe454e060a610a85280a87ab4f534f1",
"reference": "693e116f81ef98eae98c43ef785a726faf87394e", "reference": "4b0d89b37fe454e060a610a85280a87ab4f534f1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3618,9 +3629,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/Codeception/lib-innerbrowser/issues", "issues": "https://github.com/Codeception/lib-innerbrowser/issues",
"source": "https://github.com/Codeception/lib-innerbrowser/tree/1.4.1" "source": "https://github.com/Codeception/lib-innerbrowser/tree/1.5.0"
}, },
"time": "2021-03-02T08:01:54+00:00" "time": "2021-04-23T06:18:29+00:00"
}, },
{ {
"name": "codeception/module-asserts", "name": "codeception/module-asserts",
@@ -3891,6 +3902,58 @@
], ],
"time": "2020-11-10T18:47:58+00:00" "time": "2020-11-10T18:47:58+00:00"
}, },
{
"name": "getgrav/markdowndocs",
"version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/getgrav/PHP-Markdown-Documentation-Generator.git",
"reference": "4a24d1b64a88da17e8f1696dc64969f5ca769064"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/getgrav/PHP-Markdown-Documentation-Generator/zipball/4a24d1b64a88da17e8f1696dc64969f5ca769064",
"reference": "4a24d1b64a88da17e8f1696dc64969f5ca769064",
"shasum": ""
},
"require": {
"php": ">=5.5.0",
"symfony/console": ">=2.6"
},
"require-dev": {
"phpunit/phpunit": "3.7.23"
},
"bin": [
"bin/phpdoc-md"
],
"type": "library",
"autoload": {
"psr-0": {
"PHPDocsMD": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Victor Jonsson",
"email": "kontakt@victorjonsson.se"
},
{
"name": "Grav CMS",
"email": "hello@getgrav.org",
"homepage": "https://getgrav.org"
}
],
"description": "Command line tool for generating markdown-formatted class documentation",
"homepage": "https://github.com/victorjonsson/PHP-Markdown-Documentation-Generator",
"support": {
"source": "https://github.com/getgrav/PHP-Markdown-Documentation-Generator/tree/2.0.1"
},
"time": "2021-04-20T06:04:42+00:00"
},
{ {
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
"version": "7.3.0", "version": "7.3.0",
@@ -4501,16 +4564,16 @@
}, },
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
"version": "0.12.82", "version": "0.12.84",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan.git", "url": "https://github.com/phpstan/phpstan.git",
"reference": "3920f0fb0aff39263d3a4cb0bca120a67a1a6a11" "reference": "9c43f15da8798c8f30a4b099e6a94530a558cfd5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/3920f0fb0aff39263d3a4cb0bca120a67a1a6a11", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9c43f15da8798c8f30a4b099e6a94530a558cfd5",
"reference": "3920f0fb0aff39263d3a4cb0bca120a67a1a6a11", "reference": "9c43f15da8798c8f30a4b099e6a94530a558cfd5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4541,7 +4604,7 @@
"description": "PHPStan - PHP Static Analysis Tool", "description": "PHPStan - PHP Static Analysis Tool",
"support": { "support": {
"issues": "https://github.com/phpstan/phpstan/issues", "issues": "https://github.com/phpstan/phpstan/issues",
"source": "https://github.com/phpstan/phpstan/tree/0.12.82" "source": "https://github.com/phpstan/phpstan/tree/0.12.84"
}, },
"funding": [ "funding": [
{ {
@@ -4557,7 +4620,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-03-19T06:08:17+00:00" "time": "2021-04-19T17:10:54+00:00"
}, },
{ {
"name": "phpstan/phpstan-deprecation-rules", "name": "phpstan/phpstan-deprecation-rules",
@@ -6368,53 +6431,6 @@
], ],
"time": "2020-07-12T23:59:07+00:00" "time": "2020-07-12T23:59:07+00:00"
}, },
{
"name": "victorjonsson/markdowndocs",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/trilbymedia/PHP-Markdown-Documentation-Generator.git",
"reference": "c9fa153b28a79f5da89ec32aa501be92db212aed"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/trilbymedia/PHP-Markdown-Documentation-Generator/zipball/c9fa153b28a79f5da89ec32aa501be92db212aed",
"reference": "c9fa153b28a79f5da89ec32aa501be92db212aed",
"shasum": ""
},
"require": {
"php": ">=5.5.0",
"symfony/console": ">=2.6"
},
"require-dev": {
"phpunit/phpunit": "3.7.23"
},
"default-branch": true,
"bin": [
"bin/phpdoc-md"
],
"type": "library",
"autoload": {
"psr-0": {
"PHPDocsMD": "src/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Victor Jonsson",
"email": "kontakt@victorjonsson.se"
}
],
"description": "Command line tool for generating markdown-formatted class documentation",
"homepage": "https://github.com/victorjonsson/PHP-Markdown-Documentation-Generator",
"support": {
"source": "https://github.com/trilbymedia/PHP-Markdown-Documentation-Generator/tree/master"
},
"time": "2017-09-20T13:29:22+00:00"
},
{ {
"name": "webmozart/assert", "name": "webmozart/assert",
"version": "1.10.0", "version": "1.10.0",
@@ -6476,11 +6492,7 @@
], ],
"aliases": [], "aliases": [],
"minimum-stability": "stable", "minimum-stability": "stable",
"stability-flags": { "stability-flags": [],
"gregwar/image": 20,
"gregwar/cache": 20,
"victorjonsson/markdowndocs": 20
},
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
+1
View File
@@ -18,6 +18,7 @@ config:
configure: configure:
path: '/accounts/configure' path: '/accounts/configure'
redirects: redirects:
'/groups': '/accounts/groups'
'/accounts': '/accounts/groups' '/accounts': '/accounts/groups'
# Permissions # Permissions
+1 -1
View File
@@ -121,7 +121,7 @@ form:
underline: true underline: true
folder: folder:
type: text type: folder-slug
label: PLUGIN_ADMIN.FOLDER_NAME label: PLUGIN_ADMIN.FOLDER_NAME
validate: validate:
rule: slug rule: slug
+2
View File
@@ -113,6 +113,8 @@ twig:
autoescape: true # Autoescape Twig vars (DEPRECATED, always enabled in strict mode) autoescape: true # Autoescape Twig vars (DEPRECATED, always enabled in strict mode)
undefined_functions: true # Allow undefined functions undefined_functions: true # Allow undefined functions
undefined_filters: true # Allow undefined filters undefined_filters: true # Allow undefined filters
safe_functions: [] # List of PHP functions which are allowed to be used as Twig functions
safe_filters: [] # List of PHP functions which are allowed to be used as Twig filters
umask_fix: false # By default Twig creates cached files as 755, fix switches this to 775 umask_fix: false # By default Twig creates cached files as 755, fix switches this to 775
assets: # Configuration for Assets Manager (JS, CSS) assets: # Configuration for Assets Manager (JS, CSS)
+28 -17
View File
@@ -1,4 +1,5 @@
<?php <?php
/** /**
* @package Grav\Core * @package Grav\Core
* *
@@ -8,7 +9,7 @@
// Some standard defines // Some standard defines
define('GRAV', true); define('GRAV', true);
define('GRAV_VERSION', '1.7.10'); define('GRAV_VERSION', '1.7.14');
define('GRAV_SCHEMA', '1.7.0_2020-11-20_1'); define('GRAV_SCHEMA', '1.7.0_2020-11-20_1');
define('GRAV_TESTING', false); define('GRAV_TESTING', false);
@@ -22,58 +23,68 @@ if (!defined('DS')) {
define('DS', '/'); define('DS', '/');
} }
// Directories and Paths // Absolute path to Grav root. This is where Grav is installed into.
if (!defined('GRAV_ROOT')) { if (!defined('GRAV_ROOT')) {
$path = rtrim(str_replace(DIRECTORY_SEPARATOR, DS, getenv('GRAV_ROOT') ?: getcwd()), DS); $path = rtrim(str_replace(DIRECTORY_SEPARATOR, DS, getenv('GRAV_ROOT') ?: getcwd()), DS);
define('GRAV_ROOT', $path); define('GRAV_ROOT', $path);
} }
// Absolute path to Grav webroot. This is the path where your site is located in.
if (!defined('GRAV_WEBROOT')) { if (!defined('GRAV_WEBROOT')) {
define('GRAV_WEBROOT', GRAV_ROOT); $path = rtrim(getenv('GRAV_WEBROOT') ?: GRAV_ROOT, DS);
define('GRAV_WEBROOT', $path);
} }
// Relative path to user folder. This path needs to be located under GRAV_WEBROOT.
if (!defined('GRAV_USER_PATH')) { if (!defined('GRAV_USER_PATH')) {
$path = rtrim(getenv('GRAV_USER_PATH') ?: 'user', DS); $path = rtrim(getenv('GRAV_USER_PATH') ?: 'user', DS);
define('GRAV_USER_PATH', $path); define('GRAV_USER_PATH', $path);
} }
// Absolute or relative path to system folder. Defaults to GRAV_ROOT/system
// If system folder is outside of webroot, see https://github.com/getgrav/grav/issues/3297#issuecomment-810294972
if (!defined('GRAV_SYSTEM_PATH')) { if (!defined('GRAV_SYSTEM_PATH')) {
$path = rtrim(getenv('GRAV_SYSTEM_PATH') ?: 'system', DS); $path = rtrim(getenv('GRAV_SYSTEM_PATH') ?: 'system', DS);
define('GRAV_SYSTEM_PATH', $path); define('GRAV_SYSTEM_PATH', $path);
} }
// Absolute or relative path to cache folder. Defaults to GRAV_ROOT/cache
if (!defined('GRAV_CACHE_PATH')) { if (!defined('GRAV_CACHE_PATH')) {
$path = rtrim(getenv('GRAV_CACHE_PATH') ?: 'cache', DS); $path = rtrim(getenv('GRAV_CACHE_PATH') ?: 'cache', DS);
define('GRAV_CACHE_PATH', $path); define('GRAV_CACHE_PATH', $path);
} }
// Absolute or relative path to logs folder. Defaults to GRAV_ROOT/logs
if (!defined('GRAV_LOG_PATH')) { if (!defined('GRAV_LOG_PATH')) {
$path = rtrim(getenv('GRAV_LOG_PATH') ?: 'logs', DS); $path = rtrim(getenv('GRAV_LOG_PATH') ?: 'logs', DS);
define('GRAV_LOG_PATH', $path); define('GRAV_LOG_PATH', $path);
} }
// Absolute or relative path to tmp folder. Defaults to GRAV_ROOT/tmp
if (!defined('GRAV_TMP_PATH')) { if (!defined('GRAV_TMP_PATH')) {
$path = rtrim(getenv('GRAV_TMP_PATH') ?: 'tmp', DS); $path = rtrim(getenv('GRAV_TMP_PATH') ?: 'tmp', DS);
define('GRAV_TMP_PATH', $path); define('GRAV_TMP_PATH', $path);
} }
// Absolute or relative path to backup folder. Defaults to GRAV_ROOT/backup
if (!defined('GRAV_BACKUP_PATH')) { if (!defined('GRAV_BACKUP_PATH')) {
$path = rtrim(getenv('GRAV_BACKUP_PATH') ?: 'backup', DS); $path = rtrim(getenv('GRAV_BACKUP_PATH') ?: 'backup', DS);
define('GRAV_BACKUP_PATH', $path); define('GRAV_BACKUP_PATH', $path);
} }
unset($path); unset($path);
define('USER_PATH', GRAV_USER_PATH . DS); // INTERNAL: Do not use!
define('CACHE_PATH', GRAV_CACHE_PATH . DS); define('USER_DIR', GRAV_WEBROOT . '/' . GRAV_USER_PATH . '/');
define('ROOT_DIR', GRAV_ROOT . DS); define('CACHE_DIR', (!preg_match('`^(/|[a-z]:[\\\/])`ui', GRAV_CACHE_PATH) ? GRAV_ROOT . '/' : '') . GRAV_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! // DEPRECATED: Do not use!
define('CACHE_PATH', GRAV_CACHE_PATH . DS);
define('USER_PATH', GRAV_USER_PATH . DS);
define('ROOT_DIR', GRAV_ROOT . DS);
define('ASSETS_DIR', GRAV_WEBROOT . '/assets/'); define('ASSETS_DIR', GRAV_WEBROOT . '/assets/');
define('IMAGES_DIR', GRAV_WEBROOT . '/images/'); define('IMAGES_DIR', GRAV_WEBROOT . '/images/');
define('ACCOUNTS_DIR', USER_DIR .'accounts/'); define('ACCOUNTS_DIR', USER_DIR . 'accounts/');
define('PAGES_DIR', USER_DIR .'pages/'); define('PAGES_DIR', USER_DIR . 'pages/');
define('DATA_DIR', USER_DIR .'data/'); define('DATA_DIR', USER_DIR . 'data/');
define('PLUGINS_DIR', USER_DIR .'plugins/'); define('PLUGINS_DIR', USER_DIR . 'plugins/');
define('THEMES_DIR', USER_DIR .'themes/'); define('THEMES_DIR', USER_DIR . 'themes/');
define('SYSTEM_DIR', (!str_starts_with(GRAV_SYSTEM_PATH, '/') ? ROOT_DIR : '') . GRAV_SYSTEM_PATH); define('SYSTEM_DIR', (!preg_match('`^(/|[a-z]:[\\\/])`ui', GRAV_SYSTEM_PATH) ? GRAV_ROOT . '/' : '') . GRAV_SYSTEM_PATH . '/');
define('LIB_DIR', SYSTEM_DIR .'src/'); define('LIB_DIR', SYSTEM_DIR . 'src/');
define('VENDOR_DIR', ROOT_DIR .'vendor/'); define('VENDOR_DIR', GRAV_ROOT . '/vendor/');
define('LOG_DIR', (!str_starts_with(GRAV_LOG_PATH, '/') ? ROOT_DIR : '') . GRAV_LOG_PATH . DS); define('LOG_DIR', (!preg_match('`^(/|[a-z]:[\\\/])`ui', GRAV_LOG_PATH) ? GRAV_ROOT . '/' : '') . GRAV_LOG_PATH . '/');
// END DEPRECATED // END DEPRECATED
// Some extensions // Some extensions
@@ -90,7 +90,7 @@ trait AssetUtilsTrait
} }
$relative_dir = dirname($relative_path); $relative_dir = dirname($relative_path);
$link = ROOT_DIR . $relative_path; $link = GRAV_ROOT . '/' . $relative_path;
} }
// TODO: looks like this is not being used. // TODO: looks like this is not being used.
@@ -252,7 +252,7 @@ trait TestingAssetsTrait
*/ */
public function addDir($directory, $pattern = self::DEFAULT_REGEX) public function addDir($directory, $pattern = self::DEFAULT_REGEX)
{ {
$root_dir = rtrim(ROOT_DIR, '/'); $root_dir = GRAV_ROOT;
// Check if $directory is a stream. // Check if $directory is a stream.
if (strpos($directory, '://')) { if (strpos($directory, '://')) {
+2 -1
View File
@@ -238,6 +238,7 @@ class Validation
$value = trim($value); $value = trim($value);
} }
$value = preg_replace("/\r\n|\r/um", "\n", $value);
$len = mb_strlen($value); $len = mb_strlen($value);
$min = (int)($params['min'] ?? 0); $min = (int)($params['min'] ?? 0);
@@ -280,7 +281,7 @@ class Validation
$value = trim($value); $value = trim($value);
} }
return $value; return preg_replace("/\r\n|\r/um", "\n", $value);
} }
/** /**
@@ -746,6 +746,16 @@ class PageCollection extends FlexPageCollection implements PageCollectionInterfa
return $bool ? $this->select($list) : $this->unselect($list); return $bool ? $this->select($list) : $this->unselect($list);
} }
/**
* @param string|null $languageCode
* @param bool|null $fallback
* @return PageIndex
*/
public function withTranslated(string $languageCode = null, bool $fallback = null)
{
return $this->getIndex()->withTranslated($languageCode, $fallback);
}
/** /**
* Filter pages by given filters. * Filter pages by given filters.
* *
@@ -18,6 +18,7 @@ use Grav\Common\File\CompiledYamlFile;
use Grav\Common\Flex\Traits\FlexGravTrait; use Grav\Common\Flex\Traits\FlexGravTrait;
use Grav\Common\Flex\Traits\FlexIndexTrait; use Grav\Common\Flex\Traits\FlexIndexTrait;
use Grav\Common\Grav; use Grav\Common\Grav;
use Grav\Common\Language\Language;
use Grav\Common\Page\Header; use Grav\Common\Page\Header;
use Grav\Common\Page\Interfaces\PageCollectionInterface; use Grav\Common\Page\Interfaces\PageCollectionInterface;
use Grav\Common\Page\Interfaces\PageInterface; use Grav\Common\Page\Interfaces\PageInterface;
@@ -164,6 +165,31 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
return $root; return $root;
} }
/**
* @param string|null $languageCode
* @param bool|null $fallback
* @return PageIndex
*/
public function withTranslated(string $languageCode = null, bool $fallback = null)
{
if (null === $languageCode) {
return $this;
}
$entries = $this->translateEntries($this->getEntries(), $languageCode, $fallback);
$params = ['language' => $languageCode, 'language_fallback' => $fallback] + $this->getParams();
return $this->createFrom($entries)->setParams($params);
}
/**
* @return string|null
*/
public function getLanguage(): ?string
{
return $this->_params['language'] ?? null;
}
/** /**
* Get the collection params * Get the collection params
* *
@@ -174,6 +200,17 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
return $this->_params ?? []; return $this->_params ?? [];
} }
/**
* Get the collection param
*
* @param string $name
* @return mixed
*/
public function getParam(string $name)
{
return $this->_params[$name] ?? null;
}
/** /**
* Set parameters to the Collection * Set parameters to the Collection
* *
@@ -187,6 +224,20 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
return $this; return $this;
} }
/**
* Set a parameter to the Collection
*
* @param string $name
* @param mixed $value
* @return $this
*/
public function setParam(string $name, $value)
{
$this->_params[$name] = $value;
return $this;
}
/** /**
* Get the collection params * Get the collection params
* *
@@ -197,6 +248,15 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
return $this->getParams(); return $this->getParams();
} }
/**
* {@inheritdoc}
* @see FlexCollectionInterface::getCacheKey()
*/
public function getCacheKey(): string
{
return $this->getTypePrefix() . $this->getFlexType() . '.' . sha1(json_encode($this->getKeys()) . $this->getKeyField() . $this->getLanguage());
}
/** /**
* Filter pages by given filters. * Filter pages by given filters.
* *
@@ -345,6 +405,96 @@ class PageIndex extends FlexPageIndex implements PageCollectionInterface
return $index; return $index;
} }
/**
* @param array $entries
* @param string $lang
* @param bool|null $fallback
* @return array
*/
protected function translateEntries(array $entries, string $lang, bool $fallback = null): array
{
$languages = $this->getFallbackLanguages($lang, $fallback);
foreach ($entries as $key => &$entry) {
// Find out which version of the page we should load.
$translations = $this->getLanguageTemplates((string)$key);
if (!$translations) {
// No translations found, is this a folder?
continue;
}
// Find a translation.
$template = null;
foreach ($languages as $code) {
if (isset($translations[$code])) {
$template = $translations[$code];
break;
}
}
// We couldn't find a translation, remove entry from the list.
if (!isset($code, $template)) {
unset($entries['key']);
continue;
}
// Get the main key without template and langauge.
[$main_key,] = explode('|', $entry['storage_key'] . '|', 2);
// Update storage key and language.
$entry['storage_key'] = $main_key . '|' . $template . '.' . $code;
$entry['lang'] = $code;
}
unset($entry);
return $entries;
}
/**
* @return array
*/
protected function getLanguageTemplates(string $key): array
{
$meta = $this->getMetaData($key);
$template = $meta['template'] ?? 'folder';
$translations = $meta['markdown'] ?? [];
$list = [];
foreach ($translations as $code => $search) {
if (isset($search[$template])) {
// Use main template if possible.
$list[$code] = $template;
} elseif (!empty($search)) {
// Fall back to first matching template.
$list[$code] = key($search);
}
}
return $list;
}
/**
* @param string|null $languageCode
* @param bool|null $fallback
* @return array
*/
protected function getFallbackLanguages(string $languageCode = null, bool $fallback = null): array
{
$fallback = $fallback ?? true;
if (!$fallback && null !== $languageCode) {
return [$languageCode];
}
$grav = Grav::instance();
/** @var Language $language */
$language = $grav['language'];
$languageCode = $languageCode ?? '';
if ($languageCode === '' && $fallback) {
return $language->getFallbackLanguages(null, true);
}
return $fallback ? $language->getFallbackLanguages($languageCode, true) : [$languageCode];
}
/** /**
* @param array $options * @param array $options
* @return array * @return array
@@ -474,17 +474,28 @@ class PageStorage extends FolderStorage
} }
/** /**
* Check if page folder should be deleted.
*
* Deleting page can be done either by deleting everything or just a single language.
* If key contains the language, delete only it, unless it is the last language.
*
* @param string $key * @param string $key
* @return bool * @return bool
*/ */
protected function canDeleteFolder(string $key): bool protected function canDeleteFolder(string $key): bool
{ {
// Return true if there's no language in the key.
$keys = $this->extractKeysFromStorageKey($key); $keys = $this->extractKeysFromStorageKey($key);
if ($keys['lang']) { if (!$keys['lang']) {
return false; return true;
} }
return true; // Get the main key and reload meta.
$key = $this->buildStorageKey($keys);
$meta = $this->getObjectMeta($key, true);
// Return true if there aren't any markdown files left.
return empty($meta['markdown'] ?? []);
} }
/** /**
@@ -22,7 +22,6 @@ use Grav\Common\Grav;
use Grav\Common\Media\Interfaces\MediaCollectionInterface; use Grav\Common\Media\Interfaces\MediaCollectionInterface;
use Grav\Common\Media\Interfaces\MediaUploadInterface; use Grav\Common\Media\Interfaces\MediaUploadInterface;
use Grav\Common\Page\Media; use Grav\Common\Page\Media;
use Grav\Common\Page\Medium\Medium;
use Grav\Common\Page\Medium\MediumFactory; use Grav\Common\Page\Medium\MediumFactory;
use Grav\Common\User\Access; use Grav\Common\User\Access;
use Grav\Common\User\Authentication; use Grav\Common\User\Authentication;
@@ -78,16 +77,12 @@ class UserObject extends FlexObject implements UserInterface, Countable
/** @var array|null */ /** @var array|null */
protected $_uploads_original; protected $_uploads_original;
/** @var FileInterface|null */ /** @var FileInterface|null */
protected $_storage; protected $_storage;
/** @var UserGroupIndex */ /** @var UserGroupIndex */
protected $_groups; protected $_groups;
/** @var Access */ /** @var Access */
protected $_access; protected $_access;
/** @var array|null */ /** @var array|null */
protected $access; protected $access;
+1 -1
View File
@@ -527,7 +527,7 @@ class GPM extends Iterator
$plugins = $this->getRepositoryPlugins(); $plugins = $this->getRepositoryPlugins();
if (null === $themes || null === $plugins) { if (null === $themes || null === $plugins) {
if (!is_writable(ROOT_DIR . '/cache/gpm')) { if (!is_writable(GRAV_ROOT . '/cache/gpm')) {
throw new RuntimeException('The cache/gpm folder is not writable. Please check the folder permissions.'); throw new RuntimeException('The cache/gpm folder is not writable. Please check the folder permissions.');
} }
+4 -1
View File
@@ -135,7 +135,10 @@ class Installer
} }
if (!$options['sophisticated']) { if (!$options['sophisticated']) {
if ($options['theme']) { $isTheme = $options['theme'] ?? false;
// Make sure that themes are always being copied, even if option was not set!
$isTheme = $isTheme || preg_match('|/themes/[^/]+|ui', $install_path);
if ($isTheme) {
self::copyInstall($extracted, $install_path); self::copyInstall($extracted, $install_path);
} else { } else {
self::moveInstall($extracted, $install_path); self::moveInstall($extracted, $install_path);
@@ -71,15 +71,6 @@ trait MediaUploadTrait
*/ */
public function checkUploadedFile(UploadedFileInterface $uploadedFile, string $filename = null, array $settings = null): string public function checkUploadedFile(UploadedFileInterface $uploadedFile, string $filename = null, array $settings = null): string
{ {
// Add the defaults to the settings.
$settings = $this->getUploadSettings($settings);
// Destination is always needed (but it can be set in defaults).
$self = $settings['self'] ?? false;
if (!isset($settings['destination']) && $self === false) {
throw new RuntimeException($this->translate('PLUGIN_ADMIN.DESTINATION_NOT_SPECIFIED'), 400);
}
// Check if there is an upload error. // Check if there is an upload error.
switch ($uploadedFile->getError()) { switch ($uploadedFile->getError()) {
case UPLOAD_ERR_OK: case UPLOAD_ERR_OK:
@@ -101,10 +92,38 @@ trait MediaUploadTrait
throw new RuntimeException($this->translate('PLUGIN_ADMIN.UNKNOWN_ERRORS'), 400); throw new RuntimeException($this->translate('PLUGIN_ADMIN.UNKNOWN_ERRORS'), 400);
} }
$metadata = [
'filename' => $uploadedFile->getClientFilename(),
'mime' => $uploadedFile->getClientMediaType(),
'size' => $uploadedFile->getSize(),
];
return $this->checkFileMetadata($metadata, $filename, $settings);
}
/**
* Checks that file metadata meets the requirements. Returns new filename.
*
* @param array $metadata
* @param array|null $settings
* @return string|null
* @throws RuntimeException
*/
public function checkFileMetadata(array $metadata, string $filename = null, array $settings = null): string
{
// Add the defaults to the settings.
$settings = $this->getUploadSettings($settings);
// Destination is always needed (but it can be set in defaults).
$self = $settings['self'] ?? false;
if (!isset($settings['destination']) && $self === false) {
throw new RuntimeException($this->translate('PLUGIN_ADMIN.DESTINATION_NOT_SPECIFIED'), 400);
}
if (null === $filename) { if (null === $filename) {
// If no filename is given, use the filename from the uploaded file (path is not allowed). // If no filename is given, use the filename from the uploaded file (path is not allowed).
$folder = ''; $folder = '';
$filename = $uploadedFile->getClientFilename() ?? ''; $filename = $metadata['filename'] ?? '';
} else { } else {
// If caller sets the filename, we will accept any custom path. // If caller sets the filename, we will accept any custom path.
$folder = dirname($filename); $folder = dirname($filename);
@@ -128,7 +147,7 @@ trait MediaUploadTrait
$filename = date('YmdHis') . '-' . $filename; $filename = date('YmdHis') . '-' . $filename;
} }
} }
$filepath = $folder !== '' ? $folder . $filename : $filename; $filepath = $folder . $filename;
// Check if the filename is allowed. // Check if the filename is allowed.
if (!Utils::checkFilename($filename)) { if (!Utils::checkFilename($filename)) {
@@ -148,14 +167,14 @@ trait MediaUploadTrait
$filesize = $settings['filesize']; $filesize = $settings['filesize'];
if ($filesize) { if ($filesize) {
$max_filesize = $filesize * 1048576; $max_filesize = $filesize * 1048576;
if ($uploadedFile->getSize() > $max_filesize) { if ($metadata['size'] > $max_filesize) {
// TODO: use own language string // TODO: use own language string
throw new RuntimeException($this->translate('PLUGIN_ADMIN.EXCEEDED_GRAV_FILESIZE_LIMIT'), 400); throw new RuntimeException($this->translate('PLUGIN_ADMIN.EXCEEDED_GRAV_FILESIZE_LIMIT'), 400);
} }
} elseif (null === $filesize) { } elseif (null === $filesize) {
// Check size against the Grav upload limit. // Check size against the Grav upload limit.
$grav_limit = Utils::getUploadLimit(); $grav_limit = Utils::getUploadLimit();
if ($grav_limit > 0 && $uploadedFile->getSize() > $grav_limit) { if ($grav_limit > 0 && $metadata['size'] > $grav_limit) {
throw new RuntimeException($this->translate('PLUGIN_ADMIN.EXCEEDED_GRAV_FILESIZE_LIMIT'), 400); throw new RuntimeException($this->translate('PLUGIN_ADMIN.EXCEEDED_GRAV_FILESIZE_LIMIT'), 400);
} }
} }
@@ -165,6 +184,11 @@ trait MediaUploadTrait
$errors = []; $errors = [];
// Do not trust mime type sent by the browser. // Do not trust mime type sent by the browser.
$mime = Utils::getMimeByFilename($filename); $mime = Utils::getMimeByFilename($filename);
$mimeTest = $metadata['mime'] ?? $mime;
if ($mime !== $mimeTest) {
throw new RuntimeException('The mime type does not match to file extension', 400);
}
foreach ((array)$settings['accept'] as $type) { foreach ((array)$settings['accept'] as $type) {
// Force acceptance of any file when star notation // Force acceptance of any file when star notation
if ($type === '*') { if ($type === '*') {
@@ -95,8 +95,8 @@ class Excerpts
*/ */
public function processLinkExcerpt(array $excerpt, string $type = 'link'): array public function processLinkExcerpt(array $excerpt, string $type = 'link'): array
{ {
$grav = Grav::instance();
$url = htmlspecialchars_decode(rawurldecode($excerpt['element']['attributes']['href'])); $url = htmlspecialchars_decode(rawurldecode($excerpt['element']['attributes']['href']));
$url_parts = $this->parseUrl($url); $url_parts = $this->parseUrl($url);
// If there is a query, then parse it and build action calls. // If there is a query, then parse it and build action calls.
@@ -114,7 +114,7 @@ class Excerpts
); );
// Valid attributes supported. // Valid attributes supported.
$valid_attributes = Grav::instance()['config']->get('system.pages.markdown.valid_link_attributes'); $valid_attributes = $grav['config']->get('system.pages.markdown.valid_link_attributes') ?? [];
$skip = []; $skip = [];
// Unless told to not process, go through actions. // Unless told to not process, go through actions.
@@ -155,9 +155,11 @@ class Excerpts
// If scheme isn't http(s).. // If scheme isn't http(s)..
if (!empty($url_parts['scheme']) && !in_array($url_parts['scheme'], ['http', 'https'])) { if (!empty($url_parts['scheme']) && !in_array($url_parts['scheme'], ['http', 'https'])) {
// Handle custom streams. // Handle custom streams.
if ($type !== 'image' && !empty($url_parts['stream']) && !empty($url_parts['path'])) { /** @var UniformResourceLocator $locator */
$grav = Grav::instance(); $locator = $grav['locator'];
$url_parts['path'] = $grav['base_url_relative'] . '/' . $this->resolveStream("{$url_parts['scheme']}://{$url_parts['path']}"); if ($locator->isStream($url)) {
$path = $locator->findResource($url, false) ?: $locator->findResource($url, false, true);
$url_parts['path'] = $grav['base_url_relative'] . '/' . $path;
unset($url_parts['stream'], $url_parts['scheme']); unset($url_parts['stream'], $url_parts['scheme']);
} }
@@ -338,20 +340,4 @@ class Excerpts
return $url_parts; return $url_parts;
} }
/**
* @param string $url
* @return string
*/
protected function resolveStream(string $url)
{
/** @var UniformResourceLocator $locator */
$locator = Grav::instance()['locator'];
if ($locator->isStream($url)) {
return $locator->findResource($url, false) ?: $locator->findResource($url, false, true);
}
return $url;
}
} }
+1 -1
View File
@@ -2095,7 +2095,7 @@ class Page implements PageInterface
*/ */
public function filePathClean() public function filePathClean()
{ {
return str_replace(ROOT_DIR, '', $this->filePath()); return str_replace(GRAV_ROOT . DS, '', $this->filePath());
} }
/** /**
+1 -1
View File
@@ -311,7 +311,7 @@ class Plugins extends Iterator
} }
} else { } else {
$grav['log']->addWarning( $grav['log']->addWarning(
sprintf("Plugin '%s' enabled but not found! Try clearing cache with `bin/grav clear-cache`", $name) sprintf("Plugin '%s' enabled but not found! Try clearing cache with `bin/grav clearcache`", $name)
); );
return null; return null;
} }
@@ -101,7 +101,14 @@ class InitializeProcessor extends ProcessorBase
// Load pages. // Load pages.
$this->initializePages($config); $this->initializePages($config);
// Initialize URI. // Load accounts (decides class to be used).
// TODO: remove in 2.0.
$this->container['accounts'];
// Initialize session.
$this->initializeSession($config);
// Initialize URI (uses session, see issue #3269).
$this->initializeUri($config); $this->initializeUri($config);
// Grav may return redirect response right away. // Grav may return redirect response right away.
@@ -115,13 +122,6 @@ class InitializeProcessor extends ProcessorBase
} }
} }
// Load accounts (decides class to be used).
// TODO: remove in 2.0.
$this->container['accounts'];
// Initialize session.
$this->initializeSession($config);
$this->stopTimer('_init'); $this->stopTimer('_init');
// Wrap call to next handler so that debugger can profile it. // Wrap call to next handler so that debugger can profile it.
+1 -1
View File
@@ -210,7 +210,7 @@ class Security
'on_events' => '#(<[^>]+[[a-z\x00-\x20\"\'\/])([\s\/]on|\sxmlns)[a-z].*=>?#iUu', 'on_events' => '#(<[^>]+[[a-z\x00-\x20\"\'\/])([\s\/]on|\sxmlns)[a-z].*=>?#iUu',
// Match javascript:, livescript:, vbscript:, mocha:, feed: and data: protocols // Match javascript:, livescript:, vbscript:, mocha:, feed: and data: protocols
'invalid_protocols' => '#(' . implode('|', array_map('preg_quote', $invalid_protocols, ['#'])) . '):.*?#iUu', 'invalid_protocols' => '#(' . implode('|', array_map('preg_quote', $invalid_protocols, ['#'])) . '):\S.*?#iUu',
// Match -moz-bindings // Match -moz-bindings
'moz_binding' => '#-moz-binding[a-z\x00-\x20]*:#u', 'moz_binding' => '#-moz-binding[a-z\x00-\x20]*:#u',
@@ -10,10 +10,18 @@
namespace Grav\Common\Service; namespace Grav\Common\Service;
use Grav\Common\Uri; use Grav\Common\Uri;
use JsonException;
use Nyholm\Psr7\Factory\Psr17Factory; use Nyholm\Psr7\Factory\Psr17Factory;
use Nyholm\Psr7Server\ServerRequestCreator; use Nyholm\Psr7Server\ServerRequestCreator;
use Pimple\Container; use Pimple\Container;
use Pimple\ServiceProviderInterface; use Pimple\ServiceProviderInterface;
use function explode;
use function fopen;
use function function_exists;
use function in_array;
use function is_array;
use function strtolower;
use function trim;
/** /**
* Class RequestServiceProvider * Class RequestServiceProvider
@@ -36,7 +44,56 @@ class RequestServiceProvider implements ServiceProviderInterface
$psr17Factory // StreamFactory $psr17Factory // StreamFactory
); );
return $creator->fromGlobals(); $server = $_SERVER;
if (false === isset($server['REQUEST_METHOD'])) {
$server['REQUEST_METHOD'] = 'GET';
}
$method = $server['REQUEST_METHOD'];
$headers = function_exists('getallheaders') ? getallheaders() : $creator::getHeadersFromServer($_SERVER);
$post = null;
if (in_array($method, ['POST', 'PUT', 'PATCH', 'DELETE'])) {
foreach ($headers as $headerName => $headerValue) {
if ('content-type' !== strtolower($headerName)) {
continue;
}
$contentType = strtolower(trim(explode(';', $headerValue, 2)[0]));
switch ($contentType) {
case 'application/x-www-form-urlencoded':
case 'multipart/form-data':
$post = $_POST;
break 2;
case 'application/json':
case 'application/vnd.api+json':
try {
$json = file_get_contents('php://input');
$post = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
if (!is_array($post)) {
$post = null;
}
} catch (JsonException $e) {
$post = null;
}
break 2;
}
}
}
// Remove _url from ngnix routes.
$get = $_GET;
unset($get['_url']);
if (isset($server['QUERY_STRING'])) {
$query = $server['QUERY_STRING'];
if (strpos($query, '_url=') !== false) {
parse_str($query, $query);
unset($query['_url']);
$server['QUERY_STRING'] = http_build_query($query);
}
}
return $creator->fromArrays($server, $headers, $_COOKIE, $get, $post, $_FILES, fopen('php://input', 'rb') ?: null);
}; };
$container['route'] = $container->factory(function () { $container['route'] = $container->factory(function () {
@@ -0,0 +1,351 @@
<?php
/**
* @package Grav\Common\Twig
*
* @copyright Copyright (c) 2015 - 2021 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace Grav\Common\Twig\Extension;
use Grav\Common\Grav;
use Grav\Common\Utils;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
/**
* Class FilesystemExtension
* @package Grav\Common\Twig\Extension
*/
class FilesystemExtension extends AbstractExtension
{
/** @var UniformResourceLocator */
private $locator;
public function __construct()
{
$this->locator = Grav::instance()['locator'];
}
/**
* @return TwigFunction[]
*/
public function getFilters()
{
return $this->getFunctions();
}
/**
* Return a list of all functions.
*
* @return TwigFunction[]
*/
public function getFunctions()
{
return [
new TwigFunction('file_exists', [$this, 'file_exists']),
new TwigFunction('fileatime', [$this, 'fileatime']),
new TwigFunction('filectime', [$this, 'filectime']),
new TwigFunction('filemtime', [$this, 'filemtime']),
new TwigFunction('filesize', [$this, 'filesize']),
new TwigFunction('filetype', [$this, 'filetype']),
new TwigFunction('is_dir', [$this, 'is_dir']),
new TwigFunction('is_file', [$this, 'is_file']),
new TwigFunction('is_link', [$this, 'is_link']),
new TwigFunction('is_readable', [$this, 'is_readable']),
new TwigFunction('is_writable', [$this, 'is_writable']),
new TwigFunction('is_writeable', [$this, 'is_writable']),
new TwigFunction('lstat', [$this, 'lstat']),
new TwigFunction('getimagesize', [$this, 'getimagesize']),
new TwigFunction('exif_read_data', [$this, 'exif_read_data']),
new TwigFunction('read_exif_data', [$this, 'exif_read_data']),
new TwigFunction('exif_imagetype', [$this, 'exif_imagetype']),
new TwigFunction('hash_file', [$this, 'hash_file']),
new TwigFunction('hash_hmac_file', [$this, 'hash_hmac_file']),
new TwigFunction('md5_file', [$this, 'md5_file']),
new TwigFunction('sha1_file', [$this, 'sha1_file']),
new TwigFunction('get_meta_tags', [$this, 'get_meta_tags']),
];
}
/**
* @param string $filename
* @return bool
*/
public function file_exists($filename): bool
{
if (!$this->checkFilename($filename)) {
return false;
}
return file_exists($filename);
}
/**
* @param string $filename
* @return int|false
*/
public function fileatime($filename)
{
if (!$this->checkFilename($filename)) {
return false;
}
return fileatime($filename);
}
/**
* @param string $filename
* @return int|false
*/
public function filectime($filename)
{
if (!$this->checkFilename($filename)) {
return false;
}
return filectime($filename);
}
/**
* @param string $filename
* @return int|false
*/
public function filemtime($filename)
{
if (!$this->checkFilename($filename)) {
return false;
}
return filemtime($filename);
}
/**
* @param string $filename
* @return int|false
*/
public function filesize($filename)
{
if (!$this->checkFilename($filename)) {
return false;
}
return filesize($filename);
}
/**
* @param string $filename
* @return string|false
*/
public function filetype($filename)
{
if (!$this->checkFilename($filename)) {
return false;
}
return filetype($filename);
}
/**
* @param string $filename
* @return bool
*/
public function is_dir($filename): bool
{
if (!$this->checkFilename($filename)) {
return false;
}
return is_dir($filename);
}
/**
* @param string $filename
* @return bool
*/
public function is_file($filename): bool
{
if (!$this->checkFilename($filename)) {
return false;
}
return is_file($filename);
}
/**
* @param string $filename
* @return bool
*/
public function is_link($filename): bool
{
if (!$this->checkFilename($filename)) {
return false;
}
return is_link($filename);
}
/**
* @param string $filename
* @return bool
*/
public function is_readable($filename): bool
{
if (!$this->checkFilename($filename)) {
return false;
}
return is_readable($filename);
}
/**
* @param string $filename
* @return bool
*/
public function is_writable($filename): bool
{
if (!$this->checkFilename($filename)) {
return false;
}
return is_writable($filename);
}
/**
* @param string $filename
* @return array|false
*/
public function lstat($filename)
{
if (!$this->checkFilename($filename)) {
return false;
}
return lstat($filename);
}
/**
* @param string $filename
* @return array|false
*/
public function getimagesize($filename)
{
if (!$this->checkFilename($filename)) {
return false;
}
return getimagesize($filename);
}
/**
* @param string $file
* @param string|null $required_sections
* @param bool $as_arrays
* @param bool $read_thumbnail
* @return array|false
*/
public function exif_read_data($file, ?string $required_sections, bool $as_arrays = false, bool $read_thumbnail = false)
{
if (!Utils::functionExists('exif_read_data') || !$this->checkFilename($file)) {
return false;
}
return exif_read_data($file, $required_sections, $as_arrays, $read_thumbnail);
}
/**
* @param string $filename
* @return string|false
*/
public function exif_imagetype($filename)
{
if (!Utils::functionExists('exif_imagetype') || !$this->checkFilename($filename)) {
return false;
}
return @exif_imagetype($filename);
}
/**
* @param string $algo
* @param string $filename
* @param bool $binary
* @return string|false
*/
public function hash_file(string $algo, string $filename, bool $binary = false)
{
if (!$this->checkFilename($filename)) {
return false;
}
return hash_file($algo, $filename, $binary);
}
/**
* @param string $algo
* @param string $data
* @param string $key
* @param bool $binary
* @return string|false
*/
public function hash_hmac_file(string $algo, string $data, string $key, bool $binary = false)
{
if (!$this->checkFilename($data)) {
return false;
}
return hash_hmac_file($algo, $data, $key, $binary);
}
/**
* @param string $filename
* @param bool $binary
* @return string|false
*/
public function md5_file($filename, bool $binary = false)
{
if (!$this->checkFilename($filename)) {
return false;
}
return md5_file($filename, $binary);
}
/**
* @param string $filename
* @param bool $binary
* @return string|false
*/
public function sha1_file($filename, bool $binary = false)
{
if (!$this->checkFilename($filename)) {
return false;
}
return sha1_file($filename, $binary);
}
/**
* @param string $filename
* @return array|false
*/
public function get_meta_tags($filename)
{
if (!$this->checkFilename($filename)) {
return false;
}
return get_meta_tags($filename);
}
/**
* @param string $filename
* @return bool
*/
private function checkFilename($filename): bool
{
return is_string($filename) && (!str_contains($filename, '://') || $this->locator->isStream($filename));
}
}
File diff suppressed because it is too large Load Diff
@@ -47,6 +47,6 @@ class TwigNodeMarkdown extends Node implements NodeOutputInterface
->write('$lines = explode("\n", $content);' . PHP_EOL) ->write('$lines = explode("\n", $content);' . PHP_EOL)
->write('$content = preg_replace(\'/^\' . $matches[0]. \'/\', "", $lines);' . PHP_EOL) ->write('$content = preg_replace(\'/^\' . $matches[0]. \'/\', "", $lines);' . PHP_EOL)
->write('$content = join("\n", $content);' . PHP_EOL) ->write('$content = join("\n", $content);' . PHP_EOL)
->write('echo $this->env->getExtension(\'Grav\Common\Twig\TwigExtension\')->markdownFunction($context, $content);' . PHP_EOL); ->write('echo $this->env->getExtension(\'Grav\Common\Twig\Extension\GravExtension\')->markdownFunction($context, $content);' . PHP_EOL);
} }
} }
+48 -16
View File
@@ -16,6 +16,9 @@ use Grav\Common\Language\Language;
use Grav\Common\Language\LanguageCodes; use Grav\Common\Language\LanguageCodes;
use Grav\Common\Page\Interfaces\PageInterface; use Grav\Common\Page\Interfaces\PageInterface;
use Grav\Common\Page\Pages; use Grav\Common\Page\Pages;
use Grav\Common\Twig\Extension\FilesystemExtension;
use Grav\Common\Twig\Extension\GravExtension;
use Grav\Common\Utils;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use RocketTheme\Toolbox\Event\Event; use RocketTheme\Toolbox\Event\Event;
use Phive\Twig\Extensions\Deferred\DeferredExtension; use Phive\Twig\Extensions\Deferred\DeferredExtension;
@@ -34,6 +37,8 @@ use Twig\Profiler\Profile;
use Twig\TwigFilter; use Twig\TwigFilter;
use Twig\TwigFunction; use Twig\TwigFunction;
use function function_exists; use function function_exists;
use function in_array;
use function is_array;
/** /**
* Class Twig * Class Twig
@@ -154,27 +159,53 @@ class Twig
$this->twig = new TwigEnvironment($loader_chain, $params); $this->twig = new TwigEnvironment($loader_chain, $params);
if ($config->get('system.twig.undefined_functions')) { $this->twig->registerUndefinedFunctionCallback(function ($name) use ($config) {
$this->twig->registerUndefinedFunctionCallback(function ($name) { $allowed = $config->get('system.twig.safe_functions');
if (is_array($allowed) && in_array($name, $allowed, true) && function_exists($name)) {
return new TwigFunction($name, $name);
}
if ($config->get('system.twig.undefined_functions')) {
if (function_exists($name)) { if (function_exists($name)) {
return new TwigFunction($name, $name); if (!Utils::isDangerousFunction($name)) {
user_error("PHP function {$name}() was used as Twig function. This is deprecated in Grav 1.7. Please add it to system configuration: `system.twig.safe_functions`", E_USER_DEPRECATED);
return new TwigFunction($name, $name);
}
/** @var Debugger $debugger */
$debugger = $this->grav['debugger'];
$debugger->addException(new RuntimeException("Blocked potentially dangerous PHP function {$name}() being used as Twig function. If you really want to use it, please add it to system configuration: `system.twig.safe_functions`"));
} }
return new TwigFunction($name, static function () { return new TwigFunction($name, static function () {});
}); }
});
}
if ($config->get('system.twig.undefined_filters')) { return false;
$this->twig->registerUndefinedFilterCallback(function ($name) { });
$this->twig->registerUndefinedFilterCallback(function ($name) use ($config) {
$allowed = $config->get('system.twig.safe_filters');
if (is_array($allowed) && in_array($name, $allowed, true) && function_exists($name)) {
return new TwigFilter($name, $name);
}
if ($config->get('system.twig.undefined_filters')) {
if (function_exists($name)) { if (function_exists($name)) {
return new TwigFilter($name, $name); if (!Utils::isDangerousFunction($name)) {
user_error("PHP function {$name}() used as Twig filter. This is deprecated in Grav 1.7. Please add it to system configuration: `system.twig.safe_filters`", E_USER_DEPRECATED);
return new TwigFilter($name, $name);
}
/** @var Debugger $debugger */
$debugger = $this->grav['debugger'];
$debugger->addException(new RuntimeException("Blocked potentially dangerous PHP function {$name}() being used as Twig filter. If you really want to use it, please add it to system configuration: `system.twig.safe_filters`"));
} }
return new TwigFilter($name, static function () { return new TwigFilter($name, static function () {});
}); }
});
} return false;
});
$this->grav->fireEvent('onTwigInitialized'); $this->grav->fireEvent('onTwigInitialized');
@@ -188,7 +219,8 @@ class Twig
if ($config->get('system.twig.debug')) { if ($config->get('system.twig.debug')) {
$this->twig->addExtension(new DebugExtension()); $this->twig->addExtension(new DebugExtension());
} }
$this->twig->addExtension(new TwigExtension()); $this->twig->addExtension(new GravExtension());
$this->twig->addExtension(new FilesystemExtension());
$this->twig->addExtension(new DeferredExtension()); $this->twig->addExtension(new DeferredExtension());
$this->twig->addExtension(new StringLoaderExtension()); $this->twig->addExtension(new StringLoaderExtension());
@@ -211,7 +243,7 @@ class Twig
'assets' => $this->grav['assets'], 'assets' => $this->grav['assets'],
'taxonomy' => $this->grav['taxonomy'], 'taxonomy' => $this->grav['taxonomy'],
'browser' => $this->grav['browser'], 'browser' => $this->grav['browser'],
'base_dir' => rtrim(ROOT_DIR, '/'), 'base_dir' => GRAV_ROOT,
'home_url' => $pages->homeUrl($active_language), 'home_url' => $pages->homeUrl($active_language),
'base_url' => $pages->baseUrl($active_language), 'base_url' => $pages->baseUrl($active_language),
'base_url_absolute' => $pages->baseUrl($active_language, true), 'base_url_absolute' => $pages->baseUrl($active_language, true),
File diff suppressed because it is too large Load Diff
+309 -72
View File
@@ -44,7 +44,7 @@ use function strlen;
*/ */
abstract class Utils abstract class Utils
{ {
/** @var array */ /** @var array */
protected static $nonces = []; protected static $nonces = [];
protected const ROOTURL_REGEX = '{^((?:http[s]?:\/\/[^\/]+)|(?:\/\/[^\/]+))(.*)}'; protected const ROOTURL_REGEX = '{^((?:http[s]?:\/\/[^\/]+)|(?:\/\/[^\/]+))(.*)}';
@@ -178,8 +178,8 @@ abstract class Utils
/** /**
* Check if the $haystack string starts with the substring $needle * Check if the $haystack string starts with the substring $needle
* *
* @param string $haystack * @param string $haystack
* @param string|string[] $needle * @param string|string[] $needle
* @param bool $case_sensitive * @param bool $case_sensitive
* @return bool * @return bool
*/ */
@@ -202,8 +202,8 @@ abstract class Utils
/** /**
* Check if the $haystack string ends with the substring $needle * Check if the $haystack string ends with the substring $needle
* *
* @param string $haystack * @param string $haystack
* @param string|string[] $needle * @param string|string[] $needle
* @param bool $case_sensitive * @param bool $case_sensitive
* @return bool * @return bool
*/ */
@@ -227,9 +227,9 @@ abstract class Utils
/** /**
* Check if the $haystack string contains the substring $needle * Check if the $haystack string contains the substring $needle
* *
* @param string $haystack * @param string $haystack
* @param string|string[] $needle * @param string|string[] $needle
* @param bool $case_sensitive * @param bool $case_sensitive
* @return bool * @return bool
*/ */
public static function contains($haystack, $needle, $case_sensitive = true) public static function contains($haystack, $needle, $case_sensitive = true)
@@ -266,19 +266,19 @@ abstract class Utils
{ {
$regex = str_replace( $regex = str_replace(
array("\*", "\?"), // wildcard chars array("\*", "\?"), // wildcard chars
array('.*','.'), // regexp chars array('.*', '.'), // regexp chars
preg_quote($wildcard_pattern, '/') preg_quote($wildcard_pattern, '/')
); );
return preg_match('/^'.$regex.'$/is', $haystack); return preg_match('/^' . $regex . '$/is', $haystack);
} }
/** /**
* Render simple template filling up the variables in it. If value is not defined, leave it as it was. * Render simple template filling up the variables in it. If value is not defined, leave it as it was.
* *
* @param string $template Template string * @param string $template Template string
* @param array $variables Variables with values * @param array $variables Variables with values
* @param array $brackets Optional array of opening and closing brackets or symbols * @param array $brackets Optional array of opening and closing brackets or symbols
* @return string Final string filled with values * @return string Final string filled with values
*/ */
public static function simpleTemplate(string $template, array $variables, array $brackets = ['{', '}']): string public static function simpleTemplate(string $template, array $variables, array $brackets = ['{', '}']): string
@@ -376,8 +376,8 @@ abstract class Utils
/** /**
* Merge two objects into one. * Merge two objects into one.
* *
* @param object $obj1 * @param object $obj1
* @param object $obj2 * @param object $obj2
* *
* @return object * @return object
*/ */
@@ -415,7 +415,7 @@ abstract class Utils
*/ */
public static function arrayRemoveValue(array $search, $value) public static function arrayRemoveValue(array $search, $value)
{ {
foreach ((array) $value as $val) { foreach ((array)$value as $val) {
$key = array_search($val, $search); $key = array_search($val, $search);
if ($key !== false) { if ($key !== false) {
unset($search[$key]); unset($search[$key]);
@@ -481,8 +481,8 @@ abstract class Utils
/** /**
* Array combine but supports different array lengths * Array combine but supports different array lengths
* *
* @param array $arr1 * @param array $arr1
* @param array $arr2 * @param array $arr2
* @return array|false * @return array|false
*/ */
public static function arrayCombine($arr1, $arr2) public static function arrayCombine($arr1, $arr2)
@@ -495,7 +495,7 @@ abstract class Utils
/** /**
* Array is associative or not * Array is associative or not
* *
* @param array $arr * @param array $arr
* @return bool * @return bool
*/ */
public static function arrayIsAssociative($arr) public static function arrayIsAssociative($arr)
@@ -517,15 +517,15 @@ abstract class Utils
$now = new DateTime(); $now = new DateTime();
$date_formats = [ $date_formats = [
'd-m-Y H:i' => 'd-m-Y H:i (e.g. '.$now->format('d-m-Y H:i').')', 'd-m-Y H:i' => 'd-m-Y H:i (e.g. ' . $now->format('d-m-Y H:i') . ')',
'Y-m-d H:i' => 'Y-m-d H:i (e.g. '.$now->format('Y-m-d H:i').')', 'Y-m-d H:i' => 'Y-m-d H:i (e.g. ' . $now->format('Y-m-d H:i') . ')',
'm/d/Y h:i a' => 'm/d/Y h:i a (e.g. '.$now->format('m/d/Y h:i a').')', 'm/d/Y h:i a' => 'm/d/Y h:i a (e.g. ' . $now->format('m/d/Y h:i a') . ')',
'H:i d-m-Y' => 'H:i d-m-Y (e.g. '.$now->format('H:i d-m-Y').')', 'H:i d-m-Y' => 'H:i d-m-Y (e.g. ' . $now->format('H:i d-m-Y') . ')',
'h:i a m/d/Y' => 'h:i a m/d/Y (e.g. '.$now->format('h:i a m/d/Y').')', 'h:i a m/d/Y' => 'h:i a m/d/Y (e.g. ' . $now->format('h:i a m/d/Y') . ')',
]; ];
$default_format = Grav::instance()['config']->get('system.pages.dateformat.default'); $default_format = Grav::instance()['config']->get('system.pages.dateformat.default');
if ($default_format) { if ($default_format) {
$date_formats = array_merge([$default_format => $default_format.' (e.g. '.$now->format($default_format).')'], $date_formats); $date_formats = array_merge([$default_format => $default_format . ' (e.g. ' . $now->format($default_format) . ')'], $date_formats);
} }
return $date_formats; return $date_formats;
@@ -552,11 +552,11 @@ abstract class Utils
/** /**
* Truncate text by number of characters but can cut off words. * Truncate text by number of characters but can cut off words.
* *
* @param string $string * @param string $string
* @param int $limit Max number of characters. * @param int $limit Max number of characters.
* @param bool $up_to_break truncate up to breakpoint after char count * @param bool $up_to_break truncate up to breakpoint after char count
* @param string $break Break point. * @param string $break Break point.
* @param string $pad Appended padding to the end of the string. * @param string $pad Appended padding to the end of the string.
* @return string * @return string
*/ */
public static function truncate($string, $limit = 150, $up_to_break = false, $break = ' ', $pad = '&hellip;') public static function truncate($string, $limit = 150, $up_to_break = false, $break = ' ', $pad = '&hellip;')
@@ -582,7 +582,7 @@ abstract class Utils
* Truncate text by number of characters in a "word-safe" manor. * Truncate text by number of characters in a "word-safe" manor.
* *
* @param string $string * @param string $string
* @param int $limit * @param int $limit
* @return string * @return string
*/ */
public static function safeTruncate($string, $limit = 150) public static function safeTruncate($string, $limit = 150)
@@ -594,9 +594,9 @@ abstract class Utils
/** /**
* Truncate HTML by number of characters. not "word-safe"! * Truncate HTML by number of characters. not "word-safe"!
* *
* @param string $text * @param string $text
* @param int $length in characters * @param int $length in characters
* @param string $ellipsis * @param string $ellipsis
* @return string * @return string
*/ */
public static function truncateHtml($text, $length = 100, $ellipsis = '...') public static function truncateHtml($text, $length = 100, $ellipsis = '...')
@@ -607,9 +607,9 @@ abstract class Utils
/** /**
* Truncate HTML by number of characters in a "word-safe" manor. * Truncate HTML by number of characters in a "word-safe" manor.
* *
* @param string $text * @param string $text
* @param int $length in words * @param int $length in words
* @param string $ellipsis * @param string $ellipsis
* @return string * @return string
*/ */
public static function safeTruncateHtml($text, $length = 25, $ellipsis = '...') public static function safeTruncateHtml($text, $length = 25, $ellipsis = '...')
@@ -633,8 +633,8 @@ abstract class Utils
* *
* @param string $file the full path to the file to be downloaded * @param string $file the full path to the file to be downloaded
* @param bool $force_download as opposed to letting browser choose if to download or render * @param bool $force_download as opposed to letting browser choose if to download or render
* @param int $sec Throttling, try 0.1 for some speed throttling of downloads * @param int $sec Throttling, try 0.1 for some speed throttling of downloads
* @param int $bytes Size of chunks to send in bytes. Default is 1024 * @param int $bytes Size of chunks to send in bytes. Default is 1024
* @throws Exception * @throws Exception
*/ */
public static function download($file, $force_download = true, $sec = 0, $bytes = 1024) public static function download($file, $force_download = true, $sec = 0, $bytes = 1024)
@@ -645,7 +645,7 @@ abstract class Utils
$file_parts = pathinfo($file); $file_parts = pathinfo($file);
$mimetype = static::getMimeByExtension($file_parts['extension']); $mimetype = static::getMimeByExtension($file_parts['extension']);
$size = filesize($file); // File size $size = filesize($file); // File size
// clean all buffers // clean all buffers
while (ob_get_level()) { while (ob_get_level()) {
@@ -742,7 +742,7 @@ abstract class Utils
// Set from uri extension // Set from uri extension
$uri_extension = $uri->extension(); $uri_extension = $uri->extension();
if (is_string($uri_extension) && $uri->isValidExtension($uri_extension)) { if (is_string($uri_extension) && $uri->isValidExtension($uri_extension)) {
return($uri_extension); return ($uri_extension);
} }
// Use content negotiation via the `accept:` header // Use content negotiation via the `accept:` header
@@ -1060,7 +1060,7 @@ abstract class Utils
$pretty_offset = "UTC${offset_prefix}${offset_formatted}"; $pretty_offset = "UTC${offset_prefix}${offset_formatted}";
$timezone_list[$timezone] = "(${pretty_offset}) ".str_replace('_', ' ', $timezone); $timezone_list[$timezone] = "(${pretty_offset}) " . str_replace('_', ' ', $timezone);
} }
return $timezone_list; return $timezone_list;
@@ -1069,11 +1069,11 @@ abstract class Utils
/** /**
* Recursively filter an array, filtering values by processing them through the $fn function argument * Recursively filter an array, filtering values by processing them through the $fn function argument
* *
* @param array $source the Array to filter * @param array $source the Array to filter
* @param callable $fn the function to pass through each array item * @param callable $fn the function to pass through each array item
* @return array * @return array
*/ */
public static function arrayFilterRecursive(Array $source, $fn) public static function arrayFilterRecursive(array $source, $fn)
{ {
$result = []; $result = [];
foreach ($source as $key => $value) { foreach ($source as $key => $value) {
@@ -1093,15 +1093,15 @@ abstract class Utils
/** /**
* Flatten a multi-dimensional associative array into query params. * Flatten a multi-dimensional associative array into query params.
* *
* @param array $array * @param array $array
* @param string $prepend * @param string $prepend
* @return array * @return array
*/ */
public static function arrayToQueryParams($array, $prepend = '') public static function arrayToQueryParams($array, $prepend = '')
{ {
$results = []; $results = [];
foreach ($array as $key => $value) { foreach ($array as $key => $value) {
$name = $prepend ? $prepend . '[' . $key . ']' : $key; $name = $prepend ? $prepend . '[' . $key . ']' : $key;
if (is_array($value)) { if (is_array($value)) {
$results = array_merge($results, static::arrayToQueryParams($value, $name)); $results = array_merge($results, static::arrayToQueryParams($value, $name));
@@ -1138,8 +1138,8 @@ abstract class Utils
/** /**
* Flatten a multi-dimensional associative array into dot notation * Flatten a multi-dimensional associative array into dot notation
* *
* @param array $array * @param array $array
* @param string $prepend * @param string $prepend
* @return array * @return array
*/ */
public static function arrayFlattenDotNotation($array, $prepend = '') public static function arrayFlattenDotNotation($array, $prepend = '')
@@ -1147,9 +1147,9 @@ abstract class Utils
$results = array(); $results = array();
foreach ($array as $key => $value) { foreach ($array as $key => $value) {
if (is_array($value)) { if (is_array($value)) {
$results = array_merge($results, static::arrayFlattenDotNotation($value, $prepend.$key.'.')); $results = array_merge($results, static::arrayFlattenDotNotation($value, $prepend . $key . '.'));
} else { } else {
$results[$prepend.$key] = $value; $results[$prepend . $key] = $value;
} }
} }
@@ -1297,7 +1297,7 @@ abstract class Utils
* with reverse proxy setups. * with reverse proxy setups.
* *
* @param string $action * @param string $action
* @param bool $previousTick if true, generates the token for the previous tick (the previous 12 hours) * @param bool $previousTick if true, generates the token for the previous tick (the previous 12 hours)
* @return string the nonce string * @return string the nonce string
*/ */
private static function generateNonceString($action, $previousTick = false) private static function generateNonceString($action, $previousTick = false)
@@ -1334,8 +1334,8 @@ abstract class Utils
* Creates a hashed nonce tied to the passed action. Tied to the current user and time. The nonce for a given * Creates a hashed nonce tied to the passed action. Tied to the current user and time. The nonce for a given
* action is the same for 12 hours. * action is the same for 12 hours.
* *
* @param string $action the action the nonce is tied to (e.g. save-user-admin or move-page-homepage) * @param string $action the action the nonce is tied to (e.g. save-user-admin or move-page-homepage)
* @param bool $previousTick if true, generates the token for the previous tick (the previous 12 hours) * @param bool $previousTick if true, generates the token for the previous tick (the previous 12 hours)
* @return string the nonce * @return string the nonce
*/ */
public static function getNonce($action, $previousTick = false) public static function getNonce($action, $previousTick = false)
@@ -1353,7 +1353,7 @@ abstract class Utils
/** /**
* Verify the passed nonce for the give action * Verify the passed nonce for the give action
* *
* @param string|string[] $nonce the nonce to verify * @param string|string[] $nonce the nonce to verify
* @param string $action the action to verify the nonce to * @param string $action the action to verify the nonce to
* @return boolean verified or not * @return boolean verified or not
*/ */
@@ -1370,9 +1370,7 @@ abstract class Utils
} }
//Nonce generated 12-24 hours ago //Nonce generated 12-24 hours ago
$previousTick = true; return $nonce === self::getNonce($action, true);
return $nonce === self::getNonce($action, $previousTick);
} }
/** /**
@@ -1382,11 +1380,7 @@ abstract class Utils
*/ */
public static function isAdminPlugin() public static function isAdminPlugin()
{ {
if (isset(Grav::instance()['admin'])) { return isset(Grav::instance()['admin']);
return true;
}
return false;
} }
/** /**
@@ -1440,7 +1434,7 @@ abstract class Utils
while (count($keys) > 1) { while (count($keys) > 1) {
$key = array_shift($keys); $key = array_shift($keys);
if (! isset($array[$key]) || ! is_array($array[$key])) { if (!isset($array[$key]) || !is_array($array[$key])) {
$array[$key] = array(); $array[$key] = array();
} }
@@ -1731,7 +1725,7 @@ abstract class Utils
$size *= 1024 ** stripos('bkmgtpezy', $unit[0]); $size *= 1024 ** stripos('bkmgtpezy', $unit[0]);
} }
return (int) abs(round($size)); return (int)abs(round($size));
} }
/** /**
@@ -1776,7 +1770,7 @@ abstract class Utils
public static function processMarkdown($string, $block = true, $page = null) public static function processMarkdown($string, $block = true, $page = null)
{ {
$grav = Grav::instance(); $grav = Grav::instance();
$page = $page ?? $grav['page'] ?? null; $page = $page ?? $grav['page'] ?? null;
$defaults = [ $defaults = [
'markdown' => $grav['config']->get('system.pages.markdown', []), 'markdown' => $grav['config']->get('system.pages.markdown', []),
'images' => $grav['config']->get('system.images', []) 'images' => $grav['config']->get('system.images', [])
@@ -1818,12 +1812,12 @@ abstract class Utils
$ip = (string)inet_pton($ip); $ip = (string)inet_pton($ip);
// Maximum netmask length = same as packed address // Maximum netmask length = same as packed address
$len = 8*strlen($ip); $len = 8 * strlen($ip);
if ($prefix > $len) { if ($prefix > $len) {
$prefix = $len; $prefix = $len;
} }
$mask = str_repeat('f', $prefix>>2); $mask = str_repeat('f', $prefix >> 2);
switch ($prefix & 3) { switch ($prefix & 3) {
case 3: case 3:
@@ -1836,7 +1830,7 @@ abstract class Utils
$mask .= '8'; $mask .= '8';
break; break;
} }
$mask = str_pad($mask, $len>>2, '0'); $mask = str_pad($mask, $len >> 2, '0');
// Packed representation of netmask // Packed representation of netmask
$mask = pack('H*', $mask); $mask = pack('H*', $mask);
@@ -1850,11 +1844,14 @@ abstract class Utils
* Wrapper to ensure html, htm in the front of the supported page types * Wrapper to ensure html, htm in the front of the supported page types
* *
* @param array|null $defaults * @param array|null $defaults
* @return array|mixed * @return array
*/ */
public static function getSupportPageTypes(array $defaults = null) public static function getSupportPageTypes(array $defaults = null)
{ {
$types = Grav::instance()['config']->get('system.pages.types', $defaults); $types = Grav::instance()['config']->get('system.pages.types', $defaults);
if (!is_array($types)) {
return [];
}
// remove html/htm // remove html/htm
$types = static::arrayRemoveValue($types, ['html', 'htm']); $types = static::arrayRemoveValue($types, ['html', 'htm']);
@@ -1864,4 +1861,244 @@ abstract class Utils
return $types; return $types;
} }
/**
* @param string $name
* @return bool
*/
public static function isDangerousFunction(string $name): bool
{
static $commandExecutionFunctions = [
'exec',
'passthru',
'system',
'shell_exec',
'popen',
'proc_open',
'pcntl_exec',
];
static $codeExecutionFunctions = [
'assert',
'preg_replace',
'create_function',
'include',
'include_once',
'require',
'require_once'
];
static $callbackFunctions = [
'ob_start' => 0,
'array_diff_uassoc' => -1,
'array_diff_ukey' => -1,
'array_filter' => 1,
'array_intersect_uassoc' => -1,
'array_intersect_ukey' => -1,
'array_map' => 0,
'array_reduce' => 1,
'array_udiff_assoc' => -1,
'array_udiff_uassoc' => [-1, -2],
'array_udiff' => -1,
'array_uintersect_assoc' => -1,
'array_uintersect_uassoc' => [-1, -2],
'array_uintersect' => -1,
'array_walk_recursive' => 1,
'array_walk' => 1,
'assert_options' => 1,
'uasort' => 1,
'uksort' => 1,
'usort' => 1,
'preg_replace_callback' => 1,
'spl_autoload_register' => 0,
'iterator_apply' => 1,
'call_user_func' => 0,
'call_user_func_array' => 0,
'register_shutdown_function' => 0,
'register_tick_function' => 0,
'set_error_handler' => 0,
'set_exception_handler' => 0,
'session_set_save_handler' => [0, 1, 2, 3, 4, 5],
'sqlite_create_aggregate' => [2, 3],
'sqlite_create_function' => 2,
];
static $informationDiscosureFunctions = [
'phpinfo',
'posix_mkfifo',
'posix_getlogin',
'posix_ttyname',
'getenv',
'get_current_user',
'proc_get_status',
'get_cfg_var',
'disk_free_space',
'disk_total_space',
'diskfreespace',
'getcwd',
'getlastmo',
'getmygid',
'getmyinode',
'getmypid',
'getmyuid'
];
static $otherFunctions = [
'extract',
'parse_str',
'putenv',
'ini_set',
'mail',
'header',
'proc_nice',
'proc_terminate',
'proc_close',
'pfsockopen',
'fsockopen',
'apache_child_terminate',
'posix_kill',
'posix_mkfifo',
'posix_setpgid',
'posix_setsid',
'posix_setuid',
];
if (in_array($name, $commandExecutionFunctions)) {
return true;
}
if (in_array($name, $codeExecutionFunctions)) {
return true;
}
if (isset($callbackFunctions[$name])) {
return true;
}
if (in_array($name, $informationDiscosureFunctions)) {
return true;
}
if (in_array($name, $otherFunctions)) {
return true;
}
return static::isFilesystemFunction($name);
}
/**
* @param string $name
* @return bool
*/
public static function isFilesystemFunction(string $name): bool
{
static $fileWriteFunctions = [
'fopen',
'tmpfile',
'bzopen',
'gzopen',
// write to filesystem (partially in combination with reading)
'chgrp',
'chmod',
'chown',
'copy',
'file_put_contents',
'lchgrp',
'lchown',
'link',
'mkdir',
'move_uploaded_file',
'rename',
'rmdir',
'symlink',
'tempnam',
'touch',
'unlink',
'imagepng',
'imagewbmp',
'image2wbmp',
'imagejpeg',
'imagexbm',
'imagegif',
'imagegd',
'imagegd2',
'iptcembed',
'ftp_get',
'ftp_nb_get',
];
static $fileContentFunctions = [
'file_get_contents',
'file',
'filegroup',
'fileinode',
'fileowner',
'fileperms',
'glob',
'is_executable',
'is_uploaded_file',
'parse_ini_file',
'readfile',
'readlink',
'realpath',
'gzfile',
'readgzfile',
'stat',
'imagecreatefromgif',
'imagecreatefromjpeg',
'imagecreatefrompng',
'imagecreatefromwbmp',
'imagecreatefromxbm',
'imagecreatefromxpm',
'ftp_put',
'ftp_nb_put',
'hash_update_file',
'highlight_file',
'show_source',
'php_strip_whitespace',
];
static $filesystemFunctions = [
// read from filesystem
'file_exists',
'fileatime',
'filectime',
'filemtime',
'filesize',
'filetype',
'is_dir',
'is_file',
'is_link',
'is_readable',
'is_writable',
'is_writeable',
'linkinfo',
'lstat',
//'pathinfo',
'getimagesize',
'exif_read_data',
'read_exif_data',
'exif_thumbnail',
'exif_imagetype',
'hash_file',
'hash_hmac_file',
'md5_file',
'sha1_file',
'get_meta_tags',
];
if (in_array($name, $fileWriteFunctions)) {
return true;
}
if (in_array($name, $fileContentFunctions)) {
return true;
}
if (in_array($name, $filesystemFunctions)) {
return true;
}
return false;
}
} }
@@ -73,11 +73,11 @@ class InstallCommand extends GravCommand
$io = $this->getIO(); $io = $this->getIO();
$dependencies_file = '.dependencies'; $dependencies_file = '.dependencies';
$this->destination = $input->getArgument('destination') ?: GRAV_ROOT; $this->destination = $input->getArgument('destination') ?: GRAV_WEBROOT;
// fix trailing slash // fix trailing slash
$this->destination = rtrim($this->destination, DS) . DS; $this->destination = rtrim($this->destination, DS) . DS;
$this->user_path = $this->destination . USER_PATH; $this->user_path = $this->destination . GRAV_USER_PATH . DS;
if ($local_config_file = $this->loadLocalConfig()) { if ($local_config_file = $this->loadLocalConfig()) {
$io->writeln('Read local config from <cyan>' . $local_config_file . '</cyan>'); $io->writeln('Read local config from <cyan>' . $local_config_file . '</cyan>');
} }
@@ -600,7 +600,13 @@ class InstallCommand extends GpmCommand
try { try {
$output = Response::get($package->zipball_url . $query, [], [$this, 'progress']); $output = Response::get($package->zipball_url . $query, [], [$this, 'progress']);
} catch (Exception $e) { } catch (Exception $e) {
$error = str_replace("\n", "\n | '- ", $e->getMessage()); if (!empty($package->premium) && $e->getCode() === 401) {
$message = '<yellow>Unauthorized Premium License Key</yellow>';
} else {
$message = $e->getMessage();
}
$error = str_replace("\n", "\n | '- ", $message);
$io->write("\x0D"); $io->write("\x0D");
// extra white spaces to clear out the buffer properly // extra white spaces to clear out the buffer properly
$io->writeln(' |- Downloading package... <red>error</red> '); $io->writeln(' |- Downloading package... <red>error</red> ');
@@ -112,7 +112,7 @@ class UninstallCommand extends GpmCommand
unset($this->data['not_found'], $this->data['total']); unset($this->data['not_found'], $this->data['total']);
// Plugins need to be initialized in order to make clear-cache to work. // Plugins need to be initialized in order to make clearcache to work.
try { try {
$this->initializePlugins(); $this->initializePlugins();
} catch (Throwable $e) { } catch (Throwable $e) {
@@ -173,6 +173,7 @@ trait ControllerResponseTrait
if ($method !== 'GET' && $method !== 'HEAD') { if ($method !== 'GET' && $method !== 'HEAD') {
$this->setMessage($message, 'error'); $this->setMessage($message, 'error');
$referer = $request->getHeaderLine('Referer'); $referer = $request->getHeaderLine('Referer');
return $this->createRedirectResponse($referer, 303); return $this->createRedirectResponse($referer, 303);
} }
+1 -1
View File
@@ -119,7 +119,7 @@ class FlexForm implements FlexObjectFormInterface, JsonSerializable
} }
$this->setUniqueId($uniqueId); $this->setUniqueId($uniqueId);
$directory = $object->getFlexDirectory(); $directory = $object->getFlexDirectory();
$this->setFlashLookupFolder($directory->getBlueprint()->get('form/flash_folder') ?? 'tmp://forms/[SESSIONID]'); $this->setFlashLookupFolder($options['flash_folder'] ?? $directory->getBlueprint()->get('form/flash_folder') ?? 'tmp://forms/[SESSIONID]');
$this->form = $options['form'] ?? null; $this->form = $options['form'] ?? null;
if (!empty($options['reset'])) { if (!empty($options['reset'])) {
+24 -7
View File
@@ -196,9 +196,10 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface
/** /**
* Refresh object from the storage. * Refresh object from the storage.
* *
* @param bool $keepMissing
* @return bool True if the object was refreshed * @return bool True if the object was refreshed
*/ */
public function refresh(): bool public function refresh(bool $keepMissing = false): bool
{ {
$key = $this->getStorageKey(); $key = $this->getStorageKey();
if ('' === $key) { if ('' === $key) {
@@ -216,20 +217,36 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface
return false; return false;
} }
// Get current elements (if requested).
$current = $keepMissing ? $this->getElements() : [];
// Get elements from the filesystem.
$elements = $storage->readRows([$key => null])[$key] ?? null; $elements = $storage->readRows([$key => null])[$key] ?? null;
if (null !== $elements || isset($elements['__ERROR'])) { if (null !== $elements) {
$meta = $elements['_META'] ?? $meta; $meta = $elements['__META'] ?? $meta;
unset($elements['__META']);
$this->filterElements($elements); $this->filterElements($elements);
$newKey = $meta['key'] ?? $this->getKey(); $newKey = $meta['key'] ?? $this->getKey();
if ($meta) { if ($meta) {
$this->setMetaData($meta); $this->setMetaData($meta);
} }
$this->objectConstruct($elements, $newKey); $this->objectConstruct($elements, $newKey);
}
/** @var Debugger $debugger */ if ($current) {
$debugger = Grav::instance()['debugger']; // Inject back elements which are missing in the filesystem.
$debugger->addMessage("Refreshed {$this->getFlexType()} object {$this->getKey()}", 'debug'); $data = $this->getBlueprint()->flattenData($current);
foreach ($data as $property => $value) {
if (strpos($property, '.') === false) {
$this->defProperty($property, $value);
} else {
$this->defNestedProperty($property, $value);
}
}
}
/** @var Debugger $debugger */
$debugger = Grav::instance()['debugger'];
$debugger->addMessage("Refreshed {$this->getFlexType()} object {$this->getKey()}", 'debug');
}
return true; return true;
} }
@@ -320,14 +320,21 @@ trait PageLegacyTrait
// Find non-existing key. // Find non-existing key.
$parentKey = $parent ? $parent->getKey() : ''; $parentKey = $parent ? $parent->getKey() : '';
$key = trim($parentKey . '/' . basename($this->getKey()), '/'); if ($this instanceof FlexPageObject) {
$key = preg_replace('/-\d+$/', '', $key); $key = trim($parentKey . '/' . $this->folder(), '/');
$i = 1; } else {
do { $key = trim($parentKey . '/' . basename($this->getKey()), '/');
$i++; }
$test = "{$key}-{$i}";
} while ($index->containsKey($test)); if ($index->containsKey($key)) {
$key = $test; $key = preg_replace('/\d+$/', '', $key);
$i = 1;
do {
$i++;
$test = "{$key}{$i}";
} while ($index->containsKey($test));
$key = $test;
}
$folder = basename($key); $folder = basename($key);
// Get the folder name. // Get the folder name.
+3
View File
@@ -0,0 +1,3 @@
enabled: true
dropdown:
enabled: true
+1 -1
View File
@@ -2,6 +2,6 @@
title: Accueil title: Accueil
body_classes: modular body_classes: modular
visible: true visible: true
debugger: true debugger: false
--- ---
@@ -14,7 +14,7 @@ programmes:
site: 'http://www.popsu.archi.fr/' site: 'http://www.popsu.archi.fr/'
- -
nom_du_programme: 'Programme Coubertin' nom_du_programme: 'Programme Coubertin'
texte_de_presentation: "Le programme de recherche-action Coubertin construit le récit, au fil de leau, de la conception des ouvrages et des opérations daménagement des Jeux Olympiques et Paralympiques de Paris 2024. À travers une observation embarquée au sein de la SOLIDEO, l’équipe de chercheurs analyse la production architecturale et urbaine et sa capacité à transformer les pratiques daménagement.\r\n \r\n " texte_de_presentation: "Le programme de recherche-action Coubertin construit le récit, au fil de leau, de la conception des ouvrages et des opérations daménagement des Jeux Olympiques et Paralympiques de Paris 2024. À travers une observation embarquée au sein de la SOLIDEO, l’équipe de chercheurs analyse la production architecturale et urbaine et sa capacité à transformer les pratiques daménagement.\n \n "
logo: logo_coubertin.png logo: logo_coubertin.png
site: 'http://www.urbanisme-puca.gouv.fr/programme-coubertin-un-programme-de-recherche-a2089.html#:~:text=Un%20centre%20de%20ressources%20sur%20les%20Jeux%20Olympiques%20et%20Paralympiques,Olympiques%20et%20Paralympiques%20de%20Paris%E2%80%A6' site: 'http://www.urbanisme-puca.gouv.fr/programme-coubertin-un-programme-de-recherche-a2089.html#:~:text=Un%20centre%20de%20ressources%20sur%20les%20Jeux%20Olympiques%20et%20Paralympiques,Olympiques%20et%20Paralympiques%20de%20Paris%E2%80%A6'
- -
@@ -23,7 +23,7 @@ programmes:
logo: forum_solution.png logo: forum_solution.png
site: 'http://www.urbanisme-puca.gouv.fr/forums-des-solutions-en-videos-a1879.html' site: 'http://www.urbanisme-puca.gouv.fr/forums-des-solutions-en-videos-a1879.html'
visible: true visible: true
debugger: true debugger: false
media_order: '14360_default_big.jpg,10361_web_01.jpg,hyperliens_marseille.PNG,popsu.png,forum_solution.png,europan_france.jpg,logo_coubertin.png,POPSU2018_LOGO_moinsde6cm.png' media_order: '14360_default_big.jpg,10361_web_01.jpg,hyperliens_marseille.PNG,popsu.png,forum_solution.png,europan_france.jpg,logo_coubertin.png,POPSU2018_LOGO_moinsde6cm.png'
process: process:
markdown: true markdown: true
Binary file not shown.

After

Width:  |  Height:  |  Size: 790 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 970 KiB

+10 -25
View File
@@ -1,35 +1,20 @@
--- ---
title: Ressources title: Ressources
body_classes: modular body_classes: modular
media_order: 'rapport_activite_V1.pdf,rapport_activite_V1.png,rapport_activite_V1.pdf' media_order: 'Couv note orientation.PNG,Couv rapport activités.PNG,Note d''orientation EPAU 2021-2023.pdf,Rapport d''activité EPAU 2020.pdf'
visible: true visible: true
debugger: true debugger: false
rapports: rapports:
- -
titre_du_rapport: 'rapport d''activité 2020' titre_du_rapport: 'Rapport d''activité 2020'
texte_de_presentation: "Courte explicationVita estillis semper in fuga uxoresque mercenariae\r\n infugauxoresque mercenariae conductae ad tempus expacto atque, ut conductae ad tempus ex pacto atque, ut sit species matrimonii, dotis nomine futura coniunx hastam.\r\n" texte_de_presentation: "Le rapport dactivité présente les principales actions réalisées par les programmes Europan, POPSU et Coubertin à loccasion de lannée 2020. \n"
couverture: rapport_activite_V1.png couverture: 'Couv rapport activités.PNG'
pdf: rapport_activite_V1.pdf pdf: 'Rapport d''activité EPAU 2020.pdf'
- -
titre_du_rapport: 'rapport 3' titre_du_rapport: 'Note d''orientation 2021-2023'
texte_de_presentation: "Courte explicationVita estillis semper in fuga uxoresque mercenariae\r\n infugauxoresque mercenariae conductae ad tempus expacto atque, ut conductae ad tempus ex pacto atque, ut sit species matrimonii, dotis nomine futura coniunx hastam.\r\n" texte_de_presentation: "La note dorientation présente la stratégie de lEurope des projets architecturaux et urbains de 2021 à 2023. \n"
couverture: rapport_activite_V1.png couverture: 'Couv note orientation.PNG'
pdf: rapport_activite_V1.pdf pdf: 'Note d''orientation EPAU 2021-2023.pdf'
-
titre_du_rapport: 'exemple 3'
texte_de_presentation: "Courte explicationVita estillis semper in fuga uxoresque mercenariae\r\n infugauxoresque mercenariae conductae ad tempus expacto atque, ut conductae ad tempus ex pacto atque, ut sit species matrimonii, dotis nomine futura coniunx hastam.\r\n"
couverture: rapport_activite_V1.png
pdf: rapport_activite_V1.pdf
-
titre_du_rapport: 'exemple 4'
texte_de_presentation: "Courte explicationVita estillis semper in fuga uxoresque mercenariae\r\n infugauxoresque mercenariae conductae ad tempus expacto atque, ut conductae ad tempus ex pacto atque, ut sit species matrimonii, dotis nomine futura coniunx hastam.\r\n"
couverture: rapport_activite_V1.png
pdf: rapport_activite_V1.pdf
-
titre_du_rapport: 'exempl 5'
texte_de_presentation: "Courte explicationVita estillis semper in fuga uxoresque mercenariae\r\n infugauxoresque mercenariae conductae ad tempus expacto atque, ut conductae ad tempus ex pacto atque, ut sit species matrimonii, dotis nomine futura coniunx hastam.\r\n"
couverture: rapport_activite_V1.png
pdf: rapport_activite_V1.pdf
process: process:
markdown: true markdown: true
twig: false twig: false
@@ -6,7 +6,7 @@ personnes:
- -
nom: 'Hélène Peskine' nom: 'Hélène Peskine'
fonction: 'Secrétaire permanente du Plan Urbanisme Construction Architecture, Ministère de la Transition écologique, Ministère de la Cohésion des territoires et des Relations avec les Collectivités territoriales' fonction: 'Secrétaire permanente du Plan Urbanisme Construction Architecture, Ministère de la Transition écologique, Ministère de la Cohésion des territoires et des Relations avec les Collectivités territoriales'
biographie: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam nec sagittis massa. Nulla facilisi. Cras id arcu lorem, et semper purus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Duis vel enim mi, in lobortis sem. Vestibulum luctus elit eu libero ultrices id fermentum sem sagittis. Nulla imperdiet mauris sed sapien dignissim id aliquam est aliquam. Maecenas non odio ipsum, a elementum nisi. Mauris non erat eu erat placerat convallis. Mauris in pretium urna. Cras laoreet molestie odio, consequat consequat velit commodo eu. Integer vitae lectus ac nunc posuere pellentesque non at eros. Suspendisse non lectus lorem.' biographie: null
portrait: MB-3-crop.jpg portrait: MB-3-crop.jpg
admin: { } admin: { }
process: process:
Binary file not shown.

After

Width:  |  Height:  |  Size: 346 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 MiB

@@ -11,22 +11,22 @@ personnes:
- -
nom: 'Catherine Chevillot' nom: 'Catherine Chevillot'
fonction: 'Présidente de la Cité de lArchitecture et du Patrimoine' fonction: 'Présidente de la Cité de lArchitecture et du Patrimoine'
biographie: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam nec sagittis massa. Nulla facilisi. Cras id arcu lorem, et semper purus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Duis vel enim mi, in lobortis sem. Vestibulum luctus elit eu libero ultrices id fermentum sem sagittis. Nulla imperdiet mauris sed sapien dignissim id aliquam est aliquam. Maecenas non odio ipsum, a elementum nisi. Mauris non erat eu erat placerat convallis. Mauris in pretium urna. Cras laoreet molestie odio, consequat consequat velit commodo eu. Integer vitae lectus ac nunc posuere pellentesque non at eros. Suspendisse non lectus lorem.' biographie: 'Conservateur du patrimoine depuis 1987, Catherine Chevillot a été successivement adjointe au directeur du musée de Grenoble (1988), conservateur au musée dOrsay (1990), chef de la filière Sculpture au Centre de Recherche et de Restauration des Musées de France (1999), chef du service de la recherche du musée dOrsay, où elle a créé le Prix du musée dOrsay (2003), conservateur en chef au musée dOrsay (2012) et directrice du musée Rodin (2012). Après trois mandats au musée Rodin, sur proposition de la ministre de la Culture Roselyne Bachelot-Narquin, elle accède le 8 mars 2021 à la présidence de la Cité de larchitecture & du patrimoine.'
portrait: catherine-chevillot-nouvelle-presidente-de-cite.JPG portrait: 'catherine chevillot 274 (1).jpg'
- -
nom: 'Aurélie Cousi' nom: 'Aurélie Cousi'
fonction: 'Directrice, adjointe au directeur général des patrimoines, chargée de larchitecture, Ministère de la Culture' fonction: 'Directrice, adjointe au directeur général des patrimoines, chargée de larchitecture, Ministère de la Culture'
biographie: "Aurélie Cousi a rejoint le ministère de la Culture le 1 er février 2020 dans les fonctions de directrice, adjointe au directeur général des patrimoines, chargée de larchitecture. Diplômée de l’École polytehnique et ingénieure en chef des ponts, des eaux et des forêts, elle exerce depuis 15 ans au sein de l’État, de ses établissements publics et des collectivités dans les domaines de laménagement, lurbanisme et la construction publique. \r\nCheffe de la mission immobilière auprès du directeur régional et interdépartementale de l’écologie et de laménagement d’Île-de-France de 2007 à 2009, puis directrice adjointe en charge de la stratégie opérationnelle à la direction de limmobilier de l’établissement public Paris-Saclay, en charge du pilotage des projets de construction des grandes écoles et universités, Aurélie Cousi est nommée conseillère en charge de lurbanisme au cabinet du maire de Paris en 2013, avant de prendre la direction du service de laménagement à la direction de lurbanisme de 2015 à 2017. Depuis juillet 2017, elle était directrice générale adjointe en charge de laménagement au sein de Grand Paris Aménagement." biographie: "Aurélie Cousi a rejoint le ministère de la Culture le 1 er février 2020 dans les fonctions de directrice, adjointe au directeur général des patrimoines, chargée de larchitecture. Diplômée de l’École polytehnique et ingénieure en chef des ponts, des eaux et des forêts, elle exerce depuis 15 ans au sein de l’État, de ses établissements publics et des collectivités dans les domaines de laménagement, lurbanisme et la construction publique. \nCheffe de la mission immobilière auprès du directeur régional et interdépartementale de l’écologie et de laménagement d’Île-de-France de 2007 à 2009, puis directrice adjointe en charge de la stratégie opérationnelle à la direction de limmobilier de l’établissement public Paris-Saclay, en charge du pilotage des projets de construction des grandes écoles et universités, Aurélie Cousi est nommée conseillère en charge de lurbanisme au cabinet du maire de Paris en 2013, avant de prendre la direction du service de laménagement à la direction de lurbanisme de 2015 à 2017. Depuis juillet 2017, elle était directrice générale adjointe en charge de laménagement au sein de Grand Paris Aménagement."
portrait: aurelie-cousi-nommee-aux-fonctions-de-directrice.jpg portrait: aurelie-cousi-nommee-aux-fonctions-de-directrice.jpg
- -
nom: 'Alain Maugard' nom: 'Alain Maugard'
fonction: 'Président de lAssociation Europan France' fonction: 'Président de lAssociation Europan France'
biographie: "Né le 23 avril 1943 à Nérac (Lot-et-Garonne), Alain Maugard est un ancien élève de l’École polytechnique et Ingénieur général des Ponts et Chaussées. Il débute sa carrière au ministère de l’Équipement au service des Affaires économiques et internationales et dans les services urbanisme construction des Directions Départementales. Chef du service de la politique technique à la direction de la Construction et secrétaire permanent du Plan Construction, de 1978 à 1981, il devient successivement directeur adjoint de cabinet des ministres de lUrbanisme et du Logement Roger Quilliot et Paul Quilès puis directeur de la Construction au ministère de l’Équipement, du Logement, des Transports et de la Mer. En 1990, il est nommé directeur général de l’Établissement public daménagement de la Défense (epad), jusquen 1993 où il prend la présidence du cstb. Il quitte ces fonctions en 2008 pour rejoindre le Conseil général de lenvironnement et du développement durable où il assure la présidence de la section « risques, sécurité, sûreté ». En septembre 2009, il accède à la présidence de Qualibat. \r\nEn outre, Alain Maugard est membre du conseil dadministration de lAdeme. Il a également piloté le Comité opérationnel (comop) du chantier n°1 « Bâtiments neufs publics et privés » du Grenelle de lEnvironnement. \r\n\r\nBibliographie\_:\r\n- Regards sur le bâtiment — Le futur en construction, éditions Le Moniteur, 2006\r\n - Regard sur la ville durable, Alain Maugard et Jean-Pierre Cuisinier, CSTB, mars 2010\r\n - Le BEPOS pour tous (livre électronique), http://outils.xpair.com/livre/bepos-pourtous/7.htm (25 juin 2015)" biographie: "Né le 23 avril 1943 à Nérac (Lot-et-Garonne), Alain Maugard est un ancien élève de l’École polytechnique et Ingénieur général des Ponts et Chaussées. Il débute sa carrière au ministère de l’Équipement au service des Affaires économiques et internationales et dans les services urbanisme construction des Directions Départementales. Chef du service de la politique technique à la direction de la Construction et secrétaire permanent du Plan Construction, de 1978 à 1981, il devient successivement directeur adjoint de cabinet des ministres de lUrbanisme et du Logement Roger Quilliot et Paul Quilès puis directeur de la Construction au ministère de l’Équipement, du Logement, des Transports et de la Mer. En 1990, il est nommé directeur général de l’Établissement public daménagement de la Défense (epad), jusquen 1993 où il prend la présidence du cstb. Il quitte ces fonctions en 2008 pour rejoindre le Conseil général de lenvironnement et du développement durable où il assure la présidence de la section « risques, sécurité, sûreté ». En septembre 2009, il accède à la présidence de Qualibat et de l'association Europan France. \nEn outre, Alain Maugard est membre du conseil dadministration de lAdeme. Il a également piloté le Comité opérationnel (comop) du chantier n°1 « Bâtiments neufs publics et privés » du Grenelle de lEnvironnement. "
portrait: 'Alain Maugard_TROUVE.jpg' portrait: 'Alain Maugard.jpg'
debugger: true debugger: true
template: modular/personnes template: modular/personnes
media_order: 'photo_butlen.jpeg,aurelie-cousi-nommee-aux-fonctions-de-directrice.jpg,catherine-chevillot-nouvelle-presidente-de-cite.JPG,Alain Maugard_TROUVE.jpg' media_order: 'photo_butlen.jpeg,aurelie-cousi-nommee-aux-fonctions-de-directrice.jpg,catherine chevillot 274 (1).jpg,Alain Maugard.jpg'
--- ---
### Membres de l'assemblée générale du Groupement dintérêt public Europe des projets architecturaux et urbains ### Membres de l'assemblée générale de l'Europe des projets architecturaux et urbains
@@ -5,17 +5,17 @@ personnes:
- -
nom: 'Jean-Baptiste Marie' nom: 'Jean-Baptiste Marie'
fonction: 'Directeur général Intégrer la bio du conseil stratégique POPSU' fonction: 'Directeur général Intégrer la bio du conseil stratégique POPSU'
biographie: "Jean-Baptiste MARIE, architecte, docteur en architecture, diplômé de lEcole nationale supérieure darchitecture de Versailles et de lEcole Boulle. Il est directeur de la Plateforme d'observation des projets et stratégies urbaines pilotée par le Puca (Plan Urbanisme Construction Architecture) au Ministère de la Transition écologique et au Ministère \Lde la Cohésion des territoires et des Relations avec les collectivités territoriales, au sein du GIP Europe des projets architecturaux et urbains (EPAU).\r\nIl assurait auparavant, depuis 2008, le secrétariat scientifique de la plateforme européenne Popsu et depuis 2011 de la plateforme française. Il est par ailleurs Professeur des Écoles nationales supérieures d'architecture (Ensa) où il enseigne dans le champ Théories et pratiques de la conception architecturale et urbaine à l'Ensa de Clermont-Ferrand et y dirige l’équipe de recherche Ressources. Il a auparavant enseigné dans les Ensa de Normandie et de Versailles.\r\njean-baptiste.marie@developpement-durable.gouv.fr\r\n+\_33\_(1)\_40\_81\_24\_68\_\r\n+\_33\_(6)\_64\_52\_75\_57" biographie: "Jean-Baptiste MARIE, architecte, docteur en architecture, diplômé de lEcole nationale supérieure darchitecture de Versailles et de lEcole Boulle. Il est directeur de la Plateforme d'observation des projets et stratégies urbaines pilotée par le Puca (Plan Urbanisme Construction Architecture) au Ministère de la Transition écologique et au Ministère \Lde la Cohésion des territoires et des Relations avec les collectivités territoriales, au sein du GIP Europe des projets architecturaux et urbains (EPAU).\nIl assurait auparavant, depuis 2008, le secrétariat scientifique de la plateforme européenne Popsu et depuis 2011 de la plateforme française. Il est par ailleurs Professeur des Écoles nationales supérieures d'architecture (Ensa) où il enseigne dans le champ Théories et pratiques de la conception architecturale et urbaine à l'Ensa de Clermont-Ferrand et y dirige l’équipe de recherche Ressources. Il a auparavant enseigné dans les Ensa de Normandie et de Versailles.\njean-baptiste.marie@developpement-durable.gouv.fr\n+\_33\_(1)\_40\_81\_24\_68\_\n+\_33\_(6)\_64\_52\_75\_57"
portrait: jb_marie_crop.jpg portrait: jb_marie_crop.jpg
- -
nom: 'Fabienne Dran' nom: 'Fabienne Dran'
fonction: 'Assistante de direction' fonction: 'Assistante de direction'
biographie: "Fabienne.Dran@developpement-durable.gouv.fr \r\n+ 33 (0)1 40 81 93 27\r\n+33 (0)7 86 50 33 31" biographie: "Fabienne.Dran@developpement-durable.gouv.fr \n+ 33 (0)1 40 81 93 27\n+33 (0)7 86 50 33 31"
portrait: null portrait: null
- -
nom: 'Jérôme Candevan' nom: 'Jérôme Candevan'
fonction: 'Responsable du service financier et facturier de lEPAU, Agent comptable ENSA' fonction: 'Responsable du service financier et facturier de lEPAU, Agent comptable ENSA'
biographie: "jerome.candevan@paris-lavillette.archi.fr \r\n+33 (0)6 26 04 82 09\r\n" biographie: "jerome.candevan@paris-lavillette.archi.fr \n+33 (0)6 26 04 82 09\n"
portrait: null portrait: null
media_order: jb_marie_crop.jpg media_order: jb_marie_crop.jpg
--- ---
Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

@@ -5,24 +5,24 @@ personnes:
- -
nom: 'Isabelle Moulin' nom: 'Isabelle Moulin'
fonction: 'Secrétaire générale de lAssociation Europan France, Directrice du programme Europan ' fonction: 'Secrétaire générale de lAssociation Europan France, Directrice du programme Europan '
biographie: "Isabelle Moulin a travaillé avec des agences telles que\_Guy Naizot&Ass., Atelier Ruelle, Latitude Nord, Christian Devillers&Ass., en tant que cheffe de projet conception et réalisation d'espaces publics et de paysage. Elle a exercé la profession d'architecte libérale, pour la réalisation (réhabilitation /reconstruction/ aménagement) de petits équipements publics (maison des associations, halte-garderie, atelier de mécanique, projets d'aménagements paysagers) et de réalisations architecturales privées (maisons d'habitation, réhabilitations intérieures, Bureau de Presse). L'imbrication des échelles de projets, les différents types de gouvernance rencontrés, la multiple dimension à la fois urbaine, paysagère et architecturale des projets étudiés et réalisés, des relations avec un large réseau d'acteurs urbains et architecturaux, l'ont amenée à se présenter à\_la direction du concours Europan en 2012. Elle est actuellement secrétaire générale de l'association Europan France, et mise à disposition pour la direction du programme Europan auprès du GIP EPAU, l'association étant membre fondatrice de cette structure.\r\n\r\ni.moulin@europanfrance.org\r\n+33 (0)6 42 65 75 04\r\n+33 (0)1 48 57 72 66" biographie: "Isabelle Moulin a travaillé avec des agences telles que\_Guy Naizot&Ass., Atelier Ruelle, Latitude Nord, Christian Devillers&Ass., en tant que cheffe de projet conception et réalisation d'espaces publics et de paysage. Elle a exercé la profession d'architecte libérale, pour la réalisation (réhabilitation /reconstruction/ aménagement) de petits équipements publics (maison des associations, halte-garderie, atelier de mécanique, projets d'aménagements paysagers) et de réalisations architecturales privées (maisons d'habitation, réhabilitations intérieures, Bureau de Presse). L'imbrication des échelles de projets, les différents types de gouvernance rencontrés, la multiple dimension à la fois urbaine, paysagère et architecturale des projets étudiés et réalisés, des relations avec un large réseau d'acteurs urbains et architecturaux, l'ont amenée à se présenter à\_la direction du concours Europan en 2012. Elle est actuellement secrétaire générale de l'association Europan France, et mise à disposition pour la direction du programme Europan auprès du GIP EPAU, l'association étant membre fondatrice de cette structure.\n\ni.moulin@europanfrance.org\n+33 (0)6 42 65 75 04\n+33 (0)1 48 57 72 66"
portrait: 'Isabelle Moulin.jpg' portrait: 'Isabelle Moulin.jpg'
- -
nom: 'Louis Vitalis' nom: 'Louis Vitalis'
fonction: 'Chargé de missions' fonction: 'Chargé de missions'
biographie: " • Photo et bio demandées\r\nl.vitalis@europanfrance.org \r\n+33 (0)1 48 57 72 66" biographie: "Architecte formé à l'ENSA Paris Val de Seine, Docteur en architecture du Conservatoire National des Arts et Métiers et de l'UMR MAP (Modèles et simulations pour l'Architecture et le Patrimoine), Louis Vitalis est également enseignant-chercheur à l'ENSA Paris La Villette.\n\nl.vitalis@europanfrance.org \n+33 (0)1 48 57 72 66"
portrait: null portrait: 'Louis Vitalis.png'
- -
nom: 'Mimrose Akbar' nom: 'Mimrose Akbar'
fonction: 'Assistante de projets' fonction: 'Assistante de projets'
biographie: " • Photo et bio demandées\r\nm.akbar@europanfrance.org \r\n+33 (0)1 48 57 72 66" biographie: " \nm.akbar@europanfrance.org \n+33 (0)1 48 57 72 66"
portrait: null portrait: null
- -
nom: 'Mathilde Morize' nom: 'Mathilde Morize'
fonction: 'Chargée de projet ' fonction: 'Chargée de projet '
biographie: "m.morize@europanfrance.org \r\n+33 (0)1 48 57 72 66\r\n Photo et bio demandées" biographie: "m.morize@europanfrance.org \n+33 (0)1 48 57 72 66\n"
portrait: null portrait: null
media_order: 'Isabelle Moulin.jpg' media_order: 'Isabelle Moulin.jpg,Louis Vitalis.png'
--- ---
### Direction du programme Europan France ### Direction du programme Europan France
@@ -5,7 +5,7 @@ personnes:
- -
nom: 'Julien Moulard' nom: 'Julien Moulard'
fonction: 'Responsable de programme' fonction: 'Responsable de programme'
biographie: " Photo et bio demandées\r\njulien.moulard@popsu.archi.fr\r\n+ 33 (0)1 40 81 70 72\r\n+ 33 (0)7 86 50 43 17" biographie: "julien.moulard@popsu.archi.fr\n+ 33 (0)1 40 81 70 72\n+ 33 (0)7 86 50 43 17"
portrait: null portrait: null
--- ---
@@ -15,7 +15,6 @@ content:
- _equipe-epau - _equipe-epau
admin: admin:
children_display_order: collection children_display_order: collection
debugger: true debugger: false
--- ---
+3 -2
View File
@@ -1,8 +1,9 @@
--- ---
title: Contact title: Contact
body_classes: modular body_classes: modular
media_order: 'puca.png,logo cité archi.jpg,logo ministère culture.png,europan_france.jpg,logo_gouvernment.png,logo MCTRCT.png,logo min logement.png' media_order: 'logo_gouvernment.png,logo MCTRCT.png,logo min logement.png,logo ministère culture.png,europan_france.jpg,puca.png,logo cité archi.jpg'
published: true published: true
debugger: false
--- ---
![logo_gouvernment](logo_gouvernment.png "logo_gouvernment") ![logo%20MCTRCT](logo%20MCTRCT.png "logo%20MCTRCT") ![logo%20minist%C3%A8re%20culture](logo%20minist%C3%A8re%20culture.png "logo%20minist%C3%A8re%20culture") ![logo%20min%20logement](logo%20min%20logement.png "logo%20min%20logement") ![europan_france](europan_france.jpg "europan_france") ![puca](puca.png "puca") ![logo%20cit%C3%A9%20archi](logo%20cit%C3%A9%20archi.jpg "logo%20cit%C3%A9%20archi") ![logo_gouvernment](logo_gouvernment.png "logo_gouvernment")![logo%20MCTRCT](logo%20MCTRCT.png "logo%20MCTRCT")![logo%20minist%C3%A8re%20culture](logo%20minist%C3%A8re%20culture.png "logo%20minist%C3%A8re%20culture") ![logo%20min%20logement](logo%20min%20logement.png "logo%20min%20logement")![europan_france](europan_france.jpg "europan_france") ![puca](puca.png "puca")![logo%20cit%C3%A9%20archi](logo%20cit%C3%A9%20archi.jpg "logo%20cit%C3%A9%20archi")
+2
View File
@@ -0,0 +1,2 @@
.sass-cache
.DS_Store
+81 -1
View File
@@ -1,3 +1,83 @@
# v2.2.1
## 01/15/2021
1. [](#improved)
* Fixed autoescaping in preparation for Grav 1.7
1. [](#bugfix)
* Fix deprecated messages from macros [#140](https://github.com/getgrav/grav-theme-antimatter/issues/140)
# v2.2.0
## 03/21/2019
1. [](#new)
* Set Dependency of Grav 1.5.10+ which has support for new **Deferred Block** Twig extension
* Implement assets rendering using **Deferred Block** Twig extension
# v2.1.2
## 9/28/2017
1. [](#improved)
* Added polish and brazilian portuguese translations
* Allow overriding the slidebar by moving it to its own `sidebar_navigation` block [#110](https://github.com/getgrav/grav-theme-antimatter/pull/110)
1. [](#bugfix)
* Fix showcase template overlapping when not at top [#99](https://github.com/getgrav/grav-theme-antimatter/pull/99)
# v2.1.1
## 02/26/2017
1. [](#bugfix)
* Allow to add a `external` class to site.yaml links to work on modular pages [#95](https://github.com/getgrav/grav-theme-antimatter/pull/95)
# v2.1.0
## 01/24/2017
1. [](#new)
* Updated to FontAwesome 4.7.0 with [Grav icon](http://fontawesome.io/icon/grav/)
1. [](#improved)
* Added croatian
* Changed "SimpleSearch" string in the sidebar to "Search"
1. [](#bugfix)
* Removed unreachable condition [#85](https://github.com/getgrav/grav-theme-antimatter/pull/85)
* Fixed a typo in the french translation
# v2.0.0
## 07/14/2016
1. [](#new)
* Added microformats2 support [#64](https://github.com/getgrav/grav-theme-antimatter/pull/64)
1. [](#improved)
* Updated to FontAwesome 4.6.3
* Added romanian, russian and ukranian
# v2.0.0-beta.1
## 05/23/2016
1. [](#new)
* New and improved **dropdown** styling
1. [](#improved)
* Removed templates from `form` + `snipcart` plugins
* Added support for search button
* Updated some translations
* Automatically add comments if configured
* Relative path for favicon
* Slightly modified the blockquote background color
* Removed unneeded streams from YAML
* Use common language strings in Blueprint
# v1.8.0
## 11/20/2015
1. [](#new)
* Added logic to include site.menu items in modular pages
* Added a configurable lang field for HTML tag
* Added a `bottom` JS output call
1. [](#improved)
* Updated to FontAwesome 4.4.0
1. [](#bugfix)
* Fixed extra `/` in some tag URLs
* Better support for PECL Yaml parser
* Fixes for blog page blueprint
# v1.7.6 # v1.7.6
## 10/07/2015 ## 10/07/2015
@@ -46,7 +126,7 @@
1. [](#new) 1. [](#new)
* Blueprints that work with new admin plugin! * Blueprints that work with new admin plugin!
1. [](#bugfix) 1. [](#bugfix)
* Favicon with full image URL * Favicon with full image URL
# v1.6.1 # v1.6.1
## 07/24/2015 ## 07/24/2015
-7
View File
@@ -1,10 +1,3 @@
enabled: true enabled: true
dropdown: dropdown:
enabled: false enabled: false
streams:
schemes:
theme:
type: ReadOnlyStream
paths:
- user/themes/antimatter
+6 -3
View File
@@ -1,5 +1,5 @@
name: Antimatter name: Antimatter
version: 1.7.6 version: 2.2.1
description: "Antimatter is the default theme included with **Grav**" description: "Antimatter is the default theme included with **Grav**"
icon: empire icon: empire
author: author:
@@ -12,6 +12,9 @@ keywords: antimatter, theme, core, modern, fast, responsive, html5, css3
bugs: https://github.com/getgrav/grav-theme-antimatter/issues bugs: https://github.com/getgrav/grav-theme-antimatter/issues
license: MIT license: MIT
dependencies:
- { name: grav, version: '>=1.5.10' }
form: form:
validation: loose validation: loose
fields: fields:
@@ -21,7 +24,7 @@ form:
highlight: 1 highlight: 1
default: 1 default: 1
options: options:
1: Enabled 1: PLUGIN_ADMIN.ENABLED
0: Disabled 0: PLUGIN_ADMIN.DISABLED
validate: validate:
type: bool type: bool
@@ -26,9 +26,9 @@ form:
type: upload type: upload
label: Upload label: Upload
allow: allow:
@media.*.keys '@media.*.keys'
accept: accept:
@media.*.values '@media.*.values'
filename: filename:
type: text type: text
+20 -7
View File
@@ -1,5 +1,5 @@
title: Blog title: Blog
@extends: '@extends':
type: default type: default
context: blueprints://pages context: blueprints://pages
@@ -33,11 +33,10 @@ form:
fields: fields:
header.content.items: header.content.items:
type: select type: textarea
yaml: true
label: Items label: Items
default: @self.children default: '@self.children'
options:
@self.children: Children
header.content.limit: header.content.limit:
type: text type: text
@@ -72,5 +71,19 @@ form:
highlight: 1 highlight: 1
default: 1 default: 1
options: options:
1: Enabled 1: PLUGIN_ADMIN.ENABLED
0: Disabled 0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
header.content.url_taxonomy_filters:
type: toggle
label: URL Taxonomy Filters
highlight: 1
default: 1
options:
1: PLUGIN_ADMIN.ENABLED
0: PLUGIN_ADMIN.DISABLED
validate:
type: bool
+1 -1
View File
@@ -1,2 +1,2 @@
title: Nopad title: Nopad
@extends: default '@extends': default
+5 -5
View File
@@ -1,5 +1,5 @@
title: Item title: Item
@extends: '@extends':
type: default type: default
context: blueprints://pages context: blueprints://pages
@@ -26,8 +26,8 @@ form:
help: Enabled displaying of a header image help: Enabled displaying of a header image
highlight: 1 highlight: 1
options: options:
1: Enabled 1: PLUGIN_ADMIN.ENABLED
0: Disabled 0: PLUGIN_ADMIN.DISABLED
header.header_image_file: header.header_image_file:
type: text type: text
@@ -73,8 +73,8 @@ form:
label: Summary label: Summary
highlight: 1 highlight: 1
options: options:
1: Enabled 1: PLUGIN_ADMIN.ENABLED
0: Disabled 0: PLUGIN_ADMIN.DISABLED
header.summary.format: header.summary.format:
type: select type: select
@@ -1,5 +1,5 @@
title: Features title: Features
@extends: default '@extends': default
form: form:
fields: fields:
@@ -13,12 +13,12 @@ form:
fields: fields:
name: name:
default: modular/features default: modular/features
@data-options: '\Grav\Common\Page\Pages::modularTypes' '@data-options': '\Grav\Common\Page\Pages::modularTypes'
overrides: overrides:
fields: fields:
header.template: header.template:
default: modular/features default: modular/features
@data-options: '\Grav\Common\Page\Pages::modularTypes' '@data-options': '\Grav\Common\Page\Pages::modularTypes'
features: features:
type: tab type: tab
title: Features title: Features
@@ -1,5 +1,5 @@
title: Showcase title: Showcase
@extends: default '@extends': default
form: form:
fields: fields:
@@ -13,12 +13,12 @@ form:
fields: fields:
name: name:
default: modular/showcase default: modular/showcase
@data-options: '\Grav\Common\Page\Pages::modularTypes' '@data-options': '\Grav\Common\Page\Pages::modularTypes'
overrides: overrides:
fields: fields:
header.template: header.template:
default: modular/showcase default: modular/showcase
@data-options: '\Grav\Common\Page\Pages::modularTypes' '@data-options': '\Grav\Common\Page\Pages::modularTypes'
buttons: buttons:
type: tab type: tab
title: Buttons title: Buttons
@@ -38,8 +38,9 @@ form:
type: toggle type: toggle
label: Primary label: Primary
highlight: 1 highlight: 1
default: 1
options: options:
1: Yes 1: 'Yes'
0: No 0: 'No'
validate: validate:
type: bool type: bool
@@ -1,5 +1,5 @@
title: Text title: Text
@extends: default '@extends': default
form: form:
fields: fields:
@@ -13,12 +13,12 @@ form:
fields: fields:
name: name:
default: modular/text default: modular/text
@data-options: '\Grav\Common\Page\Pages::modularTypes' '@data-options': '\Grav\Common\Page\Pages::modularTypes'
overrides: overrides:
fields: fields:
header.template: header.template:
default: modular/text default: modular/text
@data-options: '\Grav\Common\Page\Pages::modularTypes' '@data-options': '\Grav\Common\Page\Pages::modularTypes'
content: content:
fields: fields:
uploads: uploads:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,98 +1,3 @@
.text-left { .text-left{text-align:left !important}.text-right{text-align:right !important}.text-center{text-align:center !important}.text-justify{text-align:justify !important}@media all and (min-width: 75em){.large-desktop-text-left{text-align:left !important}.large-desktop-text-right{text-align:right !important}.large-desktop-text-center{text-align:center !important}.large-desktop-text-justify{text-align:justify !important}}@media all and (min-width: 60em) and (max-width: 74.938em){.desktop-text-left{text-align:left !important}.desktop-text-right{text-align:right !important}.desktop-text-center{text-align:center !important}.desktop-text-justify{text-align:justify !important}}@media all and (min-width: 48em) and (max-width: 59.938em){.tablet-text-left{text-align:left !important}.tablet-text-right{text-align:right !important}.tablet-text-center{text-align:center !important}.tablet-text-justify{text-align:justify !important}}@media all and (min-width: 30.063em) and (max-width: 47.938em){.large-mobile-text-left{text-align:left !important}.large-mobile-text-right{text-align:right !important}.large-mobile-text-center{text-align:center !important}.large-mobile-text-justify{text-align:justify !important}}@media all and (max-width: 30em){.small-mobile-text-left{text-align:left !important}.small-mobile-text-right{text-align:right !important}.small-mobile-text-center{text-align:center !important}.small-mobile-text-justify{text-align:justify !important}}@media all and (min-width: 48em){.no-mobile-text-left{text-align:left !important}.no-mobile-text-right{text-align:right !important}.no-mobile-text-center{text-align:center !important}.no-mobile-text-justify{text-align:justify !important}}@media all and (max-width: 47.938em){.mobile-only-text-left{text-align:left !important}.mobile-only-text-right{text-align:right !important}.mobile-only-text-center{text-align:center !important}.mobile-only-text-justify{text-align:justify !important}}
text-align: left !important; }
.text-right { /*# sourceMappingURL=particles.css.map */
text-align: right !important; }
.text-center {
text-align: center !important; }
.text-justify {
text-align: justify !important; }
@media all and (min-width: 75em) {
.large-desktop-text-left {
text-align: left !important; }
.large-desktop-text-right {
text-align: right !important; }
.large-desktop-text-center {
text-align: center !important; }
.large-desktop-text-justify {
text-align: justify !important; } }
@media all and (min-width: 60em) and (max-width: 74.938em) {
.desktop-text-left {
text-align: left !important; }
.desktop-text-right {
text-align: right !important; }
.desktop-text-center {
text-align: center !important; }
.desktop-text-justify {
text-align: justify !important; } }
@media all and (min-width: 48em) and (max-width: 59.938em) {
.tablet-text-left {
text-align: left !important; }
.tablet-text-right {
text-align: right !important; }
.tablet-text-center {
text-align: center !important; }
.tablet-text-justify {
text-align: justify !important; } }
@media all and (min-width: 30.063em) and (max-width: 47.938em) {
.large-mobile-text-left {
text-align: left !important; }
.large-mobile-text-right {
text-align: right !important; }
.large-mobile-text-center {
text-align: center !important; }
.large-mobile-text-justify {
text-align: justify !important; } }
@media all and (max-width: 30em) {
.small-mobile-text-left {
text-align: left !important; }
.small-mobile-text-right {
text-align: right !important; }
.small-mobile-text-center {
text-align: center !important; }
.small-mobile-text-justify {
text-align: justify !important; } }
@media all and (min-width: 48em) {
.no-mobile-text-left {
text-align: left !important; }
.no-mobile-text-right {
text-align: right !important; }
.no-mobile-text-center {
text-align: center !important; }
.no-mobile-text-justify {
text-align: justify !important; } }
@media all and (max-width: 47.938em) {
.mobile-only-text-left {
text-align: left !important; }
.mobile-only-text-right {
text-align: right !important; }
.mobile-only-text-center {
text-align: center !important; }
.mobile-only-text-justify {
text-align: justify !important; } }
/*# sourceMappingURL=particles.css.map */
@@ -1,7 +1,95 @@
{ {
"version": 3, "version": 3,
"mappings": "AAsBC,UAAW;EACV,UAAU,EAAE,eAAe;;AAE5B,WAAY;EACX,UAAU,EAAE,gBAAgB;;AAE7B,YAAa;EACZ,UAAU,EAAE,iBAAiB;;AAE9B,aAAc;EACb,UAAU,EAAE,kBAAkB;;AAI9B,gCAA8C;EAC7C,wBAA4C;IAAE,UAAU,EAAE,eAAe;;EACzE,yBAA+C;IAAE,UAAU,EAAE,gBAAgB;;EAC7E,0BAA+C;IAAE,UAAU,EAAE,iBAAiB;;EAC9E,2BAA+C;IAAE,UAAU,EAAE,kBAAkB;AAJhF,0DAA8C;EAC7C,kBAA4C;IAAE,UAAU,EAAE,eAAe;;EACzE,mBAA+C;IAAE,UAAU,EAAE,gBAAgB;;EAC7E,oBAA+C;IAAE,UAAU,EAAE,iBAAiB;;EAC9E,qBAA+C;IAAE,UAAU,EAAE,kBAAkB;AAJhF,0DAA8C;EAC7C,iBAA4C;IAAE,UAAU,EAAE,eAAe;;EACzE,kBAA+C;IAAE,UAAU,EAAE,gBAAgB;;EAC7E,mBAA+C;IAAE,UAAU,EAAE,iBAAiB;;EAC9E,oBAA+C;IAAE,UAAU,EAAE,kBAAkB;AAJhF,8DAA8C;EAC7C,uBAA4C;IAAE,UAAU,EAAE,eAAe;;EACzE,wBAA+C;IAAE,UAAU,EAAE,gBAAgB;;EAC7E,yBAA+C;IAAE,UAAU,EAAE,iBAAiB;;EAC9E,0BAA+C;IAAE,UAAU,EAAE,kBAAkB;AAJhF,gCAA8C;EAC7C,uBAA4C;IAAE,UAAU,EAAE,eAAe;;EACzE,wBAA+C;IAAE,UAAU,EAAE,gBAAgB;;EAC7E,yBAA+C;IAAE,UAAU,EAAE,iBAAiB;;EAC9E,0BAA+C;IAAE,UAAU,EAAE,kBAAkB;AAJhF,gCAA8C;EAC7C,oBAA4C;IAAE,UAAU,EAAE,eAAe;;EACzE,qBAA+C;IAAE,UAAU,EAAE,gBAAgB;;EAC7E,sBAA+C;IAAE,UAAU,EAAE,iBAAiB;;EAC9E,uBAA+C;IAAE,UAAU,EAAE,kBAAkB;AAJhF,oCAA8C;EAC7C,sBAA4C;IAAE,UAAU,EAAE,eAAe;;EACzE,uBAA+C;IAAE,UAAU,EAAE,gBAAgB;;EAC7E,wBAA+C;IAAE,UAAU,EAAE,iBAAiB;;EAC9E,yBAA+C;IAAE,UAAU,EAAE,kBAAkB", "file": "particles.css",
"sources": ["../scss/nucleus/particles/_align-text.scss"], "sources": [
"names": [], "../scss/particles.scss",
"file": "particles.css" "../scss/vendor/bourbon/_bourbon.scss",
"../scss/vendor/bourbon/settings/_prefixer.scss",
"../scss/vendor/bourbon/settings/_px-to-em.scss",
"../scss/vendor/bourbon/helpers/_convert-units.scss",
"../scss/vendor/bourbon/helpers/_gradient-positions-parser.scss",
"../scss/vendor/bourbon/helpers/_is-num.scss",
"../scss/vendor/bourbon/helpers/_linear-angle-parser.scss",
"../scss/vendor/bourbon/helpers/_linear-gradient-parser.scss",
"../scss/vendor/bourbon/helpers/_linear-positions-parser.scss",
"../scss/vendor/bourbon/helpers/_linear-side-corner-parser.scss",
"../scss/vendor/bourbon/helpers/_radial-arg-parser.scss",
"../scss/vendor/bourbon/helpers/_radial-positions-parser.scss",
"../scss/vendor/bourbon/helpers/_radial-gradient-parser.scss",
"../scss/vendor/bourbon/helpers/_render-gradients.scss",
"../scss/vendor/bourbon/helpers/_shape-size-stripper.scss",
"../scss/vendor/bourbon/helpers/_str-to-num.scss",
"../scss/vendor/bourbon/functions/_assign.scss",
"../scss/vendor/bourbon/functions/_color-lightness.scss",
"../scss/vendor/bourbon/functions/_flex-grid.scss",
"../scss/vendor/bourbon/functions/_golden-ratio.scss",
"../scss/vendor/bourbon/functions/_grid-width.scss",
"../scss/vendor/bourbon/functions/_modular-scale.scss",
"../scss/vendor/bourbon/functions/_px-to-em.scss",
"../scss/vendor/bourbon/functions/_px-to-rem.scss",
"../scss/vendor/bourbon/functions/_strip-units.scss",
"../scss/vendor/bourbon/functions/_tint-shade.scss",
"../scss/vendor/bourbon/functions/_transition-property-name.scss",
"../scss/vendor/bourbon/functions/_unpack.scss",
"../scss/vendor/bourbon/css3/_animation.scss",
"../scss/vendor/bourbon/css3/_appearance.scss",
"../scss/vendor/bourbon/css3/_backface-visibility.scss",
"../scss/vendor/bourbon/css3/_background.scss",
"../scss/vendor/bourbon/css3/_background-image.scss",
"../scss/vendor/bourbon/css3/_border-image.scss",
"../scss/vendor/bourbon/css3/_border-radius.scss",
"../scss/vendor/bourbon/css3/_box-sizing.scss",
"../scss/vendor/bourbon/css3/_calc.scss",
"../scss/vendor/bourbon/css3/_columns.scss",
"../scss/vendor/bourbon/css3/_filter.scss",
"../scss/vendor/bourbon/css3/_flex-box.scss",
"../scss/vendor/bourbon/css3/_font-face.scss",
"../scss/vendor/bourbon/css3/_hyphens.scss",
"../scss/vendor/bourbon/css3/_hidpi-media-query.scss",
"../scss/vendor/bourbon/css3/_image-rendering.scss",
"../scss/vendor/bourbon/css3/_keyframes.scss",
"../scss/vendor/bourbon/css3/_linear-gradient.scss",
"../scss/vendor/bourbon/css3/_perspective.scss",
"../scss/vendor/bourbon/css3/_radial-gradient.scss",
"../scss/vendor/bourbon/css3/_transform.scss",
"../scss/vendor/bourbon/css3/_transition.scss",
"../scss/vendor/bourbon/css3/_user-select.scss",
"../scss/vendor/bourbon/css3/_placeholder.scss",
"../scss/vendor/bourbon/addons/_button.scss",
"../scss/vendor/bourbon/addons/_clearfix.scss",
"../scss/vendor/bourbon/addons/_directional-values.scss",
"../scss/vendor/bourbon/addons/_ellipsis.scss",
"../scss/vendor/bourbon/addons/_font-family.scss",
"../scss/vendor/bourbon/addons/_hide-text.scss",
"../scss/vendor/bourbon/addons/_html5-input-types.scss",
"../scss/vendor/bourbon/addons/_position.scss",
"../scss/vendor/bourbon/addons/_prefixer.scss",
"../scss/vendor/bourbon/addons/_retina-image.scss",
"../scss/vendor/bourbon/addons/_size.scss",
"../scss/vendor/bourbon/addons/_timing-functions.scss",
"../scss/vendor/bourbon/addons/_triangle.scss",
"../scss/vendor/bourbon/addons/_word-wrap.scss",
"../scss/vendor/bourbon/_bourbon-deprecated-upcoming.scss",
"../scss/configuration/nucleus/_base.scss",
"../scss/configuration/nucleus/_core.scss",
"../scss/configuration/nucleus/_breakpoints.scss",
"../scss/configuration/nucleus/_layout.scss",
"../scss/configuration/nucleus/_typography.scss",
"../scss/configuration/nucleus/_nav.scss",
"../scss/configuration/template/_base.scss",
"../scss/configuration/template/_colors.scss",
"../scss/configuration/template/_typography.scss",
"../scss/configuration/template/_bullets.scss",
"../scss/configuration/template/_variables.scss",
"../scss/nucleus/functions/_base.scss",
"../scss/nucleus/functions/_direction.scss",
"../scss/nucleus/functions/_range.scss",
"../scss/nucleus/mixins/_base.scss",
"../scss/nucleus/mixins/_breakpoints.scss",
"../scss/nucleus/mixins/_utilities.scss",
"../scss/nucleus/particles/_align-text.scss",
"../scss/nucleus/particles/_visibility.scss"
],
"mappings": "AqFsBC,AAAA,UAAU,AAAC,CACV,UAAU,CAAE,eAAgB,CAC5B,AACD,AAAA,WAAW,AAAC,CACX,UAAU,CAAE,gBAAiB,CAC7B,AACD,AAAA,YAAY,AAAC,CACZ,UAAU,CAAE,iBAAkB,CAC9B,AACD,AAAA,aAAa,AAAC,CACb,UAAU,CAAE,kBAAmB,CAC/B,AAGA,MAAM,CAAN,GAAG,MAAM,SAAS,EAAC,IAAI,EACtB,AAAA,wBAAwB,AAAxB,CAAE,UAAU,CAAE,eAAgB,CAAI,AAClC,AAAA,yBAAyB,AAAzB,CAAE,UAAU,CAAE,gBAAiB,CAAI,AACnC,AAAA,0BAA0B,AAA1B,CAAE,UAAU,CAAE,iBAAkB,CAAI,AACpC,AAAA,2BAA2B,AAA3B,CAAE,UAAU,CAAE,kBAAmB,CAAI,CAJtC,MAAM,CAAN,GAAG,MAAM,SAAS,EAAC,IAAI,OAAO,SAAS,EAAC,QAAQ,EAC/C,AAAA,kBAAkB,AAAlB,CAAE,UAAU,CAAE,eAAgB,CAAI,AAClC,AAAA,mBAAmB,AAAnB,CAAE,UAAU,CAAE,gBAAiB,CAAI,AACnC,AAAA,oBAAoB,AAApB,CAAE,UAAU,CAAE,iBAAkB,CAAI,AACpC,AAAA,qBAAqB,AAArB,CAAE,UAAU,CAAE,kBAAmB,CAAI,CAJtC,MAAM,CAAN,GAAG,MAAM,SAAS,EAAC,IAAI,OAAO,SAAS,EAAC,QAAQ,EAC/C,AAAA,iBAAiB,AAAjB,CAAE,UAAU,CAAE,eAAgB,CAAI,AAClC,AAAA,kBAAkB,AAAlB,CAAE,UAAU,CAAE,gBAAiB,CAAI,AACnC,AAAA,mBAAmB,AAAnB,CAAE,UAAU,CAAE,iBAAkB,CAAI,AACpC,AAAA,oBAAoB,AAApB,CAAE,UAAU,CAAE,kBAAmB,CAAI,CAJtC,MAAM,CAAN,GAAG,MAAM,SAAS,EAAC,QAAQ,OAAO,SAAS,EAAC,QAAQ,EACnD,AAAA,uBAAuB,AAAvB,CAAE,UAAU,CAAE,eAAgB,CAAI,AAClC,AAAA,wBAAwB,AAAxB,CAAE,UAAU,CAAE,gBAAiB,CAAI,AACnC,AAAA,yBAAyB,AAAzB,CAAE,UAAU,CAAE,iBAAkB,CAAI,AACpC,AAAA,0BAA0B,AAA1B,CAAE,UAAU,CAAE,kBAAmB,CAAI,CAJtC,MAAM,CAAN,GAAG,MAAM,SAAS,EAAC,IAAI,EACtB,AAAA,uBAAuB,AAAvB,CAAE,UAAU,CAAE,eAAgB,CAAI,AAClC,AAAA,wBAAwB,AAAxB,CAAE,UAAU,CAAE,gBAAiB,CAAI,AACnC,AAAA,yBAAyB,AAAzB,CAAE,UAAU,CAAE,iBAAkB,CAAI,AACpC,AAAA,0BAA0B,AAA1B,CAAE,UAAU,CAAE,kBAAmB,CAAI,CAJtC,MAAM,CAAN,GAAG,MAAM,SAAS,EAAC,IAAI,EACtB,AAAA,oBAAoB,AAApB,CAAE,UAAU,CAAE,eAAgB,CAAI,AAClC,AAAA,qBAAqB,AAArB,CAAE,UAAU,CAAE,gBAAiB,CAAI,AACnC,AAAA,sBAAsB,AAAtB,CAAE,UAAU,CAAE,iBAAkB,CAAI,AACpC,AAAA,uBAAuB,AAAvB,CAAE,UAAU,CAAE,kBAAmB,CAAI,CAJtC,MAAM,CAAN,GAAG,MAAM,SAAS,EAAC,QAAQ,EAC1B,AAAA,sBAAsB,AAAtB,CAAE,UAAU,CAAE,eAAgB,CAAI,AAClC,AAAA,uBAAuB,AAAvB,CAAE,UAAU,CAAE,gBAAiB,CAAI,AACnC,AAAA,wBAAwB,AAAxB,CAAE,UAAU,CAAE,iBAAkB,CAAI,AACpC,AAAA,yBAAyB,AAAzB,CAAE,UAAU,CAAE,kBAAmB,CAAI",
"names": []
} }
@@ -1,5 +1,5 @@
@import url(//fonts.googleapis.com/css?family=Montserrat:400|Raleway:300,400,600|Inconsolata); @import url(//fonts.googleapis.com/css?family=Montserrat:400|Raleway:300,400,600|Inconsolata);
#header #logo h3, #header #navbar ul.navigation, #header #navbar .panel-activation, #footer p { #header #logo h3, #header #navbar .panel-activation, #footer p {
position: relative; position: relative;
top: 50%; top: 50%;
-webkit-transform: translateY(-50%); -webkit-transform: translateY(-50%);
@@ -51,7 +51,7 @@ b, strong, label, th {
.right { .right {
float: right; } float: right; }
.default-animation, #body, #header, #header #logo h3, .modular .showcase .button { .default-animation, #body, #header, #header #logo h3, #header #navbar ul.navigation, .modular .showcase .button {
-webkit-transition: all 0.5s ease; -webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease; -moz-transition: all 0.5s ease;
transition: all 0.5s ease; } transition: all 0.5s ease; }
@@ -94,6 +94,8 @@ b, strong, label, th {
color: #0e6e90 !important; } color: #0e6e90 !important; }
#header.scrolled #navbar a:before, #header.scrolled #navbar a:after { #header.scrolled #navbar a:before, #header.scrolled #navbar a:after {
background-color: #1BB3E9 !important; } background-color: #1BB3E9 !important; }
#header.scrolled .navigation {
margin-top: 0.5rem !important; }
#header > .grid, #header #logo, #header #navbar { #header > .grid, #header #logo, #header #navbar {
height: 100%; } height: 100%; }
#header #logo { #header #logo {
@@ -106,21 +108,49 @@ b, strong, label, th {
#header #logo h3 a { #header #logo h3 a {
color: #444; } color: #444; }
#header #navbar { #header #navbar {
font-size: 0.9rem; } font-size: 0.9rem;
/* Child Indicator */ }
#header #navbar .has-children > a > span {
display: inline-block;
padding-right: 8px; }
#header #navbar .has-children > a > span:after {
font-family: FontAwesome;
content: '\f107';
position: absolute;
display: inline-block;
right: 8px;
top: 4px; }
#header #navbar .has-children > a:after, #header #navbar .has-children > a:before {
display: none; }
#header #navbar .has-children .has-children > a > span:after {
content: '\f105'; }
#header #navbar .navigation > .has-children:hover > a {
background: #f6f6f6;
border: 1px solid #ececec;
border-bottom-color: #f6f6f6;
margin: -1px -1px 0 -1px;
z-index: 1000;
position: relative;
padding-bottom: 1px; }
#header #navbar ul { #header #navbar ul {
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style: none; } list-style: none; }
#header #navbar ul.navigation { #header #navbar ul.navigation {
display: inline-block; display: inline-block;
float: right; } float: right;
margin-top: 1.4rem; }
#header #navbar ul.navigation li { #header #navbar ul.navigation li {
float: left; float: left;
position: relative; } position: relative;
/*Active dropdown nav item */
/* Dropdown CSS */
/* Active on Hover */ }
#header #navbar ul.navigation li a { #header #navbar ul.navigation li a {
font-family: "Montserrat", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif; font-family: "Montserrat", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
display: inline-block; display: inline-block;
padding: 0.3rem 0.8rem; } padding: 0.3rem 0.8rem;
-webkit-backface-visibility: hidden; }
#header #navbar ul.navigation li a:before, #header #navbar ul.navigation li a:after { #header #navbar ul.navigation li a:before, #header #navbar ul.navigation li a:after {
content: ""; content: "";
position: absolute; position: absolute;
@@ -162,29 +192,35 @@ b, strong, label, th {
-o-transform: scaleX(0.75); -o-transform: scaleX(0.75);
transform: scaleX(0.75); } transform: scaleX(0.75); }
#header #navbar ul.navigation li ul { #header #navbar ul.navigation li ul {
display: none; position: absolute;
padding: 0; background-color: #f6f6f6;
box-shadow: 0 0.05rem 1rem rgba(0, 0, 0, 0.15) !important; } border: 1px solid #ececec;
border-top: 0;
min-width: 12rem;
text-align: left;
z-index: 999;
left: -1px;
display: none; }
#header #navbar ul.navigation li ul li {
display: block;
float: none;
/* Active Dropdown nav item */ }
#header #navbar ul.navigation li ul li.active > a {
background-color: #ececec;
color: #1BB3E9; }
#header #navbar ul.navigation li ul li:hover > a {
background-color: #1BB3E9;
color: #fff; }
#header #navbar ul.navigation li ul li a {
display: block;
margin: 0 -1px; }
#header #navbar ul.navigation li ul li a:after, #header #navbar ul.navigation li ul li a:before {
display: none; }
#header #navbar ul.navigation li ul ul { #header #navbar ul.navigation li ul ul {
left: 100%; left: 100%;
top: 0; } top: 0px; }
#header #navbar ul.navigation li:hover > ul { #header #navbar ul.navigation li:hover > ul {
display: block; display: block; }
position: absolute;
background: rgba(255, 255, 255, 0.9);
width: 10rem; }
#header #navbar ul.navigation li:hover li {
float: none;
margin: 0;
padding: 0; }
#header #navbar ul.navigation li:hover li a {
padding: 0.5rem 0.8rem;
display: block; }
#header #navbar ul.navigation li:hover li a:before, #header #navbar ul.navigation li:hover li a:after {
display: none; }
#header #navbar ul.navigation li:hover li.active > a {
background: #1BB3E9;
color: #fff; }
@media only all and (max-width: 59.938em) { @media only all and (max-width: 59.938em) {
#header #navbar ul.navigation { #header #navbar ul.navigation {
display: none; } } display: none; } }
@@ -214,16 +250,14 @@ b, strong, label, th {
.header-image #header { .header-image #header {
background-color: rgba(255, 255, 255, 0); background-color: rgba(255, 255, 255, 0);
box-shadow: none; } box-shadow: none; }
.header-image #header .navigation .has-children:hover a {
color: #1BB3E9; }
.header-image #header #logo h3, .header-image #header #logo a { .header-image #header #logo h3, .header-image #header #logo a {
color: #FFFFFF; } color: #FFFFFF; }
.header-image #header a, .header-image #header .menu-btn { .header-image #header a, .header-image #header .menu-btn {
color: #FFFFFF; } color: #FFFFFF; }
.header-image #header a:before, .header-image #header a:after { .header-image #header a:before, .header-image #header a:after {
background-color: rgba(255, 255, 255, 0.7) !important; } background-color: rgba(255, 255, 255, 0.7) !important; }
.header-image #header #navbar ul.navigation ul li a {
color: #1BB3E9; }
.header-image #header #navbar ul.navigation ul li a:hover {
color: #0e6e90; }
#footer { #footer {
position: absolute; position: absolute;
@@ -357,21 +391,37 @@ blockquote > blockquote > blockquote {
border-left: 10px solid #F0AD4E; border-left: 10px solid #F0AD4E;
background: #FCF8F2; background: #FCF8F2;
color: #df8a13; } color: #df8a13; }
blockquote > blockquote > blockquote > p a {
color: #b06d0f; }
blockquote > blockquote > blockquote > p a:hover {
color: #f2b866; }
blockquote > blockquote > blockquote > blockquote > p { blockquote > blockquote > blockquote > blockquote > p {
margin-left: -94px; margin-left: -94px;
border-left: 10px solid #D9534F; border-left: 10px solid #D9534F;
background: #FDF7F7; background: #FDF7F7;
color: #b52b27; } color: #b52b27; }
blockquote > blockquote > blockquote > blockquote > p a {
color: #8b211e; }
blockquote > blockquote > blockquote > blockquote > p a:hover {
color: #de6764; }
blockquote > blockquote > blockquote > blockquote > blockquote > p { blockquote > blockquote > blockquote > blockquote > blockquote > p {
margin-left: -118px; margin-left: -118px;
border-left: 10px solid #5BC0DE; border-left: 10px solid #5BC0DE;
background: #F4F8FA; background: #F4F8FA;
color: #28a1c5; } color: #28a1c5; }
blockquote > blockquote > blockquote > blockquote > blockquote > p a {
color: #1f7e9a; }
blockquote > blockquote > blockquote > blockquote > blockquote > p a:hover {
color: #70c8e2; }
blockquote > blockquote > blockquote > blockquote > blockquote > blockquote > p { blockquote > blockquote > blockquote > blockquote > blockquote > blockquote > p {
margin-left: -142px; margin-left: -142px;
border-left: 10px solid #5CB85C; border-left: 10px solid #5CB85C;
background: #F1F9F1; background: #F1F9F1;
color: #3d8b3d; } color: #3d8b3d; }
blockquote > blockquote > blockquote > blockquote > blockquote > blockquote > p a {
color: #2d672d; }
blockquote > blockquote > blockquote > blockquote > blockquote > blockquote > p a:hover {
color: #6ec06e; }
code, code,
kbd, kbd,
@@ -385,7 +435,7 @@ code {
pre { pre {
padding: 2rem; padding: 2rem;
background: #f6f6f6; background: #f0f0f0;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 3px; } border-radius: 3px; }
pre code { pre code {
@@ -713,6 +763,11 @@ ul.pagination {
@media only all and (max-width: 47.938em) { @media only all and (max-width: 47.938em) {
.simplesearch .search-item { .simplesearch .search-item {
margin-left: 0; } } margin-left: 0; } }
.simplesearch .search-wrapper .search-submit {
height: 52px;
padding: 0 10px; }
.simplesearch .search-wrapper .search-submit img {
width: 30px; }
.simplesearch .search-details { .simplesearch .search-details {
float: right; float: right;
margin-top: -2.5rem; margin-top: -2.5rem;
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 248 KiB

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.
+15
View File
@@ -0,0 +1,15 @@
{
"project":"grav-theme-antimatter",
"platforms":{
"grav":{
"nodes":{
"theme":[
{
"source":"/",
"destination":"/user/themes/antimatter"
}
]
}
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

+294 -1
View File
@@ -1,2 +1,295 @@
en: en:
TRANSLATION_TEST: Antimatter! TRANSLATION_TEST: Antimatter!
BLOG:
ITEM:
CONTINUE_READING: Continue reading...
NEXT_POST: Next Post
PREV_POST: Previous Post
SIDEBAR:
SIMPLE_SEARCH:
HEADLINE: Search
RELATED_POSTS:
HEADLINE: Related Posts
RANDOM_ARTICLE:
HEADLINE: Random Article
FEELING_LUCKY: I'm Feeling Lucky!
SOME_TEXT_WIDGET:
HEADLINE: Some Text Widget
POPULAR_TAGS:
HEADLINE: Popular Tags
ARCHIVES:
HEADLINE: Archives
SYNDICATE:
HEADLINE: Syndicate
FORM_DATA:
SUMMARY: "Here is the summary of what you wrote to us:"
ERROR: Error
de:
TRANSLATION_TEST: Antimatter!
BLOG:
ITEM:
CONTINUE_READING: Weiterlesen...
NEXT_POST: Nächster Beitrag
PREV_POST: Vorheriger Beitrag
SIDEBAR:
SIMPLE_SEARCH:
HEADLINE: SimpleSearch
RELATED_POSTS:
HEADLINE: Ähnliche Beiträge
RANDOM_ARTICLE:
HEADLINE: Zufälliger Artikel
FEELING_LUCKY: Auf gut Glück!
SOME_TEXT_WIDGET:
HEADLINE: Text Widget Beispiel
POPULAR_TAGS:
HEADLINE: Häufigste Tags
ARCHIVES:
HEADLINE: Archiv
SYNDICATE:
HEADLINE: Abonnements
FORM_DATA:
SUMMARY: "Folgendes haben Sie uns mitgeteilt:"
ERROR: Fehler
es:
TRANSLATION_TEST: Antimatter!
BLOG:
ITEM:
CONTINUE_READING: Continuar leyendo...
NEXT_POST: Siguiente Entrada
PREV_POST: Entrada Anterior
SIDEBAR:
SIMPLE_SEARCH:
HEADLINE: Buscar
RELATED_POSTS:
HEADLINE: Entradas Relacionadas
RANDOM_ARTICLE:
HEADLINE: Artículo Aleatorio
FEELING_LUCKY: Voy a tener suerte!
SOME_TEXT_WIDGET:
HEADLINE: Algunos Widget de Texto
POPULAR_TAGS:
HEADLINE: Etiquetas Populares
ARCHIVES:
HEADLINE: Archivos
SYNDICATE:
HEADLINE: Distribuir
FORM_DATA:
SUMMARY: "Este es un resumen de lo escrito:"
ERROR: Error
fr:
TRANSLATION_TEST: Antimatter !
BLOG:
ITEM:
CONTINUE_READING: Continuer la lecture...
NEXT_POST: Article suivant
PREV_POST: Article précédent
SIDEBAR:
SIMPLE_SEARCH:
HEADLINE: Recherche simple
RELATED_POSTS:
HEADLINE: Articles en relation
RANDOM_ARTICLE:
HEADLINE: Article aléatoire
FEELING_LUCKY: Jai de la chance !
SOME_TEXT_WIDGET:
HEADLINE: Du texte gadget
POPULAR_TAGS:
HEADLINE: Tags populaires
ARCHIVES:
HEADLINE: Archives
SYNDICATE:
HEADLINE: Syndication
FORM_DATA:
SUMMARY: "Voici le résumé de ce que vous avez écrit pour nous :"
ERROR: Erreur
it:
TRANSLATION_TEST: Antimatter!
BLOG:
ITEM:
CONTINUE_READING: Continua a leggere...
NEXT_POST: Prossimo articolo
PREV_POST: Articolo precedente
SIDEBAR:
SIMPLE_SEARCH:
HEADLINE: SimpleSearch
RELATED_POSTS:
HEADLINE: Articoli correlati
RANDOM_ARTICLE:
HEADLINE: Articolo a caso
FEELING_LUCKY: Mi sento fortunato!
SOME_TEXT_WIDGET:
HEADLINE: Widget di testo
POPULAR_TAGS:
HEADLINE: Tag popolari
ARCHIVES:
HEADLINE: Archivio
SYNDICATE:
HEADLINE: Feed
FORM_DATA:
SUMMARY: "Questo è il riassunto di quanto ci hai scritto:"
ERROR: Errore
ro:
BLOG:
ITEM:
CONTINUE_READING: Mai multe...
NEXT_POST: Următorul articol
PREV_POST: Articolul anterior
SIDEBAR:
SIMPLE_SEARCH:
HEADLINE: Căutare
RELATED_POSTS:
HEADLINE: Articole corelate
RANDOM_ARTICLE:
HEADLINE: Articol aleator
FEELING_LUCKY: Mă simt norocos
SOME_TEXT_WIDGET:
HEADLINE: Text modular
POPULAR_TAGS:
HEADLINE: Etichete populare
ARCHIVES:
HEADLINE: Arhive
SYNDICATE:
HEADLINE: Abonați-vă
FORM_DATA:
SUMMARY: "Acesta este rezumatul mesajului Dvs:"
ERROR: Eroare
ru:
TRANSLATION_TEST: Antimatter!
BLOG:
ITEM:
CONTINUE_READING: Читать далее...
NEXT_POST: Следующая запись
PREV_POST: Предыдущая запись
SIDEBAR:
SIMPLE_SEARCH:
HEADLINE: Поиск
RELATED_POSTS:
HEADLINE: Также читайте
RANDOM_ARTICLE:
HEADLINE: Случайная запись
FEELING_LUCKY: Мне повезёт!
SOME_TEXT_WIDGET:
HEADLINE: Текстовой виджет
POPULAR_TAGS:
HEADLINE: Популярные теги
ARCHIVES:
HEADLINE: Архив
SYNDICATE:
HEADLINE: Синдикация
FORM_DATA:
SUMMARY: "Вы написали нам:"
ERROR: Ошибка
uk:
TRANSLATION_TEST: Antimatter!
BLOG:
ITEM:
CONTINUE_READING: Читати далі...
NEXT_POST: Наступний запис
PREV_POST: Попередній запис
SIDEBAR:
SIMPLE_SEARCH:
HEADLINE: Пошук
RELATED_POSTS:
HEADLINE: Також читайте
RANDOM_ARTICLE:
HEADLINE: Випадковий запис
FEELING_LUCKY: Мені пощастить!
SOME_TEXT_WIDGET:
HEADLINE: Текстовий віджет
POPULAR_TAGS:
HEADLINE: Популярні теги
ARCHIVES:
HEADLINE: Архів
SYNDICATE:
HEADLINE: Синдикація
FORM_DATA:
SUMMARY: "Ви написали нам:"
ERROR: Помилка
hr:
TRANSLATION_TEST: Antimatter!
BLOG:
ITEM:
CONTINUE_READING: Nastavi s čitanjem...
NEXT_POST: Slijedeća objava
PREV_POST: Prethodna objava
SIDEBAR:
SIMPLE_SEARCH:
HEADLINE: Pretraživanje
RELATED_POSTS:
HEADLINE: Povezane objave
RANDOM_ARTICLE:
HEADLINE: Slučajni članak
FEELING_LUCKY: Osjećam se sretno!
SOME_TEXT_WIDGET:
HEADLINE: Neki tekst widget
POPULAR_TAGS:
HEADLINE: Popularni tagovi
ARCHIVES:
HEADLINE: Arhiva
SYNDICATE:
HEADLINE: Kanali
FORM_DATA:
SUMMARY: "Ovo je sažetak onog što ste nam napisali:"
ERROR: Greška
pl:
TRANSLATION_TEST: Antimatter!
BLOG:
ITEM:
CONTINUE_READING: Czytaj dalej...
NEXT_POST: Następny wpis
PREV_POST: Poprzedni wpis
SIDEBAR:
SIMPLE_SEARCH:
HEADLINE: Szukaj
RELATED_POSTS:
HEADLINE: Powiązane wpisy
RANDOM_ARTICLE:
HEADLINE: Losowy wpis
FEELING_LUCKY: Szczęśliwy traf!
SOME_TEXT_WIDGET:
HEADLINE: Jakiś tekst - widget
POPULAR_TAGS:
HEADLINE: Popularne tagi
ARCHIVES:
HEADLINE: Archiwum
SYNDICATE:
HEADLINE: Feed
FORM_DATA:
SUMMARY: "Podsumowanie tego co do nas napisałeś:"
ERROR: Błąd
pt-BR:
TRANSLATION_TEST: Antimatter!
BLOG:
ITEM:
CONTINUE_READING: Continue lendo...
NEXT_POST: Próximo Post
PREV_POST: Post anterior
SIDEBAR:
SIMPLE_SEARCH:
HEADLINE: Buscar
RELATED_POSTS:
HEADLINE: Posts relacionados
RANDOM_ARTICLE:
HEADLINE: Artigo aleatório
FEELING_LUCKY: Me sinto sortudo.
SOME_TEXT_WIDGET:
HEADLINE: Algum widget de texto
POPULAR_TAGS:
HEADLINE: Tags Populares
ARCHIVES:
HEADLINE: Arquivos
SYNDICATE:
HEADLINE: Feed
FORM_DATA:
SUMMARY: "Aqui está o resumo do que você nos escreveu:"
ERROR: Erro
@@ -52,7 +52,7 @@ $rule-color: #F0F2F4;
$code-text: #c7254e; $code-text: #c7254e;
$code-bg: #f9f2f4; $code-bg: #f9f2f4;
$pre-text: #237794; $pre-text: #237794;
$pre-bg: #f6f6f6; $pre-bg: #f0f0f0;
// Dark Contrast variation // Dark Contrast variation
$dark-navbar-text: #999; $dark-navbar-text: #999;
@@ -1,4 +1,5 @@
// Header styling // Header styling
$dropdown-color: #f6f6f6;
#header { #header {
@extend .default-animation; @extend .default-animation;
@@ -32,6 +33,10 @@
#navbar a:before, #navbar a:after { #navbar a:before, #navbar a:after {
background-color: $core-accent !important; background-color: $core-accent !important;
} }
.navigation {
margin-top: 0.5rem !important;
}
} }
// set heights for vertical centering // set heights for vertical centering
@@ -56,6 +61,44 @@
#navbar { #navbar {
font-size: $core-font-size - 0.1rem; font-size: $core-font-size - 0.1rem;
/* Child Indicator */
.has-children {
& > a {
& > span {
display: inline-block;
padding-right: 8px;
&:after {
font-family: FontAwesome;
content: '\f107';
position: absolute;
display: inline-block;
right: 8px;
top: 4px;
}
}
&:after, &:before {
display: none;
}
}
& .has-children > a > span:after {
content: '\f105';
}
}
.navigation > .has-children:hover > a {
background: $dropdown-color;
border: 1px solid darken($dropdown-color, 4%);
border-bottom-color: $dropdown-color;
margin: -1px -1px 0 -1px;
z-index: 1000;
position: relative;
padding-bottom: 1px;
}
ul { ul {
margin: 0; margin: 0;
@@ -63,10 +106,12 @@
list-style: none; list-style: none;
&.navigation { &.navigation {
@extend %vertical-align;
display: inline-block; display: inline-block;
float: right; float: right;
@extend .default-animation;
margin-top: 1.4rem;
li { li {
float: left; float: left;
position: relative; position: relative;
@@ -76,6 +121,9 @@
display: inline-block; display: inline-block;
padding: 0.3rem 0.8rem; padding: 0.3rem 0.8rem;
-webkit-backface-visibility: hidden;
&:before, &:after { &:before, &:after {
content: ""; content: "";
position: absolute; position: absolute;
@@ -87,6 +135,7 @@
visibility: hidden; visibility: hidden;
@include transform(scaleX(0)); @include transform(scaleX(0));
@include transition(all 0.2s ease); @include transition(all 0.2s ease);
} }
&:hover:before { &:hover:before {
@@ -109,49 +158,55 @@
} }
} }
// Dropdown Menu Styles /*Active dropdown nav item */
ul { ul {
position: absolute;
background-color: $dropdown-color;
border: 1px solid darken($dropdown-color, 4%);
border-top: 0;
min-width: 12rem;
text-align: left;
z-index: 999;
left: -1px;
display: none; display: none;
padding: 0;
box-shadow: 0 0.05rem 1rem rgba(0,0,0, 0.15) !important;
} }
ul li {
display: block;
float: none;
/* Active Dropdown nav item */
&.active > a {
background-color: darken($dropdown-color, 4%);
color: $core-accent;
}
&:hover > a {
background-color: $core-accent;
color: $white;
}
a {
display: block;
margin: 0 -1px;
&:after, &:before {
display: none;
}
}
}
/* Dropdown CSS */
ul ul { ul ul {
left: 100%; left: 100%;
top: 0; top: 0px;
}
&:hover {
& > ul {
display: block;
position: absolute;
background: rgba($white, 0.9);
width: 10rem;
}
li {
float: none;
margin: 0;
padding: 0;
a {
padding: 0.5rem 0.8rem;
display: block;
&:before, &:after {
display: none;
}
}
&.active {
& > a {
background: $core-accent;
color: $white;
}
}
}
} }
/* Active on Hover */
&:hover > ul {
display: block;
}
} }
@include breakpoint(desktop-only) { @include breakpoint(desktop-only) {
display: none; display: none;
@@ -207,6 +262,10 @@
background-color: rgba($header-text,0); background-color: rgba($header-text,0);
box-shadow: none; box-shadow: none;
.navigation .has-children:hover a {
color: $core-accent;
}
#logo h3, #logo a { #logo h3, #logo a {
color: $header-text; color: $header-text;
} }
@@ -217,15 +276,5 @@
background-color: rgba($header-text,0.7) !important; background-color: rgba($header-text,0.7) !important;
} }
#navbar ul.navigation {
ul li a {
color: $core-accent;
&:hover {
color: darken($core-accent, 20%);
}
}
}
} }
} }
@@ -32,6 +32,17 @@
} }
} }
.search-wrapper {
.search-submit {
height: 52px;
padding: 0 10px;
img {
width: 30px;
}
}
}
.search-details { .search-details {
float: right; float: right;
margin-top: -2.5rem; margin-top: -2.5rem;
@@ -10,7 +10,7 @@
{% else %} {% else %}
<div class="blog-header"> <div class="blog-header">
{% endif %} {% endif %}
{{ page.content }} {{ page.content|raw }}
</div> </div>
{% if config.plugins.breadcrumbs.enabled %} {% if config.plugins.breadcrumbs.enabled %}
@@ -18,7 +18,7 @@
{% endif %} {% endif %}
<div class="content-wrapper blog-content-list grid pure-g"> <div class="content-wrapper blog-content-list grid pure-g">
<div id="listing" class="block pure-u-2-3"> <div id="listing" class="block pure-u-2-3 h-feed">
{% for child in collection %} {% for child in collection %}
{% include 'partials/blog_item.html.twig' with {'blog':page, 'page':child, 'truncate':true} %} {% include 'partials/blog_item.html.twig' with {'blog':page, 'page':child, 'truncate':true} %}
{% endfor %} {% endfor %}
@@ -1,5 +1,5 @@
{% extends 'partials/base.html.twig' %} {% extends 'partials/base.html.twig' %}
{% block content %} {% block content %}
{{ page.content }} {{ page.content|raw }}
{% endblock %} {% endblock %}
@@ -3,9 +3,9 @@
{% block content %} {% block content %}
<div id="error"> <div id="error">
<div> <div>
<h1>Error {{ page.header.http_response_code }}</h1> <h1>{{ 'ERROR'|t }} {{ page.header.http_response_code }}</h1>
<p> <p>
{{ page.content }} {{ page.content|raw }}
</p> </p>
</div> </div>
</div> </div>
@@ -2,7 +2,7 @@
{% block content %} {% block content %}
{{ content }} {{ content|raw }}
{% include "forms/form.html.twig" %} {% include "forms/form.html.twig" %}
{% endblock %} {% endblock %}
@@ -6,7 +6,7 @@
{% endif %} {% endif %}
<div class="blog-content-item grid pure-g-r"> <div class="blog-content-item grid pure-g-r">
<div id="item" class="block pure-u-2-3"> <div id="item" class="block pure-u-2-3 h-entry">
{% include 'partials/blog_item.html.twig' with {'blog':page.parent, 'truncate':false} %} {% include 'partials/blog_item.html.twig' with {'blog':page.parent, 'truncate':false} %}
</div> </div>
<div id="sidebar" class="block size-1-3 pure-u-1-3"> <div id="sidebar" class="block size-1-3 pure-u-1-3">
@@ -35,7 +35,7 @@
{% endfor %} {% endfor %}
{% for mitem in site.menu %} {% for mitem in site.menu %}
<li> <li>
<a href="{{ mitem.url }}"> <a {% if mitem.class %}class="{{ mitem.class }}"{% endif %} href="{{ mitem.url }}">
{% if mitem.icon %}<i class="fa fa-{{ mitem.icon }}"></i>{% endif %} {% if mitem.icon %}<i class="fa fa-{{ mitem.icon }}"></i>{% endif %}
{{ mitem.text }} {{ mitem.text }}
</a> </a>
@@ -48,9 +48,9 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{{ page.content }} {{ page.content|raw }}
{% for module in page.collection() %} {% for module in page.collection() %}
<div id="{{ _self.pageLinkName(module.menu) }}"></div> <div id="{{ _self.pageLinkName(module.menu) }}"></div>
{{ module.content }} {{ module.content|raw }}
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}
@@ -1,5 +1,5 @@
<div class="modular-row features {{ page.header.class}}"> <div class="modular-row features {{ page.header.class}}">
{{ content }} {{ content|raw }}
<div class="feature-items"> <div class="feature-items">
{% for feature in page.header.features %} {% for feature in page.header.features %}
<div class="feature"> <div class="feature">
@@ -1,10 +1,10 @@
{% set showcase_image = page.media.images|first.grayscale().contrast(20).brightness(-125).colorize(-35,81,122) %} {% set showcase_image = page.media.images|first.grayscale().contrast(20).brightness(-125).colorize(-35,81,122) %}
{% if showcase_image %} {% if showcase_image %}
<div class="modular-row showcase flush-top" style="background-image: url({{ showcase_image.url }});"> <div class="modular-row showcase{% if page == page.parent.collection.first %} flush-top{% endif %}" style="background-image: url({{ showcase_image.url }});">
{% else %} {% else %}
<div class="modular-row showcase"> <div class="modular-row showcase">
{% endif %} {% endif %}
{{ content }} {{ content|raw }}
{% for button in page.header.buttons %} {% for button in page.header.buttons %}
<a class="button{% if button.primary %} primary{% endif %}" href="{{ button.url }}">{{ button.text }}</a> <a class="button{% if button.primary %} primary{% endif %}" href="{{ button.url }}">{{ button.text }}</a>
@@ -1,7 +1,7 @@
<div class="modular-row callout"> <div class="modular-row callout">
{% set image = page.media.images|first %} {% set image = page.media.images|first %}
{% if image %} {% if image %}
{{ image.cropResize(400,400).html('','','align-'~page.header.image_align) }} {{ image.cropResize(400,400).html('','','align-'~page.header.image_align)|raw }}
{% endif %} {% endif %}
{{ content }} {{ content|raw }}
</div> </div>
@@ -1,22 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
{% set theme_config = attribute(config.themes, config.system.pages.theme) %} {% set theme_config = attribute(config.themes, config.system.pages.theme) %}
<!DOCTYPE html>
<html lang="{{ grav.language.getActive ?: grav.config.site.default_lang }}">
<head>
{% block head %} {% block head %}
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>{% if header.title %}{{ header.title|e('html') }} | {% endif %}{{ site.title|e('html') }}</title> <title>{% if header.title %}{{ header.title|e('html') }} | {% endif %}{{ site.title|e('html') }}</title>
{% include 'partials/metadata.html.twig' %} {% include 'partials/metadata.html.twig' %}
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="icon" type="image/png" href="{{ url('theme://images/favicon.png', true) }}" /> <link rel="icon" type="image/png" href="{{ url('theme://images/favicon.png') }}" />
<link rel="canonical" href="{{ page.url(true, true) }}" /> <link rel="canonical" href="{{ page.url(true, true) }}" />
{% block stylesheets %} {% block stylesheets %}
{% do assets.addCss('theme://css/pure-0.5.0/grids-min.css', 103) %} {% do assets.addCss('theme://css/pure-0.5.0/grids-min.css', 103) %}
{% do assets.addCss('theme://css-compiled/nucleus.css',102) %} {% do assets.addCss('theme://css-compiled/nucleus.css', 102) %}
{% do assets.addCss('theme://css-compiled/template.css',101) %} {% do assets.addCss('theme://css-compiled/template.css', 101) %}
{% do assets.addCss('theme://css/custom.css',100) %} {% do assets.addCss('theme://css/custom.css', 100) %}
{% do assets.addCss('theme://css/font-awesome.min.css',100) %} {% do assets.addCss('theme://css/font-awesome.min.css', 100) %}
{% do assets.addCss('theme://css/slidebars.min.css') %} {% do assets.addCss('theme://css/slidebars.min.css') %}
{% if browser.getBrowser == 'msie' and browser.getVersion == 10 %} {% if browser.getBrowser == 'msie' and browser.getVersion == 10 %}
@@ -27,17 +26,20 @@
{% do assets.addJs('theme://js/html5shiv-printshiv.min.js') %} {% do assets.addJs('theme://js/html5shiv-printshiv.min.js') %}
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{{ assets.css() }}
{% block javascripts %} {% block javascripts %}
{% do assets.addJs('jquery',101) %} {% do assets.addJs('jquery', 101) %}
{% do assets.addJs('theme://js/modernizr.custom.71422.js',100) %} {% do assets.addJs('theme://js/modernizr.custom.71422.js', 100) %}
{% do assets.addJs('theme://js/antimatter.js') %} {% do assets.addJs('theme://js/antimatter.js') %}
{% do assets.addJs('theme://js/slidebars.min.js') %} {% do assets.addJs('theme://js/slidebars.min.js') %}
{% endblock %} {% endblock %}
{{ assets.js() }}
{% endblock head%} {% block assets deferred %}
{{ assets.css()|raw }}
{{ assets.js()|raw }}
{% endblock %}
{% endblock head %}
</head> </head>
<body id="top" class="{{ page.header.body_classes }}"> <body id="top" class="{{ page.header.body_classes }}">
<div id="sb-site"> <div id="sb-site">
@@ -76,23 +78,25 @@
</footer> </footer>
{% endblock %} {% endblock %}
</div> </div>
<div class="sb-slidebar sb-left sb-width-thin"> {% block sidebar_navigation %}
<div id="panel"> <div class="sb-slidebar sb-left sb-width-thin">
{% include 'partials/navigation.html.twig' %} <div id="panel">
{% include 'partials/navigation.html.twig' %}
</div>
</div> </div>
</div> {% endblock %}
{% block bottom %} {% block bottom %}
<script>
<script> $(function () {
$(function () { $(document).ready(function() {
$(document).ready(function() { $.slidebars({
$.slidebars({ hideControlClasses: true,
hideControlClasses: true, scrollLock: true
scrollLock: true });
}); });
}); });
}); </script>
</script> {{ assets.js('bottom')|raw }}
{% endblock %} {% endblock %}
</body> </body>
</html> </html>
@@ -1,4 +1,4 @@
<div class="list-item"> <div class="list-item h-entry">
{% set header_image = page.header.header_image|defined(true) %} {% set header_image = page.header.header_image|defined(true) %}
{% set header_image_width = page.header.header_image_width|defined(900) %} {% set header_image_width = page.header.header_image_width|defined(900) %}
@@ -7,24 +7,26 @@
<div class="list-blog-header"> <div class="list-blog-header">
<span class="list-blog-date"> <span class="list-blog-date">
<span>{{ page.date|date("d") }}</span> <time class="dt-published" datetime="{{ page.date|date("c") }}">
<em>{{ page.date|date("M") }}</em> <span>{{ page.date|date("d") }}</span>
<em>{{ page.date|date("M") }}</em>
</time>
</span> </span>
{% if page.header.link %} {% if page.header.link %}
<h4> <h4 class="p-name">
{% if page.header.continue_link is not sameas(false) %} {% if page.header.continue_link is not same as(false) %}
<a href="{{ page.url }}"><i class="fa fa-angle-double-right"></i></a> <a href="{{ page.url }}"><i class="fa fa-angle-double-right u-url"></i></a>
{% endif %} {% endif %}
<a href="{{ page.header.link }}">{{ page.title }}</a> <a href="{{ page.header.link }}" class="u-url">{{ page.title }}</a>
</h4> </h4>
{% else %} {% else %}
<h4><a href="{{ page.url }}">{{ page.title }}</a></h4> <h4 class="p-name"><a href="{{ page.url }}" class="u-url">{{ page.title }}</a></h4>
{% endif %} {% endif %}
{% if page.taxonomy.tag %} {% if page.taxonomy.tag %}
<span class="tags"> <span class="tags">
{% for tag in page.taxonomy.tag %} {% for tag in page.taxonomy.tag %}
<a href="{{ blog.url }}/tag{{ config.system.param_sep }}{{ tag }}">{{ tag }}</a> <a href="{{ blog.url|rtrim('/') }}/tag{{ config.system.param_sep }}{{ tag }}" class="p-category">{{ tag }}</a>
{% endfor %} {% endfor %}
</span> </span>
{% endif %} {% endif %}
@@ -34,30 +36,39 @@
{% else %} {% else %}
{% set header_image_media = page.media.images|first %} {% set header_image_media = page.media.images|first %}
{% endif %} {% endif %}
{{ header_image_media.cropZoom(header_image_width, header_image_height).html }} {{ header_image_media.cropZoom(header_image_width, header_image_height).html|raw }}
{% endif %} {% endif %}
</div> </div>
<div class="list-blog-padding"> <div class="list-blog-padding">
{% if page.header.continue_link is sameas(false) %} {% if page.header.continue_link is same as(false) %}
{{ page.content }} <div class="e-content">
{{ page.content|raw }}
</div>
{% if not truncate %} {% if not truncate %}
{% set show_prev_next = true %} {% set show_prev_next = true %}
{% endif %} {% endif %}
{% elseif truncate and page.summary != page.content %} {% elseif truncate and page.summary != page.content %}
{{ page.summary }} <div class="p-summary e-content">
<p><a href="{{ page.url }}">Continue Reading...</a></p> {{ page.summary|raw }}
<p><a href="{{ page.url }}">{{ 'BLOG.ITEM.CONTINUE_READING'|t }}</a></p>
</div>
{% elseif truncate %} {% elseif truncate %}
{% if page.summary != page.content %} <div class="p-summary e-content">
{{ page.content|truncate(550) }} {{ page.content|raw }}
{% else %} <p><a href="{{ page.url }}">{{ 'BLOG.ITEM.CONTINUE_READING'|t }}</a></p>
{{ page.content }} </div>
{% endif %}
<p><a href="{{ page.url }}">Continue Reading...</a></p>
{% else %} {% else %}
{{ page.content }} <div class="e-content">
{{ page.content|raw }}
</div>
{% if config.plugins.comments.enabled %}
{% include 'partials/comments.html.twig' %}
{% endif %}
{% set show_prev_next = true %} {% set show_prev_next = true %}
{% endif %} {% endif %}
@@ -65,11 +76,11 @@
<p class="prev-next"> <p class="prev-next">
{% if not page.isFirst %} {% if not page.isFirst %}
<a class="button" href="{{ page.nextSibling.url }}"><i class="fa fa-chevron-left"></i> Next Post</a> <a class="button" href="{{ page.nextSibling.url }}"><i class="fa fa-chevron-left"></i> {{ 'BLOG.ITEM.NEXT_POST'|t }}</a>
{% endif %} {% endif %}
{% if not page.isLast %} {% if not page.isLast %}
<a class="button" href="{{ page.prevSibling.url }}">Previous Post <i class="fa fa-chevron-right"></i></a> <a class="button" href="{{ page.prevSibling.url }}">{{ 'BLOG.ITEM.PREV_POST'|t }} <i class="fa fa-chevron-right"></i></a>
{% endif %} {% endif %}
</p> </p>
{% endif %} {% endif %}
@@ -1,23 +1,34 @@
{% import _self as macros %}
{% macro loop(page) %} {% macro loop(page) %}
{% import _self as macros %}
{% for p in page.children.visible %} {% for p in page.children.visible %}
{% set current_page = (p.active or p.activeChild) ? 'active' : '' %} {% set current_page = (p.active or p.activeChild) ? 'active' : '' %}
<li class="{{ current_page }}"> {% if p.children.visible.count > 0 %}
<a href="{{ p.url }}"> <li class="has-children {{ current_page }}">
{% if p.header.icon %}<i class="fa fa-{{ p.header.icon }}"></i>{% endif %} <a href="{{ p.url }}">
{{ p.menu }} {% if p.header.icon %}<i class="fa fa-{{ p.header.icon }}"></i>{% endif %}
</a> {{ p.menu }}
{% if p.children.visible.count > 0 %} <span></span>
</a>
<ul> <ul>
{{ _self.loop(p) }} {{ macros.loop(p) }}
</ul> </ul>
{% endif %} </li>
</li> {% else %}
<li class="{{ current_page }}">
<a href="{{ p.url }}">
{% if p.header.icon %}<i class="fa fa-{{ p.header.icon }}"></i>{% endif %}
{{ p.menu }}
</a>
</li>
{% endif %}
{% endfor %} {% endfor %}
{% endmacro %} {% endmacro %}
<ul class="navigation"> <ul class="navigation">
{% if theme_config.dropdown.enabled %} {% if theme_config.dropdown.enabled %}
{{ _self.loop(pages) }} {{ macros.loop(pages) }}
{% else %} {% else %}
{% for page in pages.children.visible %} {% for page in pages.children.visible %}
{% set current_page = (page.active or page.activeChild) ? 'active' : '' %} {% set current_page = (page.active or page.activeChild) ? 'active' : '' %}
@@ -3,39 +3,39 @@
{% if config.plugins.simplesearch.enabled %} {% if config.plugins.simplesearch.enabled %}
<div class="sidebar-content"> <div class="sidebar-content">
<h4>SimpleSearch</h4> <h4>{{ 'SIDEBAR.SIMPLE_SEARCH.HEADLINE'|t }}</h4>
{% include 'partials/simplesearch_searchbox.html.twig' %} {% include 'partials/simplesearch_searchbox.html.twig' %}
</div> </div>
{% endif %} {% endif %}
{% if config.plugins.relatedpages.enabled and related_pages|length > 0 %} {% if config.plugins.relatedpages.enabled and related_pages|length > 0 %}
<h4>Related Posts</h4> <h4>{{ 'SIDEBAR.RELATED_POSTS.HEADLINE'|t }}</h4>
{% include 'partials/relatedpages.html.twig' %} {% include 'partials/relatedpages.html.twig' %}
{% endif %} {% endif %}
{% if config.plugins.random.enabled %} {% if config.plugins.random.enabled %}
<div class="sidebar-content"> <div class="sidebar-content">
<h4>Random Article</h4> <h4>{{ 'SIDEBAR.RANDOM_ARTICLE.HEADLINE'|t }}</h4>
<a class="button" href="{{ base_url }}/random"><i class="fa fa-retweet"></i> I'm Feeling Lucky!</a> <a class="button" href="{{ base_url }}/random"><i class="fa fa-retweet"></i> {{ 'SIDEBAR.RANDOM_ARTICLE.FEELING_LUCKY'|t }}</a>
</div> </div>
{% endif %} {% endif %}
<div class="sidebar-content"> <div class="sidebar-content">
<h4>Some Text Widget</h4> <h4>{{ 'SIDEBAR.SOME_TEXT_WIDGET.HEADLINE'|t }}</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna.</p> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna.</p>
</div> </div>
{% if config.plugins.taxonomylist.enabled %} {% if config.plugins.taxonomylist.enabled %}
<div class="sidebar-content"> <div class="sidebar-content">
<h4>Popular Tags</h4> <h4>{{ 'SIDEBAR.POPULAR_TAGS.HEADLINE'|t }}</h4>
{% include 'partials/taxonomylist.html.twig' with {'base_url':new_base_url, 'taxonomy':'tag'} %} {% include 'partials/taxonomylist.html.twig' with {'base_url':new_base_url, 'taxonomy':'tag'} %}
</div> </div>
{% endif %} {% endif %}
{% if config.plugins.archives.enabled %} {% if config.plugins.archives.enabled %}
<div class="sidebar-content"> <div class="sidebar-content">
<h4>Archives</h4> <h4>{{ 'SIDEBAR.ARCHIVES.HEADLINE'|t }}</h4>
{% include 'partials/archives.html.twig' with {'base_url':new_base_url} %} {% include 'partials/archives.html.twig' with {'base_url':new_base_url} %}
</div> </div>
{% endif %} {% endif %}
{% if config.plugins.feed.enabled %} {% if config.plugins.feed.enabled %}
<div class="sidebar-content syndicate"> <div class="sidebar-content syndicate">
<h4>Syndicate</h4> <h4>{{ 'SIDEBAR.SYNDICATE.HEADLINE'|t }}</h4>
<a class="button" href="{{ feed_url }}.atom"><i class="fa fa-rss-square"></i> Atom 1.0</a> <a class="button" href="{{ feed_url }}.atom"><i class="fa fa-rss-square"></i> Atom 1.0</a>
<a class="button" href="{{ feed_url }}.rss"><i class="fa fa-rss-square"></i> RSS</a> <a class="button" href="{{ feed_url }}.rss"><i class="fa fa-rss-square"></i> RSS</a>
</div> </div>
@@ -990,6 +990,9 @@ ul.pagination {
@media (max-width: 1024px) { @media (max-width: 1024px) {
.texte-cache { .texte-cache {
max-height: 445px; } } max-height: 445px; } }
@media (max-width: 1024px) and (max-width: 442px) {
.texte-cache {
max-height: 400px; } }
/*Style du module TEXTE lorsqu'il est ouvert*/ /*Style du module TEXTE lorsqu'il est ouvert*/
.texte-cache.ouvert { .texte-cache.ouvert {
@@ -1008,9 +1011,15 @@ ul.pagination {
@media (max-width: 1024px) { @media (max-width: 1024px) {
.modular .features { .modular .features {
width: 80% !important; width: 80% !important;
margin-left: 8rem !important; } margin: auto !important; } }
@media (max-width: 442px) {
.modular .features .feature { .modular .features .feature {
width: 24% !important; } } width: 80%; } }
@media (max-width: 1024px) {
.modular .features .feature {
width: 24%; } }
.bouton-ouverture { .bouton-ouverture {
position: relative; position: relative;
@@ -1120,10 +1129,10 @@ ul.pagination {
padding-left: 0.8rem; padding-left: 0.8rem;
font-size: 0.75rem; font-size: 0.75rem;
padding-right: 0.6rem; } } padding-right: 0.6rem; } }
.mozaique_personnes .equipe .personne .mozaique:hover { .mozaique_personnes .equipe .personne .mozaique .info:hover {
background-color: #000; background-color: #000;
color: #fff; color: #fff;
transition: 0.2s ease-in-out; } transition: 0.2s ease-in-out; }
.bouton { .bouton {
border: solid !important; border: solid !important;
@@ -1450,7 +1459,3 @@ button:focus {
.modular .modular-row:last-child { .modular .modular-row:last-child {
margin-bottom: 2rem; } margin-bottom: 2rem; }
@media (max-width: 442px) {
h1 {
font-size: 1.5rem; } }
@@ -359,6 +359,9 @@
transition: max-height 1s ease; /* Transition CSS entre l'ouverture et la fermeture*/ transition: max-height 1s ease; /* Transition CSS entre l'ouverture et la fermeture*/
@media (max-width: 1024px) { @media (max-width: 1024px) {
max-height: 445px; max-height: 445px;
@media (max-width:442px) {
max-height: 400px;
}
} }
} }
@@ -381,20 +384,22 @@
} }
.modular .features {
@media (max-width: 1024px) {
@media (max-width: 1024px) { width: 80% !important;
.modular .features { margin: auto !important;
width: 80% !important;
margin-left: 8rem !important;
}
.modular .features .feature {
width: 24% !important;
// margin-bottom: 10rem;
} }
} }
.modular .features .feature {
// margin-bottom: 10rem;
@media (max-width: 442px) {width: 80% ;}
@media (max-width: 1024px) {width: 24% ;}
}
.bouton-ouverture { .bouton-ouverture {
position: relative; position: relative;
justify-content: center; justify-content: center;
@@ -543,14 +548,16 @@
font-size: 0.75rem; font-size: 0.75rem;
padding-right: 0.6rem; padding-right: 0.6rem;
} }
} }
&:hover {
background-color: #000;
color: #fff;
transition:0.2s ease-in-out;
}
} }
&:hover {
background-color: #000;
color: #fff;
transition:0.2s ease-in-out;
}
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show More