Skip to content

About

Prose provides a TypeScript library for working with EPUB Canonical Fragment Identifiers (CFI). This library provides utilities for parsing, resolving, generating, comparing, and serializing CFIs according to the EPUB CFI 1.1 specification.

Terminal window
npm install @prose-reader/cfi

Parse a CFI string into a structured object.

import { parse } from '@prose-reader/cfi'
// Parse a simple CFI
const parsed = parse('epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)')
// Parse a range CFI
const rangeParsed = parse('epubcfi(/6/4[chap01ref]!/4[body01],/6/4[chap01ref]!/4[body01]/10[para05])')

Resolve a CFI to a DOM node or range.

import { resolve } from '@prose-reader/cfi'
// Resolve to a node
const result = resolve('epubcfi(/6/4[chap01ref]!/4[body01]/10[para05])', document)
// Resolve to a range
const rangeResult = resolve('epubcfi(/6/4[chap01ref]!/4[body01],/6/4[chap01ref]!/4[body01]/10[para05])', document, { asRange: true })

Generate a CFI from a DOM node or position.

import { generate } from '@prose-reader/cfi'
// Generate from a node
const cfi = generate(node)
// Generate with options
const cfiWithOptions = generate(node, {
includeTextAssertions: true,
textAssertionLength: 20,
includeSideBias: 'before',
spatialOffset: [50, 50],
extensions: {
'vnd.example.param': 'value'
}
})
// Generate from a position
const positionCfi = generate({
node: textNode,
offset: 5,
temporal: 30,
spatial: [25, 75]
})
// Generate a range
const rangeCfi = generate({
start: { node: startNode, offset: 0 },
end: { node: endNode, offset: 10 }
})

Compare two CFIs according to the EPUB CFI specification sorting rules.

import { compare } from '@prose-reader/cfi'
// Compare two CFIs
const result = compare(
'epubcfi(/6/4[chap01ref]!/4[body01]/10[para05])',
'epubcfi(/6/4[chap01ref]!/4[body01]/10[para06])'
)
// Returns -1 if first CFI is before second, 0 if equal, 1 if after

Convert a parsed CFI back to a string.

import { parse, serialize } from '@prose-reader/cfi'
// Parse and then serialize
const parsed = parse('epubcfi(/6/4[chap01ref]!/4[body01]/10[para05])')
const cfiString = serialize(parsed)
function parse(cfi: string): ParsedCfi

Parses a CFI string into a structured object. The parsed CFI can be either a simple path or a range.

A string that is only partly a CFI is not one, so every character has to be read as part of it. parse throws for a character that can't be, such as text after the closing parenthesis, for an epubcfi( or an assertion never closed, and for a step or an offset without its number. Whitespace around the CFI is ignored. It doesn't check that the parts come in an order the specification allows.

function resolve(
cfi: string | ParsedCfi,
document: Document,
options?: ResolveOptions
): ResolveResult

Resolves a CFI to a DOM node or range. Options include:

  • throwOnError: Whether to throw an error if the CFI cannot be resolved
  • asRange: Whether to return a range instead of a single node
function generate(
position: Node | CfiPosition | { start: CfiPosition; end: CfiPosition },
options?: GenerateOptions
): string

Generates a CFI from a DOM node or position. Options include:

  • includeTextAssertions: Whether to include text assertions
  • textAssertionLength: Maximum length of text to use for assertions
  • includeSideBias: Whether to include a side bias assertion
  • spatialOffset: Spatial coordinates for image/video content
  • extensions: Extension parameters to include
function compare(a: ParsedCfi | string, b: ParsedCfi | string): number

Compares two CFIs according to the EPUB CFI specification sorting rules. Returns:

  • -1 if first CFI is before second
  • 0 if CFIs are equal
  • 1 if first CFI is after second
function serialize(parsed: ParsedCfi): string

Converts a parsed CFI back to a string representation.