Skip to content

Commit b9be26d

Browse files
Andrew Bakerclaude
andcommitted
v1.7.18: PCP compliance, security hardening, i18n, uninstall, docblocks
Critical (PCP): - Remove echoed <style> block from admin page; extract inline <script> blocks into enqueued cs-admin-settings.js and cs-sql-editor.js - Replace document.head.appendChild(style) in cs-convert.js with wp_add_inline_style() Security: - Harden is_safe_query(): reject queries containing semicolons - Remove $_REQUEST fallback in SQL AJAX handler (POST only) - Add phpcs:ignore annotations for intentional direct DB queries Standards: - Add uninstall.php to clean up plugin options on deletion - Add load_plugin_textdomain() on init; wrap 48 user-facing strings with esc_html_e() / esc_attr_e() across frontend and admin - Remove console.warn() and console.log() from cs-convert.js - Replace date() with wp_date() in migration scan - Consolidate wp_ajax_cs_save_theme_setting hook into init() - Full DocBlocks on all methods (@SInCE, @param, @return) - Sync block.json version to plugin version Docs: - Add CHANGELOG.md in Keep a Changelog format - Add missing 1.7.16 and 1.7.17 entries to readme.txt changelog Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent 6cabf55 commit b9be26d

9 files changed

Lines changed: 727 additions & 569 deletions

File tree

CHANGELOG.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Changelog
2+
3+
All notable changes to CloudScale Code Block are documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6+
7+
## [Unreleased]
8+
9+
## [1.7.18] - 2026-03-13
10+
11+
### Security
12+
- Hardened `is_safe_query()`: SQL queries containing semicolons are now rejected, preventing statement stacking
13+
- Removed `$_REQUEST` fallback in SQL AJAX handler — only `$_POST` accepted
14+
- Added `phpcs:ignore` annotations with rationale for all intentional `$wpdb` direct-query patterns
15+
16+
### Fixed
17+
- Removed echoed `<style>` block from admin tools page — all styles now served via enqueued `cs-admin-tabs.css`
18+
- Extracted inline `<script>` blocks from settings and SQL panels into enqueued JS files (`cs-admin-settings.js`, `cs-sql-editor.js`)
19+
- Replaced dynamic `document.head.appendChild(style)` injection in block editor with `wp_add_inline_style()`
20+
- Removed `console.warn()` and `console.log()` debug calls from `cs-convert.js`
21+
22+
### Added
23+
- `uninstall.php` — removes `cs_code_default_theme` and `cs_code_theme_pair` options on plugin deletion
24+
- `load_plugin_textdomain()` called on `init`; 48 user-facing strings wrapped with i18n functions across frontend and admin
25+
- Full DocBlocks (`@since`, `@param`, `@return`) on all class methods and class definition
26+
- `@package` and `@since` tags in plugin file header
27+
28+
### Changed
29+
- `wp_ajax_cs_save_theme_setting` hook consolidated into `init()` alongside all other AJAX hooks
30+
- `date()` replaced with `wp_date()` in migration scan to respect site timezone
31+
- `block.json` version synced to plugin version
32+
33+
## [1.7.17]
34+
35+
### Added
36+
- Copy button now shows a "Copy" label alongside the clipboard icon
37+
38+
### Changed
39+
- CSS refactored for copy button styling
40+
41+
## [1.7.16]
42+
43+
### Fixed
44+
- `build_migrate_block()` JSON encoding corrected: removed `JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES` flags that caused `<`, `>`, and quote characters to be stored as literal bytes, corrupting block attributes on subsequent Gutenberg saves
45+
46+
### Changed
47+
- All enqueued assets now use `filemtime()` for cache busting
48+
- Block editor toolbar improvements
49+
50+
## [1.7.15]
51+
52+
### Fixed
53+
- Split `decode_migrated_content()` into two independent passes so the bare-`\n` newline fix always runs regardless of whether unicode escapes were already decoded in the database
54+
55+
## [1.7.14]
56+
57+
### Fixed
58+
- `decode_migrated_content()` in `render_block()` decodes unicode escapes and bare newline separators left by the v1 migration bug, fixing display of affected code blocks without requiring database changes
59+
60+
## [1.7.13]
61+
62+
### Fixed
63+
- Code Block Migrator now uses safe JSON encoding so special characters like `<`, `>`, and quotes are stored as proper unicode escapes in block comment attributes, preventing content corruption on subsequent Gutenberg saves
64+
65+
## [1.7.8]
66+
67+
### Added
68+
- Copy, Paste, and Clear buttons to the block editor toolbar
69+
70+
## [1.7.6]
71+
72+
### Fixed
73+
- White toolbar text for improved contrast
74+
- UNDEFINED language badge no longer displayed
75+
- Powered by CloudScale link added to block toolbar
76+
77+
## [1.7.3]
78+
79+
### Changed
80+
- Admin CSS embedded inline for reliable rendering across all WordPress configurations
81+
- Admin UI restyled to match the CloudScale plugin family: navy gradient banner, dark tab bar with orange active indicator, white card panels with coloured gradient section headers
82+
83+
## [1.7.0]
84+
85+
### Added
86+
- 14 popular syntax colour themes: Atom One, GitHub, Monokai, Nord, Dracula, Tokyo Night, VS 2015/VS Code, Stack Overflow, Night Owl, Gruvbox, Solarized, Panda, Tomorrow Night, Shades of Purple
87+
- Colour Theme selector in the settings panel
88+
- HCL/Terraform and TOML to the language selector
89+
- 14 new SQL quick queries organised into four groups: Health and Diagnostics, Content Summary, Bloat and Cleanup Checks, URL and Migration Helpers
90+
91+
### Changed
92+
- Each theme loads its dark and light variant from the highlight.js CDN
93+
- Toggle button switches between the dark and light variant of the chosen theme
94+
- Frontend CSS refactored to use CSS custom properties for theme-agnostic styling
95+
- Theme backgrounds and toolbar colours adapt automatically to the selected theme
96+
- Enter key now runs the SQL query; Shift+Enter inserts a newline
97+
98+
## [1.6.0]
99+
100+
### Added
101+
- Merged CloudScale SQL Command plugin into CloudScale Code Block
102+
- Combined Tools page at Tools > CloudScale Code and SQL with tabbed interface
103+
- AJAX save for theme settings (no page reload required)
104+
105+
### Removed
106+
- Separate Settings > CloudScale Code Block page
107+
- Separate Tools > CloudScale SQL page
108+
109+
## [1.5.0]
110+
111+
### Added
112+
- Code Block Migrator tool to batch-convert legacy WordPress code blocks
113+
- Auto-convert toast in the block editor for `core/code` and `core/preformatted` blocks
114+
- Transform support from `core/code` and `core/preformatted`
115+
116+
## [1.1.0]
117+
118+
### Fixed
119+
- Block now spans full content width in both editor and frontend
120+
- Dark mode is now the proper default with Atom One Dark syntax colours
121+
- Code no longer wraps; horizontal scroll on overflow
122+
- Editor style properly registered via `block.json` `editorStyle`
123+
124+
### Added
125+
- Alignment support (wide, full) in block toolbar
126+
127+
## [1.0.0]
128+
129+
### Added
130+
- Initial release: Gutenberg block and `[cs_code]` shortcode for syntax-highlighted code
131+
- Auto language detection for 30+ languages via highlight.js
132+
- One-click clipboard copy button
133+
- Dark/light mode toggle per block with site-wide default
134+
- Language badge auto-detection
135+
- Optional line numbers toggle
136+
- Custom title/filename label per block

assets/cs-admin-settings.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* CloudScale Code Block - Admin Settings Save
3+
*
4+
* Handles the AJAX save for the Code Block Settings panel.
5+
* Depends on csAdminSettings (nonce) localised by PHP.
6+
*/
7+
( function() {
8+
'use strict';
9+
10+
var saveBtn = document.getElementById( 'cs-settings-save' );
11+
var selPair = document.getElementById( 'cs-settings-pair' );
12+
var selTheme = document.getElementById( 'cs-settings-theme' );
13+
var savedMsg = document.getElementById( 'cs-settings-saved' );
14+
15+
if ( ! saveBtn ) {
16+
return;
17+
}
18+
19+
saveBtn.addEventListener( 'click', function() {
20+
saveBtn.disabled = true;
21+
saveBtn.textContent = 'Saving...';
22+
23+
var fd = new FormData();
24+
fd.append( 'action', 'cs_save_theme_setting' );
25+
fd.append( 'nonce', csAdminSettings.nonce );
26+
fd.append( 'theme', selTheme.value );
27+
fd.append( 'theme_pair', selPair.value );
28+
29+
fetch( ajaxurl, { method: 'POST', body: fd } )
30+
.then( function( r ) { return r.json(); } )
31+
.then( function( resp ) {
32+
saveBtn.disabled = false;
33+
saveBtn.textContent = '💾 Save Settings';
34+
if ( resp.success ) {
35+
savedMsg.classList.add( 'visible' );
36+
setTimeout( function() {
37+
savedMsg.classList.remove( 'visible' );
38+
}, 2000 );
39+
}
40+
} )
41+
.catch( function() {
42+
saveBtn.disabled = false;
43+
saveBtn.textContent = '💾 Save Settings';
44+
} );
45+
} );
46+
} )();

assets/cs-admin-tabs.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* ============================================================
2-
CloudScale Code and SQL — Admin UI v1.7.1
2+
CloudScale Code and SQL — Admin UI v1.7.17
33
Colour palette mirrors CloudScale Page Views: electric blue,
44
bright green, vivid orange, deep navy, white.
55
============================================================ */

assets/cs-convert.js

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
// Bail if wp.data or wp.blocks aren't available
1212
if ( ! window.wp || ! window.wp.data || ! window.wp.blocks ) {
13-
console.warn( '[CloudScale] wp.data or wp.blocks not available' );
1413
return;
1514
}
1615

@@ -101,52 +100,6 @@
101100
window.__csConvertBlock = convertBlock;
102101
window.__csConvertAll = convertAll;
103102

104-
// =========================================================================
105-
// Inject CSS
106-
// =========================================================================
107-
108-
var css = document.createElement( 'style' );
109-
css.textContent = '' +
110-
'#' + TOAST_ID + ' {' +
111-
'position: fixed;' +
112-
'bottom: 24px;' +
113-
'right: 24px;' +
114-
'z-index: 999999;' +
115-
'background: linear-gradient(135deg, #1e3a5f 0%, #0d9488 100%);' +
116-
'color: #fff;' +
117-
'padding: 16px 20px;' +
118-
'border-radius: 10px;' +
119-
'box-shadow: 0 8px 32px rgba(0,0,0,0.3);' +
120-
'display: flex;' +
121-
'align-items: center;' +
122-
'gap: 16px;' +
123-
'font-size: 14px;' +
124-
'font-weight: 500;' +
125-
'font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;' +
126-
'animation: cs-toast-in 0.3s ease-out;' +
127-
'}' +
128-
'#' + TOAST_ID + ' button {' +
129-
'background: #fff;' +
130-
'color: #1e3a5f;' +
131-
'font-weight: 700;' +
132-
'border-radius: 6px;' +
133-
'padding: 10px 24px;' +
134-
'font-size: 14px;' +
135-
'border: none;' +
136-
'white-space: nowrap;' +
137-
'cursor: pointer;' +
138-
'box-shadow: 0 2px 8px rgba(0,0,0,0.15);' +
139-
'font-family: inherit;' +
140-
'}' +
141-
'#' + TOAST_ID + ' button:hover {' +
142-
'background: #f0fdf4;' +
143-
'}' +
144-
'@keyframes cs-toast-in {' +
145-
'from { opacity: 0; transform: translateY(20px); }' +
146-
'to { opacity: 1; transform: translateY(0); }' +
147-
'}';
148-
document.head.appendChild( css );
149-
150103
// =========================================================================
151104
// Watch for core code blocks and show/hide toast
152105
// =========================================================================
@@ -188,6 +141,4 @@
188141
// Also run once after a short delay to catch initial state
189142
setTimeout( checkBlocks, 1000 );
190143

191-
console.log( '[CloudScale] Auto-convert watcher loaded' );
192-
193144
} )();

assets/cs-sql-editor.js

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/**
2+
* CloudScale Code Block - SQL Editor
3+
*
4+
* Handles the SQL query editor, quick-query buttons, and results table.
5+
* Depends on csSqlEditor (nonce) localised by PHP.
6+
*/
7+
( function() {
8+
'use strict';
9+
10+
var input = document.getElementById( 'cs-sql-input' );
11+
var runBtn = document.getElementById( 'cs-sql-run' );
12+
var clearBtn = document.getElementById( 'cs-sql-clear' );
13+
var results = document.getElementById( 'cs-sql-results' );
14+
var status = document.getElementById( 'cs-sql-status' );
15+
var meta = document.getElementById( 'cs-sql-meta' );
16+
17+
if ( ! input || ! runBtn ) {
18+
return;
19+
}
20+
21+
var nonce = csSqlEditor.nonce;
22+
23+
function escHtml( s ) {
24+
var d = document.createElement( 'div' );
25+
d.textContent = s;
26+
return d.innerHTML;
27+
}
28+
29+
function run() {
30+
var sql = input.value.trim();
31+
if ( ! sql ) {
32+
return;
33+
}
34+
35+
runBtn.disabled = true;
36+
status.textContent = 'Running...';
37+
status.style.color = '#888';
38+
results.innerHTML = '<div style="text-align:center;color:#888;padding:20px">⏳ Executing query...</div>';
39+
meta.textContent = '';
40+
41+
fetch( ajaxurl, {
42+
method: 'POST',
43+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
44+
body: 'action=cs_sql_run&nonce=' + encodeURIComponent( nonce ) + '&sql=' + encodeURIComponent( sql )
45+
} )
46+
.then( function( r ) { return r.json(); } )
47+
.then( function( resp ) {
48+
runBtn.disabled = false;
49+
50+
if ( ! resp.success ) {
51+
status.textContent = '✗ Error';
52+
status.style.color = '#c3372b';
53+
results.innerHTML = '<div style="color:#c3372b;background:#fef0f0;border:1px solid #f5bcbb;padding:12px 14px;border-radius:4px;font-family:monospace;font-size:12px;white-space:pre-wrap">'
54+
+ escHtml( typeof resp.data === 'string' ? resp.data : JSON.stringify( resp.data ) )
55+
+ '</div>';
56+
return;
57+
}
58+
59+
var d = resp.data;
60+
status.textContent = '✓ Success';
61+
status.style.color = '#1a7a34';
62+
meta.textContent = d.count + ' row' + ( d.count !== 1 ? 's' : '' ) + ' in ' + d.elapsed + 'ms';
63+
64+
if ( ! d.rows || d.rows.length === 0 ) {
65+
results.innerHTML = '<div style="text-align:center;color:#999;padding:20px">Query returned 0 rows</div>';
66+
return;
67+
}
68+
69+
var cols = Object.keys( d.rows[ 0 ] );
70+
var html = '<table class="cs-sql-table"><thead><tr>';
71+
cols.forEach( function( c ) {
72+
html += '<th>' + escHtml( c ) + '</th>';
73+
} );
74+
html += '</tr></thead><tbody>';
75+
76+
d.rows.forEach( function( row ) {
77+
html += '<tr>';
78+
cols.forEach( function( c ) {
79+
var val = row[ c ];
80+
if ( val === null ) {
81+
val = '<span style="color:#999;font-style:italic">NULL</span>';
82+
} else {
83+
val = escHtml( String( val ) );
84+
val = val.replace(
85+
/(http:\/\/[^\s&lt;,;'"]+)/g,
86+
'<span style="background:#fef0f0;color:#c3372b;padding:1px 3px;border-radius:2px">$1</span>'
87+
);
88+
}
89+
html += '<td>' + val + '</td>';
90+
} );
91+
html += '</tr>';
92+
} );
93+
94+
html += '</tbody></table>';
95+
results.innerHTML = html;
96+
} )
97+
.catch( function( e ) {
98+
runBtn.disabled = false;
99+
status.textContent = '✗ Network error';
100+
status.style.color = '#c3372b';
101+
results.innerHTML = '<div style="color:#c3372b;padding:12px">' + escHtml( e.message ) + '</div>';
102+
} );
103+
}
104+
105+
runBtn.addEventListener( 'click', run );
106+
107+
clearBtn.addEventListener( 'click', function() {
108+
input.value = '';
109+
results.innerHTML = '<div style="text-align:center;color:#999;padding:40px 0">Run a query to see results here</div>';
110+
status.textContent = '';
111+
meta.textContent = '';
112+
input.focus();
113+
} );
114+
115+
// Enter (plain) or Ctrl+Enter both run the query; Shift+Enter inserts a newline
116+
input.addEventListener( 'keydown', function( e ) {
117+
if ( e.key === 'Enter' && ! e.shiftKey ) {
118+
e.preventDefault();
119+
run();
120+
}
121+
} );
122+
123+
document.querySelectorAll( '.cs-sql-quick' ).forEach( function( btn ) {
124+
btn.addEventListener( 'click', function() {
125+
input.value = this.getAttribute( 'data-sql' );
126+
run();
127+
} );
128+
} );
129+
} )();

blocks/code/block.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"$schema": "https://schemas.wp.org/trunk/block.json",
33
"apiVersion": 3,
44
"name": "cloudscale/code-block",
5-
"version": "1.7.0",
5+
"version": "1.7.18",
66
"title": "CloudScale Code Block",
77
"category": "formatting",
88
"icon": "editor-code",

0 commit comments

Comments
 (0)