2018-10-08 01:02:27 +02:00
package html
import (
"context"
2018-10-08 03:32:30 +02:00
"fmt"
2018-10-14 00:12:46 +02:00
"regexp"
2019-02-20 01:10:18 +02:00
"github.com/MontFerret/ferret/pkg/drivers"
2018-10-08 01:02:27 +02:00
"github.com/MontFerret/ferret/pkg/runtime/core"
2018-12-22 06:14:41 +02:00
"github.com/MontFerret/ferret/pkg/runtime/values"
2019-02-13 19:31:18 +02: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-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return false , err
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
return match , nil
}
2018-10-14 19:06:27 +02:00
// PDF print a PDF of the current page.
2019-06-19 23:58:56 +02:00
// @param target (HTMLPage|String) - Target page or url.
2018-10-14 19:06:27 +02:00
// @param params (Object) - Optional, An object containing the following properties :
// Landscape (Bool) - Paper orientation. Defaults to false.
// DisplayHeaderFooter (Bool) - Display header and footer. Defaults to false.
// PrintBackground (Bool) - Print background graphics. Defaults to false.
// Scale (Float64) - Scale of the webpage rendering. Defaults to 1.
// PaperWidth (Float64) - Paper width in inches. Defaults to 8.5 inches.
// PaperHeight (Float64) - Paper height in inches. Defaults to 11 inches.
// MarginTop (Float64) - Top margin in inches. Defaults to 1cm (~0.4 inches).
// MarginBottom (Float64) - Bottom margin in inches. Defaults to 1cm (~0.4 inches).
// MarginLeft (Float64) - Left margin in inches. Defaults to 1cm (~0.4 inches).
// MarginRight (Float64) - Right margin in inches. Defaults to 1cm (~0.4 inches).
// PageRanges (String) - Paper ranges to print, e.g., '1-5, 8, 11-13'. Defaults to the empty string, which means print all pages.
// IgnoreInvalidPageRanges (Bool) - to silently ignore invalid but successfully parsed page ranges, such as '3-2'. Defaults to false.
// HeaderTemplate (String) - 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.
// FooterTemplate (String) - HTML template for the print footer. Should use the same format as the `headerTemplate`.
// PreferCSSPageSize (Bool) - 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. *
// @returns data (Binary) - Returns a base64 encoded string 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-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
arg1 := args [ 0 ]
2019-06-19 23:58:56 +02:00
page , closeAfter , err := OpenOrCastPage ( ctx , arg1 )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
2019-06-19 23:58:56 +02:00
defer func ( ) {
if closeAfter {
page . Close ( )
}
} ( )
2018-10-14 00:12:46 +02:00
2019-02-20 01:10:18 +02:00
pdfParams := drivers . PDFParams { }
2018-10-14 00:12:46 +02:00
if len ( args ) == 2 {
arg2 := args [ 1 ]
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( arg2 , types . Object )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
params , ok := arg2 . ( * values . Object )
2018-12-22 06:14:41 +02: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-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( landscape , types . Boolean )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
pdfParams . Landscape = landscape . ( values . Boolean )
2018-10-14 00:12:46 +02:00
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
displayHeaderFooter , found := params . Get ( "displayHeaderFooter" )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( displayHeaderFooter , types . Boolean )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
pdfParams . DisplayHeaderFooter = displayHeaderFooter . ( values . Boolean )
2018-10-14 00:12:46 +02:00
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
printBackground , found := params . Get ( "printBackground" )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( printBackground , types . Boolean )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
pdfParams . PrintBackground = printBackground . ( values . Boolean )
2018-10-14 00:12:46 +02:00
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
scale , found := params . Get ( "scale" )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( scale , types . Float , types . Int )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
2019-02-13 19:31:18 +02:00
if scale . Type ( ) == types . Int {
2018-12-22 06:14:41 +02:00
pdfParams . Scale = values . Float ( scale . ( values . Int ) )
} else {
pdfParams . Scale = scale . ( values . Float )
2018-10-14 00:12:46 +02:00
}
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
paperWidth , found := params . Get ( "paperWidth" )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( paperWidth , types . Float , types . Int )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
2019-02-13 19:31:18 +02:00
if paperWidth . Type ( ) == types . Int {
2018-12-22 06:14:41 +02:00
pdfParams . PaperWidth = values . Float ( paperWidth . ( values . Int ) )
} else {
pdfParams . PaperWidth = paperWidth . ( values . Float )
2018-10-14 00:12:46 +02:00
}
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
paperHeight , found := params . Get ( "paperHeight" )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( paperHeight , types . Float , types . Int )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
2019-02-13 19:31:18 +02:00
if paperHeight . Type ( ) == types . Int {
2018-12-22 06:14:41 +02:00
pdfParams . PaperHeight = values . Float ( paperHeight . ( values . Int ) )
} else {
pdfParams . PaperHeight = paperHeight . ( values . Float )
2018-10-14 00:12:46 +02:00
}
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
marginTop , found := params . Get ( "marginTop" )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( marginTop , types . Float , types . Int )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
2019-02-13 19:31:18 +02:00
if marginTop . Type ( ) == types . Int {
2018-12-22 06:14:41 +02:00
pdfParams . MarginTop = values . Float ( marginTop . ( values . Int ) )
} else {
pdfParams . MarginTop = marginTop . ( values . Float )
2018-10-14 00:12:46 +02:00
}
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
marginBottom , found := params . Get ( "marginBottom" )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( marginBottom , types . Float , types . Int )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
2019-02-13 19:31:18 +02:00
if marginBottom . Type ( ) == types . Int {
2018-12-22 06:14:41 +02:00
pdfParams . MarginBottom = values . Float ( marginBottom . ( values . Int ) )
} else {
pdfParams . MarginBottom = marginBottom . ( values . Float )
2018-10-14 00:12:46 +02:00
}
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
marginLeft , found := params . Get ( "marginLeft" )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( marginLeft , types . Float , types . Int )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
2019-02-13 19:31:18 +02:00
if marginLeft . Type ( ) == types . Int {
2018-12-22 06:14:41 +02:00
pdfParams . MarginLeft = values . Float ( marginLeft . ( values . Int ) )
} else {
pdfParams . MarginLeft = marginLeft . ( values . Float )
2018-10-14 00:12:46 +02:00
}
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
marginRight , found := params . Get ( "marginRight" )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( marginRight , types . Float , types . Int )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
2019-02-13 19:31:18 +02:00
if marginRight . Type ( ) == types . Int {
2018-12-22 06:14:41 +02:00
pdfParams . MarginRight = values . Float ( marginRight . ( values . Int ) )
} else {
pdfParams . MarginRight = marginRight . ( values . Float )
2018-10-14 00:12:46 +02:00
}
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
pageRanges , found := params . Get ( "pageRanges" )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( pageRanges , types . String )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
validate , err := ValidatePageRanges ( pageRanges . String ( ) )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02: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-22 06:14:41 +02:00
pdfParams . PageRanges = pageRanges . ( values . String )
2018-10-14 00:12:46 +02:00
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
ignoreInvalidPageRanges , found := params . Get ( "ignoreInvalidPageRanges" )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( ignoreInvalidPageRanges , types . Boolean )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
pdfParams . IgnoreInvalidPageRanges = ignoreInvalidPageRanges . ( values . Boolean )
2018-10-14 00:12:46 +02:00
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
headerTemplate , found := params . Get ( "headerTemplate" )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( headerTemplate , types . String )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
pdfParams . HeaderTemplate = headerTemplate . ( values . String )
2018-10-14 00:12:46 +02:00
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
footerTemplate , found := params . Get ( "footerTemplate" )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( footerTemplate , types . String )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
pdfParams . FooterTemplate = footerTemplate . ( values . String )
2018-10-14 00:12:46 +02:00
}
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
preferCSSPageSize , found := params . Get ( "preferCSSPageSize" )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if found {
2019-02-13 19:31:18 +02:00
err = core . ValidateType ( preferCSSPageSize , types . Boolean )
2018-12-22 06:14:41 +02:00
2018-10-14 00:12:46 +02:00
if err != nil {
return values . None , err
}
2018-12-22 06:14:41 +02:00
pdfParams . PreferCSSPageSize = preferCSSPageSize . ( values . Boolean )
2018-10-14 00:12:46 +02:00
}
}
2019-06-19 23:58:56 +02: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-22 06:14:41 +02:00
return pdf , nil
2018-10-17 14:19:44 +02:00
}