From be9dad9494d5a03bc80244a3e45fd65ae6dc353f Mon Sep 17 00:00:00 2001 From: Nivanka Fonseka Date: Tue, 24 Oct 2017 11:58:07 +0530 Subject: [PATCH] introduced the new MarkdownEditorConfig class and options to configure toolbars. Fixed issues reported at issue number #6 --- client/dist/bundle.min.js | 56450 +--------------- client/src/bundles/bundle.js | 1 + .../MarkdownEditorField.js | 234 +- package-lock.json | 2878 +- src/extensions/MarkdownFieldExtension.php | 8 - src/forms/MarkdownEditorConfig.php | 174 + src/forms/MarkdownEditorField.php | 29 + webpack.config.babel.js | 14 +- 8 files changed, 2487 insertions(+), 57301 deletions(-) create mode 100644 src/forms/MarkdownEditorConfig.php diff --git a/client/dist/bundle.min.js b/client/dist/bundle.min.js index cbb76f8..0e99131 100644 --- a/client/dist/bundle.min.js +++ b/client/dist/bundle.min.js @@ -1,56432 +1,48 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; - -/******/ // The require function -/******/ function __webpack_require__(moduleId) { - -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; - -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; - -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - -/******/ // Flag the module as loaded -/******/ module.loaded = true; - -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } - - -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; - -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; - -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; - -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - __webpack_require__(1); - __webpack_require__(7); - __webpack_require__(8); - -/***/ }), -/* 1 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _jquery = __webpack_require__(2); - - var _jquery2 = _interopRequireDefault(_jquery); - - var _react = __webpack_require__(3); - - var _react2 = _interopRequireDefault(_react); - - var _reactDom = __webpack_require__(4); - - var _reactDom2 = _interopRequireDefault(_reactDom); - - var _reactApollo = __webpack_require__(5); - - var _Injector = __webpack_require__(6); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - var InjectableInsertEmbedModal = (0, _Injector.provideInjector)(window.InsertEmbedModal.default); - - _jquery2.default.entwine('ss', function ($) { - - $('#insert-md-embed-react__dialog-wrapper').entwine({ - - Element: null, - - Data: {}, - - onunmatch: function onunmatch() { - // solves errors given by ReactDOM "no matched root found" error. - this._clearModal(); - }, - _clearModal: function _clearModal() { - _reactDom2.default.unmountComponentAtNode(this[0]); - }, - open: function open() { - this._renderModal(true); - }, - close: function close() { - this.setData({}); - this._renderModal(false); - }, - - - /** - * Renders the react modal component - * - * @param {boolean} show - * @private - */ - _renderModal: function _renderModal(show) { - var _this = this; - - var handleHide = function handleHide() { - return _this.close(); - }; - var handleInsert = function handleInsert() { - return _this._handleInsert.apply(_this, arguments); - }; - var handleCreate = function handleCreate() { - return _this._handleCreate.apply(_this, arguments); - }; - var handleLoadingError = function handleLoadingError() { - return _this._handleLoadingError.apply(_this, arguments); - }; - var store = window.ss.store; - var client = window.ss.apolloClient; - var attrs = this.getOriginalAttributes(); - - // create/update the react component - _reactDom2.default.render(_react2.default.createElement( - _reactApollo.ApolloProvider, - { store: store, client: client }, - _react2.default.createElement(InjectableInsertEmbedModal, { - show: show, - onCreate: handleCreate, - onInsert: handleInsert, - onHide: handleHide, - onLoadingError: handleLoadingError, - fileAttributes: attrs, - bodyClassName: 'modal__dialog modal__dialog--scrollable', - className: 'insert-embed-react__dialog-wrapper' - }) - ), this[0]); - }, - _handleLoadingError: function _handleLoadingError() { - this.setData({}); - this.open(); - }, - - - /** - * Handles inserting the selected file in the modal - * - * @param {object} data - * @returns {Promise} - * @private - */ - _handleInsert: function _handleInsert(data) { - var oldData = this.getData(); - this.setData(Object.assign({ Url: oldData.Url }, data)); - this.insertRemote(); - this.close(); - }, - _handleCreate: function _handleCreate(data) { - this.setData(Object.assign({}, this.getData(), data)); - this.open(); - }, - - - /** - * Find the selected node and get attributes associated to attach the data to the form - * - * @returns {object} - */ - getOriginalAttributes: function getOriginalAttributes() { - var data = this.getData(); - return data; - }, - - - /** - * Calculate placement from css class - */ - findPosition: function findPosition(cssClass) { - var alignments = ['leftAlone', 'center', 'rightAlone', 'left', 'right']; - if (typeof cssClass !== 'string') { - return ''; - } - var classes = cssClass.split(' '); - return alignments.find(function (alignment) { - return classes.indexOf(alignment) > -1; - }); - }, - insertRemote: function insertRemote() { - var $field = this.getElement(); - if (!$field) { - return false; - } - - var data = this.getData(); - var shortcode = '[embed ' + 'url="' + data.Url + '" ' + 'thumbnail="' + data.PreviewUrl + '" ' + 'width="' + data.Width + '" ' + 'height="' + data.Height + '" ' + ']'; - console.log(this); - - var pos = $field.codemirror.getCursor(); - $field.codemirror.setSelection(pos, pos); - $field.codemirror.replaceSelection("\n" + shortcode + "\n"); - this.updateTextarea(); - return true; - }, - updateTextarea: function updateTextarea() { - var $field = this.getElement(); - $($field.element).closest('.js-markdown-holder').find('textarea.markdowneditor').val($field.value()); - } - }); - }); - -/***/ }), -/* 2 */ -/***/ (function(module, exports) { - - module.exports = jQuery; - -/***/ }), -/* 3 */ -/***/ (function(module, exports) { - - module.exports = React; - -/***/ }), -/* 4 */ -/***/ (function(module, exports) { - - module.exports = ReactDom; - -/***/ }), -/* 5 */ -/***/ (function(module, exports) { - - module.exports = ReactApollo; - -/***/ }), -/* 6 */ -/***/ (function(module, exports) { - - module.exports = Injector; - -/***/ }), -/* 7 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _jquery = __webpack_require__(2); - - var _jquery2 = _interopRequireDefault(_jquery); - - var _react = __webpack_require__(3); - - var _react2 = _interopRequireDefault(_react); - - var _reactDom = __webpack_require__(4); - - var _reactDom2 = _interopRequireDefault(_reactDom); - - var _reactApollo = __webpack_require__(5); - - var _Injector = __webpack_require__(6); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - var InjectableInsertMediaModal = (0, _Injector.provideInjector)(window.InsertMediaModal.default); - - _jquery2.default.entwine('ss', function ($) { - - $('#insert-md-media-react__dialog-wrapper').entwine({ - - Element: null, - Data: {}, - onunmatch: function onunmatch() { - // solves errors given by ReactDOM "no matched root found" error. - this._clearModal(); - }, - _clearModal: function _clearModal() { - _reactDom2.default.unmountComponentAtNode(this[0]); - }, - open: function open() { - this._renderModal(true); - }, - close: function close() { - this._renderModal(false); - }, - - - /** - * Renders the react modal component - * - * @param {boolean} show - * @private - */ - _renderModal: function _renderModal(show) { - var _this = this; - - var handleHide = function handleHide() { - return _this.close(); - }; - var handleInsert = function handleInsert() { - return _this._handleInsert.apply(_this, arguments); - }; - var store = window.ss.store; - var client = window.ss.apolloClient; - var attrs = this.getOriginalAttributes(); - - delete attrs.url; - - // create/update the react component - _reactDom2.default.render(_react2.default.createElement( - _reactApollo.ApolloProvider, - { store: store, client: client }, - _react2.default.createElement(InjectableInsertMediaModal, { - title: false, - type: 'insert-media', - show: show, - onInsert: handleInsert, - onHide: handleHide, - bodyClassName: 'modal__dialog', - className: 'insert-media-react__dialog-wrapper', - requireLinkText: false, - fileAttributes: attrs - }) - ), this[0]); - }, - - - /** - * Handles inserting the selected file in the modal - * - * @param {object} data - * @param {object} file - * @returns {Promise} - * @private - */ - _handleInsert: function _handleInsert(data, file) { - var result = false; - this.setData(Object.assign({}, data, file)); - - // Sometimes AssetAdmin.js handleSubmitEditor() can't find the file - // @todo Ensure that we always return a file for any valid ID - - // in case of any errors, better to catch them than let them go silent - try { - var category = null; - if (file) { - category = file.category; - } else { - category = 'image'; - } - switch (category) { - case 'image': - result = this.insertImage(); - break; - default: - result = this.insertFile(); - } - } catch (e) { - this.statusMessage(e, 'bad'); - } - - if (result) { - this.close(); - } - return Promise.resolve(); - }, - - - /** - * Find the selected node and get attributes associated to attach the data to the form - * - * @returns {object} - */ - getOriginalAttributes: function getOriginalAttributes() { - return {}; - }, - - - /** - * Calculate placement from css class - */ - findPosition: function findPosition(cssClass) { - var alignments = ['leftAlone', 'center', 'rightAlone', 'left', 'right']; - return alignments.find(function (alignment) { - var expr = new RegExp('\\b' + alignment + '\\b'); - return expr.test(cssClass); - }); - }, - - - /** - * Get html attributes from the Form data - * - * @returns {object} - */ - getAttributes: function getAttributes() { - var data = this.getData(); - - return { - src: data.url, - alt: data.AltText, - width: data.InsertWidth, - height: data.InsertHeight, - title: data.TitleTooltip, - class: data.Alignment, - 'data-id': data.ID, - 'data-shortcode': 'image' - }; - }, - - - /** - * Get extra data not part of the actual element we're adding/modifying (e.g. Caption) - * @returns {object} - */ - getExtraData: function getExtraData() { - var data = this.getData(); - return { - CaptionText: data && data.Caption - }; - }, - - - /** - * Generic handler for inserting a file - * - * NOTE: currently not supported - * - * @returns {boolean} success - */ - insertFile: function insertFile() { - var $field = this.getElement(); - var data = this.getData(); - var linkText = data.title || data.filename; - var markdown = '[' + linkText + ']([file_link,id=' + data.ID + '])'; - - var pos = $field.codemirror.getCursor(); - $field.codemirror.setSelection(pos, pos); - $field.codemirror.replaceSelection("\n" + markdown + "\n"); - this.updateTextarea(); - return true; - }, - - - /** - * Handler for inserting an image - * - * @returns {boolean} success - */ - insertImage: function insertImage() { - var $field = this.getElement(); - if (!$field) { - return false; - } - var data = this.getData(); - var extraData = this.getExtraData(); - - var markdown = '![' + (extraData.CaptionText ? extraData.CaptionText : data.title) + ']([image_link id=' + data.ID + ' width=' + data.width + ' height=' + data.height + '] "' + data.title + '")'; - - var pos = $field.codemirror.getCursor(); - $field.codemirror.setSelection(pos, pos); - $field.codemirror.replaceSelection("\n" + markdown + "\n"); - this.updateTextarea(); - return true; - }, - - - /** - * Pop up a status message if required to notify the user what is happening - * - * @param text - * @param type - */ - statusMessage: function statusMessage(text, type) { - var content = $('
').text(text).html(); // Escape HTML entities in text - $.noticeAdd({ - text: content, - type: type, - stayTime: 5000, - inEffect: { left: '0', opacity: 'show' } - }); - }, - updateTextarea: function updateTextarea() { - var $field = this.getElement(); - $($field.element).closest('.js-markdown-holder').find('textarea.markdowneditor').val($field.value()); - } - }); - }); - -/***/ }), -/* 8 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _react = __webpack_require__(3); - - var _react2 = _interopRequireDefault(_react); - - var _reactDom = __webpack_require__(4); - - var _reactDom2 = _interopRequireDefault(_reactDom); - - var _reactSimplemdeEditor = __webpack_require__(9); - - var _reactSimplemdeEditor2 = _interopRequireDefault(_reactSimplemdeEditor); - - var _Injector = __webpack_require__(6); - - var _jquery = __webpack_require__(2); - - var _jquery2 = _interopRequireDefault(_jquery); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var SimpleMDE = __webpack_require__(14); - - - var markdownConfigs = {}; - - _jquery2.default.entwine('ss', function ($) { - - markdownConfigs.toolbar = [{ - name: "heading", - action: SimpleMDE.toggleHeadingSmaller, - className: "fa fa-header", - title: "Heading HTML" - }, { - name: "bold", - action: SimpleMDE.toggleBold, - className: "fa fa-bold", - title: "Bold" - }, { - name: "italic", - action: SimpleMDE.toggleItalic, - className: "fa fa-italic", - title: "Italic" - }, { - name: "strikethrough", - action: SimpleMDE.toggleStrikethrough, - className: "fa fa-strikethrough", - title: "Strikethrough" - }, "|", { - name: "quote", - action: SimpleMDE.toggleBlockquote, - className: "fa fa-quote-left", - title: "Quote" - }, { - name: "unordered-list", - action: SimpleMDE.toggleUnorderedList, - className: "fa fa-list-ul", - title: "Generic List" - }, { - name: "ordered-list", - action: SimpleMDE.toggleOrderedList, - className: "fa fa-list-ol", - title: "Ordered List" - }, "|", { - name: "link", - action: SimpleMDE.drawLink, - /* - action: function() { - let dialog = jQuery('#insert-link-markdown-react__dialog-wrapper'); - if (!dialog.length) { - dialog = jQuery('