first commit

This commit is contained in:
2026-03-05 13:07:40 +01:00
commit 64ba0721ee
25709 changed files with 4691006 additions and 0 deletions

View File

@@ -0,0 +1,570 @@
<?php
/**
* Plugin Name: HTML Editor Syntax Highlighter
* Description: Add syntax highlighting to the all WordPress code editors using Codemirror.js
* Author: James Bradford
* Author URI: http://bradford.digital/
* Author: Petr Mukhortov
* Author URI: http://mukhortov.com/
* Version: 2.4.4
*
* @package HESH_plugin
**/
// Check for required PHP version
if ( version_compare( PHP_VERSION, '5.2.17', '<' ) ) {
exit( sprintf( 'Foo requires PHP 5.2.17 or higher. Youre still on %s.', PHP_VERSION ) );
}
if ( preg_match( '#' . basename(__FILE__) . '#', $_SERVER['PHP_SELF'] ) ) {
die('You are not allowed to call this page directly.');
}
define( 'HESH_LIBS', plugins_url( '/', __FILE__ ) );
class Wp_Html_Editor_Syntax_Highlighter {
public function __construct () {
add_action( 'admin_init', array(&$this, 'hesh_set_options') );
add_action( 'wp_ajax_'.$this->formProcessName, array(&$this, 'hesh_options_form_process'));
// Load only on certain pages
if (
!strstr($_SERVER['SCRIPT_NAME'], 'post.php') &&
!strstr($_SERVER['SCRIPT_NAME'], 'post-new.php') &&
!strstr($_SERVER['SCRIPT_NAME'], 'editor.php')
) return;
add_action( 'admin_enqueue_scripts', array(&$this, 'hesh_admin_enqueue_scripts' ) );
add_action( 'admin_footer', array(&$this, 'hesh_output_form') );
// add_action( 'admin_notices', array(&$this, 'display_survey_notice' ));
}
// Enqueued scripts and styles for hesh.js
public function hesh_admin_enqueue_scripts () {
// get the plugin version number for cache busting purposes
$plugData = get_plugin_data( __FILE__ ); // need this temporary var to support versions of php < 5.4
$ver = $plugData['Version'];
// load minified version if not a localhost dev account
// $min = strpos(home_url(), 'localhost') ? '' : '.min' ; // no more...
wp_enqueue_script( 'jquery');
// dequeue the native WP code-editor and codemirror
if (wp_script_is( 'code-editor', 'enqueued' )) wp_dequeue_script( 'code-editor' );
if (wp_style_is( 'code-editor', 'enqueued' )) wp_dequeue_style( 'code-editor' );
// if (wp_script_is( 'wp-codemirror', 'enqueued' )) wp_dequeue_script( 'wp-codemirror' );
// if (wp_style_is( 'wp-codemirror', 'enqueued' )) wp_dequeue_style( 'wp-codemirror' );
// enqueue hesh scripts
wp_enqueue_script( 'heshJs', HESH_LIBS.'hesh.js', array('jquery', 'editor'), $ver, true );
wp_enqueue_style( 'heshCss', HESH_LIBS.'hesh.css', false, $ver );
// this shows up in js as window.heshOptions
$heshOptions = array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
// 'nonce' => wp_create_nonce( $this->formProcessName ) // TODO: use this instead of the hidden field?
);
// place all the userPreferences into the heshOptions object
foreach ($this->userPreferences as $id => $value) {
$heshOptions[$id] = $value['current'];
// error_log( $id . ': ' . $heshOptions[$id] . ' type: ' . gettype($heshOptions[$id]) ); // for debug
}
wp_localize_script(
'heshJs', // for hesh.js
'heshOptions', // the object name, shows up in js as window.heshOptions
$heshOptions // the php object to translate to js
);
}
private $surveyLink = 'https://goo.gl/forms/xvaHgd7sZEbBbFAL2';
private $formProcessName = 'hesh_options_form';
private $nonceSecretCode = 'secret-code';
private $prefix = 'hesh_';
private $userPreferences = array(); // added to the primary bar
public function hesh_set_options() {
$this->userPreferences = array(
// HIDDEN OPTIONS // added in the primary settings bar
'surveyNoticeDismissedB' => array(
'title' => 'UX Survey Notice Dismissed',
'type' => 'hidden',
// 'current' => false, // reset for debug
'current' => get_user_meta( get_current_user_id(), $this->prefix.'surveyNoticeDismissedB' , true),
'default' => false,
'set' => 'hidden',
),
// PRIMARY OPTIONS // added in the primary settings bar
'theme' => array(
'title' => 'Theme',
'type' => 'select',
'options' => $this->cssThemes,
'current' => get_user_meta( get_current_user_id(), $this->prefix.'theme' , true),
'default' => 'wordpress',
'set' => 'primary',
),
'tabSize' => array(
'title' => 'Indent',
'type' => 'select',
'options' => range(1,6),
'current' => get_user_meta( get_current_user_id(), $this->prefix.'tabSize' , true),
'default' => 4,
'set' => 'primary',
),
'lineWrapping'=> array(
'title' => 'Line Wrap',
'type' => 'checkbox',
'current' => get_user_meta( get_current_user_id(), $this->prefix.'lineWrapping' , true),
'default' => true,
'set' => 'primary',
),
'lineNumbers'=> array(
'title' => 'Numbering',
'type' => 'checkbox',
'current' => get_user_meta( get_current_user_id(), $this->prefix.'lineNumbers' , true),
'default' => true,
'set' => 'primary',
),
'fontSize'=> array(
'title' => 'Font Size',
'type' => 'select',
'options' => range(8,20),
'current' => get_user_meta( get_current_user_id(), $this->prefix.'fontSize' , true),
'default' => 13,
'set' => 'primary',
),
'lineHeight'=> array(
'title' => 'Line Height',
'type' => 'select',
'options' => range(1,2,0.25),
'current' => get_user_meta( get_current_user_id(), $this->prefix.'lineHeight' , true),
'default' => 1.5,
'set' => 'primary',
),
// ADVANCED OPTIONS // added to the advanced dropdown
'matchBrackets'=> array(
'title' => 'Match Brackets',
'type' => 'checkbox',
'current' => get_user_meta( get_current_user_id(), $this->prefix.'matchBrackets' , true),
'default' => false,
'set' => 'advanced',
'description' => 'highlight matching bracket pairs next to cursor',
),
'matchTags'=> array(
'title' => 'Match Tags',
'type' => 'checkbox',
'current' => get_user_meta( get_current_user_id(), $this->prefix.'matchTags' , true),
'default' => false,
'set' => 'advanced',
'description' => 'highlight matching html tag pairs (not shortcodes)',
),
'highlightSelectionMatches'=> array(
'title' => 'Highlight Selection Matches',
'type' => 'checkbox',
'current' => get_user_meta( get_current_user_id(), $this->prefix.'highlightSelectionMatches' , true),
'default' => false,
'set' => 'advanced',
'description' => 'highlight all instances of a currently selected word',
),
'autoCloseTags'=> array(
'title' => 'Auto Close Tags',
'type' => 'checkbox',
'current' => get_user_meta( get_current_user_id(), $this->prefix.'autoCloseTags' , true),
'default' => false,
'set' => 'advanced',
'description' => 'auto-close HTML tags when <code>></code> or <code>/</code> is typed',
),
'autoCloseBrackets'=> array(
'title' => 'Auto Close Brackets',
'type' => 'checkbox',
'current' => get_user_meta( get_current_user_id(), $this->prefix.'autoCloseBrackets' , true),
'default' => false,
'set' => 'advanced',
'description' => 'auto-close brackets and quotes when typed',
),
'foldGutter'=> array(
'title' => 'Code Folding',
'type' => 'checkbox',
'current' => get_user_meta( get_current_user_id(), $this->prefix.'foldGutter' , true),
'default' => false,
'set' => 'advanced',
// 'description' => 'fold HTML code (not shortcodes)',
),
'scrollbarStyle'=> array(
'title' => 'Show Scrollbars',
'type' => 'checkbox',
'current' => get_user_meta( get_current_user_id(), $this->prefix.'scrollbarStyle' , true),
'default' => false,
'set' => 'advanced',
),
'keyMap'=> array(
'title' => 'Key Mapping',
'type' => 'radio',
'options' => array('default', 'sublime', 'vim', 'emacs'),
'current' => get_user_meta( get_current_user_id(), $this->prefix.'keyMap' , true),
'default' => 'default',
'set' => 'advanced',
),
);
// Initialize all the hesh option fields as default if they don't exist yet
foreach ($this->userPreferences as $id => $value) {
if (!isset($value['current']) || trim($value['current'])==='')
update_user_meta( get_current_user_id(), $this->prefix.$id, $value['default']);
// error_log( $id . ': ' . $value['current'] . ': ' . isset($value['current']) ); // for debug
}
}
public function hesh_options_form_process() {
if (empty($_POST) || !wp_verify_nonce($_POST[$this->nonceSecretCode], $this->formProcessName)) {
error_log('The nonce did not verify.');
wp_die();
} else {
foreach ($this->userPreferences as $id => $value) {
$setting = $_POST[$id];
if ($setting === 'true') $setting = true;
if ($setting === 'false') $setting = false;
if (is_numeric($setting)) $setting = floatval($setting);
// error_log( $id . ': ' . $setting . ' type: ' . gettype($setting) ); // for debug
update_user_meta( get_current_user_id(), $this->prefix.$id, $setting);
}
}
}
private function hesh_output_option($id, $config) {
switch ($config['type']){
case 'select':
$this->hesh_output_primary_select($id, $config);
break;
case 'checkbox':
$this->hesh_output_primary_toggle($id, $config);
break;
}
}
private function hesh_output_primary_toggle($id, $config) {
extract($config);
?>
<label
class="CodeMirror-settings__button button button-small"
for="<?php echo $id; ?>"
>
<?php echo $title; ?>
<input type="hidden" value="false" name="<?php echo $id; ?>" />
<input
name="<?php echo $id; ?>"
id="<?php echo $id; ?>"
type="checkbox"
value="true"
class="CodeMirror-settings__option"
<?php if ($current) echo 'checked'; ?>
/>
</label>
<?php
}
private function hesh_output_primary_select($id, $config) {
extract($config);
?>
<label
class="CodeMirror-settings__button CodeMirror-settings__button--select button button-small"
for="<?php echo $id; ?>"
>
<?php echo $title; ?>
<select
id="<?php echo $id; ?>"
name="<?php echo $id; ?>"
class="CodeMirror-settings__option"
>
<?php foreach ($options as $option): ?>
<option
value="<?php echo $option; ?>"
<?php if ($current == $option) echo 'selected';?>
>
<?php echo ucfirst($option); ?>
</option>
<?php endforeach; ?>
</select>
</label>
<?php
}
private function hesh_output_fieldset($title=false) {
if ($title): ?>
<tr>
<th scope="row">
<?php echo $title; ?>
</th>
<td><fieldset>
<?php else: ?>
</fieldset></td>
</tr>
<?php endif;
}
private function hesh_output_checkbox($id, $config) {
extract($config);
?>
<label
for="<?php echo $id; ?>"
>
<input type="hidden" value="false" name="<?php echo $id; ?>" />
<input
name="<?php echo $id; ?>"
id="<?php echo $id; ?>"
type="checkbox"
value="true"
class="CodeMirror-settings__option"
<?php if ($current) echo 'checked'; ?>
/>
<?php echo $title; ?>
<?php if (isset($description)): ?>
<small
class="description CodeMirror-settings-advanced__description"
id="<?php echo $id; ?>-description"
>
<?php echo $description; ?>
</small>
<?php endif; ?>
</label>
<br/>
<?php
}
private function hesh_output_radio($id, $config) {
extract($config);
$this->hesh_output_fieldset('Key Bindings');
foreach ($options as $option):
?>
<label>
<input
type="radio"
id="<?php echo $id; ?>"
name="<?php echo $id; ?>"
value="<?php echo $option; ?>"
class="CodeMirror-settings__option"
<?php if ($current == $option) echo 'checked'; ?>
/>
<span>
<?php echo ucfirst($option); ?>
</span>
</label><br/>
<?php
endforeach;
$this->hesh_output_fieldset();
}
private function hesh_output_hidden($id, $config) {
extract($config);
?>
<input
type="hidden"
id="<?php echo $id; ?>"
name="<?php echo $id; ?>"
value="<?php echo $current; ?>"
class="CodeMirror-settings__option"
/>
<?php
}
public function hesh_output_form() {
// ob_start();
?>
<div class="CodeMirror-settings closed" id="CodeMirror-settings" style="display:none;">
<form
action="<?php echo admin_url('admin-ajax.php');?>"
method="post"
class="CodeMirror-settings__wrapper"
id="CodeMirror-settings__form"
>
<header class="CodeMirror-settings__header CodeMirror-settings__docked">
<?php
foreach ($this->userPreferences as $id => $value) {
if ( $value['set'] === 'primary' )
$this->hesh_output_option($id,$value);
if ( $value['set'] === 'hidden' )
$this->hesh_output_hidden($id,$value);
}
?>
<a
class="CodeMirror-settings__toggle-advanced"
id="CodeMirror-settings__toggle-advanced"
></a>
</header>
<div class="form CodeMirror-settings__body">
<?php wp_nonce_field($this->formProcessName,$this->nonceSecretCode);?>
<input name="action" value="hesh_options_form" type="hidden">
<table class="form-table"><tbody>
<tr><td class="CodeMirror-settings__heading" colspan="2">
<h1>
Advanced Options
</h1>
<?php /*
<!-- <small>These features are experimental and may have bugs</small> -->
<!-- <small>
<strong>HELP!</strong>
Please consider taking a short <a href="<?php echo $this->surveyLink; ?>" target="_blank" >User Experience Survey</a>
to provide feedback that will help shape the new version 3.0 of this plugin.
</small> -->
*/ ?>
</td></tr>
<?php
$this->hesh_output_fieldset('Highlighting');
$this->hesh_output_checkbox('matchBrackets',$this->userPreferences['matchBrackets']);
$this->hesh_output_checkbox('matchTags',$this->userPreferences['matchTags']);
$this->hesh_output_checkbox('highlightSelectionMatches',$this->userPreferences['highlightSelectionMatches']);
$this->hesh_output_fieldset();
$this->hesh_output_fieldset('Auto Completion');
$this->hesh_output_checkbox('autoCloseTags',$this->userPreferences['autoCloseTags']);
$this->hesh_output_checkbox('autoCloseBrackets',$this->userPreferences['autoCloseBrackets']);
$this->hesh_output_fieldset();
$this->hesh_output_fieldset('Editor Tools');
$this->hesh_output_checkbox('foldGutter',$this->userPreferences['foldGutter']);
$this->hesh_output_checkbox('scrollbarStyle',$this->userPreferences['scrollbarStyle']);
$this->hesh_output_fieldset();
$this->hesh_output_radio('keyMap',$this->userPreferences['keyMap']);
?>
</tbody></table>
</div>
<footer class="CodeMirror-settings__footer CodeMirror-settings__docked">
<p class="CodeMirror-settings__foot-content CodeMirror-settings__feedback">
<small>
<?php /* Provide a href="<?php echo $this->surveyLink; ?>" target="_blank" >feedback</a>, */ ?>
Leave a
<a href="https://wordpress.org/support/plugin/html-editor-syntax-highlighter/reviews/#new-post" target="_blank">review</a>,
fork on
<a href="https://github.com/mukhortov/HESH-WordPress-Plugin/" target="_blank">Github</a>,
or submit a
<a href="https://github.com/mukhortov/HESH-WordPress-Plugin/issues/new" target="_blank">bug report or enhancement request</a>.
</small>
</p>
<p class="CodeMirror-settings__foot-content CodeMirror-settings__credits">
<small>
Created by
<a href="http://www.bradford.digital" target="_blank">James Bradford</a>
&amp;
<a href="http://www.mukhortov.com/" target="_blank">Petr Mukhortov</a>.
</small>
</p>
</footer>
</form>
<div class="CodeMirror-settings__toggle" id="CodeMirror-settings__toggle"></div>
</div>
<?php
// return ob_get_clean();
}
/* // not currently being used
public function display_survey_notice() {
if ( $this->userPreferences['surveyNoticeDismissedB']['current'] ) return;
// https://codex.wordpress.org/Plugin_API/Action_Reference/admin_notices
?>
<div class="notice notice-info is-dismissible notice-hesh">
<p>
<strong style="font-size:1.5em;">Please Take A Short Syntax Highlighter UX Survey</strong>
<br/>
A new version of the HTML Editor Syntax Highlighter Is Coming!
Please take this 5 minute user experience survey, and share your opinion to help shape new features in the v3.0 update.
A survey link is also available in the <em>Advanced Options</em>.
<br/><br/>
<a href="<?php echo $this->surveyLink; ?>" target="_blank" class="button button-primary">Take the UX Survey</a>
</p>
</div>
<?php
} */
// to get a list of theme names: `cd node_modules/codemirror/theme/` then run `ls > css-themes.txt`
private $cssThemes = array(
'none', // special
'wordpress', // custom
'default', // special
// node_modules/codemirror/theme/
'3024-day', // SUCKS
'3024-night', //??
'abbott',
'abcdef',
'ambiance-mobile',// BROKEN
'ambiance',
'ayu-dark',
'ayu-mirage',
'base16-dark',
'base16-light',
'bespin',
'blackboard',
'cobalt',
'codepen', // custom
'colorforth',
'darcula',
'dracula',
'duotone-dark',
'duotone-light',
'eclipse',
'elegant',
'erlang-dark',
'gruvbox-dark',
'github', // from npm
'hopscotch',
'icecoder',
'idea',
'isotope',
'juejin',
'lesser-dark',
'liquibyte',
'lucario',
'material-darker',
'material-ocean',
'material-palenight',
'material',
'mbo',
'mdn-like',
'midnight',
'monokai',
'moxer',
'neat', // SUCKS
'neo',
'night',
'nord',
'oceanic-next',
'panda-syntax',
'paraiso-dark',
'paraiso-light',
'pastel-on-dark',
'railscasts',
'rubyblue',
'seti',
'shadowfox',
'solarized',
'ssms', // SUCKS
'the-matrix',
'tomorrow-night-bright',
'tomorrow-night-eighties',
'ttcn',
'twilight',
'vibrant-ink',
'xq-dark',
'xq-light', // SUCKS, that yellow...
'yeti',
'yonce',
'zenburn'
);
}
if ( is_admin() ) {
$hesh = new Wp_Html_Editor_Syntax_Highlighter();
}
?>