deps(TypeScript) - upgrade to v5, upgrade ts-loader, fix types error, fix pasteConfig getter wrapper (#2322)

* deps: upgrade typescript to v5, upgrade ts-loader to support newest TS

* Fix (??) type of `pasteConfig`

TypeScript 4.9 found something is wrong with this code, but it's unclear (to me) which line is wrong. This PR is a guess, do with it what you will.

In paste.ts there's a check to see if `pasteConfig === false`:
https://github.com/codex-team/editor.js/blob/next/src/components/modules/paste.ts#L287

However, this getter never returns false because if the LHS of the `||` is `false`, `{ }` is returned instead.

It seems like this meant to be `??` instead so that if `this.constructable[InternalBlockToolSettings.PasteConfig]` was `undefined` (missing), then `{}` would be returned instead. But maybe you meant `false` here - I don't know.

* feat: create alias for PasteConfig, fix lint

* fix: problems with types

* test: add case for disabling preventing default behavior of paste event handler, add cases for pasteConfig getter in BlockTool wrapper

* chore: upgrade CHANGELOG.md

* fix: interface naming convention

* chore: apply CHANGELOG.md suggestion

* refactor: create custom Editor instance inside test case

* fix: remove editor instance destroy after PR feedback

---------

Co-authored-by: Ryan Cavanaugh <RyanCavanaugh@users.noreply.github.com>
This commit is contained in:
Ilya Maroz 2023-04-02 16:52:42 +01:00 committed by GitHub
parent c18011595a
commit 75379c66a9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 142 additions and 24 deletions

View file

@ -7,8 +7,10 @@
- `Improvement` — The `onChange` callback won't be triggered only if all mutations contain nodes with the `data-mutation-free` attributes.
- `Fix` — Resolve compiler error from importing the BlockToolData type.
- `Fix` — Resolved a problem when document was being scrolled to the beginning after moving up a Block above the viewport.
- `Improvement` — Package size reduced by removing redundant files
- `Fix`- Several bugs caused by random browser extensions
- `Improvement` — Package size reduced by removing redundant files.
- `Fix`- Several bugs caused by random browser extensions.
- `Improvement`*Dependencies* — Upgrade TypeScript to v5.
- `Fix`*ToolsAPI*`pasteConfig` getter with `false` value could be used to disable paste handling by Editor.js core. Could be useful if your tool has its own paste handler.
### 2.26.5

View file

@ -83,9 +83,9 @@
"rimraf": "^3.0.2",
"stylelint": "^13.3.3",
"terser-webpack-plugin": "^2.3.6",
"ts-loader": "^7.0.1",
"ts-loader": "^8.4.0",
"tslint": "^6.1.1",
"typescript": "3.8.3",
"typescript": "^5.0.2",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
},

View file

@ -346,6 +346,10 @@ export default class Paste extends Module {
* @param tool - BlockTool object
*/
private getTagsConfig(tool: BlockTool): void {
if (tool.pasteConfig === false) {
return;
}
const tagsOrSanitizeConfigs = tool.pasteConfig.tags || [];
const toolTags = [];
@ -387,6 +391,10 @@ export default class Paste extends Module {
* @param tool - BlockTool object
*/
private getFilesConfig(tool: BlockTool): void {
if (tool.pasteConfig === false) {
return;
}
const { files = {} } = tool.pasteConfig;
let { extensions, mimeTypes } = files;
@ -428,7 +436,11 @@ export default class Paste extends Module {
* @param tool - BlockTool object
*/
private getPatternsConfig(tool: BlockTool): void {
if (!tool.pasteConfig.patterns || _.isEmpty(tool.pasteConfig.patterns)) {
if (
tool.pasteConfig === false ||
!tool.pasteConfig.patterns ||
_.isEmpty(tool.pasteConfig.patterns)
) {
return;
}
@ -602,7 +614,10 @@ export default class Paste extends Module {
break;
}
const { tags: tagsOrSanitizeConfigs } = tool.pasteConfig;
/**
* Returns empty array if there is no paste config
*/
const { tags: tagsOrSanitizeConfigs } = tool.pasteConfig || { tags: [] };
/**
* Reduce the tags or sanitize configs to a single array of sanitize config.

View file

@ -158,7 +158,7 @@ export default class BlockTool extends BaseTool<IBlockTool> {
* Returns Tool paste configuration
*/
public get pasteConfig(): PasteConfig {
return this.constructable[InternalBlockToolSettings.PasteConfig] || {};
return this.constructable[InternalBlockToolSettings.PasteConfig] ?? {};
}
/**

View file

@ -1,6 +1,8 @@
import Header from '@editorjs/header';
import Image from '@editorjs/simple-image';
import * as _ from '../../../src/components/utils';
import EditorJS, { BlockTool, BlockToolData } from '../../../types';
import $ from '../../../src/components/dom';
describe('Copy pasting from Editor', function () {
beforeEach(function () {
@ -13,7 +15,7 @@ describe('Copy pasting from Editor', function () {
});
afterEach(function () {
if (this.editorInstance) {
if (this.editorInstance && this.editorInstance.destroy) {
this.editorInstance.destroy();
}
});
@ -139,6 +141,72 @@ describe('Copy pasting from Editor', function () {
.get('img', { timeout: 10000 })
.should('have.attr', 'src', 'https://codex.so/public/app/img/external/codex2x.png');
});
it('should not prevent default behaviour if block\'s paste config equals false', function () {
/**
* Destroy default Editor to render custom one with different tools
*/
cy.get('@editorInstance')
.then((editorInstance: unknown) => (editorInstance as EditorJS).destroy());
const onPasteStub = cy.stub().as('onPaste');
/**
* Tool with disabled preventing default behavior of onPaste event
*/
class BlockToolWithPasteHandler implements BlockTool {
public static pasteConfig = false;
/**
* Render block
*/
public render(): HTMLElement {
const block = $.make('div', 'ce-block-with-disabled-prevent-default', {
contentEditable: 'true',
});
block.addEventListener('paste', onPasteStub);
return block;
}
/**
* Save data method
*/
public save(): BlockToolData {
return {};
}
}
cy.createEditor({
tools: {
blockToolWithPasteHandler: BlockToolWithPasteHandler,
},
}).as('editorInstanceWithBlockToolWithPasteHandler');
cy.get('@editorInstanceWithBlockToolWithPasteHandler')
.render({
blocks: [
{
type: 'blockToolWithPasteHandler',
data: {},
},
],
});
cy.get('@editorInstanceWithBlockToolWithPasteHandler')
.get('div.ce-block-with-disabled-prevent-default')
.click()
.paste({
// eslint-disable-next-line @typescript-eslint/naming-convention
'text/plain': 'Hello',
});
cy.get('@onPaste')
.should('have.been.calledWithMatch', {
defaultPrevented: false,
});
});
});
context('copying', function () {

View file

@ -253,10 +253,36 @@ describe('BlockTool', () => {
expect(tool.conversionConfig).to.be.deep.eq(options.constructable.conversionConfig);
});
it('.pasteConfig should return correct value', () => {
const tool = new BlockTool(options as any);
describe('.pasteConfig', () => {
it('should return correct value', () => {
const tool = new BlockTool(options as any);
expect(tool.pasteConfig).to.be.deep.eq(options.constructable.pasteConfig);
expect(tool.pasteConfig).to.be.deep.eq(options.constructable.pasteConfig);
});
it('should return false if `false` value was provided', () => {
const optionsWithDisabledPaste = {
...options,
constructable: class extends (options.constructable as any) {
public static pasteConfig = false;
},
};
const tool = new BlockTool(optionsWithDisabledPaste as any);
expect(tool.pasteConfig).to.be.deep.eq(optionsWithDisabledPaste.constructable.pasteConfig);
});
it('should return empty object if getter isn\'t provided', () => {
const optionsWithoutPasteConfig = {
...options,
constructable: class extends (options.constructable as any) {
public static pasteConfig = undefined;
},
};
const tool = new BlockTool(optionsWithoutPasteConfig as any);
expect(tool.pasteConfig).to.be.deep.eq({});
});
});
context('.enabledInlineTools', () => {

View file

@ -1,9 +1,9 @@
import { SanitizerConfig } from "./sanitizer-config";
import { SanitizerConfig } from './sanitizer-config';
/**
* Tool onPaste configuration object
*/
export interface PasteConfig {
interface PasteConfigSpecified {
/**
* Array of tags Tool can substitute.
*
@ -22,7 +22,7 @@ export interface PasteConfig {
* Object of string patterns Tool can substitute.
* Key is your internal key and value is RegExp
*
* @type {{[key: string]: Regexp}}
* @type {{[key: string]: RegExp}}
*/
patterns?: {[key: string]: RegExp};
@ -31,3 +31,8 @@ export interface PasteConfig {
*/
files?: {extensions?: string[], mimeTypes?: string[]};
}
/**
* Alias for PasteConfig with false
*/
export type PasteConfig = PasteConfigSpecified | false;

View file

@ -4799,7 +4799,7 @@ loader-runner@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0:
loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0:
version "1.4.2"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3"
dependencies:
@ -7492,15 +7492,16 @@ trough@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
ts-loader@^7.0.1:
version "7.0.5"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-7.0.5.tgz#789338fb01cb5dc0a33c54e50558b34a73c9c4c5"
ts-loader@^8.4.0:
version "8.4.0"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.4.0.tgz#e845ea0f38d140bdc3d7d60293ca18d12ff2720f"
integrity sha512-6nFY3IZ2//mrPc+ImY3hNWx1vCHyEhl6V+wLmL4CZcm6g1CqX7UKrkc6y0i4FwcfOhxyMPCfaEvh20f4r9GNpw==
dependencies:
chalk "^2.3.0"
chalk "^4.1.0"
enhanced-resolve "^4.0.0"
loader-utils "^1.0.2"
loader-utils "^2.0.0"
micromatch "^4.0.0"
semver "^6.0.0"
semver "^7.3.4"
tsconfig-paths@^3.14.1:
version "3.14.1"
@ -7595,9 +7596,10 @@ typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
typescript@3.8.3:
version "3.8.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
typescript@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.2.tgz#891e1a90c5189d8506af64b9ef929fca99ba1ee5"
integrity sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==
unbox-primitive@^1.0.2:
version "1.0.2"