Files
iptvnator/package.json
T
4grayandClaude Opus 5.5 7abf479de9 fix(ui): one focus ring colour everywhere via the shared mixin (#1882)
* fix(ui): one focus ring colour everywhere via the shared mixin

#1866 gave the app a keyboard focus ring token (`--app-focus-ring`, at
least 3:1 on every surface), but 59 component rings still drew their own
colour: the selection blue under several names (`--app-selection-color`,
`--mat-sys-primary`, `--app-selection-border`, the EPG's `$accent-blue`,
`--embedded-mpv-accent`, `--apd-accent`, the hero's `--accent-color`),
the heading colour, or the overlay's literal text colour. The selection
blue falls to 2.6:1 on the stronger selection tint.

- Every one now includes `focus-ring.focus-ring-declarations`, keeping its
  offset; the projects that newly import `libs/ui/styles` declare
  `ui-styles`.
- The mixin reads the token alone: it is declared on `html` in both
  themes, and the fallback chain cost bytes in every ring.
- `tools/nx/check-focus-ring-colour.mjs` joins `styles:focus-visible:
  validate`: an outline in a focus rule must use the token or, over
  video, the player's `--pc-*` palette. Three deliberate exceptions are
  listed with their reasons, and a stale one is reported. On master it
  reports these 59 rings.
- The keyboard-focus E2E asserts each ring's colour equals the token
  where it is drawn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): search fields and shadow rings take the focus colour too; guard reads them

Local review (Greptile P2): the ring-colour guard read only `outline`, so a
focus indicator drawn as a shadow or a border kept any colour. Search
fields showed focus as a `--mat-sys-primary`/selection border with a 12-16%
halo, the EPG guide's keyboard cell as an inset `$accent-blue` shadow, and
the downloads cards tinted their artwork border with the M3 primary.

- Every one now uses `--app-focus-ring` (the halos and tints keep their
  strength through `color-mix()`); over video the panel's search border
  mixes the overlay's own ring colour.
- The guard reads a focus rule's outline, its unblurred ring or line
  shadows and its border colours. Neutral boundaries (separator and
  widget-border tokens, transparent, currentColor) and blurred lift
  shadows are not indicators. On the previous commit it reports these 21
  declarations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(tooling): check every focus colour on its own; count exceptions only where they excuse a ring

Greptile on #1882 (2×P2):

- The guard joined a declaration's colours and accepted the lot when the
  token appeared anywhere, so `border-color: var(--app-focus-ring) red`
  or a `color-mix()` of the token and red passed. It now splits each
  declaration into plain colours, every `color-mix()` argument included,
  and checks each one: the token, the player palette or a neutral
  boundary. An outline or shadow ring without a colour is drawn in the
  text colour, which only a border may keep.
- An exception counted as used when its value appeared in any
  declaration (the diagnostic's amber is also a text colour), so a stale
  one was never reported. It now counts only where it excuses an
  off-token focus indicator.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(settings): the row a search result reveals takes the app focus ring

Codex on #1882 (P2): choosing a settings search result with Enter focuses
its row by script, and the keypress keeps `:focus-visible`, so the row's
60%-transparent selection outline was a real keyboard focus ring under
3:1, not the passive marker its guard exception described. The row now
includes the shared mixin (keeping its 12px radius), the exception is
gone, and the keyboard-focus E2E reveals a row with Enter and asserts the
app ring on it; with the old rule it fails on the 60% colour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(tooling): accept focus colour tokens by exact name

Greptile (local, P2): the guard matched `--app-focus-ring` and the neutral
boundary tokens by prefix, so `var(--app-focus-ring-other, red)` or
`var(--app-separator-strong)` passed. It now reads the property a `var()`
names and accepts exactly `--app-focus-ring`, a `--pc-*` palette token or
one of the four neutral boundary tokens; their fallbacks are never drawn,
since the tokens are always declared, so they are not checked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(tooling): check the body of a focus mixin, the shared ring included

Greptile (local, P2): a mixin body has no selector and its includes are
not expanded, so the shared `focus-ring-declarations` itself escaped the
colour check; turning it red would change every ring and pass. The
walker now names the mixin a declaration sits in, and the colour guard
treats the body of a mixin whose name mentions focus as a focus rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(tooling): read logical border sides in the focus colour guard

Greptile on #1882 (P2): only `border`, `border-color` and the physical
sides were read, so `border-inline-start: 2px solid red` in a focus rule
passed. The guard now reads every colour-carrying border property: the
shorthand and the physical and logical sides, with or without `-color`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(tooling): an exception excuses its own colour, not the declaration

Greptile (local, P2): an exception matched the whole declaration, so in
the player stylesheet `box-shadow: 0 0 0 2px #ffffff, 0 0 0 4px red`, or
the white mixed with red, passed. Exceptions now apply to each plain
colour, by exact value, like every other check; an exception counts as
used only where it excuses one of a focus indicator's colours.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(tooling): tell a var() or calc() width from the ring colour

Greptile (local, P2): `outline: var(--ring-width) solid var(--app-focus-
ring)` failed the guard, since any non-length token counted as a colour.
Math functions now count as lengths, and a shorthand with one colour slot
takes its literal colour, else an accepted token (the other `var()`s are
widths), else reports every candidate it cannot prove; `border-color`
still checks a colour per side.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(tooling): read a shadow ring whose spread is computed

Codex (local, P2): with `box-shadow: 0 0 0 calc(1px + 1px) red` or a
`var()` spread, only three literal zeros were left as lengths, so the
shadow looked flat and was skipped. A shadow is now skipped only when it
is provably not a ring: a literal non-zero blur in the third place, or
every length a literal zero with no `var()` that could be a spread. The
test with a variable-width token ring now asserts it is read, not skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(tooling): read shadow lengths by type, with the colour first or no blur

Greptile (local, P2): the guard took a shadow's first three tokens as its
lengths, so `0 2px` (a line in the text colour, no blur) was skipped as
blurred and a colour-first lift shadow was read as a ring. Lengths are
now read by type: a colour sits before or after them, never between, and
a missing blur is zero. A `var()` counts as a possible length, so a
shadow is skipped only when the first three possible lengths prove a
blur, or every length and the first four possible ones are zero.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(tooling): a negated focus condition does not make a focus rule

Greptile (local, P2): the colour guard read `:focus-visible` inside
`:not()` as a focus rule, so a hover style such as
`.button:hover:not(:focus-visible) { border-color: red; }` failed. The
selector is now tested without its `:not()` arguments; a focus condition
elsewhere, `:has()` included, still makes a focus rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(tooling): read a width in any CSS length unit

Greptile (local, P2): only px, em and rem were lengths, so `outline: 1pt
solid var(--app-focus-ring)` took `1pt` for the colour and failed. Every
CSS length unit (absolute, font-relative, viewport and container) now
counts as a length.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ui): the open-in-playlist chip rings in the app focus colour

Codex on #1882 (P2): the chip's inline component styles drew its focus
ring in `--app-selection-color`, out of the colour guard's reach (it reads
stylesheets). It was the only inline-style focus ring in the repository;
it now uses `--app-focus-ring` like every other ring.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): move the open-in-playlist chip styles into a stylesheet

Codex on #1882 (P2) suggested this over scanning TS inline styles: the
chip was the only component with a focus ring in inline `styles`, which
the colour guard does not read. Its styles now live in
`open-in-playlist-chip.component.scss` unchanged, the ring through the
shared `focus-ring-declarations` mixin, so the guard covers it (a drifted
colour there is reported).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 10:40:08 +02:00

334 lines
17 KiB
JSON

{
"name": "iptvnator",
"version": "0.25.0",
"engines": {
"node": "^22.22.3 || ^24.15.0"
},
"license": "MIT",
"description": "IPTV player application.",
"homepage": "https://github.com/4gray/iptvnator",
"author": {
"name": "4gray",
"email": "fourgray@proton.me"
},
"keywords": [
"angular",
"electron",
"typescript",
"m3u",
"m3u8",
"player",
"iptv",
"video",
"tv"
],
"scripts": {
"postinstall": "electron-builder install-app-deps",
"build:frontend": "nx build web",
"build:frontend:pwa": "nx build web --configuration=pwa",
"build:backend": "nx build electron-backend --configuration=production",
"serve:frontend": "nx serve web --no-tui",
"serve:frontend:pwa": "nx serve web --configuration=pwa --no-tui",
"serve:backend": "nx serve electron-backend",
"serve:marketing-demo": "nx run-many --target=serve --projects=xtream-mock-server,electron-backend --parallel=2",
"serve:marketing-demo:web": "nx run-many --target=serve --projects=xtream-mock-server,web --parallel=2",
"test:frontend": "nx test web",
"test:backend": "nx test electron-backend",
"test:unit:all": "nx run-many --target=test --all --parallel=3",
"test:unit:ci": "nx run-many --target=test --all --parallel=3 --output-style=static",
"deps:nx:test": "node --test tools/dependencies/check-nx-version-sync.test.mjs",
"deps:nx:check": "node tools/dependencies/check-nx-version-sync.mjs",
"deps:nx:validate": "pnpm run deps:nx:test && pnpm run deps:nx:check",
"deps:vite:test": "node --test tools/dependencies/vite-transform-filter.test.mjs",
"deps:electron-builder:test": "node --test tools/dependencies/app-builder-lib-keychain-password.test.mjs",
"styles:font-weights:test": "node --test tools/nx/check-font-weights.test.mjs",
"styles:font-weights:check": "node tools/nx/check-font-weights.mjs",
"styles:font-weights:validate": "pnpm run styles:font-weights:test && pnpm run styles:font-weights:check",
"styles:inputs:test": "node --test tools/nx/check-stylesheet-inputs.test.mjs",
"styles:inputs:check": "node tools/nx/check-stylesheet-inputs.mjs",
"styles:inputs:validate": "pnpm run styles:inputs:test && pnpm run styles:inputs:check",
"styles:material-tokens:test": "node --test tools/nx/check-material-token-overrides.test.mjs",
"styles:material-tokens:check": "node tools/nx/check-material-token-overrides.mjs",
"styles:material-tokens:validate": "pnpm run styles:material-tokens:test && pnpm run styles:material-tokens:check",
"styles:focus-visible:test": "node --test tools/nx/check-focus-visible.test.mjs tools/nx/check-focus-ring-colour.test.mjs",
"styles:focus-visible:check": "node tools/nx/check-focus-visible.mjs && node tools/nx/check-focus-ring-colour.mjs",
"styles:focus-visible:validate": "pnpm run styles:focus-visible:test && pnpm run styles:focus-visible:check",
"styles:icon-ligatures:test": "node --test tools/nx/check-icon-ligatures.test.mjs",
"styles:icon-ligatures:check": "node tools/nx/check-icon-ligatures.mjs",
"styles:icon-ligatures:validate": "pnpm run styles:icon-ligatures:test && pnpm run styles:icon-ligatures:check",
"a11y:icon-buttons:test": "node --test tools/nx/check-icon-button-names.test.mjs",
"a11y:icon-buttons:check": "node tools/nx/check-icon-button-names.mjs",
"a11y:icon-buttons:validate": "pnpm run a11y:icon-buttons:test && pnpm run a11y:icon-buttons:check",
"e2e:task-graphs:test": "node --test tools/nx/check-e2e-task-graphs.test.mjs",
"e2e:task-graphs:check": "node tools/nx/check-e2e-task-graphs.mjs",
"e2e:task-graphs:validate": "pnpm run e2e:task-graphs:test && pnpm run e2e:task-graphs:check",
"coverage:tools:test": "node --test tools/coverage/coverage-integrity.test.mjs tools/coverage/e2e-shard-reports.test.mjs tools/coverage/coverage-run-pool.test.mjs tools/coverage/unit-coverage-scope.test.mjs",
"coverage:unit:ci": "node tools/coverage/run-tier-a-coverage.mjs",
"coverage:merge": "node tools/coverage/merge-coverage.mjs",
"coverage:health": "node tools/coverage/coverage-health.mjs",
"coverage:policy:check": "node tools/coverage/check-coverage-policy.mjs",
"coverage:ci": "pnpm run coverage:tools:test && pnpm run coverage:policy:check && pnpm run coverage:unit:ci && pnpm run coverage:merge && node tools/coverage/coverage-health.mjs --require-report",
"coverage:e2e:summary": "node tools/coverage/e2e-semantic-summary.mjs",
"coverage:e2e:v8:web": "node tools/coverage/e2e-v8-web.mjs",
"typecheck:web": "tsc -p apps/web/tsconfig.app.json --noEmit",
"typecheck:backend": "tsc -p apps/electron-backend/tsconfig.app.json --noEmit",
"typecheck:ci": "pnpm run typecheck:web && pnpm run typecheck:backend",
"typecheck:spec": "node tools/typecheck/spec-typecheck.mjs",
"typecheck:spec:test": "node --test tools/typecheck/spec-typecheck.test.mjs",
"verify:package-layout": "node tools/packaging/verify-electron-package-layout.mjs",
"embedded-mpv:build-native:homebrew": "IPTVNATOR_EMBEDDED_MPV_ALLOW_HOMEBREW=1 nx run electron-backend:build-embedded-mpv",
"embedded-mpv:build-runtime": "node tools/embedded-mpv/build-macos-runtime.mjs",
"embedded-mpv:build-runtime:linux": "node tools/embedded-mpv/build-linux-runtime.mjs",
"embedded-mpv:stage-runtime": "node tools/embedded-mpv/stage-runtime.mjs",
"embedded-mpv:stage-runtime:macos": "node tools/embedded-mpv/stage-macos-runtime.mjs",
"embedded-mpv:stage-runtime:windows-archive": "node tools/embedded-mpv/stage-windows-runtime-archive.mjs",
"embedded-mpv:windows-runtime-pin:check": "node tools/embedded-mpv/windows-runtime-pin.mjs",
"embedded-mpv:windows-runtime-pin:refresh": "node tools/embedded-mpv/update-windows-runtime-pin.mjs",
"serve:backend:embedded-mpv": "pnpm embedded-mpv:build-native:homebrew && IPTVNATOR_EMBEDDED_MPV_ALLOW_HOMEBREW=1 IPTVNATOR_ENABLE_EMBEDDED_MPV_EXPERIMENT=1 pnpm serve:backend",
"package:app": "nx run electron-backend:make --prepackageOnly",
"make:app": "nx run electron-backend:make",
"smoke:packaged": "node tools/testing/launch-packaged-electron.mjs",
"serve:website": "nx serve website",
"build:website": "nx build website",
"i18n:check": "node tools/i18n/check-drift.mjs && node tools/i18n/check-usage.mjs",
"i18n:test": "node --test tools/i18n/check-drift.test.mjs tools/i18n/check-usage.test.mjs tools/i18n/check-duplicates.test.mjs",
"i18n:usage": "node tools/i18n/check-usage.mjs",
"i18n:duplicates": "node tools/i18n/check-duplicates.mjs",
"i18n:validate": "pnpm run i18n:test && pnpm run i18n:check",
"i18n:baseline:update": "node tools/i18n/check-drift.mjs --update-baseline",
"perf:initial-bytes": "node tools/performance/measure-initial-bytes.mjs",
"perf:initial-bytes:check": "node tools/performance/measure-initial-bytes.mjs --summary dist/performance/initial-bytes.summary.json && node tools/performance/check-journey-ratchet.mjs --summary dist/performance/initial-bytes.summary.json --only launch/renderer.initialBytes",
"perf:journeys": "nx run electron-backend-e2e:journeys",
"perf:compositing": "nx run electron-backend-e2e:compositing-report",
"perf:ratchet:check": "node tools/performance/check-journey-ratchet.mjs --summary dist/performance/journey-summary.json",
"perf:tools:test": "node --test tools/performance/measure-initial-bytes.test.mjs tools/performance/check-journey-ratchet.test.mjs tools/performance/check-baseline-direction.test.mjs tools/performance/tighten-baselines.test.mjs",
"agents:validate": "node tools/skills/validate-agent-guidance.mjs",
"skills:validate": "node tools/skills/validate-repository-skills.mjs",
"release:artwork:dry-run": "tsx --tsconfig tsconfig.base.json tools/release/generate-marketing-artwork.ts --dry-run",
"release:artwork:manifest": "tsx --tsconfig tsconfig.base.json tools/release/generate-marketing-artwork.ts --manifest",
"release:artwork:generate": "tsx --tsconfig tsconfig.base.json tools/release/generate-marketing-artwork.ts --generate",
"release:artwork:validate": "tsx --tsconfig tsconfig.base.json tools/release/generate-marketing-artwork.ts --validate",
"release:notes:validate": "node tools/release/build-release-notes.mjs --validate",
"release:notes:github": "node tools/release/build-release-notes.mjs --format github",
"release:notes:changelog": "node tools/release/build-release-notes.mjs --format changelog",
"release:notes:blog": "node tools/release/build-release-notes.mjs --format blog",
"release:notes:telegram": "node tools/release/build-release-notes.mjs --format telegram",
"release:notes:reddit": "node tools/release/build-release-notes.mjs --format reddit",
"release:verify:draft": "node tools/release/verify-draft-release.mjs",
"release:cards:dry-run": "node tools/release/generate-highlight-cards.mjs --dry-run",
"release:cards:generate": "node tools/release/generate-highlight-cards.mjs --generate",
"release:screenshots": "tsx tools/release/capture-release-screenshots.ts",
"lint": "nx run-many --target=lint --all",
"build": "nx build electron-backend"
},
"private": true,
"packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319",
"dependencies": {
"@angular/animations": "22.1.6",
"@angular/cdk": "22.1.6",
"@angular/common": "22.1.6",
"@angular/compiler": "22.1.6",
"@angular/core": "22.1.6",
"@angular/forms": "22.1.6",
"@angular/material": "22.1.6",
"@angular/platform-browser": "22.1.6",
"@angular/platform-browser-dynamic": "22.1.6",
"@angular/router": "22.1.6",
"@ngrx/effects": "22.0.1",
"@ngrx/entity": "22.0.1",
"@ngrx/router-store": "22.0.1",
"@ngrx/signals": "22.0.1",
"@ngrx/store": "22.0.1",
"@ngrx/store-devtools": "22.0.1",
"@ngx-pwa/local-storage": "22.0.0",
"@yangkghjh/videojs-aspect-ratio-panel": "0.0.1",
"angularx-qrcode": "22.0.1",
"artplayer": "5.4.0",
"axios": "1.20.0",
"better-sqlite3": "13.0.3",
"date-fns": "4.4.0",
"drizzle-orm": "0.45.2",
"electron-conf": "1.3.0",
"electron-updater": "6.8.9",
"epg-parser": "^0.5.0",
"hls.js": "1.7.1",
"iptv-playlist-parser": "github:4gray/iptv-playlist-parser#v0.15.2-iptvnator.2",
"marked": "18.0.11",
"mpegts.js": "1.8.2",
"ms": "2.1.3",
"ngx-indexed-db": "22.0.0",
"ngx-skeleton-loader": "11.3.0",
"proxy-from-env": "2.1.0",
"rxjs": "7.8.2",
"saxes": "6.0.0",
"shaka-player": "5.2.12",
"shell-path": "3.1.0",
"video.js": "8.24.0",
"videojs-contrib-quality-levels": "4.1.0",
"videojs-quality-selector-hls": "1.1.1",
"zone.js": "0.16.3"
},
"devDependencies": {
"@angular-devkit/core": "22.1.8",
"@angular-devkit/schematics": "22.1.8",
"@angular-eslint/builder": "22.5.0",
"@angular-eslint/eslint-plugin": "22.5.0",
"@angular-eslint/eslint-plugin-template": "22.5.0",
"@angular-eslint/schematics": "22.5.0",
"@angular-eslint/template-parser": "22.5.0",
"@angular/build": "22.1.8",
"@angular/cli": "22.1.8",
"@angular/common": "22.1.6",
"@angular/compiler": "22.1.6",
"@angular/compiler-cli": "22.1.6",
"@angular/core": "22.1.6",
"@angular/forms": "22.1.6",
"@angular/language-service": "22.1.6",
"@angular/platform-browser": "22.1.6",
"@angular/platform-browser-dynamic": "22.1.6",
"@angular/router": "22.1.6",
"@angular/service-worker": "22.1.6",
"@astrojs/mdx": "7.0.7",
"@astrojs/sitemap": "3.7.4",
"@babel/core": "7.29.7",
"@electron/asar": "3.4.1",
"@eslint/eslintrc": "3.3.7",
"@eslint/js": "^9.38.0",
"@faker-js/faker": "10.6.0",
"@fontsource-variable/bricolage-grotesque": "5.3.0",
"@fontsource/dm-sans": "5.3.0",
"@fontsource/ibm-plex-mono": "5.3.0",
"@fontsource/jetbrains-mono": "5.3.0",
"@fontsource/roboto": "5.3.0",
"@ngrx/eslint-plugin": "22.0.1",
"@ngx-translate/core": "16.0.4",
"@ngx-translate/http-loader": "16.0.1",
"@nx/angular": "23.2.1",
"@nx/devkit": "23.2.1",
"@nx/esbuild": "23.2.1",
"@nx/eslint": "23.2.1",
"@nx/eslint-plugin": "23.2.1",
"@nx/jest": "23.2.1",
"@nx/js": "23.2.1",
"@nx/playwright": "23.2.1",
"@nx/web": "23.2.1",
"@nx/workspace": "23.2.1",
"@playwright/test": "^1.62.1",
"@schematics/angular": "22.1.8",
"@swc-node/register": "1.12.1",
"@swc/core": "1.16.1",
"@swc/helpers": "0.5.23",
"@tailwindcss/typography": "0.5.20",
"@types/better-sqlite3": "^9.6.0",
"@types/cors": "2.8.19",
"@types/express": "5.0.6",
"@types/jest": "^30.0.0",
"@types/jsdom": "21.1.7",
"@types/mocha": "9.0.0",
"@types/node": "20.19.9",
"@types/proxy-from-env": "1.0.4",
"@types/video.js": "7.3.58",
"@typescript-eslint/eslint-plugin": "^8.69.0",
"@typescript-eslint/parser": "^8.69.0",
"@typescript-eslint/utils": "^8.69.0",
"angular-eslint": "22.5.0",
"astro": "7.2.10",
"autoprefixer": "10.5.4",
"axe-core": "4.13.0",
"cookie": "2.0.1",
"cors": "2.8.6",
"drizzle-kit": "0.31.10",
"electron": "^43.3.0",
"electron-builder": "^26.15.7",
"electron-playwright-helpers": "1.8.2",
"esbuild": "0.28.2",
"eslint": "^9.8.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-import": "2.32.0",
"eslint-plugin-playwright": "^1.6.2",
"express": "5.2.1",
"github-slugger": "2.0.0",
"globals": "15.9.0",
"html-escaper": "3.0.3",
"istanbul-lib-coverage": "3.2.2",
"istanbul-lib-report": "3.0.1",
"istanbul-reports": "3.2.0",
"jest": "^30.5.1",
"jest-environment-jsdom": "^30.5.1",
"jest-environment-node": "^30.5.1",
"jest-preset-angular": "17.0.0",
"jest-util": "^30.5.1",
"jsdom": "26.1.0",
"jsonc-eslint-parser": "^2.1.0",
"material-design-icons-iconfont": "6.7.0",
"mrmime": "2.0.1",
"ng-mocks": "14.17.6",
"node-gyp": "12.4.0",
"nx": "23.2.1",
"nx-electron": "22.0.0",
"parse-srcset": "1.0.2",
"parse5": "8.0.1",
"prettier": "^3.9.6",
"sharp": "0.35.5",
"tailwindcss": "^3.4.19",
"ts-jest": "^29.4.12",
"ts-node": "10.9.2",
"tslib": "^2.8.1",
"tsx": "4.23.13",
"typescript": "6.0.3",
"typescript-eslint": "^8.69.0",
"yaml": "2.9.0",
"zod": "4.5.4"
},
"pnpm": {
"overrides": {
"@esbuild-kit/core-utils>esbuild": "0.25.12",
"@hono/node-server@1.19.9": "1.19.17",
"@humanfs/node@0.16.7": "0.16.8",
"@xmldom/xmldom@0.8.11": "0.8.15",
"ajv@6.12.6": "6.14.0",
"ajv@8.17.1": "8.20.0",
"brace-expansion@1.1.12": "1.1.18",
"browserslist@4.28.1": "4.28.8",
"defu@6.1.4": "6.1.6",
"devalue@5.6.2": "5.6.4",
"express-rate-limit@8.2.1": "8.3.0",
"fast-uri@3.1.0": "3.1.6",
"flatted@3.3.3": "3.4.2",
"follow-redirects@1.15.11": "1.16.0",
"form-data@4.0.5": "4.0.6",
"h3@1.15.5": "1.15.10",
"hono@4.12.0": "4.13.5",
"immutable@5.1.4": "5.1.9",
"ip-address@10.1.0": "10.5.0",
"js-yaml@4.1.1": "4.3.2",
"js-yaml@4.3.0": "4.3.2",
"jsdom>ws": "8.21.3",
"lodash-es@4.17.22": "4.18.1",
"minimatch@3.1.2": "3.1.5",
"node-forge@1.3.3": "1.4.0",
"path-to-regexp@0.1.12": "0.1.13",
"picomatch@2.3.1": "2.3.2",
"picomatch@4.0.3": "4.0.7",
"postcss-selector-parser@6.1.2": "6.1.4",
"postcss@8.5.6": "8.5.26",
"qs@6.14.1": "6.15.3",
"rollup@4.52.3": "4.59.0",
"serialize-javascript@6.0.2": "7.1.0",
"smol-toml@1.6.0": "1.7.1",
"smol-toml@1.6.1": "1.7.1",
"svgo@3.3.2": "3.3.3",
"svgo@4.0.0": "4.1.0",
"svgo@4.0.2": "4.1.0",
"undici@7.28.0": "7.29.0",
"uuid@8.3.2": "11.1.1",
"yaml@1.10.2": "1.10.3"
},
"patchedDependencies": {
"nx-electron@22.0.0": "patches/nx-electron@22.0.0.patch",
"app-builder-lib@26.15.7": "patches/app-builder-lib@26.15.7.patch",
"vite@8.1.5": "patches/vite@8.1.5.patch"
}
}
}