如何将 css 样式表包含到 wicked pdf 中?

Tho*_*mas 6 ruby-on-rails wicked-pdf webpack

我被困在 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
Run Code Online (Sandbox Code Playgroud)

这是布局中的代码:

<!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>
Run Code Online (Sandbox Code Playgroud)

这是视图 pdf.erb 中的代码:

<h1 class="text-red-base">Test pdf</h1>
<h2 class="test-wicked">mldgmdjgfd</h2>
Run Code Online (Sandbox Code Playgroud)

它适用于 wicked_pdf_stylesheet_link_tag(test-wicked 从链轮应用:文本为蓝色)但不适用于 wicked_pdf_stylesheet_pack_tag(h1 应该是红色但不是)。

知道发生了什么吗?

谢谢!

art*_*rtm 7

分析

webpack 助手做出了一些假设,这些假设可能不适用于每个项目。

它们会根据running_in_develpment 的内容产生两种不同的结果返回。在 webpacker 3.0.0 或更新版本中,此方法委托给Webpacker.dev_server.running?.

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

在开发服务器运行时,webpack 助手将返回一个带有包资产路径的标签(最终使用标准asset_path助手)。实际路径取决于 rails 配置。在某些情况下,路径将与wkhtmltopdf从 a呈现的 html 不兼容file://...

  • 如果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 开发服务器的主机名/端口传递给 webpacker 标签助手(将它们传递给asset_path)。开发服务器在一个单独的进程中运行,因此即使应用程序在请求处理程序中也会响应。

  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
Run Code Online (Sandbox Code Playgroud)

在 pdf 布局中(超薄)

html
  head
    ...
    = pdf_stylesheet_pack_tag "pdf"
    = pdf_javascript_pack_tag "pdf"
    ...
Run Code Online (Sandbox Code Playgroud)