@missing-elements/h5p-verify 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,11 +2,7 @@
2
2
 
3
3
  Plays an `.h5p` package in a headless browser through
4
4
  [h5p-offline-player](https://github.com/missing-elements/h5p-offline-player) and reports whether
5
- it works. The last check before a package — generated, edited, repackaged — is handed to anyone.
6
-
7
- A zip that opens and JSON that parses prove nothing: most broken packages are valid zips that
8
- fail in the H5P runtime, or start and draw the wrong thing. This runs the real runtime, with no
9
- server and no account, in a few seconds.
5
+ it works.
10
6
 
11
7
  ```bash
12
8
  npx @missing-elements/h5p-verify course.h5p
@@ -19,45 +15,33 @@ pass course.h5p ready in 0.37 s revision sha256:872ee6f732e6a4b7…
19
15
 
20
16
  ```
21
17
  fail course.h5p state error
22
- bad-archive: This package contains no libraries, only content. … Missing: H5P.QuestionSet-1.20
23
- fix: add the library folders (H5P.QuestionSet-1.20), or --libraries hub if the destination site supplies libraries
18
+ bad-archive: This package contains no libraries, only content. … Missing: H5P.QuestionSet-1.21
19
+ fix: add the library folders (H5P.QuestionSet-1.21), or --libraries pack if the destination site supplies libraries
24
20
  ```
25
21
 
26
- Exit code 0 means it plays (there may be warnings), 1 that it does not, 2 that the check could
27
- not run. `report.json` and `screenshot.png` land in `<package>.verify/` beside the package.
28
-
29
- ## What it checks
30
-
31
- | | |
32
- |---|---|
33
- | The archive | indexed by the player: `h5p.json`, entry names, the libraries it declares against the folders it carries |
34
- | Libraries | missing ones are named; `--libraries hub` or `--libraries <url>` supplies them the way a host would |
35
- | Boot | the runtime reaches `ready`, and how long that took |
36
- | Errors | an uncaught error while booting fails the check even when the content comes up around it; one after `ready` is a warning, since content types throw non-fatal exceptions routinely |
37
- | Rendering | the content drew something: the frame's root has a height and elements |
38
- | Requests | anything the frame asked for and did not get, such as a media file `content.json` names that is not in the archive |
39
- | CSP | an outside origin the frame's policy blocked |
40
- | Provenance | the `revision` every xAPI statement from this build will carry |
22
+ Exit code 0: it plays (possibly with warnings); 1: it does not; 2: the check could not run.
23
+ `report.json` and `screenshot.png` land in `<package>.verify/`.
41
24
 
42
- What it does not check: whether the content is correct, suited to its learners, accessible, or
43
- properly licensed. Look at the screenshot; a package can start cleanly and still be laid out
44
- wrong.
25
+ It checks that the archive indexes and carries the libraries it declares, that the runtime
26
+ reaches `ready`, that nothing throws while booting (an error after `ready` is a warning), that the
27
+ content drew something, and it lists failed requests, CSP blocks and the build's `revision`. It
28
+ does not judge correctness, suitability, accessibility or licensing: look at the screenshot.
45
29
 
46
30
  ## Options
47
31
 
48
32
  | | |
49
33
  |---|---|
50
- | `--libraries hub\|<url>` | for a package exported without library folders, what h5p.com and h5p.org do by default |
34
+ | `--libraries pack\|<url>` | supply libraries for a package exported without them: `pack` is the library pack (`hub` means the same) |
51
35
  | `--out <dir>` | where the report and screenshot go |
52
- | `--browser <path>` | a Chromium-based browser; otherwise Chrome, then Edge, then Playwright's own Chromium |
36
+ | `--browser <path>` | a Chromium-based browser; otherwise Chrome, then Edge, then Playwright's Chromium |
53
37
  | `--ready <s>` | time allowed to reach `ready`, default 60 |
54
38
  | `--settle <s>` | time watched after `ready` for late errors, default 3 |
55
39
  | `--json` | the report as JSON on stdout |
56
- | `-q` | the verdict line only |
40
+ | `-q`, `--quiet` | the verdict line only |
41
+ | `-h`, `--help` | |
57
42
 
58
- Needs Node 20 or later and a Chromium-based browser. Chrome or Edge on the machine is used
59
- if there is one; otherwise `npx playwright install chromium` fetches one (about 150 MB, once).
60
- Headless, so no display is needed.
43
+ Needs Node 20 or later and a Chromium-based browser; without Chrome or Edge, run
44
+ `npx playwright install chromium`.
61
45
 
62
46
  ## From code
63
47
 
@@ -69,16 +53,8 @@ console.log(summarize(report))
69
53
  if (report.verdict !== 'pass') process.exit(1)
70
54
  ```
71
55
 
72
- ## For agents
73
-
74
- The repository ships an [agent skill](https://agentskills.io), `skills/h5p-verify`, telling an AI
75
- agent that generates H5P content when to run this and how to read what comes back:
76
-
77
- ```bash
78
- npx skills add missing-elements/h5p-offline-player --skill h5p-verify
79
- ```
80
-
81
- or copy the folder into your agent's skills directory.
56
+ An [agent skill](https://agentskills.io) for it ships in the repository:
57
+ `npx skills add missing-elements/h5p-offline-player --skill h5p-verify`.
82
58
 
83
59
  ## Licence
84
60
 
@@ -9,7 +9,8 @@ Plays the package in a headless browser through h5p-offline-player and reports w
9
9
  works. Exit code 0: it plays (warnings possible). 1: it does not. 2: could not run.
10
10
 
11
11
  Options:
12
- --libraries hub|<url> supply libraries for a package exported without its own
12
+ --libraries pack|<url> supply libraries for a package exported without its own (pack: the
13
+ published library pack; hub means the same)
13
14
  --out <dir> where report.json and screenshot.png go
14
15
  (default: <package>.verify/ beside the package)
15
16
  --browser <path> a Chromium-based browser; Chrome, Edge or Playwright's found otherwise
package/lib/verify.mjs CHANGED
@@ -39,7 +39,7 @@ const MIME = {
39
39
  /**
40
40
  * @typedef {object} VerifyOptions
41
41
  * @property {string} file the `.h5p` to play
42
- * @property {string} [libraries] `hub`, or the URL of a bundle, for a package without library folders
42
+ * @property {string} [libraries] `pack`, or the URL of a bundle, for a package without library folders
43
43
  * @property {string} [out] where `report.json` and `screenshot.png` go; nothing is written without it
44
44
  * @property {string} [browser] a Chromium-based browser executable; found automatically otherwise
45
45
  * @property {number} [readyTimeout] ms allowed to reach `ready`; default 60 000
@@ -200,23 +200,33 @@ function dedupe(messages) {
200
200
  return [...counts].map(([message, count]) => (count > 1 ? `${message} (×${count})` : message))
201
201
  }
202
202
 
203
- /** The player's `dist/`, from the installed package; the workspace needs it built first. */
203
+ /**
204
+ * The player's `dist/` and the runtime's, from the installed packages; the workspace needs both
205
+ * built first. The runtime is a package of its own (`@missing-elements/h5p-runtime`, GPL) and is
206
+ * served at `/frame-assets/`, which is where the element looks beside its own script.
207
+ */
204
208
  async function playerDist() {
205
209
  const element = require.resolve('@missing-elements/h5p-offline-player')
206
210
  const dist = dirname(element)
207
- if (!existsSync(join(dist, 'h5p-sw.js')) || !existsSync(join(dist, 'frame-assets', 'h5p.css'))) {
211
+ if (!existsSync(join(dist, 'h5p-sw.js'))) {
208
212
  throw new VerifyError(`The player is not built at ${dist} — run \`pnpm build\` in the workspace, or reinstall the package`)
209
213
  }
210
- return dist
214
+ const runtime = join(dirname(require.resolve('@missing-elements/h5p-runtime/package.json')), 'dist')
215
+ if (!existsSync(join(runtime, 'h5p.css')) || !existsSync(join(runtime, 'frame-boot.js'))) {
216
+ throw new VerifyError(`The H5P runtime is not built at ${runtime} — run \`pnpm build\` in the workspace, or reinstall @missing-elements/h5p-runtime`)
217
+ }
218
+ return { dist, runtime }
211
219
  }
212
220
 
213
- /** A static server for the player and the test page, on a free localhost port. */
214
- function serve(dist) {
221
+ /** A static server for the player, the runtime and the test page, on a free localhost port. */
222
+ function serve({ dist, runtime }) {
215
223
  const page = join(here, 'page.html')
224
+ const ASSETS = '/frame-assets/'
216
225
  const server = createServer(async (request, response) => {
217
226
  const path = decodeURIComponent(new URL(request.url ?? '/', 'http://localhost').pathname)
218
- const target = path === '/' ? page : join(dist, normalize(path).replace(/^(\.\.[/\\])+/, ''))
219
- if (target !== page && !target.startsWith(dist)) {
227
+ const safe = (root, rest) => join(root, normalize(rest).replace(/^(\.\.[/\\])+/, ''))
228
+ const target = path === '/' ? page : path.startsWith(ASSETS) ? safe(runtime, path.slice(ASSETS.length)) : safe(dist, path)
229
+ if (target !== page && !target.startsWith(dist) && !target.startsWith(runtime)) {
220
230
  response.writeHead(403).end()
221
231
  return
222
232
  }
@@ -270,7 +280,7 @@ export function summarize(report) {
270
280
  for (const reason of report.reasons) lines.push(` ${reason}`)
271
281
  const missing = report.errors.find((error) => error.missingLibraries)?.missingLibraries
272
282
  if (missing) {
273
- lines.push(` fix: add the library folders (${missing.folders.join(', ')}), or --libraries hub if the destination site supplies libraries`)
283
+ lines.push(` fix: add the library folders (${missing.folders.join(', ')}), or --libraries pack if the destination site supplies libraries`)
274
284
  }
275
285
  for (const warning of report.warnings) lines.push(` warning: ${warning}`)
276
286
  if (report.screenshot) lines.push(` screenshot: ${report.screenshot}`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@missing-elements/h5p-verify",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Plays an .h5p package in a headless browser through h5p-offline-player and reports whether it works: start-up, errors, missing libraries, a screenshot. The last check before a generated package is handed to anyone.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -39,13 +39,14 @@
39
39
  ],
40
40
  "dependencies": {
41
41
  "playwright-core": "^1.50.0",
42
- "@missing-elements/h5p-offline-player": "^0.1.9"
42
+ "@missing-elements/h5p-offline-player": "^0.6.0",
43
+ "@missing-elements/h5p-runtime": "^0.1.0"
43
44
  },
44
45
  "devDependencies": {
45
- "@types/node": "^22.13.0",
46
- "@zip.js/zip.js": "^2.17.0",
47
- "typescript": "^5.7.3",
48
- "vitest": "^5.0.1"
46
+ "@types/node": "^26.6.4",
47
+ "@zip.js/zip.js": "^2.23.0",
48
+ "typescript": "^7.0.2",
49
+ "vitest": "^5.0.3"
49
50
  },
50
51
  "engines": {
51
52
  "node": ">=20"