Skip to content

Add cursor area awareness to CSL citations#15728

Merged
Siedlerchr merged 7 commits into
JabRef:mainfrom
pluto-han:fix-for-issue-15701
May 14, 2026
Merged

Add cursor area awareness to CSL citations#15728
Siedlerchr merged 7 commits into
JabRef:mainfrom
pluto-han:fix-for-issue-15701

Conversation

@pluto-han

Copy link
Copy Markdown
Collaborator

Related issues and pull requests

Closes #15701

PR Description

This PR adds a new function CSLCitationRanges which collects the ranges of existing CSL citations, so that CSL citations can also have cursor area awareness.

Steps to test

  1. Open JabRef and a LibreOffice Writer document
  2. Open Chocolate.bib in JabRef
  3. Connect to the running LO instance
  4. Select any CSL
  5. Select any entry and cite it in the document
  6. Click anywhere in between the citation area (can be visualized by ctrl+f8)
  7. Select any other entry and try to cite
  8. Observe the following error ("the cursor is in a protected area"):
image

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
  • 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 for up to dateness and submitted a pull request to our user documentation repository

@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Add cursor area awareness to CSL citations

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Add cursor area awareness to CSL citations
• Implement CSLCitationRanges() method for CSL style detection
• Refactor citationRanges() to JStyleCitationRanges() for clarity
• Pass OOStyle parameter to overlap checking logic
Diagram
flowchart LR
  A["checkRangeOverlapsWithCursor"] -->|receives OOStyle| B["Style type check"]
  B -->|JStyle| C["JStyleCitationRanges"]
  B -->|CSL| D["CSLCitationRanges"]
  C -->|returns ranges| E["Overlap detection"]
  D -->|returns ranges| E
  E -->|prevents cursor| F["Protected citation areas"]
Loading

Grey Divider

File Changes

1. jabgui/src/main/java/org/jabref/gui/openoffice/OOBibBase.java ✨ Enhancement +4/-3

Pass OOStyle parameter to overlap checking

• Updated checkRangeOverlapsWithCursor() method signature to accept OOStyle parameter
• Pass style argument when calling checkRangeOverlapsWithCursor() in guiActionInsertEntry()

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


2. jablib/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java ✨ Enhancement +38/-5

Add CSL citation range detection and style-aware logic

• Add imports for JStyle and OOStyle classes
• Add import for UnoReferenceMark utility class
• Rename citationRanges() to JStyleCitationRanges() for JStyle-specific logic
• Implement new CSLCitationRanges() method to collect CSL citation ranges using reference marks
• Update checkRangeOverlapsWithCursor() to accept OOStyle parameter and conditionally call
 appropriate citation ranges method
• Update checkRangeOverlaps() to use renamed JStyleCitationRanges() method
• Change description from group.groupId.citationGroupIdAsString() to range.getString() for
 actual citation text

jablib/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java


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

Document citation integrity fix

• Add entry documenting fix for issue #15701 where users could cite inside other citations

CHANGELOG.md


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Optional get() after isEmpty() ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
CSLCitationRanges uses if (range.isEmpty()) continue; followed by multiple range.get() calls,
which is non-idiomatic Optional control flow and risks future unsafe access if the code changes.
Code

jablib/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java[R302-312]

+        for (String name : UnoReferenceMark.getListOfNames(doc)) {
+            Optional<XTextRange> range = UnoReferenceMark.getAnchor(doc, name);
+            if (range.isEmpty()) {
+                continue;
+            }
+
+            String description = range.get().getString();
+            result.add(new RangeForOverlapCheck<>(range.get(),
+                    new CitationGroupId(name),
+                    RangeForOverlapCheck.REFERENCE_MARK_KIND,
+                    description));
Evidence
PR Compliance ID 29 forbids new/modified code that uses isPresent/isEmpty checks followed by
get(). The added loop checks range.isEmpty() and then calls range.get() to access the value.

jablib/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java[302-312]
Best Practice: Learned patterns

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

## Issue description
New code uses `Optional.isEmpty()` and then calls `Optional.get()` multiple times. This is discouraged; prefer `ifPresent`, `map`, or unwrapping once to a local variable.
## Issue Context
This occurs in the newly added `CSLCitationRanges` method while retrieving a reference mark anchor.
## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java[302-312]

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


2. Protects non-JabRef marks ✓ Resolved 🐞 Bug ≡ Correctness
Description
OOFrontend.CSLCitationRanges marks every LibreOffice reference mark as a protected citation range,
so inserting a CSL citation can fail when the cursor is inside an unrelated reference mark
(user-created cross-references/bookmarks or other extensions’ marks). This can create false “cursor
is in a protected area” errors and prevent valid citation insertion.
Code

jablib/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java[R295-313]

+    private List<RangeForOverlapCheck<CitationGroupId>> CSLCitationRanges(XTextDocument doc)
+            throws
+            NoDocumentException,
+            WrappedTargetException {
+
+        List<RangeForOverlapCheck<CitationGroupId>> result = new ArrayList<>();
+
+        for (String name : UnoReferenceMark.getListOfNames(doc)) {
+            Optional<XTextRange> range = UnoReferenceMark.getAnchor(doc, name);
+            if (range.isEmpty()) {
+                continue;
+            }
+
+            String description = range.get().getString();
+            result.add(new RangeForOverlapCheck<>(range.get(),
+                    new CitationGroupId(name),
+                    RangeForOverlapCheck.REFERENCE_MARK_KIND,
+                    description));
+        }
Evidence
The new CSL range collector enumerates all reference marks without a JabRef-specific filter, while
existing JabRef code paths explicitly filter reference marks to JabRef-owned naming patterns before
treating them as citations/managed marks.

jablib/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java[295-316]
jablib/src/main/java/org/jabref/model/openoffice/uno/UnoReferenceMark.java[42-54]
jablib/src/main/java/org/jabref/logic/openoffice/backend/Backend52.java[53-61]
jablib/src/main/java/org/jabref/logic/openoffice/oocsltext/CSLReferenceMarkManager.java[136-164]

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

## Issue description
`CSLCitationRanges` currently iterates over *all* LibreOffice reference marks (`UnoReferenceMark.getListOfNames`) and treats them as citation-protected ranges. This can block citation insertion whenever the cursor happens to be inside any unrelated reference mark.
### Issue Context
Other parts of the codebase already filter reference marks to JabRef-owned ones (both for JStyle and CSL flows). `CSLCitationRanges` should similarly only include JabRef CSL citation reference marks (and optionally also JabRef JStyle marks if you want protection across style types).
### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java[295-316]
### Suggested approach
- Filter `UnoReferenceMark.getListOfNames(doc)` down to JabRef CSL citation marks only (e.g., using the same token/prefix logic as `CSLReferenceMarkManager.readAndUpdateExistingMarks`: split by space, require `parts.length >= 3`, `parts[0].startsWith(ReferenceMark.PREFIXES[0])` and `parts[1].startsWith(ReferenceMark.PREFIXES[1])`).
- Keep skipping marks with missing anchors.
- (Optional hardening) If you want cursor protection to work even in mixed documents, build the protected list as **(JStyleCitationRanges + filtered CSLCitationRanges)** instead of relying on unfiltered “all reference marks” behavior.

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



Remediation recommended

3. Uppercase method names added ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The new methods JStyleCitationRanges and CSLCitationRanges start with an uppercase letter, which
violates Java/JabRef lowerCamelCase naming conventions and reduces readability/consistency.
Code

jablib/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java[R275-279]

/// @return A RangeForOverlapCheck for each citation group. result.size() == nRefMarks
-    public List<RangeForOverlapCheck<CitationGroupId>> citationRanges(XTextDocument doc)
+    public List<RangeForOverlapCheck<CitationGroupId>> JStyleCitationRanges(XTextDocument doc)
       throws
       NoDocumentException,
       WrappedTargetException {
Evidence
PR Compliance ID 3 requires following JabRef naming conventions. The PR introduces/renames methods
to JStyleCitationRanges and CSLCitationRanges, both beginning with an uppercase letter.

AGENTS.md
jablib/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java[275-316]

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

## Issue description
Newly introduced method names use UpperCamelCase (`JStyleCitationRanges`, `CSLCitationRanges`) instead of Java/JabRef lowerCamelCase, reducing codebase consistency.
## Issue Context
These methods are new/modified in the OpenOffice frontend logic and should follow JabRef naming conventions.
## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java[275-316]

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


4. Changelog entry is unpolished ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The new CHANGELOG entry contains grammatical issues (e.g., another citations, which break) and
reads unprofessionally for end-user documentation.
Code

CHANGELOG.md[59]

+- We fixed an issue where users could cite inside another citations, which break the integrity. [#15701](https://github.com/JabRef/jabref/issues/15701)
Evidence
PR Compliance ID 28 requires professional, consistent user-facing documentation. The added bullet
has clear grammar issues and awkward phrasing.

CHANGELOG.md[59-59]
Best Practice: Learned patterns

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

## Issue description
The added CHANGELOG entry has grammatical errors and should be rewritten to be professional and user-facing.
## Issue Context
CHANGELOG entries are user-facing documentation and should be polished and consistent.
## Fix Focus Areas
- CHANGELOG.md[59-59]

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


Grey Divider

Qodo Logo

Comment thread jablib/src/main/java/org/jabref/logic/openoffice/frontend/OOFrontend.java Outdated

@subhramit subhramit left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good!
As a result of this, I think you have already started seeing the code unification that can be achieved eventually when we refactor in future, due to functional unifications like these. The split style-specific checkers will reduce to one function once we unify the backend.

Comment thread CHANGELOG.md Outdated
Co-authored-by: Subhramit Basu <subhramit.bb@live.in>
@pluto-han

pluto-han commented May 12, 2026

Copy link
Copy Markdown
Collaborator Author

Writing good, specific changelog entries:

Thank you, that looks better!

@pluto-han

Copy link
Copy Markdown
Collaborator Author

The split style-specific checkers will reduce to one function once we unify the backend.

Do you mean after "unification", originally separated functions would be unified into one function? Similar to :

        List<RangeForOverlapCheck<CitationGroupId>> citationRanges;
        if (style instanceof JStyle) {
            citationRanges = JStyleCitationRanges(doc);
        } else {
            citationRanges = CSLCitationRanges(doc);
        }

@subhramit

Copy link
Copy Markdown
Member

Do you mean after "unification", originally separated functions would be unified into one function? Similar to :

Yes - think of it this way. The functionality is the same - there is a range of citation marker to be guarded, irrespective of it being a CSL or JStyle. So eventually this if-else can be let go of, and just one function can embed common logic with respect to either a style interface (which covers both style types, think OOStyle), or maybe even not be dependent on the style parameter at all anymore.


/// @return A RangeForOverlapCheck for each citation group. result.size() == nRefMarks
public List<RangeForOverlapCheck<CitationGroupId>> citationRanges(XTextDocument doc)
public List<RangeForOverlapCheck<CitationGroupId>> JStyleCitationRanges(XTextDocument doc)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lowercase method names

return result;
}

private List<RangeForOverlapCheck<CitationGroupId>> CSLCitationRanges(XTextDocument doc)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lowercase method names

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I think then cslCitationRanges would be better than cSLCitationRanges, in terms of readability.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

yep cslCitationRanges would be fine

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

even better if it can be an action verb instead of a noun. Maybe just add a "get" in front

@Siedlerchr

Copy link
Copy Markdown
Member

Is the qodo concern valid? Do we check if it's a CSL or jstyle mark or will it check all kind of marks?

@pluto-han

pluto-han commented May 13, 2026

Copy link
Copy Markdown
Collaborator Author

Is the qodo concern valid? Do we check if it's a CSL or jstyle mark or will it check all kind of marks?

No, JabRef does not check the citation style. Maybe we can add a filter in cslCitationRanges that only allows CSL citations

@Siedlerchr Siedlerchr added this pull request to the merge queue May 14, 2026
@github-actions github-actions Bot added the status: to-be-merged PRs which are accepted and should go into the merge-queue. label May 14, 2026
Merged via the queue into JabRef:main with commit 6483001 May 14, 2026
57 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: libre-office status: no-bot-comments status: to-be-merged PRs which are accepted and should go into the merge-queue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add cursor area awareness (guards) to CSL citations

3 participants