~hxii/saisho

d978b2044e80bf51c18078b2d7b0e63ae69b3229 — Paul (hxii) Glushak 2 months ago 6a18b73
0.1.1 - New Muji template and feed generation
5 files changed, 193 insertions(+), 41 deletions(-)

A .gitattributes
A .gitignore
M config.php
M index.php
M template/home.php
A .gitattributes => .gitattributes +2 -0
@@ 0,0 1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

A .gitignore => .gitignore +1 -0
@@ 0,0 1,1 @@
cache/
\ No newline at end of file

M config.php => config.php +2 -0
@@ 7,8 7,10 @@ return (object) array(
  'host'            => 'https://sho.glushak.net',
  'logo'            => 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABIklEQVRYR81XWw7EIAjU+x/aRhOMSwcGX9nuT7MpMMPw0Ob0519ewC/EZypm1JiBWpxofGqQUloFF1IuhvdyF1irArEsAqfBTTUQgVvgkMTnCLyyL8UWJGe/h6uvYdMdxwgQyQriBO/NR2wadoiAOeTrCnTsEAEk42kFzEKv9ICQ00+gZNfw6OghYEMxm4CX+WvFqV44QqCCjKwjNWc+IIZfAq1CbUakjDSpBmD/6xTKFNAdYDWUp0xANU5grLcoMI7ldQJI3sB4Nd4zCjR7tPHGmkczlzhbq1iALyoQOwt0NqyzLcXQFtSHkVmGhZszc4HHcU+WeW++/7lEfO5GdFuFV8KfvZaPZd49qpc/TE6QoF9e1AB0PFNkKuaU8eb4QfcHoC7JIahBcKEAAAAASUVORK5CYII=',
  'cache_time'      => 259200,
  'feed_time'       => 86400,
  'data_folder'     => 'data',
  'cache_folder'    => 'cache',
  'template_folder' => 'template',
  'home_page'       => 'home',
  'feed_file'       => 'feed.xml',
);

M index.php => index.php +48 -5
@@ 5,11 5,11 @@

*/
$time = microtime(true);
$where = '';
// $where = '';
$files = [];

define( 'SAISHO', true );
define( 'SAISHO_VERSION', 0.1 );
define( 'SAISHO_VERSION', '0.1.1' );
$config = include ( 'config.php' );
define( 'HOME_URI', $config->host );
define( 'DATA_FOLDER', $config->data_folder );


@@ 20,11 20,12 @@ require ( 'inc/ParsedownExtra.php' );

class Saisho {

  public $config;
  public $config, $time, $extime;

  public function __construct( object $config ) {
    $this->where = ( $_SERVER['REQUEST_URI'] === '/' ) ? 'home' : 'page';
    $this->time = microtime(true);
    $this->config = $config;
    $this->where = ( $_SERVER['REQUEST_URI'] === '/' ) ? 'home' : 'page';
    $this->handle_cache();
  }



@@ 78,6 79,9 @@ class Saisho {
   * @return array
   */
  public function get_page( string $page, bool $metadata_only = false ) {
    if ( '.md' !== substr( $page, -3 ) ) {
      $page = $page . '.md';
    }
    if ( file_exists( DATA_FOLDER . DIRECTORY_SEPARATOR . $page ) ) {
      if ( $metadata_only ) {
        return (array) $this->parse_page( DATA_FOLDER . DIRECTORY_SEPARATOR . $page, false ); 


@@ 98,6 102,7 @@ class Saisho {

  private function handle_cache() {
    $hash_time = microtime(true);
    $this->rss( $this->config->feed_file );
    $request_hash = crc32( $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'] );
    $filename = substr( $_SERVER['REQUEST_URI'], 1 ) ?: $this->config->home_page;
    if ( ! file_exists( DATA_FOLDER . DIRECTORY_SEPARATOR . "{$filename}.md" ) ) {


@@ 334,6 339,44 @@ class Saisho {
    }
  }

  public function build_rss() {
    global $config;
    $home = $this->get_page('home');
    $pages = $this->get_list( 'by_date', 'desc' );
    $xml = '
    <rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
    <title>'.$home['title'].'</title>
    <link>'.$config->host.'</link>
    <description>'.$home['description'].'</description>
    <generator>Saisho '.SAISHO_VERSION.'</generator>
    <language>en-us</language>
    <lastBuildDate>'.date('r').'</lastBuildDate>
    <atom:link href="'.$config->host.'/index.xml" rel="self" type="application/rss+xml"/>'.PHP_EOL;
    foreach ( $pages as $page ) {
      $xml .= '<item>'.PHP_EOL;
      $xml .= '<title>' . $page['metadata']['title'] . '</title>'.PHP_EOL;
      $xml .= '<link>' . $page['url'] . '</link>'.PHP_EOL;
      $xml .= '<pubDate>' . date('r', $page['updated']) . '</pubDate>'.PHP_EOL;
      $xml .= '<description>' . (($page['metadata']['description'])?? '') . '</description>'.PHP_EOL;
      $xml .= '</item>'.PHP_EOL;
    }
    $xml .= '</channel></rss>';
    return $xml;
  }

  public function rss( $filename = 'feed.xml' ) {
    global $config;
    if ( ( time() - filemtime($filename) >= $config->feed_time ) || ! file_exists( $filename ) ) {
      $fh = fopen( $filename, 'w' );
      if ( ! $fh ) {
        return false;
      }
      fwrite( $fh, $this->build_rss() );
      fclose( $fh );
      return $config->host . DIRECTORY_SEPARATOR . 'feed.xml';
    }
  }

}
$saisho = new Saisho( $config );
echo '<code class="g">' . round((microtime(true) - $time)*1000,3) . 'ms</code><br>';
\ No newline at end of file

M template/home.php => template/home.php +140 -36
@@ 1,43 1,147 @@
<?php $time = microtime(true); ?>
<!DOCTYPE html>
<html>
<head>
    <link rel="icon" href="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta charset="UTF-8">
    <title>{title}</title>
    <style> :root { --b: #000; --g: #888; --w: #fff}body { font: 400 20px/1.6 sans-serif; padding: 2rem; background: var(--w); color: var(--b)}.container { max-width: 70ch }.mbh { margin: 0 0 .5rem }.mb1 { margin: 0 0 1rem }.mb2 { margin: 0 0 2rem }.g, pre { color: var(--g) }img { width: 100%; image-rendering: -moz-crisp-edges; image-rendering: pixelated }a, a:visited { color: var(--b); text-decoration-color: var(--g) }a:hover { text-decoration-color: var(--b) }pre, ul, ol, blockquote { margin: 0; padding: 0 1rem }pre { white-space: pre-wrap }@media (prefers-color-scheme: dark) { :root { --b: #fff; --g: #888; --w: #000 }} </style>
    <style>.container{display:grid;grid-gap: 1rem;grid-template-columns: 20% 80%;max-width:85ch}.footer{grid-column: 2}.content{max-width:70ch}</style>
	<link rel="icon" href="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=">
	<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,300;0,400;1,300;1,400&display=swap" rel="stylesheet">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta charset="UTF-8">
	<title>{title}</title>
	<style>* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font: 300 20px/1.62 'Roboto Mono', Monaco, Consolas, monospace;
}

body {
  padding: 1.62rem;
  display: flex;
  justify-content: center;
}

a {
  text-decoration: none;
    color: #000;
}

div {
	word-break: break-word;
}

.container {
  max-width: 60ch;
  font-size: min(max(1rem, 4vw), 1.62rem);
  margin: 0 auto;
}

ul.entry-list {
  list-style-type: none;
  text-transform: uppercase;
  line-height: 1;
  font-size: 0;
}

ul.entry-list li {
  display: inline-block;
  font-size: 2.2rem;
}

ul.entry-list li:not(:last-child):after {
  content: '\00B7';
  font-weight: 100;
}

ul.entry-list:hover li a {
  color: #ddd;
}

ul.entry-list li a:hover, .entry a, a:hover {
  color: white;
  background: black;
}

.entry {
  font-family: sans-serif;
}
.i {
  font-style: italic;
}
.s {
  text-decoration: underline
}
.db {
  display: block;
}
.dib {
  display: inline-block
}

.mt1, hr {
  margin: 1rem 0 0
}
.mb1, hr, p {
  margin: 0 0 1rem
}
.mb2 {
  margin: 0 0 2rem
}
.b {
  color: #1111ff;
}
.r {
  color: #ee1111;
}
.g {
  color: #eee
}</style>
</head>
<body>
    <div class="container">
        <div class="head mb2">
            <?php echo '<a href="'.$this->get_config()->host.'" rel="canonical">'.$this->get_config()->site_name.'</a>';
            echo ( $this->where === 'page' )? ' / {title}' : ''; ?>
        </div>
        <?php if ( $this->where === 'home' ): ?>
        <div class="content">
            {content}
            <div class="entries mb2">
            <?php
            $page_list = $this->get_list('by_date','asc');
            foreach ( $page_list as $page ) {
                echo '<div class="entry mb1">';
                echo '<a href="' . $page['url'] . '">' . $page['metadata']['title'] . '</a>' . (( $page['metadata']['date'] )? ' &mdash;<span class="g"> ' . $page['metadata']['date'] : '') . '</span>';
                echo '</div>';
            }
            ?>
        </div>
        </div>
        <?php endif; ?>
        <?php if ( $this->where === 'page' ): ?>
        <div class="content mb2">
            <?php echo ( $this->where === 'page' )? '{description}' : ''; ?>
            {content}
        </div>
        <?php endif; ?>
        <div class="footer">
            <img style="width:32px;height:auto;" src="<?php echo $this->get_config()->logo; ?>">
        </div>
    </div>
	<div class="container">
		<div class="head mb2">
			<?php echo '<a class="b" href="' . $this->get_config()->host . '" rel="canonical">' . $this->get_config()->site_name . '</a>';
			echo ( $this->where === 'page' ) ? ' / {title}' : ''; ?>
		</div>
		<?php if ( $this->where === 'home' ): ?>
            <ul class="entry-list mb2">
                <?php
                $page_list = $this->get_list( 'by_date','desc', true );
                foreach ( $page_list as $page ) {
					$style = ( isset( $page['metadata']['style']) )? $page['metadata']['style'] : '';
					$title = ( isset( $page['metadata']['title']) )? $page['metadata']['title'] : '';
                    echo '<li>';
                    echo '<a style="'.$style.'" href="' . $page['url'] . '">' . $title . '</a>';
                    echo '</li>';
                }
                ?>
            </ul>
		<?php endif; ?>
		<?php if ( $this->where === 'page' ): ?>
			<?php
				$page = substr( $_SERVER['REQUEST_URI'], 1 );
				$page = $this->get_page( $page, false );
			?>
            <div class="container mb2">
				<div class="entry">
				<?php echo ( $this->where === 'page' ) ? '{description}' : ''; ?>
                {content}</div>
            </div>
		<?php endif; ?>
		<div class="footer">
			<!-- <img style="width:32px;height:auto;" src="<?php //echo $this->get_config()->logo; ?>"> -->
            <span class="g">
				<?php
				echo 'L'. round((microtime(true) - $this->time)*1000,3) .
				(( isset( $page_list ) )? ' A' . count($page_list) : '') .
				(( $this->where === 'page' )? ' W' . str_word_count($page['content']) : '') .
				(( $this->where === 'page' )? ' D' . $page['date'] : '') .
				' V' . SAISHO_VERSION
				;?>
            </span>
		</div>
	</div>
</body>
</html>