PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.9.3
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.9.3
4.9.3 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 All 201 releases
← All changes | views/templates/parts/code-snippet.php +136 -44 4.6.2 → 4.9.3 View file →
@@ -10,9 +10,8 @@
10 10 * @var string $code_content
11 11 * @var string $language
12 12 * @var bool $show_language_label
13 13 * @var bool $show_copy_button
14 - * @var bool $show_copy_tooltip
15 14 * @var bool $show_header
16 15 * @var bool $show_line_numbers
17 16 * @var string $theme
18 17 * @var string $block_id (optional)
@@ -20,8 +19,10 @@
20 19 * @var string $file_name (optional)
21 20 * @var bool $show_traffic_lights (optional)
22 21 * @var bool $show_file_icon (optional)
23 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.
24 25 */
25 26
26 27 if ( empty( $code_content ) ) {
27 28 return;
@@ -30,11 +31,14 @@
30 31 // Generate unique ID for this code snippet
31 32 $snippet_id = isset( $block_id ) ? $block_id : 'betterdocs-code-snippet-' . wp_rand( 1000, 9999 );
32 33
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.
34 39 $show_language_label = isset( $show_language_label ) ? $show_language_label : true;
35 40 $show_copy_button = isset( $show_copy_button ) ? $show_copy_button : true;
36 -$show_copy_tooltip = isset( $show_copy_tooltip ) ? $show_copy_tooltip : false;
37 41 $show_header = isset( $show_header ) ? $show_header : true;
38 42 $file_name = isset( $file_name ) ? $file_name : '';
39 43 $show_traffic_lights = isset( $show_traffic_lights ) ? $show_traffic_lights : true;
40 44 $show_file_icon = isset( $show_file_icon ) ? $show_file_icon : true;
@@ -48,23 +52,80 @@
48 52
49 53 // Import Helper class for file icon functionality
50 54 use WPDeveloper\BetterDocs\Utils\Helper;
51 55
52 -// Generate line numbers if needed
53 -$line_numbers = [];
54 -if ( $show_line_numbers ) {
55 - $lines = explode( "\n", $code_content );
56 - $line_numbers = range( 1, count( $lines ) );
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 + ];
57 102 }
58 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 +
59 119 // Enqueue necessary assets
60 120 wp_enqueue_script( 'betterdocs-code-snippet' );
61 121 wp_enqueue_style( 'betterdocs-code-snippet' );
62 122 ?>
63 123
64 -<div class="betterdocs-code-snippet-wrapper theme-<?php echo esc_attr( $theme ); ?> <?php echo esc_attr( $snippet_id ); ?>"
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' : ''; ?>"
65 125 id="<?php echo esc_attr( $snippet_id ); ?>"
66 - data-language="<?php echo esc_attr( $language ); ?>"
126 + data-language="<?php echo esc_attr( $active_lang ); ?>"
127 + <?php echo $is_multi ? 'data-multi-lang="true"' : ''; ?>
67 128 data-copy-button="<?php echo $show_copy_button ? 'true' : 'false'; ?>">
68 129
69 130 <?php if ( $show_header ) : ?>
70 131 <div class="betterdocs-code-snippet-header betterdocs-file-preview-header">
@@ -76,57 +137,88 @@
76 137 <span class="traffic-light traffic-light-green"></span>
77 138 </div>
78 139 <?php endif; ?>
79 140
80 - <div class="betterdocs-file-info">
81 - <?php if ( $show_file_icon ) : ?>
82 - <div class="betterdocs-file-icon">
83 - <?php if ( ! empty( $file_icon ) ) : ?>
84 - <img src="<?php echo esc_url( $file_icon ); ?>" alt="<?php esc_attr_e( 'File icon', 'betterdocs' ); ?>" />
85 - <?php else : ?>
86 - <span class="betterdocs-file-icon-emoji"><?php echo esc_html( Helper::get_file_icon_by_language( $language ) ); ?></span>
87 - <?php endif; ?>
88 - </div>
89 - <?php endif; ?>
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; ?>
90 152
91 - <?php if ( ! empty( $file_name ) ) : ?>
92 - <div class="betterdocs-file-name">
93 - <span class="file-name-text"><?php echo esc_html( $file_name ); ?></span>
94 - </div>
95 - <?php endif; ?>
96 - </div>
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; ?>
97 160 </div>
98 161
99 162 <div class="betterdocs-file-preview-right">
100 - <?php if ( $show_copy_button ) : ?>
101 - <div class="betterdocs-code-snippet-copy-container">
102 - <button class="betterdocs-code-snippet-copy-button"
103 - type="button"
104 - data-clipboard-target="#<?php echo esc_attr( $snippet_id ); ?> .betterdocs-code-snippet-code code"
105 - aria-label="<?php esc_attr_e( 'Copy code to clipboard', 'betterdocs' ); ?>">
106 - <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
107 - <path d="M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1ZM19 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H19C20.1 23 21 22.1 21 21V7C21 5.9 20.1 5 19 5ZM19 21H8V7H19V21Z" fill="currentColor"/>
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"/>
108 176 </svg>
109 177 </button>
110 - <?php if ( $show_copy_tooltip ) : ?>
111 - <div class="betterdocs-code-snippet-tooltip"><?php esc_html_e( 'Copy to clipboard', 'betterdocs' ); ?></div>
112 - <?php endif; ?>
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>
113 191 </div>
114 192 <?php endif; ?>
193 +
194 + <?php if ( $show_copy_button ) : ?>
195 + <?php Helper::code_snippet_copy_button(); ?>
196 + <?php endif; ?>
115 197 </div>
116 198 </div>
117 199 <?php endif; ?>
118 200
119 201 <div class="betterdocs-code-snippet-content">
120 - <?php if ( $show_line_numbers ) : ?>
121 - <div class="betterdocs-code-snippet-line-numbers" aria-hidden="true">
122 - <?php foreach ( $line_numbers as $line_num ) : ?>
123 - <div class="line-number"><?php echo esc_html( $line_num ); ?></div>
124 - <?php endforeach; ?>
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>
125 219 </div>
126 - <?php endif; ?>
127 -
128 - <pre class="betterdocs-code-snippet-code language-<?php echo esc_attr( $language ); ?>"><code><?php echo esc_html( $code_content ); ?></code></pre>
220 + <?php endforeach; ?>
129 221 </div>
130 222 </div>
131 223
132 224 <?php