Skip to content

Print PDF link URLs next to their text when supported #15 - #16

Closed
diegocostares wants to merge 1 commit into
planio-gmbh:masterfrom
diegocostares:feat/pdftotext-urls-option
Closed

diegocostares wants to merge 1 commit into
planio-gmbh:masterfrom
diegocostares:feat/pdftotext-urls-option

Conversation

@diegocostares

@diegocostares diegocostares commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Related issues

Implements #15.

Problem

pdftotext — and therefore this gem — extracts only the visible text of a PDF. The URLs behind links live in the document's link annotations, not in the text stream, so they never make it into the output. Recovering them meant reaching for a second tool (pdfinfo -url), a second output format, and losing the association between a URL and the text that links to it.

What this does

poppler 26.09.0 added pdftotext -urls, which prints each link's URL next to its link text, e.g. link text [https://example.com/]. This PR wires that into PdfHandler:

  • When the configured pdftotext supports -urls, it is passed automatically, so link URLs are part of the extracted text out of the box. Support is probed once per binary (pdftotext -h) and cached.
  • Binaries that predate the option are detected and left untouched, so extraction keeps working unchanged on poppler < 26.09.0 — including the poppler-utils currently on ubuntu-latest in CI.
  • pdftotext_urls: false opts out; pdftotext_urls: true forces the flag on for a binary that is not auto-detected (that binary must actually support it, otherwise pdftotext errors out and no text is extracted).
  • -urls is skipped for a command that already carries it, or that uses a mode pdftotext rejects it with (-bbox, -bbox-layout, -tsv, -htmlmeta) — those exit non-zero and would silently yield empty text. A configured command without the __FILE__ placeholder no longer raises while the handler is built.

Default behaviour of every other handler is unchanged.

How to test

Unit specs cover the command assembly without needing poppler (they stub the capability probe), so they run in CI regardless of the installed version:

bundle exec rspec spec/lib/file_handler/external_command_handler/pdf_handler_spec.rb

They assert -urls is added by default when supported, omitted with pdftotext_urls: false, forced with true, skipped for incompatible/duplicate commands, and that a command without __FILE__ does not raise.

With poppler >= 26.09.0 installed, an integration example additionally extracts the fixture spec/fixtures/files/text-with-url.pdf (a link over the word "website") and asserts the URL is appended. On older poppler that one example is skipped, so the suite stays green there too.

Manual check:

pdftotext -enc UTF-8 -urls spec/fixtures/files/text-with-url.pdf -
# => ... Visit our website today [https://example.com/]

Open question

I made it on-by-default when the binary supports it, since the URL belongs with the text it annotates. This does mean the extracted text of a given PDF can change when the OS pdftotext is upgraded across the 26.09.0 boundary, without the gem itself changing — I noted it in the CHANGELOG as a behaviour change. If you'd rather keep it strictly opt-in (off unless pdftotext_urls: true), that's a one-line change in `urls_wanted?`; happy to flip it.

@diegocostares
diegocostares force-pushed the feat/pdftotext-urls-option branch from 801504f to 7ebe80e Compare September 17, 2026 23:55
@diegocostares diegocostares changed the title Add pdftotext_urls option to print link URLs #15 Print PDF link URLs next to their text when supported #15 Sep 17, 2026
@diegocostares
diegocostares force-pushed the feat/pdftotext-urls-option branch 2 times, most recently from 655b8f1 to d37018f Compare September 18, 2026 00:38
poppler 26.09.0 added `pdftotext -urls`, which prints each link's URL
next to its link text, e.g. `link text [https://example.com/]`. Wire it
into PdfHandler so those URLs become part of the extracted text.

The option is passed automatically when the configured pdftotext
supports it; the probe result is cached per binary. Older binaries are
detected and left untouched, so extraction keeps working unchanged on
poppler < 26.09.0. `pdftotext_urls: false` opts out, `true` forces it on.

-urls is added only when applicable: the command must be an array using
the file placeholder, without -urls already or a mode that rejects it
(-bbox, -bbox-layout, -tsv, -htmlmeta). These cheap checks run before the
version probe, so an odd command (empty, a string, no placeholder) is
left alone rather than spawning a process or raising while every handler
is built.
@diegocostares
diegocostares force-pushed the feat/pdftotext-urls-option branch from d37018f to 225530d Compare September 18, 2026 00:44
@diegocostares
diegocostares marked this pull request as ready for review September 18, 2026 00:45
@jkraemer

Copy link
Copy Markdown
Member

Thank you for this, however I'd rather not add a toggle for this. Overriding the pdftotext: array in
plaintext.yml is exactly what that file is for, and it already gets you there:

pdftotext:
  - /usr/bin/pdftotext
  - -enc
  - UTF-8
  - -urls
  - __FILE__
  - '-'

Repeating the binary path and -enc UTF-8 is the same thing every override
requires today (see the Mac section of the README). A per-flag boolean next to the
command arrays would be a second configuration mechanism for the same thing.

@jkraemer jkraemer closed this Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants