Preserve syntax highlighting when copying BibTeX in Source tab (#17392) by adityamukesh · Pull Request #17441 · JabRef/jabref · GitHub
Skip to content

Preserve syntax highlighting when copying BibTeX in Source tab (#17392) - #17441

Open
adityamukesh wants to merge 20 commits into
JabRef:mainfrom
adityamukesh:fix-17392-copy-syntax-highlighting
Open

adityamukesh wants to merge 20 commits into
JabRef:mainfrom
adityamukesh:fix-17392-copy-syntax-highlighting

Conversation

@adityamukesh

@adityamukesh adityamukesh commented Oct 11, 2026 •

Copy link
Copy Markdown

Summary

Copying from the BibTeX source tab now puts monospace HTML and RTF on the clipboard, so pasted source keeps its indentation, alignment, and syntax colors in rich-text applications.

BibTeXCodeArea uses BibTeXCodeTextModel, which replaces the model's default HTML and RTF export handlers. BibTeXHtmlExportFormatHandler writes one <pre> block with a monospace font, and BibTeXRtfExportFormatHandler writes Courier New (marked \fmodern, so other applications fall back to a monospace font) with \line breaks. Both keep the colors of the current theme. Because the handlers belong to the model, every copy route uses them: Ctrl+C, Ctrl+Insert, cut, and the context menu, in the Source tab, the citation relations popup, and the import dialog.

The default HTML export already put syntax colors on the clipboard, but wrote one paragraph per line in a proportional font. Pages pastes the RTF version whenever it is on the clipboard, so the RTF needed the same fix.

Analogies

Like honey retaining its color and chocolate retaining its character, copied BibTeX keeps its styling; the moon represents theme-dependent appearance.

Steps to test

  1. Open a library in JabRef with the example entry from issue #17392.
  2. Open the BibTeX source tab, select all with Ctrl + A (or Cmd + A on macOS), and copy with Ctrl + C or Cmd + C.
  3. Paste into a word processor such as LibreOffice Writer, Microsoft Word, or Pages. The source should be in a monospace font, with its indentation, the = signs lined up, and the syntax colors. Repeat with the Source tab's context menu and with Ctrl + Insert.
  4. Repeat with a selection starting or ending inside the citation key. The selection should keep its displayed color.
  5. Paste the source into a Markdown field in JabRef. It becomes a fenced code block with the exact source text.
  6. Copy a selection containing &, <, >, {, }, \, and non-ASCII characters. The pasted text should match the source.

Source tab with the example entry (JabRef in dark theme):

Source tab with the example entry in dark theme

Before, on main: copied in Light theme and pasted into Pages. The font is proportional, so the = signs do not line up:

Source copied from main and pasted into Pages

After, on this branch: copied in Light theme and pasted into Pages:

Source copied from this branch and pasted into Pages

Both screenshots were made by copying through BibTeXCodeArea with JabRef's Light theme stylesheets onto the real macOS clipboard, then pasting into Pages. In dark theme the copied colors are the dark-theme colors, so field values are near-white on a white page; whether pasted text should use a fixed light palette is an open question.

Related issues and pull requests

Closes #17392

Verification

c659f5831 replaces the earlier copy hooks with the model-level HTML export, 7d40fbb4d adds the RTF export, and 860f74424 applies the formatter's line split that the format check asked for.

On 7d40fbb4d, locally with Java 25: :jabgui:checkstyleMain and :jabgui:checkstyleTest pass, and BibTeXHtmlExportFormatHandlerTest (5 tests), BibTeXRtfExportFormatHandlerTest (3 tests), BibTeXHighlighterTest, and the entryeditor, importer, and fieldeditors GUI tests pass. The HTML tests fail when the default HTML handler is used instead. Full CI on this head is in progress.

The current head has not yet been tested by hand in running JabRef; the screenshots come from the same BibTeXCodeArea copy, as described above.

AI usage

The original description disclosed Google Antigravity (Gemini 2.5), classified as AIL2. OpenAI Codex also assisted with the subsequent PR work and this description update (the exact model identifier for this session is unavailable). The exact model identifiers for the earlier tools and the final influence classification still require contributor confirmation. Claude Code (model claude-opus-5-5) assisted with merging main and restoring the BibTeXHighlighter import in 48e7516, with sorting the CHANGELOG.md entry in a060758, with the matching updates of this description and checklist, with drafting the re-review comment, and with capturing the pasted-result screenshot. It also wrote c659f5831 (model-level HTML export, replacing the copy hooks) and 7d40fbb4d (monospace RTF export) with their tests, made the before/after screenshots, rewrote this description, and drafted the reply to the review.

The contributor must confirm review, understanding, and ownership of the current changes before the reviewed-policy compliance tag is restored. The full checklist below records verified items and outstanding work; it is not a claim that the PR is fully merge-ready.

AI CHECKLIST.md walkthrough

Checked against the current PR diff and the linked CI results. Verification-command items marked complete use equivalent CI gates; the library check excludes lint tasks that passed in separate jobs, and OpenRewrite ran with a clean-worktree check. Those full CI gates cover the earlier head 69a32d8; the local checks of 7d40fbb4d are documented above, and full CI of the current head 860f74424 is in progress. Unchecked items require further verification or contributor confirmation.

Code checklist

[!IMPORTANT]
This is a mandatory final gate. When the implementation is finished and before you open a PR, work through every box below and tick it. If a box cannot be ticked, fix the code first; mark a box [/] only if the point genuinely does not apply.

AGENTS.md describes how to write code while developing — this file confirms the finished result. Do not skip the checklist and do not skip individual points.

1. Code self-review

Read your own diff once, top to bottom, and confirm each point.

Nullability and control flow

  • No == null / != null checks — JSpecify annotations (@NullMarked, @Nullable, @NonNull) used instead.
  • No Objects.requireNonNull(...) — nullability expressed via JSpecify annotations.
  • New classes annotated with @NullMarked (org.jspecify.annotations.NullMarked).
  • [/] New packages annotated with @NullMarked (org.jspecify.annotations.NullMarked).
  • Optional consumed with ifPresent / ifPresentOrElse / map / orElseThrow — never orElse(unusedValue) nor an isPresent() + get() block.
  • [/] StringUtil.isBlank(...) used instead of s == null || s.isBlank().

Exceptions

  • No catch (Exception e) — only specific exceptions are caught.
  • No throw new RuntimeException(...) / IllegalStateException(...) — these tear down the whole application.
  • Logged exceptions are passed as the last logger argument (LOGGER.info("...", e)), not concatenated into the message string.

Style and idioms

  • [/] New BibEntry objects built with withers (withField, not setField).
  • Modern Java used: List.of() / Map.of() / Set.of(), Path.of(), SequencedCollection / SequencedSet, text blocks.
  • [/] Regexes use a precompiled Pattern.compile(...) constant, not String.matches(...).
  • Keep alphabetical ordering when adding variables or enum items.
  • [/] Background work uses org.jabref.logic.util.BackgroundTask, not new Thread().
  • No commented-out code, no trivial comments restating the code, no AI-disclosure comments in source.
  • Markdown Javadoc (///) uses Markdown syntax, not JavaDoc inline tags: `code` instead of {@code}, [ClassName] instead of {@link}.

User-facing text

  • [/] All user-facing text localized (Localization.lang in Java, % prefix in FXML).
  • [/] Sentence case (not Title Case); no trailing !; labels do not end with :.
  • [/] Variance expressed with placeholders ("...: %0"), not string concatenation.

Security

  • User-controlled data (request params, entry fields, file contents) is HTML-escaped before being written into any text/html response — including exception/error messages, not just the success body (XSS).

Tests

  • In case issue lists an example, this concrete example is covered by a test case.
  • [/] Behavior changes in org.jabref.model / org.jabref.logic have added or updated tests.
  • Tests assert object contents (assertEquals), use plain JUnit asserts (not AssertJ), have no @DisplayName, do not catch exceptions (let them propagate so JUnit reports setup/teardown failures directly), and use @TempDir instead of manual temp directories.
  • [/] Fetcher tests hit the live endpoints — the remote API is not mocked or stubbed (automated-review suggestions to mock it are rejected on purpose).

2. Verification commands

Run in this order — cheapest first. Each must pass.

  • ./gradlew :jablib:check (or ./gradlew check for all modules).
  • ./gradlew checkstyleMain checkstyleTest checkstyleJmh.
  • ./gradlew modernizer.
  • ./gradlew --no-configuration-cache :rewriteDryRun reports no changes (run ./gradlew rewriteRun to fix).
  • ./gradlew javadoc.
  • npx markdownlint-cli2 "docs/**/*.md" "*.md" (only if Markdown changed).
  • npm ci && npm run textlint reports no misspellings (only if Markdown changed).
  • [/] Only if formatting is still off after rewriteRun: docker run -v $(pwd):/github/workspace ghcr.io/leventebajczi/intellij-format:master "*.java" "" ".idea/codeStyles/Project.xml".

3. Documentation

  • CHANGELOG.md entry added if the change is visible to the user (end-user wording, no extra blank lines, sorted in next to existing entries about the same component/feature). Link the issue if one exists; link the PR only when no issue exists. Use TODO as the placeholder when neither is known yet — never a fake number. No entry for fixes to changes that were themselves introduced after the last release (feature only in ## [Unreleased]) — update the existing unreleased entry instead if needed.
  • Searched jabref/issues and jabref-koppor/issues for a related issue; linked only on a confident match, otherwise kept TODO (no closes/fixes for merely-similar issues).
  • Requirement added to docs/requirements/<area>.md if the change is a new feature or significant bug fix (skip for refactors, minor fixes, and internal changes).
  • Developer documentation under docs/ updated if behavior or architecture changed.

4. Pull request

  • PR body built from .github/PULL_REQUEST_TEMPLATE.md, every section filled.
  • All checklist items kept and marked [x], [ ], or [/].
  • "Steps to test" is a numbered list with a cropped screenshot of the result for every visible change; no video (only allowed when another program is involved, e.g. drag and drop or push to an external application).
  • All HTML comments removed from the PR body.
  • [/] PR created with gh pr create --body-file <file> (not --body).
  • [/] If CHANGELOG.md used a TODO placeholder (no issue confidently identified yet — an existing issue link always stays), the PR was opened as draft, the placeholder was replaced with the real PR-number link after PR creation, committed and pushed, and only then was the PR marked ready for review. If an issue is identified or created later, the link is switched to the issue.

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • If AI tools were used, I disclosed them in the "AI usage" section and reviewed, understood, and take full ownership of all AI-generated code
  • 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 one sentence (max 20 words) to CHANGELOG.md describing the change from the user's point of view (if the 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

The existing copyright/license declaration is retained. The user documentation describes the Source tab but not copying from it, so nothing there is outdated. The AI influence level remains open.

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot added first contrib good first issue An issue intended for project-newcomers. Varies in difficulty. component: external-application-integration Ingegeration with TeXStudio, Acrobat Reader, ... status: changes-required Pull requests that are not yet complete labels Oct 11, 2026
@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Preserve BibTeX syntax highlighting when copying from the Source tab

🐞 Bug fix 🧪 Tests 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Copy BibTeX source as plain text and styled HTML so rich-text applications retain syntax
 highlighting.
• Handle both keyboard and context-menu copying while preserving ordinary copying in other code
 areas.
• Add exporter and keyboard tests, a requirement, and a changelog entry.
Diagram

graph TD
  K["Keyboard copy"] --> D{"BibTeX decorator?"} -->|yes| H["BibTeXHighlighter"] --> E["HTML exporter"] --> C["System clipboard"] --> P["Paste target"]
  M["Menu copy"] --> D
  D -->|no| C
  H -->|plain text| C
  E --> V["Veneer tokenizer"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Resolve active theme styles for HTML
  • ➕ Copied colors could match the user's current Source-tab theme.
  • ➖ Requires resolving JavaFX CSS into portable inline HTML styles and handling missing or changing theme values.

Recommendation: Keep the PR's tokenizer-based HTML export: inline styles make the result portable, and retaining plain text protects ordinary paste behavior. The fixed palette will not necessarily match the active theme; resolve theme styles only if exact visual fidelity is required.

Files changed (9) +303 / -1

Enhancement (1) +28 / -0
BibTeXStyleClass.javaMap BibTeX token categories to inline CSS +28/-0

Map BibTeX token categories to inline CSS

• Defines portable colors and font styles for HTML export, with a default for unrecognized token categories.

jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXStyleClass.java

Bug fix (4) +146 / -1
BibTeXHighlighter.javaCoordinate highlighted clipboard copying +35/-0

Coordinate highlighted clipboard copying

• Copies a nonempty CodeArea selection, then places its plain text and generated syntax-highlighted HTML on the system clipboard.

jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXHighlighter.java

BibTeXSyntaxHtmlExporter.javaRender selected BibTeX as styled HTML +96/-0

Render selected BibTeX as styled HTML

• Uses Veneer token regions to build escaped, monospace HTML with inline syntax styles. Handles gaps and overlapping or out-of-range regions.

jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXSyntaxHtmlExporter.java

SourceTab.javaRoute context-menu copying through the BibTeX highlighter +6/-1

Route context-menu copying through the BibTeX highlighter

• Uses highlighted copying when the Source tab has a BibTeX decorator and falls back to the CodeArea's ordinary copy otherwise.

jabgui/src/main/java/org/jabref/gui/entryeditor/SourceTab.java

CodeAreaKeyBindings.javaHandle copy shortcuts in code areas +9/-0

Handle copy shortcuts in code areas

• Routes BibTeX copy shortcuts through highlighted copying, preserves ordinary copying elsewhere, and consumes the handled event.

jabgui/src/main/java/org/jabref/gui/keyboard/CodeAreaKeyBindings.java

Tests (2) +120 / -0
BibTeXSyntaxHtmlExporterTest.javaTest HTML export and token styling +85/-0

Test HTML export and token styling

• Checks document structure, representative syntax styles, HTML escaping, empty input, and category-to-style mapping.

jabgui/src/test/java/org/jabref/gui/bibtexhighlighter/BibTeXSyntaxHtmlExporterTest.java

CodeAreaKeyBindingsTest.javaTest highlighted and fallback copy shortcuts +35/-0

Test highlighted and fallback copy shortcuts

• Verifies that copy shortcuts call the BibTeX highlighter when present, otherwise copy normally, and consume the event.

jabgui/src/test/java/org/jabref/gui/keyboard/CodeAreaKeyBindingsTest.java

Documentation (2) +9 / -0
CHANGELOG.mdRecord the rich-text copy fix +1/-0

Record the rich-text copy fix

• Adds a user-facing entry for preserved BibTeX syntax highlighting when copying into rich-text applications.

CHANGELOG.md

entry-editor.mdSpecify dual-format Source-tab copying +8/-0

Specify dual-format Source-tab copying

• Adds a traceable requirement for plain-text and inline-styled HTML clipboard content.

docs/requirements/entry-editor.md

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

qodo-free-for-open-source-projects Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (1) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Pasted colors differ from the Source tab 📎 Requirement gap ≡ Correctness
Description
getInlineCss() assigns fixed token colors and font styles instead of using the theme-dependent
styling visible in the Source tab. When a user copies source under a different or customized theme,
the pasted HTML can show different colors, and strings and other categories without an editor color
rule can gain one.
Code

jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXStyleClass.java[R47-50]

+            case STRING -> "color: #067d17;";
+            case NUMBER -> "color: #1750eb;";
+            case COMMENT -> "color: #8c8c8c; font-style: italic;";
+            case MACRO -> "color: #871094;";
Evidence
The editor applies syntax classes whose colors come from theme stylesheets; the base stylesheet
defines color rules only for keywords, fields, and cite keys, using theme variables. The clipboard
mapping instead assigns fixed inline colors to every listed category, and the exporter uses a fixed
hex value for default text color, so neither necessarily matches the rendered editor.

Preserve syntax highlighting when copying BibTeX to LibreOffice
jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXStyleClass.java[8-10]
jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXStyleClass.java[42-52]
jabgui/src/main/resources/org/jabref/gui/theme/internal/jabref-base.css[1735-1746]
jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXHighlighter.java[181-185]
jabgui/src/main/resources/org/jabref/gui/theme/internal/jabref-base.css[1731-1745]
jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXStyleClass.java[42-51]
jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXSyntaxHtmlExporter.java[70-73]

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

## Issue description
Clipboard HTML uses fixed token and default text colors that can diverge from the Source tab's theme-dependent styling and add colors to categories without an editor color rule.
## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXStyleClass.java[39-52]
- jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXSyntaxHtmlExporter.java[65-73]
- jabgui/src/main/resources/org/jabref/gui/theme/internal/jabref-base.css[1731-1746]
## Recommended Fix
Derive clipboard token and default text styles from the active editor theme where feasible, and avoid adding colors to categories that have no editor color rule. Test the exported styles against the displayed categories under differing themes.

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


2. Partial copies lose their original colors ✓ Resolved
Description
copyWithSyntaxHighlighting passes only the selected text to toHtml, which computes syntax
regions without the surrounding BibTeX source used by the editor. When a selection starts or ends
inside a highlighted token, such as a field value or citation key, the copied HTML can style those
characters differently from the Source tab.
Code

jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXHighlighter.java[95]

+                String html = BibTeXSyntaxHtmlExporter.toHtml(plainText, syntaxHighlighter);
Evidence
The editor classifies regions over the full assembled source, while the copy path supplies only the
selected substring to the exporter for classification. Because a fragment's classification can
depend on text outside the selection, re-tokenizing it cannot always reproduce the regions shown in
the editor.

Preserve syntax highlighting when copying BibTeX to LibreOffice
jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXHighlighter.java[90-96]
jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXSyntaxHtmlExporter.java[28-33]
jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXHighlighter.java[150-158]
jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXHighlighter.java[145-159]
jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXHighlighter.java[90-99]

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 exporter tokenizes selected BibTeX text independently, losing the surrounding context needed to preserve the Source tab's syntax classification.
## Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXHighlighter.java[85-99]
- jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXSyntaxHtmlExporter.java[28-59]
## Recommended Fix
Compute token regions over the complete source as the editor does, intersect them with the selection, and translate their offsets into the selected text before exporting only that text. Add tests for selections starting or ending inside highlighted tokens.

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


Grey Divider

Tip of the day
💡 Did you know, you can enable the Remediation agent and Qodo fixes findings in a dedicated fix PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXHighlighter.java Outdated
Comment thread jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXStyleClass.java Outdated
Comment thread jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXStyleClass.java Outdated
Comment thread jabgui/src/main/java/org/jabref/gui/keyboard/CodeAreaKeyBindings.java Outdated
Comment thread jabgui/src/main/java/org/jabref/gui/bibtexhighlighter/BibTeXHighlighter.java Outdated
@github-actions github-actions Bot added component: external-application-integration Ingegeration with TeXStudio, Acrobat Reader, ... and removed status: changes-required Pull requests that are not yet complete component: external-application-integration Ingegeration with TeXStudio, Acrobat Reader, ... labels Oct 11, 2026
@github-actions github-actions Bot added the status: changes-required Pull requests that are not yet complete label Oct 11, 2026
@github-actions github-actions Bot added component: external-application-integration Ingegeration with TeXStudio, Acrobat Reader, ... status: changes-required Pull requests that are not yet complete and removed component: external-application-integration Ingegeration with TeXStudio, Acrobat Reader, ... status: changes-required Pull requests that are not yet complete labels Oct 11, 2026
@github-actions github-actions Bot added component: external-application-integration Ingegeration with TeXStudio, Acrobat Reader, ... status: changes-required Pull requests that are not yet complete and removed component: external-application-integration Ingegeration with TeXStudio, Acrobat Reader, ... status: changes-required Pull requests that are not yet complete labels Oct 11, 2026
@github-actions github-actions Bot removed the component: external-application-integration Ingegeration with TeXStudio, Acrobat Reader, ... label Oct 11, 2026
@github-actions github-actions Bot added status: changes-required Pull requests that are not yet complete and removed status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers labels Oct 18, 2026
…TML export

codeArea.copy() already put RTF, HTML and plain text on the clipboard, so
the extra HTML copy repeated the same export. The default HTML export writes
one paragraph per line without a font, which loses indentation and alignment.

BibTeXCodeTextModel replaces the model's HTML export handler with
BibTeXHtmlExportFormatHandler, which writes the selection as one monospace
<pre> block with the theme's syntax colors. Since the handler belongs to the
model, every copy route uses it: Ctrl+C, Ctrl+Insert, cut, and the context
menu, in the Source tab, the citation relations popup, and the import dialog.

The copy hooks in SourceTab and CodeAreaKeyBindings, the BibTeX source
clipboard marker, and the Markdown editor special case are no longer needed.
@github-actions github-actions Bot added component: import-load component: external-application-integration Ingegeration with TeXStudio, Acrobat Reader, ... and removed component: entry-editor component: keybinding component: external-application-integration Ingegeration with TeXStudio, Acrobat Reader, ... status: changes-required Pull requests that are not yet complete labels Oct 18, 2026
@github-actions github-actions Bot added the status: changes-required Pull requests that are not yet complete label Oct 18, 2026
Pages pastes the RTF flavor whenever the clipboard has one, even though
JavaFX lists HTML first. The default RTF export names Helvetica, so the
pasted source still lost its alignment.

BibTeXRtfExportFormatHandler writes the selection in Courier New, marked
as \fmodern so that applications without it pick another monospace font,
with \line breaks and the theme's syntax colors. BibTeXCodeTextModel
registers it in place of the default RTF handler.
@github-actions github-actions Bot added size: big component: external-application-integration Ingegeration with TeXStudio, Acrobat Reader, ... and removed size: medium component: external-application-integration Ingegeration with TeXStudio, Acrobat Reader, ... status: changes-required Pull requests that are not yet complete labels Oct 18, 2026
@adityamukesh

Copy link
Copy Markdown
Author

@LoayTarek5 thanks, you were right that copy() already exported the same HTML. Changes in c659f58 and 7d40fbb:

  • Removed copyWithSyntaxHighlighting / copySource and the SourceTab / CodeAreaKeyBindings changes.
  • Added BibTeXHtmlExportFormatHandler, a StyledOutput over StyledTextModel.export that writes one <pre style="font-family: monospace;"> block with the theme colors.
  • It is registered on the code area's model (BibTeXCodeTextModel) instead of registerFunction(Tag.COPY, ...), so plain copy() uses it everywhere: Ctrl+C, Ctrl+Insert, cut, the context menu, the citation relations popup and ImportEntriesDialog.
  • Pages pastes the RTF version whenever one is on the clipboard, and the default RTF export uses Helvetica, so I added BibTeXRtfExportFormatHandler too: Courier New (marked \fmodern, so other apps fall back to a monospace font), line breaks and colors.
  • Dropped the BIBTEX_SOURCE marker and the MarkdownEditor change.
  • Tests now check <pre>, monospace, whitespace, colors and escaping for HTML and RTF.
  • Updated the requirement and the changelog.

Before / after, copied in Light theme and pasted into Pages:

main:
Pasted from main

this branch:
Pasted from this branch

Written with help from Claude Code.

@pluto-han

Copy link
Copy Markdown
Collaborator

Please do not mark resolved by yourself

@LoayTarek5 LoayTarek5 left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@adityamukesh this is much better now, thanks, also could you add a LibreOffice paste too? it may take the HTML instead of the rtf.

Comment on lines +99 to +111
if (attributes.isBold()) {
css.add("font-weight: bold;");
}
if (attributes.isItalic()) {
css.add("font-style: italic;");
}
StringJoiner decoration = new StringJoiner(" ");
if (attributes.isUnderline()) {
decoration.add("underline");
}
if (attributes.isStrikeThrough()) {
decoration.add("line-through");
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

the BibTeX css only sets the fill, so i think these branches (here and in the rtf handler) can go, and also the html handler could reuse RunCollector from the rtf one, right?

}

private static void export(StyledTextModel model, StyleResolver resolver, TextPos start, TextPos end, Writer writer) throws IOException {
writer.write("<html><head><meta charset=\"utf-8\"></head><body><pre style=\"font-family: monospace;\">");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

a newline right after <pre> gets dropped, so a selection starting at a line end loses its first break, also using 'Courier New', monospace would match the rtf font

Comment on lines +59 to +65
String rtf = clipboard.getRtf();
assertTrue(rtf.startsWith("{\\rtf1\\ansi\\uc1\\deff0{\\fonttbl{\\f0\\fmodern Courier New;}}"));
assertEquals(3, rtf.split("\\\\line\n", -1).length - 1);
assertTrue(rtf.contains("\\line\n "));
assertTrue(rtf.contains(" = "));
});
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

could these compare the whole output with assertEquals? contains(" = ") passes for many wrong outputs.

@LoayTarek5

Copy link
Copy Markdown
Collaborator

@adityamukesh, any updates?

@adityamukesh

adityamukesh commented Oct 23, 2026 via email

Copy link
Copy Markdown
Author

The BibTeX stylesheets only set the fill, so both exports keep only the
text color; the bold, italic, underline and strike-through branches are
gone, and the HTML export reuses the RTF export's run collection.

HTML drops a line break directly after <pre>, so the HTML export writes
one there; a selection that starts at a line end keeps its first break.
The <pre> uses 'Courier New', monospace, like the RTF export.

The RTF tests compare the whole output.
@adityamukesh

Copy link
Copy Markdown
Author

hi sir , i have a update for u :
the three review points are fixed in ab71a6c:
the HTML and RTF exports share one TextRun collector and keep only the colour
a line break right after

 is kept, and the HTML uses 'Courier New', monospace like the RTF
the RTF tests now compare the whole output with assertEquals
the LibreOffice before/after screenshot is coming shortly

@adityamukesh

Copy link
Copy Markdown
Author

@LoayTarek5 here is the LibreOffice paste you asked for (LibreOffice Writer 26.8.1 on macOS, JabRef in Light theme). You were right that LibreOffice takes the HTML here, not the RTF.

main: every line becomes its own paragraph, the indentation and the spaces before = collapse, and the font is proportional:

LibreOffice paste from main

this branch: pasted as "Preformatted Text" in Courier New, so the indentation, the aligned = and the colors are kept:

LibreOffice paste from this branch

Pasted with LibreOffice's own paste command from the clipboard contents JabRef produces; screenshots made with help from Claude Code.

@adityamukesh

Copy link
Copy Markdown
Author

@LoayTarek5 please review it.

@adityamukesh

Copy link
Copy Markdown
Author

The failing “External services tests” check seems unrelated to this PR. It fails on main as well because of the external services. Could a maintainer re-run it later?

@adityamukesh

Copy link
Copy Markdown
Author

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: css component: external-application-integration Ingegeration with TeXStudio, Acrobat Reader, ... component: import-load component: ui first contrib good first issue An issue intended for project-newcomers. Varies in difficulty. size: medium status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copy and paste to other programs should keep syntax highlighting

6 participants