Feat (Conversion-config): pass target tool config to the conversionConfig.import method (#2848)

* pass config to the conversionConfig.import method

- Now `convertStringToBlockData` method passes target tool config the import method
- Fixed types in convesion config file (somehow imprort could return function that returns string, but import should return method that would return ToolData) this caused just type error that never been reached because types were actually ignored
- Added test that checks, that import method actualy gets passed config

* update changelog

* eslint fix

* updated test description

* jsdoc improved

* typos in changelog
This commit is contained in:
e11sy 2024-10-17 19:38:02 +03:00 committed by GitHub
commit da4257a67f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 92 additions and 11 deletions

View file

@ -3,6 +3,7 @@
### 2.31.0
- `New` - Inline tools (those with `isReadOnlySupported` specified) can now be used in read-only mode
- `Improvement` - Block manager passes target tool config to the `conversionConfig.import` method on conversion
- `Fix` - Fix selection of first block in read-only initialization with "autofocus=true"
- `Fix` - Incorrect caret position after blocks merging in Safari
- `Fix` - Several toolbox items exported by the one tool have the same shortcut displayed in toolbox
@ -49,11 +50,11 @@
- `New` "Convert to" control is now also available in Block Tunes
- `New` — Editor.js now supports contenteditable placeholders out of the box. Just add `data-placeholder` or `data-placeholder-active` attribute to make it work. The first one will work like native placeholder while the second one will show placeholder only when block is current.
- `Improvement` — Now Paragraph placeholder will be shown for the current paragraph, not only the first one.
- `Improvment` - The API `blocks.update` now accepts `tunes` data as optional third argument and makes `data` - block data as optional.
- `Improvement` - The API `blocks.update` now accepts `tunes` data as optional third argument and makes `data` - block data as optional.
- `Improvement` — The ability to merge blocks of different types (if both tools provide the conversionConfig)
- `Improvement` - The API `blocks.convert()` now returns the new block API
- `Improvement` - The API `caret.setToBlock()` now can accept either BlockAPI or block index or block id
- `Impovement` *MenuConfig* `TunesMenuConfig` type is deprecated, use the `MenuConfig` instead
- `Improvement` *MenuConfig* `TunesMenuConfig` type is deprecated, use the `MenuConfig` instead
`Improvement`*Types*`BlockToolConstructorOptions` type improved, `block` and `config` are not optional anymore
- `Improvement` - The Plus button and Block Tunes toggler are now better aligned with large line-height blocks, such as Headings
- `Improvement` — Creating links on Android devices: now the mobile keyboard will have an "Enter" key for accepting the inserted link.

View file

@ -863,7 +863,7 @@ export default class BlockManager extends Module {
/**
* Now using Conversion Config "import" we compose a new Block data
*/
let newBlockData = convertStringToBlockData(cleanData, replacingTool.conversionConfig);
let newBlockData = convertStringToBlockData(cleanData, replacingTool.conversionConfig, replacingTool.settings);
/**
* Optional data overrides.

View file

@ -1,4 +1,4 @@
import type { BlockAPI } from '../../../types';
import type { BlockAPI, ToolConfig } from '../../../types';
import type { ConversionConfig } from '../../../types/configs/conversion-config';
import type { SavedData } from '../../../types/data-formats';
import type { BlockToolData } from '../../../types/tools/block-tool-data';
@ -174,12 +174,13 @@ export function convertBlockDataToString(blockData: BlockToolData, conversionCon
*
* @param stringToImport - string to convert
* @param conversionConfig - tool's conversion config
* @param targetToolConfig - target tool config, used in conversionConfig.import method
*/
export function convertStringToBlockData(stringToImport: string, conversionConfig?: ConversionConfig): BlockToolData {
export function convertStringToBlockData(stringToImport: string, conversionConfig?: ConversionConfig, targetToolConfig?: ToolConfig): BlockToolData {
const importProp = conversionConfig?.import;
if (isFunction(importProp)) {
return importProp(stringToImport);
return importProp(stringToImport, targetToolConfig);
} else if (isString(importProp)) {
return {
[importProp]: stringToImport,

View file

@ -3,7 +3,7 @@ import type { BlockTool, BlockToolConstructorOptions } from '../../../../types';
/**
* Simple structure for Tool data
*/
interface MockToolData {
export interface MockToolData {
text: string;
}

View file

@ -1,6 +1,6 @@
import type EditorJS from '../../../../types/index';
import type { ConversionConfig, ToolboxConfig } from '../../../../types';
import ToolMock from '../../fixtures/tools/ToolMock';
import type { ConversionConfig, ToolboxConfig, ToolConfig } from '../../../../types';
import ToolMock, { type MockToolData } from '../../fixtures/tools/ToolMock';
import { nanoid } from 'nanoid';
/**
@ -444,5 +444,84 @@ describe('api.blocks', () => {
});
});
});
it('should pass tool config to the conversionConfig.import method of the tool', function () {
const existingBlock = {
id: 'test-id-123',
type: 'paragraph',
data: {
text: 'Some text',
},
};
const conversionTargetToolConfig = {
defaultStyle: 'defaultStyle',
};
/**
* Mock of Tool with conversionConfig
*/
class ToolWithConversionConfig extends ToolMock {
/**
* Specify conversion config of the tool
*/
public static get conversionConfig(): {
/**
* Method that is responsible for conversion from data to string
*/
export: (data: string) => string;
/**
* Method that is responsible for conversion from string to data
* Should return stringified config to see, if Editor actually passed tool config to it
*/
import: (content: string, config: ToolConfig) => MockToolData;
} {
return {
export: (data) => data,
/**
* Passed config should be returned
*/
import: (_content, config) => {
return { text: JSON.stringify(config) };
},
};
}
}
cy.createEditor({
tools: {
conversionTargetTool: {
class: ToolWithConversionConfig,
config: conversionTargetToolConfig,
},
},
data: {
blocks: [
existingBlock,
],
},
}).then(async (editor) => {
const { convert } = editor.blocks;
await convert(existingBlock.id, 'conversionTargetTool');
// wait for block to be converted
cy.wait(100).then(async () => {
/**
* Check that block was converted
*/
const { blocks } = await editor.save();
expect(blocks.length).to.eq(1);
expect(blocks[0].type).to.eq('conversionTargetTool');
/**
* Check that tool converted returned config as a result of import
*/
expect(blocks[0].data.text).to.eq(JSON.stringify(conversionTargetToolConfig));
});
});
});
});
});

View file

@ -1,4 +1,4 @@
import type { BlockToolData } from '../tools';
import type { BlockToolData, ToolConfig } from '../tools';
/**
* Config allows Tool to specify how it can be converted into/from another Tool
@ -12,7 +12,7 @@ export interface ConversionConfig {
* 1. String the key of Tool data object to fill it with imported string on render.
* 2. Function method that accepts importing string and composes Tool data to render.
*/
import?: ((data: string) => string) | string;
import?: ((data: string, config: ToolConfig) => BlockToolData) | string;
/**
* How to export this Tool to make other Block.