initial commit

This commit is contained in:
Nikita 2023-06-02 17:29:56 +03:00
commit 1fc59be401
38 changed files with 31653 additions and 0 deletions

13
.editorconfig Normal file
View file

@ -0,0 +1,13 @@
# editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab
[*.md]
trim_trailing_whitespace = false

3
.eslintrc.js Normal file
View file

@ -0,0 +1,3 @@
module.exports = {
extends: [ 'plugin:@wordpress/eslint-plugin/recommended' ],
};

13
.gitattributes vendored Normal file
View file

@ -0,0 +1,13 @@
# Enforce Unix newlines
*.css text eol=lf
*.html text eol=lf
*.js text eol=lf
*.jsx text eol=lf
*.json text eol=lf
*.md text eol=lf
*.php text eol=lf
*.rb text eol=lf
*.scss text eol=lf
*.svg text eol=lf
*.txt text eol=lf
*.yml text eol=lf

40
.gitignore vendored Normal file
View file

@ -0,0 +1,40 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Coverage directory used by tools like istanbul
coverage
# Assets dev files
*.hot-update.*
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Composer directories
vendor/
# Custom PHPCS configs
.phpcs.xml
phpcs.xml
# Dependency directories
node_modules/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Output of `npm pack`
*.tgz
# Output of `wp-scripts plugin-zip`
*.zip
# dotenv environment variables file
.env

8
.prettierignore Normal file
View file

@ -0,0 +1,8 @@
**/*.css
**/*.scss
**/*.php
node_modules
dist
build
vendor
vendors

3
.prettierrc.js Normal file
View file

@ -0,0 +1,3 @@
// Import the default config file and expose it in the project root.
// Useful for editor integrations.
module.exports = require("@wordpress/prettier-config");

9
.stylelintignore Normal file
View file

@ -0,0 +1,9 @@
**/*.js
**/*.jsx
**/*.min.css
**/*.build.css
node_modules
dist
build
vendor
vendors

25
.stylelintrc.js Normal file
View file

@ -0,0 +1,25 @@
module.exports = {
extends: '@wordpress/stylelint-config/scss',
rules: {
'at-rule-empty-line-before': null,
'at-rule-no-unknown': null,
'comment-empty-line-before': null,
'font-weight-notation': null,
'max-line-length': null,
'no-descending-specificity': null,
'rule-empty-line-before': null,
'selector-class-pattern': null,
'value-keyword-case': null,
'scss/operator-no-unspaced': null,
'scss/selector-no-redundant-nesting-selector': null,
'scss/at-import-partial-extension': null,
'scss/no-global-function-names': null,
'scss/comment-no-empty': null,
'scss/at-extend-no-missing-placeholder': null,
'scss/operator-no-newline-after': null,
'scss/at-if-closing-brace-newline-after': null,
'scss/at-else-empty-line-before': null,
'scss/at-if-closing-brace-space-after': null,
'no-invalid-position-at-import-rule': null,
},
};

10
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,10 @@
{
"recommendations": [
"esbenp.prettier-vscode",
"streetsidesoftware.code-spell-checker",
"editorconfig.editorconfig",
"dbaeumer.vscode-eslint",
"stylelint.vscode-stylelint",
"bmewburn.vscode-intelephense-client"
]
}

30
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,30 @@
{
"editor.defaultFormatter": null,
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[php]": {
"editor.defaultFormatter": null,
"editor.formatOnSave": false
},
"editor.formatOnSave": true,
"scss.validate": false,
"css.validate": false,
"less.validate": false,
"editor.codeActionsOnSave": {
"source.fixAll.stylelint": true
},
"stylelint.validate": [
"css",
"scss"
],
"stylelint.snippet": [
"css",
"scss"
],
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}

View file

@ -0,0 +1,14 @@
<svg width="66" height="66" viewBox="0 0 66 66" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M34.2308 6C34.2308 6 30.4843 18.0769 25 23.5385C19.4023 29.1129 7 32.7692 7 32.7692C7 32.7692 19.414 36.414 25 42C30.586 47.586 34.2308 60 34.2308 60C34.2308 60 37.5375 47.5948 43 42C48.5188 36.3475 61 32.7692 61 32.7692C61 32.7692 48.5288 29.1812 43 23.5385C37.6408 18.0687 34.2308 6 34.2308 6ZM34.1026 21C34.1026 21 31.4375 25.5726 29 28C26.5122 30.4775 22 32.8974 22 32.8974C22 32.8974 26.5173 35.0173 29 37.5C31.4827 39.9827 34.1026 45 34.1026 45C34.1026 45 36.5722 39.9866 39 37.5C41.4528 34.9878 46 32.8974 46 32.8974C46 32.8974 41.4572 30.5079 39 28C36.6181 25.569 34.1026 21 34.1026 21Z"
fill="currentColor" />
<path
d="M50.6667 53.5214C52.3932 51.802 53.5726 48 53.5726 48C53.5726 48 54.6462 51.7994 56.3333 53.5214C58.0739 55.2978 62 56.4274 62 56.4274C62 56.4274 58.0707 57.5538 56.3333 59.3333C54.6137 61.0947 53.5726 65 53.5726 65C53.5726 65 52.4252 61.0919 50.6667 59.3333C48.9081 57.5748 45 56.4274 45 56.4274C45 56.4274 48.9044 55.2763 50.6667 53.5214Z"
fill="currentColor" />
<path
d="M8.66667 46.5726C9.78384 45.4601 10.547 43 10.547 43C10.547 43 11.2416 45.4584 12.3333 46.5726C13.4596 47.7221 16 48.453 16 48.453C16 48.453 13.4575 49.1819 12.3333 50.3333C11.2206 51.473 10.547 54 10.547 54C10.547 54 9.80457 51.4712 8.66667 50.3333C7.52877 49.1954 5 48.453 5 48.453C5 48.453 7.5264 47.7082 8.66667 46.5726Z"
fill="currentColor" />
<path
d="M51.3333 5.22222C52.6536 3.9074 53.5556 1 53.5556 1C53.5556 1 54.3765 3.90543 55.6667 5.22222C56.9977 6.58066 60 7.44444 60 7.44444C60 7.44444 56.9953 8.30588 55.6667 9.66667C54.3516 11.0136 53.5556 14 53.5556 14C53.5556 14 52.6781 11.0115 51.3333 9.66667C49.9885 8.32188 47 7.44444 47 7.44444C47 7.44444 49.9858 6.56421 51.3333 5.22222Z"
fill="currentColor" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

1
build/index.asset.php Normal file
View file

@ -0,0 +1 @@
<?php return array('dependencies' => array('lodash', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-data', 'wp-dom-ready', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-react-refresh-runtime'), 'version' => '7a7febaf218bcb4733d0');

12744
build/index.js Normal file

File diff suppressed because one or more lines are too long

1
build/index.js.map Normal file

File diff suppressed because one or more lines are too long

57
build/style-index.css Normal file
View file

@ -0,0 +1,57 @@
/*!***************************************************************************************************************************************************************************************************************************************!*\
!*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/style.scss ***!
\***************************************************************************************************************************************************************************************************************************************/
.mind-toolbar-icon {
color: #e455df;
width: 20px;
height: 20px;
}
.mind-toolbar-dropdown-wrapper {
width: 100%;
}
.mind-toolbar-dropdown-wrapper button {
width: 100%;
padding-left: 8px;
padding-right: 8px;
}
.mind-toolbar-dropdown-wrapper button .dashicon {
margin-left: auto;
}
.mind-editor-toolbar-toggle {
flex: 100%;
white-space: nowrap;
}
.mind-editor-toolbar-toggle button {
color: #e455df;
}
.mind-editor-toolbar-toggle button:hover, .mind-editor-toolbar-toggle button:focus {
color: #e455df;
background: rgba(228, 85, 223, 0.05);
}
.mind-editor-toolbar-toggle svg {
margin-top: -2px;
margin-right: 6px;
margin-bottom: -2px;
}
.mind-popup {
width: 800px;
margin-top: 100px;
background-color: rgb(243, 243, 243);
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.2), 0 25px 70px 10px rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.4);
}
.mind-popup .components-modal__header {
padding: 24px 20px 12px;
}
.mind-popup .components-modal__content {
padding: 0 20px 20px;
}
.mind-popup-overlay {
background-color: rgba(143, 135, 143, 0.25);
}
/*# sourceMappingURL=style-index.css.map*/

View file

@ -0,0 +1 @@
{"version":3,"file":"./style-index.css","mappings":";;;AAGA;EACC,cAJO;EAKP;EACA;AAFD;;AAKA;EACC;AAFD;AAIC;EACC;EACA;EACA;AAFF;AAIE;EACC;AAFH;;AAQA;EACC;EACA;AALD;AAOC;EACC,cA7BM;AAwBR;AAOE;EAEC,cAjCK;EAkCL;AANH;AAUC;EACC;EACA;EACA;AARF;;AAaA;EACC;EACA;EACA;EACA;EACA;AAVD;AAYC;EACC;AAVF;AAYC;EACC;AAVF;;AAaA;EACC;AAVD,C","sources":["webpack://mind/./src/style.scss"],"sourcesContent":["$color: #e455df;\n$popup_padding: 20px;\n\n.mind-toolbar-icon {\n\tcolor: $color;\n\twidth: 20px;\n\theight: 20px;\n}\n\n.mind-toolbar-dropdown-wrapper {\n\twidth: 100%;\n\n\tbutton {\n\t\twidth: 100%;\n\t\tpadding-left: 8px;\n\t\tpadding-right: 8px;\n\n\t\t.dashicon {\n\t\t\tmargin-left: auto;\n\t\t}\n\t}\n}\n\n// Button in editor Toolbar.\n.mind-editor-toolbar-toggle {\n\tflex: 100%;\n\twhite-space: nowrap;\n\n\tbutton {\n\t\tcolor: $color;\n\n\t\t&:hover,\n\t\t&:focus {\n\t\t\tcolor: $color;\n\t\t\tbackground: rgba($color, 5%);\n\t\t}\n\t}\n\n\tsvg {\n\t\tmargin-top: -2px;\n\t\tmargin-right: 6px;\n\t\tmargin-bottom: -2px;\n\t}\n}\n\n// Popup.\n.mind-popup {\n\twidth: 800px;\n\tmargin-top: 100px;\n\tbackground-color: rgb(243, 243, 243);\n\tbox-shadow: 0 0 2px 0 rgba(0, 0, 0, 20%), 0 25px 70px 10px rgba(0, 0, 0, 25%);\n\tborder: 1px solid rgba(255, 255, 255, 40%);\n\n\t.components-modal__header {\n\t\tpadding: 24px $popup_padding 12px;\n\t}\n\t.components-modal__content {\n\t\tpadding: 0 $popup_padding $popup_padding;\n\t}\n}\n.mind-popup-overlay {\n\tbackground-color: rgba(143, 135, 143, 25%);\n}\n"],"names":[],"sourceRoot":""}

46
classes/class-admin.php Normal file
View file

@ -0,0 +1,46 @@
<?php
/**
* Plugin admin functions.
*
* @package mind
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Mind Admin class.
*/
class Mind_Admin {
/**
* Mind_Admin constructor.
*/
public function __construct() {
add_action( 'admin_menu', array( $this, 'register_admin_menu' ), 20 );
}
/**
* Register admin menu.
*
* Add new Mind Settings admin menu.
*/
public function register_admin_menu() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
add_menu_page(
esc_html__( 'Mind', 'mind' ),
esc_html__( 'Mind', 'mind' ),
'manage_options',
'mind',
array( 'Mind_Settings', 'print_settings_page' ),
// phpcs:ignore
'data:image/svg+xml;base64,' . base64_encode( file_get_contents( mind()->plugin_path . 'assets/images/admin-icon.svg' ) ),
'58.7'
);
}
}
new Mind_Admin();

67
classes/class-assets.php Normal file
View file

@ -0,0 +1,67 @@
<?php
/**
* Plugin assets functions.
*
* @package mind
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Mind Assets class.
*/
class Mind_Assets {
/**
* Mind_Assets constructor.
*/
public function __construct() {
add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor_assets' ) );
}
/**
* Loads the asset file for the given script or style.
* Returns a default if the asset file is not found.
*
* @param string $filepath The name of the file without the extension.
*
* @return array The asset file contents.
*/
public function get_asset_file( $filepath ) {
$asset_path = mind()->plugin_path . $filepath . '.asset.php';
if ( file_exists( $asset_path ) ) {
return include $asset_path;
}
return array(
'dependencies' => array(),
'version' => MIND_VERSION,
);
}
/**
* Enqueue editor assets
*/
public function enqueue_block_editor_assets() {
$asset_data = $this->get_asset_file( 'build/index' );
wp_enqueue_script(
'mind-editor',
mind()->plugin_url . 'build/index.js',
$asset_data['dependencies'],
$asset_data['version'],
true
);
wp_enqueue_style(
'mind-editor',
mind()->plugin_url . 'build/style-index.css',
array(),
$asset_data['version']
);
}
}
new Mind_Assets();

210
classes/class-settings.php Normal file
View file

@ -0,0 +1,210 @@
<?php
/**
* Plugin Settings
*
* @package mind
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
require_once mind()->plugin_path . 'vendors/class-settings-api.php';
/**
* Mind Settings Class
*/
class Mind_Settings {
/**
* Settings API instance
*
* @var object
*/
public static $settings_api;
/**
* Cached settings fields. We call settings fields method a lot of times to get default values.
* So, for performance reasons we need to cache the output.
*
* @var object
*/
public static $cached_settings_fields;
/**
* Mind_Settings constructor.
*/
public function __construct() {
self::init_actions();
}
/**
* Get Option Value
*
* @param string $option - option name.
* @param string $section - section name.
* @param string $deprecated_default - default option value.
*
* @return bool|string
*/
public static function get_option( $option, $section, $deprecated_default = '' ) {
$options = get_option( $section );
$result = '';
if ( isset( $options[ $option ] ) ) {
$result = $options[ $option ];
} else {
// find default.
$fields = self::get_settings_fields();
if ( isset( $fields[ $section ] ) && is_array( $fields[ $section ] ) ) {
foreach ( $fields[ $section ] as $field_data ) {
if ( $option === $field_data['name'] && isset( $field_data['default'] ) ) {
$result = $field_data['default'];
}
}
}
}
return 'off' === $result ? false : ( 'on' === $result ? true : $result );
}
/**
* Update Option Value
*
* @param string $option - option name.
* @param string $section - section name.
* @param string $value - new option value.
*/
public static function update_option( $option, $section, $value ) {
$options = get_option( $section );
if ( ! is_array( $options ) ) {
$options = array();
}
$options[ $option ] = $value;
update_option( $section, $options );
}
/**
* Init actions
*/
public static function init_actions() {
self::$settings_api = new Mind_Settings_API();
add_action( 'admin_init', array( __CLASS__, 'admin_init' ) );
}
/**
* Initialize the settings
*
* @return void
*/
public static function admin_init() {
// set the settings.
self::$settings_api->set_sections( self::get_settings_sections() );
self::$settings_api->set_fields( self::get_settings_fields() );
// initialize settings.
self::$settings_api->admin_init();
}
/**
* Plugin settings sections
*
* @return array
*/
public static function get_settings_sections() {
$sections = array(
array(
'id' => 'mind_general',
'title' => esc_html__( 'General', 'mind' ),
'icon' => '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" /></svg>',
),
);
return apply_filters( 'mind_settings_sections', $sections );
}
/**
* Returns all the settings fields
*
* @return array settings fields
*/
public static function get_settings_fields() {
if ( ! empty( self::$cached_settings_fields ) ) {
return self::$cached_settings_fields;
}
// retrieve openai key from the DB.
// we can't use Mind Settings API as it will result a stack trace error.
$openai_key = false;
$general_settings = get_option( 'mind_general' );
if ( isset( $general_settings['openai_key'] ) ) {
$openai_key = $general_settings['openai_key'];
}
$settings_fields = array(
'mind_general' => array(
array(
'name' => 'openai_key',
'label' => esc_html__( 'OpenAI API Key', 'mind' ),
'desc' => esc_html__( 'This setting is required, since our plugin works with OpenAI.', 'mind' ) . ' <a href="https://platform.openai.com/account/api-keys" target="_blank">Create API key</a>',
'type' => $openai_key ? 'password' : 'text',
'default' => '',
),
),
);
self::$cached_settings_fields = apply_filters( 'mind_settings_fields', $settings_fields );
return self::$cached_settings_fields;
}
/**
* The plugin page handler
*
* @return void
*/
public static function print_settings_page() {
self::$settings_api->admin_enqueue_scripts();
echo '<div class="wrap">';
echo '<h2>' . esc_html__( 'Settings', 'mind' ) . '</h2>';
self::$settings_api->show_navigation();
self::$settings_api->show_forms();
echo '</div>';
?>
<script>
(function( $ ) {
// Don't allow adding input number values that > then max attribute and < min attribute.
$('form').on('input', '[type="number"]', function(e) {
var current = parseFloat( this.value );
var min = parseFloat(this.min);
var max = parseFloat(this.max);
if ('' !== this.value) {
if (!Number.isNaN(min) && current < min) {
this.value = min;
}
if (!Number.isNaN(max) && current > max) {
this.value = max;
}
}
});
<?php if ( ! class_exists( 'Mind_Pro' ) ) : ?>
// disable pro inputs.
$('.mind-settings-control-pro').find('input, textarea').attr('disabled', 'disabled');
<?php endif; ?>
})(jQuery);
</script>
<?php
}
}
new Mind_Settings();

18
composer.json Normal file
View file

@ -0,0 +1,18 @@
{
"require-dev": {
"wp-coding-standards/wpcs": "^2.3",
"sirbrillig/phpcs-variable-analysis": "^2.8",
"phpcompatibility/phpcompatibility-wp": "^2.1",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7",
"php-stubs/wordpress-stubs": "^6.1"
},
"scripts": {
"phpcs": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs",
"phpcbf": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcbf",
"wp": "\"vendor/wp-cli/wp-cli/bin/wp\"",
"test:unit": "./vendor/bin/phpunit"
},
"config": {
"allow-plugins": true
}
}

479
composer.lock generated Normal file
View file

@ -0,0 +1,479 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "831091850fe7efc2e6b2ca4c78edf531",
"packages": [],
"packages-dev": [
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "^9.0"
},
"type": "composer-plugin",
"extra": {
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Franck Nijhof",
"email": "franck.nijhof@dealerdirect.com",
"homepage": "http://www.frenck.nl",
"role": "Developer / IT Manager"
},
{
"name": "Contributors",
"homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
"homepage": "http://www.dealerdirect.com",
"keywords": [
"PHPCodeSniffer",
"PHP_CodeSniffer",
"code quality",
"codesniffer",
"composer",
"installer",
"phpcbf",
"phpcs",
"plugin",
"qa",
"quality",
"standard",
"standards",
"style guide",
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2022-02-04T12:51:07+00:00"
},
{
"name": "php-stubs/wordpress-stubs",
"version": "v6.2.1",
"source": {
"type": "git",
"url": "https://github.com/php-stubs/wordpress-stubs.git",
"reference": "0009429e639b748eef1c955200ea0d4e5ad5627d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/0009429e639b748eef1c955200ea0d4e5ad5627d",
"reference": "0009429e639b748eef1c955200ea0d4e5ad5627d",
"shasum": ""
},
"require-dev": {
"nikic/php-parser": "< 4.12.0",
"php": "~7.3 || ~8.0",
"php-stubs/generator": "^0.8.3",
"phpdocumentor/reflection-docblock": "^5.3",
"phpstan/phpstan": "^1.10.12",
"phpunit/phpunit": "^9.5"
},
"suggest": {
"paragonie/sodium_compat": "Pure PHP implementation of libsodium",
"symfony/polyfill-php73": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
"szepeviktor/phpstan-wordpress": "WordPress extensions for PHPStan"
},
"type": "library",
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "WordPress function and class declaration stubs for static analysis.",
"homepage": "https://github.com/php-stubs/wordpress-stubs",
"keywords": [
"PHPStan",
"static analysis",
"wordpress"
],
"support": {
"issues": "https://github.com/php-stubs/wordpress-stubs/issues",
"source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.2.1"
},
"time": "2023-05-18T04:35:23+00:00"
},
{
"name": "phpcompatibility/php-compatibility",
"version": "9.3.5",
"source": {
"type": "git",
"url": "https://github.com/PHPCompatibility/PHPCompatibility.git",
"reference": "9fb324479acf6f39452e0655d2429cc0d3914243"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243",
"reference": "9fb324479acf6f39452e0655d2429cc0d3914243",
"shasum": ""
},
"require": {
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.3 || ^3.0.2"
},
"conflict": {
"squizlabs/php_codesniffer": "2.6.2"
},
"require-dev": {
"phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0"
},
"suggest": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.",
"roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
},
"type": "phpcodesniffer-standard",
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0-or-later"
],
"authors": [
{
"name": "Wim Godden",
"homepage": "https://github.com/wimg",
"role": "lead"
},
{
"name": "Juliette Reinders Folmer",
"homepage": "https://github.com/jrfnl",
"role": "lead"
},
{
"name": "Contributors",
"homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors"
}
],
"description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.",
"homepage": "http://techblog.wimgodden.be/tag/codesniffer/",
"keywords": [
"compatibility",
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues",
"source": "https://github.com/PHPCompatibility/PHPCompatibility"
},
"time": "2019-12-27T09:44:58+00:00"
},
{
"name": "phpcompatibility/phpcompatibility-paragonie",
"version": "1.3.2",
"source": {
"type": "git",
"url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git",
"reference": "bba5a9dfec7fcfbd679cfaf611d86b4d3759da26"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/bba5a9dfec7fcfbd679cfaf611d86b4d3759da26",
"reference": "bba5a9dfec7fcfbd679cfaf611d86b4d3759da26",
"shasum": ""
},
"require": {
"phpcompatibility/php-compatibility": "^9.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7",
"paragonie/random_compat": "dev-master",
"paragonie/sodium_compat": "dev-master"
},
"suggest": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.",
"roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
},
"type": "phpcodesniffer-standard",
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0-or-later"
],
"authors": [
{
"name": "Wim Godden",
"role": "lead"
},
{
"name": "Juliette Reinders Folmer",
"role": "lead"
}
],
"description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.",
"homepage": "http://phpcompatibility.com/",
"keywords": [
"compatibility",
"paragonie",
"phpcs",
"polyfill",
"standards",
"static analysis"
],
"support": {
"issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues",
"source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie"
},
"time": "2022-10-25T01:46:02+00:00"
},
{
"name": "phpcompatibility/phpcompatibility-wp",
"version": "2.1.4",
"source": {
"type": "git",
"url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git",
"reference": "b6c1e3ee1c35de6c41a511d5eb9bd03e447480a5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/b6c1e3ee1c35de6c41a511d5eb9bd03e447480a5",
"reference": "b6c1e3ee1c35de6c41a511d5eb9bd03e447480a5",
"shasum": ""
},
"require": {
"phpcompatibility/php-compatibility": "^9.0",
"phpcompatibility/phpcompatibility-paragonie": "^1.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7"
},
"suggest": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.",
"roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
},
"type": "phpcodesniffer-standard",
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0-or-later"
],
"authors": [
{
"name": "Wim Godden",
"role": "lead"
},
{
"name": "Juliette Reinders Folmer",
"role": "lead"
}
],
"description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.",
"homepage": "http://phpcompatibility.com/",
"keywords": [
"compatibility",
"phpcs",
"standards",
"static analysis",
"wordpress"
],
"support": {
"issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues",
"source": "https://github.com/PHPCompatibility/PHPCompatibilityWP"
},
"time": "2022-10-24T09:00:36+00:00"
},
{
"name": "sirbrillig/phpcs-variable-analysis",
"version": "v2.11.16",
"source": {
"type": "git",
"url": "https://github.com/sirbrillig/phpcs-variable-analysis.git",
"reference": "dc5582dc5a93a235557af73e523c389aac9a8e88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sirbrillig/phpcs-variable-analysis/zipball/dc5582dc5a93a235557af73e523c389aac9a8e88",
"reference": "dc5582dc5a93a235557af73e523c389aac9a8e88",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"squizlabs/php_codesniffer": "^3.5.6"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7 || ^1.0",
"phpcsstandards/phpcsdevcs": "^1.1",
"phpstan/phpstan": "^1.7",
"phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.5 || ^7.0 || ^8.0 || ^9.0",
"sirbrillig/phpcs-import-detection": "^1.1",
"vimeo/psalm": "^0.2 || ^0.3 || ^1.1 || ^4.24 || ^5.0@beta"
},
"type": "phpcodesniffer-standard",
"autoload": {
"psr-4": {
"VariableAnalysis\\": "VariableAnalysis/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-2-Clause"
],
"authors": [
{
"name": "Sam Graham",
"email": "php-codesniffer-variableanalysis@illusori.co.uk"
},
{
"name": "Payton Swick",
"email": "payton@foolord.com"
}
],
"description": "A PHPCS sniff to detect problems with variables.",
"keywords": [
"phpcs",
"static analysis"
],
"support": {
"issues": "https://github.com/sirbrillig/phpcs-variable-analysis/issues",
"source": "https://github.com/sirbrillig/phpcs-variable-analysis",
"wiki": "https://github.com/sirbrillig/phpcs-variable-analysis/wiki"
},
"time": "2023-03-31T16:46:32+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.7.2",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879",
"reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards",
"static analysis"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2023-02-22T23:07:41+00:00"
},
{
"name": "wp-coding-standards/wpcs",
"version": "2.3.0",
"source": {
"type": "git",
"url": "https://github.com/WordPress/WordPress-Coding-Standards.git",
"reference": "7da1894633f168fe244afc6de00d141f27517b62"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7da1894633f168fe244afc6de00d141f27517b62",
"reference": "7da1894633f168fe244afc6de00d141f27517b62",
"shasum": ""
},
"require": {
"php": ">=5.4",
"squizlabs/php_codesniffer": "^3.3.1"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.5 || ^0.6",
"phpcompatibility/php-compatibility": "^9.0",
"phpcsstandards/phpcsdevtools": "^1.0",
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"suggest": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically."
},
"type": "phpcodesniffer-standard",
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Contributors",
"homepage": "https://github.com/WordPress/WordPress-Coding-Standards/graphs/contributors"
}
],
"description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions",
"keywords": [
"phpcs",
"standards",
"wordpress"
],
"support": {
"issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues",
"source": "https://github.com/WordPress/WordPress-Coding-Standards",
"wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki"
},
"time": "2020-05-13T23:57:56+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.3.0"
}

134
mind.php Normal file
View file

@ -0,0 +1,134 @@
<?php
/**
* Plugin Name: Mind Content Assistant Plugin based on OpenAI
* Description: Write, improve, rewrite, rephrase, change a tone of your blog posts with WPMind.
* Requires at least: 6.0
* Requires PHP: 7.2
* Version: 0.1.0
* Author: WPMind Team
* Author URI: https://wp-mind.com/?utm_source=wordpress.org&utm_medium=readme&utm_campaign=byline
* License: GPLv2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: mind
*
* @package mind
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! defined( 'MIND_VERSION' ) ) {
define( 'MIND_VERSION', '0.1.0' );
}
/**
* Mind Class
*/
class Mind {
/**
* The single class instance.
*
* @var $instance
*/
private static $instance = null;
/**
* Main Instance
* Ensures only one instance of this class exists in memory at any one time.
*/
public static function instance() {
if ( is_null( self::$instance ) ) {
self::$instance = new self();
self::$instance->init();
}
return self::$instance;
}
/**
* Name of the plugin
*
* @var $plugin_name
*/
public $plugin_name;
/**
* Basename of plugin main file
*
* @var $plugin_basename
*/
public $plugin_basename;
/**
* Path to the plugin directory
*
* @var $plugin_path
*/
public $plugin_path;
/**
* URL to the plugin directory
*
* @var $plugin_url
*/
public $plugin_url;
/**
* Mind constructor.
*/
public function __construct() {
/* We do nothing here! */
}
/**
* Init options
*/
public function init() {
$this->plugin_name = esc_html__( 'Mind', 'mind' );
$this->plugin_basename = plugin_basename( __FILE__ );
$this->plugin_path = plugin_dir_path( __FILE__ );
$this->plugin_url = plugin_dir_url( __FILE__ );
// load textdomain.
load_plugin_textdomain( 'mind', false, basename( dirname( __FILE__ ) ) . '/languages' );
// include helper files.
$this->include_dependencies();
}
/**
* Activation Hook
*/
public function activation_hook() {
// Nothing here yet.
}
/**
* Deactivation Hook
*/
public function deactivation_hook() {
// Nothing here yet.
}
/**
* Include dependencies
*/
private function include_dependencies() {
require_once $this->plugin_path . 'classes/class-settings.php';
require_once $this->plugin_path . 'classes/class-admin.php';
require_once $this->plugin_path . 'classes/class-assets.php';
}
}
/**
* Function works with the Mind class instance
*
* @return object Mind
*/
function mind() {
return Mind::instance();
}
add_action( 'plugins_loaded', 'mind' );
register_activation_hook( __FILE__, array( mind(), 'activation_hook' ) );
register_deactivation_hook( __FILE__, array( mind(), 'deactivation_hook' ) );

16142
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

24
package.json Normal file
View file

@ -0,0 +1,24 @@
{
"name": "mind",
"version": "0.1.0",
"description": "Mind - Content Assistant Plugin based on OpenAI",
"author": "nK",
"license": "GPL-2.0-or-later",
"main": "build/index.js",
"scripts": {
"build": "wp-scripts build",
"start": "wp-scripts start",
"start:hot": "wp-scripts start --hot --config webpack-hot-config.js",
"lint:css": "wp-scripts lint-style",
"lint:js": "wp-scripts lint-js",
"packages-update": "wp-scripts packages-update",
"plugin-zip": "wp-scripts plugin-zip"
},
"devDependencies": {
"@wordpress/eslint-plugin": "^14.7.0",
"@wordpress/prettier-config": "^2.17.0",
"@wordpress/scripts": "^26.2.0",
"@wordpress/stylelint-config": "^21.17.0",
"prettier": "^2.8.8"
}
}

86
phpcs.xml.dist Normal file
View file

@ -0,0 +1,86 @@
<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
name="Mind"
xsi:noNamespaceSchemaLocation="./vendor/squizlabs/php_codesniffer/phpcs.xsd">
<description>Mind rules for PHP_CodeSniffer</description>
<!--
#############################################################################
COMMAND LINE ARGUMENTS
https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-ruleset.xml
#############################################################################
-->
<!-- Check the /src/ directory and the directories below it. -->
<file>./src/</file>
<exclude-pattern>./build/*</exclude-pattern>
<exclude-pattern>./vendor/*</exclude-pattern>
<exclude-pattern>./vendors/*</exclude-pattern>
<exclude-pattern>./node_modules/*</exclude-pattern>
<!-- Only check the PHP files. JS files are checked separately with JSCS and JSHint. -->
<arg name="extensions" value="php" />
<!-- Show progress, show the error codes for each message (source). -->
<arg value="ps" />
<!-- Check up to 8 files simultaneously. -->
<arg name="parallel" value="8" />
<!--
#############################################################################
SET THE RULES TO USE
See https://github.com/WordPress/WordPress-Coding-Standards
See https://github.com/PHPCompatibility/PHPCompatibility
#############################################################################
-->
<!-- Include sniffs for PHP cross-version compatibility. -->
<config name="testVersion" value="7.2-"/>
<rule ref="PHPCompatibilityWP">
<include-pattern>*\.php$</include-pattern>
</rule>
<rule ref="WordPress-Core" />
<rule ref="WordPress-Docs" />
<rule ref="WordPress.WP.I18n" />
<config name="text_domain" value="mind" />
<rule ref="VariableAnalysis.CodeAnalysis.VariableAnalysis">
<properties>
<property name="allowUnusedParametersBeforeUsed" value="true"/>
</properties>
</rule>
<rule ref="WordPress.CodeAnalysis.EmptyStatement"/>
<!--
#############################################################################
SNIFF SPECIFIC CONFIGURATION
See https://github.com/WordPress/WordPress-Coding-Standards/wiki
#############################################################################
-->
<!-- Set the minimum supported WP version to WP 6.0. -->
<config name="minimum_supported_wp_version" value="6.0"/>
<!-- Prevent error about filename with Class -->
<rule ref="WordPress.Files.FileName">
<properties>
<property name="strict_class_file_names" value="false" />
</properties>
</rule>
<!-- Verify that everything in the global namespace is prefixed with a theme specific prefix.
Multiple valid prefixes can be provided as a comma-delimited list. -->
<rule ref="WordPress.NamingConventions.PrefixAllGlobals">
<properties>
<property name="prefixes" type="array">
<element value="Mind"/>
<element value="mind"/>
</property>
</properties>
</rule>
</ruleset>

46
readme.txt Normal file
View file

@ -0,0 +1,46 @@
=== Mind ===
Contributors: nko
Tags: ai, openai, block, assistant, blocks
Requires at least: 6.0
Tested up to: 6.2
Requires PHP: 7.2
Stable tag: 0.1.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
OpenAI content assistant and enhancer for WordPress page builder Gutenberg.
== Description ==
OpenAI content assistant and enhancer for WordPress page builder Gutenberg.
== Installation ==
=== Automatic installation ===
Automatic installation is the easiest option as WordPress handles the file transfers itself and you dont need to leave your web browser. To do an automatic install of Mind, log in to your WordPress dashboard, navigate to the Plugins menu and click Add New.
In the search field type Mind and click Search Plugins. Once youve found our plugin you can view details about it such as the point release, rating and description. Most importantly of course, you can install it by simply clicking “Install Now”.
=== Manual installation ===
The manual installation method involves downloading our Mind plugin and uploading it to your webserver via your favorite FTP application. The WordPress codex contains [instructions on how to do this here](https://codex.wordpress.org/Managing_Plugins#Manual_Plugin_Installation).
== Frequently Asked Questions ==
= Website and Documentation =
There is no site available, but in the future all information will be placed here - https://www.wp-mind.com/
== Screenshots ==
== Changelog ==
= 0.1.0 =
* Release
== Arbitrary section ==
You may provide arbitrary sections, in the same format as the ones above. This may be of use for extremely complicated
plugins where more information needs to be conveyed that doesn't fit into the categories of "description" or
"installation." Arbitrary sections will be shown below the built-in sections outlined above.

View file

@ -0,0 +1,83 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { createRoot, useState } from '@wordpress/element';
import { subscribe } from '@wordpress/data';
import domReady from '@wordpress/dom-ready';
// eslint-disable-next-line import/no-extraneous-dependencies
import { throttle } from 'lodash';
/**
* Internal dependencies
*/
import TOOLBAR_ICON from './icon';
import Popup from './popup';
const TOOLBAR_TOGGLE_CONTAINER_CLASS = 'mind-editor-toolbar-toggle';
function Toggle() {
const [isOpened, setIsOpened] = useState(false);
return (
<>
<button
type="button"
className="components-button components-icon-button"
onClick={(e) => {
e.preventDefault();
setIsOpened(!isOpened);
}}
>
{TOOLBAR_ICON}
{__('Open Mind', '@@text_domain')}
</button>
{isOpened ? (
<Popup
onClose={() => {
setIsOpened(!isOpened);
}}
/>
) : null}
</>
);
}
const mountEditorToolbarToggle = () => {
const createToggle = (postHeader) => {
const toggleContainer = document.createElement('div');
toggleContainer.classList.add(TOOLBAR_TOGGLE_CONTAINER_CLASS);
postHeader.appendChild(toggleContainer);
const root = createRoot(toggleContainer);
root.render(<Toggle />);
};
// Always check if toggle is inserted, because post header sometimes gets unmounted.
subscribe(
throttle(
() => {
// Check if toggle exists already.
if (
document.querySelector(`.${TOOLBAR_TOGGLE_CONTAINER_CLASS}`)
) {
return;
}
const postHeader = document.querySelector(
'.edit-post-header__toolbar'
);
if (postHeader) {
createToggle(postHeader);
}
},
200,
{ trailing: true }
)
);
};
domReady(mountEditorToolbarToggle);

29
src/icon.js Normal file
View file

@ -0,0 +1,29 @@
export default (
<svg
width="20"
height="20"
viewBox="0 0 66 66"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="mind-toolbar-icon"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M34.2308 6C34.2308 6 30.4843 18.0769 25 23.5385C19.4023 29.1129 7 32.7692 7 32.7692C7 32.7692 19.414 36.414 25 42C30.586 47.586 34.2308 60 34.2308 60C34.2308 60 37.5375 47.5948 43 42C48.5188 36.3475 61 32.7692 61 32.7692C61 32.7692 48.5288 29.1812 43 23.5385C37.6408 18.0687 34.2308 6 34.2308 6ZM34.1026 21C34.1026 21 31.4375 25.5726 29 28C26.5122 30.4775 22 32.8974 22 32.8974C22 32.8974 26.5173 35.0173 29 37.5C31.4827 39.9827 34.1026 45 34.1026 45C34.1026 45 36.5722 39.9866 39 37.5C41.4528 34.9878 46 32.8974 46 32.8974C46 32.8974 41.4572 30.5079 39 28C36.6181 25.569 34.1026 21 34.1026 21Z"
fill="currentColor"
/>
<path
d="M50.6667 53.5214C52.3932 51.802 53.5726 48 53.5726 48C53.5726 48 54.6462 51.7994 56.3333 53.5214C58.0739 55.2978 62 56.4274 62 56.4274C62 56.4274 58.0707 57.5538 56.3333 59.3333C54.6137 61.0947 53.5726 65 53.5726 65C53.5726 65 52.4252 61.0919 50.6667 59.3333C48.9081 57.5748 45 56.4274 45 56.4274C45 56.4274 48.9044 55.2763 50.6667 53.5214Z"
fill="currentColor"
/>
<path
d="M8.66667 46.5726C9.78384 45.4601 10.547 43 10.547 43C10.547 43 11.2416 45.4584 12.3333 46.5726C13.4596 47.7221 16 48.453 16 48.453C16 48.453 13.4575 49.1819 12.3333 50.3333C11.2206 51.473 10.547 54 10.547 54C10.547 54 9.80457 51.4712 8.66667 50.3333C7.52877 49.1954 5 48.453 5 48.453C5 48.453 7.5264 47.7082 8.66667 46.5726Z"
fill="currentColor"
/>
<path
d="M51.3333 5.22222C52.6536 3.9074 53.5556 1 53.5556 1C53.5556 1 54.3765 3.90543 55.6667 5.22222C56.9977 6.58066 60 7.44444 60 7.44444C60 7.44444 56.9953 8.30588 55.6667 9.66667C54.3516 11.0136 53.5556 14 53.5556 14C53.5556 14 52.6781 11.0115 51.3333 9.66667C49.9885 8.32188 47 7.44444 47 7.44444C47 7.44444 49.9858 6.56421 51.3333 5.22222Z"
fill="currentColor"
/>
</svg>
);

50
src/index.js Normal file
View file

@ -0,0 +1,50 @@
/**
* Styles
*/
import './style.scss';
/**
* WordPress dependencies
*/
import { addFilter } from '@wordpress/hooks';
import { BlockControls } from '@wordpress/block-editor';
import { createHigherOrderComponent } from '@wordpress/compose';
console.log(2);
/**
* Internal dependencies
*/
import './editor-toolbar-toggle';
import { Toolbar, isToolbarAllowed } from './toolbar';
/**
* Override the default edit UI to include a new block inspector control for
* assigning the custom attribute if needed.
*
* @param {Function} BlockEdit Original component.
*
* @return {string} Wrapped component.
*/
const withToolbarControl = createHigherOrderComponent((OriginalComponent) => {
function MindToolbarToggle(props) {
const allow = isToolbarAllowed(props);
if (!allow) {
return <OriginalComponent {...props} />;
}
return (
<>
<OriginalComponent {...props} />
<BlockControls group="other">
<Toolbar />
</BlockControls>
</>
);
}
return MindToolbarToggle;
}, 'withToolbarControl');
addFilter('editor.BlockEdit', 'mind/block-toolbar-toggle', withToolbarControl);

30
src/popup.js Normal file
View file

@ -0,0 +1,30 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { Button, Modal } from '@wordpress/components';
/**
* Internal dependencies
*/
import TOOLBAR_ICON from './icon';
export default function Popup(props) {
const { onClose } = props;
return (
<Modal
title={
<>
{TOOLBAR_ICON}
{__('Mind', '@@text_domain')}
</>
}
className="mind-popup"
overlayClassName="mind-popup-overlay"
onRequestClose={onClose}
>
{__('Hello there :)', '@@text_domain')}
</Modal>
);
}

63
src/style.scss Normal file
View file

@ -0,0 +1,63 @@
$color: #e455df;
$popup_padding: 20px;
.mind-toolbar-icon {
color: $color;
width: 20px;
height: 20px;
}
.mind-toolbar-dropdown-wrapper {
width: 100%;
button {
width: 100%;
padding-left: 8px;
padding-right: 8px;
.dashicon {
margin-left: auto;
}
}
}
// Button in editor Toolbar.
.mind-editor-toolbar-toggle {
flex: 100%;
white-space: nowrap;
button {
color: $color;
&:hover,
&:focus {
color: $color;
background: rgba($color, 5%);
}
}
svg {
margin-top: -2px;
margin-right: 6px;
margin-bottom: -2px;
}
}
// Popup.
.mind-popup {
width: 800px;
margin-top: 100px;
background-color: rgb(243, 243, 243);
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 20%), 0 25px 70px 10px rgba(0, 0, 0, 25%);
border: 1px solid rgba(255, 255, 255, 40%);
.components-modal__header {
padding: 24px $popup_padding 12px;
}
.components-modal__content {
padding: 0 $popup_padding $popup_padding;
}
}
.mind-popup-overlay {
background-color: rgba(143, 135, 143, 25%);
}

165
src/toolbar.js Normal file
View file

@ -0,0 +1,165 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';
import {
ToolbarGroup,
DropdownMenu,
MenuGroup,
MenuItem,
Dashicon,
} from '@wordpress/components';
/**
* Internal dependencies
*/
import TOOLBAR_ICON from './icon';
const ALLOWED_BLOCKS = ['core/paragraph', 'core/heading'];
/**
* Check if Mind allowed in block toolbar.
*
* @param {Object} data - block data.
* @return {boolean} allowed.
*/
export function isToolbarAllowed(data) {
return ALLOWED_BLOCKS.includes(data.name);
}
export function Toolbar() {
const { selectedBlocks, selectedClientIds, canRemove } = useSelect(
(select) => {
const {
getBlockNamesByClientId,
getSelectedBlockClientIds,
canRemoveBlocks,
} = select('core/block-editor');
const ids = getSelectedBlockClientIds();
return {
selectedBlocks: getBlockNamesByClientId(ids),
selectedClientIds: ids,
canRemove: canRemoveBlocks(ids),
};
},
[]
);
console.log(selectedClientIds);
// const { replaceBlocks } = useDispatch( blockEditorStore );
// const onConvertToGroup = () => {
// // Activate the `transform` on the Grouping Block which does the conversion.
// const newBlocks = switchToBlockType(
// blocksSelection,
// groupingBlockName
// );
// if ( newBlocks ) {
// replaceBlocks( clientIds, newBlocks );
// }
// };
return (
<ToolbarGroup>
<DropdownMenu
icon={TOOLBAR_ICON}
label={__('Mind', '@@text_domain')}
>
{() => {
return (
<>
<MenuGroup>
<MenuItem>{__('Improve', 'mind')}</MenuItem>
<MenuItem>{__('Paraphrase', 'mind')}</MenuItem>
<MenuItem>{__('Simplify', 'mind')}</MenuItem>
<MenuItem>{__('Expand', 'mind')}</MenuItem>
<MenuItem>{__('Shorten', 'mind')}</MenuItem>
</MenuGroup>
<MenuGroup>
<DropdownMenu
icon={null}
toggleProps={{
children: (
<>
{__('Formality', 'mind')}
<Dashicon icon="arrow-right" />
</>
),
}}
popoverProps={{ placement: 'right-end' }}
className="mind-toolbar-dropdown-wrapper"
>
{() => {
return (
<>
<MenuGroup>
<MenuItem>
{__('Casual', 'mind')}
</MenuItem>
<MenuItem>
{__('Neutral', 'mind')}
</MenuItem>
<MenuItem>
{__('Formal', 'mind')}
</MenuItem>
</MenuGroup>
</>
);
}}
</DropdownMenu>
<DropdownMenu
icon={null}
toggleProps={{
children: (
<>
{__('Tone', 'mind')}
<Dashicon icon="arrow-right" />
</>
),
}}
popoverProps={{ placement: 'right-end' }}
className="mind-toolbar-dropdown-wrapper"
>
{() => {
return (
<>
<MenuGroup>
<MenuItem>
{__('Friendly', 'mind')}
</MenuItem>
<MenuItem>
{__(
'Professional',
'mind'
)}
</MenuItem>
<MenuItem>
{__('Witty', 'mind')}
</MenuItem>
<MenuItem>
{__(
'Heartfelt',
'mind'
)}
</MenuItem>
<MenuItem>
{__(
'Educational',
'mind'
)}
</MenuItem>
</MenuGroup>
</>
);
}}
</DropdownMenu>
</MenuGroup>
</>
);
}}
</DropdownMenu>
</ToolbarGroup>
);
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
vendors/assets/select2/select2.min.js vendored Normal file

File diff suppressed because one or more lines are too long

989
vendors/class-settings-api.php vendored Normal file
View file

@ -0,0 +1,989 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Mind Settings API wrapper class
* based on weDevs Settings API
*
* ADDED PR: https://github.com/tareq1988/wordpress-settings-api-class/pull/47
* ADDED: enqueue scripts manually, without `admin_enqueue_scripts` action.
* ADDED: new controls such as toggle and number slider.
*
* @author Tareq Hasan <tareq@weDevs.com>
* @link https://tareq.co Tareq Hasan
*/
class Mind_Settings_API {
/**
* Settings sections array
*
* @var array
*/
protected $settings_sections = array();
/**
* Settings fields array
*
* @var array
*/
protected $settings_fields = array();
/**
* Mind_Settings_API constructor.
*/
public function __construct() {
// add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
}
/**
* Enqueue scripts and styles
*/
public function admin_enqueue_scripts() {
wp_enqueue_style( 'wp-color-picker' );
wp_enqueue_media();
wp_enqueue_script( 'wp-color-picker' );
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'conditionize', mind()->plugin_url . 'vendors/assets/conditionize/conditionize.min.js', array( 'jquery' ), '1.0.5' );
wp_enqueue_style( 'select2', mind()->plugin_url . 'vendors/assets/select2/select2.min.css', array(), '4.0.13' );
wp_enqueue_script( 'select2', mind()->plugin_url . 'vendors/assets/select2/select2.min.js', array( 'jquery' ), '4.0.13' );
}
/**
* Set settings sections
*
* @param array $sections setting sections array
*/
public function set_sections( $sections ) {
$this->settings_sections = $sections;
return $this;
}
/**
* Add a single section
*
* @param array $section
*/
public function add_section( $section ) {
$this->settings_sections[] = $section;
return $this;
}
/**
* Set settings fields
*
* @param array $fields settings fields array
*/
public function set_fields( $fields ) {
$this->settings_fields = $fields;
return $this;
}
public function add_field( $section, $field ) {
$defaults = array(
'name' => '',
'label' => '',
'desc' => '',
'type' => 'text',
'is_pro' => false,
);
$arg = wp_parse_args( $field, $defaults );
$this->settings_fields[ $section ][] = $arg;
return $this;
}
/**
* Initialize and registers the settings sections and fileds to WordPress
*
* Usually this should be called at `admin_init` hook.
*
* This function gets the initiated settings sections and fields. Then
* registers them to WordPress and ready for use.
*/
public function admin_init() {
// register settings sections
foreach ( $this->settings_sections as $section ) {
if ( false == get_option( $section['id'] ) ) {
add_option( $section['id'] );
}
if ( isset( $section['desc'] ) && ! empty( $section['desc'] ) ) {
$section['desc'] = '<div class="inside">' . $section['desc'] . '</div>';
$callback = create_function( '', 'echo "' . str_replace( '"', '\"', $section['desc'] ) . '";' );
} elseif ( isset( $section['callback'] ) ) {
$callback = $section['callback'];
} else {
$callback = null;
}
add_settings_section( $section['id'], $section['title'], $callback, $section['id'] );
}
// register settings fields
foreach ( $this->settings_fields as $section => $field ) {
foreach ( $field as $option ) {
$name = $option['name'];
$type = isset( $option['type'] ) ? $option['type'] : 'text';
$label = isset( $option['label'] ) ? $option['label'] : '';
$callback = isset( $option['callback'] ) ? $option['callback'] : array( $this, 'callback_' . $type );
$class_name = isset( $option['class'] ) ? $option['class'] : $name;
$is_pro = isset( $option['is_pro'] ) ? $option['is_pro'] : false;
if ( $is_pro ) {
$class_name .= ' mind-settings-control-pro';
$go_pro_url = Visual_Portfolio_Admin::get_plugin_site_url(
array(
'utm_medium' => 'settings_page',
'utm_campaign' => esc_attr( $name ),
)
);
$label .= '<a class="mind-settings-control-pro-label" target="_blank" rel="noopener noreferrer" href="' . esc_url( $go_pro_url ) . '">?<span>' . esc_html__( 'This feature is available in the Pro plugin only.', '@@text_domain' ) . '</span></a>';
}
$args = array(
'id' => $name,
'class' => $class_name,
'label_for' => "{$section}[{$name}]",
'desc' => isset( $option['desc'] ) ? $option['desc'] : '',
'name' => $label,
'section' => $section,
'size' => isset( $option['size'] ) ? $option['size'] : null,
'options' => isset( $option['options'] ) ? $option['options'] : '',
'std' => isset( $option['default'] ) ? $option['default'] : '',
'sanitize_callback' => isset( $option['sanitize_callback'] ) ? $option['sanitize_callback'] : '',
'type' => $type,
'placeholder' => isset( $option['placeholder'] ) ? $option['placeholder'] : '',
'min' => isset( $option['min'] ) ? $option['min'] : '',
'max' => isset( $option['max'] ) ? $option['max'] : '',
'step' => isset( $option['step'] ) ? $option['step'] : '',
'is_pro' => isset( $option['is_pro'] ) ? $option['is_pro'] : false,
'condition' => isset( $option['condition'] ) ? $option['condition'] : null,
'conditionize' => isset( $option['condition'] ) ? $this->convert_arguments_to_conditionize_string( $option['condition'] ) : '',
);
add_settings_field( "{$section}[{$name}]", $label, $callback, $section, $section, $args );
}
}
// creates our settings in the options table
foreach ( $this->settings_sections as $section ) {
register_setting( $section['id'], $section['id'], array( $this, 'sanitize_options' ) );
}
}
/**
* Get field description for display
*
* @param array $args settings field args
*/
public function get_field_description( $args ) {
if ( ! empty( $args['desc'] ) ) {
$desc = sprintf( '<p class="description">%s</p>', $args['desc'] );
} else {
$desc = '';
}
return $desc;
}
/**
* Displays a text field for a settings field
*
* @param array $args settings field args
*/
public function callback_text( $args ) {
$value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
$size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
$type = isset( $args['type'] ) ? $args['type'] : 'text';
$placeholder = empty( $args['placeholder'] ) ? '' : ' placeholder="' . $args['placeholder'] . '"';
$html = sprintf( '<input type="%1$s" class="%2$s-text" id="%3$s[%4$s]" name="%3$s[%4$s]" value="%5$s"%6$s/>', $type, $size, $args['section'], $args['id'], $value, $placeholder );
$html .= $this->get_field_description( $args );
echo $html;
}
/**
* Displays a url field for a settings field
*
* @param array $args settings field args
*/
public function callback_url( $args ) {
$this->callback_text( $args );
}
/**
* Displays a number field for a settings field
*
* @param array $args settings field args
*/
public function callback_number( $args ) {
$value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
$size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
$type = isset( $args['type'] ) ? $args['type'] : 'number';
$placeholder = empty( $args['placeholder'] ) ? '' : ' placeholder="' . $args['placeholder'] . '"';
$min = empty( $args['min'] ) ? '' : ' min="' . $args['min'] . '"';
$max = empty( $args['max'] ) ? '' : ' max="' . $args['max'] . '"';
$step = empty( $args['max'] ) ? '' : ' step="' . $args['step'] . '"';
$html = sprintf( '<input type="%1$s" class="%2$s-number" id="%3$s[%4$s]" name="%3$s[%4$s]" value="%5$s"%6$s%7$s%8$s%9$s/>', $type, $size, $args['section'], $args['id'], $value, $placeholder, $min, $max, $step );
$html .= $this->get_field_description( $args );
echo $html;
}
/**
* Displays a checkbox for a settings field
*
* @param array $args settings field args
*/
public function callback_checkbox( $args ) {
$value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
$html = '<fieldset>';
$html .= sprintf( '<label for="wpuf-%1$s[%2$s]">', $args['section'], $args['id'] );
$html .= sprintf( '<input type="hidden" name="%1$s[%2$s]" value="off" />', $args['section'], $args['id'] );
$html .= sprintf( '<input type="checkbox" class="checkbox" id="wpuf-%1$s[%2$s]" name="%1$s[%2$s]" value="on" %3$s />', $args['section'], $args['id'], checked( $value, 'on', false ) );
$html .= sprintf( '<span class="description">%1$s</span></label>', $args['desc'] );
$html .= '</fieldset>';
echo $html;
}
/**
* Displays a multicheckbox for a settings field
*
* @param array $args settings field args
*/
public function callback_multicheck( $args ) {
$value = $this->get_option( $args['id'], $args['section'], $args['std'] );
$html = '<fieldset>';
$html .= sprintf( '<input type="hidden" name="%1$s[%2$s]" value="" />', $args['section'], $args['id'] );
foreach ( $args['options'] as $key => $label ) {
$checked = isset( $value[ $key ] ) ? $value[ $key ] : '0';
$html .= sprintf( '<label for="wpuf-%1$s[%2$s][%3$s]">', $args['section'], $args['id'], $key );
$html .= sprintf( '<input type="checkbox" class="checkbox" id="wpuf-%1$s[%2$s][%3$s]" name="%1$s[%2$s][%3$s]" value="%3$s" %4$s />', $args['section'], $args['id'], $key, checked( $checked, $key, false ) );
$html .= sprintf( '<span class="description">%1$s</span></label><br>', $label );
}
$html .= $this->get_field_description( $args );
$html .= '</fieldset>';
echo $html;
}
/**
* Displays a radio button for a settings field
*
* @param array $args settings field args
*/
public function callback_radio( $args ) {
$value = $this->get_option( $args['id'], $args['section'], $args['std'] );
$html = '<fieldset>';
foreach ( $args['options'] as $key => $label ) {
$html .= sprintf( '<label for="wpuf-%1$s[%2$s][%3$s]">', $args['section'], $args['id'], $key );
$html .= sprintf( '<input type="radio" class="radio" id="wpuf-%1$s[%2$s][%3$s]" name="%1$s[%2$s]" value="%3$s" %4$s />', $args['section'], $args['id'], $key, checked( $value, $key, false ) );
$html .= sprintf( '<span class="description">%1$s</span></label><br>', $label );
}
$html .= $this->get_field_description( $args );
$html .= '</fieldset>';
echo $html;
}
/**
* Displays a selectbox for a settings field
*
* @param array $args settings field args
*/
public function callback_select( $args ) {
$value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
$classes = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
$html = sprintf( '<select class="%1$s" name="%2$s[%3$s]" id="%2$s[%3$s]">', $classes, $args['section'], $args['id'] );
foreach ( $args['options'] as $key => $label ) {
$html .= sprintf( '<option value="%s"%s>%s</option>', $key, selected( $value, $key, false ), $label );
}
$html .= sprintf( '</select>' );
$html .= $this->get_field_description( $args );
echo $html;
}
/**
* Displays a textarea for a settings field
*
* @param array $args settings field args
*/
public function callback_textarea( $args ) {
$value = esc_textarea( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
$size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
$placeholder = empty( $args['placeholder'] ) ? '' : ' placeholder="' . $args['placeholder'] . '"';
$html = sprintf( '<textarea rows="5" cols="55" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]"%4$s>%5$s</textarea>', $size, $args['section'], $args['id'], $placeholder, $value );
$html .= $this->get_field_description( $args );
echo $html;
}
/**
* Displays the html for a settings field
*
* @param array $args settings field args
* @return string
*/
public function callback_html( $args ) {
echo $this->get_field_description( $args );
}
/**
* Displays the section title for a settings field
*
* @param array $args settings field args
* @return string
*/
public function callback_section_title( $args ) {
echo $this->get_field_description( $args );
}
/**
* Displays a rich text textarea for a settings field
*
* @param array $args settings field args
*/
public function callback_wysiwyg( $args ) {
$value = $this->get_option( $args['id'], $args['section'], $args['std'] );
$size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : '500px';
echo '<div style="max-width: ' . $size . ';">';
$editor_settings = array(
'teeny' => true,
'textarea_name' => $args['section'] . '[' . $args['id'] . ']',
'textarea_rows' => 10,
);
if ( isset( $args['options'] ) && is_array( $args['options'] ) ) {
$editor_settings = array_merge( $editor_settings, $args['options'] );
}
wp_editor( $value, $args['section'] . '-' . $args['id'], $editor_settings );
echo '</div>';
echo $this->get_field_description( $args );
}
/**
* Displays a file upload field for a settings field
*
* @param array $args settings field args
*/
public function callback_file( $args ) {
$value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
$size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
$id = $args['section'] . '[' . $args['id'] . ']';
$label = isset( $args['options']['button_label'] ) ? $args['options']['button_label'] : __( 'Choose File' );
$html = sprintf( '<input type="text" class="%1$s-text wpsa-url" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s"/>', $size, $args['section'], $args['id'], $value );
$html .= '<input type="button" class="button wpsa-browse" value="' . $label . '" />';
$html .= $this->get_field_description( $args );
echo $html;
}
/**
* Displays a image upload field for a settings field
*
* @param array $args settings field args
*/
public function callback_image( $args ) {
$value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
$size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
$id = $args['section'] . '[' . $args['id'] . ']';
$label = isset( $args['options']['button_label'] ) ? $args['options']['button_label'] : __( 'Choose Image' );
$label_remove = isset( $args['options']['button_remove_label'] ) ? $args['options']['button_remove_label'] : __( 'Remove Image' );
$img = wp_get_attachment_image_src( $value, $args['size'] ? $args['size'] : 'thumbnail' );
$img_url = $img ? $img[0] : '';
$html = sprintf( '<input type="hidden" class="%1$s-text wpsa-image-id" id="%2$s" name="%2$s" value="%3$s"/>', $size, $id, $value );
$html .= '<p class="wpsa-image-preview"><img src="' . $img_url . '" /></p>';
$html .= '<input type="button" class="button button-primary wpsa-image-browse" value="' . $label . '" />';
$html .= '<input type="button" class="button button-link wpsa-image-remove" value="' . $label_remove . '" />';
$html .= $this->get_field_description( $args );
echo $html;
}
/**
* Displays a password field for a settings field
*
* @param array $args settings field args
*/
public function callback_password( $args ) {
$value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
$size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
$html = sprintf( '<input type="password" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s"/>', $size, $args['section'], $args['id'], $value );
$html .= $this->get_field_description( $args );
echo $html;
}
/**
* Displays a color picker field for a settings field
*
* @param array $args settings field args
*/
public function callback_color( $args ) {
$value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
$size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
$html = sprintf( '<input type="text" class="%1$s-text wp-color-picker-field" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s" data-default-color="%5$s" />', $size, $args['section'], $args['id'], $value, $args['std'] );
$html .= $this->get_field_description( $args );
echo $html;
}
/**
* Displays a select box for creating the pages select box
*
* @param array $args settings field args
*/
public function callback_pages( $args ) {
$dropdown_args = array(
'selected' => esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) ),
'name' => $args['section'] . '[' . $args['id'] . ']',
'id' => $args['section'] . '[' . $args['id'] . ']',
'echo' => 0,
);
$html = wp_dropdown_pages( $dropdown_args );
echo $html;
}
/**
* Displays a toggle field for a settings field
*
* @param array $args settings field args.
*/
public function callback_toggle( $args ) {
$value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
$html = sprintf( '<label for="wpuf-%1$s[%2$s]" class="mind-toggle-field">', $args['section'], $args['id'] );
$html .= sprintf( '<input type="hidden" name="%1$s[%2$s]" value="off" />', esc_attr( $args['section'] ), esc_attr( $args['id'] ) );
$html .= sprintf( '<input type="checkbox" id="wpuf-%1$s[%2$s]" name="%1$s[%2$s]" value="on" %3$s/>', esc_attr( $args['section'] ), esc_attr( $args['id'] ), checked( $value, 'on', false ) );
$html .= sprintf( '<span class="mind-toggle-field-slider-round"></span><span class="description">%1$s</span></label>', $args['desc'] );
echo $html;
}
/**
* Displays a range field for a settings field
*
* @param array $args settings field args.
*/
public function callback_range( $args ) {
$value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
$size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
$type = isset( $args['type'] ) ? $args['type'] : 'range';
$placeholder = empty( $args['placeholder'] ) ? '' : ' placeholder="' . $args['placeholder'] . '"';
$min = empty( $args['min'] ) ? '' : ' min="' . $args['min'] . '"';
$max = empty( $args['max'] ) ? '' : ' max="' . $args['max'] . '"';
$step = empty( $args['max'] ) ? '' : ' step="' . $args['step'] . '"';
?>
<?php
echo sprintf(
'<input type="%1$s" class="%2$s-range mind-range-field" id="%3$s[%4$s]" name="%3$s[%4$s]" value="%5$s"%6$s%7$s%8$s%9$s/>',
esc_attr( $type ),
esc_attr( $size ),
esc_attr( $args['section'] ),
esc_attr( $args['id'] ),
esc_attr( $value ),
esc_attr( $placeholder ),
esc_attr( $min ),
esc_attr( $max ),
esc_attr( $step )
);
echo sprintf(
'<input type="number" class="number-range mind-range-number-field" name="%1$s[%2$s]" value="%3$s"%4$s%5$s%6$s%7$s/>',
esc_attr( $args['section'] ),
esc_attr( $args['id'] ),
esc_attr( $value ),
esc_attr( $placeholder ),
esc_attr( $min ),
esc_attr( $max ),
esc_attr( $step )
);
echo wp_kses_post( $this->get_field_description( $args ) );
?>
<?php
}
/**
* Displays a hidden field for a settings field
*
* @param array $args settings field args.
*/
public function callback_hidden( $args ) {
$value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) );
$size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
$type = isset( $args['type'] ) ? $args['type'] : 'hidden';
$placeholder = empty( $args['placeholder'] ) ? '' : ' placeholder="' . $args['placeholder'] . '"';
echo sprintf(
'<input type="%1$s" class="%2$s-text" id="%3$s[%4$s]" name="%3$s[%4$s]" value="%5$s"%6$s/>',
esc_attr( $type ),
esc_attr( $size ),
esc_attr( $args['section'] ),
esc_attr( $args['id'] ),
esc_attr( $value ),
esc_attr( $placeholder )
);
echo wp_kses_post( $this->get_field_description( $args ) );
}
/**
* Sanitize callback for Settings API
*
* @return mixed
*/
public function sanitize_options( $options ) {
if ( ! $options ) {
return $options;
}
foreach ( $options as $option_slug => $option_value ) {
$sanitize_callback = $this->get_sanitize_callback( $option_slug );
// If callback is set, call it
if ( $sanitize_callback ) {
$options[ $option_slug ] = call_user_func( $sanitize_callback, $option_value );
continue;
}
}
return $options;
}
/**
* Get sanitization callback for given option slug
*
* @param string $slug option slug
*
* @return mixed string or bool false
*/
public function get_sanitize_callback( $slug = '' ) {
if ( empty( $slug ) ) {
return false;
}
// Iterate over registered fields and see if we can find proper callback
foreach ( $this->settings_fields as $section => $options ) {
foreach ( $options as $option ) {
if ( $option['name'] != $slug ) {
continue;
}
// Return the callback name
return isset( $option['sanitize_callback'] ) && is_callable( $option['sanitize_callback'] ) ? $option['sanitize_callback'] : false;
}
}
return false;
}
/**
* Get the value of a settings field
*
* @param string $option settings field name
* @param string $section the section name this field belongs to
* @param string $default default text if it's not found
* @return string
*/
public function get_option( $option, $section, $default = '' ) {
$options = get_option( $section );
if ( isset( $options[ $option ] ) ) {
return $options[ $option ];
}
return $default;
}
/**
* Show navigations as tab
*
* Shows all the settings section labels as tab
*/
public function show_navigation() {
$html = '<h2 class="nav-tab-wrapper">';
$count = count( $this->settings_sections );
// don't show the navigation if only one section exists
if ( $count === 1 ) {
return;
}
foreach ( $this->settings_sections as $tab ) {
$html .= sprintf( '<a href="#%1$s" class="nav-tab" id="%1$s-tab">%2$s%3$s</a>', $tab['id'], isset( $tab['icon'] ) ? $tab['icon'] : '', $tab['title'] );
}
$html .= '</h2>';
echo $html;
}
/**
* Tabbable JavaScript codes & Initiate Color Picker
*
* This code uses localstorage for displaying active tabs
*/
public function script() {
?>
<script>
jQuery(function($) {
// Initiate Conditionize
$( '.metabox-holder' ).conditionize();
// Initiate Color Picker
$('.wp-color-picker-field').wpColorPicker();
// Switches option sections
$('.group').hide();
var activetab = '';
if (typeof(localStorage) != 'undefined' ) {
activetab = localStorage.getItem("activetab");
}
//if url has section id as hash then set it as active or override the current local storage value
if(window.location.hash){
activetab = window.location.hash;
if (typeof(localStorage) != 'undefined' ) {
localStorage.setItem("activetab", activetab);
}
}
if (activetab != '' && $(activetab).length ) {
$(activetab).fadeIn();
} else {
$('.group:first').fadeIn();
}
$('.group .collapsed').each(function(){
$(this).find('input:checked').parent().parent().parent().nextAll().each(
function(){
if ($(this).hasClass('last')) {
$(this).removeClass('hidden');
return false;
}
$(this).filter('.hidden').removeClass('hidden');
});
});
if (activetab != '' && $(activetab + '-tab').length ) {
$(activetab + '-tab').addClass('nav-tab-active');
}
else {
$('.nav-tab-wrapper a:first').addClass('nav-tab-active');
}
$('.nav-tab-wrapper a').click(function(evt) {
$('.nav-tab-wrapper a').removeClass('nav-tab-active');
$(this).addClass('nav-tab-active').blur();
var clicked_group = $(this).attr('href');
if (typeof(localStorage) != 'undefined' ) {
localStorage.setItem("activetab", $(this).attr('href'));
}
$('.group').hide();
$(clicked_group).fadeIn();
evt.preventDefault();
});
$('.wpsa-browse').on('click', function (event) {
event.preventDefault();
var $this = $(this);
// Create the media frame.
var file_frame = wp.media.frames.file_frame = wp.media({
title: $this.data('uploader_title'),
button: {
text: $this.data('uploader_button_text'),
},
multiple: false
});
file_frame.on('select', function () {
attachment = file_frame.state().get('selection').first().toJSON();
$this.prev('.wpsa-url').val(attachment.url).change();
});
// Finally, open the modal
file_frame.open();
});
$('.wpsa-image-browse').on('click', function(event) {
event.preventDefault();
var $this = $(this);
// Create the media frame.
var file_frame = wp.media.frames.file_frame = wp.media({
title: $this.data('uploader_title'),
button: {
text: $this.data('uploader_button_text'),
},
multiple: false,
library: { type: 'image' }
})
.on('select', function () {
attachment = file_frame.state().get('selection').first().toJSON();
var url;
if (attachment.sizes && attachment.sizes.thumbnail) {
url = attachment.sizes.thumbnail.url;
} else {
url = attachment.url;
}
$this.siblings('.wpsa-image-id').val(attachment.id).change();
$this.siblings('.wpsa-image-preview').children('img').attr('src', url);
$this.siblings('.wpsa-image-remove').css('display', 'inline-block');
$this.trigger( 'wpsa-image-browse-selected', [ attachment, url ] );
})
// Finally, open the modal
.open();
});
$('.wpsa-image-remove').each(function() {
var $this = $(this);
if ( $this.siblings('.wpsa-image-id').val() ) {
$this.css('display', 'inline-block');
}
});
$('.wpsa-image-remove').on('click', function(event) {
event.preventDefault();
var $this = $(this);
$this.siblings('.wpsa-image-id').val('').change();
$this.siblings('.wpsa-image-preview').children('img').attr('src', '');
$this.css('display', '');
$this.trigger( 'wpsa-image-removed' );
});
$( 'input.mind-range-field, input.mind-range-number-field' ).on( 'input change', function() {
const name = $( this ).attr( 'name' );
const min = parseInt( $( this ).attr( 'min' ).replace( /"/g, '' ), 10 );
const max = parseInt( $( this ).attr( 'max' ).replace( /"/g, '' ), 10 );
const val = parseInt( $( this ).val(), 10 );
const inputs = $( `input[name="${ name }"]` );
if ( max < val ) {
$( this ).val( max );
}
if ( min > val || isNaN( val ) ) {
$( this ).val( min );
}
if ( $( inputs[ 0 ] ).val() !== $( inputs[ 1 ] ).val() ) {
inputs.val( $( this ).val() );
}
});
});
</script>
<?php
}
/**
* Show the section settings forms
*
* This function displays every sections in a different form
*/
public function show_forms() {
?>
<div class="metabox-holder">
<?php foreach ( $this->settings_sections as $form ) {
echo apply_filters( 'mind_settings_show_section_form', $this->get_form( $form ), $form );
} ?>
</div>
<?php
$this->script();
}
/**
* Prints out all settings sections added to a particular settings page
*
* Part of the Settings API. Use this in a settings page callback function
* to output all the sections and fields that were added to that $page with
* add_settings_section() and add_settings_field()
*
* @global array $wp_settings_sections Storage array of all settings sections added to admin pages.
* @global array $wp_settings_fields Storage array of settings fields and info about their pages/sections.
*
* @param string $page The slug name of the page whose settings sections you want to output.
*/
public function do_settings_sections( $page ) {
global $wp_settings_sections, $wp_settings_fields;
if ( ! isset( $wp_settings_sections[ $page ] ) ) {
return;
}
foreach ( (array) $wp_settings_sections[ $page ] as $section ) {
if ( $section['callback'] ) {
call_user_func( $section['callback'], $section );
}
if ( ! isset( $wp_settings_fields ) || ! isset( $wp_settings_fields[ $page ] ) || ! isset( $wp_settings_fields[ $page ][ $section['id'] ] ) ) {
continue;
}
echo '<table class="form-table" role="presentation">';
$this->do_settings_fields( $page, $section['id'] );
echo '</table>';
}
}
/**
* Get the section settings form.
* This function return displays detailed section in a each of forms.
*
* @param array $form - Form item.
* @return string
*/
public function get_form( $form ) {
ob_start();
?>
<div id="<?php echo $form['id']; ?>" class="group" style="display: none;">
<form method="post" action="options.php">
<?php
do_action( 'wsa_form_top_' . $form['id'], $form );
settings_fields( $form['id'] );
$this->do_settings_sections( $form['id'] );
do_action( 'wsa_form_bottom_' . $form['id'], $form );
if ( isset( $this->settings_fields[ $form['id'] ] ) ) :
?>
<div class="metabox-holder-footer">
<?php submit_button(); ?>
</div>
<?php endif; ?>
</form>
</div>
<?php
return ob_get_clean();
}
/**
* Print out the settings fields for a particular settings section.
*
* Part of the Settings API. Use this in a settings page to output
* a specific section. Should normally be called by do_settings_sections()
* rather than directly.
*
* @global array $wp_settings_fields Storage array of settings fields and their pages/sections.
*
* @param string $page Slug title of the admin page whose settings fields you want to show.
* @param string $section Slug title of the settings section whose fields you want to show.
*/
public function do_settings_fields( $page, $section ) {
global $wp_settings_fields;
if ( ! isset( $wp_settings_fields[ $page ][ $section ] ) ) {
return;
}
foreach ( (array) $wp_settings_fields[ $page ][ $section ] as $field ) {
$class = '';
$condition = '';
$style = '';
if ( ! empty( $field['args']['class'] ) ) {
$class = $field['args']['class'];
}
if ( isset( $field['args']['type'] ) ) {
$class .= ' mind-setting-type-' . $field['args']['type'];
}
if ( isset( $field['args']['conditionize'] ) && ! empty( $field['args']['conditionize'] ) ) {
$condition = ' data-cond="' . esc_attr( $field['args']['conditionize'] ) . '"';
}
if ( ! empty( $class ) ) {
$class = ' class="' . esc_attr( $class ) . '"';
}
echo "<tr{$class}{$condition}{$style}>";
if ( ! empty( $field['args']['label_for'] ) ) {
echo '<th scope="row"><label for="' . esc_attr( $field['args']['label_for'] ) . '">' . $field['title'] . '</label></th>';
} else {
echo '<th scope="row">' . $field['title'] . '</th>';
}
echo '<td>';
call_user_func( $field['callback'], $field['args'] );
echo '</td>';
echo '</tr>';
}
}
/**
* Convert condition arguments to Conditionize string.
*
* @param array $conditions - Array with Condition arguments.
* @return string
*/
public function convert_arguments_to_conditionize_string( $conditions ) {
$data_condition = '';
if ( isset( $conditions ) && is_array( $conditions ) && ! empty( $conditions ) ) {
foreach ( $conditions as $key => $condition ) {
$condition['value'] = empty( $condition['value'] ) ? "''" : ( '' . $condition['value'] );
$data_condition .= $condition['control'];
if ( isset( $condition['operator'] ) && isset( $condition['value'] ) ) {
$data_condition .= ' ' . $condition['operator'] . ' ' . $condition['value'];
}
if ( 1 < count( $conditions ) && ( count( $conditions ) - 1 ) !== $key ) {
$data_condition .= ' && ';
}
}
}
return $data_condition;
}
}

9
webpack-hot-config.js Normal file
View file

@ -0,0 +1,9 @@
const defaultConfig = require('@wordpress/scripts/config/webpack.config');
module.exports = {
...defaultConfig,
devServer: {
...defaultConfig.devServer,
allowedHosts: 'all',
},
};