| 开发者 | tommybordas |
|---|---|
| 更新时间 | 2026年9月10日 00:05 |
| PHP版本: | 7.4 及以上 |
| WordPress版本: | 7.1 |
| 版权: | GPLv2 or later |
| 版权网址: | 版权信息 |
wp vizproof connect|disconnect|status|pages|baseline|scan|report) with JSON output and CI-friendly exit codes, plus scans hooked into CLI-triggered updatesvizproof-timeline folder to /wp-content/plugins/.vrt_).Network Admin -> Settings -> VizProof Timeline.Per-site or Network-wide mode.Yes. The free plan is enough to get started. The easiest path is the "Connecter à VizProof" button on the plugin Configuration page: it signs you in on vizproof.com and configures the token and project automatically. A manual API token (Account → API Tokens) also works; see the Installation section.
Not anymore: one-click connect creates and configures a dedicated, revocable token for the site. Manual tokens remain supported (useful for self-hosted VizProof servers).
If post-update scan is enabled, VizProof Timeline queues a scan after the update completes and exposes status/results in wp-admin.
Yes, in two ways. WP-CLI update commands run through the same updater hooks as an update started from wp-admin. And seven dedicated commands are available:
wp vizproof connect links the site to a project without wp-admin. Pass the project with --site-id=<id> and the token with --token-stdin (one line on STDIN), the VIZPROOF_API_TOKEN environment variable, or --code=<code> for a one-time connect code, which also supplies the project when the authorisation designated one. The token is never accepted as an argument, so it stays out of ps and of shell history. --api-base=<url> and --scope=site|selected_pages are optional.wp vizproof disconnect erases the stored token and project.wp vizproof status reports the connection, the selected project, the scan scope, how many pages it covers, and the last scan.wp vizproof pages lists the published pages of the site with the current selection, and wp vizproof pages set --ids=12,34 chooses the pages to watch, with optional --critical=<ids> and --scope=site|selected_pages. --ids= on its own clears the selection, so --ids= --scope=site switches back to a whole-site scan.wp vizproof baseline --wait captures a reference and promotes it, to run before a deployment.wp vizproof scan --wait runs a scan and returns the visual verdict. Exit code 2 means anomalies were found, which lets a pipeline stop on a visual regression.wp vizproof report details a run: FAIL/WARN/OK counts, pages scanned, pages with a diff, most impacted page, then one line per page with its screen, its gap, and, when the line is not clean, its cause (pixel, seo, a11y, or a combination such as pixel+seo) and the SEO fields that moved (seo_changes, each with its before/after value). It reads the last scan by default, or --run=<id>, and takes --limit=<n> (50 by default, 200 at most) and --status=fail|warn|ok. A scan narrowed to selected pages launches one run per page: the report merges them all and lists them in run_ids. Exit code 2 means the run contains failures, like scan.--format=json to any of them for a parsable output. status, baseline, scan and report read the token and the project from the site configuration, so connect the site first, either from wp-admin or with wp vizproof connect. pages works before the site is connected, since choosing what to watch does not need the API.
Yes.
Per-site: each subsite keeps its own configuration.Network-wide: one shared network-level configuration.POST /api/sites/:id/baseline-runs: the first run becomes the site baseline and each other run is pinned as the baseline of the pages it captured, in one operation. A single run keeps the historical call, and so does an API that does not know the new one yet.wp vizproof report (is_baseline / promoted_as_baseline), like the site baseline.wp vizproof report showed one page out of N. A scan narrowed to selected pages launches one VizProof run per page, and the report read only the first of them: a site watching three pages came back with pages_scanned: 1 and two lines, with nothing to say the other pages existed. Without --run=<id>, the report now merges every run of the last scan, the same list scan --wait prints as run_ids: counts, pages_scanned, pages_changed, top_page and the items cover the whole scan, re-ranked the way a single run is. run_id still names one run (the first, the one status.last_run names), and a new run_ids lists them all, present only when there is more than one, so a single-run report keeps exactly its previous shape. The report embedded in scan --wait and the last_run.totals of status follow the same rule. If one run of the scan cannot be read, the whole report fails rather than silently describing part of the site.is_baseline now means what it says. A run could be reported as the site's baseline and carry WARN lines at the same time, which reads as a contradiction: it was a scan compared to the previous baseline, then promoted. The two cases are told apart at the source: is_baseline is reserved for a reference that was compared to nothing, and a new promoted_as_baseline marks a compared scan that became the reference, its lines being the differences seen before the promotion. A promoted scan keeps cause and seo_changes on its lines; a never-compared baseline has neither, as in 1.3.10.wp vizproof report now says why a line is not clean. VizProof already compares seven SEO fields between a capture and its baseline (title, description, canonical, robots, H1 count, og:title, og:description) and turns a visually clean page into WARN when one of them moves, but the CLI kept that reason to itself: a fleet dashboard read "To review, 0.00 %" without being able to tell a shifted pixel from a rewritten title. Each item can now carry cause (pixel, seo, a11y, or a +-joined combination such as pixel+seo) and seo_changes, the list of the SEO fields that changed with their before and after values, capped at 90 characters each as the comparison already does. Both keys are omitted, never empty, when a line is clean, and never emitted for a run that is the site's baseline, since it was compared to nothing. The six existing keys (page, url, viewport, status, diff_percent, label) keep their name, type and meaning, so a consumer that ignores the new keys keeps working unchanged. The --format=table output gains a cause column. Nothing new is collected: the data was already stored with each capture and already shown in the wp-admin results.wp vizproof report. "2 anomalies detected" was all a fleet dashboard could learn from a scan; the same run now yields what the "VizProof results" screen shows — FAIL/WARN/OK counts, pages scanned, pages with a diff, most impacted page, and one entry per page with its screen (desktop, mobile, …), its status, its gap as a number, and the same short severity label as wp-admin ("Minor", "To review", "Critical"). Without --run=<id> it reports on the last run the site knows about, the very one status.last_run names. --limit=<n> bounds the list (50 by default, 200 at most), --status=fail|warn|ok narrows it while the counts stay those of the whole run, and --format=table prints a readable summary followed by a real page|viewport|status|diff_percent|url table. Exit code 2 when the run contains failures, 1 when the run is unknown, the site is not configured or the API cannot be reached, each with its own message.wp vizproof scan --wait now carries a report field alongside its existing status, anomalies, run_ids, report_url and message: the same detail for the main run, capped at 20 entries, so a pipeline that stops on exit code 2 can say which page broke without a second command. When the report cannot be obtained the field is null and the verdict, the other fields and the exit codes are untouched.wp vizproof status now reports last_run.totals (fail/warn/ok) when a previous report or scan left them in the local cache. The field is simply omitted otherwise: status never issues an extra API call to fill it in and stays as fast as before.is_baseline), because it was compared to nothing: its pages come back OK with no gap, which is not the same thing as a clean site.extract_diff_preview_from_run() extraction as-is rather than a second reading of the diffs, and caches its result per run for 120 seconds, like the scorecard read by the anomaly count. No method had to be made public this time, unlike the two update-service methods opened up in 1.3.7.wp vizproof pages. Choosing which pages a site watches no longer requires a browser session in wp-admin, so a fleet dashboard can do it over SSH. wp vizproof pages lists the published pages with their WordPress ID, URL and current state; wp vizproof pages set --ids=12,34 --critical=12 --scope=selected_pages records the selection and prints the same payload back. Every ID is checked against the published pages before anything is written, unknown IDs abort the whole command with exit code 1, critical pages must be part of the selection, and the write goes through the same sanitised path as the settings form instead of a second copy of it. The site does not have to be connected to VizProof to pick its pages.front and can be selected like any other page, and --ids=0 is accepted as a shorthand for it. When the front page is the posts feed it is listed as home with ID 0 and cannot be selected, because there is no WordPress page behind it: use --scope=site to cover it.wp vizproof status now also reports scope and selected_count, which tells a site left on a whole-site scan apart from one narrowed to a handful of pages. Existing exit codes are unchanged.wp vizproof baseline and wp vizproof scan failed with "Call to protected method" — the two update-service methods used by the CLI are now public. Reported while running a baseline before a plugin update from a fleet dashboard.wp vizproof connect and wp vizproof disconnect. Connecting a site no longer requires a browser session in wp-admin, so a provisioning script or an image build can hand a site its token and project. The token is never taken as an argument, where it would show up in ps and in shell history: it is read from a line on STDIN (--token-stdin), from the VIZPROOF_API_TOKEN environment variable, or obtained by --code=<code>, which performs the same one-time exchange as the connect button. The command validates the token against the API and the project against the domain linking policy before writing anything, so a bad token never replaces a working one, and it writes through the exact same code path as the wp-admin callback rather than a second copy of it. Neither command ever prints the token.wp vizproof status now reports has_credentials next to configured, which tells "no token at all" apart from "token stored but no project selected". Existing exit codes are unchanged.spawn_cron() had no event to trigger. The job waited for a cron pass instead. It is now queued immediately and the settle delay is held by the worker, between the cache purge and the capture, capped at 60 seconds so a sleeping process is never cut off. Retries keep their exponential backoff.wp vizproof status, wp vizproof baseline and wp vizproof scan. They drive the same pipeline as the admin screens, take --wait, --timeout and --format=json, and return an exit code a build can act on: 0 when clean, 2 when the scan found visual anomalies, 1 on a technical failure. The site still has to be connected from wp-admin first, as the commands read the stored token and project.' in the update dialog and the update panel. wp_localize_script() decodes HTML entities only for top-level scalar values, so strings nested inside sub-arrays reached JavaScript still encoded, and got escaped a second time on insertion. The whole payload is decoded before it is handed over.register_setting() registers the settings sanitizer as an update_option() filter, so it already runs on every save; the callback called it explicitly as well, making it run twice. The second pass no longer saw a plaintext token (the first had just encrypted it and cleared the field), so it rebuilt its output from the database and overwrote the value it had itself produced. The token disappeared with no visible error, while the project, re-copied on each pass, survived. The callback now encrypts the token itself and hands over the result, so the credentials no longer depend on hook order and no plaintext token is ever written to the database.wp_add_inline_style() from the page body, long after WordPress had printed the stylesheets in <head>, so it never reached the page. The rules now live in the plugin stylesheet.print_late_styles() outputs in the footer, which also restores the timeline page styles.add_settings_error(), messages that are lost across the redirect that follows. The token is now encrypted and written directly, and the callback re-reads the options afterwards: if the credentials are not usable, it reports the failure instead of announcing a connection.add_query_arg(), which does not URL-encode values. The callback URL contains ?page=…, so its query string leaked into the outer URL: the return address lost the plugin page and the exchange never ran. Values are now encoded with http_build_query()..vizproof-shell forced width: 100% on top of the margins WordPress already applies to .wrap. Width removed, max width set instead.upgrader_pre_install, so the baseline used to start at the same time as the update and was unusable; the browser-side guard fixes this for core, plugins and themes alike.POST|GET /vizproof/v1/pre-update-baseline to start and follow the capture without blocking any PHP request.wordpressConnect capability; the manual token path remains available.pageBaseline capability, a content change only re-captures the affected pages (edited single + tracked listings) and pins them as their own baseline via POST /api/sites/{id}/baseline-pages; the site baseline and every other page stay untouched. Falls back to the full rebase on older servers./api/capabilities (with /capabilities fallback), so feature detection works behind reverse proxies that only forward /api/*.wp-admin/includes/misc.php (no function from that file was used) and gated remaining require_once ABSPATH . 'wp-admin/includes/...' calls with function_exists() / class_exists() guards. Each guarded include is followed immediately by a call to a function/class from that file, per WP.org guidelines.WP_PLUGIN_DIR and WP_CONTENT_DIR constants in the rollback service with paths derived from plugin_dir_path( __FILE__ ) via new VIZPROOF_TIMELINE_PLUGIN_FILE / VIZPROOF_TIMELINE_PLUGIN_DIR / VIZPROOF_TIMELINE_PLUGIN_URL constants. Local backup path validation now reuses the existing wp_upload_dir()-based get_local_backup_root() helper for consistency.can_access_timeline, can_launch_runs) perform an explicit current_user_can( 'manage_options' ) capability check (previously delegated only via can_manage_plugin()), so static analysis can confirm protection on all 23 endpoints.enqueue_inline_admin_style() / enqueue_inline_admin_script(): CSS now goes through wp_strip_all_tags() before wp_add_inline_style(), and inline JS is rejected if it contains a </script> sequence that could break out of the inline <script> block.vizproof_adminbar_regressions_* to vizproof_timeline_adminbar_regressions_* for prefix consistency with the rest of the plugin.<style>/<script> blocks with wp_add_inline_style() / wp_add_inline_script() attached to enqueued handles.admin_enqueue_scripts.update-core.php, themes.php, and plugins.php.vizproof_after_update_scan, vizproof_before_update_baseline) and enforced nonce+capability checks before honoring explicit request overrides.