src/platform/pdf/README.md
# 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)