Skip to content

Fix: Comprehensive page navigation for crossref entries in both internal and external viewers (#8128)#15504

Open
Sherry0121-AC wants to merge 39 commits intoJabRef:mainfrom
Sherry0121-AC:fix-8128-crossref-pages
Open

Fix: Comprehensive page navigation for crossref entries in both internal and external viewers (#8128)#15504
Sherry0121-AC wants to merge 39 commits intoJabRef:mainfrom
Sherry0121-AC:fix-8128-crossref-pages

Conversation

@Sherry0121-AC
Copy link
Copy Markdown

@Sherry0121-AC Sherry0121-AC commented Apr 7, 2026

Related issues and pull requests

Closes #8128
Closes #8128

PR Description

This PR fixes the issue where opening sub-entries (e.g., @InCollection) via the crossref field failed to navigate to the correct start page in external and internal viewers. By implementing a logical-to-physical page translation layer and optimizing the navigation pipeline, JabRef now correctly targets the intended page, gracefully handling PDF front-matter offsets when present. This ensures a consistent and accurate research experience across all desktop platforms.

Steps to test

  1. Create a parent @Book entry in JabRef and link a local PDF file to it.
    (Optional but recommended: Use a PDF with roman-numeral front matter to verify the new logical-to-physical page translation feature).
  2. Create a child @InCollection entry. Set crossref pointing to the parent book's citation key, and set the pages field to a specific range (e.g., 186--206).
  3. External Viewer Test: Select the child entry and press F4. The default browser should open the parent PDF and automatically land on the physical page corresponding to the printed page 186.
  4. Internal Viewer Test: Go to View -> Show document viewer. The internal viewer should successfully resolve the parent file and navigate to page 186 for the selected child.

Screenshots:
![External Viewer Jump]
image
image
image
Screenshots: The external browser successfully navigating to physical page 200 (logical page 186) after pressing F4.

![Internal Viewer Jump]
image
image
image
Screenshots: The internal document viewer accurately resolving the parent file and jumping to the correct page.

Known Limitations

  • Internal Viewer State: Currently, when using the internal document viewer, navigating directly to a child entry might not jump to the specific page if the parent PDF hasn't been loaded into the viewer's cache yet (e.g., by clicking the parent entry first). The external viewer (F4) is unaffected and works perfectly. This appears to be related to the viewer's initialization lifecycle and can be addressed in a follow-up refinement.

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • I manually tested my changes in running JabRef (always required)
  • I added JUnit tests for changes (if applicable)
  • I added screenshots in the PR description (if change is visible to the user)
  • I added a screenshot in the PR description showing a library with a single entry with me as author and as title the issue number
image - [x] I described the change in `CHANGELOG.md` in a way that can be understood by the average user (if change is visible to the user) - [/] I checked the [user documentation](https://docs.jabref.org/) for up to dateness and submitted a pull request to our [user documentation repository](https://github.com/JabRef/user-documentation/tree/main/en)

@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Add comprehensive page navigation for crossref entries across all platforms

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Implement logical-to-physical PDF page translation for crossref entries
• Add page number support across all desktop platforms (Windows, macOS, Linux)
• Enable internal and external viewers to navigate to correct pages in parent PDFs
• Support crossref fallback when child entries lack direct file attachments
Diagram
flowchart LR
  A["Child Entry with crossref"] -->|resolve parent| B["Parent Entry"]
  B -->|extract pages field| C["Parse Page Number"]
  C -->|PDF with labels| D["PdfPageLabelResolver"]
  D -->|logical to physical| E["Physical Page Number"]
  E -->|pass to OS| F["Platform-specific Viewer"]
  F -->|Windows| G["SumatraPDF/-page"]
  F -->|macOS| H["Adobe/Skim/Browser"]
  F -->|Linux| I["Evince/Okular/Zathura"]
Loading

Grey Divider

File Changes

1. jabgui/src/main/java/org/jabref/gui/actions/ActionHelper.java ✨ Enhancement +10/-1

Check crossref field for file availability

jabgui/src/main/java/org/jabref/gui/actions/ActionHelper.java


2. jabgui/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java ✨ Enhancement +30/-13

Add pageNumber parameter to file opening methods

jabgui/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java


3. jabgui/src/main/java/org/jabref/gui/desktop/os/DefaultDesktop.java ✨ Enhancement +2/-2

Update method signatures with pageNumber parameter

jabgui/src/main/java/org/jabref/gui/desktop/os/DefaultDesktop.java


View more (16)
4. jabgui/src/main/java/org/jabref/gui/desktop/os/Windows.java ✨ Enhancement +57/-4

Implement Windows PDF page navigation with SumatraPDF

jabgui/src/main/java/org/jabref/gui/desktop/os/Windows.java


5. jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java ✨ Enhancement +93/-10

Implement macOS PDF page navigation for multiple viewers

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java


6. jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java ✨ Enhancement +76/-7

Implement Linux PDF page navigation for Evince/Okular/Zathura

jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java


7. jabgui/src/main/java/org/jabref/gui/util/PdfPageLabelResolver.java ✨ Enhancement +60/-0

New utility to resolve logical to physical PDF page numbers

jabgui/src/main/java/org/jabref/gui/util/PdfPageLabelResolver.java


8. jabgui/src/main/java/org/jabref/gui/documentviewer/DocumentViewerViewModel.java ✨ Enhancement +73/-3

Support crossref parent PDF and page label resolution

jabgui/src/main/java/org/jabref/gui/documentviewer/DocumentViewerViewModel.java


9. jabgui/src/main/java/org/jabref/gui/documentviewer/ShowDocumentViewerAction.java ✨ Enhancement +1/-1

Update action to check for crossref linked files

jabgui/src/main/java/org/jabref/gui/documentviewer/ShowDocumentViewerAction.java


10. jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java ✨ Enhancement +38/-1

Extract and pass page numbers when opening PDF files

jabgui/src/main/java/org/jabref/gui/fieldeditors/LinkedFileViewModel.java


11. jabgui/src/main/java/org/jabref/gui/maintable/OpenSelectedEntriesFilesAction.java ✨ Enhancement +17/-1

Support opening parent files via crossref field

jabgui/src/main/java/org/jabref/gui/maintable/OpenSelectedEntriesFilesAction.java


12. jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogViewModel.java ✨ Enhancement +1/-1

Update file opening call with pageNumber parameter

jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogViewModel.java


13. jabgui/src/main/java/org/jabref/gui/preferences/protectedterms/ProtectedTermsTabViewModel.java ✨ Enhancement +1/-1

Update file opening call with pageNumber parameter

jabgui/src/main/java/org/jabref/gui/preferences/protectedterms/ProtectedTermsTabViewModel.java


14. jabgui/src/test/java/org/jabref/gui/actions/ActionHelperTest.java 🧪 Tests +48/-0

Test crossref detection in file availability check

jabgui/src/test/java/org/jabref/gui/actions/ActionHelperTest.java


15. jabgui/src/test/java/org/jabref/gui/desktop/os/OSXTest.java 🧪 Tests +72/-0

Test macOS PDF page navigation with browser hash jump

jabgui/src/test/java/org/jabref/gui/desktop/os/OSXTest.java


16. jabgui/src/test/java/org/jabref/gui/documentviewer/DocumentViewerViewModelTest.java 🧪 Tests +165/-0

Test crossref parent PDF resolution and page label mapping

jabgui/src/test/java/org/jabref/gui/documentviewer/DocumentViewerViewModelTest.java


17. jabgui/src/test/java/org/jabref/gui/fieldeditors/LinkedFileViewModelTest.java 🧪 Tests +57/-0

Test page number parsing and passing for PDF files

jabgui/src/test/java/org/jabref/gui/fieldeditors/LinkedFileViewModelTest.java


18. jabgui/src/test/java/org/jabref/gui/util/PdfPageLabelResolverTest.java 🧪 Tests +65/-0

Test logical to physical page number resolution

jabgui/src/test/java/org/jabref/gui/util/PdfPageLabelResolverTest.java


19. CHANGELOG.md 📝 Documentation +1/-0

Document fix for crossref page navigation issue

CHANGELOG.md


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

qodo-free-for-open-source-projects bot commented Apr 7, 2026

Code Review by Qodo

🐞 Bugs (0)   📘 Rule violations (3)   📎 Requirement gaps (0)   🖥 UI issues (0)   🎨 UX Issues (0)
📘\ ⚙ Maintainability (3)

Grey Divider


Action required

1. macOS viewer preference bypass🐞
Description
OSX.openFile short-circuits for PDFs with pageNumber>1 and opens via Chrome/Edge or browser URL,
skipping the configured ExternalFileType application entirely. This changes user-visible behavior by
ignoring the preferred PDF viewer even when one is configured.
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[R29-47]

+    public void openFile(String filePath, String fileType, ExternalApplicationsPreferences externalApplicationsPreferences, int pageNumber) throws IOException {
+        if (isPdf(fileType) && pageNumber > 1) {
+            String fileUrlWithPage = Path.of(filePath).toUri().toString() + "#page=" + pageNumber;
+
+            String chromeBinary = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
+            String edgeBinary = "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge";
+
+            if (Files.exists(Path.of(chromeBinary))) {
+                new ProcessBuilder(chromeBinary, fileUrlWithPage).start();
+                return;
+            }
+            if (Files.exists(Path.of(edgeBinary))) {
+                new ProcessBuilder(edgeBinary, fileUrlWithPage).start();
+                return;
+            }
+
+            NativeDesktop.openBrowser(fileUrlWithPage, externalApplicationsPreferences);
+            return;
+        }
Evidence
The early-return branch for PDFs with pageNumber>1 executes before ExternalFileTypes lookup;
therefore the configured openWithApplication is never consulted for page jumps. The configured
application path is only reached after this early return, making it unreachable for the page-jump
case.

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[28-59]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
On macOS, `OSX.openFile(..., pageNumber)` bypasses the user-configured PDF application when `pageNumber > 1`, forcing Chrome/Edge or a browser-based `file://...#page=` open.
### Issue Context
The preference-respecting logic (`ExternalFileTypes.getExternalFileTypeByExt` and `openFileWithApplication`) is currently unreachable in the `pageNumber > 1` PDF case due to an early return.
### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[28-59]
### Suggested fix approach
1. Resolve the configured `ExternalFileType` first.
2. If an `openWithApplication` is configured, attempt `openFileWithApplication(filePath, application, pageNumber)`.
3. Only fall back to the browser hash jump strategy if no app is configured (or if you explicitly decide the configured app cannot support page jumps).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. openFileWithApplication adds -a twice📎
Description
In OSX.openFileWithApplication, the command list appends -a  and filePath twice, which can
produce an invalid open invocation. This can prevent opening the PDF (and thus page-jump behavior)
when a non-browser, non-Skim application is configured.
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[R57-80]

+        if (application != null && !application.isEmpty()) {
+            command.add("-a");
+            command.add(application);
+        }
+        command.add(filePath);
+
+        if (pageNumber > 1 && appNameLower.contains("skim")) {
+            String appleScript = String.format(
+                    "tell application \"Skim\"\n" +
+                            "  activate\n" +
+                            "  set myDoc to open POSIX file \"%s\"\n" +
+                            "  tell myDoc to go to page %d\n" +
+                            "end tell", filePath, pageNumber);
+
+            new ProcessBuilder("/usr/bin/osascript", "-e", appleScript).start();
+            return;
+        }
+
+        if (application != null && !application.isEmpty()) {
+            command.add("-a");
+            command.add(application);
+        }
+        command.add(filePath);
+        new ProcessBuilder(command).start();
Evidence
Compliance requires PDF opening to support jumping to the first page derived from pages; if the
external-viewer command construction is wrong, the open-and-jump flow can fail entirely. The added
code builds the open command by adding -a  and filePath twice before starting the process.

PDF opening: offer jump-to-first-page based on the entry's pages field
Cross-referenced PDF opening: open parent's attached PDF and jump to child's pages target
jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[57-80]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`OSX.openFileWithApplication` builds the `/usr/bin/open` command by adding the application (`-a <application>`) and `filePath` twice, producing a duplicated argument list.
## Issue Context
This method is used for opening files with a configured application, including the new page-jump behavior. Duplicated args can cause the external open to fail or behave unpredictably.
## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[57-80]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Evince page-label mismatch🐞
Description
NativeDesktop converts logical page numbers to physical page numbers for PDFs, but Linux passes
that (physical) number to evince using --page-label, which targets page labels rather than
physical indices. For PDFs with front-matter/custom labels, this opens the wrong page (or fails to
find the intended label).
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[R118-132]

+    private static void addPdfPageArguments(List<String> command, String application, String filePath, int pageNumber) {
+        if (pageNumber <= 1 || !isPdfPath(filePath)) {
+            return;
+        }
+
+        String executable = Path.of(application).getFileName().toString().toLowerCase(Locale.ROOT);
+        if (executable.contains("evince")) {
+            command.add("--page-label=" + pageNumber);
+        } else if (executable.contains("okular")) {
+            command.add("-p");
+            command.add(String.valueOf(pageNumber));
+        } else if (executable.contains("zathura")) {
+            command.add("-P");
+            command.add(String.valueOf(pageNumber));
+        }
Evidence
NativeDesktop.resolvePageNumberForOpen uses PdfPageLabelResolver which is explicitly defined as
logical→physical conversion. Linux then uses evince’s --page-label= flag, which (by its naming and
usage) expects a label string; passing a physical page number after conversion breaks the mapping
when labels differ from physical order.

jabgui/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java[187-203]
jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[118-132]
jablib/src/main/java/org/jabref/logic/pdf/PdfPageLabelResolver.java[20-42]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Linux uses `--page-label` for evince, but the page number is pre-resolved to a *physical* page in `NativeDesktop`. That means evince receives the wrong value when labels != physical indices (exactly the scenario this PR aims to improve).
### Issue Context
- `NativeDesktop.resolvePageNumberForOpen` currently always converts logical→physical for PDFs.
- Linux/evince path uses `--page-label`, which should be fed the logical label, not the physical page.
### Fix Focus Areas
- Move the logical→physical translation decision into the OS/viewer-specific layer (so evince can keep logical labels while okular/zathura can use physical indices), OR
- Keep `NativeDesktop` as-is but change evince invocation to use an argument that targets physical indices (if available in your supported command set).
- jabgui/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java[193-203]
- jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[118-142]
- jablib/src/main/java/org/jabref/logic/pdf/PdfPageLabelResolver.java[20-42]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (17)
4. macOS viewer preference bypass🐞
Description
OSX.openFile short-circuits for PDFs with pageNumber>1 and opens via Chrome/Edge or browser URL,
skipping the configured ExternalFileType application entirely. This changes user-visible behavior by
ignoring the preferred PDF viewer even when one is configured.
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[R29-47]

+    public void openFile(String filePath, String fileType, ExternalApplicationsPreferences externalApplicationsPreferences, int pageNumber) throws IOException {
+        if (isPdf(fileType) && pageNumber > 1) {
+            String fileUrlWithPage = Path.of(filePath).toUri().toString() + "#page=" + pageNumber;
+
+            String chromeBinary = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
+            String edgeBinary = "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge";
+
+            if (Files.exists(Path.of(chromeBinary))) {
+                new ProcessBuilder(chromeBinary, fileUrlWithPage).start();
+                return;
+            }
+            if (Files.exists(Path.of(edgeBinary))) {
+                new ProcessBuilder(edgeBinary, fileUrlWithPage).start();
+                return;
+            }
+
+            NativeDesktop.openBrowser(fileUrlWithPage, externalApplicationsPreferences);
+            return;
+        }
Evidence
The early-return branch for PDFs with pageNumber>1 executes before ExternalFileTypes lookup;
therefore the configured openWithApplication is never consulted for page jumps. The configured
application path is only reached after this early return, making it unreachable for the page-jump
case.

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[28-59]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
On macOS, `OSX.openFile(..., pageNumber)` bypasses the user-configured PDF application when `pageNumber > 1`, forcing Chrome/Edge or a browser-based `file://...#page=` open.
### Issue Context
The preference-respecting logic (`ExternalFileTypes.getExternalFileTypeByExt` and `openFileWithApplication`) is currently unreachable in the `pageNumber > 1` PDF case due to an early return.
### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[28-59]
### Suggested fix approach
1. Resolve the configured `ExternalFileType` first.
2. If an `openWithApplication` is configured, attempt `openFileWithApplication(filePath, application, pageNumber)`.
3. Only fall back to the browser hash jump strategy if no app is configured (or if you explicitly decide the configured app cannot support page jumps).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. openFileWithApplication adds -a twice📎
Description
In OSX.openFileWithApplication, the command list appends -a  and filePath twice, which can
produce an invalid open invocation. This can prevent opening the PDF (and thus page-jump behavior)
when a non-browser, non-Skim application is configured.
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[R57-80]

+        if (application != null && !application.isEmpty()) {
+            command.add("-a");
+            command.add(application);
+        }
+        command.add(filePath);
+
+        if (pageNumber > 1 && appNameLower.contains("skim")) {
+            String appleScript = String.format(
+                    "tell application \"Skim\"\n" +
+                            "  activate\n" +
+                            "  set myDoc to open POSIX file \"%s\"\n" +
+                            "  tell myDoc to go to page %d\n" +
+                            "end tell", filePath, pageNumber);
+
+            new ProcessBuilder("/usr/bin/osascript", "-e", appleScript).start();
+            return;
+        }
+
+        if (application != null && !application.isEmpty()) {
+            command.add("-a");
+            command.add(application);
+        }
+        command.add(filePath);
+        new ProcessBuilder(command).start();
Evidence
Compliance requires PDF opening to support jumping to the first page derived from pages; if the
external-viewer command construction is wrong, the open-and-jump flow can fail entirely. The added
code builds the open command by adding -a  and filePath twice before starting the process.

PDF opening: offer jump-to-first-page based on the entry's pages field
Cross-referenced PDF opening: open parent's attached PDF and jump to child's pages target
jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[57-80]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`OSX.openFileWithApplication` builds the `/usr/bin/open` command by adding the application (`-a <application>`) and `filePath` twice, producing a duplicated argument list.
## Issue Context
This method is used for opening files with a configured application, including the new page-jump behavior. Duplicated args can cause the external open to fail or behave unpredictably.
## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[57-80]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Evince page-label mismatch🐞
Description
NativeDesktop converts logical page numbers to physical page numbers for PDFs, but Linux passes
that (physical) number to evince using --page-label, which targets page labels rather than
physical indices. For PDFs with front-matter/custom labels, this opens the wrong page (or fails to
find the intended label).
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[R118-132]

+    private static void addPdfPageArguments(List<String> command, String application, String filePath, int pageNumber) {
+        if (pageNumber <= 1 || !isPdfPath(filePath)) {
+            return;
+        }
+
+        String executable = Path.of(application).getFileName().toString().toLowerCase(Locale.ROOT);
+        if (executable.contains("evince")) {
+            command.add("--page-label=" + pageNumber);
+        } else if (executable.contains("okular")) {
+            command.add("-p");
+            command.add(String.valueOf(pageNumber));
+        } else if (executable.contains("zathura")) {
+            command.add("-P");
+            command.add(String.valueOf(pageNumber));
+        }
Evidence
NativeDesktop.resolvePageNumberForOpen uses PdfPageLabelResolver which is explicitly defined as
logical→physical conversion. Linux then uses evince’s --page-label= flag, which (by its naming and
usage) expects a label string; passing a physical page number after conversion breaks the mapping
when labels differ from physical order.

jabgui/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java[187-203]
jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[118-132]
jablib/src/main/java/org/jabref/logic/pdf/PdfPageLabelResolver.java[20-42]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Linux uses `--page-label` for evince, but the page number is pre-resolved to a *physical* page in `NativeDesktop`. That means evince receives the wrong value when labels != physical indices (exactly the scenario this PR aims to improve).
### Issue Context
- `NativeDesktop.resolvePageNumberForOpen` currently always converts logical→physical for PDFs.
- Linux/evince path uses `--page-label`, which should be fed the logical label, not the physical page.
### Fix Focus Areas
- Move the logical→physical translation decision into the OS/viewer-specific layer (so evince can keep logical labels while okular/zathura can use physical indices), OR
- Keep `NativeDesktop` as-is but change evince invocation to use an argument that targets physical indices (if available in your supported command set).
- jabgui/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java[193-203]
- jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[118-142]
- jablib/src/main/java/org/jabref/logic/pdf/PdfPageLabelResolver.java[20-42]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. macOS viewer preference bypass🐞
Description
OSX.openFile short-circuits for PDFs with pageNumber>1 and opens via Chrome/Edge or browser URL,
skipping the configured ExternalFileType application entirely. This changes user-visible behavior by
ignoring the preferred PDF viewer even when one is configured.
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[R29-47]

+    public void openFile(String filePath, String fileType, ExternalApplicationsPreferences externalApplicationsPreferences, int pageNumber) throws IOException {
+        if (isPdf(fileType) && pageNumber > 1) {
+            String fileUrlWithPage = Path.of(filePath).toUri().toString() + "#page=" + pageNumber;
+
+            String chromeBinary = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
+            String edgeBinary = "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge";
+
+            if (Files.exists(Path.of(chromeBinary))) {
+                new ProcessBuilder(chromeBinary, fileUrlWithPage).start();
+                return;
+            }
+            if (Files.exists(Path.of(edgeBinary))) {
+                new ProcessBuilder(edgeBinary, fileUrlWithPage).start();
+                return;
+            }
+
+            NativeDesktop.openBrowser(fileUrlWithPage, externalApplicationsPreferences);
+            return;
+        }
Evidence
The early-return branch for PDFs with pageNumber>1 executes before ExternalFileTypes lookup;
therefore the configured openWithApplication is never consulted for page jumps. The configured
application path is only reached after this early return, making it unreachable for the page-jump
case.

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[28-59]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
On macOS, `OSX.openFile(..., pageNumber)` bypasses the user-configured PDF application when `pageNumber > 1`, forcing Chrome/Edge or a browser-based `file://...#page=` open.
### Issue Context
The preference-respecting logic (`ExternalFileTypes.getExternalFileTypeByExt` and `openFileWithApplication`) is currently unreachable in the `pageNumber > 1` PDF case due to an early return.
### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[28-59]
### Suggested fix approach
1. Resolve the configured `ExternalFileType` first.
2. If an `openWithApplication` is configured, attempt `openFileWithApplication(filePath, application, pageNumber)`.
3. Only fall back to the browser hash jump strategy if no app is configured (or if you explicitly decide the configured app cannot support page jumps).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. openFileWithApplication adds -a twice📎
Description
In OSX.openFileWithApplication, the command list appends -a  and filePath twice, which can
produce an invalid open invocation. This can prevent opening the PDF (and thus page-jump behavior)
when a non-browser, non-Skim application is configured.
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[R57-80]

+        if (application != null && !application.isEmpty()) {
+            command.add("-a");
+            command.add(application);
+        }
+        command.add(filePath);
+
+        if (pageNumber > 1 && appNameLower.contains("skim")) {
+            String appleScript = String.format(
+                    "tell application \"Skim\"\n" +
+                            "  activate\n" +
+                            "  set myDoc to open POSIX file \"%s\"\n" +
+                            "  tell myDoc to go to page %d\n" +
+                            "end tell", filePath, pageNumber);
+
+            new ProcessBuilder("/usr/bin/osascript", "-e", appleScript).start();
+            return;
+        }
+
+        if (application != null && !application.isEmpty()) {
+            command.add("-a");
+            command.add(application);
+        }
+        command.add(filePath);
+        new ProcessBuilder(command).start();
Evidence
Compliance requires PDF opening to support jumping to the first page derived from pages; if the
external-viewer command construction is wrong, the open-and-jump flow can fail entirely. The added
code builds the open command by adding -a  and filePath twice before starting the process.

PDF opening: offer jump-to-first-page based on the entry's pages field
Cross-referenced PDF opening: open parent's attached PDF and jump to child's pages target
jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[57-80]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`OSX.openFileWithApplication` builds the `/usr/bin/open` command by adding the application (`-a <application>`) and `filePath` twice, producing a duplicated argument list.
## Issue Context
This method is used for opening files with a configured application, including the new page-jump behavior. Duplicated args can cause the external open to fail or behave unpredictably.
## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[57-80]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Evince page-label mismatch🐞
Description
NativeDesktop converts logical page numbers to physical page numbers for PDFs, but Linux passes
that (physical) number to evince using --page-label, which targets page labels rather than
physical indices. For PDFs with front-matter/custom labels, this opens the wrong page (or fails to
find the intended label).
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[R118-132]

+    private static void addPdfPageArguments(List<String> command, String application, String filePath, int pageNumber) {
+        if (pageNumber <= 1 || !isPdfPath(filePath)) {
+            return;
+        }
+
+        String executable = Path.of(application).getFileName().toString().toLowerCase(Locale.ROOT);
+        if (executable.contains("evince")) {
+            command.add("--page-label=" + pageNumber);
+        } else if (executable.contains("okular")) {
+            command.add("-p");
+            command.add(String.valueOf(pageNumber));
+        } else if (executable.contains("zathura")) {
+            command.add("-P");
+            command.add(String.valueOf(pageNumber));
+        }
Evidence
NativeDesktop.resolvePageNumberForOpen uses PdfPageLabelResolver which is explicitly defined as
logical→physical conversion. Linux then uses evince’s --page-label= flag, which (by its naming and
usage) expects a label string; passing a physical page number after conversion breaks the mapping
when labels differ from physical order.

jabgui/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java[187-203]
jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[118-132]
jablib/src/main/java/org/jabref/logic/pdf/PdfPageLabelResolver.java[20-42]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Linux uses `--page-label` for evince, but the page number is pre-resolved to a *physical* page in `NativeDesktop`. That means evince receives the wrong value when labels != physical indices (exactly the scenario this PR aims to improve).
### Issue Context
- `NativeDesktop.resolvePageNumberForOpen` currently always converts logical→physical for PDFs.
- Linux/evince path uses `--page-label`, which should be fed the logical label, not the physical page.
### Fix Focus Areas
- Move the logical→physical translation decision into the OS/viewer-specific layer (so evince can keep logical labels while okular/zathura can use physical indices), OR
- Keep `NativeDesktop` as-is but change evince invocation to use an argument that targets physical indices (if available in your supported command set).
- jabgui/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java[193-203]
- jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[118-142]
- jablib/src/main/java/org/jabref/logic/pdf/PdfPageLabelResolver.java[20-42]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


10. macOS viewer preference bypass🐞
Description
OSX.openFile short-circuits for PDFs with pageNumber>1 and opens via Chrome/Edge or browser URL,
skipping the configured ExternalFileType application entirely. This changes user-visible behavior by
ignoring the preferred PDF viewer even when one is configured.
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[R29-47]

+    public void openFile(String filePath, String fileType, ExternalApplicationsPreferences externalApplicationsPreferences, int pageNumber) throws IOException {
+        if (isPdf(fileType) && pageNumber > 1) {
+            String fileUrlWithPage = Path.of(filePath).toUri().toString() + "#page=" + pageNumber;
+
+            String chromeBinary = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
+            String edgeBinary = "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge";
+
+            if (Files.exists(Path.of(chromeBinary))) {
+                new ProcessBuilder(chromeBinary, fileUrlWithPage).start();
+                return;
+            }
+            if (Files.exists(Path.of(edgeBinary))) {
+                new ProcessBuilder(edgeBinary, fileUrlWithPage).start();
+                return;
+            }
+
+            NativeDesktop.openBrowser(fileUrlWithPage, externalApplicationsPreferences);
+            return;
+        }
Evidence
The early-return branch for PDFs with pageNumber>1 executes before ExternalFileTypes lookup;
therefore the configured openWithApplication is never consulted for page jumps. The configured
application path is only reached after this early return, making it unreachable for the page-jump
case.

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[28-59]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
On macOS, `OSX.openFile(..., pageNumber)` bypasses the user-configured PDF application when `pageNumber > 1`, forcing Chrome/Edge or a browser-based `file://...#page=` open.
### Issue Context
The preference-respecting logic (`ExternalFileTypes.getExternalFileTypeByExt` and `openFileWithApplication`) is currently unreachable in the `pageNumber > 1` PDF case due to an early return.
### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[28-59]
### Suggested fix approach
1. Resolve the configured `ExternalFileType` first.
2. If an `openWithApplication` is configured, attempt `openFileWithApplication(filePath, application, pageNumber)`.
3. Only fall back to the browser hash jump strategy if no app is configured (or if you explicitly decide the configured app cannot support page jumps).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. openFileWithApplication adds -a twice📎
Description
In OSX.openFileWithApplication, the command list appends -a  and filePath twice, which can
produce an invalid open invocation. This can prevent opening the PDF (and thus page-jump behavior)
when a non-browser, non-Skim application is configured.
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[R57-80]

+        if (application != null && !application.isEmpty()) {
+            command.add("-a");
+            command.add(application);
+        }
+        command.add(filePath);
+
+        if (pageNumber > 1 && appNameLower.contains("skim")) {
+            String appleScript = String.format(
+                    "tell application \"Skim\"\n" +
+                            "  activate\n" +
+                            "  set myDoc to open POSIX file \"%s\"\n" +
+                            "  tell myDoc to go to page %d\n" +
+                            "end tell", filePath, pageNumber);
+
+            new ProcessBuilder("/usr/bin/osascript", "-e", appleScript).start();
+            return;
+        }
+
+        if (application != null && !application.isEmpty()) {
+            command.add("-a");
+            command.add(application);
+        }
+        command.add(filePath);
+        new ProcessBuilder(command).start();
Evidence
Compliance requires PDF opening to support jumping to the first page derived from pages; if the
external-viewer command construction is wrong, the open-and-jump flow can fail entirely. The added
code builds the open command by adding -a  and filePath twice before starting the process.

PDF opening: offer jump-to-first-page based on the entry's pages field
Cross-referenced PDF opening: open parent's attached PDF and jump to child's pages target
jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[57-80]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`OSX.openFileWithApplication` builds the `/usr/bin/open` command by adding the application (`-a <application>`) and `filePath` twice, producing a duplicated argument list.
## Issue Context
This method is used for opening files with a configured application, including the new page-jump behavior. Duplicated args can cause the external open to fail or behave unpredictably.
## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[57-80]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


12. Evince page-label mismatch🐞
Description
NativeDesktop converts logical page numbers to physical page numbers for PDFs, but Linux passes
that (physical) number to evince using --page-label, which targets page labels rather than
physical indices. For PDFs with front-matter/custom labels, this opens the wrong page (or fails to
find the intended label).
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[R118-132]

+    private static void addPdfPageArguments(List<String> command, String application, String filePath, int pageNumber) {
+        if (pageNumber <= 1 || !isPdfPath(filePath)) {
+            return;
+        }
+
+        String executable = Path.of(application).getFileName().toString().toLowerCase(Locale.ROOT);
+        if (executable.contains("evince")) {
+            command.add("--page-label=" + pageNumber);
+        } else if (executable.contains("okular")) {
+            command.add("-p");
+            command.add(String.valueOf(pageNumber));
+        } else if (executable.contains("zathura")) {
+            command.add("-P");
+            command.add(String.valueOf(pageNumber));
+        }
Evidence
NativeDesktop.resolvePageNumberForOpen uses PdfPageLabelResolver which is explicitly defined as
logical→physical conversion. Linux then uses evince’s --page-label= flag, which (by its naming and
usage) expects a label string; passing a physical page number after conversion breaks the mapping
when labels differ from physical order.

jabgui/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java[187-203]
jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[118-132]
jablib/src/main/java/org/jabref/logic/pdf/PdfPageLabelResolver.java[20-42]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Linux uses `--page-label` for evince, but the page number is pre-resolved to a *physical* page in `NativeDesktop`. That means evince receives the wrong value when labels != physical indices (exactly the scenario this PR aims to improve).
### Issue Context
- `NativeDesktop.resolvePageNumberForOpen` currently always converts logical→physical for PDFs.
- Linux/evince path uses `--page-label`, which should be fed the logical label, not the physical page.
### Fix Focus Areas
- Move the logical→physical translation decision into the OS/viewer-specific layer (so evince can keep logical labels while okular/zathura can use physical indices), OR
- Keep `NativeDesktop` as-is but change evince invocation to use an argument that targets physical indices (if available in your supported command set).
- jabgui/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java[193-203]
- jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[118-142]
- jablib/src/main/java/org/jabref/logic/pdf/PdfPageLabelResolver.java[20-42]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


13. macOS viewer preference bypass🐞
Description
OSX.openFile short-circuits for PDFs with pageNumber>1 and opens via Chrome/Edge or browser URL,
skipping the configured ExternalFileType application entirely. This changes user-visible behavior by
ignoring the preferred PDF viewer even when one is configured.
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[R29-47]

+    public void openFile(String filePath, String fileType, ExternalApplicationsPreferences externalApplicationsPreferences, int pageNumber) throws IOException {
+        if (isPdf(fileType) && pageNumber > 1) {
+            String fileUrlWithPage = Path.of(filePath).toUri().toString() + "#page=" + pageNumber;
+
+            String chromeBinary = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
+            String edgeBinary = "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge";
+
+            if (Files.exists(Path.of(chromeBinary))) {
+                new ProcessBuilder(chromeBinary, fileUrlWithPage).start();
+                return;
+            }
+            if (Files.exists(Path.of(edgeBinary))) {
+                new ProcessBuilder(edgeBinary, fileUrlWithPage).start();
+                return;
+            }
+
+            NativeDesktop.openBrowser(fileUrlWithPage, externalApplicationsPreferences);
+            return;
+        }
Evidence
The early-return branch for PDFs with pageNumber>1 executes before ExternalFileTypes lookup;
therefore the configured openWithApplication is never consulted for page jumps. The configured
application path is only reached after this early return, making it unreachable for the page-jump
case.

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[28-59]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
On macOS, `OSX.openFile(..., pageNumber)` bypasses the user-configured PDF application when `pageNumber > 1`, forcing Chrome/Edge or a browser-based `file://...#page=` open.
### Issue Context
The preference-respecting logic (`ExternalFileTypes.getExternalFileTypeByExt` and `openFileWithApplication`) is currently unreachable in the `pageNumber > 1` PDF case due to an early return.
### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[28-59]
### Suggested fix approach
1. Resolve the configured `ExternalFileType` first.
2. If an `openWithApplication` is configured, attempt `openFileWithApplication(filePath, application, pageNumber)`.
3. Only fall back to the browser hash jump strategy if no app is configured (or if you explicitly decide the configured app cannot support page jumps).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


14. openFileWithApplication adds -a twice📎
Description
In OSX.openFileWithApplication, the command list appends -a  and filePath twice, which can
produce an invalid open invocation. This can prevent opening the PDF (and thus page-jump behavior)
when a non-browser, non-Skim application is configured.
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[R57-80]

+        if (application != null && !application.isEmpty()) {
+            command.add("-a");
+            command.add(application);
+        }
+        command.add(filePath);
+
+        if (pageNumber > 1 && appNameLower.contains("skim")) {
+            String appleScript = String.format(
+                    "tell application \"Skim\"\n" +
+                            "  activate\n" +
+                            "  set myDoc to open POSIX file \"%s\"\n" +
+                            "  tell myDoc to go to page %d\n" +
+                            "end tell", filePath, pageNumber);
+
+            new ProcessBuilder("/usr/bin/osascript", "-e", appleScript).start();
+            return;
+        }
+
+        if (application != null && !application.isEmpty()) {
+            command.add("-a");
+            command.add(application);
+        }
+        command.add(filePath);
+        new ProcessBuilder(command).start();
Evidence
Compliance requires PDF opening to support jumping to the first page derived from pages; if the
external-viewer command construction is wrong, the open-and-jump flow can fail entirely. The added
code builds the open command by adding -a  and filePath twice before starting the process.

PDF opening: offer jump-to-first-page based on the entry's pages field
Cross-referenced PDF opening: open parent's attached PDF and jump to child's pages target
jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[57-80]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`OSX.openFileWithApplication` builds the `/usr/bin/open` command by adding the application (`-a <application>`) and `filePath` twice, producing a duplicated argument list.
## Issue Context
This method is used for opening files with a configured application, including the new page-jump behavior. Duplicated args can cause the external open to fail or behave unpredictably.
## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[57-80]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


15. Evince page-label mismatch🐞
Description
NativeDesktop converts logical page numbers to physical page numbers for PDFs, but Linux passes
that (physical) number to evince using --page-label, which targets page labels rather than
physical indices. For PDFs with front-matter/custom labels, this opens the wrong page (or fails to
find the intended label).
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[R118-132]

+    private static void addPdfPageArguments(List<String> command, String application, String filePath, int pageNumber) {
+        if (pageNumber <= 1 || !isPdfPath(filePath)) {
+            return;
+        }
+
+        String executable = Path.of(application).getFileName().toString().toLowerCase(Locale.ROOT);
+        if (executable.contains("evince")) {
+            command.add("--page-label=" + pageNumber);
+        } else if (executable.contains("okular")) {
+            command.add("-p");
+            command.add(String.valueOf(pageNumber));
+        } else if (executable.contains("zathura")) {
+            command.add("-P");
+            command.add(String.valueOf(pageNumber));
+        }
Evidence
NativeDesktop.resolvePageNumberForOpen uses PdfPageLabelResolver which is explicitly defined as
logical→physical conversion. Linux then uses evince’s --page-label= flag, which (by its naming and
usage) expects a label string; passing a physical page number after conversion breaks the mapping
when labels differ from physical order.

jabgui/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java[187-203]
jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[118-132]
jablib/src/main/java/org/jabref/logic/pdf/PdfPageLabelResolver.java[20-42]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Linux uses `--page-label` for evince, but the page number is pre-resolved to a *physical* page in `NativeDesktop`. That means evince receives the wrong value when labels != physical indices (exactly the scenario this PR aims to improve).
### Issue Context
- `NativeDesktop.resolvePageNumberForOpen` currently always converts logical→physical for PDFs.
- Linux/evince path uses `--page-label`, which should be fed the logical label, not the physical page.
### Fix Focus Areas
- Move the logical→physical translation decision into the OS/viewer-specific layer (so evince can keep logical labels while okular/zathura can use physical indices), OR
- Keep `NativeDesktop` as-is but change evince invocation to use an argument that targets physical indices (if available in your supported command set).
- jabgui/src/main/java/org/jabref/gui/desktop/os/NativeDesktop.java[193-203]
- jabgui/src/main/java/org/jabref/gui/desktop/os/Linux.java[118-142]
- jablib/src/main/java/org/jabref/logic/pdf/PdfPageLabelResolver.java[20-42]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


16. macOS viewer preference bypass🐞
Description
OSX.openFile short-circuits for PDFs with pageNumber>1 and opens via Chrome/Edge or browser URL,
skipping the configured ExternalFileType application entirely. This changes user-visible behavior by
ignoring the preferred PDF viewer even when one is configured.
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[R29-47]

+    public void openFile(String filePath, String fileType, ExternalApplicationsPreferences externalApplicationsPreferences, int pageNumber) throws IOException {
+        if (isPdf(fileType) && pageNumber > 1) {
+            String fileUrlWithPage = Path.of(filePath).toUri().toString() + "#page=" + pageNumber;
+
+            String chromeBinary = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
+            String edgeBinary = "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge";
+
+            if (Files.exists(Path.of(chromeBinary))) {
+                new ProcessBuilder(chromeBinary, fileUrlWithPage).start();
+                return;
+            }
+            if (Files.exists(Path.of(edgeBinary))) {
+                new ProcessBuilder(edgeBinary, fileUrlWithPage).start();
+                return;
+            }
+
+            NativeDesktop.openBrowser(fileUrlWithPage, externalApplicationsPreferences);
+            return;
+        }
Evidence
The early-return branch for PDFs with pageNumber>1 executes before ExternalFileTypes lookup;
therefore the configured openWithApplication is never consulted for page jumps. The configured
application path is only reached after this early return, making it unreachable for the page-jump
case.

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[28-59]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
On macOS, `OSX.openFile(..., pageNumber)` bypasses the user-configured PDF application when `pageNumber > 1`, forcing Chrome/Edge or a browser-based `file://...#page=` open.
### Issue Context
The preference-respecting logic (`ExternalFileTypes.getExternalFileTypeByExt` and `openFileWithApplication`) is currently unreachable in the `pageNumber > 1` PDF case due to an early return.
### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[28-59]
### Suggested fix approach
1. Resolve the configured `ExternalFileType` first.
2. If an `openWithApplication` is configured, attempt `openFileWithApplication(filePath, application, pageNumber)`.
3. Only fall back to the browser hash jump strategy if no app is configured (or if you explicitly decide the configured app cannot support page jumps).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


17. openFileWithApplication adds -a twice📎
Description
In OSX.openFileWithApplication, the command list appends -a  and filePath twice, which can
produce an invalid open invocation. This can prevent opening the PDF (and thus page-jump behavior)
when a non-browser, non-Skim application is configured.
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[R57-80]

+        if (application != null && !application.isEmpty()) {
+            command.add("-a");
+            command.add(application);
+        }
+        command.add(filePath);
+
+        if (pageNumber > 1 && appNameLower.contains("skim")) {
+            String appleScript = String.format(
+                    "tell application \"Skim\"\n" +
+                            "  activate\n" +
+                            "  set myDoc to open POSIX file \"%s\"\n" +
+                            "  tell myDoc to go to page %d\n" +
+                            "end tell", filePath, pageNumber);
+
+            new ProcessBuilder("/usr/bin/osascript", "-e", appleScript).start();
+            return;
+        }
+
+        if (application != null && !application.isEmpty()) {
+            command.add("-a");
+            command.add(application);
+        }
+        command.add(filePath);
+        new ProcessBuilder(command).start();
Evidence
Compliance requires PDF opening to support jumping to the first page derived from pages; if the
external-viewer command construction is wrong, the open-and-jump flow can fail entirely. The added
code builds the open command by adding -a  and filePath twice before starting the process.

PDF opening: offer jump-to-first-page based on the entry's pages field
Cross-referenced PDF opening: open parent's attached PDF and jump to child's pages target
jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[57-80]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`OSX.openFileWithApplication` builds the `/usr/bin/open` command by adding the application (`-a <application>`) and `filePath` twice, producing a duplicated argument list.
## Issue Context
This method is used for opening files with a configured application, including the new page-jump behavior. Duplicated args can cause the external open to fail or behave unpredictably.
## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[57-80]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


18. openFileWithApplication adds -a twice📎
Description
In OSX.openFileWithApplication, the command list appends -a  and filePath twice, which can
produce an invalid open invocation. This can prevent opening the PDF (and thus page-jump behavior)
when a non-browser, non-Skim application is configured.
Code

jabgui/src/main/java/org/jabref/gui/desktop/os/OSX.java[R57-80]

+        if (application != null && !application.isEmpty()) {
+            command.add("-a");
+            command.add(application);
+        }
+        command.add(filePath);
+
+        if (pageNumber > 1 && appNameLower.contains("skim")) {
+            String appleScript = String.format(
+                    "tell application \"Skim\"\n" +
+                            "  activate\n" +
+                            "  set myDoc to open POSIX file \"%s\"\n" +
+                            "  tell myDoc to go to page %d\n" +
+                            "end tell", filePath, pageNumber);
+
+            new ProcessBuilder("/usr/bin/osascript", "-e", appleScript).start();
+            return;
+        }
+
+        if (application != null && !application.isEmpty()) {
+            command.add("-a");
+            command.add(application);
+        }
+  ...

@github-actions github-actions bot added the status: changes-required Pull requests that are not yet complete label Apr 7, 2026
@Sherry0121-AC Sherry0121-AC force-pushed the fix-8128-crossref-pages branch from fe94d90 to 969f699 Compare April 7, 2026 16:10
@github-actions github-actions bot added status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Apr 8, 2026
@Sherry0121-AC
Copy link
Copy Markdown
Author

Sherry0121-AC commented Apr 8, 2026

Hi @koppor @calixtus , just a gentle ping on this PR as all CI checks are green now. Please let me know if any further changes are required from my side. Thanks for your time!

Copy link
Copy Markdown
Member

@koppor koppor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For what is this PR? University credits or GSoC?

Copy link
Copy Markdown
Member

@calixtus calixtus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very quick first look and some preliminary comments

@github-actions github-actions bot added status: changes-required Pull requests that are not yet complete and removed status: no-bot-comments labels Apr 12, 2026
@github-actions github-actions bot added status: no-bot-comments status: changes-required Pull requests that are not yet complete and removed status: changes-required Pull requests that are not yet complete status: no-bot-comments labels Apr 13, 2026
@github-actions github-actions bot added status: no-bot-comments status: changes-required Pull requests that are not yet complete and removed status: changes-required Pull requests that are not yet complete status: no-bot-comments labels Apr 13, 2026
@github-actions github-actions bot added status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Apr 13, 2026
@github-actions github-actions bot added status: changes-required Pull requests that are not yet complete status: no-bot-comments and removed status: no-bot-comments status: changes-required Pull requests that are not yet complete labels Apr 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for multi-paper PDFs (AKA proceedings)

4 participants