如何将CSS样式表包含到Wicked PDF中?

6

我卡在了gem wicked_pdf上。

  • 我正在生成一个PDF报告,希望包含样式表。
  • 样式表是通过webpack和tailwindcss生成的。

wicked_pdf文档中提到可以使用wicked_pdf_stylesheet_pack_tagwicked_pdf_javascript_pack_tag从webpack中包含样式表和javascript,但是没有任何效果。

下面是控制器中的代码:

      format.pdf do
        render template: "pdf_reports/show", 
        layout: "wicked_layout",
        pdf: "report"
      end

以下是布局中的代码:

<!DOCTYPE html>
    <html>
        <head>
           <%= csrf_meta_tags %>
           <%= wicked_pdf_javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
           <%= wicked_pdf_stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
           <%= wicked_pdf_stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
      </head>
      <body>
        <%= yield %>
      </body>
</html>

这里是从view pdf.erb获取的代码:
<h1 class="text-red-base">Test pdf</h1>
<h2 class="test-wicked">mldgmdjgfd</h2>

它可以使用wicked_pdf_stylesheet_link_tag(从sprockets应用test-wicked:文本为蓝色),但不能使用wicked_pdf_stylesheet_pack_tag(h1应该为红色但不是)。

有什么想法吗?

谢谢!


尝试在 JavaScript 之前引入样式表。 - Rajdeep Singh
很不幸,它也不起作用... - Thomas
此问题也被发布在 https://github.com/mileszs/wicked_pdf/issues/860 上。 - Unixmonkey
1个回答

9

分析

Webpack帮助程序做出了一些可能在每个项目中都不成立的假设。

它们根据running_in_develpment?返回的结果产生两个不同的结果。对于webpacker 3.0.0或更高版本,此方法将委托给Webpacker.dev_server.running?

如果没有运行开发服务器,则帮助程序将假定资产已经预编译,并尝试将资产内容粘贴到<style><script>标记中。如果资产在生产中预编译在应用程序运行的环境的文件系统中可用,则应该可以正常工作。这通常是正确的。

如果运行了开发服务器,则webpack帮助程序将返回一个带有打包资产路径的标记(最终使用标准的asset_path辅助函数)。实际路径取决于Rails配置。在某些情况下,该路径与通过file:// ...wkhtmltopdf呈现的HTML不兼容:

  • 如果未设置config.action_controller.asset_host,则asset_path将生成相对路径。这些在从文件呈现的wkhtmltopdf中不起作用。

  • 如果设置了config.action_controller.asset_host,整个应用程序将使用绝对URL(这是一个通用设置,控制asset_path返回的内容)。现在,如果在可以解析和访问资产主机的环境中运行,则wkhtmltopdf可能能够获取这些资产。在容器化的应用程序中可能不成立。

额外的限制

在我们的情况下,我们有一些额外的限制:

  • 我们的PDF发出操作支持传递show_as_html: truerender的参数。这使得wicked_pdf跳过PDF生成并返回中间HTML。我们在浏览器中使用它来调试HTML视图。此HTML将由开发人员的浏览器在与wkhtmltopdf运行的不同环境中呈现。

  • 我们的开发设置是单线程的,因为我们使用依赖于所有请求由同一应用程序实例服务的better_errors调试器。另一方面,我们在请求中呈现PDF。这意味着wkhtmltopdf无法从应用程序请求资产(例如通过将host:"localhost:3000"传递给asset_path),因为它已经占用了唯一可用的线程。

示例解决方案

我们的解决方案是实现自己的辅助程序,这些程序更加了解我们的设置。
  1. 在生产环境中,默认行为与我们的设置兼容,因此我们委托给原始程序,在文件系统中查找资产并将其包含在生成的HTML中。

  2. 在开发过程中,生成PDF时,我们将webpack dev服务器的主机名/端口传递给webpacker标签助手(它们将将其传递给asset_path)。Dev服务器在单独的进程中运行,因此即使应用程序位于请求处理程序中,它也会响应。

  3. 在开发过程中,当返回中间HTML(由我们的自定义助手show_as_html?确定)时,不要将host:传递给asset_pack_url,这将导致“正常”的资产路径,就像在应用程序的其余部分中一样,可以在浏览器中使用。

module PdfHelper
  def pdf_stylesheet_pack_tag(source)
    if running_in_development?
      options = { media: "all" }
      wds = Webpacker.dev_server
      options[:host] = "#{wds.host}:#{wds.port}" unless show_as_html?
      stylesheet_pack_tag(source, options)
    else
      wicked_pdf_stylesheet_pack_tag(source)
    end
  end

  def pdf_javascript_pack_tag(source)
    if running_in_development?
      options = {}
      wds = Webpacker.dev_server
      options[:host] = "#{wds.host}:#{wds.port}" unless show_as_html?
      javascript_pack_tag(source, options)
    else
      wicked_pdf_javascript_pack_tag(source)
    end
  end
end

在 PDF 布局(精简版)中。
html
  head
    ...
    = pdf_stylesheet_pack_tag "pdf"
    = pdf_javascript_pack_tag "pdf"
    ...

1
你的解决方案对我来说完美无缺,除了“show_as_html?”函数需要在helper的上下文中定义之外。我暂时的解决方法是直接在原地定义它:“def show_as_html?; params[:debug].present?; end”。我的render调用中的show_as_html选项也基于params[:debug]。 - basiszwo
1
工作得很好,只是我需要在样式表/JavaScript打包标记调用中使用扩展运算符_options_而不仅仅是_options_。 - Artur79

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接