Typesetter.io
Github
Now on
GitHub!

Documentation and Guide

Convert Markdown to PDF using PHP. Use as a Composer library or a command line tool.

Quick Start Guide

Create ebooks, flyers, one-sheets and more from markdown! This PHP command converts your markdown into a PDF.

In this quick-start guide, we're going to look at creating an ebook from our markdown. The end result will be similar to our example book.

Steps

First, initialize and version a folder using Git - you can git ignore the vendor folder if you wish (but you don't have to). Remember this is a book project, not necessarily a PHP package/project.

Then, install the CLI tool:

composer require typesetterio/typesetter-cli.

After it's installed, generate the default config file (you can customize this.) Run:

vendor/bin/typesetter init

Customize the config.php with the author and title and replace content/* with the contents for your book. A test cover has been generated for you at content/cover.jpg. If you want more customization, modify the theme/theme.html with custom print media CSS.

Finally, generate the output by running vendor/bin/typesetter generate --output=generated/my-book-title.pdf and you can find your PDF in the generated folder.

Documentation Sections

Installation

This requires PHP 8.1 or above.

This tool is meant to be part of the repository that you have your written content. Because of that, you can install it into the local directory with the following command.

composer require typesetterio/typesetter-cli

If you want to just use the Typesetter library itself in your project without getting the command line tools, use the following:

composer require typesetterio/typesetter

This documentation focuses on the main functionality - which is using the command line option to generate ebooks. However, most of the configuration and methodology also applies to using the code as a library.

Basic Usage

Before we continue, note that there are two other great resources you may want to also look at.

First, you can look at the core library typesetterio/typesetter. This has the underlying service class and may give you more context. (You don't need to do that, though, if you just want to generate an ebook from your markdown on the command line.)

Second, check out the example project to see one way of setting up a project. While you're there, you can get a free ebook!

Normally, this is meant to be used on the command line. The simplest way to use this would be like this:

vendor/bin/typesetter generate

But that's when everything is set up perfectly. We have some options to configure. Let's dig in.

Initialization

So, you installed it - now what? You can run the init command which will generate some content for you to review and modify.

vendor/bin/typesetter init

Then you'll find a local config.php that contains options for you to change. In addition, you'll receive a folder for your content. You can replace your content there.

Generation

After you've updated your configuration and put in your content, you can generate the book:

vendor/bin/typesetter generate

Boom! You'll find the output PDF directly in the same directory. Now you're done!

Ok now, where do you put your content? Or how do you make your own cover? That's covered next.

Content

You probably want to make an ebook fo your own content and markdown, right? Let's dig in to this.

Cover

There are three options for a cover. The image or the html file should be in the content folder.

First, you can generate a cover image. The file should be named cover.jpg. The default configuration for MPDF is 96dpi. The default page is a A4. This means a standard resolution that fits that is 794 x 1123 (96dpi). You may experiment with different values for larger resolution displays. Remember, the larger in size your image, the larger the resulting PDF may be.

Second, you can generate a cover with HTML. The file should be named cover.html. For more details, reference the HTML processing of MPDF.

Finally, if you do not create either of these, Typesetter will automatically generate a cover page. It will use your title and author configuration options.

Markdown Content

The content folder holds the content that is coupled with your config to create the PDF.

Chapters should be generated in sequentially named files in your content folder. Refer to League Commonmark for more tips on writing and configuring markdown processors. Out of the box there is a pretty good configuration. This includes the following functionality:

But that's not it. Coming up, check out command line options for generation, config customization to configure your book options, and advanced features.

Command Line Options

By default, the Typesetter generate command will work without any options. However, there are some that you want to use.

Command Option Description
generate --config This is the path and filename relative to your current working directory of the config file. Default is config.php in the local directory.
generate --output This is the path and filename relative to your current working directory of the output file. Directories will be created. Default is the current directory with a slugified version of the title.

Excellent! Let's move on to customizing the configuration of your project.

Config Options

By default, the configuration used during generation is a config.php file in the local directory. You can customize this with command line options if you wish. If you're using the Typesetter library directly and without the CLI, these configuration options reflect the keys of the configuration array.

Config File Format

The configuration file should return an array from PHP. You may have other functionality in it as well (it is require'd during the processing of the command). It's recommended to use full namespaced class names when creating this file as the internal namespace may change as the project progresses.

Creating Config Directly for the Library

Unless you're using the Typesetter functionality as a library, you can skip ahead.

Create a config array and pass that to the config maker. Then create a new instance of the Typesetter class. Call the generate method with your config to get a PDF binary return from MPDF.

Here is an example:

$config = [
    'title' => 'Benjamin Button',
    'observers' => [
        new \Typesetterio\Typesetter\Observers\DefaultMarkdownConfiguration(),
    ],
];
$service = new \Typesetterio\Typesetter\Typesetter(
    new \Typsetterio\Typesetter\Config($config)
);
$pdfContent = $service->generate($config);

You can customize any of the functionality that you normally can in the config.php file directly in that array. Note that you must build the configuration option as detailed above in order to use the service.

Options and Descriptions

Whether you're using the command line or Typesetter as a library, you have the following options to customize:

Option Definition Example
title The title of your book. Benjamin Button
author The author of your book. F. Scott Fitzgerald
theme The path to the folder which contains your theme info. This should at minimum have a theme.html file in it. bb
content The path to the folder with your markdown in it. ./resources/content
contentFilter A callable that is applied as a filter after the content has been gathered. Return true to keep, false to remove. fn() => true
contentExtra A path that has extra content not associated directly with the main content. This is all content you want, no filtering. ./resources/content-extra
toc-enabled Should Table of Contents be generated after cover? false
toc-links Should table of Contents link to the headers in your document? false
toc-header What header with #toc-header html attribute text? Empty will not generate one. My ToC
footer What text should be in the footer? Footer is <footer class="footer"></footer> element. Leave empty to not generate a footer. Page {PAGENO}
markdown-extensions An array of file extensions that indicate they should be rendered. Remember pages are generated in alphabetical or numerical order. ['md']
observers An array of new instances of observers. You can read more about them in the advanced section.

You're all set. But, we're not done yet! Let's move on to the advanced section.

Advanced

In this section, more advanced usage and configuration is covered.

Observers

Observers allow a decorator or visitor style of design pattern to interact with the process of generating this PDF. To make things as transparent as possible, some core items of the service are even configured in observers.

Observers must implement the Typesetterio\Typesetter\Contracts\Observer interface. You may extend the Typesetterio\Typesetter\Observers\Observer abstract class so you don't have to define every interface method. Then, you can override only the ones you want.

Observers are ran in the order they are registered.

Available observer methods available are the following:

Method Definition Parameters
initializedMarkdownEnvironment After the Commonmark Environment has been initialized, this will allow customization of it. League\CommonMark\Environment\Environment that you can add extensions or renderers.
initializedPdf After the MPDF instance is created, you can customize it with this method. Mpdf\Mpdf
coverAdded After any cover has been added, this will allow customization of the PDF. For example, you may want to alter your cover image. Mpdf\Mpdf
parsed After a chapter's markdown has been parsed into HTML and set into a Chapter. The chapter makes methods available to understand the context and modify the HTML. Note that the abstract observer class offers a getDomDocument() method that accepts a Chapter and returns a DomDocument. Then you can modify or parse content easier if you'd like. Typesetterio\Typesetter\Chapter

The following Observers are available for you. They should all be prefixed by Typestetterio\Typesetter\Observers:

Class Definition Parameters
BreakToPageBreak Puts a page break after the template tag {BREAK} The template to use - defaults to {BREAK}.
Credits This adds a box to the last chapter HTML with a class called credits-box. The default theme should make that appear centered on a new last page. You can remove this if you wish. The class to use on the box - default is credits-box.
DefaultMarkdownConfiguration This configures the markdown parser. You probably want to keep this one. Otherwise, if you'd like, you can generate a replacement to configure it on your own - which is only recommended for advanced users. Languages to process - defaults to ['html', 'php', 'js'] - into codeblocks.
FirstElementInChapterCSSClass Puts a css class of chapter-beginning on the first element of every chapter except the first. The class (defaults to chapter-beginning) and a boolean whether to skip the first chapter (default is true)

Chapter

The Typesetterio\Typesetter\Chapter class contains the content of your markdown for that specific chapter.

It contains a number of useful methods for you to interact with the content while it is being converted.

Method Definition
getHtml Get's the rendered HTML from markdown. Remember, this may have been modified by other observers first.
setHtml You must set the HTML after you've modified it. This will cast to string if it's not already.
getChapterNumber Returns an integer indicating which chapter number this is.
getTotalChapters Returns an integer indicating how many total chapters there is to be parsed.
isFirstChapter Returns an integer indicating how many total chapters there is to be parsed.
isLastChapter Returns a boolean indicating if you're dealing with the last chapter.
getMetaData If your content has YAML front matter, this will return an array of parsed properties from it. If not, an empty array.

If you'd like to just get some status updates or notifications and don't need to modify any content, check out Events.

Events

During the process of conversion, Typesetter issues some events that you may listen to. This can be useful for giving status updates or creating logs.

In order to register a listener, call the listen method with an event class and a callable.

Here's an example:

$service = new \Typesetterio\Typesetter\Typesetter();
$service->listen(\Typesetterio\Typesetter\Events\Finished::class, function () use ($myNotifier) {
    $myNotifier->alert('The process has finished');
});

At this time events do not contain any data. If you want to modify anything, please look at observers.

The following events are available (these are all going to be in the Typesetterio\Typesetter\Events namespace):

Event Definition
Starting When the generate() method is first called.
InitializedMarkdown After the markdown environment has been created and all observers have ran on it.
PDFInitialized After the MPDF instance has been created and lightly configured.
ThemeAdded When the theme has been found and applied to the PDF.
CoverImageAdded A cover image has been found in your content and added.
CoverHtmlAdded A cover html file has been found in your content and added.
CoverGenerated Typesetter was unable to find either cover option, so it generated one.
TOCGenerated The Table of Contents has been generated and added.
FooterGenerated The footer content has been generated and added.
ContentGenerating The content has started rendering. This likely is the longest part of the process.
PDFRendering The PDF has started rendering from HTML to PDF binary. This may also take a long time.
Finished The whole process has finished and a PDF string has been returned from the method.

You may listen to as many or as little events as you want. Remember, some of these are optional events based on your configuration.

Themes

Theming support is done with HTML and CSS. The theme folder should contain a theme.html which contains a <style> declaration as if it were in the head of an HTML file. This is where you can customize the theme of your PDF. Remember that you will be working with print styles in CSS so you can use things like page break.

More to come here!

Fonts

At this time, Typesetter only supports the fonts that MPDF does. It will support font management in the future.

To see the list of fonts that are available, see the MPDF Fonts Directory.

You're all set. Still need some help? You might try looking at the example book project to get some hints.

Still Have Questions?

Book a Get UnStuck telegram screen-sharing session to get help.