get( 'chat_widget_title', __( 'AI Support Assistant', 'ai-support-assistant' ) ); if ( empty( $widget_title ) ) { $widget_title = __( 'AI Support Assistant', 'ai-support-assistant' ); } // Localize parameters for the frontend JS. wp_localize_script( 'ai-support-assistant-frontend-js', 'AISupportAssistant', array( 'restUrl' => esc_url_raw( get_rest_url( null, 'ai-support-assistant/v1/chat' ) ), 'nonce' => wp_create_nonce( 'ai_support_assistant_action' ), 'restNonce' => wp_create_nonce( 'wp_rest' ), 'title' => esc_html( $widget_title ), 'greeting' => esc_html( $settings->get( 'chat_widget_greeting', __( 'Hello! I am your documentation assistant. Ask me anything, and I will search our guide files to help you.', 'ai-support-assistant' ) ) ), 'enableStreaming' => ! empty( $settings->get( 'enable_streaming', 1 ) ) ? 1 : 0, 'i18n' => array( 'typing' => __( 'Assistant is typing...', 'ai-support-assistant' ), 'error' => __( 'Sorry, unable to fetch response. Try again.', 'ai-support-assistant' ), 'placeholder' => __( 'Type your question...', 'ai-support-assistant' ), 'ready' => __( 'AI Assistant Ready', 'ai-support-assistant' ), 'chat_hint' => __( 'Ask a question to start chatting', 'ai-support-assistant' ), ), ) ); } /** * Render AI Support Assistant Shortcode. * * @param array $atts Shortcode attributes. * @return string Output HTML. */ public function render_shortcode( $atts = array() ): string { // Enqueue the registered assets. wp_enqueue_style( 'ai-support-assistant-frontend-style' ); wp_enqueue_style( 'dashicons' ); wp_enqueue_script( 'ai-support-assistant-frontend-js' ); $settings = \AISupportAssistant\Admin\Settings::get_instance(); $default_title = $settings->get( 'chat_widget_title', __( 'AI Support Assistant', 'ai-support-assistant' ) ); if ( empty( $default_title ) ) { $default_title = __( 'AI Support Assistant', 'ai-support-assistant' ); } // Merge attributes. $attributes = shortcode_atts( array( 'theme' => 'light', 'title' => $default_title, 'height' => '600px', 'width' => '450px', 'provider_override' => '', ), $atts, 'ai_support_assistant' ); // If title attribute is passed as empty or whitespace, fallback to default title from settings. if ( empty( trim( (string) $attributes['title'] ) ) ) { $attributes['title'] = $default_title; } // Buffer template output. ob_start(); $template = AI_SUPPORT_ASSISTANT_PATH . 'templates/frontend-chat.php'; if ( file_exists( $template ) ) { $theme = esc_attr( $attributes['theme'] ); $title = esc_html( $attributes['title'] ); $height = esc_attr( $this->sanitize_dimension( $attributes['height'], '600px' ) ); $width = esc_attr( $this->sanitize_dimension( $attributes['width'], '450px' ) ); $greeting = esc_html( $settings->get( 'chat_widget_greeting', __( 'Hello! I am your documentation assistant. Ask me anything, and I will search our guide files to help you.', 'ai-support-assistant' ) ) ); $show_powered_by = (int) $settings->get( 'show_powered_by', 0 ); include $template; } return ob_get_clean(); } /** * Sanitize CSS dimension attribute (e.g. 600px, 80vh, 100%, or numeric 600). * * @param mixed $val User input dimension. * @param string $default Default fallback dimension. * @return string */ private function sanitize_dimension( $val, string $default ): string { $val = trim( (string) $val ); if ( '' === $val ) { return $default; } if ( is_numeric( $val ) ) { return $val . 'px'; } if ( preg_match( '/^\d+(\.\d+)?(px|%|vh|vw|em|rem)$/i', $val ) ) { return $val; } return $default; } }