department-of-veterans-affairs/vets-website

View on GitHub
src/platform/pdf/README.md

Summary

Maintainability
Test Coverage
# Accessible PDF Generation

This package provides an API and templates for generating accessible PDFs on the client side.

## Development

### General

To update dependent packages:

`yarn workspace @department-of-veterans-affairs/platform-pdf install`

### Creating new templates

To add a new PDF template, create a new file under the `templates` directory and add it to `templates/index.js` so that it can be used. The filename is used as the key when generating PDF content. First consider if an existing template can meet your project's needs. PDFKit is powerful but tricky to work with, so it's worth following existing templates and making small iterations. Various utility methods are available in the `utils.js` file. Once a new template has been completed, sample output files must be reviewed by the Platform Accessibility team to ensure that they are fully compliant.

#### Validation / Error handling

Your template should throw an exception for any unrecoverable states. See the validation method in the Medical Records template and `MissingFieldsException` for an example.

#### Testing changes

If you are testing changes to a template, the fastest way to test changes is to use the following command to only build changes to the PDF package and the app you are testing. For instance, if you are testing changes with the Medical Records app, you would use the following command:

`yarn --cwd $( git rev-parse --show-toplevel ) watch --env entry=pdf,medical-records`

NB: you will need to kill and re-start the watch command after each change to the PDF application to see changes.

## Usage

This package provides a single API method for generating PDFs.

```js
generatePdf('template_name', 'generated_file_name', jsonData);
```

Example usage in a VA.gov React application:

```js
import { generatePdf } from '@department-of-veterans-affairs/platform-pdf/exports';

const generateVitals = async () => {
  // This data would usually be dynamically generated.
  const pdfData = {
      "headerLeft": "Lastname, Firstname",
      "headerRight": "Date of birth: January 1, 1970",
      "footerLeft": "Report generated by My HealtheVet and VA on May 15, 2023",
      "footerRight": "Page %PAGE_NUMBER% of %TOTAL_PAGES%",
      "title": "Blood pressure on April 1, 2022 at 12:34 p.m.",
      "subject": "VA Medical Record",
      "preface": "Your vitals list may not be complete. If you have any questions about your information, visit the FAQs or contact your VA Health care team.",
      "results": {
        "items": [
          {
            "items": [
              {
                "title": "Result",
                "value": "120/80",
                "inline": true
              },
              {
                "title": "Location",
                "value": "Pittsburgh VA Medical Center",
                "inline": true
              },
              {
                "title": "Provider notes",
                "value": "None noted",
                "inline": true
              }
            ]
          }
        ]
      }
  };

  try {
    await generatePdf('medicalRecords', 'vitals_report', pdfData);
  } catch (error) {
    // Error logging/presentation goes here...
  }
};
```

When called, the PDF will be generated and the end user's browser will prompt download with the filename `vitals_report.pdf`. Be sure to catch, log and gracefully handle errors to provide the best end user experience possible.

### Limitations

#### Character set support

As of June 2023, PDFKit [does not support font fallback](https://github.com/foliojs/pdfkit/issues/201), meaning that any character that doesn't have a glyph in the selected font will not render. In practice, this means that non-roman characters and multibyte characters (such as emoji) will not render without using a template and font built to support your use case. To see if a specific character is supported, you can use a tool such as [Oh My Glyph](https://www.ohmyglyph.com/glyphview.htm) to load a font and see supported glyphs.

### PDF Metadata

The following fields must be provided by the caller in the JSON data:

* Title

The following fields should be provided, but are not required:

* Author (defaults to "Department of Veterans Affairs")
* Language (defaults to "en-US")
* Subject (defaults to blank)