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  }