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.
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:
- GitHub-flavored markdown
- Attributes
- Spatie's Fenced Code / Indent Code renders
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.