Skip to content

Reusable workflow that accept markdown source files and convert them into a template driven PDF document

License

Notifications You must be signed in to change notification settings

innofactororg/markdown2pdf

Repository files navigation

Markdown to PDF converter

This repository includes a GitHub action and a Azure DevOps pipeline to publish a PDF artifact by converting Markdown files using a predefined template.

Get started

To set up a markdown2pdf workflow, several prerequisite steps are required:

  1. If needed, create a repository.

  2. If needed, add markdown documentation to the repository. It is recommended to keep the markdown files in a subfolder of a "docs" folder, for example "docs/hld".

  3. Add a "document.order" file in the markdown folder. It is recommended to only keep one order in each markdown folder.

  4. Add markdown file names to "document.order", one file name for each line.

    Ensure that the file names are in the correct order. This is how they will appear in the PDF file.

    Note that lines that start with the comment sign # will be ignored.

  5. Add a workflow file for each order file in the ".github/workflows" folder of the repository. For example ".github/workflows/docs.hld.dns.yml".

  6. Copy the sample workflow from Usage into each workflow file, customize it and commit the changes.

  7. The workflows can be started manually or automatically when creating or updating a pull request.

Workflow

The workflow converts markdown to PDF using a script and a LaTeX template.

Template sections

The template has the following sections:

  1. A Title page with a logo and the document title and subtitle.

  2. A Version history page. The content of this page is generated based on the following:

    1. If a HistoryFile exist; use the content of that file.
    2. Or, if SkipGitCommitHistory is set to true or a commit history don't exist; use the value of MainAuthor and FirstChangeDescription.
    3. Or, use git commit history. Limit the number of items to the value of GitLogLimit.
  3. A Table of Content page.

  4. Content pages with the converted markdown files. This content is generated based on the following:

    1. Merge the markdown files listed in the "OrderFile" to one markdown file.
    2. Replace markdown links that have a relative path with a absolute path.
    3. If a ReplaceFile exist; update the markdown file and replace each string that match the key from ReplaceFile, with the matching value.
    4. Build metadata for the "pandoc" converter.
    5. Convert the markdown using "pandoc" and save it as an artifact to the job.
  5. Page header on all pages, except for the Title page:

    • Left side: logo
    • Center: Project and Author(s)
    • Right side: Current date.
  6. Page footer on all pages, except for the Title page.

    • Center: page number and total number of pages.

Markdown tips

The markdown can include admonition blocks for text that need special attention.

The following blocks are supported: warning, important, note, caution, tip.

For example:

# A title

This is some regular text.

::: tip
This text is in a tip admonition block.
:::

Issues

The following are known issues:

  • Relative paths should start with ./ to ensure it can be replaced with absolute path before converting it to PDF.
  • Markdown table columns can overlap in the PDF if the table is to wide, making text unreadable. To work around this:
    • limit the text in the table. Typically it should be less than 80 characters wide.
    • split the table up.
    • use an ordered or unordered list.
  • The template is designed for a standing A4 layout. It has no option to flip page orientation for one or several pages in a document.
  • Titles are not automatically numbered. Titles can be manually numbered and maintained in the markdown document. To avoid having to manually update all titles, it is best to not use numbered titles if possible.

Action Inputs

Required

  • Title: (Required) The document title.

Optional

  • FirstChangeDescription: The first change description.

    This value will be used if a HistoryFile is not specified and a git commit comment is not available.

    Default: "Initial draft"

  • Folder: The repository folder where the order file exist.

    Default: "docs"

  • GitLogLimit: Maximum entries to get from Git Log for version history.

    Default: "15"

  • HistoryFile: The name of a history file.

    This is a file with version history content. The file must contain the following structure:

    Version|Date|Author|Description

    Example content for a history.txt file:

    1|Oct 26, 2023|Jane Doe|Initial draft
    2|Oct 28, 2023|John Doe|Added detailed design
    

    Default: ""

  • MainAuthor:

    The main author of the PDF content.

    This value will be used if a HistoryFile is not specified and author can't be retrieved from git commits.

    Default: "Innofactor"

  • OrderFile: The name of the .order file.

    This is a text file with the name of each markdown file, one for each line, in the correct order.

    Example content for a document.order file:

    summary.md
    details.md
    faq.md
    

    Default: "document.order"

  • OutFile: The name of the output file.

    This file will be uploaded to the job artifacts.

    Default: "document.pdf"

  • Project: The project ID or name. This value will be in the document header.

    Default: ""

  • ReplaceFile: The name of the replace file.

    This is a JSON file with key and value strings. Each key will be searched for in the markdown files and replaced with the value before conversion to PDF.

    Example content for a replace.json file:

    {
      "{data center name}": "WE1",
      "{organization name}": "contoso"
    }

    Default: ""

  • RetentionDays: Number of days to retain job artifacts.

    Default: "5"

  • SkipGitCommitHistory: Skip using git commit history.

    When set to true, the change history will not be retrieved from the git commit log.

    Default: "false"

  • Subtitle: The document subtitle.

    Default: ""

  • Template: The template name. Must be: designdoc.

    Default: "designdoc"

Usage

name: 📝 Convert Markdown
on:
  workflow_dispatch:
  pull_request:
    types: [opened, synchronize]
    branches: [main]
    paths:
      - "docs/design/*.md"
      - "docs/design/*.order"

permissions: {}

jobs:
  pdf:
    name: Build PDF
    permissions:
      contents: read # for checkout
    runs-on: ubuntu-22.04
    container:
      image: pandoc/extra:3.1.1-alpine
    steps:
      - name: Clone repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Build PDF
        uses: innofactororg/markdown2pdf@v3
        with:
          # The first change description.
          #
          # This value will be used if a HistoryFile
          # is not specified and a git commit comment
          # is not available.
          #
          # Default: Initial draft
          FirstChangeDescription: Initial draft

          # The repository folder where the order file exist.
          # Default: docs
          Folder: docs/design

          # Maximum entries to get from Git Log for version history.
          # Default: 15
          GitLogLimit: 15

          # The name of the history file.
          #
          # This is a file with the version history content.
          #
          # The file must contain the following structure:
          # Version|Date|Author|Description
          #
          # Example content for a history.txt file:
          # 1|Oct 26, 2023|Jane Doe|Initial draft
          # 2|Oct 28, 2023|John Doe|Added detailed design
          #
          # Default: ''
          HistoryFile: history.txt

          # The main author of the PDF content.
          #
          # This value will be used if a HistoryFile
          # is not specified and author can't be retrieved
          # from git commits.
          #
          # Default: Innofactor
          MainAuthor: Innofactor

          # The name of the .order file.
          #
          # This is a text file with the name of each markdown file,
          # one for each line, in the correct order.
          #
          # Example content for a document.order file:
          # summary.md
          # details.md
          # faq.md
          #
          # Default: document.order
          OrderFile: document.order

          # The name of the output file.
          #
          # This file will be uploaded to the job artifacts.
          #
          # Default: document.pdf
          OutFile: Design.pdf

          # The project ID or name.
          # Default: ''
          Project: 12345678

          # Skip using git commit history.
          #
          # When set to true, the change history will not be
          # retrieved from the git commit log.
          #
          # Default: false
          SkipGitCommitHistory: false

          # The document subtitle.
          # Default: ''
          Subtitle: DESIGN DOCUMENT

          # The template name. Must be: designdoc.
          # Default: designdoc
          Template: designdoc

          # The document title.
          # Required
          Title: Design

          # The name of the replace file.
          #
          # This is a JSON file with key and value strings.
          # Each key will be searched for in the markdown files and
          # replaced with the value before conversion to PDF.
          #
          # Example content for a replace.json file:
          # {
          #   "{data center name}": "WE1",
          #   "{organization name}": "contoso"
          # }
          #
          # Default:
          ReplaceFile: replace.json

          # Number of days to retain job artifacts.
          # Default: 5 days
          RetentionDays: 5

License

The code and documentation in this project are released under the BSD 3-Clause License.