quiver-cli 0.7.0 → 1.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 +110 -45
- package/bin/quiver-cli.mjs +3 -1
- package/dist/cli.js +733 -499
- package/package.json +2 -2
- package/template/.agents/AGENTS.md +4 -3
- package/template/.agents/config.json +7 -0
- package/template/.agents/plugins/opencode/rtk.ts +34 -0
- package/template/.agents/skills/agent-browser/SKILL.md +1 -0
- package/template/.agents/skills/apps/skybridge/SKILL.md +4 -0
- package/template/.agents/skills/design/impeccable/SKILL.md +36 -118
- package/template/.agents/skills/design/impeccable/reference/adapt.md +1 -0
- package/template/.agents/skills/design/impeccable/reference/adapt.native.md +58 -0
- package/template/.agents/skills/design/impeccable/reference/android.md +40 -0
- package/template/.agents/skills/design/impeccable/reference/animate.md +73 -188
- package/template/.agents/skills/design/impeccable/reference/audit.md +12 -9
- package/template/.agents/skills/design/impeccable/reference/audit.native.md +139 -0
- package/template/.agents/skills/design/impeccable/reference/bolder.md +19 -101
- package/template/.agents/skills/design/impeccable/reference/clarify.md +59 -253
- package/template/.agents/skills/design/impeccable/reference/colorize.md +51 -222
- package/template/.agents/skills/design/impeccable/reference/craft-floor.md +42 -0
- package/template/.agents/skills/design/impeccable/reference/craft.md +3 -121
- package/template/.agents/skills/design/impeccable/reference/critique.md +44 -23
- package/template/.agents/skills/design/impeccable/reference/degraded/asset-producer.md +90 -0
- package/template/.agents/skills/design/impeccable/reference/degraded/documenter.md +24 -0
- package/template/.agents/skills/design/impeccable/reference/degraded/finish-reviewer.md +37 -0
- package/template/.agents/skills/design/impeccable/reference/degraded/manual-edit-applier.md +92 -0
- package/template/.agents/skills/design/impeccable/reference/delight.md +47 -279
- package/template/.agents/skills/design/impeccable/reference/distill.md +2 -2
- package/template/.agents/skills/design/impeccable/reference/doctor.md +53 -0
- package/template/.agents/skills/design/impeccable/reference/document.md +60 -73
- package/template/.agents/skills/design/impeccable/reference/harden.md +1 -12
- package/template/.agents/skills/design/impeccable/reference/hooks.md +20 -5
- package/template/.agents/skills/design/impeccable/reference/init.md +72 -119
- package/template/.agents/skills/design/impeccable/reference/ios.md +45 -0
- package/template/.agents/skills/design/impeccable/reference/layout.md +54 -131
- package/template/.agents/skills/design/impeccable/reference/live-setup.md +102 -0
- package/template/.agents/skills/design/impeccable/reference/live.md +116 -511
- package/template/.agents/skills/design/impeccable/reference/new-work.md +105 -0
- package/template/.agents/skills/design/impeccable/reference/{product.md → operate.md} +6 -5
- package/template/.agents/skills/design/impeccable/reference/optimize.md +4 -4
- package/template/.agents/skills/design/impeccable/reference/overdrive.md +1 -4
- package/template/.agents/skills/design/impeccable/reference/polish.md +68 -212
- package/template/.agents/skills/design/impeccable/reference/quieter.md +3 -3
- package/template/.agents/skills/design/impeccable/reference/routing.md +18 -0
- package/template/.agents/skills/design/impeccable/reference/shape.md +38 -144
- package/template/.agents/skills/design/impeccable/reference/typeset.md +51 -250
- package/template/.agents/skills/design/impeccable/reference/visualize.md +47 -0
- package/template/.agents/skills/design/impeccable/scripts/command-metadata.json +1 -1
- package/template/.agents/skills/design/impeccable/scripts/concept-seed.mjs +558 -0
- package/template/.agents/skills/design/impeccable/scripts/context-signals.mjs +119 -10
- package/template/.agents/skills/design/impeccable/scripts/context.mjs +534 -45
- package/template/.agents/skills/design/impeccable/scripts/critique-storage.mjs +18 -47
- package/template/.agents/skills/design/impeccable/scripts/detector/browser/injected/index.mjs +96 -10
- package/template/.agents/skills/design/impeccable/scripts/detector/cli/main.mjs +174 -26
- package/template/.agents/skills/design/impeccable/scripts/detector/design-system.mjs +233 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/detect-antipatterns-browser.js +3348 -203
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/browser/detect-url.mjs +102 -7
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/regex/detect-text.mjs +297 -97
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +187 -16
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/detect-html.mjs +41 -11
- package/template/.agents/skills/design/impeccable/scripts/detector/findings.mjs +7 -1
- package/template/.agents/skills/design/impeccable/scripts/detector/node/file-system.mjs +16 -2
- package/template/.agents/skills/design/impeccable/scripts/detector/registry/antipatterns.mjs +207 -38
- package/template/.agents/skills/design/impeccable/scripts/detector/rules/checks.mjs +3082 -173
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/constants.mjs +11 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/fonts.mjs +30 -0
- package/template/.agents/skills/design/impeccable/scripts/doctor.mjs +336 -0
- package/template/.agents/skills/design/impeccable/scripts/embed-prompt.mjs +133 -0
- package/template/.agents/skills/design/impeccable/scripts/generate-image.mjs +240 -0
- package/template/.agents/skills/design/impeccable/scripts/hook-admin.mjs +98 -18
- package/template/.agents/skills/design/impeccable/scripts/hook-before-edit.mjs +46 -6
- package/template/.agents/skills/design/impeccable/scripts/hook-lib.mjs +518 -50
- package/template/.agents/skills/design/impeccable/scripts/hook.mjs +25 -8
- package/template/.agents/skills/design/impeccable/scripts/lib/artifact-schema.mjs +93 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/composition-catalog.mjs +200 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/concept-catalog.mjs +357 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/impeccable-config.mjs +27 -7
- package/template/.agents/skills/design/impeccable/scripts/lib/impeccable-paths.mjs +17 -8
- package/template/.agents/skills/design/impeccable/scripts/lib/provider.mjs +5 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/roll-selection.mjs +362 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/staleness-deep.mjs +457 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/staleness-notice.mjs +169 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/staleness.mjs +457 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/surface-briefs.mjs +151 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/target-slug.mjs +33 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/template-extensions.mjs +146 -0
- package/template/.agents/skills/design/impeccable/scripts/live/accept-css.mjs +617 -0
- package/template/.agents/skills/design/impeccable/scripts/live/accept-verify.mjs +60 -0
- package/template/.agents/skills/design/impeccable/scripts/live/browser-script-parts.mjs +7 -1
- package/template/.agents/skills/design/impeccable/scripts/live/completion.mjs +10 -1
- package/template/.agents/skills/design/impeccable/scripts/live/event-validation.mjs +67 -5
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/astro.mjs +47 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/detect-utils.mjs +73 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/index.mjs +143 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/journal.mjs +197 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/nextjs.mjs +49 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/nuxt.mjs +161 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/script-src.mjs +17 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/static-html.mjs +26 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/sveltekit.mjs +71 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/tag-strategy.mjs +247 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/tanstack-start.mjs +70 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/vite-generic.mjs +42 -0
- package/template/.agents/skills/design/impeccable/scripts/live/generation-preflight.mjs +149 -0
- package/template/.agents/skills/design/impeccable/scripts/live/instructions.mjs +142 -0
- package/template/.agents/skills/design/impeccable/scripts/live/poll-lanes.mjs +14 -0
- package/template/.agents/skills/design/impeccable/scripts/live/roots.mjs +508 -0
- package/template/.agents/skills/design/impeccable/scripts/live/session-store.mjs +324 -50
- package/template/.agents/skills/design/impeccable/scripts/live/source-lock.mjs +105 -0
- package/template/.agents/skills/design/impeccable/scripts/live/source-search.mjs +105 -0
- package/template/.agents/skills/design/impeccable/scripts/live/svelte-ast.mjs +961 -0
- package/template/.agents/skills/design/impeccable/scripts/live/svelte-component.mjs +588 -72
- package/template/.agents/skills/design/impeccable/scripts/live/sveltekit-adapter.mjs +59 -17
- package/template/.agents/skills/design/impeccable/scripts/live/tanstack-adapter.mjs +280 -0
- package/template/.agents/skills/design/impeccable/scripts/live/vocabulary.mjs +135 -0
- package/template/.agents/skills/design/impeccable/scripts/live-accept.mjs +210 -68
- package/template/.agents/skills/design/impeccable/scripts/live-browser.js +1562 -223
- package/template/.agents/skills/design/impeccable/scripts/live-commit-manual-edits.mjs +3 -0
- package/template/.agents/skills/design/impeccable/scripts/live-complete.mjs +33 -1
- package/template/.agents/skills/design/impeccable/scripts/live-inject.mjs +175 -255
- package/template/.agents/skills/design/impeccable/scripts/live-insert.mjs +26 -6
- package/template/.agents/skills/design/impeccable/scripts/live-manual-edit-evidence.mjs +6 -1
- package/template/.agents/skills/design/impeccable/scripts/live-poll.mjs +61 -16
- package/template/.agents/skills/design/impeccable/scripts/live-resume.mjs +39 -10
- package/template/.agents/skills/design/impeccable/scripts/live-server.mjs +573 -47
- package/template/.agents/skills/design/impeccable/scripts/live-status.mjs +17 -7
- package/template/.agents/skills/design/impeccable/scripts/live-wrap.mjs +124 -91
- package/template/.agents/skills/design/impeccable/scripts/live.mjs +88 -26
- package/template/.agents/skills/design/impeccable/scripts/palette.mjs +76 -81
- package/template/.agents/skills/design/impeccable/scripts/pin.mjs +18 -11
- package/template/.agents/skills/design/impeccable/scripts/serve-question.mjs +932 -0
- package/template/.agents/skills/design/impeccable/scripts/surface-brief.mjs +74 -0
- package/template/.agents/skills/design/shadcn/SKILL.md +46 -11
- package/template/.agents/skills/design/shadcn/cli.md +49 -16
- package/template/.agents/skills/design/shadcn/customization.md +14 -7
- package/template/.agents/skills/design/shadcn/evals/evals.json +30 -0
- package/template/.agents/skills/design/shadcn/mcp.md +27 -16
- package/template/.agents/skills/design/shadcn/registry.md +277 -0
- package/template/.agents/skills/design/shadcn/rules/chat.md +224 -0
- package/template/.agents/skills/design/shadcn/rules/composition.md +20 -2
- package/template/.agents/skills/design/shadcn/rules/styling.md +23 -0
- package/template/.agents/skills/find-skills/SKILL.md +2 -3
- package/template/.agents/skills/hono/SKILL.md +579 -0
- package/template/.agents/skills/integrations/langfuse/SKILL.md +10 -6
- package/template/.agents/skills/integrations/langfuse/references/ci-cd.md +41 -0
- package/template/.agents/skills/integrations/langfuse/references/cli.md +8 -0
- package/template/.agents/skills/integrations/langfuse/references/error-analysis.md +15 -27
- package/template/.agents/skills/integrations/langfuse/references/instrumentation.md +39 -52
- package/template/.agents/skills/integrations/langfuse/references/judge-calibration.md +5 -2
- package/template/.agents/skills/integrations/langfuse/references/prompt-engineering.md +35 -0
- package/template/.agents/skills/integrations/langfuse/references/prompt-migration.md +41 -196
- package/template/.agents/skills/integrations/langfuse/references/skill-feedback.md +3 -0
- package/template/.agents/skills/integrations/langfuse/references/trace-evaluator-upgrade.md +76 -0
- package/template/.agents/skills/integrations/langfuse/references/user-feedback.md +4 -0
- package/template/.agents/skills/integrations/langfuse/references/v4-project-migration.md +73 -0
- package/template/.agents/skills/supabase/CHANGELOG.md +71 -0
- package/template/.agents/skills/supabase/SKILL.md +145 -0
- package/template/.agents/skills/supabase/assets/feedback-issue-template.md +17 -0
- package/template/.agents/skills/supabase/references/skill-feedback.md +17 -0
- package/template/.agents/skills/supabase-postgres-best-practices/CHANGELOG.md +73 -0
- package/template/.agents/skills/supabase-postgres-best-practices/SKILL.md +64 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/_contributing.md +170 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/_sections.md +39 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/_template.md +34 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-limits.md +44 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-pagination.md +50 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-upsert.md +50 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-index-types.md +48 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-constraints.md +80 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/security-privileges.md +54 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/security-rls-performance.md +63 -0
- package/template/.agents/upstreams.json +34 -12
- package/template/.agents/skills/design/impeccable/reference/brand.md +0 -108
- package/template/.agents/skills/design/impeccable/reference/codex.md +0 -105
- package/template/.agents/skills/design/impeccable/reference/interaction-design.md +0 -189
- package/template/.agents/skills/integrations/langfuse/references/sdk-upgrade.md +0 -175
package/template/.agents/skills/design/impeccable/scripts/detector/engines/browser/detect-url.mjs
CHANGED
|
@@ -3,9 +3,68 @@ import path from 'node:path';
|
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
|
|
5
5
|
import { finding } from '../../findings.mjs';
|
|
6
|
-
import { filterByProviders } from '../../registry/antipatterns.mjs';
|
|
7
6
|
import { profileFindingsAsync, profileStep, profileStepAsync } from '../../profile/profiler.mjs';
|
|
8
7
|
import { captureVisualContrastCandidate } from '../visual/screenshot-contrast.mjs';
|
|
8
|
+
import { checkContentHiddenAtRest } from '../../rules/checks.mjs';
|
|
9
|
+
|
|
10
|
+
// On Windows, puppeteer's bundled Chrome lives in a user-writable cache
|
|
11
|
+
// directory. Its GPU process can be denied (STATUS_ACCESS_DENIED) by security
|
|
12
|
+
// software or the GPU sandbox because it launches from an untrusted path.
|
|
13
|
+
// Chrome then crash-loops the GPU process, and each relaunch briefly flashes a
|
|
14
|
+
// compositor surface, the black window users report during `detect <url>`
|
|
15
|
+
// (issue #372). The system-installed Chrome runs from a trusted location with a
|
|
16
|
+
// healthy GPU, so channel:'chrome' avoids the crash entirely; both use hardware
|
|
17
|
+
// GPU, so contrast measurement is unaffected. Scope this to Windows only: other
|
|
18
|
+
// platforms do not have the bug, so they keep the pinned bundled build for
|
|
19
|
+
// consistent measurement across machines. Fall back to bundled when the switch
|
|
20
|
+
// fails (Chrome not installed, or channel resolution fails). If the bundled
|
|
21
|
+
// launch then also fails, surface the original system-Chrome error as the
|
|
22
|
+
// cause so the real failure is not lost.
|
|
23
|
+
async function launchBrowser(puppeteer, { headless = true, args = [] } = {}) {
|
|
24
|
+
let channelError;
|
|
25
|
+
if (process.platform === 'win32') {
|
|
26
|
+
try {
|
|
27
|
+
return await puppeteer.default.launch({ channel: 'chrome', headless, args });
|
|
28
|
+
} catch (err) {
|
|
29
|
+
// System Chrome unavailable or unlaunchable; fall through to the bundled
|
|
30
|
+
// browser, but keep the error in case the fallback fails too.
|
|
31
|
+
channelError = err;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
return await puppeteer.default.launch({ headless, args });
|
|
36
|
+
} catch (err) {
|
|
37
|
+
if (channelError && err && err.cause === undefined) err.cause = channelError;
|
|
38
|
+
throw err;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Reveal sweep + invisible-text measurement for the content-hidden-at-rest
|
|
43
|
+
// rule. Scrolls through the document with instant jumps (bypasses CSS
|
|
44
|
+
// scroll-behavior: smooth) so IntersectionObserver / scroll reveal handlers
|
|
45
|
+
// get every chance to fire, returns to the top, lets transitions settle,
|
|
46
|
+
// then measures how much text still renders invisible. A healthy
|
|
47
|
+
// reveal-on-scroll page drops to ~0 after the sweep; a page whose reveal
|
|
48
|
+
// script died keeps most of its text at opacity 0.
|
|
49
|
+
async function measureContentHiddenAfterReveal(page) {
|
|
50
|
+
await page.evaluate(async () => {
|
|
51
|
+
const step = Math.max(200, Math.floor(window.innerHeight * 0.7));
|
|
52
|
+
const max = Math.max(
|
|
53
|
+
document.documentElement.scrollHeight || 0,
|
|
54
|
+
document.body?.scrollHeight || 0,
|
|
55
|
+
);
|
|
56
|
+
for (let y = 0; y <= max; y += step) {
|
|
57
|
+
window.scrollTo({ top: y, left: 0, behavior: 'instant' });
|
|
58
|
+
await new Promise(resolve => requestAnimationFrame(() => setTimeout(resolve, 40)));
|
|
59
|
+
}
|
|
60
|
+
window.scrollTo({ top: 0, left: 0, behavior: 'instant' });
|
|
61
|
+
await new Promise(resolve => setTimeout(resolve, 700));
|
|
62
|
+
});
|
|
63
|
+
return page.evaluate(() => {
|
|
64
|
+
if (typeof window.impeccableMeasureHiddenText !== 'function') return null;
|
|
65
|
+
return window.impeccableMeasureHiddenText();
|
|
66
|
+
});
|
|
67
|
+
}
|
|
9
68
|
|
|
10
69
|
function serializeDesignSystemForBrowser(designSystem) {
|
|
11
70
|
if (!designSystem?.present) return null;
|
|
@@ -151,13 +210,26 @@ async function detectUrl(url, options = {}) {
|
|
|
151
210
|
phase: 'load',
|
|
152
211
|
ruleId: 'launch-browser',
|
|
153
212
|
target: url,
|
|
154
|
-
}, () => puppeteer
|
|
213
|
+
}, () => launchBrowser(puppeteer, { headless: options?.headless ?? true, args: launchArgs }));
|
|
155
214
|
const page = await profileStepAsync(profile, {
|
|
156
215
|
engine: 'browser',
|
|
157
216
|
phase: 'load',
|
|
158
217
|
ruleId: 'new-page',
|
|
159
218
|
target: url,
|
|
160
219
|
}, () => browser.newPage());
|
|
220
|
+
|
|
221
|
+
// Uncaught exceptions and parse errors surface as pageerror events. The
|
|
222
|
+
// listener must attach before goto: a syntax error fires during the
|
|
223
|
+
// initial parse, long before the load event. Dedupe by message; a single
|
|
224
|
+
// broken loop can otherwise throw hundreds of identical errors.
|
|
225
|
+
const pageErrors = [];
|
|
226
|
+
if (options?.scriptErrors !== false) {
|
|
227
|
+
page.on('pageerror', (err) => {
|
|
228
|
+
const message = String(err?.message || err).split('\n')[0].trim().slice(0, 160);
|
|
229
|
+
if (message && !pageErrors.includes(message)) pageErrors.push(message);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
161
233
|
let results = [];
|
|
162
234
|
try {
|
|
163
235
|
await profileStepAsync(profile, {
|
|
@@ -213,9 +285,29 @@ async function detectUrl(url, options = {}) {
|
|
|
213
285
|
return window.impeccableDetect({ decorate: false, serialize: true });
|
|
214
286
|
});
|
|
215
287
|
return serializedGroups.flatMap(({ findings }) =>
|
|
216
|
-
findings.map(f => ({ id: f.type, snippet: f.detail, ignoreValue: f.ignoreValue || '' }))
|
|
288
|
+
findings.map(f => ({ id: f.type, snippet: f.detail, ignoreValue: f.ignoreValue || '', severity: f.severity || '' }))
|
|
217
289
|
);
|
|
218
290
|
});
|
|
291
|
+
// Content invisible at rest: reveal sweep, then re-measure. Runs after
|
|
292
|
+
// the main scan (which must see the true at-rest state) and before the
|
|
293
|
+
// visual contrast fallback (the sweep restores scroll to the top).
|
|
294
|
+
if (options?.contentHidden !== false) {
|
|
295
|
+
const hiddenFindings = await profileFindingsAsync(profile, {
|
|
296
|
+
engine: 'browser',
|
|
297
|
+
phase: 'scan',
|
|
298
|
+
ruleId: 'content-hidden-at-rest',
|
|
299
|
+
target: url,
|
|
300
|
+
}, async () => {
|
|
301
|
+
const measured = await measureContentHiddenAfterReveal(page);
|
|
302
|
+
return measured ? checkContentHiddenAtRest(measured) : [];
|
|
303
|
+
});
|
|
304
|
+
results.push(...hiddenFindings);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
for (const message of pageErrors.slice(0, 3)) {
|
|
308
|
+
results.push({ id: 'script-error', snippet: message });
|
|
309
|
+
}
|
|
310
|
+
|
|
219
311
|
const visualFindings = await runVisualContrastFallback(page, serializedGroups, options, profile, url);
|
|
220
312
|
results.push(...visualFindings);
|
|
221
313
|
} finally {
|
|
@@ -234,11 +326,14 @@ async function detectUrl(url, options = {}) {
|
|
|
234
326
|
}, () => browser.close());
|
|
235
327
|
}
|
|
236
328
|
}
|
|
237
|
-
return
|
|
329
|
+
return results.map(f => {
|
|
238
330
|
const item = finding(f.id, url, f.snippet);
|
|
239
331
|
if (f.ignoreValue) item.ignoreValue = f.ignoreValue;
|
|
332
|
+
// Per-finding severity promotion (e.g. hero-region pulsing dot)
|
|
333
|
+
// overrides the registry default carried by finding().
|
|
334
|
+
if (f.severity && f.severity !== item.severity) item.severity = f.severity;
|
|
240
335
|
return item;
|
|
241
|
-
})
|
|
336
|
+
});
|
|
242
337
|
}
|
|
243
338
|
|
|
244
339
|
async function createBrowserDetector(options = {}) {
|
|
@@ -249,7 +344,7 @@ async function createBrowserDetector(options = {}) {
|
|
|
249
344
|
throw new Error('puppeteer is required for URL scanning. Install: npm install puppeteer');
|
|
250
345
|
}
|
|
251
346
|
const launchArgs = options.launchArgs || (process.env.CI ? ['--no-sandbox', '--disable-setuid-sandbox'] : []);
|
|
252
|
-
const browser = options.browser || await puppeteer
|
|
347
|
+
const browser = options.browser || await launchBrowser(puppeteer, {
|
|
253
348
|
headless: options.headless ?? true,
|
|
254
349
|
args: launchArgs,
|
|
255
350
|
});
|
|
@@ -274,4 +369,4 @@ async function createBrowserDetector(options = {}) {
|
|
|
274
369
|
};
|
|
275
370
|
}
|
|
276
371
|
|
|
277
|
-
export { runVisualContrastFallback, detectUrl, createBrowserDetector };
|
|
372
|
+
export { runVisualContrastFallback, detectUrl, createBrowserDetector, launchBrowser };
|