Initial commit

Yay! HTMLy was born today.
This commit is contained in:
Danang Probo Sayekti 2014-01-01 21:56:22 +07:00
commit 643b3be88d
69 changed files with 7950 additions and 0 deletions

1
system/.htaccess Normal file
View file

@ -0,0 +1 @@
deny from all

51
system/config.ini Normal file
View file

@ -0,0 +1,51 @@
; The URL of your blog
site.url = ""
; Blog info
blog.title = "HTMLy"
blog.description = "Databaseless Blogging Platform."
; Author info
blog.author = "Admin"
blog.authorid = "admin"
blog.authorbio = "<p>I'm this blog admin.</p>"
blog.copyright = "(c) Your name."
; Social account
social.twitter = "https://twitter.com"
social.facebook = "https://www.facebook.com"
social.google = "https://plus.google.com"
social.tumblr = "http://www.tumblr.com"
; Menu link
blog.menu = ""
; Disqus
disqus.shortname = ""
; Google publisher
google.publisher = ""
; Pagination, RSS, and JSON
posts.perpage = "5"
tag.perpage = "10"
archive.perpage = "10"
search.perpage = "10"
rss.count = "30"
json.count = "10"
; Teaser char count
teaser.char = "200"
; Description char count
description.char = "150"
; Enable image thumbnail on teaser, the options is "true" and "false". If set to "true", you can specify the default thumbnail also.
img.thumbnail = "true"
default.thumbnail = ""
; Set the theme here
views.root = "themes/default"
; Framework config. No need to edit.
views.layout = "layout"

276
system/htmly.php Normal file
View file

@ -0,0 +1,276 @@
<?php
// Change this to your timezone
date_default_timezone_set('Asia/Jakarta');
// Explicitly including the dispatch framework,
// and our functions.php file
require 'system/includes/dispatch.php';
require 'system/includes/functions.php';
// Load the configuration file
config('source', 'system/config.ini');
// The front page of the blog.
// This will match the root url
get('/index', function () {
$page = from($_GET, 'page');
$page = $page ? (int)$page : 1;
$perpage = config('posts.perpage');
$posts = get_posts($page);
$total = '';
if(empty($posts) || $page < 1){
// a non-existing page
not_found();
}
render('main',array(
'page' => $page,
'posts' => $posts,
'canonical' => config('site.url'),
'description' => config('blog.description'),
'bodyclass' => 'infront',
'breadcrumb' => '',
'pagination' => has_pagination($total, $perpage, $page)
));
});
// The tag page
get('/tag/:tag',function($tag){
$page = from($_GET, 'page');
$page = $page ? (int)$page : 1;
$perpage = config('tag.perpage');
$posts = get_tag($tag);
$total = count($posts);
// Extract a specific page with results
$posts = array_slice($posts, ($page-1) * $perpage, $perpage);
if(empty($posts) || $page < 1){
// a non-existing page
not_found();
}
render('main',array(
'title' => ucfirst($tag) .' - ' . config('blog.title'),
'page' => $page,
'posts' => $posts,
'canonical' => config('site.url') . '/tag/' . $tag,
'description' => 'All posts tagged ' . ucfirst($tag) . ' on '. config('blog.title') . '.',
'bodyclass' => 'intag',
'breadcrumb' => '<a href="' . config('site.url') . '">Home</a> &#187; Posts tagged ' . ucfirst($tag),
'pagination' => has_pagination($total, $perpage, $page)
));
});
// The archive page
get('/archive/:req',function($req){
$page = from($_GET, 'page');
$page = $page ? (int)$page : 1;
$perpage = config('archive.perpage');
$posts = get_archive($req);
$total = count($posts);
// Extract a specific page with results
$posts = array_slice($posts, ($page-1) * $perpage, $perpage);
if(empty($posts) || $page < 1){
// a non-existing page
not_found();
}
$time = explode('-', $req);
if (isset($time[0]))
{
$y = 'Y';
}
else {
$y = '';
}
if (isset($time[1]))
{
$m = 'F ';
}
else {
$m = '';
}
if (isset($time[2]))
{
$d = 'd ';
}
else {
$d = '';
}
$date = strtotime($req);
if(!$date){
// a non-existing page
not_found();
}
render('main',array(
'title' => 'Archive - ' . date($d . $m . $y, $date) .' - ' . config('blog.title'),
'page' => $page,
'posts' => $posts,
'canonical' => config('site.url') . '/archive/' . $req,
'description' => 'Archive page for ' . date($d . $m . $y, $date) . ' on ' . config('blog.title') . '.',
'bodyclass' => 'inarchive',
'breadcrumb' => '<a href="' . config('site.url') . '">Home</a> &#187; Archive for ' . date($d . $m . $y, $date),
'pagination' => has_pagination($total, $perpage, $page)
));
});
// The blog post page
get('/:year/:month/:name', function($year, $month, $name){
$post = find_post($year, $month, $name);
$current = $post['current'];
if(!$current){
not_found();
}
if (array_key_exists('prev', $post)) {
$prev = $post['prev'];
}
else {
$prev = array();
}
if (array_key_exists('next', $post)) {
$next= $post['next'];
}
else {
$next = array();
}
render('post',array(
'title' => $current->title .' - ' . config('blog.title'),
'p' => $current,
'canonical' => $current->url,
'description' => $description = get_description($current->body),
'bodyclass' => 'inpost',
'breadcrumb' => '<span typeof="v:Breadcrumb"><a property="v:title" rel="v:url" href="' . config('site.url') . '">Home</a></span> &#187; <span typeof="v:Breadcrumb"><a property="v:title" rel="v:url" href="' . $current->tagurl .'">' . ucfirst($current->tag) . '</a></span> &#187; ' . $current->title,
'prev' => has_prev($prev),
'next' => has_next($next),
'type' => 'blogpost',
));
});
// The static page
get('/search/:keyword', function($keyword){
$page = from($_GET, 'page');
$page = $page ? (int)$page : 1;
$perpage = config('search.perpage');
$posts = get_keyword($keyword);
$total = count($posts);
// Extract a specific page with results
$posts = array_slice($posts, ($page-1) * $perpage, $perpage);
if(empty($posts) || $page < 1){
// a non-existing page
render('404-search', null, false);
die;
}
render('main',array(
'title' => 'Search results for: ' . $keyword . ' - ' . config('blog.title'),
'page' => $page,
'posts' => $posts,
'canonical' => config('site.url') . '/search/' . $keyword,
'description' => 'Search results for: ' . $keyword . ' on '. config('blog.title') . '.',
'bodyclass' => 'insearch',
'breadcrumb' => '<a href="' . config('site.url') . '">Home</a> &#187; Search results for: ' . $keyword,
'pagination' => has_pagination($total, $perpage, $page)
));
});
// The static page
get('/:spage', function($spage){
$post = find_spage($spage);
if(!$post){
not_found();
}
render('post',array(
'title' => $post->title .' - ' . config('blog.title'),
'canonical' => $post->url,
'description' => $description = get_description($post->body),
'bodyclass' => 'inpage',
'breadcrumb' => '<a href="' . config('site.url') . '">Home</a> &#187; ' . $post->title,
'p' => $post,
'type' => 'staticpage',
));
});
// The author page
get('/author/' . config('blog.authorid'), function(){
$user= new stdClass;
$user->body = config('blog.authorbio');
$user->title = config('blog.author');
$user->authorurl = config('site.url') . '/author/' . config('blog.authorid');
render('post',array(
'title' => $user->title .' - ' . config('blog.title'),
'canonical' => $user->authorurl,
'description' => $description = get_description($user->body),
'bodyclass' => 'inprofile',
'breadcrumb' => '<a href="' . config('site.url') . '">Home</a> &#187; ' . $user->title,
'p' => $user,
'type' => 'profile',
));
});
// The JSON API
get('/api/json',function(){
header('Content-type: application/json');
// Print the 10 latest posts as JSON
echo generate_json(get_posts(1, config('json.count')));
});
// Show the RSS feed
get('/feed/rss',function(){
header('Content-Type: application/rss+xml');
// Show an RSS feed with the 30 latest posts
echo generate_rss(get_posts(1, config('rss.count')));
});
// If we get here, it means that
// nothing has been matched above
get('.*',function(){
not_found();
});
// Serve the blog
dispatch();

View file

@ -0,0 +1,499 @@
<?php
if (!defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50300) {
error(500, 'dispatch requires at least PHP 5.3 to run.');
}
function _log($message) {
if (config('debug.enable') == true && php_sapi_name() !== 'cli') {
$file = config('debug.log');
$type = $file ? 3 : 0;
error_log("{$message}\n", $type, $file);
}
}
function site_url(){
if (config('site.url') == null)
error(500, '[site.url] is not set');
// Forcing the forward slash
return rtrim(config('site.url'),'/').'/';
}
function site_path(){
static $_path;
if (config('site.url') == null)
error(500, '[site.url] is not set');
if (!$_path)
$_path = rtrim(parse_url(config('site.url'), PHP_URL_PATH),'/');
return $_path;
}
function error($code, $message) {
@header("HTTP/1.0 {$code} {$message}", true, $code);
die($message);
}
function config($key, $value = null) {
static $_config = array();
if ($key === 'source' && file_exists($value))
$_config = parse_ini_file($value, true);
else if ($value == null)
return (isset($_config[$key]) ? $_config[$key] : null);
else
$_config[$key] = $value;
}
function to_b64($str) {
$str = base64_encode($str);
$str = preg_replace('/\//', '_', $str);
$str = preg_replace('/\+/', '.', $str);
$str = preg_replace('/\=/', '-', $str);
return trim($str, '-');
}
function from_b64($str) {
$str = preg_replace('/\_/', '/', $str);
$str = preg_replace('/\./', '+', $str);
$str = preg_replace('/\-/', '=', $str);
$str = base64_decode($str);
return $str;
}
if (extension_loaded('mcrypt')) {
function encrypt($decoded, $algo = MCRYPT_RIJNDAEL_256, $mode = MCRYPT_MODE_CBC) {
if (($secret = config('cookies.secret')) == null)
error(500, '[cookies.secret] is not set');
$secret = mb_substr($secret, 0, mcrypt_get_key_size($algo, $mode));
$iv_size = mcrypt_get_iv_size($algo, $mode);
$iv_code = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM);
$encrypted = to_b64(mcrypt_encrypt($algo, $secret, $decoded, $mode, $iv_code));
return sprintf('%s|%s', $encrypted, to_b64($iv_code));
}
function decrypt($encoded, $algo = MCRYPT_RIJNDAEL_256, $mode = MCRYPT_MODE_CBC) {
if (($secret = config('cookies.secret')) == null)
error(500, '[cookies.secret] is not set');
$secret = mb_substr($secret, 0, mcrypt_get_key_size($algo, $mode));
list($enc_str, $iv_code) = explode('|', $encoded);
$enc_str = from_b64($enc_str);
$iv_code = from_b64($iv_code);
$enc_str = mcrypt_decrypt($algo, $secret, $enc_str, $mode, $iv_code);
return rtrim($enc_str, "\0");
}
}
function set_cookie($name, $value, $expire = 31536000, $path = '/') {
$value = (function_exists('encrypt') ? encrypt($value) : $value);
setcookie($name, $value, time() + $expire, $path);
}
function get_cookie($name) {
$value = from($_COOKIE, $name);
if ($value)
$value = (function_exists('decrypt') ? decrypt($value) : $value);
return $value;
}
function delete_cookie() {
$cookies = func_get_args();
foreach ($cookies as $ck)
setcookie($ck, '', -10, '/');
}
// if we have APC loaded, enable cache functions
if (extension_loaded('apc')) {
function cache($key, $func, $ttl = 0) {
if (($data = apc_fetch($key)) === false) {
$data = call_user_func($func);
if ($data !== null) {
apc_store($key, $data, $ttl);
}
}
return $data;
}
function cache_invalidate() {
foreach (func_get_args() as $key) {
apc_delete($key);
}
}
}
function warn($name = null, $message = null) {
static $warnings = array();
if ($name == '*')
return $warnings;
if (!$name)
return count(array_keys($warnings));
if (!$message)
return isset($warnings[$name]) ? $warnings[$name] : null ;
$warnings[$name] = $message;
}
function _u($str) {
return urlencode($str);
}
function _h($str, $enc = 'UTF-8', $flags = ENT_QUOTES) {
return htmlentities($str, $flags, $enc);
}
function from($source, $name) {
if (is_array($name)) {
$data = array();
foreach ($name as $k)
$data[$k] = isset($source[$k]) ? $source[$k] : null ;
return $data;
}
return isset($source[$name]) ? $source[$name] : null ;
}
function stash($name, $value = null) {
static $_stash = array();
if ($value === null)
return isset($_stash[$name]) ? $_stash[$name] : null;
$_stash[$name] = $value;
return $value;
}
function method($verb = null) {
if ($verb == null || (strtoupper($verb) == strtoupper($_SERVER['REQUEST_METHOD'])))
return strtoupper($_SERVER['REQUEST_METHOD']);
error(400, 'bad request');
}
function client_ip() {
if (isset($_SERVER['HTTP_CLIENT_IP']))
return $_SERVER['HTTP_CLIENT_IP'];
else if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
return $_SERVER['HTTP_X_FORWARDED_FOR'];
return $_SERVER['REMOTE_ADDR'];
}
function redirect(/* $code_or_path, $path_or_cond, $cond */) {
$argv = func_get_args();
$argc = count($argv);
$path = null;
$code = 302;
$cond = true;
switch ($argc) {
case 3:
list($code, $path, $cond) = $argv;
break;
case 2:
if (is_string($argv[0]) ? $argv[0] : $argv[1]) {
$code = 302;
$path = $argv[0];
$cond = $argv[1];
} else {
$code = $argv[0];
$path = $argv[1];
}
break;
case 1:
if (!is_string($argv[0]))
error(500, 'bad call to redirect()');
$path = $argv[0];
break;
default:
error(500, 'bad call to redirect()');
}
$cond = (is_callable($cond) ? !!call_user_func($cond) : !!$cond);
if (!$cond)
return;
header('Location: '.$path, true, $code);
exit;
}
function partial($view, $locals = null) {
if (is_array($locals) && count($locals)) {
extract($locals, EXTR_SKIP);
}
if (($view_root = config('views.root')) == null)
error(500, "[views.root] is not set");
$path = basename($view);
$view = preg_replace('/'.$path.'$/', "_{$path}", $view);
$view = "{$view_root}/{$view}.html.php";
if (file_exists($view)) {
ob_start();
require $view;
return ob_get_clean();
} else {
error(500, "partial [{$view}] not found");
}
return '';
}
function content($value = null) {
return stash('$content$', $value);
}
function render($view, $locals = null, $layout = null) {
if (is_array($locals) && count($locals)) {
extract($locals, EXTR_SKIP);
}
if (($view_root = config('views.root')) == null)
error(500, "[views.root] is not set");
ob_start();
include "{$view_root}/{$view}.html.php";
content(trim(ob_get_clean()));
if ($layout !== false) {
if ($layout == null) {
$layout = config('views.layout');
$layout = ($layout == null) ? 'layout' : $layout;
}
$layout = "{$view_root}/{$layout}.html.php";
header('Content-type: text/html; charset=utf-8');
ob_start();
require $layout;
echo trim(ob_get_clean());
} else {
echo content();
}
}
function json($obj, $code = 200) {
header('Content-type: application/json', true, $code);
echo json_encode($obj);
exit;
}
function condition() {
static $cb_map = array();
$argv = func_get_args();
$argc = count($argv);
if (!$argc)
error(500, 'bad call to condition()');
$name = array_shift($argv);
$argc = $argc - 1;
if (!$argc && is_callable($cb_map[$name]))
return call_user_func($cb_map[$name]);
if (is_callable($argv[0]))
return ($cb_map[$name] = $argv[0]);
if (is_callable($cb_map[$name]))
return call_user_func_array($cb_map[$name], $argv);
error(500, 'condition ['.$name.'] is undefined');
}
function middleware($cb_or_path = null) {
static $cb_map = array();
if ($cb_or_path == null || is_string($cb_or_path)) {
foreach ($cb_map as $cb) {
call_user_func($cb, $cb_or_path);
}
} else {
array_push($cb_map, $cb_or_path);
}
}
function filter($sym, $cb_or_val = null) {
static $cb_map = array();
if (is_callable($cb_or_val)) {
$cb_map[$sym] = $cb_or_val;
return;
}
if (is_array($sym) && count($sym) > 0) {
foreach ($sym as $s) {
$s = substr($s, 1);
if (isset($cb_map[$s]) && isset($cb_or_val[$s]))
call_user_func($cb_map[$s], $cb_or_val[$s]);
}
return;
}
error(500, 'bad call to filter()');
}
function route_to_regex($route) {
$route = preg_replace_callback('@:[\w]+@i', function ($matches) {
$token = str_replace(':', '', $matches[0]);
return '(?P<'.$token.'>[a-z0-9_\0-\.]+)';
}, $route);
return '@^'.rtrim($route, '/').'$@i';
}
function route($method, $pattern, $callback = null) {
// callback map by request type
static $route_map = array(
'GET' => array(),
'POST' => array()
);
$method = strtoupper($method);
if (!in_array($method, array('GET', 'POST')))
error(500, 'Only GET and POST are supported');
// a callback was passed, so we create a route defiition
if ($callback !== null) {
// create a route entry for this pattern
$route_map[$method][$pattern] = array(
'xp' => route_to_regex($pattern),
'cb' => $callback
);
} else {
// callback is null, so this is a route invokation. look up the callback.
foreach ($route_map[$method] as $pat => $obj) {
// if the requested uri ($pat) has a matching route, let's invoke the cb
if (!preg_match($obj['xp'], $pattern, $vals))
continue;
// call middleware
middleware($pattern);
// construct the params for the callback
array_shift($vals);
preg_match_all('@:([\w]+)@', $pat, $keys, PREG_PATTERN_ORDER);
$keys = array_shift($keys);
$argv = array();
foreach ($keys as $index => $id) {
$id = substr($id, 1);
if (isset($vals[$id])) {
array_push($argv, trim(urldecode($vals[$id])));
}
}
// call filters if we have symbols
if (count($keys)) {
filter(array_values($keys), $vals);
}
// if cb found, invoke it
if (is_callable($obj['cb'])) {
call_user_func_array($obj['cb'], $argv);
}
// leave after first match
break;
}
}
}
function get($path, $cb) {
route('GET', $path, $cb);
}
function post($path, $cb) {
route('POST', $path, $cb);
}
function flash($key, $msg = null, $now = false) {
static $x = array(),
$f = null;
$f = (config('cookies.flash') ? config('cookies.flash') : '_F');
if ($c = get_cookie($f))
$c = json_decode($c, true);
else
$c = array();
if ($msg == null) {
if (isset($c[$key])) {
$x[$key] = $c[$key];
unset($c[$key]);
set_cookie($f, json_encode($c));
}
return (isset($x[$key]) ? $x[$key] : null);
}
if (!$now) {
$c[$key] = $msg;
set_cookie($f, json_encode($c));
}
$x[$key] = $msg;
}
function dispatch() {
$path = $_SERVER['REQUEST_URI'];
if (config('site.url') !== null)
$path = preg_replace('@^'.preg_quote(site_path()).'@', '', $path);
$parts = preg_split('/\?/', $path, -1, PREG_SPLIT_NO_EMPTY);
$uri = trim($parts[0], '/');
$uri = strlen($uri) ? $uri : 'index';
route(method(), "/{$uri}");
}
?>

View file

@ -0,0 +1,644 @@
<?php
// Change this to your timezone
date_default_timezone_set('Asia/Jakarta');
use dflydev\markdown\MarkdownParser;
use \Suin\RSSWriter\Feed;
use \Suin\RSSWriter\Channel;
use \Suin\RSSWriter\Item;
// Get blog post
function get_post_names(){
static $_cache = array();
if(empty($_cache)){
// Get the names of all the
// posts (newest first):
$_cache = array_reverse(glob('content/blog/*.md'));
}
return $_cache;
}
// Get static page
function get_spage_names(){
static $_cache = array();
if(empty($_cache)){
// Get the names of all the
// static page (newest first):
$_cache = array_reverse(glob('content/static/*.md'));
}
return $_cache;
}
// Return blog post
function get_posts($page = 1, $perpage = 0){
if($perpage == 0){
$perpage = config('posts.perpage');
}
$posts = get_post_names();
// Extract a specific page with results
$posts = array_slice($posts, ($page-1) * $perpage, $perpage);
$tmp = array();
// Create a new instance of the markdown parser
$md = new MarkdownParser();
foreach($posts as $k=>$v){
$post = new stdClass;
// Extract the date
$arr = explode('_', $v);
// The post author + author url
$post->author = config('blog.author');
$post->authorurl = site_url() . 'author/' . config('blog.authorid');
// The post date
$post->date = strtotime(str_replace('content/blog/','',$arr[0]));
// The archive per day
$post->archive = site_url(). str_replace('content/blog/','archive/',$arr[0]);
// The post URL
$post->url = site_url().date('Y/m', $post->date).'/'.str_replace('.md','',$arr[2]);
// The post tag
$post->tag = str_replace('content/blog/','',$arr[1]);
// The post tag url
$post->tagurl = site_url(). 'tag/' . $arr[1];
// Get the contents and convert it to HTML
$content = $md->transformMarkdown(file_get_contents($v));
// Extract the title and body
$arr = explode('</h1>', $content);
$post->title = str_replace('<h1>','',$arr[0]);
$post->body = $arr[1];
$tmp[] = $post;
}
return $tmp;
}
// Find post by year, month and name, previous, and next.
function find_post($year, $month, $name){
$posts = get_post_names();
foreach($posts as $index => $v){
if( strpos($v, "$year-$month") !== false && strpos($v, $name.'.md') !== false){
// Use the get_posts method to return
// a properly parsed object
$ar = get_posts($index+1,1);
$nx = get_posts($index,1);
$pr = get_posts($index+2,1);
if ($index == 0) {
if(isset($pr[0])) {
return array(
'current'=> $ar[0],
'prev'=> $pr[0]
);
}
else {
return array(
'current'=> $ar[0],
'prev'=> null
);
}
}
elseif (count($posts) == $index+1) {
return array(
'current'=> $ar[0],
'next'=> $nx[0]
);
}
else {
return array(
'current'=> $ar[0],
'next'=> $nx[0],
'prev'=> $pr[0]
);
}
}
}
return false;
}
// Return tag page
function get_tag($tag){
$posts = get_post_names();
$tmp = array();
// Create a new instance of the markdown parser
$md = new MarkdownParser();
foreach($posts as $index => $v){
if( strpos($v, "$tag") !== false){
$post = new stdClass;
// Extract the date
$arr = explode('_', $v);
// Make sure the tag request available
if ($tag === $arr[1]) {
// The post author + author url
$post->author = config('blog.author');
$post->authorurl = site_url() . 'author/' . config('blog.authorid');
// The post date
$post->date = strtotime(str_replace('content/blog/','',$arr[0]));
// The post URL
$post->url = site_url().date('Y/m', $post->date).'/'.str_replace('.md','',$arr[2]);
// The post tag
$post->tag = str_replace('content/blog/','',$arr[1]);
// The post tag URL
$post->tagurl = site_url(). 'tag/' . $arr[1];
// Get the contents and convert it to HTML
$content = $md->transformMarkdown(file_get_contents($v));
// Extract the title and body
$arr = explode('</h1>', $content);
$post->title = str_replace('<h1>','',$arr[0]);
$post->body = $arr[1];
$tmp[] = $post;
}
else {
not_found();
}
}
}
return $tmp;
}
// Return an archive page
function get_archive($req){
$posts = get_post_names();
$tmp = array();
// Create a new instance of the markdown parser
$md = new MarkdownParser();
foreach($posts as $index => $v){
if( strpos($v, "$req") !== false){
$post = new stdClass;
// Extract the date
$arr = explode('_', $v);
// The post author + author url
$post->author = config('blog.author');
$post->authorurl = site_url() . 'author/' . config('blog.authorid');
// The post date
$post->date = strtotime(str_replace('content/blog/','',$arr[0]));
// The post URL
$post->url = site_url().date('Y/m', $post->date).'/'.str_replace('.md','',$arr[2]);
// The post tag
$post->tag = str_replace('content/blog/','',$arr[1]);
// The post tag URL
$post->tagurl = site_url(). 'tag/' . $arr[1];
// Get the contents and convert it to HTML
$content = $md->transformMarkdown(file_get_contents($v));
// Extract the title and body
$arr = explode('</h1>', $content);
$post->title = str_replace('<h1>','',$arr[0]);
$post->body = $arr[1];
$tmp[] = $post;
}
}
return $tmp;
}
// Return an archive list, categorized by year and month
function archive_list() {
$posts = get_post_names();
$by_year = array();
$col = array();
foreach($posts as $index => $v){
$arr = explode('_', $v);
$date = str_replace('content/blog/','',$arr[0]);
$data = explode('-', $date);
$col[] = $data;
}
foreach ($col as $row){
$y = $row['0'];
$m = $row['1'];
$by_year[$y][] = $m;
}
# Most recent year first
krsort($by_year);
# Iterate for display
foreach ($by_year as $year => $months){
echo '<span class="year"><a href="' . site_url() . 'archive/' . $year . '">' . $year . '</a></span> ';
echo '(' . count($months) . ')';
echo '<ul class="month">';
# Sort the months
ksort($months);
$by_month = array_count_values($months);
foreach ($by_month as $month => $count){
$name = date('F', mktime(0,0,0,$month,1,2010));
echo '<li class="item"><a href="' . site_url() . 'archive/' . $year . '-' . $month . '">' . $name . '</a>';
echo ' (' . $count . ')</li>';
echo '</li>';
}
echo '</ul>';
}
}
// Return static page
function get_spage($posts, $spage){
$tmp = array();
// Create a new instance of the markdown parser
$md = new MarkdownParser();
foreach($posts as $index => $v){
if( strpos($v, "$spage") !== false && strpos($v, $spage.'.md') !== false){
$post = new stdClass;
// Extract the array
$arr = explode('_', $v);
// The static page URL
$url = str_replace('content/static/','',$arr[0]);
$post->url = site_url() . str_replace('.md','',$url);
// Get the contents and convert it to HTML
$content = $md->transformMarkdown(file_get_contents($v));
// Extract the title and body
$arr = explode('</h1>', $content);
$post->title = str_replace('<h1>','',$arr[0]);
$post->body = $arr[1];
$tmp[] = $post;
}
}
return $tmp;
}
// Find static page
function find_spage($spage){
$posts = get_spage_names();
foreach($posts as $index => $v){
if( strpos($v, "$spage") !== false && strpos($v, $spage.'.md') !== false){
// Use the get_spage method to return
// a properly parsed object
$arr = get_spage($posts, $spage);
return $arr[0];
}
}
return false;
}
// Return search page
function get_keyword($keyword){
$posts = get_post_names();
$tmp = array();
// Create a new instance of the markdown parser
$md = new MarkdownParser();
foreach($posts as $index => $v){
$content = $md->transformMarkdown(file_get_contents($v));
if(strpos(strtolower(strip_tags($content)), strtolower($keyword)) !== false){
$post = new stdClass;
// Extract the date
$arr = explode('_', $v);
// Make sure the tag request available
// The post author + author url
$post->author = config('blog.author');
$post->authorurl = site_url() . 'author/' . config('blog.authorid');
// The post date
$post->date = strtotime(str_replace('content/blog/','',$arr[0]));
// The post URL
$post->url = site_url().date('Y/m', $post->date).'/'.str_replace('.md','',$arr[2]);
// The post tag
$post->tag = str_replace('content/blog/','',$arr[1]);
// The post tag URL
$post->tagurl = site_url(). 'tag/' . $arr[1];
// Extract the title and body
$arr = explode('</h1>', $content);
$post->title = str_replace('<h1>','',$arr[0]);
$post->body = $arr[1];
$tmp[] = $post;
}
}
return $tmp;
}
// Helper function to determine whether
// to show the previous buttons
function has_prev($prev){
if(!empty($prev)) {
return array(
'url'=> $prev->url,
'title'=> $prev->title
);
}
}
// Helper function to determine whether
// to show the next buttons
function has_next($next){
if(!empty($next)) {
return array(
'url'=> $next->url,
'title'=> $next->title
);
}
}
// Helper function to determine whether
// to show the pagination buttons
function has_pagination($total, $perpage, $page = 1){
if(!$total) {
$total = count(get_post_names());
}
return array(
'prev'=> $page > 1,
'next'=> $total > $page*$perpage
);
}
// Get the meta description
function get_description($text) {
$string = explode('</p>', $text);
$string = preg_replace('@[\s]{2,}@',' ', strip_tags($string[0] . '</p>'));
if (strlen($string) > 1) {
return $string;
}
else {
$string = preg_replace('@[\s]{2,}@',' ', strip_tags($text));
if (strlen($string) < config('description.char')) {
return $string;
}
else {
return $string = substr($string, 0, strpos($string, ' ', config('description.char')));
}
}
}
// Get the teaser
function get_teaser($text, $url) {
if (strlen(strip_tags($text)) < config('teaser.char')) {
$string = preg_replace('@[\s]{2,}@',' ', strip_tags($text));
$body = $string . '...' . ' <a class="readmore" href="' . $url . '#more">more</a>' ;
echo '<p>' . $body . '</p>';
}
else {
$string = preg_replace('@[\s]{2,}@',' ', strip_tags($text));
$string = substr($string, 0, strpos($string, ' ', config('teaser.char')));
$body = $string . '...' . ' <a class="readmore" href="' . $url . '#more">more</a>' ;
echo '<p>' . $body . '</p>';
}
}
// Get thumbnail from image and Youtube.
function get_thumbnail($text) {
$default = config('default.thumbnail');
$dom = new DOMDocument();
$dom->loadHtml($text);
$imgTags = $dom->getElementsByTagName('img');
$vidTags = $dom->getElementsByTagName('iframe');
if ($imgTags->length > 0) {
$imgElement = $imgTags->item(0);
$imgSource = $imgElement->getAttribute('src');
return '<div class="thumbnail" style="background-image:url(' . $imgSource . ');"></div>';
}
elseif ($vidTags->length > 0) {
$vidElement = $vidTags->item(0);
$vidSource = $vidElement->getAttribute('src');
$fetch = explode("embed/", $vidSource);
if(isset($fetch[1])) {
$vidThumb = '//img.youtube.com/vi/' . $fetch[1] . '/default.jpg';
return '<div class="thumbnail" style="background-image:url(' . $vidThumb . ');"></div>';
}
}
else {
if (!empty($default)) {
return '<div class="thumbnail" style="background-image:url(' . $default . ');"></div>';
}
}
}
// Use base64 encode image to speed up page load time.
function base64_encode_image($filename=string,$filetype=string) {
if ($filename) {
$imgbinary = fread(fopen($filename, "r"), filesize($filename));
return 'data:image/' . $filetype . ';base64,' . base64_encode($imgbinary);
}
}
// Social links
function social(){
$twitter = config('social.twitter');
$facebook = config('social.facebook');
$google = config('social.google');
$tumblr = config('social.tumblr');
$rss = site_url() . 'feed/rss';
if (!empty($twitter)) {
echo '<a href="' . $twitter . '" target="_blank"><img src="' . site_url() . 'themes/default/img/twitter.png" width="32" height="32" alt="Twitter"/></a>';
}
if (!empty($facebook)) {
echo '<a href="' . $facebook . '" target="_blank"><img src="' . site_url() . 'themes/default/img/facebook.png" width="32" height="32" alt="Facebook"/></a>';
}
if (!empty($google)) {
echo '<a href="' . $google . '" target="_blank" rel="author"><img src="' . site_url() . 'themes/default/img/googleplus.png" width="32" height="32" alt="Google+"/></a>';
}
if (!empty($tumblr)) {
echo '<a href="' . $tumblr . '" target="_blank"><img src="' . site_url() . 'themes/default/img/tumblr.png" width="32" height="32" alt="Tumblr"/></a>';
}
echo '<a href="' . site_url() . 'feed/rss" target="_blank"><img src="' . site_url() . 'themes/default/img/rss.png" width="32" height="32" alt="RSS Feed"/></a>';
}
// Copyright
function copyright(){
$blogcp = config('blog.copyright');
$credit = 'Proudly powered by <a href="http://www.htmly.com" target="_blank">HTMLy</a>.';
if (!empty($blogcp)) {
return $copyright = '<p>' . $blogcp . '</p><p>' . $credit . '</p>';
}
else {
return $credit = '<p>' . $credit . '</p>';
}
}
// Disqus
function disqus($title, $url){
$disqus = config('disqus.shortname');
$script = <<<EOF
<script type="text/javascript">
var disqus_shortname = '{$disqus}';
var disqus_title = '{$title}';
var disqus_url = '{$url}';
(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
EOF;
if (!empty($disqus)) {
return $script;
}
}
// Disqus
function disqus_count(){
$disqus = config('disqus.shortname');
$script = <<<EOF
<script type="text/javascript">
var disqus_shortname = '{$disqus}';
(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = '//' + disqus_shortname + '.disqus.com/count.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
EOF;
if (!empty($disqus)) {
return $script;
}
}
// Google Publisher
function publisher(){
$publisher = config('google.publisher');
if (!empty($publisher)) {
return $publisher;
}
}
// Menu
function menu(){
$menu = config('blog.menu');
if (!empty($menu)) {
return $menu;
}
}
// The not found error
function not_found(){
error(404, render('404', null, false));
}
// Turn an array of posts into an RSS feed
function generate_rss($posts){
$feed = new Feed();
$channel = new Channel();
$channel
->title(config('blog.title'))
->description(config('blog.description'))
->url(site_url())
->appendTo($feed);
foreach($posts as $p){
$item = new Item();
$item
->title($p->title)
->description($p->body)
->url($p->url)
->appendTo($channel);
}
echo $feed;
}
// Turn an array of posts into a JSON
function generate_json($posts){
return json_encode($posts);
}