import { B as BookOptions } from './measures-BildgW3g.js'; export { C as ColumnSlot, E as ExclusionEngine, a as ExclusionPageGeometry, b as ExclusionZone, I as ImageRect, P as PageSlice, c as ParagraphMeasure, S as SpreadExclusionEngine, d as SpreadExclusionResult, e as SpreadGeometry, f as SpreadImageRect, g as computeExclusionSlots, h as computeLineWidths, i as getLineRanges, p as paginate } from './measures-BildgW3g.js'; import { K as KinsokuRules, a as KinsokuMode, L as LayoutInput, B as BreakResult } from './types-DnPOMbQV.js'; export { R as RubyAnnotation, b as RubyPreprocessResult, c as RubyType, T as TcyAnnotation, d as TcyPreprocessResult, e as buildTcyAnnotations, i as isKana, p as preprocessRuby, f as preprocessTcy } from './types-DnPOMbQV.js'; import { M as ManuscriptDialect } from './manuscript-DeQQoLzm.js'; export { I as ImageOverlayRect, m as moveImageOverlayRect, r as resizeImageOverlayRect } from './overlay-x44omB1X.js'; import { I as InChapterAnchor, R as ReadingAnchor } from './anchor-BWfPiv2j.js'; /** * Resolves cluster boundaries into a bitmask of non-breakable positions. * * Characters sharing the same cluster ID cannot be split across lines. * The returned array has `1` at positions where a break is prohibited * (i.e. the character at `pos` and `pos+1` belong to the same cluster). * * @param text - Array of Unicode codepoints. * @param clusterIds - Cluster ID for each character. Same ID = indivisible unit. * @returns Uint8Array where `1` means "cannot break after this position". */ declare function resolveClusterBoundaries(text: Uint32Array, clusterIds?: Uint32Array): Uint8Array; /** * Returns whether a break is allowed between `pos` and `pos+1` * based on cluster membership. * * @param clusterIds - Cluster ID array (optional). * @param pos - Position to check. * @param textLength - Total text length. */ declare function isClusterBreakAllowed(clusterIds: Uint32Array | undefined, pos: number, textLength: number): boolean; /** * Returns whether the given codepoint is eligible for hanging punctuation. * @param codepoint - Unicode codepoint to check. */ declare function isHangingTarget(codepoint: number): boolean; /** * Computes the largest overhang a character may take when hanging at line end. * * This is an upper bound, not the amount an actual line hangs by: the per-line * values in `BreakResult.hangingAdjustments` are the width by which the line * exceeds its available width, which is at most this value and is smaller * whenever the preceding characters do not fill the line exactly. * * @param codepoint - Unicode codepoint of the character. * @param advance - Advance width of the character in pixels. * @returns The maximum overhang amount, or 0 if not a hanging target. */ declare function computeHangingAdjustment(codepoint: number, advance: number): number; /** * All UI strings rendered by the bundled framework components. * * Every key is required, so a host supplying a whole catalog cannot silently * leave part of the UI untranslated; supply a partial catalog through the * `overrides` argument of {@link resolveMessages} instead. * * Keys whose doc comment names `{placeholder}` tokens are templates expanded by * {@link formatMessage} at render time. A translation must keep every token * spelled exactly as documented — an unknown or misspelled token is left in the * output verbatim (braces included) rather than throwing, so a typo surfaces as * literal `{n}` text in the UI. */ interface MejiroMessages { /** Subtitle shown next to the reader wordmark, unless the host passes its own `subtitle`. */ readonly logoSubtitle: string; /** Label of the reader toolbar button that opens the EPUB file picker. */ readonly openButton: string; /** Label of the reader toolbar button that toggles the settings panel. */ readonly settingsButton: string; /** Label of the reader toolbar button that inserts an image, and the default caption inside the image overlay. */ readonly imageButton: string; /** Accessible name and tooltip of the image overlay's remove control. */ readonly imageRemoveButton: string; /** Placeholder shown while an EPUB is being parsed and laid out. */ readonly loading: string; /** Accessible name of the control that turns back one spread. */ readonly prevSpread: string; /** Accessible name of the control that turns forward one spread. */ readonly nextSpread: string; /** Heading of the font group in the settings panel. */ readonly settingsFont: string; /** Label of the font-size control in the settings panel. */ readonly settingsSize: string; /** Accessible name of the button that decreases the font size. */ readonly settingsSizeDown: string; /** Accessible name of the button that increases the font size. */ readonly settingsSizeUp: string; /** Heading of the layout group in the settings panel. */ readonly settingsLayout: string; /** Label of the kinsoku-mode selector. Its options are {@link settingsStrict} and {@link settingsLoose}. */ readonly settingsKinsoku: string; /** Label of the hanging-punctuation selector. Its options are {@link toggleOn} and {@link toggleOff}. */ readonly settingsHanging: string; /** Label of the line-spacing control in the settings panel. */ readonly settingsLineSpacing: string; /** Option label for strict kinsoku mode. */ readonly settingsStrict: string; /** Option label for loose kinsoku mode. */ readonly settingsLoose: string; /** Option label for an enabled boolean setting. */ readonly toggleOn: string; /** Option label for a disabled boolean setting. */ readonly toggleOff: string; /** Primary prompt of the EPUB drop zone. */ readonly dropZoneTitle: string; /** Secondary line of the drop zone stating which files are accepted. */ readonly dropZoneHint: string; /** Heading of the table of contents, and the accessible name of the chapter navigation region. */ readonly tocTitle: string; /** Placeholder of the chapter search field in the table of contents. */ readonly tocSearchPlaceholder: string; /** Empty-state text when a chapter search matches nothing. Template: `{query}` — the current search text. */ readonly tocEmpty: string; /** Accessible name of the bookshelf region. */ readonly shelfTitle: string; /** Fallback chapter title when the EPUB gives none. Template: `{n}` — the 1-based chapter number. */ readonly chapterN: string; /** * Live-region text announcing the current position to screen readers. * Template: `{spread}` — the 1-based spread number, `{total}` — the spread count. */ readonly spreadAnnouncement: string; /** Subtitle of the preview pane inside the EPUB editor. */ readonly editorPreviewSubtitle: string; /** Heading of the EPUB editor. */ readonly editorTitle: string; /** Text shown in place of the book title before an EPUB has been loaded. */ readonly editorNoBookLoaded: string; /** Heading of the editor's paragraph list. */ readonly editorParagraphs: string; /** Heading of the editor's proofreading section. */ readonly editorProofread: string; /** Label of the button that commits edited paragraph text to the book. */ readonly editorApplyText: string; /** Heading of the editor's ruby section. */ readonly editorRuby: string; /** Instructions explaining how to select base text before entering a reading. */ readonly editorRubyHint: string; /** * Readout of the current ruby base selection. * Template: `{start}` / `{end}` — the selection bounds, `{count}` — the number of selected characters. */ readonly editorRubyRange: string; /** Placeholder of the input that receives the ruby reading. */ readonly editorRubyPlaceholder: string; /** Label of the button that applies the entered ruby to the selected base text. */ readonly editorApplyRuby: string; /** Heading of the editor's image section. */ readonly editorImages: string; /** Label of the control that inserts an image after the selected paragraph. */ readonly editorInsertImageAfterParagraph: string; /** Label of the button that exports the edited book, shared by the EPUB and manuscript editors. */ readonly editorExportEpub: string; /** Subtitle of the preview pane inside the manuscript editor. */ readonly manuscriptPreviewSubtitle: string; /** Heading of the manuscript editor. */ readonly manuscriptTitle: string; /** Instructions describing the manuscript ruby notation. Translations should keep the notation samples verbatim. */ readonly manuscriptRubyHint: string; /** Heading of the manuscript metadata section. */ readonly manuscriptMetadata: string; /** Heading of the manuscript chapter list. */ readonly manuscriptChapters: string; /** Label of the manuscript body textarea. */ readonly manuscriptDraft: string; /** Label of the cover picker, shown until a cover file has been chosen. */ readonly manuscriptChooseCoverImage: string; /** Initial book title of a manuscript the host did not pre-populate. */ readonly manuscriptDefaultTitle: string; /** * Title given to a newly added manuscript chapter. * Template: `{n}` — the 1-based position of the chapter. */ readonly manuscriptDefaultChapterTitle: string; /** Body text of the starter chapter. Doubles as notation documentation, so translations should keep a ruby sample. */ readonly manuscriptDefaultBody: string; /** Stand-in for a chapter whose title the author left blank. */ readonly untitled: string; /** Label of the button that appends a manuscript chapter. */ readonly manuscriptAddChapter: string; /** Label of the button that deletes the selected manuscript chapter. */ readonly manuscriptRemove: string; /** Label of the control that wraps the selection in emphasis dots. */ readonly manuscriptEmphasisDots: string; /** Label of the control that wraps the selection in tate-chu-yoko. */ readonly manuscriptTcy: string; /** Label of the control that wraps the selection in emphasis (`em`). */ readonly manuscriptEm: string; /** Label of the control that wraps the selection in strong emphasis (`strong`). */ readonly manuscriptStrong: string; /** * Accessible name of a chapter's drag handle in the reorder list. * Template: `{title}` — the chapter title, or {@link untitled} when blank. */ readonly manuscriptReorderHandle: string; } /** Built-in locale identifiers. */ type MejiroLocale = 'en' | 'ja'; /** Built-in English catalog (the default). */ declare const enMessages: MejiroMessages; /** Built-in Japanese catalog. */ declare const jaMessages: MejiroMessages; /** * The built-in catalogs keyed by {@link MejiroLocale}. * * Exhaustive over `MejiroLocale`, so indexing it with any valid locale always * yields a catalog — {@link resolveMessages} relies on that to skip a fallback * check. The catalogs are shared, not copied: treat the returned object as * read-only, since mutating it changes what every reader on the page renders. */ declare const messageCatalogs: Record; /** * Builds a catalog without invoking a framework runtime. * * @param locale - Built-in locale to start from. When omitted, `fallback` is * used instead, which is how a host keeps a previously resolved catalog while * still applying overrides. * @param overrides - Partial catalog merged over the base. Absent keys keep the * base string, so a host only needs to list what it wants to change. * @param fallback - Base used when `locale` is omitted. @defaultValue {@link enMessages} * @returns The merged catalog. When `overrides` is absent the base object is * returned as-is rather than copied, so callers must not mutate the result. */ declare function resolveMessages(locale: MejiroLocale | undefined, overrides: Partial | undefined, fallback?: MejiroMessages): MejiroMessages; /** * Replaces `{name}` placeholders in a template. * * Placeholder names match `\w+`. A placeholder with no matching entry in `vars` * is left in the output verbatim, braces included, rather than becoming an empty * string or throwing — a mistranslated token stays visible instead of silently * dropping information. Numbers are stringified with the default locale-less * conversion, so a caller wanting grouped digits must pass a formatted string. * Substitution is single-pass: braces introduced by a substituted value are not * expanded again. * * @param template - Message string, typically a {@link MejiroMessages} entry. * @param vars - Values keyed by placeholder name. * @returns The expanded string. */ declare function formatMessage(template: string, vars: Record): string; /** * Returns whether the given codepoint is prohibited at the start of a line. * @param codepoint - Unicode codepoint to check. * @param mode - Kinsoku mode. Defaults to 'strict'. * @param rules - Optional custom kinsoku rules. When provided, mode is ignored. */ declare function isLineStartProhibited(codepoint: number, mode?: KinsokuMode, rules?: KinsokuRules): boolean; /** * Returns whether the given codepoint is prohibited at the end of a line. * @param codepoint - Unicode codepoint to check. * @param rules - Optional custom kinsoku rules. When provided, uses rules instead of defaults. */ declare function isLineEndProhibited(codepoint: number, rules?: KinsokuRules): boolean; /** * Returns whether a break between adjacent codepoints is prohibited by pair rules. * @param left - Codepoint before the proposed line break. * @param right - Codepoint after the proposed line break. * @param rules - Optional custom kinsoku rules. When provided, uses rules instead of defaults. */ declare function isUnbreakablePair(left: number, right: number, rules?: KinsokuRules): boolean; /** * Returns a copy of the default strict kinsoku rules. */ declare function getDefaultKinsokuRules(): KinsokuRules; /** * Builds a KinsokuRules object with pre-computed lookup sets from raw codepoint arrays. * @param raw - Object with lineStartProhibited and lineEndProhibited codepoint arrays. * @returns KinsokuRules with both the raw arrays and pre-computed sets. */ declare function buildKinsokuRules(raw: { lineStartProhibited: number[]; lineEndProhibited: number[]; unbreakablePairs?: Array; }): KinsokuRules; /** * Computes line break positions for the given layout input. * * Uses a greedy O(n) algorithm with backtracking for kinsoku rules * and optional hanging punctuation support. * * The shape of the result depends only on the options: `hangingAdjustments` is * present exactly when `enableHanging` is true, and `lineWidths` exactly when * per-line `lineWidths` were passed. For empty text both are zero-length. * * A cluster wider than the available line width does not fit on any line; it is * split by the forced-break rule. That is the only case in which a break falls * between two characters sharing a cluster ID. * * @param input - Layout parameters including text, advances, and line width. * @returns Break points and optional hanging adjustments. */ declare function computeBreaks(input: LayoutInput): BreakResult; /** * Determines whether a line break is allowed after position `pos`. * * @param text - Unicode codepoint array. * @param pos - Position to check (break would occur after this index). * @param clusterIds - Optional cluster IDs for indivisible units. * @param mode - Kinsoku mode. * @param rules - Optional custom kinsoku rules. * @returns `true` if a break is allowed at this position. */ declare function canBreakAt(text: Uint32Array, pos: number, clusterIds?: Uint32Array, mode?: KinsokuMode, rules?: KinsokuRules): boolean; /** Kinds of notation tokens recognized in manuscript source. */ type ManuscriptTokenKind = 'ruby' | 'emphasis' | 'tcy' | 'em' | 'strong' | 'link' | 'footnote'; /** A notation token located in manuscript source by `[start, end)` char range. */ interface ManuscriptToken { /** * Which notation the range spells out. Determines how a highlighter should * style the span; the token carries no parsed payload, so a consumer needing * the ruby reading or link target must read it back out of the source range. */ kind: ManuscriptTokenKind; /** Inclusive start index (in code units of the source string). */ start: number; /** Exclusive end index (in code units of the source string). */ end: number; } /** * Locates manuscript-notation tokens in source text. Designed for syntax * highlighting overlays — token ranges are in **source** positions (with * markup characters intact), unlike {@link parseManuscript} whose output * positions are in the rendered plain text. * * The set of recognized tokens follows the same dialect rules as * {@link parseManuscript}. */ declare function tokenizeManuscriptSource(text: string, dialect?: ManuscriptDialect): ManuscriptToken[]; /** * Minimal key-value storage interface used by reader persistence helpers. * * Structurally satisfied by the DOM `Storage` objects (`localStorage`, * `sessionStorage`), which is the intended default; a host swaps in its own * implementation to persist elsewhere. Values are opaque strings produced by * {@link serializeReadingPosition} / {@link serializeAnnotations}. * * Implementations are allowed to throw — private-mode and quota-exhausted * browser storage does — and callers in the framework packages catch and degrade * to an in-memory copy, so an implementation should not swallow failures itself. */ interface MejiroStorage { /** * Reads a previously stored value. * * @param key - Storage key. * @returns The stored string, or `null` when the key was never written. */ getItem(key: string): string | null; /** * Writes a value, replacing any existing one. * * @param key - Storage key. * @param value - Serialized payload. * @throws When the backing store rejects the write, e.g. a quota error or * storage disabled by the user agent. */ setItem(key: string, value: string): void; /** * Deletes a key. Removing a key that was never written is not an error. * * @param key - Storage key. */ removeItem(key: string): void; } /** Persisted reading position. */ type ReadingPositionValue = ReadingAnchor; /** * Parses current and legacy reading-position payloads. * * Accepts the versioned envelope written by {@link serializeReadingPosition}, * the legacy `{ chapter, spreadIdx }` shape, and a bare `ReadingAnchor` object * (`{ chapter, paragraph, charIndex }`) — the shape a host gets from stringifying * an anchor itself, e.g. when mirroring positions to a server. * * Returns `null` for anything that is not a well-formed position, including * payloads whose `chapter` / `paragraph` / `charIndex` are not non-negative * safe integers (fractional, negative, `NaN`, `Infinity` or beyond * `Number.MAX_SAFE_INTEGER`), so consumers can index layout data with the * returned fields without further checks. */ declare function parseReadingPosition(raw: string | null): ReadingPositionValue | null; /** Serializes a reading-position anchor. */ declare function serializeReadingPosition(value: ReadingPositionValue): string; /** * A user-authored annotation on a book. * * `start` and `end` are reflow-independent: they address paragraph and character * offsets rather than page or spread positions, so an annotation survives a font * or page-size change. Both anchors are interpreted within `chapter`; an * annotation therefore cannot span chapters. * * {@link parseAnnotations} drops entries that do not match this shape, so any * value read back from storage already satisfies the constraints below. */ interface Annotation { /** * Stable identifier, unique within a book. Generated by * {@link createAnnotationId} unless the host assigns its own. */ id: string; /** Zero-based chapter index. A non-negative safe integer. */ chapter: number; /** Inclusive start of the annotated range within `chapter`. */ start: InChapterAnchor; /** Exclusive end of the annotated range within `chapter`. */ end: InChapterAnchor; /** Highlight color as a CSS color string. Host-defined; the core never interprets it. */ color?: string; /** Free-form user note attached to the range. */ note?: string; /** * Creation time as a millisecond epoch. Only required to be a finite number — * it is never used for ordering, which {@link sortAnnotations} derives from the * range instead. */ createdAt?: number; } /** * Parses an annotation payload, returning an empty list for invalid data. * * Accepts the versioned envelope written by {@link serializeAnnotations} and a * bare annotation array — the shape a host gets from stringifying the list * itself, e.g. when mirroring annotations to a server. Entries that are not * well-formed annotations are dropped. */ declare function parseAnnotations(raw: string | null): Annotation[]; /** Serializes annotations with a version envelope. */ declare function serializeAnnotations(annotations: readonly Annotation[]): string; /** Sorts annotations by chapter, paragraph, then character index. */ declare function sortAnnotations(annotations: readonly Annotation[]): Annotation[]; /** Creates a best-effort stable client-side annotation id. */ declare function createAnnotationId(): string; /** * Normalizes text to NFC before codepoint-based layout. * * Mejiro's public offsets are NFC Unicode codepoint offsets. This keeps * decomposed input such as `か\u3099` aligned with the same rendered character * as precomposed `が`. */ declare function normalizeText(str: string): string; /** * Converts a string to a Uint32Array of NFC-normalized Unicode codepoints. * * This is the recommended way to prepare text input for {@link computeBreaks}, * which requires a `Uint32Array` of codepoints. * * @param str - Input string. * @returns Uint32Array of Unicode codepoints. */ declare function toCodepoints(str: string): Uint32Array; /** * Adds natural line breaks around Japanese dialogue quotes. * * This is a manuscript-editing helper, not an EPUB-specific transform. It * normalizes CRLF to LF, inserts a break before opening quotes and after * closing quotes when they are attached to surrounding prose, trims whitespace * around inserted breaks, and avoids creating more than one blank line. * * @param text - Japanese prose manuscript text. * @returns Text with dialogue quotes separated onto their own lines. */ declare function formatDialogueLineBreaks(text: string): string; /** * Converts an array of token lengths (in codepoints) into a token boundary array * suitable for {@link LayoutInput.tokenBoundaries}. * * Each boundary is the index of the last codepoint in that token. * The last token's boundary is omitted since it coincides with text end. * * @example * ```ts * // "新しい" (3) + "プログラミング" (7) + "言語" (2) * tokenLengthsToBoundaries([3, 7, 2]) * // → Uint32Array [2, 9] (break preferred after index 2 and 9) * ``` * * @param tokenLengths - Array of token lengths in codepoints from a morphological analyzer. * @returns Uint32Array of boundary indices for use in LayoutInput. */ declare function tokenLengthsToBoundaries(tokenLengths: number[]): Uint32Array; /** A font choice shown in reader settings UIs. */ interface FontChoice { /** CSS `font-family` value applied to the book. */ value: string; /** Human-readable label shown in the picker. */ label: string; } /** Subset of {@link BookOptions} editable from bundled settings panels. */ type EditableSettings = Pick; /** Per-page header data used to render the running title and page number. */ interface PageHeaderData { /** Running title. */ title?: string; /** Page number. Hidden when `null`. */ pageNumber?: number | null; } /** * Returns a URL that is safe to place in an `href` attribute, or `null` when * the URL uses an executable or otherwise unsupported scheme. */ declare function sanitizeUrl(raw: string): string | null; export { type Annotation, BreakResult, type EditableSettings, type FontChoice, KinsokuMode, KinsokuRules, LayoutInput, type ManuscriptToken, type ManuscriptTokenKind, type MejiroLocale, type MejiroMessages, type MejiroStorage, type PageHeaderData, type ReadingPositionValue, buildKinsokuRules, canBreakAt, computeBreaks, computeHangingAdjustment, createAnnotationId, enMessages, formatDialogueLineBreaks, formatMessage, getDefaultKinsokuRules, isClusterBreakAllowed, isHangingTarget, isLineEndProhibited, isLineStartProhibited, isUnbreakablePair, jaMessages, messageCatalogs, normalizeText, parseAnnotations, parseReadingPosition, resolveClusterBoundaries, resolveMessages, sanitizeUrl, serializeAnnotations, serializeReadingPosition, sortAnnotations, toCodepoints, tokenLengthsToBoundaries, tokenizeManuscriptSource };