Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

#86: Addressed the react-fast-compare circular refs warning #91

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"license": "GPL-2.0-or-later",
"version": "2.1.0",
"engines": {
"node": ">=10.0.0",
"node": ">=12.0.0",
"npm": ">=5.7.1"
},
"scripts": {
Expand Down Expand Up @@ -42,13 +42,13 @@
"@babel/cli": "^7.2.3",
"@babel/core": "^7.2.2",
"@babel/preset-react": "^7.0.0",
"@ckeditor/ckeditor5-basic-styles": "^19.0.1",
"@ckeditor/ckeditor5-build-decoupled-document": "^19.0.2",
"@ckeditor/ckeditor5-core": "^19.0.1",
"@ckeditor/ckeditor5-basic-styles": "^20.0.0",
"@ckeditor/ckeditor5-build-decoupled-document": "^20.0.0",
"@ckeditor/ckeditor5-core": "^20.0.0",
"@ckeditor/ckeditor5-dev-env": "^20.2.0",
"@ckeditor/ckeditor5-paragraph": "^19.1.0",
"@ckeditor/ckeditor5-ui": "^19.0.1",
"@ckeditor/ckeditor5-utils": "^19.0.2",
"@ckeditor/ckeditor5-paragraph": "^20.0.0",
"@ckeditor/ckeditor5-ui": "^20.0.0",
"@ckeditor/ckeditor5-utils": "^20.0.0",
"babel-eslint": "^10.0.1",
"babel-loader": "^8.0.5",
"chai": "^4.1.2",
Expand Down
2 changes: 1 addition & 1 deletion sample/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ <h2>The three greatest things you learn from traveling</h2>
</table>
</figure>
<figure class="media">
<oembed url="https://www.youtube.com/watch?v=BLJ4GKKaiXw"></oembed>
<oembed url="https://www.youtube.com/watch?v=MhIK96w7GTI"></oembed>
</figure>
<h3>Appreciation of diversity</h3>
<p>Getting used to an entirely different culture can be challenging. While it’s also nice to learn about cultures online
Expand Down
2 changes: 1 addition & 1 deletion src/components/tree/tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default class Tree extends Component {
onClick: this.props.onClick,
showCompactText: this.props.showCompactText,
showElementTypes: this.props.showElementTypes,
activeNode: this.props.activeNode
activeNodePath: this.props.activeNodePath
} );
} );
} else {
Expand Down
4 changes: 2 additions & 2 deletions src/components/tree/treenode.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default class TreeNode extends Component {
}

handleClick( evt ) {
this.globalTreeProps.onClick( evt, this.definition.node );
this.globalTreeProps.onClick( evt, this.definition.path );
}

getChildren() {
Expand All @@ -36,7 +36,7 @@ export default class TreeNode extends Component {
}

get isActive() {
return this.definition.node === this.globalTreeProps.activeNode;
return JSON.stringify( this.definition.path ) === JSON.stringify( this.globalTreeProps.activeNodePath );
}

shouldComponentUpdate( nextProps ) {
Expand Down
4 changes: 4 additions & 0 deletions src/data/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ export default class EditorListener {
currentEditor.editing.view.off( 'render', this._config.onViewRender );
}
}

export function getCurrentEditorInstance( globalState ) {
return globalState.editors.get( globalState.currentEditorName );
}
6 changes: 3 additions & 3 deletions src/model/data/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

export const SET_MODEL_CURRENT_ROOT_NAME = 'SET_MODEL_CURRENT_ROOT_NAME';
export const SET_MODEL_CURRENT_NODE = 'SET_MODEL_CURRENT_NODE';
export const SET_MODEL_CURRENT_NODE_PATH = 'SET_MODEL_CURRENT_NODE_PATH';
export const SET_MODEL_ACTIVE_TAB = 'SET_MODEL_ACTIVE_TAB';
export const TOGGLE_MODEL_SHOW_MARKERS = 'TOGGLE_MODEL_SHOW_MARKERS';
export const TOGGLE_MODEL_SHOW_COMPACT_TEXT = 'TOGGLE_MODEL_SHOW_COMPACT_TEXT';
Expand All @@ -14,8 +14,8 @@ export function setModelCurrentRootName( currentRootName ) {
return { type: SET_MODEL_CURRENT_ROOT_NAME, currentRootName };
}

export function setModelCurrentNode( currentNode ) {
return { type: SET_MODEL_CURRENT_NODE, currentNode };
export function setModelCurrentNodePath( currentNodePath ) {
return { type: SET_MODEL_CURRENT_NODE_PATH, currentNodePath };
}

export function setModelActiveTab( tabName ) {
Expand Down
64 changes: 33 additions & 31 deletions src/model/data/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import {
SET_MODEL_CURRENT_ROOT_NAME,
SET_MODEL_CURRENT_NODE,
SET_MODEL_CURRENT_NODE_PATH,
SET_MODEL_ACTIVE_TAB,
TOGGLE_MODEL_SHOW_MARKERS,
TOGGLE_MODEL_SHOW_COMPACT_TEXT,
Expand All @@ -21,14 +21,15 @@ import {
import {
getEditorModelRanges,
getEditorModelMarkers,
getEditorModelRoots,
getEditorModelTreeDefinition,
getEditorModelNodeDefinition
} from './utils';
getEditorModelRoots
} from './utils/utils';

import { isModelRoot } from '../utils';
import { getEditorModelNodeDefinition } from './utils/nodeinspector';
import { getEditorModelTreeDefinition } from './utils/tree';
import { isModelRoot, getEditorModelNodeByRootAndPath } from '../utils';

import LocalStorageManager from '../../localstoragemanager';
import { getCurrentEditorInstance } from '../../data/utils';

export const LOCAL_STORAGE_ACTIVE_TAB = 'active-model-tab-name';
export const LOCAL_STORAGE_SHOW_MARKERS = 'model-show-markers';
Expand Down Expand Up @@ -57,12 +58,16 @@ function modelDataReducer( globalState, modelState, action ) {
switch ( action.type ) {
case SET_MODEL_CURRENT_ROOT_NAME:
return getNewCurrentRootNameState( globalState, modelState, action );
case SET_MODEL_CURRENT_NODE:
case SET_MODEL_CURRENT_NODE_PATH:
return {
...modelState,

currentNode: action.currentNode,
currentNodeDefinition: getEditorModelNodeDefinition( getCurrentEditor( globalState ), action.currentNode )
currentNodePath: action.currentNodePath,
currentNodeDefinition: getEditorModelNodeDefinition(
getCurrentEditorInstance( globalState ),
modelState.currentRootName,
action.currentNodePath
)
};

// * SET_ACTIVE_INSPECTOR_TAB – Because of the performance optimization at the beginning, update the state
Expand Down Expand Up @@ -111,7 +116,7 @@ function getNewCurrentRootNameState( globalState, modelState, action ) {
...modelState,

...getEssentialState( globalState, modelState, { currentRootName } ),
currentNode: null,
currentNodePath: null,
currentNodeDefinition: null,
currentRootName
};
Expand Down Expand Up @@ -152,7 +157,7 @@ function getNewShowCompactTextState( UIState ) {
}

function getBlankModelState( globalState, modelState = {} ) {
const currentEditor = getCurrentEditor( globalState );
const currentEditor = getCurrentEditorInstance( globalState );

if ( !currentEditor ) {
return {
Expand All @@ -165,15 +170,18 @@ function getBlankModelState( globalState, modelState = {} ) {
return {
...modelState,

...getEssentialState( globalState, modelState, { currentRootName } ),
...getEssentialState( globalState, modelState, {
currentRootName,
currentNodeDefinition: null
} ),
currentRootName,
currentNode: null,
currentNodePath: null,
currentNodeDefinition: null
};
}

function getEssentialState( globalState, modelState, modelStateOverrides ) {
const currentEditor = getCurrentEditor( globalState );
const currentEditor = getCurrentEditorInstance( globalState );
const overriddenModelState = { ...modelState, ...modelStateOverrides };
const currentRootName = overriddenModelState.currentRootName;

Expand All @@ -186,34 +194,28 @@ function getEssentialState( globalState, modelState, modelStateOverrides ) {
markers
} );

let currentNode = overriddenModelState.currentNode;
let currentNodeDefinition = overriddenModelState.currentNodeDefinition;
let currentNodeDefinition = overriddenModelState.currentNodeDefinition || null;
let currentNodePath = null;

// If there was an inspected node definition, try updating it.
if ( currentNodeDefinition ) {
currentNodePath = currentNodeDefinition.path;

if ( currentNode ) {
// * If the currentNode no longer belongs to the current root, reset the state.
// This can happen when, for instance, inspecting an element, and it gets removed from the editor content.
// * If the currentNode was detached, reset the state.
if ( currentNode.root.rootName !== currentRootName || ( !isModelRoot( currentNode ) && !currentNode.parent ) ) {
currentNode = null;
// It could be the root has changed so the current node does no belong to the new inspected root.
if ( !getEditorModelNodeByRootAndPath( currentEditor, currentRootName, currentNodePath ) ) {
currentNodePath = null;
currentNodeDefinition = null;
} else {
// Update the current node definition each time the new model state is created.
currentNodeDefinition = getEditorModelNodeDefinition( currentEditor, currentNode );
currentNodeDefinition = getEditorModelNodeDefinition( currentEditor, currentRootName, currentNodePath );
}
} else {
// No current node, no definition.
currentNodeDefinition = null;
}

return {
treeDefinition,
currentNode,
currentNodePath,
currentNodeDefinition,
ranges,
markers
};
}

function getCurrentEditor( globalState ) {
return globalState.editors.get( globalState.currentEditorName );
}
101 changes: 101 additions & 0 deletions src/model/data/utils/nodeinspector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/**
* @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/

import {
isModelElement,
isModelRoot,
getModelNodePathString,
getEditorModelNodeByRootAndPath
} from '../../utils';

import { stringifyPropertyList } from '../../../components/utils';

const DOCS_URL_PREFIX = 'https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_model_';

/**
* Returns a definition for the model node inspector.
*
* @param {Editor} currentEditor
* @param {String} currentRootName
* @param {Array} nodePath
*
* @returns {Object}
*/
export function getEditorModelNodeDefinition( currentEditor, currentRootName, nodePath ) {
const node = getEditorModelNodeByRootAndPath( currentEditor, currentRootName, nodePath );

const definition = {
path: nodePath,
rootName: currentRootName,

properties: {},
attributes: {}
};

if ( isModelElement( node ) ) {
if ( isModelRoot( node ) ) {
definition.type = 'RootElement';
definition.name = node.rootName;
definition.url = `${ DOCS_URL_PREFIX }rootelement-RootElement.html`;
} else {
definition.type = 'Element';
definition.name = node.name;
definition.url = `${ DOCS_URL_PREFIX }element-Element.html`;
}

definition.properties = {
childCount: {
value: node.childCount
},
startOffset: {
value: node.startOffset
},
endOffset: {
value: node.endOffset
},
maxOffset: {
value: node.maxOffset
}
};
} else {
definition.name = node.data;
definition.type = 'Text';
definition.url = `${ DOCS_URL_PREFIX }text-Text.html`;

definition.properties = {
startOffset: {
value: node.startOffset
},
endOffset: {
value: node.endOffset
},
offsetSize: {
value: node.offsetSize
}
};
}

definition.properties.path = { value: getModelNodePathString( node ) };

for ( const [ name, value ] of node.getAttributes() ) {
definition.attributes[ name ] = { value };
}

definition.properties = stringifyPropertyList( definition.properties );
definition.attributes = stringifyPropertyList( definition.attributes );

for ( const attribute in definition.attributes ) {
const attributePropertyDefinitions = {};
const attirbuteProperties = currentEditor.model.schema.getAttributeProperties( attribute );

for ( const name in attirbuteProperties ) {
attributePropertyDefinitions[ name ] = { value: attirbuteProperties[ name ] };
}

definition.attributes[ attribute ].subProperties = stringifyPropertyList( attributePropertyDefinitions );
}

return definition;
}
Loading