From c5efaeee1075614b4f8cc1ce373df1adcc4ee9fb Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Fri, 13 Feb 2015 18:29:13 +0100 Subject: [PATCH] static generator --- bin/cli-server | 2 +- bin/gen-static | 14 ++++ mdref/Action.php | 16 +--- mdref/Generator.php | 180 ++++++++++++++++++++++++++++++++++++++++++++ mdref/Reference.php | 14 ++++ public/.htaccess | 3 + public/index.css | 11 ++- public/index.js | 8 +- views/layout.phtml | 23 ++++-- views/sidebar.phtml | 17 +++-- 10 files changed, 259 insertions(+), 29 deletions(-) create mode 100755 bin/gen-static create mode 100644 mdref/Generator.php diff --git a/bin/cli-server b/bin/cli-server index 05d700b..30373f8 100755 --- a/bin/cli-server +++ b/bin/cli-server @@ -46,5 +46,5 @@ fi export REFPATH for p in {8000..8100}; do - php -S localhost:$p -t . index.php && break + ${PHP:-php} -S localhost:$p -t . index.php && break done diff --git a/bin/gen-static b/bin/gen-static new file mode 100755 index 0000000..15e8609 --- /dev/null +++ b/bin/gen-static @@ -0,0 +1,14 @@ +#!/usr/bin/env php +add("mdref", ROOT); + +$g = new mdref\Generator(REFS, @$argv[1]); +$g->run(); diff --git a/mdref/Action.php b/mdref/Action.php index dcd8fcb..3e318be 100644 --- a/mdref/Action.php +++ b/mdref/Action.php @@ -36,20 +36,8 @@ class Action extends Observer { $pld = new \stdClass; try { - $pld->quick = function($string) { - $md = \MarkdownDocument::createFromString($string); - $md->compile(\MarkdownDocument::AUTOLINK); - return $md->getHtml(); - }; - - $pld->file = function($file) { - $fd = fopen($file, "r"); - $md = \MarkdownDocument::createFromStream($fd); - $md->compile(\MarkdownDocument::AUTOLINK | \MarkdownDocument::TOC); - $html = $md->getHtml(); - fclose($fd); - return $html; - }; + $pld->quick = [$this->reference, "formatString"]; + $pld->file = [$this->reference, "formatFile"]; $pld->ref = implode("/", $this->baseUrl->params( $this->baseUrl->mod($ctl->getRequest()->getRequestUrl()))); diff --git a/mdref/Generator.php b/mdref/Generator.php new file mode 100644 index 0000000..7a58387 --- /dev/null +++ b/mdref/Generator.php @@ -0,0 +1,180 @@ +reference = new Reference(explode(PATH_SEPARATOR, $refs)); + $this->renderer = new Generator\Renderer($dir ?: "public/static"); + } + + /** + * Run the generator + */ + public function run() { + $this->generateRoot(); + foreach ($this->reference as $repo) { + $iter = new \RecursiveIteratorIterator($repo, + \RecursiveIteratorIterator::SELF_FIRST); + foreach ($iter as $ref) { + $this->generateEntry($ref); + } + } + } + + /** + * Generate index.html and LICENSE.html + */ + private function generateRoot() { + printf("Generating index ...\n"); + $data = $this->createPayload(null); + $data->ref = "index"; + $this->renderer->persist($data); + + printf("Generating LICENSE ...\n"); + $data->text = file_get_contents(__DIR__."/../LICENSE"); + $data->ref = "LICENSE"; + $this->renderer->persist($data); + } + + /** + * Generate HTML for an entry + * @param \mdref\Entry $ref + */ + private function generateEntry(Entry $ref) { + printf("Generating %s ...\n", $ref->getName()); + $data = $this->createPayload($ref); + $this->renderer->persist($data); + } + + /** + * Create the view payload + * @param \mdref\Entry $ref + * @param \mdref\Generator\Renderer $view + * @return \stdClass + */ + private function createPayload(Entry $ref = null) { + $pld = new \stdClass; + + $pld->quick = [$this->reference, "formatString"]; + $pld->file = [$this->reference, "formatFile"]; + $pld->refs = $this->reference; + $pld->view = $this->renderer; + if ($ref) { + $pld->entry = $ref; + $pld->ref = $ref->getName(); + } + + return $pld; + } +} + +namespace mdref\Generator; + +class Renderer +{ + /** + * @var string + */ + private $dir; + + /** + * @param string $dir output directory + */ + public function __construct($dir = "public/static") { + $this->dir = $dir; + } + + /** + * HTML entity encode special characters + * @param string $string + * @return string + */ + public function esc($string) { + return htmlspecialchars($string); + } + + /** + * Render mdref page + * @param \stdClass $pld + * @return string + */ + public function render(\stdClass $pld) { + $content = ""; + ob_start(function($data) use(&$content) { + $content .= $data; + return true; + }); + static::renderFile("views/layout.phtml", (array) $pld); + ob_end_flush(); + return $content; + } + + /** + * Persist mdref page to output directory + * @param \stdClass $data + */ + public function persist(\stdClass $data) { + $html = $this->render($data); + $file = sprintf("%s/%s.html", $this->dir, $data->ref); + $this->saveFile($file, $html); + $this->linkIndex(dirname($file)); + } + + /** + * Save data to file (write to $file.tmp and rename to $file) + * @param string $file + * @param string $data + * @throws \Exception + */ + private function saveFile($file, $data) { + $dir = dirname($file); + if (!is_dir($dir) && !mkdir($dir, 0755, true)) { + throw new \Exception("Failed to create directory '$dir'"); + } + if (!file_put_contents("$file.tmp", $data)) { + throw new \Exception("Failed to save file '$file.tmp'"); + } + if (!rename("$file.tmp", $file)) { + throw new \Exception("Failed to rename to '$file'"); + } + } + + private function linkIndex($dir) { + $index = "$dir.html"; + $link = "$dir/index.html"; + if (is_file($index) && !is_file($link)) { + printf("Generating index for '%s'\n", substr($dir, strlen($this->dir))); + link($index, $link); + } + } + + /** + * Render file + */ + static private function renderFile() { + if (func_num_args() > 1) { + extract(func_get_arg(1)); + } + include func_get_arg(0); + } +} diff --git a/mdref/Reference.php b/mdref/Reference.php index 153004f..7c22dba 100644 --- a/mdref/Reference.php +++ b/mdref/Reference.php @@ -43,5 +43,19 @@ class Reference implements \IteratorAggregate { public function getIterator() { return new \ArrayIterator($this->repos); } + + public function formatString($string) { + $md = \MarkdownDocument::createFromString($string); + $md->compile(\MarkdownDocument::AUTOLINK); + return $md->getHtml(); + } + public function formatFile($file) { + $fd = fopen($file, "r"); + $md = \MarkdownDocument::createFromStream($fd); + $md->compile(\MarkdownDocument::AUTOLINK | \MarkdownDocument::TOC); + $html = $md->getHtml(); + fclose($fd); + return $html; + } } diff --git a/public/.htaccess b/public/.htaccess index affb2a0..c236b73 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -1,4 +1,7 @@ +DirectorySlash Off RewriteEngine On +RewriteRule ^static.*\.html - [L] +RewriteRule ^(static/.+) $1.html [L] RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -d [OR] RewriteCond %{REQUEST_FILENAME} -l diff --git a/public/index.css b/public/index.css index 40f17d2..b4175ed 100644 --- a/public/index.css +++ b/public/index.css @@ -79,7 +79,7 @@ pre>code, pre>code code { color: #eee; } -p, pre, table { +p, pre, table, dl { margin: 1em 2em; } @@ -216,7 +216,14 @@ table { th, td { padding: .4em; } - +dt { + font-weight: bold; + margin-top: 1em; +} +dd { + line-height: 1.2em; + margin-left: 1em; +} h1, footer, table, .sidebar, pre>code, li h3 { box-shadow: 0 0 4px #708090; } diff --git a/public/index.js b/public/index.js index f60e8a8..27e368a 100644 --- a/public/index.js +++ b/public/index.js @@ -97,8 +97,12 @@ $(function() { return ""; } } - if (-1 !== (j = s.indexOf("\\")) && s.substr(j+1,1) !== "n") { - return ""; + if (-1 !== (j = s.lastIndexOf("\\")) && s.substr(j+1,1) !== "n") { + t = s.substring(j+1); + if (!mdref.is_constant(t)) { + return ""; + } + return ""; } switch (s.toLowerCase()) { diff --git a/views/layout.phtml b/views/layout.phtml index 69b4c74..05367b9 100644 --- a/views/layout.phtml +++ b/views/layout.phtml @@ -10,9 +10,16 @@ mdref - - - + + + + + + + + @@ -25,7 +32,7 @@ - +
+ + + + + diff --git a/views/sidebar.phtml b/views/sidebar.phtml index e371d6d..4ecce30 100644 --- a/views/sidebar.phtml +++ b/views/sidebar.phtml @@ -1,23 +1,30 @@
-- 2.30.2