devcoach 2.0.1 → 2.1.0-next.503.g8594664
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 +17 -13
- package/assets/SKILL.md +30 -6
- package/assets/references/calibration.md +6 -5
- package/assets/references/onboarding.md +7 -6
- package/assets/references/review.md +6 -5
- package/assets/static/share.js +66 -0
- package/assets/static/vendor/purify.min.js +3 -0
- package/dist/{app-GO3HPOM6.js → app-KE4H5NNP.js} +198 -96
- package/dist/bin.js +1 -1
- package/dist/chunk-2LE7K3NO.js +15 -0
- package/dist/chunk-3RBMKXAA.js +2 -0
- package/dist/chunk-4KFSUF7S.js +75 -0
- package/dist/chunk-MRABMPXO.js +3 -0
- package/dist/commands-WO3BAZJM.js +33 -0
- package/dist/{hooks-5PEDPGZD.js → hooks-6I6M3PGN.js} +1 -1
- package/dist/server-JJASGVG5.js +9 -0
- package/package.json +5 -5
- package/dist/chunk-ECN4MNGM.js +0 -66
- package/dist/chunk-OSA5I6L7.js +0 -15
- package/dist/chunk-ZCSBBJ3A.js +0 -3
- package/dist/commands-DC5NTWGY.js +0 -33
- package/dist/server-4FNXIQ2Q.js +0 -9
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/devcoach)
|
|
10
|
-
[](https://github.com/UltimaPhoenix/dev-coach/actions/workflows/ci.yml)
|
|
10
|
+
[](https://github.com/UltimaPhoenix/dev-coach/actions/workflows/ci.yml?query=branch%3Adevelop)
|
|
11
11
|
[](https://sonarcloud.io/summary/new_code?id=UltimaPhoenix_dev-coach)
|
|
12
12
|
[](https://sonarcloud.io/summary/new_code?id=UltimaPhoenix_dev-coach)
|
|
13
13
|
[](https://nodejs.org/)
|
|
@@ -153,6 +153,8 @@ npx -y devcoach install
|
|
|
153
153
|
|
|
154
154
|
Restart your agent afterward. Prefer a global binary? `npm install -g devcoach`, then run `devcoach install` (and drop the `npx -y` prefix everywhere). After upgrading devcoach, re-run `devcoach install` to refresh the skill — `devcoach stats` reminds you when it's out of date.
|
|
155
155
|
|
|
156
|
+
**Canary builds:** every change merged into the `develop` branch is published to npm under the `next` tag — `npx -y devcoach@next` (or `npm install -g devcoach@next`) runs the unreleased version, documented at [ultimaphoenix.github.io/dev-coach/next](https://ultimaphoenix.github.io/dev-coach/next/). `latest` stays the last release.
|
|
157
|
+
|
|
156
158
|
</details>
|
|
157
159
|
|
|
158
160
|
<details>
|
|
@@ -394,7 +396,7 @@ Using the Claude Code plugin? Type `/devcoach:ui` in Claude Code instead — no
|
|
|
394
396
|
| Page | What you can do |
|
|
395
397
|
|------|-----------------|
|
|
396
398
|
| **Knowledge map** | See all topics with confidence bars; adjust scores directly |
|
|
397
|
-
| **Lessons** | Browse and filter your full lesson history; star lessons to revisit |
|
|
399
|
+
| **Lessons** | Browse and filter your full lesson history; star lessons to revisit; share a lesson with a teammate or import theirs |
|
|
398
400
|
| **Settings** | Change rate limits, import/export your profile, take a backup |
|
|
399
401
|
|
|
400
402
|
Full reference: [docs/usage/web-ui.md](docs/usage/web-ui.md)
|
|
@@ -414,6 +416,8 @@ The CLI is a secondary interface for querying and managing your coaching data. E
|
|
|
414
416
|
| `devcoach lesson <id>` | Show a single lesson in full |
|
|
415
417
|
| `devcoach star <id>` | Mark a lesson as starred |
|
|
416
418
|
| `devcoach feedback <id> <know\|dont_know\|clear>` | Record comprehension |
|
|
419
|
+
| `devcoach share [id] [--last] [--link] [--file]` | Hand a lesson to a teammate (copyable text, link or `.devcoach.md`) |
|
|
420
|
+
| `devcoach import [source]` | Add a shared lesson — code, link, URL or file; no argument reads the clipboard |
|
|
417
421
|
| `devcoach set max_per_day <n>` | Max lessons per day (default 2) |
|
|
418
422
|
| `devcoach set min_gap_minutes <n>` | Minutes between lessons (default 240) |
|
|
419
423
|
| `devcoach backup [file.zip]` | Export knowledge + lessons + settings + notebook |
|
|
@@ -548,17 +552,17 @@ npm run mcpb # build the Claude Desktop .mcpb (npm run mcpb:sign to
|
|
|
548
552
|
- **MCP Inspector:** `npx @modelcontextprotocol/inspector node dist/bin.js mcp`
|
|
549
553
|
- **Stack:** `@modelcontextprotocol/server` (MCP SDK v2) · `node:sqlite` · Hono · Commander · Zod · Biome · Vitest · tsup
|
|
550
554
|
|
|
551
|
-
###
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
`devcoach` package (GitHub Actions, repo `UltimaPhoenix/dev-coach`, workflow `ci.yml`).
|
|
555
|
+
### Branches & releases
|
|
556
|
+
|
|
557
|
+
- `develop` is the integration branch: every PR targets it, and each merge publishes a **canary**
|
|
558
|
+
(`npx -y devcoach@next`, docs at `/next/`).
|
|
559
|
+
- `main` only receives releases and is always the last published version (the Claude Code
|
|
560
|
+
self-marketplace installs from it).
|
|
561
|
+
- A release is one click: run the **CI** workflow (*Run workflow* → patch / minor / major) on
|
|
562
|
+
`develop`. CI bumps the version on `develop`, tags it, fast-forwards `main`, then publishes to npm via
|
|
563
|
+
**OIDC provenance**, attaches the `.mcpb` + plugin zips to a GitHub Release, and updates the Homebrew
|
|
564
|
+
tap, the plugin marketplace and the MCP Registry. First-time setup: configure a Trusted Publisher on
|
|
565
|
+
npmjs.com for the `devcoach` package (GitHub Actions, repo `UltimaPhoenix/dev-coach`, workflow `ci.yml`).
|
|
562
566
|
|
|
563
567
|
---
|
|
564
568
|
|
package/assets/SKILL.md
CHANGED
|
@@ -10,7 +10,10 @@ description: >
|
|
|
10
10
|
or whether new tech from their recent work should be tracked; (3) a devcoach
|
|
11
11
|
hook cue requests a lesson; (4) you just completed substantial technical work
|
|
12
12
|
(code, review, commit, debugging, config, queries, infra) — then evaluate
|
|
13
|
-
silently whether ONE lesson is due, even when coaching is never mentioned
|
|
13
|
+
silently whether ONE lesson is due, even when coaching is never mentioned;
|
|
14
|
+
(5) the user wants to share a lesson with someone, or hands you a lesson they
|
|
15
|
+
were given — a `devcoach:lesson:` code, a share link, a URL, or a
|
|
16
|
+
`.devcoach.md` file — to import.
|
|
14
17
|
Do NOT use for ordinary development tasks on code, apps, or documents that
|
|
15
18
|
merely contain words like profile, lessons, or notebook — only when the subject
|
|
16
19
|
is the user's own coaching data.
|
|
@@ -40,7 +43,7 @@ The three hard rules, before anything else:
|
|
|
40
43
|
|
|
41
44
|
## Onboarding
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
Call `get_onboarding`. If `knowledge_ready` or `notebook_ready` is false — or the
|
|
44
47
|
user explicitly asks to (re-)initialise their profile — read `references/onboarding.md`
|
|
45
48
|
in this skill's directory and follow it. Do not deliver a lesson in the same turn as
|
|
46
49
|
`complete_onboarding`; end the response after confirming setup.
|
|
@@ -55,8 +58,11 @@ only an explicit "redo onboarding" goes through `references/onboarding.md`.
|
|
|
55
58
|
|
|
56
59
|
## Before delivering a lesson
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
Call the **`get_briefing`** tool — ONE silent call returns everything below (never fetch
|
|
62
|
+
the pieces one by one; each extra call is noise). Read state through tools, never through
|
|
63
|
+
`devcoach://` resources: tool names resolve in every client, a resource read needs the
|
|
64
|
+
server's client-specific name. Older server without `get_briefing` → read the
|
|
65
|
+
`devcoach://briefing` resource instead.
|
|
60
66
|
|
|
61
67
|
- `onboarding` — either flag false → onboarding first (see above)
|
|
62
68
|
- `rate_limit` — `allowed: false` → skip entirely, say nothing.
|
|
@@ -162,8 +168,19 @@ for "know" (within/above band → already calibrated, skip the call). Never call
|
|
|
162
168
|
`get_lessons({search: topic_id})` shows 2+ lessons on the topic, offer *"Want to save
|
|
163
169
|
this one? ⭐"* — `star_lesson` only if the user agrees, never silently.
|
|
164
170
|
|
|
171
|
+
**Sharing:** only when the user asks — never offer it. "Share this / the last lesson"
|
|
172
|
+
→ `share_lesson({lesson_id})` (`get_lessons` first when the lesson isn't obvious; ask if
|
|
173
|
+
ambiguous); "as a link" / "as a file" picks the `transport`. `include_context` (project,
|
|
174
|
+
branch, commit, task) only when the user explicitly asks — local paths never travel.
|
|
175
|
+
The reply is exactly what `reply_check` says: the code line goes in a fenced block,
|
|
176
|
+
verbatim, never wrapped or paraphrased. The sender name comes from the `share_name`
|
|
177
|
+
setting, then git; if the user spells a name, offer once to remember it via
|
|
178
|
+
`update_settings({key: "share_name"})`. A lesson the user was given — code, link, URL,
|
|
179
|
+
card text or `.devcoach.md` contents — goes to `import_lesson({payload})` verbatim; a
|
|
180
|
+
duplicate is a normal outcome, not an error.
|
|
181
|
+
|
|
165
182
|
**Profile expansion:** if the lesson covered a concept absent from
|
|
166
|
-
|
|
183
|
+
the profile (`get_profile`), or one that recurs across tasks, offer to track it with an estimated
|
|
167
184
|
confidence (fluent use → 6–7, uncertain → 4–5, first encounter → 2–3); `add_topic`
|
|
168
185
|
only on confirmation.
|
|
169
186
|
|
|
@@ -176,9 +193,14 @@ checkpoints, never touch the notebook.
|
|
|
176
193
|
|
|
177
194
|
- "What did I learn today/this week?" → `get_lessons({period: "today" | "week" | …})`
|
|
178
195
|
- "Show me lessons about X" → `get_lessons({category: X})` or `({search: keyword})`
|
|
179
|
-
- "How good am I at X?" / "Show my profile" →
|
|
196
|
+
- "How good am I at X?" / "Show my profile" → `get_profile`
|
|
180
197
|
- "Coaching log" → `get_lessons({period: "all"})`
|
|
181
198
|
- "Lessons to revisit" → `get_lessons({feedback: "dont_know"})`
|
|
199
|
+
- "Share this / the last lesson" / "share the lesson about X" → `get_lessons` then
|
|
200
|
+
`share_lesson({lesson_id})` (see Sharing)
|
|
201
|
+
- "Import this lesson" / a pasted `devcoach:lesson:` code, link or URL →
|
|
202
|
+
`import_lesson({payload})` verbatim
|
|
203
|
+
- "Lessons shared with me" → `get_lessons({imported: true})`
|
|
182
204
|
|
|
183
205
|
## Operating notes
|
|
184
206
|
|
|
@@ -190,3 +212,5 @@ checkpoints, never touch the notebook.
|
|
|
190
212
|
- The lesson must feel natural and contextual, not a mechanical add-on
|
|
191
213
|
- Nothing interesting to teach → `skip_lesson` (if cued) or stay silent. Better
|
|
192
214
|
nothing than forced.
|
|
215
|
+
- A share or import the user asked for is an ordinary reply, not a lesson: no card
|
|
216
|
+
bands, no feedback prompt — just what `reply_check` asks for.
|
|
@@ -6,7 +6,8 @@ Read this file when the hook cue marks the lesson as a notebook checkpoint (ever
|
|
|
6
6
|
## Step 1 — Fetch the window
|
|
7
7
|
|
|
8
8
|
Call `get_lessons()` (default `limit=10`, newest first) to get the last 10 lessons.
|
|
9
|
-
|
|
9
|
+
Call `get_profile` for the current knowledge map (older server without the tool: read the
|
|
10
|
+
`devcoach://profile` resource).
|
|
10
11
|
|
|
11
12
|
## Step 2 — Per-topic signal analysis
|
|
12
13
|
|
|
@@ -17,22 +18,22 @@ Group the 10 lessons by `topic_id`. For each topic that appeared:
|
|
|
17
18
|
| Consistent mastery | All feedback `know`, no `dont_know` | `update_knowledge(topic, +1)` if confidence < 9 |
|
|
18
19
|
| Persistent gap | 2+ lessons on same topic, any `dont_know` | `update_knowledge(topic, -1)` if confidence > 1 |
|
|
19
20
|
| Recurring topic | 3+ lessons on same topic, mixed or no feedback | no confidence change — note in notebook |
|
|
20
|
-
| New topic | `topic_id` absent from `
|
|
21
|
+
| New topic | `topic_id` absent from `get_profile` | `add_topic` — see Step 3 |
|
|
21
22
|
|
|
22
23
|
Apply at most **one** `update_knowledge` call per topic per calibration run.
|
|
23
24
|
Never call `update_knowledge` on a topic with confidence 10 (already mastered).
|
|
24
25
|
|
|
25
26
|
## Step 3 — New topic discovery
|
|
26
27
|
|
|
27
|
-
For each lesson whose `topic_id` is not in `
|
|
28
|
+
For each lesson whose `topic_id` is not in `get_profile`:
|
|
28
29
|
- 2+ lessons share this `topic_id` in the window → call `add_topic(topic_id, confidence=5)`;
|
|
29
30
|
assign it to the same group as the closest related existing topic, or `"Other"` if unclear.
|
|
30
31
|
- Only 1 lesson on this `topic_id` → note under **Open hypotheses** in the notebook; do not add yet.
|
|
31
32
|
|
|
32
33
|
## Step 4 — Update the coaching notebook
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
Call `get_briefing` for the current notebook text and its `notebook_path` — one
|
|
36
|
+
call covers both. Merge findings into the relevant sections and write the complete
|
|
36
37
|
revised markdown directly to `notebook_path` (your own Write/Edit tool), overwriting the
|
|
37
38
|
file in one go:
|
|
38
39
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# devcoach — Onboarding flow
|
|
2
2
|
|
|
3
|
-
Read this file when `
|
|
3
|
+
Read this file when `get_onboarding` reports `knowledge_ready: false` or
|
|
4
4
|
`notebook_ready: false`, or when the user explicitly asks to (re-)initialise their
|
|
5
5
|
profile ("setup devcoach", "redo onboarding", "reset my topics").
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ The onboarding flow runs inline, immediately before delivering a lesson, wheneve
|
|
|
8
8
|
it is needed. There is no separate session startup phase — this makes the skill
|
|
9
9
|
robust to context compaction and plan-mode transitions.
|
|
10
10
|
|
|
11
|
-
Check `knowledge_ready` and `notebook_ready` from `
|
|
11
|
+
Check `knowledge_ready` and `notebook_ready` from `get_onboarding` independently
|
|
12
12
|
— each step can run alone:
|
|
13
13
|
|
|
14
14
|
```
|
|
@@ -23,7 +23,8 @@ always re-runs Steps 1–4 regardless of `knowledge_ready`.
|
|
|
23
23
|
|
|
24
24
|
## Step 1 — Ask how to set up (strongly recommend Automatic; never pick for the user)
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
Call `get_onboarding` FIRST (older server without the tool: read the `devcoach://onboarding`
|
|
27
|
+
resource) — its `detected_stack`, `detected_projects`,
|
|
27
28
|
`scanned_projects`, and `notebook_path` come from a scan of the user's **full Claude
|
|
28
29
|
Code history** (every project Claude has worked in, ranked by recent activity), not
|
|
29
30
|
just the current folder. Keep `notebook_path` in scope — Step 4 needs it and there is
|
|
@@ -57,8 +58,8 @@ depend on `scanClaudeHistory`'s metadata scan). Do **not** default to Automatic
|
|
|
57
58
|
silently — surface the choice and wait for the user's answer before proceeding.
|
|
58
59
|
|
|
59
60
|
**If Import backup:** ask for the file path and call `restore` (CLI) with it. Restore
|
|
60
|
-
brings back knowledge entries automatically — no further DB steps needed.
|
|
61
|
-
`
|
|
61
|
+
brings back knowledge entries automatically — no further DB steps needed. Call
|
|
62
|
+
`get_onboarding` again after restore; if `knowledge_ready` is now true, skip to the
|
|
62
63
|
notebook-composition part of Step 4. If `notebook_ready` is also true, proceed normally.
|
|
63
64
|
|
|
64
65
|
## Step 2 — Build the topic list for the chosen mode
|
|
@@ -153,7 +154,7 @@ Automatic tiers; after the user confirms in Guided mode):
|
|
|
153
154
|
{ "topics": { "lang_a": 7, "tool_b": 8 }, "groups": { "Languages": ["lang_a"], "DevOps": ["tool_b"] } }
|
|
154
155
|
```
|
|
155
156
|
2. **Immediately after**, write the real personalized notebook markdown directly to
|
|
156
|
-
`notebook_path` (from Step 1's `
|
|
157
|
+
`notebook_path` (from Step 1's `get_onboarding` call) using your own file
|
|
157
158
|
tools — overwrite the placeholder right away, don't leave it standing. If
|
|
158
159
|
`notebook_path` already has real content (re-onboarding, or restoring), read it first
|
|
159
160
|
and fold prior notes in rather than discarding them.
|
|
@@ -17,7 +17,8 @@ redo onboarding / reset topics → references/onboarding.md, Steps 1–4 (co
|
|
|
17
17
|
|
|
18
18
|
## Review
|
|
19
19
|
|
|
20
|
-
1.
|
|
20
|
+
1. Call `get_briefing` (older server without the tool: read the `devcoach://briefing`
|
|
21
|
+
resource) — one silent call returns the profile, the taught
|
|
21
22
|
topics, the notebook, and its `notebook_path`.
|
|
22
23
|
2. Walk the user through the profile **grouped, not topic-by-topic**: show each
|
|
23
24
|
group with its topics and confidences, and ask what looks wrong. Apply
|
|
@@ -33,9 +34,9 @@ redo onboarding / reset topics → references/onboarding.md, Steps 1–4 (co
|
|
|
33
34
|
|
|
34
35
|
Re-derive the notebook from real data; the knowledge map is untouched.
|
|
35
36
|
|
|
36
|
-
1.
|
|
37
|
+
1. Call `get_onboarding` — `detected_projects` carries the history-wide
|
|
37
38
|
evidence: per-project stacks, activity volume and recency, and auto-memory
|
|
38
|
-
excerpts (and its `notebook_path`).
|
|
39
|
+
excerpts (and its `notebook_path`). Call `get_briefing` for the
|
|
39
40
|
current notebook and profile, and `get_lessons({period: "all"})` for
|
|
40
41
|
feedback history (`dont_know` lessons are open gaps).
|
|
41
42
|
2. Compose a fresh notebook (structure in `references/onboarding.md`'s notebook
|
|
@@ -47,7 +48,7 @@ Re-derive the notebook from real data; the knowledge map is untouched.
|
|
|
47
48
|
|
|
48
49
|
## New tech check (keep the profile curated)
|
|
49
50
|
|
|
50
|
-
Compare `detected_stack` + `detected_projects` (from `
|
|
51
|
+
Compare `detected_stack` + `detected_projects` (from `get_onboarding`)
|
|
51
52
|
against the current profile:
|
|
52
53
|
|
|
53
54
|
- Candidate = a detected topic **absent from the profile** that appears in **2+
|
|
@@ -60,7 +61,7 @@ against the current profile:
|
|
|
60
61
|
appear in **no** scanned project. Offer `remove_topic`; keeping them is fine.
|
|
61
62
|
- Nothing qualifies → say so in one line and stop. An overcrowded topic list
|
|
62
63
|
dilutes lesson choice — fewer, real topics beat completeness.
|
|
63
|
-
- `
|
|
64
|
+
- `get_onboarding` failing, or `detected_projects` empty → derive
|
|
64
65
|
candidates from lesson history instead (`get_lessons`: recurring stacks in
|
|
65
66
|
`task_context` that lack a matching topic), tell the user the evidence is
|
|
66
67
|
history-only, and defer the retirement pass — never guess retirements
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/* Lesson sharing helpers for the dashboard (lesson detail + lessons list).
|
|
2
|
+
The share payloads are pre-rendered by the server into #share-payloads data-* attributes so a
|
|
3
|
+
clipboard write happens synchronously inside the click (Safari refuses async writes). */
|
|
4
|
+
(function () {
|
|
5
|
+
function fallbackCopy(text) {
|
|
6
|
+
var ta = document.createElement('textarea');
|
|
7
|
+
ta.value = text;
|
|
8
|
+
ta.setAttribute('readonly', '');
|
|
9
|
+
ta.style.position = 'fixed';
|
|
10
|
+
ta.style.opacity = '0';
|
|
11
|
+
document.body.appendChild(ta);
|
|
12
|
+
ta.select();
|
|
13
|
+
var ok = false;
|
|
14
|
+
try { ok = document.execCommand('copy'); } catch (e) { ok = false; }
|
|
15
|
+
document.body.removeChild(ta);
|
|
16
|
+
return ok;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function flash(btn, label) {
|
|
20
|
+
if (!btn) return;
|
|
21
|
+
var original = btn.dataset.label || btn.textContent;
|
|
22
|
+
btn.dataset.label = original;
|
|
23
|
+
btn.textContent = label;
|
|
24
|
+
setTimeout(function () { btn.textContent = original; }, 1500);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
window.copyShare = function (kind, btn) {
|
|
28
|
+
var el = document.getElementById('share-payloads');
|
|
29
|
+
if (!el) return;
|
|
30
|
+
var text = el.dataset[kind] || '';
|
|
31
|
+
var done = function () { flash(btn, '✓ Copied'); };
|
|
32
|
+
var fail = function () { flash(btn, fallbackCopy(text) ? '✓ Copied' : 'Copy failed'); };
|
|
33
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
34
|
+
navigator.clipboard.writeText(text).then(done, fail);
|
|
35
|
+
} else {
|
|
36
|
+
fail();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/* Drop a .devcoach.md (or lessons .json) anywhere on the lessons page: the dropped file goes
|
|
41
|
+
into the import form's file input and the form submits. */
|
|
42
|
+
window.dropSharedFile = function (event) {
|
|
43
|
+
var files = event.dataTransfer && event.dataTransfer.files;
|
|
44
|
+
var form = document.getElementById('import-form');
|
|
45
|
+
var input = document.getElementById('import-file');
|
|
46
|
+
if (!files || !files.length || !form || !input) return;
|
|
47
|
+
input.files = files;
|
|
48
|
+
form.submit();
|
|
49
|
+
};
|
|
50
|
+
})();
|
|
51
|
+
|
|
52
|
+
/* Drop anywhere: only on pages that carry the import form. */
|
|
53
|
+
(function () {
|
|
54
|
+
if (!document.getElementById('import-form')) return;
|
|
55
|
+
var hint = document.getElementById('drop-hint');
|
|
56
|
+
var depth = 0;
|
|
57
|
+
function show(on) {
|
|
58
|
+
if (!hint) return;
|
|
59
|
+
hint.classList.toggle('hidden', !on);
|
|
60
|
+
hint.classList.toggle('flex', on);
|
|
61
|
+
}
|
|
62
|
+
window.addEventListener('dragenter', function (e) { e.preventDefault(); depth++; show(true); });
|
|
63
|
+
window.addEventListener('dragleave', function () { depth = Math.max(0, depth - 1); if (!depth) show(false); });
|
|
64
|
+
window.addEventListener('dragover', function (e) { e.preventDefault(); });
|
|
65
|
+
window.addEventListener('drop', function (e) { e.preventDefault(); depth = 0; show(false); window.dropSharedFile(e); });
|
|
66
|
+
})();
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/*! @license DOMPurify 3.4.13 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.13/LICENSE */
|
|
2
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).DOMPurify=t()}(this,function(){"use strict";function e(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,o=Array(t);n<t;n++)o[n]=e[n];return o}function t(t,n){return function(e){if(Array.isArray(e))return e}(t)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var o,r,i,a,l=[],c=!0,s=!1;try{if(i=(n=n.call(e)).next,0===t);else for(;!(c=(o=i.call(n)).done)&&(l.push(o.value),l.length!==t);c=!0);}catch(e){s=!0,r=e}finally{try{if(!c&&null!=n.return&&(a=n.return(),Object(a)!==a))return}finally{if(s)throw r}}return l}}(t,n)||function(t,n){if(t){if("string"==typeof t)return e(t,n);var o={}.toString.call(t).slice(8,-1);return"Object"===o&&t.constructor&&(o=t.constructor.name),"Map"===o||"Set"===o?Array.from(t):"Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o)?e(t,n):void 0}}(t,n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}const n=Object.entries,o=Object.setPrototypeOf,r=Object.isFrozen,i=Object.getPrototypeOf,a=Object.getOwnPropertyDescriptor;let l=Object.freeze,c=Object.seal,s=Object.create,u="undefined"!=typeof Reflect&&Reflect,f=u.apply,p=u.construct;l||(l=function(e){return e}),c||(c=function(e){return e}),f||(f=function(e,t){for(var n=arguments.length,o=new Array(n>2?n-2:0),r=2;r<n;r++)o[r-2]=arguments[r];return e.apply(t,o)}),p||(p=function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),o=1;o<t;o++)n[o-1]=arguments[o];return new e(...n)});const m=L(Array.prototype.forEach),d=L(Array.prototype.lastIndexOf),h=L(Array.prototype.pop),g=L(Array.prototype.push),y=L(Array.prototype.splice),b=Array.isArray,T=L(String.prototype.toLowerCase),S=L(String.prototype.toString),E=L(String.prototype.match),A=L(String.prototype.replace),N=L(String.prototype.indexOf),_=L(String.prototype.trim),w=L(Number.prototype.toString),O=L(Boolean.prototype.toString),v="undefined"==typeof BigInt?null:L(BigInt.prototype.toString),D="undefined"==typeof Symbol?null:L(Symbol.prototype.toString),R=L(Object.prototype.hasOwnProperty),C=L(Object.prototype.toString),I=L(RegExp.prototype.test),x=(k=TypeError,function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return p(k,t)});var k;function L(e){return function(t){t instanceof RegExp&&(t.lastIndex=0);for(var n=arguments.length,o=new Array(n>1?n-1:0),r=1;r<n;r++)o[r-1]=arguments[r];return f(e,t,o)}}function M(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:T;if(o&&o(e,null),!b(t))return e;let i=t.length;for(;i--;){let o=t[i];if("string"==typeof o){const e=n(o);e!==o&&(r(t)||(t[i]=e),o=e)}e[o]=!0}return e}function z(e){for(let t=0;t<e.length;t++){R(e,t)||(e[t]=null)}return e}function P(e){const o=s(null);for(const i of n(e)){var r=t(i,2);const n=r[0],a=r[1];R(e,n)&&(b(a)?o[n]=z(a):a&&"object"==typeof a&&a.constructor===Object?o[n]=P(a):o[n]=a)}return o}function U(e,t){for(;null!==e;){const n=a(e,t);if(n){if(n.get)return L(n.get);if("function"==typeof n.value)return L(n.value)}e=i(e)}return function(){return null}}const F=l(["a","abbr","acronym","address","area","article","aside","audio","b","bdi","bdo","big","blink","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","content","data","datalist","dd","decorator","del","details","dfn","dialog","dir","div","dl","dt","element","em","fieldset","figcaption","figure","font","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","img","input","ins","kbd","label","legend","li","main","map","mark","marquee","menu","menuitem","meter","nav","nobr","ol","optgroup","option","output","p","picture","pre","progress","q","rp","rt","ruby","s","samp","search","section","select","shadow","slot","small","source","spacer","span","strike","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","tr","track","tt","u","ul","var","video","wbr"]),H=l(["svg","a","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","circle","clippath","defs","desc","ellipse","enterkeyhint","exportparts","filter","font","g","glyph","glyphref","hkern","image","inputmode","line","lineargradient","marker","mask","metadata","mpath","part","path","pattern","polygon","polyline","radialgradient","rect","stop","style","switch","symbol","text","textpath","title","tref","tspan","view","vkern"]),j=l(["feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence"]),B=l(["animate","color-profile","cursor","discard","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignobject","hatch","hatchpath","mesh","meshgradient","meshpatch","meshrow","missing-glyph","script","set","solidcolor","unknown","use"]),G=l(["math","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mspace","msqrt","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover","mprescripts"]),W=l(["maction","maligngroup","malignmark","mlongdiv","mscarries","mscarry","msgroup","mstack","msline","msrow","semantics","annotation","annotation-xml","mprescripts","none"]),Y=l(["#text"]),q=l(["accept","action","align","alt","autocapitalize","autocomplete","autopictureinpicture","autoplay","background","bgcolor","border","capture","cellpadding","cellspacing","checked","cite","class","clear","color","cols","colspan","command","commandfor","controls","controlslist","coords","crossorigin","datetime","decoding","default","dir","disabled","disablepictureinpicture","disableremoteplayback","download","draggable","enctype","enterkeyhint","exportparts","face","for","headers","height","hidden","high","href","hreflang","id","inert","inputmode","integrity","ismap","kind","label","lang","list","loading","loop","low","max","maxlength","media","method","min","minlength","multiple","muted","name","nonce","noshade","novalidate","nowrap","open","optimum","part","pattern","placeholder","playsinline","popover","popovertarget","popovertargetaction","poster","preload","pubdate","radiogroup","readonly","rel","required","rev","reversed","role","rows","rowspan","spellcheck","scope","selected","shape","size","sizes","slot","span","srclang","start","src","srcset","step","style","summary","tabindex","title","translate","type","usemap","valign","value","width","wrap","xmlns"]),X=l(["accent-height","accumulate","additive","alignment-baseline","amplitude","ascent","attributename","attributetype","azimuth","basefrequency","baseline-shift","begin","bias","by","class","clip","clippathunits","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","cx","cy","d","dx","dy","diffuseconstant","direction","display","divisor","dominant-baseline","dur","edgemode","elevation","end","exponent","fill","fill-opacity","fill-rule","filter","filterunits","flood-color","flood-opacity","font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","fx","fy","g1","g2","glyph-name","glyphref","gradientunits","gradienttransform","height","href","id","image-rendering","in","in2","intercept","k","k1","k2","k3","k4","kerning","keypoints","keysplines","keytimes","lang","lengthadjust","letter-spacing","kernelmatrix","kernelunitlength","lighting-color","local","marker-end","marker-mid","marker-start","markerheight","markerunits","markerwidth","maskcontentunits","maskunits","max","mask","mask-type","media","method","mode","min","name","numoctaves","offset","operator","opacity","order","orient","orientation","origin","overflow","paint-order","path","pathlength","patterncontentunits","patterntransform","patternunits","points","preservealpha","preserveaspectratio","primitiveunits","r","rx","ry","radius","refx","refy","repeatcount","repeatdur","restart","result","rotate","scale","seed","shape-rendering","slope","specularconstant","specularexponent","spreadmethod","startoffset","stddeviation","stitchtiles","stop-color","stop-opacity","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke","stroke-width","style","surfacescale","systemlanguage","tabindex","tablevalues","targetx","targety","transform","transform-origin","text-anchor","text-decoration","text-orientation","text-rendering","textlength","type","u1","u2","unicode","values","viewbox","visibility","version","vert-adv-y","vert-origin-x","vert-origin-y","width","word-spacing","wrap","writing-mode","xchannelselector","ychannelselector","x","x1","x2","xmlns","y","y1","y2","z","zoomandpan"]),$=l(["accent","accentunder","align","bevelled","close","columnalign","columnlines","columnspacing","columnspan","denomalign","depth","dir","display","displaystyle","encoding","fence","frame","height","href","id","largeop","length","linethickness","lquote","lspace","mathbackground","mathcolor","mathsize","mathvariant","maxsize","minsize","movablelimits","notation","numalign","open","rowalign","rowlines","rowspacing","rowspan","rspace","rquote","scriptlevel","scriptminsize","scriptsizemultiplier","selection","separator","separators","stretchy","subscriptshift","supscriptshift","symmetric","voffset","width","xmlns"]),K=l(["xlink:href","xml:id","xlink:title","xml:space","xmlns:xlink"]),V=c(/{{[\w\W]*|^[\w\W]*}}/g),Z=c(/<%[\w\W]*|^[\w\W]*%>/g),J=c(/\${[\w\W]*/g),Q=c(/^data-[\-\w.\u00B7-\uFFFF]+$/),ee=c(/^aria-[\-\w]+$/),te=c(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),ne=c(/^(?:\w+script|data):/i),oe=c(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),re=c(/^html$/i),ie=c(/^[a-z][.\w]*(-[.\w]+)+$/i),ae=c(/<[/\w!]/g),le=c(/<[/\w]/g),ce=c(/<\/no(script|embed|frames)/i),se=c(/\/>/i),ue=1,fe=3,pe=7,me=8,de=9,he=11,ge=function(){return"undefined"==typeof window?null:window},ye=function(e,t,n,o){return R(e,t)&&b(e[t])?M(o.base?P(o.base):{},e[t],o.transform):n};var be=function e(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ge();const o=t=>e(t);if(o.version="3.4.13",o.removed=[],!t||!t.document||t.document.nodeType!==de||!t.Element)return o.isSupported=!1,o;let r=t.document;const i=r,a=i.currentScript;t.DocumentFragment;const u=t.HTMLTemplateElement,f=t.Node,p=t.Element,k=t.NodeFilter,L=t.NamedNodeMap;void 0===L&&(t.NamedNodeMap||t.MozNamedAttrMap),t.HTMLFormElement;const z=t.DOMParser,be=t.trustedTypes,Te=p.prototype,Se=U(Te,"cloneNode"),Ee=U(Te,"remove"),Ae=U(Te,"nextSibling"),Ne=U(Te,"childNodes"),_e=U(Te,"parentNode"),we=U(Te,"shadowRoot"),Oe=U(Te,"attributes"),ve=f&&f.prototype?U(f.prototype,"nodeType"):null,De=f&&f.prototype?U(f.prototype,"nodeName"):null,Re=f&&f.prototype?U(f.prototype,"ownerDocument"):null;if("function"==typeof u){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let Ce,Ie,xe="",ke=!1,Le=0;const Me=function(){if(Le>0)throw x('A configured TRUSTED_TYPES_POLICY callback (createHTML or createScriptURL) must not call DOMPurify.sanitize, as that causes infinite recursion. Do not pass a policy whose callbacks wrap DOMPurify as TRUSTED_TYPES_POLICY; see the "DOMPurify and Trusted Types" section of the README.')},ze=function(e){Me(),Le++;try{return Ce.createHTML(e)}finally{Le--}},Pe=function(){return ke||(Ie=function(e,t){if("object"!=typeof e||"function"!=typeof e.createPolicy)return null;let n=null;const o="data-tt-policy-suffix";t&&t.hasAttribute(o)&&(n=t.getAttribute(o));const r="dompurify"+(n?"#"+n:"");try{return e.createPolicy(r,{createHTML:e=>e,createScriptURL:e=>e})}catch(e){return console.warn("TrustedTypes policy "+r+" could not be created."),null}}(be,a),ke=!0),Ie},Ue=r,Fe=Ue.implementation,He=Ue.createNodeIterator,je=Ue.createDocumentFragment,Be=Ue.getElementsByTagName,Ge=i.importNode;let We={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]};o.isSupported="function"==typeof n&&"function"==typeof _e&&Fe&&void 0!==Fe.createHTMLDocument;const Ye=V,qe=Z,Xe=J,$e=Q,Ke=ee,Ve=ne,Ze=oe,Je=ie;let Qe=te,et=null;const tt=M({},[...F,...H,...j,...G,...Y]);let nt=null;const ot=M({},[...q,...X,...$,...K]);let rt=Object.seal(s(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),it=null,at=null;const lt=Object.seal(s(null,{tagCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeCheck:{writable:!0,configurable:!1,enumerable:!0,value:null}}));let ct=!0,st=!0,ut=!1,ft=!0,pt=!1,mt=!0,dt=!1,ht=!1,gt=null,yt=null,bt=!1,Tt=!1,St=!1,Et=!1,At=!0,Nt=!1;const _t="user-content-";let wt=!0,Ot=!1,vt={},Dt=null;const Rt=M({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","selectedcontent","style","svg","template","thead","title","video","xmp"]);let Ct=null;const It=M({},["audio","video","img","source","image","track"]);let xt=null;const kt=M({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Lt="http://www.w3.org/1998/Math/MathML",Mt="http://www.w3.org/2000/svg",zt="http://www.w3.org/1999/xhtml";let Pt=zt,Ut=!1,Ft=null;const Ht=M({},[Lt,Mt,zt],S),jt=l(["mi","mo","mn","ms","mtext"]);let Bt=M({},jt);const Gt=l(["annotation-xml"]);let Wt=M({},Gt);const Yt=M({},["title","style","font","a","script"]);let qt=null;const Xt=["application/xhtml+xml","text/html"];let $t=null,Kt=null;const Vt=r.createElement("form"),Zt=function(e){return e instanceof RegExp||e instanceof Function},Jt=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(Kt&&Kt===e)return;e&&"object"==typeof e||(e={}),e=P(e),qt=-1===Xt.indexOf(e.PARSER_MEDIA_TYPE)?"text/html":e.PARSER_MEDIA_TYPE,$t="application/xhtml+xml"===qt?S:T,et=ye(e,"ALLOWED_TAGS",tt,{transform:$t}),nt=ye(e,"ALLOWED_ATTR",ot,{transform:$t}),Ft=ye(e,"ALLOWED_NAMESPACES",Ht,{transform:S}),xt=ye(e,"ADD_URI_SAFE_ATTR",kt,{transform:$t,base:kt}),Ct=ye(e,"ADD_DATA_URI_TAGS",It,{transform:$t,base:It}),Dt=ye(e,"FORBID_CONTENTS",Rt,{transform:$t}),it=ye(e,"FORBID_TAGS",P({}),{transform:$t}),at=ye(e,"FORBID_ATTR",P({}),{transform:$t}),vt=!!R(e,"USE_PROFILES")&&(e.USE_PROFILES&&"object"==typeof e.USE_PROFILES?P(e.USE_PROFILES):e.USE_PROFILES),ct=!1!==e.ALLOW_ARIA_ATTR,st=!1!==e.ALLOW_DATA_ATTR,ut=e.ALLOW_UNKNOWN_PROTOCOLS||!1,ft=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,pt=e.SAFE_FOR_TEMPLATES||!1,mt=!1!==e.SAFE_FOR_XML,dt=e.WHOLE_DOCUMENT||!1,Tt=e.RETURN_DOM||!1,St=e.RETURN_DOM_FRAGMENT||!1,Et=e.RETURN_TRUSTED_TYPE||!1,bt=e.FORCE_BODY||!1,At=!1!==e.SANITIZE_DOM,Nt=e.SANITIZE_NAMED_PROPS||!1,wt=!1!==e.KEEP_CONTENT,Ot=e.IN_PLACE||!1,Qe=function(e){try{return I(e,""),!0}catch(e){return!1}}(e.ALLOWED_URI_REGEXP)?e.ALLOWED_URI_REGEXP:te,Pt="string"==typeof e.NAMESPACE?e.NAMESPACE:zt,Bt=R(e,"MATHML_TEXT_INTEGRATION_POINTS")&&e.MATHML_TEXT_INTEGRATION_POINTS&&"object"==typeof e.MATHML_TEXT_INTEGRATION_POINTS?P(e.MATHML_TEXT_INTEGRATION_POINTS):M({},jt),Wt=R(e,"HTML_INTEGRATION_POINTS")&&e.HTML_INTEGRATION_POINTS&&"object"==typeof e.HTML_INTEGRATION_POINTS?P(e.HTML_INTEGRATION_POINTS):M({},Gt);const t=R(e,"CUSTOM_ELEMENT_HANDLING")&&e.CUSTOM_ELEMENT_HANDLING&&"object"==typeof e.CUSTOM_ELEMENT_HANDLING?P(e.CUSTOM_ELEMENT_HANDLING):s(null);if(rt=s(null),R(t,"tagNameCheck")&&Zt(t.tagNameCheck)&&(rt.tagNameCheck=t.tagNameCheck),R(t,"attributeNameCheck")&&Zt(t.attributeNameCheck)&&(rt.attributeNameCheck=t.attributeNameCheck),R(t,"allowCustomizedBuiltInElements")&&"boolean"==typeof t.allowCustomizedBuiltInElements&&(rt.allowCustomizedBuiltInElements=t.allowCustomizedBuiltInElements),c(rt),pt&&(st=!1),St&&(Tt=!0),vt&&(et=M({},Y),nt=s(null),!0===vt.html&&(M(et,F),M(nt,q)),!0===vt.svg&&(M(et,H),M(nt,X),M(nt,K)),!0===vt.svgFilters&&(M(et,j),M(nt,X),M(nt,K)),!0===vt.mathMl&&(M(et,G),M(nt,$),M(nt,K))),lt.tagCheck=null,lt.attributeCheck=null,R(e,"ADD_TAGS")&&("function"==typeof e.ADD_TAGS?lt.tagCheck=e.ADD_TAGS:b(e.ADD_TAGS)&&(et===tt&&(et=P(et)),M(et,e.ADD_TAGS,$t))),R(e,"ADD_ATTR")&&("function"==typeof e.ADD_ATTR?lt.attributeCheck=e.ADD_ATTR:b(e.ADD_ATTR)&&(nt===ot&&(nt=P(nt)),M(nt,e.ADD_ATTR,$t))),R(e,"ADD_URI_SAFE_ATTR")&&b(e.ADD_URI_SAFE_ATTR)&&M(xt,e.ADD_URI_SAFE_ATTR,$t),R(e,"FORBID_CONTENTS")&&b(e.FORBID_CONTENTS)&&(Dt===Rt&&(Dt=P(Dt)),M(Dt,e.FORBID_CONTENTS,$t)),R(e,"ADD_FORBID_CONTENTS")&&b(e.ADD_FORBID_CONTENTS)&&(Dt===Rt&&(Dt=P(Dt)),M(Dt,e.ADD_FORBID_CONTENTS,$t)),wt&&(et["#text"]=!0),dt&&M(et,["html","head","body"]),et.table&&(M(et,["tbody"]),delete it.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw x('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw x('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');const t=Ce;Ce=e.TRUSTED_TYPES_POLICY;try{xe=ze("")}catch(e){throw Ce=t,e}}else null===e.TRUSTED_TYPES_POLICY?(Ce=void 0,xe=""):(void 0===Ce&&(Ce=Pe()),Ce&&"string"==typeof xe&&(xe=ze("")));l&&l(e),Kt=e},Qt=M({},[...H,...j,...B]),en=M({},[...G,...W]),tn=function(e){let t=_e(e);t&&t.tagName||(t={namespaceURI:Pt,tagName:"template"});const n=T(e.tagName),o=T(t.tagName);return!!Ft[e.namespaceURI]&&(e.namespaceURI===Mt?function(e,t,n){return t.namespaceURI===zt?"svg"===e:t.namespaceURI===Lt?"svg"===e&&("annotation-xml"===n||Bt[n]):Boolean(Qt[e])}(n,t,o):e.namespaceURI===Lt?function(e,t,n){return t.namespaceURI===zt?"math"===e:t.namespaceURI===Mt?"math"===e&&Wt[n]:Boolean(en[e])}(n,t,o):e.namespaceURI===zt?function(e,t,n){return!(t.namespaceURI===Mt&&!Wt[n])&&!(t.namespaceURI===Lt&&!Bt[n])&&!en[e]&&(Yt[e]||!Qt[e])}(n,t,o):!("application/xhtml+xml"!==qt||!Ft[e.namespaceURI]))},nn=function(e){g(o.removed,{element:e});try{_e(e).removeChild(e)}catch(t){if(Ee(e),!_e(e))throw x("a node selected for removal could not be detached from its tree and cannot be safely returned; refusing to sanitize in place")}},on=function(e){ln(e);const t=Ne(e);if(t){const e=[];m(t,t=>{g(e,t)}),m(e,e=>{try{Ee(e)}catch(e){}})}const n=Oe(e);if(n)for(let t=n.length-1;t>=0;--t){const o=n[t],r=o&&o.name;if("string"==typeof r)try{e.removeAttribute(r)}catch(e){}}},rn=function(e,t){try{g(o.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){g(o.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e)if(Tt||St)try{nn(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},an=function(e){const t=Oe(e);if(t)for(let n=t.length-1;n>=0;--n){const o=t[n],r=o&&o.name;if("string"==typeof r&&!nt[$t(r)])try{e.removeAttribute(r)}catch(e){}}},ln=function(e){const t=[e];for(;t.length>0;){const e=t.pop();(ve?ve(e):e.nodeType)===ue&&an(e);const n=Ne(e);if(n)for(let e=n.length-1;e>=0;--e)t.push(n[e])}},cn=function(e){let t=null,n=null;if(bt)e="<remove></remove>"+e;else{const t=E(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===qt&&Pt===zt&&(e='<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>'+e+"</body></html>");const o=Ce?ze(e):e;if(Pt===zt)try{t=(new z).parseFromString(o,qt)}catch(e){}if(!t||!t.documentElement){t=Fe.createDocument(Pt,"template",null);try{t.documentElement.innerHTML=Ut?xe:o}catch(e){}}const i=t.body||t.documentElement;return e&&n&&i.insertBefore(r.createTextNode(n),i.childNodes[0]||null),Pt===zt?Be.call(t,dt?"html":"body")[0]:dt?t.documentElement:i},sn=function(e){const t=Re?Re(e):e.ownerDocument;return He.call(t||e,e,k.SHOW_ELEMENT|k.SHOW_COMMENT|k.SHOW_TEXT|k.SHOW_PROCESSING_INSTRUCTION|k.SHOW_CDATA_SECTION,null)},un=function(e){return e=A(e,Ye," "),e=A(e,qe," "),e=A(e,Xe," ")},fn=function(e){var t;e.normalize();const n=Re?Re(e):e.ownerDocument,o=He.call(n||e,e,k.SHOW_TEXT|k.SHOW_COMMENT|k.SHOW_CDATA_SECTION|k.SHOW_PROCESSING_INSTRUCTION,null);let r=o.nextNode();for(;r;)r.data=un(r.data),r=o.nextNode();const i=null===(t=e.querySelectorAll)||void 0===t?void 0:t.call(e,"template");i&&m(i,e=>{mn(e.content)&&fn(e.content)})},pn=function(e){const t=De?De(e):null;return"string"==typeof t&&("form"===$t(t)&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||e.attributes!==Oe(e)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes||e.nodeType!==ve(e)||e.childNodes!==Ne(e)))},mn=function(e){if(!ve||"object"!=typeof e||null===e)return!1;try{return ve(e)===he}catch(e){return!1}},dn=function(e){if(!ve||"object"!=typeof e||null===e)return!1;try{return"number"==typeof ve(e)}catch(e){return!1}};function hn(e,t,n){0!==e.length&&m(e,e=>{e.call(o,t,n,Kt)})}const gn=function(e,t,n,o){return 0===e.length?t:t===n||t===o?P(t):t},yn=function(e,t){if(hn(We.beforeSanitizeElements,e,null),e!==t&&null===_e(e))return Ot&&ln(e),!0;if(pn(e))return nn(e),!0;const n=$t(De?De(e):e.nodeName);if(et=gn(We.uponSanitizeElement,et,tt,gt),hn(We.uponSanitizeElement,e,{tagName:n,allowedTags:et}),e!==t&&null===_e(e))return Ot&&ln(e),!0;if(function(e,t){return!!(mt&&e.hasChildNodes()&&!dn(e.firstElementChild)&&I(ae,e.textContent)&&I(ae,e.innerHTML))||!(!mt||e.namespaceURI!==zt||"style"!==t||!dn(e.firstElementChild))||e.nodeType===pe||!(!mt||e.nodeType!==me||!I(le,e.data))}(e,n))return nn(e),!0;if(it[n]||!(lt.tagCheck instanceof Function&<.tagCheck(n))&&!et[n]){const o=function(e,t,n){if(!it[t]&&Sn(t)){if(rt.tagNameCheck instanceof RegExp&&I(rt.tagNameCheck,t))return!1;if(rt.tagNameCheck instanceof Function&&rt.tagNameCheck(t))return!1}if(wt&&!Dt[t]){const t=_e(e),o=Ne(e);if(o&&t)for(let r=o.length-1;r>=0;--r){const i=e===n?Se(o[r],!0):o[r];t.insertBefore(i,Ae(e))}}return nn(e),!0}(e,n,t);return!1===o&&hn(We.afterSanitizeElements,e,null),o}if((ve?ve(e):e.nodeType)===ue&&!tn(e))return nn(e),!0;if(("noscript"===n||"noembed"===n||"noframes"===n)&&I(ce,e.innerHTML))return nn(e),!0;if(pt&&e.nodeType===fe){const t=un(e.textContent);e.textContent!==t&&(g(o.removed,{element:e.cloneNode()}),e.textContent=t)}return hn(We.afterSanitizeElements,e,null),!1},bn=function(e,t,n){if(at[t])return!1;if(mt&&"patchsrc"===t)return!1;if(mt&&"for"===t&&"label"!==e&&"output"!==e)return!1;if(At&&("id"===t||"name"===t)&&(n in r||n in Vt))return!1;const o=nt[t]||lt.attributeCheck instanceof Function&<.attributeCheck(t,e);if(st&&I($e,t));else if(ct&&I(Ke,t));else if(o)if(xt[t]);else if(I(Qe,A(n,Ze,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==N(n,"data:")||!Ct[e]){if(ut&&!I(Ve,A(n,Ze,"")));else if(n)return!1}else;else if(!(Sn(e)&&(rt.tagNameCheck instanceof RegExp&&I(rt.tagNameCheck,e)||rt.tagNameCheck instanceof Function&&rt.tagNameCheck(e))&&(rt.attributeNameCheck instanceof RegExp&&I(rt.attributeNameCheck,t)||rt.attributeNameCheck instanceof Function&&rt.attributeNameCheck(t,e))||"is"===t&&rt.allowCustomizedBuiltInElements&&(rt.tagNameCheck instanceof RegExp&&I(rt.tagNameCheck,n)||rt.tagNameCheck instanceof Function&&rt.tagNameCheck(n))))return!1;return!0},Tn=M({},["annotation-xml","color-profile","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","missing-glyph"]),Sn=function(e){return!Tn[T(e)]&&I(Je,e)},En=function(e,t,n,o){if(Ce&&"object"==typeof be&&"function"==typeof be.getAttributeType&&!n)switch(be.getAttributeType(e,t)){case"TrustedHTML":return ze(o);case"TrustedScriptURL":return function(e){Me(),Le++;try{return Ce.createScriptURL(e)}finally{Le--}}(o)}return o},An=function(e,t,n,r){try{n?e.setAttributeNS(n,t,r):e.setAttribute(t,r),pn(e)?nn(e):h(o.removed)}catch(n){rn(t,e)}},Nn=function(e){hn(We.beforeSanitizeAttributes,e,null);const t=e.attributes;if(!t||pn(e))return;nt=gn(We.uponSanitizeAttribute,nt,ot,yt);const n={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:nt,forceKeepAttr:void 0};let o=t.length;const r=$t(e.nodeName);for(;o--;){const i=t[o],a=i.name,l=i.namespaceURI,c=i.value,s=$t(a),u=c;let f="value"===a?u:_(u);n.attrName=s,n.attrValue=f,n.keepAttr=!0,n.forceKeepAttr=void 0,hn(We.uponSanitizeAttribute,e,n),f=n.attrValue,!Nt||"id"!==s&&"name"!==s||0===N(f,_t)||(rn(a,e),f=_t+f),mt&&I(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i,f)?rn(a,e):"attributename"===s&&E(f,"href")?rn(a,e):n.forceKeepAttr||(n.keepAttr&&(ft||!I(se,f))?(pt&&(f=un(f)),bn(r,s,f)?(f=En(r,s,l,f),f!==u&&An(e,a,l,f)):rn(a,e)):rn(a,e))}hn(We.afterSanitizeAttributes,e,null)},_n=function(e){let t=null;const n=sn(e);for(hn(We.beforeSanitizeShadowDOM,e,null);t=n.nextNode();){hn(We.uponSanitizeShadowNode,t,null),yn(t,e),Nn(t),mn(t.content)&&_n(t.content);if((ve?ve(t):t.nodeType)===ue){const e=we(t);mn(e)&&(wn(e),_n(e))}}hn(We.afterSanitizeShadowDOM,e,null)},wn=function(e){const t=[{node:e,shadow:null}];for(;t.length>0;){const e=t.pop();if(e.shadow){_n(e.shadow);continue}const n=e.node,o=(ve?ve(n):n.nodeType)===ue,r=Ne(n);if(r)for(let e=r.length-1;e>=0;--e)t.push({node:r[e],shadow:null});if(o){const e=De?De(n):null;if("string"==typeof e&&"template"===$t(e)){const e=n.content;mn(e)&&t.push({node:e,shadow:null})}}if(o){const e=we(n);mn(e)&&t.push({node:null,shadow:e},{node:e,shadow:null})}}};return o.sanitize=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=null,r=null,a=null,l=null;if(Ut=!e,Ut&&(e="\x3c!--\x3e"),"string"!=typeof e&&!dn(e)&&"string"!=typeof(e=function(e){switch(typeof e){case"string":return e;case"number":return w(e);case"boolean":return O(e);case"bigint":return v?v(e):"0";case"symbol":return D?D(e):"Symbol()";case"undefined":default:return C(e);case"function":case"object":{if(null===e)return C(e);const t=e,n=U(t,"toString");if("function"==typeof n){const e=n(t);return"string"==typeof e?e:C(e)}return C(e)}}}(e)))throw x("dirty is not a string, aborting");if(!o.isSupported)return e;ht?(et=gt,nt=yt):Jt(t),(We.uponSanitizeElement.length>0||We.uponSanitizeAttribute.length>0)&&(et=P(et)),We.uponSanitizeAttribute.length>0&&(nt=P(nt)),o.removed=[];const c=Ot&&"string"!=typeof e&&dn(e);if(c){!function(e){if(!mt)return;const t=[e];for(;t.length>0;){const e=t.pop(),n=ve?ve(e):e.nodeType;if(n===pe||n===me&&I(le,e.data)){try{Ee(e)}catch(e){}continue}if(n===ue){const t=e,n=$t(De?De(e):e.nodeName);try{t.hasAttribute&&t.hasAttribute("patchsrc")&&t.removeAttribute("patchsrc"),t.hasAttribute&&t.hasAttribute("for")&&"label"!==n&&"output"!==n&&t.removeAttribute("for")}catch(e){}}const o=Ne(e);if(o)for(let e=o.length-1;e>=0;--e)t.push(o[e])}}(e);const t=De?De(e):e.nodeName;if("string"==typeof t){const n=$t(t);if(!et[n]||it[n])throw on(e),x("root node is forbidden and cannot be sanitized in-place")}if(pn(e))throw on(e),x("root node is clobbered and cannot be sanitized in-place");try{wn(e)}catch(t){throw on(e),t}}else if(dn(e))n=cn("\x3c!----\x3e"),r=n.ownerDocument.importNode(e,!0),r.nodeType===ue&&"BODY"===r.nodeName||"HTML"===r.nodeName?n=r:n.appendChild(r),wn(r);else{if(!Tt&&!pt&&!dt&&-1===e.indexOf("<"))return Ce&&Et?ze(e):e;if(n=cn(e),!n)return Tt?null:Et?xe:""}n&&bt&&nn(n.firstChild);const s=c?e:n;try{const e=sn(s);for(;a=e.nextNode();)yn(a,s),Nn(a),mn(a.content)&&_n(a.content)}catch(t){throw c&&(on(e),m(o.removed,e=>{e.element&&ln(e.element)})),t}if(c)return m(o.removed,e=>{e.element&&ln(e.element)}),pt&&fn(e),e;if(Tt){if(pt&&fn(n),St)for(l=je.call(n.ownerDocument);n.firstChild;)l.appendChild(n.firstChild);else l=n;return(nt.shadowroot||nt.shadowrootmode)&&(l=Ge.call(i,l,!0)),l}let u=dt?n.outerHTML:n.innerHTML;return dt&&et["!doctype"]&&n.ownerDocument&&n.ownerDocument.doctype&&n.ownerDocument.doctype.name&&I(re,n.ownerDocument.doctype.name)&&(u="<!DOCTYPE "+n.ownerDocument.doctype.name+">\n"+u),pt&&(u=un(u)),Ce&&Et?ze(u):u},o.setConfig=function(){Jt(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),ht=!0,gt=et,yt=nt},o.clearConfig=function(){Kt=null,ht=!1,gt=null,yt=null,Ce=Ie,xe=""},o.isValidAttribute=function(e,t,n){Kt||Jt({});const o=$t(e),r=$t(t);return bn(o,r,n)},o.addHook=function(e,t){"function"==typeof t&&R(We,e)&&g(We[e],t)},o.removeHook=function(e,t){if(R(We,e)){if(void 0!==t){const n=d(We[e],t);return-1===n?void 0:y(We[e],n,1)[0]}return h(We[e])}},o.removeHooks=function(e){R(We,e)&&(We[e]=[])},o.removeAllHooks=function(){We={afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}},o}();return be});
|
|
3
|
+
//# sourceMappingURL=purify.min.js.map
|