public function register(Application $app) { $app['prince.path'] = null; // the common installation dirs for PrinceXML in several OS $app['prince.default_paths'] = array('/usr/local/bin/prince', '/usr/bin/prince', 'C:\\Program Files\\Prince\\engine\\bin\\prince.exe'); $app['prince'] = $app->share(function () use($app) { $princePath = $app['prince.path'] ?: $app->findPrinceXmlExecutable(); // ask the user about the location of the executable if (null == $princePath) { $princePath = $app->askForPrinceXMLExecutablePath(); if (!file_exists($princePath)) { throw new \RuntimeException(sprintf("We couldn't find the PrinceXML executable in the given directory (%s)", $princePath)); } } $prince = new Prince($princePath); $prince->setHtml(true); return $prince; }); }
public function __construct() { $app = $this; // -- global generic parameters --------------------------------------- $this['app.debug'] = true; $this['app.charset'] = 'UTF-8'; $this['app.name'] = 'easybook'; $this['app.version'] = '4.4'; $this['app.signature'] = "\n" . " | | \n" . " ,---.,---.,---., .|---.,---.,---.|__/ \n" . " |---',---|`---.| || || || || \\ \n" . " `---'`---^`---'`---|`---'`---'`---'` `\n" . " `---'\n"; // -- global directories location ------------------------------------- $this['app.dir.base'] = realpath(__DIR__ . '/../../../'); $this['app.dir.cache'] = $this['app.dir.base'] . '/app/Cache'; $this['app.dir.doc'] = $this['app.dir.base'] . '/doc'; $this['app.dir.resources'] = $this['app.dir.base'] . '/app/Resources'; $this['app.dir.plugins'] = $this['app.dir.base'] . '/src/Easybook/Plugins'; $this['app.dir.translations'] = $this['app.dir.resources'] . '/Translations'; $this['app.dir.skeletons'] = $this['app.dir.resources'] . '/Skeletons'; $this['app.dir.themes'] = $this['app.dir.resources'] . '/Themes'; // -- default edition options ----------------------------------------- // TODO: each edition type should define different values $this['app.edition.defaults'] = array('format' => 'html', 'highlight_code' => false, 'include_styles' => true, 'isbn' => null, 'labels' => array('appendix', 'chapter', 'figure'), 'margin' => array('top' => '25mm', 'bottom' => '25mm', 'inner' => '30mm', 'outter' => '20mm'), 'page_size' => 'A4', 'theme' => 'clean', 'toc' => array('deep' => 2, 'elements' => array('appendix', 'chapter')), 'two_sided' => true); // -- timer ----------------------------------------------------------- $this['app.timer.start'] = 0.0; $this['app.timer.finish'] = 0.0; // -- publishing process variables ------------------------------------ // holds the app theme dir for the current edition $this['publishing.dir.app_theme'] = ''; $this['publishing.dir.book'] = ''; $this['publishing.dir.contents'] = ''; $this['publishing.dir.resources'] = ''; $this['publishing.dir.plugins'] = ''; $this['publishing.dir.templates'] = ''; $this['publishing.dir.output'] = ''; $this['publishing.edition'] = ''; $this['publishing.items'] = array(); // the specific item currently being parsed/modified/decorated/... $this['publishing.active_item'] = array(); $this['publishing.book.slug'] = ''; $this['publishing.book.items'] = array(); // holds all the generated slugs, to avoid repetitions $this['publishing.slugs'] = array(); // holds all the internal links (used in html_chunked and epub editions) $this['publishing.links'] = array(); $this['publishing.list.images'] = array(); $this['publishing.list.tables'] = array(); $this['publishing.id'] = $this->share(function ($app) { if (null != ($isbn = $app->edition('isbn'))) { return array('scheme' => 'isbn', 'value' => $isbn); } // if the book doesn't declare an ISBN, generate // a unique ID based on RFC 4211 UUID v4 return array('scheme' => 'URN', 'value' => Toolkit::uuid()); }); // -- event dispatcher ------------------------------------------------ $this['dispatcher'] = $this->share(function () { return new EventDispatcher(); }); // -- finder ---------------------------------------------------------- $this['finder'] = function () { return new Finder(); }; // -- filesystem ------------------------------------------------------ $this['filesystem'] = $this->share(function ($app) { return new Filesystem(); }); // -- publisher ------------------------------------------------------- $this['publisher'] = $this->share(function ($app) { $outputFormat = $app->edition('format'); switch (strtolower($outputFormat)) { case 'pdf': return new PdfPublisher($app); case 'html': return new HtmlPublisher($app); case 'html_chunked': return new HtmlChunkedPublisher($app); case 'epub': case 'epub2': return new Epub2Publisher($app); //case 'epub3': // return new Epub3Publisher($app); //case 'epub3': // return new Epub3Publisher($app); default: throw new \Exception(sprintf('Unknown "%s" format for "%s" edition (allowed: "pdf", "html", "html_chunked", "epub", "epub2")', $outputFormat, $app->get('publishing.edition'))); } }); // -- parser ---------------------------------------------------------- $this['parser'] = $this->share(function ($app) { $format = strtolower($app['publishing.active_item']['config']['format']); // TODO: extensibility -> support several format parsers (RST, Textile, ...) switch ($format) { case 'md': case 'mdown': case 'markdown': return new MdParser($app); default: throw new \Exception(sprintf('Unknown "%s" format for "%s" content (easybook only supports Markdown)', $format, $app['publishing.active_item']['config']['content'])); } }); // -- twig ------------------------------------------------------------ $this['twig.options'] = array('autoescape' => false, 'charset' => $this['app.charset'], 'debug' => $this['app.debug'], 'strict_variables' => $this['app.debug']); // the twig path used by render() function. This value is set by convenience methods // (renderCustomTemplate(), renderThemeTemplate(), ...) before template rendering $this['twig.path'] = ''; // twig path for custom templates (user defined templates for book/edition) $this['twig.path.custom'] = $this->share(function ($app) { $paths = array(); // edition custom templates // <book-dir>/Resources/Templates/<edition-name>/<template-name>.twig $dir = $app['publishing.dir.templates'] . '/' . $app['publishing.edition']; if (file_exists($dir)) { $paths[] = $dir; } // edition type custom templates (epub, pdf, html, html_chunked) // <book-dir>/Resources/Templates/<edition-type>/<template-name>.twig $dir = $app['publishing.dir.templates'] . '/' . $app->edition('format'); if (file_exists($dir)) { $paths[] = $dir; } // book custom templates (same templates for all editions) // <book-dir>/Resources/Templates/<template-name>.twig $dir = $app['publishing.dir.templates']; if (file_exists($dir)) { $paths[] = $dir; } return $paths; }); // twig path for default theme templates (easybook built-in templates) $this['twig.path.theme'] = $this->share(function ($app) { $paths = array(); $theme = ucfirst($app->edition('theme')); $format = Toolkit::camelize($app->edition('format'), true); // TODO: fix the following hack if ('Epub' == $format) { $format = 'Epub2'; } // default templates for the edition/book theme // <easybook>/app/Resources/Themes/<theme>/<edition-type>/Templates/<template-name>.twig $dir = sprintf('%s/%s/%s/Templates', $app['app.dir.themes'], $theme, $format); if (file_exists($dir)) { $paths[] = $dir; } // default common templates for all the editions of the same theme // <easybook>/app/Resources/Themes/<theme>/Common/Templates/<template-name>.twig $dir = sprintf('%s/%s/Common/Templates', $app['app.dir.themes'], $theme); if (file_exists($dir)) { $paths[] = $dir; } // default base theme for every edition and every book // <easybook>/app/Resources/Themes/Base/<edition-type>/Templates/<template-name>.twig $dir = sprintf('%s/Base/%s/Templates', $app['app.dir.themes'], $format); if (file_exists($dir)) { $paths[] = $dir; } return $paths; }); // twig path for default content templates // (easybook built-in templates for contents; e.g. `license.md.twig`) $this['twig.path.contents'] = $this->share(function ($app) { $paths = array(); $theme = ucfirst($app->edition('theme')); $format = Toolkit::camelize($app->edition('format'), true); // TODO: fix the following hack if ('Epub' == $format) { $format = 'Epub2'; } // default content templates for the edition/book theme // <easybook>/app/Resources/Themes/<theme>/<edition-type>/Contents/<template-name>.twig $dir = sprintf('%s/%s/%s/Contents', $app['app.dir.themes'], $theme, $format); if (file_exists($dir)) { $paths[] = $dir; } // default content templates for every edition and every book // <easybook>/app/Resources/Themes/Base/<edition-type>/Contents/<template-name>.twig $dir = sprintf('%s/Base/%s/Contents', $app['app.dir.themes'], $format); if (file_exists($dir)) { $paths[] = $dir; } return $paths; }); $this['twig.loader'] = function () use($app) { return new \Twig_Loader_Filesystem($app['twig.path']); }; $this['twig'] = function () use($app) { $twig = new \Twig_Environment($app['twig.loader'], $app['twig.options']); $twig->addExtension(new TwigCssExtension()); $twig->addGlobal('app', $app); if (null != $app->get('book')) { $twig->addGlobal('book', $app->get('book')); $publishingEdition = $app->get('publishing.edition'); $editions = $app->book('editions'); $twig->addGlobal('edition', $editions[$publishingEdition]); } return $twig; }; // -- princeXML ------------------------------------------------------- $this['prince.default_paths'] = array('/usr/local/bin/prince', '/usr/bin/prince', 'C:\\Program Files\\Prince\\engine\\bin\\prince.exe'); $this['prince'] = $app->share(function () use($app) { // look for the executable file of PrinceXML $princePath = null; foreach ($app['prince.default_paths'] as $path) { if (file_exists($path)) { $princePath = $path; break; } } if (null == $princePath) { echo sprintf(" In order to generate PDF files, PrinceXML library must be installed. \n\n" . " We couldn't find PrinceXML executable in any of the following directories: \n" . " -> %s \n\n" . " If you haven't installed it yet, you can download a fully-functional demo at: \n" . " %s \n\n" . " If you have installed in a custom directory, please type its full absolute path:\n > ", implode($app['prince.default_paths'], "\n -> "), 'http://www.princexml.com/download'); $input = trim(fgets(STDIN)); if (file_exists($input)) { $princePath = $input; echo "\n"; } else { throw new \Exception(sprintf("We couldn't find the PrinceXML executable in the given directory (%s)", $input)); } } $prince = new Prince($princePath); $prince->setHtml(true); return $prince; }); // -- slugger --------------------------------------------------------- $this['slugger'] = $app->share(function () use($app) { return new Slugger($app); }); // -- code syntax highlighter ----------------------------------------- $this['geshi'] = function () use($app) { require_once __DIR__ . '/../../../vendor/geshi/geshi/geshi.php'; $geshi = new \GeSHi(); $geshi->enable_classes(); // this must be the first method (see Geshi doc) $geshi->set_encoding($app['app.charset']); $geshi->enable_line_numbers(GESHI_NO_LINE_NUMBERS); $geshi->enable_keyword_links(false); return $geshi; }; // -- labels --------------------------------------------------------- $this['labels'] = $app->share(function () use($app) { $labels = Yaml::parse($app['app.dir.translations'] . '/labels.' . $app->book('language') . '.yml'); // books can define their own labels files if (null != ($customLabelsFile = $app->getCustomLabelsFile())) { $customLabels = Yaml::parse($customLabelsFile); return Toolkit::array_deep_merge($labels, $customLabels); } return $labels; }); // -- titles ---------------------------------------------------------- $this['titles'] = $app->share(function () use($app) { $titles = Yaml::parse($app['app.dir.translations'] . '/titles.' . $app->book('language') . '.yml'); // books can define their own titles files if (null != ($customTitlesFile = $app->getCustomTitlesFile())) { $customTitles = Yaml::parse($customTitlesFile); return Toolkit::array_deep_merge($titles, $customTitles); } return $titles; }); }