【问题标题】:Pandoc version 2.7.3 fails to convert knitr .tex file to .docxPandoc 2.7.3 版无法将 knitr .tex 文件转换为 .docx
【发布时间】:2019-11-25 12:03:33
【问题描述】:

直到今天,我一直在将 knitr 与 Rstudio 中的 .Rnw 文件结合使用来生成 pdf 和 docx 文件,没有任何问题。 pdf 转换使用 Rstudio 本地运行,而对于 docx 转换,我只需通过将 .tex 文件提供给“编织”.Rnw 文件产生的 .tex 文件来调用 pandoc。到目前为止,我一直在使用 pandoc 版本 1.19.2.1 并且工作得很好。但是,在与同事分享我的一些代码以执行此操作后,我意识到在使用更新版本的 pandoc (2.7.3) 时该策略会失败。

到目前为止,我已经尝试更新 knitr 并理解错误,但没有取得多大成功。该问题似乎仅在需要生成的 .tex 文件的阴影区域时出现,通常是在设置 echo=TRUE 之后。

这是我的 Rnw 文件 (min_reproducible_example.Rnw)

\documentclass{article}
\usepackage{multirow}
\setlength\parindent{0pt}
\usepackage{geometry}
\usepackage{longtable}
\usepackage{float}
\usepackage{verbatim}
\usepackage{hyperref}
\geometry{left=1.5cm,right=1.5cm,top=1.5cm,bottom=1.5cm}

\title{Docx from tex file example}

\begin{document}

\maketitle

<<chunk1,echo=TRUE,message=FALSE>>=
library(survival) 

str(lung)
@

\end{document}

在 Rstudio 中点击“编译 PDF”后会生成文件:min_reproducible_example.pdf 和 min_reproducible_example.tex。

以防万一,.Rnw 文件 (min_reproducible_example.tex) 的 .tex 输出为

\documentclass{article}\usepackage[]{graphicx}\usepackage[]{color}
% maxwidth is the original width if it is less than linewidth
% otherwise use linewidth (to make sure the graphics do not exceed the margin)
\makeatletter
\def\maxwidth{ %
  \ifdim\Gin@nat@width>\linewidth
    \linewidth
  \else
    \Gin@nat@width
  \fi
}
\makeatother

\definecolor{fgcolor}{rgb}{0.345, 0.345, 0.345}
\newcommand{\hlnum}[1]{\textcolor[rgb]{0.686,0.059,0.569}{#1}}%
\newcommand{\hlstr}[1]{\textcolor[rgb]{0.192,0.494,0.8}{#1}}%
\newcommand{\hlcom}[1]{\textcolor[rgb]{0.678,0.584,0.686}{\textit{#1}}}%
\newcommand{\hlopt}[1]{\textcolor[rgb]{0,0,0}{#1}}%
\newcommand{\hlstd}[1]{\textcolor[rgb]{0.345,0.345,0.345}{#1}}%
\newcommand{\hlkwa}[1]{\textcolor[rgb]{0.161,0.373,0.58}{\textbf{#1}}}%
\newcommand{\hlkwb}[1]{\textcolor[rgb]{0.69,0.353,0.396}{#1}}%
\newcommand{\hlkwc}[1]{\textcolor[rgb]{0.333,0.667,0.333}{#1}}%
\newcommand{\hlkwd}[1]{\textcolor[rgb]{0.737,0.353,0.396}{\textbf{#1}}}%
\let\hlipl\hlkwb

\usepackage{framed}
\makeatletter
\newenvironment{kframe}{%
 \def\at@end@of@kframe{}%
 \ifinner\ifhmode%
  \def\at@end@of@kframe{\end{minipage}}%
  \begin{minipage}{\columnwidth}%
 \fi\fi%
 \def\FrameCommand##1{\hskip\@totalleftmargin \hskip-\fboxsep
 \colorbox{shadecolor}{##1}\hskip-\fboxsep
     % There is no \\@totalrightmargin, so:
     \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth}%
 \MakeFramed {\advance\hsize-\width
   \@totalleftmargin\z@ \linewidth\hsize
   \@setminipage}}%
 {\par\unskip\endMakeFramed%
 \at@end@of@kframe}
\makeatother

\definecolor{shadecolor}{rgb}{.97, .97, .97}
\definecolor{messagecolor}{rgb}{0, 0, 0}
\definecolor{warningcolor}{rgb}{1, 0, 1}
\definecolor{errorcolor}{rgb}{1, 0, 0}
\newenvironment{knitrout}{}{} % an empty environment to be redefined in TeX

\usepackage{alltt}
\usepackage{multirow}
\setlength\parindent{0pt}
\usepackage{geometry}
\usepackage{longtable}
\usepackage{float}
\usepackage{verbatim}
\usepackage{hyperref}
\geometry{left=1.5cm,right=1.5cm,top=1.5cm,bottom=1.5cm}

\title{Docx from tex file example}
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
\begin{document}

\maketitle

\begin{knitrout}
\definecolor{shadecolor}{rgb}{0.969, 0.969, 0.969}\color{fgcolor}\begin{kframe}
\begin{alltt}
\hlkwd{library}\hlstd{(survival)}
\end{alltt}
\end{kframe}
\end{knitrout}

\end{document}

接下来,我可以调用一个包装函数,在命令行中运行以下代码来生成 docx 文件:

path/to/pandoc/pandoc -o min_reproducible_example.docx min_reproducible_example.tex

我在 Windows 中工作,因此,我没有检查此问题是否仍然存在于其他操作系统中。

我认为有几行可以提供信息:

我相信这条线是罪魁祸首:

Error at "source" (line 68, column 67):
unexpected end of input
\definecolor{shadecolor}{rgb}{0.969, 0.969, 0.969}\color{fgcolor}\begin{kframe}

其中,我一直在挖掘“kframe”来自 knitr 在进行“编织”时创建的乳胶环境。此行从 pandoc 生成以下错误:

Warning message:
In shell(command) :
  '"C:/pandoc/pandoc" -o min_reproducible_example.docx min_reproducible_example.tex --default-image-extension=png' execution failed with error code 65

我不知道这个错误代码 65 是什么意思。我已经从 pandoc 的先前问题中看到了建议直接查看代码以了解错误的线程。如果需要,我可以这样做,但对我来说,以前的 pandoc 版本可以正常工作而新版本正在崩溃对我来说很奇怪。我决定在这里发布这个,想知道是否有人遇到过同样的问题。

【问题讨论】:

  • pandoc 的乳胶阅读器中很可能发生了一些变化.. 你能把它简化为一个最小的例子吗(是因为 \newenvironment{kframe} 吗?)并发布到 pandoc-discuss 或 github.com/jgm/pandoc/issues
  • 是的,我也是这么认为的,我已经在 pandoc-discuss 上发帖了,John MacFarlane 自己回答说这是 pandoc 的当前(新?)限制,因为 kframe 环境的定义使用 tex 原语。他还提到了这一点,我在这里引用“随着 pandoc 在阅读 LaTeX 方面变得更好,它开始在之前盲目跳过的事情上失败”。他还建议将环境重新定义为更简单的东西。但是,我不确定“更简单”的确切含义。

标签: r latex knitr pandoc rnw


【解决方案1】:

我将根据 pandoc-discuss 上的另一个对话发布一个可能的解决方案以供将来参考。

在与 John MacFarlane 反复讨论之后,他好心地建议我重新定义给 pandoc 带来麻烦的环境:kframe。他建议将其重新定义为:

\renewenvironment{kframe}{}{}

所以,我所做的是重新定义一个自定义 R 函数,该函数在内部调用 pandoc。我只包括下面的相关行。

  ## read the original .tex file (.Rnw output)
  tx  <- readLines(paste0(fname, '.tex'),warn=FALSE)
  ## rename the environment to something simpler as suggested by John MacFarlane in the pandoc-discuss thread
  tx2 <- gsub(pattern = "\\begin{document}", 
              replace = "\\renewenvironment{kframe}{}{}\\begin{document}", 
              x = tx, fixed = TRUE)
  ## create a file with the workaround for the kframe environment and use it in the pandoc call below 
  zz <- file(paste0(fname, '_cp.tex'), "wb")
  writeLines(tx2, con=zz)
  close(zz)

  command <- paste0('"',pdwd,'/pandoc" -o ', fname, '.docx ', fname, '_cp.tex ',
                    "--default-image-extension=png ")
  shell(command)
  # remove the file 
  file.remove(paste0(fname, '_cp.tex')) 

之后 pandoc 能够毫无怨言地执行。我注意到 pandoc 的早期版本(1.19.2.1)虽然执行没有错误,但输出的 docx 文件缺少 kframe 环境中的内容,而此修复程序可以更准确地表示 pdf。

我没有广泛尝试过这个修复,所以请留下 cmets 以防您发现任何问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-01
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多