github.com/pdfcpu/pdfcpu@v0.11.1/pkg/api/test/bookmark_test.go (about) 1 /* 2 Copyright 2020 The pdfcpu Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package test 18 19 import ( 20 "os" 21 "path/filepath" 22 "testing" 23 24 "github.com/pdfcpu/pdfcpu/pkg/api" 25 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu" 26 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/color" 27 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model" 28 ) 29 30 // Acrobat Reader "Bookmarks" = Mac Preview "Table of Contents". 31 // Mac Preview limitations: does not render color, style, outline tree collapsed by default. 32 33 func listBookmarksFile(t *testing.T, fileName string, conf *model.Configuration) ([]string, error) { 34 t.Helper() 35 36 msg := "listBookmarks" 37 38 f, err := os.Open(fileName) 39 if err != nil { 40 t.Fatalf("%s open: %v\n", msg, err) 41 } 42 defer f.Close() 43 44 if conf == nil { 45 conf = model.NewDefaultConfiguration() 46 } else { 47 conf.ValidationMode = model.ValidationRelaxed 48 } 49 conf.Cmd = model.LISTBOOKMARKS 50 51 ctx, err := api.ReadValidateAndOptimize(f, conf) 52 if err != nil { 53 t.Fatalf("%s ReadValidateAndOptimize: %v\n", msg, err) 54 } 55 56 return pdfcpu.BookmarkList(ctx) 57 } 58 59 func TestListBookmarks(t *testing.T) { 60 msg := "TestListBookmarks" 61 inDir := filepath.Join("..", "..", "samples", "bookmarks") 62 inFile := filepath.Join(inDir, "bookmarkTree.pdf") 63 64 if _, err := listBookmarksFile(t, inFile, nil); err != nil { 65 t.Fatalf("%s list bookmarks: %v\n", msg, err) 66 } 67 } 68 69 func TestAddDuplicateBookmarks(t *testing.T) { 70 msg := "TestAddDuplicateBookmarks" 71 inFile := filepath.Join(inDir, "CenterOfWhy.pdf") 72 outFile := filepath.Join("..", "..", "samples", "bookmarks", "bookmarkDuplicates.pdf") 73 74 bms := []pdfcpu.Bookmark{ 75 {PageFrom: 1, Title: "Parent1", 76 Kids: []pdfcpu.Bookmark{ 77 {PageFrom: 2, Title: "kid1"}, 78 {PageFrom: 3, Title: "kid2"}, 79 }, 80 }, 81 {PageFrom: 4, Title: "Parent2", 82 Kids: []pdfcpu.Bookmark{ 83 {PageFrom: 5, Title: "kid1"}, 84 {PageFrom: 6, Title: "kid2"}, 85 }, 86 }, 87 } 88 89 replace := true // Replace existing bookmarks. 90 if err := api.AddBookmarksFile(inFile, outFile, bms, replace, nil); err != nil { 91 t.Fatalf("%s addBookmarks: %v\n", msg, err) 92 } 93 if err := api.ValidateFile(outFile, nil); err != nil { 94 t.Fatalf("%s: %v\n", msg, err) 95 } 96 } 97 98 func TestAddSimpleBookmarks(t *testing.T) { 99 msg := "TestAddSimpleBookmarks" 100 inFile := filepath.Join(inDir, "CenterOfWhy.pdf") 101 outFile := filepath.Join("..", "..", "samples", "bookmarks", "bookmarkSimple.pdf") 102 103 bookmarkColor := color.NewSimpleColor(0xab6f30) 104 105 // TODO Emoji support! 106 107 bms := []pdfcpu.Bookmark{ 108 {PageFrom: 1, Title: "Page 1: Applicant’s Form"}, 109 {PageFrom: 2, Title: "Page 2: Bold 这是一个测试", Bold: true}, 110 {PageFrom: 3, Title: "Page 3: Italic 测试 尾巴", Italic: true, Bold: true}, 111 {PageFrom: 4, Title: "Page 4: Bold & Italic", Bold: true, Italic: true}, 112 {PageFrom: 16, Title: "Page 16: The birthday of Smalltalk", Color: &bookmarkColor}, 113 {PageFrom: 17, Title: "Page 17: Gray", Color: &color.Gray}, 114 {PageFrom: 18, Title: "Page 18: Red", Color: &color.Red}, 115 {PageFrom: 19, Title: "Page 19: Bold Red", Color: &color.Red, Bold: true}, 116 } 117 118 replace := true // Replace existing bookmarks. 119 if err := api.AddBookmarksFile(inFile, outFile, bms, replace, nil); err != nil { 120 t.Fatalf("%s addBookmarks: %v\n", msg, err) 121 } 122 if err := api.ValidateFile(outFile, nil); err != nil { 123 t.Fatalf("%s: %v\n", msg, err) 124 } 125 } 126 127 func TestAddBookmarkTree2Levels(t *testing.T) { 128 msg := "TestAddBookmarkTree2Levels" 129 inFile := filepath.Join(inDir, "CenterOfWhy.pdf") 130 outFile := filepath.Join("..", "..", "samples", "bookmarks", "bookmarkTree.pdf") 131 132 bms := []pdfcpu.Bookmark{ 133 {PageFrom: 1, Title: "Page 1: Level 1", Color: &color.Green, 134 Kids: []pdfcpu.Bookmark{ 135 {PageFrom: 2, Title: "Page 2: Level 1.1"}, 136 {PageFrom: 3, Title: "Page 3: Level 1.2", 137 Kids: []pdfcpu.Bookmark{ 138 {PageFrom: 4, Title: "Page 4: Level 1.2.1"}, 139 }}, 140 }}, 141 {PageFrom: 5, Title: "Page 5: Level 2", Color: &color.Blue, 142 Kids: []pdfcpu.Bookmark{ 143 {PageFrom: 6, Title: "Page 6: Level 2.1"}, 144 {PageFrom: 7, Title: "Page 7: Level 2.2"}, 145 {PageFrom: 8, Title: "Page 8: Level 2.3"}, 146 }}, 147 } 148 149 if err := api.AddBookmarksFile(inFile, outFile, bms, false, nil); err != nil { 150 t.Fatalf("%s addBookmarks: %v\n", msg, err) 151 } 152 if err := api.ValidateFile(outFile, nil); err != nil { 153 t.Fatalf("%s: %v\n", msg, err) 154 } 155 } 156 157 func TestRemoveBookmarks(t *testing.T) { 158 msg := "TestRemoveBookmarks" 159 inDir := filepath.Join("..", "..", "samples", "bookmarks") 160 inFile := filepath.Join(inDir, "bookmarkTree.pdf") 161 outFile := filepath.Join(inDir, "bookmarkTreeNoBookmarks.pdf") 162 163 if err := api.RemoveBookmarksFile(inFile, outFile, nil); err != nil { 164 t.Fatalf("%s removeBookmarks: %v\n", msg, err) 165 } 166 if err := api.ValidateFile(outFile, nil); err != nil { 167 t.Fatalf("%s: %v\n", msg, err) 168 } 169 } 170 171 func TestExportBookmarks(t *testing.T) { 172 msg := "TestExportBookmarks" 173 inDir := filepath.Join("..", "..", "samples", "bookmarks") 174 inFile := filepath.Join(inDir, "bookmarkTree.pdf") 175 outFile := filepath.Join(inDir, "bookmarkTree.json") 176 177 if err := api.ExportBookmarksFile(inFile, outFile, nil); err != nil { 178 t.Fatalf("%s export bookmarks: %v\n", msg, err) 179 } 180 } 181 182 func TestImportBookmarks(t *testing.T) { 183 msg := "TestImportBookmarks" 184 inDir := filepath.Join("..", "..", "samples", "bookmarks") 185 inFile := filepath.Join(inDir, "bookmarkTree.pdf") 186 inFileJSON := filepath.Join(inDir, "bookmarkTree.json") 187 outFile := filepath.Join(inDir, "bookmarkTreeImported.pdf") 188 189 replace := true 190 if err := api.ImportBookmarksFile(inFile, inFileJSON, outFile, replace, nil); err != nil { 191 t.Fatalf("%s importBookmarks: %v\n", msg, err) 192 } 193 if err := api.ValidateFile(outFile, nil); err != nil { 194 t.Fatalf("%s: %v\n", msg, err) 195 } 196 }