// Extract JSON from text with improved error handling function wcsb_extract_json_from_text($text) { // First, try to parse the entire response as JSON $json_data = json_decode($text, true); if (json_last_error() === JSON_ERROR_NONE) { return $json_data; } // If that fails, try to extract JSON using regex if (preg_match('/\{(?:[^{}]|(?R))*\}/s', $text, $matches)) { $json_string = $matches[0]; // Try to fix common JSON issues $fixed_json = wcsb_fix_json_string($json_string); $json_data = json_decode($fixed_json, true); if (json_last_error() === JSON_ERROR_NONE) { return $json_data; } } // If we have a JSON parsing error, try to extract and fix the structure manually if (strpos($text, '"title"') !== false && strpos($text, '"pages"') !== false) { try { $manual_json = wcsb_manually_extract_json($text); return $manual_json; } catch (Exception $e) { error_log('Manual JSON extraction failed: ' . $e->getMessage()); } } // If all else fails, create a basic structure with the text as HTML $fallback_data = array( 'title' => 'Generated Website', 'pages' => array( array( 'name' => 'Home', 'slug' => 'home', 'html' => '

JSON Parsing Error

The AI generated content that couldn\'t be properly formatted. Here\'s the raw response:

' . esc_html(substr($text, 0, 1000)) . '...
', 'css' => '.wcsb-error-container { padding: 20px; border: 1px solid #ddd; background: #f9f9f9; } .wcsb-error-container pre { overflow: auto; background: #f0f0f0; padding: 10px; }' ) ), 'globalCss' => '', 'globalJs' => '', 'plugins' => array(), 'theme' => 'default' ); // Log the error for debugging error_log('Failed to parse JSON from Claude response: ' . json_last_error_msg()); error_log('Raw response: ' . substr($text, 0, 500) . '...'); return $fallback_data; } // Function to fix common JSON string issues function wcsb_fix_json_string($json_string) { // Replace newlines in string values $json_string = preg_replace('/"\s*\n\s*([^"]+)\s*\n\s*"/s', '" $1 "', $json_string); // Fix escaped quotes $json_string = str_replace('\\"', '"', $json_string); // Fix unescaped newlines in strings $json_string = preg_replace_callback('/"([^"]*)"/', function($matches) { return '"' . str_replace("\n", "\\n", $matches[1]) . '"'; }, $json_string); return $json_string; } // Function to manually extract JSON structure function wcsb_manually_extract_json($text) { $result = array(); // Extract title if (preg_match('/"title":\s*"([^"]+)"/', $text, $matches)) { $result['title'] = $matches[1]; } else { $result['title'] = 'Generated Website'; } // Extract pages $result['pages'] = array(); // Extract HTML content if (preg_match('/"html":\s*"(.*?)(?:"|",\s*"css")/', $text, $matches)) { $html = $matches[1]; // Clean up the HTML $html = str_replace('\n', "\n", $html); $html = str_replace('\"', '"', $html); } else { $html = '
No content available
'; } // Extract CSS content if (preg_match('/"css":\s*"(.*?)(?:"|",\s*"js")/', $text, $matches)) { $css = $matches[1]; // Clean up the CSS $css = str_replace('\n', "\n", $css); $css = str_replace('\"', '"', $css); } else { $css = ''; } // Extract JS content if (preg_match('/"js":\s*"(.*?)(?:"|"\s*})/', $text, $matches)) { $js = $matches[1]; // Clean up the JS $js = str_replace('\n', "\n", $js); $js = str_replace('\"', '"', $js); } else { $js = ''; } $result['pages'][] = array( 'name' => 'Home', 'slug' => 'home', 'html' => $html, 'css' => $css, 'js' => $js ); // Extract global CSS if (preg_match('/"globalCss":\s*"(.*?)(?:"|",\s*"globalJs")/', $text, $matches)) { $globalCss = $matches[1]; // Clean up the global CSS $globalCss = str_replace('\n', "\n", $globalCss); $globalCss = str_replace('\"', '"', $globalCss); $result['globalCss'] = $globalCss; } else { $result['globalCss'] = ''; } // Extract global JS if (preg_match('/"globalJs":\s*"(.*?)(?:"|",\s*"plugins")/', $text, $matches)) { $globalJs = $matches[1]; // Clean up the global JS $globalJs = str_replace('\n', "\n", $globalJs); $globalJs = str_replace('\"', '"', $globalJs); $result['globalJs'] = $globalJs; } else { $result['globalJs'] = ''; } // Extract plugins if (preg_match('/"plugins":\s*\[(.*?)\]/', $text, $matches)) { $plugins_str = $matches[1]; $plugins = array(); preg_match_all('/"([^"]+)"/', $plugins_str, $plugin_matches); if (!empty($plugin_matches[1])) { $plugins = $plugin_matches[1]; } $result['plugins'] = $plugins; } else { $result['plugins'] = array(); } // Extract theme if (preg_match('/"theme":\s*"([^"]+)"/', $text, $matches)) { $result['theme'] = $matches[1]; } else { $result['theme'] = 'custom'; } return $result; } // Call Claude API directly with improved JSON handling function wcsb_call_claude_api_directly($prompt, $api_key, $max_tokens = 4000, $system = '') { // Claude API endpoint $api_url = 'https://api.anthropic.com/v1/messages'; // Get selected model $model = get_option('wcsb_claude_model', 'claude-3-5-sonnet-20240620'); // Add specific instructions for JSON formatting $json_instructions = "\n\nIMPORTANT: Your response must be a valid JSON object. Make sure to properly escape all quotes and special characters in HTML, CSS, and JavaScript strings."; // Prepare request body $request_body = array( 'model' => $model, 'max_tokens' => $max_tokens, 'temperature' => 0.5, // Lower temperature for more reliable JSON generation 'messages' => array( array( 'role' => 'user', 'content' => $prompt . $json_instructions ) ) ); // Add system prompt if provided if (!empty($system)) { $request_body['system'] = $system . "\n\nYour response MUST be valid JSON with properly escaped strings."; } // Make request to Claude API $response = wp_remote_post($api_url, array( 'headers' => array( 'Content-Type' => 'application/json', 'x-api-key' => $api_key, 'anthropic-version' => '2023-06-01' ), 'body' => json_encode($request_body), 'timeout' => 120 )); if (is_wp_error($response)) { return $response; } $response_code = wp_remote_retrieve_response_code($response); if ($response_code !== 200) { $error_body = wp_remote_retrieve_body($response); $error_data = json_decode($error_body, true); $error_message = isset($error_data['error']['message']) ? $error_data['error']['message'] : 'Unknown error'; return new WP_Error('claude_api_error', 'Claude API error: ' . $error_message); } $body = json_decode(wp_remote_retrieve_body($response), true); if (json_last_error() !== JSON_ERROR_NONE) { return new WP_Error('json_error', 'Invalid JSON response from Claude API: ' . json_last_error_msg()); } // Extract the content from the response if (isset($body['content']) && is_array($body['content']) && !empty($body['content'])) { foreach ($body['content'] as $content) { if ($content['type'] === 'text') { return $content['text']; } } } return new WP_Error('invalid_response', 'Invalid response format from Claude API'); } // Get template-specific system prompt with improved JSON formatting instructions function wcsb_get_template_prompt($template) { $templates = array( 'modern' => "You are an expert WordPress developer and designer specializing in modern, eye-catching websites. Generate a complete WordPress website based on the user's description. Your design MUST follow these principles: - Use modern, clean design with ample white space - Create responsive layouts that work on all devices - Use attractive color schemes with good contrast - Implement modern typography with readable font sizes - Include subtle animations and transitions - Use high-quality imagery and icons - Follow current web design trends Your response MUST be a valid JSON object with the following structure: { \"title\": \"Site Title\", \"pages\": [ { \"name\": \"Home\", \"slug\": \"home\", \"html\": \"Full HTML content\", \"css\": \"Page-specific CSS\", \"js\": \"Page-specific JavaScript\" } ], \"globalCss\": \"Global CSS styles\", \"globalJs\": \"Global JavaScript\", \"plugins\": [\"plugin-1\", \"plugin-2\"], \"theme\": \"Suggested theme or 'custom'\" } For the HTML and CSS: - Use modern CSS features like flexbox and grid for layouts - Include responsive design with media queries - Use CSS variables for consistent colors and styling - Create visually appealing hero sections with gradients or background images - Add subtle hover effects and transitions - Include modern UI components like cards, badges, and tooltips - Use !important for critical CSS properties to prevent theme overrides - Ensure all CSS selectors are prefixed to prevent conflicts - Make sure the design is visually appealing with proper colors and styling For JavaScript: - DO NOT include

Page Not Found

The page you are looking for does not exist, or it has been moved. Please try searching using the form below.