UNPKG

tui-editor

Version:

GFM Markdown Wysiwyg Editor - Productive and Extensible

1,256 lines (966 loc) 138 kB
/*! * tui-editor * @version 1.4.6 * @author NHN FE Development Lab <dl_javascript@nhn.com> (https://nhn.github.io/tui.editor/) * @license MIT */ (function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("jquery"), require("tui-code-snippet"), require("markdown-it"), require("to-mark"), require("highlight.js")); else if(typeof define === 'function' && define.amd) define(["jquery", "tui-code-snippet", "markdown-it", "to-mark", "highlight.js"], factory); else if(typeof exports === 'object') exports["Editor"] = factory(require("jquery"), require("tui-code-snippet"), require("markdown-it"), require("to-mark"), require("highlight.js")); else root["tui"] = root["tui"] || {}, root["tui"]["Editor"] = factory(root["$"], (root["tui"] && root["tui"]["util"]), root["markdownit"], root["toMark"], root["hljs"]); })(typeof self !== 'undefined' ? self : this, function(__WEBPACK_EXTERNAL_MODULE_0__, __WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_22__, __WEBPACK_EXTERNAL_MODULE_23__, __WEBPACK_EXTERNAL_MODULE_32__) { return /******/ (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] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = 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; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = "dist/"; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 149); /******/ }) /************************************************************************/ /******/ ({ /***/ 0: /***/ (function(module, exports) { module.exports = __WEBPACK_EXTERNAL_MODULE_0__; /***/ }), /***/ 1: /***/ (function(module, exports) { module.exports = __WEBPACK_EXTERNAL_MODULE_1__; /***/ }), /***/ 12: /***/ (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 _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; var _preview = __webpack_require__(13); var _preview2 = _interopRequireDefault(_preview); 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; } /** * @fileoverview Implements markdown preview * @author NHN FE Development Lab <dl_javascript@nhn.com> */ /** * Class Markdown Preview * @extends {Preview} */ var MarkdownPreview = function (_Preview) { _inherits(MarkdownPreview, _Preview); /** * Creates an instance of MarkdownPreview. * @param {jQuery} $el - base jQuery element * @param {EventManager} eventManager - event manager * @param {Convertor} convertor - convertor * @param {boolean} isViewer - true for view only mode * @param {Number} delayTime - lazyRunner delay time * @memberof MarkdownPreview */ function MarkdownPreview($el, eventManager, convertor, isViewer, delayTime) { _classCallCheck(this, MarkdownPreview); var _this = _possibleConstructorReturn(this, (MarkdownPreview.__proto__ || Object.getPrototypeOf(MarkdownPreview)).call(this, $el, eventManager, convertor, isViewer, delayTime)); _this._initEvent(); return _this; } /** * Initialize event * @private */ _createClass(MarkdownPreview, [{ key: '_initEvent', value: function _initEvent() { var _this2 = this; var latestMarkdownValue = ''; this.eventManager.listen('contentChangedFromMarkdown', function (markdownEditor) { latestMarkdownValue = markdownEditor.getValue(); if (_this2.isVisible()) { _this2.lazyRunner.run('refresh', latestMarkdownValue); } }); this.eventManager.listen('previewNeedsRefresh', function (value) { _this2.refresh(value || latestMarkdownValue); }); this.$el.on('scroll', function (event) { _this2.eventManager.emit('scroll', { source: 'preview', data: event }); }); } /** * render * @param {string} html - html string to render * @memberof MarkdownPreview * @override */ }, { key: 'render', value: function render(html) { _get(MarkdownPreview.prototype.__proto__ || Object.getPrototypeOf(MarkdownPreview.prototype), 'render', this).call(this, html); this.eventManager.emit('previewRenderAfter', this); } }, { key: 'remove', value: function remove() { this.$el.off('scroll'); this.$el = null; } }]); return MarkdownPreview; }(_preview2.default); exports.default = MarkdownPreview; /***/ }), /***/ 13: /***/ (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; }; }(); /** * @fileoverview Implements preview * @author NHN FE Development Lab <dl_javascript@nhn.com> */ var _jquery = __webpack_require__(0); var _jquery2 = _interopRequireDefault(_jquery); var _lazyRunner = __webpack_require__(20); var _lazyRunner2 = _interopRequireDefault(_lazyRunner); 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"); } } /** * Class Preview **/ var Preview = function () { /** * Creates an instance of Preview. * @param {jQuery} $el Container element for preview * @param {EventManager} eventManager Event manager instance * @param {Convertor} convertor Convertor instance * @param {boolean} isViewer - whether viewer mode or not * @param {Number} delayTime - lazyRunner delay time * @memberof Preview */ function Preview($el, eventManager, convertor, isViewer) { var delayTime = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 800; _classCallCheck(this, Preview); this.eventManager = eventManager; this.convertor = convertor; this.$el = $el; this.isViewer = !!isViewer; this._initContentSection(); this.lazyRunner = new _lazyRunner2.default(); this.lazyRunner.registerLazyRunFunction('refresh', this.refresh, delayTime, this); } /** * Initialize content selection * @private */ _createClass(Preview, [{ key: '_initContentSection', value: function _initContentSection() { this._$previewContent = (0, _jquery2.default)('<div class="tui-editor-contents" />'); this.$el.append(this._$previewContent); } /** * Refresh rendering * @memberof Preview * @param {string} markdown Markdown text */ }, { key: 'refresh', value: function refresh(markdown) { this.render(this.convertor.toHTMLWithCodeHightlight(markdown)); } /** * get html string * @returns {string} - html preview string * @memberof Preview */ }, { key: 'getHTML', value: function getHTML() { return this._$previewContent.html(); } /** * set html string * @param {string} html - html preview string * @memberof Preview */ }, { key: 'setHTML', value: function setHTML(html) { this._$previewContent.html(html); } /** * Render HTML on preview * @memberof Preview * @param {string} html HTML string * @protected */ }, { key: 'render', value: function render(html) { var _$previewContent = this._$previewContent; html = this.eventManager.emit('previewBeforeHook', html) || html; _$previewContent.empty(); _$previewContent.html(html); } /** * Set preview height * @memberof Preview * @param {number} height - Height for preview container */ }, { key: 'setHeight', value: function setHeight(height) { this.$el.get(0).style.height = height + 'px'; } /** * set min height * @param {number} minHeight - min height * @memberof Preview */ }, { key: 'setMinHeight', value: function setMinHeight(minHeight) { this.$el.get(0).style.minHeight = minHeight + 'px'; } /** * Is Preview visible * @returns {boolean} result */ }, { key: 'isVisible', value: function isVisible() { return this.$el.css('display') !== 'none'; } }]); return Preview; }(); exports.default = Preview; /***/ }), /***/ 14: /***/ (function(module, exports, __webpack_require__) { "use strict"; var isMac = /Mac/.test(navigator.platform); module.exports = { isMac: isMac }; /***/ }), /***/ 149: /***/ (function(module, exports, __webpack_require__) { "use strict"; var _jquery = __webpack_require__(0); var _jquery2 = _interopRequireDefault(_jquery); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var Viewer = __webpack_require__(33); // for jquery /** * @fileoverview entry point for viewer * @author NHN FE Development Lab <dl_javascript@nhn.com> */ _jquery2.default.fn.tuiEditor = function () { var options = void 0, instance = void 0; var el = this.get(0); if (el) { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } options = args[0] || {}; instance = _jquery2.default.data(el, 'tuiEditor'); if (instance) { if (typeof options === 'string') { var _instance; return (_instance = instance)[options].apply(_instance, args.slice(1)); } } else { options.el = el; instance = new Viewer(options); _jquery2.default.data(el, 'tuiEditor', instance); } } return this; }; module.exports = Viewer; /***/ }), /***/ 15: /***/ (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; }; }(); /** * @fileoverview Implements EventManager * @author NHN FE Development Lab <dl_javascript@nhn.com> */ var _tuiCodeSnippet = __webpack_require__(1); var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); 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"); } } var eventList = ['previewBeforeHook', 'previewRenderAfter', 'previewNeedsRefresh', 'addImageBlobHook', 'setMarkdownAfter', 'contentChangedFromWysiwyg', 'changeFromWysiwyg', 'contentChangedFromMarkdown', 'changeFromMarkdown', 'change', 'changeModeToWysiwyg', 'changeModeToMarkdown', 'changeModeBefore', 'changeMode', 'changePreviewStyle', 'changePreviewTabPreview', 'changePreviewTabWrite', 'openPopupAddLink', 'openPopupAddImage', 'openPopupAddTable', 'openPopupTableUtils', 'openHeadingSelect', 'openPopupCodeBlockLanguages', 'openPopupCodeBlockEditor', 'openDropdownToolbar', 'closePopupCodeBlockLanguages', 'closePopupCodeBlockEditor', 'closeAllPopup', 'command', 'addCommandBefore', 'htmlUpdate', 'markdownUpdate', 'renderedHtmlUpdated', 'removeEditor', 'convertorAfterMarkdownToHtmlConverted', 'convertorBeforeHtmlToMarkdownConverted', 'convertorAfterHtmlToMarkdownConverted', 'stateChange', 'wysiwygSetValueAfter', 'wysiwygSetValueBefore', 'wysiwygGetValueBefore', 'wysiwygProcessHTMLText', 'wysiwygRangeChangeAfter', 'wysiwygKeyEvent', 'scroll', 'click', 'mousedown', 'mouseover', 'mouseout', 'mouseup', 'contextmenu', 'keydown', 'keyup', 'keyMap', 'load', 'focus', 'blur', 'paste', 'pasteBefore', 'willPaste', 'copy', 'copyBefore', 'copyAfter', 'cut', 'cutAfter', 'drop', 'show', 'hide']; /** * Class EventManager */ var EventManager = function () { /** * Creates an instance of EventManager. * @memberof EventManager */ function EventManager() { _classCallCheck(this, EventManager); this.events = new _tuiCodeSnippet2.default.Map(); this.TYPE = new _tuiCodeSnippet2.default.Enum(eventList); } /** * Listen event and bind event handler * @memberof EventManager * @param {string} typeStr Event type string * @param {function} handler Event handler */ _createClass(EventManager, [{ key: 'listen', value: function listen(typeStr, handler) { var typeInfo = this._getTypeInfo(typeStr); var eventHandlers = this.events.get(typeInfo.type) || []; if (!this._hasEventType(typeInfo.type)) { throw new Error('There is no event type ' + typeInfo.type); } if (typeInfo.namespace) { handler.namespace = typeInfo.namespace; } eventHandlers.push(handler); this.events.set(typeInfo.type, eventHandlers); } /** * Emit event * @memberof EventManager * @param {string} eventName Event name to emit * @returns {Array} */ }, { key: 'emit', value: function emit() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } var typeStr = args.shift(); var typeInfo = this._getTypeInfo(typeStr); var eventHandlers = this.events.get(typeInfo.type); var results = void 0; if (eventHandlers) { _tuiCodeSnippet2.default.forEach(eventHandlers, function (handler) { var result = handler.apply(undefined, args); if (!_tuiCodeSnippet2.default.isUndefined(result)) { results = results || []; results.push(result); } }); } return results; } /** * Emit given event and return result * @memberof EventManager * @param {string} eventName Event name to emit * @param {string} sourceText Source text to change * @returns {string} */ }, { key: 'emitReduce', value: function emitReduce() { for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } var type = args.shift(); var eventHandlers = this.events.get(type); if (eventHandlers) { _tuiCodeSnippet2.default.forEach(eventHandlers, function (handler) { var result = handler.apply(undefined, args); if (!_tuiCodeSnippet2.default.isFalsy(result)) { args[0] = result; } }); } return args[0]; } /** * Get event type and namespace * @memberof EventManager * @param {string} typeStr Event type name * @returns {{type: string, namespace: string}} * @private */ }, { key: '_getTypeInfo', value: function _getTypeInfo(typeStr) { var splited = typeStr.split('.'); return { type: splited[0], namespace: splited[1] }; } /** * Check whether event type exists or not * @param {string} type Event type name * @returns {boolean} * @private */ }, { key: '_hasEventType', value: function _hasEventType(type) { return !_tuiCodeSnippet2.default.isUndefined(this.TYPE[this._getTypeInfo(type).type]); } /** * Add event type when given event not exists * @memberof EventManager * @param {string} type Event type name */ }, { key: 'addEventType', value: function addEventType(type) { if (this._hasEventType(type)) { throw new Error('There is already have event type ' + type); } this.TYPE.set(type); } /** * Remove event handler from given event type * @memberof EventManager * @param {string} typeStr Event type name * @param {function} [handler] - registered event handler */ }, { key: 'removeEventHandler', value: function removeEventHandler(typeStr, handler) { var _this = this; var _getTypeInfo2 = this._getTypeInfo(typeStr), type = _getTypeInfo2.type, namespace = _getTypeInfo2.namespace; if (type && handler) { this._removeEventHandlerWithHandler(type, handler); } else if (type && !namespace) { // dont use dot notation cuz eslint this.events['delete'](type); } else if (!type && namespace) { this.events.forEach(function (eventHandlers, eventType) { _this._removeEventHandlerWithTypeInfo(eventType, namespace); }); } else if (type && namespace) { this._removeEventHandlerWithTypeInfo(type, namespace); } } /** * Remove event handler with event handler * @param {string} type - event type name * @param {function} handler - event handler * @memberof EventManager * @private */ }, { key: '_removeEventHandlerWithHandler', value: function _removeEventHandlerWithHandler(type, handler) { var eventHandlers = this.events.get(type) || []; var handlerIndex = eventHandlers.indexOf(handler); if (handlerIndex >= 0) { eventHandlers.splice(handlerIndex, 1); } } /** * Remove event handler with event type information * @memberof EventManager * @param {string} type Event type name * @param {string} namespace Event namespace * @private */ }, { key: '_removeEventHandlerWithTypeInfo', value: function _removeEventHandlerWithTypeInfo(type, namespace) { var handlersToSurvive = []; var eventHandlers = this.events.get(type); if (!eventHandlers) { return; } eventHandlers.map(function (handler) { if (handler.namespace !== namespace) { handlersToSurvive.push(handler); } return null; }); this.events.set(type, handlersToSurvive); } }]); return EventManager; }(); exports.default = EventManager; /***/ }), /***/ 16: /***/ (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; }; }(); /** * @fileoverview extension manager * @author NHN FE Development Lab <dl_javascript@nhn.com> */ var _tuiCodeSnippet = __webpack_require__(1); var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); 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"); } } /** * Class ExtManager */ var ExtManager = function () { /** * Creates an instance of ExtManager. * @memberof ExtManager */ function ExtManager() { _classCallCheck(this, ExtManager); this.exts = new _tuiCodeSnippet2.default.Map(); } /** * defineExtension * Defined Extension * @memberof ExtManager * @param {string} name extension name * @param {ExtManager~extension} ext extension */ _createClass(ExtManager, [{ key: 'defineExtension', value: function defineExtension(name, ext) { this.exts.set(name, ext); } /** * Apply extensions * @memberof ExtManager * @param {object} context Context * @param {Array.<string|object>} options - options or names array */ }, { key: 'applyExtension', value: function applyExtension(context, options) { var _this = this; if (options) { options.forEach(function (option) { var hasOption = _tuiCodeSnippet2.default.isObject(option); var name = hasOption ? option.name : option; if (_this.exts.has(name)) { var ext = _this.exts.get(name); if (hasOption) { ext(context, option); } else { ext(context); } } }); } } }]); return ExtManager; }(); exports.default = new ExtManager(); /***/ }), /***/ 17: /***/ (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; }; }(); /** * @fileoverview Convertor have responsible to convert markdown and html * @author NHN FE Development Lab <dl_javascript@nhn.com> */ var _jquery = __webpack_require__(0); var _jquery2 = _interopRequireDefault(_jquery); var _tuiCodeSnippet = __webpack_require__(1); var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); var _markdownIt = __webpack_require__(22); var _markdownIt2 = _interopRequireDefault(_markdownIt); var _toMark = __webpack_require__(23); var _toMark2 = _interopRequireDefault(_toMark); var _htmlSanitizer = __webpack_require__(9); var _htmlSanitizer2 = _interopRequireDefault(_htmlSanitizer); var _markdownitTaskPlugin = __webpack_require__(24); var _markdownitTaskPlugin2 = _interopRequireDefault(_markdownitTaskPlugin); var _markdownitCodeBlockPlugin = __webpack_require__(25); var _markdownitCodeBlockPlugin2 = _interopRequireDefault(_markdownitCodeBlockPlugin); var _markdownitCodeRenderer = __webpack_require__(26); var _markdownitCodeRenderer2 = _interopRequireDefault(_markdownitCodeRenderer); var _markdownitBlockQuoteRenderer = __webpack_require__(27); var _markdownitBlockQuoteRenderer2 = _interopRequireDefault(_markdownitBlockQuoteRenderer); var _markdownitTableRenderer = __webpack_require__(28); var _markdownitTableRenderer2 = _interopRequireDefault(_markdownitTableRenderer); var _markdownitHtmlBlockRenderer = __webpack_require__(29); var _markdownitHtmlBlockRenderer2 = _interopRequireDefault(_markdownitHtmlBlockRenderer); var _markdownitBackticksRenderer = __webpack_require__(30); var _markdownitBackticksRenderer2 = _interopRequireDefault(_markdownitBackticksRenderer); var _markdownitInlinePlugin = __webpack_require__(31); var _codeBlockManager = __webpack_require__(7); var _codeBlockManager2 = _interopRequireDefault(_codeBlockManager); 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"); } } var markdownitHighlight = new _markdownIt2.default({ html: true, breaks: true, quotes: '“”‘’', langPrefix: 'lang-', highlight: function highlight(codeText, type) { return _codeBlockManager2.default.createCodeBlockHtml(type, codeText); } }); var markdownit = new _markdownIt2.default({ html: true, breaks: true, quotes: '“”‘’', langPrefix: 'lang-' }); // markdownitHighlight markdownitHighlight.block.ruler.at('code', _markdownitCodeRenderer2.default); markdownitHighlight.block.ruler.at('table', _markdownitTableRenderer2.default, { alt: ['paragraph', 'reference'] }); markdownitHighlight.block.ruler.at('blockquote', _markdownitBlockQuoteRenderer2.default, { alt: ['paragraph', 'reference', 'blockquote', 'list'] }); markdownitHighlight.block.ruler.at('html_block', _markdownitHtmlBlockRenderer2.default, { alt: ['paragraph', 'reference', 'blockquote'] }); markdownitHighlight.inline.ruler.at('backticks', _markdownitBackticksRenderer2.default); markdownitHighlight.use(_markdownitTaskPlugin2.default); markdownitHighlight.use(_markdownitCodeBlockPlugin2.default); markdownitHighlight.renderer.rules.softbreak = function (tokens, idx, options) { if (!options.breaks) { return '\n'; } var prevToken = tokens[idx - 1]; if (prevToken && prevToken.type === 'html_inline' && prevToken.content === '<br>') { return ''; } return options.xhtmlOut ? '<br />\n' : '<br>\n'; }; // markdownit markdownit.block.ruler.at('code', _markdownitCodeRenderer2.default); markdownit.block.ruler.at('table', _markdownitTableRenderer2.default, { alt: ['paragraph', 'reference'] }); markdownit.block.ruler.at('blockquote', _markdownitBlockQuoteRenderer2.default, { alt: ['paragraph', 'reference', 'blockquote', 'list'] }); markdownit.block.ruler.at('html_block', _markdownitHtmlBlockRenderer2.default, { alt: ['paragraph', 'reference', 'blockquote'] }); markdownit.inline.ruler.at('backticks', _markdownitBackticksRenderer2.default); markdownit.use(_markdownitTaskPlugin2.default); markdownit.use(_markdownitCodeBlockPlugin2.default); // This regular expression refere markdownIt. // https://github.com/markdown-it/markdown-it/blob/master/lib/common/html_re.js var attrName = '[a-zA-Z_:][a-zA-Z0-9:._-]*'; var unquoted = '[^"\'=<>`\\x00-\\x20]+'; var singleQuoted = "'[^']*'"; var doubleQuoted = '"[^"]*"'; var attrValue = '(?:' + unquoted + '|' + singleQuoted + '|' + doubleQuoted + ')'; var attribute = '(?:\\s+' + attrName + '(?:\\s*=\\s*' + attrValue + ')?)*\\s*'; var openingTag = '(\\\\<|<)([A-Za-z][A-Za-z0-9\\-]*' + attribute + ')(\\/?>)'; var HTML_TAG_RX = new RegExp(openingTag, 'g'); /** * Class Convertor */ var Convertor = function () { /** * Convertor constructor * @param {EventManager} em - EventManager instance */ function Convertor(em) { _classCallCheck(this, Convertor); this.eventManager = em; } /** * _markdownToHtmlWithCodeHighlight * Convert markdown to html with Codehighlight * @private * @memberof Convertor * @param {string} markdown markdown text * @param {object} env environment sandbox for markdownit * @returns {string} html text */ _createClass(Convertor, [{ key: '_markdownToHtmlWithCodeHighlight', value: function _markdownToHtmlWithCodeHighlight(markdown, env) { markdown = this._replaceImgAttrToDataProp(markdown); return markdownitHighlight.render(markdown, env); } /** * _markdownToHtml * Convert markdown to html * @private * @memberof Convertor * @param {string} markdown markdown text * @param {object} env environment sandbox for markdownit * @returns {string} html text */ }, { key: '_markdownToHtml', value: function _markdownToHtml(markdown, env) { markdown = markdown.replace(HTML_TAG_RX, function (match, $1, $2, $3) { return match[0] !== '\\' ? '' + $1 + $2 + ' data-tomark-pass ' + $3 : match; }); markdown = this._replaceImgAttrToDataProp(markdown); return markdownit.render(markdown, env); } /** * Replace 'onerror' attribute of img tag to data property string * @param {string} markdown markdown text * @returns {string} replaced markdown text * @private */ }, { key: '_replaceImgAttrToDataProp', value: function _replaceImgAttrToDataProp(markdown) { var onerrorStripeRegex = /(<img[^>]*)(onerror\s*=\s*[\\"']?[^\\"']*[\\"']?)(.*)/i; while (onerrorStripeRegex.exec(markdown)) { markdown = markdown.replace(onerrorStripeRegex, '$1$3'); } return markdown; } /** * Remove BR's data-tomark-pass attribute text when br in code element * @param {string} renderedHTML Rendered HTML string from markdown editor * @returns {string} * @private */ }, { key: '_removeBrToMarkPassAttributeInCode', value: function _removeBrToMarkPassAttributeInCode(renderedHTML) { var $wrapperDiv = (0, _jquery2.default)('<div />'); $wrapperDiv.html(renderedHTML); $wrapperDiv.find('code, pre').each(function (i, codeOrPre) { var $code = (0, _jquery2.default)(codeOrPre); $code.html($code.html().replace(/ data-tomark-pass &gt;/g, '&gt;')); }); renderedHTML = $wrapperDiv.html(); return renderedHTML; } /** * toHTMLWithCodeHightlight * Convert markdown to html with Codehighlight * emit convertorAfterMarkdownToHtmlConverted * @memberof Convertor * @param {string} markdown markdown text * @returns {string} html text */ }, { key: 'toHTMLWithCodeHightlight', value: function toHTMLWithCodeHightlight(markdown) { var html = this._markdownToHtmlWithCodeHighlight(markdown); html = this.eventManager.emitReduce('convertorAfterMarkdownToHtmlConverted', html); return html; } /** * toHTML * Convert markdown to html * emit convertorAfterMarkdownToHtmlConverted * @memberof Convertor * @param {string} markdown markdown text * @returns {string} html text */ }, { key: 'toHTML', value: function toHTML(markdown) { var html = this._markdownToHtml(markdown); html = this.eventManager.emitReduce('convertorAfterMarkdownToHtmlConverted', html); html = this._removeBrToMarkPassAttributeInCode(html); return html; } }, { key: 'initHtmlSanitizer', value: function initHtmlSanitizer() { this.eventManager.listen('convertorAfterMarkdownToHtmlConverted', function (html) { return (0, _htmlSanitizer2.default)(html, true); }); } /** * set link attribute to markdownitHighlight, markdownit * using linkAttribute of markdownItInlinePlugin * @param {object} attr markdown text */ }, { key: 'setLinkAttribute', value: function setLinkAttribute(attr) { var keys = Object.keys(attr); var setAttributeToToken = function setAttributeToToken(tokens, idx) { keys.forEach(function (key) { tokens[idx].attrPush([key, attr[key]]); }); }; markdownitHighlight.use(_markdownitInlinePlugin.linkAttribute, setAttributeToToken); markdownit.use(_markdownitInlinePlugin.linkAttribute, setAttributeToToken); } /** * toMarkdown * Convert html to markdown * emit convertorAfterHtmlToMarkdownConverted * @memberof Convertor * @param {string} html html text * @param {object | null} toMarkOptions - toMark library options * @returns {string} markdown text */ }, { key: 'toMarkdown', value: function toMarkdown(html, toMarkOptions) { var resultArray = []; html = this.eventManager.emitReduce('convertorBeforeHtmlToMarkdownConverted', html); var markdown = (0, _toMark2.default)(this._appendAttributeForBrIfNeed(html), toMarkOptions); markdown = this.eventManager.emitReduce('convertorAfterHtmlToMarkdownConverted', markdown); _tuiCodeSnippet2.default.forEach(markdown.split('\n'), function (line, index) { var FIND_TABLE_RX = /^\|[^|]*\|/ig; var FIND_CODE_RX = /`[^`]*<br>[^`]*`/ig; if (!FIND_CODE_RX.test(line) && !FIND_TABLE_RX.test(line)) { line = line.replace(/<br>/ig, '<br>\n'); } resultArray[index] = line; }); return resultArray.join('\n'); } }, { key: '_appendAttributeForBrIfNeed', value: function _appendAttributeForBrIfNeed(html) { var FIND_BR_RX = /<br>/ig; var FIND_DOUBLE_BR_RX = /<br \/><br \/>/ig; var FIND_PASSING_AND_NORMAL_BR_RX = /<br data-tomark-pass \/><br \/>(.)/ig; var FIRST_TWO_BRS_BEFORE_RX = /([^>]|<\/a>|<\/code>|<\/span>|<\/b>|<\/i>|<\/s>|<img [^>]*>)/; var TWO_BRS_RX = /<br data-tomark-pass \/><br data-tomark-pass \/>/; var FIND_FIRST_TWO_BRS_RX = new RegExp(FIRST_TWO_BRS_BEFORE_RX.source + TWO_BRS_RX.source, 'g'); var FIND_ATTRI_WITH_EMTPY_STR_RX = /<br data-tomark-pass="">/ig; html = html.replace(FIND_BR_RX, '<br />'); html = html.replace(FIND_DOUBLE_BR_RX, '<br data-tomark-pass /><br data-tomark-pass />'); html = html.replace(FIND_ATTRI_WITH_EMTPY_STR_RX, '<br data-tomark-pass />'); html = html.replace(FIND_PASSING_AND_NORMAL_BR_RX, '<br data-tomark-pass /><br data-tomark-pass />$1'); html = html.replace(FIND_FIRST_TWO_BRS_RX, '$1<br /><br />'); return html; } /** * get markdownit with code highlight * @returns {markdownit} - markdownit instance * @memberof Convertor * @static */ }], [{ key: 'getMarkdownitHighlightRenderer', value: function getMarkdownitHighlightRenderer() { return markdownitHighlight; } /** * get markdownit * @returns {markdownit} - markdownit instance * @memberof Convertor * @static */ }, { key: 'getMarkdownitRenderer', value: function getMarkdownitRenderer() { return markdownit; } }]); return Convertor; }(); exports.default = Convertor; /***/ }), /***/ 2: /***/ (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; }; }(); /** * @fileoverview Implements CommandManager * @author NHN FE Development Lab <dl_javascript@nhn.com> */ var _jquery = __webpack_require__(0); var _jquery2 = _interopRequireDefault(_jquery); var _tuiCodeSnippet = __webpack_require__(1); var _tuiCodeSnippet2 = _interopRequireDefault(_tuiCodeSnippet); var _command = __webpack_require__(21); var _command2 = _interopRequireDefault(_command); var _util = __webpack_require__(14); 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"); } } var KEYMAP_OS_INDEX = _util.isMac ? 1 : 0; /** * Class CommandManager */ var CommandManager = function () { /** * @param {ToastUIEditor} base nedInstance * @param {object} [options={}] - option object * @param {boolean} [options.useCommandShortcut=true] - execute command with keyMap */ function CommandManager(base) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; _classCallCheck(this, CommandManager); this._command = new _tuiCodeSnippet2.default.Map(); this._mdCom