@pie-players/pie-tool-picture-dictionary 0.3.67
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 +108 -0
- package/dist/index.d.ts +1 -0
- package/dist/lookup.d.ts +52 -0
- package/dist/tool-picture-dictionary.js +2819 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# @pie-players/pie-tool-picture-dictionary
|
|
2
|
+
|
|
3
|
+
Picture dictionary panel for the PIE assessment player. Registers
|
|
4
|
+
`<pie-tool-picture-dictionary>`.
|
|
5
|
+
|
|
6
|
+
## Lookup is host-supplied
|
|
7
|
+
|
|
8
|
+
PIE ships no endpoint. The symbol corpus behind a picture dictionary is licensed, so
|
|
9
|
+
a host supplies one.
|
|
10
|
+
|
|
11
|
+
```html
|
|
12
|
+
<pie-tool-picture-dictionary endpoint="/api/picture-dictionary" language="en">
|
|
13
|
+
</pie-tool-picture-dictionary>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```js
|
|
17
|
+
element.lookup = async ({ keyword, language, max }, signal) => ({
|
|
18
|
+
status: "ok",
|
|
19
|
+
items: [{ url: "/symbols/apple.png", caption: "An apple" }],
|
|
20
|
+
});
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
With neither, the panel says no service is configured.
|
|
24
|
+
|
|
25
|
+
The endpoint is called `same-origin`, so a route already behind the assessment's own
|
|
26
|
+
session answers with no further configuration. A host authorising some other way
|
|
27
|
+
passes a `headers` function, read per request so a short-lived token is fetched fresh;
|
|
28
|
+
one that wants no ambient credentials passes `credentials: "omit"`. Both are optional
|
|
29
|
+
properties.
|
|
30
|
+
|
|
31
|
+
### Request
|
|
32
|
+
|
|
33
|
+
`POST` with `{ keyword, language?, max? }` — the shape a picture-dictionary service
|
|
34
|
+
is expected to accept. `keyword` is normalised before it is sent, and a selection
|
|
35
|
+
longer than four words is refused without a request.
|
|
36
|
+
|
|
37
|
+
### Response
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"pictures": [
|
|
42
|
+
{ "url": "/symbols/apple.png", "caption": "An apple", "width": 120, "height": 90 }
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`images` is accepted as an alias for `pictures`, and within an entry `image` as an
|
|
48
|
+
alias for `url` — `url` wins if a payload carries both. Unknown extra fields are
|
|
49
|
+
ignored. Signed, short-lived URLs are expected and fine.
|
|
50
|
+
|
|
51
|
+
### Pointing it at an existing service
|
|
52
|
+
|
|
53
|
+
A service that already takes `{ keyword, language?, max? }` and answers
|
|
54
|
+
`{ images: [{ image }] }` needs no resolver: name it in `endpoint` and the built-in
|
|
55
|
+
lookup speaks it as it stands.
|
|
56
|
+
|
|
57
|
+
Two things such a service decides rather than this panel. If it is cross-origin from the
|
|
58
|
+
assessment, the `same-origin` default sends no credentials, so a service token goes
|
|
59
|
+
through `headers` — a path a host can use directly instead of proxying. And if it
|
|
60
|
+
defaults the language server-side, a non-default language has to be declared: the panel
|
|
61
|
+
sends `language` only when the host sets it.
|
|
62
|
+
|
|
63
|
+
A picture whose URL is not `https:`, protocol-relative, or a same-origin path is
|
|
64
|
+
dropped — host data still reaches an attribute the browser acts on, and a symbol
|
|
65
|
+
service has no reason to return `javascript:` or `data:`. Plain `http:` is dropped
|
|
66
|
+
because it is mixed content on every https deployment, which is a broken image where
|
|
67
|
+
the definition should be. A leading `/` is checked by resolving rather than by prefix:
|
|
68
|
+
`/\evil.example/x.png` looks like a path and resolves to another host, because a
|
|
69
|
+
backslash is a path separator for special schemes. If every picture is dropped the
|
|
70
|
+
panel reports "no picture" rather than rendering a broken grid.
|
|
71
|
+
|
|
72
|
+
Zero pictures is reported as "no picture", distinct from a service failure.
|
|
73
|
+
|
|
74
|
+
## Alt text
|
|
75
|
+
|
|
76
|
+
The picture *is* the definition, so it is never decorative and never gets an empty
|
|
77
|
+
`alt`. The caption becomes the `alt`; without one the keyword stands in, which at
|
|
78
|
+
least tells a screen reader user what the picture is meant to depict. The visible
|
|
79
|
+
caption is `aria-hidden`, since it is already the `alt`.
|
|
80
|
+
|
|
81
|
+
## Two entry points, deliberately
|
|
82
|
+
|
|
83
|
+
The `term` property is set by whatever selection affordance the host offers. The
|
|
84
|
+
field is the tool's keyboard route, not a convenience: a sighted keyboard-only
|
|
85
|
+
learner cannot originate a text selection in non-editable content, because Chromium
|
|
86
|
+
does not extend one with Shift+Arrow there without caret browsing — an OS-level
|
|
87
|
+
toggle that does not exist on mobile. A selection-only picture dictionary would be
|
|
88
|
+
unreachable for exactly the learners most likely to need it.
|
|
89
|
+
|
|
90
|
+
## Properties
|
|
91
|
+
|
|
92
|
+
| Name | Attribute | Type | Notes |
|
|
93
|
+
| ---------- | ---------- | -------- | ---------------------------------------------- |
|
|
94
|
+
| `visible` | `visible` | boolean | Owned by the toolbar shell. |
|
|
95
|
+
| `toolId` | `tool-id` | string | Scoped tool instance id. |
|
|
96
|
+
| `term` | `term` | string | Pre-fills and searches when the panel is open. |
|
|
97
|
+
| `termRequestId` | — | string \| number | Identity of the current `term`; optional. |
|
|
98
|
+
| `endpoint` | `endpoint` | string | Enables the built-in POST lookup. |
|
|
99
|
+
| `language` | `language` | string | BCP-47 tag sent with the request. |
|
|
100
|
+
| `lookup` | — | function | Host resolver; takes precedence over `endpoint`. |
|
|
101
|
+
| `headers` | — | function | Extra request headers for `endpoint`, read per request. |
|
|
102
|
+
| `credentials` | — | string | Overrides the `same-origin` default for `endpoint`. |
|
|
103
|
+
|
|
104
|
+
A `lookup` resolves to `{ status: "ok", items }`, `{ status: "empty" }`, or
|
|
105
|
+
`{ status: "error", reason }`. `empty` and `error` are separate on purpose: a learner
|
|
106
|
+
must not be told their word is not real when the network is down.
|
|
107
|
+
|
|
108
|
+
The panel renders its body only; floating chrome belongs to the toolbar shell.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
package/dist/lookup.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { TermLookup, TermLookupRequest, TermLookupResult } from '@pie-players/pie-players-shared/tools/term-lookup';
|
|
2
|
+
export type PictureLookupRequest = TermLookupRequest;
|
|
3
|
+
export interface PictureResult {
|
|
4
|
+
/** `https:`, protocol-relative or same-origin URL. Signed, short-lived URLs are fine. */
|
|
5
|
+
url: string;
|
|
6
|
+
/**
|
|
7
|
+
* What the picture shows.
|
|
8
|
+
*
|
|
9
|
+
* Becomes the image's `alt`. For this tool the picture *is* the definition, so it
|
|
10
|
+
* is never decorative and never gets an empty `alt`; without a caption the keyword
|
|
11
|
+
* stands in.
|
|
12
|
+
*/
|
|
13
|
+
caption?: string;
|
|
14
|
+
width?: number;
|
|
15
|
+
height?: number;
|
|
16
|
+
}
|
|
17
|
+
export type PictureLookupResult = TermLookupResult<PictureResult>;
|
|
18
|
+
export type PictureLookup = TermLookup<PictureResult>;
|
|
19
|
+
/** Pictures a single lookup may render. A symbol set rarely has more than a few. */
|
|
20
|
+
export declare const DEFAULT_MAX_PICTURES = 4;
|
|
21
|
+
/**
|
|
22
|
+
* Whether a URL is safe to put in `src`.
|
|
23
|
+
*
|
|
24
|
+
* `https:`, protocol-relative and same-origin paths pass; everything else is refused.
|
|
25
|
+
* `javascript:` and `data:` because a response reaches an attribute the browser
|
|
26
|
+
* executes for some schemes and a symbol service has no reason to return either, and
|
|
27
|
+
* plain `http:` because it is mixed content on every https deployment — the browser
|
|
28
|
+
* blocks it and the learner gets a broken image where the definition should be, which
|
|
29
|
+
* is the outcome this guard exists to prevent.
|
|
30
|
+
*
|
|
31
|
+
* A leading `/` is checked by resolving rather than by prefix: `/\evil.example/x.png`
|
|
32
|
+
* looks like a path and resolves to `https://evil.example/x.png`, because a backslash
|
|
33
|
+
* is a path separator for special schemes and a tab is stripped outright. Both land on
|
|
34
|
+
* https, so neither defeats the mixed-content guard — but "same-origin" is what this
|
|
35
|
+
* function says it means, so it is what it checks.
|
|
36
|
+
*/
|
|
37
|
+
export declare function isRenderablePictureUrl(value: string): boolean;
|
|
38
|
+
/** Read a host response into a result, ignoring unknown extra fields. */
|
|
39
|
+
export declare function readPictureResponse(payload: unknown): PictureLookupResult;
|
|
40
|
+
/**
|
|
41
|
+
* A lookup that POSTs to a host endpoint.
|
|
42
|
+
*
|
|
43
|
+
* The session cookie rides along by default, because a host is expected to put its
|
|
44
|
+
* picture route behind the same session boundary as the assessment; `credentials` and
|
|
45
|
+
* `headers` are there for a host that authorises some other way.
|
|
46
|
+
*/
|
|
47
|
+
export declare function createEndpointLookup(args: {
|
|
48
|
+
endpoint: string;
|
|
49
|
+
headers?: () => Promise<Record<string, string>> | Record<string, string>;
|
|
50
|
+
credentials?: RequestCredentials;
|
|
51
|
+
fetchImpl?: typeof fetch;
|
|
52
|
+
}): PictureLookup;
|