Compare commits
14 Commits
1bea358e24
...
prod
Author | SHA1 | Date | |
---|---|---|---|
![]() |
93d6d519da | ||
![]() |
7c640a7a14 | ||
![]() |
97231dd6bf | ||
![]() |
636612e37b | ||
![]() |
f6934de1ef | ||
![]() |
92b77e0ad1 | ||
![]() |
29437e281a | ||
![]() |
9dc1b940dc | ||
![]() |
44301d5fd4 | ||
![]() |
25a022ea48 | ||
![]() |
ea8909c5d7 | ||
![]() |
9be9a708f4 | ||
![]() |
d89f8d2ae2 | ||
![]() |
4c537bf529 |
79
.github/workflows/build.yaml
vendored
@@ -1,79 +0,0 @@
|
||||
name: Release Builds
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
permissions:
|
||||
contents: write # for release creation (svenstaro/upload-release-action)
|
||||
|
||||
if: "!github.event.release.prerelease"
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Extract Tag
|
||||
run: echo "PACKAGE_VERSION=${{ github.ref }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 7.3
|
||||
extensions: opcache, gd
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
env:
|
||||
COMPOSER_TOKEN: ${{ secrets.GLOBAL_TOKEN }}
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get -y update -qq < /dev/null > /dev/null
|
||||
sudo apt-get -y install -qq git zip < /dev/null > /dev/null
|
||||
|
||||
- name: Retrieval of Builder Scripts
|
||||
run: |
|
||||
# Real Grav URL
|
||||
curl --silent -H "Authorization: token ${{ secrets.GLOBAL_TOKEN }}" -H "Accept: application/vnd.github.v3.raw" ${{ secrets.BUILD_SCRIPT_URL }} --output build-grav.sh
|
||||
|
||||
# Development Local URL
|
||||
# curl ${{ secrets.BUILD_SCRIPT_URL }} --output build-grav.sh
|
||||
|
||||
- name: Grav Builder
|
||||
run: |
|
||||
bash ./build-grav.sh
|
||||
|
||||
- name: Upload packages to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag: ${{ env.PACKAGE_VERSION }}
|
||||
file: ./grav-dist/*.zip
|
||||
overwrite: true
|
||||
file_glob: true
|
||||
|
||||
slack:
|
||||
permissions:
|
||||
actions: read # to list jobs for workflow run (technote-space/workflow-conclusion-action)
|
||||
|
||||
name: Slack
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
steps:
|
||||
- uses: technote-space/workflow-conclusion-action@v2
|
||||
- uses: 8398a7/action-slack@v3
|
||||
with:
|
||||
status: failure
|
||||
fields: repo,message,author,action
|
||||
icon_emoji: ':octocat:'
|
||||
author_name: 'Github Action Build'
|
||||
text: '🚚 Automated Build Failure'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GLOBAL_TOKEN }}
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
76
.github/workflows/tests.yaml
vendored
@@ -1,76 +0,0 @@
|
||||
name: PHP Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ develop ]
|
||||
pull_request:
|
||||
branches: [ develop ]
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
|
||||
unit-tests:
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php: [8.3, 8.2, 8.1, 8.0, 7.4, 7.3]
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: opcache, gd
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
env:
|
||||
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# - name: Update composer
|
||||
# run: composer update
|
||||
#
|
||||
# - name: Validate composer.json and composer.lock
|
||||
# run: composer validate
|
||||
|
||||
- name: Get composer cache directory
|
||||
id: composer-cache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: ${{ runner.os }}-composer-
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --prefer-dist --no-progress
|
||||
|
||||
- name: Run test suite
|
||||
run: vendor/bin/codecept run
|
||||
|
||||
# slack:
|
||||
# name: Slack
|
||||
# needs: unit-tests
|
||||
# runs-on: ubuntu-latest
|
||||
# if: always()
|
||||
# steps:
|
||||
# - uses: technote-space/workflow-conclusion-action@v2
|
||||
# - uses: 8398a7/action-slack@v3
|
||||
# with:
|
||||
# status: failure
|
||||
# fields: repo,message,author,action
|
||||
# icon_emoji: ':octocat:'
|
||||
# author_name: 'Github Action Tests'
|
||||
# text: '💥 Automated Test Failure'
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
# if: env.WORKFLOW_CONCLUSION == 'failure'
|
48
.github/workflows/trigger-skeletons.yml
vendored
@@ -1,48 +0,0 @@
|
||||
name: Trigger Skeletons Build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Which Grav release to use'
|
||||
required: true
|
||||
default: 'latest'
|
||||
admin:
|
||||
description: 'Create also a package with Admin'
|
||||
required: true
|
||||
default: true
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
WORKFLOW: "build-skeleton.yml"
|
||||
AUTH: ":${{secrets.GLOBAL_TOKEN}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Make it rain ☔️
|
||||
run: |
|
||||
SKELETONS=`curl -s "${{secrets.SKELETONS_JSON_LIST}}"`
|
||||
echo "$SKELETONS" | jq -cr '.[]' | while read SKELETON; do
|
||||
KEY=$(echo "$SKELETON" | jq -cr 'keys[0]')
|
||||
VERSION=$(echo "$SKELETON" | jq -cr '.[]')
|
||||
URL="https://api.github.com/repos/${KEY}/actions/workflows/${WORKFLOW}/dispatches"
|
||||
|
||||
curl -X POST \
|
||||
-u "${AUTH}" \
|
||||
-H "Accept: application/vnd.github.everest-preview+json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-sS \
|
||||
${URL} \
|
||||
--data '{ "ref": "develop",
|
||||
"inputs": {
|
||||
"tag": "'"$VERSION"'",
|
||||
"version": "'"$INPUT_VERSION"'",
|
||||
"admin": "'"$INPUT_ADMIN"'"
|
||||
}
|
||||
}' > /dev/null
|
||||
echo "Dispatched Worfklow for ${KEY}@$VERSION"
|
||||
done
|
4
.gitignore
vendored
@@ -28,6 +28,10 @@ user/themes/*
|
||||
!user/themes/ateliers-55
|
||||
user/**/config/security.yaml
|
||||
|
||||
# Content
|
||||
|
||||
user/pages/*
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.gravenv
|
||||
|
27
CHANGELOG.md
@@ -1,3 +1,29 @@
|
||||
# v1.7.46
|
||||
## 05/15/2024
|
||||
|
||||
1. [](#improved)
|
||||
* Better handling of external protocols in `Utils::url()` such as `mailto:`, `tel:`, etc.
|
||||
* Handle `GRAV_ROOT` or `GRAV_WEBROOT` when `/` [#3667](https://github.com/getgrav/grav/pull/3667)
|
||||
1. [](#bugfix)
|
||||
* Fixes for multi-lang taxonomy when reinitializing the languages (e.g. LangSwitcher plugin)
|
||||
* Ensure the full filepath is checked for invalid filename in `MediaUploadTrait::checkFileMetadata()`
|
||||
* Fixed a bug in the `on_events` REGEX pattern of `Security::detectXss()` as it was not matching correctly.
|
||||
* Fixed an issue where `read_file()` Twig function could be used nefariously in content [#GHSA-f8v5-jmfh-pr69](https://github.com/getgrav/grav/security/advisories/GHSA-f8v5-jmfh-pr69)
|
||||
|
||||
# v1.7.45
|
||||
## 03/18/2024
|
||||
|
||||
1. [](#new)
|
||||
* Added new Image trait for `decoding` attribute [#3796](https://github.com/getgrav/grav/pull/3796)
|
||||
1. [](#bugfix)
|
||||
* Fixed some multibyte issues in Inflector class [#732](https://github.com/getgrav/grav/issues/732)
|
||||
* Fallback to page modified date if Page date provided is invalid and can't be parsed [getgrav/grav-plugin-admin#2394](https://github.com/getgrav/grav-plugin-admin/issues/2394)
|
||||
* Fixed a path traversal vulnerability with file uploads [#GHSA-m7hx-hw6h-mqmc](https://github.com/getgrav/grav/security/advisories/GHSA-m7hx-hw6h-mqmc)
|
||||
* Fixed a security issue with insecure Twig functions be processed [#GHSA-2m7x-c7px-hp58](https://github.com/getgrav/grav/security/advisories/GHSA-2m7x-c7px-hp58) [#GHSA-r6vw-8v8r-pmp4](https://github.com/getgrav/grav/security/advisories/GHSA-r6vw-8v8r-pmp4) [#GHSA-qfv4-q44r-g7rv](https://github.com/getgrav/grav/security/advisories/GHSA-qfv4-q44r-g7rv) [#GHSA-c9gp-64c4-2rrh](https://github.com/getgrav/grav/security/advisories/GHSA-c9gp-64c4-2rrh)
|
||||
1. [](#improved)
|
||||
* Updated composer packages
|
||||
* Updated `bin/composer.phar` to latest `2.7.2`
|
||||
|
||||
# v1.7.44
|
||||
## 01/05/2024
|
||||
|
||||
@@ -103,6 +129,7 @@
|
||||
1. [](#improved)
|
||||
* Removed outdated `xcache` setting [#3615](https://github.com/getgrav/grav/pull/3615)
|
||||
* Updated `robots.txt` [#3625](https://github.com/getgrav/grav/pull/3625)
|
||||
* Handle the situation when GRAV_ROOT or GRAV_WEBROOT are `/` [#3625](https://github.com/getgrav/grav/pull/3667)
|
||||
1. [](#bugfix)
|
||||
* Fixed `force_ssl` redirect in case of undefined hostname [#3702](https://github.com/getgrav/grav/pull/3702)
|
||||
* Fixed an issue with duplicate identical page paths
|
||||
|
17
SECURITY.md
@@ -7,22 +7,31 @@ We are focusing our security updates on the following versions
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 1.7.x | :white_check_mark: |
|
||||
| 1.6.x | :warning: |
|
||||
| 1.6.x | :x: |
|
||||
| < 1.6 | :x: |
|
||||
|
||||
## :pushpin: Note on Security Severity
|
||||
|
||||
> NOTE: Please use the following guidlines when selecting a **Severity**. Submitted advisories that are marked **High** or **Critical** that don't meet the guidelines below will be cliosed.
|
||||
|
||||
* **CRITICAL** - no account required, can modify content, or run malicious code or nefarious activity without any access.
|
||||
* **HIGH** - publisher level account able to run malicious code or nefarious activity, or other high level security things.
|
||||
* **MODERATE** - admin level account able to run malicious code or do nefarious things. other moderate security things.
|
||||
* **LOW** - super admin level account able to run malicious code or do nefarious things. other minor security things.
|
||||
|
||||
## :warning: Versions
|
||||
|
||||
Versions with :warning: will be supported for security issues, however you won't be able to update to them, you will need to manually update through the [`direct-install` command](https://learn.getgrav.org/17/admin-panel/tools).
|
||||
|
||||
If you cannot update to the latest stable version available because, for example, your server does not meet the minimum PHP requirements, you can manually install a previous version by downloading the package from our Releases directory (https://github.com/getgrav/grav/releases).
|
||||
|
||||
## Reporting a Vulnerability
|
||||
## :pencil: Reporting a Vulnerability
|
||||
|
||||
Please contact security@getgrav.org with a detailed explanation of the security issue found. If it appears to be a legitimate issues, please submit an **advisory via GitHub Security**: https://github.com/getgrav/grav/security/advisories
|
||||
|
||||
>> NOTE: Please do not use 3rd party security issue reporting services, we like to keep everything in the GitHub ecosystem for easier manageability.
|
||||
> NOTE: Please do not use 3rd party security issue reporting services, we like to keep everything in the GitHub ecosystem for easier manageability.
|
||||
|
||||
## Bug Bounties
|
||||
## :bug: Bug Bounties
|
||||
|
||||
We do greatly appreciate your efforts to improve Grav, but unfortunately because we are a small open source project, we **do not have the resources to offer bounties** for security issues found.
|
||||
|
||||
|
357
composer.lock
generated
@@ -1300,6 +1300,17 @@ form:
|
||||
auto: Auto
|
||||
lazy: Lazy
|
||||
eager: Eager
|
||||
|
||||
images.defaults.decoding:
|
||||
type: select
|
||||
size: small
|
||||
label: PLUGIN_ADMIN.IMAGES_DECODING
|
||||
help: PLUGIN_ADMIN.IMAGES_DECODING_HELP
|
||||
highlight: auto
|
||||
options:
|
||||
auto: Auto
|
||||
sync: Sync
|
||||
async: Async
|
||||
|
||||
images.seofriendly:
|
||||
type: toggle
|
||||
|
@@ -168,6 +168,7 @@ images:
|
||||
retina_scale: 1 # scale to adjust auto-sizes for better handling of HiDPI resolutions
|
||||
defaults:
|
||||
loading: auto # Let browser pick [auto|lazy|eager]
|
||||
decoding: auto # Let browser pick [auto|sync|async]
|
||||
watermark:
|
||||
image: 'system://images/watermark.png' # Path to a watermark image
|
||||
position_y: 'center' # top|center|bottom
|
||||
|
@@ -9,7 +9,7 @@
|
||||
|
||||
// Some standard defines
|
||||
define('GRAV', true);
|
||||
define('GRAV_VERSION', '1.7.44');
|
||||
define('GRAV_VERSION', '1.7.46');
|
||||
define('GRAV_SCHEMA', '1.7.0_2020-11-20_1');
|
||||
define('GRAV_TESTING', false);
|
||||
|
||||
@@ -26,12 +26,12 @@ if (!defined('DS')) {
|
||||
// Absolute path to Grav root. This is where Grav is installed into.
|
||||
if (!defined('GRAV_ROOT')) {
|
||||
$path = rtrim(str_replace(DIRECTORY_SEPARATOR, DS, getenv('GRAV_ROOT') ?: getcwd()), DS);
|
||||
define('GRAV_ROOT', $path);
|
||||
define('GRAV_ROOT', $path ?: DS);
|
||||
}
|
||||
// Absolute path to Grav webroot. This is the path where your site is located in.
|
||||
if (!defined('GRAV_WEBROOT')) {
|
||||
$path = rtrim(getenv('GRAV_WEBROOT') ?: GRAV_ROOT, DS);
|
||||
define('GRAV_WEBROOT', $path);
|
||||
define('GRAV_WEBROOT', $path ?: DS);
|
||||
}
|
||||
// Relative path to user folder. This path needs to be located under GRAV_WEBROOT.
|
||||
if (!defined('GRAV_USER_PATH')) {
|
||||
|
@@ -104,6 +104,7 @@ GRAV:
|
||||
VALIDATION_FAIL: '<b>Провера неуспела:</b>'
|
||||
INVALID_INPUT: 'Неисправан унос у'
|
||||
MISSING_REQUIRED_FIELD: 'Недостаје обавезн поље:'
|
||||
XSS_ISSUES: "Потенцијална грешка у XSS-у детектована у пољу '%s' "
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- 'Јануар'
|
||||
- 'Фебруар'
|
||||
@@ -125,6 +126,8 @@ GRAV:
|
||||
- 'Петак'
|
||||
- 'Субота'
|
||||
- 'Недеља'
|
||||
YES: "Да"
|
||||
NO: "Не"
|
||||
CRON:
|
||||
EVERY: сваки
|
||||
EVERY_HOUR: сваки сат
|
||||
|
@@ -218,7 +218,7 @@ class Backups
|
||||
if ($locator->isStream($backup_root)) {
|
||||
$backup_root = $locator->findResource($backup_root);
|
||||
} else {
|
||||
$backup_root = rtrim(GRAV_ROOT . $backup_root, '/');
|
||||
$backup_root = rtrim(GRAV_ROOT . $backup_root, DS) ?: DS;
|
||||
}
|
||||
|
||||
if (!$backup_root || !file_exists($backup_root)) {
|
||||
|
@@ -161,9 +161,15 @@ class Inflector
|
||||
*/
|
||||
public static function titleize($word, $uppercase = '')
|
||||
{
|
||||
$uppercase = $uppercase === 'first' ? 'ucfirst' : 'ucwords';
|
||||
$humanize_underscorize = static::humanize(static::underscorize($word));
|
||||
|
||||
if ($uppercase === 'first') {
|
||||
$firstLetter = mb_strtoupper(mb_substr($humanize_underscorize, 0, 1, "UTF-8"), "UTF-8");
|
||||
return $firstLetter . mb_substr($humanize_underscorize, 1, mb_strlen($humanize_underscorize, "UTF-8"), "UTF-8");
|
||||
} else {
|
||||
return mb_convert_case($humanize_underscorize, MB_CASE_TITLE, 'UTF-8');
|
||||
}
|
||||
|
||||
return $uppercase(static::humanize(static::underscorize($word)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -180,7 +186,7 @@ class Inflector
|
||||
*/
|
||||
public static function camelize($word)
|
||||
{
|
||||
return str_replace(' ', '', ucwords(preg_replace('/[^A-Z^a-z^0-9]+/', ' ', $word)));
|
||||
return str_replace(' ', '', ucwords(preg_replace('/[^\p{L}^0-9]+/', ' ', $word)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,7 +204,7 @@ class Inflector
|
||||
{
|
||||
$regex1 = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1_\2', $word);
|
||||
$regex2 = preg_replace('/([a-zd])([A-Z])/', '\1_\2', $regex1);
|
||||
$regex3 = preg_replace('/[^A-Z^a-z^0-9]+/', '_', $regex2);
|
||||
$regex3 = preg_replace('/[^\p{L}^0-9]+/u', '_', $regex2);
|
||||
|
||||
return strtolower($regex3);
|
||||
}
|
||||
@@ -219,7 +225,7 @@ class Inflector
|
||||
$regex1 = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1-\2', $word);
|
||||
$regex2 = preg_replace('/([a-z])([A-Z])/', '\1-\2', $regex1);
|
||||
$regex3 = preg_replace('/([0-9])([A-Z])/', '\1-\2', $regex2);
|
||||
$regex4 = preg_replace('/[^A-Z^a-z^0-9]+/', '-', $regex3);
|
||||
$regex4 = preg_replace('/[^\p{L}^0-9]+/', '-', $regex3);
|
||||
|
||||
$regex4 = trim($regex4, '-');
|
||||
|
||||
|
40
system/src/Grav/Common/Media/Traits/ImageDecodingTrait.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\Media
|
||||
* @author Pedro Moreno https://github.com/pmoreno-rodriguez
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\Media\Traits;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
|
||||
/**
|
||||
* Trait ImageDecodingTrait
|
||||
* @package Grav\Common\Media\Traits
|
||||
*/
|
||||
|
||||
trait ImageDecodingTrait
|
||||
{
|
||||
/**
|
||||
* Allows to set the decoding attribute from Markdown or Twig
|
||||
*
|
||||
* @param string|null $value
|
||||
* @return $this
|
||||
*/
|
||||
public function decoding($value = null)
|
||||
{
|
||||
if (null === $value) {
|
||||
$value = Grav::instance()['config']->get('system.images.defaults.decoding', 'auto');
|
||||
}
|
||||
|
||||
// Validate the provided value (similar to loading)
|
||||
if ($value !== null && $value !== 'auto') {
|
||||
$this->attributes['decoding'] = $value;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
@@ -156,7 +156,7 @@ trait MediaUploadTrait
|
||||
$filepath = $folder . $filename;
|
||||
|
||||
// Check if the filename is allowed.
|
||||
if (!Utils::checkFilename($filename)) {
|
||||
if (!Utils::checkFilename($filepath)) {
|
||||
throw new RuntimeException(
|
||||
sprintf($this->translate('PLUGIN_ADMIN.FILEUPLOAD_UNABLE_TO_UPLOAD'), $filepath, $this->translate('PLUGIN_ADMIN.BAD_FILENAME'))
|
||||
);
|
||||
|
@@ -15,6 +15,7 @@ use Grav\Common\Media\Interfaces\ImageManipulateInterface;
|
||||
use Grav\Common\Media\Interfaces\ImageMediaInterface;
|
||||
use Grav\Common\Media\Interfaces\MediaLinkInterface;
|
||||
use Grav\Common\Media\Traits\ImageLoadingTrait;
|
||||
use Grav\Common\Media\Traits\ImageDecodingTrait;
|
||||
use Grav\Common\Media\Traits\ImageMediaTrait;
|
||||
use Grav\Common\Utils;
|
||||
use Gregwar\Image\Image;
|
||||
@@ -30,6 +31,7 @@ class ImageMedium extends Medium implements ImageMediaInterface, ImageManipulate
|
||||
{
|
||||
use ImageMediaTrait;
|
||||
use ImageLoadingTrait;
|
||||
use ImageDecodingTrait;
|
||||
|
||||
/**
|
||||
* @var mixed|string
|
||||
|
@@ -225,7 +225,7 @@ class Security
|
||||
// Set the patterns we'll test against
|
||||
$patterns = [
|
||||
// Match any attribute starting with "on" or xmlns
|
||||
'on_events' => '#(<[^>]+[[a-z\x00-\x20\"\'\/])([\s\/]on|\sxmlns)[a-z].*=>?#iUu',
|
||||
'on_events' => '#(<[^>]+[a-z\x00-\x20\"\'\/])(on[a-z]+|xmlns)\s*=[\s|\'\"].*[\s|\'\"]>#iUu',
|
||||
|
||||
// Match javascript:, livescript:, vbscript:, mocha:, feed: and data: protocols
|
||||
'invalid_protocols' => '#(' . implode('|', array_map('preg_quote', $invalid_protocols, ['#'])) . ')(:|\&\#58)\S.*?#iUu',
|
||||
@@ -263,4 +263,25 @@ class Security
|
||||
'invalid_protocols' => array_map('trim', $config->get('security.xss_invalid_protocols')),
|
||||
];
|
||||
}
|
||||
|
||||
public static function cleanDangerousTwig(string $string): string
|
||||
{
|
||||
if ($string === '') {
|
||||
return $string;
|
||||
}
|
||||
|
||||
$bad_twig = [
|
||||
'twig_array_map',
|
||||
'twig_array_filter',
|
||||
'call_user_func',
|
||||
'registerUndefinedFunctionCallback',
|
||||
'undefined_functions',
|
||||
'twig.getFunction',
|
||||
'core.setEscaper',
|
||||
'twig.safe_functions',
|
||||
'read_file',
|
||||
];
|
||||
$string = preg_replace('/(({{\s*|{%\s*)[^}]*?(' . implode('|', $bad_twig) . ')[^}]*?(\s*}}|\s*%}))/i', '{# $1 #}', $string);
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@
|
||||
namespace Grav\Common;
|
||||
|
||||
use Grav\Common\Config\Config;
|
||||
use Grav\Common\Language\Language;
|
||||
use Grav\Common\Page\Collection;
|
||||
use Grav\Common\Page\Interfaces\PageInterface;
|
||||
use function is_string;
|
||||
@@ -37,6 +38,8 @@ class Taxonomy
|
||||
protected $taxonomy_map;
|
||||
/** @var Grav */
|
||||
protected $grav;
|
||||
/** @var Language */
|
||||
protected $language;
|
||||
|
||||
/**
|
||||
* Constructor that resets the map
|
||||
@@ -45,8 +48,9 @@ class Taxonomy
|
||||
*/
|
||||
public function __construct(Grav $grav)
|
||||
{
|
||||
$this->taxonomy_map = [];
|
||||
$this->grav = $grav;
|
||||
$this->language = $grav['language'];
|
||||
$this->taxonomy_map[$this->language->getLanguage()] = [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +111,8 @@ class Taxonomy
|
||||
if (!empty($key)) {
|
||||
$taxonomy .= $key;
|
||||
}
|
||||
$this->taxonomy_map[$taxonomy][(string) $value][$page->path()] = ['slug' => $page->slug()];
|
||||
$active = $this->language->getLanguage();
|
||||
$this->taxonomy_map[$active][$taxonomy][(string) $value][$page->path()] = ['slug' => $page->slug()];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,14 +128,11 @@ class Taxonomy
|
||||
{
|
||||
$matches = [];
|
||||
$results = [];
|
||||
$active = $this->language->getLanguage();
|
||||
|
||||
foreach ((array)$taxonomies as $taxonomy => $items) {
|
||||
foreach ((array)$items as $item) {
|
||||
if (isset($this->taxonomy_map[$taxonomy][$item])) {
|
||||
$matches[] = $this->taxonomy_map[$taxonomy][$item];
|
||||
} else {
|
||||
$matches[] = [];
|
||||
}
|
||||
$matches[] = $this->taxonomy_map[$active][$taxonomy][$item] ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,11 +158,13 @@ class Taxonomy
|
||||
*/
|
||||
public function taxonomy($var = null)
|
||||
{
|
||||
$active = $this->language->getLanguage();
|
||||
|
||||
if ($var) {
|
||||
$this->taxonomy_map = $var;
|
||||
$this->taxonomy_map[$active] = $var;
|
||||
}
|
||||
|
||||
return $this->taxonomy_map;
|
||||
return $this->taxonomy_map[$active] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,6 +175,7 @@ class Taxonomy
|
||||
*/
|
||||
public function getTaxonomyItemKeys($taxonomy)
|
||||
{
|
||||
return isset($this->taxonomy_map[$taxonomy]) ? array_keys($this->taxonomy_map[$taxonomy]) : [];
|
||||
$active = $this->language->getLanguage();
|
||||
return isset($this->taxonomy_map[$active][$taxonomy]) ? array_keys($this->taxonomy_map[$active][$taxonomy]) : [];
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ use Grav\Common\Language\Language;
|
||||
use Grav\Common\Language\LanguageCodes;
|
||||
use Grav\Common\Page\Interfaces\PageInterface;
|
||||
use Grav\Common\Page\Pages;
|
||||
use Grav\Common\Security;
|
||||
use Grav\Common\Twig\Exception\TwigException;
|
||||
use Grav\Common\Twig\Extension\FilesystemExtension;
|
||||
use Grav\Common\Twig\Extension\GravExtension;
|
||||
@@ -319,6 +320,7 @@ class Twig
|
||||
public function processPage(PageInterface $item, $content = null)
|
||||
{
|
||||
$content = $content ?? $item->content();
|
||||
$content = Security::cleanDangerousTwig($content);
|
||||
|
||||
// override the twig header vars for local resolution
|
||||
$this->grav->fireEvent('onTwigPageVariables', new Event(['page' => $item]));
|
||||
@@ -392,6 +394,8 @@ class Twig
|
||||
$this->grav->fireEvent('onTwigStringVariables');
|
||||
$vars += $this->twig_vars;
|
||||
|
||||
$string = Security::cleanDangerousTwig($string);
|
||||
|
||||
$name = '@Var:' . $string;
|
||||
$this->setTemplate($name, $string);
|
||||
|
||||
@@ -418,7 +422,7 @@ class Twig
|
||||
try {
|
||||
$grav = $this->grav;
|
||||
|
||||
// set the page now its been processed
|
||||
// set the page now it's been processed
|
||||
$grav->fireEvent('onTwigSiteVariables');
|
||||
|
||||
/** @var Pages $pages */
|
||||
@@ -427,13 +431,15 @@ class Twig
|
||||
/** @var PageInterface $page */
|
||||
$page = $grav['page'];
|
||||
|
||||
$content = Security::cleanDangerousTwig($page->content());
|
||||
|
||||
$twig_vars = $this->twig_vars;
|
||||
$twig_vars['theme'] = $grav['config']->get('theme');
|
||||
$twig_vars['pages'] = $pages->root();
|
||||
$twig_vars['page'] = $page;
|
||||
$twig_vars['header'] = $page->header();
|
||||
$twig_vars['media'] = $page->media();
|
||||
$twig_vars['content'] = $page->content();
|
||||
$twig_vars['content'] = $content;
|
||||
|
||||
// determine if params are set, if so disable twig cache
|
||||
$params = $grav['uri']->params(null, true);
|
||||
@@ -568,4 +574,5 @@ class Twig
|
||||
|
||||
$this->autoescape = (bool) $state;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -206,7 +206,7 @@ class Uri
|
||||
$uri = $language->setActiveFromUri($uri);
|
||||
|
||||
// split the URL and params (and make sure that the path isn't seen as domain)
|
||||
$bits = parse_url('http://domain.com' . $uri);
|
||||
$bits = static::parseUrl('http://domain.com' . $uri);
|
||||
|
||||
//process fragment
|
||||
if (isset($bits['fragment'])) {
|
||||
@@ -265,6 +265,7 @@ class Uri
|
||||
return $this->paths;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return route to the current URI. By default route doesn't include base path.
|
||||
*
|
||||
@@ -742,7 +743,7 @@ class Uri
|
||||
*/
|
||||
public static function isExternal($url)
|
||||
{
|
||||
return (0 === strpos($url, 'http://') || 0 === strpos($url, 'https://') || 0 === strpos($url, '//'));
|
||||
return (0 === strpos($url, 'http://') || 0 === strpos($url, 'https://') || 0 === strpos($url, '//') || 0 === strpos($url, 'mailto:') || 0 === strpos($url, 'tel:') || 0 === strpos($url, 'ftp://') || 0 === strpos($url, 'ftps://') || 0 === strpos($url, 'news:') || 0 === strpos($url, 'irc:') || 0 === strpos($url, 'gopher:') || 0 === strpos($url, 'nntp:') || 0 === strpos($url, 'feed:') || 0 === strpos($url, 'cvs:') || 0 === strpos($url, 'ssh:') || 0 === strpos($url, 'git:') || 0 === strpos($url, 'svn:') || 0 === strpos($url, 'hg:'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -954,9 +955,7 @@ class Uri
|
||||
$grav = Grav::instance();
|
||||
|
||||
// Remove extra slash from streams, parse_url() doesn't like it.
|
||||
if ($pos = strpos($url, ':///')) {
|
||||
$url = substr_replace($url, '://', $pos, 4);
|
||||
}
|
||||
$url = preg_replace('/([^:])(\/{2,})/', '$1/', $url);
|
||||
|
||||
$encodedUrl = preg_replace_callback(
|
||||
'%[^:/@?&=#]+%usD',
|
||||
|
@@ -989,6 +989,8 @@ abstract class Utils
|
||||
|| strtr($filename, "\t\v\n\r\0\\/", '_______') !== $filename
|
||||
// Filename should not start or end with dot or space.
|
||||
|| trim($filename, '. ') !== $filename
|
||||
// Filename should not contain path traversal
|
||||
|| str_replace('..', '', $filename) !== $filename
|
||||
// File extension should not be part of configured dangerous extensions
|
||||
|| in_array($extension, $dangerous_extensions)
|
||||
);
|
||||
@@ -1330,7 +1332,11 @@ abstract class Utils
|
||||
if ($dateformat) {
|
||||
$datetime = DateTime::createFromFormat($dateformat, $date);
|
||||
} else {
|
||||
$datetime = new DateTime($date);
|
||||
try {
|
||||
$datetime = new DateTime($date);
|
||||
} catch (Exception $e) {
|
||||
$datetime = false;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to strtotime() if DateTime approach failed
|
||||
|
0
system/src/Twig/DeferredExtension/DeferredBlockNode.php
Executable file → Normal file
0
system/src/Twig/DeferredExtension/DeferredNode.php
Executable file → Normal file
@@ -160,7 +160,7 @@ log:
|
||||
tag: grav
|
||||
debugger:
|
||||
enabled: false
|
||||
provider: clockwork
|
||||
provider: debugbar
|
||||
censored: false
|
||||
shutdown:
|
||||
close_connection: true
|
||||
@@ -178,6 +178,7 @@ images:
|
||||
retina_scale: '1'
|
||||
defaults:
|
||||
loading: auto
|
||||
decoding: auto
|
||||
watermark:
|
||||
image: 'system://images/watermark.png'
|
||||
position_y: center
|
||||
@@ -189,7 +190,7 @@ media:
|
||||
unsupported_inline_types: null
|
||||
allowed_fallback_types: null
|
||||
auto_metadata_exif: false
|
||||
upload_limit: 2097152
|
||||
upload_limit: 2147483648
|
||||
session:
|
||||
enabled: true
|
||||
initialize: true
|
||||
|
@@ -1,10 +0,0 @@
|
||||
---
|
||||
title: 'Journal d''un chantier'
|
||||
body_classes: 'title-center title-h1h2'
|
||||
---
|
||||
|
||||
Les Ateliers 55 rentrent en travaux pour 18 mois à compter du 1<sup>er</sup> février 2024. Objectif : création de 6 ateliers d'artistes, 4 ateliers-logements, 1 studio et 1 appartement en location à l'été 2025. Une construction en matériaux biosourcés (bois, paille et terre).
|
||||
|
||||
===
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras nec ullamcorper lacus, eu elementum quam. In hac habitasse platea dictumst. Duis egestas justo eget massa congue rhoncus. Pellentesque ex urna, dictum nec dapibus vitae, bibendum quis diam. Nunc ut euismod risus, non placerat nisi. Sed maximus luctus sapien at porttitor. Suspendisse pulvinar dui leo, aliquet pulvinar lectus egestas et. Morbi rutrum blandit eleifend. Maecenas ac massa eget ante ultricies tempus. Suspendisse at lobortis ligula, a aliquam eros. Phasellus in ligula et lorem malesuada volutpat. Sed ex massa, luctus sed egestas ut, feugiat in libero.
|
Before Width: | Height: | Size: 208 KiB |
@@ -1,9 +0,0 @@
|
||||
---
|
||||
title: 'Article 1'
|
||||
media_order: 'cat-8436843_1280.jpg,forsythia-8595521_1280.jpg,labrador-8554882_1280.jpg,lake-8357182_1280.jpg,landscape-8592826_1280.jpg'
|
||||
date: '05-03-2024 11:34'
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ut purus congue, accumsan erat varius, auctor sapien. Aliquam in molestie leo. Curabitur ut elit tellus. Vivamus neque metus, rhoncus quis erat sit amet, congue luctus arcu. Ut porttitor id enim in lobortis. Pellentesque consequat tincidunt est finibus pharetra. Phasellus ligula leo, efficitur at porttitor ac, scelerisque non nunc. Fusce ac ultricies elit.
|
||||
|
||||
Curabitur porttitor felis ac diam aliquam pretium. Suspendisse a augue vehicula, consectetur arcu id, lobortis leo. Duis venenatis eget metus quis lacinia. Sed placerat consequat nisl sed fermentum. Vivamus tristique diam a mi eleifend, sed interdum tellus laoreet. Ut eu lorem ut mi rutrum ornare et vitae mi. Sed dictum sapien justo, a finibus magna aliquam eu. Mauris vel metus sit amet elit tincidunt tincidunt. Nunc venenatis tellus velit, ut accumsan turpis gravida a. Nullam sapien odio, feugiat nec condimentum id, dapibus nec felis. Nullam et placerat nisi. Proin finibus, lorem sit amet faucibus gravida, ligula urna mattis ligula, vel commodo ex ex vitae nisi.
|
Before Width: | Height: | Size: 111 KiB |
Before Width: | Height: | Size: 144 KiB |
Before Width: | Height: | Size: 261 KiB |
Before Width: | Height: | Size: 443 KiB |
@@ -1,9 +0,0 @@
|
||||
---
|
||||
title: 'Article 2'
|
||||
media_order: 'mountains-8497575_1280.jpg,nuts-8585063_1280.jpg,sparrow-8387465_1280.jpg'
|
||||
date: '03-03-2024 11:34'
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ut purus congue, accumsan erat varius, auctor sapien. Aliquam in molestie leo. Curabitur ut elit tellus. Vivamus neque metus, rhoncus quis erat sit amet, congue luctus arcu. Ut porttitor id enim in lobortis. Pellentesque consequat tincidunt est finibus pharetra. Phasellus ligula leo, efficitur at porttitor ac, scelerisque non nunc. Fusce ac ultricies elit.
|
||||
|
||||
Curabitur porttitor felis ac diam aliquam pretium. Suspendisse a augue vehicula, consectetur arcu id, lobortis leo. Duis venenatis eget metus quis lacinia. Sed placerat consequat nisl sed fermentum. Vivamus tristique diam a mi eleifend, sed interdum tellus laoreet. Ut eu lorem ut mi rutrum ornare et vitae mi. Sed dictum sapien justo, a finibus magna aliquam eu. Mauris vel metus sit amet elit tincidunt tincidunt. Nunc venenatis tellus velit, ut accumsan turpis gravida a. Nullam sapien odio, feugiat nec condimentum id, dapibus nec felis. Nullam et placerat nisi. Proin finibus, lorem sit amet faucibus gravida, ligula urna mattis ligula, vel commodo ex ex vitae nisi.
|
Before Width: | Height: | Size: 327 KiB |
Before Width: | Height: | Size: 237 KiB |
Before Width: | Height: | Size: 244 KiB |
@@ -1,7 +0,0 @@
|
||||
---
|
||||
title: 'Article 3'
|
||||
media_order: 'lake-8357182_1280.jpg,landscape-8592826_1280.jpg,mountains-8497575_1280.jpg,nuts-8585063_1280.jpg'
|
||||
date: '21-02-2024 11:35'
|
||||
---
|
||||
|
||||
Mauris est nisl, lobortis scelerisque tellus vel, pretium maximus nisi. Phasellus viverra quis lacus non pulvinar. Maecenas molestie, lorem a gravida pharetra, lacus felis luctus tellus, quis tempor felis nulla id sapien. Aenean sed lectus metus. Etiam ac ornare ex. Phasellus imperdiet augue ac justo porta, in volutpat mi fringilla. Duis mattis nisl velit, sit amet euismod risus feugiat mollis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque gravida lorem eget orci pretium venenatis. Pellentesque ac odio gravida quam luctus interdum. Mauris quis laoreet risus, a congue quam. Vivamus orci ligula, viverra quis vehicula nec, faucibus vitae risus. Sed sagittis consequat massa, a egestas est pharetra nec. Vestibulum in urna consequat, varius nunc sed, semper nunc. Nam aliquet augue lacinia dignissim egestas. Ut quam mauris, sagittis sit amet tortor vel, rhoncus luctus dui.
|
Before Width: | Height: | Size: 261 KiB |
Before Width: | Height: | Size: 443 KiB |
Before Width: | Height: | Size: 327 KiB |
Before Width: | Height: | Size: 237 KiB |
Before Width: | Height: | Size: 208 KiB |
@@ -1,7 +0,0 @@
|
||||
---
|
||||
title: 'Article 4'
|
||||
date: '13-02-2024 11:36'
|
||||
media_order: 'cat-8436843_1280.jpg,forsythia-8595521_1280.jpg,labrador-8554882_1280.jpg'
|
||||
---
|
||||
|
||||
Phasellus nec hendrerit lectus, a accumsan dolor. Etiam ultrices, ante non fermentum congue, tortor orci pellentesque libero, vel lacinia risus orci eget sapien. Nam non sem consectetur, finibus felis ac, imperdiet ipsum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed sit amet nunc ultricies, tincidunt augue id, porta ante. Sed turpis ipsum, pellentesque a dictum sed, laoreet non arcu. Nulla at leo quis diam accumsan congue. Curabitur consequat varius ante, sit amet luctus magna accumsan eget. Curabitur ac ultrices felis. Mauris tempor lectus ac erat congue, nec efficitur massa bibendum. In ac felis viverra, dictum magna quis, fermentum magna. Fusce ac fermentum dui, eu tempus velit. Ut massa ligula, iaculis eget metus a, commodo viverra nisi. Vestibulum lectus diam, placerat aliquet consequat id, mattis id risus. Maecenas massa ante, vehicula luctus sapien vitae, lacinia dignissim tortor. Suspendisse tristique est ut quam molestie vehicula.
|
Before Width: | Height: | Size: 111 KiB |
Before Width: | Height: | Size: 144 KiB |
@@ -1,7 +0,0 @@
|
||||
---
|
||||
title: 'Article 5'
|
||||
media_order: 'lake-8357182_1280.jpg,mountains-8497575_1280.jpg,sparrow-8387465_1280.jpg'
|
||||
date: '14-03-2024 11:38'
|
||||
---
|
||||
|
||||
Phasellus efficitur eu turpis non sollicitudin. Aliquam cursus, tellus non faucibus pharetra, ipsum nulla pretium mi, vel auctor magna orci tristique sem. Sed mattis facilisis mauris, id pellentesque dui elementum sit amet. Duis vel venenatis risus, sed porta lorem. Morbi purus nunc, luctus eu tellus ac, commodo tincidunt nisl. Duis lacinia vitae dolor sed pellentesque. Proin blandit sodales dolor, vitae condimentum turpis sagittis ut. Pellentesque quis velit nec nulla consectetur sodales nec in nulla. Curabitur sed libero non quam rhoncus fermentum sit amet condimentum lectus. Maecenas eu pellentesque nibh.
|
Before Width: | Height: | Size: 261 KiB |
Before Width: | Height: | Size: 327 KiB |
Before Width: | Height: | Size: 244 KiB |
@@ -1,9 +0,0 @@
|
||||
---
|
||||
title: Articles
|
||||
content:
|
||||
items: '@self.children'
|
||||
order:
|
||||
by: date
|
||||
dir: desc
|
||||
---
|
||||
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
title: 'Mentions Légales'
|
||||
---
|
||||
|
||||
Mauris est nisl, lobortis scelerisque tellus vel, pretium maximus nisi. Phasellus viverra quis lacus non pulvinar. Maecenas molestie, lorem a gravida pharetra, lacus felis luctus tellus, quis tempor felis nulla id sapien. Aenean sed lectus metus. Etiam ac ornare ex. Phasellus imperdiet augue ac justo porta, in volutpat mi fringilla. Duis mattis nisl velit, sit amet euismod risus feugiat mollis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque gravida lorem eget orci pretium venenatis. Pellentesque ac odio gravida quam luctus interdum. Mauris quis laoreet risus, a congue quam. Vivamus orci ligula, viverra quis vehicula nec, faucibus vitae risus. Sed sagittis consequat massa, a egestas est pharetra nec. Vestibulum in urna consequat, varius nunc sed, semper nunc. Nam aliquet augue lacinia dignissim egestas. Ut quam mauris, sagittis sit amet tortor vel, rhoncus luctus dui.
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
title: Contact
|
||||
---
|
||||
|
||||
contact adresse mail
|
@@ -44,6 +44,10 @@
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
width: 100vw;
|
||||
@@ -79,8 +83,10 @@ header #hamburger {
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
outline: unset;
|
||||
}
|
||||
header #hamburger div {
|
||||
outline: unset;
|
||||
border-bottom: solid 1px #000;
|
||||
width: 100%;
|
||||
background-color: #000;
|
||||
@@ -142,7 +148,7 @@ nav.open {
|
||||
font-weight: normal;
|
||||
}
|
||||
#about #about-hidden.open {
|
||||
max-height: 50vh;
|
||||
max-height: 200vh;
|
||||
}
|
||||
#about #about-arrow {
|
||||
width: 7.5vh;
|
||||
@@ -153,8 +159,10 @@ nav.open {
|
||||
transform: rotate(0deg) scale(0.5);
|
||||
transition: transform 0.5s ease-out;
|
||||
cursor: pointer;
|
||||
outline: unset;
|
||||
}
|
||||
#about #about-arrow div {
|
||||
outline: unset;
|
||||
width: 50%;
|
||||
border-bottom: solid 1px #000;
|
||||
}
|
||||
@@ -295,7 +303,6 @@ article #article-wrapper .article-header .close-article div:last-of-type {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
article #article-wrapper .swiper {
|
||||
max-height: 40vh;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease-out;
|
||||
@@ -304,11 +311,19 @@ article #article-wrapper .swiper .swiper-wrapper .swiper-slide {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 7vw;
|
||||
display: flex;
|
||||
height: auto;
|
||||
max-height: 40vh;
|
||||
align-items: center;
|
||||
}
|
||||
article #article-wrapper .swiper .swiper-wrapper .swiper-slide img {
|
||||
box-sizing: content-box;
|
||||
width: 100%;
|
||||
}
|
||||
article #article-wrapper .swiper .swiper-wrapper .swiper-slide video {
|
||||
box-sizing: content-box;
|
||||
width: 100%;
|
||||
}
|
||||
article #article-wrapper .swiper .swiper-button-prev, article #article-wrapper .swiper .swiper-button-next {
|
||||
color: #000;
|
||||
transform: scale(0.5);
|
||||
@@ -374,7 +389,7 @@ article .article-content {
|
||||
align-self: center;
|
||||
}
|
||||
#about #about-hidden.open {
|
||||
max-height: 20vh;
|
||||
max-height: 200vh;
|
||||
}
|
||||
main {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
|
@@ -1 +1 @@
|
||||
{"version":3,"sourceRoot":"","sources":["../sass/styles.scss"],"names":[],"mappings":"AAAA;EACI;EACA;EAEA;EACA;;AAGJ;EACI;EACA;EAEA;EACA;;AAGJ;EACI;EACA;EAEA;EACA;;AAGJ;EACI;EACA;EAEA;EACA;;AAGJ;EACI;EACA;EAEA;EACA;;AAGJ;EACI;EACA;EAEA;EACA;;AAQJ;EACI;;AACA;EACI,OANM;;AAQV;EACI;;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;;AACA;EACI;EACA;;AAGR;EACI;;AACA;EACI;EACA;EACA,OApCA;EAqCA;;AAGR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA,kBApDA;EAqDA;EACA;EACA;;AAIJ;EACI;;AAEJ;EACI;;AAEJ;EACI;;;AAKZ;EACI,kBAtEU;EAuEV;EACA;EACA;;AACA;EACI;EACA;;AAEI;EACI;EACA;EACA,OAhFN;EAiFM;EACA;;AAGR;EACI;;;AAIZ;EACI;;;AAGJ;EACI,OAhGU;EAiGV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;EACA;EACA;;AAEJ;EACI;;AAEJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;;AAEJ;EACI;;AAEJ;EACI;;AAGR;EACI;;;AAGR;EACI;EACA;;AACA;EACI;EACA;EACA;;AACA;EACI;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;EACA;EACA;EACA;EACA,kBA3KN;;AA8KF;EACI;EACA;EACA;EACA;;AAGR;EACI;EACA;EACA,OAxLE;;AA0LN;EACI;EACA;EACA;;AAKA;EACI;;AAEJ;EACI;;;AAKhB;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;EACA;EACA,kBA1NE;EA2NF;;AACA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;EACA;;AACA;EACI,OA7OR;EA8OQ;EACA;;AACA;EACI;EACA;;AAIZ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;;AAEJ;EACI;;AAEJ;EACI;;AAIZ;EACI;EACA;EACA;EACA;;AAEI;EACI;EACA;EACA;;AACA;EACI;EACA;;AAIZ;EACI,OA7RJ;EA8RI;;AAEJ;EACI;;AAEJ;EACI;;AAIZ;EACI;EACA;EACA,OAzSM;EA0SN;EACA;;AAEJ;EACI;EACA;EACA;;AAEJ;EACI;;;AAIR;EAEQ;IACI;;EACA;IACI;IACA;;EAGR;IACI;;EACA;IACI;IACA;IACA;;EAKR;IACI;;EAGR;IACI;IACA;IACA;IACA;;EACA;IACI;;EAEJ;IACI;IACA;IACA;;EAEJ;IACI;IACA;IACA;;EAEJ;IACI;;EAGR;IACI;IACA;;EAEI;IACI;;EAKR;IACI;;EACA;IACI;;EAEJ;IACI;;;AAMhB;EACI;IACI;IACA","file":"styles.css"}
|
||||
{"version":3,"sourceRoot":"","sources":["../sass/styles.scss"],"names":[],"mappings":"AAAA;EACI;EACA;EAEA;EACA;;AAGJ;EACI;EACA;EAEA;EACA;;AAGJ;EACI;EACA;EAEA;EACA;;AAGJ;EACI;EACA;EAEA;EACA;;AAGJ;EACI;EACA;EAEA;EACA;;AAGJ;EACI;EACA;EAEA;EACA;;AAQJ;EACI;;AACA;EACI,OANM;;AAQV;EACI;;;AAIR;EACI;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;;AACA;EACI;EACA;;AAGR;EACI;;AACA;EACI;EACA;EACA,OAxCA;EAyCA;;AAGR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;EACA,kBA1DA;EA2DA;EACA;EACA;;AAIJ;EACI;;AAEJ;EACI;;AAEJ;EACI;;;AAKZ;EACI,kBA5EU;EA6EV;EACA;EACA;;AACA;EACI;EACA;;AAEI;EACI;EACA;EACA,OAtFN;EAuFM;EACA;;AAGR;EACI;;;AAIZ;EACI;;;AAGJ;EACI,OAtGU;EAuGV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;EACA;EACA;;AAEJ;EACI;;AAEJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;;AAEJ;EACI;;AAEJ;EACI;;AAGR;EACI;;;AAGR;EACI;EACA;;AACA;EACI;EACA;EACA;;AACA;EACI;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;EACA;EACA;EACA;EACA,kBAnLN;;AAsLF;EACI;EACA;EACA;EACA;;AAGR;EACI;EACA;EACA,OAhME;;AAkMN;EACI;EACA;EACA;;AAKA;EACI;;AAEJ;EACI;;;AAKhB;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;EACA;EACA,kBAlOE;EAmOF;;AACA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;EACA;EACA;;AACA;EACI,OArPR;EAsPQ;EACA;;AACA;EACI;EACA;;AAIZ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;;AAEJ;EACI;;AAEJ;EACI;;AAIZ;EACI;EACA;EACA;;AAEI;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACI;EACA;;AAEJ;EACI;EACA;;AAIZ;EACI,OA5SJ;EA6SI;;AAEJ;EACI;;AAEJ;EACI;;AAIZ;EACI;EACA;EACA,OAxTM;EAyTN;EACA;;AAEJ;EACI;EACA;EACA;;AAEJ;EACI;;;AAIR;EAEQ;IACI;;EACA;IACI;IACA;;EAGR;IACI;;EACA;IACI;IACA;IACA;;EAKR;IACI;;EAGR;IACI;IACA;IACA;IACA;;EACA;IACI;;EAEJ;IACI;IACA;IACA;;EAEJ;IACI;IACA;IACA;;EAEJ;IACI;;EAGR;IACI;IACA;;EAEI;IACI;;EAKR;IACI;;EACA;IACI;;EAEJ;IACI;;;AAMhB;EACI;IACI;IACA","file":"styles.css"}
|
@@ -19,9 +19,11 @@ $(document).ready(function() {
|
||||
body.style.overflowY = "auto";
|
||||
}
|
||||
let swiperEl = document.querySelector('.swiper');
|
||||
if (swiperEl) {
|
||||
swiperEl.style.opacity = 1;
|
||||
resizeVerticalImages();
|
||||
}
|
||||
initSwiper();
|
||||
swiperEl.style.opacity = 1;
|
||||
resizeVerticalImages();
|
||||
barba.init({
|
||||
transitions: [{
|
||||
name: 'opacity-transition',
|
||||
@@ -38,18 +40,22 @@ $(document).ready(function() {
|
||||
}]
|
||||
});
|
||||
barba.hooks.before((data) => {
|
||||
swiperEl.style.opacity = 0;
|
||||
if (swiperEl) {
|
||||
swiperEl.style.opacity = 0;
|
||||
}
|
||||
});
|
||||
barba.hooks.after((data) => {
|
||||
swiperEl = document.querySelector('.swiper');
|
||||
resizeVerticalImages();
|
||||
if (document.querySelector('.swiper') && !document.querySelector('.swiper-initialized')) {
|
||||
initSwiper();
|
||||
body.style.overflowY = "hidden";
|
||||
if (swiperEl) {
|
||||
if (document.querySelector('.swiper') && !document.querySelector('.swiper-initialized')) {
|
||||
initSwiper();
|
||||
body.style.overflowY = "hidden";
|
||||
}
|
||||
swiperEl.style.opacity = 1;
|
||||
} else {
|
||||
body.style.overflowY = "auto";
|
||||
}
|
||||
swiperEl.style.opacity = 1;
|
||||
resizeVerticalImages();
|
||||
});
|
||||
})
|
||||
|
||||
@@ -64,12 +70,34 @@ function initSwiper() {
|
||||
}
|
||||
|
||||
function resizeVerticalImages() {
|
||||
if (document.querySelector('.swiper')) {
|
||||
let verticalImages = document.querySelectorAll('.swiper-slide > img');
|
||||
for (let img of verticalImages) {
|
||||
let verticalImages = document.querySelectorAll('.swiper-slide > img');
|
||||
let imagesIndex = 0;
|
||||
for (let img of verticalImages) {
|
||||
if(img.complete){
|
||||
imagesIndex++;
|
||||
if (img.clientHeight > img.clientWidth) {
|
||||
img.style.width = "50%";
|
||||
}
|
||||
}
|
||||
if (imagesIndex === verticalImages.length) {
|
||||
swiperSlideEls = document.querySelectorAll('.swiper-slide');
|
||||
for (let swiperSlideEl of swiperSlideEls) {
|
||||
swiperSlideEl.style.maxHeight = "unset";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
img.onload = () => {
|
||||
imagesIndex++;
|
||||
if (img.clientHeight > img.clientWidth) {
|
||||
img.style.width = "50%";
|
||||
}
|
||||
if (imagesIndex === verticalImages.length) {
|
||||
swiperSlideEls = document.querySelectorAll('.swiper-slide');
|
||||
for (let swiperSlideEl of swiperSlideEls) {
|
||||
swiperSlideEl.style.maxHeight = "unset";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -61,6 +61,10 @@ $bgColor: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
width: 100vw;
|
||||
@@ -95,7 +99,9 @@ header {
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
outline: unset;
|
||||
div {
|
||||
outline: unset;
|
||||
border-bottom: solid 1px $mainColor;
|
||||
width: 100%;
|
||||
background-color: $mainColor;
|
||||
@@ -161,7 +167,7 @@ nav.open {
|
||||
font-weight: normal;
|
||||
}
|
||||
#about-hidden.open {
|
||||
max-height: 50vh;
|
||||
max-height: 200vh;
|
||||
}
|
||||
#about-arrow {
|
||||
width: 7.5vh;
|
||||
@@ -172,7 +178,9 @@ nav.open {
|
||||
transform: rotate(0deg) scale(0.5);
|
||||
transition: transform 0.5s ease-out;
|
||||
cursor: pointer;
|
||||
outline: unset;
|
||||
div {
|
||||
outline: unset;
|
||||
width: 50%;
|
||||
border-bottom: solid 1px $mainColor;
|
||||
}
|
||||
@@ -315,7 +323,6 @@ article {
|
||||
}
|
||||
}
|
||||
.swiper {
|
||||
max-height: 40vh;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease-out;
|
||||
@@ -324,10 +331,18 @@ article {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 7vw;
|
||||
display: flex;
|
||||
height: auto;
|
||||
max-height: 40vh;
|
||||
align-items: center;
|
||||
img {
|
||||
box-sizing: content-box;
|
||||
width: 100%;
|
||||
}
|
||||
video {
|
||||
box-sizing: content-box;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.swiper-button-prev, .swiper-button-next {
|
||||
@@ -401,7 +416,7 @@ article {
|
||||
align-self: center;
|
||||
}
|
||||
#about-hidden.open {
|
||||
max-height: 20vh;
|
||||
max-height: 200vh;
|
||||
}
|
||||
}
|
||||
main {
|
||||
|
@@ -8,13 +8,14 @@
|
||||
<div class="article-header">
|
||||
{% if page.parent.title == "Articles" %}
|
||||
<div class="article-siblings">
|
||||
{% if not page.isFirst %}
|
||||
<a href="{{ page.nextSibling.url }}"><i class="fa-solid fa-chevron-left"></i> Article suivant</a>
|
||||
{{ dump(page.parent.collection.prevSibling(page.path)) }}
|
||||
{% if not page.parent.collection.isFirst(page.path) %}
|
||||
<a href="{{ page.parent.collection.nextSibling(page.path).url }}"><i class="fa-solid fa-chevron-left"></i> Article suivant</a>
|
||||
{% else %}
|
||||
<div></div>
|
||||
{% endif %}
|
||||
{% if not page.isLast %}
|
||||
<a href="{{ page.prevSibling.url }}">Article précédent <i class="fa-solid fa-chevron-right"></i></a>
|
||||
{% if not page.parent.collection.isLast(page.path) %}
|
||||
<a href="{{ page.parent.collection.prevSibling(page.path).url }}">Article précédent <i class="fa-solid fa-chevron-right"></i></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -31,6 +32,11 @@
|
||||
<img src="{{ image.url }}" alt="{{ page.title }}">
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% for video in page.media.videos %}
|
||||
<div class="swiper-slide">
|
||||
<video controls src="{{ video.url }}">
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="swiper-button-next"></div>
|
||||
</div>
|
||||
|
@@ -1,9 +1,9 @@
|
||||
<div id="about" onClick="toggleAbout()">
|
||||
<div id="about-summary">
|
||||
{{ page.find('/').summary|raw }}
|
||||
{{ page.find('/a-propos').summary|raw }}
|
||||
</div>
|
||||
<div id="about-hidden">
|
||||
{{ page.find('/').content|slice(page.summary|length, page.content|length)|markdown(false) }}
|
||||
{{ page.find('/a-propos').content|slice(page.find('/a-propos').summary|length, page.find('/a-propos').content|length)|markdown(false) }}
|
||||
</div>
|
||||
<div id="about-arrow">
|
||||
<div></div>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<main>
|
||||
{% for article in page.find('/articles').children.published.order('date', 'desc') %}
|
||||
{% for article in page.find('/articles').collection %}
|
||||
<div class="article-card">
|
||||
<a href="{{ article.url }}" data-barba="link">
|
||||
<div class="img-cover">
|
||||
|