{"id":383809,"date":"2026-10-14T16:36:52","date_gmt":"2026-10-14T16:36:52","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/content-polisher-content-quality-cleanup\/"},"modified":"2026-10-14T16:36:18","modified_gmt":"2026-10-14T16:36:18","slug":"content-polisher","status":"publish","type":"plugin","link":"https:\/\/bg.wordpress.org\/plugins\/content-polisher\/","author":23582434,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"0.3.0","stable_tag":"0.3.0","tested":"7.1.3","requires":"6.5","requires_php":"8.1","requires_plugins":null,"header_name":"Content Polisher \u2013 Content Quality & Cleanup","header_author":"Denis Kanibolotskiy","header_description":"Scan your WordPress content for quality issues, preview proposed fixes, apply them safely and undo when needed.","assets_banners_color":"617dc9","last_updated":"2026-10-14 16:36:18","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/contentpolisher.com\/","header_author_uri":"https:\/\/profiles.wordpress.org\/kanibolotskiydenis\/","rating":0,"author_block_rating":0,"active_installs":0,"downloads":51,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"0.3.0":{"tag":"0.3.0","author":"kanibolotskiydenis","date":"2026-10-14 16:36:18","revision":3746790}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3746790,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3746790,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3746790,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3746790,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["0.3.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3746790,"resolution":"1","location":"assets","locale":"","width":1280,"height":900},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3746790,"resolution":"2","location":"assets","locale":"","width":1280,"height":900},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3746790,"resolution":"3","location":"assets","locale":"","width":1280,"height":900},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3746790,"resolution":"4","location":"assets","locale":"","width":1280,"height":900}},"screenshots":{"1":"Scan results: issues grouped by type, with a Before \/ After preview and one-click fixes.","2":"History: every change is listed and can be undone.","3":"Settings: content types, language, rules and exclusions.","4":"Check while you write: the Content Polisher panel in the block editor."}},"plugin_section":[],"plugin_tags":[3786,19795,1843,149880,5126],"plugin_category":[43],"plugin_contributors":[286794],"plugin_business_model":[],"class_list":["post-383809","plugin","type-plugin","status-publish","hentry","plugin_tags-cleanup","plugin_tags-content-audit","plugin_tags-proofreading","plugin_tags-spaces","plugin_tags-typography","plugin_category-customization","plugin_contributors-kanibolotskiydenis","plugin_committers-kanibolotskiydenis"],"banners":{"banner":"https:\/\/ps.w.org\/content-polisher\/assets\/banner-772x250.png?rev=3746790","banner_2x":"https:\/\/ps.w.org\/content-polisher\/assets\/banner-1544x500.png?rev=3746790","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/content-polisher\/assets\/icon-128x128.png?rev=3746790","icon_2x":"https:\/\/ps.w.org\/content-polisher\/assets\/icon-256x256.png?rev=3746790","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/content-polisher\/assets\/screenshot-1.png?rev=3746790","caption":"Scan results: issues grouped by type, with a Before \/ After preview and one-click fixes."},{"src":"https:\/\/ps.w.org\/content-polisher\/assets\/screenshot-2.png?rev=3746790","caption":"History: every change is listed and can be undone."},{"src":"https:\/\/ps.w.org\/content-polisher\/assets\/screenshot-3.png?rev=3746790","caption":"Settings: content types, language, rules and exclusions."},{"src":"https:\/\/ps.w.org\/content-polisher\/assets\/screenshot-4.png?rev=3746790","caption":"Check while you write: the Content Polisher panel in the block editor."}],"raw_content":"<!--section=description-->\n<p>Content Polisher checks the text of your posts, pages and public custom post types for small mistakes that are easy to miss: double spaces, spaces before punctuation, missing spaces after punctuation, wrong dashes, empty paragraphs and duplicate line breaks.<\/p>\n\n<p>Every issue is shown with a clear Before \/ After preview. Fix issues one by one, or fix all safe issues of a post at once. Anything that could be intentional is only suggested and waits for your review. Every change is backed up and can be undone from the History page.<\/p>\n\n<p>Everything runs on your server. Content Polisher works without an account, an API key or a connection to any external service.<\/p>\n\n<p>Documentation: <a href=\"https:\/\/contentpolisher.com\/docs\/\">contentpolisher.com\/docs<\/a><\/p>\n\n<h4>How it works<\/h4>\n\n<ol>\n<li>Open <strong>Content Polisher<\/strong> and click <strong>Scan Website<\/strong>.<\/li>\n<li>Review the issues, grouped by type, with a Before \/ After preview.<\/li>\n<li>Click <strong>Fix<\/strong> on an issue, or <strong>Fix safe issues in this post<\/strong>.<\/li>\n<li>Changed your mind? Click <strong>Undo<\/strong>, in the notice or on the <strong>History<\/strong> page.<\/li>\n<\/ol>\n\n<h4>Check while you write<\/h4>\n\n<p>In the block editor, the <strong>Content Polisher<\/strong> panel in the post sidebar checks the post you are editing \u2014 including unsaved changes \u2014 with the same rules. Fix issues one by one or all safe issues at once; fixes change the blocks in the editor, so <strong>Ctrl+Z<\/strong> undoes them and saving the post keeps them. Before publishing, the pre-publish panel shows how many issues are left.<\/p>\n\n<h4>Command line (WP-CLI)<\/h4>\n\n<p>Scan, list issues, fix and undo from the command line, e.g. in a deployment or CI check: <code>wp content-polisher scan --fail-on=safe --user=admin<\/code> exits with code 1 when safe fixes are found. Commands: <code>scan<\/code>, <code>status<\/code>, <code>issues<\/code>, <code>fix<\/code>, <code>history<\/code>, <code>undo<\/code> (see <code>wp help content-polisher<\/code>). They use the same permissions, history and undo as the dashboard.<\/p>\n\n<h4>Rules<\/h4>\n\n<ul>\n<li><strong>Double spaces<\/strong> \u2014 \"Hello  world\" \u2192 \"Hello world\".<\/li>\n<li><strong>Space before punctuation<\/strong> \u2014 \"Hello , world\" \u2192 \"Hello, world\". In French, the space before ; : ! ? is correct and is kept.<\/li>\n<li><strong>Missing space after punctuation<\/strong> \u2014 \"Hello,world\" \u2192 \"Hello, world\".<\/li>\n<li><strong>Typography<\/strong> \u2014 <code>--<\/code> \u2192 dash, spaced hyphens between words in Ukrainian, Russian and French, non-breaking space before ; : ! ? in French.<\/li>\n<li><strong>Empty paragraphs<\/strong> \u2014 <code>&lt;p&gt;&lt;\/p&gt;<\/code>, <code>&lt;p&gt;&amp;nbsp;&lt;\/p&gt;<\/code>, empty paragraph blocks.<\/li>\n<li><strong>Duplicate line breaks<\/strong> \u2014 <code>&lt;br&gt;&lt;br&gt;<\/code> (suggestion only).<\/li>\n<\/ul>\n\n<p>Content languages: English, Ukrainian, Russian, French. Interface languages: English, French, Ukrainian, Russian.<\/p>\n\n<h4>Safe by design<\/h4>\n\n<ul>\n<li>Only the visible text is changed. Tags, attributes, links, shortcodes and block markup are never modified.<\/li>\n<li>Code is never touched: <code>pre<\/code>, <code>code<\/code>, <code>script<\/code>, <code>style<\/code>, code blocks, custom HTML blocks and code shortcodes are skipped.<\/li>\n<li>URLs, e-mail addresses, domains, file names, numbers and abbreviations are recognised and left alone.<\/li>\n<li>Gutenberg blocks stay valid: text is edited only in blocks whose content is stored as HTML.<\/li>\n<li>Pages built with Elementor, Beaver Builder, SiteOrigin, Brizy, Oxygen, Bricks or Thrive Architect are skipped, because their content is stored elsewhere (Content Polisher Pro checks Elementor pages through their widgets). Divi and WPBakery text is checked without touching shortcode attributes.<\/li>\n<li>A backup of the original content is stored before every change; WordPress revisions are created as usual.<\/li>\n<li>Undo never overwrites later edits: if a post was changed after the fix, you are asked first.<\/li>\n<li>Posts open in the editor by another user are skipped. Large sites are scanned in small batches.<\/li>\n<\/ul>\n\n<h4>Multilingual sites<\/h4>\n\n<p>With the language set to <strong>Automatic<\/strong>, every post is checked in its own language: from Polylang or WPML when available, otherwise detected from the text, otherwise the site language. Language-specific typography is skipped for other languages rather than applying the wrong conventions.<\/p>\n\n<h4>Content Polisher Pro<\/h4>\n\n<p>Content Polisher is complete on its own. An optional add-on, Content Polisher Pro, adds:<\/p>\n\n<ul>\n<li>duplicate word detection (\"this is is\"), advanced typography (typographic quotes, ellipses, finer French spacing) and extended HTML checks;<\/li>\n<li>fixing all safe issues of the whole site in one batched, undoable operation;<\/li>\n<li>checking Advanced Custom Fields: Text, Text Area and WYSIWYG fields of posts, ACF blocks and options pages, including those inside Repeater, Group and Flexible Content, with AI proofreading of those fields;<\/li>\n<li>checking pages built with Elementor: the text of their widgets, including Elementor Pro and V4 atomic widgets;<\/li>\n<li>on-demand AI proofreading with your own Anthropic or OpenAI API key;<\/li>\n<li>CSV exports of scan results and of the full change history.<\/li>\n<\/ul>\n\n<p>Learn more at <a href=\"https:\/\/contentpolisher.com\/pro\/\">contentpolisher.com\/pro<\/a>. The add-on is installed next to this plugin and extends it; this plugin contains no locked features. Upgrade links appear only on Content Polisher's own screens.<\/p>\n\n<h4>External services<\/h4>\n\n<p><strong>Freemius<\/strong> (https:\/\/freemius.com) \u2014 this plugin includes the Freemius SDK, which manages purchases, licenses and updates of the optional Content Polisher Pro add-on.<\/p>\n\n<ul>\n<li>After activation, Freemius asks whether you want to opt in to receive security and feature notifications and to share basic, non-sensitive diagnostic data (site URL, WordPress, PHP and plugin versions, active plugins and theme, admin name and e-mail). Nothing is sent if you click <strong>Skip<\/strong>, and the plugin works exactly the same.<\/li>\n<li>You can change your choice at any time from the plugins list or the Account page.<\/li>\n<li>Post content is never sent to Freemius.<\/li>\n<li>Terms: https:\/\/freemius.com\/terms\/ \u2014 Privacy policy: https:\/\/freemius.com\/privacy\/<\/li>\n<\/ul>\n\n<p>No other external service is used by this plugin.<\/p>\n\n<h4>For developers<\/h4>\n\n<ul>\n<li><code>content_polisher_rules<\/code> \u2014 add rules (implement <code>ContentPolisher\\Rules\\RuleInterface<\/code> or extend <code>AbstractTextRule<\/code>).<\/li>\n<li><code>content_polisher_content_sources<\/code> \u2014 check more text than the post content, such as custom fields (implement <code>ContentPolisher\\Sources\\ContentSourceInterface<\/code>, or <code>SiteContentSourceInterface<\/code> for text that belongs to no post); each piece of text is fixed, recorded and undone on its own.<\/li>\n<li><code>content_polisher_site_capability<\/code> \u2014 capability needed to fix site-wide text such as options pages (default <code>manage_options<\/code>).<\/li>\n<li><code>content_polisher_proofreader<\/code> \u2014 provide a <code>ContentPolisher\\Proofreader\\ProofreaderInterface<\/code> engine; its suggestions appear as review-only issues.<\/li>\n<li><code>content_polisher_available_features<\/code>, <code>content_polisher_feature_enabled<\/code> \u2014 features provided by add-ons (<code>ContentPolisher\\Features\\FeatureManager<\/code>).<\/li>\n<li><code>content_polisher_loaded<\/code> (action) \u2014 Content Polisher is booted; add-ons register their hooks here.<\/li>\n<li><code>content_polisher_categories<\/code>, <code>content_polisher_dashboard_config<\/code>, <code>content_polisher_settings_sections<\/code>, <code>content_polisher_dashboard_toolbar<\/code>, <code>content_polisher_history_actions<\/code>, <code>content_polisher_enqueue_assets<\/code> \u2014 extend the screens.<\/li>\n<li><code>content_polisher_editable_blocks<\/code>, <code>content_polisher_protected_blocks<\/code>, <code>content_polisher_protected_shortcodes<\/code> \u2014 which content may be edited.<\/li>\n<li><code>content_polisher_capability<\/code> \u2014 capability to use the plugin (default <code>edit_others_posts<\/code>).<\/li>\n<li><code>content_polisher_post_types<\/code>, <code>content_polisher_post_statuses<\/code>, <code>content_polisher_post_language<\/code>, <code>content_polisher_scan_limit<\/code>, <code>content_polisher_exclude_page_builders<\/code>, <code>content_polisher_page_builder_meta<\/code>, <code>content_polisher_scan_post_content<\/code>, <code>content_polisher_upgrade_url<\/code>.<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>In <strong>Plugins \u2192 Add New<\/strong>, search for \"Content Polisher\" and click <strong>Install Now<\/strong>, then <strong>Activate<\/strong>. Or upload the ZIP in <strong>Plugins \u2192 Add New \u2192 Upload Plugin<\/strong>.<\/li>\n<li>Freemius asks whether you want to opt in to notifications and diagnostics. Choose <strong>Allow &amp; Continue<\/strong> or <strong>Skip<\/strong>: both are fine.<\/li>\n<li>Go to <strong>Content Polisher \u2192 Settings<\/strong> to choose the content types and language, then run your first scan from <strong>Content Polisher<\/strong>.<\/li>\n<\/ol>\n\n<p>To add Content Polisher Pro, buy it from <strong>Content Polisher \u2192 Add-Ons<\/strong>, then upload the <code>content-polisher-pro<\/code> ZIP like any plugin and activate it. Keep Content Polisher active: Pro requires it.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"will%20it%20break%20my%20html%20or%20my%20blocks%3F\"><h3>Will it break my HTML or my blocks?<\/h3><\/dt>\n<dd><p>No. Content Polisher never re-writes markup: it edits text between tags only and keeps every other byte exactly as it was. Block markup is checked so that edited blocks stay valid.<\/p><\/dd>\n<dt id=\"is%20my%20content%20sent%20anywhere%3F\"><h3>Is my content sent anywhere?<\/h3><\/dt>\n<dd><p>No. Scans and fixes run entirely on your server. Content Polisher never sends post content to an external service. See \"External services\" above for the optional Freemius opt-in.<\/p><\/dd>\n<dt id=\"do%20i%20need%20an%20account%20or%20a%20license%3F\"><h3>Do I need an account or a license?<\/h3><\/dt>\n<dd><p>No. Content Polisher works without an account, a license or an API key. A license is only needed for the optional Content Polisher Pro add-on.<\/p><\/dd>\n<dt id=\"does%20it%20check%20custom%20fields%20%28acf%29%3F\"><h3>Does it check custom fields (ACF)?<\/h3><\/dt>\n<dd><p>Content Polisher checks the post content. Content Polisher Pro also checks the text fields of Advanced Custom Fields (and Secure Custom Fields) in posts, ACF blocks and options pages, with the same preview, history and undo, and includes them in AI proofreading. When ACF is active, Settings \u2192 Content sources shows this option.<\/p><\/dd>\n<dt id=\"who%20can%20use%20it%3F\"><h3>Who can use it?<\/h3><\/dt>\n<dd><p>Editors and administrators (users who can edit other users' posts). Each change also requires permission to edit that specific post. Settings require the <code>manage_options<\/code> capability.<\/p><\/dd>\n<dt id=\"what%20happens%20to%20pro%20if%20i%20deactivate%20content%20polisher%3F\"><h3>What happens to Pro if I deactivate Content Polisher?<\/h3><\/dt>\n<dd><p>Content Polisher Pro needs Content Polisher. While Content Polisher is inactive, Pro does nothing and shows a notice; nothing breaks. Your Pro settings are kept.<\/p><\/dd>\n<dt id=\"what%20happens%20when%20i%20uninstall%20the%20plugin%3F\"><h3>What happens when I uninstall the plugin?<\/h3><\/dt>\n<dd><p>Settings are removed. Scan results and the change history are removed only if you enabled <strong>Delete all data<\/strong> in Settings \u2192 Advanced. Your posts are never deleted. Content Polisher Pro data is removed only when Content Polisher Pro itself is uninstalled.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>0.3.0<\/h4>\n\n<ul>\n<li>New: check the post you are editing in the block editor, with Fix, Fix all safe issues and Ignore, and a summary in the pre-publish panel. Fixes are part of the editor's undo history.<\/li>\n<li>New: WP-CLI commands <code>wp content-polisher scan|status|issues|fix|history|undo<\/code>, with <code>--fail-on<\/code> exit codes for CI checks.<\/li>\n<li>Improved: a comma or semicolon moved to the next word (\"sunset ,with\") is fixed in one step (\"sunset, with\").<\/li>\n<li>Fix: a missing space after a period was not reported when the next word looks like a domain ending (\"once.It\", \"here.In\").<\/li>\n<li>New for add-ons: the <code>content_polisher_scan_post_content<\/code> filter lets a page builder add-on check the builder's own data instead of the generated post content.<\/li>\n<\/ul>\n\n<h4>0.2.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<\/ul>","raw_excerpt":"Find double spaces, punctuation and typography mistakes in your posts and pages. Preview every fix, apply it safely and undo it with one click.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/bg.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/383809","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bg.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/bg.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/bg.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=383809"}],"author":[{"embeddable":true,"href":"https:\/\/bg.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/kanibolotskiydenis"}],"wp:attachment":[{"href":"https:\/\/bg.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=383809"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/bg.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=383809"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/bg.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=383809"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/bg.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=383809"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/bg.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=383809"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/bg.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=383809"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}