| @@ -54,8 +54,15 @@ | ||
| 54 | 54 | self::TOC_BLOCK => 'toc-block', |
| 55 | 55 | ]; |
| 56 | 56 | |
| 57 | 57 | /** |
| 58 | + * Webpack asset handle for the Rank Math block converter. Not a block of | |
| 59 | + * its own — it is an editor extension, so it is deliberately outside | |
| 60 | + * BLOCK_ASSETS, which also drives block stylesheet loading. | |
| 61 | + */ | |
| 62 | + private const CONVERTER_ASSET = 'rank-math-block-converter'; | |
| 63 | + | |
| 64 | + /** | |
| 58 | 65 | * Wire up hooks. |
| 59 | 66 | * |
| 60 | 67 | * @return void |
| 61 | 68 | */ |
| @@ -70,9 +77,14 @@ | ||
| 70 | 77 | * |
| 71 | 78 | * @return void |
| 72 | 79 | */ |
| 73 | 80 | public function enqueue_editor_assets(): void { |
| 74 | - foreach (self::BLOCK_ASSETS as $handle) { | |
| 81 | + // The converter is not a block; it repairs Rank Math's FAQ / HowTo | |
| 82 | + // blocks in place (#777) and so has to load wherever those blocks might | |
| 83 | + // be edited, alongside the block scripts themselves. | |
| 84 | + $handles = array_merge(array_values(self::BLOCK_ASSETS), [self::CONVERTER_ASSET]); | |
| 85 | + | |
| 86 | + foreach ($handles as $handle) { | |
| 75 | 87 | $asset_path = THINKRANK_PLUGIN_DIR . "assets/{$handle}.asset.php"; |
| 76 | 88 | $asset = file_exists($asset_path) |
| 77 | 89 | ? include $asset_path |
| 78 | 90 | : ['dependencies' => ['wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-i18n'], 'version' => THINKRANK_VERSION]; |
| @@ -151,10 +163,26 @@ | ||
| 151 | 163 | * @return string |
| 152 | 164 | */ |
| 153 | 165 | public function inject_block_schema(string $block_content, array $block): string { |
| 154 | 166 | $name = $block['blockName'] ?? ''; |
| 155 | - $attrs = $block['attrs'] ?? []; | |
| 167 | + $attrs = is_array($block['attrs'] ?? null) ? $block['attrs'] : []; | |
| 156 | 168 | |
| 169 | + // A leftover Rank Math FAQ / HowTo block is treated as the ThinkRank | |
| 170 | + // block it converts to, so its schema comes back on a site that has not | |
| 171 | + // run the migration yet. Returns null while Rank Math is active, since | |
| 172 | + // Rank Math is still publishing its own copy (#777). | |
| 173 | + $is_converted_source = false; | |
| 174 | + if (\ThinkRank\Integrations\Rank_Math_Blocks::is_source_block($name)) { | |
| 175 | + $fallback = \ThinkRank\Integrations\Rank_Math_Blocks::schema_fallback($name, $attrs); | |
| 176 | + if (null === $fallback) { | |
| 177 | + return $block_content; | |
| 178 | + } | |
| 179 | + | |
| 180 | + $name = $fallback['name']; | |
| 181 | + $attrs = $fallback['attrs']; | |
| 182 | + $is_converted_source = true; | |
| 183 | + } | |
| 184 | + | |
| 157 | 185 | if (!isset(self::BLOCK_ASSETS[$name])) { |
| 158 | 186 | return $block_content; |
| 159 | 187 | } |
| 160 | 188 | |
| @@ -162,9 +190,19 @@ | ||
| 162 | 190 | if (array_key_exists('outputSchema', $attrs) && false === $attrs['outputSchema']) { |
| 163 | 191 | return $block_content; |
| 164 | 192 | } |
| 165 | 193 | |
| 166 | - if (self::FAQ_BLOCK === $name) { | |
| 194 | + // The Schema master switch and the matrix's per-content-type switch. | |
| 195 | + // This producer writes its own <script> into the block's markup rather | |
| 196 | + // than registering with Schema_Graph, so gating the graph does not | |
| 197 | + // reach it — a block kept publishing FAQPage/HowTo/ItemList with Schema | |
| 198 | + // switched off (#688). | |
| 199 | + if (class_exists('ThinkRank\\Frontend\\Schema_Graph') | |
| 200 | + && !\ThinkRank\Frontend\Schema_Graph::output_allowed()) { | |
| 201 | + return $block_content; | |
| 202 | + } | |
| 203 | + | |
| 204 | + if (self::FAQ_BLOCK === $name && !$is_converted_source) { | |
| 167 | 205 | // Saved markup carries a bare <img src>, because save.js output is |
| 168 | 206 | // what the block validates against and cannot be changed without |
| 169 | 207 | // invalidating every FAQ block already in the wild. Upgrading it |
| 170 | 208 | // here gives srcset/sizes and intrinsic dimensions from the stored |
| @@ -169,8 +207,13 @@ | ||
| 169 | 207 | // invalidating every FAQ block already in the wild. Upgrading it |
| 170 | 208 | // here gives srcset/sizes and intrinsic dimensions from the stored |
| 171 | 209 | // attachment id, and drops the image entirely when the attachment |
| 172 | 210 | // has since been deleted (#418). |
| 211 | + // | |
| 212 | + // Skipped for a Rank Math block rendering through the fallback: the | |
| 213 | + // markup on the page is Rank Math's, not save.js's, so the image | |
| 214 | + // rewrite has nothing it can match and no business editing it. The | |
| 215 | + // schema below is the only thing the fallback contributes. | |
| 173 | 216 | $block_content = $this->upgrade_faq_images($block_content, $attrs); |
| 174 | 217 | } |
| 175 | 218 | |
| 176 | 219 | switch ($name) { |
| @@ -210,9 +253,9 @@ | ||
| 210 | 253 | if (false === $json) { |
| 211 | 254 | return $block_content; |
| 212 | 255 | } |
| 213 | 256 | |
| 214 | - return $block_content . "\n" . '<script type="application/ld+json">' . $json . '</script>'; | |
| 257 | + return $block_content . "\n" . '<script type="application/ld+json" data-thinkrank="block">' . $json . '</script>'; | |
| 215 | 258 | } |
| 216 | 259 | |
| 217 | 260 | /** |
| 218 | 261 | * Resolve a FAQ item's image to what should actually be rendered. |