github.com/MontFerret/ferret@v0.18.0/pkg/stdlib/html/pdf.go (about) 1 package html 2 3 import ( 4 "context" 5 "fmt" 6 "regexp" 7 8 "github.com/MontFerret/ferret/pkg/drivers" 9 "github.com/MontFerret/ferret/pkg/runtime/core" 10 "github.com/MontFerret/ferret/pkg/runtime/values" 11 "github.com/MontFerret/ferret/pkg/runtime/values/types" 12 ) 13 14 func ValidatePageRanges(pageRanges string) (bool, error) { 15 match, err := regexp.Match(`^(([1-9][0-9]*|[1-9][0-9]*)(\s*-\s*|\s*,\s*|))*$`, []byte(pageRanges)) 16 17 if err != nil { 18 return false, err 19 } 20 21 return match, nil 22 } 23 24 // PDF prints a PDF of the current page. 25 // @param {HTMLPage | String}target - Target page or url. 26 // @param {Object} [params] - An object containing the following properties: 27 // @param {Bool} [params.landscape=False] - Paper orientation. 28 // @param {Bool} [params.displayHeaderFooter=False] - Display header and footer. 29 // @param {Bool} [params.printBackground=False] - Print background graphics. 30 // @param {Float} [params.scale=1] - Scale of the webpage rendering. 31 // @param {Float} [params.paperWidth=22] - Paper width in inches. 32 // @param {Float} [params.paperHeight=28] - Paper height in inches. 33 // @param {Float} [params.marginTo=1] - Top margin in inches. 34 // @param {Float} [params.marginBottom=1] - Bottom margin in inches. 35 // @param {Float} [params.marginLeft=1] - Left margin in inches. 36 // @param {Float} [params.marginRight=1] - Right margin in inches. 37 // @param {String} [params.pageRanges] - Paper ranges to print, e.g., '1-5, 8, 11-13'. 38 // @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. 39 // @param {String} [params.footerTemplate] - HTML template for the print footer. Should use the same format as the `headerTemplate`. 40 // @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. * 41 // @return {Binary} - PDF document in binary format. 42 func PDF(ctx context.Context, args ...core.Value) (core.Value, error) { 43 err := core.ValidateArgs(args, 1, 2) 44 45 if err != nil { 46 return values.None, err 47 } 48 49 arg1 := args[0] 50 page, closeAfter, err := OpenOrCastPage(ctx, arg1) 51 52 if err != nil { 53 return values.None, err 54 } 55 56 defer func() { 57 if closeAfter { 58 page.Close() 59 } 60 }() 61 62 pdfParams := drivers.PDFParams{} 63 64 if len(args) == 2 { 65 arg2 := args[1] 66 err = core.ValidateType(arg2, types.Object) 67 68 if err != nil { 69 return values.None, err 70 } 71 72 params, ok := arg2.(*values.Object) 73 74 if !ok { 75 return values.None, core.Error(core.ErrInvalidType, "expected object") 76 } 77 78 landscape, found := params.Get("landscape") 79 80 if found { 81 err = core.ValidateType(landscape, types.Boolean) 82 83 if err != nil { 84 return values.None, err 85 } 86 87 pdfParams.Landscape = landscape.(values.Boolean) 88 } 89 90 displayHeaderFooter, found := params.Get("displayHeaderFooter") 91 92 if found { 93 err = core.ValidateType(displayHeaderFooter, types.Boolean) 94 95 if err != nil { 96 return values.None, err 97 } 98 99 pdfParams.DisplayHeaderFooter = displayHeaderFooter.(values.Boolean) 100 } 101 102 printBackground, found := params.Get("printBackground") 103 104 if found { 105 err = core.ValidateType(printBackground, types.Boolean) 106 107 if err != nil { 108 return values.None, err 109 } 110 111 pdfParams.PrintBackground = printBackground.(values.Boolean) 112 } 113 114 scale, found := params.Get("scale") 115 116 if found { 117 err = core.ValidateType(scale, types.Float, types.Int) 118 119 if err != nil { 120 return values.None, err 121 } 122 123 if scale.Type() == types.Int { 124 pdfParams.Scale = values.Float(scale.(values.Int)) 125 } else { 126 pdfParams.Scale = scale.(values.Float) 127 } 128 } 129 130 paperWidth, found := params.Get("paperWidth") 131 132 if found { 133 err = core.ValidateType(paperWidth, types.Float, types.Int) 134 135 if err != nil { 136 return values.None, err 137 } 138 139 if paperWidth.Type() == types.Int { 140 pdfParams.PaperWidth = values.Float(paperWidth.(values.Int)) 141 } else { 142 pdfParams.PaperWidth = paperWidth.(values.Float) 143 } 144 } 145 146 paperHeight, found := params.Get("paperHeight") 147 148 if found { 149 err = core.ValidateType(paperHeight, types.Float, types.Int) 150 151 if err != nil { 152 return values.None, err 153 } 154 155 if paperHeight.Type() == types.Int { 156 pdfParams.PaperHeight = values.Float(paperHeight.(values.Int)) 157 } else { 158 pdfParams.PaperHeight = paperHeight.(values.Float) 159 } 160 } 161 162 marginTop, found := params.Get("marginTop") 163 164 if found { 165 err = core.ValidateType(marginTop, types.Float, types.Int) 166 167 if err != nil { 168 return values.None, err 169 } 170 171 if marginTop.Type() == types.Int { 172 pdfParams.MarginTop = values.Float(marginTop.(values.Int)) 173 } else { 174 pdfParams.MarginTop = marginTop.(values.Float) 175 } 176 } 177 178 marginBottom, found := params.Get("marginBottom") 179 180 if found { 181 err = core.ValidateType(marginBottom, types.Float, types.Int) 182 183 if err != nil { 184 return values.None, err 185 } 186 187 if marginBottom.Type() == types.Int { 188 pdfParams.MarginBottom = values.Float(marginBottom.(values.Int)) 189 } else { 190 pdfParams.MarginBottom = marginBottom.(values.Float) 191 } 192 } 193 194 marginLeft, found := params.Get("marginLeft") 195 196 if found { 197 err = core.ValidateType(marginLeft, types.Float, types.Int) 198 199 if err != nil { 200 return values.None, err 201 } 202 203 if marginLeft.Type() == types.Int { 204 pdfParams.MarginLeft = values.Float(marginLeft.(values.Int)) 205 } else { 206 pdfParams.MarginLeft = marginLeft.(values.Float) 207 } 208 } 209 210 marginRight, found := params.Get("marginRight") 211 212 if found { 213 err = core.ValidateType(marginRight, types.Float, types.Int) 214 215 if err != nil { 216 return values.None, err 217 } 218 219 if marginRight.Type() == types.Int { 220 pdfParams.MarginRight = values.Float(marginRight.(values.Int)) 221 } else { 222 pdfParams.MarginRight = marginRight.(values.Float) 223 } 224 } 225 226 pageRanges, found := params.Get("pageRanges") 227 228 if found { 229 err = core.ValidateType(pageRanges, types.String) 230 231 if err != nil { 232 return values.None, err 233 } 234 235 validate, err := ValidatePageRanges(pageRanges.String()) 236 237 if err != nil { 238 return values.None, err 239 } 240 241 if !validate { 242 return values.None, core.Error(core.ErrInvalidArgument, fmt.Sprintf(`page ranges "%s", not valid`, pageRanges.String())) 243 } 244 245 pdfParams.PageRanges = pageRanges.(values.String) 246 } 247 248 headerTemplate, found := params.Get("headerTemplate") 249 250 if found { 251 err = core.ValidateType(headerTemplate, types.String) 252 253 if err != nil { 254 return values.None, err 255 } 256 257 pdfParams.HeaderTemplate = headerTemplate.(values.String) 258 } 259 260 footerTemplate, found := params.Get("footerTemplate") 261 262 if found { 263 err = core.ValidateType(footerTemplate, types.String) 264 265 if err != nil { 266 return values.None, err 267 } 268 269 pdfParams.FooterTemplate = footerTemplate.(values.String) 270 } 271 272 preferCSSPageSize, found := params.Get("preferCSSPageSize") 273 274 if found { 275 err = core.ValidateType(preferCSSPageSize, types.Boolean) 276 277 if err != nil { 278 return values.None, err 279 } 280 281 pdfParams.PreferCSSPageSize = preferCSSPageSize.(values.Boolean) 282 } 283 } 284 285 pdf, err := page.PrintToPDF(ctx, pdfParams) 286 287 if err != nil { 288 return values.None, err 289 } 290 291 return pdf, nil 292 }