![将最后修改日期放在由 markdown + hyperref + javascript + fancyhdr 生成的 PDF 表单上?](https://linux22.com/image/388526/%E5%B0%86%E6%9C%80%E5%90%8E%E4%BF%AE%E6%94%B9%E6%97%A5%E6%9C%9F%E6%94%BE%E5%9C%A8%E7%94%B1%20markdown%20%2B%20hyperref%20%2B%20javascript%20%2B%20fancyhdr%20%E7%94%9F%E6%88%90%E7%9A%84%20PDF%20%E8%A1%A8%E5%8D%95%E4%B8%8A%EF%BC%9F.png)
这是我的 pandoc 版本:
pandoc --version
pandoc 2.3.1
Compiled with pandoc-types 1.17.5.1, texmath 0.11.1.1, skylighting 0.7.3
Default user data directory: /Users/vle/.pandoc
Copyright (C) 2006-2018 John MacFarlane
Web: http://pandoc.org
This is free software; see the source for copying conditions.
There is no warranty, not even for merchantability or fitness
for a particular purpose.
以及测试markdown文档(testjs.md):
---
title: "Test Javascript"
geometry: "left=2.5cm,right=2cm,top=2cm,bottom=2cm"
output: pdf_document
header-includes:
- \usepackage{hyperref}
- \usepackage{fancyhdr}
- \pagestyle{fancy}
- \fancyhead[LE,LO]{Last Modified Date \TextField[name=opendate, calculate={var OpenDate = this.getField("opendate"); OpenDate.value = new Date();}]{}}
- \fancyfoot[CO,CE]{Template Version \today}
- \fancyfoot[LE,RO]{\thepage}
---
# Section
## Header :
*Try to set the current date when the PDF file is open*
\TextField[name=datefield,%
width = \hsize,%
height = 3cm,%
multiline=true,%
bordercolor= ,%
% color = 1 1 1,%
calculate={var d = this.getField("datefield"); d.value = new Date();}
]{}
\pagebreak
## Header :
*Try to set the current date when the PDF file is open*
\TextField[name=datefield1,%
width = \hsize,%
height = 3cm,%
multiline=true,%
bordercolor= ,%
% color = 1 1 1,%
calculate={var e = this.getField("datefield"); e.value = new Date();}
]{}
\pagebreak
## Header :
*Try to set the current date when the PDF file is open*
\TextField[name=datefield2,%
width = \hsize,%
height = 3cm,%
multiline=true,%
bordercolor= ,%
% color = 1 1 1,%
calculate={var f = this.getField("datefield"); f.value = new Date();}
]{}
渲染命令:
pandoc --number-section -o testjs.pdf testjs.md
在 macOS 上的 Acrobat Professional DC 中打开的输出 PDF 如下所示:
问题:
- “上次修改日期”标题字段的文本字段中未显示日期。
所有三个页面正文的文本字段中均未显示日期。
由于文本字段名称冲突,第 3 页上的文本字段“上次修改日期”未出现。
我该如何解决这些问题?
更新:
我想我找到了一些线索:一定有一些事件触发 javascript 来更新字段。因此,更实际的问题是如何在某些onsave
事件或onclick
某些表单按钮上更新标题。我更喜欢onsave
保存整个文档并更新时间戳。
答案1
我找不到独自完成此事的方法hyperref
。
使用存在两个问题hyperref
。
- 表单字段应该包含在一个
Form
环境中,而我在尝试从 JavaScript 设置字段内容时遇到了问题,因为没有这样做(就像在您的 MWE 中一样)。添加此环境会让 Adobe Reader 认为这是一个真正的 PDF 表单,这似乎有点奇怪。 hyperref
不提供对 Acrobatwillsave
文档事件的访问权限,而这是您情况下最自然的事件。
为了解决第一个问题,我建议使用pdfcomment
包并使用FreeText
注释而不是表单文本字段。
幸运的是,第二个问题很容易解决。
尝试一下这个 MWE。虽然很简单latex
,但你可以让它适应你的pandoc
MarkDown 工作流程。
它有什么作用?
- 将选项传递
en-US
给datetime2
(pdfcomment
似乎默认使用该iso
选项)。 - 设置
FreeText
注释标志使其只读(pdfcomment
硬编码它们以仅打开打印)。 - 编写在文档即将保存时运行的 JavaScript 代码。该代码获取文档中的所有注释并将内容设置为当前日期。(这并不那么聪明,并且假设唯一的注释是日期戳注释。如果有其他注释,您可以相当轻松地使其更聪明。)
- 用于
\pdfcatalog
设置文档willsave
事件来调用我们的代码。 FreeText
使用看起来漂亮的注释并将\pdfcomment
其初始化为\today
。- 设置标题。
它似乎可以很好地处理多页。
\documentclass{book}
\PassOptionsToPackage{en-US}{datetime2}
\usepackage{pdfcomment}
\makeatletter
% Set FreeText annotation flags to Print (bit 3) and ReadOnly (bit 7)
\patchcmd{\pc@annot@freetext}
{/F 4}
{/F 68}
{}
{}
\def\willsavecode{%
this.syncAnnotScan ();
var annots = this.getAnnots ();
for (var i = 0; i < annots.length; i++)
annots[i].contents = util.printd ("mmmm d, yyyy", new Date ());
}
\pdfcatalog{/AA<</WS<</S/JavaScript/JS(\Hy@escapestring{\willsavecode})>>>>}
\makeatother
\newcommand*{\datestamp}{%
\pdffreetextcomment[%
width=6cm,
height=\normalbaselineskip,
hoffset=1em,
voffset=-\dp\strutbox,
linewidth=0pt,
color=,
fontsize=10pt]{\today}}
\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyhead[LE,LO]{Last Modified Date: \datestamp}
\fancyfoot[CO,CE]{Template Version: \today}
\fancyfoot[LE,RO]{\thepage}
\begin{document}
Filler text.
\end{document}