Create single-page HTML output, prepares the terrain for PDF/ePub output
This commit is contained in:
142
libs/Format/HTMLFile/Book.php
Normal file
142
libs/Format/HTMLFile/Book.php
Normal file
@ -0,0 +1,142 @@
|
||||
<?php namespace Todaymade\Daux\Format\HTMLFile;
|
||||
|
||||
use RuntimeException;
|
||||
use Todaymade\Daux\Tree\Content;
|
||||
use Todaymade\Daux\Tree\Directory;
|
||||
|
||||
class Book
|
||||
{
|
||||
protected $cover;
|
||||
protected $tree;
|
||||
protected $pages = [];
|
||||
|
||||
public function __construct(Directory $tree, $cover)
|
||||
{
|
||||
$this->tree = $tree;
|
||||
$this->cover = $cover;
|
||||
}
|
||||
|
||||
protected function getStyles()
|
||||
{
|
||||
// TODO :: un-hardcode that
|
||||
return '<style>' . file_get_contents('themes/daux_singlepage/css/main.min.css') . '</style>';
|
||||
}
|
||||
|
||||
protected function getSectionId(Content $node)
|
||||
{
|
||||
foreach ($this->pages as $id => $page) {
|
||||
if ($page['page'] == $node) {
|
||||
return $id;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("Could not find the content page");
|
||||
}
|
||||
|
||||
protected function buildNavigation(Directory $tree)
|
||||
{
|
||||
$nav = [];
|
||||
foreach ($tree->getEntries() as $node) {
|
||||
if ($node instanceof Content) {
|
||||
if ($node->isIndex()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$nav[] = [
|
||||
'title' => $node->getTitle(),
|
||||
'href' => '#section_' . $this->getSectionId($node),
|
||||
];
|
||||
} elseif ($node instanceof Directory) {
|
||||
if (!$node->hasContent()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$page_index = ($index = $node->getIndexPage())? $index : $node->getFirstPage();
|
||||
|
||||
$nav[] = [
|
||||
'title' => $node->getTitle(),
|
||||
'href' => "#section_" . $this->getSectionId($page_index),
|
||||
'children' => $this->buildNavigation($node)
|
||||
];
|
||||
}
|
||||
}
|
||||
return $nav;
|
||||
}
|
||||
|
||||
private function renderNavigation($entries)
|
||||
{
|
||||
$nav = "";
|
||||
foreach ($entries as $entry) {
|
||||
if (array_key_exists('children', $entry)) {
|
||||
if (array_key_exists('href', $entry)) {
|
||||
$link = '<a href="' . $entry['href'] . '" class="folder">' . $entry['title'] . '</a>';
|
||||
} else {
|
||||
$link = '<a href="#" class="aj-nav folder">' . $entry['title'] . '</a>';
|
||||
}
|
||||
|
||||
$link .= $this->renderNavigation($entry['children']);
|
||||
} else {
|
||||
$link = '<a href="' . $entry['href'] . '">' . $entry['title'] . '</a>';
|
||||
}
|
||||
|
||||
$nav .= "<li>$link</li>";
|
||||
}
|
||||
|
||||
return "<ul>$nav</ul>";
|
||||
}
|
||||
|
||||
protected function generateTOC()
|
||||
{
|
||||
return "<h1>Table of Contents</h1>" .
|
||||
$this->renderNavigation($this->buildNavigation($this->tree)) .
|
||||
"</div><div class=\"page-break\"> </div>";
|
||||
}
|
||||
|
||||
protected function generateCover()
|
||||
{
|
||||
return "<div style='margin:4em 30% 4em 0;'>" .
|
||||
"<h1 style='font-size:40pt; margin-bottom:0;'>{$this->cover['title']}</h1>" .
|
||||
"<p><strong>{$this->cover['subject']}</strong> by {$this->cover['author']}</p>" .
|
||||
"</div><div class=\"page-break\"> </div>";
|
||||
}
|
||||
|
||||
protected function generatePages()
|
||||
{
|
||||
$content = '';
|
||||
foreach ($this->pages as $section => $page) {
|
||||
$content .= '<a id="section_' . $section . '"></a>';
|
||||
$content .= '<h1>' . $page['page']->getTitle() . '</h1>';
|
||||
$content .= '<section class="content">' . $page['content'] . '</section>';
|
||||
$content .= '<div class="page-break"> </div>';
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function addPage($page, $content)
|
||||
{
|
||||
$this->pages[] = ['page' => $page, 'content' => $content];
|
||||
}
|
||||
|
||||
public function generateHead()
|
||||
{
|
||||
$head = [
|
||||
"<title>{$this->cover['title']}</title>",
|
||||
"<meta name='description' content='{$this->cover['subject']}' />",
|
||||
"<meta name='author' content='{$this->cover['author']}'>",
|
||||
"<meta charset='UTF-8'>",
|
||||
$this->getStyles(),
|
||||
];
|
||||
|
||||
return '<head>' . implode('', $head) . '</head>';
|
||||
}
|
||||
|
||||
public function generateBody()
|
||||
{
|
||||
return '<body>' . $this->generateCover() . $this->generateTOC() . $this->generatePages() . '</body>';
|
||||
}
|
||||
|
||||
public function generate()
|
||||
{
|
||||
return "<!DOCTYPE html><html>" . $this->generateHead() . $this->generateBody() . "</html>";
|
||||
}
|
||||
}
|
34
libs/Format/HTMLFile/ContentPage.php
Normal file
34
libs/Format/HTMLFile/ContentPage.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php namespace Todaymade\Daux\Format\HTMLFile;
|
||||
|
||||
use Todaymade\Daux\Format\Base\EmbedImages;
|
||||
use Todaymade\Daux\Tree\Raw;
|
||||
|
||||
class ContentPage extends \Todaymade\Daux\Format\Base\ContentPage
|
||||
{
|
||||
public $attachments = [];
|
||||
|
||||
protected function generatePage()
|
||||
{
|
||||
$content = parent::generatePage();
|
||||
|
||||
//Embed images
|
||||
// We do it after generation so we can catch the images that were in html already
|
||||
$content = (new EmbedImages($this->params['tree']))
|
||||
->embed(
|
||||
$content,
|
||||
$this->file,
|
||||
function ($src, array $attributes, Raw $file) {
|
||||
|
||||
$content = base64_encode(file_get_contents($file->getPath()));
|
||||
$attr = '';
|
||||
foreach ($attributes as $name => $value) {
|
||||
$attr .= ' ' .$name . '="' . htmlentities($value, ENT_QUOTES, 'UTF-8', false) . '"';
|
||||
}
|
||||
|
||||
return "<img $attr src=\"data:image/png;base64,$content\"/>";
|
||||
}
|
||||
);
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
103
libs/Format/HTMLFile/Generator.php
Normal file
103
libs/Format/HTMLFile/Generator.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php namespace Todaymade\Daux\Format\HTMLFile;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Todaymade\Daux\Console\RunAction;
|
||||
use Todaymade\Daux\ContentTypes\Markdown\ContentType;
|
||||
use Todaymade\Daux\Daux;
|
||||
|
||||
class Generator implements \Todaymade\Daux\Format\Base\Generator
|
||||
{
|
||||
use RunAction;
|
||||
|
||||
/** @var Daux */
|
||||
protected $daux;
|
||||
|
||||
/**
|
||||
* @param Daux $daux
|
||||
*/
|
||||
public function __construct(Daux $daux)
|
||||
{
|
||||
$this->daux = $daux;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getContentTypes()
|
||||
{
|
||||
return [
|
||||
'markdown' => new ContentType($this->daux->getParams())
|
||||
];
|
||||
}
|
||||
|
||||
protected function initPDF()
|
||||
{
|
||||
// create new PDF document
|
||||
$pdf = new Book(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
|
||||
|
||||
$params = $this->daux->getParams();
|
||||
|
||||
// set document information
|
||||
$pdf->SetCreator(PDF_CREATOR);
|
||||
|
||||
|
||||
// set default header data
|
||||
$pdf->SetHeaderData('', 0, $params['title'], $params['tagline']);
|
||||
|
||||
// set header and footer fonts
|
||||
$pdf->setHeaderFont(array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
|
||||
$pdf->setFooterFont(array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));
|
||||
|
||||
// set default monospaced font
|
||||
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
|
||||
|
||||
// set margins
|
||||
$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
|
||||
$pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
|
||||
$pdf->SetFooterMargin(PDF_MARGIN_FOOTER);
|
||||
|
||||
// set auto page breaks
|
||||
$pdf->SetAutoPageBreak(true, PDF_MARGIN_BOTTOM);
|
||||
|
||||
// set image scale factor
|
||||
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
|
||||
|
||||
// set font
|
||||
$pdf->SetFont('helvetica', '', 10);
|
||||
|
||||
return $pdf;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function generateAll(InputInterface $input, OutputInterface $output, $width)
|
||||
{
|
||||
$params = $this->daux->getParams();
|
||||
|
||||
$data = ['author' => $params['author'], 'title' => $params['title'], 'subject' => $params['tagline']];
|
||||
|
||||
$book = new Book($this->daux->tree, $data);
|
||||
|
||||
$current = $this->daux->tree->getIndexPage();
|
||||
while ($current) {
|
||||
$this->runAction(
|
||||
"Generating " . $current->getTitle(),
|
||||
$output,
|
||||
$width,
|
||||
function () use ($book, $current, $params) {
|
||||
$contentType = $this->daux->getContentTypeHandler()->getType($current);
|
||||
$content = ContentPage::fromFile($current, $params, $contentType)->getContent();
|
||||
$book->addPage($current, $content);
|
||||
}
|
||||
);
|
||||
|
||||
$current = $current->getNext();
|
||||
}
|
||||
|
||||
$content = $book->generate();
|
||||
file_put_contents($input->getOption('destination') . '/file.html', $content);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user