1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-11 17:53:59 +02:00

Add normalize nodes to transforms bykey

This commit is contained in:
Samy Pesse
2016-10-24 09:33:58 +02:00
parent 1377e28bcb
commit c7f0c655ab
6 changed files with 231 additions and 54 deletions

View File

@@ -76,6 +76,7 @@
"no-unreachable": "error",
"no-unsafe-finally": "error",
"no-unused-expressions": "error",
"no-unused-vars": "warn",
"no-useless-call": "error",
"no-useless-computed-key": "error",
"no-useless-constructor": "error",

View File

@@ -25,7 +25,7 @@ const DOCUMENT_CHILDREN_RULE = {
return invalids.size ? invalids : null
},
normalize: (transform, document, invalids) => {
return invalids.reduce((t, n) => t.removeNodeByKey(n.key), transform)
return invalids.reduce((t, n) => t.removeNodeByKey(n.key, { normalize: false }), transform)
}
}
@@ -45,7 +45,7 @@ const BLOCK_CHILDREN_RULE = {
return invalids.size ? invalids : null
},
normalize: (transform, block, invalids) => {
return invalids.reduce((t, n) => t.removeNodeByKey(n.key), transform)
return invalids.reduce((t, n) => t.removeNodeByKey(n.key, { normalize: false }), transform)
}
}
@@ -64,7 +64,7 @@ const MIN_TEXT_RULE = {
return nodes.size === 0 ? true : null
},
normalize: (transform, node) => {
return transform.insertNodeByKey(node.key, 0, Text.create())
return transform.insertNodeByKey(node.key, 0, Text.create(), { normalize: false })
}
}
@@ -84,7 +84,7 @@ const INLINE_CHILDREN_RULE = {
return invalids.size ? invalids : null
},
normalize: (transform, inline, invalids) => {
return invalids.reduce((t, n) => t.removeNodeByKey(n.key), transform)
return invalids.reduce((t, n) => t.removeNodeByKey(n.key, { normalize: false }), transform)
}
}
@@ -102,7 +102,7 @@ const INLINE_NO_EMPTY = {
return inline.text == ''
},
normalize: (transform, node) => {
return transform.removeNodeByKey(node.key)
return transform.removeNodeByKey(node.key, { normalize: false })
}
}
@@ -119,12 +119,12 @@ const INLINE_VOID_TEXT_RULE = {
validate: (node) => {
return node.text !== ' ' || node.nodes.size !== 1
},
normalize: (transform, node) => {
normalize: (transform, node, result) => {
transform = node.nodes.reduce((t, child) => {
return t.removeNodeByKey(child.key)
return t.removeNodeByKey(child.key, { normalize: false })
}, transform)
return transform.insertNodeByKey(node.key, 0, Text.createFromString(' '))
return transform.insertNodeByKey(node.key, 0, Text.createFromString(' '), { normalize: false })
}
}
@@ -136,7 +136,6 @@ const INLINE_VOID_TEXT_RULE = {
const INLINE_VOID_TEXTS_AROUND_RULE = {
match: (object) => {
return object.kind == 'block'
return object.kind == 'block' || object.kind == 'inline'
},
validate: (block) => {
@@ -162,8 +161,8 @@ const INLINE_VOID_TEXTS_AROUND_RULE = {
},
normalize: (transform, block, invalids) => {
return invalids.reduce((t, { index, next, prev }) => {
if (prev) t = transform.insertNodeByKey(block.key, index, Text.create())
if (next) t = transform.insertNodeByKey(block.key, index + 1, Text.create())
if (prev) t = transform.insertNodeByKey(block.key, index, Text.create(), { normalize: false })
if (next) t = transform.insertNodeByKey(block.key, index + 1, Text.create(), { normalize: false })
return t
}, transform)
}
@@ -200,7 +199,7 @@ const NO_ADJACENT_TEXT_RULE = {
.reverse()
.reduce((t, pair) => {
const [ first, second ] = pair
return t.joinNodeByKey(second.key, first.key)
return t.joinNodeByKey(second.key, first.key, { normalize: false })
}, transform)
}
}
@@ -256,7 +255,7 @@ const NO_EMPTY_TEXT_RULE = {
},
normalize: (transform, node, invalids) => {
return invalids.reduce((t, text) => {
return t.removeNodeByKey(text.key)
return t.removeNodeByKey(text.key, { normalize: false })
}, transform)
}
}

View File

@@ -482,6 +482,7 @@ const Raw = {
untersifyBlock(object) {
if (object.isVoid || !object.nodes || !object.nodes.length) {
return {
key: object.key,
data: object.data,
kind: object.kind,
type: object.type,
@@ -508,6 +509,7 @@ const Raw = {
untersifyInline(object) {
if (object.isVoid || !object.nodes || !object.nodes.length) {
return {
key: object.key,
data: object.data,
kind: object.kind,
type: object.type,
@@ -567,6 +569,7 @@ const Raw = {
if (object.ranges) return object
return {
key: object.key,
kind: object.kind,
ranges: [{
text: object.text,

View File

@@ -1,7 +1,4 @@
import Text from '../models/text'
import Normalize from '../utils/normalize'
import uid from '../utils/uid'
/**
* Add mark to text at `offset` and `length` in node by `key`.
@@ -11,15 +8,25 @@ import uid from '../utils/uid'
* @param {Number} offset
* @param {Number} length
* @param {Mixed} mark
* @param {Object} options
* @param {Boolean} normalize
* @return {Transform}
*/
export function addMarkByKey(transform, key, offset, length, mark) {
export function addMarkByKey(transform, key, offset, length, mark, options = {}) {
const { normalize = true } = options
mark = Normalize.mark(mark)
const { state } = transform
const { document } = state
const path = document.getPath(key)
return transform.addMarkOperation(path, offset, length, mark)
const parent = document.getParent(key)
transform = transform.addMarkOperation(path, offset, length, mark)
if (normalize) {
transform = transform.normalizeNodeByKey(parent.key)
}
return transform
}
/**
@@ -29,16 +36,23 @@ export function addMarkByKey(transform, key, offset, length, mark) {
* @param {String} key
* @param {Number} index
* @param {Node} node
* @param {Object} options
* @param {Boolean} normalize
* @return {Transform}
*/
export function insertNodeByKey(transform, key, index, node) {
export function insertNodeByKey(transform, key, index, node, options = {}) {
const { normalize = true } = options
const { state } = transform
const { document } = state
const path = document.getPath(key)
const newPath = path.slice().push(index)
return transform.insertNodeOperation(path, index, node)
transform = transform.insertNodeOperation(path, index, node)
if (normalize) {
transform = transform.normalizeNodeByKey(key)
}
return transform
}
/**
@@ -49,14 +63,24 @@ export function insertNodeByKey(transform, key, index, node) {
* @param {Number} offset
* @param {String} text
* @param {Set} marks (optional)
* @param {Object} options
* @param {Boolean} normalize
* @return {Transform}
*/
export function insertTextByKey(transform, key, offset, text, marks) {
export function insertTextByKey(transform, key, offset, text, marks, options = {}) {
const { normalize = true } = options
const { state } = transform
const { document } = state
const path = document.getPath(key)
return transform.insertTextOperation(path, offset, text, marks)
const parent = document.getParent(key)
transform = transform.insertTextOperation(path, offset, text, marks)
if (normalize) {
transform = transform.normalizeNodeByKey(parent.key)
}
return transform
}
/**
@@ -65,15 +89,30 @@ export function insertTextByKey(transform, key, offset, text, marks) {
* @param {Transform} transform
* @param {String} key
* @param {String} withKey
* @param {Object} options
* @param {Boolean} normalize
* @return {Transform}
*/
export function joinNodeByKey(transform, key, withKey) {
export function joinNodeByKey(transform, key, withKey, options = {}) {
const { normalize = true } = options
const { state } = transform
const { document } = state
const path = document.getPath(key)
const withPath = document.getPath(withKey)
return transform.joinNodeOperation(path, withPath)
const parent = document.getCommonAncestor(key, withKey)
transform = transform.joinNodeOperation(path, withPath)
if (normalize) {
if (parent) {
transform = transform.normalizeNodeByKey(parent.key)
} else {
transform = transform.normalizeDocument()
}
}
return transform
}
/**
@@ -83,20 +122,28 @@ export function joinNodeByKey(transform, key, withKey) {
* @param {String} key
* @param {String} newKey
* @param {Number} index
* @param {Object} options
* @param {Boolean} normalize
* @return {Transform}
*/
export function moveNodeByKey(transform, key, newKey, newIndex) {
export function moveNodeByKey(transform, key, newKey, newIndex, options = {}) {
const { normalize = true } = options
const { state } = transform
const { document } = state
const node = document.assertDescendant(key)
const prevParent = document.getParent(key)
const path = document.getPath(key)
const newPath = document.getPath(newKey)
const parent = document.key == newKey ? document : document.assertDescendant(newKey)
const previous = newIndex == 0 ? null : parent.nodes.get(newIndex - 1)
const next = parent.nodes.get(newIndex)
transform.moveNodeOperation(path, newPath, newIndex)
transform = transform.moveNodeOperation(path, newPath, newIndex)
const parent = document.getCommonAncestor(key, newKey)
if (normalize) {
if (parent) {
transform = transform.normalizeNodeByKey(parent.key)
} else {
transform = transform.normalizeDocument()
}
}
return transform
}
@@ -109,15 +156,25 @@ export function moveNodeByKey(transform, key, newKey, newIndex) {
* @param {Number} offset
* @param {Number} length
* @param {Mark} mark
* @param {Object} options
* @param {Boolean} normalize
* @return {Transform}
*/
export function removeMarkByKey(transform, key, offset, length, mark) {
export function removeMarkByKey(transform, key, offset, length, mark, options = {}) {
const { normalize = true } = options
mark = Normalize.mark(mark)
const { state } = transform
const { document } = state
const path = document.getPath(key)
return transform.removeMarkOperation(path, offset, length, mark)
const parent = document.getParent(key)
transform = transform.removeMarkOperation(path, offset, length, mark)
if (normalize) {
transform = transform.normalizeNodeByKey(parent.key)
}
return transform
}
/**
@@ -125,19 +182,29 @@ export function removeMarkByKey(transform, key, offset, length, mark) {
*
* @param {Transform} transform
* @param {String} key
* @param {Object} options
* @param {Boolean} normalize
* @return {Transform}
*/
export function removeNodeByKey(transform, key) {
export function removeNodeByKey(transform, key, options = {}) {
const { normalize = true } = options
const { state } = transform
let { document } = state
const node = document.assertDescendant(key)
const path = document.getPath(key)
const parent = document.getParent(key)
const previous = document.getPreviousSibling(key)
const next = document.getNextSibling(key)
return transform.removeNodeOperation(path)
transform = transform.removeNodeOperation(path)
if (normalize) {
if (parent) {
transform = transform.normalizeNodeByKey(parent.key)
} else {
transform = transform.normalizeDocument()
}
}
return transform
}
/**
@@ -147,16 +214,24 @@ export function removeNodeByKey(transform, key) {
* @param {String} key
* @param {Number} offset
* @param {Number} length
* @param {Object} options
* @param {Boolean} normalize
* @return {Transform}
*/
export function removeTextByKey(transform, key, offset, length) {
export function removeTextByKey(transform, key, offset, length, options = {}) {
const { normalize = true } = options
const { state } = transform
let { document } = state
const path = document.getPath(key)
const parent = document.getParent(key)
return transform.removeTextOperation(path, offset, length)
.normalizeNodeByKey(parent)
transform = transform.removeTextOperation(path, offset, length)
if (normalize) {
transform = transform.normalizeNodeByKey(parent.key)
}
return transform
}
/**
@@ -167,16 +242,26 @@ export function removeTextByKey(transform, key, offset, length) {
* @param {Number} offset
* @param {Number} length
* @param {Mark} mark
* @param {Object} options
* @param {Boolean} normalize
* @return {Transform}
*/
export function setMarkByKey(transform, key, offset, length, mark, properties) {
export function setMarkByKey(transform, key, offset, length, mark, properties, options = {}) {
const { normalize = true } = options
mark = Normalize.mark(mark)
properties = Normalize.markProperties(properties)
const { state } = transform
const { document } = state
const path = document.getPath(key)
return transform.setMarkOperation(path, offset, length, mark, properties)
const parent = document.getParent(key)
transform = transform.setMarkOperation(path, offset, length, mark, properties)
if (normalize) {
transform = transform.normalizeNodeByKey(parent.key)
}
return transform
}
/**
@@ -185,15 +270,28 @@ export function setMarkByKey(transform, key, offset, length, mark, properties) {
* @param {Transform} transform
* @param {String} key
* @param {Object || String} properties
* @param {Object} options
* @param {Boolean} normalize
* @return {Transform}
*/
export function setNodeByKey(transform, key, properties) {
export function setNodeByKey(transform, key, properties, options = {}) {
const { normalize = true } = options
properties = Normalize.nodeProperties(properties)
const { state } = transform
const { document } = state
const path = document.getPath(key)
transform.setNodeOperation(path, properties)
const parent = document.getParent(key)
transform = transform.setNodeOperation(path, properties)
if (normalize) {
if (parent) {
transform = transform.normalizeNodeByKey(parent.key)
} else {
transform = transform.normalizeDocument()
}
}
return transform
}
@@ -204,13 +302,27 @@ export function setNodeByKey(transform, key, properties) {
* @param {Transform} transform
* @param {String} key
* @param {Number} offset
* @param {Object} options
* @param {Boolean} normalize
* @return {Transform}
*/
export function splitNodeByKey(transform, key, offset) {
export function splitNodeByKey(transform, key, offset, options = {}) {
const { normalize = true } = options
let { state } = transform
let { document } = state
const path = document.getPath(key)
const parent = document.getParent(key)
return transform.splitNodeOperation(path, offset)
transform = transform.splitNodeOperation(path, offset)
if (normalize) {
if (parent) {
transform = transform.normalizeNodeByKey(parent.key)
} else {
transform = transform.normalizeDocument()
}
}
return transform
}

View File

@@ -1,5 +1,3 @@
import Schema from '../models/schema'
import Raw from '../serializers/raw'
import warning from '../utils/warning'
import { default as defaultSchema } from '../plugins/schema'
@@ -30,8 +28,6 @@ function _refreshNode(transform, node) {
*/
function _normalizeChildrenWith(transform, schema, node) {
let { state } = transform
if (!node.nodes) {
return transform
}
@@ -53,7 +49,6 @@ function _normalizeChildrenWith(transform, schema, node) {
*/
function _normalizeNodeWith(transform, schema, node) {
let { state } = transform
const failure = schema.__validate(node)
// Node is valid?
@@ -87,6 +82,7 @@ function _normalizeNodeWith(transform, schema, node) {
*/
export function normalizeNodeWith(transform, schema, node) {
// console.log(`normalize node key=${node.key}`)
// Iterate over its children
transform = _normalizeChildrenWith(transform, schema, node)
@@ -149,7 +145,7 @@ export function normalizeDocument(transform) {
export function normalizeNodeByKey(transform, key) {
const { state } = transform
const { document } = state
const node = document.assertDescendant(key)
const node = document.key == key ? document : document.assertDescendant(key)
return transform.normalizeNodeWith(defaultSchema, node)
}

66
test.js Normal file
View File

@@ -0,0 +1,66 @@
import { Raw, Inline } from './src'
function printNode(node, depth = 0) {
const indent = Array(depth * 2).join(' ')
if (node.kind === 'text') {
console.log(`${indent}#text key=${node.key}`)
const ranges = node.getRanges()
ranges.forEach(range => {
console.log(`${indent} ${JSON.stringify(range.text)}`)
})
}
else {
console.log(`${indent}#${node.kind + (node.isVoid ? '(void)' : '')} type=${node.type} key=${node.key} ${node.data ? JSON.stringify(node.data.toJS()) : ''}`)
node.nodes.forEach(child => printNode(child, depth + 1))
}
}
function print(st) {
printNode(st.document)
console.log('')
}
const state = Raw.deserialize({
nodes: [
{
kind: 'block',
type: 'paragraph',
key: 'container',
nodes: [
{
key: 'in1',
kind: 'inline',
type: 'link',
nodes: [
{
key: 'sometext',
kind: 'text',
text: 'Hello'
},
{
key: 'in2',
kind: 'inline',
type: 'image',
isVoid: true,
nodes: [
{
kind: 'text',
text: ' '
}
]
}
]
}
]
}
]
}, { terse: true })
print(state)
const newState = state.transform()
.moveNodeByKey('in2', 'container')
.apply()
print(newState)