WP Texturize Inline Quote Fix
Stopgap mu-plugin for WordPress core Trac #18549 — fixes quotes/apostrophes wptexturize() curls the wrong way after a closing inline tag. Remove once core lands the fix.
by Dan Knauss · github.com/dknauss/wp-texturize-inline-quote-fix · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/dknauss/wp-texturize-inline-quote-fix/archive/refs/heads/main.zipReadme
WP Texturize Inline Quote Fix
A small stopgap plugin that corrects quotes and apostrophes that WordPress's
wptexturize() curls the wrong way when they sit immediately after a closing
inline HTML tag.
This is a workaround, not the fix. The real fix belongs in WordPress core and is proposed upstream. Remove this plugin once that lands.
Two builds — pick one
This repo ships two plugins that fix the same bug differently. Use one, not both.
wp-texturize-inline-quote-fix.php(default, lightweight) — post-processes already-texturized output, flipping the mis-curled quote after an inline tag. Tiny, drift-free, and rides on top of whatever core does. A couple of edge cases differ slightly from the core patch.wp-texturize-inline-quote-fix-faithful.php(demonstration / dogfood) — replaceswptexturize()with a forked copy carrying the comprehensive #18549 patch, so output matches PR #12249 byte-for-byte, including those edge cases. It forks the whole function, so it tracks a specific WordPress version (currently 7.0) — re-sync if core changeswptexturize().
Most sites want the lightweight post-process build. The faithful build is for dogfooding the exact patch on a live site, or demonstrating it for the ticket.
What it fixes
wptexturize() loses word context across an inline tag boundary, so a straight
quote right after a closing inline tag is curled as an opening quote:
| Input | Without this plugin | With this plugin |
|---|---|---|
<strong>He</strong>'s here. |
…</strong>‘s (opening — wrong) |
…</strong>’s (apostrophe) |
The word is '<a>quoted</a>' |
trailing ‘ (opening — wrong) |
trailing ’ (closing) |
A space before the quote keeps normal opening-quote behaviour
(<strong>He</strong> 'go' stays ‘go’), so quotations are untouched.
Install
It is designed as a must-use plugin. Symlink or copy the file into
wp-content/mu-plugins/:
ln -s /path/to/wp-texturize-inline-quote-fix/wp-texturize-inline-quote-fix.php \
wp-content/mu-plugins/wp-texturize-inline-quote-fix.php
It also works as a regular plugin — drop the folder in wp-content/plugins/ and
activate it.
How it works
It post-processes already-texturized output (the_content, the_title,
the_excerpt, comment_text, term_description, widget_text) at priority 12,
flipping an opening quote that immediately follows a closing inline tag to a
closing quote/apostrophe. It mirrors the bounded core patch rather than the old
4.7-era replacement engine.
Scope and limits
- Only the inline elements
a, abbr, b, bdi, bdo, cite, data, del, dfn, em, i, ins, label, mark, q, s, samp, small, span, strong, sub, sup, time, u, var. - Excludes
kbd(a core no-texturize tag) and deprecatedacronym. - Excludes
]from the trailing-context match to preserve core's "crazy" shortcode texturize fixture. - Out of scope: quote-inside-quote behaviour (Trac #29882).
Because it works on rendered output, it cannot fix content that never passes through these filters. The core patch (above) is the complete, in-engine fix.
The faithful build
wp-texturize-inline-quote-fix-faithful.php re-points every filter that core
registered wptexturize on to a forked dk_wptexturize() — WordPress 7.0's
wptexturize() with the comprehensive #18549 patch applied. It reuses core's
_wptexturize_pushpop_element() and wptexturize_primes(); only the function body
and the two new context helpers are forked.
Parity is verified against core on the same install: the #18549 fixtures produce the
corrected output, and a corpus of ordinary text (dashes, primes, quotes, shortcodes,
no-texturize tags) is byte-identical to core's wptexturize() — the fork changes
nothing but the inline-tag quote decision.
Because it forks the whole function it must track core: re-sync the body if core
changes wptexturize(), and remove the plugin once #18549 lands. A few direct
wptexturize() calls in core (not via filters) are unaffected.
License
GPL-2.0-or-later. See LICENSE.