mirror of
https://github.com/codex-team/editor.js
synced 2024-06-18 13:45:20 +02:00
Validate saved data (#591)
* Specify submodule branch for test * Change branch for testing convenience Just run: git submodule update --remote * Added checklist submodule for test * Attempt to validate data on save * Rewrite promise.then to async/await * Move validate logic to saver * Remove extra space * Fix tabs * Don't need async/await here * Remove submodule * Improve logging, remove empty blocks from data array * Remove warning * Loop over blocks only once * Make validate non-async * Get rid of await Promise.all * Make validate async * Call plugin's validate method with await * Add docs * Update docs * Make separate function for tools validation * Rename method * Add data types interfaces * Improve logging * Desctructure extraction object * Remove useless argument * Update README and changelog * Make separate changelog for version * Increase version * Bump version * Keep logs at their places * Fix logs order * Pull submodules * Improve logs grouping * log styles improved * Describe allExtractedData type * Improve JSDoc
This commit is contained in:
parent
208f8e15ab
commit
fc3e146764
12
dist/codex-editor.js
vendored
12
dist/codex-editor.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,9 @@
|
|||
# Changelog
|
||||
|
||||
### 2.7.28
|
||||
|
||||
- `New` [Tools Validation](https://github.com/codex-team/codex.editor/blob/master/docs/tools.md#validate-optional) is added.
|
||||
|
||||
### 2.2.27
|
||||
|
||||
- `New` *Mobile view* — Editor now adopted for mobile devices
|
||||
|
|
|
@ -39,7 +39,9 @@ Method that returns Tool's element {HTMLElement} that will be placed into Editor
|
|||
|
||||
Process Tool's element created by `render()` function in DOM and return Block's data.
|
||||
|
||||
### validate() _optional_
|
||||
### validate(data: BlockToolData): boolean|Promise\<boolean\> _optional_
|
||||
|
||||
Allows to check correctness of Tool's data. If data didn't pass the validation it won't be saved. Receives Tool's `data` as input param and returns `boolean` result of validation.
|
||||
|
||||
### merge() _optional_
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "codex.editor",
|
||||
"version": "2.7.27",
|
||||
"version": "2.7.28",
|
||||
"description": "CodeX Editor. Native JS, based on API and Open Source",
|
||||
"main": "dist/codex-editor.js",
|
||||
"types": "./types/index.d.ts",
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
ToolConfig,
|
||||
} from '../../types';
|
||||
|
||||
import {SavedData} from '../types-internal/block-data';
|
||||
import $ from './dom';
|
||||
import _ from './utils';
|
||||
|
||||
|
@ -369,7 +370,7 @@ export default class Block {
|
|||
* Groups Tool's save processing time
|
||||
* @return {Object}
|
||||
*/
|
||||
public async save(): Promise<void|{tool: string, data: BlockToolData, time: number}> {
|
||||
public async save(): Promise<void|SavedData> {
|
||||
const extractedBlock = await this.tool.save(this.pluginsContent as HTMLElement);
|
||||
|
||||
/**
|
||||
|
@ -398,23 +399,19 @@ export default class Block {
|
|||
* Uses Tool's validation method to check the correctness of output data
|
||||
* Tool's validation method is optional
|
||||
*
|
||||
* @description Method also can return data if it passed the validation
|
||||
* @description Method returns true|false whether data passed the validation or not
|
||||
*
|
||||
* @param {Object} data
|
||||
* @returns {Boolean|Object} valid
|
||||
* @param {BlockToolData} data
|
||||
* @returns {Promise<boolean>} valid
|
||||
*/
|
||||
public validateData(data: BlockToolData): BlockToolData|false {
|
||||
public async validate(data: BlockToolData): Promise<boolean> {
|
||||
let isValid = true;
|
||||
|
||||
if (this.tool.validate instanceof Function) {
|
||||
isValid = this.tool.validate(data);
|
||||
isValid = await this.tool.validate(data);
|
||||
}
|
||||
|
||||
if (!isValid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return data;
|
||||
return isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
*/
|
||||
import Module from '../__module';
|
||||
import {OutputData} from '../../../types';
|
||||
import {ValidatedData} from '../../types-internal/block-data';
|
||||
import Block from '../block';
|
||||
import _ from '../utils';
|
||||
|
||||
declare const VERSION: string;
|
||||
|
||||
|
@ -34,7 +36,7 @@ export default class Saver extends Module {
|
|||
ModificationsObserver.disable();
|
||||
|
||||
blocks.forEach((block: Block) => {
|
||||
chainData.push(block.save());
|
||||
chainData.push(this.getSavedData(block));
|
||||
});
|
||||
|
||||
const extractedData = await Promise.all(chainData);
|
||||
|
@ -45,9 +47,21 @@ export default class Saver extends Module {
|
|||
return this.makeOutput(sanitizedData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves and validates
|
||||
* @param {Block} block - Editor's Tool
|
||||
* @return {ValidatedData} - Tool's validated data
|
||||
*/
|
||||
private async getSavedData(block: Block): Promise<ValidatedData> {
|
||||
const blockData = await block.save();
|
||||
const isValid = blockData && await block.validate(blockData.data);
|
||||
|
||||
return {...blockData, isValid};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates output object with saved data, time and version of editor
|
||||
* @param {Object} allExtractedData
|
||||
* @param {ValidatedData} allExtractedData
|
||||
* @return {OutputData}
|
||||
*/
|
||||
private makeOutput(allExtractedData): OutputData {
|
||||
|
@ -56,20 +70,33 @@ export default class Saver extends Module {
|
|||
|
||||
console.groupCollapsed('[CodexEditor saving]:');
|
||||
|
||||
allExtractedData.forEach((extraction) => {
|
||||
/** Group process info */
|
||||
console.log(`«${extraction.tool}» saving info`, extraction);
|
||||
totalTime += extraction.time;
|
||||
allExtractedData.forEach(({tool, data, time, isValid}) => {
|
||||
totalTime += time;
|
||||
|
||||
/**
|
||||
* Capitalize Tool name
|
||||
*/
|
||||
console.group(`${tool.charAt(0).toUpperCase() + tool.slice(1)}`);
|
||||
|
||||
if (isValid) {
|
||||
/** Group process info */
|
||||
console.log(data);
|
||||
console.groupEnd();
|
||||
} else {
|
||||
console.log(`Block «${tool}» skipped because saved data is invalid`);
|
||||
console.groupEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
/** If it was stub Block, get original data */
|
||||
if (extraction.tool === this.Editor.Tools.stubTool) {
|
||||
blocks.push(extraction.data);
|
||||
if (tool === this.Editor.Tools.stubTool) {
|
||||
blocks.push(data);
|
||||
return;
|
||||
}
|
||||
|
||||
blocks.push({
|
||||
type: extraction.tool,
|
||||
data: extraction.data,
|
||||
type: tool,
|
||||
data,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
20
src/types-internal/block-data.d.ts
vendored
Normal file
20
src/types-internal/block-data.d.ts
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
import {BlockToolData} from '../../types/tools';
|
||||
|
||||
/**
|
||||
* Tool's saved data
|
||||
*/
|
||||
export interface SavedData {
|
||||
tool: string;
|
||||
data: BlockToolData;
|
||||
time: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tool's data after validation
|
||||
*/
|
||||
export interface ValidatedData {
|
||||
tool?: string;
|
||||
data?: BlockToolData;
|
||||
time?: number;
|
||||
isValid: boolean;
|
||||
}
|
Loading…
Reference in a new issue