Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/johnfactotum/foliate-js/llms.txt

Use this file to discover all available pages before exploring further.

progress.js exports two classes that together convert a raw section index and intra-section fraction into human-readable progress information. TOCProgress maps the current position to the active table-of-contents item; SectionProgress computes location numbers, estimated reading time, and book-wide fraction. Both classes are used internally by view.js. Most applications interact with their output through view.lastLocation and the relocate event rather than constructing these classes directly.

Import

import { TOCProgress, SectionProgress } from './foliate-js/progress.js'

TOCProgress

Tracks which TOC item corresponds to the reader’s current position. It handles books where a single section contains multiple TOC destinations (via fragment identifiers).

tocProgress.init(options)

Asynchronously initializes the instance. Must be called before getProgress.
options.toc
object[]
required
The book’s TOC array, where each item has .href and optionally .subitems. Mutated in place to assign internal IDs.
options.ids
any[]
required
An array of section IDs in spine order, matching book.sections[i].id. Used to map section indices to TOC entries.
options.splitHref
function
required
async (href: string) => [sectionId, fragmentId] — splits a TOC href into the section ID and its fragment identifier. Corresponds to book.splitTOCHref.
options.getFragment
function
required
(doc: Document, fragmentId: any) => Node | null — returns the DOM node for a fragment identifier within a section document. Corresponds to book.getTOCFragment.
const tocProgress = new TOCProgress()
await tocProgress.init({
    toc: book.toc,
    ids: book.sections.map(s => s.id),
    splitHref: href => book.splitTOCHref(href),
    getFragment: (doc, id) => book.getTOCFragment(doc, id),
})

tocProgress.getProgress(index, range?)

Returns the TOC item that best matches the current reading position.
index
number
required
The index of the currently visible section.
range
Range
An optional DOM Range for the visible area. When provided, the method compares fragment element positions to determine which sub-item within the section is active. When omitted, the first matching item is returned.
Returns the matching TOC item object (with .label, .href, .subitems), the preceding item if the section has no direct match, or null if nothing matches.
const tocItem = tocProgress.getProgress(index, visibleRange)
if (tocItem) console.log(tocItem.label)

SectionProgress

Computes book-wide reading progress from per-section byte sizes. Sections with linear: 'no' or size: 0 are excluded from calculations.

new SectionProgress(sections, sizePerLoc, sizePerTimeUnit)

sections
object[]
required
The book’s sections array. Each element must have .size (byte count) and optionally .linear (set to 'no' to exclude).
sizePerLoc
number
required
Number of bytes per location unit. Used to calculate location.current, location.next, and location.total.
sizePerTimeUnit
number
required
Number of bytes per time unit. Used to calculate time.section and time.total.
const sectionProgress = new SectionProgress(book.sections, 1024, 200)

sectionProgress.getProgress(index, fractionInSection, pageFraction?)

Returns a progress object for the given position within the book.
index
number
required
The index of the currently visible section.
fractionInSection
number
required
How far through the current section the reader is, as a number from 0 to 1.
pageFraction
number
default:"0"
The fraction of the current page relative to the section. Used to compute location.next (the location at the bottom of the visible page).
Returns an object with the following shape:
fraction
number
Overall book progress from 0 to 1, measured to the bottom of the current page.
section
object
{ current: number, total: number } — the current section index and total section count.
location
object
{ current: number, next: number, total: number } — location numbers at the top of the page, bottom of the page, and the book’s end.
time
object
{ section: number, total: number } — estimated time remaining in the current section and in the whole book, expressed in whatever unit sizePerTimeUnit represents.
const progress = sectionProgress.getProgress(index, fractionInSection, pageFraction)
console.log(`Location ${progress.location.current} of ${progress.location.total}`)
console.log(`${(progress.fraction * 100).toFixed(1)}% through the book`)

sectionProgress.getSection(fraction)

The inverse of getProgress. Converts a book-wide fraction back to a section index and intra-section fraction. Used by view.goToFraction().
fraction
number
required
A book-wide fraction from 0 to 1.
Returns [index, fractionInSection] where index is the section index and fractionInSection is the position within that section as a number from 0 to 1.
const [index, fractionInSection] = sectionProgress.getSection(0.5)

sectionProgress.sectionFractions

An array of numbers, one per section (plus a trailing entry at 1), where each value is the book-wide fraction at which that section begins. Index i gives the start of section i. Useful for rendering a progress bar with section boundaries.
const fractions = sectionProgress.sectionFractions
// e.g. [0, 0.08, 0.21, 0.45, ...]

Usage with view.js

view.js constructs both classes internally and exposes their output through the relocate event:
view.addEventListener('relocate', e => {
    const { fraction, location, tocItem } = e.detail
    progressBar.value = fraction
    locationLabel.textContent = `Location ${location.current}`
    chapterLabel.textContent  = tocItem?.label ?? ''
})

Build docs developers (and LLMs) love