Skip to main content

Text Index for fpdf2

Project description

Pypi Latest Version Python Support Python Types Documentation License

CI pre-commit Coverage Pypi Trusted Publisher: enabled Ruff Checks: flake-8, isort, mypy

GitHub last commit

fpdf2 Text Index

Adds a text index to fpdf2, based on the documentation and source code of Math Gemmell's Text Index:

from fpdf2_textindex import FPDF, TextIndexRenderer

pdf = FPDF()
pdf.add_page()
pdf.set_font('helvetica', size=12)
# Adding text index entry "example
pdf.cell(text="example{^}", markdown=True)
# Add the text index to a page
pdf.add_page()
pdf.insert_index_placeholder(TextIndexRenderer().render_text_index)
# Save as pdf
pdf.output("example.pdf")

The text index will have a single entry:

  • example, 1

Adding Text Index Entries

Use the text index-syntax to define index directives in a text:

Most mechanical keyboard firmware{^} supports the use of [key combinations]{^}.

Print it in the PDF by enabling markdown in fpdf2.FPDF.cell or fpdf2.FPDF.multi_cell:

pdf = FPDF()
pdf.add_page()
pdf.set_font('helvetica', size=12)
pdf.cell(
  text="Most mechanical keyboard firmware{^} supports the use of [key combinations]{^}.",
  markdown=True,
)
...

For a complete documentation of the supported text index directives, see the excellent documentation of Math Gemmell.

The only difference to this documentation is the adaption of the emphasis to the markdown style of fpdf2.

So the text:

This entry will be **emphasised**{^} in the index.
This expanded entry will be **[not emphasised]{^"* (nope)"}** in the index but here in the text.

will be printed in the PDF as:

This entry will be emphasised in the index.
This expanded entry will be not emphasised in the index but here in the text.

Similarly, the marks for italics __, underline -- and strikethrough ~~ are supported.

Inserting the Text Index

Use the adapted FPDF-class of this package that offers a fpdf2_textindex.FPDF.insert_index_placeholder-method to define a placeholder for the text index. At least, one page break is triggered after inserting the text index:

...
pdf.add_page()
pdf.insert_index_placeholder(render_index_function)

Parameters:

  • render_index_function: Function called to render the text index, receiving two parameters: pdf, an adapted FPDF instance, and entries, a list of fpdf2_textindex.TextIndexEntrys. A reference implementation is supported through fpdf2_textindex.TextIndexRenderer.render_text_index.
  • pages: The number of pages that the text index will span, including the current one. A page break occurs for each page specified.
  • allow_extra_pages: If True, allows unlimited additional pages to be added to the text index as needed. These extra text index pages are initially created at the end of the document and then reordered when the final PDF is produced.

[!NOTE] Enabling allow_extra_pages may affect page numbering for headers or footers. Since extra text index pages are added after the document content, they might cause page numbers to appear out of sequence. To maintain consistent numbering, use Page Labels to assign a specific numbering style to the index pages. When using Page Labels, any extra text index pages will follow the numbering style of the first text index page

Text Index Directive Syntax

__example__{^foo>"\* text"#demo |bar;+baz>fiz [whiz] ~z !}
           1            2     3             4      5  6

The index directive in the example will:

  1. Create a reference from the "example text" subentry within the "foo" top-level entry that leads to the directive's location in the text on the corresponding PDF page. If the entry or subentry do not exist, they will be created.
  2. Define the alias "#demo" for the path to the subentry ("foo" > "example text").
  3. Adds cross-references to the entry:
    • A SEE-cross reference to the "bar" top-level entry,
    • A SEE ALSO-cross reference to the "fiz" subentry within the "baz" top-level entry.
  4. Apply the "whiz" suffix to the directive's reference locator.
  5. Sort the entry as if its heading starts with "z".
  6. Apply an emphasis (bold) to the mark's reference locator.

The resulting index with page numbers would look like:

  • bar, 3
  • baz
    • fiz, 5
  • foo
    • example text, 6 (see bar). See also baz: fiz

if index directives with page references (locators) for "bar" and "baz" > "fiz" have been added as well.
In a real index, this would provoke an error, because either you set a reference locator to a PDF page and a SEE ALSO-cross reference or a SEE- and a SEE ALSO-cross reference, but not all three at the same time.

Example

An example can be created by example/textindex_figures.py and produces textindex_figures.pdf with all the examples from Math Gemmell's website.


Internals - Idea

For the curious reader:

This package adds a markdown parser to fpdf2 that intercepts markdown-styled strings to fpdf2.FPDF.cell or fpdf2.FPDF.multi_cell and translates Math Gemmell's Text Index-directives into markdown-links with an unset internal PDF link as destination, while the created index entries are internally saved:

"example{^}"
=
"[example](#idx0)"
+
TextIndexEntry(label="example", references=[Reference(start_id=0)])

When creating the actual text index in the PDF, all unset internal PDF link annotations that are related to the text index (identified by an unique id schema) are collected and its page, x/y-position on the page added to the entry's references:

{"idx0": LinkLocation(page=3, x=20.0, y=40.0, ...), ...}
->
TextIndexEntry.references[0].start_location = LinkLocation(page=3, x=20.0, y=40.0, ...)

Finally, a render_index_function similar to the official TOC-implementation of fpdf2 is used to render the index. The package supports a reference implementation, but the user can implement its own version if necessary.

The reference render_index_function renders each index entry according to The Chicago Manual of Style - Indexes:

"example, 3"

The unset link annotation in the text is pointed to this entry in the index and, thus, is finally set.

In the reference implementation, inverted links are added as well: To create a connection of the index entry to the text page, the printed page number will point to the text page.
So clicking on "example" on the text page will lead to corresponding entry in the text index. Clicking on the reference (locator) in the text index, page "3", will return the reader to the text page. Cross-references are connected in the same way but inside of the text index.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fpdf2_textindex-0.1.0.tar.gz (59.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fpdf2_textindex-0.1.0-py3-none-any.whl (62.0 kB view details)

Uploaded Python 3

File details

Details for the file fpdf2_textindex-0.1.0.tar.gz.

File metadata

  • Download URL: fpdf2_textindex-0.1.0.tar.gz
  • Upload date:
  • Size: 59.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fpdf2_textindex-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6155be598b302280d59bbcf8ec35d3e91cfb2670441fd15c90454e0517d291d0
MD5 f9baa8f545003c9e2206101a4cfc916c
BLAKE2b-256 f60cdd94340a8feee1f79c560021dc4c3ad5ebdbc4a0dd32deed359c82642564

See more details on using hashes here.

File details

Details for the file fpdf2_textindex-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: fpdf2_textindex-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 62.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fpdf2_textindex-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9b194fb75e2f3d05f8254c84452294c9c4c89fb0f55fa0c7ff34dcf36718d6ef
MD5 4e1a7ba1bbb66e15786e082f97667b3a
BLAKE2b-256 ec5deb5009af78cf2b35976864e9d8c1453f6e732ae539152d1763e275b24a47

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page