Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Release 2.19.1 #1465

Merged
merged 11 commits into from
Dec 8, 2020
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Temporary suppress some errors. We need to fix them partially in next patches
*/
"import/no-duplicates": ["warn"],
"@typescript-eslint/triple-slash-reference": ["off"]
},
"settings": {
"jsdoc": {
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ node_modules/*

npm-debug.log
yarn-error.log

test/cypress/screenshots
test/cypress/videos
9 changes: 9 additions & 0 deletions cypress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"env": {
},
"fixturesFolder": "test/cypress/fixtures",
"integrationFolder": "test/cypress/tests",
"screenshotsFolder": "test/cypress/screenshots",
"videosFolder": "test/cypress/videos",
"supportFile": "test/cypress/support/index.ts"
}
2 changes: 1 addition & 1 deletion dist/editor.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/editor.js.LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/*!
* Editor.js
*
* @version 2.19.0
* @version 2.19.1
*
* @licence Apache-2.0
* @author CodeX <https://codex.so>
Expand Down
12 changes: 12 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Changelog

### 2.19.1

- `Improvements` - The [Cypress](https://www.cypress.io) was integrated as the end-to-end testing framework
- `Improvements` - Native `typeof`replaced with custom utils methods
- `Improvements` - Bind shortcuts listeners on the editor wrapper instead of document (#1391)(https://github.com/codex-team/editor.js/issues/1391)
- `Fix` - The problem with destroy() method [#1380](https://github.com/codex-team/editor.js/issues/1380).
- `Fix` - add getter keyword to `block.mergeable` method [#1415](https://github.com/codex-team/editor.js/issues/1415).
- `Fix` — Fix problem with entering to Editor.js by Tab key [#1393](https://github.com/codex-team/editor.js/issues/1393)
- `Fix` - Sanitize pasted block data [#1396](https://github.com/codex-team/editor.js/issues/1396).
- `Fix` - Unnecessary block creation after arrow navigation at last non-default block[#1414](https://github.com/codex-team/editor.js/issues/1414)


### 2.19

- `New` - Read-only mode 🥳 [#837](https://github.com/codex-team/editor.js/issues/837)
Expand Down
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@editorjs/editorjs",
"version": "2.19.0",
"version": "2.19.1",
"description": "Editor.js — Native JS, based on API and Open Source",
"main": "dist/editor.js",
"types": "./types/index.d.ts",
Expand All @@ -16,13 +16,15 @@
"build:win": "rimraf dist && yarn svg:win && yarn build:prod",
"build:dev": "webpack --mode development --progress --display-error-details --display-entrypoints --watch",
"build:prod": "webpack --mode production",
"lint": "eslint src/ --ext .ts",
"lint": "eslint src/ --ext .ts && yarn lint:tests",
"lint:errors": "eslint src/ --ext .ts --quiet",
"lint:fix": "eslint src/ --ext .ts --fix",
"lint:tests": "eslint test/ --ext .ts",
"svg:win": "if not exist dist md dist && yarn svg",
"svg": "svg-sprite-generate -d src/assets/ -o dist/sprite.svg",
"pull_tools": "git submodule update --init --recursive",
"checkout_tools": "git submodule foreach git pull origin master"
"checkout_tools": "git submodule foreach git pull origin master",
"test:e2e": "cypress run"
},
"author": "CodeX",
"license": "Apache-2.0",
Expand All @@ -46,9 +48,11 @@
"core-js": "3.6.5",
"css-loader": "^3.5.3",
"cssnano": "^4.1.10",
"cypress": "^5.5.0",
"eslint": "^6.8.0",
"eslint-config-codex": "^1.3.3",
"eslint-loader": "^4.0.2",
"eslint-plugin-cypress": "^2.11.2",
"extract-text-webpack-plugin": "^3.0.2",
"html-janitor": "^2.0.4",
"license-webpack-plugin": "^2.1.4",
Expand Down
2 changes: 1 addition & 1 deletion src/codex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export default class EditorJS {
/**
* If `onReady` was passed in `configuration` then redefine onReady function
*/
if (typeof configuration === 'object' && _.isFunction(configuration.onReady)) {
if (_.isObject(configuration) && _.isFunction(configuration.onReady)) {
onReady = configuration.onReady;
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/block/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ export default class Block {
* @param {BlockToolData} options.data - Tool's initial data
* @param {BlockToolConstructable} options.Tool — Tool's class
* @param {ToolSettings} options.settings - default tool's config
* @param {Module} options.api - Editor API module for pass it to the Block Tunes
* @param options.api - Editor API module for pass it to the Block Tunes
* @param {boolean} options.readOnly - Read-Only flag
*/
constructor({
Expand Down Expand Up @@ -358,7 +358,7 @@ export default class Block {
*
* @returns {boolean}
*/
public mergeable(): boolean {
public get mergeable(): boolean {
return _.isFunction(this.tool.merge);
}

Expand Down
7 changes: 3 additions & 4 deletions src/components/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export default class Core {
* Process zero-configuration or with only holderId
* Make config object
*/
if (typeof config !== 'object') {
if (!_.isObject(config)) {
config = {
holder: config,
};
Expand Down Expand Up @@ -185,7 +185,6 @@ export default class Core {
a: true,
} as SanitizerConfig;


this.config.hideToolbar = this.config.hideToolbar ? this.config.hideToolbar : false;
this.config.tools = this.config.tools || {};
this.config.i18n = this.config.i18n || {};
Expand Down Expand Up @@ -247,11 +246,11 @@ export default class Core {
/**
* Check for a holder element's existence
*/
if (typeof holder === 'string' && !$.get(holder)) {
if (_.isString(holder) && !$.get(holder)) {
throw Error(`element with ID «${holder}» is missing. Pass correct holder's ID.`);
}

if (holder && typeof holder === 'object' && !$.isElement(holder)) {
if (holder && _.isObject(holder) && !$.isElement(holder)) {
throw Error('holder as HTMLElement if provided must be inherit from Element class.');
}
}
Expand Down
16 changes: 12 additions & 4 deletions src/components/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,11 @@ export default class Dom {
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public static isElement(node: any): node is Element {
return node && typeof node === 'object' && node.nodeType && node.nodeType === Node.ELEMENT_NODE;
if (_.isNumber(node)) {
return false;
}

return node && node.nodeType && node.nodeType === Node.ELEMENT_NODE;
}

/**
Expand All @@ -303,7 +307,11 @@ export default class Dom {
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public static isFragment(node: any): node is DocumentFragment {
return node && typeof node === 'object' && node.nodeType && node.nodeType === Node.DOCUMENT_FRAGMENT_NODE;
if (_.isNumber(node)) {
return false;
}

return node && node.nodeType && node.nodeType === Node.DOCUMENT_FRAGMENT_NODE;
}

/**
Expand Down Expand Up @@ -532,7 +540,7 @@ export default class Dom {
public static containsOnlyInlineElements(data: string | HTMLElement): boolean {
let wrapper: HTMLElement;

if (typeof data === 'string') {
if (_.isString(data)) {
wrapper = document.createElement('div');
wrapper.innerHTML = data;
} else {
Expand Down Expand Up @@ -572,7 +580,7 @@ export default class Dom {
* @returns {HTMLElement}
*/
public static getHolder(element: string | HTMLElement): HTMLElement {
if (typeof element === 'string') {
if (_.isString(element)) {
return document.getElementById(element);
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/flipper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export default class Flipper {
* @param {FlipperOptions} options - different constructing settings
*/
constructor(options: FlipperOptions) {
this.allowArrows = typeof options.allowArrows === 'boolean' ? options.allowArrows : true;
this.allowArrows = _.isBoolean(options.allowArrows) ? options.allowArrows : true;
this.iterator = new DomIterator(options.items, options.focusedItemClass);
this.activateCallback = options.activateCallback;
}
Expand Down
6 changes: 3 additions & 3 deletions src/components/i18n/namespace-internal.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import defaultDictionary from './locales/en/messages.json';
import { DictNamespaces } from '../../types-internal/i18n-internal-namespace';
import { typeOf } from '../utils';
import { isObject, isString } from '../utils';

/**
* Evaluate messages dictionary and return object for namespace chaining
Expand All @@ -12,14 +12,14 @@ function getNamespaces(dict: object, keyPath?: string): DictNamespaces<typeof de
const result = {};

Object.entries(dict).forEach(([key, section]) => {
if (typeOf(section) === 'object') {
if (isObject(section)) {
const newPath = keyPath ? `${keyPath}.${key}` : key;

/**
* Check current section values, if all of them are strings, so there is the last section
*/
const isLastSection = Object.values(section).every((sectionValue) => {
return typeOf(sectionValue) === 'string';
return isString(sectionValue);
});

/**
Expand Down
14 changes: 11 additions & 3 deletions src/components/modules/caret.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,14 +396,22 @@ export default class Caret extends Module {
const { BlockManager, Tools } = this.Editor;
const { currentBlock, nextContentfulBlock } = BlockManager;
const { nextInput } = currentBlock;
const isAtEnd = this.isAtEnd;

let nextBlock = nextContentfulBlock;

if (!nextBlock && !nextInput) {
/**
* If there is no nextBlock and currentBlock is default, do not navigate
* This code allows to exit from the last non-initial tool:
* https://github.com/codex-team/editor.js/issues/1103
*/
if (Tools.isDefault(currentBlock.tool)) {

/**
* 1. If there is a last block and it is default, do nothing
* 2. If there is a last block and it is non-default --> and caret not at the end <--, do nothing
* (https://github.com/codex-team/editor.js/issues/1414)
*/
if (Tools.isDefault(currentBlock.tool) || !isAtEnd) {
return false;
}

Expand All @@ -414,7 +422,7 @@ export default class Caret extends Module {
nextBlock = BlockManager.insertAtEnd();
}

if (force || this.isAtEnd) {
if (force || isAtEnd) {
/** If next Tool`s input exists, focus on it. Otherwise set caret to the next Block */
if (!nextInput) {
this.setToBlock(nextBlock, this.positions.START);
Expand Down
7 changes: 4 additions & 3 deletions src/components/modules/paste.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ export default class Paste extends Module {
return;
}

if (typeof toolInstance.onPaste !== 'function') {
if (!_.isFunction(toolInstance.onPaste)) {
return;
}

Expand Down Expand Up @@ -760,9 +760,10 @@ export default class Paste extends Module {
* @returns {void}
*/
private insertEditorJSData(blocks: Array<Pick<SavedData, 'data' | 'tool'>>): void {
const { BlockManager, Tools } = this.Editor;
const { BlockManager, Sanitizer, Tools } = this.Editor;
const sanitizedBlocks = Sanitizer.sanitizeBlocks(blocks);

blocks.forEach(({ tool, data }, i) => {
sanitizedBlocks.forEach(({ tool, data }, i) => {
let needToReplaceCurrentBlock = false;

if (i === 0) {
Expand Down
12 changes: 6 additions & 6 deletions src/components/modules/sanitizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export default class Sanitizer extends Module {
* Array: call sanitize for each item
*/
return this.cleanArray(dataToSanitize, rules);
} else if (typeof dataToSanitize === 'object') {
} else if (_.isObject(dataToSanitize)) {
/**
* Objects: just clean object deeper.
*/
Expand All @@ -105,7 +105,7 @@ export default class Sanitizer extends Module {
*
* Clean only strings
*/
if (typeof dataToSanitize === 'string') {
if (_.isString(dataToSanitize)) {
return this.cleanOneItem(dataToSanitize, rules);
}

Expand Down Expand Up @@ -169,7 +169,7 @@ export default class Sanitizer extends Module {
if (Object.prototype.hasOwnProperty.call(toolRules, fieldName)) {
const rule = toolRules[fieldName];

if (typeof rule === 'object') {
if (_.isObject(rule)) {
toolConfig[fieldName] = Object.assign({}, baseConfig, rule);
} else {
toolConfig[fieldName] = rule;
Expand All @@ -195,7 +195,7 @@ export default class Sanitizer extends Module {

let config = {} as SanitizerConfig;

if (typeof enableInlineTools === 'boolean' && enableInlineTools) {
if (_.isBoolean(enableInlineTools) && enableInlineTools) {
/**
* getting all tools sanitizer rule
*/
Expand Down Expand Up @@ -292,7 +292,7 @@ export default class Sanitizer extends Module {
* @returns {string}
*/
private cleanOneItem(taintString: string, rule: SanitizerConfig|boolean): string {
if (typeof rule === 'object') {
if (_.isObject(rule)) {
return this.clean(taintString, rule);
} else if (rule === false) {
return this.clean(taintString, {} as SanitizerConfig);
Expand All @@ -309,7 +309,7 @@ export default class Sanitizer extends Module {
* @param {SanitizerConfig} config - config to check
*/
private isRule(config: SanitizerConfig): boolean {
return typeof config === 'object' || typeof config === 'boolean' || _.isFunction(config);
return _.isObject(config) || _.isBoolean(config) || _.isFunction(config);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/components/modules/shortcuts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default class Shortcuts extends Module {
public add(shortcut: ShortcutData): void {
const newShortcut = new Shortcut({
name: shortcut.name,
on: document, // UI.nodes.redactor
on: this.Editor.UI.nodes.redactor,
callback: shortcut.handler,
});

Expand Down
10 changes: 8 additions & 2 deletions src/components/modules/toolbar/blockSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,14 @@ export default class BlockSettings extends Module<BlockSettingsNodes> {
* Destroys module
*/
public destroy(): void {
this.flipper.deactivate();
this.flipper = null;
/**
* Sometimes (in read-only mode) there is no Flipper
*/
if (this.flipper) {
this.flipper.deactivate();
this.flipper = null;
}

this.removeAllNodes();
}

Expand Down
14 changes: 10 additions & 4 deletions src/components/modules/toolbar/conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,14 @@ export default class ConversionToolbar extends Module<ConversionToolbarNodes> {
* Deactivates flipper and removes all nodes
*/
public destroy(): void {
this.flipper.deactivate();
this.flipper = null;
/**
* Sometimes (in read-only mode) there is no Flipper
*/
if (this.flipper) {
this.flipper.deactivate();
this.flipper = null;
}

this.removeAllNodes();
}

Expand Down Expand Up @@ -209,7 +215,7 @@ export default class ConversionToolbar extends Module<ConversionToolbarNodes> {

if (_.isFunction(exportProp)) {
exportData = exportProp(blockData);
} else if (typeof exportProp === 'string') {
} else if (_.isString(exportProp)) {
exportData = blockData[exportProp];
} else {
_.log('Conversion «export» property must be a string or function. ' +
Expand All @@ -236,7 +242,7 @@ export default class ConversionToolbar extends Module<ConversionToolbarNodes> {

if (_.isFunction(importProp)) {
newBlockData = importProp(cleaned);
} else if (typeof importProp === 'string') {
} else if (_.isString(importProp)) {
newBlockData[importProp] = cleaned;
} else {
_.log('Conversion «import» property must be a string or function. ' +
Expand Down
Loading