PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 3.5.3
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v3.5.3
4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.5.2 All 199 releases
← All changes | includes/Core/WriteWithAI.php +850 -1095 4.5.43.5.3 View file →
@@ -1,107 +1,76 @@
1 1 <?php
2 2
3 - namespace WPDeveloper\BetterDocs\Core;
3 +namespace WPDeveloper\BetterDocs\Core;
4 4
5 - use WPDeveloper\BetterDocs\Utils\Base;
6 - use WPDeveloper\BetterDocs\Core\Settings;
7 - use WPDeveloper\BetterDocs\Core\PostType;
5 +use WPDeveloper\BetterDocs\Utils\Base;
6 +use WPDeveloper\BetterDocs\Core\Settings;
7 +use WPDeveloper\BetterDocs\Core\PostType;
8 8
9 - use WPDeveloper\BetterDocs\Utils\Helper;
10 - use WPDeveloper\BetterDocs\Utils\AIHelper;
9 +use WPDeveloper\BetterDocs\Utils\Helper;
11 10
12 - class WriteWithAI extends Base {
13 -
11 +class WriteWithAI extends Base
12 +{
14 13 public $settings;
15 14
16 - public function __construct( Settings $settings ) {
15 + public function __construct(Settings $settings)
16 + {
17 17 $this->settings = $settings;
18 18 // Get the post ID from the URL
19 - $post_id = isset( $_GET[ 'post' ] ) ? intval( $_GET[ 'post' ] ) : 0; // phpcs:ignore
19 + $post_id = isset($_GET['post']) ? intval($_GET['post']) : 0;
20 20
21 - if ( ! empty( $_GET[ 'post_type' ] ) ) { // phpcs:ignore
22 - $post_type = $_GET[ 'post_type' ]; // phpcs:ignore
23 - } elseif ( $post_id > 0 ) {
24 - $post_type = get_post_type( $post_id );
21 + if (!empty($_GET['post_type'])) {
22 + $post_type = $_GET['post_type'];
23 + } else if ($post_id > 0) {
24 + $post_type = get_post_type($post_id);
25 25 } else {
26 26 $post_type = '';
27 27 }
28 28
29 - if ( ! empty( $this->isEnabledWriteWithAI() ) && 'docs' == $post_type ) {
30 - add_action( 'admin_footer', array( $this, 'ai_autowrite_button' ) );
31 - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_ai_edit_assets' ) );
29 + if (!empty($this->isEnabledWriteWithAI()) && $post_type == 'docs') {
30 + add_action('admin_footer', [$this, 'ai_autowrite_button']);
32 31 }
33 - add_action( 'wp_ajax_generate_openai_content', array( $this, 'generate_openai_content_callback' ) );
32 + add_action('wp_ajax_generate_openai_content', [$this, 'generate_openai_content_callback']);
34 33 }
35 34
36 - public function enqueue_ai_edit_assets( $hook ) {
37 - if ( 'post.php' !== $hook && 'post-new.php' !== $hook ) {
38 - return;
39 - }
40 -
41 - global $post_type;
42 - if ( 'docs' !== $post_type ) {
43 - return;
44 - }
45 -
46 - if ( empty( $this->get_api_key() ) ) {
47 - return;
48 - }
49 -
50 - betterdocs()->assets->enqueue( 'betterdocs-ai-edit', 'blocks/ai-edit.js' );
51 - betterdocs()->assets->enqueue( 'betterdocs-ai-edit-style', 'blocks/ai-edit-style.css' );
52 -
53 - wp_localize_script(
54 - 'betterdocs-ai-edit',
55 - 'betterdocsAIEdit',
56 - array(
57 - 'rest_url' => esc_url_raw( rest_url( 'betterdocs/v1/ai-edit' ) ),
58 - 'rest_nonce' => wp_create_nonce( 'wp_rest' ),
59 - 'post_id' => get_the_ID()
60 - )
61 - );
62 - }
63 -
64 - public function isEnabledWriteWithAI() {
65 - $isEnableAutoWrite = $this->settings->get( 'enable_write_with_ai', true );
35 + public function isEnabledWriteWithAI()
36 + {
37 + $isEnableAutoWrite = $this->settings->get('enable_write_with_ai', true);
66 38 return $isEnableAutoWrite;
67 39 }
68 40
69 - public function isValidAPIKey( $apiKey ) {
70 - if ( empty( $apiKey ) ) {
71 - $api_response[ 'valid' ] = false;
72 - $api_response[ 'message' ] = 'Please Insert your <a href="/admin.php?page=betterdocs-settings#betterdocs-ai">OpenAI API Key</a> to use this Write with AI feature.';
41 + public function isValidAPIKey($apiKey)
42 + {
43 + if (empty($apiKey)) {
44 + $api_response['valid'] = false;
45 + $api_response['message'] = 'Please Insert your <a href="/admin.php?page=betterdocs-settings">OpenAI API Key</a> to use this Write with AI feature.';
73 46
74 47 return $api_response;
75 48 }
76 49
77 - $ch = curl_init( 'https://api.openai.com/v1/engines' ); //phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_init
78 - curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); //phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_setopt
79 - curl_setopt(
80 - $ch,
81 - CURLOPT_HTTPHEADER,
82 - array( //phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_setopt
83 - 'Content-Type: application/json',
84 - 'Authorization: Bearer ' . $apiKey
85 - )
86 - );
50 + $ch = curl_init('https://api.openai.com/v1/engines');
51 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
52 + curl_setopt($ch, CURLOPT_HTTPHEADER, [
53 + 'Content-Type: application/json',
54 + 'Authorization: Bearer ' . $apiKey,
55 + ]);
87 56
88 - $api_response = array();
57 + $api_response = [];
89 58
90 - $response = curl_exec( $ch ); //phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_exec
91 - $httpCode = curl_getinfo( $ch, CURLINFO_HTTP_CODE ); //phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_getinfo
59 + $response = curl_exec($ch);
60 + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
92 61
93 - curl_close( $ch ); //phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_close
62 + curl_close($ch);
94 63
95 - if ( 200 == $httpCode ) {
96 - $api_response[ 'valid' ] = true;
97 - $api_response[ 'message' ] = 'Valid API Key';
64 + if ($httpCode == 200) {
65 + $api_response['valid'] = true;
66 + $api_response['message'] = 'Valid API Key';
98 67 } else {
99 - $responseData = json_decode( $response, true );
68 + $responseData = json_decode($response, true);
100 69 // Access the message data (replace 'data' with the actual key used in the response)
101 - $messageData = $responseData[ 'error' ] ? $responseData[ 'error' ] : '';
102 - $api_response[ 'valid' ] = false;
103 - $api_response[ 'message' ] = $messageData[ 'message' ] ? $messageData[ 'message' ] : 'Invalid API Key';
70 + $messageData = $responseData['error'] ? $responseData['error'] : '';
71 + $api_response['valid'] = false;
72 + $api_response['message'] = $messageData['message'] ? $messageData['message'] : 'Invalid API Key';
104 73 }
105 74
106 75 // print_r($response);
107 76
@@ -107,1239 +76,1025 @@
107 76
108 77 return $api_response;
109 78 }
110 79
111 - public function get_api_key() {
112 - $api_key = $this->settings->get( 'ai_autowrite_api_key', '' );
80 + public function get_api_key()
81 + {
82 + $api_key = $this->settings->get('ai_autowrite_api_key', '');
113 83 return $api_key;
114 84 }
115 85
116 - public function get_system_prompt() {
117 - $prompt = <<<'PROMPT'
118 -You are a Senior Technical Writer specializing in comprehensive, high-quality documentation. Your goal is to produce documentation that scores 100/100 on clarity, completeness, and structure.
119 86
120 -## Output format
121 -
122 -Return only HTML body content. Never wrap output in `<!doctype>`, `<html>`, `<head>`, `<body>`, or markdown code fences (no ```html ... ```).
123 -
124 -Use semantic, Gutenberg-friendly tags only:
125 -- Headings: `<h2>`, `<h3>`, `<h4>` (do not emit `<h1>` — it is reserved for the document title)
126 -- Paragraphs: `<p>` for prose
127 -- Lists: `<ul>`/`<ol>` with `<li>` for any list of items, steps, or bullet points — never fake a list with paragraphs or `<br>`
128 -- Links: `<a href="https://...">link text</a>` with absolute URLs
129 -- Inline emphasis: `<strong>`, `<em>`, `<code>`
130 -- Code blocks: `<pre><code>...</code></pre>` for multi-line code or commands
131 -- Quotes: `<blockquote>`
132 -- Tables: `<table>` with `<thead>`, `<tbody>`, `<tr>`, `<th>`, `<td>`
133 -- Images: `<img src="..." alt="...">`
134 -
135 -Apply `<span class="highlight">key term</span>` to important topic terms inside headings and to the first occurrence of each keyword in body text. Use it sparingly — never wrap whole sentences or wrap text inside `href`, `src`, `alt`, or other attributes.
136 -
137 -Do not emit `<style>`, `<script>`, `<iframe>`, `<form>`, or inline `style=""` / `class=""` attributes (other than the `highlight` class above).
138 -
139 -If — and only if — the user's prompt explicitly asks for raw/custom HTML, embed code, or a non-standard structure, follow that request instead of these defaults.
140 -PROMPT;
141 -
142 - return apply_filters( 'betterdocs_write_with_ai_system_prompt', $prompt );
143 - }
144 -
145 - public function generate_openai_response( $prompt, $keywords ) {
87 + public function generate_openai_response($prompt, $keywords)
88 + {
146 89 try {
147 - $api_key = $this->settings->get( 'ai_autowrite_api_key', '' );
148 - $max_tokens = $this->settings->get( 'ai_autowrite_max_token', 2500 );
149 - $model = $this->settings->get( 'write_with_ai_model', 'gpt-4o-mini' );
90 + $api_key = $this->settings->get('ai_autowrite_api_key', '');
91 + $max_tokens = $this->settings->get('ai_autowrite_max_token', 1500);
150 92
151 93 $api_endpoint = 'https://api.openai.com/v1/chat/completions'; // Update the endpoint based on OpenAI API version
152 94
153 - $request_body = AIHelper::build_openai_payload(
154 - $model,
155 - array(
156 - array(
157 - 'role' => 'system',
158 - 'content' => $this->get_system_prompt()
159 - ),
160 - array(
161 - 'role' => 'user',
162 - 'content' => $prompt
163 - )
164 - ),
165 - $max_tokens,
166 - null,
167 - 'write_with_ai'
168 - );
169 -
170 95 $request_options = array(
171 96 'headers' => array(
172 97 'Content-Type' => 'application/json',
173 - 'Authorization' => 'Bearer ' . $api_key
98 + 'Authorization' => 'Bearer ' . $api_key,
174 99 ),
175 - 'body' => json_encode( $request_body ),
176 - 'timeout' => 300
100 + 'body' => json_encode(array(
101 + 'model' => 'gpt-3.5-turbo', // Add the model parameter here
102 + 'messages' => array(
103 + array('role' => 'system', 'content' => 'You are a helpful assistant who writes documentation for users.'),
104 + array('role' => 'user', 'content' => $prompt),
105 + ),
106 + 'max_tokens' => $max_tokens,
107 +
108 + )),
109 + 'timeout' => 50,
177 110 );
178 111
179 - // GPT-5.5 reasoning can run well past the default limits; give PHP and
180 - // the HTTP call room to finish (still subject to server php-fpm/nginx limits).
181 - if ( function_exists( 'set_time_limit' ) ) {
182 - set_time_limit( 300 );
183 - }
112 + $response = wp_remote_post($api_endpoint, $request_options);
184 113
185 - $response = wp_remote_post( $api_endpoint, $request_options );
186 -
187 - if ( is_wp_error( $response ) ) {
114 + if (is_wp_error($response)) {
188 115 return 'Error: ' . $response->get_error_message();
189 116 } else {
190 - $body = wp_remote_retrieve_body( $response );
117 + $body = wp_remote_retrieve_body($response);
191 118
192 - $data = json_decode( $body, true );
119 + $data = json_decode($body, true);
193 120
194 - if ( ! empty( $data[ 'error' ] ) ) {
195 - return $data[ 'error' ][ 'message' ];
121 + if (!empty($data['error'])) {
122 + return $data['error']['message'];
196 123 }
197 124
198 - return $data[ 'choices' ][ 0 ][ 'message' ][ 'content' ]; // Update this line to get the assistant's message
125 + return $data['choices'][0]['message']['content']; // Update this line to get the assistant's message
199 126 }
200 - } catch ( Exception $error ) {
127 + } catch (Exception $error) {
201 128 return 'Error: ' . $error->getMessage();
202 129 }
203 130 }
204 131
205 - public function generate_openai_response_ai_edit( $prompt ) {
206 - $api_key = $this->settings->get( 'ai_autowrite_api_key', '' );
207 - $max_tokens = $this->settings->get( 'ai_autowrite_max_token', 2500 );
208 - $model = $this->settings->get( 'write_with_ai_model', 'gpt-4o-mini' );
209 132
210 - $api_endpoint = 'https://api.openai.com/v1/chat/completions';
211 133
212 - $payload = AIHelper::build_openai_payload(
213 - $model,
214 - array(
215 - array(
216 - 'role' => 'system',
217 - 'content' => $this->get_system_prompt()
218 - ),
219 - array(
220 - 'role' => 'user',
221 - 'content' => $prompt
222 - )
223 - ),
224 - $max_tokens,
225 - null,
226 - 'write_with_ai'
227 - );
228 -
229 - $request_options = array(
230 - 'headers' => array(
231 - 'Content-Type' => 'application/json',
232 - 'Authorization' => 'Bearer ' . $api_key
233 - ),
234 - 'body' => wp_json_encode( $payload ),
235 - 'timeout' => 300
236 - );
237 -
238 - // GPT-5.5 reasoning can run well past the default limits; give PHP and
239 - // the HTTP call room to finish (still subject to server php-fpm/nginx limits).
240 - if ( function_exists( 'set_time_limit' ) ) {
241 - set_time_limit( 300 );
242 - }
243 -
244 - $response = wp_remote_post( $api_endpoint, $request_options );
245 -
246 - if ( is_wp_error( $response ) ) {
247 - return array(
248 - 'success' => false,
249 - 'error' => $response->get_error_message(),
250 - 'model' => $model
251 - );
252 - }
253 -
254 - $body = wp_remote_retrieve_body( $response );
255 - $data = json_decode( $body, true );
256 -
257 - if ( ! empty( $data[ 'error' ] ) ) {
258 - return array(
259 - 'success' => false,
260 - 'error' => isset( $data[ 'error' ][ 'message' ] ) ? $data[ 'error' ][ 'message' ] : 'OpenAI error',
261 - 'model' => $model,
262 - 'raw' => $data
263 - );
264 - }
265 -
266 - $content = isset( $data[ 'choices' ][ 0 ][ 'message' ][ 'content' ] ) ? $data[ 'choices' ][ 0 ][ 'message' ][ 'content' ] : '';
267 - $usage = isset( $data[ 'usage' ] ) && is_array( $data[ 'usage' ] ) ? $data[ 'usage' ] : array();
268 -
269 - return array(
270 - 'success' => true,
271 - 'content' => $content,
272 - 'model' => $model,
273 - 'prompt_tokens' => isset( $usage[ 'prompt_tokens' ] ) ? (int) $usage[ 'prompt_tokens' ] : null,
274 - 'completion_tokens' => isset( $usage[ 'completion_tokens' ] ) ? (int) $usage[ 'completion_tokens' ] : null,
275 - 'total_tokens' => isset( $usage[ 'total_tokens' ] ) ? (int) $usage[ 'total_tokens' ] : null,
276 - 'finish_reason' => isset( $data[ 'choices' ][ 0 ][ 'finish_reason' ] ) ? $data[ 'choices' ][ 0 ][ 'finish_reason' ] : null
277 - );
278 - }
279 -
280 - public function generate_openai_content_callback() {
134 + public function generate_openai_content_callback()
135 + {
281 136 // Verify the nonce
282 - if ( ! isset( $_POST[ 'ai_nonce' ] ) || ! wp_verify_nonce( $_POST[ 'ai_nonce' ], 'generate_openai_content_nonce' ) ) { //phpcs:ignore
283 - wp_send_json_error( 'Invalid nonce' );
137 + if (!isset($_POST['ai_nonce']) || !wp_verify_nonce($_POST['ai_nonce'], 'generate_openai_content_nonce')) {
138 + wp_send_json_error('Invalid nonce');
284 139 wp_die();
285 140 }
286 141
287 - if ( ! current_user_can( 'edit_posts' ) ) {
288 - wp_send_json_error( 'Insufficient permissions' );
289 - wp_die();
290 - }
291 -
292 - $prompt = sanitize_text_field( $_POST[ 'prompt' ] ); //phpcs:ignore
142 + $prompt = sanitize_text_field($_POST['prompt']);
293 143 // $num_of_sections = sanitize_text_field($_POST['numOfSections']);
294 144 // $num_of_paragraphs = sanitize_text_field($_POST['numOfParagraphs']);
295 - $keywords = sanitize_text_field( $_POST[ 'keywords' ] ); //phpcs:ignore
145 + $keywords = sanitize_text_field($_POST['keywords']);
296 146
297 - $ai_instance = new WriteWithAI( $this->settings );
147 + $ai_instance = new WriteWithAI($this->settings);
298 148
299 - $generated_content = $ai_instance->generate_openai_response( $prompt, $keywords );
149 + $generated_content = $ai_instance->generate_openai_response($prompt, $keywords);
300 150
301 151 // Send the generated content as the AJAX response
302 - wp_send_json_success( $generated_content );
152 + wp_send_json_success($generated_content);
303 153 wp_die();
304 154 }
305 155
306 - public function ai_autowrite_button() {
156 + public function ai_autowrite_button()
157 + {
307 158
308 159 ?>
309 - <script>
310 - var docsTitle;
160 + <script>
161 + var docsTitle;
311 162
312 - function responseMessage(message) {
313 - return `<div class="warning-message">
314 - <span class="dashicons dashicons-warning"></span>
315 - <div class="footer-message">
316 - ${message}
317 - </div>
318 - </div>`;
319 - }
163 + function responseMessage(message) {
164 + return `<div class="warning-message">
165 + <span class="dashicons dashicons-warning"></span>
166 + <div class="footer-message">
167 + ${message}
168 + </div>
169 + </div>`;
170 + }
320 171
321 - function generateArticle(e) {
172 + function generateArticle(e) {
322 173
323 174
324 - const title = document.getElementById('betterdocs-ai-title').value;
325 - const keywords = document.getElementById('betterdocs-ai-keyword').value;
326 - // const sectionOptions = document.getElementById('bd-autowrtite-content-section');
327 - // const numOfSections = sectionOptions.options[sectionOptions.selectedIndex].value;
175 + const title = document.getElementById('betterdocs-ai-title').value;
176 + const keywords = document.getElementById('betterdocs-ai-keyword').value;
177 + // const sectionOptions = document.getElementById('bd-autowrtite-content-section');
178 + // const numOfSections = sectionOptions.options[sectionOptions.selectedIndex].value;
328 179
329 - // const paragraphOptions = document.getElementById('bd-autowrtite-content-paragraph');
330 - // const numOfParagraphs = paragraphOptions.options[paragraphOptions.selectedIndex].value;
180 + // const paragraphOptions = document.getElementById('bd-autowrtite-content-paragraph');
181 + // const numOfParagraphs = paragraphOptions.options[paragraphOptions.selectedIndex].value;
331 182
332 - const contentTextArea = document.getElementById('betterdocs-ai-content');
333 - const docGenerateBtnTxt = document.querySelector('.generate-btn span');
183 + const contentTextArea = document.getElementById('betterdocs-ai-content');
184 + const docGenerateBtnTxt = document.querySelector('.generate-btn span');
334 185
335 - // Add nonce value to the data being sent
336 - const nonce = document.querySelector('input[name="ai_nonce"]').value;
337 - const isOverwrite = document.getElementById('betterdocs-ai-checkbox').checked;
338 - const generateDocLabel = "<?php echo esc_html__( 'Generate Doc', 'betterdocs' ); ?>";
339 - const reGenerateDocLabel = "<?php echo esc_html__( 'Regenerate Doc', 'betterdocs' ); ?>";
186 + // Add nonce value to the data being sent
187 + const nonce = document.querySelector('input[name="ai_nonce"]').value;
188 + const isOverwrite = document.getElementById('betterdocs-ai-checkbox').checked;
189 + const generateDocLabel = "<?php echo esc_html__('Generate Doc', 'betterdocs'); ?>";
190 + const reGenerateDocLabel = "<?php echo esc_html__('Regenerate Doc', 'betterdocs'); ?>";
340 191
341 192
342 - // contentTextArea.value = `Write an article about ${title} in English. The article is organized by the following exact ${numOfSections} headings. Write exact ${numOfParagraphs} number of paragraphs per heading.${keywords} Use Markdown for formatting. Add an introduction and a conclusion. Style: creative. Tone: cheerful.`;
193 + // contentTextArea.value = `Write an article about ${title} in English. The article is organized by the following exact ${numOfSections} headings. Write exact ${numOfParagraphs} number of paragraphs per heading.${keywords} Use Markdown for formatting. Add an introduction and a conclusion. Style: creative. Tone: cheerful.`;
343 194
344 195
345 - // Check if the title is not empty
346 - if (title.trim() !== '' && keywords.trim() !== '') {
347 - e.preventDefault();
196 + // Check if the title is not empty
197 + if (title.trim() !== '' && keywords.trim() !== '') {
198 + e.preventDefault();
348 199
349 - if (!jQuery('#betterdocs-ai-error-message').parent().hasClass('hidden')) {
350 - jQuery('#betterdocs-ai-error-message').parent().addClass('hidden');
351 - }
200 + if (!jQuery('#betterdocs-ai-error-message').parent().hasClass('hidden')) {
201 + jQuery('#betterdocs-ai-error-message').parent().addClass('hidden');
202 + }
352 203
353 - docGenerateBtnTxt.innerHTML = "<?php echo esc_html__( 'Generating...', 'betterdocs' ); ?>";
354 - jQuery('.generate-btn').prop('disabled', true);
204 + docGenerateBtnTxt.innerHTML = "<?php echo esc_html__('Generating...', 'betterdocs'); ?>";
205 + jQuery('.generate-btn').prop('disabled', true);
355 206
356 - jQuery.post({
357 - url: ajaxurl, // Make sure ajaxurl is defined in your script
358 - type: 'POST',
359 - data: {
360 - action: 'generate_openai_content',
361 - prompt: document.querySelector('#betterdocs-ai-content').value,
362 - // numOfSections: numOfSections,
363 - // numOfParagraphs: numOfParagraphs,
364 - keywords: keywords,
365 - ai_nonce: nonce, // Pass the nonce value
366 - },
367 - success: function(response) {
368 - // Update the content in the textarea
207 + jQuery.post({
208 + url: ajaxurl, // Make sure ajaxurl is defined in your script
209 + type: 'POST',
210 + data: {
211 + action: 'generate_openai_content',
212 + prompt: document.querySelector('#betterdocs-ai-content').value,
213 + // numOfSections: numOfSections,
214 + // numOfParagraphs: numOfParagraphs,
215 + keywords: keywords,
216 + ai_nonce: nonce, // Pass the nonce value
217 + },
218 + success: function(response) {
219 + // Update the content in the textarea
369 220
370 - if (response.success && (typeof response.data === 'string')) {
371 - docGenerateBtnTxt.innerHTML = "<?php echo esc_html__( 'Generated', 'betterdocs' ); ?>";
372 - setTimeout(() => {
373 - insertContentToEditor(title, response.data, isOverwrite, keywords);
374 - docGenerateBtnTxt.innerHTML = reGenerateDocLabel;
375 - jQuery('.generate-btn').removeAttr('disabled');
376 - }, 2000);
377 - } else {
378 - // alert(response.data.message);
379 - jQuery('#betterdocs-ai-error-message').parent().removeClass('hidden');
380 - jQuery('#betterdocs-ai-error-message').html(responseMessage(response.data.message));
381 - docGenerateBtnTxt.innerHTML = generateDocLabel;
382 - jQuery('.generate-btn').removeAttr('disabled');
221 + if (response.success && (typeof response.data === 'string')) {
222 + docGenerateBtnTxt.innerHTML = "<?php echo esc_html__('Generated', 'betterdocs'); ?>";
223 + setTimeout(() => {
224 + insertContentToEditor(title, response.data, isOverwrite, keywords);
225 + docGenerateBtnTxt.innerHTML = reGenerateDocLabel;
226 + jQuery('.generate-btn').removeAttr('disabled');
383 227
384 - }
385 - },
386 - error: function(jqXHR, textStatus, errorThrown) {
387 - console.error(jqXHR, textStatus, errorThrown);
228 + // console.log(jQuery('.betterdocs-ai-autowrite-form-container').data('new-doc-page'));
388 229
389 - // Reset the UI so a slow/failed request never leaves a permanent "Generating...".
390 - var timedOut = ( textStatus === 'timeout' ) || ( jqXHR && jqXHR.status === 504 ) || ( jqXHR && jqXHR.status === 0 );
391 - var errMessage = timedOut
392 - ? "<?php echo esc_html__( 'The request timed out before a response came back. The AI may still have generated content on the server — try again, or pick a faster model / lower the token limit.', 'betterdocs' ); ?>"
393 - : "<?php echo esc_html__( 'Something went wrong while generating. Please try again.', 'betterdocs' ); ?>";
230 + // if(jQuery('.betterdocs-ai-autowrite-form-container')?.data('new-doc-page')) {
231 + // docGenerateBtnTxt.innerHTML = reGenerateDocLabel;
232 + // }
233 + }, 2000);
234 + } else {
235 + // alert(response.data.message);
236 + jQuery('#betterdocs-ai-error-message').parent().removeClass('hidden');
237 + jQuery('#betterdocs-ai-error-message').html(responseMessage(response.data.message));
238 + docGenerateBtnTxt.innerHTML = generateDocLabel;
239 + jQuery('.generate-btn').removeAttr('disabled');
394 240
395 - jQuery('#betterdocs-ai-error-message').parent().removeClass('hidden');
396 - jQuery('#betterdocs-ai-error-message').html(responseMessage(errMessage));
397 - docGenerateBtnTxt.innerHTML = generateDocLabel;
398 - jQuery('.generate-btn').removeAttr('disabled');
399 - },
400 - });
241 + }
242 + },
243 + error: function(error) {
244 + console.error(error);
245 + },
246 + });
401 247
402 - }
403 - }
248 + }
249 + }
404 250
405 - // Function to update the textarea
406 - function updateTextarea() {
407 - const title = document.getElementById('betterdocs-ai-title').value;
408 - const keywords = document.getElementById('betterdocs-ai-keyword').value;
409 - const sectionOptions = document.getElementById('bd-autowrtite-content-section');
410 - let language = 'English';
251 + // Function to update the textarea
252 + function updateTextarea() {
253 + const title = document.getElementById('betterdocs-ai-title').value;
254 + const keywords = document.getElementById('betterdocs-ai-keyword').value;
255 + const sectionOptions = document.getElementById('bd-autowrtite-content-section');
256 + let language = 'English';
411 257
412 - if (language === '') {
413 - language = 'English';
414 - }
258 + if (language === '') {
259 + language = 'English';
260 + }
415 261
416 - let keywordsText = keywords !== '' ? ` and incorporate the keywords: ${keywords}` : '';
262 + let keywordsText = keywords !== '' ? ` and incorporate the keywords: ${keywords}` : '';
417 263
418 - const contentTextArea = document.getElementById('betterdocs-ai-content');
264 + const contentTextArea = document.getElementById('betterdocs-ai-content');
419 265
420 - if (!jQuery('#betterdocs-ai-error-message').parent().hasClass('hidden')) {
421 - jQuery('#betterdocs-ai-error-message').parent().addClass('hidden');
422 - }
266 + if (!jQuery('#betterdocs-ai-error-message').parent().hasClass('hidden')) {
267 + jQuery('#betterdocs-ai-error-message').parent().addClass('hidden');
268 + }
423 269
424 - contentTextArea.value = `Write documentation for '${title}'. Cover these topics in depth: ${keywords}. Use headings, paragraphs, lists, links, code blocks, and tables wherever they help the reader. Follow the output-format rules in the system instructions.`;
425 - }
270 + contentTextArea.value = `Generate a documentation using HTML heading tags for '${title}'. Include relevant details on ${keywords} in the documentation. Ensure all content is enclosed with <p> tags and apply a <span> tag with the class 'highlight' to headings and topic tags for emphasis.`;
271 + }
426 272
427 - function convertMarkdownToHTML(markdownContent) {
428 - // Simple Markdown to HTML conversion (you may need to enhance this based on your needs)
429 - const htmlContent = markdownContent
430 - .replace(/^# (.+)$/gm, '<h1>$1</h1>')
431 - .replace(/^## (.+)$/gm, '<h2>$1</h2>')
432 - .replace(/^### (.+)$/gm, '<h3>$1</h3>')
433 - .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
434 - .replace(/\*(.+?)\*/g, '<em>$1</em>');
273 + function convertMarkdownToHTML(markdownContent) {
274 + // Simple Markdown to HTML conversion (you may need to enhance this based on your needs)
275 + const htmlContent = markdownContent
276 + .replace(/^# (.+)$/gm, '<h1>$1</h1>')
277 + .replace(/^## (.+)$/gm, '<h2>$1</h2>')
278 + .replace(/^### (.+)$/gm, '<h3>$1</h3>')
279 + .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
280 + .replace(/\*(.+?)\*/g, '<em>$1</em>');
435 281
436 - return htmlContent;
437 - }
282 + return htmlContent;
283 + }
438 284
439 - function replaceHeadingTitle(content, title, overviewTitle) {
440 - let regex = new RegExp(title, 'g');
441 - let updateContent = content.replace(regex, overviewTitle);
442 - return updateContent;
443 - }
285 + function replaceHeadingTitle(content, title, overviewTitle) {
286 + let regex = new RegExp(title, 'g');
287 + let updateContent = content.replace(regex, overviewTitle);
288 + return updateContent;
289 + }
444 290
445 - function removeFirstHeading(htmlString) {
446 - var newDiv = document.createElement('div');
447 - newDiv.innerHTML = htmlString;
448 - var firstHeading = newDiv.querySelector('h1');
449 - if (firstHeading) {
450 - firstHeading.parentNode.removeChild(firstHeading);
451 - }
452 - return newDiv.innerHTML;
453 - }
291 + function removeFirstHeading(htmlString) {
292 + var newDiv = document.createElement('div');
293 + newDiv.innerHTML = htmlString;
294 + var firstHeading = newDiv.querySelector('h1');
295 + if (firstHeading) {
296 + firstHeading.parentNode.removeChild(firstHeading);
297 + }
298 + return newDiv.innerHTML;
299 + }
454 300
455 301
456 - function escapeHtml(str) {
457 - return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
458 - }
302 + function wrapwithHeighlight(inputString, keywords) {
303 + let modifiedString = inputString.replace(/<(h\d)(.*?)>(.*?)<\/\1>/g, '<$1$2><span class="highlight">$3</span></$1>');
459 304
460 - function escapeRegex(str) {
461 - return String(str).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
462 - }
305 + const keywordArray = keywords.split(',').map(keyword => keyword.trim());
463 306
464 - function stripCodeFences(htmlString) {
465 - if (!htmlString) {
466 - return '';
467 - }
468 - return htmlString
469 - .replace(/^\s*```(?:html|HTML)?\s*\n?/, '')
470 - .replace(/\n?\s*```\s*$/, '');
471 - }
307 + keywordArray.forEach(keyword => {
308 + modifiedString = modifiedString.replace(new RegExp(`\\b(${keyword})\\b`, 'gi'), '<span class="highlight">$1</span>');
309 + });
472 310
473 - function wrapwithHeighlight(inputString, keywords) {
474 - if (!inputString) {
475 - return '';
476 - }
311 + return modifiedString;
312 + }
477 313
478 - const container = document.createElement('div');
479 - container.innerHTML = inputString;
314 + function getBodyContent(htmlString) {
315 + var match = htmlString.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
480 316
481 - // Wrap each heading's visible text with the highlight span (skip if already present)
482 - container.querySelectorAll('h1, h2, h3, h4, h5, h6').forEach(function (heading) {
483 - if (heading.querySelector('.highlight')) {
484 - return;
485 - }
486 - const text = heading.textContent;
487 - if (!text || !text.trim()) {
488 - return;
489 - }
490 - heading.innerHTML = '<span class="highlight">' + escapeHtml(text) + '</span>';
491 - });
317 + console.log(match[1].replace(/<p>\s+/g, '<p>'));
492 318
493 - // Wrap keywords only inside text nodes — never inside attributes, code, or existing highlights
494 - const keywordList = (keywords || '')
495 - .split(',')
496 - .map(function (k) { return k.trim(); })
497 - .filter(Boolean);
319 + return match ? match[1].replace(/<p>\s+/g, '<p>') : '';
320 + }
498 321
499 - if (keywordList.length) {
500 - const pattern = new RegExp('\\b(' + keywordList.map(escapeRegex).join('|') + ')\\b', 'gi');
501 - const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT, {
502 - acceptNode: function (node) {
503 - let parent = node.parentNode;
504 - while (parent && parent !== container) {
505 - if (parent.nodeType === 1) {
506 - const tag = parent.tagName.toLowerCase();
507 - if (tag === 'code' || tag === 'pre') {
508 - return NodeFilter.FILTER_REJECT;
509 - }
510 - if (parent.classList && parent.classList.contains('highlight')) {
511 - return NodeFilter.FILTER_REJECT;
512 - }
513 - }
514 - parent = parent.parentNode;
515 - }
516 - return NodeFilter.FILTER_ACCEPT;
517 - }
518 - });
519 322
520 - const textNodes = [];
521 - let current;
522 - while ((current = walker.nextNode())) {
523 - textNodes.push(current);
524 - }
323 + function insertContentToEditor(title, htmlContent, isOverwrite, keywords) {
525 324
526 - textNodes.forEach(function (textNode) {
527 - pattern.lastIndex = 0;
528 - if (!pattern.test(textNode.nodeValue)) {
529 - return;
530 - }
531 - pattern.lastIndex = 0;
532 - const fragmentHost = document.createElement('span');
533 - fragmentHost.innerHTML = escapeHtml(textNode.nodeValue).replace(pattern, '<span class="highlight">$1</span>');
534 - const parent = textNode.parentNode;
535 - while (fragmentHost.firstChild) {
536 - parent.insertBefore(fragmentHost.firstChild, textNode);
537 - }
538 - parent.removeChild(textNode);
539 - });
540 - }
325 + const {
326 + dispatch,
327 + select
328 + } = wp.data;
541 329
542 - return container.innerHTML;
543 - }
330 + htmlContent = getBodyContent(htmlContent);
331 + htmlContent = removeFirstHeading(htmlContent);
332 + htmlContent = wrapwithHeighlight(htmlContent, keywords);
333 + const isPostContent = `<?php echo isset($_GET['post']) ? get_the_content($_GET['post']) : ''; ?>`;
544 334
545 - function getBodyContent(htmlString) {
546 - if (!htmlString) {
547 - return '';
548 - }
549 - const cleaned = stripCodeFences(htmlString);
550 - const match = cleaned.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
551 - if (match) {
552 - return match[1].replace(/<p>\s+/g, '<p>');
553 - }
554 - return cleaned;
555 - }
335 + const blocks = wp.blocks.rawHandler({
336 + HTML: htmlContent
337 + });
556 338
339 + dispatch('core/editor').editPost({
340 + title: title,
341 + });
557 342
343 + const selectedBlockClientId = select('core/block-editor').getSelectedBlockClientId();
558 344
559 - function insertContentToEditor(title, htmlContent, isOverwrite, keywords) {
345 + const allBlocks = select('core/block-editor').getBlocks();
560 346
561 - const {
562 - dispatch,
563 - select
564 - } = wp.data;
347 + if (isOverwrite || isPostContent === '') {
565 348
566 - htmlContent = getBodyContent(htmlContent);
567 - htmlContent = removeFirstHeading(htmlContent);
568 - htmlContent = wrapwithHeighlight(htmlContent, keywords);
569 - const isPostContent = `<?php echo isset( $_GET[ 'post' ] ) ? esc_html( get_the_content( $_GET[ 'post' ] ) ) : ''; // phpcs:ignore ?>`;
349 + allBlocks.forEach((block) => {
350 + dispatch('core/block-editor').removeBlock(block.clientId);
351 + });
352 + dispatch('core/block-editor').insertBlocks(blocks);
570 353
571 - const blocks = wp.blocks.rawHandler({
572 - HTML: htmlContent
573 - });
354 + } else if (selectedBlockClientId) {
355 + const selectedIndex = select('core/block-editor').getBlockIndex(selectedBlockClientId);
356 + dispatch('core/block-editor').insertBlocks(blocks, selectedIndex + 1);
357 + } else {
358 + dispatch('core/block-editor').insertBlocks(blocks);
359 + }
574 360
575 - dispatch('core/editor').editPost({
576 - title: title,
577 - });
361 + closeWriteWithAIForm('afterInsertContent');
362 + }
578 363
579 - const selectedBlockClientId = select('core/block-editor').getSelectedBlockClientId();
364 + function closeWriteWithAIForm(after) {
365 + jQuery('.betterdocs-ai-autowrite-form-container').addClass('hidden');
366 + jQuery('#betterdocs-ai-autowrite-form-container-overlay').addClass('hidden');
367 + jQuery('.betterdocs-ai-button').addClass('regenerate-btn');
368 + }
580 369
581 - const allBlocks = select('core/block-editor').getBlocks();
582 370
583 - if (isOverwrite || isPostContent === '') {
371 + document.addEventListener('DOMContentLoaded', function() {
584 372
585 - allBlocks.forEach((block) => {
586 - dispatch('core/block-editor').removeBlock(block.clientId);
587 - });
588 - dispatch('core/block-editor').insertBlocks(blocks);
373 + // Subscribe to changes in the editor state
374 + let previousDocsTitle = '';
589 375
590 - } else if (selectedBlockClientId) {
591 - const selectedIndex = select('core/block-editor').getBlockIndex(selectedBlockClientId);
592 - dispatch('core/block-editor').insertBlocks(blocks, selectedIndex + 1);
593 - } else {
594 - dispatch('core/block-editor').insertBlocks(blocks);
595 - }
376 + wp.data.subscribe(() => {
377 + // Get the updated post title
378 + // const docsTitle = wp.data.select('core/editor').getEditedPostAttribute('title');
596 379
597 - closeWriteWithAIForm('afterInsertContent');
598 - }
380 + const docsTitle = wp.data.select('core/editor').getEditedPostAttribute('title');
599 381
600 - function closeWriteWithAIForm(after) {
601 - jQuery('.betterdocs-ai-autowrite-form-container').addClass('hidden');
602 - jQuery('#betterdocs-ai-autowrite-form-container-overlay').addClass('hidden');
603 - jQuery('.betterdocs-ai-button').addClass('regenerate-btn');
604 - }
382 + // Check if the title has changed
383 + if (docsTitle !== previousDocsTitle) {
384 + let currentKeywords = jQuery('#betterdocs-ai-keyword').val();
385 + if (!currentKeywords) {
386 + currentKeywords = '{Documentation Keywords}';
387 + }
388 + const currentPrompt = `Generate documentation using HTML heading tags for '${docsTitle?docsTitle:'{Documentation title}'}'. Include relevant details on ${currentKeywords} in the documentation. Ensure all content is enclosed with <p> tags and apply a <span> tag with the class 'highlight' to headings and topic tags for emphasis.`;
389 + jQuery('#betterdocs-ai-content').val(currentPrompt);
605 390
391 + jQuery('#betterdocs-ai-title').val(docsTitle);
606 392
607 - document.addEventListener('DOMContentLoaded', function() {
393 + previousDocsTitle = docsTitle;
394 + }
608 395
609 - // Subscribe to changes in the editor state
610 - let previousDocsTitle = '';
611 396
612 - wp.data.subscribe(() => {
613 - // Get the updated post title
614 - // const docsTitle = wp.data.select('core/editor').getEditedPostAttribute('title');
397 + });
398 + });
615 399
616 - const docsTitle = wp.data.select('core/editor').getEditedPostAttribute('title');
617 400
618 - // Check if the title has changed
619 - if (docsTitle !== previousDocsTitle) {
620 - let currentKeywords = jQuery('#betterdocs-ai-keyword').val();
621 - if (!currentKeywords) {
622 - currentKeywords = '{Documentation Keywords}';
623 - }
624 - const currentPrompt = `Write documentation for '${docsTitle?docsTitle:'{Documentation title}'}'. Cover these topics in depth: ${currentKeywords}. Use headings, paragraphs, lists, links, code blocks, and tables wherever they help the reader. Follow the output-format rules in the system instructions.`;
625 - jQuery('#betterdocs-ai-content').val(currentPrompt);
401 + // This example assumes that this code is executed when your script is loaded.
402 + // You may want to place it within the appropriate context in your application.
626 403
627 - jQuery('#betterdocs-ai-title').val(docsTitle);
628 404
629 - previousDocsTitle = docsTitle;
630 - }
405 + function writeWithAIForm() {
631 406
407 + let title = `<?php echo isset($_GET['post']) ? get_the_title($_GET['post']) : ''; ?>`;
408 + if (docsTitle) {
409 + title = docsTitle;
410 + }
632 411
633 - });
634 - });
412 + const promtTitle = `<?php echo isset($_GET['post']) ? get_the_title($_GET['post']) : '{Documentation Title}'; ?>`;
413 + const titlePlaceholder = "<?php echo esc_attr__('Enter a descriptive title for your documentation.', 'betterdocs'); ?>";
414 + const keywords = "<?php echo esc_attr('{Documentation Keywords}'); ?>";
415 + const keywordsPlaceholder = "<?php echo esc_attr__('Add keywords to generate precise & relevant documentation (comma-separated).', 'betterdocs'); ?>";
416 + const language = "<?php echo esc_attr('English'); ?>";
417 + const titleLabel = "<?php echo esc_html__('Documentation Title:', 'betterdocs'); ?>";
418 + const keywordLabel = "<?php echo esc_html__('Keywords:', 'betterdocs'); ?>";
419 + const secLabel = "<?php echo esc_html__('# of Sections:', 'betterdocs'); ?>";
420 + const paraLabel = "<?php echo esc_html__('# of Paragraph Per Section: ', 'betterdocs'); ?>";
421 + const langLabel = "<?php echo esc_html__('Language:', 'betterdocs'); ?>";
422 + const promtLabel = "<?php echo esc_html__('Prompt:', 'betterdocs'); ?>";
423 + const promtBtnLabel = "<?php echo esc_html__('Generate Prompt', 'betterdocs'); ?>";
424 + let promtArticleLabel = "<?php echo esc_html__('Generate Doc', 'betterdocs'); ?>";
425 + const checkboxLabel = "<?php echo esc_html__('Overwrite your existing Doc:', 'betterdocs'); ?>";
426 + const nonce = "<?php echo esc_attr(wp_create_nonce('generate_openai_content_nonce')); ?>";
635 427
636 -
637 - // This example assumes that this code is executed when your script is loaded.
638 - // You may want to place it within the appropriate context in your application.
639 -
640 -
641 - function writeWithAIForm() {
642 -
643 - let title = `<?php echo isset( $_GET[ 'post' ] ) ? esc_html( get_the_title( $_GET[ 'post' ] ) ) : ''; // phpcs:ignore ?>`;
644 - if (docsTitle) {
645 - title = docsTitle;
646 - }
647 -
648 - const promtTitle = `<?php echo isset( $_GET[ 'post' ] ) ? esc_html( get_the_title( $_GET[ 'post' ] ) ) : '{Documentation Title}'; // phpcs:ignore ?>`;
649 - const titlePlaceholder = "<?php echo esc_attr__( 'Enter a descriptive title for your documentation.', 'betterdocs' ); ?>";
650 - const keywords = "<?php echo esc_attr( '{Documentation Keywords}' ); ?>";
651 - const keywordsPlaceholder = "<?php echo esc_attr__( 'Add keywords to generate precise & relevant documentation (comma-separated).', 'betterdocs' ); ?>";
652 - const language = "<?php echo esc_attr( 'English' ); ?>";
653 - const titleLabel = "<?php echo esc_html__( 'Documentation Title:', 'betterdocs' ); ?>";
654 - const keywordLabel = "<?php echo esc_html__( 'Keywords:', 'betterdocs' ); ?>";
655 - const secLabel = "<?php echo esc_html__( '# of Sections:', 'betterdocs' ); ?>";
656 - const paraLabel = "<?php echo esc_html__( '# of Paragraph Per Section: ', 'betterdocs' ); ?>";
657 - const langLabel = "<?php echo esc_html__( 'Language:', 'betterdocs' ); ?>";
658 - const promtLabel = "<?php echo esc_html__( 'Prompt:', 'betterdocs' ); ?>";
659 - const promtBtnLabel = "<?php echo esc_html__( 'Generate Prompt', 'betterdocs' ); ?>";
660 - let promtArticleLabel = "<?php echo esc_html__( 'Generate Doc', 'betterdocs' ); ?>";
661 - const checkboxLabel = "<?php echo esc_html__( 'Overwrite your existing Doc:', 'betterdocs' ); ?>";
662 - const nonce = "<?php echo esc_attr( wp_create_nonce( 'generate_openai_content_nonce' ) ); ?>";
663 -
664 - <?php
665 - $is_valid = $this->get_api_key();
666 - $disable_field = 'disabled-input-field';
667 - if ( $this->get_api_key() ) {
668 - $disable_field = '';
669 - }
428 + <?php $is_valid = $this->get_api_key();
429 + $disable_field = 'disabled-input-field';
430 + if ($this->get_api_key()) {
431 + $disable_field = '';
432 + }
670 433 ?>
671 434
672 - let hiddenClass = 'hidden';
673 - let newDocPageAtt = 'data-new-doc-page="true"';
674 - const isPostContent = `<?php echo isset( $_GET[ 'post' ] ) ? esc_html( get_the_content( $_GET[ 'post' ] ) ) : ''; // phpcs:ignore ?>`;
435 + let hiddenClass = 'hidden';
436 + let newDocPageAtt = 'data-new-doc-page="true"';
437 + const isPostContent = `<?php echo isset($_GET['post']) ? get_the_content($_GET['post']) : ''; ?>`;
675 438
676 - if (isPostContent !== '') {
677 - hiddenClass = '';
678 - newDocPageAtt = '';
679 - }
439 + if (isPostContent !== '') {
440 + hiddenClass = '';
441 + newDocPageAtt = '';
442 + }
680 443
681 444
682 - // const prompt = `Make a knowledge base article with html heading tags about [${title}] in [${language}]. Here is some topic to describe the article: [${keywords}]. and wrap the content with p tag also add a span tag with a class named 'highlight' to all the heading and topic tags in the article.`;
445 + // const prompt = `Make a knowledge base article with html heading tags about [${title}] in [${language}]. Here is some topic to describe the article: [${keywords}]. and wrap the content with p tag also add a span tag with a class named 'highlight' to all the heading and topic tags in the article.`;
683 446
684 - // const prompt = `Create a details knowledge base article in [${language}] about [${title}] with html heading tags. Here is some topic to describe the article: [${keywords}]. And wrap the content with p tag also add a span tag with a class named 'highlight' to all the heading and topic tags in the article.`;
447 + // const prompt = `Create a details knowledge base article in [${language}] about [${title}] with html heading tags. Here is some topic to describe the article: [${keywords}]. And wrap the content with p tag also add a span tag with a class named 'highlight' to all the heading and topic tags in the article.`;
685 448
686 - const prompt = `Write documentation for '${promtTitle}'. Cover these topics in depth: ${keywords}. Use headings, paragraphs, lists, links, code blocks, and tables wherever they help the reader. Follow the output-format rules in the system instructions.`;
449 + const prompt = `Generate a documentation using HTML heading tags for '${promtTitle}'. Include relevant details on ${keywords} in the documentation. Ensure all content is enclosed with <p> tags and apply a <span> tag with the class 'highlight' to headings and topic tags for emphasis.`;
687 450
688 - const aiIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="21" height="20" viewBox="0 0 21 20" fill="none">
689 - <g clip-path="url(#clip0_2460_1729)">
690 - <path d="M10.3956 18.8608L6.10991 19.2322L6.48134 14.9465L15.3956 6.08936C15.5287 5.95329 15.6876 5.84518 15.863 5.77137C16.0384 5.69756 16.2268 5.65954 16.4171 5.65954C16.6074 5.65954 16.7957 5.69756 16.9711 5.77137C17.1466 5.84518 17.3054 5.95329 17.4385 6.08936L19.2528 7.91793C19.3865 8.05083 19.4926 8.20886 19.565 8.38293C19.6375 8.55701 19.6747 8.74368 19.6747 8.93221C19.6747 9.12075 19.6375 9.30742 19.565 9.48149C19.4926 9.65557 19.3865 9.8136 19.2528 9.9465L10.3956 18.8608ZM1.7042 5.67507C1.20277 5.58793 1.20277 4.86793 1.7042 4.78079C2.59203 4.62626 3.41374 4.21085 4.06456 3.58751C4.71538 2.96417 5.16583 2.16113 5.35848 1.28079L5.38848 1.14221C5.49705 0.647929 6.20277 0.643643 6.31705 1.13936L6.35277 1.29936C6.55248 2.17579 7.0067 2.97367 7.65837 3.59281C8.31005 4.21195 9.13013 4.62475 10.0156 4.77936C10.5199 4.86507 10.5199 5.58936 10.0156 5.67793C9.13005 5.83218 8.3098 6.24465 7.65787 6.86354C7.00594 7.48243 6.5514 8.28014 6.35134 9.1565L6.3142 9.31793C6.20134 9.81221 5.49563 9.80936 5.38705 9.31364L5.35848 9.17507C5.16564 8.29433 4.71476 7.49102 4.06339 6.86764C3.41202 6.24426 2.58969 5.82908 1.70134 5.67507H1.7042Z" stroke="white" stroke-width="1.42857" stroke-linecap="round" stroke-linejoin="round"/>
691 - </g>
692 - <defs>
693 - <clipPath id="clip0_2460_1729">
694 - <rect width="20" height="20" fill="white" transform="translate(0.5)"/>
695 - </clipPath>
696 - </defs>
697 - </svg>`;
451 + const aiIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="21" height="20" viewBox="0 0 21 20" fill="none">
452 + <g clip-path="url(#clip0_2460_1729)">
453 + <path d="M10.3956 18.8608L6.10991 19.2322L6.48134 14.9465L15.3956 6.08936C15.5287 5.95329 15.6876 5.84518 15.863 5.77137C16.0384 5.69756 16.2268 5.65954 16.4171 5.65954C16.6074 5.65954 16.7957 5.69756 16.9711 5.77137C17.1466 5.84518 17.3054 5.95329 17.4385 6.08936L19.2528 7.91793C19.3865 8.05083 19.4926 8.20886 19.565 8.38293C19.6375 8.55701 19.6747 8.74368 19.6747 8.93221C19.6747 9.12075 19.6375 9.30742 19.565 9.48149C19.4926 9.65557 19.3865 9.8136 19.2528 9.9465L10.3956 18.8608ZM1.7042 5.67507C1.20277 5.58793 1.20277 4.86793 1.7042 4.78079C2.59203 4.62626 3.41374 4.21085 4.06456 3.58751C4.71538 2.96417 5.16583 2.16113 5.35848 1.28079L5.38848 1.14221C5.49705 0.647929 6.20277 0.643643 6.31705 1.13936L6.35277 1.29936C6.55248 2.17579 7.0067 2.97367 7.65837 3.59281C8.31005 4.21195 9.13013 4.62475 10.0156 4.77936C10.5199 4.86507 10.5199 5.58936 10.0156 5.67793C9.13005 5.83218 8.3098 6.24465 7.65787 6.86354C7.00594 7.48243 6.5514 8.28014 6.35134 9.1565L6.3142 9.31793C6.20134 9.81221 5.49563 9.80936 5.38705 9.31364L5.35848 9.17507C5.16564 8.29433 4.71476 7.49102 4.06339 6.86764C3.41202 6.24426 2.58969 5.82908 1.70134 5.67507H1.7042Z" stroke="white" stroke-width="1.42857" stroke-linecap="round" stroke-linejoin="round"/>
454 + </g>
455 + <defs>
456 + <clipPath id="clip0_2460_1729">
457 + <rect width="20" height="20" fill="white" transform="translate(0.5)"/>
458 + </clipPath>
459 + </defs>
460 + </svg>`;
698 461
699 462
700 463
701 - return `
702 - <div class="betterdocs-ai-autowrite-form-container hidden" ${newDocPageAtt}>
703 - <div class="betterdocs-ai-autowrite-form-content">
704 - <div class="betterdocs-ai-autowrite-top-part">
705 - <div class="autowrite-heading">
706 - <span class="autowrite-icon">
707 - <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
708 - <g clip-path="url(#clip0_2453_20882)">
709 - <path d="M15.8322 30.1765L8.97508 30.7708L9.56936 23.9136L23.8322 9.74219C24.0451 9.52448 24.2993 9.3515 24.58 9.23341C24.8606 9.11531 25.162 9.05447 25.4665 9.05447C25.771 9.05447 26.0724 9.11531 26.3531 9.23341C26.6337 9.3515 26.8879 9.52448 27.1008 9.74219L30.0037 12.6679C30.2176 12.8805 30.3874 13.1334 30.5033 13.4119C30.6192 13.6904 30.6788 13.9891 30.6788 14.2908C30.6788 14.5924 30.6192 14.8911 30.5033 15.1696C30.3874 15.4481 30.2176 15.701 30.0037 15.9136L15.8322 30.1765ZM1.92593 9.07933C1.12365 8.9399 1.12365 7.7879 1.92593 7.64848C3.34647 7.40124 4.6612 6.73658 5.70251 5.73923C6.74382 4.74188 7.46455 3.45703 7.77279 2.04848L7.82079 1.82676C7.99451 1.03591 9.12365 1.02905 9.30651 1.82219L9.36365 2.07819C9.68319 3.48048 10.4099 4.75709 11.4526 5.74772C12.4953 6.73834 13.8074 7.39881 15.2242 7.64619C16.0311 7.78333 16.0311 8.94219 15.2242 9.0839C13.8073 9.33071 12.4949 9.99066 11.4518 10.9809C10.4087 11.9711 9.68146 13.2474 9.36136 14.6496L9.30193 14.9079C9.12136 15.6988 7.99222 15.6942 7.81851 14.901L7.77279 14.6793C7.46424 13.2702 6.74284 11.9849 5.70064 10.9874C4.65845 9.99003 3.34273 9.32574 1.92136 9.07933H1.92593Z" stroke="#E31B54" stroke-width="2.28571" stroke-linecap="round" stroke-linejoin="round"/>
710 - </g>
711 - <defs>
712 - <clipPath id="clip0_2453_20882">
713 - <rect width="32" height="32" fill="white"/>
714 - </clipPath>
715 - </defs>
716 - </svg>
717 - </span>
718 - <h1><?php echo esc_html__( 'Write Documentation with BetterDocs AI', 'betterdocs' ); ?></h1>
464 + return `
465 + <div class="betterdocs-ai-autowrite-form-container hidden" ${newDocPageAtt}>
466 + <div class="betterdocs-ai-autowrite-form-content">
467 + <div class="betterdocs-ai-autowrite-top-part">
468 + <div class="autowrite-heading">
469 + <span class="autowrite-icon">
470 + <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
471 + <g clip-path="url(#clip0_2453_20882)">
472 + <path d="M15.8322 30.1765L8.97508 30.7708L9.56936 23.9136L23.8322 9.74219C24.0451 9.52448 24.2993 9.3515 24.58 9.23341C24.8606 9.11531 25.162 9.05447 25.4665 9.05447C25.771 9.05447 26.0724 9.11531 26.3531 9.23341C26.6337 9.3515 26.8879 9.52448 27.1008 9.74219L30.0037 12.6679C30.2176 12.8805 30.3874 13.1334 30.5033 13.4119C30.6192 13.6904 30.6788 13.9891 30.6788 14.2908C30.6788 14.5924 30.6192 14.8911 30.5033 15.1696C30.3874 15.4481 30.2176 15.701 30.0037 15.9136L15.8322 30.1765ZM1.92593 9.07933C1.12365 8.9399 1.12365 7.7879 1.92593 7.64848C3.34647 7.40124 4.6612 6.73658 5.70251 5.73923C6.74382 4.74188 7.46455 3.45703 7.77279 2.04848L7.82079 1.82676C7.99451 1.03591 9.12365 1.02905 9.30651 1.82219L9.36365 2.07819C9.68319 3.48048 10.4099 4.75709 11.4526 5.74772C12.4953 6.73834 13.8074 7.39881 15.2242 7.64619C16.0311 7.78333 16.0311 8.94219 15.2242 9.0839C13.8073 9.33071 12.4949 9.99066 11.4518 10.9809C10.4087 11.9711 9.68146 13.2474 9.36136 14.6496L9.30193 14.9079C9.12136 15.6988 7.99222 15.6942 7.81851 14.901L7.77279 14.6793C7.46424 13.2702 6.74284 11.9849 5.70064 10.9874C4.65845 9.99003 3.34273 9.32574 1.92136 9.07933H1.92593Z" stroke="#E31B54" stroke-width="2.28571" stroke-linecap="round" stroke-linejoin="round"/>
473 + </g>
474 + <defs>
475 + <clipPath id="clip0_2453_20882">
476 + <rect width="32" height="32" fill="white"/>
477 + </clipPath>
478 + </defs>
479 + </svg>
480 + </span>
481 + <h1><?php echo esc_html__('Write Documentation with BetterDocs AI', 'betterdocs'); ?></h1>
719 482
720 - </div>
721 - <div class="autowrite-subheadding">
722 - <p><?php echo esc_html__( 'Generate documentation effortlessly with BetterDocs AI. Simply input your doc title, keywords, prompt and let the system automatically generate comprehensive documentation tailored to your needs.', 'betterdocs' ); ?></p>
723 - </div>
483 + </div>
484 + <div class="autowrite-subheadding">
485 + <p><?php echo esc_html__('Generate documentation effortlessly with BetterDocs AI. Simply input your doc title, keywords, prompt and let the system automatically generate comprehensive documentation tailored to your needs.', 'betterdocs'); ?></p>
486 + </div>
724 487
725 - <?php if ( empty( $this->get_api_key() ) ): ?>
726 - <div id="betterdocs-ai-message">
727 - <div class="warning-message">
728 - <span class="dashicons dashicons-warning"></span>
729 - <div>
730 - <?php echo wp_kses_post( 'Please Insert your <a target="_blank" href="' . esc_url( admin_url( 'admin.php?page=betterdocs-settings#betterdocs-ai' ) ) . '">OpenAI API Key</a> to use this Write with AI feature.', 'betterdocs' ); ?>
731 - </div>
732 - </div>
488 + <?php if (empty($this->get_api_key())) : ?>
489 + <div id="betterdocs-ai-message">
490 + <div class="warning-message">
491 + <span class="dashicons dashicons-warning"></span>
492 + <div>
493 + <?php echo wp_kses_post('Please Insert your <a target="_blank" href="' . esc_url(admin_url('admin.php?page=betterdocs-settings&tab=tab-ai-autowrite')) . '">OpenAI API Key</a> to use this Write with AI feature.', 'betterdocs'); ?>
494 + </div>
495 + </div>
733 496
734 - </div>
735 - <?php endif; ?>
497 + </div>
498 + <?php endif; ?>
736 499
737 - <div class="form-group hidden">
738 - <div id="betterdocs-ai-error-message"></div>
739 - </div>
500 + <div class="form-group hidden">
501 + <div id="betterdocs-ai-error-message"></div>
502 + </div>
503 +
504 + </div>
505 + <form id="betterdocs-ai-form" class="<?php echo esc_attr($disable_field); ?>">
506 + <div class="form-inner-content">
507 + <div class="form-group">
508 + <label for="betterdocs-ai-title">${titleLabel}</label>
509 + <input type="text" placeholder="${titlePlaceholder}" id="betterdocs-ai-title" name="betterdocs-ai-title" required value="${title}">
510 + </div>
740 511
741 - </div>
742 - <form id="betterdocs-ai-form" class="<?php echo esc_attr( $disable_field ); ?>">
743 - <div class="form-inner-content">
744 - <div class="form-group">
745 - <label for="betterdocs-ai-title">${titleLabel}</label>
746 - <input type="text" placeholder="${titlePlaceholder}" id="betterdocs-ai-title" name="betterdocs-ai-title" required value="${title}">
747 - </div>
512 + <div class="form-group">
513 + <label for="betterdocs-ai-keyword">${keywordLabel}</label>
514 + <input type="text" placeholder="${keywordsPlaceholder}" id="betterdocs-ai-keyword" name="betterdocs-ai-keyword" required>
515 + </div>
748 516
749 - <div class="form-group">
750 - <label for="betterdocs-ai-keyword">${keywordLabel}</label>
751 - <input type="text" placeholder="${keywordsPlaceholder}" id="betterdocs-ai-keyword" name="betterdocs-ai-keyword" required>
752 - </div>
517 + <div class="form-group prompt-field">
518 + <label for="betterdocs-ai-content">${promtLabel}</label>
519 + <textarea id="betterdocs-ai-content" name="betterdocs-ai-content" rows="6" required>${prompt}</textarea>
520 + <p class="input-description"><?php echo esc_html__('Ensure you include a clear and detailed prompt to receive the desired output. Follow the guidelines provided for the best results.', 'betterdocs'); ?></p>
521 + </div>
522 + <div class="betterdocs-ai-checkbox-field ${hiddenClass}">
523 + <div class="form-group">
524 + <div class="checkbox-field-label">
525 + <label for="betterdocs-ai-checkbox">${checkboxLabel}</label>
526 + <p class="input-description"><?php echo esc_html__('Overwrite the existing doc with the AI Generated Content. If Disabled, new AI Generated content will be added in the section you are currently editing.', 'betterdocs'); ?></p>
527 + </div>
528 +
529 + <div class="checkbox-input-field">
530 + <input type="checkbox" id="betterdocs-ai-checkbox" name="betterdocs-ai-checkbox" data-overwrite="false">
531 + <label for="betterdocs-ai-checkbox" class="toggle-label"></label>
532 + </div>
533 + </div>
534 + </div>
753 535
754 - <div class="form-group prompt-field">
755 - <label for="betterdocs-ai-content">${promtLabel}</label>
756 - <textarea id="betterdocs-ai-content" name="betterdocs-ai-content" rows="6" required>${prompt}</textarea>
757 - <p class="input-description"><?php echo esc_html__( 'Ensure you include a clear and detailed prompt to receive the desired output. Follow the guidelines provided for the best results.', 'betterdocs' ); ?></p>
758 - </div>
759 - <div class="betterdocs-ai-checkbox-field ${hiddenClass}">
760 - <div class="form-group">
761 - <div class="checkbox-field-label">
762 - <label for="betterdocs-ai-checkbox">${checkboxLabel}</label>
763 - <p class="input-description"><?php echo esc_html__( 'Overwrite the existing doc with the AI Generated Content. If Disabled, new AI Generated content will be added in the section you are currently editing.', 'betterdocs' ); ?></p>
764 - </div>
536 + <input type="hidden" name="ai_nonce" value="${nonce}" />
537 + </div>
538 + <div class="generate-button-container">
539 + <button type="submit" class="generate-btn" onclick="generateArticle(event)">
540 + ${aiIcon} <span>${promtArticleLabel}</span>
541 + </button>
542 + </div>
543 + </form>
544 + </div>
765 545
766 - <div class="checkbox-input-field">
767 - <input type="checkbox" id="betterdocs-ai-checkbox" name="betterdocs-ai-checkbox" data-overwrite="false">
768 - <label for="betterdocs-ai-checkbox" class="toggle-label"></label>
769 - </div>
770 - </div>
771 - </div>
546 + <div class="bd-close-button" onclick="closeWriteWithAIForm('afterClosedClicked')">✕</div>
547 + </div>
548 +
549 + <div id="betterdocs-ai-autowrite-form-container-overlay" class="hidden"></div>
550 + `;
551 + }
772 552
773 - <input type="hidden" name="ai_nonce" value="${nonce}" />
774 - </div>
775 - <div class="generate-button-container">
776 - <button type="submit" class="generate-btn" onclick="generateArticle(event)">
777 - ${aiIcon} <span>${promtArticleLabel}</span>
778 - </button>
779 - </div>
780 - </form>
781 - </div>
553 + jQuery(document).on('click', '.regenerate-btn', function() {
554 + jQuery('.betterdocs-ai-autowrite-form-container').removeClass('hidden');
555 + jQuery('#betterdocs-ai-autowrite-form-container-overlay').removeClass('hidden');
556 + });
782 557
783 - <div class="bd-close-button" onclick="closeWriteWithAIForm('afterClosedClicked')">✕</div>
784 - </div>
558 + jQuery(document).ready(function($) {
559 + // Check if we are in the Edit Post screen
560 + if ($('.block-editor-page').length > 0) {
561 + const bdAIButton = $(`<div class="betterdocs-ai-button-container">
562 + <button class="betterdocs-ai-button">
563 + <img src="<?php echo esc_url(BETTERDOCS_ABSURL . 'assets/admin/images/betterdocs-icon-white.png'); ?>" alt="<?php echo esc_attr__('betterdocs icon', 'embedpress'); ?>" />
564 + <span><?php echo esc_html__('Write with AI', 'embedpress'); ?></span>
565 + </button>
566 + </div>`);
567 + const closeBtn = $('bd-close-button');
785 568
786 - <div id="betterdocs-ai-autowrite-form-container-overlay" class="hidden"></div>
787 - `;
788 - }
569 + const formHtml = writeWithAIForm();
570 + $(formHtml).addClass('hidden');
789 571
790 - jQuery(document).on('click', '.regenerate-btn', function() {
791 - jQuery('.betterdocs-ai-autowrite-form-container').removeClass('hidden');
792 - jQuery('#betterdocs-ai-autowrite-form-container-overlay').removeClass('hidden');
793 - });
572 + $(document).on('click', '.betterdocs-ai-button', function() {
573 + $('.betterdocs-ai-autowrite-form-container').removeClass('hidden');
574 + $('#betterdocs-ai-autowrite-form-container-overlay').removeClass('hidden');
575 + });
794 576
795 - jQuery(document).ready(function($) {
796 - // Check if we are in the Edit Post screen
577 + // $(document).on('click', '.betterdocs-ai-button', function() {
578 + if ($('.betterdocs-ai-autowrite-form-container').length < 1) {
579 + $('body').append(formHtml);
797 580
798 - if ($('.block-editor-page').length > 0) {
581 + // Add event listeners to input elements
582 + document.getElementById('betterdocs-ai-title').addEventListener('input', updateTextarea);
583 + document.getElementById('betterdocs-ai-keyword').addEventListener('input', updateTextarea);
584 + // document.getElementById('bd-autowrtite-content-section').addEventListener('change', updateTextarea);
585 + // document.getElementById('bd-autowrtite-content-paragraph').addEventListener('change', updateTextarea);
586 + // document.getElementById('betterdocs-ai-language').addEventListener('input', updateTextarea);
587 + }
588 + // });
589 + const btn = document.createElement('button');
590 + wp.data.subscribe(function() {
591 + setTimeout(() => {
592 + if ($('.edit-post-header__settings').length > 0) {
593 + $('.edit-post-header__settings').prepend(bdAIButton);
594 + }
595 + }, 1);
596 + });
597 + }
799 598
800 - const bdAIButton = $(`<div class="betterdocs-ai-button-container">
801 - <button class="betterdocs-ai-button">
802 - <img src="<?php echo esc_url( BETTERDOCS_ABSURL . 'assets/admin/images/betterdocs-icon-white.png' ); ?>" alt="<?php echo esc_attr__( 'betterdocs icon', 'betterdocs' ); ?>" />
803 - <span><?php echo esc_html__( 'Write with AI', 'betterdocs' ); ?></span>
804 - </button>
805 - </div>`);
599 + $(document).on('click', '#betterdocs-ai-autowrite-form-container-overlay', function() {
600 + closeWriteWithAIForm();
601 + });
602 + });
603 + </script>
806 604
605 + <style>
606 + .hidden {
607 + display: none !important;
608 + }
807 609
808 - const closeBtn = $('bd-close-button');
610 + .disabled-input-field input,
611 + .disabled-input-field textarea,
612 + .disabled-input-field button,
613 + .disabled-input-field label {
614 + pointer-events: none;
615 + opacity: 0.6;
616 + }
809 617
810 - const formHtml = writeWithAIForm();
811 - $(formHtml).addClass('hidden');
618 + .disabled-input-field label {
619 + opacity: 1;
620 + }
812 621
813 - $(document).on('click', '.betterdocs-ai-button', function() {
814 - $('.betterdocs-ai-autowrite-form-container').removeClass('hidden');
815 - $('#betterdocs-ai-autowrite-form-container-overlay').removeClass('hidden');
816 - });
622 + .betterdocs-ai-button-container {
623 + margin-left: 10px;
624 + }
817 625
818 - // $(document).on('click', '.betterdocs-ai-button', function() {
819 - if ($('.betterdocs-ai-autowrite-form-container').length < 1) {
820 - $('body').append(formHtml);
626 + .autowrite-icon {
627 + display: flex;
628 + align-items: center;
629 + width: 55px;
630 + height: 55px;
631 + background: #FFE4E8;
632 + justify-content: center;
633 + border-radius: 50px;
634 + }
821 635
822 - // Add event listeners to input elements
823 - document.getElementById('betterdocs-ai-title').addEventListener('input', updateTextarea);
824 - document.getElementById('betterdocs-ai-keyword').addEventListener('input', updateTextarea);
825 - // document.getElementById('bd-autowrtite-content-section').addEventListener('change', updateTextarea);
826 - // document.getElementById('bd-autowrtite-content-paragraph').addEventListener('change', updateTextarea);
827 - // document.getElementById('betterdocs-ai-language').addEventListener('input', updateTextarea);
828 - }
829 - // });
830 - const btn = document.createElement('button');
831 - wp.data.subscribe(function() {
832 - setTimeout(() => {
833 - if ($('.edit-post-header__settings').length > 0) {
834 - $('.edit-post-header__settings').prepend(bdAIButton);
835 - } else if ($('.editor-header__settings').length > 0) {
836 - $('.editor-header__settings').prepend(bdAIButton);
837 - }
636 + .autowrite-icon svg {
637 + width: 28px;
638 + height: 28px;
639 + }
838 640
839 - }, 1);
840 - });
841 - }
641 + .autowrite-heading {
642 + display: flex;
643 + gap: 10px;
644 + align-items: center;
645 + }
842 646
843 - $(document).on('click', '#betterdocs-ai-autowrite-form-container-overlay', function() {
844 - closeWriteWithAIForm();
845 - });
846 - });
847 - </script>
647 + .autowrite-heading h1 {
648 + color: #1D2939;
649 + font-family: 'IBM Plex Sans', sans-serif;
650 + font-size: 24px;
651 + font-style: normal;
652 + font-weight: 500;
653 + line-height: normal;
654 + margin: 0;
655 + }
848 656
849 - <style>
850 - .hidden {
851 - display: none !important;
852 - }
657 + .autowrite-heading p,
658 + form#betterdocs-ai-form p {
659 + margin: 0;
660 + margin-bottom: 24px;
661 + }
853 662
854 - .disabled-input-field input,
855 - .disabled-input-field textarea,
856 - .disabled-input-field button,
857 - .disabled-input-field label {
858 - pointer-events: none;
859 - opacity: 0.6;
860 - }
663 + .autowrite-subheadding p {
664 + font-family: 'IBM Plex Sans', sans-serif;
665 + font-size: 14px;
666 + }
861 667
862 - .disabled-input-field label {
863 - opacity: 1;
864 - }
668 + .prompt-field .input-description {
669 + margin: 0 !important;
670 + }
865 671
866 - .betterdocs-ai-button-container {
867 - margin-left: 10px;
868 - white-space: nowrap;
869 - max-width: 145px;
870 - }
672 + .autowrite-heading p {
673 + color: #475467;
674 + font-family: 'IBM Plex Sans', sans-serif;
675 + font-size: 16px;
676 + font-style: normal;
677 + font-weight: 400;
678 + }
871 679
872 - .autowrite-icon {
873 - display: flex;
874 - align-items: center;
875 - width: 55px;
876 - height: 55px;
877 - background: #FFE4E8;
878 - justify-content: center;
879 - border-radius: 50px;
880 - }
680 + .betterdocs-ai-button {
681 + background: #00B884;
682 + border: 1px solid transparent;
683 + color: #fff;
684 + box-shadow: none;
685 + font-size: 12px;
686 + margin-right: 8px;
687 + padding: 0px 15px;
688 + cursor: pointer;
689 + border-radius: 3px;
690 + height: 38px;
691 + display: flex;
692 + align-items: center;
693 + justify-content: space-between;
694 + gap: 10px;
695 + }
881 696
882 - .autowrite-icon svg {
883 - width: 28px;
884 - height: 28px;
885 - }
697 + .betterdocs-ai-button img {
698 + width: 20px;
699 + height: 20px;
700 + }
886 701
887 - .autowrite-heading {
888 - display: flex;
889 - gap: 10px;
890 - align-items: center;
891 - }
702 + .betterdocs-ai-autowrite-form-container {
703 + position: fixed;
704 + top: 50%;
705 + left: 50%;
706 + transform: translate(-50%, -50%);
707 + z-index: 100001;
708 + width: 650px;
709 + margin: 0 auto;
710 + background-color: #fff;
711 + border-radius: 5px;
712 + font-family: 'IBM Plex Sans', sans-serif;
713 + /* max-height: 600px; */
714 + max-height: 750px;
715 + max-width: 100%;
716 + }
892 717
893 - .autowrite-heading h1 {
894 - color: #1D2939;
895 - font-family: 'IBM Plex Sans', sans-serif;
896 - font-size: 24px;
897 - font-style: normal;
898 - font-weight: 500;
899 - line-height: normal;
900 - margin: 0;
901 - }
718 + .betterdocs-ai-autowrite-form-content {
719 + background-color: #fff;
720 + padding: 20px 0px;
721 + border-radius: 5px;
722 + padding-bottom: 0;
723 + overflow: auto;
724 + /* max-height: 700px; */
725 + height: 100%;
902 726
903 - .autowrite-heading p,
904 - form#betterdocs-ai-form p {
905 - margin: 0;
906 - margin-bottom: 24px;
907 - }
727 + }
908 728
909 - .autowrite-subheadding p {
910 - font-family: 'IBM Plex Sans', sans-serif;
911 - font-size: 14px;
912 - }
729 + .betterdocs-ai-autowrite-top-part {
730 + /* padding-bottom: 20px; */
731 + border-bottom: 1px solid #ddd;
732 + /* margin-bottom: 20px; */
733 + padding: 0 40px;
734 + }
913 735
914 - .prompt-field .input-description {
915 - margin: 0 !important;
916 - }
736 + #betterdocs-ai-form {
737 + display: flex;
738 + flex-direction: column;
739 + /* height: 100%; */
740 + overflow: hidden;
741 + }
917 742
918 - .autowrite-heading p {
919 - color: #475467;
920 - font-family: 'IBM Plex Sans', sans-serif;
921 - font-size: 16px;
922 - font-style: normal;
923 - font-weight: 400;
924 - }
743 + .form-inner-content {
744 + overflow: auto;
745 + height: 100%;
746 + max-height: 435px;
747 + /* max-height: 330px; */
748 + padding: 0 40px;
749 + }
925 750
926 - .betterdocs-ai-button {
927 - background: #00B884;
928 - border: 1px solid transparent;
929 - color: #fff;
930 - box-shadow: none;
931 - font-size: 12px;
932 - margin-right: 8px;
933 - padding: 0px 15px;
934 - cursor: pointer;
935 - border-radius: 3px;
936 - height: 38px;
937 - display: flex;
938 - align-items: center;
939 - justify-content: space-between;
940 - gap: 10px;
941 - width: 135px;
942 - }
751 + .form-inner-content>.form-group {
752 + margin-top: 20px;
753 + }
943 754
944 - .betterdocs-ai-button img {
945 - width: 20px;
946 - height: 20px;
947 - }
948 755
949 - .betterdocs-ai-autowrite-form-container {
950 - position: fixed;
951 - top: 50%;
952 - left: 50%;
953 - transform: translate(-50%, -50%);
954 - z-index: 100001;
955 - width: 650px;
956 - margin: 0 auto;
957 - background-color: #fff;
958 - border-radius: 5px;
959 - font-family: 'IBM Plex Sans', sans-serif;
960 - /* max-height: 600px; */
961 - max-height: 750px;
962 - max-width: 100%;
963 - }
756 + #betterdocs-ai-autowrite-form-container-overlay {
757 + position: fixed;
758 + top: 0;
759 + right: 0;
760 + bottom: 0;
761 + left: 0;
762 + background-color: rgba(0, 0, 0, .7);
763 + z-index: 100000;
764 + }
964 765
965 - .betterdocs-ai-autowrite-form-content {
966 - background-color: #fff;
967 - padding: 20px 0px;
968 - border-radius: 5px;
969 - padding-bottom: 0;
970 - overflow: auto;
971 - /* max-height: 700px; */
972 - height: 100%;
973 766
974 - }
975 767
976 - .betterdocs-ai-autowrite-top-part {
977 - /* padding-bottom: 20px; */
978 - border-bottom: 1px solid #ddd;
979 - /* margin-bottom: 20px; */
980 - padding: 0 40px;
981 - }
768 + #betterdocs-ai-form {
769 + display: flex;
770 + flex-direction: column;
771 + }
982 772
983 - #betterdocs-ai-form {
984 - display: flex;
985 - flex-direction: column;
986 - /* height: 100%; */
987 - overflow: hidden;
988 - }
773 + #betterdocs-ai-form .form-group {
774 + margin-bottom: 24px;
775 + }
989 776
990 - .form-inner-content {
991 - overflow: auto;
992 - height: 100%;
993 - max-height: 435px;
994 - /* max-height: 330px; */
995 - padding: 0 40px;
996 - }
777 + #betterdocs-ai-form .bd-aiform-flex {
778 + display: flex;
779 + justify-content: space-between;
780 + }
997 781
998 - .form-inner-content>.form-group {
999 - margin-top: 20px;
1000 - }
782 + #betterdocs-ai-form label {
783 + font-weight: 600;
784 + margin-bottom: 5px;
785 + display: block;
786 + font-size: 14px;
787 + line-height: 20px;
788 + }
1001 789
790 + select#bd-autowrtite-content-section,
791 + #bd-autowrtite-content-paragraph,
792 + #betterdocs-ai-language {
793 + width: 150px !important;
794 + height: 40px;
795 + }
1002 796
1003 - #betterdocs-ai-autowrite-form-container-overlay {
1004 - position: fixed;
1005 - top: 0;
1006 - right: 0;
1007 - bottom: 0;
1008 - left: 0;
1009 - background-color: rgba(0, 0, 0, .7);
1010 - z-index: 100000;
1011 - }
797 + #betterdocs-ai-form input[type="text"],
798 + #betterdocs-ai-form textarea {
799 + width: 100%;
800 + padding: 8px;
801 + box-sizing: border-box;
802 + border: 1px solid #D0D5DD;
803 + border-radius: 4px;
804 + color: #667085;
805 + font-weight: 400;
806 + }
1012 807
808 + /* Override autofill text color */
809 + #betterdocs-ai-form input:-webkit-autofill {
810 + -webkit-text-fill-color: #667085 !important;
811 + }
1013 812
813 + #betterdocs-ai-form input::placeholder {
814 + color: #acb2bf;
815 + }
1014 816
1015 - #betterdocs-ai-form {
1016 - display: flex;
1017 - flex-direction: column;
1018 - }
817 + #betterdocs-ai-form textarea {
818 + color: #667085;
819 + }
1019 820
1020 - #betterdocs-ai-form .form-group {
1021 - margin-bottom: 24px;
1022 - }
821 + #betterdocs-ai-form input:focus,
822 + #betterdocs-ai-form textarea:focus {
823 + box-shadow: none;
824 + }
1023 825
1024 - #betterdocs-ai-form .bd-aiform-flex {
1025 - display: flex;
1026 - justify-content: space-between;
1027 - }
826 + #betterdocs-ai-form textarea:focus {
827 + color: inherit;
828 + box-shadow: none;
1028 829
1029 - #betterdocs-ai-form label {
1030 - font-weight: 600;
1031 - margin-bottom: 5px;
1032 - display: block;
1033 - font-size: 14px;
1034 - line-height: 20px;
1035 - }
830 + }
1036 831
1037 - select#bd-autowrtite-content-section,
1038 - #bd-autowrtite-content-paragraph,
1039 - #betterdocs-ai-language {
1040 - width: 150px !important;
1041 - height: 40px;
1042 - }
1043 832
1044 - #betterdocs-ai-form input[type="text"],
1045 - #betterdocs-ai-form textarea {
1046 - width: 100%;
1047 - padding: 8px;
1048 - box-sizing: border-box;
1049 - border: 1px solid #D0D5DD;
1050 - border-radius: 4px;
1051 - color: #667085;
1052 - font-weight: 400;
1053 - }
833 + .generate-button-container {
834 + position: sticky;
835 + bottom: 0px;
836 + width: 100%;
837 + margin-left: 0;
838 + z-index: 999999 !important;
839 + padding: 20px 0;
840 + display: flex;
841 + justify-content: end;
842 + border-top: 1px solid #ddd;
843 + background: white;
844 + border-bottom-right-radius: 5px;
845 + border-bottom-left-radius: 5px;
846 + }
1054 847
1055 - /* Override autofill text color */
1056 - #betterdocs-ai-form input:-webkit-autofill {
1057 - -webkit-text-fill-color: #667085 !important;
1058 - }
848 + .generate-button-container button {
849 + display: flex;
850 + gap: 8px;
851 + align-items: center;
852 + justify-content: center;
853 + opacity: 1 !important;
854 + margin-right: 40px;
855 + }
1059 856
1060 - #betterdocs-ai-form input::placeholder {
1061 - color: #acb2bf;
1062 - }
857 + .input-description {
858 + font-size: 14px;
859 + color: #667085;
860 + }
1063 861
1064 - #betterdocs-ai-form textarea {
1065 - color: #667085;
1066 - }
862 + .betterdocs-ai-checkbox-field .form-group {
863 + display: flex;
864 + align-items: start;
865 + /* gap: 200px; */
866 + justify-content: space-between;
867 + }
1067 868
1068 - #betterdocs-ai-form input:focus,
1069 - #betterdocs-ai-form textarea:focus {
1070 - box-shadow: none;
1071 - }
869 + .betterdocs-ai-checkbox-field input {
870 + width: 20px;
871 + height: 20px;
872 + }
1072 873
1073 - #betterdocs-ai-form textarea:focus {
1074 - color: inherit;
1075 - box-shadow: none;
874 + /* Add this CSS to your existing stylesheet or create a new one */
1076 875
1077 - }
876 + .betterdocs-ai-checkbox-field {
877 + position: relative;
878 + font-size: 16px;
879 + /* Adjust font size as needed */
880 + }
1078 881
882 + .betterdocs-ai-checkbox-field input[type=checkbox]:checked::before {
883 + padding: 2px;
884 + }
1079 885
1080 - .generate-button-container {
1081 - position: sticky;
1082 - bottom: 0px;
1083 - width: 100%;
1084 - margin-left: 0;
1085 - z-index: 999999 !important;
1086 - padding: 20px 0;
1087 - display: flex;
1088 - justify-content: end;
1089 - border-top: 1px solid #ddd;
1090 - background: white;
1091 - border-bottom-right-radius: 5px;
1092 - border-bottom-left-radius: 5px;
1093 - }
886 + .betterdocs-ai-checkbox-field input[type=checkbox] {
887 + border: 1px solid #00b884;
888 + }
1094 889
1095 - .generate-button-container button {
1096 - display: flex;
1097 - gap: 8px;
1098 - align-items: center;
1099 - justify-content: center;
1100 - opacity: 1 !important;
1101 - margin-right: 40px;
1102 - }
890 + .betterdocs-ai-checkbox-field input[type=checkbox]:checked::before {
891 + content: '\2713';
892 + color: #00b884;
893 + }
1103 894
1104 - .input-description {
1105 - font-size: 14px;
1106 - color: #667085;
1107 - }
895 + /* Change the default checkbox color */
896 + .betterdocs-ai-checkbox-field input[type="checkbox"]:hover {
897 + -webkit-appearance: none;
898 + /* WebKit/Blink Browsers */
899 + -moz-appearance: none;
900 + /* Firefox */
901 + appearance: none;
902 + border: 1px solid #00b884;
903 + /* Set the height of the checkbox */
904 + /* Optional: Round the corners */
905 + outline: none;
906 + /* Remove the default outline */
907 + }
1108 908
1109 - .betterdocs-ai-checkbox-field .form-group {
1110 - display: flex;
1111 - align-items: start;
1112 - /* gap: 200px; */
1113 - justify-content: space-between;
1114 - }
909 + /* Style the checked state */
910 + .betterdocs-ai-checkbox-field input[type="checkbox"]:checked {
911 + /* Set the background color when checked */
912 + border: 1px solid #00b884;
913 + /* Set the border color when checked */
914 + }
1115 915
1116 - .betterdocs-ai-checkbox-field input {
1117 - width: 20px;
1118 - height: 20px;
1119 - }
916 + .checkbox-field-label {
917 + width: calc(100% - 150px);
918 + }
1120 919
1121 - /* Add this CSS to your existing stylesheet or create a new one */
920 + .checkbox-field-label p {
921 + margin: 0 !important;
922 + }
1122 923
1123 - .betterdocs-ai-checkbox-field {
1124 - position: relative;
1125 - font-size: 16px;
1126 - /* Adjust font size as needed */
1127 - }
924 + .checkbox-input-field {
925 + width: 300px;
926 + text-align: right;
927 + }
1128 928
1129 - .betterdocs-ai-checkbox-field input[type=checkbox]:checked::before {
1130 - padding: 2px;
1131 - }
929 + .checkbox-input-field {
930 + position: relative;
931 + display: inline-block;
932 + width: 60px;
933 + height: 34px;
934 + }
1132 935
1133 - .betterdocs-ai-checkbox-field input[type=checkbox] {
1134 - border: 1px solid #00b884;
1135 - }
936 + .checkbox-input-field input {
937 + display: none;
938 + }
1136 939
1137 - .betterdocs-ai-checkbox-field input[type=checkbox]:checked::before {
1138 - content: '\2713';
1139 - color: #00b884;
1140 - }
940 + .toggle-label {
941 + position: absolute;
942 + cursor: pointer;
943 + top: 0;
944 + left: 0;
945 + right: 0;
946 + bottom: 0;
947 + background-color: #ccc;
948 + border-radius: 34px;
949 + transition: background-color 0.3s;
950 + scale: .9;
951 + width: 52px;
952 + height: 26px;
953 + }
1141 954
1142 - /* Change the default checkbox color */
1143 - .betterdocs-ai-checkbox-field input[type="checkbox"]:hover {
1144 - -webkit-appearance: none;
1145 - /* WebKit/Blink Browsers */
1146 - -moz-appearance: none;
1147 - /* Firefox */
1148 - appearance: none;
1149 - border: 1px solid #00b884;
1150 - /* Set the height of the checkbox */
1151 - /* Optional: Round the corners */
1152 - outline: none;
1153 - /* Remove the default outline */
1154 - }
1155 955
1156 - /* Style the checked state */
1157 - .betterdocs-ai-checkbox-field input[type="checkbox"]:checked {
1158 - /* Set the background color when checked */
1159 - border: 1px solid #00b884;
1160 - /* Set the border color when checked */
1161 - }
956 + .checkbox-input-field input:checked+.toggle-label {
957 + background-color: #00b884;
958 + }
1162 959
1163 - .checkbox-field-label {
1164 - width: calc(100% - 150px);
1165 - }
960 + .toggle-label:after {
961 + content: "";
962 + position: absolute;
963 + height: 22px;
964 + width: 22px;
965 + left: 2px;
966 + bottom: 2px;
967 + background-color: white;
968 + border-radius: 50%;
969 + transition: transform 0.3s;
970 + }
1166 971
1167 - .checkbox-field-label p {
1168 - margin: 0 !important;
1169 - }
972 + .checkbox-input-field input:checked+.toggle-label:after {
973 + transform: translateX(26px);
974 + }
1170 975
1171 - .checkbox-input-field {
1172 - width: 300px;
1173 - text-align: right;
1174 - }
976 + .generate-btn,
977 + .prompt-btn,
978 + .keep-btn {
979 + background-color: #00b884;
980 + color: #fff;
981 + border: none;
982 + padding: 10px 15px;
983 + text-align: center;
984 + text-decoration: none;
985 + display: inline-block;
986 + font-size: 16px;
987 + cursor: pointer;
988 + border-radius: 4px;
989 + }
1175 990
1176 - .checkbox-input-field {
1177 - position: relative;
1178 - display: inline-block;
1179 - width: 60px;
1180 - height: 34px;
1181 - }
991 + .generate-btn[disabled] {
992 + cursor: unset;
993 + }
1182 994
1183 - .checkbox-input-field input {
1184 - display: none;
1185 - }
995 + .bd-close-button {
996 + cursor: pointer;
997 + font-size: 18px;
998 + font-weight: bold;
999 + float: right;
1000 + position: absolute;
1001 + right: 1px;
1002 + top: 1px;
1003 + padding: 10px;
1004 + background: #ffffff;
1005 + border-radius: 25px;
1006 + width: 20px;
1007 + height: 20px;
1008 + display: flex;
1009 + align-items: center;
1010 + justify-content: center;
1011 + color: #281617;
1012 + right: -60px;
1013 + }
1186 1014
1187 - .toggle-label {
1188 - position: absolute;
1189 - cursor: pointer;
1190 - top: 0;
1191 - left: 0;
1192 - right: 0;
1193 - bottom: 0;
1194 - background-color: #ccc;
1195 - border-radius: 34px;
1196 - transition: background-color 0.3s;
1197 - scale: .9;
1198 - width: 52px;
1199 - height: 26px;
1200 - }
1015 + div#betterdocs-ai-error-message,
1016 + #betterdocs-ai-message {
1017 + font-size: 14px;
1018 + font-family: 'IBM Plex Sans', sans-serif;
1019 + color: #667085;
1020 + margin-bottom: 20px;
1021 + }
1201 1022
1023 + div#betterdocs-ai-error-message a,
1024 + #betterdocs-ai-message a {
1025 + text-decoration: none;
1026 + font-weight: 600;
1027 + }
1202 1028
1203 - .checkbox-input-field input:checked+.toggle-label {
1204 - background-color: #00b884;
1205 - }
1029 + div#betterdocs-ai-error-message a:focus,
1030 + #betterdocs-ai-message a:focus {
1031 + outline: none;
1032 + box-shadow: none;
1033 + color: #2271b1;
1034 + }
1206 1035
1207 - .toggle-label:after {
1208 - content: "";
1209 - position: absolute;
1210 - height: 22px;
1211 - width: 22px;
1212 - left: 2px;
1213 - bottom: 2px;
1214 - background-color: white;
1215 - border-radius: 50%;
1216 - transition: transform 0.3s;
1217 - }
1036 + #betterdocs-ai-message span {
1037 + color: #d63638;
1038 + }
1218 1039
1219 - .checkbox-input-field input:checked+.toggle-label:after {
1220 - transform: translateX(26px);
1221 - }
1040 + .warning-message {
1041 + display: flex;
1042 + align-items: center;
1043 + gap: 10px;
1044 + background: #fbebed;
1045 + padding: 12px;
1046 + border-radius: 5px;
1047 + font-size: 14px;
1048 + line-height: 1.4em;
1049 + border-left: 4px solid #d63638;
1050 + }
1222 1051
1223 - .generate-btn,
1224 - .prompt-btn,
1225 - .keep-btn {
1226 - background-color: #00b884;
1227 - color: #fff;
1228 - border: none;
1229 - padding: 10px 15px;
1230 - text-align: center;
1231 - text-decoration: none;
1232 - display: inline-block;
1233 - font-size: 16px;
1234 - cursor: pointer;
1235 - border-radius: 4px;
1236 - }
1052 + .warning-message svg {
1053 + width: 20px;
1054 + height: 20px;
1055 + }
1237 1056
1238 - .generate-btn[disabled] {
1239 - cursor: unset;
1240 - }
1057 + .warning-message span {
1058 + color: #d63638;
1059 + }
1241 1060
1242 - .bd-close-button {
1243 - cursor: pointer;
1244 - font-size: 18px;
1245 - font-weight: bold;
1246 - float: right;
1247 - position: absolute;
1248 - top: -16px;
1249 - border-radius: 50%;
1250 - background: #ffffff;
1251 - width: 40px;
1252 - height: 40px;
1253 - display: flex;
1254 - align-items: center;
1255 - justify-content: center;
1256 - color: #281617;
1257 - right: -42px;
1258 - }
1061 + .warning-message .footer-message {
1062 + width: calc(100% - 20px);
1063 + }
1259 1064
1260 - div#betterdocs-ai-error-message,
1261 - #betterdocs-ai-message {
1262 - font-size: 14px;
1263 - font-family: 'IBM Plex Sans', sans-serif;
1264 - color: #667085;
1265 - margin-bottom: 20px;
1266 - }
1065 + @media only screen and (max-width: 991px) {
1066 + .betterdocs-ai-autowrite-form-container {
1067 + left: 0;
1068 + right: 0;
1069 + transform: translate(0%, -50%);
1070 + }
1267 1071
1268 - div#betterdocs-ai-error-message a,
1269 - #betterdocs-ai-message a {
1270 - text-decoration: none;
1271 - font-weight: 600;
1272 - }
1072 + .betterdocs-ai-autowrite-form-content {
1073 + overflow-x: auto;
1074 + }
1075 + }
1273 1076
1274 - div#betterdocs-ai-error-message a:focus,
1275 - #betterdocs-ai-message a:focus {
1276 - outline: none;
1277 - box-shadow: none;
1278 - color: #2271b1;
1279 - }
1077 + @media only screen and (max-width: 740px) {
1280 1078
1281 - #betterdocs-ai-message span {
1282 - color: #d63638;
1283 - }
1079 + /* .bd-close-button {
1080 + right: px;
1081 + top: 1px;
1082 + border-radius: 5px;
1083 + width: 12px;
1084 + height: 12px;
1085 + color: #ffffff;
1086 + background: #00b884;
1087 + } */
1088 + .bd-close-button {
1089 + right: 0px;
1090 + top: 0px;
1091 + width: 12px;
1092 + height: 12px;
1093 + font-size: 14px;
1094 + }
1284 1095
1285 - .warning-message {
1286 - display: flex;
1287 - align-items: center;
1288 - gap: 10px;
1289 - background: #fbebed;
1290 - padding: 12px;
1291 - border-radius: 5px;
1292 - font-size: 14px;
1293 - line-height: 1.4em;
1294 - border-left: 4px solid #d63638;
1295 - }
1296 -
1297 - .warning-message svg {
1298 - width: 20px;
1299 - height: 20px;
1300 - }
1301 -
1302 - .warning-message span {
1303 - color: #d63638;
1304 - }
1305 -
1306 - .warning-message .footer-message {
1307 - width: calc(100% - 20px);
1308 - }
1309 -
1310 - @media only screen and (max-width: 991px) {
1311 - .betterdocs-ai-autowrite-form-container {
1312 - left: 0;
1313 - right: 0;
1314 - transform: translate(0%, -50%);
1315 - }
1316 -
1317 - .betterdocs-ai-autowrite-form-content {
1318 - overflow-x: auto;
1319 - }
1320 - }
1321 -
1322 - @media only screen and (max-width: 740px) {
1323 -
1324 - /* .bd-close-button {
1325 - right: px;
1326 - top: 1px;
1327 - border-radius: 5px;
1328 - width: 12px;
1329 - height: 12px;
1330 - color: #ffffff;
1331 - background: #00b884;
1332 - } */
1333 - .bd-close-button {
1334 - right: 0px;
1335 - top: 0px;
1336 - width: 12px;
1337 - height: 12px;
1338 - font-size: 14px;
1339 - }
1340 -
1341 - }
1342 - </style>
1343 - <?php
1344 1096 }
1345 - }
1097 + </style>
1098 +<?php
1099 + }
1100 +}