| @@ -1232,12 +1232,11 @@ | ||
| 1232 | 1232 | } |
| 1233 | 1233 | |
| 1234 | 1234 | if (null !== $content) { |
| 1235 | 1235 | // Get content preview (first 200 characters) with size safety |
| 1236 | - $status['content_preview'] = substr($content, 0, 200); | |
| 1237 | - if (strlen($content) > 200) { | |
| 1238 | - $status['content_preview'] .= '...'; | |
| 1239 | - } | |
| 1236 | + // substr()/strlen() count BYTES, so this cut a multibyte character | |
| 1237 | + // in half and shipped an invalid UTF-8 sequence in the preview (#687). | |
| 1238 | + $status['content_preview'] = \ThinkRank\Core\Seo_Text::trim_to_length($content, 200); | |
| 1240 | 1239 | } |
| 1241 | 1240 | |
| 1242 | 1241 | // Cache the result for 5 minutes to improve performance |
| 1243 | 1242 | set_transient($cache_key, $status, 5 * MINUTE_IN_SECONDS); |
| @@ -2212,9 +2211,9 @@ | ||
| 2212 | 2211 | $content .= "- [Technical Stack]({$website_url}): Built with {$stack}\n"; |
| 2213 | 2212 | } |
| 2214 | 2213 | |
| 2215 | 2214 | if (!empty($user_input['development_approach'])) { |
| 2216 | - $approach_summary = wp_trim_words($user_input['development_approach'], 10); | |
| 2215 | + $approach_summary = \ThinkRank\Core\Seo_Text::trim_words($user_input['development_approach'], 10); | |
| 2217 | 2216 | $content .= "- [Development Guidelines]({$website_url}): {$approach_summary}\n"; |
| 2218 | 2217 | } |
| 2219 | 2218 | |
| 2220 | 2219 | // Add robots.txt reference |