Core API
@imposia/core가 제공하는 프레임워크 중립적인 페이지 문서와 Publication 컨트롤러입니다.
@imposia/core는 페이지 문서의 기준 런타임입니다. 페이지네이션, 수명 주기, 리졸버 경계, 확장 기능, 인쇄, 내보내기를 React 없이 제공합니다. 이 문서의 모든 API는 브라우저에서만 실행됩니다.
Core 페이지 문서
mountPageDocument
mountPageDocument(
container: HTMLElement,
source: PageSource,
options?: PageDocumentOptions,
): PageDocumentController;이 함수는 화면 표시와 인쇄의 기준이 되는 canonical iframe 하나를 즉시 추가하고, 세대 준비를 시작한 뒤 동기적으로 반환합니다. 첫 문서를 읽기 전에 ready를 기다리세요.
const controller = mountPageDocument(host, { html: "<article><h1>안녕하세요</h1></article>" });
const pageDocument = await controller.ready;PageSource는 { html: string; baseUrl?: string } 또는 { lightDom: Element | DocumentFragment; baseUrl?: string }입니다.
PageDocumentOptions 필드 | 타입과 용도 |
|---|---|
css | readonly string[]. 함께 적용할 CSS입니다. |
assetResolver | 글꼴, 이미지, 미디어, 스타일시트 요청에 응답하는 비동기 리졸버입니다. |
page | { size?, orientation?, margin? }. size는 A3, A4, A5, B4, B5, Letter, Legal, Ledger 또는 사용자 정의 너비·높이를 받습니다. |
limits | 입력, 노드, 에셋, 시간 제한, 페이지, 레이아웃 패스, 생성 출력의 선택적 상한입니다. |
headerTemplate, footerTemplate | 머리말·꼬리말 장식 마크업입니다. |
decorateBlankPages | 빈 페이지에 장식을 적용할지 정합니다. |
experimental | { footnotes?: boolean; pageFloats?: boolean }. 두 기능 모두 실험 단계이며, 제한을 벗어나면 FOOTNOTE_DEFERRED 또는 PAGE_FLOAT_FALLBACK 경고와 함께 폴백합니다. |
extensions | 순서가 있는 PageExtension 또는 PublicationExtension 값입니다. |
compose | { yieldBudgetMs?: number; scheduler?: () => Promise<void> }. 기본 8ms 예산으로 메인 스레드에 실행을 양보하는 협조적 페이지네이션입니다. Infinity는 스케줄러 양보를 끕니다. |
signal | 최초 세대를 취소합니다. |
onProgress | 준비 단계가 페이지를 할당할 때마다 패스 기준 { completedPages, pass, provisional: true }를 받습니다. 이후의 수렴 패스는 수를 다시 셉니다. |
스케줄러, 글꼴, 이미지 대기는 실제 경과 시간 기준인 limits.resourceDeadlineMs에 포함됩니다. 진행률은 준비 단계의 잠정 작업을 설명하며, 최신 확정 세대는 controller.current에서만 읽으세요.
AssetResolver는 { url, kind, baseUrl, signal }을 받아 { status: "resolved", bytes, mimeType, resolvedUrl? } 또는 { status: "blocked", reason? }으로 응답합니다. 구현 방법은 이미지와 글꼴 불러오기에서 다룹니다.
확장 기능
PageExtension과 PublicationExtension은 동기식 finalizePage(page, context)도 구현할 수 있습니다. 이 훅은 Core가 장식과 margin box를 붙인 뒤, 확정 전에 승인된 페이지마다 한 번 실행되므로 page.element는 크기를 측정할 수 있는 실제 페이지 요소입니다. page.tableFragments에는 이어지는 표 조각이 원본 정보, 1부터 시작하는 연속 인덱스와 함께 들어 있습니다. 변경 내용은 확정된 iframe에 유지됩니다. 훅은 decorateBlankPages 설정과 관계없이, 의도적으로 삽입한 빈 페이지를 포함한 모든 할당 페이지에서 실행됩니다.
finalizePage는 undefined를 반환해야 합니다
finalizePage가 undefined가 아닌 값을 반환하면 세대 전체가 거부됩니다. 이 훅은 실제 페이지 요소를 변경하는 방식으로만 동작하며, 대체 값을 반환하는 방식은 없습니다.
분할된 표의 이어지는 조각에 측정된 픽셀 열 너비를 고정해야 한다면 선택형 확장인 createTableColgroupExtension()을 사용하세요. Core는 작성된 <colgroup> 요소를 항상 유지하지만, 기본적으로는 열 너비를 새로 만들지 않습니다.
PageDocumentController
| 멤버 | 반환값 | 준비 조건과 오류 |
|---|---|---|
ready | Promise<PageDocument> | 처음 확정된 문서로 이행되고, 확정할 수 없으면 거부됩니다. |
current | PageDocument | undefined | 갱신이 실패해도 이전에 확정된 문서가 남고, 컨트롤러를 제거하면 비워집니다. |
update(source, options?) | Promise<PageDocument> | 세대를 시작합니다. 더 새로운 갱신이 진행 중인 세대를 중단합니다. options.signal을 지원합니다. |
print() | Promise<void> | 최신 작업을 기다린 뒤, 마지막으로 확정에 성공한 문서를 격리된 최상위 문서 스냅샷으로 인쇄합니다. 확정된 문서가 없거나 제거 후에는 거부됩니다. |
destroy() | Promise<void> | 세대 생성·내보내기 작업을 중단하고, iframe을 제거하고, 리소스를 해제하고, 추적 중인 작업을 기다립니다. 여러 번 호출해도 안전합니다. |
PageDocument
| 멤버 | 타입·반환값 | 의미 |
|---|---|---|
iframe | HTMLIFrameElement | Core가 소유하는 canonical iframe입니다. |
generation, pageCount | number | 확정 세대 번호와 페이지 수입니다. |
pages | readonly PageMetadata[] | 페이지 번호, 좌우 면, 이름, 빈 페이지 여부, 기하 정보, 크기, 본문 텍스트입니다. |
warnings | readonly PageWarning[] | 현재 세대의 진단입니다. |
timings | { totalMs; resourceMs; paginationMs } | 세대를 만드는 데 걸린 시간입니다. 단위는 밀리초입니다. |
exportEpub(options) | Promise<Blob> | 진행 중인 최신 작업을 기다린 뒤, 마지막으로 확정된 원본을 리플로우형 EPUB 3.3 Blob으로 내보냅니다. |
EPUB 옵션에는 metadata: { title, language, identifier, modified? }가 필요하고, signal과 { maxEntries?, maxBytes? } 제한을 선택적으로 받습니다. 내보내기는 의미 구조 기준입니다. 페이지 래퍼, margin 장식, 생성된 카운터, 페이지 전용 실험 산출물은 제외됩니다.
경고
확정된 모든 PageWarning은 code, message, 그리고 generation, entryId, page를 가진 고정된 location을 포함합니다(값을 알 수 없으면 각각 undefined). 확장 기능 진단은 네임스페이스가 있는 EXTENSION_${string} 코드를 사용하고 자신의 extension 이름을 밝힙니다.
Core 유틸리티
prepareDocument(html: string, options?: PrepareDocumentOptions): PreparedDocument;
pageWarningTargetBounds(document: PageDocument, warning: PageWarning): PageWarningTargetBounds | undefined;
hasPageDocumentFrameSandbox(iframe: HTMLIFrameElement): boolean;
committedFrameGeneration(frameDocument: Document): number | undefined;
selectBlankMarkers(markers: PageSideConstraint[], pages: Map<number, number>): number[];prepareDocument는 HTML을 동기적으로 정규화·정제해{ html, headerTemplate?, footerTemplate?, warnings }를 반환합니다. 옵션은headerTemplate,footerTemplate,allowRemoteResources입니다. API 장식 옵션이 내장 템플릿보다 우선합니다. 브라우저 네이티브 HTML 파서로 파싱하므로 다른 Core API처럼 브라우저 전용이며, 경고는 오류 복구 후의 문서 순서로 정렬됩니다.pageWarningTargetBounds는 iframe 뷰포트 좌표 기준의 실시간{ left, top, width, height }를 반환합니다. 다른 세대의 경고나 위치가 없는 경고에는undefined를 반환합니다.hasPageDocumentFrameSandbox는 sandbox 토큰이 정확히 공개 토큰 집합(allow-same-origin,allow-modals)일 때만true입니다.committedFrameGeneration은 Core가 커밋 시점에 canonical frame에 찍은 세대를 반환하며, 스탬프된 세대를 아직 커밋하지 않은 프레임에는undefined입니다. 아직 전달되지 않은 더 새 커밋과 실제 손상을 구분하는 데 씁니다. 페이지 marker를 읽거나 검증하지는 않습니다.selectBlankMarkers는 이전 선택을 반영해, 좌우 면 배치를 맞추는 데 빈 페이지가 필요한 marker ID를 반환합니다. 페이지 매핑이 없는 marker에는 예외가 발생합니다.
Core Publication
mountPublication
mountPublication(
container: HTMLElement,
snapshot: PublicationSnapshot,
options?: PublicationOptions,
): PublicationController;이 함수는 순서가 있는 entry들을 하나의 페이지 순서로 조합하고 동기적으로 반환합니다. 잘못된 스냅샷이나 Publication 확장은 마운트 중에 예외를 발생시킬 수 있습니다.
const controller = mountPublication(host, {
metadata: { title: "안내서", language: "ko" },
entries: [
{ id: "cover", title: "표지", html: "<h1>안내서</h1>" },
{ id: "start", title: "시작", html: "<h1>시작</h1><p>첫 단계.</p>" },
],
});
const publication = await controller.ready;PublicationSnapshot은 metadata: { title, language?, identifier? }와 순서가 있는 entries를 담습니다. 각 entry에는 공백과 제어 문자가 없는 고유한 id, title, 선택적 baseUrl, 그리고 html 또는 lightDom 중 정확히 하나가 필요합니다. PublicationOptions는 PageDocumentOptions와 같되 extensions가 PublicationExtension[]만 받고, pageNumbering이 추가됩니다. pageNumbering: "entry"를 주면 모든 entry가 새 페이지에서 시작하고, counter(page), counter(pages), pageNumber/totalPages 템플릿 토큰이 entry 안에서 셉니다. 청구서 여러 장을 한 번에 인쇄해도 각 청구서에 "Page 1 of 2"처럼 찍힙니다. 페이지 메타데이터, 이동, 검색, entry 페이지 범위, 확장의 decoratePage 입력, target 참조는 전체 기준을 유지합니다. 기본값 "publication"은 Publication 전체에 번호를 매깁니다.
PublicationController
| 멤버 | 반환값 | 준비 조건과 오류 |
|---|---|---|
ready | Promise<PublicationDocument> | 처음 확정된 Publication입니다. |
current | PublicationDocument | undefined | 현재 확정된 문서입니다. |
resolveDestination(id) | PublicationDestination | undefined | 현재 세대에서 outline·검색 ID를 해석합니다. |
search(query) | readonly PublicationSearchResult[] | 확정 전에는 빈 배열이고, 이후에는 현재 색인을 검색합니다. |
navigate(destination) | void | 목적지 전체가 현재 세대와 일치하고 실제로 존재할 때만 이동하며, 그렇지 않으면 예외가 발생합니다. |
update(snapshot, options?) | Promise<PublicationDocument> | 완전한 스냅샷을 검증하고 준비합니다. options.signal을 지원합니다. |
print() | Promise<void> | 페이지 컨트롤러와 같은 방식으로, 마지막으로 확정에 성공한 문서를 인쇄합니다. |
destroy() | Promise<void> | 내부의 페이지·Publication 리소스를 정리합니다. |
PublicationDocument는 PageDocument에 확정된 metadata, entries, 중첩된 outline을 더합니다. 각 entry는 포함 범위인 전역 pageRange를 가집니다. PublicationDestination은 { id, entryId, page, generation }이며 세대에 묶입니다. navigate는 이전 세대의 값을 코드가 있는 ImposiaError(STALE_PUBLICATION_DESTINATION)로 거부합니다. 검색 결과는 { entry, page, excerpt, destination }입니다.