@missing-elements/h5p-embed 0.3.2 → 0.4.0
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 +6 -3
- package/package.json +2 -2
- package/site/embed.js +50 -21
package/README.md
CHANGED
|
@@ -69,8 +69,11 @@ It works at a domain's root or under a path, over https. Serve `h5p-sw.js` with
|
|
|
69
69
|
| `lang=<tag>` | The language of H5P's own buttons and dialogs, such as `de` or `pt-BR`. Default: English |
|
|
70
70
|
| `xapi=<origin>` | Relay statements to the embedding page |
|
|
71
71
|
|
|
72
|
-
A custom script and a learner's name cannot be set on the address. Opened unframed, the page
|
|
73
|
-
|
|
72
|
+
A custom script and a learner's name cannot be set on the address. Opened unframed, the page plays
|
|
73
|
+
a package from another origin `untrusted` unless `--packages` names it: none of the package's own
|
|
74
|
+
code runs, its libraries come from this domain's pack or `--default-libraries` (never from the
|
|
75
|
+
address's `libraries=`), and a button offers to play it with its own scripts only when it needs
|
|
76
|
+
them.
|
|
74
77
|
|
|
75
78
|
## Messages
|
|
76
79
|
|
|
@@ -113,7 +116,7 @@ page's script, which reads the page's `<h5p-player>`, `#loader` and `#notice` (s
|
|
|
113
116
|
`site/index.html` and `site/embed.css`). Its options: `librariesPack` (the URL `libraries=pack`
|
|
114
117
|
names), `packages` (allowed origins, `null` for any), `defaultLibraries`, `runtime` (the
|
|
115
118
|
`@missing-elements/h5p-runtime` export, for a bundled element) and `askInOwnFrame` (default
|
|
116
|
-
`true`; `false`
|
|
119
|
+
`true`; `false` plays a package from another origin as it is when a same-origin page frames it).
|
|
117
120
|
|
|
118
121
|
```js
|
|
119
122
|
import '@missing-elements/h5p-offline-player'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@missing-elements/h5p-embed",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Self-hosted H5P embeds: writes the H5P embed page as a static site for a player domain of your own, then any site frames it with an iframe and one script line. No H5P server, no third-party service; optional allowlists for package hosts and embedding sites.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@missing-elements/h5p-libraries": "^0.1.1",
|
|
47
|
-
"@missing-elements/h5p-offline-player": "^0.
|
|
47
|
+
"@missing-elements/h5p-offline-player": "^0.7.0",
|
|
48
48
|
"@missing-elements/h5p-runtime": "^0.1.2"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
package/site/embed.js
CHANGED
|
@@ -26,15 +26,17 @@ const PACK_CDN_ORIGIN = 'https://cdn.jsdelivr.net'
|
|
|
26
26
|
* @param {string | null} [options.librariesPack] the URL of a copy of `@missing-elements/h5p-libraries`
|
|
27
27
|
* on this site, which `libraries=pack` names; without one, `pack` is the element's copy on jsDelivr
|
|
28
28
|
* @param {string[] | null} [options.packages] the origins packages and library bundles may come
|
|
29
|
-
* from, besides this page's own; `null` plays any,
|
|
29
|
+
* from, besides this page's own; `null` plays any, one from another origin `untrusted` when the
|
|
30
|
+
* storage is this origin's
|
|
30
31
|
* @param {string | null} [options.defaultLibraries] the `libraries` value for an address that has
|
|
31
32
|
* none — `pack` or URLs, as the parameter — so a snippet without `&libraries=` still plays
|
|
32
33
|
* an export that carries no libraries; `&libraries=none` turns it off for one address
|
|
33
34
|
* @param {object | null} [options.runtime] the `runtime` export of `@missing-elements/h5p-runtime`,
|
|
34
35
|
* for a page that bundles the element; without it the element looks for `frame-assets/` beside itself
|
|
35
|
-
* @param {boolean} [options.askInOwnFrame] whether a package from another origin
|
|
36
|
-
*
|
|
37
|
-
* own
|
|
36
|
+
* @param {boolean} [options.askInOwnFrame] whether a package from another origin plays `untrusted`,
|
|
37
|
+
* with a click to play it with its own code when it needs that, when this page is framed by a
|
|
38
|
+
* page of its own origin, whose storage it shares. A site whose own preview frames the page for
|
|
39
|
+
* a package the visitor just chose passes `false`
|
|
38
40
|
*/
|
|
39
41
|
export function startEmbed({ librariesPack = null, packages = null, defaultLibraries = null, runtime = null, askInOwnFrame = true } = {}) {
|
|
40
42
|
const params = new URLSearchParams(location.search)
|
|
@@ -166,8 +168,16 @@ export function startEmbed({ librariesPack = null, packages = null, defaultLibra
|
|
|
166
168
|
|
|
167
169
|
/* ---------------------------------------------------------------- errors, and Safari */
|
|
168
170
|
|
|
171
|
+
/** Asks whether to play an untrusted package with its own code; set when one is played so. */
|
|
172
|
+
let askToTrust = null
|
|
173
|
+
|
|
169
174
|
player.addEventListener('error', (event) => {
|
|
170
|
-
const { code, message } = event.detail
|
|
175
|
+
const { code, message, missingLibraries } = event.detail
|
|
176
|
+
// Played untrusted, it cannot do without its own copy of a library: a click decides.
|
|
177
|
+
if (missingLibraries?.carried && player.untrusted && askToTrust) {
|
|
178
|
+
askToTrust()
|
|
179
|
+
return
|
|
180
|
+
}
|
|
171
181
|
if (code === 'no-worker' && framed) {
|
|
172
182
|
// Detected, not sniffed: a browser, an in-app one or a page that is not https may give a
|
|
173
183
|
// frame no Service Worker, and the player cannot run without one. Safari does allow it.
|
|
@@ -311,25 +321,44 @@ export function startEmbed({ librariesPack = null, packages = null, defaultLibra
|
|
|
311
321
|
return
|
|
312
322
|
}
|
|
313
323
|
|
|
314
|
-
// A host on the list was vouched for when the site was set up
|
|
315
|
-
//
|
|
324
|
+
// A host on the list was vouched for when the site was set up, and in another site's frame the
|
|
325
|
+
// storage is that site's own: those play as they are.
|
|
316
326
|
if (origin === location.origin || allowed || !sharesOriginStorage()) {
|
|
317
327
|
start(src, sources.value)
|
|
318
328
|
return
|
|
319
329
|
}
|
|
320
|
-
|
|
330
|
+
|
|
331
|
+
// Anything else from another origin would share this origin's storage. It plays untrusted, as
|
|
332
|
+
// data with the library pack's code and none of its own, and waits for a click that names the
|
|
333
|
+
// host only when it cannot play without its own, or there is no pack to play it with.
|
|
321
334
|
const host = new URL(src, location.href).host || origin
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
+
askToTrust = () => {
|
|
336
|
+
loader.hidden = true
|
|
337
|
+
const button = document.createElement('button')
|
|
338
|
+
button.type = 'button'
|
|
339
|
+
button.textContent = 'Open with its own scripts'
|
|
340
|
+
button.addEventListener('click', () => {
|
|
341
|
+
say('')
|
|
342
|
+
loader.hidden = false
|
|
343
|
+
player.untrusted = false
|
|
344
|
+
player.removeAttribute('src')
|
|
345
|
+
start(src, sources.value)
|
|
346
|
+
})
|
|
347
|
+
say(
|
|
348
|
+
`This package from ${host} plays only with its own scripts. They would run on this site and ` +
|
|
349
|
+
'could read what other packages saved in this browser. Open it only if you trust that site.'
|
|
350
|
+
)
|
|
351
|
+
notice.append(' ', button)
|
|
352
|
+
}
|
|
353
|
+
// The address's `libraries=` is the link-writer's as much as its `src`, and a bundle's code runs
|
|
354
|
+
// as the host's own: an untrusted package plays with this site's sources alone, the page's
|
|
355
|
+
// default or its pack, and the address's only once the click has trusted it.
|
|
356
|
+
const own = defaultLibraries?.trim() ? librarySources(defaultLibraries.trim()).value : ''
|
|
357
|
+
const pack = own || librarySources('pack').value
|
|
358
|
+
if (!pack) {
|
|
359
|
+
askToTrust()
|
|
360
|
+
return
|
|
361
|
+
}
|
|
362
|
+
player.untrusted = true
|
|
363
|
+
start(src, pack)
|
|
335
364
|
}
|