【问题标题】:Puppeteer doesn't respect colors when exporting RMarkdown render to .pdf将 RMarkdown 渲染导出为 .pdf 时,Puppeteer 不尊重颜色
【发布时间】:2018-11-30 23:35:24
【问题描述】:

我正在使用puppeteer(无头 Chrome)将 RMarkdown 脚本生成的 .html 呈现为 .pdf。但是,puppeteer 似乎并不尊重我的colorbackground-color 样式设置。网页渲染时不存在这个问题,提示是puppeteerRMarkdown之间的交互。

考虑以下test.Rmd 脚本:

---
title: "Testing colors"
output: html_document
---

<style>
html {
  -webkit-print-color-adjust: exact;
}

h4 {color: blue;}
</style>

#### Blue heading
<div style="color:red">This text is red</div>
<div style="background-color:red">This text has red background</div>

我们可以通过在 R 中调用rmarkdown::render( "test.Rmd", output_file="test.html" ) 将其渲染为test.html。注意-webkit-print-color-adjust 设置; it is often recommended作为颜色相关问题的解决方案,但我发现对我的情况没有效果。

puppeteer tutorials之后,我整理了以下render.js

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.setViewport({width: 400, height: 200});
    await page.goto('file:///home/sokolov/test/puppeteer/test.html');
    await page.screenshot({path: 'test.png'});
    await page.pdf({path: 'test.pdf', printBackground: true});
    await browser.close();
})();

从命令行运行node render.js 会生成test.pngtest.pdf。前者看起来完全符合您的预期:

但是,.pdf 丢失了所有颜色规范:

如果我将 render.js 中的 url 替换为外部页面(例如,https://www.w3schools.com/css/css_background.asp),则该页面以 .png.pdf 格式正确呈现。指定 printBackground: true 是使其适用于此外部页面的关键,但它似乎对我的本地 test.html 没有影响。

对如何使颜色起作用有什么想法吗?

PS 为了简要解决我为什么不简单地在我的.Rmd 中使用output: pdf_document 的问题,我想指出我正在使用的真正的 RMarkdown 文档使用 @987654353 @布局,其中doesn't play nicely with knitr。我读过的大多数教程都建议使用无头浏览器将最终的.html 渲染为.png/.pdf。除了颜色样式丢失之外,该解决方案对我来说效果很好。

【问题讨论】:

    标签: r r-markdown knitr puppeteer


    【解决方案1】:

    最简单的解决方案

    为什么不尝试删除所有!important 标签?我们的目标是 rmarkdown:render 嵌入的 css。只需运行一些搜索和替换代码,puppeteer 就会正确地为由 test.html 制作的 pdf 着色。在安装了 vim 的 shell 中运行它:

    echo "%s/%21important// | w!" | vim -e test.html

    就是这样!下面我只是记录我第一次尝试解决这个问题,并解释为什么它可能不是最好的解决方案。其他人可能会觉得它很有用。

    我的第一次尝试

    在安装了 vim 的 shell 中运行:

    echo "%s/%40media%20print%7B.\{-}%7D// | w!" | vim -e test.html

    上述命令覆盖test.html,并部分删除了@media print{} 样式。虽然@media print{} 样式没有完全或干净地删除,但新的test.html 具有预期的效果。

    这就是我正在做的事情

    我们正在处理 url 编码的 css,所以当我真的想写这个时需要%s/%40media%20print%7B.\{-}%7D//

    %s/@media print{.\{-}}//

    目标是完全删除这样的语句:@media print {a: ""}。我没有正确处理嵌套括号,因此该脚本仅部分删除了像 @media print {.a{a: ""};b{}...} 这样的语句,而第一个右括号之后的所有内容都保持不变。那是一个错误。由于与.\{-} 的非贪婪匹配而不是与.* 的贪婪匹配,我删除的太少了,这可能会删除太多。

    这是我要删除的内容

    为了便于阅读,我在 test.html 中添加了 URL decoded 的实际 CSS。你可以看到我已经删除了不匹配的大括号。有可能实际上并没有删除有问题的 css,但是删除这些行足以破坏 css 以在检测到@media print 时禁用有问题的 css。无论如何,删除这 6 个匹配项即可解决问题。

    @media print{*,:after,:before{color:#000!important;text- 
    shadow:none!important;background:0 0!important;-webkit-box- 
    shadow:none!important;box-shadow:none!important}
    

    @media print{.visible-print{display:block!important}

    @media print{.visible-print-block{display:block!important}

    @media print{.visible-print-inline{display:inline!important}

    @media print{.visible-print-inline-block{display:inline-block!important}

    @media print{.hidden-print{display:none!important}

    【讨论】:

    • 像魅力一样工作。
    猜你喜欢
    • 1970-01-01
    • 2020-06-29
    • 1970-01-01
    • 2018-11-13
    • 2022-07-27
    • 2020-11-12
    • 1970-01-01
    • 1970-01-01
    • 2018-12-04
    相关资源
    最近更新 更多