我最近发现了一个pdfcomment
可以注释我的 latex 生成的 PDF 文件的包。下面是我一直在做的一个最小工作示例:
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[rgb]{xcolor}
\usepackage{pdfcomment}
\begin{document}
A comment appears here: \pdfcomment[icon=Insert,color=red,author={author1}]{comment1_text}
\end{document}
现在出现了以下问题:我想包含其他人的评论并提供答案,该答案出现在同一个图标下。就像我在 Adobe Acrobat 中可以做的一样:我可以添加注释,写一些文字,然后点击回复按钮来输入答案。我想在 latex 中实现同样的功能。类似于(伪代码)
\begin{document}
A comment appears here:
\pdfcomment[icon=Insert,color=red,author={author1}]{comment1_text}[author={author2}]{reply_author2}
\end{document}
现在,reply_author2
在同一个注释下出现回复。这可能吗?
提供一些额外的输入。当我使用以下命令生成一个非常简单的 PDF 时:
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\begin{document}
This is a test document to show annotation in LaTeX vs Adobe Acrobat. The goal is to have the same sort of reply ability as is in Adobe which is very important for collaboration on LaTeX generated documents with people who do not use LaTeX.
\end{document}
然后我可以在 Adobe sw 中打开 PDF 并添加注释(插入文本类型)。然后我使用此python
代码:
from PyPDF2 import PdfFileReader
reader = PdfFileReader("test-ad.pdf")
for page in reader.pages:
try :
for annot in page["/Annots"] :
print (annot.getObject()) # (1)
print ("")
except :
# there are no annotations on this page
pass
直接从 PDF 中提取注释,我得到:
{'/AP': {'/N': IndirectObject(10, 0, 139968916562832)}, '/C': [0, 0, 1], '/Contents': 'insert some text', '/CreationDate': "D:20230828101145-04'00'", '/F': 4, '/M': "D:20230828101153-04'00'", '/NM': '436dc8e6-1207-4d79-91be-a5432a1ce7b9', '/P': IndirectObject(9, 0, 139968916562832), '/Popup': IndirectObject(18, 0, 139968916562832), '/RC': '<?xml version="1.0"?><body xmlns="http://www.w3.org/1999/xhtml" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/" xfa:APIVersion="Acrobat:22.1.0" xfa:spec="2.0.2" ><p dir="ltr"><span dir="ltr" style="font-size:9.9pt;text-align:left;color:#000000;font-weight:normal;font-style:normal">insert some text</span></p></body>', '/RD': [0.781097, 0.781067, 0.781097, 0.781128], '/Rect': [253.424, 703.434, 264.928, 712.807], '/Subj': 'Inserted Text', '/Subtype': '/Caret', '/T': 'me', '/Type': '/Annot'}
{'/F': 28, '/Open': False, '/Parent': IndirectObject(17, 0, 139968916562832), '/Rect': [595.276, 598.026, 799.276, 712.026], '/Subtype': '/Popup', '/Type': '/Annot'}
当我再次打开文件并添加对该注释的回复并再次使用提取注释时python
,我得到:
{'/AP': {'/N': IndirectObject(10, 0, 139968905121360)}, '/C': [0, 0, 1], '/Contents': 'insert some text', '/CreationDate': "D:20230828101145-04'00'", '/F': 4, '/M': "D:20230828101153-04'00'", '/NM': '436dc8e6-1207-4d79-91be-a5432a1ce7b9', '/P': IndirectObject(9, 0, 139968905121360), '/Popup': IndirectObject(18, 0, 139968905121360), '/RC': '<?xml version="1.0"?><body xmlns="http://www.w3.org/1999/xhtml" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/" xfa:APIVersion="Acrobat:22.1.0" xfa:spec="2.0.2" ><p dir="ltr"><span dir="ltr" style="font-size:9.9pt;text-align:left;color:#000000;font-weight:normal;font-style:normal">insert some text</span></p></body>', '/RD': [0.781097, 0.781067, 0.781097, 0.781128], '/Rect': [253.424, 703.434, 264.928, 712.807], '/Subj': 'Inserted Text', '/Subtype': '/Caret', '/T': 'me', '/Type': '/Annot'}
{'/F': 28, '/Open': False, '/Parent': IndirectObject(17, 0, 139968905121360), '/Rect': [595.276, 598.026, 799.276, 712.026], '/Subtype': '/Popup', '/Type': '/Annot'}
{'/AP': {'/N': IndirectObject(28, 0, 139968905121360), '/R': IndirectObject(29, 0, 139968905121360)}, '/C': [1, 0.819611, 0], '/Contents': 'reply to the comment', '/CreationDate': "D:20230828101251-04'00'", '/F': 28, '/IRT': IndirectObject(17, 0, 139968905121360), '/M': "D:20230828101251-04'00'", '/NM': 'dfc46577-b2cb-4666-a159-31fc4cbef078', '/Name': '/Comment', '/P': IndirectObject(9, 0, 139968905121360), '/Popup': IndirectObject(27, 0, 139968905121360), '/RC': '<?xml version="1.0"?><body xmlns="http://www.w3.org/1999/xhtml" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/" xfa:APIVersion="Acrobat:22.1.0" xfa:spec="2.0.2" ><p dir="ltr"><span dir="ltr" style="font-size:9.8pt;text-align:left;font-weight:normal;font-style:normal">reply to the comment</span></p></body>', '/Rect': [253.424, 688.807, 277.424, 712.807], '/Subj': 'Sticky Note', '/Subtype': '/Text', '/T': 'me', '/Type': '/Annot'}
{'/F': 28, '/Open': False, '/Parent': IndirectObject(26, 0, 139968905121360), '/Rect': [595.276, 598.807, 799.276, 712.807], '/Subtype': '/Popup', '/Type': '/Annot'}
我注意到的一件事是,原始注释带有标签/C
,但注释中还带有/R
。我不知道这是否就是所需的全部内容,或者还有其他详细信息。我想人们需要了解 PDF 规范。
答案1
虽然下面的原始答案可能对某些用户有用,但 OP 表示一直希望将所有对话包含在一条评论中。
因此,我添加了这个
替代答案
有了这个答案,完整的对话发生在原始的论点中\pdfcomment
。评论中的回复是通过
\addreply{<style-name>} ...
样式名称可预定义,以包含author=
字段。在此示例中,样式Jim
和Sue
已预定义,因此,当用作 的参数时\addreply
,将使用全author
名(“Jim Jones”或“Sue Smith”)。如果样式未定义,则样式名称本身将用作作者。
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[rgb]{xcolor}
\usepackage{pdfcomment}
\usepackage{listofitems}
\let\svdefinestyle\definestyle
\renewcommand\definestyle[2]{%
\defineauthor{#1}{#2}%
\svdefinestyle{#1}{#2}%
}
\def\authorstring{author}
\newcommand\defineauthor[2]{%
\setsepchar{,/=}%
\readlist*\styleoption{#2}%
\foreachitem\z\in\styleoption[]{%
\itemtomacro\styleoption[\zcnt,1]\ztmp
\ifx\ztmp\authorstring
\expandafter\xdef\csname author#1\endcsname
{\styleoption[\zcnt,2]}%
\fi
}%
}
\newcommand\theauthor[1]{\ifcsname author#1\endcsname
\csname author#1\endcsname\else#1\fi}
\newcommand\addreply[1]{\textCR\textLF\textCR\textLF Reply
\theauthor{#1}:\textCR\textLF\ignorespaces}
\definestyle{Jim}{color=red,author={Jim Jones}}
\definestyle{Sue}{color=blue,author={Sue Smith}}
\begin{document}
Jim's comment appears here:\pdfcomment[style=Jim]{%
Do I really need a comment here?
\addreply{Sue}
Yes, Jim, I think you do.
\addreply{Jim}
Very well, I guess I will leave it here.
}
An now for Sue's turn.\pdfcomment[style=Sue]{%
Jim, can you hear me now?
\addreply{Jim}
I sure can.
\addreply{Sam}
Hey, I'm just interloping into this conversation
}
\end{document}
如下图所示,完整的对话现在发生在一条评论的上下文中。每条回复都以“回复作者姓名:”作为自己的行。如果回复样式未与字段关联,则样式名称本身将用作作者,如第二个对话中author=
的情况。Sam
原始答案
这使用一系列水平连接的\pdfsquarecomment
s 来表示评论/回复链。初始调用是使用
\startcomment[<defaults for comment/reply chain>][<comment options>]{comment}
随后的答复按顺序位于源代码中,如下
\addreply[<comment options>]{comment}
这是 MWE,其中style
和Jim
已Sue
定义。请注意,\addreply
选项可以覆盖评论/回复链默认值。评论框的大小/偏移量由 定义\mycommentsize
,此处设置为.8\baselineskip
。标题Reply:
通过作者字段添加到回复标题中,如下所示author={\commentmode Jim Jones}
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[rgb]{xcolor}
\usepackage{pdfcomment}
\newlength\myhoffset
\def\mycommentsize{.8\baselineskip}% <--Can be changed
\newcommand\startcomment[1][]{%
\catcode`_=12
\gdef\commentdefault{#1}%
\gdef\commentmode{}%
\setlength\myhoffset{0pt}%
\makecommentnext}
\newcommand\addreply{%
\catcode`_=12
\gdef\commentmode{Reply: }%
\addtolength\myhoffset{\mycommentsize}%
\makecommentnext}
\newcommand\makecommentnext[2][]{%
\expandafter\pdfsquarecomment\expandafter
[\commentdefault,hoffset=\myhoffset,
open=true,opacity=.4,
height=\mycommentsize,width=\mycommentsize,#1]{#2}%
\catcode`_=8 }
\definestyle{Jim}{color=red,author={\commentmode Jim Jones}}
\definestyle{Sue}{color=blue,author={\commentmode Sue Smith}}
\begin{document}A comment appears here:
\startcomment
[borderstyle=dashed]% Global option for comment/reply chain
[style={Jim}]
{Does this require comment?}
\addreply
[style={Sue},borderstyle=solid]% Can override global default
{Yes, I think it does.}
\addreply
[style={Jim}]
{OK, I will leave it}
And we can contine the line since the comments will appear with opacity so that the underlying text can be read.
$a_b$ shows underscore is restored.
\end{document}
答案2
实际上,该包包含一个(未记录的)命令\pdfreply
,用于设置所需的/IRT
引用。该实现有点问题,因为它在第一次编译时会出错,但通过设置任意默认值,它似乎可以工作(您必须编译两次)。
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[rgb]{xcolor}
\usepackage{pdfcomment}
\makeatletter
\renewcommand*{\pc@get@PDFOBJID}[1]%
{%
\zref@extractdefault{#1}{PCPDFOBJID}{S,0}%
}%
\makeatother
\begin{document}
A comment appears here:
\pdfcomment[id=A,icon=Insert,color=red,author={author1}]{comment1_text}
\pdfreply[replyto=A,author={author2}]{comment1_text}
\end{document}