Merge branch 'develop' into feature/blueprints-update

This commit is contained in:
Flavio Copes
2016-02-11 20:10:06 +01:00
60 changed files with 4182 additions and 990 deletions

View File

@@ -20,6 +20,8 @@ notifications:
template:
- '%{repository}#%{build_number} (%{branch}): Travis Job Finished [%{duration}] (<a href="%{build_url}">Details</a>)'
format: html
slack:
secure: dowksPsxxCxGKT6nis5hUgkp6+ZDAhoqzQHF9rJnx4hx0iEygPhVBs7pKl9yL2jubYJoLs+EXwE7z1dYgDAEJh4BnfrCokCMLpFGcxVxQC/HeAUdSQ2/RtdBYR5PRT75ScaFpqM/SfXXZVtnwVXAw9Z+JC6BjQ9vmn23m51Jw4k=
env:
global:
# Colors!
@@ -40,17 +42,20 @@ env:
# BB_TOKEN value => "user:pass@"
- secure: "einUtSEkUWy2IrqLXyVjwUU+mwaaoiOXRRVdLBpA3Zye6bZx8cm5h/5AplkPWhM/NmCJoW/MwNZHHkFhlr3mDRov5iOxVmTTYfnXB+I5lxYTSgduOLLErS7mU8hfADpVDU8bHNU44fNGD3UEiG1PD4qQBX4DMlqIFmR20mjs81k="
# GH_API_USER [for curl]
- secure: "Xbk/V9aIys0NxccJGR3Zrm2GRxDnA0RuazBs1puIboTYDhbi0Z7JTL+mOx3xp5Kfoniad/xAuijQESTM9MMrKqq/qCzhAMaC1+vcL4pCHZH4NSG6DBxB9BPkKVFq+1llu5FTEf8bkxHzwGR0l1ARW6TVRcgTHr5B58bCEIwEOrI="
- secure: "AQGcX1B2NrI8ajflY4AimZDNcK2kBA3F6mbtEFQ78NkDoWhMipsQHayWXiSTzRc0YJKvQl2Y16MTwQF4VHzjTAiiZFATgA8J88vQUjIPabi/kKjqSmcLFoaAOAxStQbW6e0z2GiQ6KBMcNF1y5iUuI63xVrBvtKrYX/w5y+ako8="
# Latest Release version
- TRAVIS_TAG=$(curl --fail --user ${GH_API_USER} -s https://api.github.com/repos/getgrav/grav/releases/latest | grep tag_name | head -n 1 | cut -d '"' -f 4)
- TRAVIS_TAG=$(curl --fail -s https://api.github.com/repos/getgrav/grav/releases/latest | grep tag_name | head -n 1 | cut -d '"' -f 4)
before_install:
- export TZ=Pacific/Honolulu
- echo $TRAVIS_PHP_VERSION
- echo $TRAVIS_BRANCH
- echo $TRAVIS_PULL_REQUEST
- composer self-update
- if [ $TRAVIS_BRANCH == 'develop' ]; then
- if [ $TRAVIS_BRANCH == 'develop' ] || [ $TRAVIS_PULL_REQUEST != 'false' ]; then
composer install --dev --prefer-dist;
fi
- if [ $TRAVIS_BRANCH != 'develop' ] && [ $TRAVIS_PHP_VERSION == '5.6' ] && [ $TRAVIS_PULL_REQUEST == "false" ]; then
- if [ $TRAVIS_BRANCH != 'develop' ] && [ $TRAVIS_PHP_VERSION == "5.6" ] && [ $TRAVIS_PULL_REQUEST == "false" ]; then
go get github.com/aktau/github-release;
git clone --quiet --depth=50 --branch=master https://${BB_TOKEN}bitbucket.org/rockettheme/grav-devtools.git $RT_DEVTOOLS &>/dev/null;
if [ ! -z "$TRAVIS_TAG" ]; then
@@ -61,10 +66,11 @@ before_install:
before_script:
- if [ $TRAVIS_PHP_VERSION != 'hhvm' ]; then phpenv config-rm xdebug.ini; fi
script:
- if [ $TRAVIS_BRANCH == 'develop' ]; then
- if [ $TRAVIS_BRANCH == 'develop' ] || [ $TRAVIS_PULL_REQUEST != 'false' ]; then
vendor/bin/codecept run;
fi
- if [ ! -z "$TRAVIS_TAG" ] && [ $TRAVIS_BRANCH != 'develop' ] && [ $TRAVIS_PHP_VERSION == '5.6' ] && [ $TRAVIS_PULL_REQUEST == "false" ]; then
- echo $TRAVIS_TAG
- if [ ! -z "$TRAVIS_TAG" ] && [ $TRAVIS_BRANCH != 'develop' ] && [ $TRAVIS_PHP_VERSION == "5.6" ] && [ $TRAVIS_PULL_REQUEST == "false" ]; then
FILES="$RT_DEVTOOLS/grav-dist/*.zip";
for file in ${FILES[@]}; do
NAME=${file##*/};

View File

@@ -1,8 +1,46 @@
# v1.0.9
## XX/XX/2016
## 02/05/2016
1. [](#new)
* New **Unit Testing** via Codeception http://codeception.com/
* New **page-level SSL** functionality when using `absolute_urls`
* Added `reverse_proxy` config option for issues with non-standard ports
* Added `proxy_url` config option to support GPM behind proxy servers #639
* New `Pages::parentsRawRoutes()` method
* Enhanced `bin/gpm info` CLI command with Changelog support #559
* Ability to add empty *Folder* via admin plugin
* Added latest `jQuery 2.2.0` library to core
* Added translations from Crowdin
1. [](#improved)
* [BC] Metadata now supports only flat arrays. To use open graph metas and the likes (ie, 'og:title'), simply specify it in the key.
* Refactored `Uri::convertUrl()` method to be more reliable + tests created
* Date for last update of a modular sub-page sets modified date of modular page itself
* Split configuration up into two steps
* Moved Grav-based `base_uri` variables into `Uri::init()`
* Refactored init in `URI` to better support testing
* Allow `twig_vars` to be exposed earlier and merged later
* Avoid setting empty metadata
* Accept single group access as a string rather than requiring an array
* Return `$this` in Page constructor and init to allow chaining
* Added `ext-*` PHP requirements to `composer.json`
* Use Whoops 2.0 library while supporting old style
* Removed redundant old default-hash fallback mechanisms
* Commented out default redirects and routes in `site.yaml`
* Added `/tests` folder to deny's of all `webserver-configs/*` files
* Various PS and code style fixes
1. [](#bugfix)
* Fix default generator metadata
* Fix for broken image processing caused by `Uri::convertUrl()` bugs
* Fix loading JS and CSS from collections #623
* Fix stream overriding
* Remove the URL extension for home link
* Fix permissions when the user has no access level set at all
* Fix issue with user with multiple groups getting denied on first group
* Fixed an issue with `Pages()` internal cache lookup not being unique enough
* Fix for bug with `site.redirects` and `site.routes` being an empty list
* [Markdown] Don't process links for **special protocols**
* [Whoops] serve JSON errors when request is JSON
# v1.0.8
## 01/08/2016

View File

@@ -1,6 +1,6 @@
# ![](https://avatars1.githubusercontent.com/u/8237355?v=2&s=50) Grav [![Build Status](https://travis-ci.org/getgrav/grav.svg?branch=develop)](https://travis-ci.org/getgrav/grav)
# ![](https://avatars1.githubusercontent.com/u/8237355?v=2&s=50) Grav
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/cfd20465-d0f8-4a0a-8444-467f5b5f16ad/mini.png)](https://insight.sensiolabs.com/projects/cfd20465-d0f8-4a0a-8444-467f5b5f16ad) [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/getgrav/grav?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/cfd20465-d0f8-4a0a-8444-467f5b5f16ad/mini.png)](https://insight.sensiolabs.com/projects/cfd20465-d0f8-4a0a-8444-467f5b5f16ad) [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/getgrav/grav?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://travis-ci.org/getgrav/grav.svg?branch=develop)](https://travis-ci.org/getgrav/grav)
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.

View File

@@ -39,6 +39,7 @@ if (!function_exists('curl_version')) {
$grav = Grav::instance(array('loader' => $autoload));
$grav['config']->init();
$grav['uri']->init();
$grav['streams'];
$app = new Application('Grav Package Manager', GRAV_VERSION);

View File

@@ -43,7 +43,8 @@
},
"scripts": {
"post-create-project-cmd": "bin/grav install",
"test": "vendor/bin/codecept run unit"
"test": "vendor/bin/codecept run unit",
"test-windows": "vendor\\bin\\codecept run unit"
},
"extra": {
"branch-alias": {

1525
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,7 @@ title: PLUGIN_ADMIN.FILE_STREAMS
form:
validation: loose
hidden: true
fields:
schemes.xxx:
type: array

View File

@@ -41,4 +41,4 @@ form:
label: PLUGIN_ADMIN.SITE_ACCESS
multiple: false
validate:
type: array
type: array

View File

@@ -115,4 +115,4 @@ session:
timeout: 1800 # Timeout in seconds
name: grav-site # Name prefix of the session cookie. Use alphanumeric, dashes or underscores only. Do not use dots in the session name
secure: false # Set session secure. If true, indicates that communication for this cookie must be over an encrypted transmission. Enable this only on sites that run exclusively on HTTPS
httponly: true # Set session HTTP only. If true, indicates that cookies should be used only over HTTP, and JavaScript modification is not allowed.
httponly: true # Set session HTTP only. If true, indicates that cookies should be used only over HTTP, and JavaScript modification is not allowed.

View File

@@ -2,7 +2,7 @@
// Some standard defines
define('GRAV', true);
define('GRAV_VERSION', '1.0.8');
define('GRAV_VERSION', '1.0.9');
define('DS', '/');
define('GRAV_PHP_MIN', '5.5.9');

View File

@@ -1,39 +1,79 @@
INFLECTOR_UNCOUNTABLE:
- vybavení
- informace
- rýže
- peníze
- druhy
- série
- ryba
- ovce
INFLECTOR_IRREGULAR:
person: lidé
man: muži
child: děti
sex: pohlaví
move: pohyby
INFLECTOR_ORDINALS:
default: '.'
first: '.'
second: '.'
third: '.'
NICETIME:
NO_DATE_PROVIDED: Datum nebylo vloženo
BAD_DATE: Chybné datum
AGO: zpět
FROM_NOW: od teď
SECOND: sekunda
MINUTE: minuta
HOUR: hodina
DAY: den
WEEK: týden
MONTH: měsíc
YEAR: rok
DECADE: dekáda
SEC: sek
MIN: min
HR: hod
DAY: den
WK: t
MO: m
YR: r
DEC: dek
SECOND_PLURAL: sekundy
MINUTE_PLURAL: minuty
HOUR_PLURAL: hodiny
DAY_PLURAL: dny
WEEK_PLURAL: týdny
MONTH_PLURAL: měsíce
YEAR_PLURAL: roky
DECADE_PLURAL: dekády
SEC_PLURAL: sek
MIN_PLURAL: min
HR_PLURAL: hod
DAY_PLURAL: dny
WK_PLURAL: t
MO_PLURAL: m
YR_PLURAL: r
DEC_PLURAL: dek
MONTHS_OF_THE_YEAR: ['Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec']
DAYS_OF_THE_WEEK: ['Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota', 'Neděle']
NO_DATE_PROVIDED: Datum nebylo vloženo
BAD_DATE: Chybné datum
AGO: zpět
FROM_NOW: od teď
SECOND: sekunda
MINUTE: minuta
HOUR: hodina
DAY: den
WEEK: týden
MONTH: měsíc
YEAR: rok
DECADE: dekáda
SEC: sek
MIN: min
HR: hod
WK: t
MO: m
YR: r
DEC: dek
SECOND_PLURAL: sekundy
MINUTE_PLURAL: minuty
HOUR_PLURAL: hodiny
DAY_PLURAL: dny
WEEK_PLURAL: dny
MONTH_PLURAL: měsíce
YEAR_PLURAL: roky
DECADE_PLURAL: dekády
SEC_PLURAL: sek
MIN_PLURAL: min
HR_PLURAL: hod
WK_PLURAL: t
MO_PLURAL: m
YR_PLURAL: r
DEC_PLURAL: dek
FORM:
VALIDATION_FAIL: '<b>Ověření se nezdařilo:</b>'
MISSING_REQUIRED_FIELD: 'Chybí požadované pole:'
MONTHS_OF_THE_YEAR:
- ledna
- února
- března
- dubna
- května
- června
- července
- srpna
- září
- října
- listopadu
- prosince
DAYS_OF_THE_WEEK:
- Pondělí
- Úterý
- Středa
- Čtvrtek
- Pátek
- Sobota
- Neděle

View File

@@ -1,45 +1,82 @@
FRONTMATTER_ERROR_PAGE: |
---
title: %1$s
---
# Fehler: Frontmatter enthält Fehler
Pfad: `%2$s`
**%3$s **
```
%4$s
```
INFLECTOR_UNCOUNTABLE:
1: Informationen
2: Reis
3: Geld
INFLECTOR_IRREGULAR:
'person': 'Personen'
'man': 'Menschen'
'child': 'Kinder'
'sex': 'Geschlecht'
'move': 'Züge'
person: Personen
man: Menschen
child: Kinder
sex: Geschlecht
move: Züge
NICETIME:
NO_DATE_PROVIDED: Keine Daten vorhanden
BAD_DATE: Falsches Datum
AGO: her
FROM_NOW: ab jetzt
SECOND: Sekunde
MINUTE: Minute
HOUR: Stunde
DAY: Tag
WEEK: Woche
MONTH: Monat
YEAR: Jahr
DECADE: Dekade
SEC: sek
MIN: min
HR: std
DAY: Tag
WK: wo
MO: mo
YR: yh
DEC: dec
SECOND_PLURAL: Sekunden
MINUTE_PLURAL: Minuten
HOUR_PLURAL: Stunden
DAY_PLURAL: Tage
WEEK_PLURAL: Wochen
MONTH_PLURAL: Monate
YEAR_PLURAL: Jahre
DECADE_PLURAL: Dekaden
SEC_PLURAL: Sekunden
MIN_PLURAL: Minuten
HR_PLURAL: Stunden
DAY_PLURAL: Tage
WK_PLURAL: Wochen
MO_PLURAL: Monate
YR_PLURAL: Jahre
DEC_PLURAL: Dekaden
MONTHS_OF_THE_YEAR: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember']
DAYS_OF_THE_WEEK: ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag']
NO_DATE_PROVIDED: Keine Daten vorhanden
BAD_DATE: Falsches Datum
AGO: her
FROM_NOW: ab jetzt
SECOND: Sekunde
MINUTE: Minute
HOUR: Stunde
DAY: Tag
WEEK: Woche
MONTH: Monat
YEAR: Jahr
DECADE: Dekade
SEC: sek
MIN: Min
HR: std
WK: wo
YR: yh
DEC: Jz
SECOND_PLURAL: Sekunden
MINUTE_PLURAL: Minuten
HOUR_PLURAL: Stunden
DAY_PLURAL: Tage
WEEK_PLURAL: Wochen
MONTH_PLURAL: Monate
YEAR_PLURAL: Jahre
DECADE_PLURAL: Dekaden
SEC_PLURAL: Sekunden
MIN_PLURAL: Minuten
HR_PLURAL: Stunden
WK_PLURAL: Wochen
MO_PLURAL: Monate
YR_PLURAL: Jahre
DEC_PLURAL: Dekaden
FORM:
VALIDATION_FAIL: '<b>Überprüfung fehlgeschlagen:</b>'
INVALID_INPUT: Ungültige Eingabe in
MISSING_REQUIRED_FIELD: 'Erforderliches Feld fehlt:'
MONTHS_OF_THE_YEAR:
- Januar
- Februar
- März
- April
- Mai
- Juni
- Juli
- August
- Semptember
- Oktober
- November
- Dezember
DAYS_OF_THE_WEEK:
- Montag
- Dienstag
- Mittwoch
- Donnerstag
- Freitag
- Samstag
- Sonntag

View File

@@ -1,2 +1,21 @@
MONTHS_OF_THE_YEAR: ['Ιανουάριος', 'Φεβρουάριος', 'Μάρτιος', 'Απρίλιος', 'Μάιος', 'Ιούνιος', 'Ιούλιος', 'Αύγουστος', 'Σεπτέμβριος', 'Οκτώβριος', 'Νοέμβριος', 'Δεκέμβριος']
DAYS_OF_THE_WEEK: ['Δευτέρα', 'Τρλιτη', 'Τετάρτη', 'Πέμπτη', 'Παρασκευή', 'Σαββάτο', 'Κυριακή']
MONTHS_OF_THE_YEAR:
- Ιανουάριος
- Φεβρουάριος
- Μάρτιος
- Απρίλιος
- Μάιος
- Ιούνιος
- Ιούλιος
- Αύγουστος
- Σεπτέμβριος
- Οκτώβριος
- Νοέμβριος
- Δεκέμβριος
DAYS_OF_THE_WEEK:
- Δευτέρα
- Τρλιτη
- Τετάρτη
- Πέμπτη
- Παρασκευή
- Σαββάτο
- Κυριακή

View File

@@ -1,44 +1,75 @@
INFLECTOR_UNCOUNTABLE:
0: equipo
1: información
3: dinero
5: series
6: pescado
7: oveja
INFLECTOR_IRREGULAR:
man: hombres
child: niños
sex: sexos
INFLECTOR_ORDINALS:
first: ro
second: do
third: ro
NICETIME:
NO_DATE_PROVIDED: No se proporcionó fecha
BAD_DATE: Fecha erronea
AGO: antes
FROM_NOW: desde ahora
SECOND: segundo
MINUTE: minuto
HOUR: hora
DAY: dia
WEEK: semana
MONTH: mes
YEAR: año
DECADE: decada
SEC: seg
MIN: min
HR: hr
DAY: dia
WK: sem
MO: mes
YR: yr
DEC: dec
SECOND_PLURAL: segundos
MINUTE_PLURAL: minutos
HOUR_PLURAL: horas
DAY_PLURAL: as
WEEK_PLURAL: semanas
MONTH_PLURAL: meses
YEAR_PLURAL: años
DECADE_PLURAL: decadas
SEC_PLURAL: segs
MIN_PLURAL: mins
HR_PLURAL: hrs
DAY_PLURAL: dias
WK_PLURAL: sem
MO_PLURAL: mes
YR_PLURAL: años
DEC_PLURAL: decs
NO_DATE_PROVIDED: No se proporcionó fecha
BAD_DATE: Fecha erronea
AGO: antes
FROM_NOW: desde ahora
SECOND: segundo
MINUTE: minuto
HOUR: hora
DAY: día
WEEK: semana
MONTH: mes
YEAR: año
DECADE: década
SEC: seg
MIN: min
HR: h
WK: sem
MO: mes
YR: año
DEC: dec
SECOND_PLURAL: segundos
MINUTE_PLURAL: minutos
HOUR_PLURAL: horas
DAY_PLURAL: as
WEEK_PLURAL: semanas
MONTH_PLURAL: meses
YEAR_PLURAL: años
DECADE_PLURAL: décadas
SEC_PLURAL: segs
MIN_PLURAL: mins
HR_PLURAL: hs
WK_PLURAL: sem
MO_PLURAL: mes
YR_PLURAL: años
DEC_PLURAL: décadas
FORM:
VALIDATION_FAIL: <b>Falló la validación. </b>
INVALID_INPUT: "Dato inválido en: "
MISSING_REQUIRED_FIELD: "Falta el campo requerido: "
MONTHS_OF_THE_YEAR: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Augosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']
DAYS_OF_THE_WEEK: ['Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado', 'Domingo']
VALIDATION_FAIL: '<b>Falló la validación. </b>'
INVALID_INPUT: 'Dato inválido en: '
MISSING_REQUIRED_FIELD: 'Falta el campo requerido: '
MONTHS_OF_THE_YEAR:
- Enero
- Febrero
- Marzo
- Abril
- Mayo
- Junio
- Julio
- Agosto
- Septiembre
- Octubre
- Noviembre
- Diciembre
DAYS_OF_THE_WEEK:
- Lunes
- Martes
- Miércoles
- Jueves
- Viernes
- Sábado
- Domingo

View File

@@ -1,2 +0,0 @@
MONTHSOFTHE_YEAR: ['Tammikuu', 'Helmikuu', 'Maaliskuu', 'Huhtikuu', 'Toukokuu', 'Kesäkuu', 'Heinäkuu', 'Elokuu', 'Syyskuu', 'Lokakuu', 'Marraskuu', 'Joulukuu']
DAYSOFTHE_WEEK: ['Maanantai', 'Tiistai', 'Keskiviikko', 'Torstai', 'Perjantai', 'Lauantai', 'Sunnuntai']

View File

@@ -1,100 +1,137 @@
FRONTMATTER_ERROR_PAGE: "---\ntitle: %1$s\n---\n\n# Erreur : Frontmatter invalide\n\nPath: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
FRONTMATTER_ERROR_PAGE: |
---
title: %1$s
---
# Erreur : Frontmatter invalide
Path: `%2$s`
**%3$s**
```
%4$s
```
INFLECTOR_PLURALS:
'/(quiz)$/i': '\1zes'
'/^(ox)$/i': '\1en'
'/([m|l])ouse$/i': '\1ice'
'/(matr|vert|ind)ix|ex$/i': '\1ices'
'/(x|ch|ss|sh)$/i': '\1es'
'/([^aeiouy]|qu)ies$/i': '\1y'
'/([^aeiouy]|qu)y$/i': '\1ies'
'/(hive)$/i': '\1s'
'/(?:([^f])fe|([lr])f)$/i': '\1\2ves'
'/sis$/i': 'ses'
'/([ti])um$/i': '\1a'
'/(buffal|tomat)o$/i': '\1oes'
'/(bu)s$/i': '\1ses'
'/(alias|status)/i': '\1es'
'/(octop|vir)us$/i': '\1i'
'/(ax|test)is$/i': '\1es'
'/s$/i': 's'
'/$/': 's'
/(quiz)$/i: '\1zes'
/^(ox)$/i: '\1en'
"/([m|l])ouse$/i": '\1ice'
/(matr|vert|ind)ix|ex$/i: '\1ices'
/(x|ch|ss|sh)$/i: '\1es'
"/([^aeiouy]|qu)ies$/i": '\1y'
"/([^aeiouy]|qu)y$/i": '\1ies'
/(hive)$/i: '\1s'
"/(?:([^f])fe|([lr])f)$/i": '\1\2ves'
/sis$/i: ses
"/([ti])um$/i": '\1a'
/(buffal|tomat)o$/i: '\1oes'
/(bu)s$/i: '\1ses'
/(alias|status)/i: '\1es'
/(octop|vir)us$/i: '\1i'
/(ax|test)is$/i: '\1es'
/s$/i: s
/$/: s
INFLECTOR_SINGULAR:
'/(quiz)zes$/i': '\1'
'/(matr)ices$/i': '\1ix'
'/(vert|ind)ices$/i': '\1ex'
'/^(ox)en/i': '\1'
'/(alias|status)es$/i': '\1'
'/([octop|vir])i$/i': '\1us'
'/(cris|ax|test)es$/i': '\1is'
'/(shoe)s$/i': '\1'
'/(o)es$/i': '\1'
'/(bus)es$/i': '\1'
'/([m|l])ice$/i': '\1ouse'
'/(x|ch|ss|sh)es$/i': '\1'
'/(m)ovies$/i': '\1ovie'
'/(s)eries$/i': '\1eries'
'/([^aeiouy]|qu)ies$/i': '\1y'
'/([lr])ves$/i': '\1f'
'/(tive)s$/i': '\1'
'/(hive)s$/i': '\1'
'/([^f])ves$/i': '\1fe'
'/(^analy)ses$/i': '\1sis'
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i': '\1\2sis'
'/([ti])a$/i': '\1um'
'/(n)ews$/i': '\1ews'
'/s$/i': ''
INFLECTOR_UNCOUNTABLE: ['équipement', 'information', 'riz', 'argent', 'espèces', 'séries', 'poisson', 'mouton']
/(quiz)zes$/i: '\1'
/(matr)ices$/i: '\1ix'
/(vert|ind)ices$/i: '\1ex'
/^(ox)en/i: '\1'
/(alias|status)es$/i: '\1'
"/([octop|vir])i$/i": '\1us'
/(cris|ax|test)es$/i: '\1is'
/(shoe)s$/i: '\1'
/(o)es$/i: '\1'
/(bus)es$/i: '\1'
"/([m|l])ice$/i": '\1ouse'
/(x|ch|ss|sh)es$/i: '\1'
/(m)ovies$/i: '\1ovie'
/(s)eries$/i: '\1eries'
"/([^aeiouy]|qu)ies$/i": '\1y'
"/([lr])ves$/i": '\1f'
/(tive)s$/i: '\1'
/(hive)s$/i: '\1'
"/([^f])ves$/i": '\1fe'
/(^analy)ses$/i: '\1sis'
/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i: '\1\2sis'
"/([ti])a$/i": '\1um'
/(n)ews$/i: '\1ews'
INFLECTOR_UNCOUNTABLE:
- équipement
- informations
- riz
- argent
- espèces
- séries
- poisson
- mouton
INFLECTOR_IRREGULAR:
'person': 'personnes'
'man': 'hommes'
'child': 'enfants'
'sex': 'sexes'
'move': 'déplacements'
person: personnes
man: hommes
child: enfants
sex: sexes
move: déplacements
INFLECTOR_ORDINALS:
'default': 'ème'
'first': 'er'
'second': 'nd'
'third': 'ème'
default: ème
first: er
second: ème
third: ème
NICETIME:
NO_DATE_PROVIDED: Aucune date
BAD_DATE: Date erronée
AGO: plus tôt
FROM_NOW: à partir de maintenant
SECOND: seconde
MINUTE: minute
HOUR: heure
DAY: jour
WEEK: semaine
MONTH: mois
YEAR: an
DECADE: décennie
SEC: s
MIN: m
HR: h
DAY: j
WK: s
MO: m
YR: a
DEC: d
SECOND_PLURAL: secondes
MINUTE_PLURAL: minutes
HOUR_PLURAL: heures
DAY_PLURAL: jours
WEEK_PLURAL: semaines
MONTH_PLURAL: mois
YEAR_PLURAL: années
DECADE_PLURAL: décennies
SEC_PLURAL: s
MIN_PLURAL: m
HR_PLURAL: h
DAY_PLURAL: j
WK_PLURAL: s
MO_PLURAL: m
YR_PLURAL: a
DEC_PLURAL: d
NO_DATE_PROVIDED: Aucune date fournie
BAD_DATE: Date erronée
AGO: plus tôt
FROM_NOW: à partir de maintenant
SECOND: seconde
MINUTE: minute
HOUR: heure
DAY: jour
WEEK: semaine
MONTH: mois
YEAR: année
DECADE: décennie
SEC: s
MIN: m
HR: h
WK: sem
MO: m
YR: an
DEC: déc
SECOND_PLURAL: secondes
MINUTE_PLURAL: minutes
HOUR_PLURAL: heures
DAY_PLURAL: jours
WEEK_PLURAL: semaines
MONTH_PLURAL: mois
YEAR_PLURAL: années
DECADE_PLURAL: décennies
SEC_PLURAL: s
MIN_PLURAL: m
HR_PLURAL: h
WK_PLURAL: sem
MO_PLURAL: mois
YR_PLURAL: a
DEC_PLURAL: décs
FORM:
VALIDATION_FAIL: <b>La validation a échoué :</b>
INVALID_INPUT: Saisie non valide
MISSING_REQUIRED_FIELD: Champ obligatoire manquant :
MONTHS_OF_THE_YEAR: ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']
DAYS_OF_THE_WEEK: ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche']
VALIDATION_FAIL: '<b>La validation a échoué :</b>'
INVALID_INPUT: Saisie non valide
MISSING_REQUIRED_FIELD: 'Champ obligatoire manquant :'
MONTHS_OF_THE_YEAR:
- Janvier
- Février
- Mars
- Avril
- Mai
- Juin
- Juillet
- Août
- Septembre
- Octobre
- Novembre
- Décembre
DAYS_OF_THE_WEEK:
- Lundi
- Mardi
- Mercredi
- Jeudi
- Vendredi
- Samedi
- Dimanche

View File

@@ -1,54 +1,74 @@
INFLECTOR_UNCOUNTABLE:
- oprema
- informacije
- riža
- novac
- vrsta
- serija
- riba
- ovca
INFLECTOR_IRREGULAR:
'person': 'Osoba'
'man': 'Čovjek'
'child': 'Dijete'
'sex': 'Spol'
'move': 'Pomakni'
person: osobe
man: ljudi
child: djeca
sex: spolovi
move: Pomakni
NICETIME:
NO_DATE_PROVIDED: Datum nije upisan
BAD_DATE: Pogrešan datum
AGO: prije
FROM_NOW: od sad
SECOND: sekundi
MINUTE: minuta
HOUR: godina
DAY: dan
WEEK: tjedan
MONTH: mjesec
YEAR: godina
DECADE: desetljeće
SEC: sek
MIN: min
HR: sat
DAY: dan
WK: t
MO: m
YR: g
DEC: des
SECOND_PLURAL: sekundi
SECOND_PLURAL_MORE_THAN_TWO: sekunde
MINUTE_PLURAL: minuta
MINUTE_PLURAL_MORE_THAN_TWO: minute
HOUR_PLURAL: sati
HOUR_PLURAL_MORE_THAN_TWO: sata
DAY_PLURAL: dana
WEEK_PLURAL: tjedana
WEEK_PLURAL_MORE_THAN_TWO: tjedna
MONTH_PLURAL: mjeseci
MONTH_PLURAL_MORE_THAN_TWO: mjeseca
YEAR_PLURAL: godina
YEAR_PLURAL_MORE_THAN_TWO: godine
DECADE_PLURAL: desetljeća
SEC_PLURAL: sek
MIN_PLURAL: min
HR_PLURAL: sat
DAY_PLURAL: dan
WK_PLURAL: t
MO_PLURAL: m
YR_PLURAL: g
DEC_PLURAL: des
NO_DATE_PROVIDED: Datum nije upisan
BAD_DATE: Pogrešan datum
AGO: prije
FROM_NOW: od sada
SECOND: sekunda
MINUTE: minuta
HOUR: sat
DAY: dan
WEEK: tjedan
MONTH: mjesec
YEAR: godina
DECADE: desetljeće
SEC: sek
HR: sat
WK: t
MO: m
YR: g
DEC: des
SECOND_PLURAL: sekundi
MINUTE_PLURAL: minuta
HOUR_PLURAL: sati
DAY_PLURAL: dan
WEEK_PLURAL: tjedana
MONTH_PLURAL: mjeseci
YEAR_PLURAL: godina
DECADE_PLURAL: desetljeća
SEC_PLURAL: sek
MIN_PLURAL: min
HR_PLURAL: sat
WK_PLURAL: t
MO_PLURAL: m
YR_PLURAL: g
DEC_PLURAL: des
FORM:
VALIDATION_FAIL: <b>Validacija nije uspjela:</b>
INVALID_INPUT: Unos nije valjan
MONTHS_OF_THE_YEAR: ['Siječanj', 'Veljača', 'Ožujak', 'Travanj', 'Svibanj', 'Lipanj', 'Srpanj', 'Kolovoz', 'Rujan', 'Listopad', 'Studeni', 'Prosinac']
DAYS_OF_THE_WEEK: ['ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota', 'nedjelja']
VALIDATION_FAIL: '<b>Validacija nije uspjela:</b>'
INVALID_INPUT: Pogrešan unos u
MISSING_REQUIRED_FIELD: 'Nedostaje obavezno polje:'
MONTHS_OF_THE_YEAR:
- Siječanj
- Veljača
- Ožujak
- Travanj
- Svibanj
- Lipanj
- Srpanj
- Kolovoz
- Rujan
- Listopad
- Studeni
- Prosinac
DAYS_OF_THE_WEEK:
- Ponedjeljak
- Utorak
- Srijeda
- Četvrtak
- Petak
- Subota
- Nedjelja

View File

@@ -1,53 +1,64 @@
FRONTMATTER_ERROR_PAGE: "---\ncím: %1$s\n---\n\n# Hiba: Érvénytelen Frontmatter\n\nElérési út: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
FRONTMATTER_ERROR_PAGE: |
---
cím: %1$s
---
# Hiba: Érvénytelen Frontmatter
Elérési út: `%2$s`
**%3$s**
```
%4$s
```
INFLECTOR_IRREGULAR:
'person': 'személyek'
'man': 'férfiak'
'child': 'gyerekek'
'sex': 'nemek'
'move': 'lépések'
person: személyek
man: férfiak
child: gyerekek
sex: nemek
move: lépések
INFLECTOR_ORDINALS:
'default': '.'
'first': '.'
'second': '.'
'third': '.'
default: '.'
first: '.'
second: '.'
third: '.'
NICETIME:
NO_DATE_PROVIDED: Nincs dátum megadva
BAD_DATE: Hibás dátum
AGO: elteltével
FROM_NOW: mostantól
SECOND: másodperc
MINUTE: perc
HOUR: óra
DAY: nap
WEEK: hét
MONTH: hónap
YEAR: év
DECADE: évtized
SEC: mp
MIN: p
HR: ó
DAY: nap
WK: hét
MO:
YR: év
DEC: évt
SECOND_PLURAL: másodperc
MINUTE_PLURAL: perc
HOUR_PLURAL: óra
DAY_PLURAL: nap
WEEK_PLURAL: hét
MONTH_PLURAL: hónap
YEAR_PLURAL: év
DECADE_PLURAL: évtized
SEC_PLURAL: mp
MIN_PLURAL: perc
HR_PLURAL: ó
DAY_PLURAL: nap
WK_PLURAL: hét
MO_PLURAL:
YR_PLURAL: év
DEC_PLURAL: évt
NO_DATE_PROVIDED: Nincs dátum megadva
BAD_DATE: Hibás dátum
AGO: elteltével
FROM_NOW: mostantól
SECOND: másodperc
MINUTE: perc
HOUR: óra
DAY: nap
WEEK: hét
MONTH: hónap
YEAR: év
DECADE: évtized
SEC: mp
MIN: p
HR: ó
WK: hét
MO: hó
YR: év
DEC: évt
SECOND_PLURAL: másodperc
MINUTE_PLURAL: perc
HOUR_PLURAL: óra
DAY_PLURAL: nap
WEEK_PLURAL: hét
MONTH_PLURAL: hónap
YEAR_PLURAL: év
DECADE_PLURAL: évtized
SEC_PLURAL: mp
MIN_PLURAL: perc
HR_PLURAL: ó
WK_PLURAL: hét
MO_PLURAL:
YR_PLURAL: év
DEC_PLURAL: évt
FORM:
VALIDATION_FAIL: <b>A validáció hibát talált:</b>
INVALID_INPUT: Az itt megadott érték érvénytelen:
MISSING_REQUIRED_FIELD: Ez a kötelező mező nincs kitöltve:
VALIDATION_FAIL: '<b>A validáció hibát talált:</b>'
INVALID_INPUT: 'Az itt megadott érték érvénytelen:'
MISSING_REQUIRED_FIELD: 'Ez a kötelező mező nincs kitöltve:'

View File

@@ -1,27 +1,45 @@
NICETIME:
NO_DATE_PROVIDED: Nessuna data fornita
BAD_DATE: Data errata
AGO: fa
FROM_NOW: da adesso
SECOND: secondo
MINUTE: minuto
HOUR: ora
DAY: giorno
WEEK: settimana
MONTH: mese
YEAR: anno
DECADE: decade
SECOND_PLURAL: secondi
MINUTE_PLURAL: minuti
HOUR_PLURAL: ore
DAY_PLURAL: giorni
WEEK_PLURAL: settimane
MONTH_PLURAL: mesi
YEAR_PLURAL: anni
DECADE_PLURAL: decadi
NO_DATE_PROVIDED: Nessuna data fornita
BAD_DATE: Data errata
AGO: fa
FROM_NOW: da adesso
SECOND: secondo
MINUTE: minuto
HOUR: ora
DAY: giorno
WEEK: settimana
MONTH: mese
YEAR: anno
SECOND_PLURAL: secondi
MINUTE_PLURAL: minuti
HOUR_PLURAL: ore
DAY_PLURAL: giorni
WEEK_PLURAL: settimane
MONTH_PLURAL: mesi
YEAR_PLURAL: anni
DECADE_PLURAL: decadi
FORM:
VALIDATION_FAIL: <b>Validazione fallita:</b>
INVALID_INPUT: Input invalido in
MISSING_REQUIRED_FIELD: Campo richiesto mancante:
MONTHS_OF_THE_YEAR: ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre']
DAYS_OF_THE_WEEK: ['Lunedi', 'Martedi', 'Mercoledi', 'Giovedi', 'Venerdi', 'Sabato', 'Domenica']
VALIDATION_FAIL: '<b>Validazione fallita:</b>'
INVALID_INPUT: Input invalido in
MISSING_REQUIRED_FIELD: 'Campo richiesto mancante:'
MONTHS_OF_THE_YEAR:
- Gennaio
- Febbraio
- Marzo
- Aprile
- Maggio
- Giugno
- Luglio
- Agosto
- Settembre
- Ottobre
- Novembre
- Dicembre
DAYS_OF_THE_WEEK:
- Lunedi
- Martedi
- Mercoledi
- Giovedi
- Venerdi
- Sabato
- Domenica

59
system/languages/ja.yaml Normal file
View File

@@ -0,0 +1,59 @@
FRONTMATTER_ERROR_PAGE: "---\ntitle: %1$s\n---\n\n# Error: Invalid Frontmatter\n\nPath: `%2$s`\n\n**%3$s**\n\n```\n%4$s\n```"
INFLECTOR_PLURALS: []
INFLECTOR_SINGULAR: []
INFLECTOR_UNCOUNTABLE: []
INFLECTOR_IRREGULAR:
'person': 'みんな'
'man': '人'
'child': '子供'
'sex': '性別'
'move': '移動'
INFLECTOR_ORDINALS: []
NICETIME:
NO_DATE_PROVIDED: 日付が設定されていません
BAD_DATE: 不正な日付
AGO:
FROM_NOW: from now
SECOND:
MINUTE:
HOUR:
DAY:
WEEK:
MONTH:
YEAR:
DECADE: 10年
SEC:
MIN:
HR:
DAY:
WK:
MO:
YR:
DEC: dec
SECOND_PLURAL:
MINUTE_PLURAL:
HOUR_PLURAL:
DAY_PLURAL:
WEEK_PLURAL:
MONTH_PLURAL:
YEAR_PLURAL:
DECADE_PLURAL: 10年
SEC_PLURAL:
MIN_PLURAL:
HR_PLURAL:
DAY_PLURAL:
WK_PLURAL:
MO_PLURAL:
YR_PLURAL:
DEC_PLURAL: 10年
FORM:
VALIDATION_FAIL: <b>バリデーション失敗 :</b>
INVALID_INPUT: 不正な入力:
MISSING_REQUIRED_FIELD: 必須項目が入力されていません:
MONTHS_OF_THE_YEAR: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
DAYS_OF_THE_WEEK: ['月', '火', '水', '木', '金', '土', '日']

68
system/languages/lt.yaml Normal file
View File

@@ -0,0 +1,68 @@
INFLECTOR_UNCOUNTABLE:
2: ryžiai
3: pinigai
4: prieskoniai
5: serijos
6: žuvis
7: avis
INFLECTOR_IRREGULAR:
person: žmonės
man: žmogus
child: vaikai
sex: lytys
move: juda
NICETIME:
NO_DATE_PROVIDED: Nenurodyta data
BAD_DATE: Neteisinga data
AGO: prieš
FROM_NOW: nuo dabar
SECOND: sekundė
MINUTE: minutė
HOUR: valanda
DAY: diena
WEEK: savaitė
MONTH: mėnuo
YEAR: metai
DECADE: dešimtmetis
SEC: sek
MIN: min
HR: val
WK: sav
MO: mėn
YR: m
MINUTE_PLURAL: minutės
HOUR_PLURAL: valandos
DAY_PLURAL: dienos
WEEK_PLURAL: savaitės
MONTH_PLURAL: mėnesiai
YEAR_PLURAL: metai
DECADE_PLURAL: dešimtmečiai
SEC_PLURAL: sek
MIN_PLURAL: min
HR_PLURAL: val
WK_PLURAL: sav
MO_PLURAL: mėn
YR_PLURAL: m
FORM:
MISSING_REQUIRED_FIELD: 'Būtina užpildyti laukelį:'
MONTHS_OF_THE_YEAR:
- Sausis
- Vasaris
- Kovas
- Balandis
- Gegužė
- Birželis
- Liepa
- Rugpjūtis
- Rugsėjis
- Spalis
- Lakpritis
- Gruodis
DAYS_OF_THE_WEEK:
- Pirmadienis
- Antradienis
- Trečiadienis
- Ketvirtadienis
- Penktadienis
- Šeštadienis
- Sekmadienis

View File

@@ -1,45 +1,50 @@
INFLECTOR_IRREGULAR:
'person': 'personen'
'man': 'mensen'
'child': 'kinderen'
'sex': 'geslacht'
'move': 'verplaatsen'
person: personen
man: mensen
child: kinderen
sex: geslacht
move: verplaatsen
NICETIME:
NO_DATE_PROVIDED: geen datum opgegeven
BAD_DATE: Datumformaat onjuist
AGO: geleden
FROM_NOW: vanaf nu
SECOND: seconde
MINUTE: minuut
HOUR: uur
DAY: dag
WEEK: week
MONTH: maand
YEAR: jaar
DECADE: decenium
SEC: sec
MIN: min
HR: hr
DAY: dag
WK: wk
MO: ma
YR: yr
DEC: dec
SECOND_PLURAL: seconden
MINUTE_PLURAL: minuten
HOUR_PLURAL: uren
DAY_PLURAL: dagen
WEEK_PLURAL: weken
MONTH_PLURAL: maanden
YEAR_PLURAL: jaren
DECADE_PLURAL: decennia
SEC_PLURAL: seconden
MIN_PLURAL: minuten
HR_PLURAL: uren
DAY_PLURAL: dagen
WK_PLURAL: weken
MO_PLURAL: maanden
YR_PLURAL: jaren
DEC_PLURAL: decs
MONTHS_OF_THE_YEAR: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December']
DAYS_OF_THE_WEEK: ['Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag', 'Zaterdag', 'Zondag']
NO_DATE_PROVIDED: geen datum opgegeven
BAD_DATE: Datumformaat onjuist
AGO: geleden
FROM_NOW: vanaf nu
SECOND: seconde
MINUTE: minuut
HOUR: uur
DAY: dag
MONTH: maand
YEAR: jaar
DECADE: decenium
MO: ma
SECOND_PLURAL: seconden
MINUTE_PLURAL: minuten
HOUR_PLURAL: uren
DAY_PLURAL: dagen
WEEK_PLURAL: weken
MONTH_PLURAL: maanden
YEAR_PLURAL: jaren
DECADE_PLURAL: decennia
SEC_PLURAL: seconden
MIN_PLURAL: minuten
HR_PLURAL: uren
WK_PLURAL: weken
MO_PLURAL: maanden
YR_PLURAL: jaren
MONTHS_OF_THE_YEAR:
0: Januari
1: Februari
2: Maart
4: Mei
5: Juni
6: Juli
7: Augustus
9: Oktober
DAYS_OF_THE_WEEK:
- Maandag
- Dinsdag
- Woensdag
- Donderdag
- Vrijdag
- Zaterdag
- Zondag

90
system/languages/no.yaml Normal file
View File

@@ -0,0 +1,90 @@
FRONTMATTER_ERROR_PAGE: |
---
Tittel: %1$s
---
# Feilmelding: Ugyldig Frontmatter
Pane: '%2$s'
**%3$s **
```
%4$s
```
INFLECTOR_PLURALS:
/(quiz)$/i: '\1zes'
/^(ox)$/i: '\1en'
INFLECTOR_UNCOUNTABLE:
- utstyr
- informasjon
- ris
- penger
- arter
- serier
- fisk
- sau
INFLECTOR_IRREGULAR:
person: folk
man: menn
child: barn
sex: kjønn
move: trekk
NICETIME:
NO_DATE_PROVIDED: Ingen dato gitt
BAD_DATE: Dårlig dato
AGO: siden
FROM_NOW: fra nå
SECOND: sekund
MINUTE: minutt
HOUR: time
DAY: dag
WEEK: uke
MONTH: måned
YEAR: år
DECADE: tiår
SEC: sek
MIN: min
HR: t
WK: uke
MO:
YR: år
DEC: des
SECOND_PLURAL: sekunder
MINUTE_PLURAL: minutter
HOUR_PLURAL: timer
DAY_PLURAL: dager
WEEK_PLURAL: uker
MONTH_PLURAL: måneder
YEAR_PLURAL: år
DECADE_PLURAL: tiår
SEC_PLURAL: sek
MIN_PLURAL: min
HR_PLURAL: timer
WK_PLURAL: uker
YR_PLURAL: år
FORM:
VALIDATION_FAIL: '<b>Validering mislyktes:</b>'
INVALID_INPUT: Ugyldig innhold i
MISSING_REQUIRED_FIELD: 'Mangler påkrevd felt:'
MONTHS_OF_THE_YEAR:
- januar
- februar
- mars
- april
- mai
- juni
- juli
- august
- september
- oktober
- november
- desember
DAYS_OF_THE_WEEK:
- mandag
- tirsdag
- onsdag
- torsdag
- fredag
- lørdag
- søndag

View File

@@ -1,2 +1,74 @@
MONTHS_OF_THE_YEAR: ['Styczeń', 'Luty', 'Marzec', 'Kwiecień', 'Maj', 'Czerwiec', 'Lipiec', 'Sierpień', 'Wrzesień', 'Październik', 'Listopad', 'Grudzień']
DAYS_OF_THE_WEEK: ['Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota', 'Niedziela']
FRONTMATTER_ERROR_PAGE: |
---
title: %1$s
---
# Error: Nieprawidłowy Frontmatter
Path: `%2$s`
**%3$s**
```
%4$s
```
NICETIME:
NO_DATE_PROVIDED: Nie podano daty
BAD_DATE: Zła data
AGO: temu
FROM_NOW: od teraz
SECOND: sekunda
MINUTE: minuta
HOUR: godzina
DAY: dzień
WEEK: tydzień
MONTH: miesiąc
YEAR: rok
DECADE: dekada
SEC: sek
MIN: min
HR: godz
WK: tydź
MO: mieś
YR: rok
DEC: dekada
SECOND_PLURAL: sekund
MINUTE_PLURAL: minut
HOUR_PLURAL: godzin
DAY_PLURAL: dni
WEEK_PLURAL: tygodnie
MONTH_PLURAL: miesięcy
YEAR_PLURAL: lat
DECADE_PLURAL: dekad
SEC_PLURAL: sekund
MIN_PLURAL: minut
HR_PLURAL: godz
WK_PLURAL: tyg
MO_PLURAL: mieś
YR_PLURAL: lat
DEC_PLURAL: dekad
FORM:
VALIDATION_FAIL: '<b>Weryfikacja nie powiodła się:</b>'
INVALID_INPUT: Nieprawidłowe dane w
MISSING_REQUIRED_FIELD: 'Opuszczono wymagane pole:'
MONTHS_OF_THE_YEAR:
- Styczeń
- Luty
- Marzec
- Kwiecień
- Maj
- Czerwiec
- Lipiec
- Sierpień
- Wrzesień
- Październik
- Listopad
- Grudzień
DAYS_OF_THE_WEEK:
- Poniedziałek
- Wtorek
- Środa
- Czwartek
- Piątek
- Sobota
- Niedziela

View File

@@ -1,2 +1,55 @@
MONTHS_OF_THE_YEAR: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro']
DAYS_OF_THE_WEEK: ['Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado', 'Domingo']
INFLECTOR_UNCOUNTABLE:
1: informação
2: arroz
3: dinheiro
INFLECTOR_IRREGULAR:
man: homens
sex: sexos
NICETIME:
SECOND: segundo
MINUTE: minuto
HOUR: hora
DAY: dia
WEEK: semana
MONTH: mês
YEAR: ano
DECADE: década
SEC: seg
MIN: mín
MO: mês
YR: ano
SECOND_PLURAL: segundos
MINUTE_PLURAL: minutos
HOUR_PLURAL: horas
DAY_PLURAL: dias
WEEK_PLURAL: semanas
MONTH_PLURAL: meses
YEAR_PLURAL: anos
DECADE_PLURAL: décadas
SEC_PLURAL: seg
MIN_PLURAL: mins
HR_PLURAL: hrs
YR_PLURAL: anos
FORM:
VALIDATION_FAIL: '<b>Validação falhada: </b>'
MONTHS_OF_THE_YEAR:
- Janeiro
- Fevereiro
- Março
- Abril
- Maio
- Junho
- Julho
- Agosto
- Setembro
- Outubro
- Novembro
- Dezembro
DAYS_OF_THE_WEEK:
- Segunda
- Terça
- Quarta
- Quinta
- Sexta
- Sábado
- Domingo

View File

@@ -1,2 +1,20 @@
MONTHS_OF_THE_YEAR: ['Ianuarie', 'Februarie', 'Martie', 'Aprilue', 'Mai', 'Iunie', 'Iulie', 'August', 'Septembrie', 'Octombrie', 'Noiembrie', 'Decembrie']
DAYS_OF_THE_WEEK: ['Luni', 'Marti', 'Miercuri', 'Joi', 'Vineri', 'Sâmbătă', 'Duminică']
MONTHS_OF_THE_YEAR:
0: Ianuarie
1: Februarie
2: Martie
3: Aprilue
4: Mai
5: Iunie
6: Iulie
8: Septembrie
9: Octombrie
10: Noiembrie
11: Decembrie
DAYS_OF_THE_WEEK:
- Luni
- Marti
- Miercuri
- Joi
- Vineri
- Sâmbătă
- Duminică

View File

@@ -1,45 +1,66 @@
INFLECTOR_IRREGULAR:
'person': 'люди'
'man': 'человек'
'child': 'ребенок'
'sex': 'пол'
'move': 'движется'
person: люди
man: человек
child: ребенок
sex: пол
move: движется
NICETIME:
NO_DATE_PROVIDED: Дата не указана
BAD_DATE: Неверная дата
AGO: назад
FROM_NOW: теперь
SECOND: секунда
MINUTE: минута
HOUR: час
DAY: день
WEEK: неделя
MONTH: месяц
YEAR: год
DECADE: десятилетие
SEC: с
MIN: мин
HR: ч
DAY: д
WK: нед
MO: мес
YR: г.
DEC: гг.
SECOND_PLURAL: секунды
MINUTE_PLURAL: минуты
HOUR_PLURAL: часы
DAY_PLURAL: дни
WEEK_PLURAL: недели
MONTH_PLURAL: месяцы
YEAR_PLURAL: годы
DECADE_PLURAL: десятилетия
SEC_PLURAL: с
MIN_PLURAL: мин
HR_PLURAL: ч
DAY_PLURAL: д
WK_PLURAL: нед
MO_PLURAL: мес
YR_PLURAL: г.
DEC_PLURAL: гг.
MONTHS_OF_THE_YEAR: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь']
DAYS_OF_THE_WEEK: ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье']
NO_DATE_PROVIDED: Дата не указана
BAD_DATE: Неверная дата
AGO: назад
FROM_NOW: теперь
SECOND: секунда
MINUTE: минута
HOUR: час
DAY: д
WEEK: неделя
MONTH: месяц
YEAR: год
DECADE: десятилетие
SEC: с
MIN: мин
HR: ч
WK: нед
MO: мес
YR: г.
DEC: гг.
SECOND_PLURAL: секунды
MINUTE_PLURAL: минуты
HOUR_PLURAL: часы
DAY_PLURAL: д
WEEK_PLURAL: недели
MONTH_PLURAL: месяцы
YEAR_PLURAL: годы
DECADE_PLURAL: десятилетия
SEC_PLURAL: с
MIN_PLURAL: мин
HR_PLURAL: ч
WK_PLURAL: нед
MO_PLURAL: мес
YR_PLURAL: г.
DEC_PLURAL: гг.
FORM:
VALIDATION_FAIL: '<b>Проверка не удалась:</b>'
INVALID_INPUT: Неверный ввод в
MISSING_REQUIRED_FIELD: 'Отсутствует необходимое поле:'
MONTHS_OF_THE_YEAR:
- Январь
- Февраль
- Март
- Апрель
- Май
- Июнь
- Июль
- Август
- Сентябрь
- Октябрь
- Ноябрь
- Декабрь
DAYS_OF_THE_WEEK:
- Понедельник
- Вторник
- Среда
- Четверг
- Пятница
- Суббота
- Воскресенье

2
system/languages/sv.yaml Normal file
View File

@@ -0,0 +1,2 @@
NICETIME:
DAY: dag

View File

@@ -1,37 +1,35 @@
NICETIME:
NO_DATE_PROVIDED: Tarih yok
BAD_DATE: Yanlış tarih
AGO: önce
FROM_NOW: (şimdiden)
SECOND: saniye
MINUTE: dakika
HOUR: saat
DAY: gün
WEEK: hafta
MONTH: ay
YEAR: yıl
DECADE: onyıl
SEC: sn
MIN: dk
HR: sa
DAY: gün
WK: hft
MO: ay
YR: yl
DEC: onyl
SECOND_PLURAL: saniye
MINUTE_PLURAL: dakika
HOUR_PLURAL: saat
DAY_PLURAL: gün
WEEK_PLURAL: hafta
MONTH_PLURAL: ay
YEAR_PLURAL: yıl
DECADE_PLURAL: onyıl
SEC_PLURAL: sn
MIN_PLURAL: dk
HR_PLURAL: sa
DAY_PLURAL: gün
WK_PLURAL: hft
MO_PLURAL: ay
YR_PLURAL: yl
DEC_PLURAL: onyl
NO_DATE_PROVIDED: Tarih yok
BAD_DATE: Yanlış tarih
AGO: önce
FROM_NOW: (şimdiden)
SECOND: saniye
MINUTE: dakika
HOUR: saat
DAY: gün
WEEK: hafta
MONTH: ay
YEAR: yıl
DECADE: onyıl
SEC: sn
MIN: dk
HR: sa
WK: hft
MO: ay
YR: yl
DEC: onyl
SECOND_PLURAL: saniye
MINUTE_PLURAL: dakika
HOUR_PLURAL: saat
DAY_PLURAL: gün
WEEK_PLURAL: hafta
MONTH_PLURAL: ay
YEAR_PLURAL: yıl
DECADE_PLURAL: onyıl
SEC_PLURAL: sn
MIN_PLURAL: dk
HR_PLURAL: sa
WK_PLURAL: hft
MO_PLURAL: ay
YR_PLURAL: yl
DEC_PLURAL: onyl

View File

@@ -6,8 +6,8 @@ namespace Grav\Common;
*
* Internally uses the PhpUserAgent package https://github.com/donatj/PhpUserAgent
*
* @author RocketTHeme
* @licence MIT
* @author RocketTheme
* @license MIT
*/
class Browser
{

View File

@@ -294,7 +294,7 @@ class Validation
protected static function filterFile($value, array $params, array $field)
{
if (isset($field['multiple']) && $field['multiple'] == true) {
if (isset($field['multiple']) && $field['multiple'] === true) {
return (array) $value;
}

View File

@@ -14,6 +14,7 @@ class Errors
{
$grav = Grav::instance();
$config = $grav['config']->get('system.errors');
$jsonRequest = $_SERVER && $_SERVER['HTTP_ACCEPT'] && $_SERVER['HTTP_ACCEPT'] == 'application/json';
// Setup Whoops-based error handler
$whoops = new \Whoops\Run;
@@ -31,11 +32,11 @@ class Errors
}
if (method_exists('Whoops\Util\Misc', 'isAjaxRequest')) { //Whoops 2.0
if (Whoops\Util\Misc::isAjaxRequest()) {
if (Whoops\Util\Misc::isAjaxRequest() || $jsonRequest) {
$whoops->pushHandler(new Whoops\Handler\JsonResponseHandler);
}
} elseif (function_exists('Whoops\isAjaxRequest')) { //Whoops 2.0.0-alpha
if (Whoops\isAjaxRequest()) {
if (Whoops\isAjaxRequest() || $jsonRequest) {
$whoops->pushHandler(new Whoops\Handler\JsonResponseHandler);
}
} else { //Whoops 1.x

View File

@@ -121,6 +121,10 @@ class Installer
}
/**
* @param $state
* @param $install_path
*/
protected static function flightProcessing($state, $install_path)
{
$blueprints_path = $install_path . DS . 'blueprints.yaml';
@@ -140,6 +144,13 @@ class Installer
}
}
/**
* @param \ZipArchive $zip
* @param $install_path
* @param $tmp
*
* @return bool
*/
public static function moveInstall(\ZipArchive $zip, $install_path, $tmp)
{
$container = $zip->getNameIndex(0);
@@ -152,6 +163,13 @@ class Installer
return true;
}
/**
* @param \ZipArchive $zip
* @param $install_path
* @param $tmp
*
* @return bool
*/
public static function copyInstall(\ZipArchive $zip, $install_path, $tmp)
{
$firstDir = $zip->getNameIndex(0);
@@ -165,6 +183,13 @@ class Installer
return true;
}
/**
* @param \ZipArchive $zip
* @param $install_path
* @param $tmp
*
* @return bool
*/
public static function sophisticatedInstall(\ZipArchive $zip, $install_path, $tmp)
{
for ($i = 0, $l = $zip->numFiles; $i < $l; $i++) {
@@ -279,8 +304,6 @@ class Installer
*/
public static function lastErrorMsg()
{
$msg = 'Unknown Error';
if (is_string(self::$error)) {
return self::$error;
}
@@ -319,7 +342,7 @@ class Installer
break;
default:
return 'Unknown error';
$msg = 'Unknown Error';
break;
}

View File

@@ -4,6 +4,10 @@ namespace Grav\Common\GPM;
use Grav\Common\Utils;
use Grav\Common\GravTrait;
/**
* Class Response
* @package Grav\Common\GPM
*/
class Response
{
use GravTrait;
@@ -125,8 +129,7 @@ class Response
/**
* Progress normalized for cURL and Fopen
*
* @param args Variable length of arguments passed in by stream method
* Accepts a vsariable length of arguments passed in by stream method
*
* @return array Normalized array with useful data.
* Format: ['code' => int|false, 'filesize' => bytes, 'transferred' => bytes, 'percent' => int]
@@ -231,9 +234,10 @@ class Response
$ch = curl_init($uri);
$response = static::_curl_exec_follow($ch, $options, $callback);
$response = static::curlExecFollow($ch, $options, $callback);
$errno = curl_errno($ch);
if ($errno = curl_errno($ch)) {
if ($errno) {
$error_message = curl_strerror($errno);
throw new \RuntimeException("cURL error ({$errno}):\n {$error_message}");
}
@@ -243,7 +247,14 @@ class Response
return $response;
}
private static function _curl_exec_follow($ch, $options, $callback)
/**
* @param $ch
* @param $options
* @param $callback
*
* @return bool|mixed
*/
private static function curlExecFollow($ch, $options, $callback)
{
if ($callback) {
curl_setopt_array(

View File

@@ -319,7 +319,7 @@ class Grav extends Container
$code = $matches[2];
}
if ($code == null) {
if ($code === null) {
$code = $this['config']->get('system.pages.redirect_default_code', 301);
}

View File

@@ -118,7 +118,7 @@ class Truncator {
list($txt, $nb, $opts) = static::truncateNode($doc, $childNode, $remaining, $opts);
}
else if ($childNode->nodeType === XML_TEXT_NODE) {
list($txt, $nb, $opts) = static::truncateText($doc, $childNode, $remaining, $opts);
list($txt, $nb, $opts) = static::truncateText($childNode, $remaining, $opts);
} else {
$txt = '';
$nb = 0;
@@ -141,7 +141,7 @@ class Truncator {
return array($inner, $remaining, $opts);
}
protected static function truncateText($doc, $node, $length, $opts)
protected static function truncateText($node, $length, $opts)
{
$string = $node->textContent;
@@ -165,7 +165,7 @@ class Truncator {
$words = $words[0];
$count = count($words);
if ($count <= $length && $length > 0) {
return array($xhtml, $count, $opts);
return array($string, $count, $opts);
}
return array(implode('', array_slice($words, 0, $length)), $count, $opts);
}

View File

@@ -20,7 +20,9 @@ trait ParsedownGravTrait
/** @var Pages $pages */
protected $pages;
protected $base_url;
/** @var Uri $uri */
protected $uri;
protected $pages_dir;
protected $special_chars;
protected $twig_link_regex = '/\!*\[(?:.*)\]\((\{([\{%#])\s*(.*?)\s*(?:\2|\})\})\)/';
@@ -41,8 +43,8 @@ trait ParsedownGravTrait
$this->page = $page;
$this->pages = $grav['pages'];
$this->uri = $grav['uri'];
$this->BlockTypes['{'] [] = "TwigTag";
$this->base_url = rtrim(self::getGrav()['base_url'] . self::getGrav()['pages']->base(), '/');
$this->pages_dir = self::getGrav()['locator']->findResource('page://');
$this->special_chars = ['>' => 'gt', '<' => 'lt', '"' => 'quot'];
@@ -203,23 +205,24 @@ trait ParsedownGravTrait
//get the url and parse it
$url = parse_url(htmlspecialchars_decode($excerpt['element']['attributes']['src']));
$this_host = isset($url['host']) && $url['host'] == $this->uri->host();
// if there is no host set but there is a path, the file is local
if (!isset($url['host']) && isset($url['path'])) {
if ((!isset($url['host']) || $this_host) && isset($url['path'])) {
$path_parts = pathinfo($url['path']);
// get the local path to page media if possible
if ($path_parts['dirname'] == $this->page->url(false, false, false)) {
$url['path'] = urldecode($path_parts['basename']);
// get the media objects for this page
$media = $this->page->media();
} else {
// see if this is an external page to this one
$page_route = str_replace($this->base_url, '', $path_parts['dirname']);
$base_url = rtrim(self::getGrav()['base_url_relative'] . self::getGrav()['pages']->base(), '/');
$page_route = '/' . ltrim(str_replace($base_url, '', $path_parts['dirname']), '/');
$ext_page = $this->pages->dispatch($page_route, true);
if ($ext_page) {
$media = $ext_page->media();
$url['path'] = urldecode($path_parts['basename']);
}
}
@@ -249,7 +252,7 @@ trait ParsedownGravTrait
$medium->urlHash($url['fragment']);
}
$excerpt['element'] = $medium->parseDownElement($title, $alt, $class);
$excerpt['element'] = $medium->parseDownElement($title, $alt, $class, true);
} else {
// not a current page media file, see if it needs converting to relative
@@ -327,7 +330,7 @@ trait ParsedownGravTrait
// set path to / if not set
if (empty($url['path'])) {
$url['path'] = '/';
$url['path'] = '';
}
// if special scheme, just return
@@ -335,66 +338,11 @@ trait ParsedownGravTrait
return $excerpt;
}
// if there is no scheme, the file is local and we'll need to convert that URL
if (!isset($url['scheme']) && (count($url) > 0)) {
$url['path'] = Uri::convertUrl($this->page, Uri::buildUrl($url), $type,
true);
} else {
$url['path'] = Uri::convertUrl($this->page, $url['path'], $type, true);
}
// URL path already has these now so remove them
unset($url['query']);
unset($url['fragment']);
// if absolute urls enabled, add them
if (self::getGrav()['config']->get('system.absolute_urls', false)) {
$uri = self::getGrav()['uri'];
$url['scheme'] = str_replace('://', '', $uri->scheme());
$url['host'] = $uri->host();
if ($uri->port() != 80 && $uri->port() != 443) {
$url['port'] = $uri->port();
}
// check if page exists for this route, and if so, check if it has SSL enabled
$pages = self::getGrav()['pages'];
$routes = $pages->routes();
// if this is an image, get the proper path
$url_bits = pathinfo($url['path']);
if (isset($url_bits['extension'])) {
$target_path = $url_bits['dirname'];
} else {
$target_path = $url['path'];
}
// strip base from this path
$target_path = str_replace($uri->rootUrl(), '', $target_path);
// set to / if root
if (empty($target_path)) {
$target_path = '/';
}
// look to see if this page exists and has ssl enabled
if (isset($routes[$target_path])) {
$target_page = $pages->get($routes[$target_path]);
if ($target_page) {
$ssl_enabled = $target_page->ssl();
if (isset($ssl_enabled)) {
if ($ssl_enabled) {
$url['scheme'] = 'https';
} else {
$url['scheme'] = 'http';
}
}
}
}
}
// handle paths and such
$url = Uri::convertUrl($this->page, $url, $type);
// build the URL from the component parts and set it on the element
$excerpt['element']['attributes']['href'] = Uri::buildUrl($url);
}
return $excerpt;

View File

@@ -1,6 +1,7 @@
<?php
namespace Grav\Common\Page\Medium;
use Grav\Common\Utils;
use Grav\Common\Data\Blueprint;
class ImageMedium extends Medium
@@ -136,7 +137,15 @@ class ImageMedium extends Medium
*/
public function url($reset = true)
{
$output = preg_replace('|^' . preg_quote(GRAV_ROOT) . '|', '', $this->saveImage());
$image_path = self::$grav['locator']->findResource('cache://images', true);
$image_dir = self::$grav['locator']->findResource('cache://images', false);
$saved_image_path = $this->saveImage();
$output = preg_replace('|^' . preg_quote(GRAV_ROOT) . '|', '', $saved_image_path);
if (Utils::startsWith($output, $image_path)) {
$output = '/' . $image_dir . preg_replace('|^' . preg_quote($image_path) . '|', '', $output);
}
if ($reset) {
$this->reset();
@@ -155,6 +164,7 @@ class ImageMedium extends Medium
if (!$this->image) {
$this->image();
}
return $this;
}
@@ -261,6 +271,7 @@ class ImageMedium extends Medium
if ($this->image) {
$this->image();
$this->image->clearOperations(); // Clear previously applied operations
$this->querystring('');
$this->filter();
}

View File

@@ -155,7 +155,7 @@ class Medium extends Data implements RenderableInterface
*/
public function querystring($querystring = null, $withQuestionmark = true)
{
if ($querystring) {
if (!is_null($querystring)) {
$this->set('querystring', ltrim($querystring, '?&'));
foreach ($this->alternatives as $alt) {

View File

@@ -65,6 +65,7 @@ class Page
protected $frontmatter;
protected $language;
protected $content;
protected $content_meta;
protected $summary;
protected $raw_content;
protected $pagination;
@@ -517,7 +518,15 @@ class Page
/** @var Cache $cache */
$cache = self::getGrav()['cache'];
$cache_id = md5('page' . $this->id());
$this->content = $cache->fetch($cache_id);
$content_obj = $cache->fetch($cache_id);
if (is_array($content_obj)) {
$this->content = $content_obj['content'];
$this->content_meta = $content_obj['content_meta'];
} else {
$this->content = $content_obj;
}
$process_markdown = $this->shouldProcess('markdown');
$process_twig = $this->shouldProcess('twig');
@@ -528,7 +537,7 @@ class Page
// if no cached-content run everything
if ($this->content === false || $cache_enable == false) {
if ($this->content === false || $cache_enable === false) {
$this->content = $this->raw_content;
self::getGrav()->fireEvent('onPageContentRaw', new Event(['page' => $this]));
@@ -574,6 +583,17 @@ class Page
return $this->content;
}
public function addContentMeta($name, $value)
{
$this->content_meta[$name] = $value;
}
public function getContentMeta()
{
return $this->content_meta;
}
/**
* Process the Markdown content. Uses Parsedown or Parsedown Extra depending on configuration
*/
@@ -619,7 +639,7 @@ class Page
{
$cache = self::getGrav()['cache'];
$cache_id = md5('page' . $this->id());
$cache->save($cache_id, $this->content);
$cache->save($cache_id, ['content' => $this->content, 'content_meta' => $this->content_meta]);
}
/**
@@ -1369,8 +1389,6 @@ class Page
/** @var Uri $uri */
$uri = self::getGrav()['uri'];
$include_port = false;
// get pre-route
if ($include_lang && $language->enabled()) {
$pre_route = $language->getLanguageURLPrefix();
@@ -1881,7 +1899,7 @@ class Page
while (true) {
$theParent = $topParent->parent();
if ($theParent != null && $theParent->parent() !== null) {
if ($theParent !== null && $theParent->parent() !== null) {
$topParent = $theParent;
} else {
break;

View File

@@ -657,6 +657,15 @@ class Pages
return self::$home_route;
}
/**
* Needed for testing where we change the home route via config
*/
public static function resetHomeRoute()
{
self::$home_route = null;
return self::getHomeRoute();
}
/**
* Builds pages.
*
@@ -888,7 +897,7 @@ class Pages
$taxonomy = $this->grav['taxonomy'];
// Get the home route
$home = self::getHomeRoute();
$home = self::resetHomeRoute();
// Build routes and taxonomy map.
/** @var $page Page */

View File

@@ -3,6 +3,7 @@ namespace Grav\Common\Twig;
use Grav\Common\Grav;
use Grav\Common\Config\Config;
use Grav\Common\Language\Language;
use Grav\Common\Page\Page;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use RocketTheme\Toolbox\Event\Event;
@@ -12,7 +13,7 @@ use RocketTheme\Toolbox\Event\Event;
* that is optimized so that it only needs to be initialized once and can be reused for individual
* page template rendering as well as the main site template rendering.
*
* @author RocketTheme
* @author RocketTheme
* @license MIT
*/
class Twig
@@ -55,6 +56,8 @@ class Twig
/**
* Constructor
*
* @param Grav $grav
*/
public function __construct(Grav $grav)
{
@@ -73,7 +76,6 @@ class Twig
$config = $this->grav['config'];
/** @var UniformResourceLocator $locator */
$locator = $this->grav['locator'];
$debugger = $this->grav['debugger'];
/** @var Language $language */
$language = $this->grav['language'];
@@ -87,7 +89,7 @@ class Twig
// handle language templates if available
if ($language->enabled()) {
$lang_templates = $locator->findResource('theme://templates/'.($active_language ? $active_language : $language->getDefault()));
$lang_templates = $locator->findResource('theme://templates/' . ($active_language ? $active_language : $language->getDefault()));
if ($lang_templates) {
$this->twig_paths[] = $lang_templates;
}
@@ -98,8 +100,8 @@ class Twig
$this->grav->fireEvent('onTwigTemplatePaths');
$this->loader = new \Twig_Loader_Filesystem($this->twig_paths);
$this->loaderArray = new \Twig_Loader_Array(array());
$loader_chain = new \Twig_Loader_Chain(array($this->loaderArray, $this->loader));
$this->loaderArray = new \Twig_Loader_Array([]);
$loader_chain = new \Twig_Loader_Chain([$this->loaderArray, $this->loader]);
$params = $config->get('system.twig');
if (!empty($params['cache'])) {
@@ -114,7 +116,8 @@ class Twig
return new \Twig_Function_Function($name);
}
return new \Twig_Function_Function(function() {});
return new \Twig_Function_Function(function () {
});
});
}
@@ -124,7 +127,8 @@ class Twig
return new \Twig_Filter_Function($name);
}
return new \Twig_Filter_Function(function() {});
return new \Twig_Filter_Function(function () {
});
});
}
@@ -143,21 +147,21 @@ class Twig
$this->grav->fireEvent('onTwigExtensions');
// Set some standard variables for twig
$this->twig_vars = $this->twig_vars + array(
'config' => $config,
'uri' => $this->grav['uri'],
'base_dir' => rtrim(ROOT_DIR, '/'),
'base_url' => $this->grav['base_url'] . $language_append,
'base_url_simple' => $this->grav['base_url'],
'base_url_absolute' => $this->grav['base_url_absolute'] . $language_append,
'base_url_relative' => $this->grav['base_url_relative'] . $language_append,
'theme_dir' => $locator->findResource('theme://'),
'theme_url' => $this->grav['base_url'] .'/'. $locator->findResource('theme://', false),
'site' => $config->get('site'),
'assets' => $this->grav['assets'],
'taxonomy' => $this->grav['taxonomy'],
'browser' => $this->grav['browser'],
);
$this->twig_vars = $this->twig_vars + [
'config' => $config,
'uri' => $this->grav['uri'],
'base_dir' => rtrim(ROOT_DIR, '/'),
'base_url' => $this->grav['base_url'] . $language_append,
'base_url_simple' => $this->grav['base_url'],
'base_url_absolute' => $this->grav['base_url_absolute'] . $language_append,
'base_url_relative' => $this->grav['base_url_relative'] . $language_append,
'theme_dir' => $locator->findResource('theme://'),
'theme_url' => $this->grav['base_url'] . '/' . $locator->findResource('theme://', false),
'site' => $config->get('site'),
'assets' => $this->grav['assets'],
'taxonomy' => $this->grav['taxonomy'],
'browser' => $this->grav['browser'],
];
}
}
@@ -195,6 +199,7 @@ class Twig
*
* @param Page $item The page item to render
* @param string $content Optional content override
*
* @return string The rendered output
* @throws \Twig_Error_Loader
*/
@@ -203,7 +208,7 @@ class Twig
$content = $content !== null ? $content : $item->content();
// override the twig header vars for local resolution
$this->grav->fireEvent('onTwigPageVariables', new Event(['page' => $item]));
$this->grav->fireEvent('onTwigPageVariables', new Event(['page' => $item]));
$twig_vars = $this->twig_vars;
$twig_vars['page'] = $item;
@@ -214,6 +219,8 @@ class Twig
$modular_twig = $item->modularTwig();
$process_twig = isset($item->header()->process['twig']) ? $item->header()->process['twig'] : false;
$output = '';
try {
// Process Modular Twig
if ($modular_twig) {
@@ -240,10 +247,11 @@ class Twig
* and optional array of variables
*
* @param string $template template to render with
* @param array $vars Optional variables
* @param array $vars Optional variables
*
* @return string
*/
public function processTemplate($template, $vars = array())
public function processTemplate($template, $vars = [])
{
// override the twig header vars for local resolution
$this->grav->fireEvent('onTwigTemplateVariables');
@@ -264,11 +272,12 @@ class Twig
* Process a Twig template directly by using a Twig string
* and optional array of variables
*
* @param string $string string to render.
* @param array $vars Optional variables
* @param string $string string to render.
* @param array $vars Optional variables
*
* @return string
*/
public function processString($string, array $vars = array())
public function processString($string, array $vars = [])
{
// override the twig header vars for local resolution
$this->grav->fireEvent('onTwigStringVariables');
@@ -291,6 +300,7 @@ class Twig
* page and handles all the layout for the site display.
*
* @param string $format Output format (defaults to HTML).
*
* @return string the rendered output
* @throws \RuntimeException
*/
@@ -301,7 +311,6 @@ class Twig
$pages = $this->grav['pages'];
$page = $this->grav['page'];
$content = $page->content();
$config = $this->grav['config'];
$twig_vars = $this->twig_vars;
@@ -326,9 +335,9 @@ class Twig
} catch (\Twig_Error_Loader $e) {
$error_msg = $e->getMessage();
// Try html version of this template if initial template was NOT html
if ($ext != '.html'.TWIG_EXT) {
if ($ext != '.html' . TWIG_EXT) {
try {
$output = $this->twig->render($page->template().'.html'.TWIG_EXT, $twig_vars);
$output = $this->twig->render($page->template() . '.html' . TWIG_EXT, $twig_vars);
} catch (\Twig_Error_Loader $e) {
throw new \RuntimeException($error_msg, 400, $e);
}
@@ -345,6 +354,7 @@ class Twig
* the one being passed in
*
* @param string $template the template name
*
* @return string the template name
*/
public function template($template)

View File

@@ -5,12 +5,13 @@ use Grav\Common\Grav;
use Grav\Common\Utils;
use Grav\Common\Markdown\Parsedown;
use Grav\Common\Markdown\ParsedownExtra;
use Grav\Common\Uri;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* The Twig extension adds some filters and functions that are useful for Grav
*
* @author RocketTheme
* @author RocketTheme
* @license MIT
*/
class TwigExtension extends \Twig_Extension
@@ -19,6 +20,9 @@ class TwigExtension extends \Twig_Extension
protected $debugger;
protected $config;
/**
* TwigExtension constructor.
*/
public function __construct()
{
$this->grav = Grav::instance();
@@ -43,9 +47,9 @@ class TwigExtension extends \Twig_Extension
*/
public function getGlobals()
{
return array(
return [
'grav' => $this->grav,
);
];
}
/**
@@ -56,30 +60,30 @@ class TwigExtension extends \Twig_Extension
public function getFilters()
{
return [
new \Twig_SimpleFilter('*ize', [$this,'inflectorFilter']),
new \Twig_SimpleFilter('*ize', [$this, 'inflectorFilter']),
new \Twig_SimpleFilter('absolute_url', [$this, 'absoluteUrlFilter']),
new \Twig_SimpleFilter('contains', [$this, 'containsFilter']),
new \Twig_SimpleFilter('defined', [$this, 'definedDefaultFilter']),
new \Twig_SimpleFilter('ends_with', [$this, 'endsWithFilter']),
new \Twig_SimpleFilter('fieldName', [$this,'fieldNameFilter']),
new \Twig_SimpleFilter('ksort', [$this,'ksortFilter']),
new \Twig_SimpleFilter('fieldName', [$this, 'fieldNameFilter']),
new \Twig_SimpleFilter('ksort', [$this, 'ksortFilter']),
new \Twig_SimpleFilter('ltrim', [$this, 'ltrimFilter']),
new \Twig_SimpleFilter('markdown', [$this, 'markdownFilter']),
new \Twig_SimpleFilter('md5', [$this,'md5Filter']),
new \Twig_SimpleFilter('md5', [$this, 'md5Filter']),
new \Twig_SimpleFilter('nicetime', [$this, 'nicetimeFilter']),
new \Twig_SimpleFilter('randomize', [$this,'randomizeFilter']),
new \Twig_SimpleFilter('modulus', [$this,'modulusFilter']),
new \Twig_SimpleFilter('randomize', [$this, 'randomizeFilter']),
new \Twig_SimpleFilter('modulus', [$this, 'modulusFilter']),
new \Twig_SimpleFilter('rtrim', [$this, 'rtrimFilter']),
new \Twig_SimpleFilter('pad', [$this, 'padFilter']),
new \Twig_SimpleFilter('safe_email', [$this,'safeEmailFilter']),
new \Twig_SimpleFilter('safe_truncate', ['\Grav\Common\Utils','safeTruncate']),
new \Twig_SimpleFilter('safe_truncate_html', ['\Grav\Common\Utils','safeTruncateHTML']),
new \Twig_SimpleFilter('sort_by_key', [$this,'sortByKeyFilter']),
new \Twig_SimpleFilter('safe_email', [$this, 'safeEmailFilter']),
new \Twig_SimpleFilter('safe_truncate', ['\Grav\Common\Utils', 'safeTruncate']),
new \Twig_SimpleFilter('safe_truncate_html', ['\Grav\Common\Utils', 'safeTruncateHTML']),
new \Twig_SimpleFilter('sort_by_key', [$this, 'sortByKeyFilter']),
new \Twig_SimpleFilter('starts_with', [$this, 'startsWithFilter']),
new \Twig_SimpleFilter('t', [$this, 'translate']),
new \Twig_SimpleFilter('ta', [$this, 'translateArray']),
new \Twig_SimpleFilter('truncate', ['\Grav\Common\Utils','truncate']),
new \Twig_SimpleFilter('truncate_html', ['\Grav\Common\Utils','truncateHTML']),
new \Twig_SimpleFilter('truncate', ['\Grav\Common\Utils', 'truncate']),
new \Twig_SimpleFilter('truncate_html', ['\Grav\Common\Utils', 'truncateHTML']),
];
}
@@ -112,7 +116,8 @@ class TwigExtension extends \Twig_Extension
/**
* Filters field name by changing dot notation into array notation.
*
* @param string $str
* @param string $str
*
* @return string
*/
public function fieldNameFilter($str)
@@ -125,7 +130,8 @@ class TwigExtension extends \Twig_Extension
/**
* Protects email address.
*
* @param string $str
* @param string $str
*
* @return string
*/
public function safeEmailFilter($str)
@@ -133,8 +139,9 @@ class TwigExtension extends \Twig_Extension
$email = '';
$str_len = strlen($str);
for ($i = 0; $i < $str_len; $i++) {
$email .= "&#" . ord($str[$i]). ";";
$email .= "&#" . ord($str[$i]) . ";";
}
return $email;
}
@@ -142,7 +149,8 @@ class TwigExtension extends \Twig_Extension
* Returns array in a random order.
*
* @param array $original
* @param int $offset Can be used to return only slice of the array.
* @param int $offset Can be used to return only slice of the array.
*
* @return array
*/
public function randomizeFilter($original, $offset = 0)
@@ -160,41 +168,44 @@ class TwigExtension extends \Twig_Extension
shuffle($random);
$sizeOf = sizeof($original);
for ($x=0; $x < $sizeOf; $x++) {
for ($x = 0; $x < $sizeOf; $x++) {
if ($x < $offset) {
$sorted[] = $original[$x];
} else {
$sorted[] = array_shift($random);
}
}
return $sorted;
}
/**
* Returns the modulus of an integer
*
* @param int $number
* @param int $divider
* @param int $number
* @param int $divider
* @param array $items array of items to select from to return
*
* @return int
*/
public function modulusFilter($number, $divider, $items = null)
{
if (is_string($number)) {
$number = strlen($number);
}
public function modulusFilter($number, $divider, $items = null)
{
if (is_string($number)) {
$number = strlen($number);
}
$remainder = $number % $divider;
$remainder = $number % $divider;
if (is_array($items)) {
if (isset($items[$remainder])) {
return $items[$remainder];
} else {
return $items[0];
}
}
return $remainder;
}
if (is_array($items)) {
if (isset($items[$remainder])) {
return $items[$remainder];
} else {
return $items[0];
}
}
return $remainder;
}
/**
* Inflector supports following notations:
@@ -211,21 +222,22 @@ class TwigExtension extends \Twig_Extension
*
* @param string $action
* @param string $data
* @param int $count
* @param int $count
*
* @return mixed
*/
public function inflectorFilter($action, $data, $count = null)
{
$action = $action.'ize';
$action = $action . 'ize';
$inflector = $this->grav['inflector'];
if (in_array(
$action,
['titleize','camelize','underscorize','hyphenize', 'humanize','ordinalize','monthize']
['titleize', 'camelize', 'underscorize', 'hyphenize', 'humanize', 'ordinalize', 'monthize']
)) {
return $inflector->$action($data);
} elseif (in_array($action, ['pluralize','singularize'])) {
} elseif (in_array($action, ['pluralize', 'singularize'])) {
if ($count) {
return $inflector->$action($data, $count);
} else {
@@ -240,6 +252,7 @@ class TwigExtension extends \Twig_Extension
* Return MD5 hash from the input.
*
* @param string $str
*
* @return string
*/
public function md5Filter($str)
@@ -277,11 +290,13 @@ class TwigExtension extends \Twig_Extension
* Return ksorted collection.
*
* @param array $array
*
* @return array
*/
public function ksortFilter(array $array)
{
ksort($array);
return $array;
}
@@ -314,14 +329,32 @@ class TwigExtension extends \Twig_Extension
}
if ($long_strings) {
$periods = array("NICETIME.SECOND", "NICETIME.MINUTE", "NICETIME.HOUR", "NICETIME.DAY", "NICETIME.WEEK", "NICETIME.MONTH", "NICETIME.YEAR", "NICETIME.DECADE");
$periods = [
"NICETIME.SECOND",
"NICETIME.MINUTE",
"NICETIME.HOUR",
"NICETIME.DAY",
"NICETIME.WEEK",
"NICETIME.MONTH",
"NICETIME.YEAR",
"NICETIME.DECADE"
];
} else {
$periods = array("NICETIME.SEC", "NICETIME.MIN", "NICETIME.HR", "NICETIME.DAY", "NICETIME.WK", "NICETIME.MO", "NICETIME.YR", "NICETIME.DEC");
$periods = [
"NICETIME.SEC",
"NICETIME.MIN",
"NICETIME.HR",
"NICETIME.DAY",
"NICETIME.WK",
"NICETIME.MO",
"NICETIME.YR",
"NICETIME.DEC"
];
}
$lengths = array("60","60","24","7","4.35","12","10");
$lengths = ["60", "60", "24", "7", "4.35", "12", "10"];
$now = time();
$now = time();
// check if unix timestamp
if ((string)(int)$date == $date) {
@@ -337,15 +370,15 @@ class TwigExtension extends \Twig_Extension
// is it future date or past date
if ($now > $unix_date) {
$difference = $now - $unix_date;
$tense = $this->grav['language']->translate('NICETIME.AGO', null, true);
$difference = $now - $unix_date;
$tense = $this->grav['language']->translate('NICETIME.AGO', null, true);
} else {
$difference = $unix_date - $now;
$tense = $this->grav['language']->translate('NICETIME.FROM_NOW', null, true);
$difference = $unix_date - $now;
$tense = $this->grav['language']->translate('NICETIME.FROM_NOW', null, true);
}
for ($j = 0; $difference >= $lengths[$j] && $j < count($lengths)-1; $j++) {
for ($j = 0; $difference >= $lengths[$j] && $j < count($lengths) - 1; $j++) {
$difference /= $lengths[$j];
}
@@ -355,7 +388,9 @@ class TwigExtension extends \Twig_Extension
$periods[$j] .= '_PLURAL';
}
if ($this->grav['language']->getTranslation($this->grav['language']->getLanguage(), $periods[$j] . '_MORE_THAN_TWO')) {
if ($this->grav['language']->getTranslation($this->grav['language']->getLanguage(),
$periods[$j] . '_MORE_THAN_TWO')
) {
if ($difference > 2) {
$periods[$j] .= '_MORE_THAN_TWO';
}
@@ -366,14 +401,25 @@ class TwigExtension extends \Twig_Extension
return "$difference $periods[$j] {$tense}";
}
/**
* @param $string
*
* @return mixed
*/
public function absoluteUrlFilter($string)
{
$url = $this->grav['uri']->base();
$string = preg_replace('/((?:href|src) *= *[\'"](?!(http|ftp)))/i', "$1$url", $string);
return $string;
}
/**
* @param $string
*
* @return mixed|string
*/
public function markdownFilter($string)
{
$page = $this->grav['page'];
@@ -391,16 +437,34 @@ class TwigExtension extends \Twig_Extension
return $string;
}
/**
* @param $haystack
* @param $needle
*
* @return bool
*/
public function startsWithFilter($haystack, $needle)
{
return Utils::startsWith($haystack, $needle);
}
/**
* @param $haystack
* @param $needle
*
* @return bool
*/
public function endsWithFilter($haystack, $needle)
{
return Utils::endsWith($haystack, $needle);
}
/**
* @param $value
* @param null $default
*
* @return null
*/
public function definedDefaultFilter($value, $default = null)
{
if (isset($value)) {
@@ -410,21 +474,43 @@ class TwigExtension extends \Twig_Extension
}
}
/**
* @param $value
* @param null $chars
*
* @return string
*/
public function rtrimFilter($value, $chars = null)
{
return rtrim($value, $chars);
}
/**
* @param $value
* @param null $chars
*
* @return string
*/
public function ltrimFilter($value, $chars = null)
{
return ltrim($value, $chars);
}
/**
* @return mixed
*/
public function translate()
{
return $this->grav['language']->translate(func_get_args());
}
/**
* @param $key
* @param $index
* @param null $lang
*
* @return mixed
*/
public function translateArray($key, $index, $lang = null)
{
return $this->grav['language']->translateArray($key, $index, $lang);
@@ -435,6 +521,7 @@ class TwigExtension extends \Twig_Extension
*
* @param string $input
* @param int $multiplier
*
* @return string
*/
public function repeatFunc($input, $multiplier)
@@ -447,13 +534,14 @@ class TwigExtension extends \Twig_Extension
*
* @example {{ url('theme://images/logo.png')|default('http://www.placehold.it/150x100/f4f4f4') }}
*
* @param string $input Resource to be located.
* @param bool $domain True to include domain name.
* @param string $input Resource to be located.
* @param bool $domain True to include domain name.
*
* @return string|null Returns url to the resource or null if resource was not found.
*/
public function urlFunc($input, $domain = false)
{
if (!trim((string) $input)) {
if (!trim((string)$input)) {
return false;
}
@@ -462,14 +550,14 @@ class TwigExtension extends \Twig_Extension
}
if (strpos((string) $input, '://')) {
if (strpos((string)$input, '://')) {
/** @var UniformResourceLocator $locator */
$locator = $this->grav['locator'];
// Get relative path to the resource (or false if not found).
$resource = $locator->findResource((string) $input, false);
$resource = $locator->findResource((string)$input, false);
} else {
$resource = (string) $input;
$resource = (string)$input;
}
/** @var Uri $uri */
@@ -483,7 +571,8 @@ class TwigExtension extends \Twig_Extension
*
* @example {{ evaluate('grav.language.getLanguage') }}
*
* @param string $input String to be evaluated
* @param string $input String to be evaluated
*
* @return string Returns the evaluated string
*/
public function evaluateFunc($input)
@@ -496,7 +585,7 @@ class TwigExtension extends \Twig_Extension
* (c) 2011 Fabien Potencier
*
* @param \Twig_Environment $env
* @param $context
* @param $context
*/
public function dump(\Twig_Environment $env, $context)
{
@@ -530,11 +619,12 @@ class TwigExtension extends \Twig_Extension
* Output a Gist
*
* @param string $id
*
* @return string
*/
public function gistFunc($id)
{
return '<script src="https://gist.github.com/'.$id.'.js"></script>';
return '<script src="https://gist.github.com/' . $id . '.js"></script>';
}
/**
@@ -561,7 +651,7 @@ class TwigExtension extends \Twig_Extension
*/
public static function padFilter($input, $pad_length, $pad_string = " ", $pad_type = STR_PAD_RIGHT)
{
return str_pad($input, (int) $pad_length, $pad_string, $pad_type);
return str_pad($input, (int)$pad_length, $pad_string, $pad_type);
}
@@ -574,7 +664,7 @@ class TwigExtension extends \Twig_Extension
*/
public function arrayFunc($value)
{
return (array) $value;
return (array)$value;
}
/**
@@ -630,18 +720,17 @@ class TwigExtension extends \Twig_Extension
/**
* Used to add a nonce to a form. Call {{ nonce_field('action') }} specifying a string representing the action.
*
* For maximum protection, ensure that the string representing the action is as specific as possible.
* For maximum protection, ensure that the string representing the action is as specific as possible
*
* @todo evaluate if adding referrer or not
*
* @param string action the action
* @param string nonceParamName a custom nonce param name
* @param string $action the action
* @param string $nonceParamName a custom nonce param name
*
* @return string the nonce input field
*/
public function nonceFieldFunc($action, $nonceParamName = 'nonce')
{
$string = '<input type="hidden" id="' . $nonceParamName . '" name="' . $nonceParamName . '" value="' . Utils::getNonce($action) .'" />';
$string = '<input type="hidden" id="' . $nonceParamName . '" name="' . $nonceParamName . '" value="' . Utils::getNonce($action) . '" />';
return $string;
}
}

View File

@@ -11,6 +11,7 @@ trait WriteCacheFileTrait
use GravTrait;
protected static $umask;
/**
* This exists so template cache files use the same
* group between apache and cli

View File

@@ -21,6 +21,7 @@ class Uri
protected $content_path;
protected $extension;
protected $host;
protected $env;
protected $params;
protected $path;
protected $paths;
@@ -41,6 +42,7 @@ class Uri
$this->params = [];
$this->query = [];
$this->name = $this->buildHostname();
$this->env = $this->buildEnvironment();
$this->port = $this->buildPort();
$this->uri = $this->buildUri();
$this->scheme = $this->buildScheme();
@@ -150,18 +152,23 @@ class Uri
* @return string
*/
private function buildHost()
{
return $this->name;
}
private function buildEnvironment()
{
// set hostname
$address = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '::1';
// check for localhost variations
if ($this->name == 'localhost' || $address == '::1' || $address == '127.0.0.1') {
$host = 'localhost';
$env = 'localhost';
} else {
$host = $this->name;
$env = $this->name;
}
return $host;
return $env;
}
/**
@@ -182,6 +189,7 @@ class Uri
$this->params = [];
$this->query = [];
$this->name = [];
$this->env = [];
$this->port = [];
$this->uri = [];
$this->base = [];
@@ -189,22 +197,36 @@ class Uri
$this->root = [];
$this->url = [];
$params = parse_url($url);
$grav = Grav::instance();
$this->name = $params['host'];
$this->port = isset($params['port']) ? $params['port'] : '80';
$language = $grav['language'];
$this->uri = $params['path'];
if (isset($params['query'])) {
$this->uri .= '?' . $params['query'];
parse_str($params['query'], $this->query);
$uri_bits = Uri::parseUrl($url);
$this->name = $uri_bits['host'];
$this->port = isset($uri_bits['port']) ? $uri_bits['port'] : '80';
$this->uri = $uri_bits['path'];
// set active language
$uri = $language->setActiveFromUri($this->uri);
if (isset($uri_bits['params'])) {
$this->params = $uri_bits['params'];
}
if (isset($uri_bits['query'])) {
$this->uri .= '?' . $uri_bits['query'];
parse_str($uri_bits['query'], $this->query);
}
$this->base = $this->buildBaseUrl();
$this->host = $this->buildHost();
$this->env = $this->buildEnvironment();
$this->root_path = $this->buildRootPath();
$this->root = $this->base . $this->root_path;
$this->url = $this->base . $this->uri;
$this->url = $this->root . $uri;
$this->path = $uri;
return $this;
}
@@ -236,7 +258,7 @@ class Uri
$language = $grav['language'];
// add the port to the base for non-standard ports
if ($config->get('system.reverse_proxy_setup') == false && $this->port != '80' && $this->port != '443') {
if ($config->get('system.reverse_proxy_setup') === false && $this->port != '80' && $this->port != '443') {
$this->base .= ":" . $this->port;
}
@@ -529,7 +551,7 @@ class Uri
*/
public function environment()
{
return $this->host();
return $this->env;
}
@@ -675,10 +697,225 @@ class Uri
$pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
$pass = ($user || $pass) ? "$pass@" : '';
$path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
$params = isset($parsed_url['params']) ? static::buildParams($parsed_url['params']) : '';
$query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
$fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
return "$scheme$user$pass$host$port$path$query$fragment";
return "$scheme$user$pass$host$port$path$params$query$fragment";
}
public static function buildParams($params)
{
$grav = Grav::instance();
$params_string = '';
foreach ($params as $key => $value) {
$output[] = $key . $grav['config']->get('system.param_sep') . $value;
$params_string .= '/' . implode('/', $output);
}
return $params_string;
}
/**
* Converts links from absolute '/' or relative (../..) to a Grav friendly format
*
* @param Page $page the current page to use as reference
* @param string $url the URL as it was written in the markdown
* @param string $type the type of URL, image | link
* @param null $absolute if null, will use system default, if true will use absolute links internally
*
* @return string the more friendly formatted url
*/
public static function convertUrl(Page $page, $url, $type = 'link', $absolute = false)
{
$grav = Grav::instance();
$uri = $grav['uri'];
// Link processing should prepend language
$language = $grav['language'];
$language_append = '';
if ($type == 'link' && $language->enabled()) {
$language_append = $language->getLanguageURLPrefix();
}
// Handle Excerpt style $url array
if (is_array($url)) {
$url_path = $url['path'];
} else {
$url_path = $url;
}
$external = false;
$base = $grav['base_url_relative'];
$base_url = rtrim($base . $grav['pages']->base(), '/') . $language_append;
$pages_dir = $grav['locator']->findResource('page://');
// if absolute and starts with a base_url move on
if (isset($url['scheme']) && Utils::startsWith($url['scheme'], 'http')) {
$external = true;
} elseif (($base_url != '' && Utils::startsWith($url_path, $base_url)) ||
$url_path == '/' ||
Utils::startsWith($url_path, '#')) {
$url_path = $base_url . $url_path;
} else {
// see if page is relative to this or absolute
if (Utils::startsWith($url_path, '/')) {
$normalized_url = Utils::normalizePath($base_url . $url_path);
$normalized_path = Utils::normalizePath($pages_dir . $url_path);
} else {
$page_route = ($page->home() && !empty($url_path)) ? $page->rawRoute() : $page->route();
$normalized_url = $base_url . Utils::normalizePath($page_route . '/' . $url_path);
$normalized_path = Utils::normalizePath($page->path() . '/' . $url_path);
}
// special check to see if path checking is required.
$just_path = str_replace($normalized_url, '', $normalized_path);
if ($just_path == $page->path() || $normalized_url == '/') {
$url_path = $normalized_url;
} else {
$url_bits = static::parseUrl($normalized_path);
$full_path = ($url_bits['path']);
$raw_full_path = rawurldecode($full_path);
if (file_exists($raw_full_path)) {
$full_path = $raw_full_path;
} elseif (file_exists($full_path)) {
// do nothing
} else {
$full_path = false;
}
if ($full_path) {
$path_info = pathinfo($full_path);
$page_path = $path_info['dirname'];
$filename = '';
if ($url_path == '..') {
$page_path = $full_path;
} else {
// save the filename if a file is part of the path
if (is_file($full_path)) {
if ($path_info['extension'] != 'md') {
$filename = '/' . $path_info['basename'];
}
} else {
$page_path = $full_path;
}
}
// get page instances and try to find one that fits
$instances = $grav['pages']->instances();
if (isset($instances[$page_path])) {
/** @var Page $target */
$target = $instances[$page_path];
$url_bits['path'] = $base_url . rtrim($target->route(), '/') . $filename;
$url_path = Uri::buildUrl($url_bits);
} else {
$url_path = $normalized_url;
}
} else {
$url_path = $normalized_url;
}
}
}
// handle absolute URLs
if (!$external && ($absolute === true || $grav['config']->get('system.absolute_urls', false))) {
$url['scheme'] = str_replace('://', '', $uri->scheme());
$url['host'] = $uri->host();
if ($uri->port() != 80 && $uri->port() != 443) {
$url['port'] = $uri->port();
}
// check if page exists for this route, and if so, check if it has SSL enabled
$pages = $grav['pages'];
$routes = $pages->routes();
// if this is an image, get the proper path
$url_bits = pathinfo($url_path);
if (isset($url_bits['extension'])) {
$target_path = $url_bits['dirname'];
} else {
$target_path = $url_path;
}
// strip base from this path
$target_path = str_replace($uri->rootUrl(), '', $target_path);
// set to / if root
if (empty($target_path)) {
$target_path = '/';
}
// look to see if this page exists and has ssl enabled
if (isset($routes[$target_path])) {
$target_page = $pages->get($routes[$target_path]);
if ($target_page) {
$ssl_enabled = $target_page->ssl();
if (isset($ssl_enabled)) {
if ($ssl_enabled) {
$url['scheme'] = 'https';
} else {
$url['scheme'] = 'http';
}
}
}
}
}
// transform back to string/array as needed
if (is_array($url)) {
$url['path'] = $url_path;
} else {
$url = $url_path;
}
return $url;
}
public static function parseUrl($url)
{
$bits = parse_url($url);
$grav = Grav::instance();
list($stripped_path, $params) = static::extractParams($bits['path'], $grav['config']->get('system.param_sep'));
if (!empty($params)) {
$bits['path'] = $stripped_path;
$bits['params'] = $params;
}
return $bits;
}
public static function extractParams($uri, $delimiter)
{
$params = [];
if (strpos($uri, $delimiter) !== false) {
$bits = explode('/', $uri);
$path = [];
foreach ($bits as $bit) {
if (strpos($bit, $delimiter) !== false) {
$param = explode($delimiter, $bit);
if (count($param) == 2) {
$plain_var = filter_var(rawurldecode($param[1]), FILTER_SANITIZE_STRING);
$params[$param[0]] = $plain_var;
}
} else {
$path[] = $bit;
}
}
$uri = '/' . ltrim(implode('/', $path), '/');
}
return [$uri, $params];
}
/**
@@ -691,7 +928,7 @@ class Uri
*
* @return string the more friendly formatted url
*/
public static function convertUrl(Page $page, $markdown_url, $type = 'link', $relative = null)
public static function convertUrlOld(Page $page, $markdown_url, $type = 'link', $relative = null)
{
$grav = Grav::instance();

View File

@@ -36,7 +36,7 @@ class Group extends Data
*
* @return object
*/
public static function group_exists($groupname)
public static function groupExists($groupname)
{
return isset(self::groups()[$groupname]);
}
@@ -50,7 +50,7 @@ class Group extends Data
*/
public static function load($groupname)
{
if (self::group_exists($groupname)) {
if (self::groupExists($groupname)) {
$content = self::groups()[$groupname];
} else {
$content = [];

View File

@@ -505,7 +505,6 @@ abstract class Utils
}
//Added in version 1.0.8 to ensure that existing nonces are not broken.
//TODO: to be removed
private static function generateNonceStringOldStyle($action, $plusOneTick = false)
{
if (isset(self::getGrav()['user'])) {
@@ -529,7 +528,7 @@ abstract class Utils
/**
* Get the time-dependent variable for nonce creation.
*
* @todo now a tick lasts a day. Once the day is passed, the nonce is not valid any more. Find a better way
* Now a tick lasts a day. Once the day is passed, the nonce is not valid any more. Find a better way
* to ensure nonces issued near the end of the day do not expire in that small amount of time
*
* @return int the time part of the nonce. Changes once every 24 hours
@@ -563,7 +562,6 @@ abstract class Utils
}
//Added in version 1.0.8 to ensure that existing nonces are not broken.
//TODO: to be removed
public static function getNonceOldStyle($action, $plusOneTick = false)
{
// Don't regenerate this again if not needed
@@ -604,7 +602,6 @@ abstract class Utils
//Added in version 1.0.8 to ensure that existing nonces are not broken.
//TODO: to be removed
//Nonce generated 0-12 hours ago
if ($nonce == self::getNonceOldStyle($action)) {
return true;
@@ -615,7 +612,6 @@ abstract class Utils
if ($nonce == self::getNonceOldStyle($action, $plusOneTick)) {
return true;
}
//End TODO: to be removed
//Invalid nonce
return false;

View File

@@ -30,6 +30,9 @@ class ConsoleCommand extends Command
/**
*
*/
protected function serve() { }
protected function serve()
{
}
}
}

View File

@@ -5,6 +5,7 @@ namespace Grav;
use Codeception\Util\Fixtures;
use Faker\Factory;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
ini_set('error_log', __DIR__ . '/error.log');
@@ -34,18 +35,18 @@ if (!extension_loaded('mbstring')) {
mb_internal_encoding('UTF-8');
// Get the Grav instance
$grav = Grav::instance(
array(
'loader' => $loader
)
);
$grav = Grav::instance(['loader' => $loader]);
$grav['uri']->init();
$grav['debugger']->init();
$grav['assets']->init();
$grav['config']->set('system.cache.enabled', false);
/** @var UniformResourceLocator $locator */
$locator = $grav['locator'];
$locator->addPath('tests', '', 'tests', false);
// Set default $_SERVER value used for nonces
empty( $_SERVER['HTTP_CLIENT_IP'] ) && $_SERVER['HTTP_CLIENT_IP'] = '127.0.0.1';

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

View File

@@ -0,0 +1,5 @@
---
title: Simple Page
---
Simple Page Content

View File

@@ -0,0 +1,715 @@
<?php
use Codeception\Util\Fixtures;
use Grav\Common\Grav;
use Grav\Common\Uri;
use Grav\Common\Config\Config;
use Grav\Common\Page\Pages;
use Grav\Common\Markdown\Parsedown;
use Grav\Common\Language\Language;
/**
* Class ParsedownTest
*/
class ParsedownTest extends \Codeception\TestCase\Test
{
/** @var Parsedown $parsedown */
protected $parsedown;
/** @var Grav $grav */
protected $grav;
/** @var Pages $pages */
protected $pages;
/** @var Config $config */
protected $config;
/** @var Uri $uri */
protected $uri;
/** @var Language $language */
protected $language;
protected $old_home;
static $run = false;
protected function _before()
{
$this->grav = Fixtures::get('grav');
$this->pages = $this->grav['pages'];
$this->config = $this->grav['config'];
$this->uri = $this->grav['uri'];
$this->language = $this->grav['language'];
$this->old_home = $this->config->get('system.home.alias');
$this->config->set('system.home.alias', '/item1');
$this->config->set('system.absolute_urls', false);
$this->config->set('system.languages.supported', []);
unset($this->grav['language']);
$this->grav['language'] = new Language($this->grav);
if (!self::$run) {
/** @var UniformResourceLocator $locator */
$locator = $this->grav['locator'];
$locator->addPath('page', '', 'tests/fake/nested-site/user/pages', false);
$this->pages->init();
self::$run = true;
}
$defaults = [
'extra' => false,
'auto_line_breaks' => false,
'auto_url_links' => false,
'escape_markup' => false,
'special_chars' => ['>' => 'gt', '<' => 'lt'],
];
$page = $this->pages->dispatch('/item2/item2-2');
$this->parsedown = new Parsedown($page, $defaults);
}
protected function _after()
{
$this->config->set('system.home.alias', $this->old_home);
}
public function testImages()
{
$this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init();
$this->assertSame('<p><img src="/tests/fake/nested-site/user/pages/02.item2/02.item2-2/sample-image.jpg" /></p>',
$this->parsedown->text('![](sample-image.jpg)'));
$this->assertRegexp('|<p><img src="\/images\/.*-cache-image.jpe?g\?foo=1" \/><\/p>|',
$this->parsedown->text('![](cache-image.jpg?cropResize=200,200&foo)'));
$this->assertRegexp('|<p><img src="\/images\/.*-home-cache-image.jpe?g" \/><\/p>|',
$this->parsedown->text('![](/home-cache-image.jpg?cache)'));
$this->assertSame('<p><img src="/item2/item2-2/missing-image.jpg" alt="" /></p>',
$this->parsedown->text('![](missing-image.jpg)'));
$this->assertSame('<p><img src="/home-missing-image.jpg" alt="" /></p>',
$this->parsedown->text('![](/home-missing-image.jpg)'));
$this->config->set('system.languages.supported', ['fr','en']);
unset($this->grav['language']);
$this->grav['language'] = new Language($this->grav);
$this->uri->initializeWithURL('http://testing.dev/fr/item2/item2-2')->init();
$this->assertSame('<p><img src="/tests/fake/nested-site/user/pages/02.item2/02.item2-2/sample-image.jpg" /></p>',
$this->parsedown->text('![](sample-image.jpg)'));
$this->assertRegexp('|<p><img src="\/images\/.*-cache-image.jpe?g\?foo=1" \/><\/p>|',
$this->parsedown->text('![](cache-image.jpg?cropResize=200,200&foo)'));
}
public function testImagesSubDir()
{
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertRegexp('|<p><img src="\/subdir\/images\/.*-home-cache-image.jpe?g" \/><\/p>|',
$this->parsedown->text('![](/home-cache-image.jpg?cache)'));
$this->assertSame('<p><img src="/subdir/tests/fake/nested-site/user/pages/02.item2/02.item2-2/sample-image.jpg" /></p>',
$this->parsedown->text('![](sample-image.jpg)'));
$this->assertRegexp('|<p><img src="\/subdir\/images\/.*-cache-image.jpe?g" \/><\/p>|',
$this->parsedown->text('![](cache-image.jpg?cache)'));
$this->assertSame('<p><img src="/subdir/item2/item2-2/missing-image.jpg" alt="" /></p>',
$this->parsedown->text('![](missing-image.jpg)'));
$this->assertSame('<p><img src="/subdir/home-missing-image.jpg" alt="" /></p>',
$this->parsedown->text('![](/home-missing-image.jpg)'));
}
public function testImagesAbsoluteUrls()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init();
$this->assertSame('<p><img src="http://testing.dev/tests/fake/nested-site/user/pages/02.item2/02.item2-2/sample-image.jpg" /></p>',
$this->parsedown->text('![](sample-image.jpg)'));
$this->assertRegexp('|<p><img src="http:\/\/testing.dev\/images\/.*-cache-image.jpe?g" \/><\/p>|',
$this->parsedown->text('![](cache-image.jpg?cache)'));
$this->assertRegexp('|<p><img src="http:\/\/testing.dev\/images\/.*-home-cache-image.jpe?g" \/><\/p>|',
$this->parsedown->text('![](/home-cache-image.jpg?cache)'));
$this->assertSame('<p><img src="http://testing.dev/item2/item2-2/missing-image.jpg" alt="" /></p>',
$this->parsedown->text('![](missing-image.jpg)'));
$this->assertSame('<p><img src="http://testing.dev/home-missing-image.jpg" alt="" /></p>',
$this->parsedown->text('![](/home-missing-image.jpg)'));
}
public function testImagesSubDirAbsoluteUrls()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertSame('<p><img src="http://testing.dev/subdir/tests/fake/nested-site/user/pages/02.item2/02.item2-2/sample-image.jpg" /></p>',
$this->parsedown->text('![](sample-image.jpg)'));
$this->assertRegexp('|<p><img src="http:\/\/testing.dev\/subdir\/images\/.*-cache-image.jpe?g" \/><\/p>|',
$this->parsedown->text('![](cache-image.jpg?cache)'));
$this->assertRegexp('|<p><img src="http:\/\/testing.dev\/subdir\/images\/.*-home-cache-image.jpe?g" \/><\/p>|',
$this->parsedown->text('![](/home-cache-image.jpg?cropResize=200,200)'));
$this->assertSame('<p><img src="http://testing.dev/subdir/item2/item2-2/missing-image.jpg" alt="" /></p>',
$this->parsedown->text('![](missing-image.jpg)'));
$this->assertSame('<p><img src="http://testing.dev/subdir/home-missing-image.jpg" alt="" /></p>',
$this->parsedown->text('![](/home-missing-image.jpg)'));
}
public function testRootImages()
{
$this->uri->initializeWithURL('http://testing.dev/')->init();
$defaults = [
'extra' => false,
'auto_line_breaks' => false,
'auto_url_links' => false,
'escape_markup' => false,
'special_chars' => ['>' => 'gt', '<' => 'lt'],
];
$page = $this->pages->dispatch('/');
$this->parsedown = new Parsedown($page, $defaults);
$this->assertSame('<p><img src="/tests/fake/nested-site/user/pages/01.item1/home-sample-image.jpg" /></p>',
$this->parsedown->text('![](home-sample-image.jpg)'));
$this->assertRegexp('|<p><img src="\/images\/.*-home-cache-image.jpe?g" \/><\/p>|',
$this->parsedown->text('![](home-cache-image.jpg?cache)'));
$this->assertRegexp('|<p><img src="\/images\/.*-home-cache-image.jpe?g\?foo=1" \/><\/p>|',
$this->parsedown->text('![](home-cache-image.jpg?cropResize=200,200&foo)'));
$this->assertSame('<p><img src="/home-missing-image.jpg" alt="" /></p>',
$this->parsedown->text('![](/home-missing-image.jpg)'));
$this->config->set('system.languages.supported', ['fr','en']);
unset($this->grav['language']);
$this->grav['language'] = new Language($this->grav);
$this->uri->initializeWithURL('http://testing.dev/fr/item2/item2-2')->init();
$this->assertSame('<p><img src="/tests/fake/nested-site/user/pages/01.item1/home-sample-image.jpg" /></p>',
$this->parsedown->text('![](home-sample-image.jpg)'));
}
public function testRootImagesSubDirAbsoluteUrls()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertSame('<p><img src="http://testing.dev/subdir/tests/fake/nested-site/user/pages/02.item2/02.item2-2/sample-image.jpg" /></p>',
$this->parsedown->text('![](sample-image.jpg)'));
$this->assertRegexp('|<p><img src="http:\/\/testing.dev\/subdir\/images\/.*-cache-image.jpe?g" \/><\/p>|',
$this->parsedown->text('![](cache-image.jpg?cache)'));
$this->assertRegexp('|<p><img src="http:\/\/testing.dev\/subdir\/images\/.*-home-cache-image.jpe?g" \/><\/p>|',
$this->parsedown->text('![](/home-cache-image.jpg?cropResize=200,200)'));
$this->assertSame('<p><img src="http://testing.dev/subdir/item2/item2-2/missing-image.jpg" alt="" /></p>',
$this->parsedown->text('![](missing-image.jpg)'));
$this->assertSame('<p><img src="http://testing.dev/subdir/home-missing-image.jpg" alt="" /></p>',
$this->parsedown->text('![](/home-missing-image.jpg)'));
}
public function testRootAbsoluteLinks()
{
$this->uri->initializeWithURL('http://testing.dev/')->init();
$defaults = [
'extra' => false,
'auto_line_breaks' => false,
'auto_url_links' => false,
'escape_markup' => false,
'special_chars' => ['>' => 'gt', '<' => 'lt'],
];
$page = $this->pages->dispatch('/');
$this->parsedown = new Parsedown($page, $defaults);
$this->assertSame('<p><a href="/item1/item1-3">Down a Level</a></p>',
$this->parsedown->text('[Down a Level](item1-3)'));
$this->assertSame('<p><a href="/item2">Peer Page</a></p>',
$this->parsedown->text('[Peer Page](../item2)'));
$this->assertSame('<p><a href="/?foo=bar">With Query</a></p>',
$this->parsedown->text('[With Query](?foo=bar)'));
$this->assertSame('<p><a href="/foo:bar">With Param</a></p>',
$this->parsedown->text('[With Param](/foo:bar)'));
$this->assertSame('<p><a href="/#foo">With Anchor</a></p>',
$this->parsedown->text('[With Anchor](#foo)'));
$this->config->set('system.languages.supported', ['fr','en']);
unset($this->grav['language']);
$this->grav['language'] = new Language($this->grav);
$this->uri->initializeWithURL('http://testing.dev/fr/item2/item2-2')->init();
$this->assertSame('<p><a href="/fr/item2">Peer Page</a></p>',
$this->parsedown->text('[Peer Page](../item2)'));
$this->assertSame('<p><a href="/fr/item1/item1-3">Down a Level</a></p>',
$this->parsedown->text('[Down a Level](item1-3)'));
$this->assertSame('<p><a href="/fr/?foo=bar">With Query</a></p>',
$this->parsedown->text('[With Query](?foo=bar)'));
$this->assertSame('<p><a href="/fr/foo:bar">With Param</a></p>',
$this->parsedown->text('[With Param](/foo:bar)'));
$this->assertSame('<p><a href="/fr/#foo">With Anchor</a></p>',
$this->parsedown->text('[With Anchor](#foo)'));
}
public function testAnchorLinksLangRelativeUrls()
{
$this->config->set('system.languages.supported', ['fr','en']);
unset($this->grav['language']);
$this->grav['language'] = new Language($this->grav);
$this->uri->initializeWithURL('http://testing.dev/fr/item2/item2-2')->init();
$this->assertSame('<p><a href="/fr/item2/item2-2#foo">Current Anchor</a></p>',
$this->parsedown->text('[Current Anchor](#foo)'));
$this->assertSame('<p><a href="/fr/#foo">Root Anchor</a></p>',
$this->parsedown->text('[Root Anchor](/#foo)'));
$this->assertSame('<p><a href="/fr/item2/item2-1#foo">Peer Anchor</a></p>',
$this->parsedown->text('[Peer Anchor](../item2-1#foo)'));
$this->assertSame('<p><a href="/fr/item2/item2-1#foo">Peer Anchor 2</a></p>',
$this->parsedown->text('[Peer Anchor 2](../item2-1/#foo)'));
}
public function testAnchorLinksLangAbsoluteUrls()
{
$this->config->set('system.absolute_urls', true);
$this->config->set('system.languages.supported', ['fr','en']);
unset($this->grav['language']);
$this->grav['language'] = new Language($this->grav);
$this->uri->initializeWithURL('http://testing.dev/fr/item2/item2-2')->init();
$this->assertSame('<p><a href="http://testing.dev/fr/item2/item2-1#foo">Peer Anchor</a></p>',
$this->parsedown->text('[Peer Anchor](../item2-1#foo)'));
$this->assertSame('<p><a href="http://testing.dev/fr/item2/item2-1#foo">Peer Anchor 2</a></p>',
$this->parsedown->text('[Peer Anchor 2](../item2-1/#foo)'));
$this->assertSame('<p><a href="http://testing.dev/fr/item2/item2-2#foo">Current Anchor</a></p>',
$this->parsedown->text('[Current Anchor](#foo)'));
$this->assertSame('<p><a href="http://testing.dev/fr/#foo">Root Anchor</a></p>',
$this->parsedown->text('[Root Anchor](/#foo)'));
}
public function testExternalLinks()
{
$this->assertSame('<p><a href="http://www.cnn.com">cnn.com</a></p>',
$this->parsedown->text('[cnn.com](http://www.cnn.com)'));
$this->assertSame('<p><a href="https://www.google.com">google.com</a></p>',
$this->parsedown->text('[google.com](https://www.google.com)'));
}
public function testExternalLinksSubDir()
{
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertSame('<p><a href="http://www.cnn.com">cnn.com</a></p>',
$this->parsedown->text('[cnn.com](http://www.cnn.com)'));
$this->assertSame('<p><a href="https://www.google.com">google.com</a></p>',
$this->parsedown->text('[google.com](https://www.google.com)'));
}
public function testExternalLinksSubDirAbsoluteUrls()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertSame('<p><a href="http://www.cnn.com">cnn.com</a></p>',
$this->parsedown->text('[cnn.com](http://www.cnn.com)'));
$this->assertSame('<p><a href="https://www.google.com">google.com</a></p>',
$this->parsedown->text('[google.com](https://www.google.com)'));
}
public function testAnchorLinksRelativeUrls()
{
$this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init();
$this->assertSame('<p><a href="/item2/item2-2#foo">Current Anchor</a></p>',
$this->parsedown->text('[Current Anchor](#foo)'));
$this->assertSame('<p><a href="/#foo">Root Anchor</a></p>',
$this->parsedown->text('[Root Anchor](/#foo)'));
$this->assertSame('<p><a href="/item2/item2-1#foo">Peer Anchor</a></p>',
$this->parsedown->text('[Peer Anchor](../item2-1#foo)'));
$this->assertSame('<p><a href="/item2/item2-1#foo">Peer Anchor 2</a></p>',
$this->parsedown->text('[Peer Anchor 2](../item2-1/#foo)'));
}
public function testAnchorLinksAbsoluteUrls()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init();
$this->assertSame('<p><a href="http://testing.dev/item2/item2-1#foo">Peer Anchor</a></p>',
$this->parsedown->text('[Peer Anchor](../item2-1#foo)'));
$this->assertSame('<p><a href="http://testing.dev/item2/item2-1#foo">Peer Anchor 2</a></p>',
$this->parsedown->text('[Peer Anchor 2](../item2-1/#foo)'));
$this->assertSame('<p><a href="http://testing.dev/item2/item2-2#foo">Current Anchor</a></p>',
$this->parsedown->text('[Current Anchor](#foo)'));
$this->assertSame('<p><a href="http://testing.dev/#foo">Root Anchor</a></p>',
$this->parsedown->text('[Root Anchor](/#foo)'));
}
public function testAnchorLinksWithPortAbsoluteUrls()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithURL('http://testing.dev:8080/item2/item2-2')->init();
$this->assertSame('<p><a href="http://testing.dev:8080/item2/item2-1#foo">Peer Anchor</a></p>',
$this->parsedown->text('[Peer Anchor](../item2-1#foo)'));
$this->assertSame('<p><a href="http://testing.dev:8080/item2/item2-1#foo">Peer Anchor 2</a></p>',
$this->parsedown->text('[Peer Anchor 2](../item2-1/#foo)'));
$this->assertSame('<p><a href="http://testing.dev:8080/item2/item2-2#foo">Current Anchor</a></p>',
$this->parsedown->text('[Current Anchor](#foo)'));
$this->assertSame('<p><a href="http://testing.dev:8080/#foo">Root Anchor</a></p>',
$this->parsedown->text('[Root Anchor](/#foo)'));
}
public function testAnchorLinksSubDirRelativeUrls()
{
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertSame('<p><a href="/subdir/item2/item2-1#foo">Peer Anchor</a></p>',
$this->parsedown->text('[Peer Anchor](../item2-1#foo)'));
$this->assertSame('<p><a href="/subdir/item2/item2-1#foo">Peer Anchor 2</a></p>',
$this->parsedown->text('[Peer Anchor 2](../item2-1/#foo)'));
$this->assertSame('<p><a href="/subdir/item2/item2-2#foo">Current Anchor</a></p>',
$this->parsedown->text('[Current Anchor](#foo)'));
$this->assertSame('<p><a href="/subdir/#foo">Root Anchor</a></p>',
$this->parsedown->text('[Root Anchor](/#foo)'));
}
public function testAnchorLinksSubDirAbsoluteUrls()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertSame('<p><a href="http://testing.dev/subdir/item2/item2-1#foo">Peer Anchor</a></p>',
$this->parsedown->text('[Peer Anchor](../item2-1#foo)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item2/item2-1#foo">Peer Anchor 2</a></p>',
$this->parsedown->text('[Peer Anchor 2](../item2-1/#foo)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item2/item2-2#foo">Current Anchor</a></p>',
$this->parsedown->text('[Current Anchor](#foo)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/#foo">Root Anchor</a></p>',
$this->parsedown->text('[Root Anchor](/#foo)'));
}
public function testSlugRelativeLinks()
{
$this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init();
$this->assertSame('<p><a href="/">Up to Root Level</a></p>',
$this->parsedown->text('[Up to Root Level](../..)'));
$this->assertSame('<p><a href="/item2/item2-1">Peer Page</a></p>',
$this->parsedown->text('[Peer Page](../item2-1)'));
$this->assertSame('<p><a href="/item2/item2-2/item2-2-1">Down a Level</a></p>',
$this->parsedown->text('[Down a Level](item2-2-1)'));
$this->assertSame('<p><a href="/item2">Up a Level</a></p>',
$this->parsedown->text('[Up a Level](..)'));
$this->assertSame('<p><a href="/item3/item3-3">Up and Down</a></p>',
$this->parsedown->text('[Up and Down](../../item3/item3-3)'));
$this->assertSame('<p><a href="/item2/item2-2/item2-2-1?foo=bar">Down a Level with Query</a></p>',
$this->parsedown->text('[Down a Level with Query](item2-2-1?foo=bar)'));
$this->assertSame('<p><a href="/item2?foo=bar">Up a Level with Query</a></p>',
$this->parsedown->text('[Up a Level with Query](../?foo=bar)'));
$this->assertSame('<p><a href="/item3/item3-3?foo=bar">Up and Down with Query</a></p>',
$this->parsedown->text('[Up and Down with Query](../../item3/item3-3?foo=bar)'));
$this->assertSame('<p><a href="/item3/item3-3/foo:bar">Up and Down with Param</a></p>',
$this->parsedown->text('[Up and Down with Param](../../item3/item3-3/foo:bar)'));
$this->assertSame('<p><a href="/item3/item3-3#foo">Up and Down with Anchor</a></p>',
$this->parsedown->text('[Up and Down with Anchor](../../item3/item3-3#foo)'));
}
public function testSlugRelativeLinksAbsoluteUrls()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init();
$this->assertSame('<p><a href="http://testing.dev/item2/item2-1">Peer Page</a></p>',
$this->parsedown->text('[Peer Page](../item2-1)'));
$this->assertSame('<p><a href="http://testing.dev/item2/item2-2/item2-2-1">Down a Level</a></p>',
$this->parsedown->text('[Down a Level](item2-2-1)'));
$this->assertSame('<p><a href="http://testing.dev/item2">Up a Level</a></p>',
$this->parsedown->text('[Up a Level](..)'));
$this->assertSame('<p><a href="http://testing.dev/">Up to Root Level</a></p>',
$this->parsedown->text('[Up to Root Level](../..)'));
$this->assertSame('<p><a href="http://testing.dev/item3/item3-3">Up and Down</a></p>',
$this->parsedown->text('[Up and Down](../../item3/item3-3)'));
$this->assertSame('<p><a href="http://testing.dev/item2/item2-2/item2-2-1?foo=bar">Down a Level with Query</a></p>',
$this->parsedown->text('[Down a Level with Query](item2-2-1?foo=bar)'));
$this->assertSame('<p><a href="http://testing.dev/item2?foo=bar">Up a Level with Query</a></p>',
$this->parsedown->text('[Up a Level with Query](../?foo=bar)'));
$this->assertSame('<p><a href="http://testing.dev/item3/item3-3?foo=bar">Up and Down with Query</a></p>',
$this->parsedown->text('[Up and Down with Query](../../item3/item3-3?foo=bar)'));
$this->assertSame('<p><a href="http://testing.dev/item3/item3-3/foo:bar">Up and Down with Param</a></p>',
$this->parsedown->text('[Up and Down with Param](../../item3/item3-3/foo:bar)'));
$this->assertSame('<p><a href="http://testing.dev/item3/item3-3#foo">Up and Down with Anchor</a></p>',
$this->parsedown->text('[Up and Down with Anchor](../../item3/item3-3#foo)'));
}
public function testSlugRelativeLinksSubDir()
{
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertSame('<p><a href="/subdir/item2/item2-1">Peer Page</a></p>',
$this->parsedown->text('[Peer Page](../item2-1)'));
$this->assertSame('<p><a href="/subdir/item2/item2-2/item2-2-1">Down a Level</a></p>',
$this->parsedown->text('[Down a Level](item2-2-1)'));
$this->assertSame('<p><a href="/subdir/item2">Up a Level</a></p>',
$this->parsedown->text('[Up a Level](..)'));
$this->assertSame('<p><a href="/subdir">Up to Root Level</a></p>',
$this->parsedown->text('[Up to Root Level](../..)'));
$this->assertSame('<p><a href="/subdir/item3/item3-3">Up and Down</a></p>',
$this->parsedown->text('[Up and Down](../../item3/item3-3)'));
$this->assertSame('<p><a href="/subdir/item2/item2-2/item2-2-1?foo=bar">Down a Level with Query</a></p>',
$this->parsedown->text('[Down a Level with Query](item2-2-1?foo=bar)'));
$this->assertSame('<p><a href="/subdir/item2?foo=bar">Up a Level with Query</a></p>',
$this->parsedown->text('[Up a Level with Query](../?foo=bar)'));
$this->assertSame('<p><a href="/subdir/item3/item3-3?foo=bar">Up and Down with Query</a></p>',
$this->parsedown->text('[Up and Down with Query](../../item3/item3-3?foo=bar)'));
$this->assertSame('<p><a href="/subdir/item3/item3-3/foo:bar">Up and Down with Param</a></p>',
$this->parsedown->text('[Up and Down with Param](../../item3/item3-3/foo:bar)'));
$this->assertSame('<p><a href="/subdir/item3/item3-3#foo">Up and Down with Anchor</a></p>',
$this->parsedown->text('[Up and Down with Anchor](../../item3/item3-3#foo)'));
}
public function testSlugRelativeLinksSubDirAbsoluteUrls()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertSame('<p><a href="http://testing.dev/subdir/item2/item2-1">Peer Page</a></p>',
$this->parsedown->text('[Peer Page](../item2-1)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item2/item2-2/item2-2-1">Down a Level</a></p>',
$this->parsedown->text('[Down a Level](item2-2-1)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item2">Up a Level</a></p>',
$this->parsedown->text('[Up a Level](..)'));
$this->assertSame('<p><a href="http://testing.dev/subdir">Up to Root Level</a></p>',
$this->parsedown->text('[Up to Root Level](../..)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item3/item3-3">Up and Down</a></p>',
$this->parsedown->text('[Up and Down](../../item3/item3-3)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item2/item2-2/item2-2-1?foo=bar">Down a Level with Query</a></p>',
$this->parsedown->text('[Down a Level with Query](item2-2-1?foo=bar)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item2?foo=bar">Up a Level with Query</a></p>',
$this->parsedown->text('[Up a Level with Query](../?foo=bar)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item3/item3-3?foo=bar">Up and Down with Query</a></p>',
$this->parsedown->text('[Up and Down with Query](../../item3/item3-3?foo=bar)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item3/item3-3/foo:bar">Up and Down with Param</a></p>',
$this->parsedown->text('[Up and Down with Param](../../item3/item3-3/foo:bar)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item3/item3-3#foo">Up and Down with Anchor</a></p>',
$this->parsedown->text('[Up and Down with Anchor](../../item3/item3-3#foo)'));
}
public function testDirectoryRelativeLinks()
{
$this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init();
$this->assertSame('<p><a href="/item3/item3-3/foo:bar">Up and Down with Param</a></p>',
$this->parsedown->text('[Up and Down with Param](../../03.item3/03.item3-3/foo:bar)'));
$this->assertSame('<p><a href="/item2/item2-1">Peer Page</a></p>',
$this->parsedown->text('[Peer Page](../01.item2-1)'));
$this->assertSame('<p><a href="/item2/item2-2/item2-2-1">Down a Level</a></p>',
$this->parsedown->text('[Down a Level](01.item2-2-1)'));
$this->assertSame('<p><a href="/item3/item3-3">Up and Down</a></p>',
$this->parsedown->text('[Up and Down](../../03.item3/03.item3-3)'));
$this->assertSame('<p><a href="/item2/item2-2/item2-2-1?foo=bar">Down a Level with Query</a></p>',
$this->parsedown->text('[Down a Level with Query](01.item2-2-1?foo=bar)'));
$this->assertSame('<p><a href="/item3/item3-3?foo=bar">Up and Down with Query</a></p>',
$this->parsedown->text('[Up and Down with Query](../../03.item3/03.item3-3?foo=bar)'));
$this->assertSame('<p><a href="/item3/item3-3#foo">Up and Down with Anchor</a></p>',
$this->parsedown->text('[Up and Down with Anchor](../../03.item3/03.item3-3#foo)'));
}
public function testAbsoluteLinks()
{
$this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init();
$this->assertSame('<p><a href="/">Root</a></p>',
$this->parsedown->text('[Root](/)'));
$this->assertSame('<p><a href="/item2/item2-1">Peer Page</a></p>',
$this->parsedown->text('[Peer Page](/item2/item2-1)'));
$this->assertSame('<p><a href="/item2/item2-2/item2-2-1">Down a Level</a></p>',
$this->parsedown->text('[Down a Level](/item2/item2-2/item2-2-1)'));
$this->assertSame('<p><a href="/item2">Up a Level</a></p>',
$this->parsedown->text('[Up a Level](/item2)'));
$this->assertSame('<p><a href="/item2?foo=bar">With Query</a></p>',
$this->parsedown->text('[With Query](/item2?foo=bar)'));
$this->assertSame('<p><a href="/item2/foo:bar">With Param</a></p>',
$this->parsedown->text('[With Param](/item2/foo:bar)'));
$this->assertSame('<p><a href="/item2#foo">With Anchor</a></p>',
$this->parsedown->text('[With Anchor](/item2#foo)'));
}
public function testDirectoryAbsoluteLinksSubDir()
{
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertSame('<p><a href="/subdir/">Root</a></p>',
$this->parsedown->text('[Root](/)'));
$this->assertSame('<p><a href="/subdir/item2/item2-1">Peer Page</a></p>',
$this->parsedown->text('[Peer Page](/item2/item2-1)'));
$this->assertSame('<p><a href="/subdir/item2/item2-2/item2-2-1">Down a Level</a></p>',
$this->parsedown->text('[Down a Level](/item2/item2-2/item2-2-1)'));
$this->assertSame('<p><a href="/subdir/item2">Up a Level</a></p>',
$this->parsedown->text('[Up a Level](/item2)'));
$this->assertSame('<p><a href="/subdir/item2?foo=bar">With Query</a></p>',
$this->parsedown->text('[With Query](/item2?foo=bar)'));
$this->assertSame('<p><a href="/subdir/item2/foo:bar">With Param</a></p>',
$this->parsedown->text('[With Param](/item2/foo:bar)'));
$this->assertSame('<p><a href="/subdir/item2#foo">With Anchor</a></p>',
$this->parsedown->text('[With Anchor](/item2#foo)'));
}
public function testDirectoryAbsoluteLinksSubDirAbsoluteUrl()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertSame('<p><a href="http://testing.dev/subdir/">Root</a></p>',
$this->parsedown->text('[Root](/)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item2/item2-1">Peer Page</a></p>',
$this->parsedown->text('[Peer Page](/item2/item2-1)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item2/item2-2/item2-2-1">Down a Level</a></p>',
$this->parsedown->text('[Down a Level](/item2/item2-2/item2-2-1)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item2">Up a Level</a></p>',
$this->parsedown->text('[Up a Level](/item2)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item2?foo=bar">With Query</a></p>',
$this->parsedown->text('[With Query](/item2?foo=bar)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item2/foo:bar">With Param</a></p>',
$this->parsedown->text('[With Param](/item2/foo:bar)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item2#foo">With Anchor</a></p>',
$this->parsedown->text('[With Anchor](/item2#foo)'));
}
public function testSpecialProtocols()
{
$this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init();
$this->assertSame('<p><a href="mailto:user@domain.com">mailto</a></p>',
$this->parsedown->text('[mailto](mailto:user@domain.com)'));
$this->assertSame('<p><a href="xmpp:xyx@domain.com">xmpp</a></p>',
$this->parsedown->text('[xmpp](xmpp:xyx@domain.com)'));
$this->assertSame('<p><a href="tel:123-555-12345">tel</a></p>',
$this->parsedown->text('[tel](tel:123-555-12345)'));
$this->assertSame('<p><a href="sms:123-555-12345">sms</a></p>',
$this->parsedown->text('[sms](sms:123-555-12345)'));
}
public function testSpecialProtocolsSubDir()
{
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertSame('<p><a href="mailto:user@domain.com">mailto</a></p>',
$this->parsedown->text('[mailto](mailto:user@domain.com)'));
$this->assertSame('<p><a href="xmpp:xyx@domain.com">xmpp</a></p>',
$this->parsedown->text('[xmpp](xmpp:xyx@domain.com)'));
$this->assertSame('<p><a href="tel:123-555-12345">tel</a></p>',
$this->parsedown->text('[tel](tel:123-555-12345)'));
$this->assertSame('<p><a href="sms:123-555-12345">sms</a></p>',
$this->parsedown->text('[sms](sms:123-555-12345)'));
}
public function testSpecialProtocolsSubDirAbsoluteUrl()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertSame('<p><a href="mailto:user@domain.com">mailto</a></p>',
$this->parsedown->text('[mailto](mailto:user@domain.com)'));
$this->assertSame('<p><a href="xmpp:xyx@domain.com">xmpp</a></p>',
$this->parsedown->text('[xmpp](xmpp:xyx@domain.com)'));
$this->assertSame('<p><a href="tel:123-555-12345">tel</a></p>',
$this->parsedown->text('[tel](tel:123-555-12345)'));
$this->assertSame('<p><a href="sms:123-555-12345">sms</a></p>',
$this->parsedown->text('[sms](sms:123-555-12345)'));
}
public function testReferenceLinks()
{
$this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init();
$sample = '[relative link][r_relative]
[r_relative]: ../item2-3#blah';
$this->assertSame('<p><a href="/item2/item2-3#blah">relative link</a></p>',
$this->parsedown->text($sample));
$sample = '[absolute link][r_absolute]
[r_absolute]: /item3#blah';
$this->assertSame('<p><a href="/item3#blah">absolute link</a></p>',
$this->parsedown->text($sample));
$sample = '[external link][r_external]
[r_external]: http://www.cnn.com';
$this->assertSame('<p><a href="http://www.cnn.com">external link</a></p>',
$this->parsedown->text($sample));
}
public function testAttributeLinks()
{
$this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init();
$this->assertSame('<p><a href="/item2/item2-3" class="button">Relative Class</a></p>',
$this->parsedown->text('[Relative Class](../item2-3?classes=button)'));
$this->assertSame('<p><a href="/item2/item2-3" id="unique">Relative ID</a></p>',
$this->parsedown->text('[Relative ID](../item2-3?id=unique)'));
$this->assertSame('<p><a href="https://github.com/getgrav/grav" class="button big">External</a></p>',
$this->parsedown->text('[External](https://github.com/getgrav/grav?classes=button,big)'));
$this->assertSame('<p><a href="/item2/item2-3?id=unique">Relative Noprocess</a></p>',
$this->parsedown->text('[Relative Noprocess](../item2-3?id=unique&noprocess)'));
$this->assertSame('<p><a href="/item2/item2-3" target="_blank">Relative Target</a></p>',
$this->parsedown->text('[Relative Target](../item2-3?target=_blank)'));
$this->assertSame('<p><a href="/item2/item2-3" rel="nofollow">Relative Rel</a></p>',
$this->parsedown->text('[Relative Rel](../item2-3?rel=nofollow)'));
$this->assertSame('<p><a href="/item2/item2-3?foo=bar&baz=qux" rel="nofollow" class="button">Relative Mixed</a></p>',
$this->parsedown->text('[Relative Mixed](../item2-3?foo=bar&baz=qux&rel=nofollow&class=button)'));
}
public function testInvalidLinks()
{
$this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init();
$this->assertSame('<p><a href="/item2/item2-2/no-page">Non Existent Page</a></p>',
$this->parsedown->text('[Non Existent Page](no-page)'));
$this->assertSame('<p><a href="/item2/item2-2/existing-file.zip">Existent File</a></p>',
$this->parsedown->text('[Existent File](existing-file.zip)'));
$this->assertSame('<p><a href="/item2/item2-2/missing-file.zip">Non Existent File</a></p>',
$this->parsedown->text('[Non Existent File](missing-file.zip)'));
}
public function testInvalidLinksSubDir()
{
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertSame('<p><a href="/subdir/item2/item2-2/no-page">Non Existent Page</a></p>',
$this->parsedown->text('[Non Existent Page](no-page)'));
$this->assertSame('<p><a href="/subdir/item2/item2-2/existing-file.zip">Existent File</a></p>',
$this->parsedown->text('[Existent File](existing-file.zip)'));
$this->assertSame('<p><a href="/subdir/item2/item2-2/missing-file.zip">Non Existent File</a></p>',
$this->parsedown->text('[Non Existent File](missing-file.zip)'));
}
public function testInvalidLinksSubDirAbsoluteUrl()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
$this->assertSame('<p><a href="http://testing.dev/subdir/item2/item2-2/no-page">Non Existent Page</a></p>',
$this->parsedown->text('[Non Existent Page](no-page)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item2/item2-2/existing-file.zip">Existent File</a></p>',
$this->parsedown->text('[Existent File](existing-file.zip)'));
$this->assertSame('<p><a href="http://testing.dev/subdir/item2/item2-2/missing-file.zip">Non Existent File</a></p>',
$this->parsedown->text('[Non Existent File](missing-file.zip)'));
}
/**
* @param $string
*
* @return mixed
*/
private function stripLeadingWhitespace($string)
{
return preg_replace('/^\s*(.*)/', '', $string);
}
}

View File

@@ -1,271 +0,0 @@
<?php
use Codeception\Util\Fixtures;
use Grav\Common\Grav;
use Grav\Common\Uri;
use Grav\Common\Config\Config;
use Grav\Common\Page\Pages;
use Grav\Common\Page\Page;
use Grav\Common\Markdown\Parsedown;
/**
* Class AssetsTest
*/
class MarkdownTest extends \Codeception\TestCase\Test
{
/** @var Parsedown $parsedown */
protected $parsedown;
/** @var Grav $grav */
protected $grav;
/** @var Pages $pages */
protected $pages;
/** @var Config $config */
protected $config;
/** @var Uri $uri */
protected $uri;
static $run = false;
protected function _before()
{
$this->grav = Fixtures::get('grav');
$this->pages = $this->grav['pages'];
$this->config = $this->grav['config'];
$this->uri = $this->grav['uri'];
if (!self::$run) {
/** @var UniformResourceLocator $locator */
$locator = $this->grav['locator'];
$locator->addPath('page', '', 'tests/fake/nested-site/user/pages', false);
$this->pages->init();
self::$run = true;
}
$defaults = [
'extra' => false,
'auto_line_breaks' => false,
'auto_url_links' => false,
'escape_markup' => false,
'special_chars' => ['>' => 'gt', '<' => 'lt'],
];
$page = $this->pages->dispatch('/item2/item2-2');
$this->parsedown = new Parsedown($page, $defaults);
}
protected function _after()
{
}
/**
* @param $string
*
* @return mixed
*/
public function stripLeadingWhitespace($string)
{
return preg_replace('/^\s*(.*)/', '', $string);
}
public function testAnchorLinksNoPortRelativeUrls()
{
$this->config->set('system.absolute_urls', false);
$this->uri->initializeWithURL('http://localhost/item2/item-2-2')->init();
$this->assertSame('<p><a href="/item2/item2-1#foo">Peer Anchor</a></p>',
$this->parsedown->text('[Peer Anchor](../item2-1#foo)'));
$this->assertSame('<p><a href="/item2/item2-1/#foo">Peer Anchor 2</a></p>',
$this->parsedown->text('[Peer Anchor 2](../item2-1/#foo)'));
// $this->assertSame('<p><a href="#foo">Current Anchor</a></p>',
// $this->parsedown->text('[Current Anchor](#foo)'));
$this->assertSame('<p><a href="/#foo">Root Anchor</a></p>',
$this->parsedown->text('[Root Anchor](/#foo)'));
}
public function testAnchorLinksNoPortAbsoluteUrls()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithURL('http://localhost/item2/item-2-2')->init();
$this->assertSame('<p><a href="http://localhost/item2/item2-1#foo">Peer Anchor</a></p>',
$this->parsedown->text('[Peer Anchor](../item2-1#foo)'));
$this->assertSame('<p><a href="http://localhost/item2/item2-1/#foo">Peer Anchor 2</a></p>',
$this->parsedown->text('[Peer Anchor 2](../item2-1/#foo)'));
// $this->assertSame('<p><a href="#foo">Current Anchor</a></p>',
// $this->parsedown->text('[Current Anchor](#foo)'));
$this->assertSame('<p><a href="http://localhost/#foo">Root Anchor</a></p>',
$this->parsedown->text('[Root Anchor](/#foo)'));
}
public function testAnchorLinksWithPortAbsoluteUrls()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithURL('http://localhost:8080/item2/item-2-2')->init();
$this->assertSame('<p><a href="http://localhost:8080/item2/item2-1#foo">Peer Anchor</a></p>',
$this->parsedown->text('[Peer Anchor](../item2-1#foo)'));
$this->assertSame('<p><a href="http://localhost:8080/item2/item2-1/#foo">Peer Anchor 2</a></p>',
$this->parsedown->text('[Peer Anchor 2](../item2-1/#foo)'));
// $this->assertSame('<p><a href="http://localhost:8080#foo">Current Anchor</a></p>',
// $this->parsedown->text('[Current Anchor](#foo)'));
$this->assertSame('<p><a href="http://localhost:8080/#foo">Root Anchor</a></p>',
$this->parsedown->text('[Root Anchor](/#foo)'));
}
public function testAnchorLinksSubDirRelativeUrls()
{
$this->config->set('system.absolute_urls', false);
$this->uri->initializeWithUrlAndRootPath('http://localhost/subdir/item2/item-2-2', '/subdir')->init();
$this->assertSame('<p><a href="/subdir/item2/item2-1#foo">Peer Anchor</a></p>',
$this->parsedown->text('[Peer Anchor](../item2-1#foo)'));
$this->assertSame('<p><a href="/subdir/item2/item2-1/#foo">Peer Anchor 2</a></p>',
$this->parsedown->text('[Peer Anchor 2](../item2-1/#foo)'));
// $this->assertSame('<p><a href="/subdir/#foo">Current Anchor</a></p>',
// $this->parsedown->text('[Current Anchor](#foo)'));
$this->assertSame('<p><a href="/subdir/#foo">Root Anchor</a></p>',
$this->parsedown->text('[Root Anchor](/#foo)'));
}
public function testAnchorLinksSubDirAbsoluteUrls()
{
$this->config->set('system.absolute_urls', true);
$this->uri->initializeWithUrlAndRootPath('http://localhost/subdir/item2/item-2-2', '/subdir')->init();
$this->assertSame('<p><a href="http://localhost/subdir/item2/item2-1#foo">Peer Anchor</a></p>',
$this->parsedown->text('[Peer Anchor](../item2-1#foo)'));
$this->assertSame('<p><a href="http://localhost/subdir/item2/item2-1/#foo">Peer Anchor 2</a></p>',
$this->parsedown->text('[Peer Anchor 2](../item2-1/#foo)'));
// $this->assertSame('<p><a href="http://localhost/subdir#foo">Current Anchor</a></p>',
// $this->parsedown->text('[Current Anchor](#foo)'));
$this->assertSame('<p><a href="http://localhost/subdir/#foo">Root Anchor</a></p>',
$this->parsedown->text('[Root Anchor](/#foo)'));
}
public function testSlugRelativeLinks()
{
$this->config->set('system.absolute_urls', false);
$this->uri->initializeWithURL('http://localhost/item2/item-2-2')->init();
$this->assertSame('<p><a href="/item2/item2-1">Peer Page</a></p>',
$this->parsedown->text('[Peer Page](../item2-1)'));
$this->assertSame('<p><a href="/item2/item2-2/item2-2-1">Down a Level</a></p>',
$this->parsedown->text('[Down a Level](item2-2-1)'));
$this->assertSame('<p><a href="/item2">Up a Level</a></p>',
$this->parsedown->text('[Up a Level](..)'));
$this->assertSame('<p><a href="/item3/item3-3">Up and Down</a></p>',
$this->parsedown->text('[Up and Down](../../item3/item3-3)'));
$this->assertSame('<p><a href="/item2/item2-2/item2-2-1?foo=bar">Down a Level with Query</a></p>',
$this->parsedown->text('[Down a Level with Query](item2-2-1?foo=bar)'));
// $this->assertSame('<p><a href="/item2?foo=bar">Up a Level with Query</a></p>',
// $this->parsedown->text('[Up a Level with Query](../?foo=bar)'));
$this->assertSame('<p><a href="/item3/item3-3?foo=bar">Up and Down with Query</a></p>',
$this->parsedown->text('[Up and Down with Query](../../item3/item3-3?foo=bar)'));
$this->assertSame('<p><a href="/item3/item3-3/foo:bar">Up and Down with Param</a></p>',
$this->parsedown->text('[Up and Down with Param](../../item3/item3-3/foo:bar)'));
$this->assertSame('<p><a href="/item3/item3-3#foo">Up and Down with Anchor</a></p>',
$this->parsedown->text('[Up and Down with Anchor](../../item3/item3-3#foo)'));
}
public function testDirectoryRelativeLinks()
{
$this->config->set('system.absolute_urls', false);
$this->uri->initializeWithURL('http://localhost/item2/item-2-2')->init();
$this->assertSame('<p><a href="/item2/item2-1">Peer Page</a></p>',
$this->parsedown->text('[Peer Page](../01.item2-1)'));
$this->assertSame('<p><a href="/item2/item2-2/item2-2-1">Down a Level</a></p>',
$this->parsedown->text('[Down a Level](01.item2-2-1)'));
$this->assertSame('<p><a href="/item3/item3-3">Up and Down</a></p>',
$this->parsedown->text('[Up and Down](../../03.item3/03.item3-3)'));
$this->assertSame('<p><a href="/item2/item2-2/item2-2-1?foo=bar">Down a Level with Query</a></p>',
$this->parsedown->text('[Down a Level with Query](01.item2-2-1?foo=bar)'));
$this->assertSame('<p><a href="/item3/item3-3?foo=bar">Up and Down with Query</a></p>',
$this->parsedown->text('[Up and Down with Query](../../03.item3/03.item3-3?foo=bar)'));
// $this->assertSame('<p><a href="/item3/item3-3/foo:bar">Up and Down with Param</a></p>',
// $this->parsedown->text('[Up and Down with Param](../../03.item3/03.item3-3/foo:bar)'));
$this->assertSame('<p><a href="/item3/item3-3#foo">Up and Down with Anchor</a></p>',
$this->parsedown->text('[Up and Down with Anchor](../../03.item3/03.item3-3#foo)'));
}
public function testDirectoryAbsoluteLinks()
{
$this->config->set('system.absolute_urls', false);
$this->uri->initializeWithURL('http://localhost/item2/item-2-2')->init();
$this->assertSame('<p><a href="/item2/item2-1">Peer Page</a></p>',
$this->parsedown->text('[Peer Page](/item2/item2-1)'));
$this->assertSame('<p><a href="/item2/item2-2/item2-2-1">Down a Level</a></p>',
$this->parsedown->text('[Down a Level](/item2/item2-2/item2-2-1)'));
$this->assertSame('<p><a href="/item2">Up a Level</a></p>',
$this->parsedown->text('[Up a Level](/item2)'));
$this->assertSame('<p><a href="/item2?foo=bar">With Query</a></p>',
$this->parsedown->text('[With Query](/item2?foo=bar)'));
$this->assertSame('<p><a href="/item2/foo:bar">With Param</a></p>',
$this->parsedown->text('[With Param](/item2/foo:bar)'));
$this->assertSame('<p><a href="/item2#foo">With Anchor</a></p>',
$this->parsedown->text('[With Anchor](/item2#foo)'));
}
public function testSpecialProtocols()
{
$this->config->set('system.absolute_urls', false);
$this->uri->initializeWithURL('http://localhost/item2/item-2-2')->init();
$this->assertSame('<p><a href="mailto:user@domain.com">mailto</a></p>',
$this->parsedown->text('[mailto](mailto:user@domain.com)'));
$this->assertSame('<p><a href="xmpp:xyx@domain.com">xmpp</a></p>',
$this->parsedown->text('[xmpp](xmpp:xyx@domain.com)'));
$this->assertSame('<p><a href="tel:123-555-12345">tel</a></p>',
$this->parsedown->text('[tel](tel:123-555-12345)'));
$this->assertSame('<p><a href="sms:123-555-12345">sms</a></p>',
$this->parsedown->text('[sms](sms:123-555-12345)'));
}
public function testReferenceLinks()
{
$this->config->set('system.absolute_urls', false);
$this->uri->initializeWithURL('http://localhost/item2/item-2-2')->init();
$sample = '[relative link][r_relative]
[r_relative]: ../item2-3#blah';
$this->assertSame('<p><a href="/item2/item2-3#blah">relative link</a></p>',
$this->parsedown->text($sample));
$sample = '[absolute link][r_absolute]
[r_absolute]: /item3#blah';
$this->assertSame('<p><a href="/item3#blah">absolute link</a></p>',
$this->parsedown->text($sample));
$sample = '[external link][r_external]
[r_external]: http://www.cnn.com';
$this->assertSame('<p><a href="http://www.cnn.com">external link</a></p>',
$this->parsedown->text($sample));
}
public function testExternalLinks()
{
$this->assertSame('<p><a href="http://www.cnn.com">cnn.com</a></p>',
$this->parsedown->text('[cnn.com](http://www.cnn.com)'));
$this->assertSame('<p><a href="https://www.google.com">google.com</a></p>',
$this->parsedown->text('[google.com](https://www.google.com)'));
}
}

View File

@@ -27,10 +27,12 @@ class PagesTest extends \Codeception\TestCase\Test
{
$this->grav = Fixtures::get('grav');
$this->pages = $this->grav['pages'];
$this->grav['config']->set('system.home.alias', '/home');
if (!self::$run) {
/** @var UniformResourceLocator $locator */
$locator = $this->grav['locator'];
$locator->addPath('page', '', 'tests/fake/simple-site/user/pages', false);
$this->pages->init();
self::$run = true;
@@ -38,11 +40,194 @@ class PagesTest extends \Codeception\TestCase\Test
}
public function testBase()
{
$this->assertSame('', $this->pages->base());
$this->pages->base('/test');
$this->assertSame('/test', $this->pages->base());
$this->pages->base('');
$this->assertSame(null, $this->pages->base());
}
public function testLastModified()
{
$this->assertSame(null, $this->pages->lastModified());
$this->pages->lastModified('test');
$this->assertSame('test', $this->pages->lastModified());
}
public function testInstances()
{
$this->assertTrue(is_array($this->pages->instances()));
foreach($this->pages->instances() as $instance) {
$this->assertInstanceOf('Grav\Common\Page\Page', $instance);
}
}
public function testRoutes()
{
/** @var UniformResourceLocator $locator */
$locator = $this->grav['locator'];
$this->assertTrue(is_array($this->pages->routes()));
$this->assertSame($locator->findResource('tests://') . '/fake/simple-site/user/pages/01.home', $this->pages->routes()['/']);
$this->assertSame($locator->findResource('tests://') . '/fake/simple-site/user/pages/01.home', $this->pages->routes()['/home']);
$this->assertSame($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog', $this->pages->routes()['/blog']);
$this->assertSame($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-one', $this->pages->routes()['/blog/post-one']);
$this->assertSame($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-two', $this->pages->routes()['/blog/post-two']);
$this->assertSame($locator->findResource('tests://') . '/fake/simple-site/user/pages/03.about', $this->pages->routes()['/about']);
}
public function testAddPage()
{
/** @var UniformResourceLocator $locator */
$locator = $this->grav['locator'];
$path = $locator->findResource('tests://') . '/fake/single-pages/01.simple-page/default.md';
$aPage = new Page();
$aPage->init(new \SplFileInfo($path));
$this->pages->addPage($aPage, '/new-page');
$this->assertTrue(in_array('/new-page', array_keys($this->pages->routes())));
$this->assertSame($locator->findResource('tests://') . '/fake/single-pages/01.simple-page', $this->pages->routes()['/new-page']);
}
public function testSort()
{
/** @var UniformResourceLocator $locator */
$locator = $this->grav['locator'];
$aPage = $this->pages->dispatch('/blog');
$subPagesSorted = $this->pages->sort($aPage);
$this->assertTrue(is_array($subPagesSorted));
$this->assertTrue(count($subPagesSorted) === 2);
$this->assertSame($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-one', array_keys($subPagesSorted)[0]);
$this->assertSame($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-two', array_keys($subPagesSorted)[1]);
$this->assertTrue(in_array($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-one', array_keys($subPagesSorted)));
$this->assertTrue(in_array($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-two', array_keys($subPagesSorted)));
$this->assertSame(["slug" => "post-one"], $subPagesSorted[$locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-one']);
$this->assertSame(["slug" => "post-two"], $subPagesSorted[$locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-two']);
$subPagesSorted = $this->pages->sort($aPage, null, 'desc');
$this->assertTrue(is_array($subPagesSorted));
$this->assertTrue(count($subPagesSorted) === 2);
$this->assertSame($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-two', array_keys($subPagesSorted)[0]);
$this->assertSame($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-one', array_keys($subPagesSorted)[1]);
$this->assertTrue(in_array($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-one', array_keys($subPagesSorted)));
$this->assertTrue(in_array($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-two', array_keys($subPagesSorted)));
$this->assertSame(["slug" => "post-one"], $subPagesSorted[$locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-one']);
$this->assertSame(["slug" => "post-two"], $subPagesSorted[$locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-two']);
}
public function testSortCollection()
{
/** @var UniformResourceLocator $locator */
$locator = $this->grav['locator'];
$aPage = $this->pages->dispatch('/blog');
$subPagesSorted = $this->pages->sortCollection($aPage->children(), $aPage->orderBy());
$this->assertTrue(is_array($subPagesSorted));
$this->assertTrue(count($subPagesSorted) === 2);
$this->assertSame($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-one', array_keys($subPagesSorted)[0]);
$this->assertSame($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-two', array_keys($subPagesSorted)[1]);
$this->assertTrue(in_array($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-one', array_keys($subPagesSorted)));
$this->assertTrue(in_array($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-two', array_keys($subPagesSorted)));
$this->assertSame(["slug" => "post-one"], $subPagesSorted[$locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-one']);
$this->assertSame(["slug" => "post-two"], $subPagesSorted[$locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-two']);
$subPagesSorted = $this->pages->sortCollection($aPage->children(), $aPage->orderBy(), 'desc');
$this->assertTrue(is_array($subPagesSorted));
$this->assertTrue(count($subPagesSorted) === 2);
$this->assertSame($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-two', array_keys($subPagesSorted)[0]);
$this->assertSame($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-one', array_keys($subPagesSorted)[1]);
$this->assertTrue(in_array($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-one', array_keys($subPagesSorted)));
$this->assertTrue(in_array($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-two', array_keys($subPagesSorted)));
$this->assertSame(["slug" => "post-one"], $subPagesSorted[$locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-one']);
$this->assertSame(["slug" => "post-two"], $subPagesSorted[$locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog/post-two']);
}
public function testGet()
{
/** @var UniformResourceLocator $locator */
$locator = $this->grav['locator'];
//Page existing
$aPage = $this->pages->get($locator->findResource('tests://') . '/fake/simple-site/user/pages/03.about');
$this->assertTrue(is_object($aPage));
$this->assertInstanceOf('Grav\Common\Page\Page', $aPage);
//Page not existing
$anotherPage = $this->pages->get($locator->findResource('tests://') . '/fake/simple-site/user/pages/03.non-existing');
$this->assertFalse(is_object($anotherPage));
$this->assertNull($anotherPage);
}
public function testChildren()
{
/** @var UniformResourceLocator $locator */
$locator = $this->grav['locator'];
//Page existing
$children = $this->pages->children($locator->findResource('tests://') . '/fake/simple-site/user/pages/02.blog');
$this->assertInstanceOf('Grav\Common\Page\Collection', $children);
//Page not existing
$children = $this->pages->children($locator->findResource('tests://') . '/fake/whatever/non-existing');
$this->assertSame([], $children->toArray());
}
public function testDispatch()
{
$aPage = $this->pages->dispatch('/blog');
$this->assertInstanceOf('Grav\Common\Page\Page', $aPage);
$aPage = $this->pages->dispatch('/about');
$this->assertInstanceOf('Grav\Common\Page\Page', $aPage);
$aPage = $this->pages->dispatch('/blog/post-one');
$this->assertInstanceOf('Grav\Common\Page\Page', $aPage);
//Page not existing
$aPage = $this->pages->dispatch('/non-existing');
$this->assertNull($aPage);
}
public function testRoot()
{
$root = $this->pages->root();
$this->assertInstanceOf('Grav\Common\Page\Page', $root);
$this->assertSame('pages', $root->folder());
}
public function testBlueprints()
{
}
public function testAll()
{
$this->assertTrue(is_object($this->pages->all()));
$this->assertTrue(is_array($this->pages->all()->toArray()));
$this->assertInstanceOf('Grav\Common\Page\Page', $this->pages->all()->first());
foreach($this->pages->all() as $page) {
$this->assertInstanceOf('Grav\Common\Page\Page', $page);
}
}
public function testGetList()
@@ -52,4 +237,50 @@ class PagesTest extends \Codeception\TestCase\Test
$this->assertSame('Home', $list['/']);
$this->assertSame('Blog', $list['/blog']);
}
public function testGetTypes()
{
}
public function testTypes()
{
}
public function testModularTypes()
{
}
public function testPageTypes()
{
}
public function testAccessLevels()
{
}
public function testParents()
{
}
public function testParentsRawRoutes()
{
}
public function testGetHomeRoute()
{
}
public function testResetPages()
{
}
}

View File

@@ -247,9 +247,6 @@ class UriTest extends \Codeception\TestCase\Test
$this->assertSame($address, $this->uri->host());
$this->uri->initializeWithURL('http://localhost/')->init();
$this->assertSame($address, $this->uri->host());
//Host is set to localhost when running from local
$this->uri->initializeWithURL('http://google.com/')->init();
$this->assertSame($address, $this->uri->host());
}
public function testPort()
@@ -400,7 +397,7 @@ class UriTest extends \Codeception\TestCase\Test
public function testConvertUrl()
{
//TODO when we have a fixed testing page structure
}
public function testAddNonce()