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 CHANGED
@@ -7,7 +7,7 @@
7
7
  </p>
8
8
 
9
9
  [![npm](https://img.shields.io/npm/v/devcoach?logo=npm)](https://www.npmjs.com/package/devcoach)
10
- [![CI](https://github.com/UltimaPhoenix/dev-coach/actions/workflows/ci.yml/badge.svg)](https://github.com/UltimaPhoenix/dev-coach/actions/workflows/ci.yml)
10
+ [![CI](https://github.com/UltimaPhoenix/dev-coach/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/UltimaPhoenix/dev-coach/actions/workflows/ci.yml?query=branch%3Adevelop)
11
11
  [![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=UltimaPhoenix_dev-coach&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=UltimaPhoenix_dev-coach)
12
12
  [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=UltimaPhoenix_dev-coach&metric=coverage)](https://sonarcloud.io/summary/new_code?id=UltimaPhoenix_dev-coach)
13
13
  [![Node](https://img.shields.io/badge/node-%E2%89%A524-brightgreen?logo=node.js)](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
- ### Publishing a release
552
-
553
- Tag a commit with `v*`:
554
-
555
- ```bash
556
- git tag v1.2.3 && git push origin v1.2.3
557
- ```
558
-
559
- CI lints, type-checks, tests (Node 24 & 26), builds, and publishes to npm via **OIDC provenance**
560
- (`npm publish --provenance`). First-time setup: configure a Trusted Publisher on npmjs.com for the
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
- Read `devcoach://onboarding`. If `knowledge_ready` or `notebook_ready` is false — or the
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
- Read the **`devcoach://briefing`** MCP resource — ONE silent read returns everything
59
- below (never read the underlying resources one by one; each extra call is noise):
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
- `devcoach://profile` (or one recurs across tasks), offer to track it with an estimated
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" → read `devcoach://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
- Read `devcoach://profile` for the current knowledge map.
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 `devcoach://profile` | `add_topic` — see Step 3 |
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 `devcoach://profile`:
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
- Read `devcoach://briefing` for the current notebook text and its `notebook_path` — one
35
- resource covers both. Merge findings into the relevant sections and write the complete
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 `devcoach://onboarding` reports `knowledge_ready: false` or
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 `devcoach://onboarding` independently
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
- Read `devcoach://onboarding` FIRST — its `detected_stack`, `detected_projects`,
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. Re-read
61
- `devcoach://onboarding` after restore; if `knowledge_ready` is now true, skip to the
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 `devcoach://onboarding` read) using your own file
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. Read `devcoach://briefing` — one silent read returns the profile, the taught
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. Read `devcoach://onboarding` — `detected_projects` carries the history-wide
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`). Read `devcoach://briefing` for the
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 `devcoach://onboarding`)
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
- - `devcoach://onboarding` unreachable, or `detected_projects` empty → derive
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&&lt.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&&lt.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