Changeset 3455197
- Timestamp:
- 02/06/2026 08:05:35 AM (2 weeks ago)
- Location:
- contentpen
- Files:
-
- 6 edited
- 1 copied
-
tags/1.0.8 (copied) (copied from contentpen/trunk)
-
tags/1.0.8/README.txt (modified) (3 diffs)
-
tags/1.0.8/contentpen-plugin.php (modified) (2 diffs)
-
tags/1.0.8/includes/class-gutenberg-converter.php (modified) (2 diffs)
-
trunk/README.txt (modified) (3 diffs)
-
trunk/contentpen-plugin.php (modified) (2 diffs)
-
trunk/includes/class-gutenberg-converter.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
contentpen/tags/1.0.8/README.txt
r3455153 r3455197 4 4 Requires at least: 5.8 5 5 Tested up to: 6.7 6 Stable tag: 1.0. 76 Stable tag: 1.0.8 7 7 Requires PHP: 7.4 8 8 License: GPLv2 or later … … 55 55 == Changelog == 56 56 57 = 1.0.8 = 58 * Added fallback regex-based conversion for servers without php-xml extension 59 * Fixed critical error on servers missing DOMDocument class 60 61 = 1.0.7 = 62 * Bug fix for Gutenberg block conversion 63 64 = 1.0.6 = 65 * Added HTML to Gutenberg block conversion for posts 66 57 67 = 1.0.0 = 58 68 * Initial release … … 60 70 == Upgrade Notice == 61 71 62 = 1.0.0 = 63 Initial release of ContentPen WordPress plugin. 64 65 = 1.0.7 = 66 Fixed HTML to Gutenberg block conversion issue. 72 = 1.0.8 = 73 * Added fallback regex-based conversion for servers without php-xml extension 74 * Fixed critical error on servers missing DOMDocument class -
contentpen/tags/1.0.8/contentpen-plugin.php
r3455153 r3455197 5 5 * Plugin URI: https://contentpen.ai 6 6 * Description: Contentpen is an AI-powered content writing assistant designed to help businesses create, optimize, and publish SEO-friendly blog posts at scale. By combining deep research with your brand's unique voice, Contentpen crafts high-impact articles that outperform your competition. 7 * Version: 1.0. 77 * Version: 1.0.8 8 8 * Requires at least: 5.8 9 9 * Requires PHP: 7.4 … … 20 20 } 21 21 22 define('CONTENTPEN_VERSION', '1.0. 7');22 define('CONTENTPEN_VERSION', '1.0.8'); 23 23 define('CONTENTPEN_PLUGIN_DIR', plugin_dir_path(__FILE__)); 24 24 define('CONTENTPEN_PLUGIN_URL', plugin_dir_url(__FILE__)); -
contentpen/tags/1.0.8/includes/class-gutenberg-converter.php
r3455149 r3455197 27 27 if (strpos($html, '<!-- wp:') !== false) { 28 28 return $html; 29 } 30 31 // Check if DOMDocument is available (requires php-xml extension) 32 if (!class_exists('DOMDocument')) { 33 // Fallback: use regex-based conversion 34 return self::convert_with_regex($html); 29 35 } 30 36 … … 269 275 return "<!-- wp:code -->\n" . $html . "\n<!-- /wp:code -->\n\n"; 270 276 } 277 278 /** 279 * Fallback regex-based conversion when DOMDocument is not available. 280 * 281 * @param string $html The HTML content to convert. 282 * @return string The converted Gutenberg block content. 283 */ 284 private static function convert_with_regex($html) 285 { 286 $output = ''; 287 288 // Pattern to match top-level block elements 289 $pattern = '/<(p|h[1-6]|ul|ol|blockquote|table|figure|pre)(\s[^>]*)?>.*?<\/\1>/is'; 290 291 $last_pos = 0; 292 if (preg_match_all($pattern, $html, $matches, PREG_OFFSET_CAPTURE)) { 293 foreach ($matches[0] as $index => $match) { 294 $full_match = $match[0]; 295 $pos = $match[1]; 296 $tag = strtolower($matches[1][$index][0]); 297 298 // Handle any text between matches 299 if ($pos > $last_pos) { 300 $between = trim(substr($html, $last_pos, $pos - $last_pos)); 301 if (!empty($between) && !preg_match('/^\s*$/', $between)) { 302 $output .= self::wrap_paragraph('<p>' . $between . '</p>'); 303 } 304 } 305 306 // Convert based on tag 307 switch ($tag) { 308 case 'p': 309 $output .= self::wrap_paragraph($full_match); 310 break; 311 case 'h1': 312 case 'h2': 313 case 'h3': 314 case 'h4': 315 case 'h5': 316 case 'h6': 317 $level = (int) substr($tag, 1); 318 $output .= self::wrap_heading($full_match, $level); 319 break; 320 case 'ul': 321 $output .= self::wrap_list($full_match, false); 322 break; 323 case 'ol': 324 $output .= self::wrap_list($full_match, true); 325 break; 326 case 'blockquote': 327 $output .= self::wrap_quote($full_match); 328 break; 329 case 'table': 330 $output .= self::wrap_table($full_match); 331 break; 332 case 'figure': 333 if (stripos($full_match, '<img') !== false) { 334 $output .= self::wrap_image($full_match); 335 } else { 336 $output .= $full_match . "\n\n"; 337 } 338 break; 339 case 'pre': 340 $output .= self::wrap_code($full_match); 341 break; 342 default: 343 $output .= "<!-- wp:html -->\n" . trim($full_match) . "\n<!-- /wp:html -->\n\n"; 344 } 345 346 $last_pos = $pos + strlen($full_match); 347 } 348 349 // Handle any remaining content after last match 350 if ($last_pos < strlen($html)) { 351 $remaining = trim(substr($html, $last_pos)); 352 if (!empty($remaining) && !preg_match('/^\s*$/', $remaining)) { 353 $output .= self::wrap_paragraph('<p>' . $remaining . '</p>'); 354 } 355 } 356 } 357 358 // If no matches found, wrap entire content 359 if (empty($output)) { 360 return self::wrap_paragraph($html); 361 } 362 363 return trim($output); 364 } 271 365 } -
contentpen/trunk/README.txt
r3455153 r3455197 4 4 Requires at least: 5.8 5 5 Tested up to: 6.7 6 Stable tag: 1.0. 76 Stable tag: 1.0.8 7 7 Requires PHP: 7.4 8 8 License: GPLv2 or later … … 55 55 == Changelog == 56 56 57 = 1.0.8 = 58 * Added fallback regex-based conversion for servers without php-xml extension 59 * Fixed critical error on servers missing DOMDocument class 60 61 = 1.0.7 = 62 * Bug fix for Gutenberg block conversion 63 64 = 1.0.6 = 65 * Added HTML to Gutenberg block conversion for posts 66 57 67 = 1.0.0 = 58 68 * Initial release … … 60 70 == Upgrade Notice == 61 71 62 = 1.0.0 = 63 Initial release of ContentPen WordPress plugin. 64 65 = 1.0.7 = 66 Fixed HTML to Gutenberg block conversion issue. 72 = 1.0.8 = 73 * Added fallback regex-based conversion for servers without php-xml extension 74 * Fixed critical error on servers missing DOMDocument class -
contentpen/trunk/contentpen-plugin.php
r3455153 r3455197 5 5 * Plugin URI: https://contentpen.ai 6 6 * Description: Contentpen is an AI-powered content writing assistant designed to help businesses create, optimize, and publish SEO-friendly blog posts at scale. By combining deep research with your brand's unique voice, Contentpen crafts high-impact articles that outperform your competition. 7 * Version: 1.0. 77 * Version: 1.0.8 8 8 * Requires at least: 5.8 9 9 * Requires PHP: 7.4 … … 20 20 } 21 21 22 define('CONTENTPEN_VERSION', '1.0. 7');22 define('CONTENTPEN_VERSION', '1.0.8'); 23 23 define('CONTENTPEN_PLUGIN_DIR', plugin_dir_path(__FILE__)); 24 24 define('CONTENTPEN_PLUGIN_URL', plugin_dir_url(__FILE__)); -
contentpen/trunk/includes/class-gutenberg-converter.php
r3455149 r3455197 27 27 if (strpos($html, '<!-- wp:') !== false) { 28 28 return $html; 29 } 30 31 // Check if DOMDocument is available (requires php-xml extension) 32 if (!class_exists('DOMDocument')) { 33 // Fallback: use regex-based conversion 34 return self::convert_with_regex($html); 29 35 } 30 36 … … 269 275 return "<!-- wp:code -->\n" . $html . "\n<!-- /wp:code -->\n\n"; 270 276 } 277 278 /** 279 * Fallback regex-based conversion when DOMDocument is not available. 280 * 281 * @param string $html The HTML content to convert. 282 * @return string The converted Gutenberg block content. 283 */ 284 private static function convert_with_regex($html) 285 { 286 $output = ''; 287 288 // Pattern to match top-level block elements 289 $pattern = '/<(p|h[1-6]|ul|ol|blockquote|table|figure|pre)(\s[^>]*)?>.*?<\/\1>/is'; 290 291 $last_pos = 0; 292 if (preg_match_all($pattern, $html, $matches, PREG_OFFSET_CAPTURE)) { 293 foreach ($matches[0] as $index => $match) { 294 $full_match = $match[0]; 295 $pos = $match[1]; 296 $tag = strtolower($matches[1][$index][0]); 297 298 // Handle any text between matches 299 if ($pos > $last_pos) { 300 $between = trim(substr($html, $last_pos, $pos - $last_pos)); 301 if (!empty($between) && !preg_match('/^\s*$/', $between)) { 302 $output .= self::wrap_paragraph('<p>' . $between . '</p>'); 303 } 304 } 305 306 // Convert based on tag 307 switch ($tag) { 308 case 'p': 309 $output .= self::wrap_paragraph($full_match); 310 break; 311 case 'h1': 312 case 'h2': 313 case 'h3': 314 case 'h4': 315 case 'h5': 316 case 'h6': 317 $level = (int) substr($tag, 1); 318 $output .= self::wrap_heading($full_match, $level); 319 break; 320 case 'ul': 321 $output .= self::wrap_list($full_match, false); 322 break; 323 case 'ol': 324 $output .= self::wrap_list($full_match, true); 325 break; 326 case 'blockquote': 327 $output .= self::wrap_quote($full_match); 328 break; 329 case 'table': 330 $output .= self::wrap_table($full_match); 331 break; 332 case 'figure': 333 if (stripos($full_match, '<img') !== false) { 334 $output .= self::wrap_image($full_match); 335 } else { 336 $output .= $full_match . "\n\n"; 337 } 338 break; 339 case 'pre': 340 $output .= self::wrap_code($full_match); 341 break; 342 default: 343 $output .= "<!-- wp:html -->\n" . trim($full_match) . "\n<!-- /wp:html -->\n\n"; 344 } 345 346 $last_pos = $pos + strlen($full_match); 347 } 348 349 // Handle any remaining content after last match 350 if ($last_pos < strlen($html)) { 351 $remaining = trim(substr($html, $last_pos)); 352 if (!empty($remaining) && !preg_match('/^\s*$/', $remaining)) { 353 $output .= self::wrap_paragraph('<p>' . $remaining . '</p>'); 354 } 355 } 356 } 357 358 // If no matches found, wrap entire content 359 if (empty($output)) { 360 return self::wrap_paragraph($html); 361 } 362 363 return trim($output); 364 } 271 365 }
Note: See TracChangeset
for help on using the changeset viewer.