diff --git a/bkg.png b/bkg.png new file mode 100644 index 0000000..1c10e00 Binary files /dev/null and b/bkg.png differ diff --git a/blog.txt b/blog.txt index fc88332..ce2690b 100644 --- a/blog.txt +++ b/blog.txt @@ -1 +1,6 @@ -2020-10-01T08:05:33Z (#MWZkYw) Welcome to picoblog. For updates and such, visit [https://0xff.nu/picoblog](https://0xff.nu/picoblog). \ No newline at end of file +# nick = lucas +# url = https://picoblog.lu700.repl.co/blog.txt +# avatar = https://avatars.githubusercontent.com/u/83518257 +# description = aaaa +2021-08-27T20:08:55Z (#tad8XR4) geektweet +2021-08-27T20:09:10Z (#DcV8475) lol @ \ No newline at end of file diff --git a/includes/Slimdown.php b/includes/Slimdown.php new file mode 100644 index 0000000..063b648 --- /dev/null +++ b/includes/Slimdown.php @@ -0,0 +1,42 @@ + + * Website: https://gist.github.com/jbroadway/2836900 + * License: MIT + */ +class Slimdown { + public static $rules = array ( + '/(? '\1', // links + '/(\*\*|__)(.*?)\1/' => '\2', // bold + '/(\*|_)(.*?)\1/' => '\2', // emphasis + '/\~\~(.*?)\~\~/' => '\1', // del + '/\:\"(.*?)\"\:/' => '\1', // quote + '/`(.*?)`/' => '\1', // inline code + '/(?:!\[([^\[]+)\]\(([^\)]+)\))/' => '\'\1\'', + '/==(.*?)==/' => '\1', + ); + + /** + * Add a rule. + */ + public static function add_rule ($regex, $replacement) { + self::$rules[$regex] = $replacement; + } + + /** + * Render some Markdown into HTML. + */ + public static function render ($text) { + $text = "\n" . $text . "\n"; + foreach (self::$rules as $regex => $replacement) { + if (is_callable ( $replacement)) { + $text = preg_replace_callback ($regex, $replacement, $text); + } else { + $text = preg_replace ($regex, $replacement, $text); + } + } + return trim ($text); + } +} diff --git a/includes/picoblog.php b/includes/picoblog.php new file mode 100644 index 0000000..70f7201 --- /dev/null +++ b/includes/picoblog.php @@ -0,0 +1,218 @@ +sourcefile = $sourcefile; + $this->format = $format; + $this->readSource(); + } + + /** + * Check for and parse query string from $_SERVER['QUERY_STRING']). + * Used to get entries by ID or tag. + * + * @return array|boolean + */ + public function parseQuery() + { + if (isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING'])) { + parse_str($_SERVER['QUERY_STRING'], $return); + return $return; + } else { + return false; + } + } + + /** + * Read source file/URL + * + * @return boolean true if successful, false if not + */ + private function readSource() + { + if (is_file($this->sourcefile) && is_readable($this->sourcefile)) { + $this->rawentries = explode(PHP_EOL, file_get_contents($this->sourcefile)); + if (!empty($this->rawentries)) { + return true; + } + } elseif ($url = filter_var($this->sourcefile, FILTER_VALIDATE_URL)) { + $this->rawentries = preg_split('/\x0A/', file_get_contents($url)); + if (!empty($this->rawentries)) { + return true; + } + } + throw new \Exception("{$this->sourcefile} is empty! Aborting."); + return false; + } + + /** + * Parse entries from source file and replace tags with links + * + * @param array $entries array of raw entries + * @return void + */ + private function parseEntries(array $entries, bool $parseTags = true) + { + switch ($this->format) { + case 'twtxt': + $pattern = '/^(?[^\t]+)\t(?.+)/'; + break; + case 'picoblog': + $pattern = '/^(?[^\t]+)\t\(#(?[a-zA-Z0-9]{1,7})\)\t(?.+)/'; + break; + } + foreach ($entries as $i => $entry) { + preg_match($pattern, $entry, $matches); + if (!$matches) continue; + $id = (!empty($matches['id'])) ? $matches['id'] : $i; + $matches['entry'] = $this->parseUsers($matches['entry']); + $matches['entry'] = $this->parseHashlinks($matches['entry']); + $parsedEntries[$id] = [ + 'date' => $matches['date'], + 'entry' => ($parseTags) ? preg_replace('/#(\w+)?/', '#${1}', $matches['entry']) : $matches['entry'], + ]; + } + return $parsedEntries; + } + + /** + * Parse user's nick + * + * @param string $entry + * @return string string with parsed users + */ + /*private function parseNick(array $entries) + { + $pattern = '/^(?[^\t]+)\t(?.+)/'; + preg_match('# nick\t=\t]+)\t(?.+)/', $nick, $matchn); + //if (!$matches) continue; + //$id = (!empty($matches['id'])) ? $matches['id'] : $i; + //$matches['entry'] = $this->parseUsers($matches['entry']); + //$matches['entry'] = $this->parseHashlinks($matches['entry']); + $parsedNick = [ + 'nick' => $matchn['nick'] + ]; + return $parsedNick; + } + private function parseNick(string $entry) { + $pattern = "# nick = (.+)"; + $aaa=preg_match_all($pattern, $this->rawentries, $matches); + print_r($aaa); + return print_r($aaa); + }*/ + + /** + * Parse any mentioned users in twtxt format: @ + * + * @param string $entry + * @return string string with parsed users + */ + private function parseUsers(string $entry) { + $pattern = '/\@<([a-zA-Z0-9\.]+)\W+(https?:\/\/[^>]+)>/'; + return preg_replace($pattern,'@$1',$entry); + } + + /** + * Parse any hashtags in twtxt.net hashlink format: # + * + * @param string $entry + * @return string string with parsed hashtags + */ + private function parseHashlinks(string $entry) { + $pattern = '/#<(\w+)\W+(https?:\/\/[^>]+)>/'; + return preg_replace($pattern, '#$1', $entry); + } + + /** + * Returns a filtered list of raw entries + * + * @param string|array $search entry filter. can be 'all', 'newest', 'oldest', 'random' or an ID/Tag. + * @param bool $reverse return array in reverse order + * For ID, we're looking for ['id'=>'IDHERE']. For tag, we're looking for ['tag'=>'tagname'] + * @return boolean|array + */ + public function getEntries($search, bool $reverse = true) + { + switch ($search) { + case '': + return false; + case 'all': + return ($reverse) ? array_reverse($this->rawentries) : $this->rawentries; + case 'newest': + return [reset($this->rawentries)]; + case 'oldest': + return [end($this->rawentries)]; + case 'random': + return [$this->rawentries[array_rand($this->rawentries, 1)]]; + default: + if (isset($search['id'])) { + $filter = array_filter($this->rawentries, function ($entry) use ($search) { + preg_match("/\b$search[id]\b/i", $entry, $match); + return $match; + }); + return $filter; + } elseif (isset($search['tag'])) { + $filter = array_filter($this->rawentries, function ($entry) use ($search) { + preg_match("/#\b$search[tag]\b/i", $entry, $match); + return $match; + }); + return $filter; + } + return false; + } + } + /** + * Render Markdown in given entries and output as HTML + * + * @param array $entries array of parsed entries to render + * @param string $entryWrap tne entry wrapper, e.g.
  • {entry}
  • + * @param bool $parseTags should #tags be parsed to links? + * @return string entries in HTML + */ + public function renderEntries(array $entries, $show, string $entryWrap = '
  • {entry}
  • ', bool $parseTags = false) + { + if (!$entries) return false; + $entries = $this->parseEntries($entries, $parseTags); + //$nick = $this->parseNick($nick); + require_once('includes/Slimdown.php'); + $html = ''; + foreach ($entries as $id => $entry) { + include "settings.php"; + $text = \Slimdown::render($entry['entry']); + $date = $entry['date']; + $date_p = date("d-m-Y", strtotime($entry['date'])); + if($show!=true){ + $text = "
    " . $text . "{$date_p}
    "; + } else { + $text = "

    {$nick}

    " . $text . "

    #{$id}{$date_p}

    "; + } + $html .= str_replace('{entry}', $text, $entryWrap); + } + return $html; + } +} diff --git a/index.php b/index.php new file mode 100644 index 0000000..6ae0ca6 --- /dev/null +++ b/index.php @@ -0,0 +1,38 @@ +parseQuery(); +$entries = ($query) ? $mb->getEntries($query) : $mb->getEntries('all'); + +?> + + + + + + + + <?php echo $nick ?>@<?= $_SERVER['HTTP_HOST'] ?> + + + + + +

    picoblog

    + Currently viewing ' . implode('', $query) . '. Back to list?'; + echo($mb->renderEntries($entries, true, '{entry}')); + } else { + echo($mb->renderEntries($entries, false, '{entry}')); + } ?> + + + \ No newline at end of file diff --git a/settings.php b/settings.php new file mode 100644 index 0000000..186cc00 --- /dev/null +++ b/settings.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..bd2279f --- /dev/null +++ b/styles.css @@ -0,0 +1,23 @@ +@import url("https://lucas.koyu.space/styles.css"); +.e{ + margin:1px 10px; + padding:10px; + background:repeat-y center fixed url("bkg.png"); + background-size:cover; + color:white; +} +.e a{ + color:white; +} +/*.text{ + float:left; +}*/ +.date{ + float:right; +} +.pp{ + background:url("https://avatars.githubusercontent.com/u/83518257"); + border-radius:100%; + width:20px; + height:20px; +} \ No newline at end of file