BookStackApp / BookStack

A platform to create documentation/wiki content built with PHP & Laravel
https://www.bookstackapp.com/
MIT License
15.43k stars 1.94k forks source link

EXPORT_PDF_COMMAND using weasyprint does not work as documented for versions < 53 #5301

Closed watschi closed 3 weeks ago

watschi commented 3 weeks ago

Describe the Bug

When configuring the EXPORT_PDF_COMMAND as documented at Admin Documentation > PDF Rendering, an error is thrown because weasyprint prints its help message due to a missing option or file extension.

Steps to Reproduce

  1. Configure EXPORT_PDF_COMMAND="weasyprint {input_html_path} {output_pdf_path}"
  2. Export a page to PDF
[2024-10-30 15:46:41] production.ERROR: PDF Export via command failed with exit code 2, stdout: , stderr: usage: weasyprint [-h] [--version] [-i] [-e ENCODING] [-f {pdf,png}]
                  [-s STYLESHEET] [-m MEDIA_TYPE] [-r RESOLUTION]
                  [-u BASE_URL] [-a ATTACHMENT] [-p] [-v] [-d] [-q]
                  input output
weasyprint: error: Either specify a format with -f or choose an output filename that ends in .pdf or .png
 {"userId":3,"exception":"[object] (BookStack\\Exceptions\\PdfExportException(code: 0): PDF Export via command failed with exit code 2, stdout: , stderr: usage: weasyprint [-h] [--version] [-i] [-e ENCODING] [-f {pdf,png}]
                  [-s STYLESHEET] [-m MEDIA_TYPE] [-r RESOLUTION]
                  [-u BASE_URL] [-a ATTACHMENT] [-p] [-v] [-d] [-q]
[-s STYLESHEET] [-m MEDIA_TYPE] [-r RESOLUTION]
                  [-u BASE_URL] [-a ATTACHMENT] [-p] [-v] [-d] [-q]
                  input output
weasyprint: error: Either specify a format with -f or choose an output filename that ends in .pdf or .png
 at /var/www/bookstack/app/Entities/Tools/PdfGenerator.php:100)
[stacktrace]
#0 /var/www/bookstack/app/Entities/Tools/PdfGenerator.php(24): BookStack\\Entities\\Tools\\PdfGenerator->renderUsingCommand()
#1 /var/www/bookstack/app/Entities/Tools/ExportFormatter.php(160): BookStack\\Entities\\Tools\\PdfGenerator->fromHtml()
#2 /var/www/bookstack/app/Entities/Tools/ExportFormatter.php(100): BookStack\\Entities\\Tools\\ExportFormatter->htmlToPdf()
#3 /var/www/bookstack/app/Entities/Controllers/PageExportController.php(32): BookStack\\Entities\\Tools\\ExportFormatter->pageToPdf()
#4 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): BookStack\\Entities\\Controllers\\PageExportController->pdf()
#5 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(43): Illuminate\\Routing\\Controller->callAction()
#6 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Route.php(259): Illuminate\\Routing\\ControllerDispatcher->dispatch()
#7 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Route.php(205): Illuminate\\Routing\\Route->runController()
#8 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Router.php(806): Illuminate\\Routing\\Route->run()
#9 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(144): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}()
#10 /var/www/bookstack/app/Http/Middleware/CheckUserHasPermission.php(25): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#11 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\CheckUserHasPermission->handle()
#12 /var/www/bookstack/app/Http/Middleware/Authenticate.php(23): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#13 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\Authenticate->handle()
#14 /var/www/bookstack/app/Http/Middleware/Localization.php(32): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#15 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\Localization->handle()
#16 /var/www/bookstack/app/Http/Middleware/RunThemeActions.php(26): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#17 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\RunThemeActions->handle()
#18 /var/www/bookstack/app/Http/Middleware/CheckEmailConfirmed.php(47): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#19 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\CheckEmailConfirmed->handle()
#20 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(78): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#21 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle()
#22 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#23 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle()
#24 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#25 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest()
#26 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Session\\Middleware\\StartSession->handle()
#27 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#28 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle()
#29 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#30 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()
#31 /var/www/bookstack/app/Http/Middleware/ApplyCspRules.php(33): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#32 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\ApplyCspRules->handle()
#33 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#34 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Router.php(805): Illuminate\\Pipeline\\Pipeline->then()
#35 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Router.php(784): Illuminate\\Routing\\Router->runRouteWithinStack()
#36 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Router.php(748): Illuminate\\Routing\\Router->runRoute()
#37 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Routing/Router.php(737): Illuminate\\Routing\\Router->dispatchToRoute()
#38 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(200): Illuminate\\Routing\\Router->dispatch()
#39 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(144): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()
#40 /var/www/bookstack/app/Http/Middleware/PreventResponseCaching.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#41 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\PreventResponseCaching->handle()
#42 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(39): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#43 /var/www/bookstack/app/Http/Middleware/TrustProxies.php(41): Illuminate\\Http\\Middleware\\TrustProxies->handle()
#44 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): BookStack\\Http\\Middleware\\TrustProxies->handle()
#45 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#46 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(40): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()
#47 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle()
#48 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#49 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle()
#50 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(99): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#51 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()
#52 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#53 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(175): Illuminate\\Pipeline\\Pipeline->then()
#54 /var/www/bookstack/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(144): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()
#55 /var/www/bookstack/public/index.php(52): Illuminate\\Foundation\\Http\\Kernel->handle()
#56 {main}
"}

Expected Behaviour

Export the page to pdf.

Screenshots or Additional Context

This issue can be resolved by adding the --format pdf argument to the weasyprint command (see https://codeberg.org/bookstack/website/pulls/190). Edit: Or by updating weasyprint to a current version. Opening this issue so others affected can find it.

Also @ssddanbrown: Does it make sense to add a pdf extension to the export filename here (PdfGenerator.php)? I know other tools like pandoc also use file extensions to determine the output format if not explicitly mentioned, maybe this will save some people some time.

weasyprint version:

# weasyprint --version
WeasyPrint version 51

Browser Details

No response

Exact BookStack Version

v24.10

watschi commented 3 weeks ago

Did some more research, the --format option has been deprecated as of weasyprint version 53 (2021). Ubuntu 20.04, which will reach End of Standard Support next April, ships version 51. Probably not worth it to implement any changes based on it.