如何将 css 样式表包含在邪恶的 pdf 中?



我被困在宝石wicked_pdf上。

  • 我正在生成一个pdf报告,我想包括样式表。
  • 样式表是通过带有顺风的webpack生成的。

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>

以下是视图pdf.erb中的代码:

<h1 class="text-red-base">Test pdf</h1>
<h2 class="test-wicked">mldgmdjgfd</h2>

它适用于wicked_pdf_stylesheet_link_tag(从链轮应用测试邪恶:文本为蓝色)但不适用于wicked_pdf_stylesheet_pack_tag(h1 应该是红色但不是)。

知道发生了什么吗?

谢谢!

分析

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

它们产生两种不同的结果,具体取决于running_in_develpment回报。对于 webpacker 3.0.0 或更高版本,此方法委托给Webpacker.dev_server.running?

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

在运行开发服务器的情况下,webpack 帮助程序将返回一个标记,其中包含包资产的资产路径(最终使用标准asset_path助手)。实际路径取决于导轨配置。在某些情况下,路径将与wkhtmltopdffile://...呈现的html不兼容:

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

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

其他限制

在我们的例子中,我们有一些额外的约束:

  • 我们的 PDF 发射动作支持一个参数,使它们show_as_html: true传递给render。这使得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

在 pdf 布局中(苗条)

html
head
...
= pdf_stylesheet_pack_tag "pdf"
= pdf_javascript_pack_tag "pdf"
...

最新更新