Browse Source

feat: allow specifying pageSize for print (#22014)

Shelley Vohr 5 years ago
parent
commit
928175bdfe

+ 2 - 0
docs/api/web-contents.md

@@ -1282,6 +1282,8 @@ Returns [`PrinterInfo[]`](structures/printer-info.md)
     * `vertical` Number (optional) - The vertical dpi.
   * `header` String (optional) - String to be printed as page header.
   * `footer` String (optional) - String to be printed as page footer.
+  * `pageSize` String | Size (optional) - Specify page size of the printed document. Can be `A3`,
+  `A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`.
 * `callback` Function (optional)
   * `success` Boolean - Indicates success of the print call.
   * `failureReason` String - Called back if the print fails; can be `cancelled` or `failed`.

+ 2 - 0
docs/api/webview-tag.md

@@ -569,6 +569,8 @@ Stops any `findInPage` request for the `webview` with the provided `action`.
     * `vertical` Number (optional) - The vertical dpi.
   * `header` String (optional) - String to be printed as page header.
   * `footer` String (optional) - String to be printed as page footer.
+  * `pageSize` String | Size (optional) - Specify page size of the printed document. Can be `A3`,
+  `A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`.
 
 Returns `Promise<void>`
 

+ 31 - 2
lib/browser/api/web-contents.js

@@ -340,9 +340,38 @@ WebContents.prototype.printToPDF = function (options) {
   }
 }
 
-WebContents.prototype.print = function (...args) {
+WebContents.prototype.print = function (options = {}, callback) {
+  // TODO(codebytere): deduplicate argument sanitization by moving rest of
+  // print param logic into new file shared between printToPDF and print
+  if (typeof options === 'object') {
+    // Optionally set size for PDF.
+    if (options.pageSize !== undefined) {
+      const pageSize = options.pageSize
+      if (typeof pageSize === 'object') {
+        if (!pageSize.height || !pageSize.width) {
+          throw new Error('height and width properties are required for pageSize')
+        }
+        // Dimensions in Microns - 1 meter = 10^6 microns
+        options.mediaSize = {
+          name: 'CUSTOM',
+          custom_display_name: 'Custom',
+          height_microns: Math.ceil(pageSize.height),
+          width_microns: Math.ceil(pageSize.width)
+        }
+      } else if (PDFPageSizes[pageSize]) {
+        options.mediaSize = PDFPageSizes[pageSize]
+      } else {
+        throw new Error(`Unsupported pageSize: ${pageSize}`)
+      }
+    }
+  }
+
   if (features.isPrintingEnabled()) {
-    this._print(...args)
+    if (callback) {
+      this._print(options, callback)
+    } else {
+      this._print(options)
+    }
   } else {
     console.error('Error: Printing feature is disabled.')
   }

+ 6 - 0
shell/browser/api/electron_api_web_contents.cc

@@ -1897,6 +1897,12 @@ void WebContents::Print(gin_helper::Arguments* args) {
   options.Get("duplexMode", &duplex_mode);
   settings.SetIntKey(printing::kSettingDuplexMode, duplex_mode);
 
+  // We've already done necessary parameter sanitization at the
+  // JS level, so we can simply pass this through.
+  base::Value media_size(base::Value::Type::DICTIONARY);
+  if (options.Get("mediaSize", &media_size))
+    settings.SetKey(printing::kSettingMediaSize, std::move(media_size));
+
   // Set custom dots per inch (dpi)
   gin_helper::Dictionary dpi_settings;
   int dpi = 72;

+ 7 - 0
spec-main/api-web-contents-spec.ts

@@ -128,6 +128,13 @@ describe('webContents module', () => {
       }).to.throw('webContents.print(): Invalid deviceName provided.')
     })
 
+    it('throws when an invalid pageSize is passed', () => {
+      expect(() => {
+        // @ts-ignore this line is intentionally incorrect
+        w.webContents.print({ pageSize: 'i-am-a-bad-pagesize' }, () => {})
+      }).to.throw('Unsupported pageSize: i-am-a-bad-pagesize')
+    })
+
     it('does not crash', () => {
       expect(() => {
         w.webContents.print({ silent: true })