mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-19 05:31:56 +02:00
Normalize children before normalizing a node itself
This commit is contained in:
@@ -52,8 +52,9 @@ class State extends new Record(DEFAULTS) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const state = new State({ document, selection })
|
const state = new State({ document, selection })
|
||||||
|
|
||||||
|
// transform.apply will normalize the document
|
||||||
return state.transform()
|
return state.transform()
|
||||||
.normalize()
|
|
||||||
.apply({ save: false })
|
.apply({ save: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -102,7 +102,7 @@ const INLINE_NO_EMPTY = {
|
|||||||
return inline.text == ''
|
return inline.text == ''
|
||||||
},
|
},
|
||||||
normalize: (transform, node) => {
|
normalize: (transform, node) => {
|
||||||
return transform.removeNodeByKey(node.key)
|
return transform.removeNodeByKey(node.key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,9 +270,9 @@ const schema = Schema.create({
|
|||||||
rules: [
|
rules: [
|
||||||
DOCUMENT_CHILDREN_RULE,
|
DOCUMENT_CHILDREN_RULE,
|
||||||
BLOCK_CHILDREN_RULE,
|
BLOCK_CHILDREN_RULE,
|
||||||
MIN_TEXT_RULE,
|
|
||||||
INLINE_CHILDREN_RULE,
|
INLINE_CHILDREN_RULE,
|
||||||
INLINE_VOID_TEXT_RULE,
|
INLINE_VOID_TEXT_RULE,
|
||||||
|
MIN_TEXT_RULE,
|
||||||
INLINE_NO_EMPTY,
|
INLINE_NO_EMPTY,
|
||||||
INLINE_VOID_TEXTS_AROUND_RULE,
|
INLINE_VOID_TEXTS_AROUND_RULE,
|
||||||
NO_ADJACENT_TEXT_RULE,
|
NO_ADJACENT_TEXT_RULE,
|
||||||
|
@@ -147,6 +147,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
normalize,
|
normalize,
|
||||||
normalizeWith,
|
normalizeWith,
|
||||||
|
normalizeNodeWith,
|
||||||
normalizeDocument,
|
normalizeDocument,
|
||||||
normalizeSelection,
|
normalizeSelection,
|
||||||
normalizeNodeByKey
|
normalizeNodeByKey
|
||||||
@@ -293,6 +294,7 @@ export default {
|
|||||||
|
|
||||||
normalize,
|
normalize,
|
||||||
normalizeWith,
|
normalizeWith,
|
||||||
|
normalizeNodeWith,
|
||||||
normalizeDocument,
|
normalizeDocument,
|
||||||
normalizeSelection,
|
normalizeSelection,
|
||||||
normalizeNodeByKey
|
normalizeNodeByKey
|
||||||
|
@@ -1,56 +1,124 @@
|
|||||||
import Schema from '../models/schema'
|
import Schema from '../models/schema'
|
||||||
|
import Raw from '../serializers/raw'
|
||||||
import warning from '../utils/warning'
|
import warning from '../utils/warning'
|
||||||
import { default as defaultSchema } from '../plugins/schema'
|
import { default as defaultSchema } from '../plugins/schema'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize a node using a schema.
|
* Refresh a reference to a node that have been modified in a transform.
|
||||||
|
* @param {Transform} transform
|
||||||
|
* @param {Node} node
|
||||||
|
* @return {Node} newNode
|
||||||
|
*/
|
||||||
|
|
||||||
|
function _refreshNode(transform, node) {
|
||||||
|
const { state } = transform
|
||||||
|
const { document } = state
|
||||||
|
|
||||||
|
if (node.kind == 'document') {
|
||||||
|
return document
|
||||||
|
}
|
||||||
|
|
||||||
|
return document.getDescendant(node.key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize all children of a node
|
||||||
|
* @param {Transform} transform
|
||||||
|
* @param {Schema} schema
|
||||||
|
* @param {Node} node
|
||||||
|
* @return {Transform} transform
|
||||||
|
*/
|
||||||
|
|
||||||
|
function _normalizeChildrenWith(transform, schema, node) {
|
||||||
|
let { state } = transform
|
||||||
|
|
||||||
|
if (!node.nodes) {
|
||||||
|
return transform
|
||||||
|
}
|
||||||
|
|
||||||
|
return node.nodes.reduce(
|
||||||
|
(t, child) => {
|
||||||
|
return t.normalizeNodeWith(schema, child)
|
||||||
|
},
|
||||||
|
transform
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize a node without its children
|
||||||
|
* @param {Transform} transform
|
||||||
|
* @param {Schema} schema
|
||||||
|
* @param {Node} node
|
||||||
|
* @return {Transform} transform
|
||||||
|
*/
|
||||||
|
|
||||||
|
function _normalizeNodeWith(transform, schema, node) {
|
||||||
|
let { state } = transform
|
||||||
|
const failure = schema.__validate(node)
|
||||||
|
|
||||||
|
// Node is valid?
|
||||||
|
if (!failure) {
|
||||||
|
return transform
|
||||||
|
}
|
||||||
|
|
||||||
|
const { value, rule } = failure
|
||||||
|
|
||||||
|
// Normalize and get the new state
|
||||||
|
transform = rule.normalize(transform, node, value)
|
||||||
|
|
||||||
|
// Search for the updated node in the new state
|
||||||
|
const newNode = _refreshNode(transform, node)
|
||||||
|
|
||||||
|
// Node no longer exist, go back to normalize parents
|
||||||
|
if (!newNode) {
|
||||||
|
return transform
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalizeNodeWith(transform, schema, newNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize a node (itself and its children) using a schema.
|
||||||
*
|
*
|
||||||
* @param {Transform} transform
|
* @param {Transform} transform
|
||||||
* @param {Node} node
|
* @param {Schema} schema
|
||||||
|
* @param {Node} node
|
||||||
* @return {Transform}
|
* @return {Transform}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function normalizeWith(transform, schema, node) {
|
export function normalizeNodeWith(transform, schema, node) {
|
||||||
let { state } = transform
|
// Iterate over its children
|
||||||
|
transform = _normalizeChildrenWith(transform, schema, node)
|
||||||
|
|
||||||
// If no node specific, normalize the whole document
|
// Refresh the node reference, and normalize it
|
||||||
node = node || state.document
|
node = _refreshNode(transform, node)
|
||||||
|
if (node) {
|
||||||
|
transform = _normalizeNodeWith(transform, schema, node)
|
||||||
|
}
|
||||||
|
|
||||||
const failure = schema.__validate(node)
|
return transform
|
||||||
|
}
|
||||||
|
|
||||||
if (failure) {
|
/**
|
||||||
const { value, rule } = failure
|
* Normalize state using a schema.
|
||||||
|
*
|
||||||
|
* @param {Transform} transform
|
||||||
|
* @param {Schema} schema
|
||||||
|
* @return {Transform} transform
|
||||||
|
*/
|
||||||
|
|
||||||
// Normalize and get the new state
|
export function normalizeWith(transform, schema) {
|
||||||
transform = rule.normalize(transform, node, value)
|
const { state } = transform
|
||||||
const newState = transform.state
|
const { document } = state
|
||||||
|
|
||||||
// Search for the updated node in the new state
|
return transform.normalizeNodeWith(schema, document)
|
||||||
node = newState.document.getDescendant(node.key)
|
|
||||||
|
|
||||||
// Node no longer exist, exit
|
|
||||||
if (!node) {
|
|
||||||
return transform
|
|
||||||
}
|
|
||||||
|
|
||||||
return transform.normalizeWith(schema, node)
|
|
||||||
}
|
|
||||||
|
|
||||||
// No child, stop here
|
|
||||||
if (!node.nodes) {
|
|
||||||
return transform
|
|
||||||
}
|
|
||||||
|
|
||||||
return node.nodes.reduce((t, child) => {
|
|
||||||
return t.normalizeWith(schema, child)
|
|
||||||
}, transform)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize the state using the core schema.
|
* Normalize the state using the core schema.
|
||||||
*
|
*
|
||||||
* @param {Transform} transform
|
* @param {Transform} transform
|
||||||
* @return {Transform}
|
* @return {Transform} transform
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function normalize(transform) {
|
export function normalize(transform) {
|
||||||
@@ -60,10 +128,10 @@ export function normalize(transform) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize the whole document
|
* Normalize only the document
|
||||||
*
|
*
|
||||||
* @param {Transform} transform
|
* @param {Transform} transform
|
||||||
* @return {Transform}
|
* @return {Transform} transform
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function normalizeDocument(transform) {
|
export function normalizeDocument(transform) {
|
||||||
@@ -71,10 +139,11 @@ export function normalizeDocument(transform) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize a specific node of the document using core schema
|
* Normalize a specific node using core schema
|
||||||
*
|
*
|
||||||
* @param {Transform} transform
|
* @param {Transform} transform
|
||||||
* @return {Transform}
|
* @param {Node or String} key
|
||||||
|
* @return {Transform} transform
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function normalizeNodeByKey(transform, key) {
|
export function normalizeNodeByKey(transform, key) {
|
||||||
@@ -82,14 +151,14 @@ export function normalizeNodeByKey(transform, key) {
|
|||||||
const { document } = state
|
const { document } = state
|
||||||
const node = document.assertDescendant(key)
|
const node = document.assertDescendant(key)
|
||||||
|
|
||||||
return transform.normalizeWith(defaultSchema, node)
|
return transform.normalizeNodeWith(defaultSchema, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize the selection.
|
* Normalize only the selection.
|
||||||
*
|
*
|
||||||
* @param {Transform} transform
|
* @param {Transform} transform
|
||||||
* @return {Transform}
|
* @return {Transform} transform
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function normalizeSelection(transform) {
|
export function normalizeSelection(transform) {
|
||||||
@@ -99,20 +168,19 @@ export function normalizeSelection(transform) {
|
|||||||
|
|
||||||
// If the selection is nulled (not normal)
|
// If the selection is nulled (not normal)
|
||||||
if (
|
if (
|
||||||
selection.anchorKey == null ||
|
selection.isUnset ||
|
||||||
selection.focusKey == null ||
|
|
||||||
!document.hasDescendant(selection.anchorKey) ||
|
!document.hasDescendant(selection.anchorKey) ||
|
||||||
!document.hasDescendant(selection.focusKey)
|
!document.hasDescendant(selection.focusKey)
|
||||||
) {
|
) {
|
||||||
warning('Selection was invalid and reset to start of the document')
|
warning('Selection was invalid and reset to start of the document')
|
||||||
const firstText = document.getTexts().first()
|
const firstText = document.getTexts().first()
|
||||||
selection = selection.merge({
|
selection = selection.merge({
|
||||||
anchorKey: firstText.key,
|
anchorKey: firstText.key,
|
||||||
anchorOffset: 0,
|
anchorOffset: 0,
|
||||||
focusKey: firstText.key,
|
focusKey: firstText.key,
|
||||||
focusOffset: 0,
|
focusOffset: 0,
|
||||||
isBackward: false
|
isBackward: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
state = state.merge({ selection })
|
state = state.merge({ selection })
|
||||||
|
Reference in New Issue
Block a user