quiver-cli 1.3.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +197 -239
- package/dist/cli.js +3163 -2040
- package/package.json +10 -11
- package/template/.agents/AGENTS.md +0 -26
- package/template/.agents/commands/cp.md +0 -108
- package/template/.agents/commands/next-setup.md +0 -1064
- package/template/.agents/commands/review.md +0 -68
- package/template/.agents/commands/terraform-readme.md +0 -38
- package/template/.agents/config.json +0 -80
- package/template/.agents/plugins/opencode/rtk.ts +0 -34
- package/template/.agents/skills/agent-browser/SKILL.md +0 -52
- package/template/.agents/skills/apps/skybridge/SKILL.md +0 -52
- package/template/.agents/skills/code/cleanup/SKILL.md +0 -26
- package/template/.agents/skills/code/improve/SKILL.md +0 -122
- package/template/.agents/skills/code/improve/references/audit-playbook.md +0 -130
- package/template/.agents/skills/code/improve/references/closing-the-loop.md +0 -96
- package/template/.agents/skills/code/improve/references/plan-template.md +0 -197
- package/template/.agents/skills/code/vercel-react-best-practices/AGENTS.md +0 -3810
- package/template/.agents/skills/code/vercel-react-best-practices/README.md +0 -123
- package/template/.agents/skills/code/vercel-react-best-practices/SKILL.md +0 -149
- package/template/.agents/skills/code/vercel-react-best-practices/metadata.json +0 -15
- package/template/.agents/skills/code/vercel-react-best-practices/rules/_sections.md +0 -46
- package/template/.agents/skills/code/vercel-react-best-practices/rules/_template.md +0 -28
- package/template/.agents/skills/code/vercel-react-best-practices/rules/advanced-effect-event-deps.md +0 -56
- package/template/.agents/skills/code/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
- package/template/.agents/skills/code/vercel-react-best-practices/rules/advanced-init-once.md +0 -42
- package/template/.agents/skills/code/vercel-react-best-practices/rules/advanced-use-latest.md +0 -39
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-api-routes.md +0 -38
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-cheap-condition-before-await.md +0 -37
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-defer-await.md +0 -82
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-dependencies.md +0 -51
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-parallel.md +0 -28
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-analyzable-paths.md +0 -63
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -60
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-preload.md +0 -50
- package/template/.agents/skills/code/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
- package/template/.agents/skills/code/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
- package/template/.agents/skills/code/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
- package/template/.agents/skills/code/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -107
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-early-exit.md +0 -50
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-flatmap-filter.md +0 -60
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-index-maps.md +0 -37
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-request-idle-callback.md +0 -105
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-activity.md +0 -26
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +0 -30
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-resource-hints.md +0 -85
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-script-defer-async.md +0 -68
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-usetransition-loading.md +0 -75
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +0 -40
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +0 -38
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-memo.md +0 -44
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +0 -45
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-no-inline-components.md +0 -82
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -35
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +0 -64
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-use-deferred-value.md +0 -59
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +0 -73
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-auth-actions.md +0 -96
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-cache-react.md +0 -76
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-dedup-props.md +0 -65
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-hoist-static-io.md +0 -149
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-no-shared-module-state.md +0 -50
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-parallel-nested-fetching.md +0 -34
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-serialization.md +0 -38
- package/template/.agents/skills/data/prisma-cli/SKILL.md +0 -265
- package/template/.agents/skills/data/prisma-cli/references/agent-safety.md +0 -27
- package/template/.agents/skills/data/prisma-cli/references/complete.md +0 -22
- package/template/.agents/skills/data/prisma-cli/references/db-execute.md +0 -78
- package/template/.agents/skills/data/prisma-cli/references/db-pull.md +0 -185
- package/template/.agents/skills/data/prisma-cli/references/db-push.md +0 -150
- package/template/.agents/skills/data/prisma-cli/references/db-seed.md +0 -188
- package/template/.agents/skills/data/prisma-cli/references/debug.md +0 -46
- package/template/.agents/skills/data/prisma-cli/references/dev.md +0 -157
- package/template/.agents/skills/data/prisma-cli/references/format.md +0 -48
- package/template/.agents/skills/data/prisma-cli/references/generate.md +0 -173
- package/template/.agents/skills/data/prisma-cli/references/init.md +0 -139
- package/template/.agents/skills/data/prisma-cli/references/mcp.md +0 -39
- package/template/.agents/skills/data/prisma-cli/references/migrate-deploy.md +0 -127
- package/template/.agents/skills/data/prisma-cli/references/migrate-dev.md +0 -145
- package/template/.agents/skills/data/prisma-cli/references/migrate-diff.md +0 -89
- package/template/.agents/skills/data/prisma-cli/references/migrate-reset.md +0 -80
- package/template/.agents/skills/data/prisma-cli/references/migrate-resolve.md +0 -57
- package/template/.agents/skills/data/prisma-cli/references/migrate-status.md +0 -65
- package/template/.agents/skills/data/prisma-cli/references/studio.md +0 -137
- package/template/.agents/skills/data/prisma-cli/references/validate.md +0 -53
- package/template/.agents/skills/data/prisma-client-api/SKILL.md +0 -216
- package/template/.agents/skills/data/prisma-client-api/references/client-methods.md +0 -223
- package/template/.agents/skills/data/prisma-client-api/references/constructor.md +0 -221
- package/template/.agents/skills/data/prisma-client-api/references/filters.md +0 -256
- package/template/.agents/skills/data/prisma-client-api/references/model-queries.md +0 -281
- package/template/.agents/skills/data/prisma-client-api/references/query-options.md +0 -276
- package/template/.agents/skills/data/prisma-client-api/references/raw-queries.md +0 -198
- package/template/.agents/skills/data/prisma-client-api/references/relations.md +0 -308
- package/template/.agents/skills/data/prisma-client-api/references/transactions.md +0 -184
- package/template/.agents/skills/design/impeccable/SKILL.md +0 -84
- package/template/.agents/skills/design/impeccable/reference/adapt.md +0 -312
- package/template/.agents/skills/design/impeccable/reference/adapt.native.md +0 -58
- package/template/.agents/skills/design/impeccable/reference/android.md +0 -46
- package/template/.agents/skills/design/impeccable/reference/animate.md +0 -89
- package/template/.agents/skills/design/impeccable/reference/audit.md +0 -136
- package/template/.agents/skills/design/impeccable/reference/audit.native.md +0 -139
- package/template/.agents/skills/design/impeccable/reference/bolder.md +0 -33
- package/template/.agents/skills/design/impeccable/reference/clarify.md +0 -94
- package/template/.agents/skills/design/impeccable/reference/colorize.md +0 -86
- package/template/.agents/skills/design/impeccable/reference/craft-floor.md +0 -44
- package/template/.agents/skills/design/impeccable/reference/craft.md +0 -5
- package/template/.agents/skills/design/impeccable/reference/critique.md +0 -806
- package/template/.agents/skills/design/impeccable/reference/degraded/asset-producer.md +0 -37
- package/template/.agents/skills/design/impeccable/reference/degraded/documenter.md +0 -24
- package/template/.agents/skills/design/impeccable/reference/degraded/finish-reviewer.md +0 -38
- package/template/.agents/skills/design/impeccable/reference/degraded/manual-edit-applier.md +0 -92
- package/template/.agents/skills/design/impeccable/reference/delight.md +0 -70
- package/template/.agents/skills/design/impeccable/reference/distill.md +0 -111
- package/template/.agents/skills/design/impeccable/reference/doctor.md +0 -54
- package/template/.agents/skills/design/impeccable/reference/document.md +0 -416
- package/template/.agents/skills/design/impeccable/reference/extract.md +0 -69
- package/template/.agents/skills/design/impeccable/reference/harden.md +0 -336
- package/template/.agents/skills/design/impeccable/reference/hooks.md +0 -111
- package/template/.agents/skills/design/impeccable/reference/init.md +0 -131
- package/template/.agents/skills/design/impeccable/reference/ios.md +0 -51
- package/template/.agents/skills/design/impeccable/reference/layout.md +0 -84
- package/template/.agents/skills/design/impeccable/reference/live-setup.md +0 -102
- package/template/.agents/skills/design/impeccable/reference/live.md +0 -323
- package/template/.agents/skills/design/impeccable/reference/new-work.md +0 -145
- package/template/.agents/skills/design/impeccable/reference/onboard.md +0 -234
- package/template/.agents/skills/design/impeccable/reference/operate.md +0 -61
- package/template/.agents/skills/design/impeccable/reference/optimize.md +0 -258
- package/template/.agents/skills/design/impeccable/reference/overdrive.md +0 -127
- package/template/.agents/skills/design/impeccable/reference/polish.md +0 -105
- package/template/.agents/skills/design/impeccable/reference/quieter.md +0 -99
- package/template/.agents/skills/design/impeccable/reference/routing.md +0 -18
- package/template/.agents/skills/design/impeccable/reference/shape.md +0 -59
- package/template/.agents/skills/design/impeccable/reference/typeset.md +0 -80
- package/template/.agents/skills/design/impeccable/reference/visualize.md +0 -46
- package/template/.agents/skills/design/impeccable/scripts/build-phase.mjs +0 -1022
- package/template/.agents/skills/design/impeccable/scripts/command-metadata.json +0 -94
- package/template/.agents/skills/design/impeccable/scripts/comp-diff.mjs +0 -391
- package/template/.agents/skills/design/impeccable/scripts/comp-spec.mjs +0 -513
- package/template/.agents/skills/design/impeccable/scripts/concept-seed.mjs +0 -814
- package/template/.agents/skills/design/impeccable/scripts/context-signals.mjs +0 -325
- package/template/.agents/skills/design/impeccable/scripts/context.mjs +0 -1565
- package/template/.agents/skills/design/impeccable/scripts/critique-storage.mjs +0 -473
- package/template/.agents/skills/design/impeccable/scripts/data/font-index-failures.json +0 -121
- package/template/.agents/skills/design/impeccable/scripts/data/font-index.json +0 -1
- package/template/.agents/skills/design/impeccable/scripts/detect-csp.mjs +0 -198
- package/template/.agents/skills/design/impeccable/scripts/detect.mjs +0 -30
- package/template/.agents/skills/design/impeccable/scripts/detector/browser/injected/index.mjs +0 -2204
- package/template/.agents/skills/design/impeccable/scripts/detector/cli/main.mjs +0 -432
- package/template/.agents/skills/design/impeccable/scripts/detector/design-system.mjs +0 -1311
- package/template/.agents/skills/design/impeccable/scripts/detector/detect-antipatterns-browser.js +0 -9043
- package/template/.agents/skills/design/impeccable/scripts/detector/detect-antipatterns.mjs +0 -51
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/browser/detect-url.mjs +0 -434
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/regex/detect-text.mjs +0 -1319
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +0 -1241
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/detect-html.mjs +0 -288
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs +0 -189
- package/template/.agents/skills/design/impeccable/scripts/detector/findings.mjs +0 -18
- package/template/.agents/skills/design/impeccable/scripts/detector/node/file-system.mjs +0 -213
- package/template/.agents/skills/design/impeccable/scripts/detector/profile/profiler.mjs +0 -166
- package/template/.agents/skills/design/impeccable/scripts/detector/registry/antipatterns.mjs +0 -635
- package/template/.agents/skills/design/impeccable/scripts/detector/rules/checks.mjs +0 -5681
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/color.mjs +0 -596
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/constants.mjs +0 -127
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/fonts.mjs +0 -30
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/inline-ignores.mjs +0 -148
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/page.mjs +0 -7
- package/template/.agents/skills/design/impeccable/scripts/doctor.mjs +0 -329
- package/template/.agents/skills/design/impeccable/scripts/embed-prompt.mjs +0 -166
- package/template/.agents/skills/design/impeccable/scripts/font-match.mjs +0 -457
- package/template/.agents/skills/design/impeccable/scripts/generate-image.mjs +0 -447
- package/template/.agents/skills/design/impeccable/scripts/hook-admin.mjs +0 -819
- package/template/.agents/skills/design/impeccable/scripts/hook-before-edit.mjs +0 -538
- package/template/.agents/skills/design/impeccable/scripts/hook-lib.mjs +0 -2490
- package/template/.agents/skills/design/impeccable/scripts/hook.mjs +0 -79
- package/template/.agents/skills/design/impeccable/scripts/lib/artifact-schema.mjs +0 -93
- package/template/.agents/skills/design/impeccable/scripts/lib/composition-catalog.mjs +0 -200
- package/template/.agents/skills/design/impeccable/scripts/lib/concept-catalog.mjs +0 -396
- package/template/.agents/skills/design/impeccable/scripts/lib/design-parser.mjs +0 -880
- package/template/.agents/skills/design/impeccable/scripts/lib/font-fingerprint.mjs +0 -564
- package/template/.agents/skills/design/impeccable/scripts/lib/font-index.mjs +0 -130
- package/template/.agents/skills/design/impeccable/scripts/lib/hero-checks.mjs +0 -246
- package/template/.agents/skills/design/impeccable/scripts/lib/image-metrics.mjs +0 -306
- package/template/.agents/skills/design/impeccable/scripts/lib/impeccable-config.mjs +0 -640
- package/template/.agents/skills/design/impeccable/scripts/lib/impeccable-paths.mjs +0 -137
- package/template/.agents/skills/design/impeccable/scripts/lib/is-generated.mjs +0 -72
- package/template/.agents/skills/design/impeccable/scripts/lib/live-path-globs.mjs +0 -37
- package/template/.agents/skills/design/impeccable/scripts/lib/open-system-browser.mjs +0 -26
- package/template/.agents/skills/design/impeccable/scripts/lib/png.mjs +0 -281
- package/template/.agents/skills/design/impeccable/scripts/lib/provider.mjs +0 -5
- package/template/.agents/skills/design/impeccable/scripts/lib/raster.mjs +0 -194
- package/template/.agents/skills/design/impeccable/scripts/lib/roll-selection.mjs +0 -369
- package/template/.agents/skills/design/impeccable/scripts/lib/staleness-deep.mjs +0 -485
- package/template/.agents/skills/design/impeccable/scripts/lib/staleness-notice.mjs +0 -169
- package/template/.agents/skills/design/impeccable/scripts/lib/staleness.mjs +0 -533
- package/template/.agents/skills/design/impeccable/scripts/lib/surface-briefs.mjs +0 -149
- package/template/.agents/skills/design/impeccable/scripts/lib/target-args.mjs +0 -42
- package/template/.agents/skills/design/impeccable/scripts/lib/target-slug.mjs +0 -33
- package/template/.agents/skills/design/impeccable/scripts/lib/template-extensions.mjs +0 -146
- package/template/.agents/skills/design/impeccable/scripts/live/accept-css.mjs +0 -617
- package/template/.agents/skills/design/impeccable/scripts/live/accept-verify.mjs +0 -60
- package/template/.agents/skills/design/impeccable/scripts/live/browser-script-parts.mjs +0 -84
- package/template/.agents/skills/design/impeccable/scripts/live/completion.mjs +0 -28
- package/template/.agents/skills/design/impeccable/scripts/live/event-validation.mjs +0 -199
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/astro.mjs +0 -47
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/detect-utils.mjs +0 -73
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/index.mjs +0 -143
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/journal.mjs +0 -197
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/nextjs.mjs +0 -49
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/nuxt.mjs +0 -161
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/script-src.mjs +0 -17
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/static-html.mjs +0 -26
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/sveltekit.mjs +0 -71
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/tag-strategy.mjs +0 -247
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/tanstack-start.mjs +0 -70
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/vite-generic.mjs +0 -42
- package/template/.agents/skills/design/impeccable/scripts/live/generation-preflight.mjs +0 -149
- package/template/.agents/skills/design/impeccable/scripts/live/insert-ui.mjs +0 -458
- package/template/.agents/skills/design/impeccable/scripts/live/instructions.mjs +0 -142
- package/template/.agents/skills/design/impeccable/scripts/live/manual-apply.mjs +0 -939
- package/template/.agents/skills/design/impeccable/scripts/live/manual-edit-routes.mjs +0 -357
- package/template/.agents/skills/design/impeccable/scripts/live/manual-edits-buffer.mjs +0 -152
- package/template/.agents/skills/design/impeccable/scripts/live/poll-lanes.mjs +0 -14
- package/template/.agents/skills/design/impeccable/scripts/live/project-ignores.mjs +0 -139
- package/template/.agents/skills/design/impeccable/scripts/live/roots.mjs +0 -508
- package/template/.agents/skills/design/impeccable/scripts/live/session-store.mjs +0 -563
- package/template/.agents/skills/design/impeccable/scripts/live/source-lock.mjs +0 -105
- package/template/.agents/skills/design/impeccable/scripts/live/source-search.mjs +0 -105
- package/template/.agents/skills/design/impeccable/scripts/live/svelte-ast.mjs +0 -969
- package/template/.agents/skills/design/impeccable/scripts/live/svelte-component.mjs +0 -1366
- package/template/.agents/skills/design/impeccable/scripts/live/sveltekit-adapter.mjs +0 -304
- package/template/.agents/skills/design/impeccable/scripts/live/tanstack-adapter.mjs +0 -259
- package/template/.agents/skills/design/impeccable/scripts/live/ui-surfaces.mjs +0 -75
- package/template/.agents/skills/design/impeccable/scripts/live/vocabulary.mjs +0 -171
- package/template/.agents/skills/design/impeccable/scripts/live-accept.mjs +0 -938
- package/template/.agents/skills/design/impeccable/scripts/live-browser-dom.js +0 -146
- package/template/.agents/skills/design/impeccable/scripts/live-browser-ignores.js +0 -242
- package/template/.agents/skills/design/impeccable/scripts/live-browser-session.js +0 -123
- package/template/.agents/skills/design/impeccable/scripts/live-browser.js +0 -12551
- package/template/.agents/skills/design/impeccable/scripts/live-commit-manual-edits.mjs +0 -1200
- package/template/.agents/skills/design/impeccable/scripts/live-complete.mjs +0 -107
- package/template/.agents/skills/design/impeccable/scripts/live-copy-edit-agent.mjs +0 -800
- package/template/.agents/skills/design/impeccable/scripts/live-discard-manual-edits.mjs +0 -51
- package/template/.agents/skills/design/impeccable/scripts/live-inject.mjs +0 -463
- package/template/.agents/skills/design/impeccable/scripts/live-insert.mjs +0 -292
- package/template/.agents/skills/design/impeccable/scripts/live-manual-edit-evidence.mjs +0 -368
- package/template/.agents/skills/design/impeccable/scripts/live-poll.mjs +0 -430
- package/template/.agents/skills/design/impeccable/scripts/live-resume.mjs +0 -123
- package/template/.agents/skills/design/impeccable/scripts/live-server.mjs +0 -1698
- package/template/.agents/skills/design/impeccable/scripts/live-status.mjs +0 -71
- package/template/.agents/skills/design/impeccable/scripts/live-target.mjs +0 -30
- package/template/.agents/skills/design/impeccable/scripts/live-wrap.mjs +0 -927
- package/template/.agents/skills/design/impeccable/scripts/live.mjs +0 -334
- package/template/.agents/skills/design/impeccable/scripts/modern-screenshot.umd.js +0 -14
- package/template/.agents/skills/design/impeccable/scripts/palette.mjs +0 -628
- package/template/.agents/skills/design/impeccable/scripts/pin.mjs +0 -224
- package/template/.agents/skills/design/impeccable/scripts/serve-question.mjs +0 -1783
- package/template/.agents/skills/design/impeccable/scripts/surface-brief.mjs +0 -74
- package/template/.agents/skills/design/shadcn/SKILL.md +0 -277
- package/template/.agents/skills/design/shadcn/agents/openai.yml +0 -5
- package/template/.agents/skills/design/shadcn/assets/shadcn-small.png +0 -0
- package/template/.agents/skills/design/shadcn/assets/shadcn.png +0 -0
- package/template/.agents/skills/design/shadcn/cli.md +0 -290
- package/template/.agents/skills/design/shadcn/customization.md +0 -209
- package/template/.agents/skills/design/shadcn/evals/evals.json +0 -77
- package/template/.agents/skills/design/shadcn/mcp.md +0 -105
- package/template/.agents/skills/design/shadcn/registry.md +0 -277
- package/template/.agents/skills/design/shadcn/rules/base-vs-radix.md +0 -306
- package/template/.agents/skills/design/shadcn/rules/chat.md +0 -250
- package/template/.agents/skills/design/shadcn/rules/composition.md +0 -213
- package/template/.agents/skills/design/shadcn/rules/forms.md +0 -192
- package/template/.agents/skills/design/shadcn/rules/icons.md +0 -101
- package/template/.agents/skills/design/shadcn/rules/styling.md +0 -185
- package/template/.agents/skills/find-skills/SKILL.md +0 -141
- package/template/.agents/skills/hono/SKILL.md +0 -593
- package/template/.agents/skills/integrations/langfuse/SKILL.md +0 -150
- package/template/.agents/skills/integrations/langfuse/references/ci-cd.md +0 -41
- package/template/.agents/skills/integrations/langfuse/references/cli.md +0 -60
- package/template/.agents/skills/integrations/langfuse/references/create-dataset.md +0 -35
- package/template/.agents/skills/integrations/langfuse/references/error-analysis.md +0 -87
- package/template/.agents/skills/integrations/langfuse/references/instrumentation.md +0 -121
- package/template/.agents/skills/integrations/langfuse/references/judge-calibration.md +0 -293
- package/template/.agents/skills/integrations/langfuse/references/prompt-engineering.md +0 -35
- package/template/.agents/skills/integrations/langfuse/references/prompt-migration.md +0 -79
- package/template/.agents/skills/integrations/langfuse/references/sdk-upgrade.md +0 -34
- package/template/.agents/skills/integrations/langfuse/references/setting-up-evals.md +0 -65
- package/template/.agents/skills/integrations/langfuse/references/skill-feedback.md +0 -35
- package/template/.agents/skills/integrations/langfuse/references/trace-evaluator-upgrade.md +0 -76
- package/template/.agents/skills/integrations/langfuse/references/user-feedback.md +0 -66
- package/template/.agents/skills/integrations/langfuse/references/v4-project-migration.md +0 -75
- package/template/.agents/skills/integrations/posthog/SKILL.md +0 -102
- package/template/.agents/skills/integrations/posthog/references/error-tracking-alerts.md +0 -63
- package/template/.agents/skills/integrations/posthog/references/error-tracking-assigning-issues.md +0 -77
- package/template/.agents/skills/integrations/posthog/references/error-tracking-fingerprints.md +0 -57
- package/template/.agents/skills/integrations/posthog/references/error-tracking-monitoring.md +0 -140
- package/template/.agents/skills/integrations/posthog/references/error-tracking-nextjs.md +0 -490
- package/template/.agents/skills/integrations/posthog/references/error-tracking-source-maps.md +0 -45
- package/template/.agents/skills/integrations/posthog/references/feature-flags-best-practices.md +0 -139
- package/template/.agents/skills/integrations/posthog/references/feature-flags-react.md +0 -302
- package/template/.agents/skills/integrations/posthog/references/identify-users.md +0 -202
- package/template/.agents/skills/integrations/posthog/references/integration-example.md +0 -706
- package/template/.agents/skills/integrations/posthog/references/integration-nextjs.md +0 -385
- package/template/.agents/skills/integrations/posthog/references/integration-step-1-begin.md +0 -43
- package/template/.agents/skills/integrations/posthog/references/integration-step-2-edit.md +0 -37
- package/template/.agents/skills/integrations/posthog/references/integration-step-3-revise.md +0 -22
- package/template/.agents/skills/integrations/posthog/references/integration-step-4-conclude.md +0 -38
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-anthropic.md +0 -200
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-basics.md +0 -62
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-costs.md +0 -197
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-manual-capture.md +0 -397
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-traces.md +0 -98
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-vercel-ai.md +0 -120
- package/template/.agents/skills/repo/repo-ci/SKILL.md +0 -265
- package/template/.agents/skills/repo/repo-init-next-js/SKILL.md +0 -129
- package/template/.agents/skills/repo/repo-init-next-js/references/file-contents.md +0 -800
- package/template/.agents/skills/repo/repo-init-next-js/scripts/setup.sh +0 -47
- package/template/.agents/skills/repo/repo-init-node/SKILL.md +0 -196
- package/template/.agents/skills/skill-creator/LICENSE.txt +0 -202
- package/template/.agents/skills/skill-creator/SKILL.md +0 -485
- package/template/.agents/skills/skill-creator/agents/analyzer.md +0 -274
- package/template/.agents/skills/skill-creator/agents/comparator.md +0 -202
- package/template/.agents/skills/skill-creator/agents/grader.md +0 -223
- package/template/.agents/skills/skill-creator/assets/eval_review.html +0 -146
- package/template/.agents/skills/skill-creator/eval-viewer/generate_review.py +0 -471
- package/template/.agents/skills/skill-creator/eval-viewer/viewer.html +0 -1325
- package/template/.agents/skills/skill-creator/references/schemas.md +0 -430
- package/template/.agents/skills/skill-creator/scripts/__init__.py +0 -0
- package/template/.agents/skills/skill-creator/scripts/aggregate_benchmark.py +0 -401
- package/template/.agents/skills/skill-creator/scripts/generate_report.py +0 -326
- package/template/.agents/skills/skill-creator/scripts/improve_description.py +0 -247
- package/template/.agents/skills/skill-creator/scripts/package_skill.py +0 -136
- package/template/.agents/skills/skill-creator/scripts/quick_validate.py +0 -103
- package/template/.agents/skills/skill-creator/scripts/run_eval.py +0 -310
- package/template/.agents/skills/skill-creator/scripts/run_loop.py +0 -328
- package/template/.agents/skills/skill-creator/scripts/utils.py +0 -47
- package/template/.agents/skills/supabase/CHANGELOG.md +0 -78
- package/template/.agents/skills/supabase/SKILL.md +0 -149
- package/template/.agents/skills/supabase/assets/feedback-issue-template.md +0 -17
- package/template/.agents/skills/supabase/references/skill-feedback.md +0 -17
- package/template/.agents/skills/supabase-postgres-best-practices/CHANGELOG.md +0 -73
- package/template/.agents/skills/supabase-postgres-best-practices/SKILL.md +0 -64
- package/template/.agents/skills/supabase-postgres-best-practices/references/_contributing.md +0 -170
- package/template/.agents/skills/supabase-postgres-best-practices/references/_sections.md +0 -39
- package/template/.agents/skills/supabase-postgres-best-practices/references/_template.md +0 -34
- package/template/.agents/skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +0 -55
- package/template/.agents/skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +0 -49
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +0 -46
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-limits.md +0 -44
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-pooling.md +0 -41
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +0 -46
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-batch-inserts.md +0 -54
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-n-plus-one.md +0 -53
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-pagination.md +0 -50
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-upsert.md +0 -50
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-advisory.md +0 -56
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +0 -68
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-short-transactions.md +0 -50
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-skip-locked.md +0 -54
- package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +0 -45
- package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +0 -55
- package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +0 -55
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-composite-indexes.md +0 -44
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-covering-indexes.md +0 -40
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-index-types.md +0 -48
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-missing-indexes.md +0 -43
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-partial-indexes.md +0 -45
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-constraints.md +0 -80
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-data-types.md +0 -46
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +0 -59
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +0 -55
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-partitioning.md +0 -55
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-primary-keys.md +0 -61
- package/template/.agents/skills/supabase-postgres-best-practices/references/security-privileges.md +0 -54
- package/template/.agents/skills/supabase-postgres-best-practices/references/security-rls-basics.md +0 -50
- package/template/.agents/skills/supabase-postgres-best-practices/references/security-rls-performance.md +0 -63
- package/template/.agents/skills/writing/humanizer/LICENSE +0 -21
- package/template/.agents/skills/writing/humanizer/README.md +0 -209
- package/template/.agents/skills/writing/humanizer/SKILL.md +0 -456
- package/template/.agents/upstreams.json +0 -115
|
@@ -1,596 +0,0 @@
|
|
|
1
|
-
// ─── Section 2: Color Utilities ─────────────────────────────────────────────
|
|
2
|
-
|
|
3
|
-
function isNeutralColor(color) {
|
|
4
|
-
if (!color || color === 'transparent') return true;
|
|
5
|
-
|
|
6
|
-
// rgb/rgba — use channel spread. Threshold 30 ≈ 11.7% of the 0–255 range.
|
|
7
|
-
const rgb = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
8
|
-
if (rgb) {
|
|
9
|
-
return (Math.max(+rgb[1], +rgb[2], +rgb[3]) - Math.min(+rgb[1], +rgb[2], +rgb[3])) < 30;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// oklch()/lch() — chroma is the second numeric component.
|
|
13
|
-
// oklch chroma is ~0–0.4 in sRGB gamut; >= 0.02 reads as tinted, not gray.
|
|
14
|
-
// lch chroma is ~0–150; >= 3 reads as tinted. jsdom emits both formats
|
|
15
|
-
// literally (it does NOT convert them to rgb).
|
|
16
|
-
const oklch = color.match(/oklch\(\s*[\d.]+%?\s*([\d.-]+)/i);
|
|
17
|
-
if (oklch) return parseFloat(oklch[1]) < 0.02;
|
|
18
|
-
const lch = color.match(/lch\(\s*[\d.]+%?\s*([\d.-]+)/i);
|
|
19
|
-
if (lch) return parseFloat(lch[1]) < 3;
|
|
20
|
-
|
|
21
|
-
// oklab()/lab() — a and b are signed axes; chroma = sqrt(a² + b²).
|
|
22
|
-
// oklab a/b are ~-0.4..0.4, threshold 0.02. lab a/b are ~-128..127, threshold 3.
|
|
23
|
-
const oklab = color.match(/oklab\(\s*[\d.]+%?\s*([\d.-]+)\s+([\d.-]+)/i);
|
|
24
|
-
if (oklab) {
|
|
25
|
-
const a = parseFloat(oklab[1]), b = parseFloat(oklab[2]);
|
|
26
|
-
return Math.hypot(a, b) < 0.02;
|
|
27
|
-
}
|
|
28
|
-
const lab = color.match(/lab\(\s*[\d.]+%?\s*([\d.-]+)\s+([\d.-]+)/i);
|
|
29
|
-
if (lab) {
|
|
30
|
-
const a = parseFloat(lab[1]), b = parseFloat(lab[2]);
|
|
31
|
-
return Math.hypot(a, b) < 3;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// hsl/hsla — saturation is the second numeric component (percent).
|
|
35
|
-
// Modern jsdom usually converts hsl() to rgb, but handle it directly for
|
|
36
|
-
// safety across versions and for any engine that preserves the format.
|
|
37
|
-
const hsl = color.match(/hsla?\(\s*[\d.-]+\s*,?\s*([\d.]+)%/i);
|
|
38
|
-
if (hsl) return parseFloat(hsl[1]) < 10;
|
|
39
|
-
|
|
40
|
-
// hwb(hue whiteness% blackness%) — a pixel is fully gray when
|
|
41
|
-
// whiteness + blackness >= 100; chroma-like saturation = 1 - (w+b)/100.
|
|
42
|
-
const hwb = color.match(/hwb\(\s*[\d.-]+\s+([\d.]+)%\s+([\d.]+)%/i);
|
|
43
|
-
if (hwb) {
|
|
44
|
-
const w = parseFloat(hwb[1]), b = parseFloat(hwb[2]);
|
|
45
|
-
return (1 - Math.min(100, w + b) / 100) < 0.1;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Unknown / unrecognized format — err on the side of DETECTING rather
|
|
49
|
-
// than silently skipping. This is the opposite of the previous default,
|
|
50
|
-
// which was the root cause of the oklch bug.
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function parseRgb(color) {
|
|
55
|
-
if (!color || color === 'transparent') return null;
|
|
56
|
-
const m = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
|
|
57
|
-
if (!m) return null;
|
|
58
|
-
return { r: +m[1], g: +m[2], b: +m[3], a: m[4] !== undefined ? +m[4] : 1 };
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function relativeLuminance({ r, g, b }) {
|
|
62
|
-
const [rs, gs, bs] = [r / 255, g / 255, b / 255].map(c =>
|
|
63
|
-
c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4
|
|
64
|
-
);
|
|
65
|
-
return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function contrastRatio(c1, c2) {
|
|
69
|
-
const l1 = relativeLuminance(c1);
|
|
70
|
-
const l2 = relativeLuminance(c2);
|
|
71
|
-
return (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// The CSS color functions worth pulling out of a longer declaration. The set
|
|
75
|
-
// is deliberately closed: `linear-gradient(` and `url(` also look like
|
|
76
|
-
// `name(` and must not be read as colors.
|
|
77
|
-
const COLOR_FUNCTION_NAMES = new Set([
|
|
78
|
-
'rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'oklch', 'oklab', 'lch', 'lab', 'color', 'color-mix',
|
|
79
|
-
]);
|
|
80
|
-
|
|
81
|
-
// Pull every color-function token out of a value, with balanced-paren capture
|
|
82
|
-
// so nested forms (`color-mix(in oklab, oklch(...) 20%, transparent)`) survive
|
|
83
|
-
// whole. Returns the raw substrings in source order.
|
|
84
|
-
function extractColorFunctionTokens(value) {
|
|
85
|
-
const str = String(value || '');
|
|
86
|
-
const tokens = [];
|
|
87
|
-
const re = /([a-z][a-z-]*)\(/gi;
|
|
88
|
-
let m;
|
|
89
|
-
while ((m = re.exec(str)) !== null) {
|
|
90
|
-
if (!COLOR_FUNCTION_NAMES.has(m[1].toLowerCase())) continue;
|
|
91
|
-
let depth = 0, end = -1;
|
|
92
|
-
for (let i = m.index + m[0].length - 1; i < str.length; i++) {
|
|
93
|
-
if (str[i] === '(') depth++;
|
|
94
|
-
else if (str[i] === ')') { depth--; if (depth === 0) { end = i; break; } }
|
|
95
|
-
}
|
|
96
|
-
if (end < 0) break;
|
|
97
|
-
tokens.push(str.slice(m.index, end + 1));
|
|
98
|
-
re.lastIndex = end + 1;
|
|
99
|
-
}
|
|
100
|
-
return tokens;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function parseGradientColors(bgImage) {
|
|
104
|
-
if (!bgImage || !bgImage.includes('gradient')) return [];
|
|
105
|
-
const colors = [];
|
|
106
|
-
const tokenSpans = [];
|
|
107
|
-
let from = 0;
|
|
108
|
-
// Stops arrive in whatever syntax the author wrote and the browser kept.
|
|
109
|
-
// A dark ground painted as `linear-gradient(oklch(...), oklch(...))` used
|
|
110
|
-
// to read as a gradient with no stops at all.
|
|
111
|
-
for (const token of extractColorFunctionTokens(bgImage)) {
|
|
112
|
-
const start = bgImage.indexOf(token, from);
|
|
113
|
-
if (start < 0) break;
|
|
114
|
-
tokenSpans.push({ start, end: start + token.length });
|
|
115
|
-
from = start + token.length;
|
|
116
|
-
const c = parseAnyColor(token);
|
|
117
|
-
if (c) colors.push(c);
|
|
118
|
-
}
|
|
119
|
-
for (const m of bgImage.matchAll(/#([0-9a-f]{6}|[0-9a-f]{3})\b/gi)) {
|
|
120
|
-
// Nested hex inside color-mix is an ingredient, not a stop (issue #578).
|
|
121
|
-
if (tokenSpans.some(s => m.index >= s.start && m.index < s.end)) continue;
|
|
122
|
-
const h = m[1];
|
|
123
|
-
if (h.length === 6) {
|
|
124
|
-
colors.push({ r: parseInt(h.slice(0,2),16), g: parseInt(h.slice(2,4),16), b: parseInt(h.slice(4,6),16), a: 1 });
|
|
125
|
-
} else {
|
|
126
|
-
colors.push({ r: parseInt(h[0]+h[0],16), g: parseInt(h[1]+h[1],16), b: parseInt(h[2]+h[2],16), a: 1 });
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return colors;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function hasChroma(c, threshold = 30) {
|
|
133
|
-
if (!c) return false;
|
|
134
|
-
return (Math.max(c.r, c.g, c.b) - Math.min(c.r, c.g, c.b)) >= threshold;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function getHue(c) {
|
|
138
|
-
if (!c) return 0;
|
|
139
|
-
const r = c.r / 255, g = c.g / 255, b = c.b / 255;
|
|
140
|
-
const max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
141
|
-
if (max === min) return 0;
|
|
142
|
-
const d = max - min;
|
|
143
|
-
let h;
|
|
144
|
-
if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
|
145
|
-
else if (max === g) h = ((b - r) / d + 2) / 6;
|
|
146
|
-
else h = ((r - g) / d + 4) / 6;
|
|
147
|
-
return Math.round(h * 360);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function colorToHex(c) {
|
|
151
|
-
if (!c) return '?';
|
|
152
|
-
return '#' + [c.r, c.g, c.b].map(v => v.toString(16).padStart(2, '0')).join('');
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// ─── Color-space conversions ────────────────────────────────────────────────
|
|
156
|
-
//
|
|
157
|
-
// Every function here lands on 8-bit sRGB, clamped to gamut. Chrome, Safari,
|
|
158
|
-
// and Firefox all keep the authored color space in getComputedStyle output
|
|
159
|
-
// (`oklch(0.84 0.19 80.46)`, `lch(20 5 60)`, `color(srgb 1.04 0.72 -0.21)`),
|
|
160
|
-
// so a detector that only reads rgb() is blind on any modern palette. The
|
|
161
|
-
// expected outputs are pinned in tests/detect-antipatterns.test.js against
|
|
162
|
-
// what Chrome itself paints for the same strings.
|
|
163
|
-
|
|
164
|
-
function clamp01(x) {
|
|
165
|
-
return Number.isFinite(x) ? Math.max(0, Math.min(1, x)) : 0;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Linear-light sRGB channel to the encoded 0-255 value.
|
|
169
|
-
function encodeSrgbChannel(x) {
|
|
170
|
-
const c = clamp01(x);
|
|
171
|
-
return Math.round((c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055) * 255);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
function decodeSrgbChannel(x) {
|
|
175
|
-
const c = Number.isFinite(x) ? x : 0;
|
|
176
|
-
const sign = c < 0 ? -1 : 1;
|
|
177
|
-
const abs = Math.abs(c);
|
|
178
|
-
return sign * (abs <= 0.04045 ? abs / 12.92 : Math.pow((abs + 0.055) / 1.055, 2.4));
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function linearSrgbToColor(r, g, b, a = 1) {
|
|
182
|
-
return { r: encodeSrgbChannel(r), g: encodeSrgbChannel(g), b: encodeSrgbChannel(b), a };
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// OKLab to sRGB (Björn Ottosson's matrices). L in 0..1, a/b are signed axes.
|
|
186
|
-
function oklabToRgb(L, a, b) {
|
|
187
|
-
const l_ = L + 0.3963377774 * a + 0.2158037573 * b;
|
|
188
|
-
const m_ = L - 0.1055613458 * a - 0.0638541728 * b;
|
|
189
|
-
const s_ = L - 0.0894841775 * a - 1.2914855480 * b;
|
|
190
|
-
const lc = l_ * l_ * l_, mc = m_ * m_ * m_, sc = s_ * s_ * s_;
|
|
191
|
-
return linearSrgbToColor(
|
|
192
|
-
4.0767416621 * lc - 3.3077115913 * mc + 0.2309699292 * sc,
|
|
193
|
-
-1.2684380046 * lc + 2.6097574011 * mc - 0.3413193965 * sc,
|
|
194
|
-
-0.0041960863 * lc - 0.7034186147 * mc + 1.7076147010 * sc,
|
|
195
|
-
);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// OKLCH to sRGB. L in 0..1, C in 0..~0.4 typical, H in degrees. Chroma past
|
|
199
|
-
// the sRGB gamut clamps per channel rather than producing NaN.
|
|
200
|
-
function oklchToRgb(L, C, H) {
|
|
201
|
-
const hRad = (H * Math.PI) / 180;
|
|
202
|
-
return oklabToRgb(L, C * Math.cos(hRad), C * Math.sin(hRad));
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// CIE Lab to sRGB. CSS lab()/lch() use the D50 white point; the matrix below
|
|
206
|
-
// is the Bradford-adapted XYZ-D50 to linear-sRGB transform from CSS Color 4.
|
|
207
|
-
function labToRgb(L, a, b) {
|
|
208
|
-
const kappa = 24389 / 27, epsilon = 216 / 24389;
|
|
209
|
-
const fy = (L + 16) / 116, fx = fy + a / 500, fz = fy - b / 200;
|
|
210
|
-
const invert = (t) => (t * t * t > epsilon ? t * t * t : (116 * t - 16) / kappa);
|
|
211
|
-
const yr = L > kappa * epsilon ? Math.pow((L + 16) / 116, 3) : L / kappa;
|
|
212
|
-
const Xn = 0.3457 / 0.3585, Zn = (1 - 0.3457 - 0.3585) / 0.3585;
|
|
213
|
-
const x = invert(fx) * Xn, y = yr, z = invert(fz) * Zn;
|
|
214
|
-
return linearSrgbToColor(
|
|
215
|
-
3.1341359569958707 * x - 1.6173863321612538 * y - 0.4906619460083532 * z,
|
|
216
|
-
-0.9787955029120890 * x + 1.9162545672595240 * y + 0.0334427311613195 * z,
|
|
217
|
-
0.0719553798841168 * x - 0.2289768264158322 * y + 1.4053860583241250 * z,
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
function lchToRgb(L, C, H) {
|
|
222
|
-
const hRad = (H * Math.PI) / 180;
|
|
223
|
-
return labToRgb(L, C * Math.cos(hRad), C * Math.sin(hRad));
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// color(<space> c1 c2 c3) for the spaces that turn up in real stylesheets.
|
|
227
|
-
// `srgb` is what Chrome serializes most color-mix() results into, routinely
|
|
228
|
-
// with channels outside 0..1. Spaces we do not model return null so callers
|
|
229
|
-
// abstain instead of measuring against a color we invented.
|
|
230
|
-
function colorFunctionToRgb(space, c1, c2, c3) {
|
|
231
|
-
switch (space) {
|
|
232
|
-
case 'srgb':
|
|
233
|
-
return { r: Math.round(clamp01(c1) * 255), g: Math.round(clamp01(c2) * 255), b: Math.round(clamp01(c3) * 255), a: 1 };
|
|
234
|
-
case 'srgb-linear':
|
|
235
|
-
return linearSrgbToColor(c1, c2, c3);
|
|
236
|
-
case 'display-p3': {
|
|
237
|
-
const [R, G, B] = [decodeSrgbChannel(c1), decodeSrgbChannel(c2), decodeSrgbChannel(c3)];
|
|
238
|
-
return linearSrgbToColor(
|
|
239
|
-
1.2249401762805587 * R - 0.2249404646817506 * G + 0.0000002884022551 * B,
|
|
240
|
-
-0.0420569547096138 * R + 1.0420571661298634 * G - 0.0000002113202247 * B,
|
|
241
|
-
-0.0196375587040044 * R - 0.0786360772174755 * G + 1.0982736359214800 * B,
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
default:
|
|
245
|
-
return null;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
function hslToRgb(h, s, l) {
|
|
250
|
-
h = ((h % 360) + 360) % 360;
|
|
251
|
-
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
252
|
-
const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
|
|
253
|
-
const m0 = l - c / 2;
|
|
254
|
-
const [r, g, b] =
|
|
255
|
-
h < 60 ? [c, x, 0] :
|
|
256
|
-
h < 120 ? [x, c, 0] :
|
|
257
|
-
h < 180 ? [0, c, x] :
|
|
258
|
-
h < 240 ? [0, x, c] :
|
|
259
|
-
h < 300 ? [x, 0, c] : [c, 0, x];
|
|
260
|
-
return {
|
|
261
|
-
r: Math.round((r + m0) * 255),
|
|
262
|
-
g: Math.round((g + m0) * 255),
|
|
263
|
-
b: Math.round((b + m0) * 255),
|
|
264
|
-
a: 1,
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
function hwbToRgb(h, w, bl) {
|
|
269
|
-
if (w + bl >= 1) {
|
|
270
|
-
const g = Math.round((w / (w + bl)) * 255);
|
|
271
|
-
return { r: g, g, b: g, a: 1 };
|
|
272
|
-
}
|
|
273
|
-
const base = hslToRgb(h, 1, 0.5);
|
|
274
|
-
const mix = (c) => Math.round(((c / 255) * (1 - w - bl) + w) * 255);
|
|
275
|
-
return { r: mix(base.r), g: mix(base.g), b: mix(base.b), a: 1 };
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// Common CSS named colors — the handful that actually show up in generated
|
|
279
|
-
// UIs, not the full 148-name spec list. Includes the achromatic names so a
|
|
280
|
-
// named gray parses (and correctly reads as no-chroma) instead of being
|
|
281
|
-
// treated as an unknown color.
|
|
282
|
-
const CSS_NAMED_COLORS = {
|
|
283
|
-
black: { r: 0, g: 0, b: 0 },
|
|
284
|
-
white: { r: 255, g: 255, b: 255 },
|
|
285
|
-
gray: { r: 128, g: 128, b: 128 },
|
|
286
|
-
grey: { r: 128, g: 128, b: 128 },
|
|
287
|
-
silver: { r: 192, g: 192, b: 192 },
|
|
288
|
-
dimgray: { r: 105, g: 105, b: 105 },
|
|
289
|
-
darkgray: { r: 169, g: 169, b: 169 },
|
|
290
|
-
lightgray: { r: 211, g: 211, b: 211 },
|
|
291
|
-
gainsboro: { r: 220, g: 220, b: 220 },
|
|
292
|
-
whitesmoke: { r: 245, g: 245, b: 245 },
|
|
293
|
-
red: { r: 255, g: 0, b: 0 },
|
|
294
|
-
crimson: { r: 220, g: 20, b: 60 },
|
|
295
|
-
tomato: { r: 255, g: 99, b: 71 },
|
|
296
|
-
coral: { r: 255, g: 127, b: 80 },
|
|
297
|
-
salmon: { r: 250, g: 128, b: 114 },
|
|
298
|
-
orange: { r: 255, g: 165, b: 0 },
|
|
299
|
-
gold: { r: 255, g: 215, b: 0 },
|
|
300
|
-
yellow: { r: 255, g: 255, b: 0 },
|
|
301
|
-
olive: { r: 128, g: 128, b: 0 },
|
|
302
|
-
lime: { r: 0, g: 255, b: 0 },
|
|
303
|
-
green: { r: 0, g: 128, b: 0 },
|
|
304
|
-
teal: { r: 0, g: 128, b: 128 },
|
|
305
|
-
turquoise: { r: 64, g: 224, b: 208 },
|
|
306
|
-
cyan: { r: 0, g: 255, b: 255 },
|
|
307
|
-
aqua: { r: 0, g: 255, b: 255 },
|
|
308
|
-
skyblue: { r: 135, g: 206, b: 235 },
|
|
309
|
-
dodgerblue: { r: 30, g: 144, b: 255 },
|
|
310
|
-
blue: { r: 0, g: 0, b: 255 },
|
|
311
|
-
navy: { r: 0, g: 0, b: 128 },
|
|
312
|
-
indigo: { r: 75, g: 0, b: 130 },
|
|
313
|
-
rebeccapurple: { r: 102, g: 51, b: 153 },
|
|
314
|
-
purple: { r: 128, g: 0, b: 128 },
|
|
315
|
-
violet: { r: 238, g: 130, b: 238 },
|
|
316
|
-
orchid: { r: 218, g: 112, b: 214 },
|
|
317
|
-
magenta: { r: 255, g: 0, b: 255 },
|
|
318
|
-
fuchsia: { r: 255, g: 0, b: 255 },
|
|
319
|
-
hotpink: { r: 255, g: 105, b: 180 },
|
|
320
|
-
pink: { r: 255, g: 192, b: 203 },
|
|
321
|
-
maroon: { r: 128, g: 0, b: 0 },
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
// Split a string on top-level commas (ignoring commas nested in parens).
|
|
325
|
-
function splitTopLevelCommas(str) {
|
|
326
|
-
const parts = [];
|
|
327
|
-
let depth = 0, start = 0;
|
|
328
|
-
for (let i = 0; i < str.length; i++) {
|
|
329
|
-
const ch = str[i];
|
|
330
|
-
if (ch === '(') depth++;
|
|
331
|
-
else if (ch === ')') depth = Math.max(0, depth - 1);
|
|
332
|
-
else if (ch === ',' && depth === 0) {
|
|
333
|
-
parts.push(str.slice(start, i).trim());
|
|
334
|
-
start = i + 1;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
const tail = str.slice(start).trim();
|
|
338
|
-
if (tail) parts.push(tail);
|
|
339
|
-
return parts;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// Evaluate a CSS color-mix() expression to {r,g,b,a}. Returns null when
|
|
343
|
-
// the expression can't be resolved (unresolved var(), unknown colors).
|
|
344
|
-
//
|
|
345
|
-
// Mixing is done with premultiplied alpha in sRGB regardless of the
|
|
346
|
-
// declared interpolation space. That is exact for the dominant generated-UI
|
|
347
|
-
// pattern — `color-mix(in oklab, <color> N%, transparent)` — where the
|
|
348
|
-
// result is simply <color> at alpha N% in ANY rectangular space, and a
|
|
349
|
-
// close-enough approximation for opaque-opaque mixes (the detector only
|
|
350
|
-
// consumes these values for contrast/chroma thresholds, not for display).
|
|
351
|
-
function parseColorMix(str) {
|
|
352
|
-
const m = String(str).trim().match(/^color-mix\(/i);
|
|
353
|
-
if (!m) return null;
|
|
354
|
-
// Balanced-paren capture of the arguments.
|
|
355
|
-
let depth = 0, end = -1;
|
|
356
|
-
const open = str.indexOf('(');
|
|
357
|
-
for (let i = open; i < str.length; i++) {
|
|
358
|
-
if (str[i] === '(') depth++;
|
|
359
|
-
else if (str[i] === ')') { depth--; if (depth === 0) { end = i; break; } }
|
|
360
|
-
}
|
|
361
|
-
if (end < 0) return null;
|
|
362
|
-
const args = splitTopLevelCommas(str.slice(open + 1, end));
|
|
363
|
-
if (args.length !== 3 || !/^in\s/i.test(args[0])) return null;
|
|
364
|
-
|
|
365
|
-
const parseComponent = (component) => {
|
|
366
|
-
// Percentage may lead or trail the color per spec.
|
|
367
|
-
let pct = null;
|
|
368
|
-
let colorStr = component;
|
|
369
|
-
const trail = component.match(/\s+([\d.]+)%$/);
|
|
370
|
-
const lead = component.match(/^([\d.]+)%\s+/);
|
|
371
|
-
if (trail) { pct = parseFloat(trail[1]); colorStr = component.slice(0, trail.index).trim(); }
|
|
372
|
-
else if (lead) { pct = parseFloat(lead[1]); colorStr = component.slice(lead[0].length).trim(); }
|
|
373
|
-
let color;
|
|
374
|
-
if (/^transparent$/i.test(colorStr)) color = { r: 0, g: 0, b: 0, a: 0 };
|
|
375
|
-
else color = parseAnyColor(colorStr);
|
|
376
|
-
if (!color) return null;
|
|
377
|
-
return { color, pct };
|
|
378
|
-
};
|
|
379
|
-
|
|
380
|
-
const c1 = parseComponent(args[1]);
|
|
381
|
-
const c2 = parseComponent(args[2]);
|
|
382
|
-
if (!c1 || !c2) return null;
|
|
383
|
-
let p1 = c1.pct, p2 = c2.pct;
|
|
384
|
-
if (p1 == null && p2 == null) { p1 = 50; p2 = 50; }
|
|
385
|
-
else if (p1 == null) p1 = 100 - p2;
|
|
386
|
-
else if (p2 == null) p2 = 100 - p1;
|
|
387
|
-
const sum = p1 + p2;
|
|
388
|
-
if (sum <= 0) return null;
|
|
389
|
-
// Per spec: weights normalize to sum; when sum < 100 the result alpha is
|
|
390
|
-
// additionally scaled by sum/100.
|
|
391
|
-
const w1 = p1 / sum, w2 = p2 / sum;
|
|
392
|
-
const alphaScale = sum < 100 ? sum / 100 : 1;
|
|
393
|
-
const a1 = c1.color.a ?? 1, a2 = c2.color.a ?? 1;
|
|
394
|
-
const a = (a1 * w1 + a2 * w2) * alphaScale;
|
|
395
|
-
if (a <= 0) return { r: 0, g: 0, b: 0, a: 0 };
|
|
396
|
-
const mix = (ch) => Math.round((c1.color[ch] * a1 * w1 + c2.color[ch] * a2 * w2) / (a1 * w1 + a2 * w2));
|
|
397
|
-
return { r: mix('r'), g: mix('g'), b: mix('b'), a: Math.min(1, a) };
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
// Composite a translucent color over an opaque(ish) base (simple
|
|
401
|
-
// source-over in sRGB). Returns an opaque {r,g,b,a:1}.
|
|
402
|
-
function compositeColorOver(top, base) {
|
|
403
|
-
const a = top.a ?? 1;
|
|
404
|
-
return {
|
|
405
|
-
r: Math.round(top.r * a + base.r * (1 - a)),
|
|
406
|
-
g: Math.round(top.g * a + base.g * (1 - a)),
|
|
407
|
-
b: Math.round(top.b * a + base.b * (1 - a)),
|
|
408
|
-
a: 1,
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// A color() / lab() / lch() component: a bare number, a percentage against
|
|
413
|
-
// `scale`, or the `none` keyword (which resolves to zero for our purposes).
|
|
414
|
-
function parseColorComponent(token, scale = 1) {
|
|
415
|
-
if (token == null) return null;
|
|
416
|
-
const t = String(token).trim();
|
|
417
|
-
if (/^none$/i.test(t)) return 0;
|
|
418
|
-
const num = parseFloat(t);
|
|
419
|
-
if (!Number.isFinite(num)) return null;
|
|
420
|
-
return t.endsWith('%') ? (num / 100) * scale : num;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
function parseAlphaToken(token) {
|
|
424
|
-
if (token == null) return 1;
|
|
425
|
-
const t = String(token).trim();
|
|
426
|
-
if (/^none$/i.test(t)) return 1;
|
|
427
|
-
const num = parseFloat(t);
|
|
428
|
-
if (!Number.isFinite(num)) return 1;
|
|
429
|
-
return t.endsWith('%') ? num / 100 : num;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
// Extended color parser: rgb/rgba/hex/oklch/oklab/lch/lab/hsl/hwb/color()/
|
|
433
|
-
// color-mix/common named colors. Returns null on no match. Use this when the
|
|
434
|
-
// input might be any CSS color form; use plain parseRgb when you only expect
|
|
435
|
-
// computed rgb() values from real browsers.
|
|
436
|
-
function parseAnyColor(s) {
|
|
437
|
-
if (!s || typeof s !== 'string') return null;
|
|
438
|
-
const str = s.trim();
|
|
439
|
-
if (str === 'transparent' || str === 'currentcolor' || str === 'inherit') return null;
|
|
440
|
-
if (/^color-mix\(/i.test(str)) return parseColorMix(str);
|
|
441
|
-
let m;
|
|
442
|
-
m = str.match(/rgba?\(\s*(\d+(?:\.\d+)?)\s*,?\s*(\d+(?:\.\d+)?)\s*,?\s*(\d+(?:\.\d+)?)(?:\s*[,/]\s*([\d.]+)(%)?)?\s*\)/);
|
|
443
|
-
if (m) {
|
|
444
|
-
const c = { r: Math.round(+m[1]), g: Math.round(+m[2]), b: Math.round(+m[3]), a: 1 };
|
|
445
|
-
if (m[4] !== undefined) c.a = m[5] === '%' ? parseFloat(m[4]) / 100 : +m[4];
|
|
446
|
-
return c;
|
|
447
|
-
}
|
|
448
|
-
m = str.match(/^#([0-9a-f]{3,8})$/i);
|
|
449
|
-
if (m) {
|
|
450
|
-
const h = m[1];
|
|
451
|
-
if (h.length === 3 || h.length === 4) {
|
|
452
|
-
return {
|
|
453
|
-
r: parseInt(h[0] + h[0], 16),
|
|
454
|
-
g: parseInt(h[1] + h[1], 16),
|
|
455
|
-
b: parseInt(h[2] + h[2], 16),
|
|
456
|
-
a: h.length === 4 ? parseInt(h[3] + h[3], 16) / 255 : 1,
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
if (h.length === 6 || h.length === 8) {
|
|
460
|
-
return {
|
|
461
|
-
r: parseInt(h.slice(0, 2), 16),
|
|
462
|
-
g: parseInt(h.slice(2, 4), 16),
|
|
463
|
-
b: parseInt(h.slice(4, 6), 16),
|
|
464
|
-
a: h.length === 8 ? parseInt(h.slice(6, 8), 16) / 255 : 1,
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
// OKLCH parser. Tailwind v4's CSS minifier squishes the space after
|
|
469
|
-
// `%` ("21.5%.02 50"), so the separator between L and C may be absent.
|
|
470
|
-
// Match L (with optional %), then C and H separated permissively.
|
|
471
|
-
m = str.match(/oklch\(\s*([\d.]+)(%?)\s*[\s,]*\s*([\d.]+)\s*[\s,]+\s*([-\d.]+)(?:deg)?(?:\s*\/\s*([\d.]+)(%)?)?\s*\)/i);
|
|
472
|
-
if (m) {
|
|
473
|
-
const Lnum = parseFloat(m[1]);
|
|
474
|
-
const L = m[2] === '%' ? Lnum / 100 : Lnum;
|
|
475
|
-
const rgb = oklchToRgb(L, parseFloat(m[3]), parseFloat(m[4]));
|
|
476
|
-
if (m[5] !== undefined) {
|
|
477
|
-
const alpha = parseFloat(m[5]);
|
|
478
|
-
rgb.a = m[6] === '%' ? alpha / 100 : alpha;
|
|
479
|
-
}
|
|
480
|
-
return rgb;
|
|
481
|
-
}
|
|
482
|
-
// OKLAB — a/b are signed axes; percentages map 100% → 0.4.
|
|
483
|
-
m = str.match(/oklab\(\s*([\d.]+)(%?)\s+(-?[\d.]+)(%?)\s+(-?[\d.]+)(%?)(?:\s*\/\s*([\d.]+)(%)?)?\s*\)/i);
|
|
484
|
-
if (m) {
|
|
485
|
-
const L = m[2] === '%' ? parseFloat(m[1]) / 100 : parseFloat(m[1]);
|
|
486
|
-
const a = m[4] === '%' ? parseFloat(m[3]) * 0.004 : parseFloat(m[3]);
|
|
487
|
-
const b = m[6] === '%' ? parseFloat(m[5]) * 0.004 : parseFloat(m[5]);
|
|
488
|
-
const rgb = oklabToRgb(L, a, b);
|
|
489
|
-
if (m[7] !== undefined) {
|
|
490
|
-
const alpha = parseFloat(m[7]);
|
|
491
|
-
rgb.a = m[8] === '%' ? alpha / 100 : alpha;
|
|
492
|
-
}
|
|
493
|
-
return rgb;
|
|
494
|
-
}
|
|
495
|
-
// LCH / LAB — CIE, D50 white point. Chrome serializes lch(20% 5 60) as
|
|
496
|
-
// `lch(20 5 60)`, so L arrives with or without its percent sign. In both
|
|
497
|
-
// spaces L runs 0..100 and 100% means 100.
|
|
498
|
-
m = str.match(/^lch\(\s*([\d.]+%?|none)\s+([\d.]+%?|none)\s+(-?[\d.]+)(?:deg)?(?:\s*\/\s*([\d.]+%?|none))?\s*\)$/i);
|
|
499
|
-
if (m) {
|
|
500
|
-
const L = parseColorComponent(m[1], 100);
|
|
501
|
-
const C = parseColorComponent(m[2], 150);
|
|
502
|
-
const H = parseFloat(m[3]);
|
|
503
|
-
if (L == null || C == null || !Number.isFinite(H)) return null;
|
|
504
|
-
const rgb = lchToRgb(L, C, H);
|
|
505
|
-
rgb.a = parseAlphaToken(m[4]);
|
|
506
|
-
return rgb;
|
|
507
|
-
}
|
|
508
|
-
m = str.match(/^lab\(\s*([\d.]+%?|none)\s+(-?[\d.]+%?|none)\s+(-?[\d.]+%?|none)(?:\s*\/\s*([\d.]+%?|none))?\s*\)$/i);
|
|
509
|
-
if (m) {
|
|
510
|
-
const L = parseColorComponent(m[1], 100);
|
|
511
|
-
const a = parseColorComponent(m[2], 125);
|
|
512
|
-
const b = parseColorComponent(m[3], 125);
|
|
513
|
-
if (L == null || a == null || b == null) return null;
|
|
514
|
-
const rgb = labToRgb(L, a, b);
|
|
515
|
-
rgb.a = parseAlphaToken(m[4]);
|
|
516
|
-
return rgb;
|
|
517
|
-
}
|
|
518
|
-
// color(<space> c1 c2 c3 [/ alpha]) — what Chrome hands back for most
|
|
519
|
-
// color-mix() results and for any wide-gamut color an author wrote.
|
|
520
|
-
m = str.match(/^color\(\s*([a-z0-9-]+)\s+(-?[\d.eE+-]+%?|none)\s+(-?[\d.eE+-]+%?|none)\s+(-?[\d.eE+-]+%?|none)(?:\s*\/\s*([\d.]+%?|none))?\s*\)$/i);
|
|
521
|
-
if (m) {
|
|
522
|
-
const c1 = parseColorComponent(m[2]);
|
|
523
|
-
const c2 = parseColorComponent(m[3]);
|
|
524
|
-
const c3 = parseColorComponent(m[4]);
|
|
525
|
-
if (c1 == null || c2 == null || c3 == null) return null;
|
|
526
|
-
const rgb = colorFunctionToRgb(m[1].toLowerCase(), c1, c2, c3);
|
|
527
|
-
if (!rgb) return null;
|
|
528
|
-
rgb.a = parseAlphaToken(m[5]);
|
|
529
|
-
return rgb;
|
|
530
|
-
}
|
|
531
|
-
// HSL/HSLA — comma or space syntax, optional deg on hue.
|
|
532
|
-
m = str.match(/hsla?\(\s*(-?[\d.]+)(?:deg)?\s*[,\s]\s*([\d.]+)%\s*[,\s]\s*([\d.]+)%(?:\s*[,/]\s*([\d.]+)(%)?)?\s*\)/i);
|
|
533
|
-
if (m) {
|
|
534
|
-
const rgb = hslToRgb(parseFloat(m[1]), parseFloat(m[2]) / 100, parseFloat(m[3]) / 100);
|
|
535
|
-
if (m[4] !== undefined) {
|
|
536
|
-
const alpha = parseFloat(m[4]);
|
|
537
|
-
rgb.a = m[5] === '%' ? alpha / 100 : alpha;
|
|
538
|
-
}
|
|
539
|
-
return rgb;
|
|
540
|
-
}
|
|
541
|
-
// HWB — hue whiteness% blackness%.
|
|
542
|
-
m = str.match(/hwb\(\s*(-?[\d.]+)(?:deg)?\s+([\d.]+)%\s+([\d.]+)%(?:\s*\/\s*([\d.]+)(%)?)?\s*\)/i);
|
|
543
|
-
if (m) {
|
|
544
|
-
const rgb = hwbToRgb(parseFloat(m[1]), parseFloat(m[2]) / 100, parseFloat(m[3]) / 100);
|
|
545
|
-
if (m[4] !== undefined) {
|
|
546
|
-
const alpha = parseFloat(m[4]);
|
|
547
|
-
rgb.a = m[5] === '%' ? alpha / 100 : alpha;
|
|
548
|
-
}
|
|
549
|
-
return rgb;
|
|
550
|
-
}
|
|
551
|
-
const named = CSS_NAMED_COLORS[str.toLowerCase()];
|
|
552
|
-
if (named) return { ...named, a: 1 };
|
|
553
|
-
return null;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
// True when a computed background-color string names no paint at all. Used to
|
|
557
|
-
// tell "this layer is see-through" (walk on to the ancestor) apart from "this
|
|
558
|
-
// layer has a color we could not read" (stop and abstain).
|
|
559
|
-
//
|
|
560
|
-
// `inherit` belongs here even though it is not literally see-through: it means
|
|
561
|
-
// "paint with the parent's background-color", and walking on to the parent IS
|
|
562
|
-
// that resolution. Real browsers resolve the keyword before getComputedStyle
|
|
563
|
-
// output; only jsdom's partial cascade hands it through verbatim, and treating
|
|
564
|
-
// it as unreadable would make the walk abstain on a surface it can know.
|
|
565
|
-
// (`currentcolor` is NOT here — it is real paint in the element's own text
|
|
566
|
-
// color; resolveBackgroundInfo substitutes the computed color for it.)
|
|
567
|
-
function isNoPaintColorValue(value) {
|
|
568
|
-
const v = String(value || '').trim().toLowerCase();
|
|
569
|
-
if (!v) return true;
|
|
570
|
-
return v === 'transparent' || v === 'none' || v === 'initial' || v === 'inherit' || v === 'unset' || v === 'revert' || v === 'revert-layer';
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
export {
|
|
574
|
-
isNeutralColor,
|
|
575
|
-
parseRgb,
|
|
576
|
-
relativeLuminance,
|
|
577
|
-
contrastRatio,
|
|
578
|
-
parseGradientColors,
|
|
579
|
-
extractColorFunctionTokens,
|
|
580
|
-
hasChroma,
|
|
581
|
-
getHue,
|
|
582
|
-
colorToHex,
|
|
583
|
-
oklabToRgb,
|
|
584
|
-
oklchToRgb,
|
|
585
|
-
labToRgb,
|
|
586
|
-
lchToRgb,
|
|
587
|
-
colorFunctionToRgb,
|
|
588
|
-
hslToRgb,
|
|
589
|
-
hwbToRgb,
|
|
590
|
-
CSS_NAMED_COLORS,
|
|
591
|
-
splitTopLevelCommas,
|
|
592
|
-
parseColorMix,
|
|
593
|
-
parseAnyColor,
|
|
594
|
-
compositeColorOver,
|
|
595
|
-
isNoPaintColorValue,
|
|
596
|
-
};
|