Last active
July 2, 2018 16:51
-
-
Save SnugglePilot/efb48ffaf3e91a3c55e4b71b93d8c6c5 to your computer and use it in GitHub Desktop.
the LUX Web Engine: a simple not-a-blog thing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// LUX Web Engine - created bespoke for SnugglePilot.com. | |
// Created by Andy Moore. Run this code at your own risk. "Whatever" license I guess. | |
// Changelog/instructions: http://snugglepilot.com/?p=lux%20web%20engine | |
// v8 - Updated July 2nd, 2018 | |
// ############## | |
// Configuration: | |
// ############## | |
$contentPath = "content/"; // relative folder to your content (text) files | |
$imagePath = "images/"; // relative folder to your image files | |
$defaultFile = "default"; // what content (text) file to show if no other is specified | |
$failFile = "404"; // what content (text) file to show if something was specified, but doesn't exist | |
$suffix = ".txt"; // what extension your content files have. | |
// so, eg, "content/default.txt" will be what is shown when you first load this page. | |
// Patterns are regular-expressions. Try using this site to make your own: https://regexr.com/ | |
$linkPattern = "/\[[\w\d -'\|]+\]/"; // What we turn into links. default: [Link] or [real file|Label] | |
$imagePattern = "/\[[\w\d]+\.[\w\d]+\]/"; // What we turn into images. default: [image.png] | |
$boldPattern = "/\*.*?\*/"; // What we turn bold. default: *bold* | |
$italicsPattern = "/(?:^| )_.*?_/"; // What we turn into italics. default: _italics_ | |
$hrPattern = "/(?:[\r\n])---[\r\n]/"; // What we turn into an <HR>. default: --- (alone on a line) | |
$quotePattern = "/^> .*$/m"; // What we turn into a quote. default: > | |
$bulletedListCharacter = "*"; // What we use to indicate a bulleted list. | |
$numberedListCharacter = "#"; // What we use to indicate a numbered list. | |
$lineBreakListTolerance = 1; // How many line breaks starts a new list? | |
$linkSplitCharacter = "|"; // What we use to split a link description, eg [link|displayed text] | |
$latestEntryKeyword = "<<LATEST_ENTRIES>>"; // What we turn into a list of recently updated things. | |
$numberOfLatestEntries = 5; // How many latest entries to display. | |
// ####################################################### | |
// Not much to edit after this, unless you really want to. | |
// ####################################################### | |
// Global variables. We don't use these in the content; they are available if you want to include | |
// them in the header or the footer. | |
$pageTitle = ""; // Populated by ParseContent | |
$pageModifyDate = ""; // Populated by ParseContent | |
$content = ParseContent(); // Generate content and populate the above global vars. | |
// This actually renders the page: | |
include("header.php"); // Just HTML, put what you like here. | |
echo $content; | |
include("footer.php"); // Just HTML, put what you like here. | |
// ####################################################### | |
// This is the heavy-lifting main-parser for the site. | |
function ParseContent() { | |
global $latestEntryKeyword, $numberOfLatestEntries, $bulletedListCharacter, $numberedListCharacter; | |
// Fetch appropriate content. | |
$content = GetRelevantContent(); | |
// Parse [Links] to other content. | |
// Eg, if you write [Link] it will instead display this as an <a href="link.txt">Link</a>. | |
// Will turn spaces into underscores automatically. make sure your content files are all lower case. | |
$content = ParseLinkTags($content); | |
// Parse [image.png] references: | |
// Same as links but shows images instead. make sure they are lower case. | |
$content = ParseImageTags($content); | |
// Generate latest entries lists with magic keyword: | |
// (this is an unstyled hack right now but it works. Just put the magic word in your document and it'll be fine) | |
if (strpos($content, $latestEntryKeyword) !== false) { | |
$content = str_replace($latestEntryKeyword, GetLatestEntries($numberOfLatestEntries), $content); | |
} | |
// Parse formatting things: | |
$content = ParseList($content, $bulletedListCharacter, "ul"); // lists should come before bold because they use the same character. | |
$content = ParseList($content, $numberedListCharacter, "ol"); | |
$content = ParseQuotes($content); | |
$content = ParseBoldTags($content); | |
$content = ParseItalicsTags($content); | |
$content = ParseHRTags($content); | |
// This converts newline characters to <BR> characters: | |
$content = nl2br($content); | |
return $content; | |
} | |
// This checks the URL and fetches the relevant content. | |
function GetRelevantContent() { | |
global $contentPath, $suffix, $failFile, $defaultFile, $pageTitle, $pageModifyDate; | |
if (isset($_GET["p"])) { | |
// A specific page has been requested: | |
$contentFile = $_GET["p"]; | |
$contentFile = str_replace("%20", " ", $contentFile); | |
if ($contentFile != $defaultFile) { | |
$pageTitle = $contentFile; | |
} | |
} else { | |
// Falling back to default file: | |
$contentFile = $defaultFile; | |
} | |
$fileFullPath = $contentPath . $contentFile . $suffix; | |
if (!file_exists($fileFullPath)) { | |
// Show error file - invalid link: | |
$fileFullPath = $contentPath . $failFile . $suffix; | |
$pageTitle = $failFile; | |
if (!file_exists($fileFullPath)) { | |
// Great, the error file doesn't exist. | |
http_response_code(404); | |
echo "<html><head><title>404</title></head><body>Site owner hasn't set up a 404 page.</body></html>"; | |
die(); | |
} | |
} | |
$pageModifyDate = TimeElapsed("@".filemtime($fileFullPath)); | |
return file_get_contents($fileFullPath); | |
} | |
function ParseQuotes($content) { | |
global $quotePattern; | |
$matches = GetPatternMatch($content, $quotePattern); | |
for ($i = 0; $i < count($matches); $i++) { | |
// strip out the tag | |
$targetPhrase = substr($matches[$i], 1); | |
$targetPhrase = "<blockquote>".$targetPhrase."</blockquote>"; | |
$content = str_replace($matches[$i], $targetPhrase, $content); | |
} | |
return $content; | |
} | |
function ParseBoldTags($content) { | |
global $boldPattern; | |
$matches = GetPatternMatch($content, $boldPattern); | |
for ($i = 0; $i < count($matches); $i++) { | |
// strip out the tag | |
$targetPhrase = substr($matches[$i], 1, strlen($matches[$i])-2); | |
$targetPhrase = "<strong>".$targetPhrase."</strong>"; | |
$content = str_replace($matches[$i], $targetPhrase, $content); | |
} | |
return $content; | |
} | |
function ParseItalicsTags($content) { | |
global $italicsPattern; | |
$matches = GetPatternMatch($content, $italicsPattern); | |
for ($i = 0; $i < count($matches); $i++) { | |
// strip out the tag | |
$targetPhrase = substr($matches[$i], 2, strlen($matches[$i])-3); | |
$targetPhrase = " <em>".$targetPhrase."</em>"; | |
$content = str_replace($matches[$i], $targetPhrase, $content); | |
} | |
return $content; | |
} | |
function ParseHRTags($content) { | |
global $hrPattern; | |
$matches = GetPatternMatch($content, $hrPattern); | |
for ($i = 0; $i < count($matches); $i++) { | |
$targetPhrase = "<br/><hr/>"; | |
$content = str_replace($matches[$i], $targetPhrase, $content); | |
} | |
return $content; | |
} | |
function ParseList($content, $listCharacter, $listType) { | |
global $lineBreakListTolerance; | |
// grabbed this from: https://stackoverflow.com/questions/2344563/a-regex-that-converts-text-lists-to-html-in-php | |
$listPattern = "/^\\".$listCharacter." .*$/m"; | |
$matches = GetPatternMatch($content, $listPattern); | |
for ($i = 0; $i < count($matches); $i++) { | |
// strip out the tag | |
$targetPhrase = substr($matches[$i], 2); | |
// This puts each dot in it's own list: | |
$targetPhrase = "<".$listType."><li>".$targetPhrase."</li></".$listType.">"; | |
$content = str_replace($matches[$i], $targetPhrase, $content); | |
} | |
// This removes double </ul><ul> tags to simplify things: | |
// {0,2} for the \n tag would be better but that doesn't properly capture mushed together html :/ | |
$content = preg_replace("/(\<\/".$listType."\>\n{1,".$lineBreakListTolerance."}(.*)\<".$listType."\>*)+/","", $content); | |
return $content; | |
} | |
// Just a loop to fire GetTextLink a whole bunch. | |
function ParseLinkTags($content) { | |
global $linkPattern, $linkSplitCharacter; | |
$matches = GetPatternMatch($content, $linkPattern); | |
for ($i = 0; $i < count($matches); $i++) { | |
// strip out the braces | |
$reference = substr($matches[$i], 1, strlen($matches[$i])-2); | |
$label = $reference; | |
// check for split links (eg: [real link|displayed text]) | |
$split = explode($linkSplitCharacter, $reference, 2); | |
if (count($split) == 2) { | |
if (strlen($split[0]) <= 0) { | |
// We can't make a link if the pre-split area is size zero. eg: [|display text] | |
return $content; | |
} else { | |
// in case the last half of the split fails, let's at least trim the pipe out. | |
$reference = $split[0]; | |
} | |
if (strlen($split[1]) > 0) { | |
// We only use the label if it has content. [realLink|] will pretend you didn't use a pipe. | |
$label = $split[1]; | |
} | |
} | |
$link = GetTextLink($reference, $label); | |
$content = str_replace($matches[$i], $link, $content); | |
} | |
return $content; | |
} | |
// This converts a word to a text link from your content folder. | |
function GetTextLink($for, $label) { | |
$formatted = trim(strtolower($for)); | |
$replacedSpaces = str_replace(" ", "%20", $formatted); | |
$link = "<a href='?p=".$replacedSpaces."'>".$label."</a>"; | |
return $link; | |
} | |
// Just a loop to fire GetImageTag a whole bunch. | |
function ParseImageTags($content) { | |
global $imagePattern; | |
$matches = GetPatternMatch($content, $imagePattern); | |
for ($i = 0; $i < count($matches); $i++) { | |
$content = str_replace($matches[$i], GetImageTag($matches[$i]), $content); | |
} | |
return $content; | |
} | |
// This converts a filename to a proper image link. | |
function GetImageTag($filename) { | |
global $imagePath; | |
$reference = substr($filename, 1, strlen($filename)-2); | |
$reference = strtolower($reference); | |
return "<img src='".$imagePath.$reference."'/>"; | |
} | |
// HTML-formats a nice list of the latest N updated content files. | |
function GetLatestEntries($listLength) { | |
global $contentPath, $suffix; | |
$files = glob($contentPath."*".$suffix); | |
$files = array_combine($files, array_map("filemtime", $files)); | |
arsort($files); | |
if ($listLength > count($files)) { | |
$listLength = count($files); | |
} | |
$entries = "<hr>"; | |
for ($i = 0; $i < $listLength; $i++) { | |
$flatName = basename(key($files)); | |
$flatName = str_replace($suffix, "", $flatName); | |
$entries .= "<br>"; | |
$entries .= GetTextLink($flatName, $flatName); | |
$entries .= " (".TimeElapsed("@".current($files)).")"; | |
next($files); | |
} | |
$entries .= "<br><br><hr>"; | |
return $entries; | |
} | |
// Shortcut to fetch the regex pa ttern. | |
function GetPatternMatch($content, $pattern) { | |
preg_match_all($pattern, $content, $matches); | |
return $matches[0]; | |
} | |
// Stole this from stack overflow to make nice dates. | |
// Will show "updated 10 seconds ago" or "updated a year ago". | |
function TimeElapsed($datetime, $full = false) { | |
$now = new DateTime; | |
$ago = new DateTime($datetime); | |
$diff = $now->diff($ago); | |
$diff->w = floor($diff->d / 7); | |
$diff->d -= $diff->w * 7; | |
$string = array( | |
'y' => 'year', | |
'm' => 'month', | |
'w' => 'week', | |
'd' => 'day', | |
'h' => 'hour', | |
'i' => 'minute', | |
's' => 'second', | |
); | |
foreach ($string as $k => &$v) { | |
if ($diff->$k) { | |
$v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : ''); | |
} else { | |
unset($string[$k]); | |
} | |
} | |
if (!$full) $string = array_slice($string, 0, 1); | |
return $string ? implode(', ', $string) . ' ago' : 'just now'; | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment