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

fix parent-based schema rules with multiple rules present

This commit is contained in:
Ian Storm Taylor
2019-12-02 23:23:30 -05:00
parent 6fc935a4b8
commit ed2b84ca7a
7 changed files with 163 additions and 27 deletions

View File

@@ -7,6 +7,7 @@ import {
MarkEntry, MarkEntry,
AncestorEntry, AncestorEntry,
Descendant, Descendant,
DescendantEntry,
} from 'slate' } from 'slate'
import { MarkError, NodeError } from './errors' import { MarkError, NodeError } from './errors'
@@ -53,10 +54,10 @@ export const checkNode = (
rule: NodeRule, rule: NodeRule,
rules: NodeRule[] rules: NodeRule[]
): NodeError | undefined => { ): NodeError | undefined => {
const { validate: v } = rule const { match: m, validate: v } = rule
const [node, path] = entry const [node, path] = entry
if (Editor.isMatch(editor, entry, rule.match)) { if (Editor.isMatch(editor, entry, m)) {
if ('properties' in v) { if ('properties' in v) {
for (const k in v.properties) { for (const k in v.properties) {
const p = v.properties[k] const p = v.properties[k]
@@ -117,7 +118,7 @@ export const checkAncestor = (
editor: Editor, editor: Editor,
entry: AncestorEntry, entry: AncestorEntry,
rule: NodeRule, rule: NodeRule,
ancestorRules: NodeRule[] parentRules: NodeRule[]
): [NodeRule, NodeError] | undefined => { ): [NodeRule, NodeError] | undefined => {
const { validate: v } = rule const { validate: v } = rule
const [parent, parentPath] = entry const [parent, parentPath] = entry
@@ -140,8 +141,8 @@ export const checkAncestor = (
if (child && !processed.has(child)) { if (child && !processed.has(child)) {
processed.add(child) processed.add(child)
for (const r of ancestorRules) { for (const r of parentRules) {
const e = checkParent(editor, entry, index, rule, r) const e = checkParent(editor, entry, [child, childPath], r)
if (e) { if (e) {
return [r, e] return [r, e]
@@ -260,20 +261,19 @@ export const checkAncestor = (
export const checkParent = ( export const checkParent = (
editor: Editor, editor: Editor,
entry: AncestorEntry, entry: AncestorEntry,
index: number, childEntry: DescendantEntry,
rule: NodeRule, rule: NodeRule
childRule: NodeRule
): NodeError | undefined => { ): NodeError | undefined => {
const { validate: cv } = childRule const { match: m, validate: v } = rule
const [parent, parentPath] = entry const [parent, parentPath] = entry
const child = Node.child(parent, index) const [child, childPath] = childEntry
const childPath = parentPath.concat(index) const index = childPath[childPath.length - 1]
if ( if (
'parent' in cv && 'parent' in v &&
cv.parent != null && v.parent != null &&
Editor.isMatch(editor, [child, childPath], rule.match) && Editor.isMatch(editor, [child, childPath], m) &&
!Editor.isMatch(editor, [parent, parentPath], cv.parent) !Editor.isMatch(editor, [parent, parentPath], v.parent)
) { ) {
return { return {
code: 'parent_invalid', code: 'parent_invalid',
@@ -284,15 +284,15 @@ export const checkParent = (
} }
if ( if (
'previous' in cv && 'previous' in v &&
cv.previous != null && v.previous != null &&
index > 0 && index > 0 &&
Editor.isMatch(editor, [child, childPath], rule.match) Editor.isMatch(editor, [child, childPath], m)
) { ) {
const prevChild = Node.child(parent, index - 1) const prevChild = Node.child(parent, index - 1)
const prevPath = parentPath.concat(index - 1) const prevPath = parentPath.concat(index - 1)
if (!Editor.isMatch(editor, [prevChild, prevPath], cv.previous)) { if (!Editor.isMatch(editor, [prevChild, prevPath], v.previous)) {
return { return {
code: 'previous_sibling_invalid', code: 'previous_sibling_invalid',
node: prevChild, node: prevChild,
@@ -302,15 +302,15 @@ export const checkParent = (
} }
if ( if (
'next' in cv && 'next' in v &&
cv.next != null && v.next != null &&
index < parent.children.length - 1 && index < parent.children.length - 1 &&
Editor.isMatch(editor, [child, childPath], rule.match) Editor.isMatch(editor, [child, childPath], m)
) { ) {
const nextChild = Node.child(parent, index + 1) const nextChild = Node.child(parent, index + 1)
const nextPath = parentPath.concat(index + 1) const nextPath = parentPath.concat(index + 1)
if (!Editor.isMatch(editor, [nextChild, nextPath], cv.next)) { if (!Editor.isMatch(editor, [nextChild, nextPath], v.next)) {
return { return {
code: 'next_sibling_invalid', code: 'next_sibling_invalid',
node: nextChild, node: nextChild,

View File

@@ -16,7 +16,7 @@ export const withSchema = (
const { normalizeNode } = editor const { normalizeNode } = editor
const markRules: MarkRule[] = [] const markRules: MarkRule[] = []
const nodeRules: NodeRule[] = [] const nodeRules: NodeRule[] = []
const ancestorRules: NodeRule[] = [] const parentRules: NodeRule[] = []
for (const rule of rules) { for (const rule of rules) {
if (rule.for === 'mark') { if (rule.for === 'mark') {
@@ -29,7 +29,7 @@ export const withSchema = (
'next' in rule.validate || 'next' in rule.validate ||
'previous' in rule.validate 'previous' in rule.validate
) { ) {
ancestorRules.push(rule) parentRules.push(rule)
} }
} }
} }
@@ -48,7 +48,7 @@ export const withSchema = (
} }
if (!Text.isText(n)) { if (!Text.isText(n)) {
const failure = checkAncestor(editor, [n, p], r, ancestorRules) const failure = checkAncestor(editor, [n, p], r, parentRules)
if (failure) { if (failure) {
rule = failure[0] rule = failure[0]

View File

@@ -0,0 +1,33 @@
/** @jsx jsx */
import { jsx } from 'slate-hyperscript'
export const schema = [
{
for: 'node',
match: { a: true },
validate: {
next: [{ b: true }],
},
},
{
for: 'node',
match: { a: true },
validate: {},
},
]
export const input = (
<editor>
<element a>one</element>
<element c>two</element>
<element b>three</element>
</editor>
)
export const output = (
<editor>
<element a>one</element>
<element b>three</element>
</editor>
)

View File

@@ -0,0 +1,37 @@
/** @jsx jsx */
import { jsx } from 'slate-hyperscript'
export const schema = [
{
for: 'node',
match: { c: true },
validate: {
parent: { b: true },
},
},
{
for: 'node',
match: { a: true },
validate: {},
},
]
export const input = (
<editor>
<element a>
<element a>one</element>
<element a>two</element>
<element c>three</element>
</element>
</editor>
)
export const output = (
<editor>
<element a>
<element a>one</element>
<element a>two</element>
</element>
</editor>
)

View File

@@ -7,7 +7,7 @@ export const schema = [
for: 'node', for: 'node',
match: { c: true }, match: { c: true },
validate: { validate: {
parent: [{ b: true }], parent: { b: true },
}, },
}, },
] ]

View File

@@ -0,0 +1,33 @@
/** @jsx jsx */
import { jsx } from 'slate-hyperscript'
export const schema = [
{
for: 'node',
match: { c: true },
validate: {
parent: { b: true },
},
},
]
export const input = (
<editor>
<element b>
<element a>one</element>
<element a>two</element>
<element c>three</element>
</element>
</editor>
)
export const output = (
<editor>
<element b>
<element a>one</element>
<element a>two</element>
<element c>three</element>
</element>
</editor>
)

View File

@@ -0,0 +1,33 @@
/** @jsx jsx */
import { jsx } from 'slate-hyperscript'
export const schema = [
{
for: 'node',
match: { a: true },
validate: {
next: [{ b: true }],
},
},
{
for: 'node',
match: { c: true },
validate: {},
},
]
export const input = (
<editor>
<element a>one</element>
<element c>two</element>
<element b>three</element>
</editor>
)
export const output = (
<editor>
<element a>one</element>
<element b>three</element>
</editor>
)