mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-04-14 18:32:01 +02:00
remove the slate-schema package (#3291)
This commit is contained in:
parent
9d4a9d7a65
commit
e68a5cd305
13
Readme.md
13
Readme.md
@ -141,13 +141,12 @@ If you're maintaining a translation, feel free to pull request it here!
|
||||
|
||||
Slate's codebase is monorepo managed with [Lerna](https://lernajs.io/). It consists of a handful of packages—although you won't always use all of them. They are:
|
||||
|
||||
| **Package** | **Version** | **Size** | **Description** |
|
||||
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
|
||||
| [`slate`](./packages/slate) | [](./slate/package.json) | [](https://unpkg.com/slate/dist/slate.min.js) | Slate's core data model logic. |
|
||||
| [`slate-history`](./packages/slate-history) | [](./slate-history/package.json) | [](https://unpkg.com/slate-history/dist/slate-history.min.js) | A plugin that adds undo/redo history to Slate. |
|
||||
| [`slate-hyperscript`](./packages/slate-hyperscript) | [](./slate-hyperscript/package.json) | [](https://unpkg.com/slate-hyperscript/dist/slate-hyperscript.min.js) | A hyperscript tool to write JSX Slate documents! |
|
||||
| [`slate-react`](./packages/slate-react) | [](./slate-react/package.json) | [](https://unpkg.com/slate-react/dist/slate-react.min.js) | React components for rendering Slate editors. |
|
||||
| [`slate-schema`](./packages/slate-schema) | [](./slate-schema/package.json) | [](https://unpkg.com/slate-schema/dist/slate-schema.min.js) | A plugin for enforcing constraints on Slate content. |
|
||||
| **Package** | **Version** | **Size** | **Description** |
|
||||
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
|
||||
| [`slate`](./packages/slate) | [](./slate/package.json) | [](https://unpkg.com/slate/dist/slate.min.js) | Slate's core data model logic. |
|
||||
| [`slate-history`](./packages/slate-history) | [](./slate-history/package.json) | [](https://unpkg.com/slate-history/dist/slate-history.min.js) | A plugin that adds undo/redo history to Slate. |
|
||||
| [`slate-hyperscript`](./packages/slate-hyperscript) | [](./slate-hyperscript/package.json) | [](https://unpkg.com/slate-hyperscript/dist/slate-hyperscript.min.js) | A hyperscript tool to write JSX Slate documents! |
|
||||
| [`slate-react`](./packages/slate-react) | [](./slate-react/package.json) | [](https://unpkg.com/slate-react/dist/slate-react.min.js) | React components for rendering Slate editors. |
|
||||
|
||||
<br />
|
||||
|
||||
|
@ -13,7 +13,6 @@ import Core from '../../packages/slate/package.json'
|
||||
import History from '../../packages/slate-history/package.json'
|
||||
import Hyperscript from '../../packages/slate-hyperscript/package.json'
|
||||
import React from '../../packages/slate-react/package.json'
|
||||
import Schema from '../../packages/slate-schema/package.json'
|
||||
|
||||
/**
|
||||
* Return a Rollup configuration for a `pkg` with `env` and `target`.
|
||||
@ -168,5 +167,4 @@ export default [
|
||||
...factory(History),
|
||||
...factory(Hyperscript),
|
||||
...factory(React),
|
||||
...factory(Schema),
|
||||
]
|
||||
|
@ -97,9 +97,8 @@ slate-hyperscript 447 -> 345
|
||||
slate-plain-serializer 56 -> 0
|
||||
slate-prop-types 62 -> 0
|
||||
slate-react-placeholder 62 -> 0
|
||||
slate-schema 0 -> 439
|
||||
|
||||
total 13,807 -> 5,344 (39%)
|
||||
total 13,807 -> 4,905 (36%)
|
||||
```
|
||||
|
||||
It's quite a big difference! And that doesn't even include the dependencies that were shed in the process too.
|
||||
|
@ -12,7 +12,7 @@ One of Slate's core principles is that, unlike most other editors, it does **not
|
||||
|
||||
For the most part, this leads to increased flexbility without many downsides, but there are certain cases where you have to do a bit more work. Pasting is one of those cases.
|
||||
|
||||
Since Slate knows nothing about your schema, it can't know how to parse pasted HTML content (or other content). So, by default whenever a user pastes content into a Slate editor, it will parse it as plain text. If you want it to be smarter about pasted content, you need to override the `insert_data` command and deserialize the `DataTransfer` object's `text/html` data as you wish.
|
||||
Since Slate knows nothing about your domain, it can't know how to parse pasted HTML content (or other content). So, by default whenever a user pastes content into a Slate editor, it will parse it as plain text. If you want it to be smarter about pasted content, you need to override the `insert_data` command and deserialize the `DataTransfer` object's `text/html` data as you wish.
|
||||
|
||||
### What browsers and devices does Slate support?
|
||||
|
||||
|
@ -130,7 +130,7 @@ const App = () => {
|
||||
|
||||
Okay, so we've got the hotkey handler setup... but! If you happen to now try selecting text and hitting `Ctrl-B`, you won't notice any change. That's because we haven't told Slate how to render a "bold" mark.
|
||||
|
||||
For every format you want to add to your schema, Slate will break up the text content into "leaves", and you need to tell Slate how to read it, just like for elements. So let's define a `Leaf` component:
|
||||
For every format you add, Slate will break up the text content into "leaves", and you need to tell Slate how to read it, just like for elements. So let's define a `Leaf` component:
|
||||
|
||||
```js
|
||||
// Define a React component to render leaves with bold text.
|
||||
|
@ -83,7 +83,6 @@
|
||||
"slate-history": "*",
|
||||
"slate-hyperscript": "*",
|
||||
"slate-react": "*",
|
||||
"slate-schema": "*",
|
||||
"typescript": "^3.7.2"
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ type HyperscriptCreators<T = any> = Record<
|
||||
/**
|
||||
* `HyperscriptShorthands` are dictionaries of properties applied to specific
|
||||
* kind of object, keyed by tag name. They allow you to easily define custom
|
||||
* hyperscript tags for your schema.
|
||||
* hyperscript tags for your domain.
|
||||
*/
|
||||
|
||||
type HyperscriptShorthands = Record<string, Record<string, any>>
|
||||
|
@ -1 +0,0 @@
|
||||
This package contains the core logic of Slate. Feel free to poke around to learn more!
|
@ -1,38 +0,0 @@
|
||||
{
|
||||
"name": "slate-schema",
|
||||
"description": "A mixin for ensuring your Slate content conforms to a set of rules.",
|
||||
"version": "0.52.6",
|
||||
"license": "MIT",
|
||||
"repository": "git://github.com/ianstormtaylor/slate.git",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.es.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"umd": "dist/slate-schema.js",
|
||||
"umdMin": "dist/slate-schema.min.js",
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
"dist/"
|
||||
],
|
||||
"devDependencies": {
|
||||
"slate": "^0.52.6",
|
||||
"slate-hyperscript": "^0.52.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"slate": ">=0.50.0"
|
||||
},
|
||||
"umdGlobals": {
|
||||
"slate": "Slate"
|
||||
},
|
||||
"keywords": [
|
||||
"content",
|
||||
"editor",
|
||||
"enforce",
|
||||
"normalize",
|
||||
"normalization",
|
||||
"rules",
|
||||
"schema",
|
||||
"slate",
|
||||
"validate",
|
||||
"validation"
|
||||
]
|
||||
}
|
@ -1,319 +0,0 @@
|
||||
import {
|
||||
NodeEntry,
|
||||
Node,
|
||||
Text,
|
||||
Editor,
|
||||
AncestorEntry,
|
||||
Descendant,
|
||||
DescendantEntry,
|
||||
} from 'slate'
|
||||
|
||||
import { NodeError } from './errors'
|
||||
import { NodeRule, ChildValidation } from './rules'
|
||||
|
||||
/**
|
||||
* Check a node object.
|
||||
*/
|
||||
|
||||
export const checkNode = (
|
||||
editor: Editor,
|
||||
entry: NodeEntry,
|
||||
rule: NodeRule,
|
||||
rules: NodeRule[]
|
||||
): NodeError | undefined => {
|
||||
const { match: m, validate: v } = rule
|
||||
const [node, path] = entry
|
||||
|
||||
if (Editor.isMatch(editor, entry, m)) {
|
||||
if ('properties' in v) {
|
||||
const { children, text, ...existing } = node
|
||||
|
||||
for (const k in v.properties) {
|
||||
const p = v.properties[k]
|
||||
const value = node[k]
|
||||
const isInvalid = typeof p === 'function' ? !p(value) : p !== value
|
||||
|
||||
if (isInvalid) {
|
||||
return { code: 'node_property_invalid', node, path, property: k }
|
||||
}
|
||||
|
||||
delete existing[k]
|
||||
}
|
||||
|
||||
for (const k in existing) {
|
||||
return { code: 'node_property_invalid', node, path, property: k }
|
||||
}
|
||||
}
|
||||
|
||||
if ('text' in v && v.text != null) {
|
||||
const text = Node.text(node)
|
||||
|
||||
if (!v.text(text)) {
|
||||
return { code: 'node_text_invalid', node, path, text }
|
||||
}
|
||||
}
|
||||
|
||||
if (!Text.isText(node)) {
|
||||
if ('first' in v && v.first != null && node.children.length !== 0) {
|
||||
const n = Node.child(node, 0)
|
||||
const p = path.concat(0)
|
||||
|
||||
if (!Editor.isMatch(editor, [n, p], v.first)) {
|
||||
return { code: 'first_child_invalid', node: n, path: p, index: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
if ('last' in v && v.last != null && node.children.length !== 0) {
|
||||
const i = node.children.length - 1
|
||||
const n = Node.child(node, i)
|
||||
const p = path.concat(i)
|
||||
|
||||
if (!Editor.isMatch(editor, [n, p], v.last)) {
|
||||
return { code: 'last_child_invalid', node: n, path: p, index: i }
|
||||
}
|
||||
}
|
||||
|
||||
if ('leaves' in v && v.leaves != null) {
|
||||
for (const [n, p] of Editor.texts(editor, { at: path })) {
|
||||
const { text, ...existing } = n
|
||||
|
||||
for (const k in v.leaves) {
|
||||
const l = v.leaves[k]
|
||||
const value = n[k]
|
||||
const isInvalid = typeof l === 'function' ? !l(value) : l !== value
|
||||
|
||||
if (isInvalid) {
|
||||
return {
|
||||
code: 'node_leaf_invalid',
|
||||
node: n,
|
||||
path: p,
|
||||
property: k,
|
||||
}
|
||||
}
|
||||
|
||||
delete existing[k]
|
||||
}
|
||||
|
||||
for (const k in existing) {
|
||||
return { code: 'node_leaf_invalid', node: n, path: p, property: k }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check an ancestor node object's children.
|
||||
*/
|
||||
|
||||
export const checkAncestor = (
|
||||
editor: Editor,
|
||||
entry: AncestorEntry,
|
||||
rule: NodeRule,
|
||||
parentRules: NodeRule[]
|
||||
): [NodeRule, NodeError] | undefined => {
|
||||
const { validate: v } = rule
|
||||
const [parent, parentPath] = entry
|
||||
const processed = new Set()
|
||||
const isMatch = Editor.isMatch(editor, entry, rule.match)
|
||||
const groups = 'children' in v && v.children != null ? v.children : []
|
||||
let index = 0
|
||||
let count = 0
|
||||
let g = 0
|
||||
|
||||
while (true) {
|
||||
const group = groups[g] as ChildValidation | undefined
|
||||
const child = parent.children[index] as Descendant | undefined
|
||||
const childPath = parentPath.concat(index)
|
||||
|
||||
// For each child check the parent-related validations. But ensure that we
|
||||
// only ever check each child once, which isn't guaranteed since we're not
|
||||
// iterating just over the children in one go.
|
||||
if (child && !processed.has(child)) {
|
||||
processed.add(child)
|
||||
|
||||
for (const r of parentRules) {
|
||||
const e = checkParent(editor, entry, [child, childPath], r)
|
||||
|
||||
if (e) {
|
||||
return [r, e]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we're out of children and groups we're done.
|
||||
if (!child && !group) {
|
||||
break
|
||||
}
|
||||
|
||||
// If the entry doesn't match the rule, then the `children` validation is
|
||||
// irrelevant, so just keep iterating the children.
|
||||
if (!isMatch) {
|
||||
if (child) {
|
||||
index++
|
||||
continue
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If we're out of groups, just continue iterating the children.
|
||||
if (!group) {
|
||||
index++
|
||||
continue
|
||||
}
|
||||
|
||||
if (
|
||||
child &&
|
||||
Editor.isMatch(editor, [child, childPath], group.match || {})
|
||||
) {
|
||||
count++
|
||||
}
|
||||
// Since we want to report overflow on last matching child we don't
|
||||
// immediately v for count > max, but instead do so once we find
|
||||
// a child that doesn't match.
|
||||
if (child && group.max != null && count > group.max) {
|
||||
if (g < groups.length - 1 && (group.min == null || count >= group.min)) {
|
||||
g++
|
||||
count = 0
|
||||
continue
|
||||
} else {
|
||||
return [
|
||||
rule,
|
||||
{
|
||||
code: 'child_max_invalid',
|
||||
node: child,
|
||||
path: childPath,
|
||||
count,
|
||||
max: group.max,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// If there's no child, we're either done, we're in an optional group, or
|
||||
// we're missing a child in a group with a mininmum set.
|
||||
if (!child) {
|
||||
if (group.min != null && count < group.min) {
|
||||
return [
|
||||
rule,
|
||||
{
|
||||
code: 'child_min_invalid',
|
||||
node: child,
|
||||
path: childPath,
|
||||
count,
|
||||
min: group.min,
|
||||
},
|
||||
]
|
||||
} else {
|
||||
g++
|
||||
count = 0
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if (Editor.isMatch(editor, [child, childPath], group.match || {})) {
|
||||
index++
|
||||
continue
|
||||
}
|
||||
|
||||
// If there are more children definitions after this one, then this
|
||||
// child might actually be valid for a future one.
|
||||
if (g + 1 < groups.length) {
|
||||
// If we've already satisfied the current child definition's minimum
|
||||
// then we can proceed to the next definition.
|
||||
if (group.min == null || count >= group.min) {
|
||||
g++
|
||||
count = 0
|
||||
continue
|
||||
}
|
||||
|
||||
// The current group might be missing an element, and the child is
|
||||
// actually a member of the next group. If so, the next validation
|
||||
// won't report errors, and we can break to error out as minimum.
|
||||
const nc = groups[g + 1]
|
||||
|
||||
if (nc && Editor.isMatch(editor, [child, childPath], nc.match || {})) {
|
||||
return [
|
||||
rule,
|
||||
{
|
||||
code: 'child_min_invalid',
|
||||
node: child,
|
||||
path: childPath,
|
||||
count,
|
||||
min: group.min,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
return [rule, { code: 'child_invalid', node: child, path: childPath }]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a parent node object's children.
|
||||
*/
|
||||
|
||||
export const checkParent = (
|
||||
editor: Editor,
|
||||
entry: AncestorEntry,
|
||||
childEntry: DescendantEntry,
|
||||
rule: NodeRule
|
||||
): NodeError | undefined => {
|
||||
const { match: m, validate: v } = rule
|
||||
const [parent, parentPath] = entry
|
||||
const [child, childPath] = childEntry
|
||||
const index = childPath[childPath.length - 1]
|
||||
|
||||
if (
|
||||
'parent' in v &&
|
||||
v.parent != null &&
|
||||
Editor.isMatch(editor, [child, childPath], m) &&
|
||||
!Editor.isMatch(editor, [parent, parentPath], v.parent)
|
||||
) {
|
||||
return {
|
||||
code: 'parent_invalid',
|
||||
node: parent,
|
||||
path: parentPath,
|
||||
index,
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
'previous' in v &&
|
||||
v.previous != null &&
|
||||
index > 0 &&
|
||||
Editor.isMatch(editor, [child, childPath], m)
|
||||
) {
|
||||
const prevChild = Node.child(parent, index - 1)
|
||||
const prevPath = parentPath.concat(index - 1)
|
||||
|
||||
if (!Editor.isMatch(editor, [prevChild, prevPath], v.previous)) {
|
||||
return {
|
||||
code: 'previous_sibling_invalid',
|
||||
node: prevChild,
|
||||
path: prevPath,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
'next' in v &&
|
||||
v.next != null &&
|
||||
index < parent.children.length - 1 &&
|
||||
Editor.isMatch(editor, [child, childPath], m)
|
||||
) {
|
||||
const nextChild = Node.child(parent, index + 1)
|
||||
const nextPath = parentPath.concat(index + 1)
|
||||
|
||||
if (!Editor.isMatch(editor, [nextChild, nextPath], v.next)) {
|
||||
return {
|
||||
code: 'next_sibling_invalid',
|
||||
node: nextChild,
|
||||
path: nextPath,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,150 +0,0 @@
|
||||
import { Editor, Text, NodeEntry } from 'slate'
|
||||
|
||||
import { NodeRule, SchemaRule } from './rules'
|
||||
import { NodeError } from './errors'
|
||||
import { checkNode, checkAncestor } from './checkers'
|
||||
|
||||
/**
|
||||
* The schema plugin augments an editor to ensure that its content is normalized
|
||||
* to always obey a schema after operations are applied.
|
||||
*/
|
||||
|
||||
export const defineSchema = (
|
||||
rules: SchemaRule[] = []
|
||||
): ((editor: Editor) => Editor) => {
|
||||
const nodeRules: NodeRule[] = rules
|
||||
const parentRules = rules.filter(rule => {
|
||||
return (
|
||||
'parent' in rule.validate ||
|
||||
'next' in rule.validate ||
|
||||
'previous' in rule.validate
|
||||
)
|
||||
})
|
||||
|
||||
return (editor: Editor): Editor => {
|
||||
const { normalizeNode } = editor
|
||||
|
||||
editor.normalizeNode = (entry: NodeEntry) => {
|
||||
const [n, p] = entry
|
||||
let error: NodeError | undefined
|
||||
let rule: NodeRule | undefined
|
||||
|
||||
for (const r of nodeRules) {
|
||||
error = checkNode(editor, [n, p], r, nodeRules)
|
||||
|
||||
if (error) {
|
||||
rule = r
|
||||
break
|
||||
}
|
||||
|
||||
if (!Text.isText(n)) {
|
||||
const failure = checkAncestor(editor, [n, p], r, parentRules)
|
||||
|
||||
if (failure) {
|
||||
rule = failure[0]
|
||||
error = failure[1]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (error == null) {
|
||||
return normalizeNode(entry)
|
||||
}
|
||||
|
||||
const prevLength = editor.operations.length
|
||||
|
||||
// First run the user-provided `normalize` function if one exists...
|
||||
if (rule != null && rule.normalize) {
|
||||
rule.normalize(editor, error)
|
||||
}
|
||||
|
||||
// If the `normalize` function did add any operations to the editor,
|
||||
// we assume that it fully handled the normalization and exit.
|
||||
if (editor.operations.length > prevLength) {
|
||||
return
|
||||
}
|
||||
|
||||
switch (error.code) {
|
||||
case 'first_child_invalid':
|
||||
case 'last_child_invalid': {
|
||||
const { path } = error
|
||||
const [parent, parentPath] = Editor.parent(editor, path)
|
||||
|
||||
if (parent.children.length > 1) {
|
||||
Editor.removeNodes(editor, { at: path })
|
||||
} else if (parentPath.length === 0) {
|
||||
const range = Editor.range(editor, parentPath)
|
||||
Editor.removeNodes(editor, {
|
||||
at: range,
|
||||
match: ([, p]) => p.length === 1,
|
||||
})
|
||||
} else {
|
||||
Editor.removeNodes(editor, { at: parentPath })
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
case 'child_max_invalid': {
|
||||
const { path } = error
|
||||
const [parent, parentPath] = Editor.parent(editor, path)
|
||||
|
||||
if (parent.children.length === 1 && parentPath.length !== 0) {
|
||||
Editor.removeNodes(editor, { at: parentPath })
|
||||
} else {
|
||||
Editor.removeNodes(editor, { at: path })
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
case 'child_min_invalid': {
|
||||
const { path } = error
|
||||
const [, parentPath] = Editor.parent(editor, path)
|
||||
|
||||
if (parentPath.length === 0) {
|
||||
const range = Editor.range(editor, parentPath)
|
||||
Editor.removeNodes(editor, {
|
||||
at: range,
|
||||
match: ([, p]) => p.length === 1,
|
||||
})
|
||||
} else {
|
||||
Editor.removeNodes(editor, { at: parentPath })
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
case 'child_invalid':
|
||||
case 'next_sibling_invalid':
|
||||
case 'node_leaf_invalid':
|
||||
case 'node_property_invalid':
|
||||
case 'node_text_invalid':
|
||||
case 'previous_sibling_invalid': {
|
||||
const { path } = error
|
||||
Editor.removeNodes(editor, { at: path })
|
||||
break
|
||||
}
|
||||
|
||||
case 'parent_invalid': {
|
||||
const { path, index } = error
|
||||
const childPath = path.concat(index)
|
||||
Editor.removeNodes(editor, { at: childPath })
|
||||
break
|
||||
}
|
||||
|
||||
default: {
|
||||
const _: never = error
|
||||
throw new Error(
|
||||
`Cannot normalize unknown validation error: "${JSON.stringify(
|
||||
error
|
||||
)}"`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return editor
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
import { Ancestor, Descendant, Node, Path } from 'slate'
|
||||
|
||||
export interface ChildInvalidError {
|
||||
code: 'child_invalid'
|
||||
node: Descendant
|
||||
path: Path
|
||||
}
|
||||
|
||||
export interface ChildMaxInvalidError {
|
||||
code: 'child_max_invalid'
|
||||
node: Descendant
|
||||
path: Path
|
||||
count: number
|
||||
max: number
|
||||
}
|
||||
|
||||
export interface ChildMinInvalidError {
|
||||
code: 'child_min_invalid'
|
||||
node: Descendant | undefined
|
||||
path: Path
|
||||
count: number
|
||||
min: number
|
||||
}
|
||||
|
||||
export interface FirstChildInvalidError {
|
||||
code: 'first_child_invalid'
|
||||
node: Descendant
|
||||
path: Path
|
||||
index: number
|
||||
}
|
||||
|
||||
export interface LastChildInvalidError {
|
||||
code: 'last_child_invalid'
|
||||
node: Descendant
|
||||
path: Path
|
||||
index: number
|
||||
}
|
||||
|
||||
export interface NextSiblingInvalidError {
|
||||
code: 'next_sibling_invalid'
|
||||
node: Node
|
||||
path: Path
|
||||
}
|
||||
|
||||
export interface NodeLeafInvalidError {
|
||||
code: 'node_leaf_invalid'
|
||||
node: Node
|
||||
path: Path
|
||||
property: string
|
||||
}
|
||||
|
||||
export interface NodePropertyInvalidError {
|
||||
code: 'node_property_invalid'
|
||||
node: Node
|
||||
path: Path
|
||||
property: string
|
||||
}
|
||||
|
||||
export interface NodeTextInvalidError {
|
||||
code: 'node_text_invalid'
|
||||
node: Node
|
||||
path: Path
|
||||
text: string
|
||||
}
|
||||
|
||||
export interface ParentInvalidError {
|
||||
code: 'parent_invalid'
|
||||
node: Ancestor
|
||||
path: Path
|
||||
index: number
|
||||
}
|
||||
|
||||
export interface PreviousSiblingInvalidError {
|
||||
code: 'previous_sibling_invalid'
|
||||
node: Node
|
||||
path: Path
|
||||
}
|
||||
|
||||
export type NodeError =
|
||||
| ChildInvalidError
|
||||
| ChildMaxInvalidError
|
||||
| ChildMinInvalidError
|
||||
| FirstChildInvalidError
|
||||
| LastChildInvalidError
|
||||
| NextSiblingInvalidError
|
||||
| NodeLeafInvalidError
|
||||
| NodePropertyInvalidError
|
||||
| NodeTextInvalidError
|
||||
| ParentInvalidError
|
||||
| PreviousSiblingInvalidError
|
||||
|
||||
export type SchemaError = NodeError
|
@ -1,3 +0,0 @@
|
||||
export * from './errors'
|
||||
export * from './define-schema'
|
||||
export * from './rules'
|
@ -1,29 +0,0 @@
|
||||
import { Editor, NodeMatch } from 'slate'
|
||||
import { NodeError } from './errors'
|
||||
|
||||
export interface ChildValidation {
|
||||
match?: NodeMatch
|
||||
min?: number
|
||||
max?: number
|
||||
}
|
||||
|
||||
export interface NodeValidation {
|
||||
children?: ChildValidation[]
|
||||
first?: NodeMatch
|
||||
last?: NodeMatch
|
||||
leaves?: Record<string, any>
|
||||
next?: NodeMatch
|
||||
parent?: NodeMatch
|
||||
previous?: NodeMatch
|
||||
properties?: Record<string, any>
|
||||
text?: (text: string) => boolean
|
||||
}
|
||||
|
||||
export interface NodeRule {
|
||||
for: 'node'
|
||||
match: NodeMatch
|
||||
validate: NodeValidation
|
||||
normalize: (editor: Editor, error: NodeError) => void
|
||||
}
|
||||
|
||||
export type SchemaRule = NodeRule
|
@ -1,14 +0,0 @@
|
||||
import assert from 'assert'
|
||||
import { fixtures } from '../../../support/fixtures'
|
||||
import { Editor } from 'slate'
|
||||
import { defineSchema } from '..'
|
||||
|
||||
describe('slate-schema', () => {
|
||||
fixtures(__dirname, 'validations', ({ module }) => {
|
||||
const { input, schema, output } = module
|
||||
const withSchema = defineSchema(schema)
|
||||
const editor = withSchema(input)
|
||||
Editor.normalize(editor, { force: true })
|
||||
assert.deepEqual(editor.children, output.children)
|
||||
})
|
||||
})
|
@ -1,30 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ match: [{ b: true }, { c: true }] }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element d>two</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
@ -1,32 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ match: { b: true } }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element c>two</element>
|
||||
<element c>three</element>
|
||||
<element c>four</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
@ -1,30 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ max: 1, match: { b: true } }, { match: { b: true } }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element c>two</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
@ -1,30 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ match: { b: true } }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element c>two</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
@ -1,24 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ match: [{ b: true }, { c: true }] }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element c>two</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,27 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [
|
||||
{ max: 1, match: { b: true } },
|
||||
{ max: 1, match: { b: true } },
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,23 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ match: { b: true } }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,30 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ match: 'text', max: 1 }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element b>two</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element a>
|
||||
<text />
|
||||
</element>
|
||||
</editor>
|
||||
)
|
@ -1,29 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ match: 'text', max: 1 }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element a>
|
||||
<text />
|
||||
</element>
|
||||
</editor>
|
||||
)
|
@ -1,32 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ max: 1 }, { max: 1 }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element b>two</element>
|
||||
<element b>three</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element b>two</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
@ -1,30 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ max: 1 }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element b>two</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
@ -1,24 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ max: 1 }, { max: 1 }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,23 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ max: 1 }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,26 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [
|
||||
{ match: { b: true }, min: 1 },
|
||||
{ match: { c: true }, min: 0 },
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element c>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = <editor />
|
@ -1,23 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ min: 1, max: 1 }, { min: 1 }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = <editor />
|
@ -1,23 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ min: 2 }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = <editor />
|
@ -1,27 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [
|
||||
{ match: { b: true }, min: 1, max: 1 },
|
||||
{ match: { c: true }, min: 0 },
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element c>two</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,26 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [
|
||||
{ match: { b: true }, min: 1, max: 1 },
|
||||
{ match: { c: true }, min: 0 },
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,24 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ min: 1, max: 1 }, { min: 1 }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,23 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
children: [{ min: 1 }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,32 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
first: [{ b: true }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element c>one</element>
|
||||
<element b>two</element>
|
||||
<element b>three</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>two</element>
|
||||
<element b>three</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
@ -1,23 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
first: [{ b: true }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element c>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = <editor />
|
@ -1,25 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
first: [{ b: true }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element b>two</element>
|
||||
<element b>three</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,32 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
last: [{ b: true }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element b>two</element>
|
||||
<element c>three</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element b>two</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
@ -1,23 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
last: [{ b: true }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element c>one</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = <editor />
|
@ -1,25 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
last: [{ b: true }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<element b>one</element>
|
||||
<element b>two</element>
|
||||
<element b>three</element>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,31 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
leaves: {
|
||||
bold: v => v === true || v === undefined,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<text unknown>word</text>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element a>
|
||||
<text />
|
||||
</element>
|
||||
</editor>
|
||||
)
|
@ -1,31 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
leaves: {
|
||||
bold: v => v === true || v === undefined,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<text bold="invalid">word</text>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element a>
|
||||
<text />
|
||||
</element>
|
||||
</editor>
|
||||
)
|
@ -1,31 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
leaves: {
|
||||
bold: v => v === true || v === undefined,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>
|
||||
<text bold>word</text>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = (
|
||||
<editor>
|
||||
<element a>
|
||||
<text bold>word</text>
|
||||
</element>
|
||||
</editor>
|
||||
)
|
@ -1,33 +0,0 @@
|
||||
/** @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>
|
||||
)
|
@ -1,28 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
next: [{ b: true }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
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>
|
||||
)
|
@ -1,23 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
next: [{ b: true }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>one</element>
|
||||
<element b>two</element>
|
||||
<element c>three</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,37 +0,0 @@
|
||||
/** @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>
|
||||
)
|
@ -1,32 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { c: true },
|
||||
validate: {
|
||||
parent: { b: true },
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
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>
|
||||
)
|
@ -1,33 +0,0 @@
|
||||
/** @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>
|
||||
)
|
@ -1,33 +0,0 @@
|
||||
/** @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>
|
||||
)
|
@ -1,28 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
next: [{ b: true }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
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>
|
||||
)
|
@ -1,23 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
next: [{ b: true }],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>one</element>
|
||||
<element b>two</element>
|
||||
<element c>three</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,25 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
properties: {
|
||||
a: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a thing="unknown">
|
||||
word
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = <editor />
|
@ -1,26 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
properties: {
|
||||
a: true,
|
||||
thing: v => v == null || v === 'valid',
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a thing="invalid">
|
||||
word
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = <editor />
|
@ -1,26 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
properties: {
|
||||
a: true,
|
||||
thing: v => v == null || v === 'valid',
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a thing="valid">
|
||||
word
|
||||
</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,21 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
text: v => v === 'valid',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>invalid</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = <editor />
|
@ -1,21 +0,0 @@
|
||||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from 'slate-hyperscript'
|
||||
|
||||
export const schema = [
|
||||
{
|
||||
for: 'node',
|
||||
match: { a: true },
|
||||
validate: {
|
||||
text: v => v === 'valid',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<element a>valid</element>
|
||||
</editor>
|
||||
)
|
||||
|
||||
export const output = input
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"extends": "../../config/typescript/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"composite": true
|
||||
},
|
||||
"references": []
|
||||
}
|
@ -4,7 +4,7 @@ import { Editor, Node, Path } from '..'
|
||||
/**
|
||||
* `Element` objects are a type of node in a Slate document that contain other
|
||||
* element nodes or text nodes. They can be either "blocks" or "inlines"
|
||||
* depending on the Slate editor's schema.
|
||||
* depending on the Slate editor's configuration.
|
||||
*/
|
||||
|
||||
export interface Element {
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
import { jsx } from '../..'
|
||||
|
||||
export const schema = {}
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<block>
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
import { jsx } from '../..'
|
||||
|
||||
export const schema = {}
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<block>
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
import { jsx } from '../..'
|
||||
|
||||
export const schema = {}
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<block>
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
import { jsx } from '../..'
|
||||
|
||||
export const schema = {}
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<block>
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
import { jsx } from '../..'
|
||||
|
||||
export const schema = {}
|
||||
|
||||
export const input = (
|
||||
<editor>
|
||||
<block>
|
||||
|
@ -4,7 +4,7 @@ This directory contains a set of examples that give you an idea for how you migh
|
||||
|
||||
- [**Plain text**](./plaintext.js) — showing the most basic case: a glorified `<textarea>`.
|
||||
- [**Rich text**](./richtext.js) — showing the features you'd expect from a basic editor.
|
||||
- [**Forced Layout**](./forced-layout.js) - showing how to use schema rules to enforce document structure
|
||||
- [**Forced Layout**](./forced-layout.js) - showing how to use constraints to enforce a document structure.
|
||||
- [**Markdown Shortcuts**](./markdown-shortcuts.js) — showing how to add key handlers for Markdown-like shortcuts.
|
||||
- [**Links**](./links.js) — showing how wrap text in inline nodes with associated data.
|
||||
- [**Images**](./images.js) — showing how to use void (text-less) nodes to add images.
|
||||
|
@ -2,46 +2,43 @@ import React, { useState, useCallback, useMemo } from 'react'
|
||||
import { Slate, Editable, withReact } from 'slate-react'
|
||||
import { Editor, createEditor } from 'slate'
|
||||
import { withHistory } from 'slate-history'
|
||||
import { defineSchema } from 'slate-schema'
|
||||
|
||||
const withSchema = defineSchema([
|
||||
{
|
||||
for: 'node',
|
||||
match: 'editor',
|
||||
validate: {
|
||||
children: [
|
||||
{ match: { type: 'title' }, min: 1, max: 1 },
|
||||
{ match: { type: 'paragraph' }, min: 1 },
|
||||
],
|
||||
},
|
||||
normalize: (editor, error) => {
|
||||
const { code, path } = error
|
||||
const [index] = path
|
||||
const type = index === 0 ? 'title' : 'paragraph'
|
||||
const withLayout = editor => {
|
||||
const { normalizeNode } = editor
|
||||
|
||||
switch (code) {
|
||||
case 'child_invalid':
|
||||
case 'child_max_invalid': {
|
||||
Editor.setNodes(editor, { type }, { at: path })
|
||||
break
|
||||
}
|
||||
editor.normalizeNode = path => {
|
||||
if (path.length === 0) {
|
||||
if (editor.children.length < 1) {
|
||||
const title = { type: 'title', children: [{ text: 'Untitled' }] }
|
||||
Editor.insertNodes(editor, title, { at: path.concat(0) })
|
||||
}
|
||||
|
||||
case 'child_min_invalid': {
|
||||
const block = { type, children: [{ text: '' }] }
|
||||
Editor.insertNodes(editor, block, { at: path })
|
||||
break
|
||||
if (editor.children.length < 2) {
|
||||
const paragraph = { type: 'paragraph', children: [{ text: '' }] }
|
||||
Editor.insertNodes(editor, paragraph, { at: path.concat(1) })
|
||||
}
|
||||
|
||||
for (const [child, childPath] of Node.children(editor, path)) {
|
||||
const type = childPath[0] === 0 ? 'title' : 'paragraph'
|
||||
|
||||
if (child.type !== type) {
|
||||
Editor.setNodes(editor, { type }, { at: childPath })
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
return normalizeNode(path)
|
||||
}
|
||||
|
||||
return editor
|
||||
}
|
||||
|
||||
const ForcedLayoutExample = () => {
|
||||
const [value, setValue] = useState(initialValue)
|
||||
const [selection, setSelection] = useState(null)
|
||||
const renderElement = useCallback(props => <Element {...props} />, [])
|
||||
const editor = useMemo(
|
||||
() => withSchema(withHistory(withReact(createEditor()))),
|
||||
() => withLayout(withHistory(withReact(createEditor()))),
|
||||
[]
|
||||
)
|
||||
return (
|
||||
@ -83,7 +80,7 @@ const initialValue = [
|
||||
children: [
|
||||
{
|
||||
text:
|
||||
'This example shows how to enforce your layout with schema-specific rules. This document will always have a title block at the top and at least one paragraph in the body. Try deleting them and see what happens!',
|
||||
'This example shows how to enforce your layout with domain-specific constraints. This document will always have a title block at the top and at least one paragraph in the body. Try deleting them and see what happens!',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -4,7 +4,6 @@
|
||||
{ "path": "./packages/slate" },
|
||||
{ "path": "./packages/slate-history" },
|
||||
{ "path": "./packages/slate-hyperscript" },
|
||||
{ "path": "./packages/slate-react" },
|
||||
{ "path": "./packages/slate-schema" }
|
||||
{ "path": "./packages/slate-react" }
|
||||
]
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user