Reading text
Get a page’s text with page.text.get():
const page = doc.page(pageRef);
const { text } = await page.text.get();text is the page’s text in reading order, as a normal JavaScript string. Lines are separated
by \r\n.
Part of a page#
Characters on a page are numbered from 0. To read just some of them (the text a user selected, or a search match), pass a range:
const selected = await page.text.slice({ start: 120, count: 42 });A range is always { start, count }: start is the first character, count how many. Search
matches and selections are ranges too, so you can pass them straight in:
const { matches } = await doc.search.query({ text: 'total' });
const found = await doc.page(matches[0].page).text.slice(matches[0]);A whole document#
There’s no single call for the whole document; read the pages and join them:
const { pages } = await doc.pages.list();
const texts = await Promise.all(pages.map((page) => doc.page(page.ref).text.get()));
const fullText = texts.map(({ text }) => text).join('\n\n');The engine reads pages one at a time in the background, so this is fine for long documents too.
Permissions#
Reading text needs the doc.text.copy permission, because text you read can leave the document.
Without it, both calls fail with Forbidden.
A user without doc.text.copy can still search (without snippets)
and select text: both need only where the text is,
not what it says. That lets you allow highlighting a PDF while stopping its text from being
copied.
Good to know#
Characters and string positions#
The engine numbers characters the way the PDF stores them. Most of the time that matches the
string: character 5 is text[5]. Two things make them differ:
- Characters outside the Basic Multilingual Plane (most emoji, some CJK characters) are one character in the PDF but two positions in a JavaScript string.
- Characters with no text of their own (a glyph the PDF maps to no Unicode character) have a number but add nothing to the string.
That’s why you pass ranges to slice() instead of cutting text yourself: slice() converts for
you. get() also returns charCount (how many characters the page has) and, when the two
numberings differ, a charMap that records where. You only need charMap if you convert
positions yourself, for example to run your own search over text:
import { charRangeForTextOffsets } from '@embedpdf/engine';
const snapshot = await page.text.get();
const at = snapshot.text.indexOf('Total');
const range = charRangeForTextOffsets(snapshot, { start: at, count: 'Total'.length });
// range is { start, count } in characters: ready for slice(), layout.segments() or a highlight.Your feedback goes directly to the documentation team.