Skip to content

v0.2.0

Choose a tag to compare

@alekswebnet alekswebnet released this 01 Oct 10:23
· 285 commits to main since this release

The player follows the content's height by default now. There is also a new package,
@missing-elements/h5p-cmi5, so an
LMS can launch an .h5p package and record the learner's result through cmi5.

The player follows the content's height by default

auto-resize used to be opt-in, and nearly every page set it, since without it the frame stays
at 150px. The element now sizes itself to the content unless told otherwise:

<h5p-player src="course.h5p"></h5p-player>                    <!-- follows the content -->
<h5p-player src="course.h5p" auto-resize="off"></h5p-player>  <!-- you size it -->
  • auto-resize="off" is for a page that sizes the element itself: a fixed height in its
    stylesheet, or a flex or grid cell that scrolls inside. Setting it removes the inline height
    the element wrote, and only that; an inline height of your own is left alone.
  • A bare auto-resize is still accepted and means the default, so pages written for 0.1.x
    keep working.
  • The resize event fires as before, in both modes.

cmi5: @missing-elements/h5p-cmi5

npm i @missing-elements/h5p-offline-player @missing-elements/h5p-cmi5
import '@missing-elements/h5p-offline-player'
import { isCmi5Launch, startCmi5 } from '@missing-elements/h5p-cmi5'

if (isCmi5Launch()) {
  startCmi5(document.querySelector('h5p-player')).then((session) => {
    document.querySelector('#exit').onclick = () => session.exit()
  })
}

The package turns a page holding the element into a cmi5 assignable unit. The .h5p stays on
your static host; the LMS imports only a small course structure that names your page. Once the
LMS opens the page, the package:

  • trades the launch's one-time token for LRS access, reads the launch data and the learner's
    preferences, and sends initialized;
  • relays every statement the content emits to the LMS's LRS, as the launch's learner, with the
    LMS's context and the build's context.revision on each, so the LRS knows which version of the
    package each result came from;
  • when the content finishes, sends passed or failed and completed. The launch's mastery
    score decides, or the content's own pass mark when the launch has none. Each goes out once per
    registration, so a learner who opens the course again does not complete it twice;
  • sends terminated from your Exit button, then returns the learner to the LMS.

A reload resumes the session on the token it kept. Nothing is sent as the page unloads: a page
cannot tell a reload from a closed tab, and the LMS records a tab closed without Exit as
abandoned. Keep launchMethod="OwnWindow" in the course structure. It makes the LMS open the
page top level, and framed on another origin, Safari and every browser on iOS give the page no
Service Worker.

How it was checked.

  • ADL's CATAPULT player, the reference cmi5 launching
    system, validates every statement against the specification's numbered requirements. The run
    launches the demo page, reloads it mid-session, answers a question of a real quiz, finishes,
    presses Exit, then launches the same registration a second time. It passed with nothing
    rejected; pnpm cmi5:catapult runs it again.
  • SCORM Cloud launched the hosted demo and recorded the result.
  • The package's tests go through every requirement of the specification that can fall on
    the assignable unit, from ADL's own list
    (@cmi5/requirements). Each one is either
    covered by a test or marked with the reason it belongs to the LMS, the course structure or
    your page.

No dependencies. The protocol is a handful of fetch calls, a few kilobytes once minified.

What is left to your page. Applying the learner's audio preference, which cmi5 has the
assignable unit apply and the element has no control for; it is on the session as
learnerPreferences.audioPreference. Showing a launch that failed, which startCmi5 rejects
with the LMS's reason.

If you installed 0.1.0 or 0.2.0 (both on npm earlier on 2026-10-01): 0.3.0 changes what is
sent.

  • completed no longer carries a score; only passed and failed may, as cmi5 requires.
  • Without a mastery score, passed or failed now goes out by the content's own verdict, so a
    course with moveOn="Passed" can be satisfied.
  • completed and passed go out once per registration instead of once per session.
  • The recorded event has a completed field, and there is a new registration-unread event
    for an LRS that will not say what earlier sessions recorded.
  • The context template's values win over a statement's own.
  • Every statement is timestamped in UTC.

Try it on the demo site: /demo/cmi5.html
runs a simulated launch in the page with every statement shown, and offers the
course structure for importing
into an LMS. The guide, including why cmi5 rather than SCORM or LTI for this player, is
docs/cmi5.md.

Demo site

  • The /embed page is gone. It let a site with nowhere to host a file frame the hosted
    player. Safari gives a cross-origin iframe no Service Worker, and every browser on iOS is
    Safari underneath, so on every iPhone and iPad it could only show a link to open the content
    on its own. A site links to the hosted player page instead.
  • /demo/cmi5.html is new; see above.

Documentation

The README is shorter. Its longer sections moved to
docs/: streaming
video, packages without libraries, the frame's CSP, the build's revision, resume, the verifier,
cmi5 and development. Its attributes, properties, methods and events are tables now, checked
against the element.

Upgrading

npm i @missing-elements/h5p-offline-player@0.2.0
  • If your page sizes the element itself, add auto-resize="off". Otherwise the inline
    height the element now writes overrides your stylesheet. Pages that already set auto-resize
    need nothing.
  • Without a build step, copy h5p-sw.js again. The worker itself did not change, but an
    element and a worker of different versions log a warning asking you to re-copy it.

@missing-elements/h5p-normalize (0.1.1) and @missing-elements/h5p-verify (0.1.0) are
unchanged.

Full Changelog: v0.1.10...v0.2.0