Skip to content

Commit

Permalink
Add —ignore-invalid-pages option (#45)
Browse files Browse the repository at this point in the history
* add —ignore-invalid-pages option

* Update pdf.go

change CLI option description

---------

Co-authored-by: jerbob92 <jerbob92@users.noreply.github.com>
  • Loading branch information
josiasmontag and jerbob92 committed Jul 16, 2024
1 parent c7b5c22 commit 1f500d3
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 16 deletions.
2 changes: 1 addition & 1 deletion cmd/explode.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ var explodeCmd = &cobra.Command{
pageRange = cmd.Flag("pages").Value.String()
}

parsedPageRange, _, err := pdf.NormalizePageRange(pageCount.PageCount, pageRange)
parsedPageRange, _, err := pdf.NormalizePageRange(pageCount.PageCount, pageRange, ignoreInvalidPages)
if err != nil {
handleError(cmd, fmt.Errorf("invalid page range '%s': %w\n", pageRange, err), ExitCodeInvalidPageRange)
return
Expand Down
2 changes: 1 addition & 1 deletion cmd/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ var imagesCmd = &cobra.Command{
pageRange = pages
}

parsedPageRange, _, err := pdf.NormalizePageRange(pageCount.PageCount, pageRange)
parsedPageRange, _, err := pdf.NormalizePageRange(pageCount.PageCount, pageRange, ignoreInvalidPages)
if err != nil {
handleError(cmd, fmt.Errorf("invalid page range '%s': %w\n", pageRange, err), ExitCodeInvalidPageRange)
return
Expand Down
2 changes: 1 addition & 1 deletion cmd/merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ var mergeCmd = &cobra.Command{
return
}

pageRange, calculatedPageCount, err := pdf.NormalizePageRange(pageCount.PageCount, "first-last")
pageRange, calculatedPageCount, err := pdf.NormalizePageRange(pageCount.PageCount, "first-last", false)
if err != nil {
closeFunc()
handleError(cmd, fmt.Errorf("invalid page range 'first-last': %w\n", err), ExitCodeInvalidPageRange)
Expand Down
8 changes: 5 additions & 3 deletions cmd/pdf.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ import (

var (
// Used for flags.
password string
stdFileDelimiter string
pages string
password string
stdFileDelimiter string
pages string
ignoreInvalidPages bool
)

func addGenericPDFOptions(command *cobra.Command) {
Expand All @@ -29,6 +30,7 @@ func addGenericPDFOptions(command *cobra.Command) {

func addPagesOption(intro string, command *cobra.Command) {
command.Flags().StringVarP(&pages, "pages", "", "first-last", intro+". Ranges are like '1-3,5', which will result in a PDF file with pages 1, 2, 3 and 5. You can use the keywords first and last. You can prepend a page number with r to start counting from the end. Examples: use '2-last' for the second page until the last page, use '3-r1' for page 3 until the second-last page.")
command.Flags().BoolVarP(&ignoreInvalidPages, "ignore-invalid-pages", "", false, "Ignore non-existing pages in the pages option.")
}

func isExperimentalError(err error) bool {
Expand Down
2 changes: 1 addition & 1 deletion cmd/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ var renderCmd = &cobra.Command{
pageRange = pages
}

parsedPageRange, _, err := pdf.NormalizePageRange(pageCount.PageCount, pageRange)
parsedPageRange, _, err := pdf.NormalizePageRange(pageCount.PageCount, pageRange, ignoreInvalidPages)
if err != nil {
handleError(cmd, fmt.Errorf("invalid page range '%s': %w\n", pageRange, err), ExitCodeInvalidPageRange)
return
Expand Down
2 changes: 1 addition & 1 deletion cmd/text.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ var textCmd = &cobra.Command{
pageRange = pages
}

parsedPageRange, _, err := pdf.NormalizePageRange(pageCount.PageCount, pageRange)
parsedPageRange, _, err := pdf.NormalizePageRange(pageCount.PageCount, pageRange, ignoreInvalidPages)
if err != nil {
handleError(cmd, fmt.Errorf("invalid page range '%s': %w\n", pageRange, err), ExitCodeInvalidPageRange)
return
Expand Down
2 changes: 1 addition & 1 deletion cmd/thumbnails.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ var thumbnailsCmd = &cobra.Command{
pageRange = pages
}

parsedPageRange, _, err := pdf.NormalizePageRange(pageCount.PageCount, pageRange)
parsedPageRange, _, err := pdf.NormalizePageRange(pageCount.PageCount, pageRange, ignoreInvalidPages)
if err != nil {
handleError(cmd, fmt.Errorf("invalid page range '%s': %w\n", pageRange, err), ExitCodeInvalidPageRange)
return
Expand Down
16 changes: 15 additions & 1 deletion pdf/pdf.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func ClosePdfium() {
// supports simple instructions like 1-5 or just a page number. This method
// can automatically calculate ends and reverse pages for example.
// This way we can also properly validate page ranges.
func NormalizePageRange(pageCount int, pageRange string) (*string, *int, error) {
func NormalizePageRange(pageCount int, pageRange string, ignoreInvalidPages bool) (*string, *int, error) {
calculatedPageCount := 0
var calculatedPageNumbers []string
seenPageNumbers := map[int]bool{}
Expand All @@ -48,21 +48,35 @@ func NormalizePageRange(pageCount int, pageRange string) (*string, *int, error)
} else if strings.HasPrefix(pageRangeParts[pageRangePartI], "r") {
parsedPageNumber, err := strconv.Atoi(strings.TrimPrefix(pageRangeParts[pageRangePartI], "r"))
if err != nil {
if ignoreInvalidPages {
continue
}
return nil, nil, fmt.Errorf("%s is not a valid page number", strings.TrimPrefix(pageRangeParts[pageRangePartI], "r"))
}

if pageCount-parsedPageNumber < 1 || pageCount-parsedPageNumber > pageCount {
if ignoreInvalidPages {
pageNumbers = append(pageNumbers, 1)
continue
}
return nil, nil, fmt.Errorf("%d is not a valid page number, the document has %d page(s)", pageCount-parsedPageNumber, pageCount)
}

pageNumbers = append(pageNumbers, pageCount-parsedPageNumber)
} else {
parsedPageNumber, err := strconv.Atoi(pageRangeParts[pageRangePartI])
if err != nil {
if ignoreInvalidPages {
continue
}
return nil, nil, fmt.Errorf("%s is not a valid page number", pageRangeParts[pageRangePartI])
}

if parsedPageNumber < 1 || parsedPageNumber > pageCount {
if ignoreInvalidPages {
pageNumbers = append(pageNumbers, pageCount)
continue
}
return nil, nil, fmt.Errorf("%s is not a valid page number, the document has %d page(s)", pageRangeParts[pageRangePartI], pageCount)
}

Expand Down
28 changes: 22 additions & 6 deletions pdf/pdf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,66 +6,82 @@ import (

func TestNormalizePageRange(t *testing.T) {
tests := []struct {
name string
pageCount int
pageRange string
want string
wantErr string
name string
pageCount int
pageRange string
ignoreInvalidPages bool
want string
wantErr string
}{
{
"test first-last",
5,
"first-last",
false,
"1,2,3,4,5",
"",
},
{
"test page-range",
5,
"1-5",
false,
"1,2,3,4,5",
"",
},
{
"test out of range page-range",
5,
"1-10",
false,
"1,2,3,4,5",
"10 is not a valid page number, the document has 5 page(s)",
},
{
"test out of range page-range",
20,
"1,2,4-22",
false,
"1,2,3,4,5",
"22 is not a valid page number, the document has 20 page(s)",
},
{
"test reverse page-range",
5,
"1-r2",
false,
"1,2,3",
"",
},
{
"test negative reverse page-range",
5,
"1-r6",
false,
"1,2,3",
"-1 is not a valid page number, the document has 5 page(s)",
},
{
"test removal of duplicate pages",
5,
"1-3,first-last,2,3",
false,
"1,2,3,4,5",
"",
},
{
"test ignore invalid pages",
5,
"3-10,6,2",
true,
"3,4,5,2",
"",
},
}

for i := range tests {
t.Run(tests[i].name, func(t *testing.T) {
normalizedPageRange, _, err := NormalizePageRange(tests[i].pageCount, tests[i].pageRange)
normalizedPageRange, _, err := NormalizePageRange(tests[i].pageCount, tests[i].pageRange, tests[i].ignoreInvalidPages)
if tests[i].wantErr == "" && err != nil {
t.Errorf("expected no error but got error %s", err.Error())
} else if tests[i].wantErr != "" && err == nil {
Expand Down

0 comments on commit 1f500d3

Please sign in to comment.