Skip to content

Commit

Permalink
fix schema normalization bug for child_max_invalid
Browse files Browse the repository at this point in the history
  • Loading branch information
ianstormtaylor committed Nov 10, 2018
1 parent 03d531b commit b33605e
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 18 deletions.
39 changes: 21 additions & 18 deletions packages/slate/src/plugins/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,8 @@ function validateNodes(node, rule, rules = []) {
return true
}

function rewind(pastZero = false) {
if (index > 0 || pastZero) {
function rewind() {
if (index > 0) {
index -= 1
count = lastCount
}
Expand All @@ -422,10 +422,10 @@ function validateNodes(node, rule, rules = []) {
const error = validateRules(child, def.match)

if (error) {
// Since we want to report overflow on last matching child we don't
// immediately check for count > max, but instead do so once we find
// a child that doesn't match.
if (max != null && count - 1 > max) {
// Since we want to report overflow on last matching child we don't
// immediately check for count > max, but instead do so once we find
// a child that doesn't match.
rewind()
return fail('child_max_invalid', {
rule,
Expand All @@ -441,22 +441,21 @@ function validateNodes(node, rule, rules = []) {
// If there are more groups after this one then child might actually
// be valid.
if (nextDef()) {
// We already have all children required for current group, so this
// error can safely be ignored.
// If we've already satisfied the minimum for the current group,
// then we can rewind and proceed to the next group.
if (lastCount - 1 >= lastMin) {
rewind(true)
index -= 1
continue
}

// Otherwise we know that current value is underflowing. There are
// three possible causes: there might just not be enough elements
// for current group, and current child is in fact the first of
// the next group; current group is underflowing, but there is also
// an invalid child before the next group; or current group is not
// underflowing but it appears so because there's an invalid child
// between its members.
// three possible causes for this...

// 1. There might just not be enough elements for current group, and
// current child is in fact the first of the next group. If so, the
// next def will not report errors, in which case we can rewind and
// report an minimum error.
if (validateRules(child, def.match) == null) {
// It's the first case, so we just report an underflow.
rewind()
return fail('child_min_invalid', {
rule,
Expand All @@ -466,11 +465,15 @@ function validateNodes(node, rule, rules = []) {
limit: lastMin,
})
}

// 2. The current group is underflowing, but there is also an
// invalid child before the next group.
// 3. Or the current group is not underflowing but it appears so
// because there's an invalid child between its members.
// It's either the second or third case. If it's the second then
// we could report an underflow, but presence of an invalid child
// is arguably more important, so we report it first. It also lets
// us avoid checking for which case exactly is it.

error.rule = rule
error.node = node
error.child = child
Expand All @@ -497,9 +500,9 @@ function validateNodes(node, rule, rules = []) {
}
}

// Since we want to report overflow on last matching child we don't
// immediately check for count > max, but do so after processing all nodes.
if (max != null && count > max) {
// Since we want to report overflow on last matching child we don't
// immediately check for count > max, but do so after processing all nodes.
return fail('child_max_invalid', {
rule,
node,
Expand Down
55 changes: 55 additions & 0 deletions packages/slate/test/schema/custom/child-min-max-invalid-default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/** @jsx h */

import h from '../../helpers/h'

export const schema = {
blocks: {
paragraph: {},
title: {},
quote: {
nodes: [
{
match: [{ type: 'title' }],
min: 1,
max: 1,
},
{
match: [{ type: 'paragraph' }],
},
],
},
},
}

export const input = (
<value>
<document>
<quote>
<block type="title">
<text />
</block>
<block type="title">
<text />
</block>
<paragraph>
<text />
</paragraph>
</quote>
</document>
</value>
)

export const output = (
<value>
<document>
<quote>
<block type="title">
<text />
</block>
<paragraph>
<text />
</paragraph>
</quote>
</document>
</value>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/** @jsx h */

import h from '../../helpers/h'

export const schema = {
blocks: {
heading: {},
quote: {
nodes: [
{
match: [
{
type: 'heading',
data: { level: v => v === 1 },
},
],
min: 1,
max: 1,
},
{
match: [
{
type: 'heading',
data: { level: v => v === 2 },
},
],
min: 1,
max: 1,
},
],
},
},
}

export const input = (
<value>
<document>
<quote>
<block type="heading" data={{ level: 1 }}>
<text />
</block>
<block type="heading" data={{ level: 2 }}>
<text />
</block>
</quote>
</document>
</value>
)

export const output = (
<value>
<document>
<quote>
<block type="heading" data={{ level: 1 }}>
<text />
</block>
<block type="heading" data={{ level: 2 }}>
<text />
</block>
</quote>
</document>
</value>
)
39 changes: 39 additions & 0 deletions packages/slate/test/schema/custom/child-min-max-invalid-valid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/** @jsx h */

import h from '../../helpers/h'

export const schema = {
blocks: {
paragraph: {},
title: {},
quote: {
nodes: [
{
match: [{ type: 'title' }],
min: 1,
max: 1,
},
{
match: [{ type: 'paragraph' }],
},
],
},
},
}

export const input = (
<value>
<document>
<quote>
<block type="title">
<text />
</block>
<paragraph>
<text />
</paragraph>
</quote>
</document>
</value>
)

export const output = input

0 comments on commit b33605e

Please sign in to comment.