diff --git a/.gitignore b/.gitignore index 95b8017..e346ea0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,12 @@ .DS_Store -CODE2PROMPT*.txt +C2P-*.* node_modules playwright-report/* +!playwright-report/FOLDER-DESCRIPTION.md test-results/* +!test-results/FOLDER-DESCRIPTION.md coverage/* +!coverage/FOLDER-DESCRIPTION.md docs/* -references/.venv +!docs/FOLDER-DESCRIPTION.md +codemap/* diff --git a/JSDOC_index.md b/JSDOC_index.md index 1665287..482b613 100644 --- a/JSDOC_index.md +++ b/JSDOC_index.md @@ -31,7 +31,7 @@ Node tooling exists only for tests, docs, validation, and i18n extraction. ```text lab.html ├─ face-api.js (Vladmandic) + MediaPipe Tasks Vision - ├─ scripts/main.js — application controller; exposes window.gstmxx + ├─ lab-js/main.js — application controller; exposes window.gstmxx │ ├─ camera.js — webcam stream lifecycle, 2s recording │ ├─ engine.js — face-api 2D detection / landmarks / descriptors / matching │ ├─ engine-3d.js — MediaPipe ImageEmbedder experimental visual-embedding path @@ -73,7 +73,7 @@ with "does the modified face still match". This split is documented in the ## Module map -### Core scripts (`scripts/`) +### Core scripts (`lab-js/`) - **`main.js`** — application entry point; initialises subsystems, dispatches the `gstmxxReady` lifecycle event, and exposes the public API on `window.gstmxx`. diff --git a/README.md b/README.md index 6446d36..eac4bc7 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ authoring guide — kept there so they live in one place only. ## Internationalization Runtime translations for English, Italian, and Portuguese are shipped through -`scripts/i18n.js` (a single inline message catalog + `data-i18n*` attributes + +`lab-js/i18n.js` (a single inline message catalog + `data-i18n*` attributes + `t()` in JS). There is no `locales/` directory and no build step. Translated pages currently include `index.html`, `lab.html`, and `loader.html`; other static pages are English-baseline until they add `data-i18n*` bindings. See diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..9676385 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,36 @@ +# Security Policy + +## Reporting a vulnerability + +Report privately to **vecna@hermescenter.org**, or open a [GitHub private security advisory](https://github.com/vecna/ghostmaxxing/security/advisories/new). +Please do not open a public issue for an unpatched vulnerability. + +Expect an acknowledgement within 5 working days and an assessment within 15. +We will tell you when a fix ships and credit you unless you ask us not to. + +## Scope + +Ghostmaxxing is a static site with no backend. Everything runs client-side and no face data is transmitted. That shapes what a vulnerability looks like here. + +**In scope** + +- Any path by which biometric data (camera frames, descriptors, embeddings, saved faces, thumbnails) leaves the browser or persists where a user does not expect it. +- XSS or injection in any page, particularly `report.html` — a person reading that page may be at risk, and a compromise there is a safety problem, not only a security one. +- Escape from the Ghostyle plugin sandbox into a scope that could exfiltrate data or persist across sessions. +- Weaknesses in the reporting channel described on `report.html`, including anything that could deanonymise a submitter or leak submission metadata. +- Supply-chain issues in vendored assets under `lab-js/vendor/` or `styles/vendor/`. + +**Out of scope** + +- The recognition pipeline failing to match, or a Ghostyle failing to defeat a match. This is the subject of the project, not a defect. See the disclaimer in the README. +- Anything related to the whistleblowing submission platform, hosted at https://raccontaci.nina.watch, should be reported at https://globaleaks.org +- Reports generated by automated scanners with no demonstrated impact. +- Missing hardening headers with no exploitable consequence on a static site. + +## A note on the Ghostyle threat model + +Ghostyles are arbitrary JavaScript that runs in the user's browser, and the project treats them that way deliberately — review is a maintainer reading the whole file. A malicious Ghostyle is therefore not in itself a vulnerability report. A way for a Ghostyle to reach beyond its documented surface **is**. + +## Machine-readable pointer + +`/.well-known/security.txt` (RFC 9116) points here. diff --git a/about.html b/about.html index 86038ba..1dafec3 100644 --- a/about.html +++ b/about.html @@ -5,7 +5,7 @@ Vision & About — Ghostmaxxing - + @@ -16,30 +16,57 @@ - - + + + + + +
+ + + + Ghostmaxxing + A public lab for testing camouflage + + + +
-
- - - - Ghostmaxxing - - - A public lab for testing face-recognition camouflage - - - - -
Vision & About @@ -55,7 +82,7 @@

Make the machine-readable face contestable.

-
+

Workshop assistant.

@@ -287,8 +314,63 @@

On this page

-
+ + + diff --git a/apple-touch-icon.png b/apple-touch-icon.png deleted file mode 100644 index 0357109..0000000 Binary files a/apple-touch-icon.png and /dev/null differ diff --git a/codemap/.keep b/codemap/.keep new file mode 100644 index 0000000..e69de29 diff --git a/codemap/codemap-template.html b/codemap/codemap-template.html new file mode 100644 index 0000000..e58f21d --- /dev/null +++ b/codemap/codemap-template.html @@ -0,0 +1,558 @@ + + + + + + + Ghostmaxxing — Code Map + + + + +
+

Ghostmaxxing code map

+ 0 modules · 0 events · 0 pages + +
+ + + +
+ +
+ import + event + entry point +
+
+ +

+
+
+
+
+ + + + + diff --git a/coverage/FOLDER-CONTENT.md b/coverage/FOLDER-DESCRIPTION.md similarity index 100% rename from coverage/FOLDER-CONTENT.md rename to coverage/FOLDER-DESCRIPTION.md diff --git a/data/FOLDER-CONTENT.md b/data/FOLDER-DESCRIPTION.md similarity index 100% rename from data/FOLDER-CONTENT.md rename to data/FOLDER-DESCRIPTION.md diff --git a/data/camera-facts.json b/data/camera-facts.json new file mode 100644 index 0000000..df6a937 --- /dev/null +++ b/data/camera-facts.json @@ -0,0 +1,74 @@ +{ + "dome": [ + { + "text": "The tinted bubble hides which way the lens is actually pointed — you cannot tell if you are in frame." + }, + { + "text": "Dome housings are cheap enough that most are never checked for the angle they were mounted at." + }, + { + "text": "A dome reads as \"watching everywhere\" by design — most of that field of view is unused, or unmonitored.", + "href": "/genealogy.html" + } + ], + "cube": [ + { + "text": "Basic box units are commonly left on their factory default password, live feed searchable by anyone online.", + "href": "/report.html" + }, + { + "text": "A box camera's recording almost never comes with a public record of who can access the footage." + }, + { + "text": "Cheap sensors like this one are deployed at volume precisely because nobody has to justify each one." + } + ], + "glasses": [ + { + "text": "Face-recognition glasses let matching happen with no visible lens at all — no moment of being told you were scanned.", + "href": "/genealogy.html" + }, + { + "text": "Wearable cameras move the decision to record from a fixed public notice to one person's judgment." + }, + { + "text": "There is no dome, no housing, no blinking light — the absence of a visible camera is the whole design." + } + ], + "pill": [ + { + "text": "Pill-shaped sensors are cheap enough to deploy in bulk, with no requirement to prove they improve safety first." + }, + { + "text": "Miniaturized units like this are built to be missed — the smaller the housing, the less anyone questions it." + }, + { + "text": "Bulk deployment is the business model: price per unit matters more than whether each one is needed." + } + ], + "street": [ + { + "text": "Pole-mounted units are frequently wired into shared city-wide systems with little public oversight of who can query them.", + "href": "/report.html" + }, + { + "text": "A single street pole can host several sensors at once, each logged to a different, rarely-audited system." + }, + { + "text": "Municipal camera networks routinely outlive the policy that was supposed to govern how they're used.", + "href": "/references/" + } + ], + "bullet": [ + { + "text": "Long-range bullet cameras are marketed on resolution alone — accuracy claims rarely account for real lighting, angle, or distance." + }, + { + "text": "The longer the barrel, the further this unit claims to identify a face — a claim almost never tested at that range." + }, + { + "text": "Higher zoom does not mean higher confidence; matching error still rises with distance and motion.", + "href": "/references/" + } + ] +} \ No newline at end of file diff --git a/docs/FOLDER-CONTENT.md b/docs/FOLDER-DESCRIPTION.md similarity index 100% rename from docs/FOLDER-CONTENT.md rename to docs/FOLDER-DESCRIPTION.md diff --git a/fediverse.html b/fediverse.html new file mode 100644 index 0000000..5ca7ce6 --- /dev/null +++ b/fediverse.html @@ -0,0 +1,366 @@ + + + + + + + In the Fediverse — Ghostmaxxing + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Ghostmaxxing + A public lab for testing + camouflage + + + +
+ +
+
+
+
+ + distribution +

In the Fediverse

+

+ Follow approved experiments, documented ghostyles and project + news from Mastodon or any compatible Fediverse service. +

+ +
+

One lab, several feeds

+

+ Ghostmaxxing does not push everything through one account. Each + feed has a clear source or selection rule, so you can follow + the parts of the project you care about without accepting a + personalised recommendation system. +

+ +

Primary accounts

+
    +
  • + @video@ghostmaxxing.vecna.eu — + approved video experiments contributed through the lab. +
  • +
  • + @ghostyles@ghostmaxxing.vecna.eu + — approved pictures and videos associated with a documented + ghostyle: a specific attempt to alter a face-recognition + reading under stated test conditions. +
  • +
  • + @clipboard@ghostmaxxing.vecna.eu + — approved stills, screenshots and visual fragments from the + lab. +
  • +
  • + @news@ghostmaxxing.vecna.eu — + project news and editorial updates published by the + Ghostmaxxing team. +
  • +
+ +

Transparent filters

+

+ These accounts are automatic views of + @ghostyles. Their rules are encoded in their names + and applied once for everyone; they do not profile individual + followers. +

+
    +
  • + @ghostyles-pictures@ghostmaxxing.vecna.eu + — re-shares every approved ghostyle picture. +
  • +
  • + @ghostyles-video@ghostmaxxing.vecna.eu + — re-shares every approved ghostyle video. +
  • +
  • + @ghostyles-daily@ghostmaxxing.vecna.eu + — publishes one random selection from the preceding 24-hour + window. +
  • +
  • + @ghostyles-weekly@ghostmaxxing.vecna.eu + — publishes one random selection from the preceding seven-day + window. +
  • +
  • + @ghostyles-top-rated@ghostmaxxing.vecna.eu + — publishes the item with the most Fediverse likes in the + preceding 24-hour window. +
  • +
+
+ +
+

How to follow an account

+
    +
  1. Open the search field in Mastodon or another Fediverse app.
  2. +
  3. Paste one complete address from the lists above.
  4. +
  5. + Check that the account is hosted on + ghostmaxxing.vecna.eu, then select Follow. +
  6. +
+

+ The first search may take a few seconds while your server + discovers the account. These are public, automatically accepted + follows: Ghostmaxxing does not manually approve followers. +

+
+ +
+

From an experiment to a public post

+
    +
  1. + You run an experiment in the browser. Running it does not, by + itself, publish a recording or image. +
  2. +
  3. + If you explicitly choose to contribute a video or PNG image, + the lab asks you to accept the current consent notice before + it sends the file. +
  4. +
  5. + The contribution enters a private queue. A human moderator + reviews it before anything becomes public. +
  6. +
  7. + If it is approved, Ghostmaxxing creates one public post. The + same record can then appear on the web, in RSS, as an + ActivityPub object and in followers' Fediverse timelines. +
  8. +
+

+ Approval is editorial, not a technical certification. A + published result documents what happened in a particular test; + it is not a promise that the same look will defeat every model, + camera or deployment. +

+
+ +
+

Your contribution and your control

+

+ A contribution does not require a Ghostmaxxing account and is + not published under your name. Here, “anonymous contribution” + means that the public post has no contributor account or + byline; it does not mean that ordinary network data can never + be processed by the web server or its infrastructure. +

+
    +
  • + Before you upload: work created in the lab is + not placed in the moderation queue merely because you ran an + experiment. Use the client controls to keep, download or + discard it on your device. +
  • +
  • + When you upload: the server receives the + selected media, its submission type and consent version. A + submission may also include its ghostyle identifier, app + version, an optional note and experiment metrics. +
  • +
  • + While it is pending: the original file is + held for moderation. Pending media that has not been reviewed + is automatically removed after 14 days. Rejected media is + removed rather than published. +
  • +
  • + If it is approved: video is transcoded and + container metadata, including embedded device or location + fields, is stripped before publication. PNG images are + published as submitted, so remove sensitive image content or + metadata before contributing one. +
  • +
  • + Your deletion code: after an upload, the lab + returns a unique secret code. Keep it somewhere safe. It is + the credential that lets you remove that contribution while + it is pending or after publication. Anyone who obtains the + code can request that deletion, so do not publish it. +
  • +
+

+ Deleting an approved contribution removes its post and media + from Ghostmaxxing and sends a deletion notice to known + followers. Federation is a form of distribution, however: + another server or person may already have cached, copied or + re-shared the material. No federated publisher can guarantee + that every remote copy will disappear. +

+
+ +
+

Prefer RSS?

+

+ You do not need a social account to subscribe. Use the + combined RSS feed, or replace + all in that address with an account handle such as + video, ghostyles, news or + clipboard to receive only that stream. +

+
+ +
+

Try it, then decide what to share

+

+ Open the lab to test a look locally, or + read the project's vision and limits + before contributing. If you have found a real-world deployment + we should investigate, you can also + report it to us. +

+
+ +
+
+
+
+ + + + + + + + diff --git a/genealogy.html b/genealogy.html new file mode 100644 index 0000000..69ab041 --- /dev/null +++ b/genealogy.html @@ -0,0 +1,381 @@ + + + + + + + The genealogy of the read — Ghostmaxxing + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + + Ghostmaxxing + A public lab for testing camouflage + + + +
+ +
+
+

After 15+ years of prosthetics, 3D printing, makeup, glitter and clothing — join the quest to find the most effective deceiver against modern surveillance.

+ +
+
+

How to read the lenses

+
+ + + + + + + + + Open lens. Still reading. Not defeated. + + + + + + + + + Spent lens. A documented intervention exists. The lens is out, and the pink ring is the mark of the counter-move — the same pink that blows across every era below. +
+
+
+
+ +
+ +
+

Meet the villains.

+ +
+ +
+
+
+ + + + + + + + +

Smart glasses

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + +

Pole-mounted reader

+
+
+
+ + +
+ +
+
+

Dates mark first public demonstration, not deployment. Every era is a documented result under stated conditions — local, conditional and temporary. Read the archive entries.

+
+
+ +
+ + + + + + + diff --git a/ghostyle-transfer.html b/ghostyle-transfer.html index 67c71a8..94ac6f0 100644 --- a/ghostyle-transfer.html +++ b/ghostyle-transfer.html @@ -16,38 +16,65 @@ - - - - + + + + + + + +
+ + + + Ghostmaxxing + A public lab for testing camouflage + + + +
-
- - - - Ghostmaxxing - - - A public lab for testing face-recognition camouflage - - - - -
-
+
Lab · Ghostyle transfer

Lift a Ghostyle off one face, wear it on another.

@@ -170,7 +197,64 @@

Mode

- + + + + + diff --git a/ghostyles/brush.js b/ghostyles/brush.js index 572c6c6..2dffe25 100644 --- a/ghostyles/brush.js +++ b/ghostyles/brush.js @@ -2,7 +2,7 @@ * ==Ghostyle== * @name Face Brush * @slug brush - * @version 0.1.0 + * @version 0.2.0 * @author vecna * @license AGPL-3.0-only * @release_date 2026-07-04 @@ -84,8 +84,14 @@ let latest = null; let boundCanvas = null; /** Saved handlers so `onClear` can detach cleanly. */ let handlers = null; -/** The injected floating control panel element. */ +/** The injected control panel element. */ let panel = null; +/** Timestamp of the last frame that carried real landmarks, 0 if never. */ +let lastFaceAt = 0; +/** Handle for the "is a face still there?" watchdog. */ +let faceWatch = null; +/** The bus listener, kept so it is only ever registered once. */ +let busBound = false; /** Current brush settings (snapshotted per stroke at pointerdown). */ const brush = { color: '#00e5ff', alpha: 0.85, widthPx: 26 }; @@ -275,17 +281,33 @@ function detach() { function buildPanel() { if (panel) return; + + // lab.html reserves #gm-pluginbar-mount for exactly this. Mounting there + // means the panel inherits the lab's own type and surface tokens instead of + // hard-coding a second visual language on top of the app, and it lands + // inside a container the lab already shows and hides for command Ghostyles. + // + // The fixed-position fallback is for hosts that have no plugin bar — + // loader.html, a bare test page, someone's own embed. + const mount = document.getElementById('gm-pluginbar-mount'); + panel = document.createElement('div'); panel.setAttribute('data-gstmxx-plugin', 'brush'); - panel.style.cssText = [ - 'position:fixed', 'left:50%', 'bottom:16px', 'transform:translateX(-50%)', - 'z-index:400', 'display:flex', 'flex-wrap:wrap', 'gap:10px', 'align-items:center', - 'padding:10px 14px', 'border-radius:12px', 'pointer-events:auto', - 'background:rgba(15,17,21,0.86)', 'backdrop-filter:blur(8px)', - 'border:1px solid rgba(255,255,255,0.12)', 'color:#eef2ff', - 'font:13px/1.2 Inter,system-ui,sans-serif', 'box-shadow:0 8px 30px rgba(0,0,0,0.45)', - 'max-width:calc(100vw - 24px)' - ].join(';'); + + const shared = [ + 'display:flex', 'flex-wrap:wrap', 'gap:10px', 'align-items:center', + 'pointer-events:auto', 'color:var(--fg,#eef2ff)', + 'font:13px/1.2 var(--sans,system-ui),sans-serif' + ]; + panel.style.cssText = mount + ? shared.join(';') + : shared.concat([ + 'position:fixed', 'left:50%', 'bottom:16px', 'transform:translateX(-50%)', + 'z-index:400', 'padding:10px 14px', 'border-radius:12px', + 'background:var(--panel,rgba(15,17,21,0.86))', 'backdrop-filter:blur(8px)', + 'border:1px solid var(--line,rgba(255,255,255,0.12))', + 'box-shadow:0 8px 30px rgba(0,0,0,0.45)', 'max-width:calc(100vw - 24px)' + ]).join(';'); const label = (text) => { const s = document.createElement('span'); @@ -320,7 +342,7 @@ function buildPanel() { b.style.cssText = [ 'padding:6px 10px', 'border-radius:8px', 'cursor:pointer', 'background:rgba(159,122,234,0.22)', 'border:1px solid rgba(159,122,234,0.5)', - 'color:#fff', 'font:600 12px Inter,system-ui,sans-serif' + 'color:#fff', 'font:600 12px var(--sans,system-ui),sans-serif' ].join(';'); b.onclick = fn; return b; @@ -330,16 +352,28 @@ function buildPanel() { count.setAttribute('data-role', 'count'); count.style.cssText = 'opacity:0.7;min-width:74px;text-align:right'; + // Shown whenever no face has been seen recently. The controls stay visible + // and usable underneath — the plugin is loaded and its settings are real + // even when there is nothing to paint on yet. + const hint = document.createElement('p'); + hint.setAttribute('data-role', 'hint'); + hint.style.cssText = [ + 'flex-basis:100%', 'margin:2px 0 0', 'font-size:12px', 'line-height:1.45', + 'color:var(--muted,#b9a892)' + ].join(';'); + panel.append( label('Brush'), color, label('size'), size, label('opacity'), opacity, btn('Undo', 'Remove last stroke', () => { strokes.pop(); updatePanel(); }), btn('Clear', 'Remove all strokes', () => { strokes = []; updatePanel(); }), btn('Copy state', 'Copy the painted state as JSON', copyState), btn('Bake Ghostyle', 'Download this state as a standalone .js Ghostyle', bakeGhostyle), - count + count, hint ); - document.body.appendChild(panel); + + (mount || document.body).appendChild(panel); updatePanel(); + updateFaceState(); } function updatePanel() { @@ -348,6 +382,32 @@ function updatePanel() { if (c) c.textContent = `${strokes.length} stroke${strokes.length === 1 ? '' : 's'}`; } +/** + * Tell the reader why nothing is happening. Three states, and the difference + * between them matters: a plugin that says nothing when no face is found is + * indistinguishable from a plugin that is broken. + */ +function updateFaceState() { + if (!panel) return; + const hint = panel.querySelector('[data-role="hint"]'); + if (!hint) return; + + const age = lastFaceAt ? Date.now() - lastFaceAt : Infinity; + + if (age < 1500) { + hint.textContent = ''; + hint.style.display = 'none'; + return; + } + + hint.style.display = ''; + hint.textContent = lastFaceAt + ? 'Lost the face — strokes are kept and will snap back when it returns.' + : 'No face detected yet. The brush anchors to facial landmarks, so it ' + + 'needs one before it can paint. Check the lens is clean and that you ' + + 'are evenly lit and facing the camera.'; +} + function removePanel() { if (panel && panel.parentNode) panel.parentNode.removeChild(panel); panel = null; @@ -468,9 +528,69 @@ export function onDraw(ctx, landmarks){ // ------------------------------ plugin hooks ------------------------------- export function onInit() { + // NOTE ON LIFECYCLE, because this is the trap: + // + // onInit fires ONCE per plugin at page load, when ghostyles.json is read + // and the module is imported. It is a REGISTRATION hook. Every + // Ghostyle gets one, whether or not the reader ever selects it. + // onClear fires on deactivation. + // There is no onActivate hook at all. + // + // So onInit must not build UI: eight plugins building panels at load would + // all mount at once, and onClear would then destroy this one permanently + // since onInit never runs a second time. + // + // The activation signal is the `effectChanged` event on the shared bus, + // which is what lab-ui.js uses to show and hide the plugin bar. Listen to + // the same thing and the panel's lifetime matches the bar's exactly. + bindBus(); return 'Face Brush ready — save a baseline, then hold and paint to watch the distance climb.'; } +/** + * Subscribe to the engine bus so the panel appears on activation and leaves on + * deactivation. `window.gstmxx.events` is the same EventTarget as + * `state.gstmxxEvents`; going through the global keeps this plugin free of + * imports, which is the contract every Ghostyle is written to. + * + * main.js may not have published the global yet when plugins are registered, + * so this retries briefly rather than failing silently. + */ +function bindBus(attempt = 0) { + if (busBound) return; + + const bus = window.gstmxx && window.gstmxx.events; + if (!bus) { + if (attempt < 40) setTimeout(() => bindBus(attempt + 1), 100); + return; + } + + busBound = true; + bus.addEventListener('effectChanged', (event) => { + const active = event.detail && event.detail.activeEffect; + if (active === 'brush') openPanel(); + else if (panel) closePanel(); + }); +} + +/** Activation: build the panel and start watching for the face. */ +function openPanel() { + lastFaceAt = 0; + buildPanel(); + // onDraw only fires while a face is present, so it cannot be what notices a + // face going away. This can. + clearInterval(faceWatch); + faceWatch = setInterval(updateFaceState, 1000); +} + +/** Deactivation: tear the panel down but keep the strokes. */ +function closePanel() { + removePanel(); + clearInterval(faceWatch); + faceWatch = null; + lastFaceAt = 0; +} + /** * Called every render tick on the visible overlay, and also on the offscreen * composite that gets re-detected. We (a) cache the latest live landmarks so @@ -479,7 +599,21 @@ export function onInit() { * (c) redraw every stroke from the current landmarks. */ export function onDraw(ctx, landmarks) { + // The panel used to be built here, AFTER the landmarks guard below, so a + // session that never resolved a face never got any controls at all — the + // plugin looked broken when it was merely waiting. Panel construction now + // happens in onInit(); this hook only reports whether a face is present. if (!landmarks || !landmarks.positions) return; + + if (ctx.canvas.isConnected) { + // Safety net: if the bus never materialised, a live frame still proves + // this plugin is the active one, so build the panel here rather than + // leaving the reader with an empty bar. + if (!panel) openPanel(); + lastFaceAt = Date.now(); + updateFaceState(); + } + const positions = landmarks.positions.map((p) => ({ x: p.x, y: p.y })); const frame = eyeFrame(positions); const connected = ctx.canvas.isConnected; // visible overlay vs offscreen composite @@ -489,7 +623,6 @@ export function onDraw(ctx, landmarks) { if (boundCanvas !== ctx.canvas) { if (boundCanvas) detach(); attach(ctx.canvas); - buildPanel(); } } @@ -500,6 +633,6 @@ export function onDraw(ctx, landmarks) { /** Called when the effect is switched off. Tear down input + panel; keep strokes. */ export function onClear() { detach(); - removePanel(); + closePanel(); latest = null; -} +} \ No newline at end of file diff --git a/images/FOLDER-CONTENT.md b/images/FOLDER-CONTENT.md deleted file mode 100644 index 03a043c..0000000 --- a/images/FOLDER-CONTENT.md +++ /dev/null @@ -1,7 +0,0 @@ -# images - -This folder contains static image assets used by the public pages and report pages. - -The files include the Ghostmaxxing logo and mark, social cards, homepage imagery, favicon artwork, and report-section illustrations. They are project assets used by HTML and CSS rather than source logic. - -Image files are excluded from code2prompt because uploading SVG, PNG, and WebP assets is usually not useful for chatbot code review. The filenames remain visible in the directory tree and this summary explains their role. diff --git a/images/FOLDER-DESCRIPTION.md b/images/FOLDER-DESCRIPTION.md new file mode 100644 index 0000000..a3f8a0c --- /dev/null +++ b/images/FOLDER-DESCRIPTION.md @@ -0,0 +1,7 @@ +# images + +This folder contains static image assets used by the public pages, lab-adjacent demos, logo specimen page, social previews, and report pages. + +Root-level assets include social cards, homepage imagery, the wide homepage camera band used by `styles/pages.css`, and an older camera-band SVG kept as a previous unused asset. The nested folders split reusable brand/logo files, Ghostutter shard art, surveillance icon sets, editorial motifs, report illustrations, and social profile/header media. + +Image binaries are excluded from code2prompt because uploading SVG, PNG, and WebP assets is usually not useful for chatbot code review. The folder descriptions in this tree are included so the chatbot still receives asset intent, usage, and ownership context. diff --git a/images/genealogy-thumbnail.webp b/images/genealogy-thumbnail.webp new file mode 100644 index 0000000..85425cd Binary files /dev/null and b/images/genealogy-thumbnail.webp differ diff --git a/images/ghostmaxxing-favicon.svg b/images/ghostmaxxing-favicon.svg deleted file mode 100644 index dd9dd8b..0000000 --- a/images/ghostmaxxing-favicon.svg +++ /dev/null @@ -1,9 +0,0 @@ - -Ghostmaxxing favicon mark -Cropped eye-only version of the Ghostmaxxing mark for use at 16-32px. - - - - - - diff --git a/images/ghostmaxxing-homepage.webp b/images/ghostmaxxing-homepage.webp deleted file mode 100644 index 487e955..0000000 Binary files a/images/ghostmaxxing-homepage.webp and /dev/null differ diff --git a/images/ghostmaxxing-logo.svg b/images/ghostmaxxing-logo.svg deleted file mode 100644 index 37f4fce..0000000 --- a/images/ghostmaxxing-logo.svg +++ /dev/null @@ -1,16 +0,0 @@ - -Ghostmaxxing -The Ghostmaxxing wordmark, paired with the broken-lens camera mark: a public lab for testing face-recognition camouflage. - - - - - - - - - - -Ghostmaxxing -A PUBLIC LAB FOR TESTING FACE-RECOGNITION CAMOUFLAGE - diff --git a/images/ghostmaxxing-mark.svg b/images/ghostmaxxing-mark.svg deleted file mode 100644 index 4489ff4..0000000 --- a/images/ghostmaxxing-mark.svg +++ /dev/null @@ -1,14 +0,0 @@ - -Ghostmaxxing mark -A stylized surveillance camera from the camera-flowers motif, its lens crossed out like a knocked-out eye in a comic panel, tilted to match the camera's own angle. - - - - - - - - - - - diff --git a/images/homepage-camera-band.svg b/images/homepage-camera-band.svg deleted file mode 100644 index 5d0646a..0000000 --- a/images/homepage-camera-band.svg +++ /dev/null @@ -1,482 +0,0 @@ - -Camera flowers footer band, broken -A wide decorative band of surveillance cameras growing from stems and leaves, each lens crossed out like a knocked-out eye, designed as a bottom-aligned footer motif. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/images/homepage-face-art-clean.png b/images/homepage-face-art-clean.png deleted file mode 100644 index 8860030..0000000 Binary files a/images/homepage-face-art-clean.png and /dev/null differ diff --git a/images/icons/FOLDER-DESCRIPTION.md b/images/icons/FOLDER-DESCRIPTION.md new file mode 100644 index 0000000..8698edc --- /dev/null +++ b/images/icons/FOLDER-DESCRIPTION.md @@ -0,0 +1,7 @@ +# images/icons + +This folder contains SVG surveillance-camera icons used by the genealogy, specimen, homepage, and editorial motif demos. + +The icon set includes bullet, dome, cube, pill/depth-array, smart-glasses, and street-pole camera forms. Many icons have two states: a dazzled/static lens variant and an `-alive` open-lens variant. The surrounding pages and `styles/ghostutter.css` combine these icons with Ghostutter marks for hover, focus, and historical camera-family displays. + +The SVG files are excluded from code2prompt because they are visual assets. This description preserves the purpose and naming convention of the omitted icon set. diff --git a/images/icons/cam-bullet.svg b/images/icons/cam-bullet.svg new file mode 100644 index 0000000..a4b70d1 --- /dev/null +++ b/images/icons/cam-bullet.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/images/icons/cam-cube.svg b/images/icons/cam-cube.svg new file mode 100644 index 0000000..d1a197a --- /dev/null +++ b/images/icons/cam-cube.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/images/icons/cam-dome.svg b/images/icons/cam-dome.svg new file mode 100644 index 0000000..63d9b9f --- /dev/null +++ b/images/icons/cam-dome.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/images/icons/cam-glasses.svg b/images/icons/cam-glasses.svg new file mode 100644 index 0000000..c29fc69 --- /dev/null +++ b/images/icons/cam-glasses.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/images/icons/cam-pill.svg b/images/icons/cam-pill.svg new file mode 100644 index 0000000..1f293b5 --- /dev/null +++ b/images/icons/cam-pill.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/images/icons/cam-street.svg b/images/icons/cam-street.svg new file mode 100644 index 0000000..c315f5a --- /dev/null +++ b/images/icons/cam-street.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/images/logo/FOLDER-DESCRIPTION.md b/images/logo/FOLDER-DESCRIPTION.md new file mode 100644 index 0000000..fd37925 --- /dev/null +++ b/images/logo/FOLDER-DESCRIPTION.md @@ -0,0 +1,9 @@ +# images/logo + +This folder contains the Ghostmaxxing brand mark, wordmark/lockup, favicon, and maskable icon exports used across the site. + +The mark files are grouped by surface and behavior: `mark-ondark.svg` and `mark-onlight.svg` are the main full-color static marks, `mark-animated-*` are self-contained animated SVG variants, `mark-mono-*` are single-color ink/cream variants, and `mark-small-*` are simplified small-size cuts. PNG favicon and maskable icon files support browser and PWA metadata. + +The top-level lockup files provide horizontal and stacked wordmark compositions in on-dark, on-light, mono-cream, and mono-ink variants. `styles/logo.css` documents how to use static image assets versus inline SVG plus CSS animation. + +The image files are excluded from code2prompt because they are visual brand assets. This description is included so prompt output keeps the asset taxonomy and usage rules. diff --git a/images/logo/favicon-16.png b/images/logo/favicon-16.png new file mode 100644 index 0000000..a88dbe6 Binary files /dev/null and b/images/logo/favicon-16.png differ diff --git a/images/logo/favicon-180.png b/images/logo/favicon-180.png new file mode 100644 index 0000000..dba8121 Binary files /dev/null and b/images/logo/favicon-180.png differ diff --git a/images/logo/favicon-32.png b/images/logo/favicon-32.png new file mode 100644 index 0000000..67962a8 Binary files /dev/null and b/images/logo/favicon-32.png differ diff --git a/images/logo/favicon-48.png b/images/logo/favicon-48.png new file mode 100644 index 0000000..9bdd71e Binary files /dev/null and b/images/logo/favicon-48.png differ diff --git a/images/logo/favicon-512.png b/images/logo/favicon-512.png new file mode 100644 index 0000000..a79abac Binary files /dev/null and b/images/logo/favicon-512.png differ diff --git a/images/logo/icon-maskable-512.png b/images/logo/icon-maskable-512.png new file mode 100644 index 0000000..4946abe Binary files /dev/null and b/images/logo/icon-maskable-512.png differ diff --git a/images/logo/mark-animated-ondark.svg b/images/logo/mark-animated-ondark.svg new file mode 100644 index 0000000..d113385 --- /dev/null +++ b/images/logo/mark-animated-ondark.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/logo/mark-animated-onlight.svg b/images/logo/mark-animated-onlight.svg new file mode 100644 index 0000000..cf200ff --- /dev/null +++ b/images/logo/mark-animated-onlight.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + diff --git a/images/logo/mark-color.svg b/images/logo/mark-color.svg new file mode 100644 index 0000000..7d91f63 --- /dev/null +++ b/images/logo/mark-color.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/images/logo/mark-favicon.svg b/images/logo/mark-favicon.svg new file mode 100644 index 0000000..6eef044 --- /dev/null +++ b/images/logo/mark-favicon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/images/logo/mark-mono-cream.svg b/images/logo/mark-mono-cream.svg new file mode 100644 index 0000000..b4407f2 --- /dev/null +++ b/images/logo/mark-mono-cream.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/images/logo/mark-mono-ink.svg b/images/logo/mark-mono-ink.svg new file mode 100644 index 0000000..2ef6766 --- /dev/null +++ b/images/logo/mark-mono-ink.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/images/logo/mark-ondark.svg b/images/logo/mark-ondark.svg new file mode 100644 index 0000000..130c759 --- /dev/null +++ b/images/logo/mark-ondark.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/images/logo/mark-onlight.svg b/images/logo/mark-onlight.svg new file mode 100644 index 0000000..7d91f63 --- /dev/null +++ b/images/logo/mark-onlight.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/images/logo/mark-small-mono-cream.svg b/images/logo/mark-small-mono-cream.svg new file mode 100644 index 0000000..71083cf --- /dev/null +++ b/images/logo/mark-small-mono-cream.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/images/logo/mark-small-mono-ink.svg b/images/logo/mark-small-mono-ink.svg new file mode 100644 index 0000000..f990a02 --- /dev/null +++ b/images/logo/mark-small-mono-ink.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/images/logo/mark-small-ondark.svg b/images/logo/mark-small-ondark.svg new file mode 100644 index 0000000..75073df --- /dev/null +++ b/images/logo/mark-small-ondark.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/images/logo/mark-small-onlight.svg b/images/logo/mark-small-onlight.svg new file mode 100644 index 0000000..ba4c8d0 --- /dev/null +++ b/images/logo/mark-small-onlight.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/images/motifs/FOLDER-DESCRIPTION.md b/images/motifs/FOLDER-DESCRIPTION.md new file mode 100644 index 0000000..fe166e7 --- /dev/null +++ b/images/motifs/FOLDER-DESCRIPTION.md @@ -0,0 +1,7 @@ +# images/motifs + +This folder contains large editorial SVG motifs used by the homepage, specimen page, and genealogy page. + +`camera-band.svg` is the wide surveillance-camera band used as a page/footer motif. `genealogy-tree.svg` is the tall tree illustration for the genealogy layout. `hero-sprout.svg` supports the sprout/field visual language, and `soil-edge.svg` provides the repeating ground edge used at the bottom of genealogy scenes. + +The SVG files are excluded from code2prompt because they are visual assets. This description gives reviewers enough context to understand references from HTML and CSS without uploading the full vector art. diff --git a/images/motifs/plume-head.svg b/images/motifs/plume-head.svg new file mode 100644 index 0000000..e4b7d1f --- /dev/null +++ b/images/motifs/plume-head.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/motifs/pyre.svg b/images/motifs/pyre.svg new file mode 100644 index 0000000..ebe1ce6 --- /dev/null +++ b/images/motifs/pyre.svg @@ -0,0 +1,37 @@ + \ No newline at end of file diff --git a/images/motifs/smoke-base.svg b/images/motifs/smoke-base.svg new file mode 100644 index 0000000..468fc00 --- /dev/null +++ b/images/motifs/smoke-base.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/motifs/smoke-cut.svg b/images/motifs/smoke-cut.svg new file mode 100644 index 0000000..bf6ed9a --- /dev/null +++ b/images/motifs/smoke-cut.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/motifs/smoke-resume.svg b/images/motifs/smoke-resume.svg new file mode 100644 index 0000000..67f3e37 --- /dev/null +++ b/images/motifs/smoke-resume.svg @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/images/motifs/smoke-tile.svg b/images/motifs/smoke-tile.svg new file mode 100644 index 0000000..38e61fd --- /dev/null +++ b/images/motifs/smoke-tile.svg @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/images/motifs/soil-edge.svg b/images/motifs/soil-edge.svg new file mode 100644 index 0000000..f1da460 --- /dev/null +++ b/images/motifs/soil-edge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/motifs/whirlwind-a.svg b/images/motifs/whirlwind-a.svg new file mode 100644 index 0000000..491ebfd --- /dev/null +++ b/images/motifs/whirlwind-a.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/motifs/whirlwind-b.svg b/images/motifs/whirlwind-b.svg new file mode 100644 index 0000000..e84c4a4 --- /dev/null +++ b/images/motifs/whirlwind-b.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/motifs/whirlwind-c.svg b/images/motifs/whirlwind-c.svg new file mode 100644 index 0000000..5579cd7 --- /dev/null +++ b/images/motifs/whirlwind-c.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/motifs/whirlwind-d.svg b/images/motifs/whirlwind-d.svg new file mode 100644 index 0000000..2259a67 --- /dev/null +++ b/images/motifs/whirlwind-d.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/motifs/whirlwind.svg b/images/motifs/whirlwind.svg new file mode 100644 index 0000000..18ccaf3 --- /dev/null +++ b/images/motifs/whirlwind.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/previous(now-unused)-camera-band.svg b/images/previous(now-unused)-camera-band.svg deleted file mode 100644 index b1f1a38..0000000 --- a/images/previous(now-unused)-camera-band.svg +++ /dev/null @@ -1,502 +0,0 @@ - -Camera flowers footer band -A wide decorative band of surveillance cameras growing from stems and leaves, designed as a bottom-aligned footer motif. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/images/report/FOLDER-CONTENT.md b/images/report/FOLDER-CONTENT.md deleted file mode 100644 index 65d1bc8..0000000 --- a/images/report/FOLDER-CONTENT.md +++ /dev/null @@ -1,7 +0,0 @@ -# images/report - -This folder contains SVG illustrations used by `report.html` and related report-page styling. - -The assets depict report concepts such as public sightings, countermeasures, procurement officials, system overview, affected individuals, weak spots, and control panels. - -They are excluded from code2prompt because they are visual assets rather than source logic. diff --git a/images/report/FOLDER-DESCRIPTION.md b/images/report/FOLDER-DESCRIPTION.md new file mode 100644 index 0000000..6b7f122 --- /dev/null +++ b/images/report/FOLDER-DESCRIPTION.md @@ -0,0 +1,7 @@ +# images/report + +This folder contains SVG illustrations used by `report.html` and related report-page styling. + +The assets depict report concepts such as public sightings, countermeasures, procurement officials, system overview, affected individuals, weak spots, control panels, and contracts/market pressure. `report.html` places them in the audience-card icon slots. + +The SVG files are excluded from code2prompt because they are visual assets rather than source logic. This folder description is included so reviewers understand what the omitted report art represents. diff --git a/images/social/FOLDER-DESCRIPTION.md b/images/social/FOLDER-DESCRIPTION.md new file mode 100644 index 0000000..8f07d78 --- /dev/null +++ b/images/social/FOLDER-DESCRIPTION.md @@ -0,0 +1,7 @@ +# images/social + +This folder contains social-profile media that does not fit the root social-card files. + +`header-1500x500.png` is the wide social header/banner image shown in the visual specimen page and intended for social profile surfaces. Root-level `images/social-card.svg` and `images/social-card-square.svg` remain the Open Graph and preview card assets used by page metadata. + +The PNG file is excluded from code2prompt because it is a visual asset. This description keeps the relationship between profile headers and root social-card metadata clear. diff --git a/images/social/header-1500x500.png b/images/social/header-1500x500.png new file mode 100644 index 0000000..8935f70 Binary files /dev/null and b/images/social/header-1500x500.png differ diff --git a/index.html b/index.html index ba4cf2c..0745043 100644 --- a/index.html +++ b/index.html @@ -1,89 +1,477 @@ - - - - - Ghostmaxxing - - - - - - - - - - - - - -
-
-
- - - - Ghostmaxxing - - - A public lab for testing face-recognition camouflage + + + + + + + + Ghostmaxxing + + + + + + + + + + + + + + + + + + + +
+ + + + Ghostmaxxing + A public lab for testing camouflage + + + +
+ + +
+ + + +
+ + + +
+
+ +
- -
-
-

Disrupt
the read.

-

Ghostmaxxing is a real-time web app for testing face-recognition - camouflage. Point your camera, change how your face looks, and watch a local recognition - pipeline react — live. Everything runs in your browser, so your data stays with you.

-

Built for hands-on workshops and - self-experiments: see for yourself when a look stops a match, under your own conditions - — not a promise that it will hold anywhere else.

- -
- Video Loader - -
- +

+
+ Open the lab ↗ +
+
+
-
-
- Portrait split between face-recognition overlay and adversarial camouflage. -
- -
- -
-
-
- -
- - +
+

Disrupt
the + read.

+

Ghostmaxxing + is a real-time web app for testing face-recognition camouflage. Point + your camera, change how your face looks, and watch how (the open source recognition + software) react. Everything runs in your device. Your data + stays with you, until you don't decide to share your successful camouflage.

+

Built + for hands-on workshops and + self-experiments.

+ Open + the lab ↗ +
+ +
+

How + it works

+
+
+ +

1. Detect

+

A local pipeline + reads your face the way a deployed system would — landmarks, + descriptors, a baseline match.

+
+
+ +

2. Camouflage

+

Apply a Ghostyle or + your own intervention — makeup, an overlay, a physical change to the + face.

+
+
+ +

3. Retest

+

Compare the match, in + your browser, under your own conditions. A local result, not a + protection guarantee.

+
+
+
+ +
+
+
+

References + archive

+

A + longer lineage than most people think

+

CV Dazzle, + adversarial makeup, physical-world attacks, face-obfuscation + research — each entry names what was demonstrated and what remains + limited.

+ Explore + references → +
+
+

Workshops

+

Bring + a laptop and curiosity

+

Hands-on + sessions testing local recognition behavior together. No biometric + data is uploaded by the browser lab.

+ See + upcoming workshops → +
+
+
+ + + + + + + + + + + + + + + diff --git a/jsdoc.clean.json b/jsdoc.clean.json index 5a46e3a..4d91718 100644 --- a/jsdoc.clean.json +++ b/jsdoc.clean.json @@ -1,19 +1,19 @@ { "plugins": ["plugins/markdown"], "source": { - "include": ["scripts", "ghostyles"], + "include": ["lab-js", "ghostyles"], "includePattern": ".+\\.js(doc|x)?$", "excludePattern": "(^|\\/|\\\\)_", - "exclude": ["scripts/transfer.js", "scripts/realtime.js"] + "exclude": ["lab-js/vendor/**"] }, "opts": { "template": "node_modules/clean-jsdoc-theme/dist", "tutorials": "./tutorials", - "basePath": "/docs/jsdoc/", + "basePath": "/docs/", "theme_opts": { "footer": "
Ghostmaxxing v0.1.0 | Last updated: July 2026
" }, - "destination": "./docs/jsdoc", + "destination": "./docs", "recurse": true, "readme": "./JSDOC_index.md" }, diff --git a/lab-js/FOLDER-DESCRIPTION.md b/lab-js/FOLDER-DESCRIPTION.md new file mode 100644 index 0000000..e991384 --- /dev/null +++ b/lab-js/FOLDER-DESCRIPTION.md @@ -0,0 +1,15 @@ +# scripts + +This folder contains the browser runtime JavaScript for Ghostmaxxing. The app is a static ES-module site with no production bundling step, so these files are loaded directly by `lab.html`, `loader.html`, `ghostyle-transfer.html`, `realtime.html`. + +The index.hmtl or other informative/support pages scripts AREN'T here, they are in ../pages-js. + +The main lab runtime is coordinated by `main.js`, with `state.js` holding shared mutable state and the `gstmxxEvents` event bus. Camera lifecycle and recording live in `camera.js`; DOM lookup and UI status helpers live in `dom.js`; project constants, local model URLs, thresholds, and upload settings live in `config.js`. + +Face analysis is split across several modules. `engine.js` owns the primary face-api 2D detector, landmarks, descriptors, matching, and composite Ghostyle checks. `engine-3d.js` owns the experimental MediaPipe ImageEmbedder path. `mediapipe-loop.js` streams 478-point face landmarks for UV overlays, while `auto-find-loop.js`, `bbox-overlay.js`, `landmark-analysis.js`, `analyze-panel.js`, and `face-thumbnails.js` provide live readouts, result classification, explanations, and local thumbnails. + +Ghostyle execution is handled by `ghostyles-manager.js` for 2D plugin loading and by `plugins3d-loader.js` plus `ghostyle3d-uv-renderer.js` for UV/3D rendering. `utils.js` supplies geometry, canvas, logging, and public helper functions exposed to plugin authors through `window.gstmxx`. `Ghostmaxxing.d.ts` documents that public API for editor support. + +Standalone page scripts include `home.js` for homepage i18n wiring, `loader.js` for repeatable MP4/video fixture analysis, `realtime.js` for the calibration/tracking demo, `transfer.js` for the Ghostyle transfer lab, `ghostutter.js` for the optional Ghostutter mark runtime, `mobile-ui.js` for legacy mobile drawer/fullscreen controls, `export-makeup.js` for PNG clipboard/share export, and `upload-consent.js` for the local clip consent and receipt flow. + +`lab-js/i18n.js` is intentionally excluded from code2prompt output. It is the runtime localization catalog containing the English baseline plus Italian and Portuguese translations. The project has localization support via `initI18n()`, `applyI18n()`, and `setupLocaleSelect()`, with the selected locale stored in `localStorage` under `ghostmaxxing-locale`; the message catalog itself is omitted from prompt uploads by policy. diff --git a/scripts/Ghostmaxxing.d.ts b/lab-js/Ghostmaxxing.d.ts similarity index 73% rename from scripts/Ghostmaxxing.d.ts rename to lab-js/Ghostmaxxing.d.ts index 407d4cd..276a9c2 100644 --- a/scripts/Ghostmaxxing.d.ts +++ b/lab-js/Ghostmaxxing.d.ts @@ -7,7 +7,7 @@ */ /** - * @source scripts/utils.js + * @source lab-js/utils.js */ export interface GhostmaxxingPoint { x: number; @@ -15,7 +15,7 @@ export interface GhostmaxxingPoint { } /** - * @source scripts/engine.js + * @source lab-js/engine.js */ export interface GhostmaxxingFaceBox { x: number; @@ -25,7 +25,7 @@ export interface GhostmaxxingFaceBox { } /** - * @source scripts/ghostyle3d-uv-renderer.js + * @source lab-js/ghostyle3d-uv-renderer.js */ export interface GhostmaxxingPaintUvParams { landmarks3d?: Array<{ x: number; y: number; z?: number }>; @@ -33,7 +33,7 @@ export interface GhostmaxxingPaintUvParams { } /** - * @source scripts/ghostyles-manager.js + * @source lab-js/ghostyles-manager.js */ export type GhostmaxxingOnDraw = ( ctx: CanvasRenderingContext2D, @@ -42,7 +42,7 @@ export type GhostmaxxingOnDraw = ( ) => void; /** - * @source scripts/ghostyles-manager.js + * @source lab-js/ghostyles-manager.js */ export type GhostmaxxingPaintUV = ( ctx: CanvasRenderingContext2D, @@ -51,7 +51,7 @@ export type GhostmaxxingPaintUV = ( ) => void; /** - * @source scripts/ghostyles-manager.js + * @source lab-js/ghostyles-manager.js */ export interface GhostmaxxingPluginModule { onInit?: () => string | void; @@ -71,7 +71,7 @@ export interface GhostmaxxingPluginModule { } /** - * @source scripts/ghostyles-manager.js + * @source lab-js/ghostyles-manager.js */ export interface GhostmaxxingPluginRecord { id: string; @@ -85,38 +85,38 @@ export interface GhostmaxxingPluginRecord { } /** - * @source scripts/state.js + * @source lab-js/state.js */ export interface GhostmaxxingMatchResult { [key: string]: unknown; } /** - * @source scripts/main.js + * @source lab-js/main.js */ export interface GhostmaxxingApi { - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ log(message: string, sourcePlugin?: string | null): void; - /** @source scripts/main.js */ + /** @source lab-js/main.js */ clearVisibleLogs(): void; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ distance(a: number[], b: number[]): number; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ avgPoint(points: GhostmaxxingPoint[]): GhostmaxxingPoint; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ lerp(a: GhostmaxxingPoint, b: GhostmaxxingPoint, t: number): GhostmaxxingPoint; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ scaleFrom(center: GhostmaxxingPoint, point: GhostmaxxingPoint, scale: number): GhostmaxxingPoint; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ point(x: number, y: number): GhostmaxxingPoint; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ drawClosedPath( ctx: CanvasRenderingContext2D, points: GhostmaxxingPoint[], @@ -125,7 +125,7 @@ export interface GhostmaxxingApi { lineWidth?: number ): void; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ drawOpenPath( ctx: CanvasRenderingContext2D, points: GhostmaxxingPoint[], @@ -134,13 +134,13 @@ export interface GhostmaxxingApi { dashed?: boolean ): void; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ drawLabel(ctx: CanvasRenderingContext2D, text: string, x: number, y: number): void; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ roundRect(ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, r: number): void; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ expandEyePolygon( eye: GhostmaxxingPoint[], eyebrow: GhostmaxxingPoint[], @@ -148,7 +148,7 @@ export interface GhostmaxxingApi { eyebrowLift?: number ): GhostmaxxingPoint[]; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ drawEyeWing( ctx: CanvasRenderingContext2D, eye: GhostmaxxingPoint[], @@ -166,7 +166,7 @@ export interface GhostmaxxingApi { } ): void; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ drawCheekSweep( ctx: CanvasRenderingContext2D, anchor: GhostmaxxingPoint, @@ -178,73 +178,73 @@ export interface GhostmaxxingApi { stroke: string ): void; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ drawContourBand(ctx: CanvasRenderingContext2D, pts: GhostmaxxingPoint[], label: string): void; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ clipLeftHalf(ctx: CanvasRenderingContext2D, landmarks: unknown): boolean; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ clipRightHalf(ctx: CanvasRenderingContext2D, landmarks: unknown): boolean; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ clipLeftHalfUV(ctx: CanvasRenderingContext2D, landmarks3d: unknown): boolean; - /** @source scripts/utils.js */ + /** @source lab-js/utils.js */ clipRightHalfUV(ctx: CanvasRenderingContext2D, landmarks3d: unknown): boolean; - /** @source scripts/main.js */ + /** @source lab-js/main.js */ events: EventTarget; - /** @source scripts/main.js */ + /** @source lab-js/main.js */ getDb(): { [key: string]: unknown }; - /** @source scripts/main.js */ + /** @source lab-js/main.js */ getDb3d(): { [key: string]: unknown }; - /** @source scripts/main.js */ + /** @source lab-js/main.js */ getActiveEffect(): string | null; - /** @source scripts/main.js */ + /** @source lab-js/main.js */ getLastResult(): GhostmaxxingMatchResult | null; - /** @source scripts/main.js */ + /** @source lab-js/main.js */ getMatchThreshold(): number; - /** @source scripts/main.js */ + /** @source lab-js/main.js */ getMatchThreshold3d(): number; - /** @source scripts/plugins3d-loader.js */ + /** @source lab-js/plugins3d-loader.js */ getActiveEffect3d(): string | null; - /** @source scripts/plugins3d-loader.js */ + /** @source lab-js/plugins3d-loader.js */ activateEffect3d(id: string): boolean; - /** @source scripts/plugins3d-loader.js */ + /** @source lab-js/plugins3d-loader.js */ deactivateEffect3d(): boolean; - /** @source scripts/plugins3d-loader.js */ + /** @source lab-js/plugins3d-loader.js */ toggleEffect3d(id: string): boolean; - /** @source scripts/plugins3d-loader.js */ + /** @source lab-js/plugins3d-loader.js */ reloadPlugins3d(): boolean; - /** @source scripts/ghostyles-manager.js */ + /** @source lab-js/ghostyles-manager.js */ reloadPlugins(): Promise; - /** @source scripts/main.js */ + /** @source lab-js/main.js */ lastLandmarks3d: Array<{ x: number; y: number; z?: number }> | null; - /** @source scripts/engine.js */ + /** @source lab-js/engine.js */ compositeAndDetect(liveResult: unknown): Promise; - /** @source scripts/engine-3d.js */ + /** @source lab-js/engine-3d.js */ compositeAndDetect3d(): Promise; - /** @source scripts/config.js */ + /** @source lab-js/config.js */ detectorOptions: unknown; - /** @source scripts/mediapipe-loop.js */ + /** @source lab-js/mediapipe-loop.js */ FaceLandmarker?: unknown; } diff --git a/scripts/analyze-panel.js b/lab-js/analyze-panel.js similarity index 100% rename from scripts/analyze-panel.js rename to lab-js/analyze-panel.js diff --git a/scripts/auto-find-loop.js b/lab-js/auto-find-loop.js similarity index 100% rename from scripts/auto-find-loop.js rename to lab-js/auto-find-loop.js diff --git a/scripts/bbox-overlay.js b/lab-js/bbox-overlay.js similarity index 100% rename from scripts/bbox-overlay.js rename to lab-js/bbox-overlay.js diff --git a/scripts/camera.js b/lab-js/camera.js similarity index 97% rename from scripts/camera.js rename to lab-js/camera.js index 7a8fdde..0d83d7d 100644 --- a/scripts/camera.js +++ b/lab-js/camera.js @@ -42,7 +42,7 @@ import { t } from './i18n.js'; * @returns {Promise} * @throws {Error} If the page is in an insecure context, or the user denies * camera permission. - * @see scripts/main.js – called once at the end of `init()` after every + * @see lab-js/main.js – called once at the end of `init()` after every * model has been loaded. * @see startEffectLoop – kicked off here. */ @@ -93,7 +93,7 @@ export async function startCamera() { * boot, before camera permissions are granted). * * @see startCamera – called once after the stream starts. - * @see scripts/engine.js – `drawGhostyleOverlay()` calls this before + * @see lab-js/engine.js – `drawGhostyleOverlay()` calls this before * drawing, in case the window has been resized since the last frame. */ export function resizeCanvas() { @@ -178,7 +178,7 @@ export function stopEffectLoop() { * * @returns {Promise} * @see RECORDING_CONFIG – controls mode, endpoint, and duration. - * @see scripts/main.js – wires the `recordBtn` click handler to this. + * @see lab-js/main.js – wires the `recordBtn` click handler to this. */ export async function recordOneSecond() { if (state.isRecording || state.isSystemBusy) return; diff --git a/scripts/config.js b/lab-js/config.js similarity index 84% rename from scripts/config.js rename to lab-js/config.js index 58cd294..8cd4217 100644 --- a/scripts/config.js +++ b/lab-js/config.js @@ -16,9 +16,9 @@ const VENDOR_ROOT_URL = new URL('./vendor/', import.meta.url).href; /** * Local URLs for vendored face-api model shards (TinyFaceDetector + landmarks / * recognition / age-gender / expressions). Every network fetch stays inside - * `/scripts/vendor` so pages can run without third-party CDNs. + * `/lab-js/vendor` so pages can run without third-party CDNs. * - * @see scripts/main.js – `loadModels()` reads these and calls `faceapi.nets.*.loadFromUri()`. + * @see lab-js/main.js – `loadModels()` reads these and calls `faceapi.nets.*.loadFromUri()`. */ export const MODEL_URLS = { tiny: VENDOR_ROOT_URL, @@ -56,23 +56,23 @@ export const THUMBNAIL_JPEG_QUALITY = 0.8; /** * Vendored tasks-vision ES module path used for dynamic imports. * - * @see scripts/engine-3d.js – `loadMobileNet()` does `await import(MEDIAPIPE_TASKS_VISION_URL)`. - * @see scripts/mediapipe-loop.js – uses the same package for face landmarks. + * @see lab-js/engine-3d.js – `loadMobileNet()` does `await import(MEDIAPIPE_TASKS_VISION_URL)`. + * @see lab-js/mediapipe-loop.js – uses the same package for face landmarks. */ export const MEDIAPIPE_TASKS_VISION_URL = new URL('./vendor/tasks-vision@0.10.35.js', import.meta.url).href; /** * Local URL of the MediaPipe WASM directory loaded by `FilesetResolver.forVisionTasks()`. * - * @see scripts/engine-3d.js - * @see scripts/mediapipe-loop.js + * @see lab-js/engine-3d.js + * @see lab-js/mediapipe-loop.js */ export const MEDIAPIPE_WASM_URL = new URL('./vendor/wasm', import.meta.url).href; /** * Local URL of the MediaPipe FaceLandmarker `.task` bundle (float16, 478 landmarks). * - * @see scripts/mediapipe-loop.js – passed to `FaceLandmarker.createFromOptions()`. + * @see lab-js/mediapipe-loop.js – passed to `FaceLandmarker.createFromOptions()`. */ export const MEDIAPIPE_FACE_LANDMARKER_URL = new URL('./vendor/face_landmarker.task', import.meta.url).href; @@ -80,7 +80,7 @@ export const MEDIAPIPE_FACE_LANDMARKER_URL = new URL('./vendor/face_landmarker.t * Local URL of the MediaPipe ImageEmbedder model bundle (MobileNetV3 Small, float32). * Produces the embedding vector consumed by the 3D recognition pipeline. * - * @see scripts/engine-3d.js – passed to `ImageEmbedder.createFromOptions()`. + * @see lab-js/engine-3d.js – passed to `ImageEmbedder.createFromOptions()`. */ export const MEDIAPIPE_IMAGE_EMBEDDER_URL = new URL('./vendor/mobilenet_v3_small.tflite', import.meta.url).href; @@ -91,7 +91,7 @@ export const MEDIAPIPE_IMAGE_EMBEDDER_URL = new URL('./vendor/mobilenet_v3_small * minimum confidence for a face to be reported; `inputSize` is the square * input dimension fed to the detector (larger = more accurate, slower). * - * @see scripts/engine.js – `detectFaceInCam`, `runEffectPass`, `compositeAndDetect`. + * @see lab-js/engine.js – `detectFaceInCam`, `runEffectPass`, `compositeAndDetect`. */ export const DETECTOR_OPTIONS = new faceapi.TinyFaceDetectorOptions({ inputSize: 416, @@ -104,7 +104,7 @@ export const DETECTOR_OPTIONS = new faceapi.TinyFaceDetectorOptions({ * the upload contract is documented inline so the backend implementer doesn't * need to read the recording code. * - * @see scripts/camera.js – `recordOneSecond()` reads `mode`, `uploadEndpoint`, `durationMs`. + * @see lab-js/camera.js – `recordOneSecond()` reads `mode`, `uploadEndpoint`, `durationMs`. */ export const RECORDING_CONFIG = { // Mode of operation: 'queue' keeps the recorded Blob in the browser so the diff --git a/scripts/db.js b/lab-js/db.js similarity index 94% rename from scripts/db.js rename to lab-js/db.js index d86d763..9357f41 100644 --- a/scripts/db.js +++ b/lab-js/db.js @@ -57,7 +57,7 @@ function createEmptyDb3d() { * @returns {{faces: Array, modelVersion: string}} * The current 3D DB state. There is no `nextId` field — 3D IDs come from * the 2D DB to keep the two stores aligned. - * @see scripts/main.js – called once during init to populate `state.db3d`. + * @see lab-js/main.js – called once during init to populate `state.db3d`. * @see clearDb3d – called from inside this function when the model version * does not match the stored data. */ @@ -85,7 +85,7 @@ export function loadDb3d() { * Serialise `state.db3d` to `localStorage` under `STORAGE_KEY_3D`. Called * after every successful 3D save so the next reload sees the new embedding. * - * @see scripts/engine-3d.js – `saveFace3d()` calls this after pushing a record. + * @see lab-js/engine-3d.js – `saveFace3d()` calls this after pushing a record. */ export function persistDb3d() { localStorage.setItem(STORAGE_KEY_3D, JSON.stringify(state.db3d)); @@ -113,8 +113,8 @@ export function clearDb3d() { * its own counter. * * @returns {{nextId: number, faces: Array}} The current DB state. - * @see scripts/main.js – called once during init to populate `state.db`. - * @see scripts/engine.js – `saveFace()` increments and persists `nextId`. + * @see lab-js/main.js – called once during init to populate `state.db`. + * @see lab-js/engine.js – `saveFace()` increments and persists `nextId`. */ export function loadDb() { try { @@ -136,7 +136,7 @@ export function loadDb() { * happens here so every code path that mutates the DB has consistent UI * feedback without having to remember to fire the event itself. * - * @see scripts/engine.js – `saveFace()` calls this after pushing a record. + * @see lab-js/engine.js – `saveFace()` calls this after pushing a record. * @see clearDb – calls this to persist the empty state and notify listeners. * @see tests/unit/db.test.js – verifies persistence and event emission. */ @@ -155,7 +155,7 @@ export function persistDb() { * the match threshold label, and the badge in the header. Called whenever * the DB shape changes or the app starts up. * - * @see scripts/main.js – `init()` calls this once after loading the DBs. + * @see lab-js/main.js – `init()` calls this once after loading the DBs. * @see clearDb – calls this after wiping the data so the UI shows zero. */ export function renderDbStats() { diff --git a/scripts/dom.js b/lab-js/dom.js similarity index 94% rename from scripts/dom.js rename to lab-js/dom.js index be07843..d6faba7 100644 --- a/scripts/dom.js +++ b/lab-js/dom.js @@ -71,8 +71,8 @@ export const els = { * (defaults to neutral styling). Only 'live' and 'error' apply a CSS class. * @param {string} text Human-readable status text shown to the right of the * dot. - * @see scripts/camera.js – sets `('live', …)` once the webcam stream starts. - * @see scripts/main.js – sets `('init', …)` while models load, `('error', …)` + * @see lab-js/camera.js – sets `('live', …)` once the webcam stream starts. + * @see lab-js/main.js – sets `('init', …)` while models load, `('error', …)` * on failure. */ export function setStatus(kind, text) { @@ -88,9 +88,9 @@ export function setStatus(kind, text) { * timer doesn't fade out a freshly drawn frame. Called between detection * passes and on effect changes. * - * @see scripts/engine.js – `detectFaceInCam()` clears the overlay before + * @see lab-js/engine.js – `detectFaceInCam()` clears the overlay before * drawing the new detection result. - * @see scripts/ghostyles-manager.js – `toggleEffect()` uses this indirectly + * @see lab-js/ghostyles-manager.js – `toggleEffect()` uses this indirectly * via `clearActiveEffect()` when switching off an effect. */ export function clearOverlay() { @@ -108,7 +108,7 @@ export function clearOverlay() { * and last composited canvas, disable the copy-makeup button, and clear the * overlay canvas. Side-effect only — no event is dispatched. * - * @see scripts/ghostyles-manager.js – `toggleEffect()` calls this when the + * @see lab-js/ghostyles-manager.js – `toggleEffect()` calls this when the * user deactivates the currently active effect. */ export function clearActiveEffect() { @@ -140,7 +140,7 @@ export function clearActiveEffect() { * callers must set it before invoking this. * * @param {HTMLButtonElement} button The button that was just clicked. - * @see scripts/ghostyles-manager.js – `toggleEffect()` calls this after + * @see lab-js/ghostyles-manager.js – `toggleEffect()` calls this after * setting `state.activeEffect`. */ export function effectSelected(button) { diff --git a/scripts/engine-3d.js b/lab-js/engine-3d.js similarity index 100% rename from scripts/engine-3d.js rename to lab-js/engine-3d.js diff --git a/scripts/engine.js b/lab-js/engine.js similarity index 100% rename from scripts/engine.js rename to lab-js/engine.js diff --git a/scripts/export-makeup.js b/lab-js/export-makeup.js similarity index 100% rename from scripts/export-makeup.js rename to lab-js/export-makeup.js diff --git a/scripts/face-thumbnails.js b/lab-js/face-thumbnails.js similarity index 100% rename from scripts/face-thumbnails.js rename to lab-js/face-thumbnails.js diff --git a/scripts/ghostyle3d-uv-renderer.js b/lab-js/ghostyle3d-uv-renderer.js similarity index 100% rename from scripts/ghostyle3d-uv-renderer.js rename to lab-js/ghostyle3d-uv-renderer.js diff --git a/scripts/ghostyles-manager.js b/lab-js/ghostyles-manager.js similarity index 99% rename from scripts/ghostyles-manager.js rename to lab-js/ghostyles-manager.js index 7d69a23..139da1b 100644 --- a/scripts/ghostyles-manager.js +++ b/lab-js/ghostyles-manager.js @@ -14,7 +14,7 @@ import { t } from './i18n.js'; * The first time is to extract the metadata, the second time is to import the module. * @param {string} url - The URL of the ghostyle script to fetch. * @throws {Error} Throws an error if the HTTP request fails or the response is not OK. - * @see scripts/main.js – loads ghostyle list and calls this function for each URL. + * @see lab-js/main.js – loads ghostyle list and calls this function for each URL. * @see tests/unit/ghostyles-manager.test.js – unit tests for metadata extraction. * @returns {{ * id: string, diff --git a/scripts/i18n.js b/lab-js/i18n.js similarity index 88% rename from scripts/i18n.js rename to lab-js/i18n.js index e491ea5..f99c4b6 100644 --- a/scripts/i18n.js +++ b/lab-js/i18n.js @@ -25,7 +25,7 @@ export const LOCALE_STORAGE_KEY = 'ghostmaxxing-locale'; export const messages = { transfer_page_title: { - context: 'ghostyle-transfer.html:7; scripts/transfer.js:143', + context: 'ghostyle-transfer.html:7; lab-js/transfer.js:143', it: 'Trasferimento Ghostyle — Ghostmaxxing', en: 'Ghostyle Transfer — Ghostmaxxing', pt: 'Transferencia de Ghostyle — Ghostmaxxing', @@ -59,28 +59,28 @@ export const messages = { notes: 'Glossary: mesh, landmarks.', }, transfer_engine_loading: { - context: 'ghostyle-transfer.html:60; scripts/transfer.js:26', + context: 'ghostyle-transfer.html:60; lab-js/transfer.js:26', it: 'Motore mesh: caricamento…', en: 'Mesh engine: loading…', pt: 'Motor de malha: carregando…', notes: 'Glossary: mesh.', }, transfer_engine_unavailable: { - context: 'scripts/transfer.js:160', + context: 'lab-js/transfer.js:160', it: 'Motore mesh: non disponibile, solo modalità riquadro', en: 'Mesh engine: unavailable, box mode only', pt: 'Motor de malha: indisponivel, somente modo caixa', notes: 'Glossary: mesh.', }, transfer_engine_ready: { - context: 'scripts/transfer.js:169', + context: 'lab-js/transfer.js:169', it: 'Motore mesh: pronto (face-api 68pt)', en: 'Mesh engine: ready (face-api 68pt)', pt: 'Motor de malha: pronto (face-api 68pt)', notes: 'Glossary: mesh, face-api.', }, transfer_engine_failed: { - context: 'scripts/transfer.js:171', + context: 'lab-js/transfer.js:171', it: 'Motore mesh: modelli non caricati, solo modalità riquadro', en: 'Mesh engine: models failed, box mode only', pt: 'Motor de malha: modelos falharam, somente modo caixa', @@ -222,57 +222,57 @@ export const messages = { pt: 'Redefinir', }, transfer_msg_load_after_target: { - context: 'ghostyle-transfer.html:150; scripts/transfer.js:27; scripts/transfer.js:337', + context: 'ghostyle-transfer.html:150; lab-js/transfer.js:27; lab-js/transfer.js:337', it: 'Carica un dopo e un target, poi disegna un riquadro su ogni volto.', en: 'Load an after and a target, then draw a box on each face.', pt: 'Carregue um depois e um alvo, depois desenhe uma caixa em cada rosto.', }, transfer_msg_ready: { - context: 'scripts/transfer.js:337', + context: 'lab-js/transfer.js:337', it: 'Pronto. Premi Trasferisci Ghostyle.', en: 'Ready. Press Transfer Ghostyle.', pt: 'Pronto. Pressione Transferir Ghostyle.', notes: 'Glossary: Ghostyle.', }, transfer_msg_extracting: { - context: 'scripts/transfer.js:670', + context: 'lab-js/transfer.js:670', it: 'Estrazione del trucco…', en: 'Extracting paint…', pt: 'Extraindo pintura…', }, transfer_msg_detecting: { - context: 'scripts/transfer.js:699', + context: 'lab-js/transfer.js:699', it: 'Rilevamento landmark…', en: 'Detecting landmarks…', pt: 'Detectando landmarks…', notes: 'Glossary: landmarks.', }, transfer_msg_done: { - context: 'scripts/transfer.js:753', + context: 'lab-js/transfer.js:753', it: 'Fatto.', en: 'Done.', pt: 'Concluido.', }, transfer_msg_error: { - context: 'scripts/transfer.js:807', + context: 'lab-js/transfer.js:807', it: 'Errore: {message}', en: 'Error: {message}', pt: 'Erro: {message}', }, transfer_note_box_set: { - context: 'scripts/transfer.js:316', + context: 'lab-js/transfer.js:316', it: 'riquadro volto impostato', en: 'face box set', pt: 'caixa do rosto definida', }, transfer_note_draw_box: { - context: 'scripts/transfer.js:318', + context: 'lab-js/transfer.js:318', it: 'disegna un riquadro sul volto', en: 'draw a box over the face', pt: 'desenhe uma caixa sobre o rosto', }, transfer_result_empty: { - context: 'ghostyle-transfer.html:155; scripts/transfer.js:126', + context: 'ghostyle-transfer.html:155; lab-js/transfer.js:126', it: 'Il risultato trasferito apparirà qui.', en: 'The transferred result will appear here.', pt: 'O resultado transferido aparecera aqui.', @@ -297,38 +297,38 @@ export const messages = { pt: 'Modo', }, transfer_mode_not_run: { - context: 'ghostyle-transfer.html:166; scripts/transfer.js:28', + context: 'ghostyle-transfer.html:166; lab-js/transfer.js:28', it: 'Non ancora eseguito.', en: 'Not run yet.', pt: 'Ainda nao executado.', }, transfer_mode_placed: { - context: 'scripts/transfer.js:103', + context: 'lab-js/transfer.js:103', it: 'Posizionato con: {mode}', en: 'Placed using: {mode}', pt: 'Posicionado usando: {mode}', }, transfer_mode_box: { - context: 'scripts/transfer.js:697', + context: 'lab-js/transfer.js:697', it: 'riquadro', en: 'box', pt: 'caixa', }, transfer_mode_mesh: { - context: 'scripts/transfer.js:736', + context: 'lab-js/transfer.js:736', it: 'mesh ({count} triangoli)', en: 'mesh ({count} triangles)', pt: 'malha ({count} triangulos)', notes: 'Glossary: mesh.', }, transfer_mode_box_no_face: { - context: 'scripts/transfer.js:748', + context: 'lab-js/transfer.js:748', it: 'riquadro (nessun volto rilevato)', en: 'box (no face detected)', pt: 'caixa (nenhum rosto detectado)', }, transfer_mode_box_unavailable: { - context: 'scripts/transfer.js:750', + context: 'lab-js/transfer.js:750', it: 'riquadro (motore mesh non disponibile)', en: 'box (mesh engine unavailable)', pt: 'caixa (motor de malha indisponivel)', @@ -392,7 +392,7 @@ export const messages = { notes: 'Glossary: 3D mesh.', }, save_your_face_status: { - context: 'lab.html:63; scripts/lab-ui.js:295', + context: 'lab.html:63; lab-js/lab-ui.js:295', it: 'Salva il tuo volto', en: 'Save your face', pt: 'Salve seu rosto', @@ -544,13 +544,13 @@ export const messages = { pt: 'Trocar câmera', }, enter_fullscreen_button: { - context: 'lab.html:121; scripts/lab-ui.js:118', + context: 'lab.html:121; lab-js/lab-ui.js:118', it: 'Entra in schermo intero', en: 'Enter fullscreen', pt: 'Entrar em tela cheia', }, exit_fullscreen_button: { - context: 'scripts/lab-ui.js:116', + context: 'lab-js/lab-ui.js:116', it: 'Esci dallo schermo intero', en: 'Exit fullscreen', pt: 'Sair da tela cheia', @@ -756,13 +756,13 @@ export const messages = { pt: 'Compartilhar um clipe', }, no_clips_recorded: { - context: 'lab.html:174; scripts/lab-ui.js:142', + context: 'lab.html:174; lab-js/lab-ui.js:142', it: 'Nessuna clip registrata.', en: 'No clips recorded yet.', pt: 'Nenhum clipe gravado ainda.', }, clips_ready_to_send: { - context: 'scripts/lab-ui.js:142', + context: 'lab-js/lab-ui.js:142', it: '{count} clip pronte da inviare.', en: '{count} clip(s) ready to send.', pt: '{count} clipe(s) prontos para enviar.', @@ -810,43 +810,43 @@ export const messages = { pt: 'Descartar clipe', }, upload_meta_recorded_label: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Registrata', en: 'Recorded', pt: 'Gravado', }, upload_meta_size_label: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Dimensione', en: 'Size', pt: 'Tamanho', }, upload_meta_ghostyle_label: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Ghostyle', en: 'Ghostyle', pt: 'Ghostyle', }, upload_meta_result_label: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Risultato', en: 'Result', pt: 'Resultado', }, upload_clip_ready_status: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Clip pronta nel browser. Nessun upload finche non dai consenso.', en: 'Clip ready in the browser. Nothing uploads until you consent.', pt: 'Clipe pronto no navegador. Nada é enviado até você consentir.', }, upload_clip_discarded_status: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Clip scartata.', en: 'Clip discarded.', pt: 'Clipe descartado.', }, upload_receipt_created_status: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Upload ricevuto. La ricevuta privata è nel log.', en: 'Upload received. The private receipt is in the log.', pt: 'Envio recebido. O recibo privado está no registro.', @@ -864,91 +864,91 @@ export const messages = { pt: 'Recibos privados deste navegador. Guarde-os para acessar o futuro URL público e revogar o envio com o token de exclusão.', }, receipt_log_empty: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Nessuna ricevuta salvata in questo browser.', en: 'No receipts saved in this browser.', pt: 'Nenhum recibo salvo neste navegador.', }, receipt_status_pending: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'in moderazione', en: 'pending', pt: 'pendente', }, receipt_status_deleted: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'revocata', en: 'revoked', pt: 'revogado', }, receipt_status_delete_failed: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'revoca fallita', en: 'revoke failed', pt: 'revogação falhou', }, receipt_status_imported: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'importata', en: 'imported', pt: 'importado', }, receipt_upload_id_label: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Upload ID', en: 'Upload ID', pt: 'ID do envio', }, receipt_consent_label: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Consenso', en: 'Consent', pt: 'Consentimento', }, receipt_open_public_button: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Apri URL pubblico', en: 'Open public URL', pt: 'Abrir URL público', }, receipt_copy_private_button: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Copia ricevuta privata', en: 'Copy private receipt', pt: 'Copiar recibo privado', }, receipt_revoke_button: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Revoca', en: 'Revoke', pt: 'Revogar', }, receipt_copied_status: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Ricevuta privata copiata.', en: 'Private receipt copied.', pt: 'Recibo privado copiado.', }, receipt_copy_failed_status: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Impossibile copiare la ricevuta privata.', en: 'Could not copy the private receipt.', pt: 'Não foi possível copiar o recibo privado.', }, receipt_revoke_working_status: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Revoca in corso...', en: 'Revoking...', pt: 'Revogando...', }, receipt_revoke_done_status: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Upload revocato.', en: 'Upload revoked.', pt: 'Envio revogado.', }, receipt_revoke_failed_status: { - context: 'scripts/upload-consent.js', + context: 'lab-js/upload-consent.js', it: 'Revoca non riuscita: {message}', en: 'Revoke failed: {message}', pt: 'Revogação falhou: {message}', @@ -1053,13 +1053,13 @@ export const messages = { pt: 'Copiar relatório', }, not_available_label: { - context: 'scripts/dom.js:123', + context: 'lab-js/dom.js:123', it: 'N/D', en: 'N/A', pt: 'N/D', }, off_status: { - context: 'scripts/dom.js:124', + context: 'lab-js/dom.js:124', it: 'off', en: 'off', pt: 'off', @@ -1071,1108 +1071,1108 @@ export const messages = { pt: 'nenhum', }, active_style_missing_console: { - context: 'scripts/dom.js:172', + context: 'lab-js/dom.js:172', it: 'Nessuno stile trovato per l\'effetto attivo {effect}', en: 'No style found for active effect {effect}', pt: 'Nenhum estilo encontrado para o efeito ativo {effect}', }, mirror_webcam_on_status: { - context: 'scripts/main.js:42; scripts/camera.js:71', + context: 'lab-js/main.js:42; lab-js/camera.js:71', it: 'Webcam speculare: ON', en: 'Mirror webcam: ON', pt: 'Webcam espelhada: ON', }, mirror_webcam_button: { - context: 'scripts/main.js:42; scripts/camera.js:71', + context: 'lab-js/main.js:42; lab-js/camera.js:71', it: 'Webcam speculare', en: 'Mirror webcam', pt: 'Espelhar webcam', }, switching_camera_log: { - context: 'scripts/main.js:50', + context: 'lab-js/main.js:50', it: 'Cambio fotocamera... ({mode})', en: 'Switching camera... ({mode})', pt: 'Trocando câmera... ({mode})', }, camera_switch_error: { - context: 'scripts/main.js:57', + context: 'lab-js/main.js:57', it: 'Errore nel cambio fotocamera.', en: 'Error while switching camera.', pt: 'Erro ao trocar a câmera.', }, loading_models_status: { - context: 'scripts/main.js:142', + context: 'lab-js/main.js:142', it: 'caricamento modelli', en: 'loading models', pt: 'carregando modelos', }, error_status: { - context: 'scripts/main.js:164', + context: 'lab-js/main.js:164', it: 'errore', en: 'error', pt: 'erro', }, loading_error_log: { - context: 'scripts/main.js:560', + context: 'lab-js/main.js:560', it: 'Errore durante il caricamento: {message}', en: 'Error while loading: {message}', pt: 'Erro ao carregar: {message}', }, save_face_error: { - context: 'scripts/main.js:522', + context: 'lab-js/main.js:522', it: 'Errore durante il salvataggio del volto.', en: 'Error while saving the face.', pt: 'Erro ao salvar o rosto.', }, makeup_analysis_error: { - context: 'scripts/main.js:534', + context: 'lab-js/main.js:534', it: 'Errore durante l\'analisi del trucco.', en: 'Error while analyzing the makeup.', pt: 'Erro ao analisar a maquiagem.', }, error_console_prefix: { - context: 'scripts/main.js:162', + context: 'lab-js/main.js:162', it: 'Errore:', en: 'Error:', pt: 'Erro:', }, face_thumbnail_alt: { - context: 'scripts/main.js:296', + context: 'lab-js/main.js:296', it: 'Miniatura volto ID {id}', en: 'Face thumbnail ID {id}', pt: 'Miniatura do rosto ID {id}', }, no_preview: { - context: 'scripts/main.js:302; scripts/analyze-panel.js:138', + context: 'lab-js/main.js:302; lab-js/analyze-panel.js:138', it: 'nessuna anteprima', en: 'no preview', pt: 'sem prévia', }, delete_id_label: { - context: 'scripts/main.js:334; scripts/main.js:346; scripts/main.js:350', + context: 'lab-js/main.js:334; lab-js/main.js:346; lab-js/main.js:350', it: 'Cancella ID {id}', en: 'Delete ID {id}', pt: 'Excluir ID {id}', }, confirm_delete_id_label: { - context: 'scripts/main.js:355; scripts/main.js:356', + context: 'lab-js/main.js:355; lab-js/main.js:356', it: 'Conferma cancellazione ID {id}', en: 'Confirm deletion of ID {id}', pt: 'Confirmar exclusão do ID {id}', }, no_saved_faces_empty: { - context: 'scripts/main.js:381', + context: 'lab-js/main.js:381', it: 'Nessun volto salvato.', en: 'No saved faces.', pt: 'Nenhum rosto salvo.', }, confirm_question: { - context: 'scripts/main.js:542; scripts/main.js:546; scripts/main.js:548', + context: 'lab-js/main.js:542; lab-js/main.js:546; lab-js/main.js:548', it: 'Conferma?', en: 'Confirm?', pt: 'Confirmar?', }, loading_face_system_log: { - context: 'scripts/main.js:556', + context: 'lab-js/main.js:556', it: 'Caricamento sistema di riconoscimento facciale (face-api.js)...', en: 'Loading face-recognition system (face-api.js)...', pt: 'Carregando sistema de reconhecimento facial (face-api.js)...', notes: 'Glossary: face-api.js, face recognition.', }, loading_embedder_log: { - context: 'scripts/main.js:564', + context: 'lab-js/main.js:564', it: 'Caricamento ImageEmbedder per il motore di riconoscimento 3D...', en: 'Loading ImageEmbedder for the 3D recognition engine...', pt: 'Carregando ImageEmbedder para o motor de reconhecimento 3D...', notes: 'Glossary: ImageEmbedder, 3D recognition engine.', }, plugin_reload_started_log: { - context: 'scripts/main.js:429', + context: 'lab-js/main.js:429', it: 'Ricarica plugin in corso...', en: 'Reloading plugins...', pt: 'Recarregando plugins...', }, plugin_reload_done_log: { - context: 'scripts/main.js:434', + context: 'lab-js/main.js:434', it: 'Reload completato: {count} plugin caricati.', en: 'Reload complete: {count} plugins loaded.', pt: 'Recarga concluída: {count} plugins carregados.', }, plugin_reload_error_log: { - context: 'scripts/main.js:436', + context: 'lab-js/main.js:436', it: 'Errore durante reload plugins: {message}', en: 'Error while reloading plugins: {message}', pt: 'Erro ao recarregar plugins: {message}', }, thumbnail_capture_failed_log: { - context: 'scripts/main.js:485', + context: 'lab-js/main.js:485', it: 'Acquisizione miniatura fallita: {message}', en: 'Thumbnail capture failed: {message}', pt: 'Falha ao capturar miniatura: {message}', }, embedder_unavailable_log: { - context: 'scripts/main.js:568', + context: 'lab-js/main.js:568', it: 'ImageEmbedder non disponibile: {message} — solo face-api attivo.', en: 'ImageEmbedder unavailable: {message} — only face-api is active.', pt: 'ImageEmbedder indisponível: {message} — só o face-api está ativo.', notes: 'Glossary: ImageEmbedder, face-api.', }, loading_makeup_plugins_log: { - context: 'scripts/main.js:571', + context: 'lab-js/main.js:571', it: 'Caricamento plugin di makeup in corso...', en: 'Loading makeup plugins...', pt: 'Carregando plugins de maquiagem...', }, ghostyles_json_error_log: { - context: 'scripts/main.js:593', + context: 'lab-js/main.js:593', it: 'Errore durante la lettura di ghostyles.json: {message}', en: 'Error while reading ghostyles.json: {message}', pt: 'Erro ao ler ghostyles.json: {message}', }, init_complete_webcam_log: { - context: 'scripts/main.js:596', + context: 'lab-js/main.js:596', it: 'Inizializzazione completata. Avvio webcam in corso...', en: 'Initialization complete. Starting webcam...', pt: 'Inicialização concluída. Iniciando webcam...', }, webcam_permission_error: { - context: 'scripts/main.js:600', + context: 'lab-js/main.js:600', it: 'Impossibile inizializzare webcam: verifica i permessi camera per {origin}', en: 'Could not start webcam: check camera permissions for {origin}', pt: 'Não foi possível iniciar a webcam: verifique as permissões da câmera para {origin}', }, ready_start_log: { - context: 'scripts/main.js:621', + context: 'lab-js/main.js:621', it: 'Tutto pronto! Inizia scansionando il tuo volto o attivando una guida makeup.', en: 'All set! Start by scanning your face or turning on a makeup guide.', pt: 'Tudo pronto! Comece escaneando seu rosto ou ativando uma guia de maquiagem.', }, face_api_models_not_loaded_log: { - context: 'scripts/engine.js:27', + context: 'lab-js/engine.js:27', it: '[ERROR] face-api modelli non caricati. Riprova tra pochi secondi.', en: '[ERROR] face-api models not loaded. Try again in a few seconds.', pt: '[ERROR] modelos face-api não carregados. Tente de novo em alguns segundos.', notes: 'Glossary: face-api.', }, no_face_webcam_log: { - context: 'scripts/engine.js:38', + context: 'lab-js/engine.js:38', it: 'Nessun volto rilevato nella webcam.', en: 'No face detected in the webcam.', pt: 'Nenhum rosto detectado na webcam.', }, face_api_error_log: { - context: 'scripts/engine.js:47', + context: 'lab-js/engine.js:47', it: '[ERRORE face-api] {message}', en: '[face-api ERROR] {message}', pt: '[ERRO face-api] {message}', notes: 'Glossary: face-api.', }, face_saved_log: { - context: 'scripts/engine.js:330', + context: 'lab-js/engine.js:330', it: 'Impronta biometrica salvata con ID {id}. Detection score: {score}.', en: 'Biometric faceprint saved with ID {id}. Detection score: {score}.', pt: 'Impressão biométrica salva com ID {id}. Pontuação da detecção: {score}.', notes: 'Glossary: biometric faceprint, detection score.', }, match_2d_ghostyle_unclear_headline: { - context: 'scripts/landmark-analysis.js:134', + context: 'lab-js/landmark-analysis.js:134', it: 'Il rilevatore con il Ghostyle vede il volto con ID {id} - diversita {diversity}%.', en: 'With the Ghostyle, the detector sees the face as ID {id} - diversity {diversity}%.', pt: 'Com o Ghostyle, o detector vê o rosto como ID {id} - diversidade {diversity}%.', notes: 'Glossary: Ghostyle, detector, diversity.', }, match_2d_detector_failed_headline: { - context: 'scripts/landmark-analysis.js:142', + context: 'lab-js/landmark-analysis.js:142', it: 'Rilevatore ingannato dal Ghostyle! face-api non trova un volto nel disegno composito.', en: 'Detector fooled by the Ghostyle! face-api does not find a face in the composite drawing.', pt: 'Detector enganado pelo Ghostyle! face-api não encontra um rosto no desenho composto.', notes: 'Glossary: detector, Ghostyle, face-api, composite.', }, match_2d_weak_detection_headline: { - context: 'scripts/landmark-analysis.js:150', + context: 'lab-js/landmark-analysis.js:150', it: 'Individuazione sul Ghostyle con bassa confidenza (face-api non vede chiaramente un volto).', en: 'Low-confidence detection on the Ghostyle (face-api does not clearly see a face).', pt: 'Detecção com baixa confiança no Ghostyle (face-api não vê claramente um rosto).', notes: 'Glossary: detection confidence, Ghostyle, face-api.', }, match_2d_ghostyle_eluded_headline: { - context: 'scripts/landmark-analysis.js:159', + context: 'lab-js/landmark-analysis.js:159', it: 'Ghostyle attivo: volto rilevato ma diversita {diversity}% sopra soglia {threshold}%.', en: 'Ghostyle active: face detected, but diversity {diversity}% is above threshold {threshold}%.', pt: 'Ghostyle ativo: rosto detectado, mas diversidade {diversity}% acima do limite {threshold}%.', notes: 'Glossary: Ghostyle, diversity, threshold.', }, match_2d_live_matched_headline: { - context: 'scripts/landmark-analysis.js:169', + context: 'lab-js/landmark-analysis.js:169', it: 'Corrispondenza trovata: ID {id} (diversita {diversity}% sotto soglia {threshold}%).', en: 'Match found: ID {id} (diversity {diversity}% below threshold {threshold}%).', pt: 'Correspondência encontrada: ID {id} (diversidade {diversity}% abaixo do limite {threshold}%).', notes: 'Glossary: match, diversity, threshold.', }, match_2d_live_eluded_headline: { - context: 'scripts/landmark-analysis.js:178', + context: 'lab-js/landmark-analysis.js:178', it: 'Nessuna corrispondenza: diversita {diversity}% sopra soglia {threshold}%.', en: 'No match: diversity {diversity}% above threshold {threshold}%.', pt: 'Sem correspondência: diversidade {diversity}% acima do limite {threshold}%.', notes: 'Glossary: match, diversity, threshold.', }, webcam_unavailable_log: { - context: 'scripts/camera.js:51', + context: 'lab-js/camera.js:51', it: 'Webcam non disponibile in questo contesto.{hint}', en: 'Webcam unavailable in this context.{hint}', pt: 'Webcam indisponível neste contexto.{hint}', }, webcam_https_hint: { - context: 'scripts/camera.js:50', + context: 'lab-js/camera.js:50', it: ' La pagina deve essere servita via HTTPS o da localhost (su mobile l\'IP locale non basta).', en: ' The page must be served over HTTPS or from localhost (on mobile, a local IP is not enough).', pt: ' A página deve ser servida por HTTPS ou por localhost (no celular, um IP local não basta).', }, webcam_live_status: { - context: 'scripts/camera.js:79', + context: 'lab-js/camera.js:79', it: 'webcam attiva', en: 'webcam active', pt: 'webcam ativa', }, webcam_active_log: { - context: 'scripts/camera.js:80', + context: 'lab-js/camera.js:80', it: 'Webcam attiva. Premi l\'icona bersaglio per la scansione o scegli un effetto.', en: 'Webcam active. Press the target icon to scan or choose an effect.', pt: 'Webcam ativa. Pressione o ícone de alvo para escanear ou escolha um efeito.', }, webcam_stream_inactive_log: { - context: 'scripts/camera.js:188', + context: 'lab-js/camera.js:188', it: 'Errore: Webcam stream non attivo.', en: 'Error: webcam stream is not active.', pt: 'Erro: o stream da webcam não está ativo.', }, recording_started_log: { - context: 'scripts/camera.js:198', + context: 'lab-js/camera.js:198', it: 'Registrazione avviata...', en: 'Recording started...', pt: 'Gravação iniciada...', }, recording_queued_log: { - context: 'scripts/camera.js:248', + context: 'lab-js/camera.js:248', it: 'Registrazione pronta nel browser: {filename}', en: 'Recording ready in the browser: {filename}', pt: 'Gravação pronta no navegador: {filename}', }, video_uploading_log: { - context: 'scripts/camera.js:233', + context: 'lab-js/camera.js:233', it: 'Caricamento del video sul server in corso...', en: 'Uploading video to the server...', pt: 'Enviando vídeo para o servidor...', }, video_upload_done_log: { - context: 'scripts/camera.js:245', + context: 'lab-js/camera.js:245', it: 'Caricamento completato con successo sul server (HTTP {status}) - File: {filename}', en: 'Upload completed successfully on the server (HTTP {status}) - File: {filename}', pt: 'Envio concluído com sucesso no servidor (HTTP {status}) - Arquivo: {filename}', }, video_upload_http_error_log: { - context: 'scripts/camera.js:247', + context: 'lab-js/camera.js:247', it: 'Errore durante il caricamento del video: Server HTTP {status} {statusText}', en: 'Error while uploading video: server HTTP {status} {statusText}', pt: 'Erro ao enviar vídeo: servidor HTTP {status} {statusText}', }, video_upload_network_error_log: { - context: 'scripts/camera.js:250', + context: 'lab-js/camera.js:250', it: 'Errore di rete durante il caricamento del video: {message}', en: 'Network error while uploading video: {message}', pt: 'Erro de rede ao enviar vídeo: {message}', }, recording_downloaded_log: { - context: 'scripts/camera.js:265', + context: 'lab-js/camera.js:265', it: 'Registrazione completata e scaricata: {filename}', en: 'Recording completed and downloaded: {filename}', pt: 'Gravação concluída e baixada: {filename}', }, media_recorder_error_log: { - context: 'scripts/camera.js:288', + context: 'lab-js/camera.js:288', it: 'Errore durante l\'inizializzazione di MediaRecorder: {message}', en: 'Error while initializing MediaRecorder: {message}', pt: 'Erro ao inicializar MediaRecorder: {message}', }, local_archive_cleared_log: { - context: 'scripts/db.js:193', + context: 'lab-js/db.js:193', it: 'Archivio locale cancellato. Il contatore ID riparte da 0.', en: 'Local archive cleared. The ID counter restarts from 0.', pt: 'Arquivo local apagado. O contador de ID recomeça em 0.', }, incompatible_3d_db_log: { - context: 'scripts/db.js:71', + context: 'lab-js/db.js:71', it: 'Database 3D incompatibile col nuovo modello, svuoto', en: '3D database incompatible with the new model, clearing it', pt: 'Banco de dados 3D incompatível com o novo modelo, apagando', notes: 'Glossary: 3D database.', }, image_embedder_ready_log: { - context: 'scripts/engine-3d.js:63', + context: 'lab-js/engine-3d.js:63', it: '[3D] ImageEmbedder pronto.', en: '[3D] ImageEmbedder ready.', pt: '[3D] ImageEmbedder pronto.', notes: 'Glossary: ImageEmbedder.', }, image_embedder_not_loaded_error: { - context: 'scripts/engine-3d.js:105', + context: 'lab-js/engine-3d.js:105', it: '[engine-3d] ImageEmbedder non caricato.', en: '[engine-3d] ImageEmbedder not loaded.', pt: '[engine-3d] ImageEmbedder não carregado.', notes: 'Glossary: ImageEmbedder.', }, no_embedding_returned_error: { - context: 'scripts/engine-3d.js:110', + context: 'lab-js/engine-3d.js:110', it: 'Nessun embedding restituito dal modello.', en: 'No embedding returned by the model.', pt: 'Nenhum embedding retornado pelo modelo.', notes: 'Glossary: embedding.', }, embedding_extraction_error: { - context: 'scripts/engine-3d.js:115', + context: 'lab-js/engine-3d.js:115', it: 'Errore estrazione embedding: {message}', en: 'Embedding extraction error: {message}', pt: 'Erro ao extrair embedding: {message}', notes: 'Glossary: embedding.', }, image_embedder_not_ready_save_log: { - context: 'scripts/engine-3d.js:152', + context: 'lab-js/engine-3d.js:152', it: '[3D] ImageEmbedder non pronto — embedding 3D non salvato.', en: '[3D] ImageEmbedder not ready — 3D embedding not saved.', pt: '[3D] ImageEmbedder não está pronto — embedding 3D não salvo.', notes: 'Glossary: ImageEmbedder, embedding.', }, db_3d_not_initialized_log: { - context: 'scripts/engine-3d.js:156', + context: 'lab-js/engine-3d.js:156', it: '[3D] DB 3D non inizializzato.', en: '[3D] 3D DB not initialized.', pt: '[3D] DB 3D não inicializado.', notes: 'Glossary: 3D DB.', }, embedding_extraction_log: { - context: 'scripts/engine-3d.js:163', + context: 'lab-js/engine-3d.js:163', it: '[3D] Errore estrazione embedding: {message}', en: '[3D] Embedding extraction error: {message}', pt: '[3D] Erro ao extrair embedding: {message}', notes: 'Glossary: embedding.', }, image_embedder_saved_log: { - context: 'scripts/engine-3d.js:172', + context: 'lab-js/engine-3d.js:172', it: '[3D] Embedding ImageEmbedder salvato con ID {id}.', en: '[3D] ImageEmbedder embedding saved with ID {id}.', pt: '[3D] Embedding do ImageEmbedder salvo com ID {id}.', notes: 'Glossary: ImageEmbedder, embedding.', }, image_embedder_not_ready_compare_log: { - context: 'scripts/engine-3d.js:267', + context: 'lab-js/engine-3d.js:267', it: '[3D] ImageEmbedder non pronto — confronto 3D saltato.', en: '[3D] ImageEmbedder not ready — 3D comparison skipped.', pt: '[3D] ImageEmbedder não está pronto — comparação 3D ignorada.', notes: 'Glossary: ImageEmbedder.', }, live_embedding_extraction_log: { - context: 'scripts/engine-3d.js:278', + context: 'lab-js/engine-3d.js:278', it: '[3D] Errore estrazione embedding live: {message}', en: '[3D] Live embedding extraction error: {message}', pt: '[3D] Erro ao extrair embedding ao vivo: {message}', notes: 'Glossary: live embedding.', }, match_3d_ghostyle_matched_headline: { - context: 'scripts/engine-3d.js:316', + context: 'lab-js/engine-3d.js:316', it: '[3D] Ghostyle presente: ImageEmbedder abbina ID {id} (similarità {similarity} ≥ {threshold}).', en: '[3D] Ghostyle present: ImageEmbedder matches ID {id} (similarity {similarity} ≥ {threshold}).', pt: '[3D] Ghostyle presente: ImageEmbedder corresponde ao ID {id} (similaridade {similarity} ≥ {threshold}).', notes: 'Glossary: Ghostyle, ImageEmbedder, similarity.', }, match_3d_ghostyle_eluded_headline: { - context: 'scripts/engine-3d.js:321', + context: 'lab-js/engine-3d.js:321', it: '[3D] Ghostyle presente: ImageEmbedder non abbina (similarità {similarity} < {threshold}). Embedding visivo spostato.', en: '[3D] Ghostyle present: ImageEmbedder does not match (similarity {similarity} < {threshold}). Visual embedding shifted.', pt: '[3D] Ghostyle presente: ImageEmbedder não corresponde (similaridade {similarity} < {threshold}). Embedding visual deslocado.', notes: 'Glossary: Ghostyle, ImageEmbedder, embedding, similarity.', }, match_3d_empty_db_headline: { - context: 'scripts/engine-3d.js:327', + context: 'lab-js/engine-3d.js:327', it: '[3D] DB 3D vuoto, nessun confronto ImageEmbedder.', en: '[3D] 3D DB empty, no ImageEmbedder comparison.', pt: '[3D] DB 3D vazio, sem comparação do ImageEmbedder.', notes: 'Glossary: 3D DB, ImageEmbedder.', }, match_3d_live_matched_headline: { - context: 'scripts/engine-3d.js:332', + context: 'lab-js/engine-3d.js:332', it: '[3D] Corrispondenza ImageEmbedder: ID {id} (similarità {similarity} ≥ {threshold}).', en: '[3D] ImageEmbedder match: ID {id} (similarity {similarity} ≥ {threshold}).', pt: '[3D] Correspondência ImageEmbedder: ID {id} (similaridade {similarity} ≥ {threshold}).', notes: 'Glossary: ImageEmbedder, match, similarity.', }, match_3d_live_eluded_headline: { - context: 'scripts/engine-3d.js:337', + context: 'lab-js/engine-3d.js:337', it: '[3D] Nessuna corrispondenza ImageEmbedder (max similarità {similarity} < {threshold}).', en: '[3D] No ImageEmbedder match (max similarity {similarity} < {threshold}).', pt: '[3D] Nenhuma correspondência ImageEmbedder (similaridade máxima {similarity} < {threshold}).', notes: 'Glossary: ImageEmbedder, match, similarity.', }, record_clip_first_toast: { - context: 'scripts/lab-ui.js:102', + context: 'lab-js/lab-ui.js:102', it: 'Registra prima una clip', en: 'Record a clip first', pt: 'Grave um clipe primeiro', }, fullscreen_not_available_toast: { - context: 'scripts/lab-ui.js:117', + context: 'lab-js/lab-ui.js:117', it: 'Schermo intero non disponibile qui', en: 'Fullscreen not available here', pt: 'Tela cheia indisponível aqui', }, ghostyle_not_loaded_toast: { - context: 'scripts/lab-ui.js:204', + context: 'lab-js/lab-ui.js:204', it: 'Ghostyle "{id}" non caricato', en: 'Ghostyle "{id}" not loaded', pt: 'Ghostyle "{id}" não carregado', notes: 'Glossary: Ghostyle.', }, pinned_to_slot_toast: { - context: 'scripts/lab-ui.js:242', + context: 'lab-js/lab-ui.js:242', it: 'Fissato nello slot {slot} → {name}', en: 'Pinned to Slot {slot} → {name}', pt: 'Fixado no slot {slot} → {name}', notes: 'Glossary: pinned, slot.', }, measuring_status: { - context: 'scripts/lab-ui.js:302', + context: 'lab-js/lab-ui.js:302', it: 'Misurazione…', en: 'Measuring…', pt: 'Medindo…', }, no_face_found_status: { - context: 'scripts/lab-ui.js:343', + context: 'lab-js/lab-ui.js:343', it: 'Volto non trovato', en: 'No face found', pt: 'Rosto não encontrado', }, no_face_in_frame_status: { - context: 'scripts/lab-ui.js:356', + context: 'lab-js/lab-ui.js:356', it: 'Nessun volto nel frame', en: 'No face in frame', pt: 'Nenhum rosto no quadro', notes: 'Glossary: frame.', }, escaped_status: { - context: 'scripts/lab-ui.js:344; scripts/lab-ui.js:364', + context: 'lab-js/lab-ui.js:344; lab-js/lab-ui.js:364', it: 'Escapou', en: 'Escaped', pt: 'Escapou', }, recognised_status: { - context: 'scripts/lab-ui.js:345; scripts/lab-ui.js:364', + context: 'lab-js/lab-ui.js:345; lab-js/lab-ui.js:364', it: 'Reconhecido', en: 'Recognised', pt: 'Reconhecido', }, visual_comparison_title: { - context: 'scripts/analyze-panel.js:142', + context: 'lab-js/analyze-panel.js:142', it: 'Confronto visivo', en: 'Visual comparison', pt: 'Comparação visual', }, visual_comparison_label: { - context: 'scripts/analyze-panel.js:143', + context: 'lab-js/analyze-panel.js:143', it: 'Confronto visivo base vs attuale', en: 'Baseline vs current visual comparison', pt: 'Comparação visual da base com o rosto atual', notes: 'Glossary: baseline.', }, baseline_thumbnail_alt: { - context: 'scripts/analyze-panel.js:137', + context: 'lab-js/analyze-panel.js:137', it: 'Thumbnail volto base ID {id}', en: 'Baseline face thumbnail ID {id}', pt: 'Miniatura do rosto base ID {id}', notes: 'Glossary: baseline thumbnail.', }, current_thumbnail_alt: { - context: 'scripts/analyze-panel.js:150', + context: 'lab-js/analyze-panel.js:150', it: 'Thumbnail volto attuale', en: 'Current face thumbnail', pt: 'Miniatura do rosto atual', }, current_you_label: { - context: 'scripts/analyze-panel.js:151', + context: 'lab-js/analyze-panel.js:151', it: 'Tu ora', en: 'You now', pt: 'Você agora', }, face_detected_title: { - context: 'scripts/analyze-panel.js:167; scripts/analyze-panel.js:194', + context: 'lab-js/analyze-panel.js:167; lab-js/analyze-panel.js:194', it: 'Volto rilevato', en: 'Face detected', pt: 'Rosto detectado', }, no_face_snapshot: { - context: 'scripts/analyze-panel.js:168; scripts/analyze-panel.js:430', + context: 'lab-js/analyze-panel.js:168; lab-js/analyze-panel.js:430', it: 'Nessun volto rilevato nello snapshot.', en: 'No face detected in the snapshot.', pt: 'Nenhum rosto detectado no snapshot.', notes: 'Glossary: snapshot.', }, recognition_title: { - context: 'scripts/analyze-panel.js:171; scripts/analyze-panel.js:206', + context: 'lab-js/analyze-panel.js:171; lab-js/analyze-panel.js:206', it: 'Riconoscimento', en: 'Recognition', pt: 'Reconhecimento', }, no_recognition_data: { - context: 'scripts/analyze-panel.js:172', + context: 'lab-js/analyze-panel.js:172', it: 'Nessun dato di riconoscimento disponibile.', en: 'No recognition data available.', pt: 'Nenhum dado de reconhecimento disponível.', }, no_id_found: { - context: 'scripts/analyze-panel.js:180', + context: 'lab-js/analyze-panel.js:180', it: 'Nessun ID trovato', en: 'No ID found', pt: 'Nenhum ID encontrado', }, estimated_age_label: { - context: 'scripts/analyze-panel.js:195', + context: 'lab-js/analyze-panel.js:195', it: 'Eta stimata:', en: 'Estimated age:', pt: 'Idade estimada:', }, predicted_gender_label: { - context: 'scripts/analyze-panel.js:197', + context: 'lab-js/analyze-panel.js:197', it: 'Genere predetto:', en: 'Predicted gender:', pt: 'Gênero previsto:', }, dominant_emotion_label: { - context: 'scripts/analyze-panel.js:199', + context: 'lab-js/analyze-panel.js:199', it: 'Emozione dominante:', en: 'Dominant emotion:', pt: 'Emoção dominante:', }, detection_confidence_label: { - context: 'scripts/analyze-panel.js:201; scripts/analyze-panel.js:422', + context: 'lab-js/analyze-panel.js:201; lab-js/analyze-panel.js:422', it: 'Confidence detection:', en: 'Detection confidence:', pt: 'Confiança da detecção:', notes: 'Glossary: detection confidence.', }, state_label: { - context: 'scripts/analyze-panel.js:207', + context: 'lab-js/analyze-panel.js:207', it: 'Stato:', en: 'Status:', pt: 'Estado:', }, match_with_id_label: { - context: 'scripts/analyze-panel.js:208; scripts/analyze-panel.js:434', + context: 'lab-js/analyze-panel.js:208; lab-js/analyze-panel.js:434', it: 'Match con ID:', en: 'Match with ID:', pt: 'Correspondência com ID:', notes: 'Glossary: match.', }, diversity_from_baseline_label: { - context: 'scripts/analyze-panel.js:209; scripts/analyze-panel.js:436', + context: 'lab-js/analyze-panel.js:209; lab-js/analyze-panel.js:436', it: 'Diversita dal volto base:', en: 'Diversity from baseline face:', pt: 'Diversidade em relação ao rosto base:', notes: 'Glossary: diversity, baseline.', }, recognition_threshold_label: { - context: 'scripts/analyze-panel.js:211; scripts/analyze-panel.js:438', + context: 'lab-js/analyze-panel.js:211; lab-js/analyze-panel.js:438', it: 'Soglia di riconoscimento:', en: 'Recognition threshold:', pt: 'Limite de reconhecimento:', notes: 'Glossary: recognition threshold.', }, interpretation_label: { - context: 'scripts/analyze-panel.js:213', + context: 'lab-js/analyze-panel.js:213', it: 'Interpretazione:', en: 'Interpretation:', pt: 'Interpretação:', }, analysis_interpretation: { - context: 'scripts/analyze-panel.js:213', + context: 'lab-js/analyze-panel.js:213', it: 'il tuo volto attuale e {diversity} diverso dal volto base {id}; sopra {threshold}% di diversita il sistema non ti riconosce.', en: 'your current face is {diversity} different from the baseline face {id}; above {threshold}% diversity, the system does not recognise you.', pt: 'seu rosto atual está {diversity} diferente do rosto base {id}; acima de {threshold}% de diversidade, o sistema não reconhece você.', notes: 'Glossary: baseline, diversity.', }, analysis_explainer_age: { - context: 'scripts/analyze-panel.js:17', + context: 'lab-js/analyze-panel.js:17', it: 'Eta stimata dal modello - e solo una statistica, puo sbagliare di 5-10 anni.', en: 'Age estimated by the model - it is only a statistic and can be wrong by 5-10 years.', pt: 'Idade estimada pelo modelo - é apenas uma estatística e pode errar por 5-10 anos.', }, analysis_explainer_gender: { - context: 'scripts/analyze-panel.js:18', + context: 'lab-js/analyze-panel.js:18', it: 'Genere predetto dal modello - addestrato su dataset con bias noti.', en: 'Gender predicted by the model - trained on datasets with known bias.', pt: 'Gênero previsto pelo modelo - treinado em conjuntos de dados com vieses conhecidos.', notes: 'Glossary: dataset bias.', }, analysis_explainer_emotion: { - context: 'scripts/analyze-panel.js:19', + context: 'lab-js/analyze-panel.js:19', it: 'Emozione dominante tra quelle che il modello distingue: happy, sad, angry, fearful, disgusted, surprised, neutral.', en: 'Dominant emotion among the ones the model can distinguish: happy, sad, angry, fearful, disgusted, surprised, neutral.', pt: 'Emoção dominante entre as que o modelo distingue: happy, sad, angry, fearful, disgusted, surprised, neutral.', }, analysis_explainer_confidence: { - context: 'scripts/analyze-panel.js:20', + context: 'lab-js/analyze-panel.js:20', it: 'Quanto il rilevatore e sicuro di vedere un volto nello snapshot. Sotto 50% spesso non viene rilevato nulla.', en: 'How sure the detector is that it sees a face in the snapshot. Below 50%, often nothing is detected.', pt: 'Quão seguro o detector está de ver um rosto no snapshot. Abaixo de 50%, muitas vezes nada é detectado.', notes: 'Glossary: detector confidence, snapshot.', }, analysis_explainer_distance: { - context: 'scripts/analyze-panel.js:21', + context: 'lab-js/analyze-panel.js:21', it: 'Quanto il tuo volto attuale e diverso dal volto base salvato con questo ID. Piu la percentuale e alta, meno il sistema riesce a riconoscerti.', en: 'How different your current face is from the baseline face saved with this ID. The higher the percentage, the less the system can recognise you.', pt: 'Quão diferente seu rosto atual está do rosto base salvo com este ID. Quanto maior a porcentagem, menos o sistema consegue reconhecer você.', notes: 'Glossary: baseline face.', }, analysis_explainer_threshold: { - context: 'scripts/analyze-panel.js:22', + context: 'lab-js/analyze-panel.js:22', it: 'Sopra questa percentuale di diversita il sistema non ti riconosce piu. Sotto, si.', en: 'Above this diversity percentage, the system no longer recognises you. Below it, it does.', pt: 'Acima desta porcentagem de diversidade, o sistema não reconhece mais você. Abaixo dela, reconhece.', notes: 'Glossary: diversity threshold.', }, analysis_explainer_embedder: { - context: 'scripts/analyze-panel.js:23', + context: 'lab-js/analyze-panel.js:23', it: 'Il motore 3D usa una scala diversa (cosine similarity, 0-1, piu alto = piu simile).', en: 'The 3D engine uses a different scale (cosine similarity, 0-1, higher = more similar).', pt: 'O motor 3D usa uma escala diferente (similaridade de cosseno, 0-1, maior = mais parecido).', notes: 'Glossary: cosine similarity.', }, analyze_error_log: { - context: 'scripts/analyze-panel.js:269', + context: 'lab-js/analyze-panel.js:269', it: '[ERRORE analyze] {message}', en: '[analyze ERROR] {message}', pt: '[ERRO analyze] {message}', }, report_copied_log: { - context: 'scripts/analyze-panel.js:230', + context: 'lab-js/analyze-panel.js:230', it: 'Report copiato negli appunti', en: 'Report copied to clipboard', pt: 'Relatório copiado para a área de transferência', }, report_copy_failed_log: { - context: 'scripts/analyze-panel.js:232', + context: 'lab-js/analyze-panel.js:232', it: 'Impossibile copiare il report negli appunti', en: 'Could not copy the report to clipboard', pt: 'Não foi possível copiar o relatório para a área de transferência', }, report_title_markdown: { - context: 'scripts/analyze-panel.js:399; scripts/analyze-panel.js:410', + context: 'lab-js/analyze-panel.js:399; lab-js/analyze-panel.js:410', it: '### Ghostmaxxing - Analisi del trucco', en: '### Ghostmaxxing - Makeup analysis', pt: '### Ghostmaxxing - Análise da maquiagem', }, yes_value: { - context: 'scripts/analyze-panel.js:412', + context: 'lab-js/analyze-panel.js:412', it: 'si', en: 'yes', pt: 'sim', }, no_value: { - context: 'scripts/analyze-panel.js:401; scripts/analyze-panel.js:412', + context: 'lab-js/analyze-panel.js:401; lab-js/analyze-panel.js:412', it: 'no', en: 'no', pt: 'não', }, report_face_detected_line: { - context: 'scripts/analyze-panel.js:401; scripts/analyze-panel.js:412', + context: 'lab-js/analyze-panel.js:401; lab-js/analyze-panel.js:412', it: 'Volto rilevato: {value}', en: 'Face detected: {value}', pt: 'Rosto detectado: {value}', }, report_recognition_2d_heading: { - context: 'scripts/analyze-panel.js:403; scripts/analyze-panel.js:426', + context: 'lab-js/analyze-panel.js:403; lab-js/analyze-panel.js:426', it: 'Riconoscimento (face-api 2D)', en: 'Recognition (face-api 2D)', pt: 'Reconhecimento (face-api 2D)', notes: 'Glossary: face-api 2D.', }, no_data_available: { - context: 'scripts/analyze-panel.js:405', + context: 'lab-js/analyze-panel.js:405', it: 'Nessun dato disponibile.', en: 'No data available.', pt: 'Nenhum dado disponível.', }, report_estimated_age_line: { - context: 'scripts/analyze-panel.js:416', + context: 'lab-js/analyze-panel.js:416', it: 'Eta stimata: {value}', en: 'Estimated age: {value}', pt: 'Idade estimada: {value}', }, report_predicted_gender_line: { - context: 'scripts/analyze-panel.js:418', + context: 'lab-js/analyze-panel.js:418', it: 'Genere predetto: {value}', en: 'Predicted gender: {value}', pt: 'Gênero previsto: {value}', }, report_dominant_emotion_line: { - context: 'scripts/analyze-panel.js:420', + context: 'lab-js/analyze-panel.js:420', it: 'Emozione dominante: {value}', en: 'Dominant emotion: {value}', pt: 'Emoção dominante: {value}', }, report_detection_confidence_line: { - context: 'scripts/analyze-panel.js:422', + context: 'lab-js/analyze-panel.js:422', it: 'Confidence detection: {value}', en: 'Detection confidence: {value}', pt: 'Confiança da detecção: {value}', notes: 'Glossary: detection confidence.', }, no_baseline_face_database: { - context: 'scripts/analyze-panel.js:432', + context: 'lab-js/analyze-panel.js:432', it: 'Nessun volto base nel database.', en: 'No baseline face in the database.', pt: 'Nenhum rosto base no banco de dados.', notes: 'Glossary: baseline face.', }, report_match_with_id_line: { - context: 'scripts/analyze-panel.js:434', + context: 'lab-js/analyze-panel.js:434', it: 'Match con ID: {value}', en: 'Match with ID: {value}', pt: 'Correspondência com ID: {value}', notes: 'Glossary: match.', }, report_diversity_line: { - context: 'scripts/analyze-panel.js:436', + context: 'lab-js/analyze-panel.js:436', it: 'Diversita dal volto base: {value}', en: 'Diversity from baseline face: {value}', pt: 'Diversidade em relação ao rosto base: {value}', notes: 'Glossary: diversity, baseline.', }, report_recognition_threshold_line: { - context: 'scripts/analyze-panel.js:438', + context: 'lab-js/analyze-panel.js:438', it: 'Soglia di riconoscimento: {value}', en: 'Recognition threshold: {value}', pt: 'Limite de reconhecimento: {value}', notes: 'Glossary: recognition threshold.', }, report_status_line: { - context: 'scripts/analyze-panel.js:440', + context: 'lab-js/analyze-panel.js:440', it: 'Stato: {value}', en: 'Status: {value}', pt: 'Estado: {value}', }, report_embedder_3d_heading: { - context: 'scripts/analyze-panel.js:444', + context: 'lab-js/analyze-panel.js:444', it: 'Embedder 3D (MediaPipe)', en: '3D Embedder (MediaPipe)', pt: 'Embedder 3D (MediaPipe)', notes: 'Glossary: Embedder, MediaPipe.', }, report_cosine_similarity_line: { - context: 'scripts/analyze-panel.js:447; scripts/analyze-panel.js:449', + context: 'lab-js/analyze-panel.js:447; lab-js/analyze-panel.js:449', it: 'Cosine similarity con ID {id}: {value}', en: 'Cosine similarity with ID {id}: {value}', pt: 'Similaridade de cosseno com ID {id}: {value}', notes: 'Glossary: cosine similarity.', }, no_embedding_data_available: { - context: 'scripts/analyze-panel.js:451', + context: 'lab-js/analyze-panel.js:451', it: 'Nessun dato embedding disponibile.', en: 'No embedding data available.', pt: 'Nenhum dado de embedding disponível.', notes: 'Glossary: embedding.', }, image_copied_log: { - context: 'scripts/export-makeup.js:49', + context: 'lab-js/export-makeup.js:49', it: 'Immagine con referto diagnostico copiata negli appunti!', en: 'Image with diagnostic report copied to clipboard!', pt: 'Imagem com relatório de diagnóstico copiada para a área de transferência!', }, image_shared_log: { - context: 'scripts/export-makeup.js:59', + context: 'lab-js/export-makeup.js:59', it: 'Immagine condivisa con successo!', en: 'Image shared successfully!', pt: 'Imagem compartilhada com sucesso!', }, image_copy_unavailable_log: { - context: 'scripts/export-makeup.js:62', + context: 'lab-js/export-makeup.js:62', it: 'Impossibile copiare l\'immagine (permessi mancanti o Share API non supportata).', en: 'Could not copy the image (missing permissions or Share API not supported).', pt: 'Não foi possível copiar a imagem (permissões ausentes ou Share API não suportada).', notes: 'Glossary: Share API.', }, image_copy_error_log: { - context: 'scripts/export-makeup.js:66', + context: 'lab-js/export-makeup.js:66', it: 'Errore durante la copia. Forse manca il permesso nel browser?', en: 'Error while copying. Maybe the browser permission is missing?', pt: 'Erro ao copiar. Talvez falte a permissão no navegador?', }, plugin_missing_name_log: { - context: 'scripts/ghostyles-manager.js:101', + context: 'lab-js/ghostyles-manager.js:101', it: 'Plugin {id} senza @name nell\'header, uso fallback {fallback}', en: 'Plugin {id} has no @name in the header, using fallback {fallback}', pt: 'Plugin {id} sem @name no cabeçalho, usando fallback {fallback}', notes: 'Glossary: plugin header.', }, plugin_missing_version_log: { - context: 'scripts/ghostyles-manager.js:108', + context: 'lab-js/ghostyles-manager.js:108', it: 'Plugin {id} senza @version', en: 'Plugin {id} has no @version', pt: 'Plugin {id} sem @version', }, plugin_not_renderable_log: { - context: 'scripts/ghostyles-manager.js:112', + context: 'lab-js/ghostyles-manager.js:112', it: 'Plugin {id} non esporta ne onDraw ne paintUV, ignorato', en: 'Plugin {id} exports neither onDraw nor paintUV, ignored', pt: 'Plugin {id} não exporta onDraw nem paintUV, ignorado', notes: 'Glossary: onDraw, paintUV.', }, plugin_invalid_release_date_log: { - context: 'scripts/ghostyles-manager.js:117', + context: 'lab-js/ghostyles-manager.js:117', it: 'Plugin {id} ha @release_date non valida ({releaseDate}), ignorata', en: 'Plugin {id} has invalid @release_date ({releaseDate}), ignored', pt: 'Plugin {id} tem @release_date inválida ({releaseDate}), ignorada', }, ghostyle_loaded_log: { - context: 'scripts/ghostyles-manager.js:143', + context: 'lab-js/ghostyles-manager.js:143', it: 'Caricato con successo ghostyle {name} da {url}', en: 'Successfully loaded ghostyle {name} from {url}', pt: 'Ghostyle {name} carregado com sucesso de {url}', notes: 'Glossary: ghostyle.', }, plugin_runtime_error_log: { - context: 'scripts/ghostyles-manager.js:164; scripts/plugins3d-loader.js:58', + context: 'lab-js/ghostyles-manager.js:164; lab-js/plugins3d-loader.js:58', it: 'Plugin {id} ha lanciato: {message} ({hook})', en: 'Plugin {id} threw: {message} ({hook})', pt: 'Plugin {id} lançou erro: {message} ({hook})', }, ghostyle_already_active_log: { - context: 'scripts/ghostyles-manager.js:348', + context: 'lab-js/ghostyles-manager.js:348', it: 'Effetto {name} già attivo. Disattivazione in corso...', en: 'Effect {name} already active. Deactivating...', pt: 'Efeito {name} já ativo. Desativando...', }, ghostyle_switched_log: { - context: 'scripts/ghostyles-manager.js:367', + context: 'lab-js/ghostyles-manager.js:367', it: 'Effetto {previous} disattivato, abiliato {name}. Sarà applicato al volto nella webcam.', en: 'Effect {previous} deactivated, {name} enabled. It will be applied to the face in the webcam.', pt: 'Efeito {previous} desativado, {name} ativado. Será aplicado ao rosto na webcam.', }, ghostyle_activated_log: { - context: 'scripts/ghostyles-manager.js:369', + context: 'lab-js/ghostyles-manager.js:369', it: 'Effetto {name} attivato. Sarà applicato al volto nella webcam.', en: 'Effect {name} activated. It will be applied to the face in the webcam.', pt: 'Efeito {name} ativado. Será aplicado ao rosto na webcam.', }, updated_meta_label: { - context: 'scripts/ghostyles-manager.js:258', + context: 'lab-js/ghostyles-manager.js:258', it: 'aggiornato {time}', en: 'updated {time}', pt: 'atualizado {time}', }, pin_to_slot_title: { - context: 'scripts/ghostyles-manager.js:279; scripts/ghostyles-manager.js:286', + context: 'lab-js/ghostyles-manager.js:279; lab-js/ghostyles-manager.js:286', it: 'Fissa nello slot {slot}', en: 'Pin to Slot {slot}', pt: 'Fixar no slot {slot}', notes: 'Glossary: pin, slot.', }, pin_ghostyle_to_slot_label: { - context: 'scripts/ghostyles-manager.js:280; scripts/ghostyles-manager.js:287', + context: 'lab-js/ghostyles-manager.js:280; lab-js/ghostyles-manager.js:287', it: 'Fissa {name} nello slot {slot}', en: 'Pin {name} to Slot {slot}', pt: 'Fixar {name} no slot {slot}', notes: 'Glossary: pin, slot.', }, params_heading: { - context: 'scripts/plugins3d-loader.js:373', + context: 'lab-js/plugins3d-loader.js:373', it: 'Parametri - {name}', en: 'Parameters - {name}', pt: 'Parâmetros - {name}', }, capture_thumbnail_video_required_error: { - context: 'scripts/face-thumbnails.js:154', + context: 'lab-js/face-thumbnails.js:154', it: 'captureThumbnail: elemento video richiesto.', en: 'captureThumbnail: video element is required.', pt: 'captureThumbnail: elemento de vídeo obrigatório.', }, capture_thumbnail_invalid_box_error: { - context: 'scripts/face-thumbnails.js:156', + context: 'lab-js/face-thumbnails.js:156', it: 'captureThumbnail: riquadro volto non valido.', en: 'captureThumbnail: invalid face box.', pt: 'captureThumbnail: caixa de rosto inválida.', }, capture_thumbnail_frame_not_ready_error: { - context: 'scripts/face-thumbnails.js:162', + context: 'lab-js/face-thumbnails.js:162', it: 'captureThumbnail: frame video non pronto.', en: 'captureThumbnail: video frame not ready.', pt: 'captureThumbnail: quadro de vídeo não pronto.', }, capture_thumbnail_context_error: { - context: 'scripts/face-thumbnails.js:181', + context: 'lab-js/face-thumbnails.js:181', it: 'captureThumbnail: contesto 2d non disponibile.', en: 'captureThumbnail: 2d context unavailable.', pt: 'captureThumbnail: contexto 2d indisponível.', }, uv_path_required_error: { - context: 'scripts/ghostyle3d-uv-renderer.js:25', + context: 'lab-js/ghostyle3d-uv-renderer.js:25', it: '[uv-renderer] uvPath obbligatorio', en: '[uv-renderer] uvPath is required', pt: '[uv-renderer] uvPath obrigatório', }, media_devices_unavailable_error: { - context: 'scripts/camera.js:53', + context: 'lab-js/camera.js:53', it: 'mediaDevices unavailable (insecure context?)', en: 'mediaDevices unavailable (insecure context?)', pt: 'mediaDevices unavailable (insecure context?)', }, plugins3d_not_initialized_error: { - context: 'scripts/plugins3d-loader.js:92', + context: 'lab-js/plugins3d-loader.js:92', it: '[plugins3d] initPlugins3dLoader() non chiamato', en: '[plugins3d] initPlugins3dLoader() not called', pt: '[plugins3d] initPlugins3dLoader() não chamado', }, plugins3d_missing_dom_error: { - context: 'scripts/plugins3d-loader.js:537', + context: 'lab-js/plugins3d-loader.js:537', it: '[plugins3d] elementi DOM mancanti', en: '[plugins3d] missing DOM elements', pt: '[plugins3d] elementos DOM ausentes', }, canvas_2d_context_error: { - context: 'scripts/export-makeup.js:178', + context: 'lab-js/export-makeup.js:178', it: 'Impossibile creare il contesto canvas 2D.', en: 'Could not create 2D canvas context.', pt: 'Não foi possível criar o contexto canvas 2D.', }, console_get_face_embedding_error: { - context: 'scripts/engine-3d.js:115', + context: 'lab-js/engine-3d.js:115', it: '[getFaceEmbedding]', en: '[getFaceEmbedding]', pt: '[getFaceEmbedding]', }, console_uv_load_error: { - context: 'scripts/ghostyle3d-uv-renderer.js:58', + context: 'lab-js/ghostyle3d-uv-renderer.js:58', it: '[uv-renderer] errore caricamento UV:', en: '[uv-renderer] UV loading error:', pt: '[uv-renderer] erro ao carregar UV:', }, uv_map_loaded_log: { - context: 'scripts/ghostyle3d-uv-renderer.js:55', + context: 'lab-js/ghostyle3d-uv-renderer.js:55', it: 'UV map caricata ({landmarks} landmark, {triangles} triangoli)', en: 'UV map loaded ({landmarks} landmarks, {triangles} triangles)', pt: 'Mapa UV carregado ({landmarks} landmarks, {triangles} triângulos)', notes: 'Glossary: UV map, landmarks, triangles.', }, uv_map_load_error_log: { - context: 'scripts/ghostyle3d-uv-renderer.js:59', + context: 'lab-js/ghostyle3d-uv-renderer.js:59', it: 'Errore caricamento UV map: {message}', en: 'Error loading UV map: {message}', pt: 'Erro ao carregar mapa UV: {message}', notes: 'Glossary: UV map.', }, console_uv_paint_error: { - context: 'scripts/ghostyle3d-uv-renderer.js:368', + context: 'lab-js/ghostyle3d-uv-renderer.js:368', it: '[uv-renderer] paintUV errore:', en: '[uv-renderer] paintUV error:', pt: '[uv-renderer] erro paintUV:', }, console_detection_error: { - context: 'scripts/engine.js:46', + context: 'lab-js/engine.js:46', it: '[detectFaceInCam]', en: '[detectFaceInCam]', pt: '[detectFaceInCam]', }, console_resized_detection_missing: { - context: 'scripts/engine.js:96', + context: 'lab-js/engine.js:96', it: 'resized.detection non disponibile:', en: 'resized.detection unavailable:', pt: 'resized.detection indisponível:', }, console_composite_detection_error: { - context: 'scripts/engine.js:121', + context: 'lab-js/engine.js:121', it: '[compositeAndDetect]', en: '[compositeAndDetect]', pt: '[compositeAndDetect]', }, console_clipboard_fallback: { - context: 'scripts/export-makeup.js:53', + context: 'lab-js/export-makeup.js:53', it: 'Clipboard write fallito, provo fallback', en: 'Clipboard write failed, trying fallback', pt: 'Falha ao escrever na área de transferência, tentando alternativa', }, console_share_failed: { - context: 'scripts/export-makeup.js:62', + context: 'lab-js/export-makeup.js:62', it: 'Share failed', en: 'Share failed', pt: 'Compartilhamento falhou', }, console_bbox_overlay_missing: { - context: 'scripts/bbox-overlay.js:121', + context: 'lab-js/bbox-overlay.js:121', it: '[bbox-overlay] #bboxOverlay o #overlay mancante, init saltato', en: '[bbox-overlay] missing #bboxOverlay or #overlay, skipping init', pt: '[bbox-overlay] #bboxOverlay ou #overlay ausente, init ignorado', }, overlay_face_detected_label: { - context: 'scripts/bbox-overlay.js:558', + context: 'lab-js/bbox-overlay.js:558', it: 'volto rilevato', en: 'face detected', pt: 'rosto detectado', }, overlay_estimated_age_label: { - context: 'scripts/bbox-overlay.js:559', + context: 'lab-js/bbox-overlay.js:559', it: 'eta stimata: {age}', en: 'estimated age: {age}', pt: 'idade estimada: {age}', }, overlay_estimated_gender_label: { - context: 'scripts/bbox-overlay.js:560', + context: 'lab-js/bbox-overlay.js:560', it: 'genere stimato: {gender}', en: 'estimated gender: {gender}', pt: 'gênero estimado: {gender}', }, console_mediapipe_events_missing: { - context: 'scripts/mediapipe-loop.js:68', + context: 'lab-js/mediapipe-loop.js:68', it: '[mediapipe-loop] gstmxx.events non trovato, skip init', en: '[mediapipe-loop] gstmxx.events not found, skipping init', pt: '[mediapipe-loop] gstmxx.events não encontrado, init ignorado', }, console_mediapipe_video_missing: { - context: 'scripts/mediapipe-loop.js:73', + context: 'lab-js/mediapipe-loop.js:73', it: '[mediapipe-loop] #video non trovato, skip init', en: '[mediapipe-loop] #video not found, skipping init', pt: '[mediapipe-loop] #video não encontrado, init ignorado', }, console_mediapipe_init_error: { - context: 'scripts/mediapipe-loop.js:88', + context: 'lab-js/mediapipe-loop.js:88', it: '[mediapipe-loop] errore init:', en: '[mediapipe-loop] init error:', pt: '[mediapipe-loop] erro de init:', }, mediapipe_load_error_log: { - context: 'scripts/mediapipe-loop.js:90', + context: 'lab-js/mediapipe-loop.js:90', it: 'Errore caricamento MediaPipe: {message}', en: 'Error loading MediaPipe: {message}', pt: 'Erro ao carregar MediaPipe: {message}', notes: 'Glossary: MediaPipe.', }, mediapipe_ready_log: { - context: 'scripts/mediapipe-loop.js:99', + context: 'lab-js/mediapipe-loop.js:99', it: 'MediaPipe FaceLandmarker pronto (478 landmark 3D)', en: 'MediaPipe FaceLandmarker ready (478 3D landmarks)', pt: 'MediaPipe FaceLandmarker pronto (478 landmarks 3D)', notes: 'Glossary: MediaPipe FaceLandmarker, 3D landmarks.', }, console_mediapipe_tick_error: { - context: 'scripts/mediapipe-loop.js:138', + context: 'lab-js/mediapipe-loop.js:138', it: '[mediapipe-loop] errore tick:', en: '[mediapipe-loop] tick error:', pt: '[mediapipe-loop] erro de tick:', }, console_lab_ui_bus_missing: { - context: 'scripts/lab-ui.js:380', + context: 'lab-js/lab-ui.js:380', it: '[lab-ui] state.gstmxxEvents non trovato — readout/effect mirroring disabilitati', en: '[lab-ui] state.gstmxxEvents not found — readout/effect mirroring disabled', pt: '[lab-ui] state.gstmxxEvents não encontrado — readout/espelhamento de efeito desativados', }, console_auto_find_tick_error: { - context: 'scripts/auto-find-loop.js:116', + context: 'lab-js/auto-find-loop.js:116', it: '[auto-find-loop] tick error:', en: '[auto-find-loop] tick error:', pt: '[auto-find-loop] erro de tick:', @@ -2247,13 +2247,13 @@ export const messages = { pt: 'Ações de rosto', }, loader_record_face_button: { - context: 'loader.html:64; scripts/loader.js:250', + context: 'loader.html:64; lab-js/loader.js:250', it: 'Registra volto', en: 'Record face', pt: 'Gravar rosto', }, loader_seek_face_button: { - context: 'loader.html:65; scripts/loader.js:303', + context: 'loader.html:65; lab-js/loader.js:303', it: 'Cerca volto', en: 'Seek face', pt: 'Buscar rosto', @@ -2291,94 +2291,94 @@ export const messages = { notes: 'Glossary: timestamp.', }, loader_status_action_failed: { - context: 'scripts/loader.js:222', + context: 'lab-js/loader.js:222', it: 'azione fallita', en: 'action failed', pt: 'ação falhou', }, loader_status_loading_faceapi: { - context: 'scripts/loader.js:396', + context: 'lab-js/loader.js:396', it: 'caricamento face-api', en: 'loading face-api', pt: 'carregando face-api', notes: 'Glossary: face-api.', }, loader_status_loading_3d_embedder: { - context: 'scripts/loader.js:404', + context: 'lab-js/loader.js:404', it: 'caricamento embedder 3D', en: 'loading 3D embedder', pt: 'carregando embedder 3D', notes: 'Glossary: 3D embedder.', }, loader_status_ready: { - context: 'scripts/loader.js:474', + context: 'lab-js/loader.js:474', it: 'pronto', en: 'ready', pt: 'pronto', }, loader_status_model_load_failed: { - context: 'scripts/loader.js:480', + context: 'lab-js/loader.js:480', it: 'caricamento modelli fallito', en: 'model load failed', pt: 'falha ao carregar modelos', }, loader_log_loaded_local_video: { - context: 'scripts/loader.js:428', + context: 'lab-js/loader.js:428', it: 'Video locale caricato: {name}', en: 'Loaded local video: {name}', pt: 'Vídeo local carregado: {name}', }, loader_ready_log: { - context: 'scripts/loader.js:475', + context: 'lab-js/loader.js:475', it: 'Loader pronto. Seleziona un MP4 e premi Registra volto o Cerca volto.', en: 'Loader ready. Select an MP4 and press Record face or Seek face.', pt: 'Carregador pronto. Selecione um MP4 e pressione Gravar rosto ou Buscar rosto.', notes: 'Glossary: MP4.', }, loader_model_error_log: { - context: 'scripts/loader.js:481', + context: 'lab-js/loader.js:481', it: 'Errore modelli loader: {message}', en: 'Loader model error: {message}', pt: 'Erro de modelo do carregador: {message}', }, loader_action_error: { - context: 'scripts/loader.js:223', + context: 'lab-js/loader.js:223', it: 'errore', en: 'error', pt: 'erro', }, loader_action_record_face: { - context: 'scripts/loader.js:231; scripts/loader.js:250', + context: 'lab-js/loader.js:231; lab-js/loader.js:250', it: 'registra volto', en: 'record face', pt: 'gravar rosto', }, loader_action_seek_face: { - context: 'scripts/loader.js:286; scripts/loader.js:303', + context: 'lab-js/loader.js:286; lab-js/loader.js:303', it: 'cerca volto', en: 'seek face', pt: 'buscar rosto', }, loader_chip_pressed: { - context: 'scripts/loader.js:146', + context: 'lab-js/loader.js:146', it: 'premuto', en: 'pressed', pt: 'pressionado', }, loader_chip_video: { - context: 'scripts/loader.js:147', + context: 'lab-js/loader.js:147', it: 'video', en: 'video', pt: 'vídeo', }, loader_no_face_result: { - context: 'scripts/loader.js:233; scripts/loader.js:288', + context: 'lab-js/loader.js:233; lab-js/loader.js:288', it: 'nessun volto rilevato', en: 'no face detected', pt: 'nenhum rosto detectado', }, loader_no_2d_face_message: { - context: 'scripts/loader.js:234; scripts/loader.js:289', + context: 'lab-js/loader.js:234; lab-js/loader.js:289', it: 'Nessuna rilevazione 2D face-api era disponibile in questo frame.', en: 'No 2D face-api detection was available at this frame.', pt: 'Nenhuma detecção 2D do face-api estava disponível neste frame.', diff --git a/scripts/lab-ui.js b/lab-js/lab-ui.js similarity index 100% rename from scripts/lab-ui.js rename to lab-js/lab-ui.js diff --git a/scripts/landmark-analysis.js b/lab-js/landmark-analysis.js similarity index 100% rename from scripts/landmark-analysis.js rename to lab-js/landmark-analysis.js diff --git a/scripts/loader.js b/lab-js/loader.js similarity index 100% rename from scripts/loader.js rename to lab-js/loader.js diff --git a/scripts/main.js b/lab-js/main.js similarity index 100% rename from scripts/main.js rename to lab-js/main.js diff --git a/scripts/mediapipe-loop.js b/lab-js/mediapipe-loop.js similarity index 100% rename from scripts/mediapipe-loop.js rename to lab-js/mediapipe-loop.js diff --git a/scripts/mobile-ui.js b/lab-js/mobile-ui.js similarity index 100% rename from scripts/mobile-ui.js rename to lab-js/mobile-ui.js diff --git a/scripts/plugins3d-loader.js b/lab-js/plugins3d-loader.js similarity index 98% rename from scripts/plugins3d-loader.js rename to lab-js/plugins3d-loader.js index 42525ec..07148ae 100644 --- a/scripts/plugins3d-loader.js +++ b/lab-js/plugins3d-loader.js @@ -69,9 +69,6 @@ function deactivateBroken3dPlugin(entry, err) { runtime.events.dispatchEvent(new CustomEvent('effectChanged', { detail: { activeEffect: null, previous } })); - runtime.events.dispatchEvent(new CustomEvent('effectChanged3d', { - detail: { active: null, previous } - })); } } @@ -404,8 +401,7 @@ function getActivePaintEntry() { /** * Synchronizes loader state after a ghostyle effect change by selecting the - * active `paintUV` entry, preparing its parameters, refreshing controls, and - * notifying listeners through `effectChanged3d`. + * active `paintUV` entry, preparing its parameters, refreshing controls. * * @returns {void} * @see initPlugins3dLoader - Called during initialization and by the `effectChanged` event listener. @@ -422,12 +418,6 @@ function syncActiveEntry() { hideParamsPanel(); clearCanvas(); } - - if (prev !== runtime.activePluginId) { - runtime.events.dispatchEvent(new CustomEvent('effectChanged3d', { - detail: { active: runtime.activePluginId, previous: prev } - })); - } } /** diff --git a/scripts/realtime.js b/lab-js/realtime.js similarity index 100% rename from scripts/realtime.js rename to lab-js/realtime.js diff --git a/scripts/state.js b/lab-js/state.js similarity index 99% rename from scripts/state.js rename to lab-js/state.js index b84255b..4f0939a 100644 --- a/scripts/state.js +++ b/lab-js/state.js @@ -169,7 +169,7 @@ * @property {EventTarget} gstmxxEvents * In-app event bus. All cross-module events are dispatched here and exposed to * plugins as `window.gstmxx.events`. Events on this bus: `ready`, `detection`, - * `effectChanged`, `effectChanged3d`, `landmarks3d`, `matchStateChanged`, + * `effectChanged`, `landmarks3d`, `matchStateChanged`, * `beforeEfficacyComposite`, `dbChanged`, `mediapipeReady`. (NB: `gstmxxReady` * is dispatched on `window`, not here.) * **Range:** a single EventTarget instance (never reassigned). diff --git a/scripts/transfer.js b/lab-js/transfer.js similarity index 100% rename from scripts/transfer.js rename to lab-js/transfer.js diff --git a/scripts/upload-consent.js b/lab-js/upload-consent.js similarity index 100% rename from scripts/upload-consent.js rename to lab-js/upload-consent.js diff --git a/scripts/utils.js b/lab-js/utils.js similarity index 99% rename from scripts/utils.js rename to lab-js/utils.js index ddd99e1..8e3f36e 100644 --- a/scripts/utils.js +++ b/lab-js/utils.js @@ -34,7 +34,7 @@ import { state } from './state.js'; * @param {number[]} a First vector. * @param {number[]} b Second vector, same length as `a`. * @returns {number} Euclidean distance, or `Infinity` if inputs are invalid. - * @see scripts/engine.js – `seekFaceInDb()` and `computeCompositeMetrics()` + * @see lab-js/engine.js – `seekFaceInDb()` and `computeCompositeMetrics()` * use this against 128-D face-api descriptors. */ export function distance(a, b) { @@ -568,7 +568,7 @@ export function formatRelativeTime(dateLike) { * by clicking the log box. * * @see setLog – calls this after pushing a new entry. - * @see scripts/main.js – wires the click handler that toggles + * @see lab-js/main.js – wires the click handler that toggles * `state.isLogExpanded`. */ export function updateLogDisplay() { diff --git a/lab-js/vendor/FOLDER-DESCRIPTION.md b/lab-js/vendor/FOLDER-DESCRIPTION.md new file mode 100644 index 0000000..4b02d30 --- /dev/null +++ b/lab-js/vendor/FOLDER-DESCRIPTION.md @@ -0,0 +1,9 @@ +# lab-js/vendor + +This folder contains third-party browser runtime assets mirrored into the repository so local demos and workshops can avoid network requests to external model and library hosts. + +The files come from face-api.js, MediaPipe Tasks Vision, face-api model weights, MediaPipe model files, and the local refresh helper `fetch-sources.sh`. They are used by the detection, recognition, landmarking, and MediaPipe/3D paths at runtime. + +`face-api.js` is loaded as a classic script before the ES modules that call the global `faceapi` object. The model shards and manifests provide TinyFaceDetector, 68-point landmarks, recognition descriptors, age/gender, and expression models. `tasks-vision@0.10.35.js`, `face_landmarker.task`, `mobilenet_v3_small.tflite`, and the nested `wasm/` runtime support the MediaPipe face-landmark and ImageEmbedder paths. + +These files are excluded from code2prompt because they are vendored libraries, model weights, WASM support files, and generated manifests. Their exact source URLs and refresh rules are documented in `lab-js/vendor/README.md` in the repository, but only this summary and the nested folder description are uploaded to the chatbot. diff --git a/scripts/vendor/README.md b/lab-js/vendor/README.md similarity index 93% rename from scripts/vendor/README.md rename to lab-js/vendor/README.md index 3303e25..08c181b 100644 --- a/scripts/vendor/README.md +++ b/lab-js/vendor/README.md @@ -1,6 +1,6 @@ Vendor asset inventory for third-party runtime files. -Use `scripts/vendor/fetch-sources.sh` to refresh the assets it manages. +Use `lab-js/vendor/fetch-sources.sh` to refresh the assets it manages. ## Library bundles @@ -44,4 +44,4 @@ Source reference for this block is currently `justadudewhohacks/face-api.js-mode ## Update rule -When any source URL or version segment above changes, re-run `scripts/vendor/fetch-sources.sh` and verify runtime no longer requests third-party hosts. +When any source URL or version segment above changes, re-run `lab-js/vendor/fetch-sources.sh` and verify runtime no longer requests third-party hosts. diff --git a/scripts/vendor/age_gender_model-shard1 b/lab-js/vendor/age_gender_model-shard1 similarity index 100% rename from scripts/vendor/age_gender_model-shard1 rename to lab-js/vendor/age_gender_model-shard1 diff --git a/scripts/vendor/age_gender_model-weights_manifest.json b/lab-js/vendor/age_gender_model-weights_manifest.json similarity index 100% rename from scripts/vendor/age_gender_model-weights_manifest.json rename to lab-js/vendor/age_gender_model-weights_manifest.json diff --git a/scripts/vendor/face-api.js b/lab-js/vendor/face-api.js similarity index 100% rename from scripts/vendor/face-api.js rename to lab-js/vendor/face-api.js diff --git a/scripts/vendor/face_expression_model-shard1 b/lab-js/vendor/face_expression_model-shard1 similarity index 100% rename from scripts/vendor/face_expression_model-shard1 rename to lab-js/vendor/face_expression_model-shard1 diff --git a/scripts/vendor/face_expression_model-weights_manifest.json b/lab-js/vendor/face_expression_model-weights_manifest.json similarity index 100% rename from scripts/vendor/face_expression_model-weights_manifest.json rename to lab-js/vendor/face_expression_model-weights_manifest.json diff --git a/scripts/vendor/face_landmark_68_model-shard1 b/lab-js/vendor/face_landmark_68_model-shard1 similarity index 100% rename from scripts/vendor/face_landmark_68_model-shard1 rename to lab-js/vendor/face_landmark_68_model-shard1 diff --git a/scripts/vendor/face_landmark_68_model-weights_manifest.json b/lab-js/vendor/face_landmark_68_model-weights_manifest.json similarity index 100% rename from scripts/vendor/face_landmark_68_model-weights_manifest.json rename to lab-js/vendor/face_landmark_68_model-weights_manifest.json diff --git a/scripts/vendor/face_landmarker.task b/lab-js/vendor/face_landmarker.task similarity index 100% rename from scripts/vendor/face_landmarker.task rename to lab-js/vendor/face_landmarker.task diff --git a/scripts/vendor/face_recognition_model-shard1 b/lab-js/vendor/face_recognition_model-shard1 similarity index 100% rename from scripts/vendor/face_recognition_model-shard1 rename to lab-js/vendor/face_recognition_model-shard1 diff --git a/scripts/vendor/face_recognition_model-shard2 b/lab-js/vendor/face_recognition_model-shard2 similarity index 100% rename from scripts/vendor/face_recognition_model-shard2 rename to lab-js/vendor/face_recognition_model-shard2 diff --git a/scripts/vendor/face_recognition_model-weights_manifest.json b/lab-js/vendor/face_recognition_model-weights_manifest.json similarity index 100% rename from scripts/vendor/face_recognition_model-weights_manifest.json rename to lab-js/vendor/face_recognition_model-weights_manifest.json diff --git a/scripts/vendor/fetch-sources.sh b/lab-js/vendor/fetch-sources.sh similarity index 92% rename from scripts/vendor/fetch-sources.sh rename to lab-js/vendor/fetch-sources.sh index 6db482c..bde6341 100755 --- a/scripts/vendor/fetch-sources.sh +++ b/lab-js/vendor/fetch-sources.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash set -euo pipefail -# Sync all third-party runtime assets into scripts/vendor. -# Run from scripts/vendor or from repo root. +# Sync all third-party runtime assets into lab-js/vendor. +# Run from lab-js/vendor or from repo root. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" @@ -36,4 +36,4 @@ fetch "https://storage.googleapis.com/mediapipe-models/face_landmarker/face_land fetch "https://storage.googleapis.com/mediapipe-models/image_embedder/mobilenet_v3_small/float32/1/mobilenet_v3_small.tflite" "mobilenet_v3_small.tflite" # face-api library bundle is intentionally separate from this script: -# scripts/vendor/face-api.js comes from https://cdn.jsdelivr.net/npm/@vladmandic/face-api/dist/face-api.js +# lab-js/vendor/face-api.js comes from https://cdn.jsdelivr.net/npm/@vladmandic/face-api/dist/face-api.js diff --git a/scripts/vendor/mobilenet_v3_small.tflite b/lab-js/vendor/mobilenet_v3_small.tflite similarity index 100% rename from scripts/vendor/mobilenet_v3_small.tflite rename to lab-js/vendor/mobilenet_v3_small.tflite diff --git a/scripts/vendor/tasks-vision@0.10.35.js b/lab-js/vendor/tasks-vision@0.10.35.js similarity index 100% rename from scripts/vendor/tasks-vision@0.10.35.js rename to lab-js/vendor/tasks-vision@0.10.35.js diff --git a/scripts/vendor/tiny_face_detector_model-shard1 b/lab-js/vendor/tiny_face_detector_model-shard1 similarity index 100% rename from scripts/vendor/tiny_face_detector_model-shard1 rename to lab-js/vendor/tiny_face_detector_model-shard1 diff --git a/scripts/vendor/tiny_face_detector_model-weights_manifest.json b/lab-js/vendor/tiny_face_detector_model-weights_manifest.json similarity index 100% rename from scripts/vendor/tiny_face_detector_model-weights_manifest.json rename to lab-js/vendor/tiny_face_detector_model-weights_manifest.json diff --git a/scripts/vendor/wasm/FOLDER-CONTENT.md b/lab-js/vendor/wasm/FOLDER-DESCRIPTION.md similarity index 65% rename from scripts/vendor/wasm/FOLDER-CONTENT.md rename to lab-js/vendor/wasm/FOLDER-DESCRIPTION.md index da0a31e..1fbe02b 100644 --- a/scripts/vendor/wasm/FOLDER-CONTENT.md +++ b/lab-js/vendor/wasm/FOLDER-DESCRIPTION.md @@ -1,7 +1,7 @@ -# scripts/vendor/wasm +# lab-js/vendor/wasm This folder contains the WebAssembly runtime support files for MediaPipe Tasks Vision. -The files come from the `@mediapipe/tasks-vision@0.10.35` package and are loaded by MediaPipe-backed face-landmarking and embedding code paths when the app runs locally. +The files come from the `@mediapipe/tasks-vision@0.10.35` package and are loaded by MediaPipe-backed face-landmarking and embedding code paths when the app runs locally. `config.js` exposes the local URL used by `mediapipe-loop.js` and the experimental 3D/visual-embedding runtime. They are excluded from code2prompt because they are vendored generated runtime assets, not project-authored source code. diff --git a/scripts/vendor/wasm/vision_wasm_internal.js b/lab-js/vendor/wasm/vision_wasm_internal.js similarity index 100% rename from scripts/vendor/wasm/vision_wasm_internal.js rename to lab-js/vendor/wasm/vision_wasm_internal.js diff --git a/scripts/vendor/wasm/vision_wasm_internal.wasm b/lab-js/vendor/wasm/vision_wasm_internal.wasm similarity index 100% rename from scripts/vendor/wasm/vision_wasm_internal.wasm rename to lab-js/vendor/wasm/vision_wasm_internal.wasm diff --git a/lab.html b/lab.html index dbf27a8..fed7289 100644 --- a/lab.html +++ b/lab.html @@ -16,13 +16,22 @@ - + - + + + + + + + Ghostmaxxing + +
@@ -298,15 +307,15 @@

Ghostyle

- - - - - - - - - + + + + + + + + + diff --git a/loader.html b/loader.html index a125e16..86ca3c8 100644 --- a/loader.html +++ b/loader.html @@ -4,11 +4,21 @@ - Ghostmaxxing | Video Loader + Ghostmaxxing | Makeup Video Loader & Face Engine Debugger - - - + + + + + + + + + + + + + @@ -16,7 +26,7 @@
- + Ghostmaxxing Internal video loader @@ -94,10 +104,10 @@

Activity log

- - - - + + + + diff --git a/package-lock.json b/package-lock.json index 9dc09e5..81d4faf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,8 @@ "devDependencies": { "@playwright/test": "^1.60.0", "@vitest/coverage-v8": "^4.1.8", + "acorn": "^8.18.0", + "acorn-walk": "^8.3.5", "canvas": "^3.2.3", "clean-jsdoc-theme": "^5.0.2", "http-server": "^14.1.1", @@ -25,6 +27,8 @@ }, "node_modules/@asamuzakjp/css-color": { "version": "5.1.11", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz", + "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==", "dev": true, "license": "MIT", "dependencies": { @@ -40,6 +44,8 @@ }, "node_modules/@asamuzakjp/dom-selector": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz", + "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==", "dev": true, "license": "MIT", "dependencies": { @@ -55,6 +61,8 @@ }, "node_modules/@asamuzakjp/generational-cache": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz", + "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==", "dev": true, "license": "MIT", "engines": { @@ -63,11 +71,15 @@ }, "node_modules/@asamuzakjp/nwsapi": { "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", "dev": true, "license": "MIT" }, "node_modules/@babel/helper-string-parser": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, "license": "MIT", "engines": { @@ -76,6 +88,8 @@ }, "node_modules/@babel/helper-validator-identifier": { "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, "license": "MIT", "engines": { @@ -83,11 +97,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.7", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.29.7" + "@babel/types": "^7.29.8" }, "bin": { "parser": "bin/babel-parser.js" @@ -97,7 +113,9 @@ } }, "node_modules/@babel/types": { - "version": "7.29.7", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", "dev": true, "license": "MIT", "dependencies": { @@ -110,6 +128,8 @@ }, "node_modules/@bcoe/v8-coverage": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", "dev": true, "license": "MIT", "engines": { @@ -118,6 +138,8 @@ }, "node_modules/@bramus/specificity": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz", + "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", "dev": true, "license": "MIT", "dependencies": { @@ -128,13 +150,13 @@ } }, "node_modules/@clean-jsdoc-theme/bhasha": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@clean-jsdoc-theme/bhasha/-/bhasha-5.1.0.tgz", - "integrity": "sha512-FIl9hdMgzpObaDTU+lmecqEDTc/d/S2ZsMWaJ46/9ZzswHlK4qwV/cjxGUhx0I+WxNPtz6WpRXMdQMldHpRD+Q==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@clean-jsdoc-theme/bhasha/-/bhasha-5.1.1.tgz", + "integrity": "sha512-9a9QYqAdRVVXVVtjrXt4SVZQDOZ67Eb6U6fE4QXtXVhLdFsLAWGYokz2eQO0nGwHDXuUyUjZSO4gJrqib/1igg==", "dev": true, "license": "MIT", "dependencies": { - "@clean-jsdoc-theme/utils": "^5.1.0" + "@clean-jsdoc-theme/utils": "^5.1.1" }, "funding": { "type": "github", @@ -145,15 +167,15 @@ } }, "node_modules/@clean-jsdoc-theme/dwar": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@clean-jsdoc-theme/dwar/-/dwar-5.1.0.tgz", - "integrity": "sha512-JtuzLazAYAhvUDQCiaOr54Ia3wzdvkP7VI+rOjJL86s6O1hmVt2N99c1uBQWYztt9iuDP2G+ycMC1XLA7Zkxlw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@clean-jsdoc-theme/dwar/-/dwar-5.1.1.tgz", + "integrity": "sha512-eB8WmH/9zgkmWOkBJB9dqWeJUf3k7JKcERcPA+wkC1nZaOp65z8/1QPzq66s8tVDWTqj4TecxOUUIs7u8pv2zA==", "dev": true, "license": "MIT", "dependencies": { - "@clean-jsdoc-theme/rang": "^5.1.0", - "@clean-jsdoc-theme/setu": "^5.1.0", - "@clean-jsdoc-theme/utils": "^5.1.0", + "@clean-jsdoc-theme/rang": "^5.1.1", + "@clean-jsdoc-theme/setu": "^5.1.1", + "@clean-jsdoc-theme/utils": "^5.1.1", "@mdx-js/mdx": "^3.0.0", "@shikijs/rehype": "^4.2.0", "esbuild": "^0.28.0", @@ -172,14 +194,14 @@ } }, "node_modules/@clean-jsdoc-theme/rang": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@clean-jsdoc-theme/rang/-/rang-5.1.0.tgz", - "integrity": "sha512-HmPkg3Lv30drdugLjyac/rBU0EFYT7JzDET55h6VAuuYX9mJFfe+N+Fx7om45I+7sJtQnSGhXSS4jhA7xHNvlw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@clean-jsdoc-theme/rang/-/rang-5.1.1.tgz", + "integrity": "sha512-wTDkbOk9MH5bcRlCbsbConXdvdVftF9yPKmDaiGQy1A16LLeqSF0Ta9saa7Iwc7UZb++w3G3Na6RUX/DKLKmrw==", "dev": true, "license": "MIT", "dependencies": { - "@clean-jsdoc-theme/bhasha": "^5.1.0", - "@clean-jsdoc-theme/utils": "^5.1.0", + "@clean-jsdoc-theme/bhasha": "^5.1.1", + "@clean-jsdoc-theme/utils": "^5.1.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "lucide-preact": "^1.17.0", @@ -195,14 +217,14 @@ } }, "node_modules/@clean-jsdoc-theme/setu": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@clean-jsdoc-theme/setu/-/setu-5.1.0.tgz", - "integrity": "sha512-ZiBxWrWiB4l8uCq80Qr29J9n65AHEWF70BJackXF1D6dXHc1OzwOVvarvMdjlkuZ+Su+M7qgHkkQGMumuieyDQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@clean-jsdoc-theme/setu/-/setu-5.1.1.tgz", + "integrity": "sha512-FZEG1Nr0rRTN75m0iQ1uoZXdP4DTafV5B1Yqw4yJdjjXpiMB/0Ab7xJ0BcdAlYAlZjWsvINsbeyegF26xxJAog==", "dev": true, "license": "MIT", "dependencies": { - "@clean-jsdoc-theme/bhasha": "^5.1.0", - "@clean-jsdoc-theme/utils": "^5.1.0", + "@clean-jsdoc-theme/bhasha": "^5.1.1", + "@clean-jsdoc-theme/utils": "^5.1.1", "@jsdoc/salty": "^0.2.12", "hast-util-from-html": "^2.0.3", "hast-util-to-html": "^9.0.5", @@ -224,9 +246,9 @@ } }, "node_modules/@clean-jsdoc-theme/utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@clean-jsdoc-theme/utils/-/utils-5.1.0.tgz", - "integrity": "sha512-Ev68pg3mb8sYRdGWiaL807FpS9wnbv8ZCdCkr40d609hfWUw7CNEu8CYTzQLXfVnqU655V9sm4eOZoFLf/TCDA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@clean-jsdoc-theme/utils/-/utils-5.1.1.tgz", + "integrity": "sha512-UfQsd8iAEdtYxZlvFxcuuBDhZfo73n60KaruQGOty5UXzjYCpbnAPmFN2E3gs7oIfTnw76fRLvEU2N7xiaxkLg==", "dev": true, "license": "MIT", "dependencies": { @@ -238,7 +260,9 @@ } }, "node_modules/@csstools/color-helpers": { - "version": "6.0.2", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.1.1.tgz", + "integrity": "sha512-gLNsunvwf3mCi5u5o46/Z/JcJMnhbHSaZ69rkgPzNM3J4s8hWwpPUQB6/tt0EDFyCiWzxANlx+2LJwpYj4zS1w==", "dev": true, "funding": [ { @@ -256,7 +280,9 @@ } }, "node_modules/@csstools/css-calc": { - "version": "3.2.1", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.3.0.tgz", + "integrity": "sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==", "dev": true, "funding": [ { @@ -278,7 +304,9 @@ } }, "node_modules/@csstools/css-color-parser": { - "version": "4.1.1", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.2.0.tgz", + "integrity": "sha512-5+5LEmFuY1AjXdYhmgjTJogtQnP1evJ1zrBZGUNZ0thkpwnnmKxcHdAMn/OtFjAb25zA+jKDVYVRl+5G7rjv1A==", "dev": true, "funding": [ { @@ -292,8 +320,8 @@ ], "license": "MIT", "dependencies": { - "@csstools/color-helpers": "^6.0.2", - "@csstools/css-calc": "^3.2.1" + "@csstools/color-helpers": "^6.1.1", + "@csstools/css-calc": "^3.3.0" }, "engines": { "node": ">=20.19.0" @@ -305,6 +333,8 @@ }, "node_modules/@csstools/css-parser-algorithms": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", "dev": true, "funding": [ { @@ -325,7 +355,9 @@ } }, "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.1.5", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.8.tgz", + "integrity": "sha512-CpMLjAvwQg3BL5S0IeqsZNMH7EQrEWi0kLKOC13ZBF0ZwERiLWlibNPJr8G1kdU3Ms/r2KiNrF81pUh2HwAHdg==", "dev": true, "funding": [ { @@ -349,6 +381,8 @@ }, "node_modules/@csstools/css-tokenizer": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", "dev": true, "funding": [ { @@ -365,44 +399,10 @@ "node": ">=20.19.0" } }, - "node_modules/@emnapi/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", - "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", - "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", "cpu": [ "ppc64" ], @@ -417,9 +417,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", - "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", "cpu": [ "arm" ], @@ -434,9 +434,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", - "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", "cpu": [ "arm64" ], @@ -451,9 +451,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", - "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", "cpu": [ "x64" ], @@ -468,9 +468,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", - "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", "cpu": [ "arm64" ], @@ -485,9 +485,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", - "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", "cpu": [ "x64" ], @@ -502,9 +502,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", - "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", "cpu": [ "arm64" ], @@ -519,9 +519,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", - "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", "cpu": [ "x64" ], @@ -536,9 +536,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", - "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", "cpu": [ "arm" ], @@ -553,9 +553,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", - "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", "cpu": [ "arm64" ], @@ -570,9 +570,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", - "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", "cpu": [ "ia32" ], @@ -587,9 +587,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", - "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", "cpu": [ "loong64" ], @@ -604,9 +604,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", - "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", "cpu": [ "mips64el" ], @@ -621,9 +621,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", - "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", "cpu": [ "ppc64" ], @@ -638,9 +638,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", - "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", "cpu": [ "riscv64" ], @@ -655,9 +655,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", - "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", "cpu": [ "s390x" ], @@ -672,9 +672,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", - "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", "cpu": [ "x64" ], @@ -689,9 +689,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", - "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", "cpu": [ "arm64" ], @@ -706,9 +706,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", - "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", "cpu": [ "x64" ], @@ -723,9 +723,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", - "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", "cpu": [ "arm64" ], @@ -740,9 +740,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", - "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", "cpu": [ "x64" ], @@ -757,9 +757,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", - "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", "cpu": [ "arm64" ], @@ -774,9 +774,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", - "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", "cpu": [ "x64" ], @@ -791,9 +791,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", - "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", "cpu": [ "arm64" ], @@ -808,9 +808,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", - "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", "cpu": [ "ia32" ], @@ -825,9 +825,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", - "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", "cpu": [ "x64" ], @@ -843,6 +843,8 @@ }, "node_modules/@exodus/bytes": { "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.1.tgz", + "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==", "dev": true, "license": "MIT", "engines": { @@ -859,6 +861,8 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", "engines": { @@ -867,11 +871,15 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -937,27 +945,10 @@ "dev": true, "license": "BSD-2-Clause" }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.5.tgz", - "integrity": "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" - } - }, "node_modules/@oxc-project/types": { - "version": "0.133.0", + "version": "0.144.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.144.0.tgz", + "integrity": "sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg==", "dev": true, "license": "MIT", "funding": { @@ -1063,23 +1054,25 @@ ] }, "node_modules/@playwright/test": { - "version": "1.60.0", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.62.1.tgz", + "integrity": "sha512-DTcUc8qii+cpHvtOwggMtBRMjKZHXYWdw8syRYu2vtzuq4Wxphqq4NfCs5Zt44L6mA8rfDfj+PHnxFc/FeK6mQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.60.0" + "playwright": "1.62.1" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz", - "integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.4.tgz", + "integrity": "sha512-jHC2cnyKz5xU2fhECtFl8OZ83cYNt13GZQD+0uMJ/X3o+ijmd56okHhTUwxVSHPx1IRVIJEZ1/1pPzeLCU6XKA==", "cpu": [ "arm64" ], @@ -1094,7 +1087,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.3", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-Dc5mPD8F5F/FS8i01syd7FTF6yB2fVthH/TRkjwJkzUK6EpoxHtqvZQP5Zwq80/5z19TWYHIg1KOHboCgVx/aQ==", "cpu": [ "arm64" ], @@ -1109,9 +1104,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz", - "integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.4.tgz", + "integrity": "sha512-fpDm4oBo6SqLvWUYCmFhdde3U9KH2fRNNMeAnAPAIwxRL345xutL0EtEUcuoxsoazdJGv/MuDBQHlCDrtbvqOg==", "cpu": [ "x64" ], @@ -1126,9 +1121,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz", - "integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.4.tgz", + "integrity": "sha512-rSJoreDE/HoIzoaib6MTp5jQtCTdMHKIvItAKT/ImS6Y6Ww76oUaeMyp4Vc/fAgd/ehji068IxetHXAnqUwN9A==", "cpu": [ "x64" ], @@ -1143,9 +1138,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz", - "integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.4.tgz", + "integrity": "sha512-/jm8OGHgn7oGaJu3i/qZI9spUGcJ+y/lk43ttQ/iO1tOd9NissG6o97bighBCiL+BKRngmcDuR6ikfwYdJmVuQ==", "cpu": [ "arm" ], @@ -1160,9 +1155,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz", - "integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.4.tgz", + "integrity": "sha512-tIP06BeD9EqvECBrPZ+sqdPlYrT+aYaAiu1wYziVx5elRK/ftm33JxVDy2bXGbr6J0CrtirCkR87/X5a2euEng==", "cpu": [ "arm64" ], @@ -1180,9 +1175,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz", - "integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.4.tgz", + "integrity": "sha512-Ql1Q0EQqVThvn9VAVlwNzsUvbSFtCMGjLpRRi4pk5i7NZZ4n5ISiLMjHYtus4VQ2PvkSw24zyaCVsiS+sXPj1w==", "cpu": [ "arm64" ], @@ -1200,9 +1195,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz", - "integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.4.tgz", + "integrity": "sha512-GjbjXD4XXfN19D0LZNbmiCBUoDiRACsYHr0yaIbbn8aFsXjHZifcYqu/W5Er5X2X990WjHXFrxarn5chzItorQ==", "cpu": [ "ppc64" ], @@ -1220,9 +1215,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz", - "integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.4.tgz", + "integrity": "sha512-p5WR0NOwaRmJ/B1b6IjEFLLivwEsf3PrdBIhRbhTCQisbo2SvHHpG4ELB/+FgQNnB88LTOF86upmJmbvZdQ2lw==", "cpu": [ "s390x" ], @@ -1240,9 +1235,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz", - "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.4.tgz", + "integrity": "sha512-4/GyVjmhR+Tc6HLJvwc1sOhPqAZtySiSMesOZyX6JQ5XBxoTDEMKQzvo07NIK6nTon/SivlZqvhzvuVBNQhObQ==", "cpu": [ "x64" ], @@ -1260,9 +1255,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz", - "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.4.tgz", + "integrity": "sha512-l9eeLsCNvPpmSXUej0etw/J1eqV0Jj1D5G/xG6YTijmE6dkv6E2QezgWbTfQk63v952DPqrjOCoiqxq7Bw0YUQ==", "cpu": [ "x64" ], @@ -1280,9 +1275,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz", - "integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.4.tgz", + "integrity": "sha512-e0F355MSTMm3+UOqtV3L24gFUp2N5m1f8L/7d56deik6va+AXdrt9F8LbzGpeWGWRbZEDq4m8NVnJDeBtf9DZg==", "cpu": [ "arm64" ], @@ -1296,29 +1291,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz", - "integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "1.10.0", - "@emnapi/runtime": "1.10.0", - "@napi-rs/wasm-runtime": "^1.1.4" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz", - "integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.4.tgz", + "integrity": "sha512-AWLi0uBRYh6QlE7OKhiz+phZC0qwtij2QZmhmOdsLdFn64m7oMpooE9ICE3lhm9xMb4SpDo2WbHcxX1iFLFtqw==", "cpu": [ "arm64" ], @@ -1333,9 +1309,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz", - "integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.4.tgz", + "integrity": "sha512-UwSDJOg3dqCAejWdxclJjCsh3Qq4vLYMDxmyHqo1btz3stK2VqgwNd3mm5tuIwzSlGIQ/1H9Hr+Zn09mrezNqQ==", "cpu": [ "x64" ], @@ -1351,20 +1327,22 @@ }, "node_modules/@rolldown/pluginutils": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", "dev": true, "license": "MIT" }, "node_modules/@shikijs/core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.2.0.tgz", - "integrity": "sha512-Hc87Ab1Ld/vEbZRCbwx344I5v+4RU8CVToUTRkqXL1+TjbuOp9U5Xa0M23V4GEWHxVn+yO5otb+HkQVm3ptWQQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.4.3.tgz", + "integrity": "sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/primitive": "4.2.0", - "@shikijs/types": "4.2.0", + "@shikijs/primitive": "4.4.3", + "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4", + "@types/hast": "^3.0.5", "hast-util-to-html": "^9.0.5" }, "engines": { @@ -1372,13 +1350,13 @@ } }, "node_modules/@shikijs/engine-javascript": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.2.0.tgz", - "integrity": "sha512-fjETeq1k5ffyXqRgS6+3hpvqseLalp1kjNfRbXpUgWR8FpZ1CmQfiNHovc5lncYjt/Vg5JK/WJEmLahjwMa0og==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.4.3.tgz", + "integrity": "sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "4.2.0", + "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.6" }, @@ -1387,13 +1365,13 @@ } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.2.0.tgz", - "integrity": "sha512-hTorK1dffPkpbMUk6Z+828PgRo7d07HbnizoP0hNPFjhxMHctj0Px/qoHeGMYafc6ju+u9iMldN4JbVzNQM++g==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.4.3.tgz", + "integrity": "sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "4.2.0", + "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2" }, "engines": { @@ -1401,44 +1379,44 @@ } }, "node_modules/@shikijs/langs": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.2.0.tgz", - "integrity": "sha512-bwrVRlJ0wUhZxAbVdvBbv2TTC9yLsh4C/IO5Ofz0T8MQntgDvyVnkbjw9vi50r1kx7RCIJdnJnjZAwmAsXFLZQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.4.3.tgz", + "integrity": "sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "4.2.0" + "@shikijs/types": "4.4.3" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/primitive": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.2.0.tgz", - "integrity": "sha512-NOq+DtUkVBJtZMVXL5A0vI0Xk8nvDYaXetFHSJFlOqjDZIVhIPRYFdGkSoElDqNuegikcc3A76SNUa8dTqtAYA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.4.3.tgz", + "integrity": "sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "4.2.0", + "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" + "@types/hast": "^3.0.5" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/rehype": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@shikijs/rehype/-/rehype-4.2.0.tgz", - "integrity": "sha512-ST3EWye/dwF1gWskczJNBnwFtDzEQ9ceytXZtyc/GfwR5V0qJrkoSGZO55O3SAKDDsXkTDcsfwd9pVe7ROlAHg==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/rehype/-/rehype-4.4.3.tgz", + "integrity": "sha512-vkG9jG1aRnrx05R31uAOKQHE8qpY7r1cBXE2sAZgFK2IaPnQHwaP4L1C6amQixmZ8thBsKwfbSsYxMDoo46UWQ==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "4.2.0", - "@types/hast": "^3.0.4", + "@shikijs/types": "4.4.3", + "@types/hast": "^3.0.5", "hast-util-to-string": "^3.0.1", - "shiki": "4.2.0", + "shiki": "4.4.3", "unified": "^11.0.5", "unist-util-visit": "^5.1.0" }, @@ -1447,27 +1425,27 @@ } }, "node_modules/@shikijs/themes": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.2.0.tgz", - "integrity": "sha512-RX8IHYeLv8Cu2W6ruc3RxUqWn0IYCqSrMBzi/uRGAmfyDNOnNO5BF/Px7o97n4XTpmFTo5GbRaazuOWj+2ak2w==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.4.3.tgz", + "integrity": "sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "4.2.0" + "@shikijs/types": "4.4.3" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/types": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.2.0.tgz", - "integrity": "sha512-VT/MKtlpOhEPZloSH3Pb9WCZEBDoQVMa9jedp5UAwmJOar1DVc9DRODAxmYPW9M93IK4ryuqRejFfmlvlVDemw==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.4.3.tgz", + "integrity": "sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==", "dev": true, "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" + "@types/hast": "^3.0.5" }, "engines": { "node": ">=20" @@ -1482,22 +1460,15 @@ }, "node_modules/@standard-schema/spec": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "dev": true, "license": "MIT" }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", - "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@types/chai": { "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { @@ -1517,11 +1488,15 @@ }, "node_modules/@types/deep-eql": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true, "license": "MIT" }, @@ -1536,9 +1511,9 @@ } }, "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz", + "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==", "dev": true, "license": "MIT", "dependencies": { @@ -1553,9 +1528,9 @@ "license": "MIT" }, "node_modules/@types/markdown-it": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", - "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.2.0.tgz", + "integrity": "sha512-NoQ2yGlLWj4wpxMs+TYmRKk3thDrQ97agr7sFqfLsAlvoS8SNQuTrlObhFqG9iugdTtgOE9jpJ6FNM4ZGsa5xQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1602,19 +1577,21 @@ "license": "MIT" }, "node_modules/@ungap/structured-clone": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", - "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", + "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==", "dev": true, "license": "ISC" }, "node_modules/@vitest/coverage-v8": { - "version": "4.1.8", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.10.tgz", + "integrity": "sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.1.8", + "@vitest/utils": "4.1.10", "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", @@ -1628,8 +1605,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "4.1.8", - "vitest": "4.1.8" + "@vitest/browser": "4.1.10", + "vitest": "4.1.10" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -1638,14 +1615,16 @@ } }, "node_modules/@vitest/expect": { - "version": "4.1.8", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", + "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.8", - "@vitest/utils": "4.1.8", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" }, @@ -1654,11 +1633,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.1.8", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", + "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.1.8", + "@vitest/spy": "4.1.10", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -1679,7 +1660,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.1.8", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", + "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1690,11 +1673,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.1.8", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", + "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.1.8", + "@vitest/utils": "4.1.10", "pathe": "^2.0.3" }, "funding": { @@ -1702,12 +1687,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.1.8", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", + "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.8", - "@vitest/utils": "4.1.8", + "@vitest/pretty-format": "4.1.10", + "@vitest/utils": "4.1.10", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -1716,7 +1703,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.1.8", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", + "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", "dev": true, "license": "MIT", "funding": { @@ -1724,11 +1713,13 @@ } }, "node_modules/@vitest/utils": { - "version": "4.1.8", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", + "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.8", + "@vitest/pretty-format": "4.1.10", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" }, @@ -1737,9 +1728,9 @@ } }, "node_modules/acorn": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", - "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", "dev": true, "license": "MIT", "bin": { @@ -1759,10 +1750,23 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", "dev": true, "license": "MIT", "engines": { @@ -1774,6 +1778,8 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { @@ -1795,6 +1801,8 @@ }, "node_modules/assertion-error": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "engines": { @@ -1802,7 +1810,9 @@ } }, "node_modules/ast-v8-to-istanbul": { - "version": "1.0.3", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.5.tgz", + "integrity": "sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==", "dev": true, "license": "MIT", "dependencies": { @@ -1823,6 +1833,8 @@ }, "node_modules/async": { "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "dev": true, "license": "MIT" }, @@ -1860,6 +1872,8 @@ }, "node_modules/basic-auth": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", "dev": true, "license": "MIT", "dependencies": { @@ -1871,6 +1885,8 @@ }, "node_modules/bidi-js": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", "dev": true, "license": "MIT", "dependencies": { @@ -1923,6 +1939,8 @@ }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1935,6 +1953,8 @@ }, "node_modules/call-bound": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, "license": "MIT", "dependencies": { @@ -1989,6 +2009,8 @@ }, "node_modules/chai": { "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", "engines": { @@ -1997,6 +2019,8 @@ }, "node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { @@ -2075,18 +2099,23 @@ } }, "node_modules/clean-jsdoc-theme": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/clean-jsdoc-theme/-/clean-jsdoc-theme-5.0.2.tgz", - "integrity": "sha512-yvfNEcsd3FvweIZq0mZ3tj6fWt5K7nsvGyBZPZ/QLP1pGxKlPIqnlRTHmib3teoG7Qq2RJjy0MEydSe9BH/8WA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/clean-jsdoc-theme/-/clean-jsdoc-theme-5.1.1.tgz", + "integrity": "sha512-BtsYb2byya5kTLnpdDzRKFOjZbqz4clVFcXh6zx61OISztd4hvrfJji2lzw+1ts9qqUxMZV9/ot75Mg8qEHedg==", "dev": true, "license": "MIT", "dependencies": { - "@clean-jsdoc-theme/bhasha": "^5.0.2", - "@clean-jsdoc-theme/dwar": "^5.0.2", - "@clean-jsdoc-theme/rang": "^5.0.2", - "@clean-jsdoc-theme/setu": "^5.0.2", - "@clean-jsdoc-theme/utils": "^5.0.2", - "ora": "^9.3.0" + "@clean-jsdoc-theme/bhasha": "^5.1.1", + "@clean-jsdoc-theme/dwar": "^5.1.1", + "@clean-jsdoc-theme/rang": "^5.1.1", + "@clean-jsdoc-theme/setu": "^5.1.1", + "@clean-jsdoc-theme/utils": "^5.1.1", + "ora": "^9.3.0", + "preact": "^10.22.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ankitskvmdam" }, "peerDependencies": { "jsdoc": ">=4.x" @@ -2144,6 +2173,8 @@ }, "node_modules/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2155,6 +2186,8 @@ }, "node_modules/color-name": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, @@ -2171,11 +2204,15 @@ }, "node_modules/convert-source-map": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, "node_modules/corser": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", "dev": true, "license": "MIT", "engines": { @@ -2184,6 +2221,8 @@ }, "node_modules/css-tree": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", "dev": true, "license": "MIT", "dependencies": { @@ -2196,6 +2235,8 @@ }, "node_modules/data-urls": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", "dev": true, "license": "MIT", "dependencies": { @@ -2208,6 +2249,8 @@ }, "node_modules/debug": { "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -2224,6 +2267,8 @@ }, "node_modules/decimal.js": { "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", "dev": true, "license": "MIT" }, @@ -2279,6 +2324,8 @@ }, "node_modules/detect-libc": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2301,6 +2348,8 @@ }, "node_modules/dunder-proto": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, "license": "MIT", "dependencies": { @@ -2323,11 +2372,13 @@ } }, "node_modules/entities": { - "version": "8.0.0", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, "license": "BSD-2-Clause", "engines": { - "node": ">=20.19.0" + "node": ">=0.12" }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" @@ -2335,6 +2386,8 @@ }, "node_modules/es-define-property": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, "license": "MIT", "engines": { @@ -2343,6 +2396,8 @@ }, "node_modules/es-errors": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, "license": "MIT", "engines": { @@ -2350,12 +2405,16 @@ } }, "node_modules/es-module-lexer": { - "version": "2.1.0", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", "dev": true, "license": "MIT", "dependencies": { @@ -2400,9 +2459,9 @@ } }, "node_modules/esbuild": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", - "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -2413,32 +2472,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.1", - "@esbuild/android-arm": "0.28.1", - "@esbuild/android-arm64": "0.28.1", - "@esbuild/android-x64": "0.28.1", - "@esbuild/darwin-arm64": "0.28.1", - "@esbuild/darwin-x64": "0.28.1", - "@esbuild/freebsd-arm64": "0.28.1", - "@esbuild/freebsd-x64": "0.28.1", - "@esbuild/linux-arm": "0.28.1", - "@esbuild/linux-arm64": "0.28.1", - "@esbuild/linux-ia32": "0.28.1", - "@esbuild/linux-loong64": "0.28.1", - "@esbuild/linux-mips64el": "0.28.1", - "@esbuild/linux-ppc64": "0.28.1", - "@esbuild/linux-riscv64": "0.28.1", - "@esbuild/linux-s390x": "0.28.1", - "@esbuild/linux-x64": "0.28.1", - "@esbuild/netbsd-arm64": "0.28.1", - "@esbuild/netbsd-x64": "0.28.1", - "@esbuild/openbsd-arm64": "0.28.1", - "@esbuild/openbsd-x64": "0.28.1", - "@esbuild/openharmony-arm64": "0.28.1", - "@esbuild/sunos-x64": "0.28.1", - "@esbuild/win32-arm64": "0.28.1", - "@esbuild/win32-ia32": "0.28.1", - "@esbuild/win32-x64": "0.28.1" + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" } }, "node_modules/escape-string-regexp": { @@ -2541,6 +2600,8 @@ }, "node_modules/estree-walker": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", "dependencies": { @@ -2549,6 +2610,8 @@ }, "node_modules/eventemitter3": { "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true, "license": "MIT" }, @@ -2563,7 +2626,9 @@ } }, "node_modules/expect-type": { - "version": "1.3.0", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2593,6 +2658,8 @@ }, "node_modules/fdir": { "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", "engines": { @@ -2609,6 +2676,8 @@ }, "node_modules/follow-redirects": { "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "dev": true, "funding": [ { @@ -2644,7 +2713,10 @@ }, "node_modules/fsevents": { "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, + "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ @@ -2656,6 +2728,8 @@ }, "node_modules/function-bind": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, "license": "MIT", "funding": { @@ -2677,6 +2751,8 @@ }, "node_modules/get-intrinsic": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2700,6 +2776,8 @@ }, "node_modules/get-proto": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "dev": true, "license": "MIT", "dependencies": { @@ -2719,6 +2797,8 @@ }, "node_modules/gopd": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, "license": "MIT", "engines": { @@ -2737,6 +2817,8 @@ }, "node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { @@ -2745,6 +2827,8 @@ }, "node_modules/has-symbols": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, "license": "MIT", "engines": { @@ -2756,6 +2840,8 @@ }, "node_modules/hasown": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "dev": true, "license": "MIT", "dependencies": { @@ -2799,32 +2885,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-from-html/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/hast-util-from-html/node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/hast-util-from-parse5": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", @@ -3111,6 +3171,8 @@ }, "node_modules/he": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, "license": "MIT", "bin": { @@ -3118,18 +3180,22 @@ } }, "node_modules/html-encoding-sniffer": { - "version": "6.0.0", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", "dev": true, "license": "MIT", "dependencies": { - "@exodus/bytes": "^1.6.0" + "whatwg-encoding": "^2.0.0" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": ">=12" } }, "node_modules/html-escaper": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true, "license": "MIT" }, @@ -3146,6 +3212,8 @@ }, "node_modules/http-proxy": { "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3159,6 +3227,8 @@ }, "node_modules/http-server": { "version": "14.1.1", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", + "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", "dev": true, "license": "MIT", "dependencies": { @@ -3183,19 +3253,10 @@ "node": ">=12" } }, - "node_modules/http-server/node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-encoding": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/iconv-lite": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", "dependencies": { @@ -3323,6 +3384,8 @@ }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true, "license": "MIT" }, @@ -3341,6 +3404,8 @@ }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -3349,6 +3414,8 @@ }, "node_modules/istanbul-lib-report": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -3362,6 +3429,8 @@ }, "node_modules/istanbul-reports": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -3374,6 +3443,8 @@ }, "node_modules/js-tokens": { "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", "dev": true, "license": "MIT" }, @@ -3417,21 +3488,10 @@ "node": ">=12.0.0" } }, - "node_modules/jsdoc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/jsdom": { "version": "29.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz", + "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==", "dev": true, "license": "MIT", "dependencies": { @@ -3469,6 +3529,45 @@ } } }, + "node_modules/jsdom/node_modules/entities": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/jsdom/node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.6.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/jsdom/node_modules/parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^8.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/klaw": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", @@ -3480,7 +3579,9 @@ } }, "node_modules/lightningcss": { - "version": "1.32.0", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -3494,23 +3595,23 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" } }, "node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", "cpu": [ "arm64" ], @@ -3529,7 +3630,9 @@ } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.32.0", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", "cpu": [ "arm64" ], @@ -3548,9 +3651,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", - "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", "cpu": [ "x64" ], @@ -3569,9 +3672,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", - "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", "cpu": [ "x64" ], @@ -3590,9 +3693,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", - "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", "cpu": [ "arm" ], @@ -3611,9 +3714,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", - "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", "cpu": [ "arm64" ], @@ -3635,9 +3738,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", - "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", "cpu": [ "arm64" ], @@ -3659,9 +3762,9 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", "cpu": [ "x64" ], @@ -3683,9 +3786,9 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", "cpu": [ "x64" ], @@ -3707,9 +3810,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", - "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", "cpu": [ "arm64" ], @@ -3728,9 +3831,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", "cpu": [ "x64" ], @@ -3804,7 +3907,9 @@ } }, "node_modules/lru-cache": { - "version": "11.5.1", + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -3812,9 +3917,9 @@ } }, "node_modules/lucide-preact": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/lucide-preact/-/lucide-preact-1.21.0.tgz", - "integrity": "sha512-GUJs/vYSHNM5HU0UwNADfKvDbNDQ7i6vciniCvtpRVMsXy+FOcaRHgRhqVcY/CiORqA6oMC8xK5JJ7Wvb1r1Sw==", + "version": "1.31.0", + "resolved": "https://registry.npmjs.org/lucide-preact/-/lucide-preact-1.31.0.tgz", + "integrity": "sha512-Of9TS1ZFAnWpDZZ/iQl4ydyNHU8peDEtqgQFDOhVAU3SdYosUvP/BJeP0lFLZ4QWx5dxABhToeD03Btoa7G/ug==", "dev": true, "license": "ISC", "peerDependencies": { @@ -3833,6 +3938,8 @@ }, "node_modules/magic-string": { "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3840,17 +3947,21 @@ } }, "node_modules/magicast": { - "version": "0.5.3", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.4.tgz", + "integrity": "sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.3", - "@babel/types": "^7.29.0", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", "source-map-js": "^1.2.1" } }, "node_modules/make-dir": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "license": "MIT", "dependencies": { @@ -3877,9 +3988,9 @@ } }, "node_modules/markdown-it": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz", - "integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==", + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.0.tgz", + "integrity": "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==", "dev": true, "funding": [ { @@ -3894,8 +4005,8 @@ "license": "MIT", "dependencies": { "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.1", + "entities": "^4.5.0", + "linkify-it": "^5.0.2", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" @@ -3915,19 +4026,6 @@ "markdown-it": "*" } }, - "node_modules/markdown-it/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/markdown-table": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", @@ -3954,6 +4052,8 @@ }, "node_modules/math-intrinsics": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true, "license": "MIT", "engines": { @@ -4310,13 +4410,15 @@ }, "node_modules/mdn-data": { "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", "dev": true, "license": "CC0-1.0" }, "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.1.0.tgz", + "integrity": "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==", "dev": true, "license": "MIT" }, @@ -5091,6 +5193,8 @@ }, "node_modules/mime": { "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, "license": "MIT", "bin": { @@ -5128,6 +5232,8 @@ }, "node_modules/minimist": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, "license": "MIT", "funding": { @@ -5156,13 +5262,15 @@ }, "node_modules/ms": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.16", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", - "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", "dev": true, "funding": [ { @@ -5186,9 +5294,9 @@ "license": "MIT" }, "node_modules/node-abi": { - "version": "3.92.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", - "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", + "version": "3.94.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.94.0.tgz", + "integrity": "sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==", "dev": true, "license": "MIT", "dependencies": { @@ -5207,6 +5315,8 @@ }, "node_modules/object-inspect": { "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", "engines": { @@ -5217,7 +5327,9 @@ } }, "node_modules/obug": { - "version": "2.1.2", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", "dev": true, "funding": [ "https://github.com/sponsors/sxzz", @@ -5275,6 +5387,8 @@ }, "node_modules/opener": { "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", "dev": true, "license": "(WTFPL OR MIT)", "bin": { @@ -5282,9 +5396,9 @@ } }, "node_modules/ora": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-9.4.0.tgz", - "integrity": "sha512-84cglkRILFxdtA8hAvLNdMrtBpPNBTrQ9/ulg0FA7xLMnD6mifv+enAIeRmvtv+WgdCE+LPGOfQmtJRrVaIVhQ==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-9.4.1.tgz", + "integrity": "sha512-6VlU9MLXbjVQD04AZCMX28hVtA5bUoadvUqO76MUCVA0ilwJbMiHsITRPfyVm6p/BC0Av/BXMujx39WCe1LEqw==", "dev": true, "license": "MIT", "dependencies": { @@ -5364,28 +5478,49 @@ "license": "MIT" }, "node_modules/parse5": { - "version": "8.0.1", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", "dev": true, "license": "MIT", "dependencies": { - "entities": "^8.0.0" + "entities": "^6.0.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/pathe": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, "node_modules/picocolors": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.4", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, "license": "MIT", "engines": { @@ -5396,35 +5531,41 @@ } }, "node_modules/playwright": { - "version": "1.60.0", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.1.tgz", + "integrity": "sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.60.0" + "playwright-core": "1.62.1" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { - "version": "1.60.0", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz", + "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==", "dev": true, "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/portfinder": { "version": "1.0.38", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.38.tgz", + "integrity": "sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg==", "dev": true, "license": "MIT", "dependencies": { @@ -5436,9 +5577,9 @@ } }, "node_modules/postcss": { - "version": "8.5.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", - "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", "dev": true, "funding": [ { @@ -5456,7 +5597,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.16", + "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -5465,15 +5606,22 @@ } }, "node_modules/preact": { - "version": "10.29.2", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.2.tgz", - "integrity": "sha512-7tNmwg/7mzzAoB/8kSg6Hl37JraAZw3Z3A0JSY7VXlZwo82Xn0G7wKbNNs2qoF4ZEEsQGTwDAroNdqKs1ofJxQ==", + "version": "10.29.8", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.8.tgz", + "integrity": "sha512-ej2aVZ+vZ8WO7tvlQWRM9N63A0KzF9q4mWJfDUHgYaIofWY9hu74QdnQrjoPMmZi2/nZ5gN0bJCQF49xQqx09Q==", "dev": true, "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "preact-render-to-string": ">=5" + }, + "peerDependenciesMeta": { + "preact-render-to-string": { + "optional": true + } } }, "node_modules/preact-render-to-string": { @@ -5538,6 +5686,8 @@ }, "node_modules/punycode": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", "engines": { @@ -5555,11 +5705,14 @@ } }, "node_modules/qs": { - "version": "6.15.2", + "version": "6.15.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.1.0" + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" }, "engines": { "node": ">=0.6" @@ -5584,6 +5737,16 @@ "rc": "cli.js" } }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -5832,6 +5995,8 @@ }, "node_modules/require-from-string": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, "license": "MIT", "engines": { @@ -5840,6 +6005,8 @@ }, "node_modules/requires-port": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true, "license": "MIT" }, @@ -5871,11 +6038,13 @@ } }, "node_modules/rolldown": { - "version": "1.0.3", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.4.tgz", + "integrity": "sha512-rSr7irW0K7QRWzjdJXqZowkcRdDtjRduh43rBltnVKd0VFq839l1lJoDvGJb6gl7+4rTTCrPWu+YfujUL8Ug7w==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.133.0", + "@oxc-project/types": "=0.144.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -5885,35 +6054,40 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.3", - "@rolldown/binding-darwin-arm64": "1.0.3", - "@rolldown/binding-darwin-x64": "1.0.3", - "@rolldown/binding-freebsd-x64": "1.0.3", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", - "@rolldown/binding-linux-arm64-gnu": "1.0.3", - "@rolldown/binding-linux-arm64-musl": "1.0.3", - "@rolldown/binding-linux-ppc64-gnu": "1.0.3", - "@rolldown/binding-linux-s390x-gnu": "1.0.3", - "@rolldown/binding-linux-x64-gnu": "1.0.3", - "@rolldown/binding-linux-x64-musl": "1.0.3", - "@rolldown/binding-openharmony-arm64": "1.0.3", - "@rolldown/binding-wasm32-wasi": "1.0.3", - "@rolldown/binding-win32-arm64-msvc": "1.0.3", - "@rolldown/binding-win32-x64-msvc": "1.0.3" + "@rolldown/binding-android-arm64": "1.2.4", + "@rolldown/binding-darwin-arm64": "1.2.4", + "@rolldown/binding-darwin-x64": "1.2.4", + "@rolldown/binding-freebsd-x64": "1.2.4", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.4", + "@rolldown/binding-linux-arm64-gnu": "1.2.4", + "@rolldown/binding-linux-arm64-musl": "1.2.4", + "@rolldown/binding-linux-ppc64-gnu": "1.2.4", + "@rolldown/binding-linux-s390x-gnu": "1.2.4", + "@rolldown/binding-linux-x64-gnu": "1.2.4", + "@rolldown/binding-linux-x64-musl": "1.2.4", + "@rolldown/binding-openharmony-arm64": "1.2.4", + "@rolldown/binding-win32-arm64-msvc": "1.2.4", + "@rolldown/binding-win32-x64-msvc": "1.2.4" } }, "node_modules/safe-buffer": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "license": "MIT" }, "node_modules/saxes": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, "license": "ISC", "dependencies": { @@ -5925,11 +6099,15 @@ }, "node_modules/secure-compare": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", "dev": true, "license": "MIT" }, "node_modules/semver": { - "version": "7.8.4", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, "license": "ISC", "bin": { @@ -5940,20 +6118,20 @@ } }, "node_modules/shiki": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.2.0.tgz", - "integrity": "sha512-hjNax6o/ylDy9lefQEaSDtzaT3iVNtZ3WmpQnbuQNoG4xvnSKf2kSKbihZVO4JRG1TTMejs7CmNRYlWgAL66pQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.4.3.tgz", + "integrity": "sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/core": "4.2.0", - "@shikijs/engine-javascript": "4.2.0", - "@shikijs/engine-oniguruma": "4.2.0", - "@shikijs/langs": "4.2.0", - "@shikijs/themes": "4.2.0", - "@shikijs/types": "4.2.0", + "@shikijs/core": "4.4.3", + "@shikijs/engine-javascript": "4.4.3", + "@shikijs/engine-oniguruma": "4.4.3", + "@shikijs/langs": "4.4.3", + "@shikijs/themes": "4.4.3", + "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" + "@types/hast": "^3.0.5" }, "engines": { "node": ">=20" @@ -5961,6 +6139,8 @@ }, "node_modules/side-channel": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5979,6 +6159,8 @@ }, "node_modules/side-channel-list": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "dev": true, "license": "MIT", "dependencies": { @@ -5994,6 +6176,8 @@ }, "node_modules/side-channel-map": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "license": "MIT", "dependencies": { @@ -6011,6 +6195,8 @@ }, "node_modules/side-channel-weakmap": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", "dependencies": { @@ -6029,6 +6215,8 @@ }, "node_modules/siginfo": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, "license": "ISC" }, @@ -6104,6 +6292,8 @@ }, "node_modules/source-map-js": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -6123,11 +6313,15 @@ }, "node_modules/stackback": { "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, "license": "MIT" }, "node_modules/std-env": { - "version": "4.1.0", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", "dev": true, "license": "MIT" }, @@ -6176,9 +6370,9 @@ "license": "MIT" }, "node_modules/string-width": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz", - "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz", + "integrity": "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==", "dev": true, "license": "MIT", "dependencies": { @@ -6224,13 +6418,16 @@ } }, "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/style-to-js": { @@ -6255,6 +6452,8 @@ }, "node_modules/supports-color": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { @@ -6266,6 +6465,8 @@ }, "node_modules/symbol-tree": { "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true, "license": "MIT" }, @@ -6281,9 +6482,9 @@ } }, "node_modules/tar-fs": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", - "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz", + "integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==", "dev": true, "license": "MIT", "dependencies": { @@ -6312,11 +6513,15 @@ }, "node_modules/tinybench": { "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", "dev": true, "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.2.4", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", "dev": true, "license": "MIT", "engines": { @@ -6325,6 +6530,8 @@ }, "node_modules/tinyglobby": { "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { @@ -6339,7 +6546,9 @@ } }, "node_modules/tinyrainbow": { - "version": "3.1.0", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", + "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", "dev": true, "license": "MIT", "engines": { @@ -6347,23 +6556,29 @@ } }, "node_modules/tldts": { - "version": "7.4.2", + "version": "7.4.10", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.10.tgz", + "integrity": "sha512-GgouD1B+sWwvkaEq8vXC15DjQitxbvs12oIXELpconwm+Tg3zfcEv4jgzq3vtKverDXsg3VI8aRgNL2Nra0Iog==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^7.4.2" + "tldts-core": "^7.4.10" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "7.4.2", + "version": "7.4.10", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.10.tgz", + "integrity": "sha512-KnQjp53ZekKgm/r3l+u8kJGGzYgrWdP8+Mql7a4vijh2WE0IrZWspQj/TpTxDho/YxO+AnOZnIjQcCD+q6iJsw==", "dev": true, "license": "MIT" }, "node_modules/tough-cookie": { - "version": "6.0.1", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.2.tgz", + "integrity": "sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -6375,6 +6590,8 @@ }, "node_modules/tr46": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", "dev": true, "license": "MIT", "dependencies": { @@ -6417,14 +6634,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD", - "optional": true - }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -6498,6 +6707,8 @@ }, "node_modules/union": { "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", "dev": true, "dependencies": { "qs": "^6.4.0" @@ -6610,6 +6821,8 @@ }, "node_modules/url-join": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", "dev": true, "license": "MIT" }, @@ -6666,14 +6879,16 @@ } }, "node_modules/vite": { - "version": "8.0.16", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.1.tgz", + "integrity": "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==", "dev": true, "license": "MIT", "dependencies": { - "lightningcss": "^1.32.0", - "picomatch": "^4.0.4", - "postcss": "^8.5.15", - "rolldown": "1.0.3", + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.25", + "rolldown": "~1.2.1", "tinyglobby": "^0.2.17" }, "bin": { @@ -6690,7 +6905,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.1.18", + "@vitejs/devtools": "^0.4.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -6743,7 +6958,10 @@ }, "node_modules/vite/node_modules/fsevents": { "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, + "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ @@ -6754,17 +6972,19 @@ } }, "node_modules/vitest": { - "version": "4.1.8", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", + "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.1.8", - "@vitest/mocker": "4.1.8", - "@vitest/pretty-format": "4.1.8", - "@vitest/runner": "4.1.8", - "@vitest/snapshot": "4.1.8", - "@vitest/spy": "4.1.8", - "@vitest/utils": "4.1.8", + "@vitest/expect": "4.1.10", + "@vitest/mocker": "4.1.10", + "@vitest/pretty-format": "4.1.10", + "@vitest/runner": "4.1.10", + "@vitest/snapshot": "4.1.10", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", @@ -6792,12 +7012,12 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.8", - "@vitest/browser-preview": "4.1.8", - "@vitest/browser-webdriverio": "4.1.8", - "@vitest/coverage-istanbul": "4.1.8", - "@vitest/coverage-v8": "4.1.8", - "@vitest/ui": "4.1.8", + "@vitest/browser-playwright": "4.1.10", + "@vitest/browser-preview": "4.1.10", + "@vitest/browser-webdriverio": "4.1.10", + "@vitest/coverage-istanbul": "4.1.10", + "@vitest/coverage-v8": "4.1.10", + "@vitest/ui": "4.1.10", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -6843,6 +7063,8 @@ }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "dev": true, "license": "MIT", "dependencies": { @@ -6865,6 +7087,8 @@ }, "node_modules/webidl-conversions": { "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -6873,6 +7097,9 @@ }, "node_modules/whatwg-encoding": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", "dev": true, "license": "MIT", "dependencies": { @@ -6884,6 +7111,8 @@ }, "node_modules/whatwg-mimetype": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", "dev": true, "license": "MIT", "engines": { @@ -6892,6 +7121,8 @@ }, "node_modules/whatwg-url": { "version": "16.0.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz", + "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", "dev": true, "license": "MIT", "dependencies": { @@ -6905,6 +7136,8 @@ }, "node_modules/why-is-node-running": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, "license": "MIT", "dependencies": { @@ -6927,6 +7160,8 @@ }, "node_modules/xml-name-validator": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", "dev": true, "license": "Apache-2.0", "engines": { @@ -6935,6 +7170,8 @@ }, "node_modules/xmlchars": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true, "license": "MIT" }, @@ -6946,9 +7183,9 @@ "license": "Apache-2.0" }, "node_modules/yoctocolors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", - "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.2.0.tgz", + "integrity": "sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 8d6cd7b..bb25cd5 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "web-ar", "ghostyles" ], - "author": "Vecna", + "author": "vecna (me.vecna.eu)", "scripts": { "start": "http-server . -p 8080 -c-1 -o /lab.html", "serve": "http-server . -p 8080 -c-1", @@ -43,14 +43,17 @@ "update:coverage-badge": "node scripts-dev/update-coverage-badge.js", "update:references": "node references/build-references-page.js", "i18n:extract": "node scripts-dev/extract-i18n-pot.cjs", - "web-client-setup": "npm update:references; npm run docs:rebuild; node scripts-dev/install-client-interface.cjs", + "web-client-setup": "npm run update:references; npm run docs:rebuild; node scripts-dev/install-client-interface.cjs", "check": "npm run validate:ghostyles && npm run test:unit", "prepare:e2e": "playwright install chromium", - "c2p": "code2prompt . --no-ignore --include '*.html,*.css,*.js,*.cjs,*.json,*.md,*.d.ts,*.xml,**/*.html,**/*.css,**/*.js,**/*.cjs,**/*.json,**/*.md,**/*.d.ts,**/*.xml' --exclude 'node_modules/**,package-lock.json,CODE2PROMPT*.txt,.DS_Store,**/.DS_Store,tests/**/*.js,tests/**/*.jpg,tests/**/*.mjpeg,scripts/i18n.js,scripts-dev/extract-i18n-pot.cjs,scripts/vendor/README.md,scripts/vendor/**/*.js,scripts/vendor/**/*.json,scripts/vendor/**/*.wasm,scripts/vendor/**/*.task,scripts/vendor/**/*.tflite,scripts/vendor/**/*-shard*,scripts/vendor/foca.sh,styles/vendor/README.md,styles/vendor/**/*.css,styles/vendor/**/*.woff2,docs/jsdoc/**,coverage/**/*.html,coverage/**/*.js,coverage/**/*.css,coverage/**/*.json,coverage/**/*.info,coverage/**/*.png,playwright-report/**/*.html,test-results/**/*.json,images/**/*.svg,images/**/*.png,images/**/*.webp,data/**/*.json,translations/README.md,translations/**/*.pot,translations/**/*.csv,references/index.html,references/*.js,references/*.txt' --sort name_asc --output-format markdown -O \"CODE2PROMPT-$(date +%Y-%m-%d).txt\"" + "c2p": "node scripts-dev/code2prompt.js", + "codemap": "node scripts-dev/build-codemap.js && node scripts-dev/build-codemap-html.js" }, "devDependencies": { "@playwright/test": "^1.60.0", "@vitest/coverage-v8": "^4.1.8", + "acorn": "^8.18.0", + "acorn-walk": "^8.3.5", "canvas": "^3.2.3", "clean-jsdoc-theme": "^5.0.2", "http-server": "^14.1.1", diff --git a/pages-js/FOLDER-DESCRIPTION.md b/pages-js/FOLDER-DESCRIPTION.md new file mode 100644 index 0000000..9414149 --- /dev/null +++ b/pages-js/FOLDER-DESCRIPTION.md @@ -0,0 +1,17 @@ +# pages-js + +This folder contains the small page-level JavaScript files for Ghostmaxxing's static informational and content pages. Unlike the main lab runtime in `lab-js/`, these scripts are not the app engine; they handle specific UI behaviors for landing pages and support pages such as the homepage, genealogy page, and shared site navigation. + +The scripts here are loaded directly by the HTML pages without a bundling step, and they keep page logic small, self-contained, and dependency-light. + +## Files + +- `index.js` — homepage camera-field interaction. It builds the animated field of camera icons, loads fact copy from `/data/camera-facts.json`, reveals camera facts as each type is cleared, updates the progress state, and triggers the finale when all camera types are found. + +- `nav.js` — shared site navigation menu behavior for the "Know more" dropdown. It toggles the menu, handles outside clicks and Escape key dismissal, and closes the menu when focus leaves the nav. + +- `stamp.js` — genealogy stamp layout script. It bends caption text around a circular stamp or emblem by computing arc geometry, keeping the letters aligned with the icon, and re-laying out on resize or when web fonts finish loading. + +## Purpose + +This folder is intentionally compact: it holds only page-specific interactions that are not part of the face-analysis or lab tooling. The code here favors direct DOM work and lightweight behaviors over broad shared state or application architecture. diff --git a/pages-js/index.js b/pages-js/index.js new file mode 100644 index 0000000..9c91921 --- /dev/null +++ b/pages-js/index.js @@ -0,0 +1,233 @@ +/* The homepage camera field. + * + * The arc, and why it ends the way it does: + * + * You tap a camera. Every camera of that type leaves the field and a fact + * about it appears, with the camera itself beside it — LIVE, yellow iris, + * because the fact describes something it is doing right now. Nothing here + * has been defeated; it has been named. + * + * As types are cleared the plume head behind the field becomes more visible. + * It was always there. The cameras were the noise. + * + * When the sixth type goes, the ground turns from soil to cream over two + * seconds and the whirlwind arrives. That is NOT a win screen. The two in the + * plume head are still reading and the closing line says so. What has changed + * is that you can see them. + * + * If you are tempted to make the plume head shrink and vanish here, read + * tutorials/visual-direction.md first: "never claim the wind won." + */ +(function () { + 'use strict'; + + var TYPES = [ + { label: 'Dome camera', key: 'dome' }, + { label: 'Box camera', key: 'cube' }, + { label: 'Smart glasses', key: 'glasses' }, + { label: 'Pill sensor', key: 'pill' }, + { label: 'Street pole unit', key: 'street' }, + { label: 'Bullet camera', key: 'bullet' } + ]; + + var field = document.getElementById('camField'); + var stage = document.getElementById('camStage'); + var halfTop = document.getElementById('camHalfTop'); + var halfBottom = document.getElementById('camHalfBottom'); + var plume = document.getElementById('camPlume'); + var finale = document.getElementById('camFinale'); + var resetBtn = document.getElementById('camReset'); + if (!field || !stage) { return; } + + var FACTS = null; + var cleared = Object.create(null); + var clearedCount = 0; + + /* Optional. Without the catch a 404 makes r.json() reject and the console + fills with an unhandled rejection; the panel falls back to the label. */ + fetch('/data/camera-facts.json') + .then(function (r) { return r.ok ? r.json() : null; }) + .then(function (j) { FACTS = j; }) + .catch(function () { FACTS = null; }); + + /* Icons are cloned from