在 Adobe Acrobat Pro 中,向页面添加链接并不困难,但我想知道是否还有一种方法可以向链接添加“替代文本”(有时称为“标题文本”)。在 HTML 中,这将这样完成:
<a href="url" title="Text goes here">link</a>
然后,当鼠标悬停在链接上时,文本会显示为小工具提示。有 PDF 的等效项吗?如果是这样,你如何添加它?
实际上PDF确实支持替代文本。它是逻辑结构记录的 PDF 参考 1.7 第 10.8.2 节“替代描述”的一部分
/跨度 << /Lang (en-us) /Alt (six-point star) >> BDC (✡) Tj EMC
在 PDF 语法中,链接注释支持Contents条目作为备用描述:
/Annots [
<<
/Type /Annot
/Subtype /Link
/Border [1 1 1]
/Dest [4 0 R /XYZ 0 0 null]
/Rect [ 50 50 80 60 ]
/Contents (Link)
>>
]
引用“PDF 参考 - 第 6 版 - Adobe® 便携式文档格式 - 版本 1.7 - 2006 年 11 月”:
Contents 文本字符串 (可选) 要为注释显示的文本,或者,如果此类注释不显示文本,则以人类可读的形式对注释内容进行替代描述。无论哪种情况,在提取文档内容以支持残障用户的可访问性或用于其他目的时,此文本都很有用
稍后:
对于所有其他注释类型(Link、Movie、Widget、PrinterMark 和 TrapNet),Contents 条目以人类可读的形式提供注释内容的替代表示形式
当存在边框时,Sumatra PDF v3.1.2 可以很好地显示:
但是,其他 PDF 阅读器并未广泛支持。
W3C 在其WCAG 2.0 的 PDF 技术中推荐了另一种在链接上显示替代文本以实现可访问性的方法:
不可以,无法将替代文本添加到 PDF 中的链接。 PDF 参考中没有对此做出规定。
相关说明,PDF 中的链接和 HTML 文档中的链接的处理方式完全不同。 PDF 中的链接实际上是一种注释,位于页面顶部的指定坐标处,与文档中的文本或图像没有技术关系。 HTML 文档中的链接与它们超链接的元素有直接关系。
替代文本或替代文本与标题文本不同。标题文本是供人类消费的元数据。替代文本是媒体上的替代文本内容,以防媒体加载失败。
还有一个技巧,使用不可见的表单按钮,该按钮不执行任何操作,但允许在鼠标悬停在其上方时添加一个小的弹出工具提示文本。
正式地,根据 ISO 32000-1 14.9.3 中定义的 PDF 1.7(请参阅 Adobe 网站免费下载相当于 PDF 1.7 ISO 标准的文档),人们将为注释提供替代文本 - 例如例如链接注释 - 通过将键“Contents”添加到其数据结构并提供替代文本作为该键的文本字符串值。
不幸的是,Acrobat 似乎没有提供用户界面来添加或编辑链接注释的“内容”文本字符串,即使存在,也不会用于工具提示。相反,工具提示似乎始终是链接注释的目标,至少在它指向 URL 时是这样。
因此,在视觉层面上,人们可以通过在具有所需行为的链接注释区域顶部添加一些其他不可见元素来解决此问题。这不是一个很好的技巧,至少对我来说是这样。此外,它对 PDF 的可访问性没有帮助,因为它引入了另一个杂散对象......
面对同样的问题,我使用JS lib“pdf-lib”(https://pdf-lib.js.org/docs/api/classes/pdfdocument)来编辑pdf文件的内容并添加缺少的内容注释上的属性。
const pdfLib = require('pdf-lib');
const fs = require('fs');
function getNewMap(pdfDoc, str){
return pdfDoc.context.obj(
{
Alt: new pdfLib.PDFString(str),
Contents: new pdfLib.PDFString(str)
}).dict;
}
const pdfData = await fs.readFile('your-pdf-document.pdf');
const pdfDoc = await pdfLib.PDFDocument.load(pdfData);
pdfDoc.context.enumerateIndirectObjects().forEach(_o => {
const pdfRef = _o[0];
const pdfObject = _o[1];
if (typeof pdfObject?.lookup === "function"){
if (pdfObject.lookup(pdfLib.PDFName.of('Type'))?.encodedName === "/Annot"){
// We use the link URI to implement annotation "Alt" & "Contents" attributes
const annotLinkUri = pdfObject.lookup(pdfLib.PDFName.of('A')).get(pdfLib.PDFName.of('URI')).value;
const titleFromUri = annotLinkUri.replace(/(http:|)(^|\/\/)(.*?\/)/g, "").replace(/\//g, "").trim();
// We build the new map with "Alt" and "Contents" attributes and assign it to the "Annot" object dictionary
const newMap = getNewMap(pdfDoc, titleFromUri);
const newdict = new Map([...pdfObject.dict, ...newMap]);
pdfObject.dict = newdict;
}
}
})
// We save the file
const pdfBytes = await pdfDoc.save();
await fs.promises.writeFile("your-pdf-document-accessible.pdf", pdfBytes);