Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions document.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@ import (
// Options configures a Document. The zero value is valid and yields a
// deterministic, uncompressed document with no timestamps.
type Options struct {
// Title and Author populate the document information dictionary. Empty
// values are omitted.
Title string
Author string
// Title, Author, Subject and Keywords populate the document information
// dictionary. Empty values are omitted. Subject is a one-line description of
// the document; Keywords is a list of search terms (conventionally
// comma-separated). Each is written as a PDF text string, so a non-ASCII value
// is encoded UTF-16BE.
Title string
Author string
Subject string
Keywords string

// Producer is the /Producer string in the information dictionary. When
// empty it defaults to DefaultProducer.
Expand Down Expand Up @@ -215,7 +220,8 @@ func (d *Document) Write(w io.Writer) error {
bd.put(catalog, catDict)

var info objRef
hasInfo := d.opts.Title != "" || d.opts.Author != "" || d.producer() != "" || d.opts.Now != nil
hasInfo := d.opts.Title != "" || d.opts.Author != "" || d.opts.Subject != "" ||
d.opts.Keywords != "" || d.producer() != "" || d.opts.Now != nil
if hasInfo {
info = bd.add(d.infoDict())
}
Expand Down Expand Up @@ -399,6 +405,12 @@ func (d *Document) infoDict() *pdfDict {
if d.opts.Author != "" {
info.set("Author", pdfTextString(d.opts.Author))
}
if d.opts.Subject != "" {
info.set("Subject", pdfTextString(d.opts.Subject))
}
if d.opts.Keywords != "" {
info.set("Keywords", pdfTextString(d.opts.Keywords))
}
if p := d.producer(); p != "" {
info.set("Producer", pdfString(p))
}
Expand Down
40 changes: 40 additions & 0 deletions subjectkeywords_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) the go-pdfkit/pdfkit authors.
// SPDX-License-Identifier: BSD-3-Clause

package pdfkit

import (
"bytes"
"testing"
)

// Subject and Keywords reach the information dictionary as text strings.
func TestInfoSubjectAndKeywords(t *testing.T) {
doc := New(Options{Subject: "A study of widgets", Keywords: "widgets, gadgets, gizmos"})
doc.AddPage(A4)
var b bytes.Buffer
if err := doc.Write(&b); err != nil {
t.Fatal(err)
}
for _, want := range []string{"/Subject (A study of widgets)", "/Keywords (widgets, gadgets, gizmos)"} {
if !bytes.Contains(b.Bytes(), []byte(want)) {
t.Errorf("output missing %q\n%s", want, b.String())
}
}
}

// A non-ASCII Subject/Keywords value is encoded UTF-16BE, like Title/Author.
func TestInfoSubjectKeywordsAccentedUTF16(t *testing.T) {
doc := New(Options{Subject: "Résumé", Keywords: "clé, référence"})
doc.AddPage(A4)
var b bytes.Buffer
if err := doc.Write(&b); err != nil {
t.Fatal(err)
}
if !bytes.Contains(b.Bytes(), []byte("<FEFF")) {
t.Errorf("accented Subject/Keywords were not written UTF-16BE\n%s", b.String())
}
if bytes.Contains(b.Bytes(), []byte("Résumé")) {
t.Errorf("accented Subject leaked into the PDF as raw UTF-8")
}
}