Skip to content

Developer Reference

The PDF engine renders your template in a hidden container, captures it, and assembles the pages. Two extension points let you change what appears in the document without affecting the live site.

Widget overrides

An element that works on screen doesn't always work on a page. An interactive map, a video embed, or a collapsed accordion all need a different representation in print.

There are two layers, and which you use depends on where the substitution can be resolved.

Server-side

Swap a widget's rendered HTML while the PDF template is rendered on the server. Use this when the replacement depends on data the browser doesn't have.

dms_pdf_register_widget_render( 'dms_listing_map', function ( string $html, array $context ): string {
  return '<img src="' . esc_url( $context['static_map_url'] ) . '" alt="Map" />';
} );

The callback receives the widget's HTML and a context array, and returns replacement HTML. It runs only during PDF generation — the live page is untouched.

Client-side

Transform the live DOM in the hidden render container. Use this for visual adjustments — expanding an accordion so its content is captured, swapping a video embed for its thumbnail.

DMSPdf.registerWidget( 'dms_listing_tabs', function ( element ) {
  element.querySelectorAll( '.dms-tab-panel' ).forEach( function ( panel ) {
    panel.style.display = 'block';
  } );
} );

Most visual overrides belong client-side. Reach for the server layer only when the substitution needs data unavailable in the browser.

QR code colours

The QR code element reads its colours from two CSS custom properties on .dms-pdf-qr:

Property Controls Fallback
--dms-qr-color The code modules #000000
--dms-qr-bg The background #ffffff

The element only writes these inline when its Code Color or Background Color is set to something other than the default, or is bound to a global colour. Otherwise a theme can set them:

.dms-pdf-qr {
  --dms-qr-color: var(--e-global-color-primary);
}

The renderer resolves the property to a concrete colour before painting the SVG, so any value the browser can compute works, including nested var() references.

dms_pdf_render_settings

Filters the render settings resolved for a listing type, before they're handed to the client engine.

add_filter( 'dms_pdf_render_settings', function ( array $settings, $type ): array {
  // Force maximum quality for a specific type.
  if ( $type->get( 'slug' ) === 'classics' ) {
    $settings['scale']       = 3.0;
    $settings['jpegQuality'] = 1.0;
  }

  return $settings;
}, 10, 2 );

The array carries:

Key Meaning
scale Capture scale — 1.0, 1.5, 2.0, or 3.0 from the Resolution setting
jpegQuality 0.5–1.0, derived from Image Quality
format letter, a4, or legal
marginPx Page margin in pixels
selectableText Whether the invisible text layer is added

Useful for overriding settings per type, per listing, or conditionally — a heavier document for print-quality downloads and a lighter one for mobile visitors, say.

The generation pipeline

Generation runs as a sequence of stages, each in its own module under assets/js/pdf/stages/:

Stage Does
request-nonce Obtains a token for the template request
load-template Fetches the rendered PDF template
assets Waits for images and fonts to be ready
inject Places the markup in the hidden container
widget-overrides Applies client-side widget transforms
normalize Resolves styles that don't translate to capture
paginate Splits content across pages
capture Rasterises each page
text-layer Overlays the selectable text layer
metadata Applies title, author, subject, and keywords
assemble Builds the PDF document
download Triggers the browser download
cleanup Removes the hidden container

Knowing the order helps when diagnosing a specific failure — a missing image is an assets problem, wrong page breaks are paginate, and text that can't be selected is text-layer.

Notes

  • The engine is enqueued only on listing pages whose type has a PDF template set, so it costs nothing elsewhere.
  • Generation is entirely client-side; there's no server-side render of the final document and nothing is written to disk.
  • Static map images are the exception — they're generated and cached server-side, which is what the Clear Map Image Directory action empties.