mirror of
https://github.com/codex-team/editor.js
synced 2024-06-02 14:02:17 +02:00
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:
parent
c18011595a
commit
75379c66a9
|
@ -7,8 +7,10 @@
|
||||||
- `Improvement` — The `onChange` callback won't be triggered only if all mutations contain nodes with the `data-mutation-free` attributes.
|
- `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` — 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.
|
- `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
|
- `Improvement` — Package size reduced by removing redundant files.
|
||||||
- `Fix`- Several bugs caused by random browser extensions
|
- `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
|
### 2.26.5
|
||||||
|
|
||||||
|
|
|
@ -83,9 +83,9 @@
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"stylelint": "^13.3.3",
|
"stylelint": "^13.3.3",
|
||||||
"terser-webpack-plugin": "^2.3.6",
|
"terser-webpack-plugin": "^2.3.6",
|
||||||
"ts-loader": "^7.0.1",
|
"ts-loader": "^8.4.0",
|
||||||
"tslint": "^6.1.1",
|
"tslint": "^6.1.1",
|
||||||
"typescript": "3.8.3",
|
"typescript": "^5.0.2",
|
||||||
"webpack": "^4.43.0",
|
"webpack": "^4.43.0",
|
||||||
"webpack-cli": "^3.3.11"
|
"webpack-cli": "^3.3.11"
|
||||||
},
|
},
|
||||||
|
|
|
@ -346,6 +346,10 @@ export default class Paste extends Module {
|
||||||
* @param tool - BlockTool object
|
* @param tool - BlockTool object
|
||||||
*/
|
*/
|
||||||
private getTagsConfig(tool: BlockTool): void {
|
private getTagsConfig(tool: BlockTool): void {
|
||||||
|
if (tool.pasteConfig === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const tagsOrSanitizeConfigs = tool.pasteConfig.tags || [];
|
const tagsOrSanitizeConfigs = tool.pasteConfig.tags || [];
|
||||||
const toolTags = [];
|
const toolTags = [];
|
||||||
|
|
||||||
|
@ -387,6 +391,10 @@ export default class Paste extends Module {
|
||||||
* @param tool - BlockTool object
|
* @param tool - BlockTool object
|
||||||
*/
|
*/
|
||||||
private getFilesConfig(tool: BlockTool): void {
|
private getFilesConfig(tool: BlockTool): void {
|
||||||
|
if (tool.pasteConfig === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const { files = {} } = tool.pasteConfig;
|
const { files = {} } = tool.pasteConfig;
|
||||||
let { extensions, mimeTypes } = files;
|
let { extensions, mimeTypes } = files;
|
||||||
|
|
||||||
|
@ -428,7 +436,11 @@ export default class Paste extends Module {
|
||||||
* @param tool - BlockTool object
|
* @param tool - BlockTool object
|
||||||
*/
|
*/
|
||||||
private getPatternsConfig(tool: BlockTool): void {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,7 +614,10 @@ export default class Paste extends Module {
|
||||||
break;
|
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.
|
* Reduce the tags or sanitize configs to a single array of sanitize config.
|
||||||
|
|
|
@ -158,7 +158,7 @@ export default class BlockTool extends BaseTool<IBlockTool> {
|
||||||
* Returns Tool paste configuration
|
* Returns Tool paste configuration
|
||||||
*/
|
*/
|
||||||
public get pasteConfig(): PasteConfig {
|
public get pasteConfig(): PasteConfig {
|
||||||
return this.constructable[InternalBlockToolSettings.PasteConfig] || {};
|
return this.constructable[InternalBlockToolSettings.PasteConfig] ?? {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import Header from '@editorjs/header';
|
import Header from '@editorjs/header';
|
||||||
import Image from '@editorjs/simple-image';
|
import Image from '@editorjs/simple-image';
|
||||||
import * as _ from '../../../src/components/utils';
|
import * as _ from '../../../src/components/utils';
|
||||||
|
import EditorJS, { BlockTool, BlockToolData } from '../../../types';
|
||||||
|
import $ from '../../../src/components/dom';
|
||||||
|
|
||||||
describe('Copy pasting from Editor', function () {
|
describe('Copy pasting from Editor', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
@ -13,7 +15,7 @@ describe('Copy pasting from Editor', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
if (this.editorInstance) {
|
if (this.editorInstance && this.editorInstance.destroy) {
|
||||||
this.editorInstance.destroy();
|
this.editorInstance.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -139,6 +141,72 @@ describe('Copy pasting from Editor', function () {
|
||||||
.get('img', { timeout: 10000 })
|
.get('img', { timeout: 10000 })
|
||||||
.should('have.attr', 'src', 'https://codex.so/public/app/img/external/codex2x.png');
|
.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 () {
|
context('copying', function () {
|
||||||
|
|
|
@ -253,10 +253,36 @@ describe('BlockTool', () => {
|
||||||
expect(tool.conversionConfig).to.be.deep.eq(options.constructable.conversionConfig);
|
expect(tool.conversionConfig).to.be.deep.eq(options.constructable.conversionConfig);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('.pasteConfig should return correct value', () => {
|
describe('.pasteConfig', () => {
|
||||||
const tool = new BlockTool(options as any);
|
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', () => {
|
context('.enabledInlineTools', () => {
|
||||||
|
|
11
types/configs/paste-config.d.ts
vendored
11
types/configs/paste-config.d.ts
vendored
|
@ -1,9 +1,9 @@
|
||||||
import { SanitizerConfig } from "./sanitizer-config";
|
import { SanitizerConfig } from './sanitizer-config';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tool onPaste configuration object
|
* Tool onPaste configuration object
|
||||||
*/
|
*/
|
||||||
export interface PasteConfig {
|
interface PasteConfigSpecified {
|
||||||
/**
|
/**
|
||||||
* Array of tags Tool can substitute.
|
* Array of tags Tool can substitute.
|
||||||
*
|
*
|
||||||
|
@ -22,7 +22,7 @@ export interface PasteConfig {
|
||||||
* Object of string patterns Tool can substitute.
|
* Object of string patterns Tool can substitute.
|
||||||
* Key is your internal key and value is RegExp
|
* Key is your internal key and value is RegExp
|
||||||
*
|
*
|
||||||
* @type {{[key: string]: Regexp}}
|
* @type {{[key: string]: RegExp}}
|
||||||
*/
|
*/
|
||||||
patterns?: {[key: string]: RegExp};
|
patterns?: {[key: string]: RegExp};
|
||||||
|
|
||||||
|
@ -31,3 +31,8 @@ export interface PasteConfig {
|
||||||
*/
|
*/
|
||||||
files?: {extensions?: string[], mimeTypes?: string[]};
|
files?: {extensions?: string[], mimeTypes?: string[]};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for PasteConfig with false
|
||||||
|
*/
|
||||||
|
export type PasteConfig = PasteConfigSpecified | false;
|
||||||
|
|
22
yarn.lock
22
yarn.lock
|
@ -4799,7 +4799,7 @@ loader-runner@^2.4.0:
|
||||||
version "2.4.0"
|
version "2.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
|
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"
|
version "1.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3"
|
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -7492,15 +7492,16 @@ trough@^1.0.0:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
|
resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
|
||||||
|
|
||||||
ts-loader@^7.0.1:
|
ts-loader@^8.4.0:
|
||||||
version "7.0.5"
|
version "8.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-7.0.5.tgz#789338fb01cb5dc0a33c54e50558b34a73c9c4c5"
|
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.4.0.tgz#e845ea0f38d140bdc3d7d60293ca18d12ff2720f"
|
||||||
|
integrity sha512-6nFY3IZ2//mrPc+ImY3hNWx1vCHyEhl6V+wLmL4CZcm6g1CqX7UKrkc6y0i4FwcfOhxyMPCfaEvh20f4r9GNpw==
|
||||||
dependencies:
|
dependencies:
|
||||||
chalk "^2.3.0"
|
chalk "^4.1.0"
|
||||||
enhanced-resolve "^4.0.0"
|
enhanced-resolve "^4.0.0"
|
||||||
loader-utils "^1.0.2"
|
loader-utils "^2.0.0"
|
||||||
micromatch "^4.0.0"
|
micromatch "^4.0.0"
|
||||||
semver "^6.0.0"
|
semver "^7.3.4"
|
||||||
|
|
||||||
tsconfig-paths@^3.14.1:
|
tsconfig-paths@^3.14.1:
|
||||||
version "3.14.1"
|
version "3.14.1"
|
||||||
|
@ -7595,9 +7596,10 @@ typedarray@^0.0.6:
|
||||||
version "0.0.6"
|
version "0.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||||
|
|
||||||
typescript@3.8.3:
|
typescript@^5.0.2:
|
||||||
version "3.8.3"
|
version "5.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.2.tgz#891e1a90c5189d8506af64b9ef929fca99ba1ee5"
|
||||||
|
integrity sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==
|
||||||
|
|
||||||
unbox-primitive@^1.0.2:
|
unbox-primitive@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
|
|
Loading…
Reference in a new issue