2017-05-11 07:06:41 +00:00
/ * *
* Copyright 2017 Google Inc . All rights reserved .
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
var fs = require ( 'fs' ) ;
var EventEmitter = require ( 'events' ) ;
var helpers = require ( './helpers' ) ;
2017-05-12 17:50:06 +00:00
var mime = require ( 'mime' ) ;
2017-06-15 07:20:37 +00:00
var Request = require ( './Request' ) ;
2017-06-16 04:22:41 +00:00
var Dialog = require ( './Dialog' ) ;
2017-05-11 07:06:41 +00:00
class Page extends EventEmitter {
/ * *
2017-06-15 01:37:42 +00:00
* @ param { ! Connection } client
2017-05-11 07:06:41 +00:00
* @ return { ! Promise < ! Page > }
* /
2017-06-16 04:35:31 +00:00
static async create ( client ) {
2017-05-11 07:06:41 +00:00
await Promise . all ( [
client . send ( 'Network.enable' , { } ) ,
client . send ( 'Page.enable' , { } ) ,
client . send ( 'Runtime.enable' , { } ) ,
client . send ( 'Security.enable' , { } ) ,
] ) ;
var screenDPI = await helpers . evaluate ( client , ( ) => window . devicePixelRatio , [ ] ) ;
2017-06-16 04:35:31 +00:00
var page = new Page ( client , screenDPI . result . value ) ;
2017-05-11 07:06:41 +00:00
// Initialize default page size.
2017-06-14 14:41:26 +00:00
await page . setViewportSize ( { width : 400 , height : 300 } ) ;
2017-05-11 07:06:41 +00:00
return page ;
}
/ * *
2017-06-15 01:37:42 +00:00
* @ param { ! Connection } client
2017-05-11 07:06:41 +00:00
* @ param { number } screenDPI
* /
2017-06-16 04:35:31 +00:00
constructor ( client , screenDPI ) {
2017-05-11 07:06:41 +00:00
super ( ) ;
this . _client = client ;
this . _screenDPI = screenDPI ;
this . _extraHeaders = { } ;
2017-05-13 00:55:29 +00:00
/** @type {!Map<string, !InPageCallback>} */
this . _sourceURLToPageCallback = new Map ( ) ;
/** @type {!Map<string, !InPageCallback>} */
2017-05-11 07:06:41 +00:00
this . _scriptIdToPageCallback = new Map ( ) ;
2017-06-15 07:20:37 +00:00
/** @type {?function(!Request)} */
this . _requestInterceptor = null ;
2017-05-11 07:06:41 +00:00
2017-06-17 03:20:36 +00:00
this . _screenshotTaskChain = Promise . resolve ( ) ;
2017-05-11 07:06:41 +00:00
client . on ( 'Debugger.paused' , event => this . _onDebuggerPaused ( event ) ) ;
2017-05-13 00:55:29 +00:00
client . on ( 'Debugger.scriptParsed' , event => this . _onScriptParsed ( event ) ) ;
2017-05-11 07:06:41 +00:00
client . on ( 'Network.responseReceived' , event => this . emit ( Page . Events . ResponseReceived , event . response ) ) ;
client . on ( 'Network.loadingFailed' , event => this . emit ( Page . Events . ResourceLoadingFailed , event ) ) ;
2017-06-15 07:20:37 +00:00
client . on ( 'Network.requestIntercepted' , event => this . _onRequestIntercepted ( event ) ) ;
2017-05-11 07:06:41 +00:00
client . on ( 'Runtime.consoleAPICalled' , event => this . _onConsoleAPI ( event ) ) ;
2017-05-13 20:44:24 +00:00
client . on ( 'Page.javascriptDialogOpening' , event => this . _onDialog ( event ) ) ;
2017-05-11 07:06:41 +00:00
client . on ( 'Runtime.exceptionThrown' , exception => this . _handleException ( exception . exceptionDetails ) ) ;
}
2017-06-15 07:20:37 +00:00
/ * *
* @ param { ? function ( ! Request ) } interceptor
* /
async setRequestInterceptor ( interceptor ) {
this . _requestInterceptor = interceptor ;
await this . _client . send ( 'Network.enableRequestInterception' , { enabled : ! ! interceptor } ) ;
}
/ * *
* @ param { ! Object } event
* /
_onRequestIntercepted ( event ) {
var request = new Request ( this . _client , event . InterceptionId , event . request ) ;
this . _requestInterceptor ( request ) ;
}
2017-05-12 17:01:22 +00:00
/ * *
* @ param { string } url
* @ return { ! Promise }
* /
2017-05-12 17:19:01 +00:00
async addScriptTag ( url ) {
2017-06-15 21:56:40 +00:00
return this . evaluate ( addScriptTag , url ) ;
2017-05-12 17:01:22 +00:00
/ * *
* @ param { string } url
* /
function addScriptTag ( url ) {
var script = document . createElement ( 'script' ) ;
script . src = url ;
var promise = new Promise ( x => script . onload = x ) ;
document . head . appendChild ( script ) ;
return promise ;
}
}
2017-05-12 17:19:01 +00:00
/ * *
* @ param { string } filePath
* @ return { ! Promise }
* /
async injectFile ( filePath ) {
2017-05-12 21:45:47 +00:00
var code = fs . readFileSync ( filePath , 'utf8' ) ;
await helpers . evaluateText ( this . _client , code , false /* awaitPromise */ ) ;
2017-05-12 17:19:01 +00:00
}
2017-05-11 07:06:41 +00:00
/ * *
* @ param { string } name
* @ param { function ( ? ) } callback
* /
async setInPageCallback ( name , callback ) {
var hasCallback = await this . evaluate ( function ( name ) {
return ! ! window [ name ] ;
} , name ) ;
if ( hasCallback )
throw new Error ( ` Failed to set in-page callback with name ${ name } : window[' ${ name } '] already exists! ` ) ;
var sourceURL = '__in_page_callback__' + name ;
2017-05-13 00:55:29 +00:00
this . _sourceURLToPageCallback . set ( sourceURL , new InPageCallback ( name , callback ) ) ;
2017-06-15 21:56:40 +00:00
var text = helpers . evaluationString ( inPageCallback , [ name ] , false /* wrapInPromise */ , sourceURL ) ;
2017-05-13 00:55:29 +00:00
await Promise . all ( [
this . _client . send ( 'Debugger.enable' , { } ) ,
this . _client . send ( 'Page.addScriptToEvaluateOnLoad' , { scriptSource : text } ) ,
helpers . evaluateText ( this . _client , text , false /* awaitPromise */ )
] ) ;
2017-05-11 07:06:41 +00:00
function inPageCallback ( callbackName ) {
window [ callbackName ] = ( ... args ) => {
window [ callbackName ] . _ _args = args ;
debugger ;
2017-06-13 22:00:55 +00:00
var result = window [ callbackName ] . _ _result ;
delete window [ callbackName ] . _ _result ;
delete window [ callbackName ] . _ _args ;
return result ;
2017-05-11 07:06:41 +00:00
} ;
}
}
/ * *
2017-05-13 00:55:29 +00:00
* @ param { ! InPageCallback } inPageCallback
2017-05-11 07:06:41 +00:00
* /
2017-05-13 00:55:29 +00:00
async _handleInPageCallback ( inPageCallback ) {
var name = inPageCallback . name ;
var callback = inPageCallback . callback ;
2017-05-11 07:06:41 +00:00
var args = await this . evaluate ( callbackName => window [ callbackName ] . _ _args , name ) ;
2017-06-14 15:21:56 +00:00
var result = await Promise . resolve ( callback . apply ( null , args ) ) ;
2017-05-11 07:06:41 +00:00
await this . evaluate ( assignResult , name , result ) ;
this . _client . send ( 'Debugger.resume' ) ;
/ * *
* @ param { string } callbackName
* @ param { string } callbackResult
* /
function assignResult ( callbackName , callbackResult ) {
window [ callbackName ] . _ _result = callbackResult ;
}
}
_onDebuggerPaused ( event ) {
var location = event . callFrames [ 0 ] ? event . callFrames [ 0 ] . location : null ;
2017-05-13 00:55:29 +00:00
var inPageCallback = location ? this . _scriptIdToPageCallback . get ( location . scriptId ) : null ;
if ( inPageCallback ) {
this . _handleInPageCallback ( inPageCallback ) ;
2017-05-11 07:06:41 +00:00
return ;
}
this . _client . send ( 'Debugger.resume' ) ;
}
2017-05-13 00:55:29 +00:00
_onScriptParsed ( event ) {
var inPageCallback = this . _sourceURLToPageCallback . get ( event . url ) ;
if ( inPageCallback )
this . _scriptIdToPageCallback . set ( event . scriptId , inPageCallback ) ;
}
2017-05-11 07:06:41 +00:00
/ * *
* @ param { ! Object } headers
* @ return { ! Promise }
* /
async setExtraHTTPHeaders ( headers ) {
this . _extraHeaders = { } ;
// Note: header names are case-insensitive.
for ( var key of Object . keys ( headers ) )
this . _extraHeaders [ key . toLowerCase ( ) ] = headers [ key ] ;
return this . _client . send ( 'Network.setExtraHTTPHeaders' , { headers } ) ;
}
/ * *
* @ return { ! Object }
* /
extraHTTPHeaders ( ) {
return Object . assign ( { } , this . _extraHeaders ) ;
}
/ * *
* @ param { string } userAgent
* @ return { ! Promise }
* /
async setUserAgentOverride ( userAgent ) {
this . _userAgent = userAgent ;
return this . _client . send ( 'Network.setUserAgentOverride' , { userAgent } ) ;
}
/ * *
* @ return { string }
* /
userAgentOverride ( ) {
return this . _userAgent ;
}
2017-06-16 18:21:44 +00:00
/ * *
* @ param { ! Object } exceptionDetails
* /
async _handleException ( exceptionDetails ) {
var message = await this . _getExceptionMessage ( exceptionDetails ) ;
this . emit ( Page . Events . Error , new Error ( message ) ) ;
2017-05-11 07:06:41 +00:00
}
_onConsoleAPI ( event ) {
var values = event . args . map ( arg => arg . value || arg . description || '' ) ;
2017-05-13 18:05:54 +00:00
this . emit ( Page . Events . ConsoleMessage , values . join ( ' ' ) ) ;
2017-05-11 07:06:41 +00:00
}
2017-05-13 20:44:24 +00:00
_onDialog ( event ) {
2017-06-16 04:22:41 +00:00
var dialogType = null ;
2017-05-13 20:44:24 +00:00
if ( event . type === 'alert' )
2017-06-16 04:22:41 +00:00
dialogType = Dialog . Type . Alert ;
2017-05-13 20:44:24 +00:00
else if ( event . type === 'confirm' )
2017-06-16 04:22:41 +00:00
dialogType = Dialog . Type . Confirm ;
2017-05-13 20:44:24 +00:00
else if ( event . type === 'prompt' )
2017-06-16 04:22:41 +00:00
dialogType = Dialog . Type . Prompt ;
2017-05-13 20:44:24 +00:00
else if ( event . type === 'beforeunload' )
2017-06-16 04:22:41 +00:00
dialogType = Dialog . Type . BeforeUnload ;
console . assert ( dialogType , 'Unknown javascript dialog type: ' + event . type ) ;
var dialog = new Dialog ( this . _client , dialogType , event . message ) ;
this . emit ( Page . Events . Dialog , dialog ) ;
2017-05-13 20:44:24 +00:00
}
2017-05-11 07:06:41 +00:00
/ * *
* @ return { ! Promise < string > }
* /
async url ( ) {
return this . evaluate ( function ( ) {
return window . location . href ;
} ) ;
}
/ * *
* @ param { string } html
* @ return { ! Promise }
* /
async setContent ( html ) {
var resourceTree = await this . _client . send ( 'Page.getResourceTree' , { } ) ;
await this . _client . send ( 'Page.setDocumentContent' , {
frameId : resourceTree . frameTree . frame . id ,
html : html
} ) ;
}
/ * *
* @ param { string } html
* @ return { ! Promise < boolean > }
* /
async navigate ( url ) {
var loadPromise = new Promise ( fulfill => this . _client . once ( 'Page.loadEventFired' , fulfill ) ) . then ( ( ) => true ) ;
var interstitialPromise = new Promise ( fulfill => this . _client . once ( 'Security.certificateError' , fulfill ) ) . then ( ( ) => false ) ;
var referrer = this . _extraHeaders . referer ;
// Await for the command to throw exception in case of illegal arguments.
2017-05-15 05:17:57 +00:00
try {
await this . _client . send ( 'Page.navigate' , { url , referrer } ) ;
} catch ( e ) {
return false ;
}
2017-05-11 07:06:41 +00:00
return await Promise . race ( [ loadPromise , interstitialPromise ] ) ;
}
/ * *
* @ param { ! { width : number , height : number } } size
* @ return { ! Promise }
* /
2017-06-14 14:41:26 +00:00
async setViewportSize ( size ) {
2017-05-11 07:06:41 +00:00
this . _size = size ;
var width = size . width ;
var height = size . height ;
var zoom = this . _screenDPI ;
return Promise . all ( [
this . _client . send ( 'Emulation.setDeviceMetricsOverride' , {
width ,
height ,
deviceScaleFactor : 1 ,
scale : 1 / zoom ,
mobile : false ,
fitWindow : false
} ) ,
this . _client . send ( 'Emulation.setVisibleSize' , {
width : width / zoom ,
height : height / zoom ,
} )
] ) ;
}
/ * *
* @ return { ! { width : number , height : number } }
* /
2017-06-14 14:41:26 +00:00
viewportSize ( ) {
2017-05-11 07:06:41 +00:00
return this . _size ;
}
/ * *
* @ param { function ( ) } fun
* @ param { ! Array < * > } args
2017-06-12 06:10:33 +00:00
* @ return { ! Promise < ( ! Object | undefined ) > }
2017-05-11 07:06:41 +00:00
* /
async evaluate ( fun , ... args ) {
2017-06-15 21:56:40 +00:00
var code = helpers . evaluationString ( fun , args , false /* wrapInPromise */ ) ;
var response = await this . _client . send ( 'Runtime.evaluate' , {
expression : code
} ) ;
2017-05-11 07:06:41 +00:00
if ( response . exceptionDetails ) {
2017-06-16 18:21:44 +00:00
var message = await this . _getExceptionMessage ( response . exceptionDetails ) ;
throw new Error ( 'Evaluation failed: ' + message ) ;
2017-05-11 07:06:41 +00:00
}
2017-06-16 17:34:13 +00:00
2017-06-15 21:56:40 +00:00
var remoteObject = response . result ;
if ( remoteObject . type !== 'object' )
return remoteObject . value ;
var isPromise = remoteObject . type === 'object' && remoteObject . subtype === 'promise' ;
var response = await this . _client . send ( 'Runtime.callFunctionOn' , {
objectId : remoteObject . objectId ,
functionDeclaration : 'function() { return this; }' ,
returnByValue : true ,
awaitPromise : isPromise
} ) ;
await this . _client . send ( 'Runtime.releaseObject' , {
objectId : remoteObject . objectId
} ) ;
2017-05-11 07:06:41 +00:00
if ( response . exceptionDetails ) {
2017-06-16 18:21:44 +00:00
var message = await this . _getExceptionMessage ( response . exceptionDetails ) ;
throw new Error ( 'Evaluation failed with ' + message ) ;
2017-05-11 07:06:41 +00:00
}
2017-06-15 21:56:40 +00:00
2017-05-11 07:06:41 +00:00
return response . result . value ;
2017-06-16 18:21:44 +00:00
}
2017-06-16 17:34:13 +00:00
2017-06-16 18:21:44 +00:00
/ * *
* @ param { ! Object } exceptionDetails
* @ return { string }
* /
async _getExceptionMessage ( exceptionDetails ) {
var message = '' ;
var exception = exceptionDetails . exception ;
if ( exception ) {
var response = await this . _client . send ( 'Runtime.callFunctionOn' , {
2017-06-16 17:34:13 +00:00
objectId : exception . objectId ,
2017-06-16 18:21:44 +00:00
functionDeclaration : 'function() { return this.message; }' ,
2017-06-16 17:34:13 +00:00
returnByValue : true ,
} ) ;
2017-06-16 18:21:44 +00:00
message = response . result . value ;
} else {
message = exceptionDetails . text ;
}
if ( exceptionDetails . stackTrace ) {
for ( var callframe of exceptionDetails . stackTrace . callFrames ) {
var location = callframe . url + ':' + callframe . lineNumber + ':' + callframe . columnNumber ;
var functionName = callframe . functionName || '<anonymous>' ;
message += ` \n at ${ functionName } ( ${ location } ) ` ;
}
2017-06-16 17:34:13 +00:00
}
2017-06-16 18:21:44 +00:00
return message ;
2017-05-11 07:06:41 +00:00
}
2017-05-12 18:32:02 +00:00
/ * *
* @ param { function ( ) } fun
* @ param { ! Array < * > } args
* @ return { ! Promise }
* /
async evaluateOnInitialized ( fun , ... args ) {
2017-06-15 21:56:40 +00:00
var code = helpers . evaluationString ( fun , args , false /* wrapInPromise */ ) ;
2017-05-12 18:32:02 +00:00
await this . _client . send ( 'Page.addScriptToEvaluateOnLoad' , {
scriptSource : code
} ) ;
}
2017-05-11 07:06:41 +00:00
/ * *
2017-06-17 00:15:24 +00:00
* @ param { ! Object = } options
2017-05-11 07:06:41 +00:00
* @ return { ! Promise < ! Buffer > }
* /
2017-06-17 00:15:24 +00:00
async screenshot ( options ) {
2017-06-17 03:20:36 +00:00
options = options || { } ;
2017-06-17 00:15:24 +00:00
var screenshotType = null ;
if ( options . path ) {
var mimeType = mime . lookup ( options . path ) ;
if ( mimeType === 'image/png' )
screenshotType = 'png' ;
else if ( mimeType === 'image/jpeg' )
screenshotType = 'jpeg' ;
2017-06-17 05:34:29 +00:00
console . assert ( screenshotType , 'Unsupported screenshot mime type: ' + mimeType ) ;
2017-06-17 00:15:24 +00:00
}
if ( options . type ) {
2017-06-17 05:34:29 +00:00
console . assert ( ! screenshotType || options . type === screenshotType , ` Passed screenshot type ' ${ options . type } ' does not match the type inferred from the file path: ' ${ screenshotType } ' ` ) ;
console . assert ( options . type === 'png' || options . type === 'jpeg' , 'Unknown options.type value: ' + options . type ) ;
2017-06-17 00:15:24 +00:00
screenshotType = options . type ;
}
if ( ! screenshotType )
screenshotType = 'png' ;
if ( options . quality ) {
console . assert ( screenshotType === 'jpeg' , 'options.quality is unsupported for the ' + screenshotType + ' screenshots' ) ;
console . assert ( typeof options . quality === 'number' , 'Expected options.quality to be a number but found ' + ( typeof options . quality ) ) ;
console . assert ( Number . isInteger ( options . quality ) , 'Expected options.quality to be an integer' ) ;
console . assert ( options . quality >= 0 && options . quality <= 100 , 'Expected options.quality to be between 0 and 100 (inclusive), got ' + options . quality ) ;
}
2017-06-17 05:34:29 +00:00
console . assert ( ! options . clip || ! options . fullPage , 'options.clip and options.fullPage are exclusive' ) ;
2017-06-17 00:15:24 +00:00
if ( options . clip ) {
console . assert ( typeof options . clip . x === 'number' , 'Expected options.clip.x to be a number but found ' + ( typeof options . clip . x ) ) ;
console . assert ( typeof options . clip . y === 'number' , 'Expected options.clip.y to be a number but found ' + ( typeof options . clip . y ) ) ;
console . assert ( typeof options . clip . width === 'number' , 'Expected options.clip.width to be a number but found ' + ( typeof options . clip . width ) ) ;
console . assert ( typeof options . clip . height === 'number' , 'Expected options.clip.height to be a number but found ' + ( typeof options . clip . height ) ) ;
}
2017-06-17 03:20:36 +00:00
this . _screenshotTaskChain = this . _screenshotTaskChain . then ( this . _screenshotTask . bind ( this , screenshotType , options ) ) ;
return this . _screenshotTaskChain ;
}
2017-06-17 00:15:24 +00:00
2017-06-17 03:20:36 +00:00
/ * *
* @ param { string } screenshotType
* @ param { ! Object = } options
* @ return { ! Promise < ! Buffer > }
* /
async _screenshotTask ( screenshotType , options ) {
2017-06-17 00:15:24 +00:00
if ( options . clip ) {
2017-05-11 07:06:41 +00:00
await Promise . all ( [
this . _client . send ( 'Emulation.setVisibleSize' , {
2017-06-17 00:15:24 +00:00
width : Math . ceil ( options . clip . width / this . _screenDPI ) ,
height : Math . ceil ( options . clip . height / this . _screenDPI ) ,
2017-05-11 07:06:41 +00:00
} ) ,
this . _client . send ( 'Emulation.forceViewport' , {
2017-06-17 00:15:24 +00:00
x : options . clip . x / this . _screenDPI ,
y : options . clip . y / this . _screenDPI ,
2017-05-11 07:06:41 +00:00
scale : 1 ,
} )
] ) ;
2017-06-17 05:34:29 +00:00
} else if ( options . fullPage ) {
var response = await this . _client . send ( 'Page.getLayoutMetrics' ) ;
await Promise . all ( [
this . _client . send ( 'Emulation.setVisibleSize' , {
width : Math . ceil ( response . contentSize . width / this . _screenDPI ) ,
height : Math . ceil ( response . contentSize . height / this . _screenDPI ) ,
} ) ,
this . _client . send ( 'Emulation.forceViewport' , {
x : 0 ,
y : 0 ,
scale : 1 ,
} )
] ) ;
2017-05-11 07:06:41 +00:00
}
var result = await this . _client . send ( 'Page.captureScreenshot' , {
fromSurface : true ,
format : screenshotType ,
2017-06-17 00:15:24 +00:00
quality : options . quality
2017-05-11 07:06:41 +00:00
} ) ;
2017-06-17 05:34:29 +00:00
if ( options . clip || options . fullPage ) {
2017-05-11 07:06:41 +00:00
await Promise . all ( [
2017-06-14 14:41:26 +00:00
this . setViewportSize ( this . viewportSize ( ) ) ,
2017-05-11 07:06:41 +00:00
this . _client . send ( 'Emulation.resetViewport' )
] ) ;
}
2017-06-17 00:15:24 +00:00
var buffer = new Buffer ( result . data , 'base64' ) ;
if ( options . path )
fs . writeFileSync ( options . path , buffer ) ;
return buffer ;
2017-05-12 17:50:06 +00:00
}
2017-05-14 18:29:42 +00:00
/ * *
* @ param { string } filePath
* @ param { ! Object = } options
2017-06-13 07:28:29 +00:00
* @ return { ! Promise }
2017-05-14 18:29:42 +00:00
* /
async printToPDF ( filePath , options ) {
options = options || { } ;
var scale = options . scale || 1 ;
var displayHeaderFooter = options . displayHeaderFooter || false ;
var printBackground = options . printBackground || true ;
var landscape = options . landscape || false ;
var pageRanges = options . pageRanges || '' ;
var paperWidth = 8.5 ;
var paperHeight = 11 ;
if ( options . format ) {
var format = Page . PaperFormats [ options . format ] ;
console . assert ( format , 'Unknown paper format: ' + options . format ) ;
paperWidth = format . width ;
paperHeight = format . height ;
} else {
paperWidth = convertPrintParameterToInches ( options . width ) || paperWidth ;
paperHeight = convertPrintParameterToInches ( options . height ) || paperHeight ;
}
var marginOptions = options . margin || { } ;
var marginTop = convertPrintParameterToInches ( marginOptions . top ) || 0 ;
var marginLeft = convertPrintParameterToInches ( marginOptions . left ) || 0 ;
var marginBottom = convertPrintParameterToInches ( marginOptions . bottom ) || 0 ;
var marginRight = convertPrintParameterToInches ( marginOptions . right ) || 0 ;
var result = await this . _client . send ( 'Page.printToPDF' , {
landscape : landscape ,
displayHeaderFooter : displayHeaderFooter ,
printBackground : printBackground ,
scale : scale ,
paperWidth : paperWidth ,
paperHeight : paperHeight ,
marginTop : marginTop ,
marginBottom : marginBottom ,
marginLeft : marginLeft ,
marginRight : marginRight ,
pageRanges : pageRanges
} ) ;
var buffer = new Buffer ( result . data , 'base64' ) ;
fs . writeFileSync ( filePath , buffer ) ;
}
2017-05-11 07:06:41 +00:00
/ * *
* @ return { ! Promise < string > }
* /
async plainText ( ) {
return this . evaluate ( function ( ) {
return document . body . innerText ;
} ) ;
}
/ * *
* @ return { ! Promise < string > }
* /
async title ( ) {
return this . evaluate ( function ( ) {
return document . title ;
} ) ;
}
/ * *
* @ return { ! Promise }
* /
async close ( ) {
2017-06-14 22:45:59 +00:00
await this . _client . dispose ( ) ;
2017-05-11 07:06:41 +00:00
}
}
2017-05-13 00:55:29 +00:00
class InPageCallback {
/ * *
* @ param { string } name
* @ param { function ( ? ) : ? } callback
* /
constructor ( name , callback ) {
this . name = name ;
this . callback = callback ;
}
}
2017-05-14 18:29:42 +00:00
/** @enum {string} */
Page . PaperFormats = {
Letter : { width : 8.5 , height : 11 } ,
Legal : { width : 8.5 , height : 14 } ,
Tabloid : { width : 11 , height : 17 } ,
Ledger : { width : 17 , height : 11 } ,
A0 : { width : 33.1 , height : 46.8 } ,
A1 : { width : 23.4 , height : 33.1 } ,
A2 : { width : 16.5 , height : 23.4 } ,
A3 : { width : 11.7 , height : 16.5 } ,
A4 : { width : 8.27 , height : 11.7 } ,
A5 : { width : 5.83 , height : 8.27 } ,
} ;
var unitToPixels = {
'px' : 1 ,
'in' : 96 ,
'cm' : 37.8 ,
'mm' : 3.78
} ;
/ * *
* @ param { ( string | number | undefined ) } parameter
* @ return { ( number | undefined ) }
* /
function convertPrintParameterToInches ( parameter ) {
if ( typeof parameter === 'undefined' )
return undefined ;
var pixels ;
if ( typeof parameter === 'number' ) {
// Treat numbers as pixel values to be aligned with phantom's paperSize.
pixels = /** @type {number} */ ( parameter ) ;
} else if ( typeof parameter === 'string' ) {
var text = parameter ;
var unit = text . substring ( text . length - 2 ) . toLowerCase ( ) ;
var valueText = '' ;
if ( unitToPixels . hasOwnProperty ( unit ) ) {
valueText = text . substring ( 0 , text . length - 2 ) ;
} else {
// In case of unknown unit try to parse the whole parameter as number of pixels.
// This is consistent with phantom's paperSize behavior.
unit = 'px' ;
valueText = text ;
}
var value = Number ( valueText ) ;
console . assert ( ! isNaN ( value ) , 'Failed to parse parameter value: ' + text ) ;
2017-06-12 06:10:33 +00:00
pixels = value * unitToPixels [ unit ] ;
2017-05-14 18:29:42 +00:00
} else {
throw new Error ( 'printToPDF Cannot handle parameter type: ' + ( typeof parameter ) ) ;
}
return pixels / 96 ;
2017-06-11 08:32:59 +00:00
}
2017-05-14 18:29:42 +00:00
2017-05-11 07:06:41 +00:00
Page . Events = {
2017-05-13 19:04:30 +00:00
ConsoleMessage : 'consolemessage' ,
2017-06-16 04:22:41 +00:00
Dialog : 'dialog' ,
2017-06-16 18:21:44 +00:00
Error : 'error' ,
2017-05-13 19:04:30 +00:00
ResourceLoadingFailed : 'resourceloadingfailed' ,
ResponseReceived : 'responsereceived' ,
2017-05-11 07:06:41 +00:00
} ;
module . exports = Page ;