PluginProbe
ZIP AI – AI Website Builder & AI Agent / 0.0.12
ZIP AI – AI Website Builder & AI Agent v0.0.12
0.0.13 0.0.12 0.0.11 0.0.10 0.0.9 trunk 0.0.4 0.0.5 0.0.6 0.0.7 0.0.8
zip-ai / inc / imports / import-texture-gate.php

import-texture-gate.php in ZIP AI – AI Website Builder & AI Agent 0.0.12, at inc/imports/import-texture-gate.php

115 lines 3.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Import Texture Gate. This disables WordPress `wptexturize` on imported pages.
4 *
5 * Why this exists
6 * ----------------
7 * WordPress runs `wptexturize` on every `the_content` render. The filter
8 * silently rewrites characters in the post body:
9 *
10 * `'` → `’` (curly right single quotation mark, U+2019)
11 * `"foo"` → `“foo”` (curly double quotes)
12 * `--` → `—` (em-dash)
13 * `...` → `…` (horizontal ellipsis)
14 *
15 * For a blog post this is a usability win. For a designed page imported from
16 * raw HTML it is text corruption. The source authored "I'd" with ASCII U+0027
17 * and expects that exact glyph. The rendered page ships "I’d" with U+2019. That
18 * glyph renders about 10px wider in most fonts. It shifts text wrapping. This
19 * was verified on adam-preiser. The hero h1 wrapped to 5 lines on the import
20 * and 4 lines on the source. The CSS, font, width and line-height matched. Only
21 * the apostrophe character differed. This added 73px of vertical drift. Across
22 * every paragraph with punctuation, the whole hero section grew 186px taller
23 * than the source.
24 *
25 * Scope
26 * -----
27 * This is active only when the rendered post has the
28 * `spectra_blocks_pro_gs_user_css` post meta. The FSE import pipeline sets that
29 * meta. All non-imported posts still get the standard wptexturize treatment.
30 *
31 * `run_wptexturize` is a core WordPress filter. It short-circuits
32 * `wptexturize()` entirely. Returning `false` makes the function pass text
33 * through unchanged. The filter is checked once per `wptexturize()` call, not
34 * per character. So this adds one extra `get_post_meta` lookup per
35 * imported-page render. The result is cached statically after the first call.
36 * This avoids repeating it across the many internal wptexturize calls on a
37 * single page.
38 *
39 * @package zip-ai
40 */
41
42 namespace ZipAI\MCP\Classes\Imports;
43
44 defined( 'ABSPATH' ) || exit;
45
46 /**
47 * Disables wptexturize on imported posts so authored characters render
48 * verbatim (no `'`→`’`, `"`→`“”`, `--`→`—`, `...`→`…` rewrites).
49 *
50 * @since 0.0.5
51 */
52 class ImportTextureGate {
53 /**
54 * Per-page imported-CSS post-meta key (the GBS-local store). Its presence
55 * marks a page as FSE-imported. Mirrors spectra-blocks'
56 * `GenCssOrphanStripper::META_KEY` (kept local to avoid coupling to a
57 * spectra-blocks class that may be inactive).
58 *
59 * @var string
60 */
61 private const PAGE_CSS_META_KEY = 'spectra_blocks_pro_gs_user_css';
62
63 /**
64 * Register the wptexturize gate filter.
65 *
66 * @return void
67 */
68 public function __construct() {
69 add_filter( 'run_wptexturize', array( $this, 'maybe_disable' ) );
70 }
71
72 /**
73 * Filter callback. Returns `false` (disable wptexturize) when the
74 * current post is an imported page; otherwise returns the value
75 * unchanged so other plugins / WP defaults still drive the decision.
76 *
77 * @param bool $run Current wptexturize-enabled state.
78 * @return bool
79 */
80 public function maybe_disable( bool $run ): bool {
81 // Skip admin views — block editor (and any admin renders of
82 // post content) should see the WP-standard treatment. The
83 // editor doesn't actually run wptexturize on the served block
84 // markup, but we keep the admin/REST skips for consistency.
85 if ( is_admin() ) {
86 return $run;
87 }
88
89 // Skip REST renders (block editor's `ServerSideRender` preview)
90 // for the same consistency reason.
91 if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
92 return $run;
93 }
94
95 $post_id = get_the_ID();
96 if ( ! $post_id ) {
97 return $run;
98 }
99
100 // Gate: per-page imported CSS post meta exists IFF the page came
101 // through the FSE import pipeline.
102 /**
103 * Narrowed type for `$is_imported_cache`.
104 *
105 * @var array<int,bool> $is_imported_cache
106 */
107 static $is_imported_cache = array();
108 if ( ! isset( $is_imported_cache[ $post_id ] ) ) {
109 $is_imported_cache[ $post_id ] = '' !== get_post_meta( $post_id, self::PAGE_CSS_META_KEY, true );
110 }
111
112 return $is_imported_cache[ $post_id ] ? false : $run;
113 }
114 }
115