Optional module · pdftoolkit/pdf-to-html 0.1.1

English · Français

Reference scope

The retained reference is Deriving HTML from PDF 1.2, September 2026, a PDF Association usage specification for Well-Tagged ISO 32000-2 files. It has 74 physical pages, including front matter and annexes. It is not an HTML-to-PDF specification or a specification for visual layout reconstruction.

resources/reference.json inventories its sections. Recording a section does not prove implementation of every rule. Released code, executable tests, independent validation and diagnostics must be considered together.

Three scopes to distinguish

  1. Source model and semantic derivation: applications supply explicit structure, Unicode content, attributes, widgets, associated files and policies.
  2. PDF file adapter: the reader recovers those facts from accepted encodings, operators and mechanisms. A modeled feature does not mean that every external PDF using it can be ingested.
  3. Browser/runtime integration: serving HTML, resolving assets, accepting form submissions and providing a JavaScript runtime belong to the application. Returning script bytes does not execute or emulate them.

Implemented mechanisms and evidence

The table describes executable behavior in this package, including explicit application ports. Its tests do not establish universal input-file acceptance or certification of the source document.

Reference Implementation Classes Executable evidence
4.1–4.2 Document title/language, head/body, class styles, form association and page-label navigation; XMP title and source metadata are read from PDF. DerivationSession, DocumentMetadataReader HtmlDeriverTest: testDocumentMetadataTextEscapingAndPageNavigation; ReadingSourceTest: testIndependentPdf20StructureContentAndMetadata.
4.3.1–4.3.4 Depth-first logical order, transitive role maps and namespace-object identity; HTML content-model repair preserves content and unique IDs. RoleResolver, ContentModelRepair HtmlDeriverTest: role chains, distinct namespace identities and cycles; HtmlBoundaryTest: nested anchors/labels, captions, lists and repair budgets.
4.3.5 Heading levels, captions, labels, FENote/note roles, lists/description lists, tables, figures, MathML formulas, code, links and interactive/non-interactive forms have specific transformations. Graphics engines remain injectable. DerivationSession, WidgetDeriver, ContentRenderer HtmlDeriverTest: description lists, captions, inline figures and Reference/Link; AdvancedDerivationTest: visual group rendering and ruby adaptation; six HTML5 cases: code and MathML included.
4.3.6 Lang, ActualText including an empty replacement, Alt, E, IDs and Ref-derived links are distinct; replacements preserve page anchors and omitted targets do not create broken links. StructureProperties, SourceValues, DerivationSession HtmlDeriverTest: replacement/expansion and marked-content wrappers; AdvancedDerivationTest: replacement anchors and suppressed targets; ReadingScenariosTest: binary IDs and invalid optional text diagnostics.
4.3.7 Class/direct attributes use explicit owner precedence; List, Table, Layout, PrintField, HTML/CSS/ARIA, matching NSO and UserProperties produce attributes/CSS or diagnostics. PDF points convert to CSS pixels. AttributeDeriver, ClassName AttributeDeriverTest: owners, namespaces, layout and conversions; HtmlDeriverTest: class/direct precedence.
4.4.1–4.4.7 Marked text, embedded ToUnicode, supported simple-font mappings, Form XObjects and supported images are read. cm, Form Matrix, q/Q, page rotation and UserUnit compose logical image dimensions; paths/shadings use explicit graphic nodes and a rendering port. ContentReader, ContentMatrix, FontTextDecoder, ToUnicodeReader ReadingSourceTest: actual PDF Unicode/Form/image content; ReadingScenariosTest: quote operators, state restoration, nested matrices, shear/rotation/UserUnit, unsupported images and preallocation limits.
4.4.8 OBJR, URI/GoTo/structure targets and separate Name/String destination spaces; widget inheritance, options/export values, flags, appearances and actual Annots/CropBox visibility. Signature widgets report status without inventing validation. SourceReadSession, WidgetDeriver, AppearanceRenderer ReadingScenariosTest: destination identity, absent widgets and CropBox; WidgetDeriverTest: choice/radio/text, readonly, rich text, file inputs, submit/reset/signature and visibility.
4.5 and annex B Opt-in, document-scoped JavaScript bridge for common fields/events, validation, calculation, formatting, reset and shared widget names. No PHP execution and no complete ISO 21757-1 API emulation. ScriptDeriver, DerivationPolicy ScriptDeriverTest, Node runtime harness: script initialization, duplicate field names, rejected values, calculations, readonly and reset.
4.6 Alternative/Supplement plans, embedded HTML/MathML/images and explicit asset ownership; URL-reference media types are inferred from path extensions. CSS, SVG, JavaScript and remote references follow separate policies. Head supplements retain safe metadata and never refresh directives. AssociationPlan, AssetCollection, DerivationSession, SafetyFilter HtmlDeriverTest: Alternative/Supplement; AdvancedDerivationTest: head metadata, SVG dimensions and duplicate IDs; HtmlBoundaryTest: head resources and stylesheets; ReadingScenariosTest: URL media types and local-file URL policy.
Annex A URL/CSS/fragment validation, escaping, entity/DTD rejection, cumulative traversal/output/asset budgets, graph-cycle checks and checks before expansion. SafetyFilter, Serializer, ReadingBudget HtmlBoundaryTest: fragments, CSS obfuscation, entity expansion, cycles and raw closing tags; ReadingScenariosTest: cyclic destinations, shared trees, UTF-16 XMP and Unicode snapshot/expansion budgets.
Annex C PdfToHtml requests an injected authentication provider for encrypted input and requires authenticated permissions; derivation emits the permission context. Decryption and viewer enforcement belong to the supplied implementation/application. PdfToHtml, AuthenticationProvider, AuthenticatedPermissions HtmlDeriverTest: testEncryptedPermissionContextAndSessionReuse; the provider interface is an integration boundary, not a built-in cryptographic backend.
Annex D Reading order, language, alternatives, form labels and table relationships are carried by the preceding mechanisms. Semantic authoring and assistive-technology review remain necessary. StructureProperties, WidgetDeriver, AttributeDeriver AdvancedDerivationTest: form labels/navigation; independent oracle: language, alternatives, IDs and links. No accessibility certification is inferred.

For the numbered body, the physical PDF page equals the printed page plus six. The source inventory records physical ranges.

MathML filtering admits 192 element names from the W3C MathML 3 RelaxNG modules, their 129 schema attribute names and explicitly supported global/Core additions. This is a vocabulary/security filter, not validation against every MathML grammar constraint. Presentation, Content and elementary MathML are preserved where accepted; Content MathML and mstack are not obsolete, but native browser rendering is not promised. Vocabulary outside the supported Core subset reports extended-mathml-vocabulary. No computer algebra system or rendering polyfill is supplied. Namespace and HTML-integration tests in HtmlBoundaryTest also cover forged MathML names, foreign XML and embedded HTML. SVG/OpenMath foreign XML is outside this profile.

File-ingestion boundaries

  • The native reader accepts PDF 1.0–2.0 syntax and PDF 2.0 UTF-8 strings. It still rejects encrypted input, hybrid xrefs, unsupported filters and damaged syntax. An AuthenticationProvider supplies the external authenticated/decrypted model; this package does not include native cryptographic authentication.
  • The input needs a usable structure tree. No OCR, inferred tagging or geometric reading-order reconstruction is performed. MCIDs, parents, cycles, page membership and namespace identities are checked explicitly.
  • Text uses embedded ToUnicode codespaces, bfchar/bfrange and embedded-stream UseCMap inheritance, or known simple-font encoding vectors/Differences with unambiguous glyph mappings. Named external CMaps and composite fonts without a usable ToUnicode collection are not implicitly resolved. Unsupported text becomes an explicit graphic/diagnostic node; malformed mappings are rejected.
  • Inline BI…ID…EI images are rejected explicitly rather than scanned heuristically. Image extraction accepts supported DeviceGray/DeviceRGB JPEG or decoded eight-bit samples without Mask/SMask/Decode transformations. Other codecs, masks, colour spaces and depths need an application decoder/renderer.
  • Affine transforms determine logical edge lengths, not sample dimensions or a complete CSS reproduction of PDF positioning/clipping. Degenerate/non-finite transforms and ambiguous reused Form/image contexts fail explicitly or produce an unsupported-image node. Rendering paths, shadings and full appearance groups requires the explicit ContentRenderer/AppearanceRenderer ports.

Safe defaults and enabled profiles

The default DerivationPolicy disables allowActiveContent and allowRemoteResources, keeps preferVisualFigures=false and produces semantic figure content. Native PHP derivation never executes scripts or fetches URLs. Supported, sanitized embedded HTML/MathML and raster assets can still be derived.

Enabling allowActiveContent deliberately exports trusted JavaScript/runtime and allows restricted imported CSS/SVG; it is not a browser sandbox or proof that source scripts are safe. allowRemoteResources separately permits output resource URLs, which a receiving browser may fetch. It does not make the PHP library fetch them. Neither setting implements the full Acrobat/ISO 21757-1 JavaScript API.

ScriptAssetEmitter externalizes enabled script source as pdf-script-<sha256>.js, retaining its exact JavaScript bytes without HTML closing-script ambiguities. Applications must write every returned asset beside the HTML, or consistently remap URLs. This is packaging, not script sanitization. HtmlBoundaryTest exercises closing-script payloads; the default safe profile emits no script runtime.

preferVisualFigures=true requests rendering through the supplied engine; it neither installs nor launches one. Readonly controls without native HTML readonly behavior report the required application/runtime enforcement. Form submission, trust and permission enforcement remain application responsibilities.

Accessible HTML still requires review of authoring, reading order, text alternatives, forms and actual assistive-technology behavior. No blanket ISO, WTPDF, PDF/UA or WCAG certification is claimed.

Reproducible evidence

CI runs PHP 8.3–8.5, PHPUnit, static analysis and formatting. It also runs:

  1. validate_reference.py: original filename, 900894 bytes, SHA-256, CC-BY-4.0 identity and 74 pages via an independent reader.
  2. build_reading_fixture.py --check: recreate the original MIT PDF 2.0 fixture using pinned pypdf 6.20.1 and compare its bytes and manifest. No PHP writer creates this input.
  3. validate_derivation.py: independently inspect the PDF with pypdf, run the PHP conversion and parse the real result with html5lib's HTML5 parser. Check Unicode, title/language, forms, links, unique IDs, alternatives and asset hashes, plus six synthetic semantic transformations. It also checks PDF 2.0 simple-font metrics, indirect descriptors and the AcroForm default-appearance font resources independently of text extraction.
  4. runtime.cjs: execute the opt-in bridge in a bounded Node harness, exercising common field operations without a browser or network.

The initial 0.1.0 candidate passes 192 tests / 592 assertions on each PHP version, PHPStan level 8, PSR-12 checks across 78 PHP files and Composer's strict, platform and advisory checks. These counts identify the reviewed candidate; the executable suite remains the source of truth for subsequent changes.

The input has SHA-256 53b69e6ab8bf438c5fd896990ce26e1fbd0eb8a8a475c4a1bbd9e8e90fab23c0. Its one-pixel image is painted at 20 PDF points: reading preserves 20 × 20 points and derivation produces rounded 27 × 27 CSS pixels, rather than treating the sample grid as its physical size. Matrix tests additionally cover q/Q, nested Forms, rotation, shear and UserUnit.

Central documentation presents the input PDF, every rendered page, executable PHP, actual HTML/JSON and exact released-source provenance. HTML5 parsing and these tests are evidence for the exercised cases, not a universal HTML/CSS/ARIA validator or automatic accessibility certification.

Documented HTML and security adaptations

The reference and current HTML authoring rules do not agree in every case. These decisions are explicit adaptations, with diagnostics, rather than claims that incompatible markup can be reproduced unchanged:

Reference, physical PDF page Adaptation
Table 1, page 21: RB maps to rb Emit span, retain data-pdf-se-type="RB" and report obsolete-ruby-base. WHATWG classifies rb/rtc as obsolete; imported fragments using them are repaired with diagnostics.
Widget mappings, pages 59–60: rich-text RV Retain plain text with a diagnostic. HTML input has no children and textarea cannot contain rich-text element markup.
Widget flags, pages 59–60: ReadOnly Use native readonly where HTML provides it. Other controls retain data-pdf-readonly and report the application/runtime enforcement requirement; ARIA metadata alone does not prevent interaction. See testReadOnlyChoiceUsesAnExplicitBridgeRatherThanInvalidReadonly in the widget tests.
4.4.7.3, page 55: marked-content Alt Emit span role="img" aria-label="…" instead of invalid span[alt], treating the described sequence as a named atomic group. Report the adaptation and review its assistive-technology semantics.
Table attributes, page 45: Scope Both Omit unsupported scope="both" with a diagnostic; retain explicit Headers associations when supplied.
Widget mappings, page 59: FileSelect value Do not prefill a browser file input; omit the PDF value and report the limitation.
4.6 and annex A, pages 65–68: associated content Scripts, imported stylesheets/SVG and active head content need an explicit policy. Imported CSS remains restricted; imports, URL-bearing declarations and expressions are filtered. HTTP-equivalent metadata such as refresh is never imported.

HTML authorities: obsolete features, file inputs, table scope, and ARIA naming requirements. MathML authorities: official RelaxNG modules, presentation markup, content markup and MathML Core. See security before enabling an active-content policy.

Guide source at the documented commit ↗