2018-10-08 01:02:27 +02:00
package html
import (
"context"
2018-10-07 21:32:30 -04:00
"fmt"
2018-10-14 00:12:46 +02:00
"regexp"
2019-02-19 18:10:18 -05:00
"github.com/MontFerret/ferret/pkg/drivers"
2018-10-08 01:02:27 +02:00
"github.com/MontFerret/ferret/pkg/runtime/core"
2018-12-21 23:14:41 -05:00
"github.com/MontFerret/ferret/pkg/runtime/values"
2019-02-13 12:31:18 -05:00
"github.com/MontFerret/ferret/pkg/runtime/values/types"
2018-10-08 01:02:27 +02:00
)
2018-10-14 00:12:46 +02:00
func ValidatePageRanges ( pageRanges string ) ( bool , error ) {
match , err := regexp . Match ( ` ^(([1-9][0-9]*|[1-9][0-9]*)(\s*-\s*|\s*,\s*|))*$ ` , [ ] byte ( pageRanges ) )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return false , err
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
return match , nil
}
2019-09-07 14:03:17 -04:00
// PDF prints a PDF of the current page.
2020-08-07 21:49:29 -04:00
// @param {HTMLPage | String}target - Target page or url.
// @param {Object} [params] - An object containing the following properties:
// @param {Bool} [params.landscape=False] - Paper orientation.
// @param {Bool} [params.displayHeaderFooter=False] - Display header and footer.
// @param {Bool} [params.printBackground=False] - Print background graphics.
// @param {Float} [params.scale=1] - Scale of the webpage rendering.
// @param {Float} [params.paperWidth=22] - Paper width in inches.
// @param {Float} [params.paperHeight=28] - Paper height in inches.
// @param {Float} [params.marginTo=1] - Top margin in inches.
// @param {Float} [params.marginBottom=1] - Bottom margin in inches.
// @param {Float} [params.marginLeft=1] - Left margin in inches.
// @param {Float} [params.marginRight=1] - Right margin in inches.
// @param {String} [params.pageRanges] - Paper ranges to print, e.g., '1-5, 8, 11-13'.
// @param {Bool} [params.ignoreInvalidPageRanges=False] - to silently ignore invalid but successfully parsed page ranges, such as '3-2'.
// @param {String} [params.headerTemplate] - HTML template for the print header. Should be valid HTML markup with following classes used to inject printing values into them: - `date`: formatted print date - `title`: document title - `url`: document location - `pageNumber`: current page number - `totalPages`: total pages in the document For example, `<span class=title></span>` would generate span containing the title.
// @param {String} [params.footerTemplate] - HTML template for the print footer. Should use the same format as the `headerTemplate`.
// @param {Bool} [params.preferCSSPageSize=False] - Whether or not to prefer page size as defined by css. Defaults to false, in which case the content will be scaled to fit the paper size. *
// @return {Binary} - PDF document in binary format.
2018-10-14 00:12:46 +02:00
func PDF ( ctx context . Context , args ... core . Value ) ( core . Value , error ) {
err := core . ValidateArgs ( args , 1 , 2 )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
arg1 := args [ 0 ]
2019-06-19 17:58:56 -04:00
page , closeAfter , err := OpenOrCastPage ( ctx , arg1 )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
2019-06-19 17:58:56 -04:00
defer func ( ) {
if closeAfter {
page . Close ( )
}
} ( )
2018-10-14 00:12:46 +02:00
2019-02-19 18:10:18 -05:00
pdfParams := drivers . PDFParams { }
2018-10-14 00:12:46 +02:00
if len ( args ) == 2 {
arg2 := args [ 1 ]
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( arg2 , types . Object )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
params , ok := arg2 . ( * values . Object )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if ! ok {
return values . None , core . Error ( core . ErrInvalidType , "expected object" )
}
landscape , found := params . Get ( "landscape" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( landscape , types . Boolean )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
pdfParams . Landscape = landscape . ( values . Boolean )
2018-10-14 00:12:46 +02:00
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
displayHeaderFooter , found := params . Get ( "displayHeaderFooter" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( displayHeaderFooter , types . Boolean )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
pdfParams . DisplayHeaderFooter = displayHeaderFooter . ( values . Boolean )
2018-10-14 00:12:46 +02:00
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
printBackground , found := params . Get ( "printBackground" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( printBackground , types . Boolean )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
pdfParams . PrintBackground = printBackground . ( values . Boolean )
2018-10-14 00:12:46 +02:00
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
scale , found := params . Get ( "scale" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( scale , types . Float , types . Int )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
2019-02-13 12:31:18 -05:00
if scale . Type ( ) == types . Int {
2018-12-21 23:14:41 -05:00
pdfParams . Scale = values . Float ( scale . ( values . Int ) )
} else {
pdfParams . Scale = scale . ( values . Float )
2018-10-14 00:12:46 +02:00
}
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
paperWidth , found := params . Get ( "paperWidth" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( paperWidth , types . Float , types . Int )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
2019-02-13 12:31:18 -05:00
if paperWidth . Type ( ) == types . Int {
2018-12-21 23:14:41 -05:00
pdfParams . PaperWidth = values . Float ( paperWidth . ( values . Int ) )
} else {
pdfParams . PaperWidth = paperWidth . ( values . Float )
2018-10-14 00:12:46 +02:00
}
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
paperHeight , found := params . Get ( "paperHeight" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( paperHeight , types . Float , types . Int )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
2019-02-13 12:31:18 -05:00
if paperHeight . Type ( ) == types . Int {
2018-12-21 23:14:41 -05:00
pdfParams . PaperHeight = values . Float ( paperHeight . ( values . Int ) )
} else {
pdfParams . PaperHeight = paperHeight . ( values . Float )
2018-10-14 00:12:46 +02:00
}
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
marginTop , found := params . Get ( "marginTop" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( marginTop , types . Float , types . Int )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
2019-02-13 12:31:18 -05:00
if marginTop . Type ( ) == types . Int {
2018-12-21 23:14:41 -05:00
pdfParams . MarginTop = values . Float ( marginTop . ( values . Int ) )
} else {
pdfParams . MarginTop = marginTop . ( values . Float )
2018-10-14 00:12:46 +02:00
}
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
marginBottom , found := params . Get ( "marginBottom" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( marginBottom , types . Float , types . Int )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
2019-02-13 12:31:18 -05:00
if marginBottom . Type ( ) == types . Int {
2018-12-21 23:14:41 -05:00
pdfParams . MarginBottom = values . Float ( marginBottom . ( values . Int ) )
} else {
pdfParams . MarginBottom = marginBottom . ( values . Float )
2018-10-14 00:12:46 +02:00
}
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
marginLeft , found := params . Get ( "marginLeft" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( marginLeft , types . Float , types . Int )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
2019-02-13 12:31:18 -05:00
if marginLeft . Type ( ) == types . Int {
2018-12-21 23:14:41 -05:00
pdfParams . MarginLeft = values . Float ( marginLeft . ( values . Int ) )
} else {
pdfParams . MarginLeft = marginLeft . ( values . Float )
2018-10-14 00:12:46 +02:00
}
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
marginRight , found := params . Get ( "marginRight" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( marginRight , types . Float , types . Int )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
2019-02-13 12:31:18 -05:00
if marginRight . Type ( ) == types . Int {
2018-12-21 23:14:41 -05:00
pdfParams . MarginRight = values . Float ( marginRight . ( values . Int ) )
} else {
pdfParams . MarginRight = marginRight . ( values . Float )
2018-10-14 00:12:46 +02:00
}
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
pageRanges , found := params . Get ( "pageRanges" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( pageRanges , types . String )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
validate , err := ValidatePageRanges ( pageRanges . String ( ) )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if ! validate {
return values . None , core . Error ( core . ErrInvalidArgument , fmt . Sprintf ( ` page ranges "%s", not valid ` , pageRanges . String ( ) ) )
}
2018-12-21 23:14:41 -05:00
pdfParams . PageRanges = pageRanges . ( values . String )
2018-10-14 00:12:46 +02:00
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
ignoreInvalidPageRanges , found := params . Get ( "ignoreInvalidPageRanges" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( ignoreInvalidPageRanges , types . Boolean )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
pdfParams . IgnoreInvalidPageRanges = ignoreInvalidPageRanges . ( values . Boolean )
2018-10-14 00:12:46 +02:00
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
headerTemplate , found := params . Get ( "headerTemplate" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( headerTemplate , types . String )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
pdfParams . HeaderTemplate = headerTemplate . ( values . String )
2018-10-14 00:12:46 +02:00
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
footerTemplate , found := params . Get ( "footerTemplate" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( footerTemplate , types . String )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
pdfParams . FooterTemplate = footerTemplate . ( values . String )
2018-10-14 00:12:46 +02:00
}
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
preferCSSPageSize , found := params . Get ( "preferCSSPageSize" )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 12:31:18 -05:00
err = core . ValidateType ( preferCSSPageSize , types . Boolean )
2018-12-21 23:14:41 -05:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
pdfParams . PreferCSSPageSize = preferCSSPageSize . ( values . Boolean )
2018-10-14 00:12:46 +02:00
}
}
2019-06-19 17:58:56 -04:00
pdf , err := page . PrintToPDF ( ctx , pdfParams )
2018-10-14 00:12:46 +02:00
2018-10-17 14:19:44 +02:00
if err != nil {
return values . None , err
}
2018-12-21 23:14:41 -05:00
return pdf , nil
2018-10-17 14:19:44 +02:00
}