Compare commits
42 commits
master
...
feature/bo
Author | SHA1 | Date | |
---|---|---|---|
|
cdf54b5a42 | ||
|
f80a1b93d1 | ||
|
b18c124e44 | ||
|
5089b567d3 | ||
|
cc877fdf41 | ||
|
69df09aea2 | ||
|
8e65b99838 | ||
|
6fb160babf | ||
|
50b57b7918 | ||
|
81b99af874 | ||
|
9112618871 | ||
|
7644e060d4 | ||
|
02da39ebdf | ||
|
1fdab97b07 | ||
|
a2b825ff49 | ||
|
d25f0df4a0 | ||
|
e6f832e5fb | ||
|
88132e2b17 | ||
|
ed50308d4c | ||
|
5decee52b8 | ||
|
9b03d0c37b | ||
|
014674cdf6 | ||
|
0c996ec58d | ||
|
4d02148e3b | ||
|
a871b7f455 | ||
|
0fb616381e | ||
|
08c0aa8ef9 | ||
|
99283e90a4 | ||
|
c4f9eb8d4e | ||
|
2465906151 | ||
|
f1048d2366 | ||
|
e50cc1404b | ||
|
782139cf08 | ||
|
c6b86381f0 | ||
|
a484681e38 | ||
|
84c1424ed4 | ||
|
ed92a8a730 | ||
|
158f6fafb9 | ||
|
c5f5512c63 | ||
|
25f259e7bc | ||
|
716c972fdc | ||
|
a4035ffa98 |
65 changed files with 2823 additions and 4700 deletions
|
@ -1,25 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
[ -n "$PICO_BUILD_ENV" ] || { echo "No Pico build environment specified" >&2; exit 1; }
|
||||
|
||||
# parameters
|
||||
ARCHIVE_DIR="${1:-$PICO_PROJECT_DIR}" # directory to create release archives in
|
||||
|
||||
# print parameters
|
||||
echo "Cleaning up build environment..."
|
||||
printf 'PICO_DEPLOY_DIR="%s"\n' "$PICO_DEPLOY_DIR"
|
||||
printf 'PICO_BUILD_DIR="%s"\n' "$PICO_BUILD_DIR"
|
||||
printf 'ARCHIVE_DIR="%s"\n' "$ARCHIVE_DIR"
|
||||
echo
|
||||
|
||||
echo "Removing deployment directory..."
|
||||
[ ! -d "$PICO_DEPLOY_DIR" ] || rm -rf "$PICO_DEPLOY_DIR"
|
||||
|
||||
echo "Removing build directory..."
|
||||
[ ! -d "$PICO_BUILD_DIR" ] || rm -rf "$PICO_BUILD_DIR"
|
||||
|
||||
echo "Removing release archives..."
|
||||
find "$ARCHIVE_DIR" -mindepth 1 -maxdepth 1 \
|
||||
\( -name 'pico-release-*.tar.gz' -o -name 'pico-release-*.zip' \) \
|
||||
-delete
|
|
@ -1,44 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
[ -n "$PICO_BUILD_ENV" ] || { echo "No Pico build environment specified" >&2; exit 1; }
|
||||
|
||||
# get current Pico milestone
|
||||
VERSION="$(php -r "require_once('$PICO_PROJECT_DIR/lib/Pico.php'); echo Pico::VERSION;")"
|
||||
MILESTONE="Pico$([[ "$VERSION" =~ ^([0-9]+\.[0-9]+)\. ]] && echo " ${BASH_REMATCH[1]}")"
|
||||
|
||||
echo "Deploying $PROJECT_REPO_BRANCH branch ($MILESTONE)..."
|
||||
echo
|
||||
|
||||
# clone repo
|
||||
github-clone.sh "$PICO_DEPLOY_DIR" "https://github.com/$DEPLOY_REPO_SLUG.git" "$DEPLOY_REPO_BRANCH"
|
||||
|
||||
cd "$PICO_DEPLOY_DIR"
|
||||
|
||||
# setup repo
|
||||
github-setup.sh
|
||||
|
||||
# generate phpDocs
|
||||
generate-phpdoc.sh \
|
||||
"$PICO_PROJECT_DIR/.phpdoc.xml" \
|
||||
"$PICO_DEPLOY_DIR/phpDoc/$PICO_DEPLOYMENT.cache" "$PICO_DEPLOY_DIR/phpDoc/$PICO_DEPLOYMENT" \
|
||||
"$MILESTONE API Documentation ($PROJECT_REPO_BRANCH branch)"
|
||||
|
||||
if [ -z "$(git status --porcelain "$PICO_DEPLOY_DIR/phpDoc/$PICO_DEPLOYMENT.cache")" ]; then
|
||||
# nothing to do
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# update phpDoc list
|
||||
update-phpdoc-list.sh \
|
||||
"$PICO_DEPLOY_DIR/_data/phpDoc.yml" \
|
||||
"$PICO_DEPLOYMENT" "branch" "<code>$PROJECT_REPO_BRANCH</code> branch" "$(date +%s)"
|
||||
|
||||
# commit phpDocs
|
||||
github-commit.sh \
|
||||
"Update phpDocumentor class docs for $PROJECT_REPO_BRANCH branch @ $PROJECT_REPO_COMMIT" \
|
||||
"$PICO_DEPLOY_DIR/phpDoc/$PICO_DEPLOYMENT.cache" "$PICO_DEPLOY_DIR/phpDoc/$PICO_DEPLOYMENT" \
|
||||
"$PICO_DEPLOY_DIR/_data/phpDoc.yml"
|
||||
|
||||
# deploy phpDocs
|
||||
github-deploy.sh "$PROJECT_REPO_SLUG" "heads/$PROJECT_REPO_BRANCH" "$PROJECT_REPO_COMMIT"
|
|
@ -1,119 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
[ -n "$PICO_BUILD_ENV" ] || { echo "No Pico build environment specified" >&2; exit 1; }
|
||||
|
||||
DEPLOY_FULL="true"
|
||||
if [ "$DEPLOY_PHPDOC_RELEASES" != "true" ]; then
|
||||
echo "Skipping phpDoc release deployment because it has been disabled"
|
||||
DEPLOY_FULL="false"
|
||||
fi
|
||||
if [ "$DEPLOY_VERSION_BADGE" != "true" ]; then
|
||||
echo "Skipping version badge deployment because it has been disabled"
|
||||
DEPLOY_FULL="false"
|
||||
fi
|
||||
if [ "$DEPLOY_VERSION_FILE" != "true" ]; then
|
||||
echo "Skipping version file deployment because it has been disabled"
|
||||
DEPLOY_FULL="false"
|
||||
fi
|
||||
if [ "$DEPLOY_CLOC_STATS" != "true" ]; then
|
||||
echo "Skipping cloc statistics deployment because it has been disabled"
|
||||
DEPLOY_FULL="false"
|
||||
fi
|
||||
|
||||
if [ "$DEPLOY_FULL" != "true" ]; then
|
||||
if [ "$DEPLOY_PHPDOC_RELEASES" != "true" ] \
|
||||
&& [ "$DEPLOY_VERSION_BADGE" != "true" ] \
|
||||
&& [ "$DEPLOY_VERSION_FILE" != "true" ] \
|
||||
&& [ "$DEPLOY_CLOC_STATS" != "true" ]
|
||||
then
|
||||
# nothing to do
|
||||
exit 0
|
||||
fi
|
||||
echo
|
||||
fi
|
||||
|
||||
# parse version
|
||||
. "$PICO_TOOLS_DIR/functions/parse-version.sh.inc"
|
||||
|
||||
if ! parse_version "$PROJECT_REPO_TAG"; then
|
||||
echo "Invalid version '$PROJECT_REPO_TAG'; aborting..." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Deploying Pico $VERSION_MILESTONE ($VERSION_STABILITY)..."
|
||||
printf 'VERSION_FULL="%s"\n' "$VERSION_FULL"
|
||||
printf 'VERSION_NAME="%s"\n' "$VERSION_NAME"
|
||||
printf 'VERSION_ID="%s"\n' "$VERSION_ID"
|
||||
echo
|
||||
|
||||
# clone repo
|
||||
github-clone.sh "$PICO_DEPLOY_DIR" "https://github.com/$DEPLOY_REPO_SLUG.git" "$DEPLOY_REPO_BRANCH"
|
||||
|
||||
cd "$PICO_DEPLOY_DIR"
|
||||
|
||||
# setup repo
|
||||
github-setup.sh
|
||||
|
||||
# generate phpDocs
|
||||
if [ "$DEPLOY_PHPDOC_RELEASES" == "true" ]; then
|
||||
# generate phpDocs
|
||||
generate-phpdoc.sh \
|
||||
"$PICO_PROJECT_DIR/.phpdoc.xml" \
|
||||
"-" "$PICO_DEPLOY_DIR/phpDoc/$PICO_DEPLOYMENT" \
|
||||
"Pico $VERSION_MILESTONE API Documentation (v$VERSION_FULL)"
|
||||
|
||||
if [ -n "$(git status --porcelain "$PICO_DEPLOY_DIR/phpDoc/$PICO_DEPLOYMENT")" ]; then
|
||||
# update phpDoc list
|
||||
update-phpdoc-list.sh \
|
||||
"$PICO_DEPLOY_DIR/_data/phpDoc.yml" \
|
||||
"$PICO_DEPLOYMENT" "version" "Pico $VERSION_FULL" "$(date +%s)"
|
||||
|
||||
# commit phpDocs
|
||||
github-commit.sh \
|
||||
"Update phpDocumentor class docs for v$VERSION_FULL" \
|
||||
"$PICO_DEPLOY_DIR/phpDoc/$PICO_DEPLOYMENT" "$PICO_DEPLOY_DIR/_data/phpDoc.yml"
|
||||
fi
|
||||
fi
|
||||
|
||||
# don't update version badge, version file and cloc statistics for pre-releases
|
||||
if [ "$VERSION_STABILITY" == "stable" ]; then
|
||||
# update version badge
|
||||
if [ "$DEPLOY_VERSION_BADGE" == "true" ]; then
|
||||
generate-badge.sh \
|
||||
"$PICO_DEPLOY_DIR/badges/pico-version.svg" \
|
||||
"release" "$VERSION_FULL" "blue"
|
||||
|
||||
# commit version badge
|
||||
github-commit.sh \
|
||||
"Update version badge for v$VERSION_FULL" \
|
||||
"$PICO_DEPLOY_DIR/badges/pico-version.svg"
|
||||
fi
|
||||
|
||||
# update version file
|
||||
if [ "$DEPLOY_VERSION_FILE" == "true" ]; then
|
||||
update-version-file.sh \
|
||||
"$PICO_DEPLOY_DIR/_data/version.yml" \
|
||||
"$VERSION_FULL"
|
||||
|
||||
# commit version file
|
||||
github-commit.sh \
|
||||
"Update version file for v$VERSION_FULL" \
|
||||
"$PICO_DEPLOY_DIR/_data/version.yml"
|
||||
fi
|
||||
|
||||
# update cloc statistics
|
||||
if [ "$DEPLOY_CLOC_STATS" == "true" ]; then
|
||||
update-cloc-stats.sh \
|
||||
"$PICO_PROJECT_DIR" \
|
||||
"$PICO_DEPLOY_DIR/_data/cloc.yml"
|
||||
|
||||
# commit cloc statistics
|
||||
github-commit.sh \
|
||||
"Update cloc statistics for v$VERSION_FULL" \
|
||||
"$PICO_DEPLOY_DIR/_data/cloc.yml"
|
||||
fi
|
||||
fi
|
||||
|
||||
# deploy
|
||||
github-deploy.sh "$PROJECT_REPO_SLUG" "tags/$PROJECT_REPO_TAG" "$PROJECT_REPO_COMMIT"
|
|
@ -1,19 +0,0 @@
|
|||
if [ -z "$PICO_BUILD_ENV" ]; then
|
||||
echo "No Pico build environment specified" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# add project build dir to $PATH
|
||||
export PATH="$PICO_PROJECT_DIR/.build:$PATH"
|
||||
|
||||
# set environment variables
|
||||
__picocms_cmd export RELEASE_REPO_SLUG="${RELEASE_REPO_SLUG:-picocms/pico-composer}"
|
||||
__picocms_cmd export RELEASE_REPO_BRANCH="${RELEASE_REPO_BRANCH:-master}"
|
||||
|
||||
if [ "$PROJECT_REPO_SLUG" != "picocms/Pico" ]; then
|
||||
__picocms_cmd export DEPLOY_REPO_SLUG="${DEPLOY_REPO_SLUG:-$PROJECT_REPO_SLUG}"
|
||||
__picocms_cmd export DEPLOY_REPO_BRANCH="${DEPLOY_REPO_BRANCH:-gh-pages}"
|
||||
else
|
||||
__picocms_cmd export DEPLOY_REPO_SLUG="${DEPLOY_REPO_SLUG:-picocms.github.io}"
|
||||
__picocms_cmd export DEPLOY_REPO_BRANCH="${DEPLOY_REPO_BRANCH:-master}"
|
||||
fi
|
|
@ -1,40 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
[ -n "$PICO_BUILD_ENV" ] || { echo "No Pico build environment specified" >&2; exit 1; }
|
||||
|
||||
# setup build system
|
||||
BUILD_REQUIREMENTS=( --phpcs )
|
||||
[ "$1" != "--deploy" ] || BUILD_REQUIREMENTS+=( --cloc --phpdoc )
|
||||
"$PICO_TOOLS_DIR/setup/$PICO_BUILD_ENV.sh" "${BUILD_REQUIREMENTS[@]}"
|
||||
|
||||
# set COMPOSER_ROOT_VERSION when necessary
|
||||
if [ -z "$COMPOSER_ROOT_VERSION" ] && [ -n "$PROJECT_REPO_BRANCH" ]; then
|
||||
echo "Setting up Composer..."
|
||||
|
||||
PICO_VERSION_PATTERN="$(php -r "
|
||||
\$json = json_decode(file_get_contents('$PICO_PROJECT_DIR/composer.json'), true);
|
||||
if (\$json !== null) {
|
||||
if (isset(\$json['extra']['branch-alias']['dev-$PROJECT_REPO_BRANCH'])) {
|
||||
echo 'dev-$PROJECT_REPO_BRANCH';
|
||||
}
|
||||
}
|
||||
")"
|
||||
|
||||
if [ -z "$PICO_VERSION_PATTERN" ]; then
|
||||
PICO_VERSION_PATTERN="$(php -r "
|
||||
require_once('$PICO_PROJECT_DIR/lib/Pico.php');
|
||||
echo preg_replace('/\.[0-9]+-dev$/', '.x-dev', Pico::VERSION);
|
||||
")"
|
||||
fi
|
||||
|
||||
if [ -n "$PICO_VERSION_PATTERN" ]; then
|
||||
export COMPOSER_ROOT_VERSION="$PICO_VERSION_PATTERN"
|
||||
fi
|
||||
|
||||
echo
|
||||
fi
|
||||
|
||||
# install dependencies
|
||||
echo "Running \`composer install\`$([ -n "$COMPOSER_ROOT_VERSION" ] && echo -n " ($COMPOSER_ROOT_VERSION)")..."
|
||||
composer install --no-suggest
|
|
@ -1,91 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
[ -n "$PICO_BUILD_ENV" ] || { echo "No Pico build environment specified" >&2; exit 1; }
|
||||
|
||||
# parameters
|
||||
VERSION="${1:-$PROJECT_REPO_TAG}" # version to create a release for
|
||||
ARCHIVE_DIR="${2:-$PICO_PROJECT_DIR}" # directory to create release archives in
|
||||
|
||||
# print parameters
|
||||
echo "Creating new release..."
|
||||
printf 'VERSION="%s"\n' "$VERSION"
|
||||
echo
|
||||
|
||||
# guess version string
|
||||
if [ -z "$VERSION" ]; then
|
||||
PICO_VERSION="$(php -r "
|
||||
require_once('$PICO_PROJECT_DIR/lib/Pico.php');
|
||||
echo preg_replace('/-(?:dev|n|nightly)(?:[.-]?[0-9]+)?(?:[.-]dev)?$/', '', Pico::VERSION);
|
||||
")"
|
||||
|
||||
VERSION="v$PICO_VERSION-dev+${PROJECT_REPO_BRANCH:-master}"
|
||||
echo "Creating development release of Pico v$PICO_VERSION ($VERSION)..."
|
||||
echo
|
||||
fi
|
||||
|
||||
# parse version
|
||||
. "$PICO_TOOLS_DIR/functions/parse-version.sh.inc"
|
||||
|
||||
if ! parse_version "$VERSION"; then
|
||||
echo "Unable to create release archive: Invalid version '$VERSION'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DEPENDENCY_VERSION="$VERSION_FULL@$VERSION_STABILITY"
|
||||
if [ "$VERSION_STABILITY" == "dev" ] && [ -n "$VERSION_BUILD" ]; then
|
||||
DEPENDENCY_VERSION="dev-$VERSION_BUILD"
|
||||
fi
|
||||
|
||||
# clone repo
|
||||
github-clone.sh "$PICO_BUILD_DIR" "https://github.com/$RELEASE_REPO_SLUG.git" "$RELEASE_REPO_BRANCH"
|
||||
|
||||
cd "$PICO_BUILD_DIR"
|
||||
|
||||
# force Pico version
|
||||
echo "Updating composer dependencies..."
|
||||
composer require --no-update \
|
||||
"picocms/pico $DEPENDENCY_VERSION" \
|
||||
"picocms/pico-theme $DEPENDENCY_VERSION" \
|
||||
"picocms/pico-deprecated $DEPENDENCY_VERSION"
|
||||
echo
|
||||
|
||||
# force minimum stability <= beta due to Parsedown 1.8 currently being in beta
|
||||
if [ "$VERSION_STABILITY" == "stable" ] || [ "$VERSION_STABILITY" == "rc" ]; then
|
||||
VERSION_STABILITY="beta"
|
||||
fi
|
||||
|
||||
# set minimum stability
|
||||
if [ "$VERSION_STABILITY" != "stable" ]; then
|
||||
echo "Setting minimum stability to '$VERSION_STABILITY'..."
|
||||
composer config "minimum-stability" "$VERSION_STABILITY"
|
||||
composer config "prefer-stable" "true"
|
||||
echo
|
||||
fi
|
||||
|
||||
# install dependencies
|
||||
echo "Running \`composer install\`..."
|
||||
composer install --no-suggest --prefer-dist --no-dev --optimize-autoloader
|
||||
echo
|
||||
|
||||
# prepare release
|
||||
echo "Replacing 'index.php'..."
|
||||
cp vendor/picocms/pico/index.php.dist index.php
|
||||
|
||||
echo "Adding 'README.md', 'CONTRIBUTING.md', 'CHANGELOG.md'..."
|
||||
cp vendor/picocms/pico/README.md README.md
|
||||
cp vendor/picocms/pico/CONTRIBUTING.md CONTRIBUTING.md
|
||||
cp vendor/picocms/pico/CHANGELOG.md CHANGELOG.md
|
||||
|
||||
echo "Removing '.git' directories of plugins and themes..."
|
||||
find themes/ -type d -path 'themes/*/.git' -print0 | xargs -0 rm -rf
|
||||
find plugins/ -type d -path 'plugins/*/.git' -print0 | xargs -0 rm -rf
|
||||
|
||||
echo "Preparing 'composer.json' for release..."
|
||||
composer require --no-update \
|
||||
"picocms/pico ^$VERSION_MILESTONE" \
|
||||
"picocms/pico-theme ^$VERSION_MILESTONE" \
|
||||
"picocms/pico-deprecated ^$VERSION_MILESTONE"
|
||||
|
||||
# create release archives
|
||||
create-release.sh "$PICO_BUILD_DIR" "$ARCHIVE_DIR" "pico-release-v$VERSION_FULL"
|
12
.gitattributes
vendored
12
.gitattributes
vendored
|
@ -1,12 +0,0 @@
|
|||
/.build export-ignore
|
||||
/.github export-ignore
|
||||
/assets/.gitignore export-ignore
|
||||
/config/.gitignore export-ignore
|
||||
/content/.gitignore export-ignore
|
||||
/plugins/.gitignore export-ignore
|
||||
/themes/.gitignore export-ignore
|
||||
/.gitattributes export-ignore
|
||||
/.gitignore export-ignore
|
||||
/.phpcs.xml export-ignore
|
||||
/.phpdoc.xml export-ignore
|
||||
/.travis.yml export-ignore
|
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
|
@ -1 +0,0 @@
|
|||
custom: https://www.bountysource.com/teams/picocms
|
48
.github/PULL_REQUEST_TEMPLATE.md
vendored
48
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
@ -1,48 +0,0 @@
|
|||
<!--
|
||||
|
||||
Developer Certificate of Origin
|
||||
===============================
|
||||
|
||||
By contributing to Pico, you accept and agree to the following terms and conditions (the *Developer Certificate of Origin*) for your present and future contributions submitted to Pico. Please refer to the *Developer Certificate of Origin* section in Pico's [`CONTRIBUTING.md`](https://github.com/picocms/Pico/blob/master/CONTRIBUTING.md#developer-certificate-of-origin) for details.
|
||||
|
||||
```
|
||||
Developer Certificate of Origin
|
||||
Version 1.1
|
||||
|
||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
||||
1 Letterman Drive
|
||||
Suite D4700
|
||||
San Francisco, CA, 94129
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
|
||||
Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
```
|
||||
|
||||
-->
|
28
.github/workflows/stale.yml
vendored
28
.github/workflows/stale.yml
vendored
|
@ -1,28 +0,0 @@
|
|||
name: "Mark or close stale issues and PRs"
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 12 * * *"
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: 7
|
||||
days-before-close: 2
|
||||
stale-issue-message: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed in two days if no further activity
|
||||
occurs. Thank you for your contributions! :+1:
|
||||
stale-pr-message: >
|
||||
This pull request has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed in two days if no further activity
|
||||
occurs. Thank you for your contributions! :+1:
|
||||
stale-pr-label: "info: Stale"
|
||||
stale-issue-label: "info: Stale"
|
||||
exempt-issue-labels: "type: Bug,type: Enhancement,type: Feature,type: Idea,type: Release,info: Pinned"
|
||||
exempt-pr-labels: "type: Bug,type: Enhancement,type: Feature,type: Idea,type: Release,info: Pinned"
|
||||
remove-stale-when-updated: true
|
||||
|
30
.gitignore
vendored
30
.gitignore
vendored
|
@ -12,15 +12,27 @@ desktop.ini
|
|||
|
||||
# Composer
|
||||
/composer.lock
|
||||
/composer.phar
|
||||
/vendor
|
||||
|
||||
# Build system
|
||||
/.build/build
|
||||
/.build/deploy
|
||||
/.build/ci-tools
|
||||
/pico-release-*.tar.gz
|
||||
/pico-release-*.zip
|
||||
|
||||
# phpDocumentor
|
||||
/.build/phpdoc
|
||||
/.build/phpdoc.cache
|
||||
/_build/phpdoc/
|
||||
/_build/phpdoc.cache/
|
||||
/_build/phpdoc-*/
|
||||
|
||||
# User config
|
||||
/config/config.php
|
||||
|
||||
# User themes
|
||||
/themes/*
|
||||
!/themes/default
|
||||
!/themes/alpha
|
||||
|
||||
# User plugins
|
||||
/plugins/*
|
||||
!/plugins/0?-*
|
||||
!/plugins/1?-*
|
||||
!/plugins/DummyPlugin.php
|
||||
|
||||
# User content
|
||||
/content
|
||||
|
|
15
.htaccess
15
.htaccess
|
@ -1,23 +1,16 @@
|
|||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
# May be required to access sub directories
|
||||
#May be required to access sub-directories
|
||||
#RewriteBase /
|
||||
|
||||
# Deny access to internal dirs and files by passing the URL to Pico
|
||||
RewriteRule ^(config|content|content-sample|lib|vendor)(/|$) index.php [L]
|
||||
RewriteRule ^(CHANGELOG\.md|composer\.(json|lock|phar))(/|$) index.php [L]
|
||||
RewriteRule (^\.|/\.)(?!well-known(/|$)) index.php [L]
|
||||
|
||||
# Enable URL rewriting
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^ index.php [L]
|
||||
RewriteRule ^(.*)$ index.php?$1 [L,QSA]
|
||||
RewriteRule ^(config|content|content-sample|lib|vendor)/.* - [R=404,L]
|
||||
|
||||
<IfModule mod_env.c>
|
||||
# Let Pico know about available URL rewriting
|
||||
SetEnv PICO_URL_REWRITING 1
|
||||
</IfModule>
|
||||
</IfModule>
|
||||
|
||||
# Prevent file browsing
|
||||
Options -Indexes -MultiViews
|
||||
Options -Indexes
|
||||
|
|
16
.phpcs.xml
16
.phpcs.xml
|
@ -11,10 +11,9 @@
|
|||
<file>.</file>
|
||||
|
||||
<!--
|
||||
Exclude .build/, .github/ and vendor/ dirs as well as minified JavaScript files
|
||||
Exclude _build/ and vendor/ dirs as well as minified JavaScript files
|
||||
-->
|
||||
<exclude-pattern type="relative">^.build/</exclude-pattern>
|
||||
<exclude-pattern type="relative">^.github/</exclude-pattern>
|
||||
<exclude-pattern type="relative">^_build/</exclude-pattern>
|
||||
<exclude-pattern type="relative">^vendor/</exclude-pattern>
|
||||
<exclude-pattern>*.min.js</exclude-pattern>
|
||||
|
||||
|
@ -42,15 +41,4 @@
|
|||
<rule ref="PSR2">
|
||||
<exclude name="PSR1.Classes.ClassDeclaration.MissingNamespace"/>
|
||||
</rule>
|
||||
|
||||
<!--
|
||||
The PHP-FIG PSR-2 Coding Style doesn't fully apply to JavaScript files
|
||||
Furthermore, some sniffs aren't able to handle JavaScript peculiarities
|
||||
-->
|
||||
<rule ref="Generic.ControlStructures.InlineControlStructure">
|
||||
<exclude-pattern>*.js</exclude-pattern>
|
||||
</rule>
|
||||
<rule ref="Squiz.Functions.MultiLineFunctionDeclaration">
|
||||
<exclude-pattern>*.js</exclude-pattern>
|
||||
</rule>
|
||||
</ruleset>
|
||||
|
|
17
.phpdoc.xml
17
.phpdoc.xml
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<phpdocumentor>
|
||||
<title><![CDATA[Pico API Documentation]]></title>
|
||||
<phpdoc>
|
||||
<title><![CDATA[Pico 1.0 API Documentation]]></title>
|
||||
<parser>
|
||||
<target>.build/phpdoc.cache</target>
|
||||
<target>_build/phpdoc.cache</target>
|
||||
</parser>
|
||||
<transformer>
|
||||
<target>.build/phpdoc</target>
|
||||
<target>_build/phpdoc</target>
|
||||
</transformer>
|
||||
<transformations>
|
||||
<template name="clean"/>
|
||||
|
@ -15,13 +15,12 @@
|
|||
<file>index.php</file>
|
||||
<file>index.php.dist</file>
|
||||
|
||||
<!-- exclude .build and .github directories -->
|
||||
<ignore>.build/*</ignore>
|
||||
<ignore>.github/*</ignore>
|
||||
<!-- exclude build environment -->
|
||||
<ignore>_build/*</ignore>
|
||||
|
||||
<!-- exclude user config -->
|
||||
<ignore>config/*</ignore>
|
||||
<file>config/config.yml.template</file>
|
||||
<file>config/config.php.template</file>
|
||||
|
||||
<!-- exclude all plugins -->
|
||||
<ignore>plugins/*</ignore>
|
||||
|
@ -30,4 +29,4 @@
|
|||
<!-- exclude vendor dir -->
|
||||
<ignore>vendor/*</ignore>
|
||||
</files>
|
||||
</phpdocumentor>
|
||||
</phpdoc>
|
||||
|
|
110
.travis.yml
110
.travis.yml
|
@ -1,82 +1,44 @@
|
|||
dist: bionic
|
||||
sudo: false
|
||||
|
||||
language: php
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7
|
||||
- hhvm
|
||||
- nightly
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache/files
|
||||
|
||||
jobs:
|
||||
include:
|
||||
# Test stage
|
||||
- php: 5.3
|
||||
dist: precise
|
||||
- php: 5.4
|
||||
dist: trusty
|
||||
- php: 5.5
|
||||
dist: trusty
|
||||
- php: 5.6
|
||||
dist: xenial
|
||||
- php: 7.0
|
||||
dist: xenial
|
||||
- php: 7.1
|
||||
- php: 7.2
|
||||
- php: 7.3
|
||||
- php: 7.4
|
||||
- php: nightly
|
||||
- php: hhvm-3.24 # until Dec 2018
|
||||
- php: hhvm-3.27 # until Sep 2019
|
||||
- php: hhvm-3.30 # until Nov 2019
|
||||
|
||||
# Branch deployment stage
|
||||
- stage: deploy-branch
|
||||
if: type == "push" && tag IS blank
|
||||
php: 5.3
|
||||
dist: precise
|
||||
install:
|
||||
- '[[ ",$DEPLOY_PHPDOC_BRANCHES," == *,"$TRAVIS_BRANCH",* ]] || travis_terminate 0'
|
||||
- install.sh --deploy
|
||||
script:
|
||||
- deploy-branch.sh
|
||||
|
||||
# Release deployment stage
|
||||
- stage: deploy-release
|
||||
if: tag IS present
|
||||
php: 5.3
|
||||
dist: precise
|
||||
install:
|
||||
- install.sh --deploy
|
||||
script:
|
||||
- '[ "$PROJECT_REPO_TAG" == "v$(php -r "require_once(\"lib/Pico.php\"); echo Pico::VERSION;")" ]'
|
||||
- deploy-release.sh
|
||||
before_deploy:
|
||||
- release.sh "$PROJECT_REPO_TAG"
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key: ${GITHUB_OAUTH_TOKEN}
|
||||
file:
|
||||
- pico-release-$PROJECT_REPO_TAG.tar.gz
|
||||
- pico-release-$PROJECT_REPO_TAG.zip
|
||||
skip_cleanup: true
|
||||
name: Version ${PROJECT_REPO_TAG:1}
|
||||
draft: true
|
||||
on:
|
||||
tags: true
|
||||
|
||||
# Ignore nightly build failures
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: nightly
|
||||
fast_finish: true
|
||||
|
||||
before_install:
|
||||
- export PICO_TOOLS_DIR="$HOME/__picocms_tools"
|
||||
- git clone --branch="$TOOLS_REPO_BRANCH" "https://github.com/$TOOLS_REPO_SLUG.git" "$PICO_TOOLS_DIR"
|
||||
- . "$PICO_TOOLS_DIR/init/travis.sh.inc"
|
||||
- . "$PICO_PROJECT_DIR/.build/init.sh.inc"
|
||||
fast-finish: true
|
||||
|
||||
install:
|
||||
- install.sh
|
||||
- composer install
|
||||
|
||||
before_script:
|
||||
- export PATH="$TRAVIS_BUILD_DIR/_build:$TRAVIS_BUILD_DIR/vendor/bin:$PATH"
|
||||
|
||||
script:
|
||||
- phpcs --standard=.phpcs.xml "$PICO_PROJECT_DIR"
|
||||
- phpcs --standard=.phpcs.xml "$TRAVIS_BUILD_DIR"
|
||||
|
||||
after_success:
|
||||
- deploy-phpdoc-branch.sh
|
||||
|
||||
before_deploy:
|
||||
- deploy-phpdoc-release.sh
|
||||
- composer install --no-dev --optimize-autoloader
|
||||
- find vendor/ -type d -path 'vendor/*/*/.git' -print0 | xargs -0 rm -rf
|
||||
- mv index.php.dist index.php
|
||||
- tar -czf "pico-release-$TRAVIS_TAG.tar.gz" README.md LICENSE.md CONTRIBUTING.md CHANGELOG.md composer.json composer.lock config content-sample lib plugins themes vendor .htaccess index.php
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key: ${GITHUB_OAUTH_TOKEN}
|
||||
file: pico-release-$TRAVIS_TAG.tar.gz
|
||||
skip_cleanup: true
|
||||
on:
|
||||
tags: true
|
||||
php: 5.3
|
||||
|
||||
sudo: false
|
||||
|
|
427
CHANGELOG.md
427
CHANGELOG.md
|
@ -1,427 +1,26 @@
|
|||
Pico Changelog
|
||||
==============
|
||||
|
||||
**Note:** This changelog only provides technical information about the changes
|
||||
introduced with a particular Pico version, and is meant to supplement
|
||||
the actual code changes. The information in this changelog are often
|
||||
insufficient to understand the implications of larger changes. Please
|
||||
refer to both the UPGRADE and NEWS sections of the docs for more
|
||||
details.
|
||||
|
||||
**Note:** Changes breaking backwards compatibility (BC) are marked with an `!`
|
||||
(exclamation mark). This doesn't include changes for which BC is
|
||||
preserved by Pico's official `PicoDeprecated` plugin. If a previously
|
||||
deprecated feature is later removed in `PicoDeprecated`, this change
|
||||
is going to be marked as BC-breaking change in both Pico's and
|
||||
`PicoDeprecated`'s changelog. Please note that BC-breaking changes
|
||||
are only possible with a new major version.
|
||||
|
||||
### Version 2.1.4
|
||||
Released: 2020-08-29
|
||||
|
||||
```
|
||||
* [Changed] Silence PHP errors in Parsedown
|
||||
* [Fixed] #560: Improve charset guessing for formatted date strings using
|
||||
`strftime()` (Pico always uses UTF-8, but `strftime()` might not)
|
||||
```
|
||||
|
||||
### Version 2.1.3
|
||||
Released: 2020-07-10
|
||||
|
||||
```
|
||||
* [New] Add `locale` option to `config/config.yml`
|
||||
* [Changed] Improve Pico docs
|
||||
```
|
||||
|
||||
### Version 2.1.2
|
||||
Released: 2020-04-10
|
||||
|
||||
```
|
||||
* [Fixed] Fix DummyPlugin declaring API version 3
|
||||
```
|
||||
|
||||
### Version 2.1.1
|
||||
Released: 2019-12-31
|
||||
|
||||
```
|
||||
* [Fixed] Require Parsedown 1.8.0-beta-7 and Parsedown Extra 0.8.0-beta-1 due
|
||||
to changes in Parsedown and Parsedown Extra breaking BC beyond repair
|
||||
* [Changed] #523: Check for hidden pages based on page ID instead of full paths
|
||||
* [Changed] Improve Pico docs
|
||||
```
|
||||
|
||||
### Version 2.1.0
|
||||
Released: 2019-11-24
|
||||
|
||||
```
|
||||
* [Changed] Add Pico's official logo and tagline to `content-sample/_meta.md`
|
||||
* [Changed] Improve `content-sample/theme.md` to show Pico's official logo and
|
||||
the usage of the new image utility classes of Pico's default theme
|
||||
* [Changed] Improve Pico docs and PHPDoc class docs
|
||||
```
|
||||
|
||||
### Version 2.1.0-beta.1
|
||||
Released: 2019-11-03
|
||||
|
||||
```
|
||||
* [New] Introduce API version 3
|
||||
* [New] Add `assets_dir`, `assets_url` and `plugins_url` config params
|
||||
* [New] Add `%config.*%` Markdown placeholders for scalar config params and the
|
||||
`%assets_url%`, `%themes_url%` and `%plugins_url%` placeholders
|
||||
* [New] Add `content-sample/theme.md` for theme testing purposes
|
||||
* [New] Introduce API versioning for themes and support theme-specific configs
|
||||
using the new `pico-theme.yml` in a theme's directory; `pico-theme.yml`
|
||||
allows a theme to influence Pico's Twig config, to register known meta
|
||||
headers and to provide defaults for theme config params
|
||||
* [New] Add `assets_url`, `themes_url` and `plugins_url` Twig variables
|
||||
* [New] Add `pages` Twig function to deal with Pico's page tree; this function
|
||||
replaces the raw usage of Pico's `pages` array in themes
|
||||
* [New] Add `url` Twig filter to replace URL placeholders (e.g. `%base_url%`)
|
||||
in strings using the new `Pico::substituteUrl()` method
|
||||
* [New] Add `onThemeLoading` and `onThemeLoaded` events
|
||||
* [New] Add `debug` config param and the `Pico::isDebugModeEnabled()` method,
|
||||
checking the `PICO_DEBUG` environment variable, to enable debugging
|
||||
* [New] Add new `Pico::getNormalizedPath()` method to normalize a path; this
|
||||
method should be used to prevent content dir breakouts when dealing
|
||||
with paths provided by user input
|
||||
* [New] Add new `Pico::getUrlFromPath()` method to guess a URL from a file path
|
||||
* [New] Add new `Pico::getAbsoluteUrl()` method to make a relative URL absolute
|
||||
* [New] #505: Create pre-built `.zip` release archives
|
||||
* [Fixed] #461: Proberly handle content files with a UTF-8 BOM
|
||||
* [Changed] Rename `theme_url` config param to `themes_url`; the `theme_url`
|
||||
Twig variable and Markdown placeholder are kept unchanged
|
||||
* [Changed] Update to Parsedown Extra 0.8 and Parsedown 1.8 (both still beta)
|
||||
* [Changed] Enable Twig's `autoescape` feature by default; outputting a
|
||||
variable now causes Twig to escape HTML markup; Pico's `content`
|
||||
variable is a notable exception, as it is marked as being HTML safe
|
||||
* [Changed] Rename `prev_page` Twig variable to `previous_page`
|
||||
* [Changed] Mark `markdown` and `content` Twig filters as well as the `content`
|
||||
variable as being HTML safe
|
||||
* [Changed] Add `$singleLine` param to `markdown` Twig filter as well as the
|
||||
`Pico::parseFileContent()` method to parse just a single line of
|
||||
Markdown input
|
||||
* [Changed] Add `AbstractPicoPlugin::configEnabled()` method to check whether
|
||||
a plugin should be enabled or disabled based on Pico's config
|
||||
* [Changed] Deprecate the use of `AbstractPicoPlugin::__call()`, use
|
||||
`PicoPluginInterface::getPico()` instead
|
||||
* [Changed] Update to Twig 1.36 as last version supporting PHP 5.3, use a
|
||||
Composer-based installation to use a newer Twig version
|
||||
* [Changed] Add `$basePath` and `$endSlash` params to `Pico::getAbsolutePath()`
|
||||
* [Changed] Deprecate `Pico::getBaseThemeUrl()`
|
||||
* [Changed] Replace various `file_exists` calls with proper `is_file` calls
|
||||
* [Changed] Refactor release & build system
|
||||
* [Changed] Improve Pico docs and PHPDoc class docs
|
||||
* [Changed] Various small improvements
|
||||
* [Removed] Remove superfluous `base_dir` and `theme_dir` Twig variables
|
||||
* [Removed] Remove `PicoPluginInterface::__construct()`
|
||||
```
|
||||
|
||||
### Version 2.0.5-beta.1
|
||||
Released: 2019-01-03
|
||||
|
||||
```
|
||||
* [New] Add PHP 7.3 tests
|
||||
* [New] Add `2.0.x-dev` alias for master branch to `composer.json`
|
||||
* [Changed] Update to Parsedown Extra 0.8 and Parsedown 1.8 (both still beta)
|
||||
* [Changed] Improve release & build process
|
||||
```
|
||||
|
||||
### Version 2.0.4
|
||||
Released: 2018-12-17
|
||||
|
||||
```
|
||||
* [Fixed] Proberly handle hostnames with ports in `Pico::getBaseUrl()`
|
||||
* [Changed] Improve documentation
|
||||
```
|
||||
|
||||
### Version 2.0.3
|
||||
Released: 2018-12-03
|
||||
|
||||
```
|
||||
* [Fixed] Support alternative server ports in `Pico::getBaseUrl()`
|
||||
* [Changed] Don't require server environment variables to be configured
|
||||
* [Changed] Improve release & build process
|
||||
* [Changed] Improve documentation
|
||||
* [Changed] Improve PHP class docs
|
||||
* [Changed] Various small improvements
|
||||
```
|
||||
|
||||
### Version 2.0.2
|
||||
Released: 2018-08-12
|
||||
|
||||
```
|
||||
* [Fixed] Support Windows paths (`\` instead of `/`) in `Pico::evaluateRequestUrl()`
|
||||
```
|
||||
|
||||
### Version 2.0.1
|
||||
Released: 2018-07-29
|
||||
|
||||
```
|
||||
* [Changed] Improve documentation
|
||||
* [Changed] Add missing "Formatted Date", "Time" and "Hidden" meta headers; use
|
||||
the "Hidden" meta header to manually hide a page in the pages list
|
||||
```
|
||||
|
||||
### Version 2.0.0
|
||||
Released: 2018-07-01
|
||||
|
||||
```
|
||||
* [New] Add Bountysource
|
||||
* [Changed] Improve documentation
|
||||
* [Changed] Improve release & build process
|
||||
* [Changed] Add `Pico::setConfig()` example to `index.php.dist`
|
||||
* [Fixed] Don't load `config/config.yml` multiple times
|
||||
```
|
||||
|
||||
### Version 2.0.0-beta.3
|
||||
Released: 2018-04-07
|
||||
|
||||
```
|
||||
* [Changed] Add `README.md`, `CONTRIBUTING.md` and `CHANGELOG.md` of main repo
|
||||
to pre-bundled releases, keep `.gitignore`
|
||||
* [Changed] Deny access to a possibly existing `composer.phar` in `.htaccess`
|
||||
* [Changed] Disallow the use of the `callback` filter for the `url_param` and
|
||||
`form_param` Twig functions
|
||||
* [Changed] Improve documentation
|
||||
* [Fixed] Fix page tree when sorting pages by arbitrary values
|
||||
* [Fixed] Fix sorting of `Pico::$nativePlugins`
|
||||
```
|
||||
|
||||
### Version 2.0.0-beta.2
|
||||
Released: 2018-01-21
|
||||
|
||||
```
|
||||
* [New] Improve release & build process and move most build tools to the new
|
||||
`picocms/ci-tools` repo, allowing them to be used by other projects
|
||||
* [New] Add page tree; refer to the `Pico::buildPageTree()` method for more
|
||||
details; also see the `onPageTreeBuilt` event
|
||||
* [Changed] Update dependencies: Twig 1.35
|
||||
* [Changed] ! Improve `.htaccess` and deny access to all dot files by default
|
||||
* [Changed] ! Throw a `RuntimeException` when non-native plugins are loaded,
|
||||
but Pico's `PicoDeprecated` plugin is not loaded
|
||||
* [Changed] ! Change `AbstractPicoPlugin::$enabled`'s behavior: setting it to
|
||||
TRUE now leads to throwing a `RuntimeException` when the plugin's
|
||||
dependencies aren't fulfilled; use NULL to maintain old behavior
|
||||
* [Changed] ! Force themes to use `.twig` as file extension for Twig templates
|
||||
* [Changed] Improve PHP class docs
|
||||
* [Changed] Various small improvements
|
||||
```
|
||||
|
||||
### Version 2.0.0-beta.1
|
||||
Released: 2017-11-05
|
||||
|
||||
```
|
||||
* [New] Pico is on its way to its second major release!
|
||||
* [New] Improve Pico's release & build process
|
||||
* [New] Add "Developer Certificate of Origin" to `CONTRIBUTING.md`
|
||||
* [New] Add license & copyright header to all relevant files
|
||||
* [New] Add Pico version constants (`Pico::VERSION` and `Pico::VERSION_ID`),
|
||||
and add a `version` Twig variable and `%version%` Markdown placeholder
|
||||
* [New] Add Pico API versioning for plugins (see `Pico::API_VERSION` constant);
|
||||
Pico now triggers events on plugins using the latest API version only
|
||||
("native" plugins), `PicoDeprecated` takes care of all other plugins;
|
||||
as a result, old plugin's always depend on `PicoDeprecated` now
|
||||
* [New] Add a theme and plugin installer for composer; Pico now additionally
|
||||
uses the new `vendor/pico-plugin.php` file to discover plugins
|
||||
installed by composer and loads them using composer's autoloader;
|
||||
see the `picocms/composer-installer` repo for more details; Pico
|
||||
loads plugins installed by composer first and ignores conflicting
|
||||
plugins in Pico's `plugins/` dir
|
||||
* [New] Add `$enableLocalPlugins` parameter to `Pico::__construct()` to allow
|
||||
website developers to disable local plugin discovery by scanning the
|
||||
`plugins/` dir (i.e. load plugins from `vendor/pico-plugin.php` only)
|
||||
* [New] Add public `AbstractPicoPlugin::getPluginConfig()` method
|
||||
* [New] Add public `Pico::loadPlugin()` method and the corresponding
|
||||
`onPluginManuallyLoaded` event
|
||||
* [New] Add public `Pico::resolveFilePath()` method (replaces the protected
|
||||
`Pico::discoverRequestFile()` method)
|
||||
* [New] Add public `Pico::is404Content()` method
|
||||
* [New] Add public `Pico::getYamlParser()` method and the corresponding
|
||||
`onYamlParserRegistered` event
|
||||
* [New] Add public `Pico::substituteFileContent()` method
|
||||
* [New] Add public `Pico::getPageId()` method
|
||||
* [New] Add public `Pico::getFilesGlob()` method
|
||||
* [New] Add public `Pico::getVendorDir()` method, returning Pico's installation
|
||||
directory (i.e. `/var/www/pico/vendor/picocms/pico`); don't confuse
|
||||
this with composer's `vendor/` dir!
|
||||
* [New] Add `$default` parameter to `Pico::getConfig()` method
|
||||
* [New] Add empty `assets/` and `content/` dirs
|
||||
* [New] #305: Add `url_param` and `form_param` Twig functions, and the public
|
||||
`Pico::getUrlParameter()` and `Pico::getFormParameter()` methods,
|
||||
allowing theme developers to access URL GET and HTTP POST parameters
|
||||
* [New] Add `$meta` parameter to `markdown` Twig filter
|
||||
* [New] Add `remove` fallback to `sort_by` Twig filter
|
||||
* [New] Add `theme_url` config parameter
|
||||
* [New] Add public `Pico::getBaseThemeUrl()` method
|
||||
* [New] Add `REQUEST_URI` routing method, allowing one to simply rewrite all
|
||||
requests to `index.php` (e.g. use `FallbackResource` or `mod_rewrite`
|
||||
in your `.htaccess` for Apache, or use `try_files` for nginx)
|
||||
* [New] #299: Add built-in 404 page as fallback when no `404.md` is found
|
||||
* [New] Allow sorting pages by arbitrary meta values
|
||||
* [New] Add `onSinglePageLoading` event, allowing one to skip a page
|
||||
* [New] Add `onSinglePageContent` event
|
||||
* [New] Add some config parameters to change Parsedown's behavior
|
||||
* [Changed] ! Disallow running the same Pico instance multiple times by
|
||||
throwing a `RuntimeException` when calling `Pico::run()`
|
||||
* [Changed] ! #203: Load plugins from `plugins/<plugin name>/<plugin name>.php`
|
||||
and `plugins/<plugin name>.php` only (directory and file name must
|
||||
match case-sensitive), and throw a `RuntimeException` when Pico is
|
||||
unable to load a plugin; also throw a `RuntimeException` when
|
||||
superfluous files or directories in `plugins/` are found; use a
|
||||
scope-isolated `require()` to include plugin files
|
||||
* [Changed] ! Use a plugin dependency topology to sort `Pico::$plugins`,
|
||||
changing the execution order of plugins so that plugins, on which
|
||||
other plugins depend, are always executed before their dependants
|
||||
* [Changed] ! Don't pass `$plugins` parameter to `onPluginsLoaded` event by
|
||||
reference anymore; use `Pico::loadPlugin()` instead
|
||||
* [Changed] ! Leave `Pico::$pages` unsorted when a unknown sort method was
|
||||
configured; this usually means that a plugin wants to sort it
|
||||
* [Changed] Overhaul page discovery events: add `onPagesDiscovered` event which
|
||||
is triggered right before `Pico::$pages` is sorted and move the
|
||||
`$currentPage`, `$previousPage` and `$nextPage` parameters of the
|
||||
`onPagesLoaded` event to the new `onCurrentPageDiscovered` event
|
||||
* [Changed] Move the `$twig` parameter of the `onPageRendering` event to the
|
||||
`onTwigRegistered` event, replacing the `onTwigRegistration` event
|
||||
* [Changed] Unify the `onParsedownRegistration` event by renaming it to
|
||||
`onParsedownRegistered` and add the `$parsedown` parameter
|
||||
* [Changed] #330: Replace `config/config.php` by a modular YAML-based approach;
|
||||
you can now use a arbitrary number of `config/*.yml` files to
|
||||
configure Pico
|
||||
* [Changed] ! When trying to auto-detect Pico's `content` dir, Pico no longer
|
||||
searches just for a (possibly empty) directory, but rather checks
|
||||
whether a `index.md` exists in this directory
|
||||
* [Changed] ! Use the relative path between `index.php` and `Pico::$themesDir`
|
||||
for Pico's theme URL (also refer to the new `theme_url` config and
|
||||
the public `Pico::getBaseThemeUrl()` method for more details)
|
||||
* [Changed] #347: Drop the superfluous trailing "/index" from Pico's URLs
|
||||
* [Changed] Flip registered meta headers array, so that the array key is used
|
||||
to search for a meta value and the array value is used to store the
|
||||
found meta value (previously it was the other way round)
|
||||
* [Changed] ! Add lazy loading for `Pico::$yamlParser`, `Pico::$parsedown` and
|
||||
`Pico::$twig`; the corresponding events are no longer part of
|
||||
Pico's event flow and are triggered on demand
|
||||
* [Changed] ! Trigger the `onMetaHeaders` event just once; the event is no
|
||||
longer part of Pico's event flow and is triggered on demand
|
||||
* [Changed] Don't lower meta headers on the first level of a page's meta data
|
||||
(i.e. `SomeKey: value` is accessible using `$meta['SomeKey']`)
|
||||
* [Changed] Don't compare registered meta headers case-insensitive, require
|
||||
matching case
|
||||
* [Changed] Allow users to explicitly set values for the `date_formatted` and
|
||||
`time` meta headers in a page's YAML front matter
|
||||
* [Changed] Add page siblings for all pages
|
||||
* [Changed] ! Treat pages or directories that are prefixed by `_` as hidden;
|
||||
when requesting a hidden page, Pico responds with a 404 page;
|
||||
hidden pages are still in `Pico::$pages`, but are moved to the end
|
||||
of the pages array when sorted alphabetically or by date
|
||||
* [Changed] ! Don't treat explicit requests to a 404 page as successful request
|
||||
* [Changed] Change method visibility of `Pico::getFiles()` to public
|
||||
* [Changed] Change method visibility of `Pico::triggerEvent()` to public;
|
||||
at first glance this method triggers events on native plugins only,
|
||||
however, `PicoDeprecated` takes care of triggering events for other
|
||||
plugins, thus you can use this method to trigger (custom) events on
|
||||
all plugins; never use it to trigger Pico core events!
|
||||
* [Changed] Move Pico's default theme to the new `picocms/pico-theme` repo; the
|
||||
theme was completely rewritten from scratch and is a much better
|
||||
starting point for creating your own theme; refer to the theme's
|
||||
`CHANGELOG.md` for more details
|
||||
* [Changed] Move `PicoDeprecated` plugin to the new `picocms/pico-deprecated`
|
||||
repo; refer to the plugin's `CHANGELOG.md` for more details
|
||||
* [Changed] Update dependencies: Twig 1.34, Symfony YAML 2.8, Parsedown 1.6
|
||||
* [Changed] Improve Pico docs and PHP class docs
|
||||
* [Changed] A vast number of small improvements and changes...
|
||||
* [Removed] ! Remove `PicoParsePagesContent` plugin
|
||||
* [Removed] ! Remove `PicoExcerpt` plugin
|
||||
* [Removed] Remove `rewrite_url` and `is_front_page` Twig variables
|
||||
* [Removed] Remove superfluous parameters of various events to reduce Pico's
|
||||
error-proneness (plugins hopefully interfere with each other less)
|
||||
```
|
||||
|
||||
### Version 1.0.6
|
||||
Released: 2017-07-25
|
||||
|
||||
```
|
||||
* [Changed] Improve documentation
|
||||
* [Changed] Improve handling of Pico's Twig config (`$config['twig_config']`)
|
||||
* [Changed] Improve PHP platform requirement checks
|
||||
```
|
||||
|
||||
### Version 1.0.5
|
||||
Released: 2017-05-02
|
||||
|
||||
```
|
||||
* [Changed] Improve documentation
|
||||
* [Fixed] Improve hostname detection with proxies
|
||||
* [Fixed] Fix detection of Windows-based server environments
|
||||
* [Removed] Remove Twitter links
|
||||
```
|
||||
|
||||
### Version 1.0.4
|
||||
Released: 2016-10-04
|
||||
|
||||
```
|
||||
* [New] Add Pico's social icons to default theme
|
||||
* [Changed] Improve documentation
|
||||
* [Changed] Add CSS flexbox rules to default theme
|
||||
* [Fixed] Fix handling of non-YAML 1-line front matters
|
||||
* [Fixed] Fix responsiveness in default theme
|
||||
```
|
||||
|
||||
### Version 1.0.3
|
||||
Released: 2016-05-11
|
||||
|
||||
```
|
||||
* [Changed] Improve documentation
|
||||
* [Changed] Heavily extend nginx configuration docs
|
||||
* [Changed] Add CSS rules for definition lists to default theme
|
||||
* [Changed] Always use `on404Content...` execution path when serving a `404.md`
|
||||
* [Changed] Deny access to `.git` directory, `CHANGELOG.md`, `composer.json`
|
||||
and `composer.lock` (`.htaccess` file)
|
||||
* [Changed] Use Pico's `404.md` to deny access to `.git`, `config`, `content`,
|
||||
* `content-sample`, `lib` and `vendor` dirs (`.htaccess` file)
|
||||
* [Fixed] #342: Fix responsiveness in default theme
|
||||
* [Fixed] #344: Improve HTTPS detection with proxies
|
||||
* [Fixed] #346: Force HTTPS to load Google Fonts in default theme
|
||||
```
|
||||
|
||||
### Version 1.0.2
|
||||
Released: 2016-03-16
|
||||
|
||||
```
|
||||
* [Changed] Various small improvements and changes...
|
||||
* [Fixed] Check dependencies when a plugin is enabled by default
|
||||
* [Fixed] Allow `Pico::$requestFile` to point to somewhere outside `content_dir`
|
||||
* [Fixed] #336: Fix `Date` meta header parsing with ISO-8601 datetime strings
|
||||
```
|
||||
|
||||
### Version 1.0.1
|
||||
Released: 2016-02-27
|
||||
|
||||
```
|
||||
* [Changed] Improve documentation
|
||||
* [Changed] Replace `version_compare()` with `PHP_VERSION_ID` in
|
||||
`index.php.dist` (available since PHP 5.2.7)
|
||||
* [Fixed] Suppress PHP warning when using `date_default_timezone_get()`
|
||||
* [Fixed] #329: Force Apache's `MultiViews` feature to be disabled
|
||||
```
|
||||
|
||||
### Version 1.0.0
|
||||
Released: 2015-12-24
|
||||
Released: -
|
||||
|
||||
```
|
||||
* [New] On Christmas Eve, we are happy to announce Pico's first stable release!
|
||||
The Pico Community wants to thank all contributors and users who made
|
||||
this possible. Merry Christmas and a Happy New Year 2016!
|
||||
* [New] This is Picos first stable release! The Pico Community wants to thank
|
||||
all contributors and users which made this possible!
|
||||
* [New] Adding `$queryData` parameter to `Pico::getPageUrl()` method
|
||||
* [Changed] Improve documentation
|
||||
* [New] Default Theme: Use Twitter Bootstrap `4.0.0-alpha` + Font Awesome `4.5.0` via MaxCDN
|
||||
* [New] Default Theme: `Blog Example` included!
|
||||
* [New] Default Theme: `blog`, `blog-post` and `blog-post-full` layouts
|
||||
* [New] Default Theme: `blog/` directory in `content-sample` with new demo posts
|
||||
* [New] Default Theme: add `theme_config` to `config/config.php.template`
|
||||
* [New] Default Theme: use new `sort_by` twig filters
|
||||
* [Changed] Moving `LICENSE` to `LICENSE.md`
|
||||
* [Changed] Throw `LogicException` instead of `RuntimeException` when calling
|
||||
`Pico::setConfig()` after processing has started
|
||||
* [Changed] Default theme now highlights the current page and shows pages with
|
||||
a title in the navigation only
|
||||
* [Changed] Default theme now highlights the current page and only lists pages
|
||||
with a title in the navigation
|
||||
* [Changed] #292: Ignore YAML parse errors (meta data) in `Pico::readPages()`
|
||||
* [Changed] Various small improvements and changes...
|
||||
* [Fixed] Support empty meta header
|
||||
* [Fixed] #307: Fix path handling on Windows
|
||||
```
|
||||
|
||||
### Version 1.0.0-beta.2
|
||||
|
@ -459,6 +58,10 @@ Released: 2015-11-30
|
|||
### Version 1.0.0-beta.1
|
||||
Released: 2015-11-06
|
||||
|
||||
**Note:** This changelog only provides basic information about the enormous
|
||||
changes introduced with Pico 1.0.0-beta.1. Please refer to the
|
||||
UGPRADE section of the docs for details.
|
||||
|
||||
```
|
||||
* [Security] (9e2604a) Prevent content_dir breakouts using malicious URLs
|
||||
* [New] Pico is on its way to its first stable release!
|
||||
|
|
128
CONTRIBUTING.md
128
CONTRIBUTING.md
|
@ -3,9 +3,9 @@ Contributing to Pico
|
|||
|
||||
Pico aims to be a high quality Content Management System (CMS) but at the same time wants to give contributors freedom when submitting fixes or improvements.
|
||||
|
||||
By contributing to Pico, you accept and agree to the *Developer Certificate of Origin* for your present and future contributions submitted to Pico. Please refer to the *Developer Certificate of Origin* section below.
|
||||
As such we want to *encourage* but not obligate you, the contributor, to follow these guidelines. The only exception to this are the guidelines elucidated in the *Prevent `merge-hell`* section.
|
||||
|
||||
Aside from this, we want to *encourage*, but not obligate you, the contributor, to follow the following guidelines. The only exception to this are the guidelines elucidated in the *Prevent `merge-hell`* section. Having said that: we really appreciate it when you apply the guidelines in part or wholly as that will save us time which, in turn, we can spend on bugfixes and new features.
|
||||
Having said that: we really appreciate it when you apply the guidelines in part or wholly as that will save us time which, in turn, we can spend on bugfixes and new features.
|
||||
|
||||
Issues
|
||||
------
|
||||
|
@ -14,86 +14,13 @@ If you want to report an *issue* with Pico's core, please create a new [Issue](h
|
|||
|
||||
Before creating a [new Issue on GitHub](https://github.com/picocms/Pico/issues/new), please make sure the problem wasn't reported yet using [GitHubs search engine](https://github.com/picocms/Pico/search?type=Issues).
|
||||
|
||||
Please describe your issue as clear as possible and always include the *Pico version* you're using. Provided that you're using *plugins*, include a list of them too. We need information about the *actual and expected behavior*, the *steps to reproduce* the problem, and what steps you have taken to resolve the problem by yourself (i.e. *your own troubleshooting*).
|
||||
Please describe your issue as clear as possible and always include the *Pico version* you're using. Provided that you're using *plugins*, include a list of them too. We need information about the *actual and expected behavior*, the *steps to reproduce* the problem, and what steps have you taken to resolve the problem by yourself (i.e. *your own troubleshooting*)?
|
||||
|
||||
Contributing
|
||||
------------
|
||||
Contributing code
|
||||
-----------------
|
||||
|
||||
Once you decide you want to contribute to *Pico's core* (which we really appreciate!) you can fork the project from https://github.com/picocms/Pico. If you're interested in developing a *plugin* or *theme* for Pico, please refer to the [development section](http://picocms.org/development/) of our website.
|
||||
|
||||
### Developer Certificate of Origin
|
||||
|
||||
By contributing to Pico, you accept and agree to the following terms and conditions for your present and future contributions submitted to Pico. Except for the license granted herein to Pico and recipients of software distributed by Pico, you reserve all right, title, and interest in and to your contributions. All contributions are subject to the following DCO + license terms.
|
||||
|
||||
```
|
||||
Developer Certificate of Origin
|
||||
Version 1.1
|
||||
|
||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
||||
1 Letterman Drive
|
||||
Suite D4700
|
||||
San Francisco, CA, 94129
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
|
||||
Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
```
|
||||
|
||||
All contributions to this project are licensed under the following MIT License:
|
||||
|
||||
```
|
||||
Copyright (c) <YEAR> <COPYRIGHT HOLDER>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
```
|
||||
|
||||
Please note that developing a *plugin* or *theme* for Pico is *not* assumed to be a contribution to Pico itself. By developing a plugin or theme you rather create a 3rd-party project that just uses Pico. Following the spirit of open source, we want to *encourage* you to release your plugin or theme under the terms of a [OSI-approved open source license](https://opensource.org/licenses). After all, Pico is open source, too!
|
||||
|
||||
### Prevent `merge-hell`
|
||||
|
||||
Please do *not* develop your contribution on the `master` branch of your fork, but create a separate feature branch, that is based off the `master` branch, for each feature that you want to contribute.
|
||||
|
@ -122,7 +49,7 @@ With this command you can specify a file or folder to limit which files it will
|
|||
|
||||
Pico accepts the problems of having redundant documentation on different places (concretely Pico's inline user docs, the `README.md` and the website) for the sake of a better user experience. When updating the docs, please make sure to keep them in sync.
|
||||
|
||||
If you update the [`README.md`](https://github.com/picocms/Pico/blob/master/README.md) or [`content-sample/index.md`](https://github.com/picocms/Pico/blob/master/content-sample/index.md), please make sure to update the corresponding files in the [`_docs`](https://github.com/picocms/picocms.github.io/tree/master/_docs/) folder of the `picocms.github.io` repo (i.e. [Pico's website](http://picocms.org/docs/)) and vice versa. Unfortunately this involves three (!) different markdown parsers. If you're experiencing problems, use Pico's [`erusev/parsedown-extra`](https://github.com/erusev/parsedown-extra) as a reference. You can try to make the contents compatible to [Kramdown](http://kramdown.gettalong.org/) (Pico's website) and [CommonMarker](https://github.com/gjtorikian/commonmarker) (`README.md`) by yourself, otherwise please address the issues in your pull request message and we'll take care of it.
|
||||
If you update the [`README.md`](https://github.com/picocms/Pico/blob/master/README.md) or [`content-sample/index.md`](https://github.com/picocms/Pico/blob/master/content-sample/index.md), please make sure to update the corresponding files in the [`_docs`](https://github.com/picocms/Pico/tree/gh-pages/_docs/) folder of the `gh-pages` branch (i.e. [Pico's website](http://picocms.org/docs/)) and vice versa. Unfortunately this involves three (!) different markdown parsers. If you're experiencing problems, use Pico's [`erusev/parsedown-extra`](https://github.com/erusev/parsedown-extra) as a reference. You can try to make the contents compatible to [Redcarpet](https://github.com/vmg/redcarpet) by yourself, otherwise please address the issues in your pull request message and we'll take care of it.
|
||||
|
||||
Versioning
|
||||
----------
|
||||
|
@ -148,12 +75,12 @@ Pico's actual development happens in separate development branches. Development
|
|||
- `enhancement/` for smaller improvements, and
|
||||
- `bugfix/` for non-trivial bug fixes.
|
||||
|
||||
As soon as development reaches a point where feedback is appreciated, a pull request is opened. After some time (very soon for bug fixes, and other improvements should have a reasonable feedback phase) the pull request is merged and the development branch will be deleted. Trivial bug fixes that will be part of the next `PATCH` version will be merged directly into `master`.
|
||||
As soon as development reaches a point where feedback is appreciated, a pull request is opened. After some time (very soon for bug fixes, and other improvements should have a reasonable feedback phase) the pull request is merged and the development branch will be deleted. Trivial bug fixes which will be part of the next `PATCH` version will be merged directly into `master`.
|
||||
|
||||
Build & Release process
|
||||
-----------------------
|
||||
|
||||
We're using [Travis CI](https://travis-ci.com) to automate the build & release process of Pico. It generates and deploys a [PHP class documentation](http://picocms.org/phpDoc/) (powered by [phpDoc](http://phpdoc.org)) for new releases and on every commit to the `master` branch. Travis also prepares new releases by generating Pico's pre-built release packages, a version badge, code statistics (powered by [cloc](https://github.com/AlDanial/cloc)) and updates our website (the [`picocms.github.io` repo](https://github.com/picocms/picocms.github.io)). Please refer to our [`.travis.yml`](https://github.com/picocms/Pico/blob/master/.travis.yml), the [`picocms/ci-tools` repo](https://github.com/picocms/ci-tools) and the [`.build` directory](https://github.com/picocms/Pico/tree/master/.build) for details.
|
||||
We're using [Travis CI](https://travis-ci.com) to automate the build & release process of Pico. It generates and deploys [phpDoc](http://phpdoc.org) class docs for new releases and on every commit to the `master` branch. Travis also prepares new releases by generating Pico's pre-built packages and uploading them to GitHub. Please refer to [our `.travis.yml`](https://github.com/picocms/Pico/blob/master/.travis.yml) for details.
|
||||
|
||||
As insinuated above, it is important that each commit to `master` is deployable. Once development of a new Pico release is finished, trigger Pico's build & release process by pushing a new Git tag. This tag should reference a (usually empty) commit on `master`, which message should adhere to the following template:
|
||||
|
||||
|
@ -167,43 +94,4 @@ Version 1.0.0
|
|||
* [Removed] ...
|
||||
```
|
||||
|
||||
Before pushing a new Git tag, make sure to update the `Pico::VERSION` and `Pico::VERSION_ID` constants. The versions of Pico's official [default theme](https://github.com/picocms/pico-theme) and the [`PicoDeprecated` plugin](https://github.com/picocms/pico-deprecated) both strictly follow Pico's version. Since Pico's pre-built release package contains them, you must always create a new release of them (even though nothing has changed) before creating a new Pico release.
|
||||
|
||||
If you're pushing a new major or minor release of Pico, you should also update Pico's `composer.json` to require the latest minor releases of Pico's dependencies. Besides, don't forget to update the `@version` tags in the PHP class docs.
|
||||
|
||||
Travis CI will draft the new [release on GitHub](https://github.com/picocms/Pico/releases) automatically, but will require you to manually amend the descriptions formatting. The latest Pico version is always available at https://github.com/picocms/Pico/releases/latest, so please make sure to publish this URL rather than version-specific URLs. [Packagist](http://packagist.org/packages/picocms/pico) will be updated automatically.
|
||||
|
||||
Labeling of Issues & Pull Requests
|
||||
----------------------------------
|
||||
|
||||
Pico makes use of GitHub's label and milestone features, to aide developers in quickly identifying and prioritizing which issues need to be worked on. The starting point for labeling issues and pull requests is the `type` label, which is explained in greater detail below. The `type` label might get combined with a `pri` label, describing the issue's priority, and a `status` label, describing the current status of the issue.
|
||||
|
||||
Issues and pull requests labeled with `info: Feedback Needed` indicate that feedback from others is highly appreciated. We always appreciate feedback at any time and from anyone, but when this label is present, we explicitly *ask* you to give feedback. It would be great if you leave a comment!
|
||||
|
||||
- The `type: Bug` label is assigned to issues or pull requests, which have been identified as bugs or security issues in Pico's core. It might get combined with the `pri: High` label, when the problem was identified as security issue, or as a so-called "show stopper" bug. In contrast, uncritical problems might get labeled with `pri: Low`. `type: Bug` issues and pull requests are usually labeled with one of the following `status` labels when being closed:
|
||||
- `status: Resolved` is used when the issue has been resolved.
|
||||
- `status: Conflict` indicates a conflict with another issue or behavior of Pico, making it impossible to resolve the problem at the moment.
|
||||
- `status: Won't Fix` means, that there is indeed a problem, but for some reason we made the decision that resolving it isn't reasonable, making it intended behavior.
|
||||
- `status: Rejected` is used when the issue was rejected for another reason.
|
||||
|
||||
- The `type: Enhancement` and `type: Feature` labels are used to tag pull requests, which introduce either a comparatively small enhancement, or a "big" new feature. As with the `type: Bug` label, they might get combined with the `pri: High` or `pri: Low` labels to indicate the pull request's priority. If a pull request isn't mergeable at the moment, it is labeled with `status: Work In Progress` until development of the pull request is finished. After merging or closing the pull request, it is labeled with one of the `status` labels as described above for the `type: Bug` label.
|
||||
|
||||
- The `type: Idea` label is similar to the `type: Enhancement` and `type: Feature` labels, but is used for issues or incomplete and abandoned pull requests. It is otherwise used in the exact same way as `type: Enhancement` and `type: Feature`.
|
||||
|
||||
- The `type: Release` label is used in the exact same way as `type: Feature` and indicates the primary pull request of a new Pico release (please refer to the *Branching* and *Build & Release process* sections above).
|
||||
|
||||
- The `type: Notice`, `type: Support` and `type: Discussion` labels are used to indicate "fyi" issues, support-related issues (e.g. issues opened by users or developers asking questions), and issues with disucssions about arbitrary topics related to Pico. They are neither combined with `pri` labels, nor with `status` labels.
|
||||
|
||||
- The `type: Duplicate` label is used when there is already another issue or pull request related to this problem or feature request. Issues labeled with `type: Duplicate` are immediately closed.
|
||||
|
||||
- The `type: Invalid` label is used for everything else, e.g. issues or pull requests not related to Pico, or invalid bug reports. This includes supposed bug reports that concern actually intended behavior.
|
||||
|
||||
The `status: Deferred` label might get added to any open issue or pull request to indicate that it is still unresolved and will be resolved later. This is also true for the `info: Pinned` label: It indicates a important issue or pull request that remains open on purpose.
|
||||
|
||||
After resolving a issue, we usually keep it open for about a week to give users some more time for feedback and further questions. This is especially true for issues with the `type: Notice`, `type: Support`, `type: Discussion` and `type: Invalid` labels. After 7 days with no interaction, [Probot](https://probot.github.io/)'s [Stale](https://github.com/apps/stale) bot adds the `info: Stale` label to the issue to ask the participants whether the issue has been resolved. If no more activity occurs, the issue will be automatically closed by Stale bot 2 days later.
|
||||
|
||||
Issues and pull requests labeled with `info: Information Needed` indicate that we have asked one of the participants for further information and didn't receive any feedback yet. It is usually added after Stale bot adds the `info: Stale` label to give the participants some more days to give the necessary information.
|
||||
|
||||
Issues and pull requests, which are rather related to upstream projects (i.e. projects Pico depends on, like Twig), are additionally labeled with `info: Upstream`.
|
||||
|
||||
When a issue or pull request isn't directly related to Pico's core, but the project as a whole, it is labeled with `info: Meta`. Issues labeled with `info: Website` are related to [Pico's website](http://picocms.org), however, in this case it is usually expedient to move the issue to the [`picocms.github.io` repo](https://github.com/picocms/picocms.github.io) instead. The same applies to the `info: Pico CMS for Nextcloud` label; these issues are related to [Pico CMS for Nextcloud](https://apps.nextcloud.com/apps/cms_pico).
|
||||
|
|
286
README.md
286
README.md
|
@ -1,273 +1,153 @@
|
|||
Pico
|
||||
====
|
||||
|
||||
[![License](https://picocms.github.io/badges/pico-license.svg)](https://github.com/picocms/Pico/blob/master/LICENSE.md)
|
||||
[![Version](https://picocms.github.io/badges/pico-version.svg)](https://github.com/picocms/Pico/releases/latest)
|
||||
[![Build Status](https://api.travis-ci.org/picocms/Pico.svg?branch=master)](https://travis-ci.org/picocms/Pico)
|
||||
[![Libera.Chat](https://picocms.github.io/badges/pico-chat.svg)](https://web.libera.chat/#picocms)
|
||||
[![Open Bounties on Bountysource](https://www.bountysource.com/badge/team?team_id=198139&style=bounties_received)](https://www.bountysource.com/teams/picocms)
|
||||
[![License](https://img.shields.io/github/license/picocms/Pico.svg)](https://github.com/picocms/Pico/blob/master/LICENSE.md)
|
||||
[![Version](https://img.shields.io/github/release/picocms/Pico.svg)](https://github.com/picocms/Pico/releases/latest)
|
||||
[![Build Status](https://img.shields.io/travis/picocms/Pico.svg)](https://travis-ci.org/picocms/Pico)
|
||||
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/theshka/pico.svg)](https://scrutinizer-ci.com/g/theshka/Pico/?branch=master)
|
||||
[![Tweet Button](https://cloud.githubusercontent.com/assets/640217/11483728/b0842918-976f-11e5-9185-d53261b3125b.png)](https://twitter.com/intent/tweet?text=Pico+is+a+stupidly+simple%2C+blazing+fast%2C+flat+file+CMS.+Visit+http%3A%2F%2Fpicocms.org+and+downlaod+%23picocms+today%21+via+%40gitpicocms&related=gitpicocms)
|
||||
|
||||
Pico is a stupidly simple, blazing fast, flat file CMS.
|
||||
|
||||
Visit us at http://picocms.org/ and see http://picocms.org/about/ for more info.
|
||||
|
||||
---
|
||||
|
||||
### PHP 8.0+ Users
|
||||
|
||||
Seeing an `Unparenthesized a ? b : c ? d : e is not supported.` error?
|
||||
|
||||
Pico currently has issues with PHP versions newer than 8.0. This is due to Pico's dependencies, and not Pico itself. There's currently an "alpha" build of Pico you can download as a [Pre-Bundled Release](https://github.com/picocms/Pico/releases/tag/v3.0.0-alpha.2) that solves this issue.
|
||||
|
||||
This "alpha" is **perfectly safe** to use in production, as the *only* changes are **updated dependencies and version number strings**. If you're curious, you can confirm this by [comparing the changes](https://github.com/picocms/Pico/compare/pico-3.0-alpha) between branches.
|
||||
|
||||
More work was intended to be done on this branch, hence the "3.0" label, but it hasn't happened yet. There's an [on-going discussion](https://github.com/picocms/Pico/issues/608) about getting just these updated dependencies merged in as an official update (either Pico 2.2 or 3.0) as soon as possible.
|
||||
|
||||
Sorry for the inconvenience, and thanks to all Pico users for your patience on the matter. ❤️
|
||||
|
||||
---
|
||||
Pico is a stupidly simple, blazing fast, flat file CMS. See http://picocms.org/ for more info.
|
||||
|
||||
Screenshot
|
||||
----------
|
||||
-------
|
||||
|
||||
![Pico Screenshot](https://picocms.github.io/screenshots/pico-21.png)
|
||||
![Pico Screenshot](https://cloud.githubusercontent.com/assets/640217/11488304/1b17b388-978b-11e5-9827-532d14a79f2e.gif)
|
||||
|
||||
Table of Contents
|
||||
-------
|
||||
* [Pico](#pico)
|
||||
* [Install](#install)
|
||||
* [Pre-Bundled Release](#using-a-pre-bundled-release---for-users)
|
||||
* [Using Composer](#using-composer---for-developers)
|
||||
* [Upgrade](#upgrade)
|
||||
* [Run](#run)
|
||||
* [Config](#config)
|
||||
* [Getting Help](#getting-help)
|
||||
* [...as a user](#-as-a-user)
|
||||
* [...as a developer](#-as-a-developer)
|
||||
* [... still need help?](#-still-need-help-with-pico)
|
||||
* [Contributing](#contributing)
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Installing Pico is dead simple - and done in seconds! If you have access to a shell on your server (i.e. SSH access), we recommend using [Composer][]. If not, use a pre-bundled release. If you don't know what "SSH access" is, head over to the pre-bundled release. 😇
|
||||
You can install Pico either using a pre-bundled release or with composer. Pico is also available on [Packagist.org][] and may be included in other projects via `composer require picocms/pico`. Pico requires PHP 5.3+
|
||||
|
||||
Pico requires PHP 5.3.6+ and the PHP extensions `dom` and `mbstring` to be enabled.
|
||||
### Using a pre-bundled release - for users
|
||||
|
||||
### I want to use Composer
|
||||
1. [Download the latest Pico release][LatestRelease]
|
||||
|
||||
Starting with Pico 2.0 we recommend installing Pico using Composer whenever possible. Trust us, you won't regret it when it comes to upgrading Pico! Anyway, if you don't want to use Composer, or if you simply can't use Composer because you don't have access to a shell on your server, don't despair, installing Pico using a pre-bundled release is still easier than everything you know!
|
||||
2. Upload all files to the `httpdocs` directory (e.g. `/var/www/html`) of your server.
|
||||
|
||||
###### Step 1
|
||||
|
||||
Open a shell and navigate to the `httpdocs` directory (e.g. `/var/www/html`) of your server. Download Composer and run it with the `create-project` option to install it to the desired directory (e.g. `/var/www/html/pico`):
|
||||
|
||||
```shell
|
||||
$ curl -sSL https://getcomposer.org/installer | php
|
||||
$ php composer.phar create-project picocms/pico-composer pico
|
||||
```
|
||||
|
||||
###### Step 2
|
||||
|
||||
What second step? There's no second step. That's it! Open your favorite web browser and navigate to your brand new, stupidly simple, blazing fast, flat file CMS! Pico's sample contents will explain how to create your own contents. 😊
|
||||
|
||||
### I want to use a pre-bundled release
|
||||
|
||||
Do you know the feeling: You want to install a new website, so you upload all files of your favorite CMS and run the setup script - just to find out that you forgot about creating the SQL database first? Later the setup script tells you that the file permissions are wrong. Heck, what does this even mean? Forget about it, Pico is different!
|
||||
|
||||
###### Step 1
|
||||
|
||||
[Download the latest Pico release][LatestRelease] and upload all files to the desired install directory of Pico within the `httpdocs` directory (e.g. `/var/www/html/pico`) of your server.
|
||||
|
||||
###### Step 2
|
||||
|
||||
Okay, here's the catch: There's no catch. That's it! Open your favorite web browser and navigate to your brand new, stupidly simple, blazing fast, flat file CMS! Pico's sample contents will explain how to create your own contents. 😊
|
||||
|
||||
### I want to manage my website using a Git repository
|
||||
|
||||
Git is a very powerful distributed version-control system - and it can be used to establish a nice workflow around your Pico website. Using a Git repository for your website aids content creation and deployment, including collaborative editing and version control. If you want to manage your website in a Git repository, you use a Composer-based installation.
|
||||
|
||||
1. Fork [Pico's Composer starter project][PicoComposerGit] using [GitHub's fork button][HelpFork]. If you don't want to use GitHub you aren't required to, you can choose whatever Git server you want. Forking manually just requires some extra steps: First clone the Git repository locally, add your Git server as a remote and push the repository to this new remote.
|
||||
|
||||
2. Clone your fork locally and add your contents and assets. You can edit Pico's `composer.json` to include 3rd-party plugins and themes, or simply add your own plugins and themes to Pico's `plugins` resp. `themes` directories. Don't forget to commit your changes and push them to your Git server.
|
||||
|
||||
3. Open a shell on your webserver and navigate to the `httpdocs` directory (e.g. `/var/www/html`). Download Composer, clone your Git repository to the desired directory (e.g. `/var/www/html/pico`) and install Pico's dependencies using Composer's `install` option:
|
||||
### Using Composer - for developers
|
||||
|
||||
1. Open a shell and navigate to the desired install directory of Pico within the `httpdocs` directory (e.g. `/var/www/html`) of your server. You can now clone Pico's Git repository as follows:
|
||||
```shell
|
||||
$ curl -sSL https://getcomposer.org/installer | php
|
||||
$ git clone https://github.com/<YOUR_USERNAME>/<YOUR_REPOSITORY> pico
|
||||
$ php composer.phar --working-dir=pico install
|
||||
$ git clone https://github.com/picocms/Pico.git .
|
||||
```
|
||||
> Please note that this gives you the current development version of Pico, what is likely *unstable* and *not ready for production use*!
|
||||
|
||||
4. If you update your website's contents, simply commit your changes and push them to your Git server. Open a shell on your webserver and navigate to Pico's install directory within the `httpdocs` directory (e.g. `/var/www/html/pico`) of your server. Pull all changes from your Git server and update Pico's dependencies using Composer's `update` option:
|
||||
|
||||
2. Download [composer][] and run it with the `install` option:
|
||||
```shell
|
||||
$ git pull
|
||||
$ php composer.phar update
|
||||
$ curl -sS https://getcomposer.org/installer | php
|
||||
$ php composer.phar install
|
||||
```
|
||||
|
||||
### I'm a developer
|
||||
|
||||
So, you're one of these amazing people making all of this possible? We love you folks! As a developer we recommend you to clone [Pico's Git repository][PicoGit] as well as the Git repositories of [Pico's default theme][PicoThemeGit] and the [`PicoDeprecated` plugin][PicoDeprecatedGit]. You can set up your workspace using [Pico's Composer starter project][PicoComposerGit] and include all of Pico's components using local packages.
|
||||
|
||||
Using Pico's Git repositories is different from using one of the installation methods elucidated above. It gives you the current development version of Pico, what is likely *unstable* and *not ready for production use*!
|
||||
|
||||
1. Open a shell and navigate to the desired directory of Pico's development workspace within the `httpdocs` directory (e.g. `/var/www/html/pico`) of your server. Download and extract Pico's Composer starter project into the `workspace` directory:
|
||||
|
||||
```shell
|
||||
$ curl -sSL https://github.com/picocms/pico-composer/archive/master.tar.gz | tar xz
|
||||
$ mv pico-composer-master workspace
|
||||
```
|
||||
|
||||
2. Clone the Git repositories of all Pico components (Pico's core, Pico's default theme and the `PicoDeprecated` plugin) into the `components` directory:
|
||||
|
||||
```shell
|
||||
$ mkdir components
|
||||
$ git clone https://github.com/picocms/Pico.git components/pico
|
||||
$ git clone https://github.com/picocms/pico-theme.git components/pico-theme
|
||||
$ git clone https://github.com/picocms/pico-deprecated.git components/pico-deprecated
|
||||
```
|
||||
|
||||
3. Instruct Composer to use the local Git repositories as replacement for the `picocms/pico` (Pico's core), `picocms/pico-theme` (Pico's default theme) and `picocms/pico-deprecated` (the `PicoDeprecated` plugin) packages. Update the `composer.json` of your development workspace (i.e. `workspace/composer.json`) accordingly:
|
||||
|
||||
```json
|
||||
{
|
||||
"repositories": [
|
||||
{
|
||||
"type": "path",
|
||||
"url": "../components/pico",
|
||||
"options": { "symlink": true }
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"url": "../components/pico-theme",
|
||||
"options": { "symlink": true }
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"url": "../components/pico-deprecated",
|
||||
"options": { "symlink": true }
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"picocms/pico": "dev-master",
|
||||
"picocms/pico-theme": "dev-master",
|
||||
"picocms/pico-deprecated": "dev-master",
|
||||
"picocms/composer-installer": "^1.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
4. Download Composer and run it with the `install` option:
|
||||
|
||||
```shell
|
||||
$ curl -sSL https://getcomposer.org/installer | php
|
||||
$ php composer.phar --working-dir=workspace install
|
||||
```
|
||||
|
||||
You can now open your web browser and navigate to Pico's development workspace. All changes you make to Pico's components will automatically be reflected in the development workspace.
|
||||
|
||||
By the way, you can also find all of Pico's components on [Packagist.org][Packagist]: [Pico's core][PicoPackagist], [Pico's default theme][PicoThemePackagist], the [`PicoDeprecated` plugin][PicoDeprecatedPackagist] and [Pico's Composer starter project][PicoComposerPackagist].
|
||||
[^ toc][]
|
||||
|
||||
Upgrade
|
||||
-------
|
||||
|
||||
Do you remember when you installed Pico? It was ingeniously simple, wasn't it? Upgrading Pico is no difference! The upgrade process differs depending on whether you used [Composer][] or a pre-bundled release to install Pico. Please note that you should *always* create a backup of your Pico installation before upgrading!
|
||||
Upgrading Pico is very easy: You just have to replace all of Pico's files - that's it! Nevertheless you should *always* create a backup of your Pico installation before upgrading.
|
||||
|
||||
Pico follows [Semantic Versioning 2.0][SemVer] and uses version numbers like `MAJOR`.`MINOR`.`PATCH`. When we update the `PATCH` version (e.g. `2.0.0` to `2.0.1`), we made backwards-compatible bug fixes. If we change the `MINOR` version (e.g. `2.0` to `2.1`), we added functionality in a backwards-compatible manner. Upgrading Pico is dead simple in both cases. Simply head over to the appropiate Upgrade sections below.
|
||||
Pico follows [Semantic Versioning 2.0][SemVer] and uses version numbers like `MAJOR`.`MINOR`.`PATCH`. When we update...
|
||||
|
||||
But wait, we forgot to mention what happens when we update the `MAJOR` version (e.g. `2.0` to `3.0`). In this case we made incompatible API changes. We will then provide a appropriate upgrade tutorial, so please head over to the ["Upgrade" page on our website][HelpUpgrade].
|
||||
- the `PATCH` version (e.g. `1.0.0` to `1.0.1`), we made backwards-compatible bug fixes. It's then sufficient to extract [Pico's latest release][LatestRelease] to your existing installation directory and overwriting all files. Alternatively you can either use the [*source code* of Pico's latest release][LatestRelease] or pull from Pico's Git repository, but are then required to update Pico's [composer][] dependencies manually by running `php composer.phar update`.
|
||||
|
||||
### I've used Composer to install Pico
|
||||
- the `MINOR` version (e.g. `1.0` to `1.1`), we added functionality in a backwards-compatible manner, but anyway recommend you to "install" Pico newly. Backup all of your files, empty your installation directory and install Pico as elucidated above. You can then copy your `config/config.php` and `content` directory without any change. If applicable, you can also copy the folder of your custom theme within the `themes` directory. Provided that you're using plugins, also copy all of your plugins from the `plugins` directory.
|
||||
|
||||
Upgrading Pico is dead simple if you've used Composer to install Pico. Simply open a shell and navigate to Pico's install directory within the `httpdocs` directory (e.g. `/var/www/html/pico`) of your server. You can now upgrade Pico using just a single command:
|
||||
- the `MAJOR` version (e.g. `1.0` to `2.0`), we made incompatible API changes. We will then provide a appropriate upgrade tutorial.
|
||||
|
||||
```shell
|
||||
$ php composer.phar update
|
||||
```
|
||||
Upgrading Pico 0.8 or 0.9 to Pico 1.0 is a special case. The new `PicoDeprecated` plugin ensures backwards compatibility, so you basically can follow the above upgrade instructions as if we updated the `MINOR` version. However, we recommend you to take some further steps to confine the necessity of `PicoDeprecated` as far as possible. For more information about what has changed with Pico 1.0 and a step-by-step upgrade tutorial, please refer to the [upgrade page of our website][HelpUpgrade].
|
||||
|
||||
That's it! Composer will automatically update Pico and all plugins and themes you've installed using Composer. Please make sure to manually update all plugins and themes you've installed manually.
|
||||
[^ toc][]
|
||||
|
||||
### I've used a pre-bundled release to install Pico
|
||||
Run
|
||||
---
|
||||
|
||||
Okay, installing Pico was easy, but upgrading Pico is going to be hard, isn't it? I'm afraid I have to disappoint you. It's just as simple as installing Pico!
|
||||
You have nothing to consider specially, simply navigate to your Pico install using your favorite web browser. Pico's default contents will explain how to use your brand new, stupidly simple, blazing fast, flat file CMS.
|
||||
|
||||
First you'll have to delete the `vendor` directory of your Pico installation (e.g. if you've installed Pico to `/var/www/html/pico`, delete `/var/www/html/pico/vendor`). Then [download the latest Pico release][LatestRelease] and upload all files to your existing Pico installation directory. You will be prompted whether you want to overwrite files like `index.php`, `.htaccess`, ... - simply hit "Yes".
|
||||
### You don't have a web server?
|
||||
No worries! Starting with PHP 5.4 the easiest way to get started using Pico is with [PHP's built-in web server][PHPServer].
|
||||
|
||||
That's it! Now that Pico is up-to-date, you need to update all plugins and themes you've installed.
|
||||
1. Navigate to Pico's installation directory using a shell.
|
||||
|
||||
### I'm a developer
|
||||
2. Start PHPs built-in web server:
|
||||
```shell
|
||||
$ php -S 127.0.0.1:8080
|
||||
```
|
||||
3. Access Pico from http://localhost:8080.
|
||||
|
||||
As a developer you should know how to stay up-to-date... 😉 For the sake of completeness, if you want to upgrade Pico, simply open a shell and navigate to Pico's development workspace (e.g. `/var/www/html/pico`). Then pull the latest commits from the Git repositories of [Pico's core][PicoGit], [Pico's default theme][PicoThemeGit] and the [`PicoDeprecated` plugin][PicoDeprecatedGit]. Let Composer update your dependencies and you're ready to go.
|
||||
> Please note that PHPs built-in web server is for *development* and *testing* purposes *only!*
|
||||
|
||||
```shell
|
||||
$ git -C components/pico pull
|
||||
$ git -C components/pico-theme pull
|
||||
$ git -C components/pico-deprecated pull
|
||||
$ php composer.phar --working-dir=workspace update
|
||||
```
|
||||
[^ toc][]
|
||||
|
||||
Config
|
||||
---
|
||||
Once Pico is installed, you will need to copy your sites config file from `config/config.php.template` to `config/config.php`. The most important config items to set are `$config['timezone']`, `$config['base_url']`, and `$config['site_title']`
|
||||
|
||||
[^ toc][]
|
||||
|
||||
Getting Help
|
||||
------------
|
||||
|
||||
#### Getting Help as a user
|
||||
### ... as a user
|
||||
If you want to get started using Pico, please refer to our [user docs][HelpUserDocs]. Please read the [upgrade notes][HelpUpgrade] if you want to upgrade from Pico 0.8 or 0.9 to Pico 1.0. You can find officially supported plugins and themes on [our website][OfficialPlugins]. A greater choice of third-party plugins and themes can be found in our [Wiki][] on the [plugins][WikiPlugins] or [themes][WikiThemes] pages respectively. If you want to create your own plugin or theme, please refer to the "Getting Help as a developer" section below.
|
||||
|
||||
If you want to get started using Pico, please refer to our [user docs][HelpUserDocs]. Please read the [upgrade notes][HelpUpgrade] if you want to upgrade from Pico 1.0 to Pico 2.0. You can find officially supported [plugins][OfficialPlugins] and [themes][OfficialThemes] on our website. A greater choice of third-party plugins and themes can be found in our [Wiki][] on the [plugins][WikiPlugins] or [themes][WikiThemes] pages respectively. If you want to create your own plugin or theme, please refer to the "Getting Help as a developer" section below.
|
||||
### ... as a developer
|
||||
If you're a developer, please refer to the "Contributing" section below and our [contribution guidelines][ContributionGuidelines]. To get you started with creating a plugin or theme, please read the [dev docs on our website][HelpDevDocs].
|
||||
|
||||
#### Getting Help as a developer
|
||||
### ... still need help with Pico?
|
||||
When the docs can't answer your question or when you're experiencing problems with Pico, please don't hesitate to create a new [Issue][Issues] on GitHub. Concerning problems with plugins or themes, please refer to the website of the developer of this plugin or theme.
|
||||
|
||||
If you're a developer, please refer to the "Contributing" section below and our [contribution guidelines][ContributionGuidelines]. To get you started with creating a plugin or theme, please read the [developer docs on our website][HelpDevDocs].
|
||||
> **Before creating a new Issue,** please make sure the problem wasn't reported yet using [GitHubs search engine][IssuesSearch]. Please describe your issue as clear as possible and always include steps to reproduce the problem.
|
||||
|
||||
#### You still need help or experience a problem with Pico?
|
||||
|
||||
When the docs can't answer your question, you can get help by joining us on [#picocms on Libera.Chat][LiberaChat] ([logs][LiberaChatLogs]). When you're experiencing problems with Pico, please don't hesitate to create a new [Issue][Issues] on GitHub. Concerning problems with plugins or themes, please refer to the website of the developer of this plugin or theme.
|
||||
|
||||
**Before creating a new Issue,** please make sure the problem wasn't reported yet using [GitHubs search engine][IssuesSearch]. Please describe your issue as clear as possible and always include the *Pico version* you're using. Provided that you're using *plugins*, include a list of them too. We need information about the *actual and expected behavior*, the *steps to reproduce* the problem, and what steps you have taken to resolve the problem by yourself (i.e. *your own troubleshooting*).
|
||||
[^ toc][]
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
<!--flippa verify-->
|
||||
[![I Love Open Source](http://www.iloveopensource.io/images/logo-lightbg.png)](http://www.iloveopensource.io/projects/524c55dcca7964c617000756)
|
||||
|
||||
You want to contribute to Pico? We really appreciate that! You can help make Pico better by [contributing code][PullRequests] or [reporting issues][Issues], but please take note of our [contribution guidelines][ContributionGuidelines]. In general you can contribute in three different areas:
|
||||
|
||||
1. Plugins & Themes: You're a plugin developer or theme designer? We love you folks! You can find tons of information about how to develop plugins and themes at http://picocms.org/development/. If you have created a plugin or theme, please add it to our [Wiki][], either on the [plugins][WikiPlugins] or [themes][WikiThemes] page. You may also [Submit][] it to our website, where it'll be displayed on the official [plugin][OfficialPlugins] or [theme][OfficialThemes] pages!
|
||||
1. Plugins & Themes: You're a plugin developer or theme designer? We love you guys! You can find tons of information about how to develop plugins and themes at http://picocms.org/development/. If you have created a plugin or theme, please add it to our [Wiki][], either on the [plugins][WikiPlugins] or [themes page][WikiThemes]. Doing so, we may select and promote your plugin or theme on [our website][OfficialPlugins] as officially supported!
|
||||
|
||||
2. Documentation: We always appreciate people improving our documentation. You can either improve the [inline user docs][EditInlineDocs] or the more extensive [user docs on our website][EditUserDocs]. You can also improve the [docs for plugin and theme developers][EditDevDocs]. Simply fork our website's Git repository from https://github.com/picocms/picocms.github.io, change the Markdown files and open a [pull request][PullRequestsWebsite].
|
||||
2. Documentation: We always appreciate people improving our documentation. You can either improve the [inline user docs][EditInlineDocs] or the more extensive [user docs on our website][EditUserDocs]. You can also improve the [docs for plugin and theme developers][EditDevDocs]. Simply fork Pico from https://github.com/picocms/Pico, change the Markdown files and open a [pull request][PullRequests].
|
||||
|
||||
3. Pico's Core: The supreme discipline is to work on Pico's Core. Your contribution should help *every* Pico user to have a better experience with Pico. If this is the case, fork Pico from https://github.com/picocms/Pico and open a [pull request][PullRequests]. We look forward to your contribution!
|
||||
|
||||
By contributing to Pico, you accept and agree to the *Developer Certificate of Origin* for your present and future contributions submitted to Pico. Please refer to the ["Developer Certificate of Origin" section in our `CONTRIBUTING.md`][ContributionGuidelinesDCO].
|
||||
[^ toc][]
|
||||
|
||||
You don't have time to contribute code to Pico, but still want to "stand a coffee" for the ones who do? You can contribute monetary to Pico using [Bountysource][], a crowd funding website that focuses on individual issues and feature requests. Just refer to the "Bounties and Fundraisers" section below for more info.
|
||||
|
||||
Bounties and Fundraisers
|
||||
------------------------
|
||||
|
||||
Pico uses [Bountysource][] to allow monetary contributions to the project. Bountysource is a crowd funding website that focuses on individual issues and feature requests in Open Source projects using micropayment. Users, or "Backers", can pledge money for fixing a specific issue, implementing new features, or developing a new plugin or theme. Open source software developers, or "Bounty Hunters", can then pick up and solve these tasks to earn the money.
|
||||
|
||||
Obviously this won't allow a developer to replace a full time job, it's rather aiming to "stand a coffee". However, it helps bringing users and developers closer together, and shows developers what users want and how much they care about certain things. Nevertheless you can still donate money to the project itself, as an easy way to say "Thank You" and to support Pico.
|
||||
|
||||
If you want to encourage developers to [fix a specific issue][Issues] or implement a feature, simply [pledge a new bounty][Bountysource] or back an existing one.
|
||||
|
||||
As a developer you can pick up a bounty by simply contributing to Pico (please refer to the "Contributing" section above). You don't have to be a official Pico Contributor! Pico is a Open Source project, anyone can open [pull requests][PullRequests] and claim bounties.
|
||||
|
||||
Official Pico Contributors won't claim bounties on their own behalf, Pico will never take any money out of Bountysource. All money collected by Pico is used to pledge new bounties or to support projects Pico depends on.
|
||||
|
||||
[Composer]: https://getcomposer.org/
|
||||
[^ toc]: #table-of-contents
|
||||
[Packagist.org]: http://packagist.org/packages/picocms/pico
|
||||
[LatestRelease]: https://github.com/picocms/Pico/releases/latest
|
||||
[PicoGit]: https://github.com/picocms/Pico
|
||||
[PicoThemeGit]: https://github.com/picocms/pico-theme
|
||||
[PicoDeprecatedGit]: https://github.com/picocms/pico-deprecated
|
||||
[PicoComposerGit]: https://github.com/picocms/pico-composer
|
||||
[Packagist]: https://packagist.org/
|
||||
[PicoPackagist]: https://packagist.org/packages/picocms/pico
|
||||
[PicoThemePackagist]: https://packagist.org/packages/picocms/pico-theme
|
||||
[PicoDeprecatedPackagist]: https://packagist.org/packages/picocms/pico-deprecated
|
||||
[PicoComposerPackagist]: https://packagist.org/packages/picocms/pico-composer
|
||||
[composer]: https://getcomposer.org/
|
||||
[SemVer]: http://semver.org
|
||||
[HelpFork]: https://help.github.com/en/github/getting-started-with-github/fork-a-repo
|
||||
[HelpUpgrade]: http://picocms.org/in-depth/upgrade/
|
||||
[PHPServer]: http://php.net/manual/en/features.commandline.webserver.php
|
||||
[HelpUpgrade]: http://picocms.org/upgrade/
|
||||
[HelpUserDocs]: http://picocms.org/docs/
|
||||
[HelpDevDocs]: http://picocms.org/development/
|
||||
[Submit]: http://picocms.org/in-depth/submission_guidelines
|
||||
[OfficialPlugins]: http://picocms.org/plugins/
|
||||
[OfficialThemes]: http://picocms.org/themes/
|
||||
[OfficialPlugins]: http://picocms.org/customization/
|
||||
[Wiki]: https://github.com/picocms/Pico/wiki
|
||||
[WikiPlugins]: https://github.com/picocms/Pico/wiki/Pico-Plugins
|
||||
[WikiThemes]: https://github.com/picocms/Pico/wiki/Pico-Themes
|
||||
[Issues]: https://github.com/picocms/Pico/issues
|
||||
[IssuesSearch]: https://github.com/picocms/Pico/search?type=Issues
|
||||
[LiberaChat]: https://web.libera.chat/#picocms
|
||||
[LiberaChatLogs]: http://picocms.org/irc-logs
|
||||
[PullRequests]: https://github.com/picocms/Pico/pulls
|
||||
[PullRequestsWebsite]: https://github.com/picocms/picocms.github.io/pulls
|
||||
[ContributionGuidelines]: https://github.com/picocms/Pico/blob/master/CONTRIBUTING.md
|
||||
[ContributionGuidelinesDCO]: https://github.com/picocms/Pico/blob/master/CONTRIBUTING.md#developer-certificate-of-origin
|
||||
[EditInlineDocs]: https://github.com/picocms/Pico/edit/master/content-sample/index.md
|
||||
[EditUserDocs]: https://github.com/picocms/picocms.github.io/tree/master/_docs
|
||||
[EditDevDocs]: https://github.com/picocms/picocms.github.io/tree/master/_development
|
||||
[Bountysource]: https://www.bountysource.com/teams/picocms
|
||||
[EditUserDocs]: https://github.com/picocms/Pico/tree/gh-pages/_docs
|
||||
[EditDevDocs]: https://github.com/picocms/Pico/tree/gh-pages/_development
|
||||
|
|
15
SECURITY.md
15
SECURITY.md
|
@ -1,15 +0,0 @@
|
|||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Only the most recent stable version of Pico is supported.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
To mitigate the impact of possible security issues we ask you to disclose any security issues with Pico privately first ("responsible disclosure"). To do so please send an email to Pico's lead developer:
|
||||
|
||||
> Daniel Rudolf \<picocms.org@daniel-rudolf.de\>
|
||||
|
||||
You should receive an answer within 48 hours.
|
||||
|
||||
All messages with valid security reports will be puslished on GitHub in full text.
|
40
_build/deploy-phpdoc-branch.sh
Executable file
40
_build/deploy-phpdoc-branch.sh
Executable file
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
if [ "$TRAVIS_PHP_VERSION" != "5.3" ]; then
|
||||
echo "Skipping phpDoc deployment because this is not on the required runtime"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [[ ",$DEPLOY_PHPDOC_BRANCHES," != *,"$TRAVIS_BRANCH",* ]]; then
|
||||
echo "Skipping phpDoc deployment because this branch ($TRAVIS_BRANCH) is not permitted to deploy"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||
echo "Skipping phpDoc deployment because this pull request (#$TRAVIS_PULL_REQUEST) is not permitted to deploy"
|
||||
exit
|
||||
fi
|
||||
|
||||
PHPDOC_ID="${TRAVIS_BRANCH//\//_}"
|
||||
PHPDOC_GIT_DIR="$TRAVIS_BUILD_DIR/_build/phpdoc-$PHPDOC_ID.git"
|
||||
|
||||
# clone repo
|
||||
echo "Cloning repo..."
|
||||
git clone --branch="gh-pages" "https://github.com/$TRAVIS_REPO_SLUG.git" "$PHPDOC_GIT_DIR"
|
||||
[ $? -eq 0 ] || exit 1
|
||||
|
||||
cd "$PHPDOC_GIT_DIR"
|
||||
echo
|
||||
|
||||
# generate phpDocs
|
||||
generate-phpdoc.sh \
|
||||
"$TRAVIS_BUILD_DIR/.phpdoc.xml" \
|
||||
"$PHPDOC_GIT_DIR/phpDoc/$PHPDOC_ID.cache" "$PHPDOC_GIT_DIR/phpDoc/$PHPDOC_ID" \
|
||||
"Pico 1.0 API Documentation ($TRAVIS_BRANCH branch)"
|
||||
[ $? -eq 0 ] || exit 1
|
||||
|
||||
# deploy phpDocs
|
||||
deploy-phpdoc.sh \
|
||||
"Update phpDocumentor class docs for $TRAVIS_BRANCH branch @ $TRAVIS_COMMIT" \
|
||||
"$TRAVIS_REPO_SLUG" "heads/$TRAVIS_BRANCH" "$TRAVIS_COMMIT"
|
||||
[ $? -eq 0 ] || exit 1
|
27
_build/deploy-phpdoc-release.sh
Executable file
27
_build/deploy-phpdoc-release.sh
Executable file
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
[ "$DEPLOY_PHPDOC_RELEASES" == "true" ] || exit
|
||||
|
||||
PHPDOC_ID="${TRAVIS_BRANCH//\//_}"
|
||||
PHPDOC_GIT_DIR="$TRAVIS_BUILD_DIR/_build/phpdoc-$PHPDOC_ID.git"
|
||||
|
||||
# clone repo
|
||||
echo "Cloning repo..."
|
||||
git clone --branch="gh-pages" "https://github.com/$TRAVIS_REPO_SLUG.git" "$PHPDOC_GIT_DIR"
|
||||
[ $? -eq 0 ] || exit 1
|
||||
|
||||
cd "$PHPDOC_GIT_DIR"
|
||||
echo
|
||||
|
||||
# generate phpDocs
|
||||
generate-phpdoc.sh \
|
||||
"$TRAVIS_BUILD_DIR/.phpdoc.xml" \
|
||||
"-" "$PHPDOC_GIT_DIR/phpDoc/$PHPDOC_ID" \
|
||||
"Pico 1.0 API Documentation ($TRAVIS_TAG)"
|
||||
[ $? -eq 0 ] || exit 1
|
||||
|
||||
# deploy phpDocs
|
||||
deploy-phpdoc.sh \
|
||||
"Update phpDocumentor class docs for $TRAVIS_TAG" \
|
||||
"$TRAVIS_REPO_SLUG" "tags/$TRAVIS_TAG" "$TRAVIS_COMMIT"
|
||||
[ $? -eq 0 ] || exit 1
|
80
_build/deploy-phpdoc.sh
Executable file
80
_build/deploy-phpdoc.sh
Executable file
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# environment variables
|
||||
# GITHUB_OAUTH_TOKEN GitHub authentication token, see https://github.com/settings/tokens
|
||||
|
||||
# parameters
|
||||
COMMIT_MESSAGE="$1" # commit message
|
||||
CHECK_REPO_SLUG="$2" # optional GitHub repo (e.g. picocms/Pico) to check
|
||||
# its latest commit as basic race condition protection
|
||||
CHECK_REMOTE_REF="$3" # optional remote Git reference (e.g. heads/master)
|
||||
CHECK_LOCAL_COMMIT="$4" # optional local commit SHA1
|
||||
|
||||
# print parameters
|
||||
echo "Deploying phpDocs..."
|
||||
printf 'COMMIT_MESSAGE="%s"\n' "$COMMIT_MESSAGE"
|
||||
printf 'CHECK_REPO_SLUG="%s"\n' "$CHECK_REPO_SLUG"
|
||||
printf 'CHECK_REMOTE_REF="%s"\n' "$CHECK_REMOTE_REF"
|
||||
printf 'CHECK_LOCAL_COMMIT="%s"\n' "$CHECK_LOCAL_COMMIT"
|
||||
echo
|
||||
|
||||
# check for changes
|
||||
if [ -z "$(git status --porcelain)" ]; then
|
||||
printf 'Nothing to deploy; skipping...\n\n'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# setup git
|
||||
printf 'Preparing repo...\n'
|
||||
git config push.default simple
|
||||
git config user.name "Travis CI"
|
||||
git config user.email "travis-ci@picocms.org"
|
||||
|
||||
if [ -n "$GITHUB_OAUTH_TOKEN" ]; then
|
||||
git config credential.helper 'store --file=.git/credentials'
|
||||
(umask 077 && echo "https://GitHub:$GITHUB_OAUTH_TOKEN@github.com" > .git/credentials)
|
||||
fi
|
||||
|
||||
# commit changes
|
||||
printf '\nCommiting changes...\n'
|
||||
git add --all
|
||||
git commit --message="$COMMIT_MESSAGE"
|
||||
|
||||
# race condition protection for concurrent Travis builds
|
||||
# this is no definite protection (race conditions are still possible during `git push`),
|
||||
# but it should give a basic protection without disabling concurrent builds completely
|
||||
if [ -n "$CHECK_REPO_SLUG" ] && [ -n "$CHECK_REMOTE_REF" ] && [ -n "$CHECK_LOCAL_COMMIT" ]; then
|
||||
# retrieve information using GitHub APIv3
|
||||
printf '\nChecking latest commit...\n'
|
||||
CHECK_API_URL="https://api.github.com/repos/$CHECK_REPO_SLUG/git/refs/$CHECK_REMOTE_REF"
|
||||
if [ -n "$GITHUB_OAUTH_TOKEN" ]; then
|
||||
CHECK_API_RESPONSE="$(wget -O- --header="Authorization: token $GITHUB_OAUTH_TOKEN" "$CHECK_API_URL" 2> /dev/null)"
|
||||
else
|
||||
CHECK_API_RESPONSE="$(wget -O- "$CHECK_API_URL" 2> /dev/null)"
|
||||
fi
|
||||
|
||||
# evaluate JSON response
|
||||
CHECK_REMOTE_COMMIT="$(echo "$CHECK_API_RESPONSE" | php -r "
|
||||
\$json = json_decode(stream_get_contents(STDIN), true);
|
||||
if (\$json !== null) {
|
||||
if (isset(\$json['ref']) && (\$json['ref'] === 'refs/$CHECK_REMOTE_REF')) {
|
||||
if (isset(\$json['object']) && isset(\$json['object']['sha'])) {
|
||||
echo \$json['object']['sha'];
|
||||
}
|
||||
}
|
||||
}
|
||||
")"
|
||||
|
||||
# compare source reference against the latest commit
|
||||
if [ "$CHECK_REMOTE_COMMIT" != "$CHECK_LOCAL_COMMIT" ]; then
|
||||
echo "WARNING: latest local commit '$CHECK_LOCAL_COMMIT' doesn't match latest remote commit '$CHECK_REMOTE_COMMIT'" >&2
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# push changes
|
||||
printf '\nPushing changes...\n'
|
||||
git push origin
|
||||
|
||||
echo
|
48
_build/generate-phpdoc.sh
Executable file
48
_build/generate-phpdoc.sh
Executable file
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# parameters
|
||||
PHPDOC_CONFIG="$1" # phpDoc config file
|
||||
PHPDOC_CACHE_DIR="$2" # phpDoc cache dir
|
||||
PHPDOC_TARGET_DIR="$3" # phpDoc output dir
|
||||
PHPDOC_TITLE="$4" # API docs title
|
||||
|
||||
# print parameters
|
||||
echo "Generating phpDocs..."
|
||||
printf 'PHPDOC_CONFIG="%s"\n' "$PHPDOC_CONFIG"
|
||||
printf 'PHPDOC_CACHE_DIR="%s"\n' "$PHPDOC_CACHE_DIR"
|
||||
printf 'PHPDOC_TARGET_DIR="%s"\n' "$PHPDOC_TARGET_DIR"
|
||||
printf 'PHPDOC_TITLE="%s"\n' "$PHPDOC_TITLE"
|
||||
echo
|
||||
|
||||
# update a separate phpDoc cache
|
||||
if [ "$PHPDOC_CACHE_DIR" != "-" ]; then
|
||||
# parse phpDoc files (i.e. update cache)
|
||||
printf "Update phpDoc cache...\n"
|
||||
phpdoc project:parse --config "$PHPDOC_CONFIG" \
|
||||
--target "$PHPDOC_CACHE_DIR"
|
||||
|
||||
# check for changes
|
||||
printf '\nCheck for phpDoc cache changes...\n'
|
||||
if [ -z "$(git status --porcelain "$PHPDOC_CACHE_DIR")" ]; then
|
||||
printf 'No changes detected; skipping phpDocs renewal...\n\n'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# NOTE: actually the following command should be `phpdoc project:transform`
|
||||
# instead of `phpdoc project:run`, but the command seems to be broken...
|
||||
echo
|
||||
else
|
||||
# create temporary cache files in PHPDOC_TARGET_DIR
|
||||
PHPDOC_CACHE_DIR="$PHPDOC_TARGET_DIR"
|
||||
fi
|
||||
|
||||
# transform phpDoc files (i.e. rewrite API docs)
|
||||
printf 'Rewrite phpDocs...\n'
|
||||
rm -rf "$PHPDOC_TARGET_DIR"
|
||||
phpdoc project:run --config "$PHPDOC_CONFIG" \
|
||||
--cache-folder "$PHPDOC_CACHE_DIR" \
|
||||
--target "$PHPDOC_TARGET_DIR" \
|
||||
--title "$PHPDOC_TITLE"
|
||||
|
||||
echo
|
2
assets/.gitignore
vendored
2
assets/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
# This directory is meant to be empty
|
||||
*
|
|
@ -2,7 +2,7 @@
|
|||
"name": "picocms/pico",
|
||||
"type": "library",
|
||||
"description": "Pico is a flat file CMS, this means there is no administration backend and database to deal with. You simply create .md files in the \"content\" folder and that becomes a page.",
|
||||
"keywords": ["pico", "picocms", "pico-cms", "simple", "flat-file", "cms", "content-management", "website", "markdown-to-html", "php", "markdown", "yaml", "twig" ],
|
||||
"keywords": ["flat-file","cms","php","twig","markdown"],
|
||||
"homepage": "http://picocms.org/",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
|
@ -11,18 +11,10 @@
|
|||
"email": "gilbert@pellegrom.me",
|
||||
"role": "Project Founder"
|
||||
},
|
||||
{
|
||||
"name": "Daniel Rudolf",
|
||||
"email": "picocms.org@daniel-rudolf.de",
|
||||
"role": "Lead Developer"
|
||||
},
|
||||
{
|
||||
"name": "The Pico Community",
|
||||
"homepage": "http://picocms.org/"
|
||||
},
|
||||
{
|
||||
"name": "Contributors",
|
||||
"homepage": "https://github.com/picocms/Pico/graphs/contributors"
|
||||
"homepage": "https://github.com/picocms/Pico/graphs/contributors",
|
||||
"role": "Contributors"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
|
@ -32,16 +24,13 @@
|
|||
},
|
||||
"require": {
|
||||
"php": ">=5.3.6",
|
||||
"ext-mbstring": "*",
|
||||
"twig/twig": "^1.36",
|
||||
"symfony/yaml" : "^2.8",
|
||||
"erusev/parsedown": "1.8.0-beta-7",
|
||||
"erusev/parsedown-extra": "0.8.0-beta-1"
|
||||
"twig/twig": "^1.18",
|
||||
"erusev/parsedown-extra": "^0.7",
|
||||
"symfony/yaml" : "^2.3"
|
||||
},
|
||||
"suggest": {
|
||||
"picocms/pico-theme": "Pico requires a theme to actually display the contents of your website. This is Pico's official default theme.",
|
||||
"picocms/pico-deprecated": "PicoDeprecated's purpose is to maintain backward compatibility to older versions of Pico.",
|
||||
"picocms/composer-installer": "This Composer plugin is responsible for installing Pico plugins and themes using the Composer package manager."
|
||||
"require-dev" : {
|
||||
"phpdocumentor/phpdocumentor": "^2.8",
|
||||
"squizlabs/php_codesniffer": "^2.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
|
@ -49,11 +38,5 @@
|
|||
"PicoPluginInterface": "lib/",
|
||||
"AbstractPicoPlugin": "lib/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.1.x-dev",
|
||||
"dev-pico-3.0": "3.0.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
3
config/.gitignore
vendored
3
config/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
|||
# This directory is meant to be empty, except for config.yml.template
|
||||
*
|
||||
!config.yml.template
|
67
config/config.php.template
Normal file
67
config/config.php.template
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
/**
|
||||
* Pico configuration
|
||||
*
|
||||
* This is the configuration file for {@link Pico}. It comes loaded with the
|
||||
* default values, which can be found in {@link Pico::getConfig()} (see
|
||||
* {@path "lib/Pico.php"}).
|
||||
*
|
||||
* To override any of the default settings below, copy this file to
|
||||
* {@path "config/config.php"}, uncomment the line, then make and
|
||||
* save your changes.
|
||||
*
|
||||
* @author Gilbert Pellegrom
|
||||
* @link http://picocms.org
|
||||
* @license http://opensource.org/licenses/MIT
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* BASIC
|
||||
*/
|
||||
// $config['site_title'] = 'Pico'; // Site title
|
||||
// $config['base_url'] = ''; // Override base URL (e.g. http://example.com)
|
||||
// $config['rewrite_url'] = null; // A boolean indicating forced URL rewriting
|
||||
|
||||
/*
|
||||
* THEME
|
||||
*/
|
||||
// $config['theme'] = 'default'; // Set the theme (defaults to "default")
|
||||
// $config['theme_config'] = array( // Configure the default theme
|
||||
// 'about_us' => '',
|
||||
// 'social_media' => array(
|
||||
// 'github' => '',
|
||||
// 'facebook' => '',
|
||||
// 'twitter' => ''
|
||||
// ),
|
||||
// 'copyright' => ''
|
||||
// );
|
||||
// $config['twig_config'] = array( // Twig settings
|
||||
// 'cache' => false, // To enable Twig caching change this to a path to a writable directory
|
||||
// 'autoescape' => false, // Auto-escape Twig vars
|
||||
// 'debug' => false // Enable Twig debug
|
||||
// );
|
||||
|
||||
/*
|
||||
* CONTENT
|
||||
*/
|
||||
// $config['date_format'] = '%D %T'; // Set the PHP date format as described here: http://php.net/manual/en/function.strftime.php
|
||||
// $config['pages_order_by'] = 'alpha'; // Order pages by "alpha" or "date"
|
||||
// $config['pages_order'] = 'asc'; // Order pages "asc" or "desc"
|
||||
// $config['content_dir'] = 'content-sample/'; // Content directory
|
||||
// $config['content_ext'] = '.md'; // File extension of content files to serve
|
||||
|
||||
/*
|
||||
* TIMEZONE
|
||||
*/
|
||||
// $config['timezone'] = 'UTC'; // Timezone may be required by your php install
|
||||
|
||||
/*
|
||||
* PLUGINS
|
||||
*/
|
||||
// $config['DummyPlugin.enabled'] = false; // Force DummyPlugin to be disabled
|
||||
|
||||
/*
|
||||
* CUSTOM
|
||||
*/
|
||||
// $config['custom_setting'] = 'Hello'; // Can be accessed by {{ config.custom_setting }} in a theme
|
|
@ -1,60 +0,0 @@
|
|||
##
|
||||
# Basic
|
||||
#
|
||||
site_title: Pico # The title of your website
|
||||
base_url: ~ # Pico will try to guess its base URL, if this fails, override it here;
|
||||
# Example: https://example.com/pico/
|
||||
rewrite_url: ~ # A boolean (true or false) indicating whether URL rewriting is forced
|
||||
debug: ~ # Set this to true to enable Pico's debug mode
|
||||
timezone: ~ # Your PHP installation might require you to manually specify a timezone
|
||||
locale: ~ # Your PHP installation might require you to manually specify a locale to use
|
||||
|
||||
##
|
||||
# Theme
|
||||
#
|
||||
theme: default # The name of your custom theme
|
||||
themes_url: ~ # Pico will try to guess the URL to the themes dir of your installation;
|
||||
# If this fails, override it here. Example: https://example.com/pico/themes/
|
||||
theme_config: # Additional theme-specific config
|
||||
widescreen: false # Default theme: Use more horizontal space (i.e. make the site container wider)
|
||||
twig_config: # Twig template engine config
|
||||
autoescape: html # Let Twig escape variables by default
|
||||
strict_variables: false # If set to true, Twig will bail out when unset variables are being used
|
||||
charset: utf-8 # The charset used by Twig templates
|
||||
debug: ~ # Enable Twig's debug mode
|
||||
cache: false # Enable Twig template caching by specifying a path to a writable directory
|
||||
auto_reload: ~ # Recompile Twig templates whenever the source code changes
|
||||
|
||||
##
|
||||
# Content
|
||||
#
|
||||
date_format: %D %T # Pico's default date format;
|
||||
# See https://php.net/manual/en/function.strftime.php for more info
|
||||
pages_order_by_meta: author # Sort pages by meta value "author" (set "pages_order_by" to "meta")
|
||||
pages_order_by: alpha # Change how Pico sorts pages ("alpha" for alphabetical order, "date", or "meta")
|
||||
pages_order: asc # Sort pages in ascending ("asc") or descending ("desc") order
|
||||
content_dir: ~ # The path to Pico's content directory
|
||||
content_ext: .md # The file extension of your Markdown files
|
||||
content_config: # Parsedown Markdown parser config
|
||||
extra: true # Use the Parsedown Extra parser to support extended markup;
|
||||
# See https://michelf.ca/projects/php-markdown/extra/ for more info
|
||||
breaks: false # A boolean indicating whether breaks in the markup should be reflected in the
|
||||
# parsed contents of the page
|
||||
escape: false # Escape HTML markup in your content files; don't confuse this with some sort of
|
||||
# safe mode, enabling this doesn't allow you to process untrusted user input!
|
||||
auto_urls: true # Automatically link URLs found in your markup
|
||||
assets_dir: assets/ # The path to Pico's assets directory
|
||||
assets_url: ~ # Pico will try to guess the URL to the assets dir of your installation;
|
||||
# If this fails, override it here. Example: https://example.com/pico/assets/
|
||||
|
||||
##
|
||||
# Plugins
|
||||
#
|
||||
plugins_url: ~ # Pico will try to guess the URL to the plugins dir of your installation;
|
||||
# If this fails, override it here. Example: https://example.com/pico/plugins/
|
||||
DummyPlugin.enabled: false # Force the plugin "DummyPlugin" to be disabled
|
||||
|
||||
##
|
||||
# Custom
|
||||
#
|
||||
my_custom_setting: Hello World! # You can access custom settings in themes using {{ config.my_custom_setting }}
|
|
@ -1,14 +0,0 @@
|
|||
---
|
||||
Logo: %theme_url%/img/pico-white.svg
|
||||
Tagline: Making the web easy.
|
||||
Social:
|
||||
- title: Visit us on GitHub
|
||||
url: https://github.com/picocms/Pico
|
||||
icon: octocat
|
||||
- title: Join us on Libera.Chat
|
||||
url: https://web.libera.chat/#picocms
|
||||
icon: chat
|
||||
- title: Help us by creating/collecting bounties and pledging to fundraisers
|
||||
url: https://www.bountysource.com/teams/picocms
|
||||
icon: dollar
|
||||
---
|
7
content-sample/blog.md
Normal file
7
content-sample/blog.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
Title: Blog Example
|
||||
Description: Pico is a stupidly simple, blazing fast, flat file CMS.
|
||||
Template: blog
|
||||
---
|
||||
|
||||
<!-- All posts in the 'content-sample/blog' folder will be shown here...-->
|
13
content-sample/blog/post1.md
Normal file
13
content-sample/blog/post1.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
Title: Post with Sidebar
|
||||
Description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ultricies tristique nulla et mattis. Phasellus id massa eget nisl congue blandit sit amet id ligula. Praesent et nulla eu augue tempus sagittis. Mauris faucibus nibh et nibh cursus in vestibulum sapien egestas. Curabitur ut lectus tortor.
|
||||
Author: PicoCMS
|
||||
Date: Dec 31 2015 11:59:59
|
||||
Template: blog-post
|
||||
---
|
||||
|
||||
This is `post1.md` in the `blog` folder.
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ultricies tristique nulla et mattis. Phasellus id massa eget nisl congue blandit sit amet id ligula. Praesent et nulla eu augue tempus sagittis. Mauris faucibus nibh et nibh cursus in vestibulum sapien egestas. Curabitur ut lectus tortor. Sed ipsum eros, egestas ut eleifend non, elementum vitae eros. Mauris felis diam, pellentesque vel lacinia ac, dictum a nunc. Mauris mattis nunc sed mi sagittis et facilisis tortor volutpat. Etiam tincidunt urna mattis erat placerat placerat ac eu tellus. Ut nec velit id nisl tincidunt vehicula id a metus. Pellentesque erat neque, faucibus id ultricies vel, mattis in ante. Donec lobortis, mauris id congue scelerisque, diam nisl accumsan orci, condimentum porta est magna vel arcu. Curabitur varius ante dui. Vivamus sit amet ante ac diam ullamcorper sodales sed a odio.
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ultricies tristique nulla et mattis. Phasellus id massa eget nisl congue blandit sit amet id ligula. Praesent et nulla eu augue tempus sagittis. Mauris faucibus nibh et nibh cursus in vestibulum sapien egestas. Curabitur ut lectus tortor. Sed ipsum eros, egestas ut eleifend non, elementum vitae eros. Mauris felis diam, pellentesque vel lacinia ac, dictum a nunc. Mauris mattis nunc sed mi sagittis et facilisis tortor volutpat. Etiam tincidunt urna mattis erat placerat placerat ac eu tellus. Ut nec velit id nisl tincidunt vehicula id a metus. Pellentesque erat neque, faucibus id ultricies vel, mattis in ante. Donec lobortis, mauris id congue scelerisque, diam nisl accumsan orci, condimentum porta est magna vel arcu. Curabitur varius ante dui. Vivamus sit amet ante ac diam ullamcorper sodales sed a odio.
|
14
content-sample/blog/post2.md
Normal file
14
content-sample/blog/post2.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
Title: Post Full-Width
|
||||
Description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ultricies tristique nulla et mattis. Phasellus id massa eget nisl congue blandit sit amet id ligula. Praesent et nulla eu augue tempus sagittis. Mauris faucibus nibh et nibh cursus in vestibulum sapien egestas. Curabitur ut lectus tortor.
|
||||
Author: PicoCMS
|
||||
Date: Jan 1 2016 12:00:00
|
||||
Image: "http://placehold.it/1200x300&text=Blog+Image"
|
||||
Template: blog-post-full
|
||||
---
|
||||
|
||||
This is `post2.md` in the `blog` folder.
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ultricies tristique nulla et mattis. Phasellus id massa eget nisl congue blandit sit amet id ligula. Praesent et nulla eu augue tempus sagittis. Mauris faucibus nibh et nibh cursus in vestibulum sapien egestas. Curabitur ut lectus tortor. Sed ipsum eros, egestas ut eleifend non, elementum vitae eros. Mauris felis diam, pellentesque vel lacinia ac, dictum a nunc. Mauris mattis nunc sed mi sagittis et facilisis tortor volutpat. Etiam tincidunt urna mattis erat placerat placerat ac eu tellus. Ut nec velit id nisl tincidunt vehicula id a metus. Pellentesque erat neque, faucibus id ultricies vel, mattis in ante. Donec lobortis, mauris id congue scelerisque, diam nisl accumsan orci, condimentum porta est magna vel arcu. Curabitur varius ante dui. Vivamus sit amet ante ac diam ullamcorper sodales sed a odio.
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ultricies tristique nulla et mattis. Phasellus id massa eget nisl congue blandit sit amet id ligula. Praesent et nulla eu augue tempus sagittis. Mauris faucibus nibh et nibh cursus in vestibulum sapien egestas. Curabitur ut lectus tortor. Sed ipsum eros, egestas ut eleifend non, elementum vitae eros. Mauris felis diam, pellentesque vel lacinia ac, dictum a nunc. Mauris mattis nunc sed mi sagittis et facilisis tortor volutpat. Etiam tincidunt urna mattis erat placerat placerat ac eu tellus. Ut nec velit id nisl tincidunt vehicula id a metus. Pellentesque erat neque, faucibus id ultricies vel, mattis in ante. Donec lobortis, mauris id congue scelerisque, diam nisl accumsan orci, condimentum porta est magna vel arcu. Curabitur varius ante dui. Vivamus sit amet ante ac diam ullamcorper sodales sed a odio.
|
|
@ -5,8 +5,8 @@ Description: Pico is a stupidly simple, blazing fast, flat file CMS.
|
|||
|
||||
## Welcome to Pico
|
||||
|
||||
Congratulations, you have successfully installed [Pico][] %version%.
|
||||
%meta.description% <!-- replaced by the above Description header -->
|
||||
Congratulations, you have successfully installed [Pico](http://picocms.org/).
|
||||
%meta.description% <!-- replaced by the above Description meta header -->
|
||||
|
||||
## Creating Content
|
||||
|
||||
|
@ -15,19 +15,19 @@ database to deal with. You simply create `.md` files in the `content` folder
|
|||
and those files become your pages. For example, this file is called `index.md`
|
||||
and is shown as the main landing page.
|
||||
|
||||
When you install Pico, it comes with some sample contents that will display
|
||||
until you add your own content. Simply add some `.md` files to your `content`
|
||||
folder in Pico's root directory. No configuration is required, Pico will
|
||||
automatically use the `content` folder as soon as you create your own
|
||||
`index.md`. Just check out [Pico's sample contents][SampleContents] for an
|
||||
example!
|
||||
When you install Pico, it comes with a `content-sample` folder. Inside this
|
||||
folder is a sample website that will display until you add your own content.
|
||||
You should create your own `content` folder in Pico's root directory and place
|
||||
your files there. No configuration is required, Pico will automatically use the
|
||||
`content` folder if it exists.
|
||||
|
||||
If you create a folder within the content directory (e.g. `content/sub`) and
|
||||
put an `index.md` inside it, you can access that folder at the URL
|
||||
`%base_url%?sub`. If you want another page within the sub folder, simply create
|
||||
a text file with the corresponding name and you will be able to access it
|
||||
(e.g. `content/sub/page.md` is accessible from the URL `%base_url%?sub/page`).
|
||||
Below we've shown some examples of locations and their corresponding URLs:
|
||||
If you create a folder within the content folder (e.g. `content/sub`) and put
|
||||
an `index.md` inside it, you can access that folder at the URL
|
||||
`http://example.com/?sub`. If you want another page within the sub folder,
|
||||
simply create a text file with the corresponding name and you will be able to
|
||||
access it (e.g. `content/sub/page.md` is accessible from the URL
|
||||
`http://example.com/?sub/page`). Below we've shown some examples of locations
|
||||
and their corresponding URLs:
|
||||
|
||||
<table style="width: 100%; max-width: 40em;">
|
||||
<thead>
|
||||
|
@ -53,10 +53,6 @@ Below we've shown some examples of locations and their corresponding URLs:
|
|||
<td>content/sub/page.md</td>
|
||||
<td><a href="%base_url%?sub/page">?sub/page</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>content/theme.md</td>
|
||||
<td><a href="%base_url%?theme">?theme</a> (hidden in menu)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>content/a/very/long/url.md</td>
|
||||
<td>
|
||||
|
@ -71,28 +67,17 @@ If a file cannot be found, the file `content/404.md` will be shown. You can add
|
|||
`404.md` files to any directory. So, for example, if you wanted to use a special
|
||||
error page for your blog, you could simply create `content/blog/404.md`.
|
||||
|
||||
Pico strictly separates contents of your website (the Markdown files in your
|
||||
`content` directory) and how these contents should be displayed (the Twig
|
||||
templates in your `themes` directory). However, not every file in your `content`
|
||||
directory might actually be a distinct page. For example, some themes (including
|
||||
Pico's default theme) use some special "hidden" file to manage meta data (like
|
||||
`_meta.md` in Pico's sample contents). Some other themes use a `_footer.md` to
|
||||
represent the contents of the website's footer. The common point is the `_`: all
|
||||
files and directories prefixed by a `_` in your `content` directory are hidden.
|
||||
These pages can't be accessed from a web browser, Pico will show a 404 error
|
||||
page instead.
|
||||
|
||||
As a common practice, we recommend you to separate your contents and assets
|
||||
(like images, downloads, etc.). We even deny access to your `content` directory
|
||||
by default. If you want to use some assets (e.g. a image) in one of your content
|
||||
files, use Pico's `assets` folder. You can then access them in your Markdown
|
||||
using the <code>%assets_url%</code> placeholder, for example:
|
||||
<code>!\[Image Title\](%assets_url%/image.png)</code>
|
||||
files, you should create an `assets` folder in Pico's root directory and upload
|
||||
your assets there. You can then access them in your markdown using
|
||||
<code>%base_url%/assets/</code> for example:
|
||||
<code>!\[Image Title\](%base_url%/assets/image.png)</code>
|
||||
|
||||
### Text File Markup
|
||||
|
||||
Text files are marked up using [Markdown][] and [Markdown Extra][MarkdownExtra].
|
||||
They can also contain regular HTML.
|
||||
Text files are marked up using [Markdown][]. They can also contain regular HTML.
|
||||
|
||||
At the top of text files you can place a block comment and specify certain meta
|
||||
attributes of the page using [YAML][] (the "YAML header"). For example:
|
||||
|
@ -101,26 +86,13 @@ attributes of the page using [YAML][] (the "YAML header"). For example:
|
|||
Title: Welcome
|
||||
Description: This description will go in the meta description tag
|
||||
Author: Joe Bloggs
|
||||
Date: 2001-04-25
|
||||
Date: 2013/01/01
|
||||
Robots: noindex,nofollow
|
||||
Template: index
|
||||
---
|
||||
|
||||
These values will be contained in the `{{ meta }}` variable in themes (see
|
||||
below). Meta headers sometimes have a special meaning: For instance, Pico not
|
||||
only passes through the `Date` meta header, but rather evaluates it to really
|
||||
"understand" when this page was created. This comes into play when you want to
|
||||
sort your pages not just alphabetically, but by date. Another example is the
|
||||
`Template` meta header: It controls what Twig template Pico uses to display
|
||||
this page (e.g. if you add `Template: blog`, Pico uses `blog.twig`).
|
||||
|
||||
In an attempt to separate contents and styling, we recommend you to not use
|
||||
inline CSS in your Markdown files. You should rather add appropriate CSS
|
||||
classes to your theme. For example, you might want to add some CSS classes to
|
||||
your theme to rule how much of the available space a image should use (e.g.
|
||||
`img.small { width: 80%; }`). You can then use these CSS classes in your
|
||||
Markdown files, for example:
|
||||
<code>!\[Image Title\](%assets_url%/image.png) {.small}</code>
|
||||
These values will be contained in the `{{ meta }}` variable in themes
|
||||
(see below).
|
||||
|
||||
There are also certain variables that you can use in your text files:
|
||||
|
||||
|
@ -128,45 +100,45 @@ There are also certain variables that you can use in your text files:
|
|||
* <code>%base_url%</code> - The URL to your Pico site; internal links
|
||||
can be specified using <code>%base_url%?sub/page</code>
|
||||
* <code>%theme_url%</code> - The URL to the currently used theme
|
||||
* <code>%assets_url%</code> - The URL to Pico's `assets` directory
|
||||
* <code>%themes_url%</code> - The URL to Pico's `themes` directory;
|
||||
don't confuse this with <code>%theme_url%</code>
|
||||
* <code>%plugins_url%</code> - The URL to Pico's `plugins` directory
|
||||
* <code>%version%</code> - Pico's current version string (e.g. `2.0.0`)
|
||||
* <code>%meta.*%</code> - Access any meta variable of the current
|
||||
page, e.g. <code>%meta.author%</code> is replaced with `Joe Bloggs`
|
||||
* <code>%config.*%</code> - Access any scalar config variable,
|
||||
e.g. <code>%config.theme%</code> is replaced with `default`
|
||||
|
||||
### Blogging
|
||||
|
||||
Pico is not blogging software - but makes it very easy for you to use it as a
|
||||
blog. You can find many plugins out there implementing typical blogging
|
||||
blog. We even include a simple blog layout in our default template! However,
|
||||
you can find many plugins out there implementing typical blogging
|
||||
features like authentication, tagging, pagination and social plugins. See the
|
||||
below Plugins section for details.
|
||||
|
||||
If you want to use Pico as a blogging software, you probably want to do
|
||||
something like the following:
|
||||
|
||||
1. Put all your blog articles in a separate `blog` folder in your `content`
|
||||
directory. All these articles should have a `Date` meta header.
|
||||
2. Create a `blog.md` or `blog/index.md` in your `content` directory. Add
|
||||
`Template: blog-index` to the YAML header of this page. It will later show a
|
||||
list of all your blog articles (see step 3).
|
||||
3. Create the new Twig template `blog-index.twig` (the file name must match the
|
||||
`Template` meta header from Step 2) in your theme directory. This template
|
||||
probably isn't very different from your default `index.twig` (i.e. copy
|
||||
`index.twig`), it will create a list of all your blog articles. Add the
|
||||
following Twig snippet to `blog-index.twig` near `{{ content }}`:
|
||||
directory. All these articles should have both a `Date` and `Template` meta
|
||||
header, the latter with e.g. `blog-post` as value (see Step 2).
|
||||
2. Create a new Twig template called `blog-post.twig` (this must match the
|
||||
`Template` meta header from Step 1) in your theme directory. This template
|
||||
probably isn't very different from your default `index.twig`, it specifies
|
||||
how your article pages will look like.
|
||||
3. Create a `blog.md` in your `content` folder and set its `Template` meta
|
||||
header to e.g. `blog`. Also create a `blog.twig` in your theme directory.
|
||||
This template will show a list of your articles, so you probably want to
|
||||
do something like this:
|
||||
```
|
||||
{% for page in pages("blog")|sort_by("time")|reverse if not page.hidden %}
|
||||
<div class="post">
|
||||
<h3><a href="{{ page.url }}">{{ page.title }}</a></h3>
|
||||
<p class="date">{{ page.date_formatted }}</p>
|
||||
<p class="excerpt">{{ page.description }}</p>
|
||||
</div>
|
||||
{% for page in pages|sort_by("time")|reverse %}
|
||||
{% if page.id starts with "blog/" %}
|
||||
<div class="post">
|
||||
<h3><a href="{{ page.url }}">{{ page.title }}</a></h3>
|
||||
<p class="date">{{ page.date_formatted }}</p>
|
||||
<p class="excerpt">{{ page.description }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
```
|
||||
4. Make sure to exclude the blog articles from your page navigation. You can
|
||||
achieve this by adding `{% if not page starts with "blog/" %}...{% endif %}`
|
||||
to the navigation loop (`{% for page in pages %}...{% endfor %}`) in your
|
||||
themes `index.twig`.
|
||||
|
||||
## Customization
|
||||
|
||||
|
@ -182,326 +154,153 @@ details.
|
|||
|
||||
### Themes
|
||||
|
||||
You can create themes for your Pico installation in the `themes` folder. Pico
|
||||
uses [Twig][] for template rendering. You can select your theme by setting the
|
||||
`theme` option in `config/config.yml` to the name of your theme folder.
|
||||
You can create themes for your Pico installation in the `themes` folder. Check
|
||||
out the default theme for an example. Pico uses [Twig][] for template
|
||||
rendering. You can select your theme by setting the `$config['theme']` option
|
||||
in `config/config.php` to the name of your theme folder.
|
||||
|
||||
[Pico's default theme][PicoTheme] isn't really intended to be used for a
|
||||
productive website, it's rather a starting point for creating your own theme.
|
||||
If the default theme isn't sufficient for you, and you don't want to create
|
||||
your own theme, you can use one of the great themes third-party developers and
|
||||
designers created in the past. As with plugins, you can find themes on [our website][OfficialThemes].
|
||||
All themes must include an `index.twig` (or `index.html`) file to define the
|
||||
HTML structure of the theme. Below are the Twig variables that are available
|
||||
to use in your theme. Please note that paths (e.g. `{{ base_dir }}`) and URLs
|
||||
(e.g. `{{ base_url }}`) don't have a trailing slash.
|
||||
|
||||
All themes must include an `index.twig` file to define the HTML structure of
|
||||
the theme, and a `pico-theme.yml` to set the necessary config parameters. Just
|
||||
refer to Pico's default theme as an example. You can use different templates
|
||||
for different content files by specifying the `Template` meta header. Simply
|
||||
add e.g. `Template: blog` to the YAML header of a content file and Pico will
|
||||
use the `blog.twig` template in your theme folder to display the page.
|
||||
|
||||
Below are the Twig variables that are available to use in themes. Please note
|
||||
that URLs (e.g. `{{ base_url }}`) never include a trailing slash.
|
||||
|
||||
* `{{ site_title }}` - Shortcut to the site title (see `config/config.yml`)
|
||||
* `{{ config }}` - Contains the values you set in `config/config.yml`
|
||||
* `{{ config }}` - Contains the values you set in `config/config.php`
|
||||
(e.g. `{{ config.theme }}` becomes `default`)
|
||||
* `{{ base_url }}` - The URL to your Pico site; use Twig's `link` filter to
|
||||
* `{{ base_dir }}` - The path to your Pico root directory
|
||||
* `{{ base_url }}` - The URL to your Pico site; use Twigs `link` filter to
|
||||
specify internal links (e.g. `{{ "sub/page"|link }}`),
|
||||
this guarantees that your link works whether URL rewriting
|
||||
is enabled or not
|
||||
* `{{ theme_dir }}` - The path to the currently active theme
|
||||
* `{{ theme_url }}` - The URL to the currently active theme
|
||||
* `{{ assets_url }}` - The URL to Pico's `assets` directory
|
||||
* `{{ themes_url }}` - The URL to Pico's `themes` directory; don't confuse this
|
||||
with `{{ theme_url }}`
|
||||
* `{{ plugins_url }}` - The URL to Pico's `plugins` directory
|
||||
* `{{ version }}` - Pico's current version string (e.g. `%version%`)
|
||||
* `{{ meta }}` - Contains the meta values of the current page
|
||||
* `{{ meta.title }}` - The `Title` YAML header
|
||||
* `{{ meta.description }}` - The `Description` YAML header
|
||||
* `{{ meta.author }}` - The `Author` YAML header
|
||||
* `{{ meta.date }}` - The `Date` YAML header
|
||||
* `{{ meta.date_formatted }}` - The formatted date of the page as specified
|
||||
by the `date_format` parameter in your
|
||||
`config/config.yml`
|
||||
* `{{ meta.time }}` - The [Unix timestamp][UnixTimestamp] derived from the
|
||||
`Date` YAML header
|
||||
* `{{ meta.robots }}` - The `Robots` YAML header
|
||||
* `{{ rewrite_url }}` - A boolean flag indicating enabled/disabled URL rewriting
|
||||
* `{{ site_title }}` - Shortcut to the site title (see `config/config.php`)
|
||||
* `{{ meta }}` - Contains the meta values from the current page
|
||||
* `{{ meta.title }}`
|
||||
* `{{ meta.description }}`
|
||||
* `{{ meta.author }}`
|
||||
* `{{ meta.date }}`
|
||||
* `{{ meta.date_formatted }}`
|
||||
* `{{ meta.time }}`
|
||||
* `{{ meta.robots }}`
|
||||
* ...
|
||||
* `{{ content }}` - The content of the current page after it has been processed
|
||||
through Markdown
|
||||
* `{{ previous_page }}` - The data of the previous page, relative to
|
||||
`current_page`
|
||||
* `{{ current_page }}` - The data of the current page; refer to the "Pages"
|
||||
section below for details
|
||||
* `{{ next_page }}` - The data of the next page, relative to `current_page`
|
||||
* `{{ content }}` - The content of the current page
|
||||
(after it has been processed through Markdown)
|
||||
* `{{ pages }}` - A collection of all the content pages in your site
|
||||
* `{{ page.id }}` - The relative path to the content file (unique ID)
|
||||
* `{{ page.url }}` - The URL to the page
|
||||
* `{{ page.title }}` - The title of the page (YAML header)
|
||||
* `{{ page.description }}` - The description of the page (YAML header)
|
||||
* `{{ page.author }}` - The author of the page (YAML header)
|
||||
* `{{ page.time }}` - The timestamp derived from the `Date` header
|
||||
* `{{ page.date }}` - The date of the page (YAML header)
|
||||
* `{{ page.date_formatted }}` - The formatted date of the page
|
||||
* `{{ page.raw_content }}` - The raw, not yet parsed contents of the page;
|
||||
use Twigs `content` filter to get the parsed
|
||||
contents of a page by passing its unique ID
|
||||
(e.g. `{{ "sub/page"|content }}`)
|
||||
* `{{ page.meta }}`- The meta values of the page
|
||||
* `{{ prev_page }}` - The data of the previous page (relative to `current_page`)
|
||||
* `{{ current_page }}` - The data of the current page
|
||||
* `{{ next_page }}` - The data of the next page (relative to `current_page`)
|
||||
* `{{ is_front_page }}` - A boolean flag for the front page
|
||||
|
||||
To call assets from your theme, use `{{ theme_url }}`. For instance, to include
|
||||
the CSS file `themes/my_theme/example.css`, add
|
||||
`<link rel="stylesheet" href="{{ theme_url }}/example.css" type="text/css" />`
|
||||
to your `index.twig`. This works for arbitrary files in your theme's folder,
|
||||
including images and JavaScript files.
|
||||
Pages can be used like the following:
|
||||
|
||||
Please note that Twig escapes HTML in all strings before outputting them. So
|
||||
for example, if you add `headline: My <strong>favorite</strong> color` to the
|
||||
YAML header of a page and output it using `{{ meta.headline }}`, you'll end up
|
||||
seeing `My <strong>favorite</strong> color` - yes, including the markup! To
|
||||
actually get it parsed, you must use `{{ meta.headline|raw }}` (resulting in
|
||||
the expected <code>My **favorite** color</code>). Notable exceptions to this
|
||||
are Pico's `content` variable (e.g. `{{ content }}`), Pico's `content` filter
|
||||
(e.g. `{{ "sub/page"|content }}`), and Pico's `markdown` filter, they all are
|
||||
marked as HTML safe.
|
||||
|
||||
#### Dealing with pages
|
||||
|
||||
There are several ways to access Pico's pages list. You can access the current
|
||||
page's data using the `current_page` variable, or use the `prev_page` and/or
|
||||
`next_page` variables to access the respective previous/next page in Pico's
|
||||
pages list. But more importantly there's the `pages()` function. No matter how
|
||||
you access a page, it will always consist of the following data:
|
||||
|
||||
* `{{ id }}` - The relative path to the content file (unique ID)
|
||||
* `{{ url }}` - The URL to the page
|
||||
* `{{ title }}` - The title of the page (`Title` YAML header)
|
||||
* `{{ description }}` - The description of the page (`Description` YAML header)
|
||||
* `{{ author }}` - The author of the page (`Author` YAML header)
|
||||
* `{{ date }}` - The date of the page (`Date` YAML header)
|
||||
* `{{ date_formatted }}` - The formatted date of the page as specified by the
|
||||
`date_format` parameter in your `config/config.yml`
|
||||
* `{{ time }}` - The [Unix timestamp][UnixTimestamp] derived from the page's
|
||||
date
|
||||
* `{{ raw_content }}` - The raw, not yet parsed contents of the page; use the
|
||||
filter to get the parsed contents of a page by passing
|
||||
its unique ID (e.g. `{{ "sub/page"|content }}`)
|
||||
* `{{ meta }}` - The meta values of the page (see global `{{ meta }}` above)
|
||||
* `{{ prev_page }}` - The data of the respective previous page
|
||||
* `{{ next_page }}` - The data of the respective next page
|
||||
* `{{ tree_node }}` - The page's node in Pico's page tree; check out Pico's
|
||||
[page tree documentation][FeaturesPageTree] for details
|
||||
|
||||
Pico's `pages()` function is the best way to access all of your site's pages.
|
||||
It uses Pico's page tree to easily traverse a subset of Pico's pages list. It
|
||||
allows you to filter pages and to build recursive menus (like dropdowns). By
|
||||
default, `pages()` returns a list of all main pages (e.g. `content/page.md` and
|
||||
`content/sub/index.md`, but not `content/sub/page.md` or `content/index.md`).
|
||||
If you want to return all pages below a specific folder (e.g. `content/blog/`),
|
||||
pass the folder name as first parameter to the function (e.g. `pages("blog")`).
|
||||
Naturally you can also pass variables to the function. For example, to return a
|
||||
list of all child pages of the current page, use `pages(current_page.id)`.
|
||||
Check out the following code snippet:
|
||||
|
||||
<section class="articles">
|
||||
{% for page in pages(current_page.id) if not page.hidden %}
|
||||
<article>
|
||||
<h2><a href="{{ page.url }}">{{ page.title }}</a></h2>
|
||||
{{ page.id|content }}
|
||||
</article>
|
||||
<ul class="nav">
|
||||
{% for page in pages %}
|
||||
<li><a href="{{ page.url }}">{{ page.title }}</a></li>
|
||||
{% endfor %}
|
||||
</section>
|
||||
</ul>
|
||||
|
||||
The `pages()` function is very powerful and also allows you to return not just
|
||||
a page's child pages by passing the `depth` and `depthOffset` params. For
|
||||
example, if you pass `pages(depthOffset=-1)`, the list will also include Pico's
|
||||
main index page (i.e. `content/index.md`). This one is commonly used to create
|
||||
a theme's main navigation. If you want to learn more, head over to Pico's
|
||||
complete [`pages()` function documentation][FeaturesPagesFunction].
|
||||
Additional to Twigs extensive list of filters, functions and tags, Pico also
|
||||
provides some useful additional filters to make theming easier. You can parse
|
||||
any Markdown string to HTML using the `markdown` filter. Arrays can be sorted
|
||||
by one of its keys or a arbitrary deep sub-key using the `sort_by` filter
|
||||
(e.g. `{% for page in pages|sort_by("meta:nav"|split(":")) %}...{% endfor %}`
|
||||
iterates through all pages, ordered by the `nav` meta header; please note the
|
||||
`"meta:nav"|split(":")` part of the example, which passes `['meta', 'nav']` to
|
||||
the filter describing a key path). You can return all values of a given key or
|
||||
key path of an array using the `map` filter (e.g. `{{ pages|map("title") }}`
|
||||
returns all page titles).
|
||||
|
||||
If you want to access the data of a particular page, use Pico's `pages`
|
||||
variable. Just take `content/_meta.md` in Pico's sample contents for an
|
||||
example: `content/_meta.md` contains some meta data you might want to use in
|
||||
your theme. If you want to output the page's `tagline` meta value, use
|
||||
`{{ pages["_meta"].meta.logo }}`. Don't ever try to use Pico's `pages` variable
|
||||
as an replacement for Pico's `pages()` function. Its usage looks very similar,
|
||||
it will kinda work and you might even see it being used in old themes, but be
|
||||
warned: It slows down Pico. Always use Pico's `pages()` function when iterating
|
||||
Pico's page list (e.g. `{% for page in pages() %}…{% endfor %}`).
|
||||
You can use different templates for different content files by specifying the
|
||||
`Template` meta header. Simply add e.g. `Template: blog-post` to a content file
|
||||
and Pico will use the `blog-post.twig` file in your theme folder to render
|
||||
the page.
|
||||
|
||||
#### Twig filters and functions
|
||||
|
||||
Additional to [Twig][]'s extensive list of filters, functions and tags, Pico
|
||||
also provides some useful additional filters and functions to make theming
|
||||
even easier.
|
||||
|
||||
* Pass the unique ID of a page to the `link` filter to return the page's URL
|
||||
(e.g. `{{ "sub/page"|link }}` gets `%base_url%?sub/page`).
|
||||
* You can replace URL placeholders (like <code>%base_url%</code>) in
|
||||
arbitrary strings using the `url` filter. This is helpful together with meta
|
||||
variables, e.g. if you add <code>image: %assets_url%/stock.jpg</code>
|
||||
to the YAML header of a page, `{{ meta.image|url }}` will return
|
||||
`%assets_url%/stock.jpg`.
|
||||
* To get the parsed contents of a page, pass its unique ID to the `content`
|
||||
filter (e.g. `{{ "sub/page"|content }}`).
|
||||
* You can parse any Markdown string using the `markdown` filter. For example,
|
||||
you might use Markdown in the `description` meta variable and later parse it
|
||||
in your theme using `{{ meta.description|markdown }}`. You can also pass meta
|
||||
data as parameter to replace <code>%meta.*%</code> placeholders
|
||||
(e.g. `{{ "Written by *%meta.author%*"|markdown(meta) }}` yields "Written by
|
||||
*John Doe*"). However, please note that all contents will be wrapped inside
|
||||
HTML paragraph elements (i.e. `<p>…</p>`). If you want to parse just a single
|
||||
line of Markdown markup, pass the `singleLine` param to the `markdown` filter
|
||||
(e.g. `{{ "This really is a *single* line"|markdown(singleLine=true) }}`).
|
||||
* Arrays can be sorted by one of its keys using the `sort_by` filter
|
||||
(e.g. `{% for page in pages|sort_by([ 'meta', 'nav' ]) %}...{% endfor %}`
|
||||
iterates through all pages, ordered by the `nav` meta header; please note the
|
||||
`[ 'meta', 'nav' ]` part of the example, it instructs Pico to sort by
|
||||
`page.meta.nav`). Items which couldn't be sorted are moved to the bottom of
|
||||
the array; you can specify `bottom` (move items to bottom; default), `top`
|
||||
(move items to top), `keep` (keep original order) or `remove` (remove items)
|
||||
as second parameter to change this behavior.
|
||||
* You can return all values of a given array key using the `map` filter
|
||||
(e.g. `{{ pages|map("title") }}` returns all page titles).
|
||||
* Use the `url_param` and `form_param` Twig functions to access HTTP GET (i.e.
|
||||
a URL's query string like `?some-variable=my-value`) and HTTP POST (i.e. data
|
||||
of a submitted form) parameters. This allows you to implement things like
|
||||
pagination, tags and categories, dynamic pages, and even more - with pure
|
||||
Twig! Simply head over to our [introductory page for accessing HTTP
|
||||
parameters][FeaturesHttpParams] for details.
|
||||
You don't have to create your own theme if Pico's default theme isn't
|
||||
sufficient for you, you can use one of the great themes third-party developers
|
||||
and designers created in the past. As with plugins, you can find themes in
|
||||
[our Wiki][WikiThemes].
|
||||
|
||||
### Plugins
|
||||
|
||||
#### Plugins for users
|
||||
|
||||
Officially tested plugins can be found at http://picocms.org/plugins/, but
|
||||
there are many awesome third-party plugins out there! A good start point for
|
||||
discovery is [our Wiki][WikiPlugins].
|
||||
Officially tested plugins can be found at http://picocms.org/customization/,
|
||||
but there are many awesome third-party plugins out there! A good start point
|
||||
for discovery is [our Wiki][WikiPlugins].
|
||||
|
||||
Pico makes it very easy for you to add new features to your website using
|
||||
plugins. Just like Pico, you can install plugins either using [Composer][]
|
||||
(e.g. `composer require phrozenbyte/pico-file-prefixes`), or manually by
|
||||
uploading the plugin's file (just for small plugins consisting of a single file,
|
||||
e.g. `PicoFilePrefixes.php`) or directory (e.g. `PicoFilePrefixes`) to your
|
||||
`plugins` directory. We always recommend you to use Composer whenever possible,
|
||||
because it makes updating both Pico and your plugins way easier. Anyway,
|
||||
depending on the plugin you want to install, you may have to go through some
|
||||
more steps (e.g. specifying config variables) to make the plugin work. Thus you
|
||||
should always check out the plugin's docs or `README.md` file to learn the
|
||||
necessary steps.
|
||||
Pico makes it very easy for you to add new features to your website. Simply
|
||||
upload the files of the plugin to the `plugins/` directory and you're done.
|
||||
Depending on the plugin you've installed, you may have to go through some more
|
||||
steps (e.g. specifying config variables), the plugin docs or `README` file will
|
||||
explain what to do.
|
||||
|
||||
Plugins which were written to work with Pico 1.0 and later can be enabled and
|
||||
disabled through your `config/config.yml`. If you want to e.g. disable the
|
||||
`PicoDeprecated` plugin, add the following line to your `config/config.yml`:
|
||||
`PicoDeprecated.enabled: false`. To force the plugin to be enabled, replace
|
||||
`false` by `true`.
|
||||
Plugins which were written to work with Pico 1.0 can be enabled and disabled
|
||||
through your `config/config.php`. If you want to e.g. disable the `PicoExcerpt`
|
||||
plugin, add the following line to your `config/config.php`:
|
||||
`$config['PicoExcerpt.enabled'] = false;`. To force the plugin to be enabled
|
||||
replace `false` with `true`.
|
||||
|
||||
#### Plugins for developers
|
||||
|
||||
You're a plugin developer? We love you guys! You can find tons of information
|
||||
about how to develop plugins at http://picocms.org/development/. If you've
|
||||
developed a plugin before and want to upgrade it to Pico 2.0, refer to the
|
||||
developed a plugin for Pico 0.9 or older, you probably want to upgrade it
|
||||
to the brand new plugin system introduced with Pico 1.0. Please refer to the
|
||||
[upgrade section of the docs][PluginUpgrade].
|
||||
|
||||
## Config
|
||||
|
||||
Configuring Pico really is stupidly simple: Just create a `config/config.yml`
|
||||
to override the default Pico settings (and add your own custom settings). Take
|
||||
a look at the `config/config.yml.template` for a brief overview of the
|
||||
available settings and their defaults. To override a setting, simply copy the
|
||||
line from `config/config.yml.template` to `config/config.yml` and set your
|
||||
custom value.
|
||||
|
||||
But we didn't stop there. Rather than having just a single config file, you can
|
||||
use a arbitrary number of config files. Simply create a `.yml` file in Pico's
|
||||
`config` dir and you're good to go. This allows you to add some structure to
|
||||
your config, like a separate config file for your theme (`config/my_theme.yml`).
|
||||
|
||||
Please note that Pico loads config files in a special way you should be aware
|
||||
of. First of all it loads the main config file `config/config.yml`, and then
|
||||
any other `*.yml` file in Pico's `config` dir in alphabetical order. The file
|
||||
order is crucial: Config values which have been set already, cannot be
|
||||
overwritten by a succeeding file. For example, if you set `site_title: Pico` in
|
||||
`config/a.yml` and `site_title: My awesome site!` in `config/b.yml`, your site
|
||||
title will be "Pico".
|
||||
|
||||
Since YAML files are plain text files, users might read your Pico config by
|
||||
navigating to `%base_url%/config/config.yml`. This is no problem in the first
|
||||
place, but might get a problem if you use plugins that require you to store
|
||||
security-relevant data in the config (like credentials). Thus you should
|
||||
*always* make sure to configure your webserver to deny access to Pico's
|
||||
`config` dir. Just refer to the "URL Rewriting" section below. By following the
|
||||
instructions, you will not just enable URL rewriting, but also deny access to
|
||||
Pico's `config` dir.
|
||||
You can override the default Pico settings (and add your own custom settings)
|
||||
by editing `config/config.php` in the Pico directory. For a brief overview of
|
||||
the available settings and their defaults see `config/config.php.template`. To
|
||||
override a setting, copy `config/config.php.template` to `config/config.php`,
|
||||
uncomment the setting and set your custom value.
|
||||
|
||||
### URL Rewriting
|
||||
|
||||
Pico's default URLs (e.g. %base_url%/?sub/page) already are very user-friendly.
|
||||
Additionally, Pico offers you a URL rewrite feature to make URLs even more
|
||||
user-friendly (e.g. %base_url%/sub/page). Below you'll find some basic info
|
||||
about how to configure your webserver proberly to enable URL rewriting.
|
||||
|
||||
#### Apache
|
||||
user-friendly (e.g. %base_url%/sub/page).
|
||||
|
||||
If you're using the Apache web server, URL rewriting probably already is
|
||||
enabled - try it yourself, click on the [second URL](%base_url%/sub/page). If
|
||||
URL rewriting doesn't work (you're getting `404 Not Found` error messages from
|
||||
Apache), please make sure to enable the [`mod_rewrite` module][ModRewrite] and
|
||||
to enable `.htaccess` overrides. You might have to set the
|
||||
[`AllowOverride` directive][AllowOverride] to `AllowOverride All` in your
|
||||
virtual host config file or global `httpd.conf`/`apache.conf`. Assuming
|
||||
rewritten URLs work, but Pico still shows no rewritten URLs, force URL
|
||||
rewriting by setting `rewrite_url: true` in your `config/config.yml`. If you
|
||||
rather get a `500 Internal Server Error` no matter what you do, try removing
|
||||
the `Options` directive from Pico's `.htaccess` file (it's the last line).
|
||||
you get an error message from your web server, please make sure to enable the
|
||||
[`mod_rewrite` module][ModRewrite]. Assuming the second URL works, but Pico
|
||||
still shows no rewritten URLs, force URL rewriting by setting
|
||||
`$config['rewrite_url'] = true;` in your `config/config.php`.
|
||||
|
||||
#### Nginx
|
||||
If you're using Nginx, you can use the following configuration to enable
|
||||
URL rewriting. Don't forget to adjust the path (`/pico/`; line `1` and `4`)
|
||||
to match your installation directory. You can then enable URL rewriting by
|
||||
setting `$config['rewrite_url'] = true;` in your `config/config.php`.
|
||||
|
||||
If you're using Nginx, you can use the following config to enable URL rewriting
|
||||
(lines `5` to `8`) and denying access to Pico's internal files (lines `1` to
|
||||
`3`). You'll need to adjust the path (`/pico` on lines `1`, `2`, `5` and `7`)
|
||||
to match your installation directory. Additionally, you'll need to enable URL
|
||||
rewriting by setting `rewrite_url: true` in your `config/config.yml`. The Nginx
|
||||
config should provide the *bare minimum* you need for Pico. Nginx is a very
|
||||
extensive subject. If you have any trouble, please read through our
|
||||
[Nginx config docs][NginxConfig].
|
||||
|
||||
```
|
||||
location ~ ^/pico/((config|content|vendor|composer\.(json|lock|phar))(/|$)|(.+/)?\.(?!well-known(/|$))) {
|
||||
try_files /pico/index.php$is_args$args =404;
|
||||
}
|
||||
|
||||
location /pico/ {
|
||||
index index.php;
|
||||
try_files $uri $uri/ /pico/index.php$is_args$args;
|
||||
}
|
||||
```
|
||||
|
||||
#### Lighttpd
|
||||
|
||||
Pico runs smoothly on Lighttpd. You can use the following config to enable URL
|
||||
rewriting (lines `6` to `9`) and denying access to Pico's internal files (lines
|
||||
`1` to `4`). Make sure to adjust the path (`/pico` on lines `2`, `3` and `7`)
|
||||
to match your installation directory, and let Pico know about available URL
|
||||
rewriting by setting `rewrite_url: true` in your `config/config.yml`. The
|
||||
config below should provide the *bare minimum* you need for Pico.
|
||||
|
||||
```
|
||||
url.rewrite-once = (
|
||||
"^/pico/(config|content|vendor|composer\.(json|lock|phar))(/|$)" => "/pico/index.php",
|
||||
"^/pico/(.+/)?\.(?!well-known(/|$))" => "/pico/index.php"
|
||||
)
|
||||
|
||||
url.rewrite-if-not-file = (
|
||||
"^/pico(/|$)" => "/pico/index.php"
|
||||
)
|
||||
```
|
||||
location /pico/ {
|
||||
index index.php;
|
||||
try_files $uri $uri/ /pico/?$uri&$args;
|
||||
}
|
||||
|
||||
## Documentation
|
||||
|
||||
For more help have a look at the Pico documentation at https://picocms.org/docs/.
|
||||
For more help have a look at the Pico documentation at http://picocms.org/docs.
|
||||
|
||||
[Pico]: https://picocms.org/
|
||||
[PicoTheme]: https://github.com/picocms/pico-theme
|
||||
[SampleContents]: https://github.com/picocms/Pico/tree/master/content-sample
|
||||
[Markdown]: https://daringfireball.net/projects/markdown/syntax
|
||||
[MarkdownExtra]: https://michelf.ca/projects/php-markdown/extra/
|
||||
[Markdown]: http://daringfireball.net/projects/markdown/syntax
|
||||
[YAML]: https://en.wikipedia.org/wiki/YAML
|
||||
[Twig]: https://twig.symfony.com/doc/
|
||||
[UnixTimestamp]: https://en.wikipedia.org/wiki/Unix_time
|
||||
[Composer]: https://getcomposer.org/
|
||||
[FeaturesHttpParams]: https://picocms.org/in-depth/features/http-params/
|
||||
[FeaturesPageTree]: https://picocms.org/in-depth/features/page-tree/
|
||||
[FeaturesPagesFunction]: https://picocms.org/in-depth/features/pages-function/
|
||||
[Twig]: http://twig.sensiolabs.org/documentation
|
||||
[WikiThemes]: https://github.com/picocms/Pico/wiki/Pico-Themes
|
||||
[WikiPlugins]: https://github.com/picocms/Pico/wiki/Pico-Plugins
|
||||
[OfficialThemes]: https://picocms.org/themes/
|
||||
[PluginUpgrade]: https://picocms.org/development/#migrating-plugins
|
||||
[PluginUpgrade]: http://picocms.org/development/#upgrade
|
||||
[ModRewrite]: https://httpd.apache.org/docs/current/mod/mod_rewrite.html
|
||||
[AllowOverride]: https://httpd.apache.org/docs/current/mod/core.html#allowoverride
|
||||
[NginxConfig]: https://picocms.org/in-depth/nginx/
|
||||
|
|
|
@ -1,195 +0,0 @@
|
|||
---
|
||||
title: Theme Styling Test
|
||||
hidden: true
|
||||
---
|
||||
|
||||
Theme Styling Test
|
||||
==================
|
||||
|
||||
This is `theme.md` in Pico's content directory. This page doesn't show up in the website's menu due to `hidden: true` in the page's YAML header. The purpose of this page is to aid theme development - below you'll find basically every format that is possible with Markdown. If you develop a theme, you should make sure that all examples below show decent.
|
||||
|
||||
Text
|
||||
----
|
||||
|
||||
**Lorem ipsum dolor sit amet,** consectetur adipisici elit, *sed eiusmod tempor* incidunt ut labore et dolore magna aliqua.[^1] ~~Ut enim ad minim veniam,~~ quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat.[^2] [Quis aute iure reprehenderit][Link] in voluptate velit esse cillum dolore eu fugiat nulla pariatur. `Excepteur` sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
[![Pico Logo](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MDAiIGhlaWdodD0iNDAwIiB2aWV3Qm94PSIwIDAgNDAwIDQwMCI+PHBhdGggZD0ibTI5OC40IDE5NC43cTAtMTQuMTUtLjgtMzEuMmwtLjg1LTE0LjI1aC01MS4wNXY4OS45NWw4IDEuMXE5LjYgMS4wNSAxNy42IDEuMDUgNy45NSAwIDE3LjUtMS4wNSA0LjgtLjU1IDcuOTUtMS4xIDEuNjUtMjIuMiAxLjY1LTQ0LjVtLTY5Ljc1LTQ1LjhoLTQ5LjN2MTgyLjQ1bDcuNy44NXE5LjMuOCAxNyAuOCAxMi4zIDAgMjQuNi0xLjY1eiIgZmlsbD0iIzJlYWU5YiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTM4Ljg1IC00MC45NSkiLz48L3N2Zz4K)](%base_url% "Pico Logo") {.image .small .float-right}
|
||||
|
||||
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
||||
|
||||
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
|
||||
|
||||
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
|
||||
|
||||
Headings
|
||||
--------
|
||||
|
||||
# h1
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
## h2
|
||||
|
||||
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
||||
|
||||
### h3
|
||||
|
||||
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
|
||||
|
||||
#### h4
|
||||
|
||||
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
|
||||
|
||||
##### h5
|
||||
|
||||
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.
|
||||
|
||||
###### h6
|
||||
|
||||
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
|
||||
|
||||
Horizontal line
|
||||
---------------
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
---
|
||||
|
||||
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
||||
|
||||
List
|
||||
----
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
* Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
|
||||
1. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
||||
2. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
|
||||
3. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
|
||||
* Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum.
|
||||
- Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
||||
- Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
|
||||
1. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.
|
||||
2. At vero eos et accusam et justo duo dolores et ea rebum.
|
||||
1. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet
|
||||
2. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
|
||||
3. At vero eos et accusam et justo duo dolores et ea rebum.
|
||||
|
||||
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.
|
||||
|
||||
Definition list
|
||||
---------------
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Duis autem
|
||||
: Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
|
||||
|
||||
Lorem ipsum dolor sit amet
|
||||
: Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
||||
|
||||
Ut wisi enim ad minim veniam
|
||||
: Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
|
||||
: Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
|
||||
|
||||
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
|
||||
|
||||
Blockquote
|
||||
----------
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
> Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse
|
||||
> molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero
|
||||
> eros et accumsan et iusto odio dignissim qui blandit praesent luptatum
|
||||
> zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum
|
||||
> dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod
|
||||
> tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
||||
>
|
||||
> > Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit
|
||||
> > lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure
|
||||
> > dolor in hendrerit in vulputate velit esse molestie consequat, vel illum
|
||||
> > dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
|
||||
> > dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te
|
||||
> > feugait nulla facilisi.
|
||||
>
|
||||
> Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet
|
||||
> doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet,
|
||||
> consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
|
||||
> laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam,
|
||||
> quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex
|
||||
> ea commodo consequat.
|
||||
|
||||
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.
|
||||
|
||||
Code block
|
||||
----------
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
```
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>This is a title</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Hello world!</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
||||
|
||||
Table
|
||||
-----
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Lorem ipsum | Duis autem vel eum | Ut wisi enim ad minim veniam
|
||||
----------- | ------------------ | ----------------------------
|
||||
**Duis autem vel eum iriure dolor** in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. | *Lorem ipsum dolor sit amet,* consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. | ~~Ut wisi enim ad minim veniam,~~ quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
|
||||
[Duis autem vel eum iriure dolor][Link] in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. | `Nam liber tempor` cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. | Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
||||
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. | | Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.
|
||||
|
||||
At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
|
||||
|
||||
Forms
|
||||
-----
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
<fieldset>
|
||||
<legend>Legend</legend>
|
||||
<label>Label</label>
|
||||
<input type="checkbox"/>
|
||||
<input type="checkbox" checked="checked"/>
|
||||
<input type="radio"/>
|
||||
<input type="radio" checked="checked"/><br/>
|
||||
<input type="text" value="Lorem ipsum"/>
|
||||
<input type="password" value="Ut enim"/><br/>
|
||||
<input type="submit" value="Submit"/>
|
||||
<input type="reset" value="Reset"/>
|
||||
<input type="button" value="Button (Input)"/>
|
||||
<button>Button</button><br/>
|
||||
<textarea>Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua<br/>.</textarea><br/>
|
||||
<select>
|
||||
<option>Lorem ipsum</option>
|
||||
<option>Ut enim</option>
|
||||
</select><br/>
|
||||
<select multiple="multiple">
|
||||
<option>Lorem ipsum</option>
|
||||
<option selected="selected">Ut enim</option>
|
||||
<option>Quis aute iure</option>
|
||||
<option>Excepteur sint</option>
|
||||
</select>
|
||||
</fieldset>
|
||||
|
||||
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
||||
|
||||
*[Lorem ipsum]: Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua.
|
||||
|
||||
[Link]: %base_url% "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat."
|
||||
|
||||
[^1]: Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
|
||||
[^2]: Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
2
content/.gitignore
vendored
2
content/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
# This directory is meant to be empty
|
||||
*
|
20
index.php
20
index.php
|
@ -1,28 +1,14 @@
|
|||
<?php // @codingStandardsIgnoreFile
|
||||
/**
|
||||
* This file is part of Pico. It's copyrighted by the contributors recorded
|
||||
* in the version control history of the file, available from the following
|
||||
* original location:
|
||||
*
|
||||
* <https://github.com/picocms/Pico/blob/master/index.php>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* License-Filename: LICENSE
|
||||
*/
|
||||
|
||||
// load dependencies
|
||||
if (is_file(__DIR__ . '/vendor/autoload.php')) {
|
||||
if(is_file(__DIR__ . '/vendor/autoload.php')) {
|
||||
// composer root package
|
||||
require_once(__DIR__ . '/vendor/autoload.php');
|
||||
} elseif (is_file(__DIR__ . '/../../../vendor/autoload.php')) {
|
||||
} elseif(is_file(__DIR__ . '/../../../vendor/autoload.php')) {
|
||||
// composer dependency package
|
||||
require_once(__DIR__ . '/../../../vendor/autoload.php');
|
||||
} else {
|
||||
die(
|
||||
"Cannot find 'vendor/autoload.php'. If you're using a composer-based Pico install, run `composer install`. "
|
||||
. "If you're rather trying to use one of Pico's pre-built release packages, make sure to download Pico's "
|
||||
. "latest release package named 'pico-release-v*.tar.gz' (don't download a source code package)."
|
||||
);
|
||||
die("Cannot find `vendor/autoload.php`. Run `composer install`.");
|
||||
}
|
||||
|
||||
// instance Pico
|
||||
|
|
|
@ -1,25 +1,9 @@
|
|||
<?php // @codingStandardsIgnoreFile
|
||||
/**
|
||||
* This file is part of Pico. It's copyrighted by the contributors recorded
|
||||
* in the version control history of the file, available from the following
|
||||
* original location:
|
||||
*
|
||||
* <https://github.com/picocms/Pico/blob/master/index.php.dist>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* License-Filename: LICENSE
|
||||
*/
|
||||
|
||||
// check PHP platform requirements
|
||||
if (PHP_VERSION_ID < 50306) {
|
||||
// check PHP version
|
||||
if (version_compare(PHP_VERSION, '5.3.6', '<')) {
|
||||
die('Pico requires PHP 5.3.6 or above to run');
|
||||
}
|
||||
if (!extension_loaded('dom')) {
|
||||
die("Pico requires the PHP extension 'dom' to run");
|
||||
}
|
||||
if (!extension_loaded('mbstring')) {
|
||||
die("Pico requires the PHP extension 'mbstring' to run");
|
||||
}
|
||||
|
||||
// load dependencies
|
||||
require_once(__DIR__ . '/vendor/autoload.php');
|
||||
|
@ -32,8 +16,5 @@ $pico = new Pico(
|
|||
'themes/' // themes dir
|
||||
);
|
||||
|
||||
// override configuration?
|
||||
//$pico->setConfig(array());
|
||||
|
||||
// run application
|
||||
echo $pico->run();
|
||||
|
|
|
@ -1,27 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of Pico. It's copyrighted by the contributors recorded
|
||||
* in the version control history of the file, available from the following
|
||||
* original location:
|
||||
*
|
||||
* <https://github.com/picocms/Pico/blob/master/lib/AbstractPicoPlugin.php>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* License-Filename: LICENSE
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract class to extend from when implementing a Pico plugin
|
||||
*
|
||||
* Please refer to {@see PicoPluginInterface} for more information about how
|
||||
* to develop a plugin for Pico.
|
||||
*
|
||||
* @see PicoPluginInterface
|
||||
*
|
||||
* @author Daniel Rudolf
|
||||
* @link http://picocms.org
|
||||
* @license http://opensource.org/licenses/MIT The MIT License
|
||||
* @version 2.1
|
||||
* @license http://opensource.org/licenses/MIT
|
||||
* @version 1.0
|
||||
*/
|
||||
abstract class AbstractPicoPlugin implements PicoPluginInterface
|
||||
{
|
||||
|
@ -31,33 +18,25 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
|
|||
* @see PicoPluginInterface::getPico()
|
||||
* @var Pico
|
||||
*/
|
||||
protected $pico;
|
||||
private $pico;
|
||||
|
||||
/**
|
||||
* Boolean indicating if this plugin is enabled (TRUE) or disabled (FALSE)
|
||||
* Boolean indicating if this plugin is enabled (true) or disabled (false)
|
||||
*
|
||||
* @see PicoPluginInterface::isEnabled()
|
||||
* @see PicoPluginInterface::setEnabled()
|
||||
* @var bool|null
|
||||
* @var boolean
|
||||
*/
|
||||
protected $enabled;
|
||||
protected $enabled = true;
|
||||
|
||||
/**
|
||||
* Boolean indicating if this plugin was ever enabled/disabled manually
|
||||
*
|
||||
* @see PicoPluginInterface::isStatusChanged()
|
||||
* @var bool
|
||||
* @var boolean
|
||||
*/
|
||||
protected $statusChanged = false;
|
||||
|
||||
/**
|
||||
* Boolean indicating whether this plugin matches Pico's API version
|
||||
*
|
||||
* @see AbstractPicoPlugin::checkCompatibility()
|
||||
* @var bool|null
|
||||
*/
|
||||
protected $nativePlugin;
|
||||
|
||||
/**
|
||||
* List of plugins which this plugin depends on
|
||||
*
|
||||
|
@ -72,14 +51,12 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
|
|||
*
|
||||
* @see AbstractPicoPlugin::checkDependants()
|
||||
* @see PicoPluginInterface::getDependants()
|
||||
* @var object[]|null
|
||||
* @var object[]
|
||||
*/
|
||||
protected $dependants;
|
||||
private $dependants;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of a Pico plugin
|
||||
*
|
||||
* @param Pico $pico current instance of Pico
|
||||
* @see PicoPluginInterface::__construct()
|
||||
*/
|
||||
public function __construct(Pico $pico)
|
||||
{
|
||||
|
@ -87,13 +64,21 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see PicoPluginInterface::handleEvent()
|
||||
*/
|
||||
public function handleEvent($eventName, array $params)
|
||||
{
|
||||
// plugins can be enabled/disabled using the config
|
||||
if ($eventName === 'onConfigLoaded') {
|
||||
$this->configEnabled();
|
||||
$pluginEnabled = $this->getConfig(get_called_class() . '.enabled');
|
||||
if ($pluginEnabled !== null) {
|
||||
$this->setEnabled($pluginEnabled);
|
||||
} else {
|
||||
$pluginConfig = $this->getConfig(get_called_class());
|
||||
if (is_array($pluginConfig) && isset($pluginConfig['enabled'])) {
|
||||
$this->setEnabled($pluginConfig['enabled']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->isEnabled() || ($eventName === 'onPluginsLoaded')) {
|
||||
|
@ -104,33 +89,7 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Enables or disables this plugin depending on Pico's config
|
||||
*/
|
||||
protected function configEnabled()
|
||||
{
|
||||
$pluginEnabled = $this->getPico()->getConfig(get_called_class() . '.enabled');
|
||||
if ($pluginEnabled !== null) {
|
||||
$this->setEnabled($pluginEnabled);
|
||||
} else {
|
||||
$pluginEnabled = $this->getPluginConfig('enabled');
|
||||
if ($pluginEnabled !== null) {
|
||||
$this->setEnabled($pluginEnabled);
|
||||
} elseif ($this->enabled) {
|
||||
$this->setEnabled(true, true, true);
|
||||
} elseif ($this->enabled === null) {
|
||||
// make sure dependencies are already fulfilled,
|
||||
// otherwise the plugin needs to be enabled manually
|
||||
try {
|
||||
$this->setEnabled(true, false, true);
|
||||
} catch (RuntimeException $e) {
|
||||
$this->enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see PicoPluginInterface::setEnabled()
|
||||
*/
|
||||
public function setEnabled($enabled, $recursive = true, $auto = false)
|
||||
{
|
||||
|
@ -138,7 +97,6 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
|
|||
$this->enabled = (bool) $enabled;
|
||||
|
||||
if ($enabled) {
|
||||
$this->checkCompatibility();
|
||||
$this->checkDependencies($recursive);
|
||||
} else {
|
||||
$this->checkDependants($recursive);
|
||||
|
@ -146,7 +104,7 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see PicoPluginInterface::isEnabled()
|
||||
*/
|
||||
public function isEnabled()
|
||||
{
|
||||
|
@ -154,7 +112,7 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see PicoPluginInterface::isStatusChanged()
|
||||
*/
|
||||
public function isStatusChanged()
|
||||
{
|
||||
|
@ -162,48 +120,20 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see PicoPluginInterface::getPico()
|
||||
*/
|
||||
public function getPico()
|
||||
{
|
||||
return $this->pico;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns either the value of the specified plugin config variable or
|
||||
* the config array
|
||||
*
|
||||
* @param string $configName optional name of a config variable
|
||||
* @param mixed $default optional default value to return when the
|
||||
* named config variable doesn't exist
|
||||
*
|
||||
* @return mixed if no name of a config variable has been supplied, the
|
||||
* plugin's config array is returned; otherwise it returns either the
|
||||
* value of the named config variable, or, if the named config variable
|
||||
* doesn't exist, the provided default value or NULL
|
||||
*/
|
||||
public function getPluginConfig($configName = null, $default = null)
|
||||
{
|
||||
$pluginConfig = $this->getPico()->getConfig(get_called_class(), array());
|
||||
|
||||
if ($configName === null) {
|
||||
return $pluginConfig;
|
||||
}
|
||||
|
||||
return isset($pluginConfig[$configName]) ? $pluginConfig[$configName] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes all not satisfiable method calls to Pico
|
||||
*
|
||||
* @see PicoPluginInterface::getPico()
|
||||
*
|
||||
* @deprecated 2.1.0
|
||||
*
|
||||
* @param string $methodName name of the method to call
|
||||
* @param array $params parameters to pass
|
||||
*
|
||||
* @return mixed return value of the called method
|
||||
* @see Pico
|
||||
* @param string $methodName name of the method to call
|
||||
* @param array $params parameters to pass
|
||||
* @return mixed return value of the called method
|
||||
*/
|
||||
public function __call($methodName, array $params)
|
||||
{
|
||||
|
@ -220,38 +150,37 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
|
|||
/**
|
||||
* Enables all plugins which this plugin depends on
|
||||
*
|
||||
* @see PicoPluginInterface::getDependencies()
|
||||
*
|
||||
* @param bool $recursive enable required plugins automatically
|
||||
*
|
||||
* @throws RuntimeException thrown when a dependency fails
|
||||
* @see PicoPluginInterface::getDependencies()
|
||||
* @param boolean $recursive enable required plugins automatically
|
||||
* @return void
|
||||
* @throws RuntimeException thrown when a dependency fails
|
||||
*/
|
||||
protected function checkDependencies($recursive)
|
||||
{
|
||||
foreach ($this->getDependencies() as $pluginName) {
|
||||
try {
|
||||
$plugin = $this->getPico()->getPlugin($pluginName);
|
||||
$plugin = $this->getPlugin($pluginName);
|
||||
} catch (RuntimeException $e) {
|
||||
throw new RuntimeException(
|
||||
"Unable to enable plugin '" . get_called_class() . "': "
|
||||
"Unable to enable plugin '" . get_called_class() . "':"
|
||||
. "Required plugin '" . $pluginName . "' not found"
|
||||
);
|
||||
}
|
||||
|
||||
// plugins which don't implement PicoPluginInterface are always enabled
|
||||
if (($plugin instanceof PicoPluginInterface) && !$plugin->isEnabled()) {
|
||||
if (is_a($plugin, 'PicoPluginInterface') && !$plugin->isEnabled()) {
|
||||
if ($recursive) {
|
||||
if (!$plugin->isStatusChanged()) {
|
||||
$plugin->setEnabled(true, true, true);
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"Unable to enable plugin '" . get_called_class() . "': "
|
||||
"Unable to enable plugin '" . get_called_class() . "':"
|
||||
. "Required plugin '" . $pluginName . "' was disabled manually"
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"Unable to enable plugin '" . get_called_class() . "': "
|
||||
"Unable to enable plugin '" . get_called_class() . "':"
|
||||
. "Required plugin '" . $pluginName . "' is disabled"
|
||||
);
|
||||
}
|
||||
|
@ -260,7 +189,7 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see PicoPluginInterface::getDependencies()
|
||||
*/
|
||||
public function getDependencies()
|
||||
{
|
||||
|
@ -270,16 +199,15 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
|
|||
/**
|
||||
* Disables all plugins which depend on this plugin
|
||||
*
|
||||
* @see PicoPluginInterface::getDependants()
|
||||
*
|
||||
* @param bool $recursive disabled dependant plugins automatically
|
||||
*
|
||||
* @throws RuntimeException thrown when a dependency fails
|
||||
* @see PicoPluginInterface::getDependants()
|
||||
* @param boolean $recursive disabled dependant plugins automatically
|
||||
* @return void
|
||||
* @throws RuntimeException thrown when a dependency fails
|
||||
*/
|
||||
protected function checkDependants($recursive)
|
||||
{
|
||||
$dependants = $this->getDependants();
|
||||
if ($dependants) {
|
||||
if (!empty($dependants)) {
|
||||
if ($recursive) {
|
||||
foreach ($this->getDependants() as $pluginName => $plugin) {
|
||||
if ($plugin->isEnabled()) {
|
||||
|
@ -294,8 +222,8 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
|
|||
}
|
||||
}
|
||||
} else {
|
||||
$dependantsList = 'plugin' . ((count($dependants) > 1) ? 's' : '') . ' '
|
||||
. "'" . implode("', '", array_keys($dependants)) . "'";
|
||||
$dependantsList = 'plugin' . ((count($dependants) > 1) ? 's' : '') . ' ';
|
||||
$dependantsList .= "'" . implode("', '", array_keys($dependants)) . "'";
|
||||
throw new RuntimeException(
|
||||
"Unable to disable plugin '" . get_called_class() . "': "
|
||||
. "Required by " . $dependantsList
|
||||
|
@ -305,15 +233,15 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see PicoPluginInterface::getDependants()
|
||||
*/
|
||||
public function getDependants()
|
||||
{
|
||||
if ($this->dependants === null) {
|
||||
$this->dependants = array();
|
||||
foreach ($this->getPico()->getPlugins() as $pluginName => $plugin) {
|
||||
foreach ($this->getPlugins() as $pluginName => $plugin) {
|
||||
// only plugins which implement PicoPluginInterface support dependencies
|
||||
if ($plugin instanceof PicoPluginInterface) {
|
||||
if (is_a($plugin, 'PicoPluginInterface')) {
|
||||
$dependencies = $plugin->getDependencies();
|
||||
if (in_array(get_called_class(), $dependencies)) {
|
||||
$this->dependants[$pluginName] = $plugin;
|
||||
|
@ -324,35 +252,4 @@ abstract class AbstractPicoPlugin implements PicoPluginInterface
|
|||
|
||||
return $this->dependants;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks compatibility with Pico's API version
|
||||
*
|
||||
* Pico automatically adds a dependency to {@see PicoDeprecated} when the
|
||||
* plugin's API is older than Pico's API. {@see PicoDeprecated} furthermore
|
||||
* throws a exception if it can't provide compatibility in such cases.
|
||||
* However, we still have to decide whether this plugin is compatible to
|
||||
* newer API versions, what requires some special (version specific)
|
||||
* precaution and is therefore usually not the case.
|
||||
*
|
||||
* @throws RuntimeException thrown when the plugin's and Pico's API aren't
|
||||
* compatible
|
||||
*/
|
||||
protected function checkCompatibility()
|
||||
{
|
||||
if ($this->nativePlugin === null) {
|
||||
$picoClassName = get_class($this->pico);
|
||||
$picoApiVersion = defined($picoClassName . '::API_VERSION') ? $picoClassName::API_VERSION : 1;
|
||||
$pluginApiVersion = defined('static::API_VERSION') ? static::API_VERSION : 1;
|
||||
|
||||
$this->nativePlugin = ($pluginApiVersion === $picoApiVersion);
|
||||
|
||||
if (!$this->nativePlugin && ($pluginApiVersion > $picoApiVersion)) {
|
||||
throw new RuntimeException(
|
||||
"Unable to enable plugin '" . get_called_class() . "': The plugin's API (version "
|
||||
. $pluginApiVersion . ") isn't compatible with Pico's API (version " . $picoApiVersion . ")"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
2346
lib/Pico.php
2346
lib/Pico.php
File diff suppressed because it is too large
Load diff
|
@ -1,82 +1,80 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of Pico. It's copyrighted by the contributors recorded
|
||||
* in the version control history of the file, available from the following
|
||||
* original location:
|
||||
*
|
||||
* <https://github.com/picocms/Pico/blob/master/lib/PicoPluginInterface.php>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* License-Filename: LICENSE
|
||||
*/
|
||||
|
||||
/**
|
||||
* Common interface for Pico plugins
|
||||
*
|
||||
* For a list of supported events see {@see DummyPlugin}; you can use
|
||||
* {@see DummyPlugin} as template for new plugins. For a list of deprecated
|
||||
* events see {@see PicoDeprecated}.
|
||||
* For a list of supported events see {@link DummyPlugin}; you can use
|
||||
* {@link DummyPlugin} as template for new plugins. For a list of deprecated
|
||||
* events see {@link PicoDeprecated}.
|
||||
*
|
||||
* If you're developing a new plugin, you MUST both implement this interface
|
||||
* and define the class constant `API_VERSION`. You SHOULD always use the
|
||||
* API version of Pico's latest milestone when releasing a plugin. If you're
|
||||
* developing a new version of an existing plugin, it is strongly recommended
|
||||
* to update your plugin to use Pico's latest API version.
|
||||
* You SHOULD NOT use deprecated events when implementing this interface.
|
||||
* Deprecated events are triggered by the {@link PicoDeprecated} plugin, if
|
||||
* plugins which don't implement this interface are loaded. You can take
|
||||
* advantage from this behaviour if you want to do something only when old
|
||||
* plugins are loaded. Consequently the old events are never triggered when
|
||||
* your plugin is implementing this interface and no old plugins are present.
|
||||
*
|
||||
* If you're developing a new plugin, you MUST implement this interface. If
|
||||
* you're the developer of an old plugin, it is STRONGLY RECOMMENDED to use
|
||||
* the events introduced in Pico 1.0 when releasing a new version of your
|
||||
* plugin. If you want to use any of the new events, you MUST implement
|
||||
* this interface and update all other events you use.
|
||||
*
|
||||
* @author Daniel Rudolf
|
||||
* @link http://picocms.org
|
||||
* @license http://opensource.org/licenses/MIT The MIT License
|
||||
* @version 2.1
|
||||
* @license http://opensource.org/licenses/MIT
|
||||
* @version 1.0
|
||||
*/
|
||||
interface PicoPluginInterface
|
||||
{
|
||||
/**
|
||||
* Constructs a new instance of a Pico plugin
|
||||
*
|
||||
* @param Pico $pico current instance of Pico
|
||||
*/
|
||||
public function __construct(Pico $pico);
|
||||
|
||||
/**
|
||||
* Handles a event that was triggered by Pico
|
||||
*
|
||||
* @param string $eventName name of the triggered event
|
||||
* @param array $params passed parameters
|
||||
* @param string $eventName name of the triggered event
|
||||
* @param array $params passed parameters
|
||||
* @return void
|
||||
*/
|
||||
public function handleEvent($eventName, array $params);
|
||||
|
||||
/**
|
||||
* Enables or disables this plugin
|
||||
*
|
||||
* @see PicoPluginInterface::isEnabled()
|
||||
* @see PicoPluginInterface::isStatusChanged()
|
||||
*
|
||||
* @param bool $enabled enable (TRUE) or disable (FALSE) this plugin
|
||||
* @param bool $recursive when TRUE, enable or disable recursively.
|
||||
* @see PicoPluginInterface::isEnabled()
|
||||
* @see PicoPluginInterface::isStatusChanged()
|
||||
* @param boolean $enabled enable (true) or disable (false) this plugin
|
||||
* @param boolean $recursive when true, enable or disable recursively
|
||||
* In other words, if you enable a plugin, all required plugins are
|
||||
* enabled, too. When disabling a plugin, all depending plugins are
|
||||
* disabled likewise. Recursive operations are only performed as long
|
||||
* as a plugin wasn't enabled/disabled manually. This parameter is
|
||||
* optional and defaults to TRUE.
|
||||
* @param bool $auto enable or disable to fulfill a dependency. This
|
||||
* parameter is optional and defaults to FALSE.
|
||||
*
|
||||
* @throws RuntimeException thrown when a dependency fails
|
||||
* optional and defaults to true.
|
||||
* @param boolean $auto enable or disable to fulfill a dependency
|
||||
* This parameter is optional and defaults to false.
|
||||
* @return void
|
||||
* @throws RuntimeException thrown when a dependency fails
|
||||
*/
|
||||
public function setEnabled($enabled, $recursive = true, $auto = false);
|
||||
|
||||
/**
|
||||
* Returns a boolean indicating whether this plugin is enabled or not
|
||||
* Returns true if this plugin is enabled, false otherwise
|
||||
*
|
||||
* You musn't rely on the return value when Pico's `onConfigLoaded` event
|
||||
* wasn't triggered on all plugins yet. This method might even return NULL
|
||||
* then. The plugin's status might change later.
|
||||
*
|
||||
* @see PicoPluginInterface::setEnabled()
|
||||
*
|
||||
* @return bool|null plugin is enabled (TRUE) or disabled (FALSE)
|
||||
* @see PicoPluginInterface::setEnabled()
|
||||
* @return boolean plugin is enabled (true) or disabled (false)
|
||||
*/
|
||||
public function isEnabled();
|
||||
|
||||
/**
|
||||
* Returns TRUE if the plugin was ever enabled/disabled manually
|
||||
* Returns true if the plugin was ever enabled/disabled manually
|
||||
*
|
||||
* @see PicoPluginInterface::setEnabled()
|
||||
*
|
||||
* @return bool plugin is in its default state (TRUE), FALSE otherwise
|
||||
* @see PicoPluginInterface::setEnabled()
|
||||
* @return boolean plugin is in its default state (true), false otherwise
|
||||
*/
|
||||
public function isStatusChanged();
|
||||
|
||||
|
@ -95,11 +93,10 @@ interface PicoPluginInterface
|
|||
public function getDependants();
|
||||
|
||||
/**
|
||||
* Returns the plugin's instance of Pico
|
||||
* Returns the plugins instance of Pico
|
||||
*
|
||||
* @see Pico
|
||||
*
|
||||
* @return Pico the plugin's instance of Pico
|
||||
* @see Pico
|
||||
* @return Pico the plugins instance of Pico
|
||||
*/
|
||||
public function getPico();
|
||||
}
|
||||
|
|
|
@ -1,22 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of Pico. It's copyrighted by the contributors recorded
|
||||
* in the version control history of the file, available from the following
|
||||
* original location:
|
||||
*
|
||||
* <https://github.com/picocms/Pico/blob/master/lib/PicoTwigExtension.php>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* License-Filename: LICENSE
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pico's Twig extension to implement additional filters
|
||||
* Picos Twig extension to implement additional filters
|
||||
*
|
||||
* @author Daniel Rudolf
|
||||
* @link http://picocms.org
|
||||
* @license http://opensource.org/licenses/MIT The MIT License
|
||||
* @version 2.1
|
||||
* @license http://opensource.org/licenses/MIT
|
||||
* @version 1.0
|
||||
*/
|
||||
class PicoTwigExtension extends Twig_Extension
|
||||
{
|
||||
|
@ -41,9 +31,8 @@ class PicoTwigExtension extends Twig_Extension
|
|||
/**
|
||||
* Returns the extensions instance of Pico
|
||||
*
|
||||
* @see Pico
|
||||
*
|
||||
* @return Pico the extension's instance of Pico
|
||||
* @see Pico
|
||||
* @return Pico the extensions instance of Pico
|
||||
*/
|
||||
public function getPico()
|
||||
{
|
||||
|
@ -53,8 +42,7 @@ class PicoTwigExtension extends Twig_Extension
|
|||
/**
|
||||
* Returns the name of the extension
|
||||
*
|
||||
* @see Twig_ExtensionInterface::getName()
|
||||
*
|
||||
* @see Twig_ExtensionInterface::getName()
|
||||
* @return string the extension name
|
||||
*/
|
||||
public function getName()
|
||||
|
@ -63,40 +51,17 @@ class PicoTwigExtension extends Twig_Extension
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a list of Pico-specific Twig filters
|
||||
* Returns the Twig filters markdown, map and sort_by
|
||||
*
|
||||
* @see Twig_ExtensionInterface::getFilters()
|
||||
*
|
||||
* @return Twig_SimpleFilter[] array of Pico's Twig filters
|
||||
* @see Twig_ExtensionInterface::getFilters()
|
||||
* @return Twig_SimpleFilter[] array of Picos Twig filters
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return array(
|
||||
'markdown' => new Twig_SimpleFilter(
|
||||
'markdown',
|
||||
array($this, 'markdownFilter'),
|
||||
array('is_safe' => array('html'))
|
||||
),
|
||||
'markdown' => new Twig_SimpleFilter('markdown', array($this, 'markdownFilter')),
|
||||
'map' => new Twig_SimpleFilter('map', array($this, 'mapFilter')),
|
||||
'sort_by' => new Twig_SimpleFilter('sort_by', array($this, 'sortByFilter')),
|
||||
'link' => new Twig_SimpleFilter('link', array($this->pico, 'getPageUrl')),
|
||||
'url' => new Twig_SimpleFilter('url', array($this->pico, 'substituteUrl'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of Pico-specific Twig functions
|
||||
*
|
||||
* @see Twig_ExtensionInterface::getFunctions()
|
||||
*
|
||||
* @return Twig_SimpleFunction[] array of Pico's Twig functions
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return array(
|
||||
'url_param' => new Twig_SimpleFunction('url_param', array($this, 'urlParamFunction')),
|
||||
'form_param' => new Twig_SimpleFunction('form_param', array($this, 'formParamFunction')),
|
||||
'pages' => new Twig_SimpleFunction('pages', array($this, 'pagesFunction'))
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -108,19 +73,19 @@ class PicoTwigExtension extends Twig_Extension
|
|||
* Don't use it to parse the contents of a page, use the `content` filter
|
||||
* instead, what ensures the proper preparation of the contents.
|
||||
*
|
||||
* @see Pico::substituteFileContent()
|
||||
* @see Pico::parseFileContent()
|
||||
*
|
||||
* @param string $markdown markdown to parse
|
||||
* @param array $meta meta data to use for %meta.*% replacement
|
||||
* @param bool $singleLine whether to parse just a single line of markup
|
||||
*
|
||||
* @return string parsed HTML
|
||||
* @param string $markdown markdown to parse
|
||||
* @return string parsed HTML
|
||||
*/
|
||||
public function markdownFilter($markdown, array $meta = array(), $singleLine = false)
|
||||
public function markdownFilter($markdown)
|
||||
{
|
||||
$markdown = $this->getPico()->substituteFileContent($markdown, $meta);
|
||||
return $this->getPico()->parseFileContent($markdown, $singleLine);
|
||||
if ($this->getPico()->getParsedown() === null) {
|
||||
throw new LogicException(
|
||||
'Unable to apply Twig "markdown" filter: '
|
||||
. 'Parsedown instance wasn\'t registered yet'
|
||||
);
|
||||
}
|
||||
|
||||
return $this->getPico()->getParsedown()->text($markdown);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,18 +94,15 @@ class PicoTwigExtension extends Twig_Extension
|
|||
* This method is registered as the Twig `map` filter. You can use this
|
||||
* filter to e.g. get all page titles (`{{ pages|map("title") }}`).
|
||||
*
|
||||
* @param array|Traversable $var variable to map
|
||||
* @param mixed $mapKeyPath key to map; either a scalar or a
|
||||
* @param array|Traversable $var variable to map
|
||||
* @param mixed $mapKeyPath key to map; either a scalar or a
|
||||
* array interpreted as key path (i.e. ['foo', 'bar'] will return all
|
||||
* $item['foo']['bar'] values)
|
||||
*
|
||||
* @return array mapped values
|
||||
*
|
||||
* @throws Twig_Error_Runtime
|
||||
* @return array mapped values
|
||||
*/
|
||||
public function mapFilter($var, $mapKeyPath)
|
||||
{
|
||||
if (!is_array($var) && (!is_object($var) || !($var instanceof Traversable))) {
|
||||
if (!is_array($var) && (!is_object($var) || !is_a($var, 'Traversable'))) {
|
||||
throw new Twig_Error_Runtime(sprintf(
|
||||
'The map filter only works with arrays or "Traversable", got "%s"',
|
||||
is_object($var) ? get_class($var) : gettype($var)
|
||||
|
@ -160,29 +122,26 @@ class PicoTwigExtension extends Twig_Extension
|
|||
*
|
||||
* This method is registered as the Twig `sort_by` filter. You can use this
|
||||
* filter to e.g. sort the pages array by a arbitrary meta value. Calling
|
||||
* `{{ pages|sort_by([ "meta", "nav" ]) }}` returns all pages sorted by the
|
||||
* meta value `nav`. The sorting algorithm will never assume equality of
|
||||
* two values, it will then fall back to the original order. The result is
|
||||
* `{{ pages|sort_by("meta:nav"|split(":")) }}` returns all pages sorted by
|
||||
* the meta value `nav`. Please note the `"meta:nav"|split(":")` part of
|
||||
* the example. The sorting algorithm will never assume equality of two
|
||||
* values, it will then fall back to the original order. The result is
|
||||
* always sorted in ascending order, apply Twigs `reverse` filter to
|
||||
* achieve a descending order.
|
||||
*
|
||||
* @param array|Traversable $var variable to sort
|
||||
* @param mixed $sortKeyPath key to use for sorting; either
|
||||
* @param array|Traversable $var variable to sort
|
||||
* @param mixed $sortKeyPath key to use for sorting; either
|
||||
* a scalar or a array interpreted as key path (i.e. ['foo', 'bar']
|
||||
* will sort $var by $item['foo']['bar'])
|
||||
* @param string $fallback specify what to do with items
|
||||
* @param string $fallback specify what to do with items
|
||||
* which don't contain the specified sort key; use "bottom" (default)
|
||||
* to move these items to the end of the sorted array, "top" to rank
|
||||
* them first, "keep" to keep the original order, or "remove" to remove
|
||||
* these items
|
||||
*
|
||||
* @return array sorted array
|
||||
*
|
||||
* @throws Twig_Error_Runtime
|
||||
* to move those items to the end of the sorted array, "top" to rank
|
||||
* them first, or "keep" to keep the original order of those items
|
||||
* @return array sorted array
|
||||
*/
|
||||
public function sortByFilter($var, $sortKeyPath, $fallback = 'bottom')
|
||||
{
|
||||
if (is_object($var) && ($var instanceof Traversable)) {
|
||||
if (is_object($var) && is_a($var, 'Traversable')) {
|
||||
$var = iterator_to_array($var, true);
|
||||
} elseif (!is_array($var)) {
|
||||
throw new Twig_Error_Runtime(sprintf(
|
||||
|
@ -190,15 +149,12 @@ class PicoTwigExtension extends Twig_Extension
|
|||
is_object($var) ? get_class($var) : gettype($var)
|
||||
));
|
||||
}
|
||||
if (($fallback !== 'top') && ($fallback !== 'bottom') && ($fallback !== 'keep') && ($fallback !== "remove")) {
|
||||
throw new Twig_Error_Runtime(
|
||||
'The sort_by filter only supports the "top", "bottom", "keep" and "remove" fallbacks'
|
||||
);
|
||||
if (($fallback !== 'top') && ($fallback !== 'bottom') && ($fallback !== 'keep')) {
|
||||
throw new Twig_Error_Runtime('The sort_by filter only supports the "top", "bottom" and "keep" fallbacks');
|
||||
}
|
||||
|
||||
$twigExtension = $this;
|
||||
$varKeys = array_keys($var);
|
||||
$removeItems = array();
|
||||
uksort($var, function ($a, $b) use ($twigExtension, $var, $varKeys, $sortKeyPath, $fallback, &$removeItems) {
|
||||
$aSortValue = $twigExtension->getKeyOfVar($var[$a], $sortKeyPath);
|
||||
$aSortValueNull = ($aSortValue === null);
|
||||
|
@ -206,15 +162,7 @@ class PicoTwigExtension extends Twig_Extension
|
|||
$bSortValue = $twigExtension->getKeyOfVar($var[$b], $sortKeyPath);
|
||||
$bSortValueNull = ($bSortValue === null);
|
||||
|
||||
if (($fallback === 'remove') && ($aSortValueNull || $bSortValueNull)) {
|
||||
if ($aSortValueNull) {
|
||||
$removeItems[$a] = $var[$a];
|
||||
}
|
||||
if ($bSortValueNull) {
|
||||
$removeItems[$b] = $var[$b];
|
||||
}
|
||||
return ($aSortValueNull - $bSortValueNull);
|
||||
} elseif ($aSortValueNull xor $bSortValueNull) {
|
||||
if ($aSortValueNull xor $bSortValueNull) {
|
||||
if ($fallback === 'top') {
|
||||
return ($aSortValueNull - $bSortValueNull) * -1;
|
||||
} elseif ($fallback === 'bottom') {
|
||||
|
@ -232,10 +180,6 @@ class PicoTwigExtension extends Twig_Extension
|
|||
return ($aIndex > $bIndex) ? 1 : -1;
|
||||
});
|
||||
|
||||
if ($removeItems) {
|
||||
$var = array_diff_key($var, $removeItems);
|
||||
}
|
||||
|
||||
return $var;
|
||||
}
|
||||
|
||||
|
@ -243,17 +187,16 @@ class PicoTwigExtension extends Twig_Extension
|
|||
* Returns the value of a variable item specified by a scalar key or a
|
||||
* arbitrary deep sub-key using a key path
|
||||
*
|
||||
* @param array|Traversable|ArrayAccess|object $var base variable
|
||||
* @param mixed $keyPath scalar key or a
|
||||
* @param array|Traversable|ArrayAccess|object $var base variable
|
||||
* @param mixed $keyPath scalar key or a
|
||||
* array interpreted as key path (when passing e.g. ['foo', 'bar'],
|
||||
* the method will return $var['foo']['bar']) specifying the value
|
||||
*
|
||||
* @return mixed the requested value or NULL when the given key or key path
|
||||
* didn't match
|
||||
* @return mixed the requested
|
||||
* value or NULL when the given key or key path didn't match
|
||||
*/
|
||||
public static function getKeyOfVar($var, $keyPath)
|
||||
{
|
||||
if (!$keyPath) {
|
||||
if (empty($keyPath)) {
|
||||
return null;
|
||||
} elseif (!is_array($keyPath)) {
|
||||
$keyPath = array($keyPath);
|
||||
|
@ -261,9 +204,9 @@ class PicoTwigExtension extends Twig_Extension
|
|||
|
||||
foreach ($keyPath as $key) {
|
||||
if (is_object($var)) {
|
||||
if ($var instanceof ArrayAccess) {
|
||||
if (is_a($var, 'ArrayAccess')) {
|
||||
// use ArrayAccess, see below
|
||||
} elseif ($var instanceof Traversable) {
|
||||
} elseif (is_a($var, 'Traversable')) {
|
||||
$var = iterator_to_array($var);
|
||||
} elseif (isset($var->{$key})) {
|
||||
$var = $var->{$key};
|
||||
|
@ -292,196 +235,4 @@ class PicoTwigExtension extends Twig_Extension
|
|||
|
||||
return $var;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters a URL GET parameter with a specified filter
|
||||
*
|
||||
* The Twig function disallows the use of the `callback` filter.
|
||||
*
|
||||
* @see Pico::getUrlParameter()
|
||||
*
|
||||
* @param string $name name of the URL GET parameter
|
||||
* to filter
|
||||
* @param int|string $filter the filter to apply
|
||||
* @param mixed|array $options either a associative options
|
||||
* array to be used by the filter or a scalar default value
|
||||
* @param int|string|int[]|string[] $flags flags and flag strings to be
|
||||
* used by the filter
|
||||
*
|
||||
* @return mixed either the filtered data, FALSE if the filter fails, or
|
||||
* NULL if the URL GET parameter doesn't exist and no default value is
|
||||
* given
|
||||
*/
|
||||
public function urlParamFunction($name, $filter = '', $options = null, $flags = null)
|
||||
{
|
||||
$filter = $filter ? (is_string($filter) ? filter_id($filter) : (int) $filter) : false;
|
||||
if (!$filter || ($filter === FILTER_CALLBACK)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->pico->getUrlParameter($name, $filter, $options, $flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters a HTTP POST parameter with a specified filter
|
||||
*
|
||||
* The Twig function disallows the use of the `callback` filter.
|
||||
*
|
||||
* @see Pico::getFormParameter()
|
||||
*
|
||||
* @param string $name name of the HTTP POST
|
||||
* parameter to filter
|
||||
* @param int|string $filter the filter to apply
|
||||
* @param mixed|array $options either a associative options
|
||||
* array to be used by the filter or a scalar default value
|
||||
* @param int|string|int[]|string[] $flags flags and flag strings to be
|
||||
* used by the filter
|
||||
*
|
||||
* @return mixed either the filtered data, FALSE if the filter fails, or
|
||||
* NULL if the HTTP POST parameter doesn't exist and no default value
|
||||
* is given
|
||||
*/
|
||||
public function formParamFunction($name, $filter = '', $options = null, $flags = null)
|
||||
{
|
||||
$filter = $filter ? (is_string($filter) ? filter_id($filter) : (int) $filter) : false;
|
||||
if (!$filter || ($filter === FILTER_CALLBACK)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->pico->getFormParameter($name, $filter, $options, $flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all pages within a particular branch of Pico's page tree
|
||||
*
|
||||
* This function should be used most of the time when dealing with Pico's
|
||||
* pages array, as it allows one to easily traverse Pico's pages tree
|
||||
* ({@see Pico::getPageTree()}) to retrieve a subset of Pico's pages array
|
||||
* in a very convenient and performant way.
|
||||
*
|
||||
* The function's default parameters are `$start = ""`, `$depth = 0`,
|
||||
* `$depthOffset = 0` and `$offset = 1`. A positive `$offset` is equivalent
|
||||
* to `$depth = $depth + $offset`, `$depthOffset = $depthOffset + $offset`
|
||||
* and `$offset = 0`.
|
||||
*
|
||||
* Consequently the default `$start = ""`, `$depth = 0`, `$depthOffset = 0`
|
||||
* and `$offset = 1` is equivalent to `$depth = 1`, `$depthOffset = 1` and
|
||||
* `$offset = 0`. `$start = ""` instruct the function to start from the
|
||||
* root node (i.e. the node of Pico's main index page at `index.md`).
|
||||
* `$depth` tells the function what pages to return. In this example,
|
||||
* `$depth = 1` matches the start node (i.e. the zeroth generation) and all
|
||||
* its descendant pages until the first generation (i.e. the start node's
|
||||
* children). `$depthOffset` instructs the function to exclude some of the
|
||||
* older generations. `$depthOffset = 1` specifically tells the function
|
||||
* to exclude the zeroth generation, so that the function returns all of
|
||||
* Pico's main index page's direct child pages (like `sub/index.md` and
|
||||
* `page.md`, but not `sub/page.md`) only.
|
||||
*
|
||||
* Passing `$depthOffset = -1` only is the same as passing `$start = ""`,
|
||||
* `$depth = 1`, `$depthOffset = 0` and `$offset = 0`. The only difference
|
||||
* is that `$depthOffset` won't exclude the zeroth generation, so that the
|
||||
* function returns Pico's main index page as well as all of its direct
|
||||
* child pages.
|
||||
*
|
||||
* Passing `$depth = 0`, `$depthOffset = -2` and `$offset = 2` is the same
|
||||
* as passing `$depth = 2`, `$depthOffset = 0` and `$offset = 0`. Both will
|
||||
* return the zeroth, first and second generation of pages. For Pico's main
|
||||
* index page this would be `index.md` (0th gen), `sub/index.md` (1st gen),
|
||||
* `sub/page.md` (2nd gen) and `page.md` (1st gen). If you want to return
|
||||
* 2nd gen pages only, pass `$offset = 2` only (with implicit `$depth = 0`
|
||||
* and `$depthOffset = 0` it's the same as `$depth = 2`, `$depthOffset = 2`
|
||||
* and `$offset = 0`).
|
||||
*
|
||||
* Instead of an integer you can also pass `$depth = null`. This is the
|
||||
* same as passing an infinitely large number as `$depth`, so that this
|
||||
* function simply returns all descendant pages. Consequently passing
|
||||
* `$start = ""`, `$depth = null`, `$depthOffset = 0` and `$offset = 0`
|
||||
* returns Pico's full pages array.
|
||||
*
|
||||
* If `$depth` is negative after taking `$offset` into consideration, the
|
||||
* function will throw a {@see Twig_Error_Runtime} exception, since this
|
||||
* would simply make no sense and is likely an error. Passing a negative
|
||||
* `$depthOffset` is equivalent to passing `$depthOffset = 0`.
|
||||
*
|
||||
* But what about a negative `$offset`? Passing `$offset = -1` instructs
|
||||
* the function not to start from the given `$start` node, but its parent
|
||||
* node. Consequently `$offset = -2` instructs the function to use the
|
||||
* `$start` node's grandparent node. Obviously this won't make any sense
|
||||
* for Pico's root node, but just image `$start = "sub/index"`. Passing
|
||||
* this together with `$offset = -1` is equivalent to `$start = ""` and
|
||||
* `$offset = 0`.
|
||||
*
|
||||
* @param string $start name of the node to start from
|
||||
* @param int|null $depth return pages until the given maximum depth;
|
||||
* pass NULL to return all descendant pages; defaults to 0
|
||||
* @param int $depthOffset start returning pages from the given
|
||||
* minimum depth; defaults to 0
|
||||
* @param int $offset ascend (positive) or descend (negative) the
|
||||
* given number of branches before returning pages; defaults to 1
|
||||
*
|
||||
* @return array[] the data of the matched pages
|
||||
*
|
||||
* @throws Twig_Error_Runtime
|
||||
*/
|
||||
public function pagesFunction($start = '', $depth = 0, $depthOffset = 0, $offset = 1)
|
||||
{
|
||||
$start = (string) $start;
|
||||
if (basename($start) === 'index') {
|
||||
$start = dirname($start);
|
||||
}
|
||||
|
||||
for (; $offset < 0; $offset++) {
|
||||
if (in_array($start, array('', '.', '/'), true)) {
|
||||
$offset = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
$start = dirname($start);
|
||||
}
|
||||
|
||||
$depth = ($depth !== null) ? $depth + $offset : null;
|
||||
$depthOffset = $depthOffset + $offset;
|
||||
|
||||
if (($depth !== null) && ($depth < 0)) {
|
||||
throw new Twig_Error_Runtime('The pages function doesn\'t support negative depths');
|
||||
}
|
||||
|
||||
$pageTree = $this->getPico()->getPageTree();
|
||||
if (in_array($start, array('', '.', '/'), true)) {
|
||||
if (($depth === null) && ($depthOffset <= 0)) {
|
||||
return $this->getPico()->getPages();
|
||||
}
|
||||
|
||||
$startNode = isset($pageTree['']['/']) ? $pageTree['']['/'] : null;
|
||||
} else {
|
||||
$branch = dirname($start);
|
||||
$branch = ($branch !== '.') ? $branch : '/';
|
||||
$node = (($branch !== '/') ? $branch . '/' : '') . basename($start);
|
||||
$startNode = isset($pageTree[$branch][$node]) ? $pageTree[$branch][$node] : null;
|
||||
}
|
||||
|
||||
if (!$startNode) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$getPagesClosure = function ($nodes, $depth, $depthOffset) use (&$getPagesClosure) {
|
||||
$pages = array();
|
||||
foreach ($nodes as $node) {
|
||||
if (isset($node['page']) && ($depthOffset <= 0)) {
|
||||
$pages[$node['page']['id']] = &$node['page'];
|
||||
}
|
||||
if (isset($node['children']) && ($depth > 0)) {
|
||||
$pages += $getPagesClosure($node['children'], $depth - 1, $depthOffset - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return $pages;
|
||||
};
|
||||
|
||||
return $getPagesClosure(
|
||||
array($startNode),
|
||||
($depth !== null) ? $depth : INF,
|
||||
$depthOffset
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
3
plugins/.gitignore
vendored
3
plugins/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
|||
# This directory is meant to be empty, except for DummyPlugin.php
|
||||
*
|
||||
!DummyPlugin.php
|
437
plugins/00-PicoDeprecated.php
Normal file
437
plugins/00-PicoDeprecated.php
Normal file
|
@ -0,0 +1,437 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Serve features of Pico deprecated since v1.0
|
||||
*
|
||||
* This plugin exists for backward compatibility and is disabled by default.
|
||||
* It gets automatically enabled when a plugin which doesn't implement
|
||||
* {@link PicoPluginInterface} is loaded. This plugin triggers deprecated
|
||||
* events and automatically enables {@link PicoParsePagesContent} and
|
||||
* {@link PicoExcerpt}. These plugins heavily impact Pico's performance! You
|
||||
* can disable this plugin by calling {@link PicoDeprecated::setEnabled()}.
|
||||
*
|
||||
* The following deprecated events are triggered by this plugin:
|
||||
*
|
||||
* | Event | ... triggers the deprecated event |
|
||||
* | ------------------- | --------------------------------------------------------- |
|
||||
* | onPluginsLoaded | plugins_loaded() |
|
||||
* | onConfigLoaded | config_loaded($config) |
|
||||
* | onRequestUrl | request_url($url) |
|
||||
* | onContentLoading | before_load_content($file) |
|
||||
* | onContentLoaded | after_load_content($file, $rawContent) |
|
||||
* | on404ContentLoading | before_404_load_content($file) |
|
||||
* | on404ContentLoaded | after_404_load_content($file, $rawContent) |
|
||||
* | onMetaHeaders | before_read_file_meta($headers) |
|
||||
* | onMetaParsed | file_meta($meta) |
|
||||
* | onContentParsing | before_parse_content($rawContent) |
|
||||
* | onContentParsed | after_parse_content($content) |
|
||||
* | onContentParsed | content_parsed($content) |
|
||||
* | onSinglePageLoaded | get_page_data($pages, $meta) |
|
||||
* | onPagesLoaded | get_pages($pages, $currentPage, $previousPage, $nextPage) |
|
||||
* | onTwigRegistration | before_twig_register() |
|
||||
* | onPageRendering | before_render($twigVariables, $twig, $templateName) |
|
||||
* | onPageRendered | after_render($output) |
|
||||
*
|
||||
* Since Pico 1.0 the config is stored in {@path "config/config.php"}. This
|
||||
* plugin tries to read {@path "config.php"} in Pico's root dir and overwrites
|
||||
* all settings previously specified in {@path "config/config.php"}.
|
||||
*
|
||||
* @author Daniel Rudolf
|
||||
* @link http://picocms.org
|
||||
* @license http://opensource.org/licenses/MIT
|
||||
* @version 1.0
|
||||
*/
|
||||
class PicoDeprecated extends AbstractPicoPlugin
|
||||
{
|
||||
/**
|
||||
* This plugin is disabled by default
|
||||
*
|
||||
* @see AbstractPicoPlugin::$enabled
|
||||
*/
|
||||
protected $enabled = false;
|
||||
|
||||
/**
|
||||
* The requested file
|
||||
*
|
||||
* @see PicoDeprecated::getRequestFile()
|
||||
* @var string|null
|
||||
*/
|
||||
protected $requestFile;
|
||||
|
||||
/**
|
||||
* Enables this plugin on demand and triggers the deprecated event
|
||||
* plugins_loaded()
|
||||
*
|
||||
* @see DummyPlugin::onPluginsLoaded()
|
||||
*/
|
||||
public function onPluginsLoaded(array &$plugins)
|
||||
{
|
||||
if (!empty($plugins)) {
|
||||
foreach ($plugins as $plugin) {
|
||||
if (!is_a($plugin, 'PicoPluginInterface')) {
|
||||
// the plugin doesn't implement PicoPluginInterface; it uses deprecated events
|
||||
// enable PicoDeprecated if it hasn't be explicitly enabled/disabled yet
|
||||
if (!$this->isStatusChanged()) {
|
||||
$this->setEnabled(true, true, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no plugins were found, so it actually isn't necessary to call deprecated events
|
||||
// anyway, this plugin also ensures compatibility apart from events used by old plugins,
|
||||
// so enable PicoDeprecated if it hasn't be explicitly enabled/disabled yet
|
||||
if (!$this->isStatusChanged()) {
|
||||
$this->setEnabled(true, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->isEnabled()) {
|
||||
$this->triggerEvent('plugins_loaded');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated event config_loaded($config)
|
||||
*
|
||||
* This method also defines deprecated constants, reads the `config.php`
|
||||
* in Pico's root dir, enables the plugins {@link PicoParsePagesContent}
|
||||
* and {@link PicoExcerpt} and makes `$config` globally accessible (the
|
||||
* latter was removed with Pico 0.9 and was added again as deprecated
|
||||
* feature with Pico 1.0)
|
||||
*
|
||||
* @see PicoDeprecated::defineConstants()
|
||||
* @see PicoDeprecated::loadRootDirConfig()
|
||||
* @see PicoDeprecated::enablePlugins()
|
||||
* @see DummyPlugin::onConfigLoaded()
|
||||
* @param mixed[] &$config array of config variables
|
||||
* @return void
|
||||
*/
|
||||
public function onConfigLoaded(array &$config)
|
||||
{
|
||||
$this->defineConstants();
|
||||
$this->loadRootDirConfig($config);
|
||||
$this->enablePlugins();
|
||||
$GLOBALS['config'] = &$config;
|
||||
|
||||
$this->triggerEvent('config_loaded', array(&$config));
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines deprecated constants
|
||||
*
|
||||
* `ROOT_DIR`, `LIB_DIR`, `PLUGINS_DIR`, `THEMES_DIR` and `CONTENT_EXT`
|
||||
* are deprecated since v1.0, `CONTENT_DIR` existed just in v0.9,
|
||||
* `CONFIG_DIR` just for a short time between v0.9 and v1.0 and
|
||||
* `CACHE_DIR` was dropped with v1.0 without a replacement.
|
||||
*
|
||||
* @see PicoDeprecated::onConfigLoaded()
|
||||
* @return void
|
||||
*/
|
||||
protected function defineConstants()
|
||||
{
|
||||
if (!defined('ROOT_DIR')) {
|
||||
define('ROOT_DIR', $this->getRootDir());
|
||||
}
|
||||
if (!defined('CONFIG_DIR')) {
|
||||
define('CONFIG_DIR', $this->getConfigDir());
|
||||
}
|
||||
if (!defined('LIB_DIR')) {
|
||||
$picoReflector = new ReflectionClass('Pico');
|
||||
define('LIB_DIR', dirname($picoReflector->getFileName() . '/'));
|
||||
}
|
||||
if (!defined('PLUGINS_DIR')) {
|
||||
define('PLUGINS_DIR', $this->getPluginsDir());
|
||||
}
|
||||
if (!defined('THEMES_DIR')) {
|
||||
define('THEMES_DIR', $this->getThemesDir());
|
||||
}
|
||||
if (!defined('CONTENT_DIR')) {
|
||||
define('CONTENT_DIR', $this->getConfig('content_dir'));
|
||||
}
|
||||
if (!defined('CONTENT_EXT')) {
|
||||
define('CONTENT_EXT', $this->getConfig('content_ext'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read config.php in Pico's root dir
|
||||
*
|
||||
* @see PicoDeprecated::onConfigLoaded()
|
||||
* @see Pico::loadConfig()
|
||||
* @param mixed[] &$realConfig array of config variables
|
||||
* @return void
|
||||
*/
|
||||
protected function loadRootDirConfig(array &$realConfig)
|
||||
{
|
||||
if (file_exists($this->getRootDir() . 'config.php')) {
|
||||
// config.php in Pico::$rootDir is deprecated
|
||||
// use config.php in Pico::$configDir instead
|
||||
$config = null;
|
||||
require($this->getRootDir() . 'config.php');
|
||||
|
||||
if (is_array($config)) {
|
||||
if (isset($config['base_url'])) {
|
||||
$config['base_url'] = rtrim($config['base_url'], '/') . '/';
|
||||
}
|
||||
if (isset($config['content_dir'])) {
|
||||
$config['content_dir'] = rtrim($config['content_dir'], '/') . '/';
|
||||
}
|
||||
|
||||
$realConfig = $config + $realConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the plugins PicoParsePagesContent and PicoExcerpt
|
||||
*
|
||||
* @see PicoParsePagesContent
|
||||
* @see PicoExcerpt
|
||||
* @return void
|
||||
*/
|
||||
protected function enablePlugins()
|
||||
{
|
||||
// enable PicoParsePagesContent and PicoExcerpt
|
||||
// we can't enable them during onPluginsLoaded because we can't know
|
||||
// if the user disabled us (PicoDeprecated) manually in the config
|
||||
$plugins = $this->getPlugins();
|
||||
if (isset($plugins['PicoParsePagesContent'])) {
|
||||
// parse all pages content if this plugin hasn't
|
||||
// be explicitly enabled/disabled yet
|
||||
if (!$plugins['PicoParsePagesContent']->isStatusChanged()) {
|
||||
$plugins['PicoParsePagesContent']->setEnabled(true, true, true);
|
||||
}
|
||||
}
|
||||
if (isset($plugins['PicoExcerpt'])) {
|
||||
// enable excerpt plugin if it hasn't be explicitly enabled/disabled yet
|
||||
if (!$plugins['PicoExcerpt']->isStatusChanged()) {
|
||||
$plugins['PicoExcerpt']->setEnabled(true, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated event request_url($url)
|
||||
*
|
||||
* @see DummyPlugin::onRequestUrl()
|
||||
*/
|
||||
public function onRequestUrl(&$url)
|
||||
{
|
||||
$this->triggerEvent('request_url', array(&$url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets PicoDeprecated::$requestFile to trigger the deprecated
|
||||
* events after_load_content() and after_404_load_content()
|
||||
*
|
||||
* @see PicoDeprecated::onContentLoaded()
|
||||
* @see PicoDeprecated::on404ContentLoaded()
|
||||
* @see DummyPlugin::onRequestFile()
|
||||
*/
|
||||
public function onRequestFile(&$file)
|
||||
{
|
||||
$this->requestFile = &$file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated before_load_content($file)
|
||||
*
|
||||
* @see DummyPlugin::onContentLoading()
|
||||
*/
|
||||
public function onContentLoading(&$file)
|
||||
{
|
||||
$this->triggerEvent('before_load_content', array(&$file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated event after_load_content($file, $rawContent)
|
||||
*
|
||||
* @see DummyPlugin::onContentLoaded()
|
||||
*/
|
||||
public function onContentLoaded(&$rawContent)
|
||||
{
|
||||
$this->triggerEvent('after_load_content', array(&$this->requestFile, &$rawContent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated before_404_load_content($file)
|
||||
*
|
||||
* @see DummyPlugin::on404ContentLoading()
|
||||
*/
|
||||
public function on404ContentLoading(&$file)
|
||||
{
|
||||
$this->triggerEvent('before_404_load_content', array(&$file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated event after_404_load_content($file, $rawContent)
|
||||
*
|
||||
* @see DummyPlugin::on404ContentLoaded()
|
||||
*/
|
||||
public function on404ContentLoaded(&$rawContent)
|
||||
{
|
||||
$this->triggerEvent('after_404_load_content', array(&$this->requestFile, &$rawContent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated event before_read_file_meta($headers)
|
||||
*
|
||||
* @see DummyPlugin::onMetaHeaders()
|
||||
*/
|
||||
public function onMetaHeaders(array &$headers)
|
||||
{
|
||||
$this->triggerEvent('before_read_file_meta', array(&$headers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated event file_meta($meta)
|
||||
*
|
||||
* @see DummyPlugin::onMetaParsed()
|
||||
*/
|
||||
public function onMetaParsed(array &$meta)
|
||||
{
|
||||
$this->triggerEvent('file_meta', array(&$meta));
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated event before_parse_content($rawContent)
|
||||
*
|
||||
* @see DummyPlugin::onContentParsing()
|
||||
*/
|
||||
public function onContentParsing(&$rawContent)
|
||||
{
|
||||
$this->triggerEvent('before_parse_content', array(&$rawContent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated events after_parse_content($content) and
|
||||
* content_parsed($content)
|
||||
*
|
||||
* @see DummyPlugin::onContentParsed()
|
||||
*/
|
||||
public function onContentParsed(&$content)
|
||||
{
|
||||
$this->triggerEvent('after_parse_content', array(&$content));
|
||||
|
||||
// deprecated since v0.8
|
||||
$this->triggerEvent('content_parsed', array(&$content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated event get_page_data($pages, $meta)
|
||||
*
|
||||
* @see DummyPlugin::onSinglePageLoaded()
|
||||
*/
|
||||
public function onSinglePageLoaded(array &$pageData)
|
||||
{
|
||||
$this->triggerEvent('get_page_data', array(&$pageData, $pageData['meta']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated event
|
||||
* get_pages($pages, $currentPage, $previousPage, $nextPage)
|
||||
*
|
||||
* Please note that the `get_pages()` event gets `$pages` passed without a
|
||||
* array index. The index is rebuild later using either the `id` array key
|
||||
* or is derived from the `url` array key. Duplicates are prevented by
|
||||
* adding `~dup` when necessary.
|
||||
*
|
||||
* @see DummyPlugin::onPagesLoaded()
|
||||
*/
|
||||
public function onPagesLoaded(
|
||||
array &$pages,
|
||||
array &$currentPage = null,
|
||||
array &$previousPage = null,
|
||||
array &$nextPage = null
|
||||
) {
|
||||
// remove keys of pages array
|
||||
$plainPages = array();
|
||||
foreach ($pages as &$pageData) {
|
||||
$plainPages[] = &$pageData;
|
||||
}
|
||||
unset($pageData);
|
||||
|
||||
$this->triggerEvent('get_pages', array(&$plainPages, &$currentPage, &$previousPage, &$nextPage));
|
||||
|
||||
// re-index pages array
|
||||
$pages = array();
|
||||
foreach ($plainPages as &$pageData) {
|
||||
if (!isset($pageData['id'])) {
|
||||
$urlPrefixLength = strlen($this->getBaseUrl()) + intval(!$this->isUrlRewritingEnabled());
|
||||
$pageData['id'] = substr($pageData['url'], $urlPrefixLength);
|
||||
}
|
||||
|
||||
// prevent duplicates
|
||||
$id = $pageData['id'];
|
||||
for ($i = 1; isset($pages[$id]); $i++) {
|
||||
$id = $pageData['id'] . '~dup' . $i;
|
||||
}
|
||||
|
||||
$pages[$id] = &$pageData;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated event before_twig_register()
|
||||
*
|
||||
* @see DummyPlugin::onTwigRegistration()
|
||||
*/
|
||||
public function onTwigRegistration()
|
||||
{
|
||||
$this->triggerEvent('before_twig_register');
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated event before_render($twigVariables, $twig, $templateName)
|
||||
*
|
||||
* Please note that the `before_render()` event gets `$templateName` passed
|
||||
* without its file extension. The file extension is later added again.
|
||||
*
|
||||
* @see DummyPlugin::onPageRendering()
|
||||
*/
|
||||
public function onPageRendering(Twig_Environment &$twig, array &$twigVariables, &$templateName)
|
||||
{
|
||||
// template name contains file extension since Pico 1.0
|
||||
$fileExtension = '';
|
||||
if (($fileExtensionPos = strrpos($templateName, '.')) !== false) {
|
||||
$fileExtension = substr($templateName, $fileExtensionPos);
|
||||
$templateName = substr($templateName, 0, $fileExtensionPos);
|
||||
}
|
||||
|
||||
$this->triggerEvent('before_render', array(&$twigVariables, &$twig, &$templateName));
|
||||
|
||||
// add original file extension
|
||||
$templateName = $templateName . $fileExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the deprecated event after_render($output)
|
||||
*
|
||||
* @see DummyPlugin::onPageRendered()
|
||||
*/
|
||||
public function onPageRendered(&$output)
|
||||
{
|
||||
$this->triggerEvent('after_render', array(&$output));
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers a deprecated event on all plugins
|
||||
*
|
||||
* Deprecated events are also triggered on plugins which implement
|
||||
* {@link PicoPluginInterface}. Please note that the methods are called
|
||||
* directly and not through {@link PicoPluginInterface::handleEvent()}.
|
||||
*
|
||||
* @param string $eventName event to trigger
|
||||
* @param array $params parameters to pass
|
||||
* @return void
|
||||
*/
|
||||
protected function triggerEvent($eventName, array $params = array())
|
||||
{
|
||||
foreach ($this->getPlugins() as $plugin) {
|
||||
if (method_exists($plugin, $eventName)) {
|
||||
call_user_func_array(array($plugin, $eventName), $params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
40
plugins/01-PicoParsePagesContent.php
Normal file
40
plugins/01-PicoParsePagesContent.php
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Parses the contents of all pages
|
||||
*
|
||||
* This plugin exists for backward compatibility and is disabled by default.
|
||||
* It gets automatically enabled when {@link PicoDeprecated} is enabled. You
|
||||
* can avoid this by calling {@link PicoParsePagesContent::setEnabled()}.
|
||||
*
|
||||
* This plugin heavily impacts Pico's performance, you should avoid to enable
|
||||
* it whenever possible! If you must parse the contents of a page, do this
|
||||
* selectively and only for pages you really need to.
|
||||
*
|
||||
* @author Daniel Rudolf
|
||||
* @link http://picocms.org
|
||||
* @license http://opensource.org/licenses/MIT
|
||||
* @version 1.0
|
||||
*/
|
||||
class PicoParsePagesContent extends AbstractPicoPlugin
|
||||
{
|
||||
/**
|
||||
* This plugin is disabled by default
|
||||
*
|
||||
* @see AbstractPicoPlugin::$enabled
|
||||
*/
|
||||
protected $enabled = false;
|
||||
|
||||
/**
|
||||
* Parses the contents of all pages
|
||||
*
|
||||
* @see DummyPlugin::onSinglePageLoaded()
|
||||
*/
|
||||
public function onSinglePageLoaded(array &$pageData)
|
||||
{
|
||||
if (!isset($pageData['content'])) {
|
||||
$pageData['content'] = $this->prepareFileContent($pageData['raw_content'], $pageData['meta']);
|
||||
$pageData['content'] = $this->parseFileContent($pageData['content']);
|
||||
}
|
||||
}
|
||||
}
|
81
plugins/02-PicoExcerpt.php
Normal file
81
plugins/02-PicoExcerpt.php
Normal file
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Creates a excerpt for the contents of each page (as of Pico v0.9 and older)
|
||||
*
|
||||
* This plugin exists for backward compatibility and is disabled by default.
|
||||
* It gets automatically enabled when {@link PicoDeprecated} is enabled. You
|
||||
* can avoid this by calling {@link PicoExcerpt::setEnabled()}.
|
||||
*
|
||||
* This plugin doesn't do its job very well and depends on
|
||||
* {@link PicoParsePagesContent}, what heavily impacts Pico's performance. You
|
||||
* should either use the Description meta header field or write something own.
|
||||
* Best solution seems to be a filter for twig, see e.g.
|
||||
* {@link https://gist.github.com/james2doyle/6629712}.
|
||||
*
|
||||
* @author Daniel Rudolf
|
||||
* @link http://picocms.org
|
||||
* @license http://opensource.org/licenses/MIT
|
||||
* @version 1.0
|
||||
*/
|
||||
class PicoExcerpt extends AbstractPicoPlugin
|
||||
{
|
||||
/**
|
||||
* This plugin is disabled by default
|
||||
*
|
||||
* @see AbstractPicoPlugin::$enabled
|
||||
*/
|
||||
protected $enabled = false;
|
||||
|
||||
/**
|
||||
* This plugin depends on PicoParsePagesContent
|
||||
*
|
||||
* @see PicoParsePagesContent
|
||||
* @see AbstractPicoPlugin::$dependsOn
|
||||
*/
|
||||
protected $dependsOn = array('PicoParsePagesContent');
|
||||
|
||||
/**
|
||||
* Adds the default excerpt length of 50 words to the config
|
||||
*
|
||||
* @see DummyPlugin::onConfigLoaded()
|
||||
*/
|
||||
public function onConfigLoaded(array &$config)
|
||||
{
|
||||
if (!isset($config['excerpt_length'])) {
|
||||
$config['excerpt_length'] = 50;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a excerpt for the contents of each page
|
||||
*
|
||||
* @see PicoExcerpt::createExcerpt()
|
||||
* @see DummyPlugin::onSinglePageLoaded()
|
||||
*/
|
||||
public function onSinglePageLoaded(array &$pageData)
|
||||
{
|
||||
if (!isset($pageData['excerpt'])) {
|
||||
$pageData['excerpt'] = $this->createExcerpt(
|
||||
strip_tags($pageData['content']),
|
||||
$this->getConfig('excerpt_length')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to create a excerpt of a string
|
||||
*
|
||||
* @param string $string the string to create a excerpt from
|
||||
* @param int $wordLimit the maximum number of words the excerpt should be long
|
||||
* @return string excerpt of $string
|
||||
*/
|
||||
protected function createExcerpt($string, $wordLimit)
|
||||
{
|
||||
$words = explode(' ', $string);
|
||||
if (count($words) > $wordLimit) {
|
||||
return trim(implode(' ', array_slice($words, 0, $wordLimit))) . '…';
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
}
|
|
@ -1,14 +1,4 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of Pico. It's copyrighted by the contributors recorded
|
||||
* in the version control history of the file, available from the following
|
||||
* original location:
|
||||
*
|
||||
* <https://github.com/picocms/Pico/blob/master/plugins/DummyPlugin.php>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* License-Filename: LICENSE
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pico dummy plugin - a template for plugins
|
||||
|
@ -18,51 +8,22 @@
|
|||
*
|
||||
* @author Daniel Rudolf
|
||||
* @link http://picocms.org
|
||||
* @license http://opensource.org/licenses/MIT The MIT License
|
||||
* @version 2.1
|
||||
* @license http://opensource.org/licenses/MIT
|
||||
* @version 1.0
|
||||
*/
|
||||
class DummyPlugin extends AbstractPicoPlugin
|
||||
final class DummyPlugin extends AbstractPicoPlugin
|
||||
{
|
||||
/**
|
||||
* API version used by this plugin
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const API_VERSION = 3;
|
||||
|
||||
/**
|
||||
* This plugin is disabled by default
|
||||
*
|
||||
* Usually you should remove this class property (or set it to NULL) to
|
||||
* leave the decision whether this plugin should be enabled or disabled by
|
||||
* default up to Pico. If all the plugin's dependenies are fulfilled (see
|
||||
* {@see DummyPlugin::$dependsOn}), Pico enables the plugin by default.
|
||||
* Otherwise the plugin is silently disabled.
|
||||
*
|
||||
* If this plugin should never be disabled *silently* (e.g. when dealing
|
||||
* with security-relevant stuff like access control, or similar), set this
|
||||
* to TRUE. If Pico can't fulfill all the plugin's dependencies, it will
|
||||
* throw an RuntimeException.
|
||||
*
|
||||
* If this plugin rather does some "crazy stuff" a user should really be
|
||||
* aware of before using it, you can set this to FALSE. The user will then
|
||||
* have to enable the plugin manually. However, if another plugin depends
|
||||
* on this plugin, it might get enabled silently nevertheless.
|
||||
*
|
||||
* No matter what, the user can always explicitly enable or disable this
|
||||
* plugin in Pico's config.
|
||||
* This plugin is enabled by default?
|
||||
*
|
||||
* @see AbstractPicoPlugin::$enabled
|
||||
* @var bool|null
|
||||
* @var boolean
|
||||
*/
|
||||
protected $enabled = false;
|
||||
|
||||
/**
|
||||
* This plugin depends on ...
|
||||
*
|
||||
* If your plugin doesn't depend on any other plugin, remove this class
|
||||
* property.
|
||||
*
|
||||
* @see AbstractPicoPlugin::$dependsOn
|
||||
* @var string[]
|
||||
*/
|
||||
|
@ -74,27 +35,12 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
* This event is triggered nevertheless the plugin is enabled or not.
|
||||
* It is NOT guaranteed that plugin dependencies are fulfilled!
|
||||
*
|
||||
* @see Pico::loadPlugin()
|
||||
* @see Pico::getPlugin()
|
||||
* @see Pico::getPlugins()
|
||||
*
|
||||
* @param object[] $plugins loaded plugin instances
|
||||
* @see Pico::getPlugin()
|
||||
* @see Pico::getPlugins()
|
||||
* @param object[] &$plugins loaded plugin instances
|
||||
* @return void
|
||||
*/
|
||||
public function onPluginsLoaded(array $plugins)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when Pico manually loads a plugin
|
||||
*
|
||||
* @see Pico::loadPlugin()
|
||||
* @see Pico::getPlugin()
|
||||
* @see Pico::getPlugins()
|
||||
*
|
||||
* @param object $plugin loaded plugin instance
|
||||
*/
|
||||
public function onPluginManuallyLoaded($plugin)
|
||||
public function onPluginsLoaded(array &$plugins)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
@ -102,52 +48,21 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
/**
|
||||
* Triggered after Pico has read its configuration
|
||||
*
|
||||
* @see Pico::getConfig()
|
||||
* @see Pico::getBaseUrl()
|
||||
* @see Pico::isUrlRewritingEnabled()
|
||||
*
|
||||
* @param array &$config array of config variables
|
||||
* @see Pico::getConfig()
|
||||
* @param mixed[] &$config array of config variables
|
||||
* @return void
|
||||
*/
|
||||
public function onConfigLoaded(array &$config)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered before Pico loads its theme
|
||||
*
|
||||
* @see Pico::loadTheme()
|
||||
* @see DummyPlugin::onThemeLoaded()
|
||||
*
|
||||
* @param string &$theme name of current theme
|
||||
*/
|
||||
public function onThemeLoading(&$theme)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered after Pico loaded its theme
|
||||
*
|
||||
* @see DummyPlugin::onThemeLoading()
|
||||
* @see Pico::getTheme()
|
||||
* @see Pico::getThemeApiVersion()
|
||||
*
|
||||
* @param string $theme name of current theme
|
||||
* @param int $themeApiVersion API version of the theme
|
||||
* @param array &$themeConfig config array of the theme
|
||||
*/
|
||||
public function onThemeLoaded($theme, $themeApiVersion, array &$themeConfig)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered after Pico has evaluated the request URL
|
||||
*
|
||||
* @see Pico::getRequestUrl()
|
||||
*
|
||||
* @param string &$url part of the URL describing the requested contents
|
||||
* @see Pico::getRequestUrl()
|
||||
* @param string &$url part of the URL describing the requested contents
|
||||
* @return void
|
||||
*/
|
||||
public function onRequestUrl(&$url)
|
||||
{
|
||||
|
@ -157,10 +72,10 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
/**
|
||||
* Triggered after Pico has discovered the content file to serve
|
||||
*
|
||||
* @see Pico::resolveFilePath()
|
||||
* @see Pico::getRequestFile()
|
||||
*
|
||||
* @param string &$file absolute path to the content file to serve
|
||||
* @see Pico::getBaseUrl()
|
||||
* @see Pico::getRequestFile()
|
||||
* @param string &$file absolute path to the content file to serve
|
||||
* @return void
|
||||
*/
|
||||
public function onRequestFile(&$file)
|
||||
{
|
||||
|
@ -170,35 +85,12 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
/**
|
||||
* Triggered before Pico reads the contents of the file to serve
|
||||
*
|
||||
* @see Pico::loadFileContent()
|
||||
* @see DummyPlugin::onContentLoaded()
|
||||
* @see Pico::loadFileContent()
|
||||
* @see DummyPlugin::onContentLoaded()
|
||||
* @param string &$file path to the file which contents will be read
|
||||
* @return void
|
||||
*/
|
||||
public function onContentLoading()
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered before Pico reads the contents of a 404 file
|
||||
*
|
||||
* @see Pico::load404Content()
|
||||
* @see DummyPlugin::on404ContentLoaded()
|
||||
*/
|
||||
public function on404ContentLoading()
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered after Pico has read the contents of the 404 file
|
||||
*
|
||||
* @see DummyPlugin::on404ContentLoading()
|
||||
* @see Pico::getRawContent()
|
||||
* @see Pico::is404Content()
|
||||
*
|
||||
* @param string &$rawContent raw file contents
|
||||
*/
|
||||
public function on404ContentLoaded(&$rawContent)
|
||||
public function onContentLoading(&$file)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
@ -206,28 +98,64 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
/**
|
||||
* Triggered after Pico has read the contents of the file to serve
|
||||
*
|
||||
* If Pico serves a 404 file, this event is triggered with the raw contents
|
||||
* of said 404 file. Use {@see Pico::is404Content()} to check for this
|
||||
* case when necessary.
|
||||
*
|
||||
* @see DummyPlugin::onContentLoading()
|
||||
* @see Pico::getRawContent()
|
||||
* @see Pico::is404Content()
|
||||
*
|
||||
* @param string &$rawContent raw file contents
|
||||
* @see Pico::getRawContent()
|
||||
* @param string &$rawContent raw file contents
|
||||
* @return void
|
||||
*/
|
||||
public function onContentLoaded(&$rawContent)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered before Pico reads the contents of a 404 file
|
||||
*
|
||||
* @see Pico::load404Content()
|
||||
* @see DummyPlugin::on404ContentLoaded()
|
||||
* @param string &$file path to the file which contents were requested
|
||||
* @return void
|
||||
*/
|
||||
public function on404ContentLoading(&$file)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered after Pico has read the contents of the 404 file
|
||||
*
|
||||
* @see Pico::getRawContent()
|
||||
* @param string &$rawContent raw file contents
|
||||
* @return void
|
||||
*/
|
||||
public function on404ContentLoaded(&$rawContent)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when Pico reads its known meta header fields
|
||||
*
|
||||
* @see Pico::getMetaHeaders()
|
||||
* @param string[] &$headers list of known meta header
|
||||
* fields; the array value specifies the YAML key to search for, the
|
||||
* array key is later used to access the found value
|
||||
* @return void
|
||||
*/
|
||||
public function onMetaHeaders(array &$headers)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered before Pico parses the meta header
|
||||
*
|
||||
* @see Pico::parseFileMeta()
|
||||
* @see DummyPlugin::onMetaParsed()
|
||||
* @see Pico::parseFileMeta()
|
||||
* @see DummyPlugin::onMetaParsed()
|
||||
* @param string &$rawContent raw file contents
|
||||
* @param string[] &$headers known meta header fields
|
||||
* @return void
|
||||
*/
|
||||
public function onMetaParsing()
|
||||
public function onMetaParsing(&$rawContent, array &$headers)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
@ -235,10 +163,9 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
/**
|
||||
* Triggered after Pico has parsed the meta header
|
||||
*
|
||||
* @see DummyPlugin::onMetaParsing()
|
||||
* @see Pico::getFileMeta()
|
||||
*
|
||||
* @param string[] &$meta parsed meta data
|
||||
* @see Pico::getFileMeta()
|
||||
* @param string[] &$meta parsed meta data
|
||||
* @return void
|
||||
*/
|
||||
public function onMetaParsed(array &$meta)
|
||||
{
|
||||
|
@ -248,12 +175,13 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
/**
|
||||
* Triggered before Pico parses the pages content
|
||||
*
|
||||
* @see Pico::prepareFileContent()
|
||||
* @see Pico::substituteFileContent()
|
||||
* @see DummyPlugin::onContentPrepared()
|
||||
* @see DummyPlugin::onContentParsed()
|
||||
* @see Pico::prepareFileContent()
|
||||
* @see DummyPlugin::prepareFileContent()
|
||||
* @see DummyPlugin::onContentParsed()
|
||||
* @param string &$rawContent raw file contents
|
||||
* @return void
|
||||
*/
|
||||
public function onContentParsing()
|
||||
public function onContentParsing(&$rawContent)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
@ -261,13 +189,12 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
/**
|
||||
* Triggered after Pico has prepared the raw file contents for parsing
|
||||
*
|
||||
* @see DummyPlugin::onContentParsing()
|
||||
* @see Pico::parseFileContent()
|
||||
* @see DummyPlugin::onContentParsed()
|
||||
*
|
||||
* @param string &$markdown Markdown contents of the requested page
|
||||
* @see Pico::parseFileContent()
|
||||
* @see DummyPlugin::onContentParsed()
|
||||
* @param string &$content prepared file contents for parsing
|
||||
* @return void
|
||||
*/
|
||||
public function onContentPrepared(&$markdown)
|
||||
public function onContentPrepared(&$content)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
@ -275,11 +202,9 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
/**
|
||||
* Triggered after Pico has parsed the contents of the file to serve
|
||||
*
|
||||
* @see DummyPlugin::onContentParsing()
|
||||
* @see DummyPlugin::onContentPrepared()
|
||||
* @see Pico::getFileContent()
|
||||
*
|
||||
* @param string &$content parsed contents (HTML) of the requested page
|
||||
* @see Pico::getFileContent()
|
||||
* @param string &$content parsed contents
|
||||
* @return void
|
||||
*/
|
||||
public function onContentParsed(&$content)
|
||||
{
|
||||
|
@ -289,8 +214,10 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
/**
|
||||
* Triggered before Pico reads all known pages
|
||||
*
|
||||
* @see DummyPlugin::onPagesDiscovered()
|
||||
* @see DummyPlugin::onPagesLoaded()
|
||||
* @see Pico::readPages()
|
||||
* @see DummyPlugin::onSinglePageLoaded()
|
||||
* @see DummyPlugin::onPagesLoaded()
|
||||
* @return void
|
||||
*/
|
||||
public function onPagesLoading()
|
||||
{
|
||||
|
@ -298,54 +225,26 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
}
|
||||
|
||||
/**
|
||||
* Triggered before Pico loads a single page
|
||||
* Triggered when Pico reads a single page from the list of all known pages
|
||||
*
|
||||
* Set the `$skipFile` parameter to TRUE to remove this page from the pages
|
||||
* array. Pico usually passes NULL by default, unless it is a conflicting
|
||||
* page (i.e. `content/sub.md`, but there's also a `content/sub/index.md`),
|
||||
* then it passes TRUE. Don't change this value incautiously if it isn't
|
||||
* NULL! Someone likely set it to TRUE or FALSE on purpose...
|
||||
* The `$pageData` parameter consists of the following values:
|
||||
*
|
||||
* @see DummyPlugin::onSinglePageContent()
|
||||
* @see DummyPlugin::onSinglePageLoaded()
|
||||
* | Array key | Type | Description |
|
||||
* | -------------- | ------ | ---------------------------------------- |
|
||||
* | id | string | relative path to the content file |
|
||||
* | url | string | URL to the page |
|
||||
* | title | string | title of the page (YAML header) |
|
||||
* | description | string | description of the page (YAML header) |
|
||||
* | author | string | author of the page (YAML header) |
|
||||
* | time | string | timestamp derived from the Date header |
|
||||
* | date | string | date of the page (YAML header) |
|
||||
* | date_formatted | string | formatted date of the page |
|
||||
* | raw_content | string | raw, not yet parsed contents of the page |
|
||||
* | meta | string | parsed meta data of the page |
|
||||
*
|
||||
* @param string $id relative path to the content file
|
||||
* @param bool|null $skipPage set this to TRUE to remove this page from the
|
||||
* pages array, otherwise leave it unchanged
|
||||
*/
|
||||
public function onSinglePageLoading($id, &$skipPage)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when Pico loads the raw contents of a single page
|
||||
*
|
||||
* Please note that this event isn't triggered when the currently processed
|
||||
* page is the requested page. The reason for this exception is that the
|
||||
* raw contents of this page were loaded already.
|
||||
*
|
||||
* @see DummyPlugin::onSinglePageLoading()
|
||||
* @see DummyPlugin::onSinglePageLoaded()
|
||||
*
|
||||
* @param string $id relative path to the content file
|
||||
* @param string &$rawContent raw file contents
|
||||
*/
|
||||
public function onSinglePageContent($id, &$rawContent)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when Pico loads a single page
|
||||
*
|
||||
* Please refer to {@see Pico::readPages()} for information about the
|
||||
* structure of a single page's data.
|
||||
*
|
||||
* @see DummyPlugin::onSinglePageLoading()
|
||||
* @see DummyPlugin::onSinglePageContent()
|
||||
*
|
||||
* @param array &$pageData data of the loaded page
|
||||
* @see DummyPlugin::onPagesLoaded()
|
||||
* @param array &$pageData data of the loaded page
|
||||
* @return void
|
||||
*/
|
||||
public function onSinglePageLoaded(array &$pageData)
|
||||
{
|
||||
|
@ -353,58 +252,23 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
}
|
||||
|
||||
/**
|
||||
* Triggered after Pico has discovered all known pages
|
||||
* Triggered after Pico has read all known pages
|
||||
*
|
||||
* Pico's pages array isn't sorted until the `onPagesLoaded` event is
|
||||
* triggered. Please refer to {@see Pico::readPages()} for information
|
||||
* about the structure of Pico's pages array and the structure of a single
|
||||
* page's data.
|
||||
* See {@link DummyPlugin::onSinglePageLoaded()} for details about the
|
||||
* structure of the page data.
|
||||
*
|
||||
* @see DummyPlugin::onPagesLoading()
|
||||
* @see DummyPlugin::onPagesLoaded()
|
||||
*
|
||||
* @param array[] &$pages list of all known pages
|
||||
* @see Pico::getPages()
|
||||
* @see Pico::getCurrentPage()
|
||||
* @see Pico::getPreviousPage()
|
||||
* @see Pico::getNextPage()
|
||||
* @param array[] &$pages data of all known pages
|
||||
* @param array|null &$currentPage data of the page being served
|
||||
* @param array|null &$previousPage data of the previous page
|
||||
* @param array|null &$nextPage data of the next page
|
||||
* @return void
|
||||
*/
|
||||
public function onPagesDiscovered(array &$pages)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered after Pico has sorted the pages array
|
||||
*
|
||||
* Please refer to {@see Pico::readPages()} for information about the
|
||||
* structure of Pico's pages array and the structure of a single page's
|
||||
* data.
|
||||
*
|
||||
* @see DummyPlugin::onPagesLoading()
|
||||
* @see DummyPlugin::onPagesDiscovered()
|
||||
* @see Pico::getPages()
|
||||
*
|
||||
* @param array[] &$pages sorted list of all known pages
|
||||
*/
|
||||
public function onPagesLoaded(array &$pages)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when Pico discovered the current, previous and next pages
|
||||
*
|
||||
* If Pico isn't serving a regular page, but a plugin's virtual page, there
|
||||
* will neither be a current, nor previous or next pages. Please refer to
|
||||
* {@see Pico::readPages()} for information about the structure of a single
|
||||
* page's data.
|
||||
*
|
||||
* @see Pico::getCurrentPage()
|
||||
* @see Pico::getPreviousPage()
|
||||
* @see Pico::getNextPage()
|
||||
*
|
||||
* @param array|null &$currentPage data of the page being served
|
||||
* @param array|null &$previousPage data of the previous page
|
||||
* @param array|null &$nextPage data of the next page
|
||||
*/
|
||||
public function onCurrentPageDiscovered(
|
||||
public function onPagesLoaded(
|
||||
array &$pages,
|
||||
array &$currentPage = null,
|
||||
array &$previousPage = null,
|
||||
array &$nextPage = null
|
||||
|
@ -413,16 +277,11 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
}
|
||||
|
||||
/**
|
||||
* Triggered after Pico built the page tree
|
||||
* Triggered before Pico registers the twig template engine
|
||||
*
|
||||
* Please refer to {@see Pico::buildPageTree()} for information about
|
||||
* the structure of Pico's page tree array.
|
||||
*
|
||||
* @see Pico::getPageTree()
|
||||
*
|
||||
* @param array &$pageTree page tree
|
||||
* @return void
|
||||
*/
|
||||
public function onPageTreeBuilt(array &$pageTree)
|
||||
public function onTwigRegistration()
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
@ -430,12 +289,14 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
/**
|
||||
* Triggered before Pico renders the page
|
||||
*
|
||||
* @see DummyPlugin::onPageRendered()
|
||||
*
|
||||
* @param string &$templateName file name of the template
|
||||
* @param array &$twigVariables template variables
|
||||
* @see Pico::getTwig()
|
||||
* @see DummyPlugin::onPageRendered()
|
||||
* @param Twig_Environment &$twig twig template engine
|
||||
* @param mixed[] &$twigVariables template variables
|
||||
* @param string &$templateName file name of the template
|
||||
* @return void
|
||||
*/
|
||||
public function onPageRendering(&$templateName, array &$twigVariables)
|
||||
public function onPageRendering(Twig_Environment &$twig, array &$twigVariables, &$templateName)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
@ -443,62 +304,11 @@ class DummyPlugin extends AbstractPicoPlugin
|
|||
/**
|
||||
* Triggered after Pico has rendered the page
|
||||
*
|
||||
* @see DummyPlugin::onPageRendering()
|
||||
*
|
||||
* @param string &$output contents which will be sent to the user
|
||||
* @param string &$output contents which will be sent to the user
|
||||
* @return void
|
||||
*/
|
||||
public function onPageRendered(&$output)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when Pico reads its known meta header fields
|
||||
*
|
||||
* @see Pico::getMetaHeaders()
|
||||
*
|
||||
* @param string[] &$headers list of known meta header fields; the array
|
||||
* key specifies the YAML key to search for, the array value is later
|
||||
* used to access the found value
|
||||
*/
|
||||
public function onMetaHeaders(array &$headers)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when Pico registers the YAML parser
|
||||
*
|
||||
* @see Pico::getYamlParser()
|
||||
*
|
||||
* @param \Symfony\Component\Yaml\Parser &$yamlParser YAML parser instance
|
||||
*/
|
||||
public function onYamlParserRegistered(\Symfony\Component\Yaml\Parser &$yamlParser)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when Pico registers the Parsedown parser
|
||||
*
|
||||
* @see Pico::getParsedown()
|
||||
*
|
||||
* @param Parsedown &$parsedown Parsedown instance
|
||||
*/
|
||||
public function onParsedownRegistered(Parsedown &$parsedown)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered when Pico registers the twig template engine
|
||||
*
|
||||
* @see Pico::getTwig()
|
||||
*
|
||||
* @param Twig_Environment &$twig Twig instance
|
||||
*/
|
||||
public function onTwigRegistered(Twig_Environment &$twig)
|
||||
{
|
||||
// your code
|
||||
}
|
||||
}
|
||||
|
|
2
themes/.gitignore
vendored
2
themes/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
# This directory is meant to be empty
|
||||
*
|
229
themes/alpha/assets/css/bootstrap.theme.css
vendored
Executable file
229
themes/alpha/assets/css/bootstrap.theme.css
vendored
Executable file
|
@ -0,0 +1,229 @@
|
|||
/**
|
||||
* Pico's Default Theme - Twitter Bootstrap 4
|
||||
*
|
||||
* @author Gilbert Pellegrom
|
||||
* @author Tyler Heshka
|
||||
* @link http://picocms.org
|
||||
* @license http://opensource.org/licenses/MIT
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
/* Main Styles
|
||||
/*---------------------------------------------*/
|
||||
body {
|
||||
font: 14px/1.8em 'Open Sans', Helvetica, Arial, Helvetica, sans-serif;
|
||||
color: #444;
|
||||
background: #FFF;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
a, a:visited {
|
||||
color: #2EAE9B;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover, a:active {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
margin-bottom: 0.6em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 20px 0;
|
||||
border: 0;
|
||||
border-top: 1px solid #eeeeee;
|
||||
border-bottom: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
padding: 0 0 0 15px;
|
||||
margin: 0 0 20px;
|
||||
border-left: 5px solid #eeeeee;
|
||||
}
|
||||
|
||||
code,
|
||||
pre {
|
||||
padding: 0 3px 2px;
|
||||
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
|
||||
font-size: 12px;
|
||||
color: #333333;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 2px 4px;
|
||||
color: #333;
|
||||
white-space: nowrap;
|
||||
background-color: #f7f7f9;
|
||||
border: 1px solid #e1e1e8;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
padding: 9.5px;
|
||||
margin: 0 0 10px;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
white-space: pre;
|
||||
white-space: pre-wrap;
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #ccc;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
pre code {
|
||||
padding: 0;
|
||||
color: inherit;
|
||||
white-space: pre;
|
||||
white-space: pre-wrap;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* Nav Styles
|
||||
/*---------------------------------------------*/
|
||||
.navbar {
|
||||
background: #2EAE9B !important;
|
||||
color: #AFE1DA !important;
|
||||
padding: 10px 0;
|
||||
margin-bottom: 0px;
|
||||
-webkit-border-radius: 0 !important;
|
||||
-moz-border-radius: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
color: #FFF !important;
|
||||
font-weight: bold;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.nav-item a {
|
||||
color: #AFE1DA !important;
|
||||
}
|
||||
|
||||
.nav-item a:hover {
|
||||
color: #FFF !important;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
margin-left: -1em;
|
||||
margin-right: -1em;
|
||||
}
|
||||
|
||||
/* Main column and sidebar layout
|
||||
/*---------------------------------------------*/
|
||||
|
||||
/* Sidebar modules for boxing content */
|
||||
.sidebar-module {
|
||||
padding: 1rem;
|
||||
}
|
||||
.sidebar-module-inset {
|
||||
padding: 1rem;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: .25rem;
|
||||
}
|
||||
.sidebar-module-inset p:last-child,
|
||||
.sidebar-module-inset ul:last-child,
|
||||
.sidebar-module-inset ol:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Blog posts
|
||||
/*---------------------------------------------*/
|
||||
|
||||
.blog-post {
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
.blog-post-title {
|
||||
margin-bottom: .25rem;
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
.blog-post-meta {
|
||||
margin-bottom: 1.25rem;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* Footer Styles
|
||||
/*---------------------------------------------*/
|
||||
.footer {
|
||||
background: #707070;
|
||||
padding: 10px 0;
|
||||
margin-top: 100px;
|
||||
color: #C0C0C0;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
color: #DDD;
|
||||
}
|
||||
|
||||
.footer a:hover {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
/* Media Queries
|
||||
/*---------------------------------------------*/
|
||||
|
||||
/* Small devices (landscape phones, 34em and up) */
|
||||
@media (min-width: 34em) {
|
||||
.navbar {
|
||||
padding: 20px 0;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 20px 0;
|
||||
margin-top: 90px;
|
||||
}
|
||||
}
|
||||
/* Medium devices (tablets, 48em and up) */
|
||||
@media (min-width: 48em) {
|
||||
.navbar {
|
||||
padding: 30px 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 30px 0;
|
||||
margin-top: 100px;
|
||||
}
|
||||
}
|
||||
/* Large devices (desktops, 62em and up) */
|
||||
@media (min-width: 62em) {
|
||||
.navbar {
|
||||
padding: 40px 0;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 40px 0;
|
||||
margin-top: 110px;
|
||||
}
|
||||
}
|
||||
/* Extra large devices (large desktops, 75em and up) */
|
||||
@media (min-width: 75em) {
|
||||
.navbar {
|
||||
padding: 50px 0;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 50px 0;
|
||||
margin-top: 120px;
|
||||
}
|
||||
}
|
20
themes/alpha/blog-post-full.twig
Normal file
20
themes/alpha/blog-post-full.twig
Normal file
|
@ -0,0 +1,20 @@
|
|||
{% include 'includes/htmlHead.twig' %}
|
||||
{% include 'includes/head.twig' %}
|
||||
<body>
|
||||
{% include 'includes/nav.twig' %}
|
||||
<!-- Main Content -->
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
{% include 'includes/blog-breadcrumb.twig' %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{% include 'includes/blog-meta.twig' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'includes/foot.twig' %}
|
||||
</body>
|
||||
{% include 'includes/htmlFoot.twig' %}
|
23
themes/alpha/blog-post.twig
Normal file
23
themes/alpha/blog-post.twig
Normal file
|
@ -0,0 +1,23 @@
|
|||
{% include 'includes/htmlHead.twig' %}
|
||||
{% include 'includes/head.twig' %}
|
||||
<body>
|
||||
{% include 'includes/nav.twig' %}
|
||||
<!-- Main Content -->
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
{% include 'includes/blog-breadcrumb.twig' %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-8">
|
||||
{% include 'includes/blog-meta.twig' %}
|
||||
</div>
|
||||
<div class="col-sm-3 col-sm-offset-1">
|
||||
{% include 'includes/blog-sidebar.twig' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'includes/foot.twig' %}
|
||||
</body>
|
||||
{% include 'includes/htmlFoot.twig' %}
|
18
themes/alpha/blog.twig
Normal file
18
themes/alpha/blog.twig
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% include 'includes/htmlHead.twig' %}
|
||||
{% include 'includes/head.twig' %}
|
||||
<body>
|
||||
{% include 'includes/nav.twig' %}
|
||||
<!-- Main Content -->
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-8">
|
||||
{% include 'includes/blog-list.twig' %}
|
||||
</div>
|
||||
<div class="col-sm-3 col-sm-offset-1">
|
||||
{% include 'includes/blog-sidebar.twig' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'includes/foot.twig' %}
|
||||
</body>
|
||||
{% include 'includes/htmlFoot.twig' %}
|
5
themes/alpha/includes/blog-breadcrumb.twig
Normal file
5
themes/alpha/includes/blog-breadcrumb.twig
Normal file
|
@ -0,0 +1,5 @@
|
|||
<!-- Breadcrumbs -->
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="{{ "blog" | link }}">Blog</a></li>
|
||||
<li class="active">{{ meta.title }}</li>
|
||||
</ol>
|
17
themes/alpha/includes/blog-list.twig
Normal file
17
themes/alpha/includes/blog-list.twig
Normal file
|
@ -0,0 +1,17 @@
|
|||
<!-- Blog List -->
|
||||
{% for page in pages|sort_by("time")|reverse %}
|
||||
{% if page.id starts with "blog/" %}
|
||||
<!-- Blog Post Meta -->
|
||||
<div class="blog-post">
|
||||
<!-- Blog Post Meta -->
|
||||
<h2 class="blog-post-title"><a href="{{ page.url }}">{{ page.title }}</a></h2>
|
||||
<p class="blog-post-meta">
|
||||
<i class="fa fa-calendar"></i> {{ page.date }}
|
||||
by <strong>{{ page.author }}</strong>
|
||||
</p>
|
||||
<!-- Blog Content -->
|
||||
{{ page.description|slice(0, 500) }}
|
||||
</div>
|
||||
<hr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
16
themes/alpha/includes/blog-meta.twig
Normal file
16
themes/alpha/includes/blog-meta.twig
Normal file
|
@ -0,0 +1,16 @@
|
|||
<!-- Blog Post -->
|
||||
<div class="blog-post">
|
||||
<!-- Blog Post Meta -->
|
||||
<h2 class="blog-post-title">{{ meta.title }}</h2>
|
||||
<p class="blog-post-meta">
|
||||
<i class="fa fa-calendar"></i> {{ meta.date }}
|
||||
by <strong>{{ meta.author }}</strong>
|
||||
</p>
|
||||
<hr>
|
||||
<!-- Blog Image -->
|
||||
{% if meta.image %}
|
||||
<img src="{{ meta.image }}" class="img-responsive" alt="{{ meta.image }}" /><br>
|
||||
{% endif %}
|
||||
<!-- Blog Content -->
|
||||
{{content}}
|
||||
</div>
|
51
themes/alpha/includes/blog-sidebar.twig
Normal file
51
themes/alpha/includes/blog-sidebar.twig
Normal file
|
@ -0,0 +1,51 @@
|
|||
<!-- Sidebar -->
|
||||
<div class="sidebar-module">
|
||||
<h4>Connect with {{ site_title }}</h4>
|
||||
<ol class="list-unstyled">
|
||||
{% if config.theme_config.social_media.github %}
|
||||
<li>
|
||||
<a href="https://github.com/{{config.theme_config.social_media.github}}">
|
||||
<i class="fa fa-github fa-fw fa-2x"></i><span class="lead"> GitHub</span>
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>
|
||||
<a href="https://github.com/picocms/Pico.git">
|
||||
<i class="fa fa-github fa-fw fa-2x"></i><span class="lead"> GitHub</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if config.theme_config.social_media.facebook %}
|
||||
<li>
|
||||
<a href="https://facebook.com/{{config.theme_config.social_media.facebook}}">
|
||||
<i class="fa fa-facebook fa-fw fa-2x"></i><span class="lead"> Facebook</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if config.theme_config.social_media.twitter %}
|
||||
<li>
|
||||
<a href="https://twitter.com/{{config.theme_config.social_media.twitter}}">
|
||||
<i class="fa fa-twitter fa-fw fa-2x"></i><span class="lead"> Twitter</span>
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>
|
||||
<a href="https://twitter.com/gitpicocms">
|
||||
<i class="fa fa-twitter fa-fw fa-2x"></i><span class="lead"> Twitter</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-module sidebar-module-inset">
|
||||
<h4>About {{ site_title }}</h4>
|
||||
{% if config.theme_config.about_us %}
|
||||
<p>{{ config.theme_config.about_us }}</p>
|
||||
{% else %}
|
||||
<p>Pico is a stupidly simple, blazing fast, flat file CMS,
|
||||
this means there is no administration backend or database
|
||||
to deal with. You simply create `.md` files in the `content-sample`
|
||||
folder and that becomes a page.</p>
|
||||
{% endif %}
|
||||
</div>
|
21
themes/alpha/includes/foot.twig
Normal file
21
themes/alpha/includes/foot.twig
Normal file
|
@ -0,0 +1,21 @@
|
|||
<!-- Footer -->
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<p class="text-center">
|
||||
{% if config.theme_config.copyright %}
|
||||
{{ config.theme_config.copyright }}
|
||||
{% else %}
|
||||
<a href="http://picocms.org/">Pico</a>
|
||||
was made by <a href="http://gilbert.pellegrom.me">Gilbert Pellegrom</a>
|
||||
and is maintained by <a href="https://github.com/picocms/Pico/graphs/contributors">The Pico Community</a>.
|
||||
Released under the MIT License.
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Javascript -->
|
||||
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
|
||||
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha/js/bootstrap.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
|
||||
<script src="//raw.githubusercontent.com/chuckcarpenter/REM-unit-polyfill/1.3.4/js/rem.min.js"></script>
|
33
themes/alpha/includes/head.twig
Normal file
33
themes/alpha/includes/head.twig
Normal file
|
@ -0,0 +1,33 @@
|
|||
<head>
|
||||
<!-- Page Meta -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="generator" content="Pico 1.0">
|
||||
|
||||
<!-- Post Meta -->
|
||||
{% if meta.description %}
|
||||
<meta name="description" content="{{ meta.description|striptags }}">
|
||||
{% endif %}{% if meta.robots %}
|
||||
<meta name="robots" content="{{ meta.robots }}">
|
||||
{% endif %}{% if meta.author %}
|
||||
<meta name="author" content="{{ meta.author }}">
|
||||
{% endif %}
|
||||
|
||||
<!-- Page Title -->
|
||||
<title>{% if meta.title %}{{ meta.title }} | {% endif %}{{ site_title }}</title>
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Open+Sans:400,700" type="text/css">
|
||||
|
||||
<!-- Stylesheets -->
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha/css/bootstrap.min.css" type="text/css" />
|
||||
<link rel="stylesheet" href="{{ theme_url }}/assets/css/bootstrap.theme.css" type="text/css" />
|
||||
|
||||
<!-- Icons -->
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
|
||||
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
1
themes/alpha/includes/htmlFoot.twig
Normal file
1
themes/alpha/includes/htmlFoot.twig
Normal file
|
@ -0,0 +1 @@
|
|||
</html>
|
2
themes/alpha/includes/htmlHead.twig
Normal file
2
themes/alpha/includes/htmlHead.twig
Normal file
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
20
themes/alpha/includes/nav.twig
Normal file
20
themes/alpha/includes/nav.twig
Normal file
|
@ -0,0 +1,20 @@
|
|||
<!-- Navigation -->
|
||||
<nav class="navbar navbar-light">
|
||||
<button class="navbar-toggler hidden-sm-up pull-right" type="button" data-toggle="collapse" data-target="#CollapsingNavbar">
|
||||
☰
|
||||
</button>
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="{{ 'index'|link }}">{{ site_title }}</a>
|
||||
<div class="collapse navbar-toggleable-xs" id="CollapsingNavbar">
|
||||
<ul class="nav navbar-nav pull-right">
|
||||
{% for page in pages %}
|
||||
{% if page.id starts with "blog/" %}{% else %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ page.url }}">{{ page.title }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
15
themes/alpha/index.twig
Executable file
15
themes/alpha/index.twig
Executable file
|
@ -0,0 +1,15 @@
|
|||
{% include 'includes/htmlHead.twig' %}
|
||||
{% include 'includes/head.twig' %}
|
||||
<body>
|
||||
{% include 'includes/nav.twig' %}
|
||||
<!-- Main Content -->
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
{{ content }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'includes/foot.twig' %}
|
||||
</body>
|
||||
{% include 'includes/htmlFoot.twig' %}
|
50
themes/default/index.html
Normal file
50
themes/default/index.html
Normal file
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" class="no-js">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<title>{% if meta.title %}{{ meta.title }} | {% endif %}{{ site_title }}</title>
|
||||
{% if meta.description %}
|
||||
<meta name="description" content="{{ meta.description }}">
|
||||
{% endif %}{% if meta.robots %}
|
||||
<meta name="robots" content="{{ meta.robots }}">
|
||||
{% endif %}
|
||||
|
||||
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Open+Sans:400,700" type="text/css" />
|
||||
<link rel="stylesheet" href="{{ theme_url }}/style.css" type="text/css" />
|
||||
|
||||
<script src="{{ theme_url }}/scripts/modernizr-2.6.1.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header id="header">
|
||||
<div class="inner clearfix">
|
||||
<h1><a href="{{ base_url }}" id="logo">{{ site_title }}</a></h1>
|
||||
<nav>
|
||||
<a href="#" class="menu-icon"></a>
|
||||
<ul>
|
||||
{% for page in pages %}
|
||||
{% if page.id starts with "blog" %}{% else %}
|
||||
<li><a href="{{ page.url }}">{{ page.title }}</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section id="content">
|
||||
<div class="inner">
|
||||
{{ content }}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer id="footer">
|
||||
<div class="inner">
|
||||
<a href="http://picocms.org/">Pico</a> was made by <a href="http://gilbert.pellegrom.me">Gilbert Pellegrom</a>
|
||||
from <a href="http://dev7studios.com">Dev7studios</a>.
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
themes/default/menu-icon.png
Normal file
BIN
themes/default/menu-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
4
themes/default/scripts/modernizr-2.6.1.min.js
vendored
Normal file
4
themes/default/scripts/modernizr-2.6.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
372
themes/default/style.css
Normal file
372
themes/default/style.css
Normal file
|
@ -0,0 +1,372 @@
|
|||
/*=================================*/
|
||||
/* Pico Default Theme
|
||||
/* By: Gilbert Pellegrom
|
||||
/* http: //dev7studios.com
|
||||
/*=================================*/
|
||||
|
||||
/* Reset Styles
|
||||
/*---------------------------------------------*/
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, font, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
font-weight: inherit;
|
||||
font-style: inherit;
|
||||
font-size: 100%;
|
||||
font-family: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
body {
|
||||
line-height: 1;
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
caption, th, td {
|
||||
text-align: left;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: "";
|
||||
}
|
||||
|
||||
blockquote, q {
|
||||
quotes: "" "";
|
||||
}
|
||||
|
||||
/* HTML5 tags */
|
||||
header, section, footer,
|
||||
aside, nav, article, figure {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* hand cursor on clickable input elements */
|
||||
label, input[type=button], input[type=submit], button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* make buttons play nice in IE:
|
||||
www.viget.com/inspire/styling-the-button-element-in-internet-explorer/ */
|
||||
button {
|
||||
width: auto;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/* Sharper Thumbnails */
|
||||
img {
|
||||
-ms-interpolation-mode: bicubic;
|
||||
}
|
||||
|
||||
/* Input Styles
|
||||
/*---------------------------------------------*/
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
padding: 5px;
|
||||
font: 400 1em Verdana, Sans-serif;
|
||||
color: #666;
|
||||
background: #fff;
|
||||
border: 1px solid #999999;
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
|
||||
input:focus,
|
||||
textarea:focus,
|
||||
select:focus {
|
||||
color: #000;
|
||||
background: #fff;
|
||||
border: 1px solid #666666;
|
||||
}
|
||||
|
||||
/* Main Styles
|
||||
/*---------------------------------------------*/
|
||||
body {
|
||||
font: 14px/1.8em 'Open Sans', Helvetica, Arial, Helvetica, sans-serif;
|
||||
color: #444;
|
||||
background: #fff;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
a, a:visited {
|
||||
color: #2EAE9B;
|
||||
text-decoration: none;
|
||||
-webkit-transition: all 0.2s linear;
|
||||
-moz-transition: all 0.2s linear;
|
||||
-ms-transition: all 0.2s linear;
|
||||
-o-transition: all 0.2s linear;
|
||||
transition: all 0.2s linear;
|
||||
}
|
||||
|
||||
a:hover, a:active {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: #000;
|
||||
line-height: 1.2em;
|
||||
margin-bottom: 0.6em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.7em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5em;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
p, table {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
padding-left: 30px;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
b, strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
i, em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
u {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
abbr, acronym {
|
||||
cursor: help;
|
||||
border-bottom: 0.1em dotted;
|
||||
}
|
||||
|
||||
td, td img {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
td, th {
|
||||
border: solid 1px #999;
|
||||
padding: 0.25em 0.5em;
|
||||
}
|
||||
|
||||
th {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
sub {
|
||||
vertical-align: sub;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
sup {
|
||||
vertical-align: super;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: Courier, "Courier New", Monaco, Tahoma;
|
||||
background: #eee;
|
||||
color: #333;
|
||||
padding: 0px 2px;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #eee;
|
||||
padding: 20px;
|
||||
margin-bottom: 1em;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
font-style: italic;
|
||||
margin: 0 0 1em 15px;
|
||||
padding-left: 10px;
|
||||
border-left: 5px solid #dddddd;
|
||||
}
|
||||
|
||||
/* Structure Styles
|
||||
/*---------------------------------------------*/
|
||||
.inner {
|
||||
width: 850px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#header {
|
||||
background: #2EAE9B;
|
||||
padding: 60px 0;
|
||||
margin-bottom: 80px;
|
||||
color: #afe1da;
|
||||
}
|
||||
#header a {
|
||||
color: #afe1da;
|
||||
}
|
||||
#header h1 a,
|
||||
#header a:hover,
|
||||
#header .active a {
|
||||
color: #fff;
|
||||
}
|
||||
#header h1 {
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
float: left;
|
||||
}
|
||||
#header .menu-icon {
|
||||
display: none;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
background: #afe1da url(menu-icon.png) center;
|
||||
}
|
||||
#header nav {
|
||||
float: right;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#header nav a {
|
||||
font-weight: bold;
|
||||
margin-left: 20px;
|
||||
}
|
||||
#header a:hover#menu-icon {
|
||||
background-color: #444;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
#header ul {
|
||||
list-style: none;
|
||||
}
|
||||
#header li {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
}
|
||||
#footer {
|
||||
background: #707070;
|
||||
padding: 60px 0;
|
||||
margin-top: 80px;
|
||||
color: #C0C0C0;
|
||||
}
|
||||
#footer a { color: #ddd; }
|
||||
#footer a:hover { color: #fff; }
|
||||
|
||||
/* Misc Styles
|
||||
/*---------------------------------------------*/
|
||||
.clearfix:before,
|
||||
.clearfix:after {
|
||||
content: " ";
|
||||
display: table;
|
||||
}
|
||||
.clearfix:after {
|
||||
clear: both;
|
||||
}
|
||||
.clearfix {
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
/* Media Queries
|
||||
/*---------------------------------------------*/
|
||||
|
||||
/* Small Devices, Tablets */
|
||||
@media only screen and (max-width : 768px) {
|
||||
.inner {
|
||||
width: 85%;
|
||||
}
|
||||
.inner img {
|
||||
width:100%;
|
||||
}
|
||||
#header {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
#header h1 a {
|
||||
font-size:1em;
|
||||
}
|
||||
#header .menu-icon {
|
||||
display:inline-block;
|
||||
}
|
||||
#header nav a { color: #000; }
|
||||
#header nav a:hover { color: #afe1da; }
|
||||
#header nav ul, nav:active ul {
|
||||
display: none;
|
||||
position: absolute;
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
border: 5px solid #444;
|
||||
right: 2.7em;
|
||||
top: 100px;
|
||||
width: 80%;
|
||||
border-radius: 4px 0 4px 4px;
|
||||
z-index: 9999;
|
||||
}
|
||||
#header nav li {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
padding: 10px 0;
|
||||
margin: 0;
|
||||
}
|
||||
#header nav:hover ul {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Extra Small Devices, Phones */
|
||||
@media only screen and (max-width : 480px) {
|
||||
.inner {
|
||||
width: 85%;
|
||||
}
|
||||
.inner img {
|
||||
width:100%;
|
||||
}
|
||||
#header {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
#header h1 a {
|
||||
font-size:1em;
|
||||
}
|
||||
#header .menu-icon {
|
||||
display:inline-block;
|
||||
}
|
||||
#header nav a { color: #000; }
|
||||
#header nav a:hover { color: #afe1da; }
|
||||
#header nav ul, nav:active ul {
|
||||
display: none;
|
||||
position: absolute;
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
border: 5px solid #444;
|
||||
right: 0em;
|
||||
top: 100px;
|
||||
width: auto;
|
||||
border-radius: 4px 0 4px 4px;
|
||||
}
|
||||
#header nav li {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
padding: 10px 0;
|
||||
margin: 0;
|
||||
}
|
||||
#header nav:hover ul {
|
||||
display: block;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue