saaze
saaze copied to clipboard
Provide repository for themes and plugins
As Saaze can be extended quite easily, it is expected that more extensions and template-themes will emerge. We should collect them "somewhere", so people can find them easily.
I created an extension for Saaze modeled after the documentation as given in Extending. This extension provides:
- MathJax support for inline and display math, i.e., single dollar and double dollar notation, taking into account to not spoil with math within code-blocks
- Embedding YouTube videos like so:
[youtube] shortcode [/youtube] - Embedding Tweets from Twitter like so:
[twitter] Tweet URL [/twitter]
File definitions.php is:
<?php
require_once 'MathParser.php';
return [
\Saaze\Interfaces\ContentParserInterface::class => \MathParser::class,
];
File MathParser.php is:
<?php
use Saaze\Content\MarkdownContentParser;
class MathParser extends MarkdownContentParser {
/**
* Work on abc $$uvw$$ xyz.
* Needs MathJax. For this you have to include:
* <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
* <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
*
* @param string $content
* @return string
*/
private function displayMath($content) {
$last = 0;
for (;;) {
$start = strpos($content,"$$",$last);
if ($start === false) break;
$end = strpos($content,"$$",$start+2);
if ($end === false) break;
$last = $end + 2;
$content = substr($content,0,$start)
. "\n<div class=math>\n"
. substr($content,$start,$last-$start)
. "\n</div>\n"
. substr($content,$last);
$last += strlen("\n<div class=math>\n") + strlen("\n</div>\n");
}
return $content;
}
/**
* Work on abc $uvw$ xyz.
* @param string $content
* @return string
*/
private function inlineMath($content) {
$last = 0;
for (;;) {
$start = strpos($content,"$",$last);
if ($start === false) break;
// Check if display math with double dollar found?
if (substr($content,$start+1,1) == "$") { $last = $start + 2; continue; }
$end = strpos($content,"$",$start+1);
if ($end === false) break;
// Check for display math again, just in case
if (substr($content,$end+1,1) == "$") { $last = $end + 2; continue; }
// Replace $xyz$" with \\(xyz\\)
$content = substr_replace($content,"\\\\(",$start,1);
$content = substr_replace($content,"\\\\)",$end+2,1);
$last = $end + 5; // effectivley added four chars
}
return $content;
}
/**
* Convert [youtube]xxx[/youtube] tags in your markdown to HTML:
* <iframe width="560" height="315" src=https://www.youtube.com/embed/xxx
* frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
* Example: [youtube] a5pnnkXpX-U [/youtube]
*
* @param string $content
* @return string
*/
private function youtube($content) {
$last = 0;
for (;;) {
$start = strpos($content,"[youtube]",$last);
if ($start === false) break;
// strlen("[youtube]") == 9
$end = strpos($content,"[/youtube]",$start+9);
if ($end === false) break;
$video = trim(substr($content,$start+9,$end-$start-9));
$last = $end + 10;
$content = substr_replace($content
,"<iframe width=560 height=315 src=https://www.youtube.com/embed/"
. $video
. " frameborder=0 allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"
,$start,$last-$start);
}
return $content;
}
/**
* Convert [twitter]xxx[/twitter] tags in your markdown HTML which Twitter-JavaScript understands.
* xxx is for example: https://twitter.com/eklausmeier/status/1352896936051937281
* i.e., just the URL, no other information is required.
* This xxx is "Copy link to Tweet" button in Twitter.
*
* Make sure that your layout-template contains the following:
* <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
*
* @param string $content
* @return string
*/
private function twitter($content) {
$last = 0;
for (;;) {
$start = strpos($content,"[twitter]",$last);
if ($start === false) break;
// strlen("[twitter]") == 9
$end = strpos($content,"[/twitter]",$start+9);
if ($end === false) break;
$tweet = trim(substr($content,$start+9,$end-$start-9));
$last = $end + 10;
$content = substr_replace($content
,"<blockquote class=\"twitter-tweet\"><a href=\""
. $tweet
. "\"</a></blockquote>"
,$start,$last-$start);
}
return $content;
}
/**
* Parse raw content and return HTML
* @param string $content
* @return string
*/
public function toHtml($content) {
$arr = explode("`",$content); // known deficiency: does not cope for HTML comments
// even elements can be changed, uneven are code-block elements
for($i=0, $size=count($arr); $i<$size; $i+=2) {
$arr[$i] = $this->displayMath($arr[$i]);
$arr[$i] = $this->inlineMath($arr[$i]);
$arr[$i] = $this->youtube($arr[$i]);
$arr[$i] = $this->twitter($arr[$i]);
}
return parent::toHtml(implode("`",$arr)); // markdown to HTML
}
}
The following JavaScript libraries have to be present in layout.blade.php:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>
@hasSection('title')
@yield('title') - Saaze
@else
Saaze
@endif
</title>
<link rel="stylesheet" href="https://unpkg.com/tailwindcss@^2.1.0/dist/base.min.css" />
<link rel="stylesheet" href="https://unpkg.com/tailwindcss@^2.1.0/dist/components.min.css" />
<link rel="stylesheet" href="https://unpkg.com/@tailwindcss/[email protected]/dist/typography.min.css" />
<link rel="stylesheet" href="https://unpkg.com/tailwindcss@^2.1.0/dist/utilities.min.css" />
<link href="https://unpkg.com/[email protected]/themes/prism.css" rel="stylesheet" />
<link href="https://unpkg.com/[email protected]/plugins/line-numbers/prism-line-numbers.css" rel="stylesheet" />
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<script src="https://unpkg.com/[email protected]/components/prism-core.min.js"></script>
<script src="https://unpkg.com/[email protected]/plugins/autoloader/prism-autoloader.min.js"></script>
<script src="https://unpkg.com/[email protected]/plugins/line-numbers/prism-line-numbers.min.js"></script>
</head>
<body class="line-numbers">
<header class="p-6 sm:px-10 sm:flex sm:justify-between sm:items-center mb-10 sm:mb-20">
<div class="mb-4 sm:mb-0">
<a href="/" class="text-xl text-purple-600">Saaze</a>
</div>
<nav>
<ul class="flex">
<li><a href="{{ $GLOBALS['rbase'] }}/" class="text-purple-600">Home</a></li>
<li class="ml-10"><a href="{{ $GLOBALS['rbase'] }}/about" class="text-purple-600">About</a></li>
<li class="ml-10"><a href="{{ $GLOBALS['rbase'] }}/blog" class="text-purple-600">Blog</a></li>
</ul>
</nav>
</header>
<div class="font-serif prose prose-sm sm:prose lg:prose-lg xl:prose-xl mx-auto px-6 my-10 sm:my-20">
@yield('content')
</div>
<footer class="prose prose-sm sm:prose lg:prose-lg xl:prose-xl mx-auto px-6 my-20 sm:my-32">
<p class="text-center text-gray-600 text-xs sm:text-base">Copyright © {{ date('Y') }}</p>
</footer>
</body>
</html>
Prism.js or font-change is not required for this extension. I added it anyway, as my blog contains some code snippets.