mirror of
https://github.com/codex-team/editor.js
synced 2026-03-16 07:35:48 +01:00
add docs to the class methods and extend utils
This commit is contained in:
parent
7f5b0a5f9f
commit
7b1ddc944b
5 changed files with 592 additions and 147 deletions
|
|
@ -244,6 +244,20 @@ var Util = function () {
|
|||
|
||||
return Array.prototype.slice.call(collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if object is empty
|
||||
*
|
||||
* @param {Object} object
|
||||
* @return {boolean}
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: "isEmpty",
|
||||
value: function isEmpty(object) {
|
||||
|
||||
return Object.keys(object).length === 0 && object.constructor === Object;
|
||||
}
|
||||
}]);
|
||||
|
||||
return Util;
|
||||
|
|
@ -471,7 +485,7 @@ var _createClass = function () { function defineProperties(target, props) { for
|
|||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
var modules = ["blockManager.js","events.js","renderer.js","toolbar.js","tools.js","ui.js"].map(function (module) {
|
||||
var modules = ["blockManager.js","events.js","renderer.js","sanitizer.js","toolbar.js","tools.js","ui.js"].map(function (module) {
|
||||
return __webpack_require__(4)("./" + module);
|
||||
});
|
||||
|
||||
|
|
@ -813,11 +827,12 @@ module.exports = function () {
|
|||
|
||||
var map = {
|
||||
"./blockManager.js": 5,
|
||||
"./events.js": 7,
|
||||
"./renderer.js": 8,
|
||||
"./toolbar.js": 9,
|
||||
"./tools.js": 10,
|
||||
"./ui.js": 11
|
||||
"./events.js": 6,
|
||||
"./renderer.js": 7,
|
||||
"./sanitizer.js": 8,
|
||||
"./toolbar.js": 10,
|
||||
"./tools.js": 11,
|
||||
"./ui.js": 12
|
||||
};
|
||||
function webpackContext(req) {
|
||||
return __webpack_require__(webpackContextResolve(req));
|
||||
|
|
@ -847,7 +862,7 @@ var _createClass = function () { function defineProperties(target, props) { for
|
|||
* @classdesc Manage editor`s blocks storage and appearance
|
||||
*/
|
||||
|
||||
var _block = __webpack_require__(6);
|
||||
var _block = __webpack_require__(15);
|
||||
|
||||
var _block2 = _interopRequireDefault(_block);
|
||||
|
||||
|
|
@ -1294,94 +1309,6 @@ module.exports = BlockManager;
|
|||
/* 6 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* WEBPACK VAR INJECTION */(function($) {
|
||||
|
||||
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; }; }();
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
/**
|
||||
*
|
||||
* @class Block
|
||||
* @classdesc This class describes editor`s block, including block`s HTMLElement, data and tool
|
||||
*
|
||||
* @property {Tool} tool — current block tool (Paragraph, for example)
|
||||
* @property {Object} CSS — block`s css classes
|
||||
*
|
||||
*/
|
||||
|
||||
var Block = function () {
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @param {Object} tool — current block plugin`s instance
|
||||
*/
|
||||
function Block(tool) {
|
||||
_classCallCheck(this, Block);
|
||||
|
||||
this.tool = tool;
|
||||
|
||||
this.CSS = {
|
||||
wrapper: 'ce-block',
|
||||
content: 'ce-block__content'
|
||||
};
|
||||
|
||||
this._html = this.compose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make default block wrappers and put tool`s content there
|
||||
*
|
||||
* @returns {HTMLDivElement}
|
||||
* @private
|
||||
*/
|
||||
|
||||
|
||||
_createClass(Block, [{
|
||||
key: 'compose',
|
||||
value: function compose() {
|
||||
|
||||
var wrapper = $.make('div', this.CSS.wrapper),
|
||||
content = $.make('div', this.CSS.content);
|
||||
|
||||
content.appendChild(this.tool.html);
|
||||
wrapper.appendChild(content);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get block`s HTML
|
||||
*
|
||||
* @returns {HTMLDivElement}
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'html',
|
||||
get: function get() {
|
||||
|
||||
return this._html;
|
||||
}
|
||||
}]);
|
||||
|
||||
return Block;
|
||||
}();
|
||||
|
||||
Block.displayName = 'Block';
|
||||
exports.default = Block;
|
||||
module.exports = exports['default'];
|
||||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))
|
||||
|
||||
/***/ }),
|
||||
/* 7 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* WEBPACK VAR INJECTION */(function(Module) {
|
||||
|
||||
|
|
@ -1483,7 +1410,7 @@ module.exports = exports["default"];
|
|||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
|
||||
|
||||
/***/ }),
|
||||
/* 8 */
|
||||
/* 7 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
|
@ -1787,10 +1714,376 @@ module.exports = Renderer;
|
|||
// })({});
|
||||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))
|
||||
|
||||
/***/ }),
|
||||
/* 8 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* WEBPACK VAR INJECTION */(function(Module, _) {
|
||||
|
||||
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; }; }();
|
||||
|
||||
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; }
|
||||
|
||||
/**
|
||||
* Codex Sanitizer
|
||||
*
|
||||
* @module Sanitizer module
|
||||
* Clears HTML from taint tags
|
||||
*
|
||||
* @version 2.0.0
|
||||
*
|
||||
* @usage
|
||||
* Module can be used within two ways:
|
||||
* 1) When you have an instance
|
||||
* - this.moduleInstance['Sanitizer'].clean(yourDirtyString);
|
||||
* 2) As static method
|
||||
* - CodexEditor.Sanitizer.clean(yourDirtyString, yourCustomConfiguration);
|
||||
*
|
||||
*
|
||||
* Look up the SanitizerConfig object as example to make your custom restrictions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} SanitizerConfig
|
||||
* @property {Object} tags - define tags restrictions
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* tags : {
|
||||
* p: true,
|
||||
* a: {
|
||||
* href: true,
|
||||
* rel: "nofollow",
|
||||
* target: "_blank"
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
var Sanitizer = function (_Module) {
|
||||
_inherits(Sanitizer, _Module);
|
||||
|
||||
/**
|
||||
* Initializes Sanitizer module
|
||||
* Sets default configuration if custom not exists
|
||||
*
|
||||
* @property {HTMLJanitor} this.janitor - Sanitizer library
|
||||
*
|
||||
* @param {SanitizerConfig} config
|
||||
*/
|
||||
function Sanitizer(config) {
|
||||
_classCallCheck(this, Sanitizer);
|
||||
|
||||
// default config
|
||||
var _this = _possibleConstructorReturn(this, (Sanitizer.__proto__ || Object.getPrototypeOf(Sanitizer)).call(this, config));
|
||||
|
||||
_this.instantConfig = {};
|
||||
_this.janitorInstance = null;
|
||||
|
||||
/** Custom configuration */
|
||||
_this.sanitizerConfig = config.settings ? config.settings.sanitizer : {};
|
||||
|
||||
/** HTML Janitor library */
|
||||
_this.sanitizerInstance = __webpack_require__(9);
|
||||
|
||||
return _this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If developer uses editor's API, then he can customize sanitize restrictions.
|
||||
* Or, sanitizing config can be defined globally in editors initialization. That config will be used everywhere
|
||||
* At least, if there is no config overrides, that API uses Default configuration
|
||||
*
|
||||
* @uses https://www.npmjs.com/package/html-janitor
|
||||
*
|
||||
* @param {HTMLJanitor} library - sanitizer extension
|
||||
*/
|
||||
|
||||
|
||||
_createClass(Sanitizer, [{
|
||||
key: 'clean',
|
||||
|
||||
|
||||
/**
|
||||
* Cleans string from unwanted tags
|
||||
* @param {String} taintString - HTML string
|
||||
*
|
||||
* @return {String} clean HTML
|
||||
*/
|
||||
value: function clean(taintString) {
|
||||
|
||||
return this.janitorInstance.clean(taintString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans string from unwanted tags
|
||||
* @static
|
||||
*
|
||||
* Method allows to use default config
|
||||
*
|
||||
* @param {String} taintString - taint string
|
||||
* @param {SanitizerConfig} customConfig - allowed tags
|
||||
*
|
||||
* @return {String} clean HTML
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'sanitizerInstance',
|
||||
set: function set(library) {
|
||||
|
||||
this.janitorInstance = new library(this.instanceConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets sanitizer configuration. Uses default config if user didn't pass the restriction
|
||||
* @param {SanitizerConfig} config
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'sanitizerConfig',
|
||||
set: function set(config) {
|
||||
|
||||
if (_.isEmpty(config)) {
|
||||
|
||||
this.instanceConfig = {
|
||||
tags: {
|
||||
p: {},
|
||||
a: {
|
||||
href: true,
|
||||
target: '_blank',
|
||||
rel: 'nofollow'
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
|
||||
this.instanceConfig = config;
|
||||
}
|
||||
}
|
||||
}], [{
|
||||
key: 'clean',
|
||||
value: function clean(taintString, customConfig) {
|
||||
|
||||
var newInstance = Sanitizer(customConfig);
|
||||
|
||||
return newInstance.clean(taintString);
|
||||
}
|
||||
}]);
|
||||
|
||||
return Sanitizer;
|
||||
}(Module);
|
||||
|
||||
Sanitizer.displayName = 'Sanitizer';
|
||||
exports.default = Sanitizer;
|
||||
module.exports = exports['default'];
|
||||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(1)))
|
||||
|
||||
/***/ }),
|
||||
/* 9 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (root, factory) {
|
||||
if (true) {
|
||||
!(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
||||
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
||||
(__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) :
|
||||
__WEBPACK_AMD_DEFINE_FACTORY__),
|
||||
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
||||
} else if (typeof exports === 'object') {
|
||||
module.exports = factory();
|
||||
} else {
|
||||
root.HTMLJanitor = factory();
|
||||
}
|
||||
}(this, function () {
|
||||
|
||||
/**
|
||||
* @param {Object} config.tags Dictionary of allowed tags.
|
||||
* @param {boolean} config.keepNestedBlockElements Default false.
|
||||
*/
|
||||
function HTMLJanitor(config) {
|
||||
|
||||
var tagDefinitions = config['tags'];
|
||||
var tags = Object.keys(tagDefinitions);
|
||||
|
||||
var validConfigValues = tags
|
||||
.map(function(k) { return typeof tagDefinitions[k]; })
|
||||
.every(function(type) { return type === 'object' || type === 'boolean' || type === 'function'; });
|
||||
|
||||
if(!validConfigValues) {
|
||||
throw new Error("The configuration was invalid");
|
||||
}
|
||||
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
// TODO: not exhaustive?
|
||||
var blockElementNames = ['P', 'LI', 'TD', 'TH', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'PRE'];
|
||||
function isBlockElement(node) {
|
||||
return blockElementNames.indexOf(node.nodeName) !== -1;
|
||||
}
|
||||
|
||||
var inlineElementNames = ['A', 'B', 'STRONG', 'I', 'EM', 'SUB', 'SUP', 'U', 'STRIKE'];
|
||||
function isInlineElement(node) {
|
||||
return inlineElementNames.indexOf(node.nodeName) !== -1;
|
||||
}
|
||||
|
||||
HTMLJanitor.prototype.clean = function (html) {
|
||||
var sandbox = document.createElement('div');
|
||||
sandbox.innerHTML = html;
|
||||
|
||||
this._sanitize(sandbox);
|
||||
|
||||
return sandbox.innerHTML;
|
||||
};
|
||||
|
||||
HTMLJanitor.prototype._sanitize = function (parentNode) {
|
||||
var treeWalker = createTreeWalker(parentNode);
|
||||
var node = treeWalker.firstChild();
|
||||
if (!node) { return; }
|
||||
|
||||
do {
|
||||
// Ignore nodes that have already been sanitized
|
||||
if (node._sanitized) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node.nodeType === Node.TEXT_NODE) {
|
||||
// If this text node is just whitespace and the previous or next element
|
||||
// sibling is a block element, remove it
|
||||
// N.B.: This heuristic could change. Very specific to a bug with
|
||||
// `contenteditable` in Firefox: http://jsbin.com/EyuKase/1/edit?js,output
|
||||
// FIXME: make this an option?
|
||||
if (node.data.trim() === ''
|
||||
&& ((node.previousElementSibling && isBlockElement(node.previousElementSibling))
|
||||
|| (node.nextElementSibling && isBlockElement(node.nextElementSibling)))) {
|
||||
parentNode.removeChild(node);
|
||||
this._sanitize(parentNode);
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all comments
|
||||
if (node.nodeType === Node.COMMENT_NODE) {
|
||||
parentNode.removeChild(node);
|
||||
this._sanitize(parentNode);
|
||||
break;
|
||||
}
|
||||
|
||||
var isInline = isInlineElement(node);
|
||||
var containsBlockElement;
|
||||
if (isInline) {
|
||||
containsBlockElement = Array.prototype.some.call(node.childNodes, isBlockElement);
|
||||
}
|
||||
|
||||
// Block elements should not be nested (e.g. <li><p>...); if
|
||||
// they are, we want to unwrap the inner block element.
|
||||
var isNotTopContainer = !! parentNode.parentNode;
|
||||
var isNestedBlockElement =
|
||||
isBlockElement(parentNode) &&
|
||||
isBlockElement(node) &&
|
||||
isNotTopContainer;
|
||||
|
||||
var nodeName = node.nodeName.toLowerCase();
|
||||
|
||||
var allowedAttrs = getAllowedAttrs(this.config, nodeName, node);
|
||||
|
||||
var isInvalid = isInline && containsBlockElement;
|
||||
|
||||
// Drop tag entirely according to the whitelist *and* if the markup
|
||||
// is invalid.
|
||||
if (isInvalid || shouldRejectNode(node, allowedAttrs)
|
||||
|| (!this.config.keepNestedBlockElements && isNestedBlockElement)) {
|
||||
// Do not keep the inner text of SCRIPT/STYLE elements.
|
||||
if (! (node.nodeName === 'SCRIPT' || node.nodeName === 'STYLE')) {
|
||||
while (node.childNodes.length > 0) {
|
||||
parentNode.insertBefore(node.childNodes[0], node);
|
||||
}
|
||||
}
|
||||
parentNode.removeChild(node);
|
||||
|
||||
this._sanitize(parentNode);
|
||||
break;
|
||||
}
|
||||
|
||||
// Sanitize attributes
|
||||
for (var a = 0; a < node.attributes.length; a += 1) {
|
||||
var attr = node.attributes[a];
|
||||
|
||||
if (shouldRejectAttr(attr, allowedAttrs, node)) {
|
||||
node.removeAttribute(attr.name);
|
||||
// Shift the array to continue looping.
|
||||
a = a - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Sanitize children
|
||||
this._sanitize(node);
|
||||
|
||||
// Mark node as sanitized so it's ignored in future runs
|
||||
node._sanitized = true;
|
||||
} while ((node = treeWalker.nextSibling()));
|
||||
};
|
||||
|
||||
function createTreeWalker(node) {
|
||||
return document.createTreeWalker(node,
|
||||
NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT,
|
||||
null, false);
|
||||
}
|
||||
|
||||
function getAllowedAttrs(config, nodeName, node){
|
||||
if (typeof config.tags[nodeName] === 'function') {
|
||||
return config.tags[nodeName](node);
|
||||
} else {
|
||||
return config.tags[nodeName];
|
||||
}
|
||||
}
|
||||
|
||||
function shouldRejectNode(node, allowedAttrs){
|
||||
if (typeof allowedAttrs === 'undefined') {
|
||||
return true;
|
||||
} else if (typeof allowedAttrs === 'boolean') {
|
||||
return !allowedAttrs;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function shouldRejectAttr(attr, allowedAttrs, node){
|
||||
var attrName = attr.name.toLowerCase();
|
||||
|
||||
if (allowedAttrs === true){
|
||||
return false;
|
||||
} else if (typeof allowedAttrs[attrName] === 'function'){
|
||||
return !allowedAttrs[attrName](attr.value, node);
|
||||
} else if (typeof allowedAttrs[attrName] === 'undefined'){
|
||||
return true;
|
||||
} else if (allowedAttrs[attrName] === false) {
|
||||
return true;
|
||||
} else if (typeof allowedAttrs[attrName] === 'string') {
|
||||
return (allowedAttrs[attrName] !== attr.value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return HTMLJanitor;
|
||||
|
||||
}));
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 10 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* WEBPACK VAR INJECTION */(function(Module, $) {
|
||||
|
||||
|
|
@ -2008,7 +2301,7 @@ module.exports = exports['default'];
|
|||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(2)))
|
||||
|
||||
/***/ }),
|
||||
/* 10 */
|
||||
/* 11 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
|
@ -2271,7 +2564,7 @@ module.exports = exports['default'];
|
|||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(1)))
|
||||
|
||||
/***/ }),
|
||||
/* 11 */
|
||||
/* 12 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
|
@ -2446,7 +2739,7 @@ var UI = function (_Module) {
|
|||
/**
|
||||
* Load CSS
|
||||
*/
|
||||
var styles = __webpack_require__(12);
|
||||
var styles = __webpack_require__(13);
|
||||
|
||||
/**
|
||||
* Make tag
|
||||
|
|
@ -2735,10 +3028,10 @@ module.exports = exports['default'];
|
|||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(2)))
|
||||
|
||||
/***/ }),
|
||||
/* 12 */
|
||||
/* 13 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
exports = module.exports = __webpack_require__(13)(undefined);
|
||||
exports = module.exports = __webpack_require__(14)(undefined);
|
||||
// imports
|
||||
|
||||
|
||||
|
|
@ -2749,7 +3042,7 @@ exports.push([module.i, ":root {\n\n /**\n * Toolbar buttons\n */\n\n
|
|||
|
||||
|
||||
/***/ }),
|
||||
/* 13 */
|
||||
/* 14 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/*
|
||||
|
|
@ -2830,6 +3123,94 @@ function toComment(sourceMap) {
|
|||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 15 */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
/* WEBPACK VAR INJECTION */(function($) {
|
||||
|
||||
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; }; }();
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
/**
|
||||
*
|
||||
* @class Block
|
||||
* @classdesc This class describes editor`s block, including block`s HTMLElement, data and tool
|
||||
*
|
||||
* @property {Tool} tool — current block tool (Paragraph, for example)
|
||||
* @property {Object} CSS — block`s css classes
|
||||
*
|
||||
*/
|
||||
|
||||
var Block = function () {
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @param {Object} tool — current block plugin`s instance
|
||||
*/
|
||||
function Block(tool) {
|
||||
_classCallCheck(this, Block);
|
||||
|
||||
this.tool = tool;
|
||||
|
||||
this.CSS = {
|
||||
wrapper: 'ce-block',
|
||||
content: 'ce-block__content'
|
||||
};
|
||||
|
||||
this._html = this.compose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make default block wrappers and put tool`s content there
|
||||
*
|
||||
* @returns {HTMLDivElement}
|
||||
* @private
|
||||
*/
|
||||
|
||||
|
||||
_createClass(Block, [{
|
||||
key: 'compose',
|
||||
value: function compose() {
|
||||
|
||||
var wrapper = $.make('div', this.CSS.wrapper),
|
||||
content = $.make('div', this.CSS.content);
|
||||
|
||||
content.appendChild(this.tool.html);
|
||||
wrapper.appendChild(content);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get block`s HTML
|
||||
*
|
||||
* @returns {HTMLDivElement}
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'html',
|
||||
get: function get() {
|
||||
|
||||
return this._html;
|
||||
}
|
||||
}]);
|
||||
|
||||
return Block;
|
||||
}();
|
||||
|
||||
Block.displayName = 'Block';
|
||||
exports.default = Block;
|
||||
module.exports = exports['default'];
|
||||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
||||
//# sourceMappingURL=codex-editor.js.map
|
||||
File diff suppressed because one or more lines are too long
34
package-lock.json
generated
34
package-lock.json
generated
|
|
@ -2986,6 +2986,14 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "5.0.1"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
|
|
@ -2996,14 +3004,6 @@
|
|||
"strip-ansi": "3.0.1"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "5.0.1"
|
||||
}
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.5",
|
||||
"bundled": true,
|
||||
|
|
@ -7994,6 +7994,15 @@
|
|||
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
|
||||
"dev": true
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
||||
|
|
@ -8021,15 +8030,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
|
|
|
|||
|
|
@ -2,9 +2,36 @@
|
|||
* Codex Sanitizer
|
||||
*
|
||||
* @module Sanitizer module
|
||||
* Clears HTML from dirty tags
|
||||
* Clears HTML from taint tags
|
||||
*
|
||||
* @version 2.0.0
|
||||
*
|
||||
* @usage
|
||||
* Module can be used within two ways:
|
||||
* 1) When you have an instance
|
||||
* - this.moduleInstance['Sanitizer'].clean(yourDirtyString);
|
||||
* 2) As static method
|
||||
* - CodexEditor.Sanitizer.clean(yourDirtyString, yourCustomConfiguration);
|
||||
*
|
||||
*
|
||||
* Look up the SanitizerConfig object as example to make your custom restrictions
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {Object} SanitizerConfig
|
||||
* @property {Object} tags - define tags restrictions
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* tags : {
|
||||
* p: true,
|
||||
* a: {
|
||||
* href: true,
|
||||
* rel: "nofollow",
|
||||
* target: "_blank"
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
export default class Sanitizer extends Module {
|
||||
|
||||
|
|
@ -14,55 +41,76 @@ export default class Sanitizer extends Module {
|
|||
*
|
||||
* @property {HTMLJanitor} this.janitor - Sanitizer library
|
||||
*
|
||||
* @param config
|
||||
* @param {SanitizerConfig} config
|
||||
*/
|
||||
constructor(config) {
|
||||
|
||||
super(config);
|
||||
|
||||
// default config
|
||||
this._config = {};
|
||||
this._janitor = null;
|
||||
this.instantConfig = {};
|
||||
this.janitorInstance = null;
|
||||
|
||||
/** Custom configuration */
|
||||
this.sanitizerConfig = config.settings.sanitizer;
|
||||
this.sanitizerConfig = config.settings ? config.settings.sanitizer : {};
|
||||
|
||||
/** HTML Janitor library */
|
||||
this.sanitizerInstance = require('html-janitor');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param library
|
||||
* If developer uses editor's API, then he can customize sanitize restrictions.
|
||||
* Or, sanitizing config can be defined globally in editors initialization. That config will be used everywhere
|
||||
* At least, if there is no config overrides, that API uses Default configuration
|
||||
*
|
||||
* @description If developer uses editor's API, then he can customize sane restrictions.
|
||||
* Or, sane config can be defined globally in editors initialization. That config will be used everywhere
|
||||
* At least, if there is no config overrides, that API uses BASIC Default configation
|
||||
* @uses https://www.npmjs.com/package/html-janitor
|
||||
*
|
||||
* @param {HTMLJanitor} library - sanitizer extension
|
||||
*/
|
||||
set sanitizerInstance(library) {
|
||||
this._janitor = new library(this._config);
|
||||
|
||||
this.janitorInstance = new library(this.instanceConfig);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets sanitizer configuration. Uses default config if user didn't pass the restriction
|
||||
* @param {SanitizerConfig} config
|
||||
*/
|
||||
set sanitizerConfig(config) {
|
||||
|
||||
this._config = {
|
||||
tags: {
|
||||
p: {},
|
||||
a: {
|
||||
href: true,
|
||||
target: '_blank',
|
||||
rel: 'nofollow'
|
||||
if (_.isEmpty(config)) {
|
||||
|
||||
this.instanceConfig = {
|
||||
tags: {
|
||||
p: {},
|
||||
a: {
|
||||
href: true,
|
||||
target: '_blank',
|
||||
rel: 'nofollow'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} else {
|
||||
|
||||
this.instanceConfig = config;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans string from unwanted tags
|
||||
* @param dirtyString
|
||||
* @return {*}
|
||||
* @param {String} taintString - HTML string
|
||||
*
|
||||
* @return {String} clean HTML
|
||||
*/
|
||||
clean(dirtyString) {
|
||||
return this._janitor.clean(dirtyString);
|
||||
clean(taintString) {
|
||||
|
||||
return this.janitorInstance.clean(taintString);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,13 +119,17 @@ export default class Sanitizer extends Module {
|
|||
*
|
||||
* Method allows to use default config
|
||||
*
|
||||
* @param {String} dirtyString - taint string
|
||||
* @param {Object} customConfig - allowed tags
|
||||
* @param {String} taintString - taint string
|
||||
* @param {SanitizerConfig} customConfig - allowed tags
|
||||
*
|
||||
* @return {String} clean HTML
|
||||
*/
|
||||
static clean(dirtyString, customConfig) {
|
||||
static clean(taintString, customConfig) {
|
||||
|
||||
let newInstance = Sanitizer(customConfig);
|
||||
|
||||
return newInstance.clean(dirtyString);
|
||||
return newInstance.clean(taintString);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,4 +97,16 @@ export default class Util {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if object is empty
|
||||
*
|
||||
* @param {Object} object
|
||||
* @return {boolean}
|
||||
*/
|
||||
static isEmpty(object) {
|
||||
|
||||
return Object.keys(object).length === 0 && object.constructor === Object;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue