Examples

Each example below is a complete, runnable report from the Examples/ directory. Every preview on this page is the actual rendered PDF — produced by running:

ym convert report.yml

Grab any example folder, tweak the YAML, and re-render to see your changes.


Simple example

The essentials: headings from keys, word-wrapped paragraphs, a sub-heading, nested bullets, an ordered list, and a table. Start here, then read Document structure.

Report title: 
  - > 
    Here is the first paragraph. You will notice that I have used the `-` character to create
    a YAML list. Under the first list item, I have also used the `>` character which tells
    the parser that you plan on entering a multi-line string that is to be word-wrapped. 

    You can insert linebreaks wherever you want within the YAML
    source but new paragraphs won't be created unless you put use two new line characters.

  - Sub-heading: >
     In order to create a report structure of Heading -> Paragraph -> Subheading, we have to 
     use lists. This is because a YAML key can only have one value. A Paragraph and a Subheading
     coming under the top level heading is effectively two values for the YAML Heading key.

     However, if you want to have a structure of Heading -> Paragraph, Heading -> Paragraph, then
     you can use a simple, key: value structure.

  - Standard content types:
    - Bullets:
      - Bullet 1
      - Bullet 2
      - Bullet 3
      - - Bullet 4
        - Bullet 5
        - Bullet 6
    - Ordered list:
        1: First Item
        2: Second item
        3: 
           12: Fourth item,
           6: Fifth item,
           10: Sixth Item
    - Tables:
      - Item Number: 12.01
        Description: There is a problem here. This report documents it.
        Location: Under the stairs
      - Item Number: 12.02
        Description: There are five ladybugs on the table cloth
        Location: Kitchen
      - Item Number: 45
        Description: The item numbers are arbitray values you structure.
        Location: This table
Simple example, page 1

Page 1

Simple example, page 2

Page 2


Document configuration

Override the body font, heading font, heading colour, and typographic ratio with a _style block in the document front matter. See Configuration.

_style:
  body:
    font: NotoSans
  headings:
    font: AppleGaramond
    ratio: minor third
    color: "#dd9922"

Customizing your document configuration and styling: 
  - >
    There are `three` categories of document configuration
  - 1: The document template
    2: Text styles
    3: Table styles
    
  - >
    These three categories are set at three different levels of priority
  - 1: The internal defaults (lowest priority)
    2: Project config
    3: Document config (highest priority)
      
  - >
    Each level of priority in the configuration heirarchy effectively inherits the configuration of the level of the priority above it.
    
    Using a combination of the internal defaults, you can customize the style of your documents with a minimum amount of configuration text.
    
  - The document template (_doc): 
    - >
      The template controls settings such as
    - - Page size
      - Margins
      - PDF background file path
      - And whether or not you have a separate set of the above settings applying to the first page of your document or not.

    - >
      Currently, the document template is internally configured to only use a single content frame. This limitation would only affect you if you wanted to do something like a two-column layout (where text flows into the second column on the same oage once the first one is full).
    
  - Text styles (_style): 
    - >
      With text styles, you can control the body text
    - Text styling attributes:
      - Font family
      - Text color
      - Size
      - Line spacing ratio
      - Bullet style: 
        - Bullet color
        - Bullet symbol heirarchy
        - Bullet indentation
    
    - >
      You can also control the text heading styles separately from the body text by adjusting their
      
    - - Font family
      - Text color
      - Typographic ratio (in musical intervals)
  
      
    
Document configuration, page 1

Page 1

Document configuration, page 2

Page 2


Document variables

Define _vars, render them into text with Jinja ({{ "{{var}}" }}), and reach into nested values. See Variables.

_vars:
  a: "hello"
  b: true
  c: 23
  d: -0.013
  e: {'key': 'value', 'key2': 'val2'}
  f: ['val1', 'val2']
Document Variables (_vars): 
  - >
    When creating a report yaml document, you have the option to include document-level variables by using the 
    '_vars' key in the root of the document.

    These variables can be rendered as part of your strings (using jinja) within the report content using the double-braces 
    (e.g. {% raw %}{{variable_name}}{% endraw%}). When rendered using jinja, all values are stringified and only the string 
    representation is shown (i.e. the result of str(var)).
    
    This document has five variables defined, a, b, c, d, e.
  - _spacer: 0 # The use of a "0-spacer" is a hack to prevent the paragraph above being interpreted as a bullet point.

  - - a = {{a}}
    - b = {{b}}
    - c = {{c}}
    - d = {{d}}
    - e = {{e.key2}}
    - f = {{f}}
  - Passing Python Objects: >
      It is also possible to pass variable data as Python objects to blocks (see "YMPrint blocks") using the $var syntax (similar to bash).

      You cannot use the dollar-sign variable name syntax (e.g. $varname) within content that is to be displayed (if attempted, an
      error will be raised). The intended use-case is for passing data within the document to be used as <i>block parameters</i>.

      For example, you might want to have some consistent spacer used throughout your document. Instead of typing "_spacer: 5" at all
      locations, you can instead set a variable in the _vars to something like "small_space: 5" and employ the variable at each spacer
      as such "_spacer: $small_space".

      The data you set in the _vars key can be any of the native YAML datatypes: str, int, float, null/None, bool, list, and dict.
  - Computing new Python objects within code: >
      It is also possible to use a _py code block (see "YMPrint blocks") to create variables of arbitrary classes/datatypes and pass
      that data to block parameters.

      A ready example of this would be the _matplotfig block which has a "fig" parameter that expects a matplotlib figure. 

      You would first generate the figure in a _py block and assign the generated figure to a variable. You would then use the
      dollar-sign syntax to pass that computed variable into the "fig" parameter of the _matplotfig code block (see YMPrint blocks
      for details.)
    

  
Document variables, page 1

Page 1

Document variables, page 2

Page 2


PDF backgrounds

Overlay the document onto a designed PDF template and auto-populate its form fields from _vars (here: field_a, field_b, field_c, field_d). See PDF backgrounds.

_doc:
  background: background.pdf
_vars:
  field_a: 1645
  field_b: 99 Sycamore St, Canada
  field_c: $4434.04
  field_d: An enormous moose
_style:
  body:
    size: 9
  headings:
    ratio: major second
Custom styling with PDF backgrounds:
  - >
    You can design your own custom templates in an external PDF document and use it as a background for your YMPrint document
    (as you can see in this document). The fields are populated and the form fields are flattened so that the populated values
    look like normal PDF content.

    The PDF content from the report is overlayed on top of the existing document content in the background.

  - Auto-populated PDF form fields from variables: >
      One of the original design intents of inline document variables is to use them to dynamically populate PDF 
      form fields. By doing so, you can create documents with dynamic headers that give the illusion of working with
      a more sophisticated page layout software.

      Form fields are _automatically_ populated when a document variable name exactly matches the PDF form field name.

    If you want to avoid this behaviour:
      - Make sure that none of your variable names match your field names (i.e. using a special naming convention for your form field names to prevent accidental clashes)
      - Do not use form fields
    Example: The form fields below have been populated from the document vars
PDF backgrounds — content overlaid on a custom template with populated form fields

YMPrint blocks

The full block catalogue in one document: images, admonitions, block quotes, page breaks, horizontal rules, spacers, executable _py, a non-executable _code block, and _loadjson. See the Blocks reference.

_doc:
  body:
    font: NotoSans
  headings:
    font: NotoSans
Using Blocks: 
  - >
    YMPrint uses a special "block syntax" for defining custom content types. Some of these are similar to 
    content types you might expect to see in markdown, e.g. images or code blocks, or extensions to common
    markdown such as admonitions.

  - Images (`_img`):
    _img:
      src: catpuccin.png # Either relative or absolute path. Relative paths are relative to the .yml report file.
      caption: "Figure 1: The catpuccin cat"
      scale_ratio: 0.3
  - Admonitions:
    - "The following admonitions blocks are available:"
    -
      - _info
      - _warning
      - _danger
      - _tip
      - _note
    - They are rendered below

    _info: Here is an "info" admonition
    _warning: Here is a "warning" admonition
    _danger: Here is a danger admonition
    _tip: Here is a helpful tip
    _note: This is useful when you want to give a note
  - Block quotes (`_blockquote`):
    _blockquote: 
        quote: “What you do makes a difference, and you have to decide what kind of difference you want to make.”
        attribution: Jane Goodall
  - Page breaks (`_pagebreak`):
    - >
      You can insert an arbitrary page break using _pagebreak, such as the one below. _pagebreak accepts null as a value.
    - _pagebreak: 
  - Horizontal rules (`_hrule`):
    - >
      Unlike a horizontal rule in Markdown (which does not have properties you can adjust)
      the `_hrule` block in YMPrint has optional parameters like width_ratio,
      thickness, cap, and color that you can manipulate.
    - _hrule_default: null
    - _hrule_red:
        width_ratio: 0.8
        thickness: 2
        color: "#bb3322"
    - _hrule_blue:
        width_ratio: 0.6
        thickness: 3
        color: "#4422dd"
        cap: round
    - _hrule_green:
        width_ratio: 0.4
        thickness: 4
        color: "#22dd44"
    - _hrule_yellow:
        width_ratio: 0.2
        thickness: 6
        color: "#dddd22"
        cap: round
  - Vertical spacers (`_spacer`):
    - >
      You can create arbitrary amounts of vertical white space so you can manually
      adjust the positioning of your content.

      The `_spacer` object accepts a distance in points for the amount of vertical
      space to insert.

      Below, a spacer is inserted in between each line of text
    - _spacer: 5
    - There is a 5 pt spacer above
    - _spacer: 10
    - There is a 10 pt spacer above
    - _spacer: 20
    - There is a 20 pt spacer above
    - _spacer: 40
    - There is a 40 pt spacer above
  - Executable code Blocks (`_py`):
    - >
      In a `_py` code block, Python code will be executed using `exec()` with the "vars"
      dictionary from the document context passed in as its global scope and an optional namespace
      dictionary as its local scope. If no namespace is passed, the "vars" dictionary will be the local
      scope.
      
      Any "_vars" you set in your document
      front matter will be available to your Python code and any variables you create in your
      Python code will be available to your document vars.

      The Python environment used to execute is the same environment that YMPrint is running insert.
      At this time, external Python subprocesses have not been implemented.

    - _py:
        echo: true
        caption: >
          Once this code executes, the variables will be accessible from the "vars" key in the document context under
          a namespace called py1.
        line_numbers: true
        namespace: py1
        source: |
          import math
          a = 3
          b = 4
          c = math.sin(a/b)
          acc = []
          for k in [a, b, c]:
              acc.append(k)
    - "Now, the values of the variables a, b, and c can be included in the document:"
    -
      - a = {{py1.a}} (using py1.a)
      - b = {{py1.b}} (using py1.b)
      - c = {{py1.c}} (using py1.c)
  - _code:
      source: |
        yaml_data: is being shown
        you can put: any yaml data together
        more examples:
          - - cell-padding
            - cell_size
            - row_size
  - Dynamic JSON variables (`_loadjson`):
    - >
      You can dynamically build your vars context by including a _loadjson block in your
      document. 

      Similar to the _py block, you can pass an optional namespace parameter to load the 
      variables into a namespace under the vars dictionary. If no namespace is passed,
      then the variables will be available under the vars dictionary.
    - _loadjson:
        path: extra_vars.json
        namespace: extra_vars
    - "Here are the values of the vars contained within the 'extravars' namespace:"
    -
      - bn = {{extra_vars.bn}}
      - dx = {{extra_vars.dx}}
YMPrint blocks, page 1

Page 1 — images & admonitions

YMPrint blocks, page 2

Page 2 — quotes, rules & spacers

YMPrint blocks, page 3

Page 3 — executable Python

YMPrint blocks, page 4

Page 4 — code & JSON variables