Initial commit

master
Markus Koch 2017-01-27 20:29:27 +01:00
commit ccb900b158
15 changed files with 936 additions and 0 deletions

8
.gitignore vendored 100644
View File

@ -0,0 +1,8 @@
downloads
b/*/*.*
!b/2017/00-template.php
!b/img/2017/fft.png
!b/pimg/keep
s/*
p/*
!p/00-template.php

18
README.MD 100644
View File

@ -0,0 +1,18 @@
[Simpub CMS] - A Simple CMS for Nerds
=====================================
Directories and Files
---------------------
* index.php: Main page, assembles layout and loads sub pages
* shared.php: Shared functions and global settings
* blog.php: Blog core (include from page in /p/ to use)
* page.php: Page core (include from page in /p/ to use)
* control.php: Admin interface
* style.css: Main style file
* userstyle.css: User-defined styles used on content pages
* /p/: User content (use 404.php as error handler)
* /b/: User blog posts. Create subdirectory with year, then drop .php blog posts into there
* /b/img: Again, create subfolder with year, drop images in there
* /b/pimg: Must be writable by www-data, will contain auto-generated thumbnails
* /s/: Resources for pages

44
_index.html 100644
View File

@ -0,0 +1,44 @@
<html>
<head>
<title>Error 500 - Down for maintenance</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=700px, initial-scale=.5"><!-- or width=device-width -->
<link rel="stylesheet" type="text/css" href="style.css" />
<link rel="stylesheet" type="text/css" href="userstyle.css" />
</head>
<!--
Hello random person reading the source code! Nice to meet you!
This page has been generated by [Simpub CMS] which is open source software.
You can find it here: https://git.notsyncing.net:8080/web/simpub
-->
<body>
<nav>
<div id="navContainer">
<ul class="pagetitle"><li style="float: left;"><a class="pagetitle" href="/">[Simpub CMS]</a></li></ul>
</div>
</nav>
<div id="contentContainer">
<content>
<div id="content">
<p style="text-align:center;">
<table border=0>
<tr>
<td style="font-size:14em;">500</td><td style="padding-left:50px; font-size:4em; text-align:left;">Down for maintenance!</td>
</tr>
</table>
</p>
<p>
The site is currently down for maintenance.
Please try again later.
</p>
</div>
</content>
<div id="footer">
|x| I am falling, I am fading, I have lost it all... |x|
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,55 @@
<?php
$blogentry = (object) array(
'file' => __FILE__,
'title' => 'Title',
'description' => 'Description',
'author' => 'Markus',
'tags' => 'video,tags',
'status' => 'unlisted', // released, private, unlisted
'ctime' => strtotime("2017-01-24 20:20")
);
if (!isset($CMS_ACTIVE) or !renderPost()) return;
?>
<p>
<?php
includeVideo("https://www.youtube.com/embed/fzQ6gRAEoy0");
// Preview can be "+" (auto gen), "" (take src) or "<url>" (take url)
// Link will normally link to self
includeGraphics("Random FFT image", "2017/fft.png", $preview="", $style="width:640px;", $link="http://notsyncing.net/");
?>
</p>
<?php
if (extended()) {
?>
<h2>Hidden section</h2>
<p>
This will only show when opening the post, but not on the overview page.
</p>
<?php
}
?>
<h2>Protected section</h2>
<?php
if (password("hello")) {
?>
<p>
This will only show after entering the correct password.
</p>
<?php
}
?>
<h2>Some provided styles</h2>
<p>
<div class="code">
$ some formatted code <br>
$ foobar
</div>
</p>
<p>
Inline <code>$code</code> is also possible.
</p>

BIN
b/img/2017/fft.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

0
b/pimg/keep 100644
View File

263
blog.php 100644
View File

@ -0,0 +1,263 @@
<?php
/*
* blog.php : This file provides the meta data parser for the CMS. It generates the temporary
* file containing the sorted posts. It also handles pre-parsing of embedded content
* such as images.
*/
if (!isset($CMS_ACTIVE)) exit();
require_once "shared.php";
if (isset($_GET['b'])) { // Blog post selector
$postUrl = $_GET['b'];
preg_match("/^[a-z0-9\\-" . POSTS_DIR_SEP . "]*$/", $postUrl, $matches); // SECURITY: Only lowercase a-z + numbers
if (!$matches)
unset($postUrl);
else {
$postUrl=substr($postUrl, 0, POSTS_MAX_FILENAME);
$postUrl=POSTS_ROOT . str_replace(POSTS_DIR_SEP, "/", $postUrl) . ".php";
if (!file_exists($postUrl)) {
unset($postUrl);
}
}
}
$postsPage = 0;
$postsSkip = 0;
if (isset($_GET['s'])) { // Page selector for post listing
if (is_numeric($_GET['s']) && $_GET['s'] < 100) { // SECURITY: MAX 100 pages
$postsPage = (int)$_GET['s'];
$postsSkip = $postsPage * POSTS_PAGE_SIZE;
}
}
$tagSearchUrl = "";
if (isset($_GET['t'])) { // Tag search
$tagSearch = $_GET['t'];
preg_match("/^[a-z0-9]*$/", $tagSearch, $matches); // SECURITY: Only lowercase a-z + numbers
if (!$matches)
unset($tagSearch);
else {
$tagSearch=substr($tagSearch, 0, POSTS_TAG_SEARCH); // SECURITY: Max search length POSTS_TAG_SEARCH
$tagSearchUrl="&t=$tagSearch";
}
}
$userPassword = "";
if (isset($_POST['password'])) { // Protected sections
$userPassword = $_POST['password'];
preg_match("/^[a-z0-9]*$/", $userPassword, $matches); // SECURITY: Only lowercase a-z + numbers
if (!$matches)
$userPassword = "";
else {
$userPassword=substr($userPassword, 0, 32); // SECURITY: Max PW len = 32
}
}
// --- $postUrl is now safe to use! (Full FS path)
// --- $postsPage is now safe to use!
// --- $tagSearch is now safe to use!
// --- $userPassword is now safe to use!
// Function called by the individual post headers to determin whether to display it and
// to configure / complete the metadata.
function renderPost() {
global $CMS_INDEXING;
global $blogentry;
global $counters;
global $meta;
global $pageTitle;
global $postUrl;
global $htmlHead;
$counters['figure'] = 1;
$counters['video'] = 1;
$counters['sources'] = 1;
$meta['sources'] = array();
$blogentry->file = substr($blogentry->file, strlen(POSTS_ROOT), -4);
if (!(($posts = apcu_fetch('posts')) && isset($posts[$blogentry->file]) && $blogentry=$posts[$blogentry->file])) {
//echo "[DBG] Regenerate meta info block...";
if (!isset($blogentry->file))
$blogentry->file = "";
if (!isset($blogentry->title))
$blogentry->title = "Untitled";
if (!isset($blogentry->description))
$blogentry->description = $blogentry->title;
if (!isset($blogentry->author))
$blogentry->author = "Anonymous";
if (!isset($blogentry->status))
$blogentry->status = "private";
if (!isset($blogentry->ctime))
$blogentry->ctime = time();
if (!isset($blogentry->tags))
$blogentry->tags = "untagged";
$blogentry->tags = explode(',', $blogentry->tags);
sort($blogentry->tags);
$blogentry->permalink = "?p=blog&b=" . str_replace("/", POSTS_DIR_SEP, $blogentry->file);
$blogentry->isPublic = ($blogentry->status == "released");
}
$renderIt = $CMS_INDEXING || ($blogentry->status == "released") || ($blogentry->status == "unlisted");
if ($renderIt) {
if (isset($postUrl) && !$CMS_INDEXING) { // Set meta information
$pageTitle = $blogentry->title;
$htmlHead .= '<meta name="description" content="' . $blogentry->description . '">
<meta name="keywords" content="' . join(",", $blogentry->tags) . '">
<meta name="author" content="' . $blogentry->author . '">';
}
echo "<blogheading><table><tr><td><h1><a href=\"$blogentry->permalink\">$blogentry->title</a></h1></td>";
//echo '<td class="date">' . date("l, F jS Y, H:i", $blogentry->ctime) . "</td></tr></table></blogheading>";
echo '<td class="head"><span class="author">' . $blogentry->author . '</span> | <span class="date">' . date("l, F jS Y, H:i", $blogentry->ctime) . "</span></td></tr></table></blogheading>";
}
return $renderIt;
}
function renderFooter() {
global $counters;
global $meta;
$i = 1;
if ($counters['sources'] > 1) {
echo '<hr class="sourceSeparator"><p class="sources">Sources:<br>';
foreach ($meta['sources'] as $v) {
echo '<span id="src' . $i . '">&nbsp;&nbsp;&nbsp;&nbsp;[' . $i++ . ']: <a href="' . $v . '">' . $v . '</a></span><br>';
}
echo '</p><hr class="sourceSeparator">';
}
global $blogentry;
echo '<p class="tags">Tags: ';
foreach ($blogentry->tags as $v) {
echo '<a href="/?p=blog&t=' . $v . '">' . $v . '</a> ';
}
echo "</p>";
}
function extended() {
global $CMS_SINGLE_POST;
global $blogentry;
$renderExt = isset($CMS_SINGLE_POST) && $CMS_SINGLE_POST;
if ($renderExt) {
echo '<span id="more"></span>';
}
else {
echo '<p><a href="' . $blogentry->permalink . '#more">&rarr; Click here to continue reading &larr;</a></p>';
}
return $renderExt;
}
function password($pw) {
global $userPassword;
if ("$userPassword" == "$pw") {
echo '<span id="prot"></span>';
return true;
}
else {
echo "<p>";
if ($userPassword == "")
echo "This section is protected. To view it, enter the correct password.";
else
echo "The password you entered is incorrect! Please try again.";
?>
<form action="#prot" method="post">
<input type="password" name="password"> <input type="submit" value="Unlock section">
</form>
</p>
<?php
}
}
//apcu_clear_cache();
if (!($posts = apcu_fetch('posts'))) {
$CMS_INDEXING = true;
//echo "[DBG] Regenerate post index";
$posts = array();
foreach ($blogDirs as $dirName) {
// Find all posts
$Directory = new RecursiveDirectoryIterator('b/' . $dirName . '/');
$Iterator = new RecursiveIteratorIterator($Directory);
$objects = new RegexIterator($Iterator, '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH);
// Load Meta data and put it into one big archive
//$posts = array();
foreach($objects as $file => $object){
ob_start(); // These ob_lines will prevent output of actual HTML (the function already does this?!)
require "$file";
$blogentry->includeFile = $file;
//echo "<hr>";
ob_end_clean(); // Enable output, drop cached
//array_push($posts, $blogentry);
$posts[$blogentry->file] = $blogentry;
}
# Create list of columns relevant for sorting
$sort = array();
foreach($posts as $k=>$v) {
$sort['ctime'][$k] = $v->ctime;;
// $sort['author'][$k] = $v->author;
}
// Now sort the entries
// Multiple keys: array_multisort($sort['author'], SORT_ASC, $sort['title'], SORT_ASC,$posts);
array_multisort($sort['ctime'], SORT_DESC, $posts);
}
// Store to cache
apcu_store('posts', $posts, CACHE_POSTS_TTL);
$CMS_INDEXING = false;
}
echo "<blog>";
if (isset($postUrl)) { // Display post
$CMS_SINGLE_POST = true;
echo '<div class="post">';
// Header is rendered in renderPost()
require $postUrl; // This will render the body
//if ($blogentry->isPublic) { // Render the blog footer
//echo "<p class=\"author\">Written by $blogentry->author</p>";
renderFooter();
//}
echo '</div>';
}
else {
//echo "<h1>Blog posts</h1>";
if (isset($tagSearch)) {
echo "<h1 class=\"bloginfoheader\">Archive for '$tagSearch'</h1>";
$pageTitle = "Archive for '$tagSearch'";
}
$i = 0;
$morePosts = false;
foreach($posts as $k=>$v) {
if ($v->isPublic) {
if (!isset($tagSearch) || in_array($tagSearch, $v->tags)) {
if ($i++ >= $postsSkip) {
//echo "<a href=\"$v->permalink\">$v->title by $v->author</a><br>";
echo '<div class="post">';
require $v->includeFile;
renderFooter();
echo "</div>";
echo '<hr class="postSeparator">';
if (($i % POSTS_PAGE_SIZE) == 0) {
$morePosts = true;
break;
}
}
}
}
}
if ($morePosts || $postsSkip > 0)
echo "<p><table class=\"blognav\"><tr>";
if ($morePosts)
echo '<td><a href="' . "?p=blog$tagSearchUrl&s=" . ($postsPage+1) . '">&lt;&lt; Older posts</a></td>';
if ($postsSkip > 0)
echo '<td style="text-align:right;"><a href="' . "?p=blog$tagSearchUrl&s=" . ($postsPage-1) . '">Newer posts &gt;&gt;</a></td>';
if ($morePosts || $postsSkip > 0)
echo "</tr></table></p>";
}
echo "</blog>";
?>

4
control.php 100644
View File

@ -0,0 +1,4 @@
<?php
apcu_clear_cache();
?>
Purged cache.

BIN
img/cc-byncsa.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 B

96
index.php 100644
View File

@ -0,0 +1,96 @@
<?php
$CMS_ACTIVE = true;
require_once "shared.php";
$pageTitle = "";
if (isset($_GET['p'])) {
$page = $_GET['p'];
preg_match("/^[a-z0-9\-]*$/", $page, $matches); // SECURITY: Only lowercase a-z + numbers + -
if (!$matches)
$page=HOME_PAGE;
$page=substr($page, 0, 12); // SECURITY: Max 12 chars
}
else {
$page=HOME_PAGE;
}
$pageUrl="p/$page.php";
if (!file_exists($pageUrl)) {
$pageUrl="p/404.php";
$pageTitle = "Error 404";
}
// --- $page and $pageUrl are now SAFE TO USE
$htmlHead = "";
function mkMenu() {
global $page;
global $menuItems;
global $pageTitle;
foreach ($menuItems as $item) {
$menCls = "";
$titleStyle = "";
if (($_SERVER['REQUEST_URI'] == $item['link']) || (strstr($item['highlight'], $page))) {
$menCls = "class=\"selectedMenu\"";
$pageTitle = $item['label'];
}
echo '<li ' . $menCls . '><a href="' . $item['link'] . '">&nbsp;&nbsp;' . $item['label'] . '&nbsp;&nbsp;</a></li> ';
// The &nbsp; in the line above can be removed when using a fixed width style in the .css file.
}
}
if ($page==HOME_PAGE && !strstr($_SERVER['REQUEST_URI'], "&")) // TODO: The second clause is pretty cheap...
$homesel = 'class="selectedMenu"';
else
$homesel = "";
ob_start(function($output) {
global $pageTitle;
global $htmlHead;
$output = '<!DOCTYPE html>
<html>
<head>
<title>' . $pageTitle . ($pageTitle == "" ? "" : " - ") . PAGE_NAME . '</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=700px, initial-scale=.5"><!-- or width=device-width -->
' . $htmlHead . '
<link rel="stylesheet" type="text/css" href="style.css" />
<link rel="stylesheet" type="text/css" href="userstyle.css" />
</head>' . $output;
return $output;
});
?>
<!--
Hello random person reading the source code! Nice to meet you!
This page has been generated by [Simpub CMS] which is open source software.
You can find it here: https://git.notsyncing.net:8080/web/simpub
-->
<body>
<nav>
<div id="navContainer">
<ul class="pagetitle"><li <?php echo $homesel; ?> style="float: left;"><a class="pagetitle" href="/"><?php echo PAGE_NAME; ?></a></li></ul>
<ul>
<?php mkMenu(); ?>
</ul>
</div>
</nav>
<div id="contentContainer">
<content>
<div id="content">
<?php
require $pageUrl;
?>
</div>
</content>
<div id="footer">
Copyright <?php echo PAGE_AUTHOR; ?><!-- and <a href="/?p=extcontent">others</a>--> | <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/us/"><img style="position:relative;top:4px;opacity:0.75;" src="/img/cc-byncsa.png"></a> | <?php echo date("Y"); ?>
</div>
</div>
</body>
</html>
<?php
ob_end_flush();
?>

20
p/00-template.php 100644
View File

@ -0,0 +1,20 @@
<?php
if (!isset($CMS_ACTIVE)) exit();
require("page.php");
?>
<h1>Subpage template</h1>
<p>
This is a subpage. The following code demonstrates the features of page.php.
</p>
<?php
beginEntry("Category 0");
addEntry("Entry 0", "b/img/2016/fft.png", "//link", "Description");
addEntry("Entry 1", "b/img/2016/fft.png", "//link", "Description");
endEntry();
beginEntry("Category 1");
addEntry("Entry 2", "b/img/2016/fft.png", "//link", "Description");
addEntry("Entry 3", "b/img/2016/fft.png", "//link", "Description");
endEntry();
?>

13
page.php 100644
View File

@ -0,0 +1,13 @@
<?php
if (!isset($CMS_ACTIVE)) exit();
function beginEntry($name) {
echo "<div class=\"post\"><details open><summary class=\"pageDetailsHeading\">$name<!--<h2>$name</h2>--></summary><table class=\"listing\">";
}
function addEntry($title, $preview, $link, $description) {
//echo '<tr><td colspan="2"><h3>' . $title . '</h3></td></tr>';
echo '<tr><td style="border-left:2px solid blue;"><a href="' . $link . '"><h3>' . $title . '</h3><img class="previewImage" width=320px src="' . $preview . '"></a></td><td style="border-right:2px solid blue;"><h3>&nbsp;</h3><br>' . $description . '</td></tr><tr><td>&nbsp;</td></tr>';
}
function endEntry() {
echo '</table></details></div><hr class="postSeparator">';
}
?>

138
shared.php 100644
View File

@ -0,0 +1,138 @@
<?php
define('PAGE_NAME', '[Simpub CMS]'); // Title of the page
define('PAGE_AUTHOR', 'Simpub CMS'); // Author of the page (used in footer)
define('HOME_PAGE', 'blog'); // Entry page (and link for logo)
define('CACHE_POSTS_TTL', 3600); // Time to cache the posts list (1h)
define('POSTS_BASE', "/b/"); // Root directory of the posts (relative)
define('POSTS_ROOT', $_SERVER['DOCUMENT_ROOT'] . POSTS_BASE); // Root directory of the posts (absolute)
define('POSTS_PAGE_SIZE', 10); // Numbers of posts on a page
define('POSTS_DIR_SEP', "."); // Directory separator (/) in post names
define('POSTS_MAX_FILENAME', 30); // Maximum length of a post name (including suffix)
define('POSTS_TAG_SEARCH', 30); // Maximum length for the tag search argument
$menuItems = array(
array("label" => "Page A", "link" => "?p=00-template", "highlight" => "related-subpages,00-template"),
array("label" => "Page B", "link" => "?p=404", "highlight" => "404"),
array("label" => "Repository", "link" => "https://git.notsyncing.net:8080", "highlight" => ""),
array("label" => "Contact", "link" => "?p=00-template", "highlight" => "")
);
$blogDirs = array("2017");
/*
* This function will include an image as figure.
* returns : Number of the figure for later referencing.
* $title : Image title, will be prefixed with Figure n.
* $path : If $path starts with http or / it will be
* treated as an absolute path and no downscaled preview will be rendered.
* Other paths will be prefixed with /b/img.
* $preview : When set to "", no preview will be generated. Otherwise the specified
* path will be used.
* $link : Link to follow when clicking the image. Default is the full resolution image.
*/
$counters['figure'] = 1;
function includeGraphics($title, $path, $preview="+", $style="", $link="+") {
global $blogentry;
global $counters;
$title = "Figure " . $counters['figure'] . ". $title";
// TODO: External image
if (substr($path, 0, 4) == "http" || $path[0] == "/") {
$preview="";
$spath=$path;
}
else {
$spath = POSTS_BASE . "img/" . $path;
$fpath = $_SERVER['DOCUMENT_ROOT'] . $spath;
}
if ($preview == "+") {
$previewPath = POSTS_BASE . "pimg/" . str_replace("/", "_", $path);
$fpreviewPath = $_SERVER['DOCUMENT_ROOT'] . $previewPath;
if (!file_exists($fpreviewPath)) {
preg_match("/^[A-Za-z_\.\-0-9\/]*$/", $fpath, $matches); // SANITIZED!
if (!$matches) {
echo "<p>SERVER ERROR: Image not valid!</p>";
return ;
}
$page=substr($page,0,12); // SECURITY: Max 12 chars
exec("gm convert '$fpath' -resize 640 '$fpreviewPath';");
}
}
elseif ($preview == "") {
$previewPath = $spath;
}
else {
$previewPath = $preview;
}
if ($link == "+")
$link = $spath;
echo '<figure>
<a href="' . $link . '">
<img style="' . $style . '" title="' . $title . '" style="margin: 0px;padding: 0px;" src="' . $previewPath . '">
</a>
<figcaption>' . $title . '</figcaption>
</figure>';
return $counters['figure']++;
}
/*
* This function will include a video.
* returns : Number of the video for later referencing.
* $url : URL of the video. Autodetects YouTube. Otherwise HTML5 video.
* $title : Display "Video n. $title" below the video.
* $width : Width of the player
*/
$counters['video'] = 1;
function includeVideo($url, $title="", $width=640) {
global $counters;
// TODO: HTML5 video
echo '<videoframe><div class="videoframe" style="width:' . $width . 'px;height:' . $width*9/16 . 'px">';
echo '<iframe width="100%" height="100%" src="' . $url . '" frameborder="0" allowfullscreen></iframe>';
echo '</div></videoframe>';
if ($title != "") {
echo '<vidcaption>Video ' . $counters['video'] . ". $title</vidcaption>";
}
return $counters['video']++;
}
/*
* This function will add a reference
* returns : Number of the source for later referencing
* $url : URL of the source, if its a number it will not create a new entry.
*/
$meta['sources'] = array();
$counters['sources'] = 1;
function addSource($url) {
global $counters;
global $meta;
if (is_numeric($url)) {
echo "<a href=\"#src$url\">[" . $url . "]</a>";
return $url;
}
else {
// Check whether source already exists
$i = 1;
foreach ($meta['sources'] as $v) {
if ($v == $url) {
echo "<a href=\"#src$i\">[" . $i . "]</a>";
return $i;
}
$i++;
}
// If not found, then add
$meta['sources'][$counters['sources']] = $url;
echo "<a href=\"#src$i\">[" . $counters['sources'] . "]</a>";
return $counters['sources']++;
}
}
?>

277
style.css 100644
View File

@ -0,0 +1,277 @@
/* ------------- General ------------- */
body {
padding:0px;
margin:0px;
font-family: sans-serif;
min-width:724px;
background-color: black;
color: white;
}
/* ------------- Nav bar ------------- */
nav {
width:100%;
height:50px;
background-color:#151515;
box-shadow: 0px 0px 4px white;
border-bottom: 1px solid #222222;
}
nav ul {
list-style: none;
margin: 0;
padding: 0;
text-align: center;
}
nav li {
display: inline-block;
margin: 0 10px;
margin-top: 4px;
transition: all 0.3s;
}
nav a {
padding-top:12px;
padding-bottom:9px;
text-decoration: none;
display: block;
color: #285064;
}
nav ul a {
/*FIXEDWITH width: 80px;*/
padding-top:12px;
padding-bottom:14px;
text-decoration: none;
display: block;
color: #d6d6d6; /*#c21234*/
}
nav a:hover {
color: #ffffff;
border-bottom: 2px solid #ff1234;
margin-bottom: -2px;
}
.selectedMenu {
border-bottom: 2px solid #d91234;
margin-bottom: -2px;
}
.pagetitle {
float: left;
width:auto;
font-family: monospace;
letter-spacing: -2px;
font-size: 20pt;
margin-top: -4px;
padding-bottom: 9px;
}
#navContainer {
max-width: 1280px;
padding:0px;
margin-left: auto;
margin-right: auto;
}
/* ------------- Content ------------- */
#contentContainer {
margin: 10px;
}
#content {
background-color: black;
max-width: 1280px;
padding:12px;
margin-left: auto;
margin-right: auto;
border-radius: 2px;
border: 1px solid #444444;
text-align:justify;
}
#footer {
background-color: #333333;
max-width: 1280px;
padding:10px;
padding-left:12px;
padding-right:12px;
border-radius: 2px;
margin-left: auto;
margin-right: auto;
border: 1px solid #eeeeee;
text-align:center;
font-size: 10pt;
color: #eeeeee;
vertical-align: middle;
}
#footer a {
color: #222222;
text-decoration: none;
}
/* ------------- Elements ------------- */
content {
font-size:11pt;
}
content img {
}
content figure {
font-style: italic;
margin-left:16px;
}
content figcaption {
margin-left: 2px;
}
content .videoframe {
margin-left:16px;
box-shadow: 0px 0px 3px white;
border: 1 px solid #f3f3f3;
}
content vidcaption {
margin-left: 18px;
font-style: italic;
}
content a {
color:#aaaaaa;
text-decoration: none;
}
content pre {
background-color:#dddddd;
padding: 3px;
border-radius: 3px;
}
/* ------------- Blog ------------- */
blog .head {
font-size:10pt;
text-align:right;
vertical-align:top;
}
blog .author {
font-style: italic;
}
blog .date {
}
blog .tags {
font-size: 10pt;
font-style: italic;
}
blog .tags a {
background-color:#222222;
color: white;
padding: 3px;
border-radius: 3px;
}
blog .sources {
font-size: 9pt;
text-align: left;
}
blog h2 {
margin-top:40px;
}
blog img {
width: 640px;
box-shadow: 0px 0px 3px white;
border: 1 px solid #f3f3f3;
}
blog .bloginfoheader { /* Stuff like Search results for 'xx' */
background-color:gray;
color:#f5f5f5;
border-radius: 4px;
padding:2px;
}
blogheading h1 {
/*margin:0px;*/
}
blogheading table {
padding:0px;
margin:0px;
margin-bottom:-18px; /* Cheap fix to correct some spacing */
margin-left:-2px;
margin-top:-2px;
border: 0px;
width:100%;
}
blogheading td {
margin:0px;
padding:0px;
}
blogheading tr {
margin:0px;
padding:0px;
}
blogheading a {
color: inherit;
text-decoration: inherit;
}
.postSeparator {
border:0px;
margin-top: 20px;
/*border-bottom: 1px solid black;
box-shadow: 1px 1px 2px black;*/
}
.blognav {
margin-top:30px;
margin-left:10px;
margin-right:10px;
width: calc(100% - 20px);
}
.blognav a {
background-color: #cccccc;
border-radius: 10px;
padding: 10px;
border: 1px solid black;
transition-duration: .3s;
}
.blognav a:hover {
background-color: #eeeeee;
}
.post {
background-color:#121212; /* #f2f2f2 */
border-radius: 2px;
border: 1px solid #cccccc;
margin: -2px;
padding: 4px;
}
.sourceSeparator {
border:none;
border-bottom: 1px solid #bbbbbb;
}
/* ------------- Entries ------------- */
.pageDetailsHeading {
font-size:1.5em;
font-weight: bold;
margin: 0.3em;
margin-left: 0px;
cursor: pointer;
}
.listing {
width:100%;
}
.listing td {
padding-left: 10px;
padding-right: 10px;
}
.listing .previewImage {
padding-left: 20px;
}
/* ------------- Generic elements ------------- */
.code {
font-family: monospace;
background: #080808;
border: white dashed 1px;
padding: 3px;
word-wrap: break-word;
text-align: left;
/*white-space: pre-wrap;*/
/*line-height: 1.8em;*/
}
code {
font-family: monospace;
background: #080808;
border: white dashed 1px;
padding: 2px;
line-height: 1.8em;
}

0
userstyle.css 100644
View File