Merge branch 'master' of github.com:gilbitron/Pico

This commit is contained in:
kpavlov 2013-09-18 08:23:33 +03:00
commit f553e211c5
8 changed files with 400 additions and 318 deletions

2
.gitignore vendored
View file

@ -20,4 +20,4 @@ themes/*
!themes/default/*
# User config
config.php
config.php

View file

@ -1,4 +1,6 @@
Pico
====
Pico is a stupidly simple, blazing fast, flat file CMS. See http://pico.dev7studios.com for more info.
Pico is a stupidly simple, blazing fast, flat file CMS. See http://pico.dev7studios.com for more info.
Want to say thanks? [Consider tipping me](https://www.gittip.com/gilbitron).

View file

@ -9,6 +9,14 @@
* [changed] get_files no longer gets dotfiles
* [fixed] Issues with updating Pico install once in use
2013.09.04 - version 0.7
* [New] Added before_read_file_meta and get_page_data plugin hooks to customize page meta data
* [Changed] Make get_files() ignore dotfiles
* [Changed] Make get_pages() ignore Emacs and temp files
* [Changed] Use composer version of Markdown
* [Changed] Other small tweaks
* [Fixed] Date warnings and other small bugs
2013.05.07 - version 0.6.2
* [Changed] Replaced glob_recursive with get_files

View file

@ -6,16 +6,16 @@ keywords: Pico CMS
## Welcome to Pico
Congratulations you have successfully installed [Pico](http://pico.dev7studios.com). Pico is a stupidly simple, blazing fast, flat file CMS.
Congratulations, you have successfully installed [Pico](http://pico.dev7studios.com). Pico is a stupidly simple, blazing fast, flat file CMS.
### Creating Content
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. For example this file is called `index.md` and is shown as the main landing page.
folder and that becomes a page. For example, this file is called `index.md` and is shown as the main landing page.
If you created folder within the content folder (e.g. `content/sub`) and put an `index.md` inside it, you can access that folder at the URL
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://yousite.com/sub`. If you want another page within the sub folder, simply create a text file with the corresponding name (e.g. `content/sub/page.md`)
and will be able to access it from the URL `http://yousite.com/sub/page`. Below we've shown some examples of content locations and their corresponing URL's:
and you will be able to access it from the URL `http://yousite.com/sub/page`. Below we've shown some examples of content locations and their corresponing URL's:
<table>
<thead>
@ -56,7 +56,7 @@ There are also certain variables that you can use in your text files:
### Themes
You can create themes for your Pico installation and in the "themes" folder. Check out the default theme for an example of a theme. Pico uses
You can create themes for your Pico installation in the "themes" folder. Check out the default theme for an example of a theme. Pico uses
[Twig](http://twig.sensiolabs.org/documentation) for it's templating engine. You can select your theme by setting the `$config['theme']` variable
in config.php to your theme folder.
@ -99,7 +99,15 @@ Pages can be used like:
{% endfor %}
&lt;/ul&gt;</pre>
### Plugins
See [http://pico.dev7studios.com/plugins](http://pico.dev7studios.com/plugins)
### Config
You can override the default Pico settings (and add your own custom settings) by editing config.php in the root Pico directory. The config.php file
list all of the settings and their defaults. To override a setting simply uncomment it in config.php and set your custom value.
lists all of the settings and their defaults. To override a setting, simply uncomment it in config.php and set your custom value.
### Documentation
For more help have a look at the Pico documentation at [http://pico.dev7studios.com/docs](http://pico.dev7studios.com/docs)

View file

@ -8,6 +8,8 @@ define('PLUGINS_DIR', ROOT_DIR .'plugins/');
define('THEMES_DIR', ROOT_DIR .'themes/');
define('CACHE_DIR', LIB_DIR .'cache/');
date_default_timezone_set('UTC');
require(ROOT_DIR .'vendor/autoload.php');
require(LIB_DIR .'pico.php');
$pico = new Pico();

View file

@ -7,349 +7,348 @@ use \Michelf\MarkdownExtra;
* @author Gilbert Pellegrom
* @link http://pico.dev7studios.com
* @license http://opensource.org/licenses/MIT
* @version 0.6.2
* @version 0.7
*/
class Pico
{
class Pico {
private $plugins;
private $plugins;
/**
* The constructor carries out all the processing in Pico.
* Does URL routing, Markdown processing and Twig processing.
*/
public function __construct()
{
// Load plugins
$this->load_plugins();
$this->run_hooks('plugins_loaded');
/**
* The constructor carries out all the processing in Pico.
* Does URL routing, Markdown processing and Twig processing.
*/
public function __construct()
{
// Load plugins
$this->load_plugins();
$this->run_hooks('plugins_loaded');
// Get request url and script url
$url = '';
$request_url = (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : '';
$script_url = (isset($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : '';
// Get request url and script url
$url = '';
$request_url = (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : '';
$script_url = (isset($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : '';
// Get our url path and trim the / of the left and the right
if($request_url != $script_url) $url = trim(preg_replace('/'. str_replace('/', '\/', str_replace('index.php', '', $script_url)) .'/', '', $request_url, 1), '/');
$url = preg_replace('/\?.*/', '', $url); // Strip query string
$this->run_hooks('request_url', array(&$url));
// Get our url path and trim the / of the left and the right
if ($request_url != $script_url) $url = trim(preg_replace('/' . str_replace('/', '\/', str_replace('index.php', '', $script_url)) . '/', '', $request_url, 1), '/');
$url = preg_replace('/\?.*/', '', $url); // Strip query string
$this->run_hooks('request_url', array(&$url));
// Get the file path
if($url) $file = CONTENT_DIR . $url;
else $file = CONTENT_DIR .'index';
// Get the file path
if ($url) $file = CONTENT_DIR . $url;
else $file = CONTENT_DIR . 'index';
// Load the file
if(is_dir($file)) $file = CONTENT_DIR . $url .'/index'. CONTENT_EXT;
else $file .= CONTENT_EXT;
// Load the file
if (is_dir($file)) $file = CONTENT_DIR . $url . '/index' . CONTENT_EXT;
else $file .= CONTENT_EXT;
$this->run_hooks('before_load_content', array(&$file));
if(file_exists($file)){
$content = file_get_contents($file);
} else {
$this->run_hooks('before_404_load_content', array(&$file));
$content = file_get_contents(CONTENT_DIR .'404'. CONTENT_EXT);
header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
$this->run_hooks('after_404_load_content', array(&$file, &$content));
}
$this->run_hooks('after_load_content', array(&$file, &$content));
// Load the settings
$settings = $this->get_config();
$this->run_hooks('config_loaded', array(&$settings));
$this->run_hooks('before_load_content', array(&$file));
if (file_exists($file)) {
$content = file_get_contents($file);
} else {
$this->run_hooks('before_404_load_content', array(&$file));
$content = file_get_contents(CONTENT_DIR . '404' . CONTENT_EXT);
header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found');
$this->run_hooks('after_404_load_content', array(&$file, &$content));
}
$this->run_hooks('after_load_content', array(&$file, &$content));
$meta = $this->read_file_meta($content);
$this->run_hooks('file_meta', array(&$meta));
$content = $this->parse_content($content);
$this->run_hooks('content_parsed', array(&$content));
// Get all the pages
$pages = $this->get_pages($settings['base_url'], $settings['pages_order_by'], $settings['pages_order'], $settings['excerpt_length']);
$prev_page = array();
$current_page = array();
$next_page = array();
while($current_page = current($pages)){
if((isset($meta['title'])) && ($meta['title'] == $current_page['title'])){
break;
}
next($pages);
}
$prev_page = next($pages);
prev($pages);
$next_page = prev($pages);
$this->run_hooks('get_pages', array(&$pages, &$current_page, &$prev_page, &$next_page));
// Load the settings
$settings = $this->get_config();
$this->run_hooks('config_loaded', array(&$settings));
$meta = $this->read_file_meta($content);
$this->run_hooks('file_meta', array(&$meta));
$content = $this->parse_content($content);
$this->run_hooks('content_parsed', array(&$content));
// Get all the pages
$pages = $this->get_pages($settings['base_url'], $settings['pages_order_by'], $settings['pages_order'],
$settings['meta_max_length'], $settings['excerpt_length']);
$prev_page = array();
$current_page = array();
$next_page = array();
while ($current_page = current($pages)) {
if ((isset($meta['title'])) && ($meta['title'] == $current_page['title'])) {
break;
}
next($pages);
}
$prev_page = next($pages);
prev($pages);
$next_page = prev($pages);
$this->run_hooks('get_pages', array(&$pages, &$current_page, &$prev_page, &$next_page));
// Load the theme
$this->run_hooks('before_twig_register');
Twig_Autoloader::register();
$loader = new Twig_Loader_Filesystem(THEMES_DIR . $settings['theme']);
$twig = new Twig_Environment($loader, $settings['twig_config']);
$twig->addExtension(new Twig_Extension_Debug());
$twig_vars = array(
'config' => $settings,
'base_dir' => rtrim(ROOT_DIR, '/'),
'base_url' => $settings['base_url'],
'theme_dir' => THEMES_DIR . $settings['theme'],
'theme_url' => $settings['base_url'] . '/' . basename(THEMES_DIR) . '/' . $settings['theme'],
'site_title' => $settings['site_title'],
'meta' => $meta,
'content' => $content,
'pages' => $pages,
'prev_page' => $prev_page,
'current_page' => $current_page,
'next_page' => $next_page,
'is_front_page' => $url ? false : true,
);
// Load the theme
$this->run_hooks('before_twig_register');
Twig_Autoloader::register();
$loader = new Twig_Loader_Filesystem(THEMES_DIR . $settings['theme']);
$twig = new Twig_Environment($loader, $settings['twig_config']);
$twig->addExtension(new Twig_Extension_Debug());
$twig_vars = array(
'config' => $settings,
'base_dir' => rtrim(ROOT_DIR, '/'),
'base_url' => $settings['base_url'],
'theme_dir' => THEMES_DIR . $settings['theme'],
'theme_url' => $settings['base_url'] .'/'. basename(THEMES_DIR) .'/'. $settings['theme'],
'site_title' => $settings['site_title'],
'meta' => $meta,
'content' => $content,
'pages' => $pages,
'prev_page' => $prev_page,
'current_page' => $current_page,
'next_page' => $next_page,
'is_front_page' => $url ? false : true,
);
// use a custom template if specified Template: [filename] in page meta e.g. Template: spesh to try and use spesh.html in theme folder
$template = ((isset($meta['template']) && file_exists($twig_vars['theme_dir'] . '/' . $meta['template'] . $settings['template_ext'])) ? $meta['template'] . $settings['template_ext'] : 'index' . $settings['template_ext']);
$this->run_hooks('before_render', array(&$twig_vars, &$twig));
$this->run_hooks('before_render', array(&$twig_vars, &$twig));
$output = $twig->render($template, $twig_vars);
$this->run_hooks('after_render', array(&$output));
echo $output;
}
$this->run_hooks('after_render', array(&$output));
echo $output;
}
/**
* Load any plugins
*/
private function load_plugins()
{
$this->plugins = array();
$plugins = $this->get_files(PLUGINS_DIR, '.php');
if(!empty($plugins)){
foreach($plugins as $plugin){
include_once($plugin);
$plugin_name = preg_replace("/\\.[^.\\s]{3}$/", '', basename($plugin));
if(class_exists($plugin_name)){
$obj = new $plugin_name;
$this->plugins[] = $obj;
}
}
}
}
/**
* Load any plugins
*/
private function load_plugins()
{
$this->plugins = array();
$plugins = $this->get_files(PLUGINS_DIR, '.php');
if (!empty($plugins)) {
foreach ($plugins as $plugin) {
include_once($plugin);
$plugin_name = preg_replace("/\\.[^.\\s]{3}$/", '', basename($plugin));
if (class_exists($plugin_name)) {
$obj = new $plugin_name;
$this->plugins[] = $obj;
}
}
}
}
/**
* Parses the content using Markdown
*
* @param string $content the raw txt content
* @return string $content the Markdown formatted content
*/
/**
* Parses the content using Markdown
*
* @param string $content the raw txt content
* @return string $content the Markdown formatted content
*/
private function parse_content(&$content)
{
$content = preg_replace('#/\*.+?\*/#s', '', $content); // Remove comments and meta
$content = str_replace('%base_url%', $this->base_url(), $content);
$content = MarkdownExtra::defaultTransform($content);
{
$content = preg_replace('#/\*.+?\*/#s', '', $content); // Remove comments and meta
$content = str_replace('%base_url%', $this->base_url(), $content);
$content = MarkdownExtra::defaultTransform($content);
return $content;
}
return $content;
}
/**
* Parses the file meta from the txt file header. Meta keys are converted to lowercase automatically.
*
* @param string $content the raw txt content
* @return array $headers an array of meta values
*/
private function read_file_meta($content)
{
global $config;
/**
* Parses the file meta from the txt file header.
* Meta keys are converted to lowercase automatically.
*
* @param string $content the raw txt content
* @return array $headers an array of meta values
*/
private function read_file_meta($content)
{
global $config;
$headers = array(
'title' => 'Title',
'description' => 'Description',
'author' => 'Author',
'date' => 'Date',
'robots' => 'Robots'
);
$headers = array();
if (preg_match_all("/\/\*(.+?)\*\/(.*)/ms", $content, $h_and_c)) {
preg_match_all('/(\w+)\s*:\s*(.*)/i', $h_and_c[1][0], $m);
for ($i = 0; $i < count($m[0]); $i++) {
$headers[strtolower($m[1][$i])] = trim($m[2][$i]);
}
}
// Add support for custom headers by hooking into the headers array
$this->run_hooks('before_read_file_meta', array(&$headers));
if (isset($headers['date'])) $headers['date_formatted'] = date($config['date_format'], strtotime($headers['date']));
foreach ($headers as $field => $regex){
if (preg_match('/^[ \t\/*#@]*' . preg_quote($regex, '/') . ':(.*)$/mi', $content, $match) && $match[1]){
$headers[ $field ] = trim(preg_replace("/\s*(?:\*\/|\?>).*/", '', $match[1]));
} else {
$headers[ $field ] = '';
}
}
if(isset($headers['date'])) $headers['date_formatted'] = date($config['date_format'], strtotime($headers['date']));
if (empty($headers['title'])) {
preg_match('/^(.+?)[ ]*\n(=+|-+)[ ]*\n+/imu', $content, $matches);
if (count($matches) > 0) {
$headers['title'] = $matches[1];
} else {
preg_match('/^\#{1}([^\#].*)$/imu', $content, $matches);
if (count($matches) > 0) {
$headers['title'] = $matches[1];
}
}
}
return $headers;
}
return $headers;
}
/**
* Loads the config
*
* @return array $config an array of config values
*/
private function get_config()
{
global $config;
@include_once(ROOT_DIR .'config.php');
/**
* Loads the config
*
* @return array $config an array of config values
*/
private function get_config()
{
global $config;
@include_once(ROOT_DIR . 'config.php');
$defaults = array(
'site_title' => 'Pico',
'base_url' => $this->base_url(),
'theme' => 'default',
'date_format' => 'jS M Y',
'twig_config' => array('cache' => false, 'autoescape' => false, 'debug' => false),
'pages_order_by' => 'alpha',
'pages_order' => 'asc',
$defaults = array(
'site_title' => 'Pico',
'base_url' => $this->base_url(),
'theme' => 'default',
'date_format' => 'jS M Y',
'twig_config' => array('cache' => false, 'autoescape' => false, 'debug' => false),
'pages_order_by' => 'alpha',
'pages_order' => 'asc',
'excerpt_length' => 50,
'template_ext' => '.html'
);
);
if (is_array($config)) $config = array_merge($defaults, $config);
else $config = $defaults;
if(is_array($config)) $config = array_merge($defaults, $config);
else $config = $defaults;
return $config;
}
/**
* Get a list of pages
*
* @param string $base_url the base URL of the site
* @param string $order_by order by "alpha" or "date"
* @param string $order order "asc" or "desc"
* @return array $sorted_pages an array of pages
*/
return $config;
}
/**
* Get a list of pages
*
* @param string $base_url the base URL of the site
* @param string $order_by order by "alpha" or "date"
* @param string $order order "asc" or "desc"
* @return array $sorted_pages an array of pages
*/
private function get_pages($base_url, $order_by = 'alpha', $order = 'asc', $meta_max_length = 2048, $excerpt_length = 50)
{
global $config;
{
global $config;
$pages = $this->get_files(CONTENT_DIR, CONTENT_EXT);
$sorted_pages = array();
$date_id = 0;
foreach($pages as $key=>$page){
// Skip 404
if(basename($page) == '404'. CONTENT_EXT){
unset($pages[$key]);
continue;
}
$pages = $this->get_files(CONTENT_DIR, CONTENT_EXT);
$sorted_pages = array();
$date_id = 0;
foreach ($pages as $key => $page) {
// Skip 404
if (basename($page) == '404' . CONTENT_EXT) {
unset($pages[$key]);
continue;
}
// Ignore Emacs (and Nano) temp files
if (in_array(substr($page, -1), array('~', '#'))) {
unset($pages[$key]);
continue;
}
// Get title and format $page
// Ignore Emacs (and Nano) temp files
if (in_array(substr($page, -1), array('~','#'))) {
unset($pages[$key]);
continue;
}
// Get title and format $page
$page_content = file_get_contents($page, NULL, NULL, 0, $meta_max_length);
$page_meta = $this->read_file_meta($page_content);
if (!$page_meta) trigger_error("$page meta not read");
$page_content = $this->parse_content($page_content);
$url = str_replace(CONTENT_DIR, $base_url . '/', $page);
$url = str_replace('index' . CONTENT_EXT, '', $url);
$url = str_replace(CONTENT_EXT, '', $url);
$data = array();
// these are generic fields that are added
foreach ($page_meta as $meta_key => $value) {
$data[$meta_key] = isset($page_meta[$meta_key]) ? $value : null;
}
// these are special fields and need to be overwritten
$extras = array(
'url' => $url,
'date_formatted' => isset($page_meta['date']) ? date($config['date_format'], strtotime($page_meta['date'])) : null,
'content' => $page_content,
'excerpt' => isset($page_meta['excerpt']) ? $page_meta['excerpt'] : $this->limit_words(strip_tags($page_content), $excerpt_length),
$page_meta = $this->read_file_meta($page_content);
$page_content = $this->parse_content($page_content);
$url = str_replace(CONTENT_DIR, $base_url .'/', $page);
$url = str_replace('index'. CONTENT_EXT, '', $url);
$url = str_replace(CONTENT_EXT, '', $url);
$data = array(
'title' => isset($page_meta['title']) ? $page_meta['title'] : '',
'url' => $url,
'author' => isset($page_meta['author']) ? $page_meta['author'] : '',
'date' => isset($page_meta['date']) ? $page_meta['date'] : '',
'date_formatted' => isset($page_meta['date']) ? date($config['date_format'], strtotime($page_meta['date'])) : '',
'content' => $page_content,
'excerpt' => $this->limit_words(strip_tags($page_content), $excerpt_length),
'last_modified' => new DateTime('@' . filemtime($page))
);
$data = array_merge($data, $extras);
if ($order_by == 'date') {
$sorted_pages[$page_meta['date'] . $date_id] = $data;
$date_id++;
} else $sorted_pages[] = $data;
}
);
if ($order == 'desc') krsort($sorted_pages);
else ksort($sorted_pages);
// Extend the data provided with each page by hooking into the data array
$this->run_hooks('get_page_data', array(&$data, $page_meta));
return $sorted_pages;
}
if($order_by == 'date' && isset($page_meta['date'])){
$sorted_pages[$page_meta['date'].$date_id] = $data;
$date_id++;
}
else $sorted_pages[] = $data;
}
if($order == 'desc') krsort($sorted_pages);
else ksort($sorted_pages);
return $sorted_pages;
}
/**
* Processes any hooks and runs them
*
* @param string $hook_id the ID of the hook
* @param array $args optional arguments
*/
private function run_hooks($hook_id, $args = array())
{
if(!empty($this->plugins)){
foreach($this->plugins as $plugin){
if(is_callable(array($plugin, $hook_id))){
call_user_func_array(array($plugin, $hook_id), $args);
}
}
}
}
/**
* Processes any hooks and runs them
*
* @param string $hook_id the ID of the hook
* @param array $args optional arguments
*/
private function run_hooks($hook_id, $args = array())
{
if (!empty($this->plugins)) {
foreach ($this->plugins as $plugin) {
if (is_callable(array($plugin, $hook_id))) {
call_user_func_array(array($plugin, $hook_id), $args);
}
}
}
}
/**
* Helper function to work out the base URL
*
* @return string the base url
*/
private function base_url()
{
global $config;
if(isset($config['base_url']) && $config['base_url']) return $config['base_url'];
/**
* Helper function to work out the base URL
*
* @return string the base url
*/
private function base_url()
{
global $config;
if (isset($config['base_url']) && $config['base_url']) return $config['base_url'];
$url = '';
$request_url = (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : '';
$script_url = (isset($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : '';
if($request_url != $script_url) $url = trim(preg_replace('/'. str_replace('/', '\/', str_replace('index.php', '', $script_url)) .'/', '', $request_url, 1), '/');
$url = '';
$request_url = (isset($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : '';
$script_url = (isset($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : '';
if ($request_url != $script_url) $url = trim(preg_replace('/' . str_replace('/', '\/', str_replace('index.php', '', $script_url)) . '/', '', $request_url, 1), '/');
$protocol = $this->get_protocol();
return rtrim(str_replace($url, '', $protocol . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']), '/');
}
$protocol = $this->get_protocol();
return rtrim(str_replace($url, '', $protocol . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']), '/');
}
/**
* Tries to guess the server protocol. Used in base_url()
*
* @return string the current protocol
*/
private function get_protocol()
{
preg_match("|^HTTP[S]?|is",$_SERVER['SERVER_PROTOCOL'],$m);
return strtolower($m[0]);
}
/**
* Helper function to recusively get all files in a directory
*
* @param string $directory start directory
* @param string $ext optional limit to file extensions
* @return array the matched files
*/
private function get_files($directory, $ext = '')
{
$array_items = array();
if($handle = opendir($directory)){
while(false !== ($file = readdir($handle))){
if(preg_match("/^(^\.)/", $file) === 0){
if(is_dir($directory. "/" . $file)){
$array_items = array_merge($array_items, $this->get_files($directory. "/" . $file, $ext));
} else {
$file = $directory . "/" . $file;
if(!$ext || strstr($file, $ext)) $array_items[] = preg_replace("/\/\//si", "/", $file);
}
}
}
closedir($handle);
}
return $array_items;
}
/**
* Helper function to limit the words in a string
*
* @param string $string the given string
* @param int $word_limit the number of words to limit to
* @return string the limited string
*/
private function limit_words($string, $word_limit)
{
$words = explode(' ',$string);
return trim(implode(' ', array_splice($words, 0, $word_limit))) .'...';
}
/**
* Tries to guess the server protocol. Used in base_url()
*
* @return string the current protocol
*/
private function get_protocol()
{
preg_match("|^HTTP[S]?|is", $_SERVER['SERVER_PROTOCOL'], $m);
return strtolower($m[0]);
}
/**
* Helper function to recusively get all files in a directory
*
* @param string $directory start directory
* @param string $ext optional limit to file extensions
* @return array the matched files
*/
private function get_files($directory, $ext = '')
{
$array_items = array();
if ($handle = opendir($directory)) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
if (is_dir($directory . "/" . $file)) {
$array_items = array_merge($array_items, $this->get_files($directory . "/" . $file, $ext));
} else {
$file = $directory . "/" . $file;
if (!$ext || strstr($file, $ext)) $array_items[] = preg_replace("/\/\//si", "/", $file);
}
}
}
closedir($handle);
}
return $array_items;
}
/**
* Helper function to limit the words in a string
*
* @param string $string the given string
* @param int $word_limit the number of words to limit to
* @return string the limited string
*/
private function limit_words($string, $word_limit)
{
$words = explode(' ', $string);
return trim(implode(' ', array_splice($words, 0, $word_limit))) . '...';
}
}
}

View file

@ -44,6 +44,11 @@ class Pico_Plugin {
}
public function before_read_file_meta(&$headers)
{
}
public function file_meta(&$meta)
{
@ -54,6 +59,11 @@ class Pico_Plugin {
}
public function get_page_data(&$data, $page_meta)
{
}
public function get_pages(&$pages, &$current_page, &$prev_page, &$next_page)
{
@ -76,4 +86,4 @@ class Pico_Plugin {
}
// End of file
// End of file

View file

@ -102,5 +102,58 @@
"keywords": [
"templating"
]
},
{
"name": "michelf/php-markdown",
"version": "1.3",
"version_normalized": "1.3.0.0",
"source": {
"type": "git",
"url": "https://github.com/michelf/php-markdown.git",
"reference": "fcdd3e0781ae40c2b9847874e0755ff4f5559688"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/michelf/php-markdown/zipball/fcdd3e0781ae40c2b9847874e0755ff4f5559688",
"reference": "fcdd3e0781ae40c2b9847874e0755ff4f5559688",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"time": "2013-04-11 18:53:11",
"type": "library",
"extra": {
"branch-alias": {
"dev-lib": "1.3.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-0": {
"Michelf": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Michel Fortin",
"email": "michel.fortin@michelf.ca",
"homepage": "http://michelf.ca/",
"role": "Developer"
},
{
"name": "John Gruber",
"homepage": "http://daringfireball.net/"
}
],
"description": "PHP Markdown",
"homepage": "http://michelf.ca/projects/php-markdown/",
"keywords": [
"markdown"
]
}
]