Move PicoDeprecated plugin and default theme to separate repos

See https://github.com/picocms/pico-theme for Pico's default theme and https://github.com/picocms/pico-deprecated for the PicoDeprecated plugin.
This commit is contained in:
Daniel Rudolf 2017-05-01 22:12:18 +02:00
parent a39bc38620
commit cbb8ece579
No known key found for this signature in database
GPG Key ID: A061F02CD8DE4538
18 changed files with 11 additions and 1255 deletions

13
.gitignore vendored
View File

@ -20,18 +20,5 @@ desktop.ini
/_build/phpdoc.cache
/_build/deploy-*.git
# User config
/config/config.yml
# User themes
/themes/*
!/themes/default
# User plugins
/plugins/*
!/plugins/0?-*
!/plugins/1?-*
!/plugins/DummyPlugin.php
# User content
/content

View File

@ -25,8 +25,10 @@
"require": {
"php": ">=5.3.6",
"twig/twig": "^1.18",
"symfony/yaml" : "^2.3",
"erusev/parsedown-extra": "^0.7",
"symfony/yaml" : "^2.3"
"picocms/pico-theme": "~2.0.0",
"picocms/pico-deprecated": "~2.0.0"
},
"require-dev" : {
"phpdocumentor/phpdocumentor": "^2.8",

3
config/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# This directory is meant to be empty, except for config.yml.template
*
!config.yml.template

3
plugins/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# This directory is meant to be empty, except for DummyPlugin.php
*
!DummyPlugin.php

View File

@ -1,504 +0,0 @@
<?php
/**
* Maintain backward compatibility to older Pico releases
*
* This plugin exists for backward compatibility and is disabled by default.
* It gets automatically enabled when a plugin which either doesn't implement
* {@link PicoPluginInterface} (plugins for Pico 0.X) or define the
* {@link PicoDeprecated::API_VERSION} (plugins for Pico 1.0) is loaded.
*
* 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 2.0 the config is stored in `config/*.yml` files. This plugin
* also tries to read {@path "config/config.php"} (Pico 1.0) and
* {@path "config.php"} in Pico's root dir (Pico 0.X) and overwrites all
* previously specified settings.
*
* @author Daniel Rudolf
* @link http://picocms.org
* @license http://opensource.org/licenses/MIT The MIT License
* @version 2.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 ($plugins) {
foreach ($plugins as $plugin) {
if (!($plugin instanceof 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 array &$config array of config variables
* @return void
*/
public function onConfigLoaded(array &$config)
{
$this->defineConstants();
$this->loadScriptedConfig($config);
$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 config dir (i.e. config/config.php)
*
* @see PicoDeprecated::onConfigLoaded()
* @see Pico::loadConfig()
* @param array &$realConfig array of config variables
* @return void
*/
protected function loadScriptedConfig(array &$realConfig)
{
if (file_exists($this->getConfigDir() . 'config.php')) {
// scope isolated require()
$includeClosure = function ($configFile) {
require($configFile);
return (isset($config) && is_array($config)) ? $config : array();
};
if (PHP_VERSION_ID >= 50400) {
$includeClosure = $includeClosure->bindTo(null);
}
// config.php in Pico::$configDir (i.e. config/config.php) is deprecated
// use *.yml files in Pico::$configDir instead
$config = $includeClosure($this->getConfigDir() . 'config.php');
if ($config) {
if (!empty($config['base_url'])) {
$config['base_url'] = rtrim($config['base_url'], '/') . '/';
}
if (!empty($config['content_dir'])) {
$config['content_dir'] = $this->getAbsolutePath($config['content_dir']);
}
if (!empty($config['theme_url'])) {
if (preg_match('#^[A-Za-z][A-Za-z0-9+\-.]*://#', $config['theme_url'])) {
$config['theme_url'] = rtrim($config['theme_url'], '/') . '/';
} else {
$config['theme_url'] = $this->getBaseUrl() . rtrim($config['theme_url'], '/') . '/';
}
}
if (!empty($config['timezone'])) {
date_default_timezone_set($config['timezone']);
}
$realConfig = $config + $realConfig;
}
}
}
/**
* Read config.php in Pico's root dir
*
* @see PicoDeprecated::onConfigLoaded()
* @see Pico::loadConfig()
* @param array &$realConfig array of config variables
* @return void
*/
protected function loadRootDirConfig(array &$realConfig)
{
if (file_exists($this->getRootDir() . 'config.php')) {
$config = null;
// scope isolated require()
$includeClosure = function ($configFile) use (&$config) {
require($configFile);
};
if (PHP_VERSION_ID >= 50400) {
$includeClosure = $includeClosure->bindTo(null);
}
// config.php in Pico::$rootDir is deprecated
// use config.php in Pico::$configDir instead
$includeClosure($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');
}
/**
* Adds the deprecated variables rewrite_url and is_front_page, 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)
{
// rewrite_url and is_front_page are deprecated since Pico 2.0
if (!isset($twigVariables['rewrite_url'])) {
$twigVariables['rewrite_url'] = $this->isUrlRewritingEnabled();
}
if (!isset($twigVariables['is_front_page'])) {
$frontPage = $this->getConfig('content_dir') . 'index' . $this->getConfig('content_ext');
$twigVariables['is_front_page'] = ($this->getRequestFile() === $frontPage);
}
// 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);
}
}
}
}

2
themes/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# This directory is meant to be empty
*

View File

@ -1,23 +0,0 @@
Icon fonts generator
## Fontello
Copyright (C) 2011 by Vitaly Puzrin
Author: Vitaly Puzrin
License: The MIT License <https://github.com/fontello/fontello/blob/master/LICENSE>
Homepage: http://fontello.com/
Font license info
## Font Awesome
Copyright (C) 2012 by Dave Gandy
Author: Dave Gandy
License: SIL OFL 1.1 <http://scripts.sil.org/OFL>
Homepage: http://fortawesome.github.com/Font-Awesome/
Icons: menu, github-circled ("octocat"), chat

Binary file not shown.

View File

@ -1,16 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Copyright (C) 2017 by original authors @ fontello.com</metadata>
<defs>
<font id="fontello" horiz-adv-x="1000" >
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
<missing-glyph horiz-adv-x="1000" />
<glyph glyph-name="chat" unicode="&#xe800;" d="M786 421q0-77-53-143t-143-104-197-38q-48 0-98 9-70-49-155-72-21-5-48-9h-2q-6 0-12 5t-6 12q-1 1-1 3t1 4 1 3l1 3t2 3 2 3 3 3 2 2q3 3 13 14t15 16 12 17 14 21 11 25q-69 40-108 98t-40 125q0 78 53 144t143 104 197 38 197-38 143-104 53-144z m214-142q0-67-40-126t-108-98q5-14 11-25t14-21 13-16 14-17 13-14q0 0 2-2t3-3 2-3 2-3l1-3t1-3 1-4-1-3q-2-8-7-13t-12-4q-28 4-48 9-86 23-156 72-50-9-98-9-151 0-263 74 32-3 49-3 90 0 172 25t148 72q69 52 107 119t37 141q0 43-13 85 72-39 114-99t42-128z" horiz-adv-x="1000" />
<glyph glyph-name="octocat" unicode="&#xf09b;" d="M429 779q116 0 215-58t156-156 57-215q0-140-82-252t-211-155q-15-3-22 4t-7 17q0 1 0 43t0 75q0 54-29 79 32 3 57 10t53 22 45 37 30 58 11 84q0 67-44 115 21 51-4 114-16 5-46-6t-51-25l-21-13q-52 15-107 15t-108-15q-8 6-23 15t-47 22-47 7q-25-63-5-114-44-48-44-115 0-47 12-83t29-59 45-37 52-22 57-10q-21-20-27-58-12-5-25-8t-32-3-36 12-31 35q-11 18-27 29t-28 14l-11 1q-12 0-16-2t-3-7 5-8 7-6l4-3q12-6 24-21t18-29l6-13q7-21 24-34t37-17 39-3 31 1l13 3q0-22 0-50t1-30q0-10-8-17t-22-4q-129 43-211 155t-82 252q0 117 58 215t155 156 216 58z m-267-616q2 4-3 7-6 1-8-1-1-4 4-7 5-3 7 1z m18-19q4 3-1 9-6 5-9 2-4-3 1-9 5-6 9-2z m16-25q6 4 0 11-4 7-9 3-5-3 0-10t9-4z m24-23q4 4-2 10-7 7-11 2-5-5 2-11 6-6 11-1z m32-14q1 6-8 9-8 2-10-4t7-9q8-3 11 4z m35-3q0 7-10 6-9 0-9-6 0-7 10-6 9 0 9 6z m32 5q-1 7-10 5-9-1-8-8t10-4 8 7z" horiz-adv-x="857.1" />
<glyph glyph-name="menu" unicode="&#xf0c9;" d="M857 100v-71q0-15-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 25t25 11h785q15 0 26-11t10-25z m0 286v-72q0-14-10-25t-26-10h-785q-15 0-25 10t-11 25v72q0 14 11 25t25 10h785q15 0 26-10t10-25z m0 285v-71q0-14-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 26t25 10h785q15 0 26-10t10-26z" horiz-adv-x="857.1" />
</font>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,60 +0,0 @@
@font-face {
font-family: 'fontello';
src: url('font/fontello.eot?13793670');
src: url('font/fontello.eot?13793670#iefix') format('embedded-opentype'),
url('font/fontello.woff2?13793670') format('woff2'),
url('font/fontello.woff?13793670') format('woff'),
url('font/fontello.ttf?13793670') format('truetype'),
url('font/fontello.svg?13793670#fontello') format('svg');
font-weight: normal;
font-style: normal;
}
/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
/*
@media screen and (-webkit-min-device-pixel-ratio:0) {
@font-face {
font-family: 'fontello';
src: url('../font/fontello.svg?13793670#fontello') format('svg');
}
}
*/
[class^="icon-"]:before, [class*=" icon-"]:before {
font-family: "fontello";
font-style: normal;
font-weight: normal;
speak: none;
display: inline-block;
text-decoration: inherit;
width: 1em;
margin-right: .2em;
text-align: center;
/* opacity: .8; */
/* For safety - reset parent styles, that can break glyph codes*/
font-variant: normal;
text-transform: none;
/* fix buttons height, for twitter bootstrap */
line-height: 1em;
/* Animation center compensation - margins should be symmetric */
/* remove if not needed */
margin-left: .2em;
/* you can be more comfortable with increased icons size */
/* font-size: 120%; */
/* Font smoothing. That was taken from TWBS */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
/* Uncomment for 3D effect */
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
}
.icon-chat:before { content: '\e800'; } /* '' */
.icon-octocat:before { content: '\f09b'; } /* '' */
.icon-menu:before { content: '\f0c9'; } /* '' */

View File

@ -1,73 +0,0 @@
<!DOCTYPE html>
<html class="no-js">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<title>{% if meta.title %}{{ meta.title }} | {% endif %}{{ site_title }}</title>
{% if meta.description %}
<meta name="description" content="{{ meta.description|striptags }}" />
{% endif %}{% if meta.robots %}
<meta name="robots" content="{{ meta.robots }}" />
{% endif %}
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Droid+Sans:400,700|Droid+Sans+Mono" type="text/css" />
<link rel="stylesheet" href="{{ theme_url }}/style.css" type="text/css" />
<link rel="stylesheet" href="{{ theme_url }}/fontello.css" type="text/css" />
</head>
<body{% if config.theme_config.widescreen %} class="widescreen"{% endif %}>
<div id="header">
<div class="container">
<a id="nav-toggle" title="Toggle Menu" role="button" aria-controls="nav" aria-expanded="false" tabindex="1">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Menu</span>
</a>
<h1>
<a href="{{ "index"|link }}">{{ site_title }}</a>
</h1>
<div id="nav" role="region" tabindex="-1">
<ul>
{% for page in pages if page.title and not page.hidden %}
{% set pageDepth = page.id|split('/')|length %}
{% if (pageDepth == 2) and (page.id ends with "/index") or (pageDepth == 1) %}
<li{% if page.id == current_page.id %} class="active"{% endif %}>
<a href="{{ page.url }}">{{ page.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</div>
</div>
</div>
<div id="main">
<div class="container">
{{ content }}
</div>
</div>
<div id="footer">
<div class="container">
<div class="social">
{% for social in pages._meta.meta.social %}
<a href="{{ social.url }}" title="{{ social.title }}" role="button">
<span class="icon-{{ social.icon }}" aria-hidden="true"></span>
<span class="sr-only">{{ social.title }}</span>
</a>
{% endfor %}
</div>
<p>
<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 <a href="https://github.com/picocms/Pico/blob/master/LICENSE.md">MIT license</a>.
</p>
</div>
</div>
<script src="{{ theme_url }}/js/modernizr-3.3.1-custom.min.js" type="text/javascript"></script>
<script src="{{ theme_url }}/js/utils.js" type="text/javascript"></script>
<script src="{{ theme_url }}/js/pico.js" type="text/javascript"></script>
</body>
</html>

View File

@ -1,3 +0,0 @@
/*! modernizr 3.3.1 (Custom Build) | MIT *
* https://modernizr.com/download/?-classlist-csstransitions-requestanimationframe !*/
!function(e,n,t){function r(e,n){return typeof e===n}function i(){var e,n,t,i,o,s,a;for(var f in y)if(y.hasOwnProperty(f)){if(e=[],n=y[f],n.name&&(e.push(n.name.toLowerCase()),n.options&&n.options.aliases&&n.options.aliases.length))for(t=0;t<n.options.aliases.length;t++)e.push(n.options.aliases[t].toLowerCase());for(i=r(n.fn,"function")?n.fn():n.fn,o=0;o<e.length;o++)s=e[o],a=s.split("."),1===a.length?Modernizr[a[0]]=i:(!Modernizr[a[0]]||Modernizr[a[0]]instanceof Boolean||(Modernizr[a[0]]=new Boolean(Modernizr[a[0]])),Modernizr[a[0]][a[1]]=i),C.push((i?"":"no-")+a.join("-"))}}function o(e){return e.replace(/([a-z])-([a-z])/g,function(e,n,t){return n+t.toUpperCase()}).replace(/^-/,"")}function s(e,n){return!!~(""+e).indexOf(n)}function a(e,n){return function(){return e.apply(n,arguments)}}function f(e,n,t){var i;for(var o in e)if(e[o]in n)return t===!1?e[o]:(i=n[e[o]],r(i,"function")?a(i,t||n):i);return!1}function l(){return"function"!=typeof n.createElement?n.createElement(arguments[0]):T?n.createElementNS.call(n,"http://www.w3.org/2000/svg",arguments[0]):n.createElement.apply(n,arguments)}function u(e){return e.replace(/([A-Z])/g,function(e,n){return"-"+n.toLowerCase()}).replace(/^ms-/,"-ms-")}function d(){var e=n.body;return e||(e=l(T?"svg":"body"),e.fake=!0),e}function p(e,t,r,i){var o,s,a,f,u="modernizr",p=l("div"),c=d();if(parseInt(r,10))for(;r--;)a=l("div"),a.id=i?i[r]:u+(r+1),p.appendChild(a);return o=l("style"),o.type="text/css",o.id="s"+u,(c.fake?c:p).appendChild(o),c.appendChild(p),o.styleSheet?o.styleSheet.cssText=e:o.appendChild(n.createTextNode(e)),p.id=u,c.fake&&(c.style.background="",c.style.overflow="hidden",f=w.style.overflow,w.style.overflow="hidden",w.appendChild(c)),s=t(p,e),c.fake?(c.parentNode.removeChild(c),w.style.overflow=f,w.offsetHeight):p.parentNode.removeChild(p),!!s}function c(n,r){var i=n.length;if("CSS"in e&&"supports"in e.CSS){for(;i--;)if(e.CSS.supports(u(n[i]),r))return!0;return!1}if("CSSSupportsRule"in e){for(var o=[];i--;)o.push("("+u(n[i])+":"+r+")");return o=o.join(" or "),p("@supports ("+o+") { #modernizr { position: absolute; } }",function(e){return"absolute"==getComputedStyle(e,null).position})}return t}function m(e,n,i,a){function f(){d&&(delete P.style,delete P.modElem)}if(a=r(a,"undefined")?!1:a,!r(i,"undefined")){var u=c(e,i);if(!r(u,"undefined"))return u}for(var d,p,m,v,h,y=["modernizr","tspan","samp"];!P.style&&y.length;)d=!0,P.modElem=l(y.shift()),P.style=P.modElem.style;for(m=e.length,p=0;m>p;p++)if(v=e[p],h=P.style[v],s(v,"-")&&(v=o(v)),P.style[v]!==t){if(a||r(i,"undefined"))return f(),"pfx"==n?v:!0;try{P.style[v]=i}catch(g){}if(P.style[v]!=h)return f(),"pfx"==n?v:!0}return f(),!1}function v(e,n,t,i,o){var s=e.charAt(0).toUpperCase()+e.slice(1),a=(e+" "+_.join(s+" ")+s).split(" ");return r(n,"string")||r(n,"undefined")?m(a,n,i,o):(a=(e+" "+E.join(s+" ")+s).split(" "),f(a,n,t))}function h(e,n,r){return v(e,t,t,n,r)}var y=[],g={_version:"3.3.1",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,n){var t=this;setTimeout(function(){n(t[e])},0)},addTest:function(e,n,t){y.push({name:e,fn:n,options:t})},addAsyncTest:function(e){y.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=g,Modernizr=new Modernizr;var C=[],w=n.documentElement;Modernizr.addTest("classlist","classList"in w);var x="Moz O ms Webkit",_=g._config.usePrefixes?x.split(" "):[];g._cssomPrefixes=_;var S=function(n){var r,i=prefixes.length,o=e.CSSRule;if("undefined"==typeof o)return t;if(!n)return!1;if(n=n.replace(/^@/,""),r=n.replace(/-/g,"_").toUpperCase()+"_RULE",r in o)return"@"+n;for(var s=0;i>s;s++){var a=prefixes[s],f=a.toUpperCase()+"_"+r;if(f in o)return"@-"+a.toLowerCase()+"-"+n}return!1};g.atRule=S;var E=g._config.usePrefixes?x.toLowerCase().split(" "):[];g._domPrefixes=E;var T="svg"===w.nodeName.toLowerCase(),z={elem:l("modernizr")};Modernizr._q.push(function(){delete z.elem});var P={style:z.elem.style};Modernizr._q.unshift(function(){delete P.style}),g.testAllProps=v;var b=g.prefixed=function(e,n,t){return 0===e.indexOf("@")?S(e):(-1!=e.indexOf("-")&&(e=o(e)),n?v(e,n,t):v(e,"pfx"))};Modernizr.addTest("requestanimationframe",!!b("requestAnimationFrame",e),{aliases:["raf"]}),g.testAllProps=h,Modernizr.addTest("csstransitions",h("transition","all",!0)),i(),delete g.addTest,delete g.addAsyncTest;for(var L=0;L<Modernizr._q.length;L++)Modernizr._q[L]();e.Modernizr=Modernizr}(window,document);

View File

@ -1,70 +0,0 @@
/**
* Pico's Default Theme - JavaScript helper
*
* Pico is a stupidly simple, blazing fast, flat file CMS.
*
* @author Daniel Rudolf
* @link http://picocms.org
* @license http://opensource.org/licenses/MIT The MIT License
* @version 2.0
*/
function main()
{
// capability CSS classes
document.documentElement.className = 'js';
// wrap tables
var tables = document.querySelectorAll('#main > .container > table');
for (var i = 0; i < tables.length; i++) {
if (!/\btable-responsive\b/.test(tables[i].parentElement.className)) {
var tableWrapper = document.createElement('div');
tableWrapper.className = 'table-responsive';
tables[i].parentElement.insertBefore(tableWrapper, tables[i]);
tableWrapper.appendChild(tables[i]);
}
}
// responsive menu
var menu = document.getElementById('nav'),
menuToggle = document.getElementById('nav-toggle'),
toggleMenuEvent = function (event) {
if (event.type === 'keydown') {
if ((event.keyCode != 13) && (event.keyCode != 32)) {
return;
}
}
event.preventDefault();
if (menuToggle.getAttribute('aria-expanded') === 'false') {
menuToggle.setAttribute('aria-expanded', 'true');
utils.slideDown(menu, null, function () {
if (event.type === 'keydown') {
menu.focus();
}
});
} else {
menuToggle.setAttribute('aria-expanded', 'false');
utils.slideUp(menu);
}
},
onResizeEvent = function () {
if (utils.isElementVisible(menuToggle)) {
menu.className = 'hidden';
menuToggle.addEventListener('click', toggleMenuEvent);
menuToggle.addEventListener('keydown', toggleMenuEvent);
} else {
menu.className = '';
menu.removeAttribute('data-slide-id');
menuToggle.removeEventListener('click', toggleMenuEvent);
menuToggle.removeEventListener('keydown', toggleMenuEvent);
}
};
window.addEventListener('resize', onResizeEvent);
onResizeEvent();
}
main();

View File

@ -1,135 +0,0 @@
/**
* Pico's Default Theme - JavaScript helper
*
* Pico is a stupidly simple, blazing fast, flat file CMS.
*
* @author Daniel Rudolf
* @link http://picocms.org
* @license http://opensource.org/licenses/MIT The MIT License
* @version 2.0
*/
utils = {};
/**
* Checks whether the client's browser is able to slide elements or not
*
* @return boolean TRUE when the browser supports sliding, FALSE otherwise
*/
utils.canSlide = function ()
{
return (Modernizr.classlist && Modernizr.requestanimationframe && Modernizr.csstransitions);
};
/**
* Slides a element up (i.e. hide a element by changing its height to 0px)
*
* @param HTMLElement element the element to slide up
* @param function finishCallback function to call when the animation has
* been finished (i.e. the element is hidden)
* @param function startCallback function to call when the animation starts
* @return void
*/
utils.slideUp = function (element, finishCallback, startCallback)
{
if (!utils.canSlide()) {
if (startCallback) startCallback();
element.className += (element.className !== '') ? ' hidden' : 'hidden';
if (finishCallback) window.requestAnimationFrame(finishCallback);
return;
}
element.style.height = element.clientHeight + 'px';
var slideId = parseInt(element.getAttribute('data-slide-id')) || 0;
element.setAttribute('data-slide-id', ++slideId);
window.requestAnimationFrame(function () {
element.classList.add('slide');
window.requestAnimationFrame(function () {
element.style.height = '0px';
if (startCallback) {
startCallback();
}
window.setTimeout(function () {
if (parseInt(element.getAttribute('data-slide-id')) !== slideId) return;
element.classList.add('hidden');
element.classList.remove('slide');
element.style.height = null;
if (finishCallback) {
window.requestAnimationFrame(finishCallback);
}
}, 500);
});
});
};
/**
* Slides a element down (i.e. show a hidden element)
*
* @param HTMLElement element the element to slide down
* @param function finishCallback function to call when the animation has
* been finished (i.e. the element is visible)
* @param function startCallback function to call when the animation starts
* @return void
*/
utils.slideDown = function (element, finishCallback, startCallback)
{
if (!utils.canSlide()) {
if (startCallback) startCallback();
element.className = element.className.replace(/\bhidden\b */g, '');
if (finishCallback) window.requestAnimationFrame(finishCallback);
return;
}
var cssRuleOriginalValue = element.clientHeight + 'px',
slideId = parseInt(element.getAttribute('data-slide-id')) || 0;
element.setAttribute('data-slide-id', ++slideId);
element.style.height = null;
element.classList.remove('hidden');
element.classList.remove('slide');
var cssRuleValue = element.clientHeight + 'px';
element.style.height = cssRuleOriginalValue;
window.requestAnimationFrame(function () {
element.classList.add('slide');
window.requestAnimationFrame(function () {
element.style.height = cssRuleValue;
if (startCallback) {
startCallback();
}
window.setTimeout(function () {
if (parseInt(element.getAttribute('data-slide-id')) !== slideId) return;
element.classList.remove('slide');
element.style.height = null;
if (finishCallback) {
window.requestAnimationFrame(finishCallback);
}
}, 500);
});
});
};
/**
* Checks whether a element is visible or not
*
* @param HTMLElement element the element to check
* @return boolean TRUE when the element is visible, FALSE otherwise
*/
utils.isElementVisible = function (element)
{
return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
};

View File

@ -1,357 +0,0 @@
/**
* Pico's Default Theme
*
* Pico's default theme is a bit bare - but that's intentional! The default
* theme isn't meant for production use, it's actually a template for you to
* design your own theme around.
*
* Pico is a stupidly simple, blazing fast, flat file CMS.
*
* @author Gilbert Pellegrom
* @author Daniel Rudolf
* @link http://picocms.org
* @license http://opensource.org/licenses/MIT The MIT License
* @version 2.0
*/
* {
box-sizing: border-box;
border: 0 none;
margin: 0;
padding: 0;
}
.hidden { display: none !important; }
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0 none;
}
.slide {
overflow-y: hidden !important;
-webkit-transition: height .5s ease-in !important;
transition: height .5s ease-in !important;
}
/*** BASIC LAYOUT ***/
html, body { height: 100%; }
body { display: flex; flex-direction: column; }
#main { flex: 1 0 auto; }
#header, #footer { flex: 0 0 auto; }
#main {
padding: 5em 0 4em;
}
.container {
max-width: 48em;
padding: 0 0.5em;
margin: 0 auto;
}
.widescreen .container { max-width: 72em; }
/* very ugly overflow fix, avoid this whenever possible! */
#main .container { overflow-x: auto; }
/*** BASIC LAYOUT: HEADER ***/
#header { background: #2EAE9B; }
#header h1 {
float: left;
font-size: 2rem;
margin: 0;
padding: 1.5em 1em 1.5em 0;
}
#header h1 a, #header h1 a:hover { color: #fff; }
#nav {
text-align: right;
padding: 3em 0;
}
#nav ul {
list-style: none;
margin: 0;
padding: 0;
}
#nav ul li {
display: inline-block;
margin-left: 1em;
padding: 0;
font-weight: bold;
}
#nav a, #nav-toggle { color: #afe1da; }
#nav .active a, #nav a:hover, #nav-toggle:hover { color: #fff; }
#nav-toggle { display: none; }
/* IE8 + IE9 clearfix */
#header > .container:after {
content: '';
display: block;
clear: both;
}
/*** BASIC LAYOUT: FOOTER ***/
#footer {
background: #707070;
color: #C0C0C0;
}
#footer a { color: #ddd; }
#footer a:hover { color: #fff; }
#footer p {
margin: 0;
padding: 3em 0;
}
#footer .social {
float: right;
padding: 1.5em 0 1.5em 1em;
font-size: 2rem;
}
/*** BASIC LAYOUT: EXTRA SMALL DEVICES ***/
@media (max-width: 767px) {
#main { padding: 2em 0 1em; }
#header h1 {
float: none;
padding: 0.5em 0;
}
#nav {
clear: right;
padding: 0;
}
#nav ul {
padding-bottom: 1em;
}
#nav ul li {
display: block;
margin-left: 0;
text-align: center;
}
#nav ul li a {
display: block;
padding: 0.5em 0;
}
.js #nav-toggle {
display: block;
float: right;
width: 2em;
margin: 0.6667em 0 0.6667em 1.3333em;
font-size: 1.5rem;
line-height: 2em;
text-align: center;
cursor: pointer;
}
.js #nav-toggle > * { vertical-align: middle; }
#footer p { padding: 1em 0; }
#footer .social { padding: 0.5em 0 0.5em 1em; }
}
/*** TYPOGRAPHY ***/
html { font-size: 16px; }
body {
font-family: 'Droid Sans', 'Helvetica', 'Arial', sans-serif;
font-size: 1rem;
line-height: 1.6;
font-variant-ligatures: common-ligatures;
text-rendering: optimizeLegibility;
font-kerning: normal;
color: #444;
}
p, td, th, li, dd {
text-align: justify;
overflow-wrap: break-word;
word-wrap: break-word;
}
p, hr, table, .table-responsive, ol, ul, dl, pre, blockquote, fieldset {
margin-bottom: 1em;
}
a {
color: #2EAE9B;
text-decoration: none;
-webkit-transition: color .2s ease-in;
transition: color .2s ease-in;
}
a:hover { color: #444; }
h1, h2, h3, h4, h5, h6 {
margin-bottom: 0.6em;
font-weight: bold;
color: #333;
}
h1 { font-size: 2rem; }
h2 { font-size: 1.7rem; }
h3 { font-size: 1.4rem; }
h4 { font-size: 1.1rem; }
h5 { font-size: 1rem; }
h6 { font-size: 1rem; font-weight: normal; font-style: italic; }
img { max-width: 100%; }
hr {
border: 0.15em solid #f5f5f5;
border-radius: 0.3em;
background: #f5f5f5;
}
abbr { text-decoration: underline dotted; }
/*** TABLES ***/
table { border-spacing: 0; }
td, th {
padding: 0.4em 1em;
vertical-align: top;
}
th {
font-weight: bold;
text-align: center;
background: #f5f5f5;
color: #333;
}
td, th { border: solid 1px #ccc; }
tr:not(:last-child) td, tr:not(:last-child) th { border-bottom: 0 none; }
thead tr:last-child th { border-bottom: 0 none; }
td:not(:last-child), th:not(:last-child) { border-right: 0 none; }
tr:first-child td:first-child, tr:first-child th:first-child { border-top-left-radius: 0.3em; }
tr:first-child td:last-child, tr:first-child th:last-child { border-top-right-radius: 0.3em; }
tbody tr:last-child td:first-child { border-bottom-left-radius: 0.3em; }
tbody tr:last-child td:last-child { border-bottom-right-radius: 0.3em; }
table thead + tbody tr:first-child td { border-radius: 0 !important; }
.table-responsive { overflow-x: auto; }
.table-responsive > table { margin-bottom: 0; }
/*** LISTS ***/
ol, ul {
list-style-position: outside;
padding-left: 1.5em;
}
ol { padding-left: 2.5em; }
li { padding-left: 0.5em; }
dt { font-weight: bold; }
dd { margin-left: 2em; }
/*** CODE ***/
code {
margin: 0 0.1em;
padding: 0.1em 0.2em;
border: 1px solid #ccc;
border-radius: 0.3em;
background: #f5f5f5;
font-family: 'Droid Sans Mono', 'Courier New', 'Courier', monospace;
font-size: 0.9rem;
}
pre {
padding: 0 1em;
border: 1px solid #ccc;
border-radius: 0.3em;
background: #f5f5f5;
line-height: 1.4;
}
pre code {
display: block;
margin: 0;
padding: 1.1111em 0;
border: 0 none;
background: transparent;
overflow-x: auto;
}
/*** BLOCKQUOTE ***/
blockquote {
font-style: italic;
margin-left: 1em;
padding-left: 1em;
border-left: 0.5em solid #f5f5f5;
}
/*** FORMS ***/
label, fieldset legend { font-weight: bold; }
input:not([type="checkbox"]):not([type="radio"]), button, select, textarea, fieldset, fieldset legend {
border: solid 1px #ccc;
border-radius: 0.3em;
background: #fff;
-webkit-transition: none .2s ease-in;
transition: none .2s ease-in;
-webkit-transition-property: border-color, background, box-shadow;
transition-property: border-color, background, box-shadow;
}
input:not([type="checkbox"]):not([type="radio"]), button, select, textarea {
padding: 0.5em 1em;
outline: 0 none;
font-size: 1rem;
}
input:focus:not([type="checkbox"]):not([type="radio"]), button:focus, select:focus, textarea:focus {
border-color: #2EAE9B;
box-shadow: 0 0 8px #2EAE9B;
}
input[type="button"]:focus, input[type="submit"]:focus, input[type="reset"]:focus, button:focus,
input[type="button"]:hover, input[type="submit"]:hover, input[type="reset"]:hover, button:hover {
background: #f5f5f5;
cursor: pointer;
}
textarea, select[multiple] {
vertical-align: bottom;
overflow: auto;
}
fieldset {
padding: 1em;
background: #f5f5f5;
}
fieldset legend { padding: 0 0.5em; }
fieldset label, fieldset input, fieldset button,
fieldset select, fieldset textarea {
margin: 0.2em 0.5em;
}
fieldset label:first-child, fieldset input:first-child, fieldset button:first-child,
fieldset select:first-child, fieldset textarea:first-child {
margin-left: 0;
}
fieldset label:last-child, fieldset input:last-child, fieldset button:last-child,
fieldset select:last-child, fieldset textarea:last-child {
margin-right: 0;
}
/* Firefox input size fix */
input::-moz-focus-inner, button::-moz-focus-inner {
border: 0;
padding: 0;
}