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
← All changes | includes/Editors/BlockEditor/Blocks/CodeSnippet.php +81 -12 4.5.04.9.2 View file →
@@ -1,8 +1,12 @@
1 1 <?php
2 +namespace WPDeveloper\BetterDocs\Editors\BlockEditor\Blocks;
2 3
3 -namespace WPDeveloper\BetterDocs\Editors\BlockEditor\Blocks;
4 +if ( ! defined( 'ABSPATH' ) ) {
5 + exit;
6 +}
4 7
8 +
5 9 use WPDeveloper\BetterDocs\Editors\BlockEditor\Block;
6 10
7 11 class CodeSnippet extends Block {
8 12
@@ -22,17 +26,23 @@
22 26 * @return array
23 27 */
24 28 public function get_default_attributes() {
25 29 return [
26 - 'blockId' => '',
27 - 'blockMeta' => (object) [],
28 - 'resOption' => 'Desktop',
29 - 'codeContent' => '',
30 - 'language' => 'javascript',
31 - 'showLanguageLabel' => true,
32 - 'showCopyButton' => true,
33 - 'showLineNumbers' => false,
34 - 'theme' => 'light'
30 + 'blockId' => '',
31 + 'blockMeta' => (object) [],
32 + 'resOption' => 'Desktop',
33 + 'codeContent' => '',
34 + 'language' => 'javascript',
35 + 'codeVariants' => [],
36 + 'showLanguageLabel' => true,
37 + 'showCopyButton' => true,
38 + 'showHeader' => true,
39 + 'showLineNumbers' => false,
40 + 'theme' => 'light',
41 + 'fileName' => 'filename.js',
42 + 'showFileIcon' => true,
43 + 'fileIcon' => '',
44 + 'showTrafficLights' => true
35 45 ];
36 46 }
37 47
38 48 /**
@@ -41,8 +51,21 @@
41 51 public function register_scripts() {
42 52 $this->assets_manager->register( 'betterdocs-code-snippet', 'public/css/code-snippet.css' );
43 53 $this->assets_manager->register( 'betterdocs-code-snippet', 'public/js/code-snippet.js', [ 'wp-element' ] );
44 54
55 + // Self-hosted Highlight.js (vendored under assets/static/vendor/highlightjs/,
56 + // same convention as assets/vendor/scalar/). The frontend + editor read
57 + // these URLs off the localized config instead of hitting cdnjs.
58 + $this->assets_manager->localize(
59 + 'betterdocs-code-snippet',
60 + 'BetterDocsCodeSnippetConfig',
61 + [
62 + 'hljsUrl' => $this->assets_manager->asset_url( 'vendor/highlightjs/highlight.min.js' ),
63 + 'cssLight' => $this->assets_manager->asset_url( 'vendor/highlightjs/github.min.css' ),
64 + 'cssDark' => $this->assets_manager->asset_url( 'vendor/highlightjs/github-dark.min.css' )
65 + ]
66 + );
67 +
45 68 // Enqueue CodeMirror for Gutenberg editor
46 69 if ( is_admin() ) {
47 70 add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_editor_assets' ], 5 );
48 71 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_editor_assets' ], 5 );
@@ -75,9 +98,11 @@
75 98 * Check if we're in editor mode
76 99 * @return bool
77 100 */
78 101 public function is_editor_mode() {
79 - return defined( 'REST_REQUEST' ) && REST_REQUEST && ! empty( $_REQUEST['context'] ) && $_REQUEST['context'] === 'edit';
102 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- REST request context check.
103 + $context = isset( $_REQUEST['context'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['context'] ) ) : '';
104 + return defined( 'REST_REQUEST' ) && REST_REQUEST && 'edit' === $context;
80 105 }
81 106
82 107 /**
83 108 * Render the block
@@ -98,11 +123,13 @@
98 123
99 124 return [
100 125 'code_content' => $attributes['codeContent'],
101 126 'language' => $attributes['language'],
127 + // Combined [primary + codeVariants] list the template renders as a
128 + // language dropdown when it holds more than one entry.
129 + 'code_variants' => $this->build_variants( $attributes ),
102 130 'show_language_label' => $attributes['showLanguageLabel'],
103 131 'show_copy_button' => $attributes['showCopyButton'],
104 - 'show_copy_tooltip' => isset( $attributes['showCopyTooltip'] ) ? $attributes['showCopyTooltip'] : false,
105 132 'show_header' => isset( $attributes['showHeader'] ) ? $attributes['showHeader'] : true,
106 133 'show_line_numbers' => $attributes['showLineNumbers'],
107 134 'theme' => $attributes['theme'],
108 135 'block_id' => $attributes['blockId'],
@@ -113,6 +140,48 @@
113 140 'show_traffic_lights' => isset( $attributes['showTrafficLights'] ) ? $attributes['showTrafficLights'] : true,
114 141 'show_file_icon' => isset( $attributes['showFileIcon'] ) ? $attributes['showFileIcon'] : true,
115 142 'file_icon' => isset( $attributes['fileIcon'] ) ? $attributes['fileIcon'] : '',
116 143 ];
144 + }
145 +
146 + /**
147 + * Build the ordered language list: the primary language/code first, then
148 + * each non-empty entry from `codeVariants`. One entry → single-language
149 + * (renders exactly as before); more → language dropdown.
150 + *
151 + * @param array $attributes
152 + * @return array<int, array{language: string, code: string, file_name: string}>
153 + */
154 + protected function build_variants( $attributes ) {
155 + $variants = [];
156 +
157 + $primary_code = isset( $attributes['codeContent'] ) ? (string) $attributes['codeContent'] : '';
158 + if ( '' !== $primary_code ) {
159 + $variants[] = [
160 + 'language' => isset( $attributes['language'] ) ? (string) $attributes['language'] : 'javascript',
161 + 'code' => $primary_code,
162 + 'file_name' => isset( $attributes['fileName'] ) ? (string) $attributes['fileName'] : ''
163 + ];
164 + }
165 +
166 + if ( ! empty( $attributes['codeVariants'] ) && is_array( $attributes['codeVariants'] ) ) {
167 + foreach ( $attributes['codeVariants'] as $variant ) {
168 + if ( ! is_array( $variant ) ) {
169 + continue;
170 + }
171 +
172 + $code = isset( $variant['codeContent'] ) ? (string) $variant['codeContent'] : '';
173 + if ( '' === $code ) {
174 + continue;
175 + }
176 +
177 + $variants[] = [
178 + 'language' => isset( $variant['language'] ) ? (string) $variant['language'] : 'javascript',
179 + 'code' => $code,
180 + 'file_name' => isset( $variant['fileName'] ) ? (string) $variant['fileName'] : ''
181 + ];
182 + }
183 + }
184 +
185 + return $variants;
117 186 }
118 187 }