This repository has been archived on 2022-08-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
outline/app/components/Editor/schema.js
2017-11-08 00:08:35 -08:00

134 lines
4.1 KiB
JavaScript

// @flow
import React from 'react';
import Code from './components/Code';
import HorizontalRule from './components/HorizontalRule';
import InlineCode from './components/InlineCode';
import Image from './components/Image';
import Link from './components/Link';
import ListItem from './components/ListItem';
import TodoList from './components/TodoList';
import {
Heading1,
Heading2,
Heading3,
Heading4,
Heading5,
Heading6,
} from './components/Heading';
import Paragraph from './components/Paragraph';
import BlockToolbar from './components/Toolbar/BlockToolbar';
import type { Props, Node, Transform } from './types';
type Options = {
onInsertImage: Function,
onChange: Function,
};
const createSchema = ({ onInsertImage, onChange }: Options) => {
return {
marks: {
bold: (props: Props) => <strong>{props.children}</strong>,
code: (props: Props) => <InlineCode>{props.children}</InlineCode>,
italic: (props: Props) => <em>{props.children}</em>,
underlined: (props: Props) => <u>{props.children}</u>,
deleted: (props: Props) => <del>{props.children}</del>,
added: (props: Props) => <mark>{props.children}</mark>,
},
nodes: {
'block-toolbar': (props: Props) => (
<BlockToolbar
onChange={onChange}
onInsertImage={onInsertImage}
{...props}
/>
),
paragraph: (props: Props) => <Paragraph {...props} />,
'block-quote': (props: Props) => (
<blockquote {...props.attributes}>{props.children}</blockquote>
),
'horizontal-rule': HorizontalRule,
'bulleted-list': (props: Props) => (
<ul {...props.attributes}>{props.children}</ul>
),
'ordered-list': (props: Props) => (
<ol {...props.attributes}>{props.children}</ol>
),
'todo-list': (props: Props) => (
<TodoList {...props.attributes}>{props.children}</TodoList>
),
table: (props: Props) => (
<table {...props.attributes}>{props.children}</table>
),
'table-row': (props: Props) => (
<tr {...props.attributes}>{props.children}</tr>
),
'table-head': (props: Props) => (
<th {...props.attributes}>{props.children}</th>
),
'table-cell': (props: Props) => (
<td {...props.attributes}>{props.children}</td>
),
code: Code,
image: Image,
link: Link,
'list-item': ListItem,
heading1: (props: Props) => <Heading1 placeholder {...props} />,
heading2: (props: Props) => <Heading2 {...props} />,
heading3: (props: Props) => <Heading3 {...props} />,
heading4: (props: Props) => <Heading4 {...props} />,
heading5: (props: Props) => <Heading5 {...props} />,
heading6: (props: Props) => <Heading6 {...props} />,
},
rules: [
// ensure first node is always a heading
{
match: (node: Node) => {
return node.kind === 'document';
},
validate: (document: Node) => {
const firstNode = document.nodes.first();
return firstNode && firstNode.type === 'heading1' ? null : firstNode;
},
normalize: (transform: Transform, document: Node, firstNode: Node) => {
transform.setBlock({ type: 'heading1' });
},
},
// automatically removes any marks in first heading
{
match: (node: Node) => {
return node.kind === 'heading1';
},
validate: (heading: Node) => {
const hasMarks = heading.getMarks().isEmpty();
const hasInlines = heading.getInlines().isEmpty();
return !(hasMarks && hasInlines);
},
normalize: (transform: Transform, heading: Node) => {
transform.unwrapInlineByKey(heading.key);
heading.getMarks().forEach(mark => {
heading.nodes.forEach(textNode => {
if (textNode.kind === 'text') {
transform.removeMarkByKey(
textNode.key,
0,
textNode.text.length,
mark
);
}
});
});
return transform;
},
},
],
};
};
export default createSchema;