├── .editorconfig ├── .gitignore ├── build ├── index.asset.php ├── index.js └── index.js.map ├── core-block-custom-attributes.php ├── package-lock.json ├── package.json ├── readme.txt └── src ├── attributes ├── sidebarSelect.js └── toolbarButton.js └── index.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | # WordPress Coding Standards 5 | # https://make.wordpress.org/core/handbook/coding-standards/ 6 | 7 | root = true 8 | 9 | [*] 10 | charset = utf-8 11 | end_of_line = lf 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | indent_style = tab 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Coverage directory used by tools like istanbul 9 | coverage 10 | 11 | # Compiled binary addons (https://nodejs.org/api/addons.html) 12 | build/Release 13 | 14 | # Dependency directories 15 | node_modules/ 16 | 17 | # Optional npm cache directory 18 | .npm 19 | 20 | # Optional eslint cache 21 | .eslintcache 22 | 23 | # Output of 'npm pack' 24 | *.tgz 25 | 26 | # dotenv environment variables file 27 | .env 28 | -------------------------------------------------------------------------------- /build/index.asset.php: -------------------------------------------------------------------------------- 1 | array('wp-element'), 'version' => '5b0b5d21bb8aeab7f9f385ea9a3050fa'); -------------------------------------------------------------------------------- /build/index.js: -------------------------------------------------------------------------------- 1 | /******/ (function() { // webpackBootstrap 2 | /******/ var __webpack_modules__ = ({ 3 | 4 | /***/ "./src/attributes/sidebarSelect.js": 5 | /*!*****************************************!*\ 6 | !*** ./src/attributes/sidebarSelect.js ***! 7 | \*****************************************/ 8 | /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { 9 | 10 | "use strict"; 11 | __webpack_require__.r(__webpack_exports__); 12 | /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/extends */ "./node_modules/@babel/runtime/helpers/esm/extends.js"); 13 | /* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element"); 14 | /* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_1__); 15 | /* harmony import */ var classnames__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! classnames */ "./node_modules/classnames/index.js"); 16 | /* harmony import */ var classnames__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(classnames__WEBPACK_IMPORTED_MODULE_2__); 17 | 18 | 19 | 20 | /* Add custom attribute to image block, in Sidebar */ 21 | const { 22 | __ 23 | } = wp.i18n; // Enable custom attributes on Image block 24 | 25 | const enableSidebarSelectOnBlocks = ['core/image']; 26 | const { 27 | createHigherOrderComponent 28 | } = wp.compose; 29 | const { 30 | Fragment 31 | } = wp.element; 32 | const { 33 | InspectorControls 34 | } = wp.blockEditor; 35 | const { 36 | PanelBody, 37 | SelectControl 38 | } = wp.components; 39 | 40 | /** 41 | * Declare our custom attribute 42 | */ 43 | 44 | const setSidebarSelectAttribute = (settings, name) => { 45 | // Do nothing if it's another block than our defined ones. 46 | if (!enableSidebarSelectOnBlocks.includes(name)) { 47 | return settings; 48 | } 49 | 50 | return Object.assign({}, settings, { 51 | attributes: Object.assign({}, settings.attributes, { 52 | imageAttribute: { 53 | type: 'string' 54 | } 55 | }) 56 | }); 57 | }; 58 | 59 | wp.hooks.addFilter('blocks.registerBlockType', 'custom-attributes/set-sidebar-select-attribute', setSidebarSelectAttribute); 60 | /** 61 | * Add Custom Select to Image Sidebar 62 | */ 63 | 64 | const withSidebarSelect = createHigherOrderComponent(BlockEdit => { 65 | return props => { 66 | // If current block is not allowed 67 | if (!enableSidebarSelectOnBlocks.includes(props.name)) { 68 | return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(BlockEdit, props); 69 | } 70 | 71 | const { 72 | attributes, 73 | setAttributes 74 | } = props; 75 | const { 76 | imageAttribute 77 | } = attributes; 78 | return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(Fragment, null, (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(BlockEdit, props), (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(InspectorControls, null, (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(PanelBody, { 79 | title: __('Image Custom Attributes') 80 | }, (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(SelectControl, { 81 | label: __('Custom Attribute'), 82 | value: imageAttribute, 83 | options: [{ 84 | label: __('None'), 85 | value: '' 86 | }, { 87 | label: __('One'), 88 | value: 'one' 89 | }], 90 | onChange: value => { 91 | setAttributes({ 92 | imageAttribute: value 93 | }); 94 | } 95 | })))); 96 | }; 97 | }, 'withSidebarSelect'); 98 | wp.hooks.addFilter('editor.BlockEdit', 'custom-attributes/with-sidebar-select', withSidebarSelect); 99 | /** 100 | * Add custom class to block in Edit 101 | */ 102 | 103 | const withSidebarSelectProp = createHigherOrderComponent(BlockListBlock => { 104 | return props => { 105 | // If current block is not allowed 106 | if (!enableSidebarSelectOnBlocks.includes(props.name)) { 107 | return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(BlockListBlock, props); 108 | } 109 | 110 | const { 111 | attributes 112 | } = props; 113 | const { 114 | imageAttribute 115 | } = attributes; 116 | 117 | if (imageAttribute) { 118 | return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(BlockListBlock, (0,_babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__["default"])({}, props, { 119 | className: 'has-option-' + imageAttribute 120 | })); 121 | } else { 122 | return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(BlockListBlock, props); 123 | } 124 | }; 125 | }, 'withSidebarSelectProp'); 126 | wp.hooks.addFilter('editor.BlockListBlock', 'custom-attributes/with-sidebar-select-prop', withSidebarSelectProp); 127 | /** 128 | * Save our custom attribute 129 | */ 130 | 131 | const saveSidebarSelectAttribute = (extraProps, blockType, attributes) => { 132 | // Do nothing if it's another block than our defined ones. 133 | if (enableSidebarSelectOnBlocks.includes(blockType.name)) { 134 | const { 135 | imageAttribute 136 | } = attributes; 137 | 138 | if (imageAttribute) { 139 | extraProps.className = classnames__WEBPACK_IMPORTED_MODULE_2___default()(extraProps.className, 'has-option-' + imageAttribute); 140 | } 141 | } 142 | 143 | return extraProps; 144 | }; 145 | 146 | wp.hooks.addFilter('blocks.getSaveContent.extraProps', 'custom-attributes/save-sidebar-select-attribute', saveSidebarSelectAttribute); 147 | 148 | /***/ }), 149 | 150 | /***/ "./src/attributes/toolbarButton.js": 151 | /*!*****************************************!*\ 152 | !*** ./src/attributes/toolbarButton.js ***! 153 | \*****************************************/ 154 | /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { 155 | 156 | "use strict"; 157 | __webpack_require__.r(__webpack_exports__); 158 | /* harmony import */ var _babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/extends */ "./node_modules/@babel/runtime/helpers/esm/extends.js"); 159 | /* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element"); 160 | /* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_1__); 161 | /* harmony import */ var classnames__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! classnames */ "./node_modules/classnames/index.js"); 162 | /* harmony import */ var classnames__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(classnames__WEBPACK_IMPORTED_MODULE_2__); 163 | 164 | 165 | 166 | /* Add custom attribute to paragraph block, in Toolbar */ 167 | const { 168 | __ 169 | } = wp.i18n; // Enable custom attributes on Paragraph block 170 | 171 | const enableToolbarButtonOnBlocks = ['core/paragraph']; 172 | const { 173 | createHigherOrderComponent 174 | } = wp.compose; 175 | const { 176 | Fragment 177 | } = wp.element; 178 | const { 179 | BlockControls 180 | } = wp.blockEditor; 181 | const { 182 | ToolbarGroup, 183 | ToolbarButton 184 | } = wp.components; 185 | 186 | /** 187 | * Declare our custom attribute 188 | */ 189 | 190 | const setToolbarButtonAttribute = (settings, name) => { 191 | // Do nothing if it's another block than our defined ones. 192 | if (!enableToolbarButtonOnBlocks.includes(name)) { 193 | return settings; 194 | } 195 | 196 | return Object.assign({}, settings, { 197 | attributes: Object.assign({}, settings.attributes, { 198 | paragraphAttribute: { 199 | type: 'string' 200 | } 201 | }) 202 | }); 203 | }; 204 | 205 | wp.hooks.addFilter('blocks.registerBlockType', 'custom-attributes/set-toolbar-button-attribute', setToolbarButtonAttribute); 206 | /** 207 | * Add Custom Button to Paragraph Toolbar 208 | */ 209 | 210 | const withToolbarButton = createHigherOrderComponent(BlockEdit => { 211 | return props => { 212 | // If current block is not allowed 213 | if (!enableToolbarButtonOnBlocks.includes(props.name)) { 214 | return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(BlockEdit, props); 215 | } 216 | 217 | const { 218 | attributes, 219 | setAttributes 220 | } = props; 221 | const { 222 | paragraphAttribute 223 | } = attributes; 224 | return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(Fragment, null, (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(BlockControls, { 225 | group: "block" 226 | }, (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(ToolbarGroup, null, (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(ToolbarButton, { 227 | icon: "format-status", 228 | label: __('Custom Button', 'core-block-custom-attributes'), 229 | isActive: paragraphAttribute === 'custom', 230 | onClick: () => { 231 | if (paragraphAttribute === 'custom') { 232 | setAttributes({ 233 | paragraphAttribute: false 234 | }); 235 | } else { 236 | setAttributes({ 237 | paragraphAttribute: 'custom' 238 | }); 239 | } 240 | } 241 | }))), (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(BlockEdit, props)); 242 | }; 243 | }, 'withToolbarButton'); 244 | wp.hooks.addFilter('editor.BlockEdit', 'custom-attributes/with-toolbar-button', withToolbarButton); 245 | /** 246 | * Add custom class to block in Edit 247 | */ 248 | 249 | const withToolbarButtonProp = createHigherOrderComponent(BlockListBlock => { 250 | return props => { 251 | // If current block is not allowed 252 | if (!enableToolbarButtonOnBlocks.includes(props.name)) { 253 | return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(BlockListBlock, props); 254 | } 255 | 256 | const { 257 | attributes 258 | } = props; 259 | const { 260 | paragraphAttribute 261 | } = attributes; 262 | 263 | if (paragraphAttribute && 'custom' === paragraphAttribute) { 264 | return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(BlockListBlock, (0,_babel_runtime_helpers_extends__WEBPACK_IMPORTED_MODULE_0__["default"])({}, props, { 265 | className: 'has-custom-attribute' 266 | })); 267 | } else { 268 | return (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_1__.createElement)(BlockListBlock, props); 269 | } 270 | }; 271 | }, 'withToolbarButtonProp'); 272 | wp.hooks.addFilter('editor.BlockListBlock', 'custom-attributes/with-toolbar-button-prop', withToolbarButtonProp); 273 | /** 274 | * Save our custom attribute 275 | */ 276 | 277 | const saveToolbarButtonAttribute = (extraProps, blockType, attributes) => { 278 | // Do nothing if it's another block than our defined ones. 279 | if (enableToolbarButtonOnBlocks.includes(blockType.name)) { 280 | const { 281 | paragraphAttribute 282 | } = attributes; 283 | 284 | if (paragraphAttribute && 'custom' === paragraphAttribute) { 285 | extraProps.className = classnames__WEBPACK_IMPORTED_MODULE_2___default()(extraProps.className, 'has-custom-attribute'); 286 | } 287 | } 288 | 289 | return extraProps; 290 | }; 291 | 292 | wp.hooks.addFilter('blocks.getSaveContent.extraProps', 'custom-attributes/save-toolbar-button-attribute', saveToolbarButtonAttribute); 293 | 294 | /***/ }), 295 | 296 | /***/ "./node_modules/classnames/index.js": 297 | /*!******************************************!*\ 298 | !*** ./node_modules/classnames/index.js ***! 299 | \******************************************/ 300 | /***/ (function(module, exports) { 301 | 302 | var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! 303 | Copyright (c) 2018 Jed Watson. 304 | Licensed under the MIT License (MIT), see 305 | http://jedwatson.github.io/classnames 306 | */ 307 | /* global define */ 308 | 309 | (function () { 310 | 'use strict'; 311 | 312 | var hasOwn = {}.hasOwnProperty; 313 | 314 | function classNames() { 315 | var classes = []; 316 | 317 | for (var i = 0; i < arguments.length; i++) { 318 | var arg = arguments[i]; 319 | if (!arg) continue; 320 | 321 | var argType = typeof arg; 322 | 323 | if (argType === 'string' || argType === 'number') { 324 | classes.push(arg); 325 | } else if (Array.isArray(arg)) { 326 | if (arg.length) { 327 | var inner = classNames.apply(null, arg); 328 | if (inner) { 329 | classes.push(inner); 330 | } 331 | } 332 | } else if (argType === 'object') { 333 | if (arg.toString === Object.prototype.toString) { 334 | for (var key in arg) { 335 | if (hasOwn.call(arg, key) && arg[key]) { 336 | classes.push(key); 337 | } 338 | } 339 | } else { 340 | classes.push(arg.toString()); 341 | } 342 | } 343 | } 344 | 345 | return classes.join(' '); 346 | } 347 | 348 | if ( true && module.exports) { 349 | classNames.default = classNames; 350 | module.exports = classNames; 351 | } else if (true) { 352 | // register as 'classnames', consistent with npm package name 353 | !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function () { 354 | return classNames; 355 | }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), 356 | __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); 357 | } else {} 358 | }()); 359 | 360 | 361 | /***/ }), 362 | 363 | /***/ "@wordpress/element": 364 | /*!*********************************!*\ 365 | !*** external ["wp","element"] ***! 366 | \*********************************/ 367 | /***/ (function(module) { 368 | 369 | "use strict"; 370 | module.exports = window["wp"]["element"]; 371 | 372 | /***/ }), 373 | 374 | /***/ "./node_modules/@babel/runtime/helpers/esm/extends.js": 375 | /*!************************************************************!*\ 376 | !*** ./node_modules/@babel/runtime/helpers/esm/extends.js ***! 377 | \************************************************************/ 378 | /***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 379 | 380 | "use strict"; 381 | __webpack_require__.r(__webpack_exports__); 382 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 383 | /* harmony export */ "default": function() { return /* binding */ _extends; } 384 | /* harmony export */ }); 385 | function _extends() { 386 | _extends = Object.assign || function (target) { 387 | for (var i = 1; i < arguments.length; i++) { 388 | var source = arguments[i]; 389 | 390 | for (var key in source) { 391 | if (Object.prototype.hasOwnProperty.call(source, key)) { 392 | target[key] = source[key]; 393 | } 394 | } 395 | } 396 | 397 | return target; 398 | }; 399 | 400 | return _extends.apply(this, arguments); 401 | } 402 | 403 | /***/ }) 404 | 405 | /******/ }); 406 | /************************************************************************/ 407 | /******/ // The module cache 408 | /******/ var __webpack_module_cache__ = {}; 409 | /******/ 410 | /******/ // The require function 411 | /******/ function __webpack_require__(moduleId) { 412 | /******/ // Check if module is in cache 413 | /******/ var cachedModule = __webpack_module_cache__[moduleId]; 414 | /******/ if (cachedModule !== undefined) { 415 | /******/ return cachedModule.exports; 416 | /******/ } 417 | /******/ // Create a new module (and put it into the cache) 418 | /******/ var module = __webpack_module_cache__[moduleId] = { 419 | /******/ // no module.id needed 420 | /******/ // no module.loaded needed 421 | /******/ exports: {} 422 | /******/ }; 423 | /******/ 424 | /******/ // Execute the module function 425 | /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); 426 | /******/ 427 | /******/ // Return the exports of the module 428 | /******/ return module.exports; 429 | /******/ } 430 | /******/ 431 | /************************************************************************/ 432 | /******/ /* webpack/runtime/compat get default export */ 433 | /******/ !function() { 434 | /******/ // getDefaultExport function for compatibility with non-harmony modules 435 | /******/ __webpack_require__.n = function(module) { 436 | /******/ var getter = module && module.__esModule ? 437 | /******/ function() { return module['default']; } : 438 | /******/ function() { return module; }; 439 | /******/ __webpack_require__.d(getter, { a: getter }); 440 | /******/ return getter; 441 | /******/ }; 442 | /******/ }(); 443 | /******/ 444 | /******/ /* webpack/runtime/define property getters */ 445 | /******/ !function() { 446 | /******/ // define getter functions for harmony exports 447 | /******/ __webpack_require__.d = function(exports, definition) { 448 | /******/ for(var key in definition) { 449 | /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { 450 | /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); 451 | /******/ } 452 | /******/ } 453 | /******/ }; 454 | /******/ }(); 455 | /******/ 456 | /******/ /* webpack/runtime/hasOwnProperty shorthand */ 457 | /******/ !function() { 458 | /******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } 459 | /******/ }(); 460 | /******/ 461 | /******/ /* webpack/runtime/make namespace object */ 462 | /******/ !function() { 463 | /******/ // define __esModule on exports 464 | /******/ __webpack_require__.r = function(exports) { 465 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 466 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 467 | /******/ } 468 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 469 | /******/ }; 470 | /******/ }(); 471 | /******/ 472 | /************************************************************************/ 473 | var __webpack_exports__ = {}; 474 | // This entry need to be wrapped in an IIFE because it need to be in strict mode. 475 | !function() { 476 | "use strict"; 477 | /*!**********************!*\ 478 | !*** ./src/index.js ***! 479 | \**********************/ 480 | __webpack_require__.r(__webpack_exports__); 481 | /* harmony import */ var _attributes_toolbarButton__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./attributes/toolbarButton */ "./src/attributes/toolbarButton.js"); 482 | /* harmony import */ var _attributes_sidebarSelect__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./attributes/sidebarSelect */ "./src/attributes/sidebarSelect.js"); 483 | 484 | 485 | }(); 486 | /******/ })() 487 | ; 488 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /build/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","mappings":"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","sources":["webpack://core-block-custom-attributes/./src/attributes/sidebarSelect.js","webpack://core-block-custom-attributes/./src/attributes/toolbarButton.js","webpack://core-block-custom-attributes/./node_modules/classnames/index.js","webpack://core-block-custom-attributes/external window [\"wp\",\"element\"]","webpack://core-block-custom-attributes/./node_modules/@babel/runtime/helpers/esm/extends.js","webpack://core-block-custom-attributes/webpack/bootstrap","webpack://core-block-custom-attributes/webpack/runtime/compat get default export","webpack://core-block-custom-attributes/webpack/runtime/define property getters","webpack://core-block-custom-attributes/webpack/runtime/hasOwnProperty shorthand","webpack://core-block-custom-attributes/webpack/runtime/make namespace object","webpack://core-block-custom-attributes/./src/index.js"],"sourcesContent":["/* Add custom attribute to image block, in Sidebar */\nconst { __ } = wp.i18n;\n\n// Enable custom attributes on Image block\nconst enableSidebarSelectOnBlocks = [\n 'core/image'\n];\n\nconst { createHigherOrderComponent } = wp.compose;\nconst { Fragment } = wp.element;\nconst { InspectorControls } = wp.blockEditor;\nconst { PanelBody, SelectControl } = wp.components;\n\nimport classnames from 'classnames'\n\n/**\n * Declare our custom attribute\n */\nconst setSidebarSelectAttribute = ( settings, name ) => {\n // Do nothing if it's another block than our defined ones.\n if ( ! enableSidebarSelectOnBlocks.includes( name ) ) {\n return settings;\n }\n\n return Object.assign( {}, settings, {\n attributes: Object.assign( {}, settings.attributes, {\n imageAttribute: { type: 'string' }\n } ),\n } );\n};\nwp.hooks.addFilter(\n 'blocks.registerBlockType',\n 'custom-attributes/set-sidebar-select-attribute',\n setSidebarSelectAttribute\n);\n\n/**\n * Add Custom Select to Image Sidebar\n */\nconst withSidebarSelect = createHigherOrderComponent( ( BlockEdit ) => {\n return ( props ) => {\n\n // If current block is not allowed\n \tif ( ! enableSidebarSelectOnBlocks.includes( props.name ) ) {\n return (\n \n );\n }\n\n const { attributes, setAttributes } = props;\n const { imageAttribute } = attributes;\n\n return (\n \n \n \n \t\n\t {\n setAttributes( {\n imageAttribute: value,\n } );\n } }\n /> \n\t \n \n \n );\n };\n}, 'withSidebarSelect' );\n\nwp.hooks.addFilter(\n 'editor.BlockEdit',\n 'custom-attributes/with-sidebar-select',\n withSidebarSelect\n);\n\n\n/**\n * Add custom class to block in Edit\n */\nconst withSidebarSelectProp = createHigherOrderComponent( ( BlockListBlock ) => {\n return ( props ) => {\n\n // If current block is not allowed\n if ( ! enableSidebarSelectOnBlocks.includes( props.name ) ) {\n return (\n \n );\n }\n\n const { attributes } = props;\n const { imageAttribute } = attributes;\n\n if ( imageAttribute ) {\n return \n } else {\n return \n }\n };\n}, 'withSidebarSelectProp' );\n\nwp.hooks.addFilter(\n 'editor.BlockListBlock',\n 'custom-attributes/with-sidebar-select-prop',\n withSidebarSelectProp\n);\n\n\n/**\n * Save our custom attribute\n */\nconst saveSidebarSelectAttribute = ( extraProps, blockType, attributes ) => {\n // Do nothing if it's another block than our defined ones.\n if ( enableSidebarSelectOnBlocks.includes( blockType.name ) ) {\n const { imageAttribute } = attributes;\n if ( imageAttribute ) {\n extraProps.className = classnames( extraProps.className, 'has-option-' + imageAttribute )\n }\n } \n\n return extraProps;\n\n};\nwp.hooks.addFilter(\n 'blocks.getSaveContent.extraProps',\n 'custom-attributes/save-sidebar-select-attribute',\n saveSidebarSelectAttribute\n);","/* Add custom attribute to paragraph block, in Toolbar */\nconst { __ } = wp.i18n;\n\n// Enable custom attributes on Paragraph block\nconst enableToolbarButtonOnBlocks = [\n 'core/paragraph'\n];\n\nconst { createHigherOrderComponent } = wp.compose;\nconst { Fragment } = wp.element;\nconst { BlockControls } = wp.blockEditor;\nconst {\n ToolbarGroup,\n ToolbarButton\n} = wp.components;\n\nimport classnames from 'classnames'\n\n/**\n * Declare our custom attribute\n */\nconst setToolbarButtonAttribute = ( settings, name ) => {\n // Do nothing if it's another block than our defined ones.\n if ( ! enableToolbarButtonOnBlocks.includes( name ) ) {\n return settings;\n }\n\n return Object.assign( {}, settings, {\n attributes: Object.assign( {}, settings.attributes, {\n paragraphAttribute: { type: 'string' }\n } ),\n } );\n};\nwp.hooks.addFilter(\n 'blocks.registerBlockType',\n 'custom-attributes/set-toolbar-button-attribute',\n setToolbarButtonAttribute\n);\n\n/**\n * Add Custom Button to Paragraph Toolbar\n */\nconst withToolbarButton = createHigherOrderComponent( ( BlockEdit ) => {\n return ( props ) => {\n\n // If current block is not allowed\n \tif ( ! enableToolbarButtonOnBlocks.includes( props.name ) ) {\n return (\n \n );\n }\n\n const { attributes, setAttributes } = props;\n const { paragraphAttribute } = attributes;\n\n return (\n \n \n \n {\n if ( paragraphAttribute === 'custom' ) {\n setAttributes( { paragraphAttribute: false } )\n } else {\n setAttributes( { paragraphAttribute: 'custom' } )\n }\n } }\n />\n \n \n \n \n );\n };\n}, 'withToolbarButton' );\n\nwp.hooks.addFilter(\n 'editor.BlockEdit',\n 'custom-attributes/with-toolbar-button',\n withToolbarButton\n);\n\n\n/**\n * Add custom class to block in Edit\n */\nconst withToolbarButtonProp = createHigherOrderComponent( ( BlockListBlock ) => {\n return ( props ) => {\n\n // If current block is not allowed\n if ( ! enableToolbarButtonOnBlocks.includes( props.name ) ) {\n return (\n \n );\n }\n\n const { attributes } = props;\n const { paragraphAttribute } = attributes;\n\n if ( paragraphAttribute && 'custom' === paragraphAttribute ) {\n return \n } else {\n return \n }\n };\n}, 'withToolbarButtonProp' );\n\nwp.hooks.addFilter(\n 'editor.BlockListBlock',\n 'custom-attributes/with-toolbar-button-prop',\n withToolbarButtonProp\n);\n\n\n/**\n * Save our custom attribute\n */\nconst saveToolbarButtonAttribute = ( extraProps, blockType, attributes ) => {\n // Do nothing if it's another block than our defined ones.\n if ( enableToolbarButtonOnBlocks.includes( blockType.name ) ) {\n const { paragraphAttribute } = attributes;\n if ( paragraphAttribute && 'custom' === paragraphAttribute ) {\n extraProps.className = classnames( extraProps.className, 'has-custom-attribute' )\n }\n } \n\n return extraProps;\n\n};\nwp.hooks.addFilter(\n 'blocks.getSaveContent.extraProps',\n 'custom-attributes/save-toolbar-button-attribute',\n saveToolbarButtonAttribute\n);","/*!\n Copyright (c) 2018 Jed Watson.\n Licensed under the MIT License (MIT), see\n http://jedwatson.github.io/classnames\n*/\n/* global define */\n\n(function () {\n\t'use strict';\n\n\tvar hasOwn = {}.hasOwnProperty;\n\n\tfunction classNames() {\n\t\tvar classes = [];\n\n\t\tfor (var i = 0; i < arguments.length; i++) {\n\t\t\tvar arg = arguments[i];\n\t\t\tif (!arg) continue;\n\n\t\t\tvar argType = typeof arg;\n\n\t\t\tif (argType === 'string' || argType === 'number') {\n\t\t\t\tclasses.push(arg);\n\t\t\t} else if (Array.isArray(arg)) {\n\t\t\t\tif (arg.length) {\n\t\t\t\t\tvar inner = classNames.apply(null, arg);\n\t\t\t\t\tif (inner) {\n\t\t\t\t\t\tclasses.push(inner);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (argType === 'object') {\n\t\t\t\tif (arg.toString === Object.prototype.toString) {\n\t\t\t\t\tfor (var key in arg) {\n\t\t\t\t\t\tif (hasOwn.call(arg, key) && arg[key]) {\n\t\t\t\t\t\t\tclasses.push(key);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tclasses.push(arg.toString());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn classes.join(' ');\n\t}\n\n\tif (typeof module !== 'undefined' && module.exports) {\n\t\tclassNames.default = classNames;\n\t\tmodule.exports = classNames;\n\t} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {\n\t\t// register as 'classnames', consistent with npm package name\n\t\tdefine('classnames', [], function () {\n\t\t\treturn classNames;\n\t\t});\n\t} else {\n\t\twindow.classNames = classNames;\n\t}\n}());\n","module.exports = window[\"wp\"][\"element\"];","export default function _extends() {\n _extends = Object.assign || function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n\n return target;\n };\n\n return _extends.apply(this, arguments);\n}","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = function(module) {\n\tvar getter = module && module.__esModule ?\n\t\tfunction() { return module['default']; } :\n\t\tfunction() { return module; };\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import './attributes/toolbarButton';\nimport './attributes/sidebarSelect'; "],"names":["__","wp","i18n","enableSidebarSelectOnBlocks","createHigherOrderComponent","compose","Fragment","element","InspectorControls","blockEditor","PanelBody","SelectControl","components","classnames","setSidebarSelectAttribute","settings","name","includes","Object","assign","attributes","imageAttribute","type","hooks","addFilter","withSidebarSelect","BlockEdit","props","setAttributes","label","value","withSidebarSelectProp","BlockListBlock","saveSidebarSelectAttribute","extraProps","blockType","className","enableToolbarButtonOnBlocks","BlockControls","ToolbarGroup","ToolbarButton","setToolbarButtonAttribute","paragraphAttribute","withToolbarButton","withToolbarButtonProp","saveToolbarButtonAttribute"],"sourceRoot":""} -------------------------------------------------------------------------------- /core-block-custom-attributes.php: -------------------------------------------------------------------------------- 1 | { 20 | // Do nothing if it's another block than our defined ones. 21 | if ( ! enableSidebarSelectOnBlocks.includes( name ) ) { 22 | return settings; 23 | } 24 | 25 | return Object.assign( {}, settings, { 26 | attributes: Object.assign( {}, settings.attributes, { 27 | imageAttribute: { type: 'string' } 28 | } ), 29 | } ); 30 | }; 31 | wp.hooks.addFilter( 32 | 'blocks.registerBlockType', 33 | 'custom-attributes/set-sidebar-select-attribute', 34 | setSidebarSelectAttribute 35 | ); 36 | 37 | /** 38 | * Add Custom Select to Image Sidebar 39 | */ 40 | const withSidebarSelect = createHigherOrderComponent( ( BlockEdit ) => { 41 | return ( props ) => { 42 | 43 | // If current block is not allowed 44 | if ( ! enableSidebarSelectOnBlocks.includes( props.name ) ) { 45 | return ( 46 | 47 | ); 48 | } 49 | 50 | const { attributes, setAttributes } = props; 51 | const { imageAttribute } = attributes; 52 | 53 | return ( 54 | 55 | 56 | 57 | 60 | { 74 | setAttributes( { 75 | imageAttribute: value, 76 | } ); 77 | } } 78 | /> 79 | 80 | 81 | 82 | ); 83 | }; 84 | }, 'withSidebarSelect' ); 85 | 86 | wp.hooks.addFilter( 87 | 'editor.BlockEdit', 88 | 'custom-attributes/with-sidebar-select', 89 | withSidebarSelect 90 | ); 91 | 92 | 93 | /** 94 | * Add custom class to block in Edit 95 | */ 96 | const withSidebarSelectProp = createHigherOrderComponent( ( BlockListBlock ) => { 97 | return ( props ) => { 98 | 99 | // If current block is not allowed 100 | if ( ! enableSidebarSelectOnBlocks.includes( props.name ) ) { 101 | return ( 102 | 103 | ); 104 | } 105 | 106 | const { attributes } = props; 107 | const { imageAttribute } = attributes; 108 | 109 | if ( imageAttribute ) { 110 | return 111 | } else { 112 | return 113 | } 114 | }; 115 | }, 'withSidebarSelectProp' ); 116 | 117 | wp.hooks.addFilter( 118 | 'editor.BlockListBlock', 119 | 'custom-attributes/with-sidebar-select-prop', 120 | withSidebarSelectProp 121 | ); 122 | 123 | 124 | /** 125 | * Save our custom attribute 126 | */ 127 | const saveSidebarSelectAttribute = ( extraProps, blockType, attributes ) => { 128 | // Do nothing if it's another block than our defined ones. 129 | if ( enableSidebarSelectOnBlocks.includes( blockType.name ) ) { 130 | const { imageAttribute } = attributes; 131 | if ( imageAttribute ) { 132 | extraProps.className = classnames( extraProps.className, 'has-option-' + imageAttribute ) 133 | } 134 | } 135 | 136 | return extraProps; 137 | 138 | }; 139 | wp.hooks.addFilter( 140 | 'blocks.getSaveContent.extraProps', 141 | 'custom-attributes/save-sidebar-select-attribute', 142 | saveSidebarSelectAttribute 143 | ); -------------------------------------------------------------------------------- /src/attributes/toolbarButton.js: -------------------------------------------------------------------------------- 1 | /* Add custom attribute to paragraph block, in Toolbar */ 2 | const { __ } = wp.i18n; 3 | 4 | // Enable custom attributes on Paragraph block 5 | const enableToolbarButtonOnBlocks = [ 6 | 'core/paragraph' 7 | ]; 8 | 9 | const { createHigherOrderComponent } = wp.compose; 10 | const { Fragment } = wp.element; 11 | const { BlockControls } = wp.blockEditor; 12 | const { 13 | ToolbarGroup, 14 | ToolbarButton 15 | } = wp.components; 16 | 17 | import classnames from 'classnames' 18 | 19 | /** 20 | * Declare our custom attribute 21 | */ 22 | const setToolbarButtonAttribute = ( settings, name ) => { 23 | // Do nothing if it's another block than our defined ones. 24 | if ( ! enableToolbarButtonOnBlocks.includes( name ) ) { 25 | return settings; 26 | } 27 | 28 | return Object.assign( {}, settings, { 29 | attributes: Object.assign( {}, settings.attributes, { 30 | paragraphAttribute: { type: 'string' } 31 | } ), 32 | } ); 33 | }; 34 | wp.hooks.addFilter( 35 | 'blocks.registerBlockType', 36 | 'custom-attributes/set-toolbar-button-attribute', 37 | setToolbarButtonAttribute 38 | ); 39 | 40 | /** 41 | * Add Custom Button to Paragraph Toolbar 42 | */ 43 | const withToolbarButton = createHigherOrderComponent( ( BlockEdit ) => { 44 | return ( props ) => { 45 | 46 | // If current block is not allowed 47 | if ( ! enableToolbarButtonOnBlocks.includes( props.name ) ) { 48 | return ( 49 | 50 | ); 51 | } 52 | 53 | const { attributes, setAttributes } = props; 54 | const { paragraphAttribute } = attributes; 55 | 56 | return ( 57 | 58 | 59 | 60 | { 65 | if ( paragraphAttribute === 'custom' ) { 66 | setAttributes( { paragraphAttribute: false } ) 67 | } else { 68 | setAttributes( { paragraphAttribute: 'custom' } ) 69 | } 70 | } } 71 | /> 72 | 73 | 74 | 75 | 76 | ); 77 | }; 78 | }, 'withToolbarButton' ); 79 | 80 | wp.hooks.addFilter( 81 | 'editor.BlockEdit', 82 | 'custom-attributes/with-toolbar-button', 83 | withToolbarButton 84 | ); 85 | 86 | 87 | /** 88 | * Add custom class to block in Edit 89 | */ 90 | const withToolbarButtonProp = createHigherOrderComponent( ( BlockListBlock ) => { 91 | return ( props ) => { 92 | 93 | // If current block is not allowed 94 | if ( ! enableToolbarButtonOnBlocks.includes( props.name ) ) { 95 | return ( 96 | 97 | ); 98 | } 99 | 100 | const { attributes } = props; 101 | const { paragraphAttribute } = attributes; 102 | 103 | if ( paragraphAttribute && 'custom' === paragraphAttribute ) { 104 | return 105 | } else { 106 | return 107 | } 108 | }; 109 | }, 'withToolbarButtonProp' ); 110 | 111 | wp.hooks.addFilter( 112 | 'editor.BlockListBlock', 113 | 'custom-attributes/with-toolbar-button-prop', 114 | withToolbarButtonProp 115 | ); 116 | 117 | 118 | /** 119 | * Save our custom attribute 120 | */ 121 | const saveToolbarButtonAttribute = ( extraProps, blockType, attributes ) => { 122 | // Do nothing if it's another block than our defined ones. 123 | if ( enableToolbarButtonOnBlocks.includes( blockType.name ) ) { 124 | const { paragraphAttribute } = attributes; 125 | if ( paragraphAttribute && 'custom' === paragraphAttribute ) { 126 | extraProps.className = classnames( extraProps.className, 'has-custom-attribute' ) 127 | } 128 | } 129 | 130 | return extraProps; 131 | 132 | }; 133 | wp.hooks.addFilter( 134 | 'blocks.getSaveContent.extraProps', 135 | 'custom-attributes/save-toolbar-button-attribute', 136 | saveToolbarButtonAttribute 137 | ); -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import './attributes/toolbarButton'; 2 | import './attributes/sidebarSelect'; --------------------------------------------------------------------------------