PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.9.2
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.9.2
4.9.2 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 All 200 releases
betterdocs / views / templates / parts / code-snippet.php

code-snippet.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 4.9.2, at views/templates/parts/code-snippet.php

238 lines 10.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- view template receives variables via extract(); prefixing is impractical.
3
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7 /**
8 * Template part for BetterDocs Code Snippet
9 *
10 * @var string $code_content
11 * @var string $language
12 * @var bool $show_language_label
13 * @var bool $show_copy_button
14 * @var bool $show_header
15 * @var bool $show_line_numbers
16 * @var string $theme
17 * @var string $block_id (optional)
18 * @var string $widget_type (optional)
19 * @var string $file_name (optional)
20 * @var bool $show_traffic_lights (optional)
21 * @var bool $show_file_icon (optional)
22 * @var string $file_icon (optional)
23 * @var array $code_variants (optional) [ { language, code, file_name } ] — when
24 * more than one, the header renders a language dropdown.
25 */
26
27 if ( empty( $code_content ) ) {
28 return;
29 }
30
31 // Generate unique ID for this code snippet
32 $snippet_id = isset( $block_id ) ? $block_id : 'betterdocs-code-snippet-' . wp_rand( 1000, 9999 );
33
34 // Set defaults for optional parameters
35 // Gates the language name on the multi-language switcher. The Elementor switch
36 // and the block's showLanguageLabel attribute both fed this variable and nothing
37 // ever read it, so the control was a no-op in both editors. Default stays true,
38 // so existing content renders exactly as before.
39 $show_language_label = isset( $show_language_label ) ? $show_language_label : true;
40 $show_copy_button = isset( $show_copy_button ) ? $show_copy_button : true;
41 $show_header = isset( $show_header ) ? $show_header : true;
42 $file_name = isset( $file_name ) ? $file_name : '';
43 $show_traffic_lights = isset( $show_traffic_lights ) ? $show_traffic_lights : true;
44 $show_file_icon = isset( $show_file_icon ) ? $show_file_icon : true;
45 $file_icon = isset( $file_icon ) ? $file_icon : '';
46
47 // Sanitize inputs (preserve code content as-is for display purposes)
48 $language = sanitize_text_field( $language );
49 $theme = sanitize_text_field( $theme );
50 $file_name = sanitize_text_field( $file_name );
51 $file_icon = esc_url( $file_icon );
52
53 // Import Helper class for file icon functionality
54 use WPDeveloper\BetterDocs\Utils\Helper;
55
56 // Build the language list. Callers that don't pass code_variants (Elementor /
57 // shortcode) fall back to the single primary language/code — identical to the
58 // previous behaviour.
59 $variants = ( isset( $code_variants ) && is_array( $code_variants ) && ! empty( $code_variants ) )
60 ? $code_variants
61 : [
62 [
63 'language' => $language,
64 'code' => $code_content,
65 'file_name' => $file_name
66 ]
67 ];
68
69 // Normalize every entry up front. `code_variants` arrives from block attributes
70 // (and from Pro's API-docs generator), so a caller can legitimately hand over an
71 // entry missing `language` or `code` — reading them directly emitted PHP 8
72 // warnings mid-render. The tab template already guards this way.
73 $variants = array_values(
74 array_filter(
75 array_map(
76 function ( $variant ) {
77 if ( ! is_array( $variant ) ) {
78 return null;
79 }
80
81 return [
82 'language' => isset( $variant['language'] ) ? (string) $variant['language'] : '',
83 'code' => isset( $variant['code'] ) ? (string) $variant['code'] : '',
84 'file_name' => isset( $variant['file_name'] ) ? (string) $variant['file_name'] : ''
85 ];
86 },
87 $variants
88 )
89 )
90 );
91
92 // Everything below indexes $variants[0]; keep the single-entry fallback so an
93 // empty or fully-invalid list still renders rather than fatalling.
94 if ( empty( $variants ) ) {
95 $variants = [
96 [
97 'language' => $language,
98 'code' => (string) $code_content,
99 'file_name' => $file_name
100 ]
101 ];
102 }
103
104 $is_multi = count( $variants ) > 1;
105 $active = $variants[0];
106 $active_lang = sanitize_text_field( $active['language'] );
107
108 // Dropdown/tab label for an entry: a custom filename overrides (so the API-docs
109 // cURL sample reads "cURL", not "Bash"), otherwise the language's display name.
110 // The block default filename ("filename.js") never wins.
111 $lang_label = function ( $variant ) {
112 $file = isset( $variant['file_name'] ) ? (string) $variant['file_name'] : '';
113 if ( '' !== $file && 'filename.js' !== $file ) {
114 return $file;
115 }
116 return Helper::get_language_label( sanitize_text_field( isset( $variant['language'] ) ? $variant['language'] : '' ) );
117 };
118
119 // Enqueue necessary assets
120 wp_enqueue_script( 'betterdocs-code-snippet' );
121 wp_enqueue_style( 'betterdocs-code-snippet' );
122 ?>
123
124 <div class="betterdocs-code-snippet-wrapper theme-<?php echo esc_attr( $theme ); ?> <?php echo esc_attr( $snippet_id ); ?><?php echo $is_multi ? ' is-multi-lang' : ''; ?>"
125 id="<?php echo esc_attr( $snippet_id ); ?>"
126 data-language="<?php echo esc_attr( $active_lang ); ?>"
127 <?php echo $is_multi ? 'data-multi-lang="true"' : ''; ?>
128 data-copy-button="<?php echo $show_copy_button ? 'true' : 'false'; ?>">
129
130 <?php if ( $show_header ) : ?>
131 <div class="betterdocs-code-snippet-header betterdocs-file-preview-header">
132 <div class="betterdocs-file-preview-left">
133 <?php if ( $show_traffic_lights ) : ?>
134 <div class="betterdocs-traffic-lights">
135 <span class="traffic-light traffic-light-red"></span>
136 <span class="traffic-light traffic-light-yellow"></span>
137 <span class="traffic-light traffic-light-green"></span>
138 </div>
139 <?php endif; ?>
140
141 <?php if ( ! $is_multi ) : ?>
142 <div class="betterdocs-file-info">
143 <?php if ( $show_file_icon ) : ?>
144 <div class="betterdocs-file-icon">
145 <?php if ( ! empty( $file_icon ) ) : ?>
146 <img src="<?php echo esc_url( $file_icon ); ?>" alt="<?php esc_attr_e( 'File icon', 'betterdocs' ); ?>" />
147 <?php else : ?>
148 <span class="betterdocs-file-icon-emoji"><?php echo esc_html( Helper::get_file_icon_by_language( $active_lang ) ); ?></span>
149 <?php endif; ?>
150 </div>
151 <?php endif; ?>
152
153 <?php if ( ! empty( $file_name ) ) : ?>
154 <div class="betterdocs-file-name">
155 <span class="file-name-text"><?php echo esc_html( $file_name ); ?></span>
156 </div>
157 <?php endif; ?>
158 </div>
159 <?php endif; ?>
160 </div>
161
162 <div class="betterdocs-file-preview-right">
163 <?php if ( $is_multi ) : ?>
164 <div class="betterdocs-code-lang-dropdown">
165 <button type="button" class="betterdocs-code-lang-toggle" aria-haspopup="listbox" aria-expanded="false">
166 <span class="betterdocs-code-lang-current">
167 <?php if ( $show_file_icon ) : ?>
168 <span class="betterdocs-file-icon-emoji"><?php echo esc_html( Helper::get_file_icon_by_language( $active_lang ) ); ?></span>
169 <?php endif; ?>
170 <?php if ( $show_language_label ) : ?>
171 <span class="betterdocs-code-lang-label"><?php echo esc_html( $lang_label( $active ) ); ?></span>
172 <?php endif; ?>
173 </span>
174 <svg class="betterdocs-code-lang-caret" width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
175 <path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
176 </svg>
177 </button>
178 <ul class="betterdocs-code-lang-menu" role="listbox">
179 <?php foreach ( $variants as $i => $variant ) : ?>
180 <?php $v_lang = sanitize_text_field( $variant['language'] ); ?>
181 <li class="betterdocs-code-lang-option<?php echo 0 === $i ? ' is-active' : ''; ?>"
182 role="option"
183 data-lang-index="<?php echo esc_attr( $i ); ?>">
184 <?php if ( $show_file_icon ) : ?>
185 <span class="betterdocs-file-icon-emoji"><?php echo esc_html( Helper::get_file_icon_by_language( $v_lang ) ); ?></span>
186 <?php endif; ?>
187 <span class="betterdocs-code-lang-label"><?php echo esc_html( $lang_label( $variant ) ); ?></span>
188 </li>
189 <?php endforeach; ?>
190 </ul>
191 </div>
192 <?php endif; ?>
193
194 <?php if ( $show_copy_button ) : ?>
195 <?php Helper::code_snippet_copy_button(); ?>
196 <?php endif; ?>
197 </div>
198 </div>
199 <?php endif; ?>
200
201 <div class="betterdocs-code-snippet-content">
202 <?php foreach ( $variants as $i => $variant ) : ?>
203 <?php
204 $v_lang = sanitize_text_field( $variant['language'] );
205 $v_code = (string) $variant['code'];
206 ?>
207 <div class="betterdocs-code-snippet-panel<?php echo 0 === $i ? ' is-active' : ''; ?>"
208 data-lang-index="<?php echo esc_attr( $i ); ?>"
209 <?php echo 0 === $i ? '' : 'hidden'; ?>>
210 <?php if ( $show_line_numbers ) : ?>
211 <div class="betterdocs-code-snippet-line-numbers" aria-hidden="true">
212 <?php foreach ( range( 1, max( 1, substr_count( $v_code, "\n" ) + 1 ) ) as $line_num ) : ?>
213 <div class="line-number"><?php echo esc_html( $line_num ); ?></div>
214 <?php endforeach; ?>
215 </div>
216 <?php endif; ?>
217
218 <pre class="betterdocs-code-snippet-code language-<?php echo esc_attr( $v_lang ); ?>"><code><?php echo esc_html( $v_code ); ?></code></pre>
219 </div>
220 <?php endforeach; ?>
221 </div>
222 </div>
223
224 <?php
225 // Add inline script for copy functionality if copy button is enabled
226 if ( $show_copy_button ) :
227 ?>
228 <script type="text/javascript">
229 document.addEventListener('DOMContentLoaded', function() {
230 // Initialize copy functionality for this specific snippet
231 const snippet = document.getElementById('<?php echo esc_js( $snippet_id ); ?>');
232 if (snippet && window.BetterDocsCodeSnippet) {
233 window.BetterDocsCodeSnippet.initCopyButton(snippet);
234 }
235 });
236 </script>
237 <?php endif; ?>
238