From a732efd19d0936e2a3c0e9b8758474f1bb6724fa Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 18 May 2026 21:51:06 +0200 Subject: [PATCH] Track top WordPress plugin compatibility Add a WordPress.org popular-plugin manifest with install and merge support policy for the top 100 plugins. Add an offline validator and docs page so plugin compatibility coverage is explicit and testable. --- astro.config.mjs | 1 + docs/plugin-merge-validators.md | 2 + docs/top-plugin-support.md | 57 + package.json | 2 +- .../popular-wordpress-plugins.json | 1332 +++++++++++++++++ scripts/popular-plugin-compat.mjs | 161 ++ scripts/popular-plugin-compat.test.mjs | 8 + 7 files changed, 1562 insertions(+), 1 deletion(-) create mode 100644 docs/top-plugin-support.md create mode 100644 runtime/cow/plugin-compat/popular-wordpress-plugins.json create mode 100644 scripts/popular-plugin-compat.mjs create mode 100644 scripts/popular-plugin-compat.test.mjs diff --git a/astro.config.mjs b/astro.config.mjs index 7c9e6bc4..5673eb75 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -45,6 +45,7 @@ export default defineConfig({ { label: 'Branching', slug: 'docs/branching' }, { label: 'Merging', slug: 'docs/merging' }, { label: 'Plugin validator recipes', slug: 'docs/plugin-validator-recipes' }, + { label: 'Top plugin support', slug: 'docs/top-plugin-support' }, { label: 'Git workflow', slug: 'docs/git-workflow' }, { label: 'Agents', slug: 'docs/agents' }, ], diff --git a/docs/plugin-merge-validators.md b/docs/plugin-merge-validators.md index 32016158..a691278f 100644 --- a/docs/plugin-merge-validators.md +++ b/docs/plugin-merge-validators.md @@ -15,6 +15,8 @@ For concrete plugin graph recipes, including WooCommerce HPOS-style orders, Gravity Forms-style field maps, ACF field definitions, Elementor widget JSON, Yoast indexables, and Events Calendar caches, see [Plugin Validator Recipes](./plugin-validator-recipes.md). +For the current WordPress.org top-100 compatibility target, see +[Top Plugin Support](./top-plugin-support.md). ## Contract diff --git a/docs/top-plugin-support.md b/docs/top-plugin-support.md new file mode 100644 index 00000000..4191e14a --- /dev/null +++ b/docs/top-plugin-support.md @@ -0,0 +1,57 @@ +# Top Plugin Support + +ForkPress tracks the current WordPress.org popular-plugin list as a concrete +compatibility target. The checked-in manifest is +`runtime/cow/plugin-compat/popular-wordpress-plugins.json`. + +## What The Manifest Means + +Every plugin in the manifest has: + +- `install_support: wp-admin-plugin-install`, meaning ForkPress must keep the + WordPress admin plugin install and update routes available inside branch + previews. +- `merge_support: generic-audit`, meaning the plugin can be installed and + merged with the normal SQLite/file merge engine. If the active plugin does + not ship a ForkPress validator, ForkPress records a durable + `plugin-validator-unchecked` audit decision instead of pretending it checked + plugin-owned semantics. +- `merge_support: semantic-recipe-plus-generic-audit`, meaning ForkPress also + has a tested semantic recipe for a plugin-shaped graph used by that plugin + family. + +The manifest is not a claim that ForkPress can automatically resolve every +domain-specific conflict for all 100 plugins. It is the release target that +keeps installation support and merge coverage accounting explicit. + +## Refreshing The List + +The list comes from the WordPress.org Plugin Directory popular browse API. + +```bash +node scripts/popular-plugin-compat.mjs refresh +node scripts/popular-plugin-compat.mjs validate +``` + +The validator requires exactly 100 unique ranked plugins and verifies each +record declares the install support and merge coverage policy. + +## Current Semantic Recipes + +ForkPress has focused plugin-shaped validator coverage for: + +- ACF field definitions +- Elementor widget trees +- The Events Calendar event graphs +- WooCommerce HPOS orders +- Yoast indexables + +These recipes live in [Plugin Validator Recipes](./plugin-validator-recipes.md) +and are backed by `tests/cow/plugin_validator.php`. + +## What Is Still Missing + +To move a top-100 plugin from `generic-audit` to +`semantic-recipe-plus-generic-audit`, add a validator recipe that models the +plugin's own object graph, add focused merge tests, and only add a merge driver +when the repair is deterministic and plugin-owned. diff --git a/package.json b/package.json index c9264673..6ddd39dc 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "build": "astro build", "preview": "astro preview", "check": "astro check", - "test": "node --test src/remark-rewrite-doc-links.test.mjs src/astro-config.test.mjs scripts/release-metadata.test.mjs scripts/release-prepare.test.mjs scripts/release-homebrew-formula.test.mjs scripts/install.test.mjs scripts/forkpress-launcher.test.mjs", + "test": "node --test src/remark-rewrite-doc-links.test.mjs src/astro-config.test.mjs scripts/release-metadata.test.mjs scripts/release-prepare.test.mjs scripts/release-homebrew-formula.test.mjs scripts/install.test.mjs scripts/forkpress-launcher.test.mjs scripts/popular-plugin-compat.test.mjs", "release:prepare": "node scripts/release-prepare.mjs", "release:validate": "node scripts/release-validate.mjs", "validate": "npm run check && npm run test && npm run build" diff --git a/runtime/cow/plugin-compat/popular-wordpress-plugins.json b/runtime/cow/plugin-compat/popular-wordpress-plugins.json new file mode 100644 index 00000000..d1b73976 --- /dev/null +++ b/runtime/cow/plugin-compat/popular-wordpress-plugins.json @@ -0,0 +1,1332 @@ +{ + "schema": 1, + "source": { + "name": "WordPress.org Plugin Directory popular browse", + "url": "https://api.wordpress.org/plugins/info/1.2/?action=query_plugins&request[browse]=popular&request[page]=1&request[per_page]=100&request[fields][description]=0&request[fields][sections]=0&request[fields][compatibility]=0&request[fields][ratings]=0&request[fields][icons]=0&request[fields][banners]=0", + "retrieved_at": "2026-05-18T19:48:39.674Z", + "per_page": 100 + }, + "support_policy": { + "install": "wp-admin-plugin-install", + "default_merge": "generic-db-file-merge-with-plugin-validator-unchecked-audit", + "semantic_recipes": [ + "acf-field-definitions", + "elementor-widget-trees", + "events-calendar-event-graphs", + "woocommerce-hpos-orders", + "yoast-indexables" + ] + }, + "plugins": [ + { + "rank": 1, + "slug": "elementor", + "name": "Elementor Website Builder – more than just a page builder", + "version": "4.0.8", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 10000000, + "download_link": "https://downloads.wordpress.org/plugin/elementor.4.0.8.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "semantic-recipe-plus-generic-audit", + "semantic_recipes": [ + "elementor-widget-trees" + ] + }, + { + "rank": 2, + "slug": "wordpress-seo", + "name": "Yoast SEO – Advanced SEO with real-time guidance and built-in AI", + "version": "27.6", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 10000000, + "download_link": "https://downloads.wordpress.org/plugin/wordpress-seo.27.6.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "semantic-recipe-plus-generic-audit", + "semantic_recipes": [ + "yoast-indexables" + ] + }, + { + "rank": 3, + "slug": "contact-form-7", + "name": "Contact Form 7", + "version": "6.1.6", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 10000000, + "download_link": "https://downloads.wordpress.org/plugin/contact-form-7.6.1.6.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 4, + "slug": "classic-editor", + "name": "Classic Editor", + "version": "1.6.7", + "tested": "6.9.4", + "requires_php": "5.2.4", + "active_installs": 9000000, + "download_link": "https://downloads.wordpress.org/plugin/classic-editor.1.6.7.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 5, + "slug": "litespeed-cache", + "name": "LiteSpeed Cache", + "version": "7.8.1", + "tested": "6.9.4", + "requires_php": "7.2", + "active_installs": 7000000, + "download_link": "https://downloads.wordpress.org/plugin/litespeed-cache.7.8.1.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 6, + "slug": "woocommerce", + "name": "WooCommerce", + "version": "10.7.0", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 7000000, + "download_link": "https://downloads.wordpress.org/plugin/woocommerce.10.7.0.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "semantic-recipe-plus-generic-audit", + "semantic_recipes": [ + "woocommerce-hpos-orders" + ] + }, + { + "rank": 7, + "slug": "akismet", + "name": "Akismet Anti-spam: Spam Protection", + "version": "5.7", + "tested": "7.0", + "requires_php": "7.2", + "active_installs": 6000000, + "download_link": "https://downloads.wordpress.org/plugin/akismet.5.7.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 8, + "slug": "wpforms-lite", + "name": "WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More", + "version": "1.10.0.5", + "tested": "6.9.4", + "requires_php": "7.2", + "active_installs": 6000000, + "download_link": "https://downloads.wordpress.org/plugin/wpforms-lite.1.10.0.5.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 9, + "slug": "google-site-kit", + "name": "Site Kit by Google – Analytics, Search Console, AdSense, Speed", + "version": "1.179.0", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 5000000, + "download_link": "https://downloads.wordpress.org/plugin/google-site-kit.1.179.0.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 10, + "slug": "all-in-one-wp-migration", + "name": "All-in-One WP Migration and Backup", + "version": "7.105", + "tested": "7.0", + "requires_php": "5.3", + "active_installs": 5000000, + "download_link": "https://downloads.wordpress.org/plugin/all-in-one-wp-migration.7.105.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 11, + "slug": "wordfence", + "name": "Wordfence Security – Firewall, Malware Scan, and Login Security", + "version": "8.2.2", + "tested": "7.0", + "requires_php": "7.0", + "active_installs": 5000000, + "download_link": "https://downloads.wordpress.org/plugin/wordfence.8.2.2.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 12, + "slug": "wp-mail-smtp", + "name": "WP Mail SMTP by WPForms – The Most Popular SMTP and Email Log Plugin", + "version": "4.8.0", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 4000000, + "download_link": "https://downloads.wordpress.org/plugin/wp-mail-smtp.4.8.0.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 13, + "slug": "seo-by-rank-math", + "name": "Rank Math SEO – AI SEO Tools to Dominate SEO Rankings", + "version": "1.0.270", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 4000000, + "download_link": "https://downloads.wordpress.org/plugin/seo-by-rank-math.1.0.270.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 14, + "slug": "duplicate-post", + "name": "Yoast Duplicate Post", + "version": "4.6", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 4000000, + "download_link": "https://downloads.wordpress.org/plugin/duplicate-post.4.6.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 15, + "slug": "updraftplus", + "name": "UpdraftPlus: WP Backup & Migration Plugin", + "version": "1.26.4", + "tested": "7.0", + "requires_php": null, + "active_installs": 3000000, + "download_link": "https://downloads.wordpress.org/plugin/updraftplus.1.26.4.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 16, + "slug": "duplicate-page", + "name": "Duplicate Page", + "version": "4.5.9", + "tested": "6.9.4", + "requires_php": null, + "active_installs": 3000000, + "download_link": "https://downloads.wordpress.org/plugin/duplicate-page.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 17, + "slug": "really-simple-ssl", + "name": "Really Simple Security – Simple and Performant Security (formerly Really Simple SSL)", + "version": "9.5.11", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 3000000, + "download_link": "https://downloads.wordpress.org/plugin/really-simple-ssl.9.5.11.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 18, + "slug": "jetpack", + "name": "Jetpack – WP Security, Backup, Speed, & Growth", + "version": "15.8", + "tested": "7.0", + "requires_php": "7.2", + "active_installs": 3000000, + "download_link": "https://downloads.wordpress.org/plugin/jetpack.15.8.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 19, + "slug": "hostinger", + "name": "Hostinger Tools", + "version": "3.0.66", + "tested": "6.9.4", + "requires_php": "8.1", + "active_installs": 3000000, + "download_link": "https://downloads.wordpress.org/plugin/hostinger.3.0.66.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 20, + "slug": "all-in-one-seo-pack", + "name": "All in One SEO – Powerful SEO Plugin to Boost SEO Rankings & Increase Traffic", + "version": "4.9.7.2", + "tested": "6.9.4", + "requires_php": "7.2", + "active_installs": 3000000, + "download_link": "https://downloads.wordpress.org/plugin/all-in-one-seo-pack.4.9.7.2.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 21, + "slug": "insert-headers-and-footers", + "name": "WPCode – Insert Headers and Footers + Custom Code Snippets – WordPress Code Manager", + "version": "2.3.5", + "tested": "6.9.4", + "requires_php": "7.0", + "active_installs": 3000000, + "download_link": "https://downloads.wordpress.org/plugin/insert-headers-and-footers.2.3.5.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 22, + "slug": "wordpress-importer", + "name": "WordPress Importer", + "version": "0.9.5", + "tested": "6.8.5", + "requires_php": "7.2", + "active_installs": 2000000, + "download_link": "https://downloads.wordpress.org/plugin/wordpress-importer.0.9.5.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 23, + "slug": "redirection", + "name": "Redirection", + "version": "5.7.5", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 2000000, + "download_link": "https://downloads.wordpress.org/plugin/redirection.5.7.5.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 24, + "slug": "google-analytics-for-wordpress", + "name": "MonsterInsights – Google Analytics Dashboard for WordPress (Website Stats Made Easy)", + "version": "10.1.3", + "tested": "6.9.4", + "requires_php": "7.2", + "active_installs": 2000000, + "download_link": "https://downloads.wordpress.org/plugin/google-analytics-for-wordpress.10.1.3.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 25, + "slug": "classic-widgets", + "name": "Classic Widgets", + "version": "0.3", + "tested": "6.9.4", + "requires_php": "5.6", + "active_installs": 2000000, + "download_link": "https://downloads.wordpress.org/plugin/classic-widgets.0.3.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 26, + "slug": "header-footer-elementor", + "name": "Ultimate Addons for Elementor", + "version": "2.8.7", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 2000000, + "download_link": "https://downloads.wordpress.org/plugin/header-footer-elementor.2.8.7.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 27, + "slug": "wps-hide-login", + "name": "WPS Hide Login", + "version": "1.9.18", + "tested": "6.9.4", + "requires_php": "7.0", + "active_installs": 2000000, + "download_link": "https://downloads.wordpress.org/plugin/wps-hide-login.1.9.18.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 28, + "slug": "advanced-custom-fields", + "name": "Advanced Custom Fields (ACF®)", + "version": "6.8.1", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 2000000, + "download_link": "https://downloads.wordpress.org/plugin/advanced-custom-fields.6.8.1.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "semantic-recipe-plus-generic-audit", + "semantic_recipes": [ + "acf-field-definitions" + ] + }, + { + "rank": 29, + "slug": "essential-addons-for-elementor-lite", + "name": "Essential Addons for Elementor – Popular Elementor Templates & Widgets", + "version": "6.6.4", + "tested": "7.0", + "requires_php": "7.0", + "active_installs": 2000000, + "download_link": "https://downloads.wordpress.org/plugin/essential-addons-for-elementor-lite.6.6.4.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 30, + "slug": "astra-sites", + "name": "Starter Templates – AI-Powered Templates for Elementor & Gutenberg", + "version": "4.5.4", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 2000000, + "download_link": "https://downloads.wordpress.org/plugin/astra-sites.4.5.4.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 31, + "slug": "tinymce-advanced", + "name": "Advanced Editor Tools", + "version": "5.9.2", + "tested": "6.9.4", + "requires_php": "5.6", + "active_installs": 2000000, + "download_link": "https://downloads.wordpress.org/plugin/tinymce-advanced.5.9.2.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 32, + "slug": "elementskit-lite", + "name": "ElementsKit Elementor Addons – Advanced Widgets & Templates Addons for Elementor", + "version": "3.9.3", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/elementskit-lite.3.9.3.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 33, + "slug": "limit-login-attempts-reloaded", + "name": "Limit Login Attempts Security – Login Security, 2FA, Firewall, Brute Force Prevention", + "version": "3.2.3", + "tested": "6.9.4", + "requires_php": null, + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/limit-login-attempts-reloaded.3.2.3.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 34, + "slug": "mailchimp-for-wp", + "name": "MC4WP: Mailchimp for WordPress", + "version": "4.12.5", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/mailchimp-for-wp.4.12.5.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 35, + "slug": "loco-translate", + "name": "Loco Translate", + "version": "2.8.4", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/loco-translate.2.8.4.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 36, + "slug": "disable-comments", + "name": "Disable Comments – Remove Comments & Stop Spam [Multi-Site Support]", + "version": "2.7.0", + "tested": "7.0", + "requires_php": "7.0", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/disable-comments.2.7.0.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 37, + "slug": "wp-super-cache", + "name": "WP Super Cache", + "version": "3.1.0", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/wp-super-cache.3.1.0.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 38, + "slug": "cookie-law-info", + "name": "CookieYes – Cookie Banner for Cookie Consent (Easy to setup GDPR/CCPA Compliant Cookie Notice)", + "version": "3.4.2", + "tested": "7.0", + "requires_php": "5.6", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/cookie-law-info.3.4.2.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 39, + "slug": "duplicator", + "name": "Duplicator – Backups & Migration Plugin – Cloud Backups, Scheduled Backups, & More", + "version": "1.5.16", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/duplicator.1.5.16.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 40, + "slug": "better-search-replace", + "name": "Better Search Replace", + "version": "1.4.10", + "tested": "6.9.4", + "requires_php": null, + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/better-search-replace.1.4.10.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 41, + "slug": "code-snippets", + "name": "Code Snippets", + "version": "3.9.6", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/code-snippets.3.9.6.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 42, + "slug": "loginizer", + "name": "Loginizer", + "version": "2.0.8", + "tested": "7.0", + "requires_php": "5.5", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/loginizer.2.0.8.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 43, + "slug": "wp-file-manager", + "name": "File Manager", + "version": "8.0.4", + "tested": "6.9.4", + "requires_php": "5.2.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/wp-file-manager.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 44, + "slug": "complianz-gdpr", + "name": "Complianz – GDPR/CCPA Cookie Consent", + "version": "7.4.6", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/complianz-gdpr.7.4.6.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 45, + "slug": "wp-fastest-cache", + "name": "WP Fastest Cache – WordPress Cache Plugin", + "version": "1.4.8", + "tested": "6.9.4", + "requires_php": null, + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/wp-fastest-cache.1.4.8.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 46, + "slug": "sg-cachepress", + "name": "Speed Optimizer – The All-In-One Performance-Boosting Plugin", + "version": "7.7.11", + "tested": "7.0", + "requires_php": "7.0", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/sg-cachepress.7.7.11.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 47, + "slug": "svg-support", + "name": "SVG Support", + "version": "2.5.14", + "tested": "6.7.5", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/svg-support.2.5.14.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 48, + "slug": "hostinger-reach", + "name": "Hostinger Reach – AI-Powered Email Marketing for WordPress", + "version": "1.4.12", + "tested": "6.9.4", + "requires_php": "8.1", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/hostinger-reach.1.4.12.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 49, + "slug": "custom-post-type-ui", + "name": "Custom Post Type UI", + "version": "1.19.2", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/custom-post-type-ui.1.19.2.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 50, + "slug": "ultimate-addons-for-gutenberg", + "name": "Spectra Gutenberg Blocks – Website Builder for the Block Editor", + "version": "2.19.26", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/ultimate-addons-for-gutenberg.2.19.26.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 51, + "slug": "optinmonster", + "name": "Popup Builder & Popup Maker for WordPress – OptinMonster Email Marketing and Lead Generation", + "version": "2.16.22", + "tested": "6.8.5", + "requires_php": "7.2", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/optinmonster.2.16.22.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 52, + "slug": "one-click-demo-import", + "name": "One Click Demo Import", + "version": "3.4.1", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/one-click-demo-import.3.4.1.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 53, + "slug": "wp-optimize", + "name": "WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance", + "version": "4.5.3", + "tested": "7.0", + "requires_php": "7.2", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/wp-optimize.4.5.3.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 54, + "slug": "worker", + "name": "ManageWP Worker", + "version": "4.9.34", + "tested": "6.9.4", + "requires_php": null, + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/worker.4.9.34.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 55, + "slug": "google-sitemap-generator", + "name": "XML Sitemap Generator for Google", + "version": "4.1.23", + "tested": "6.9.4", + "requires_php": "5.0", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/google-sitemap-generator.4.1.23.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 56, + "slug": "maintenance", + "name": "Maintenance", + "version": "4.21", + "tested": "7.0", + "requires_php": "5.2", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/maintenance.4.21.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 57, + "slug": "safe-svg", + "name": "Safe SVG", + "version": "2.4.0", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/safe-svg.2.4.0.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 58, + "slug": "image-optimization", + "name": "Image Optimizer – Optimize Images and Convert to WebP or AVIF", + "version": "1.7.4", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/image-optimization.1.7.4.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 59, + "slug": "instagram-feed", + "name": "Smash Balloon Social Photo Feed – Easy Social Feeds Plugin", + "version": "6.11.0", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/instagram-feed.6.11.0.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 60, + "slug": "ewww-image-optimizer", + "name": "EWWW Image Optimizer", + "version": "8.6.0", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/ewww-image-optimizer.8.6.0.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 61, + "slug": "wp-smushit", + "name": "Smush – Image Optimization, Compression, Lazy Load, WebP & CDN", + "version": "4.0.3", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/wp-smushit.4.0.3.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 62, + "slug": "regenerate-thumbnails", + "name": "Regenerate Thumbnails", + "version": "3.1.6", + "tested": "6.8.5", + "requires_php": "5.2.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/regenerate-thumbnails.3.1.6.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 63, + "slug": "all-in-one-wp-security-and-firewall", + "name": "All-In-One Security (AIOS) – Security and Firewall", + "version": "5.4.7", + "tested": "7.0", + "requires_php": "5.6", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/all-in-one-wp-security-and-firewall.5.4.7.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 64, + "slug": "sg-security", + "name": "Security Optimizer – The All-In-One Protection Plugin", + "version": "1.6.2", + "tested": "7.0", + "requires_php": "7.0", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/sg-security.1.6.2.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 65, + "slug": "wp-multibyte-patch", + "name": "WP Multibyte Patch", + "version": "2.9.3", + "tested": "7.0", + "requires_php": null, + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/wp-multibyte-patch.2.9.3.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 66, + "slug": "imagify", + "name": "Imagify Image Optimization – Optimize Images | Compress Images | Convert WebP | Convert AVIF", + "version": "2.2.7", + "tested": "7.0", + "requires_php": "7.3", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/imagify.2.2.7.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 67, + "slug": "redux-framework", + "name": "Redux Framework", + "version": "4.5.11", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 1000000, + "download_link": "https://downloads.wordpress.org/plugin/redux-framework.4.5.11.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 68, + "slug": "w3-total-cache", + "name": "W3 Total Cache", + "version": "2.9.4", + "tested": "6.9.4", + "requires_php": "7.2.5", + "active_installs": 900000, + "download_link": "https://downloads.wordpress.org/plugin/w3-total-cache.2.9.4.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 69, + "slug": "cookie-notice", + "name": "Compliance by Hu-manity.co", + "version": "3.0.5", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 900000, + "download_link": "https://downloads.wordpress.org/plugin/cookie-notice.3.0.5.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 70, + "slug": "wpvivid-backuprestore", + "name": "WPvivid — Backup, Migration & Staging", + "version": "0.9.127", + "tested": "6.9.4", + "requires_php": "5.3", + "active_installs": 900000, + "download_link": "https://downloads.wordpress.org/plugin/wpvivid-backuprestore.0.9.127.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 71, + "slug": "wp-reviews-plugin-for-google", + "name": "Widgets for Google Reviews", + "version": "13.2.9", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 900000, + "download_link": "https://downloads.wordpress.org/plugin/wp-reviews-plugin-for-google.13.2.9.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 72, + "slug": "gtranslate", + "name": "Translate WordPress with GTranslate", + "version": "3.0.10", + "tested": "6.9.4", + "requires_php": null, + "active_installs": 900000, + "download_link": "https://downloads.wordpress.org/plugin/gtranslate.3.0.10.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 73, + "slug": "woocommerce-payments", + "name": "WooPayments: Integrated WooCommerce Payments", + "version": "10.7.1", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 900000, + "download_link": "https://downloads.wordpress.org/plugin/woocommerce-payments.10.7.1.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 74, + "slug": "autoptimize", + "name": "Autoptimize", + "version": "3.1.15.1", + "tested": "6.9.4", + "requires_php": "7.1", + "active_installs": 900000, + "download_link": "https://downloads.wordpress.org/plugin/autoptimize.3.1.15.1.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 75, + "slug": "google-listings-and-ads", + "name": "Google for WooCommerce", + "version": "3.6.2", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 900000, + "download_link": "https://downloads.wordpress.org/plugin/google-listings-and-ads.3.6.2.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 76, + "slug": "smart-slider-3", + "name": "Smart Slider 3", + "version": "3.5.1.34", + "tested": "6.9.4", + "requires_php": "7.0", + "active_installs": 800000, + "download_link": "https://downloads.wordpress.org/plugin/smart-slider-3.3.5.1.34.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 77, + "slug": "polylang", + "name": "Polylang", + "version": "3.8.4", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 800000, + "download_link": "https://downloads.wordpress.org/plugin/polylang.3.8.4.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 78, + "slug": "breadcrumb-navxt", + "name": "Breadcrumb NavXT", + "version": "7.5.1", + "tested": "6.9.4", + "requires_php": "7.0", + "active_installs": 800000, + "download_link": "https://downloads.wordpress.org/plugin/breadcrumb-navxt.7.5.1.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 79, + "slug": "woocommerce-paypal-payments", + "name": "WooCommerce PayPal Payments", + "version": "4.0.3", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 800000, + "download_link": "https://downloads.wordpress.org/plugin/woocommerce-paypal-payments.4.0.3.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 80, + "slug": "flamingo", + "name": "Flamingo", + "version": "2.6.2", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 800000, + "download_link": "https://downloads.wordpress.org/plugin/flamingo.2.6.2.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 81, + "slug": "duracelltomi-google-tag-manager", + "name": "GTM4WP – A Google Tag Manager (GTM) plugin for WordPress", + "version": "1.22.3", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/duracelltomi-google-tag-manager.1.22.3.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 82, + "slug": "better-wp-security", + "name": "Kadence Security – Password, Two Factor Authentication, and Brute Force Protection", + "version": "10.0.1", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/better-wp-security.10.0.1.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 83, + "slug": "antispam-bee", + "name": "Antispam Bee", + "version": "2.11.11", + "tested": "7.0", + "requires_php": "5.2", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/antispam-bee.2.11.11.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 84, + "slug": "woocommerce-gateway-stripe", + "name": "WooCommerce Stripe Payment Gateway", + "version": "10.7.0", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/woocommerce-gateway-stripe.10.7.0.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 85, + "slug": "creame-whatsapp-me", + "name": "Joinchat – Enhanced "click to chat"", + "version": "6.2.0", + "tested": "7.0", + "requires_php": "7.0", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/creame-whatsapp-me.6.2.0.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 86, + "slug": "mainwp-child", + "name": "MainWP Child – Securely Connects to the MainWP Dashboard to Manage Multiple Sites", + "version": "6.0.11", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/mainwp-child.6.0.11.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 87, + "slug": "coming-soon", + "name": "Website Builder by SeedProd — Theme Builder, Landing Page Builder, Coming Soon Page, Maintenance Mode", + "version": "6.20.1", + "tested": "7.0", + "requires_php": "5.6", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/coming-soon.6.20.1.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 88, + "slug": "user-role-editor", + "name": "User Role Editor", + "version": "4.64.6", + "tested": "6.9.4", + "requires_php": "7.3", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/user-role-editor.4.64.6.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 89, + "slug": "popup-maker", + "name": "Popup Maker – Boost Sales, Conversions, Optins, Subscribers with the Ultimate WP Popup Builder", + "version": "1.22.0", + "tested": "7.0.0", + "requires_php": "7.4", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/popup-maker.1.22.0.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 90, + "slug": "premium-addons-for-elementor", + "name": "Premium Addons for Elementor – Powerful Elementor Templates & Widgets", + "version": "4.11.77", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/premium-addons-for-elementor.4.11.77.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 91, + "slug": "fluentform", + "name": "Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder", + "version": "6.2.2", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/fluentform.6.2.2.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 92, + "slug": "click-to-chat-for-whatsapp", + "name": "Click to Chat – HoliThemes", + "version": "4.39", + "tested": "7.0", + "requires_php": "5.6", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/click-to-chat-for-whatsapp.4.39.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 93, + "slug": "the-events-calendar", + "name": "The Events Calendar", + "version": "6.16.2", + "tested": "6.9.4", + "requires_php": "7.4", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/the-events-calendar.6.16.2.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "semantic-recipe-plus-generic-audit", + "semantic_recipes": [ + "events-calendar-event-graphs" + ] + }, + { + "rank": 94, + "slug": "backuply", + "name": "Backuply – Backup, Restore, Migrate and Clone", + "version": "1.5.2", + "tested": "6.9.4", + "requires_php": "5.5", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/backuply.1.5.2.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 95, + "slug": "tablepress", + "name": "TablePress – Tables in WordPress made easy", + "version": "3.3", + "tested": "7.0", + "requires_php": "7.4", + "active_installs": 700000, + "download_link": "https://downloads.wordpress.org/plugin/tablepress.3.3.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 96, + "slug": "custom-css-js", + "name": "Simple Custom CSS and JS", + "version": "3.52", + "tested": "6.9.4", + "requires_php": "5.2.4", + "active_installs": 600000, + "download_link": "https://downloads.wordpress.org/plugin/custom-css-js.3.52.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 97, + "slug": "royal-elementor-addons", + "name": "Royal Addons for Elementor – Addons and Templates Kit for Elementor", + "version": "1.7.1060", + "tested": "6.9.4", + "requires_php": "5.6", + "active_installs": 600000, + "download_link": "https://downloads.wordpress.org/plugin/royal-elementor-addons.1.7.1060.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 98, + "slug": "sucuri-scanner", + "name": "Sucuri Security – Auditing, Malware Scanner and Security Hardening", + "version": "2.7.2", + "tested": "6.9.4", + "requires_php": null, + "active_installs": 600000, + "download_link": "https://downloads.wordpress.org/plugin/sucuri-scanner.2.7.2.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 99, + "slug": "enable-media-replace", + "name": "Enable Media Replace", + "version": "4.1.9", + "tested": "7.0", + "requires_php": "5.6", + "active_installs": 600000, + "download_link": "https://downloads.wordpress.org/plugin/enable-media-replace.4.1.9.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + }, + { + "rank": 100, + "slug": "post-types-order", + "name": "Post Types Order", + "version": "2.4.7", + "tested": "7.0", + "requires_php": "5.6", + "active_installs": 600000, + "download_link": "https://downloads.wordpress.org/plugin/post-types-order.2.4.7.zip", + "install_support": "wp-admin-plugin-install", + "merge_support": "generic-audit", + "semantic_recipes": [] + } + ] +} diff --git a/scripts/popular-plugin-compat.mjs b/scripts/popular-plugin-compat.mjs new file mode 100644 index 00000000..85409456 --- /dev/null +++ b/scripts/popular-plugin-compat.mjs @@ -0,0 +1,161 @@ +#!/usr/bin/env node +import { readFileSync, writeFileSync } from 'node:fs'; +import { dirname, resolve } from 'node:path'; +import { fileURLToPath, pathToFileURL } from 'node:url'; + +const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +const defaultManifest = 'runtime/cow/plugin-compat/popular-wordpress-plugins.json'; +const sourceUrl = + 'https://api.wordpress.org/plugins/info/1.2/?action=query_plugins&request[browse]=popular&request[page]=1&request[per_page]=100&request[fields][description]=0&request[fields][sections]=0&request[fields][compatibility]=0&request[fields][ratings]=0&request[fields][icons]=0&request[fields][banners]=0'; + +const semanticRecipes = new Map([ + ['advanced-custom-fields', ['acf-field-definitions']], + ['elementor', ['elementor-widget-trees']], + ['the-events-calendar', ['events-calendar-event-graphs']], + ['woocommerce', ['woocommerce-hpos-orders']], + ['wordpress-seo', ['yoast-indexables']], +]); + +if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) { + main(process.argv.slice(2)).catch((error) => { + console.error(error.message); + process.exit(1); + }); +} + +async function main(argv) { + const [command = 'validate', path = defaultManifest] = argv; + if (command === 'refresh') { + await refresh(path); + return; + } + if (command === 'validate') { + validate(JSON.parse(readFileSync(resolve(repoRoot, path), 'utf8'))); + console.log(`Popular plugin compatibility manifest is valid: ${path}`); + return; + } + printUsage(); + process.exit(command === '--help' || command === 'help' ? 0 : 1); +} + +async function refresh(path) { + const response = await fetch(sourceUrl, { + headers: { + 'User-Agent': 'ForkPress popular plugin compatibility manifest', + }, + }); + if (!response.ok) { + throw new Error(`WordPress.org plugin API returned ${response.status}`); + } + const payload = await response.json(); + const plugins = Array.isArray(payload.plugins) ? payload.plugins : []; + if (plugins.length !== 100) { + throw new Error(`Expected 100 popular plugins, got ${plugins.length}`); + } + + const manifest = { + schema: 1, + source: { + name: 'WordPress.org Plugin Directory popular browse', + url: sourceUrl, + retrieved_at: new Date().toISOString(), + per_page: 100, + }, + support_policy: { + install: 'wp-admin-plugin-install', + default_merge: 'generic-db-file-merge-with-plugin-validator-unchecked-audit', + semantic_recipes: [ + 'acf-field-definitions', + 'elementor-widget-trees', + 'events-calendar-event-graphs', + 'woocommerce-hpos-orders', + 'yoast-indexables', + ], + }, + plugins: plugins.map((plugin, index) => pluginRecord(plugin, index + 1)), + }; + validate(manifest); + writeFileSync(resolve(repoRoot, path), `${JSON.stringify(manifest, null, 2)}\n`); + console.log(`Wrote ${path}`); +} + +function pluginRecord(plugin, rank) { + const slug = requiredString(plugin.slug, `plugin ${rank} slug`); + const recipes = semanticRecipes.get(slug) ?? []; + return { + rank, + slug, + name: requiredString(plugin.name, `${slug} name`), + version: optionalString(plugin.version), + tested: optionalString(plugin.tested), + requires_php: optionalString(plugin.requires_php), + active_installs: Number.isFinite(plugin.active_installs) ? plugin.active_installs : null, + download_link: optionalString(plugin.download_link), + install_support: 'wp-admin-plugin-install', + merge_support: recipes.length > 0 ? 'semantic-recipe-plus-generic-audit' : 'generic-audit', + semantic_recipes: recipes, + }; +} + +function validate(manifest) { + if (manifest.schema !== 1) { + throw new Error('Manifest schema must be 1.'); + } + if (!manifest.source || manifest.source.per_page !== 100 || !manifest.source.url) { + throw new Error('Manifest source metadata must include url and per_page = 100.'); + } + if (manifest.support_policy?.install !== 'wp-admin-plugin-install') { + throw new Error('Manifest support policy must declare wp-admin plugin install support.'); + } + if (manifest.support_policy?.default_merge !== 'generic-db-file-merge-with-plugin-validator-unchecked-audit') { + throw new Error('Manifest support policy must declare the default generic merge audit behavior.'); + } + if (!Array.isArray(manifest.plugins) || manifest.plugins.length !== 100) { + throw new Error('Manifest must contain exactly 100 plugin records.'); + } + + const slugs = new Set(); + for (let index = 0; index < manifest.plugins.length; index += 1) { + const plugin = manifest.plugins[index]; + const rank = index + 1; + if (plugin.rank !== rank) { + throw new Error(`Plugin at index ${index} must have rank ${rank}.`); + } + const slug = requiredString(plugin.slug, `plugin ${rank} slug`); + if (slugs.has(slug)) { + throw new Error(`Duplicate plugin slug: ${slug}`); + } + slugs.add(slug); + requiredString(plugin.name, `${slug} name`); + if (plugin.install_support !== 'wp-admin-plugin-install') { + throw new Error(`${slug} must declare install support.`); + } + if (!['generic-audit', 'semantic-recipe-plus-generic-audit'].includes(plugin.merge_support)) { + throw new Error(`${slug} has unsupported merge support: ${plugin.merge_support}`); + } + const recipes = semanticRecipes.get(slug) ?? []; + if (JSON.stringify(plugin.semantic_recipes ?? []) !== JSON.stringify(recipes)) { + throw new Error(`${slug} semantic recipe list is out of date.`); + } + if (recipes.length > 0 && plugin.merge_support !== 'semantic-recipe-plus-generic-audit') { + throw new Error(`${slug} must use semantic recipe merge support.`); + } + } +} + +function requiredString(value, label) { + if (typeof value !== 'string' || value.trim() === '') { + throw new Error(`Missing ${label}.`); + } + return value; +} + +function optionalString(value) { + return typeof value === 'string' && value.trim() !== '' ? value : null; +} + +function printUsage() { + console.log(`Usage: + node scripts/popular-plugin-compat.mjs refresh [manifest] + node scripts/popular-plugin-compat.mjs validate [manifest]`); +} diff --git a/scripts/popular-plugin-compat.test.mjs b/scripts/popular-plugin-compat.test.mjs new file mode 100644 index 00000000..a66eb692 --- /dev/null +++ b/scripts/popular-plugin-compat.test.mjs @@ -0,0 +1,8 @@ +import { execFileSync } from 'node:child_process'; +import { test } from 'node:test'; + +test('popular plugin compatibility manifest is valid', () => { + execFileSync('node', ['scripts/popular-plugin-compat.mjs', 'validate'], { + stdio: 'pipe', + }); +});