|
3 | 3 |
|
4 | 4 | ## Print |
5 | 5 |
|
6 | | -1. Add a QR code at the bottom of printed pages so it's easier for someone to navigate to from a printed page. We have a QrCode component. |
7 | | - |
8 | | -2. Need to make sure that on print, when we have a tabbed code block with multiple languages, only the first language is printed and the other language tabs are hidden. The styling should be different for print for the code block. Maybe move other language code tabs to an appendix and add a link to them. |
9 | | - |
10 | | -[This article](https://excessivelyadequate.com/posts/print.html) shows how to control the following properties in Chrome's Print Properties dialog box from CSS: Layout, Paper size, Margins, Headers and footers, and Background graphics. Headers and footers is the checkbox that by default is enabled and adds information on printed pages. It also shows how to use Chrome from the terminal in headless mode to output a PDF file from an HTML page. |
11 | | - |
12 | | -3. For printed pages, your header should shift from a navigation tool to a document identifier. Since users cannot click links or icons on paper, these elements are "cruft" that waste space and ink. |
13 | | - |
14 | | -2. Need a layout alternative to Markup that formats for print. It should hide Table Of Contents. Need a fixed header format that adds article title, subtitle, and date. |
15 | | - |
16 | 6 | __Recommended Print Header Format__ |
17 | 7 |
|
18 | | -A professional print header typically includes only these three elements: |
| 8 | +For printed pages, your header should shift from a navigation tool to a document identifier. Since users cannot click links or icons on paper, these elements are "cruft" that waste space and ink. A professional print header typically includes only these three elements: |
19 | 9 |
|
20 | 10 | - Brand Identity: A high-contrast version of your logo or the site name in plain text for brand recognition. |
21 | 11 | - Document Title: The main title of the page (usually the <h1>), ensuring the reader knows exactly what the document is. |
22 | 12 |
|
23 | | -__Expand External Links For Print__ |
24 | | - |
25 | | -We can't (yet) directly interface with a printed page to explore links, so link URLs should be visible on the printed version of the Web page. To keep the page relatively clean, I prefer to expand only outbound links in articles, and suppress internal ones. If you've used relative URLs on your website for local links, you can easily do this through an attribute selector and `:after` pseudo classes, thus preventing internal links and links around images from being printed: |
26 | | - |
27 | | -- Break Lists across pages, the separators between columns are broken too |
28 | | -- Break code blocks across pages |
29 | | -- Callouts are breaking across pages, they shouldn't |
30 | | - |
31 | 13 | ## PDF File Generation |
32 | 14 |
|
33 | 15 | - Need a workflow to generate PDF files from Markdown for downloads. |
@@ -93,6 +75,74 @@ if (window.matchMedia) { |
93 | 75 | } |
94 | 76 | ``` |
95 | 77 |
|
| 78 | +[This article](https://excessivelyadequate.com/posts/print.html) shows how to control the following properties in Chrome's Print Properties dialog box from CSS: Layout, Paper size, Margins, Headers and footers, and Background graphics. Headers and footers is the checkbox that by default is enabled and adds information on printed pages. It also shows how to use Chrome from the terminal in headless mode to output a PDF file from an HTML page. |
| 79 | + |
| 80 | +Handling Dynamic Content |
| 81 | + |
| 82 | +If your page fetches data (like an API call) that needs to be visible in the print, the load event might fire before your data arrives. In that case, you should call `print()` only after your data-fetching logic completes: |
| 83 | + |
| 84 | +```typescript |
| 85 | +async function prepareAndPrint() { |
| 86 | + // 1. Fetch your data or render dynamic elements |
| 87 | + await fetchData() |
| 88 | + await renderTable() |
| 89 | + |
| 90 | + // 2. Trigger the print dialog now that the DOM is ready |
| 91 | + window.print() |
| 92 | +} |
| 93 | + |
| 94 | +// Call this function when you want the process to start |
| 95 | +prepareAndPrint() |
| 96 | +``` |
| 97 | + |
| 98 | +To ensure your script has executed and the document is ready before the user prints, you should use the `beforeprint` event listener. |
| 99 | + |
| 100 | +This event is specifically designed to run code after a print request is initiated (by Ctrl+P, the menu, or `window.print()`) but before the browser captures the page for the print preview. |
| 101 | + |
| 102 | +The "Safe Preparation" Pattern |
| 103 | + |
| 104 | +Since you want to ensure the document is finished loading and your script has run, you can combine a global "ready" flag with the beforeprint listener. |
| 105 | + |
| 106 | +```typescript |
| 107 | +let isDataReady = false; |
| 108 | + |
| 109 | +// 1. Run your heavy loading/processing logic on page load |
| 110 | + |
| 111 | +window.addEventListener('load', async () => { |
| 112 | + await myComplexScript() // Your data fetching or DOM manipulation |
| 113 | + isDataReady = true |
| 114 | +}) |
| 115 | + |
| 116 | +// 2. Hook into the print intent |
| 117 | + |
| 118 | +window.addEventListener('beforeprint', () => { |
| 119 | + if (!isDataReady) { |
| 120 | + // Optional: Warn the user or perform a last-second synchronous update |
| 121 | + console.warn("Print triggered before background script finished.") |
| 122 | + } |
| 123 | + prepareDOMForPrinting() // Final tweaks (hide buttons, expand sections, etc.) |
| 124 | +}) |
| 125 | +``` |
| 126 | + |
| 127 | +How this meets your requirements: |
| 128 | + |
| 129 | +Guaranteed Execution: The code inside beforeprint is guaranteed to finish before the print preview is generated. |
| 130 | + |
| 131 | +Check Load Status: By using a flag (like isDataReady), you can verify if your initial "load" scripts finished. If they haven't, you can run critical logic immediately inside the beforeprint block. |
| 132 | + |
| 133 | +Automatic Trigger: This doesn't open the print dialog itself; it just "sits and waits" for the user to trigger it manually. |
| 134 | + |
| 135 | +Important Limitations |
| 136 | + |
| 137 | +Synchronous Only: The `beforeprint` event does not support await. If you try to fetch data from an API inside the beforeprint listener, the print dialog will likely open before the data returns. |
| 138 | +Best Practice: Always perform your heavy asynchronous work (API calls, massive DOM construction) on load. Use beforeprint only for synchronous UI adjustments like toggling classes or updating timestamps. |
| 139 | + |
| 140 | +```bash |
| 141 | +chrome --headless --print-to-pdf=book.pdf --no-margins --virtual-time-budget=1337 manuscript.html |
| 142 | +``` |
| 143 | + |
| 144 | +The `--virtual-time-budget=NUMBER` flag defines how long4 Chrome waits between page load and printing - this allows the layout to settle and JavaScript code to run. Complex documents might require a value higher than `1337`. On some platforms, you might need to supply the `--disable-gpu` flag as well. |
| 145 | + |
96 | 146 | ## ToolTips |
97 | 147 |
|
98 | 148 | Need a tooltip component for consistency. |
|
0 commit comments