mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-11 01:33:58 +02:00
fixes
This commit is contained in:
@@ -4,21 +4,23 @@ import React from 'react'
|
|||||||
import initialState from './state.json'
|
import initialState from './state.json'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a set of node renderers.
|
* Define a schema.
|
||||||
*
|
*
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const NODES = {
|
const schema = {
|
||||||
'block-quote': props => <blockquote>{props.children}</blockquote>,
|
nodes: {
|
||||||
'bulleted-list': props => <ul>{props.children}</ul>,
|
'block-quote': props => <blockquote>{props.children}</blockquote>,
|
||||||
'heading-one': props => <h1>{props.children}</h1>,
|
'bulleted-list': props => <ul>{props.children}</ul>,
|
||||||
'heading-two': props => <h2>{props.children}</h2>,
|
'heading-one': props => <h1>{props.children}</h1>,
|
||||||
'heading-three': props => <h3>{props.children}</h3>,
|
'heading-two': props => <h2>{props.children}</h2>,
|
||||||
'heading-four': props => <h4>{props.children}</h4>,
|
'heading-three': props => <h3>{props.children}</h3>,
|
||||||
'heading-five': props => <h5>{props.children}</h5>,
|
'heading-four': props => <h4>{props.children}</h4>,
|
||||||
'heading-six': props => <h6>{props.children}</h6>,
|
'heading-five': props => <h5>{props.children}</h5>,
|
||||||
'list-item': props => <li>{props.children}</li>
|
'heading-six': props => <h6>{props.children}</h6>,
|
||||||
|
'list-item': props => <li>{props.children}</li>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,26 +75,15 @@ class AutoMarkdown extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="editor">
|
<div className="editor">
|
||||||
<Editor
|
<Editor
|
||||||
|
schema={schema}
|
||||||
state={this.state.state}
|
state={this.state.state}
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
onKeyDown={this.onKeyDown}
|
onKeyDown={this.onKeyDown}
|
||||||
renderNode={this.renderNode}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Render a `node`.
|
|
||||||
*
|
|
||||||
* @param {Node} node
|
|
||||||
* @return {Element}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderNode = (node) => {
|
|
||||||
return NODES[node.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* On change.
|
* On change.
|
||||||
*
|
*
|
||||||
|
@@ -47,6 +47,44 @@ function CodeBlock(props) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a Prism.js decorator for code blocks.
|
||||||
|
*
|
||||||
|
* @param {Text} text
|
||||||
|
* @param {Block} block
|
||||||
|
*/
|
||||||
|
|
||||||
|
function codeBlockDecorator(text, block) {
|
||||||
|
let characters = text.characters.asMutable()
|
||||||
|
const language = block.data.get('language')
|
||||||
|
const string = text.text
|
||||||
|
const grammar = Prism.languages[language]
|
||||||
|
const tokens = Prism.tokenize(string, grammar)
|
||||||
|
let offset = 0
|
||||||
|
|
||||||
|
for (const token of tokens) {
|
||||||
|
if (typeof token == 'string') {
|
||||||
|
offset += token.length
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const length = offset + token.content.length
|
||||||
|
const type = `highlight-${token.type}`
|
||||||
|
|
||||||
|
for (let i = offset; i < length; i++) {
|
||||||
|
let char = characters.get(i)
|
||||||
|
let { marks } = char
|
||||||
|
marks = marks.add(Mark.create({ type }))
|
||||||
|
char = char.merge({ marks })
|
||||||
|
characters = characters.set(i, char)
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = length
|
||||||
|
}
|
||||||
|
|
||||||
|
return characters.asImmutable()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a schema.
|
* Define a schema.
|
||||||
*
|
*
|
||||||
@@ -57,36 +95,7 @@ const schema = {
|
|||||||
nodes: {
|
nodes: {
|
||||||
code: {
|
code: {
|
||||||
component: CodeBlock,
|
component: CodeBlock,
|
||||||
decorator: (block, text) => {
|
decorator: codeBlockDecorator,
|
||||||
let characters = text.characters.asMutable()
|
|
||||||
const language = block.data.get('language')
|
|
||||||
const string = text.text
|
|
||||||
const grammar = Prism.languages[language]
|
|
||||||
const tokens = Prism.tokenize(string, grammar)
|
|
||||||
let offset = 0
|
|
||||||
|
|
||||||
for (const token of tokens) {
|
|
||||||
if (typeof token == 'string') {
|
|
||||||
offset += token.length
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const length = offset + token.content.length
|
|
||||||
const type = `highlight-${token.type}`
|
|
||||||
|
|
||||||
for (let i = offset; i < length; i++) {
|
|
||||||
let char = characters.get(i)
|
|
||||||
let { marks } = char
|
|
||||||
marks = marks.add(Mark.create({ type }))
|
|
||||||
char = char.merge({ marks })
|
|
||||||
characters = characters.set(i, char)
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = length
|
|
||||||
}
|
|
||||||
|
|
||||||
return characters.asImmutable()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
marks: {
|
marks: {
|
||||||
|
@@ -10,41 +10,36 @@ import initialState from './state.json'
|
|||||||
const DEFAULT_NODE = 'paragraph'
|
const DEFAULT_NODE = 'paragraph'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a set of node renderers.
|
* Define a schema.
|
||||||
*
|
*
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const NODES = {
|
const schema = {
|
||||||
'block-quote': props => <blockquote {...props.attributes}>{props.children}</blockquote>,
|
nodes: {
|
||||||
'bulleted-list': props => <ul {...props.attributes}>{props.children}</ul>,
|
'block-quote': props => <blockquote {...props.attributes}>{props.children}</blockquote>,
|
||||||
'heading-one': props => <h1 {...props.attributes}>{props.children}</h1>,
|
'bulleted-list': props => <ul {...props.attributes}>{props.children}</ul>,
|
||||||
'heading-two': props => <h2 {...props.attributes}>{props.children}</h2>,
|
'heading-one': props => <h1 {...props.attributes}>{props.children}</h1>,
|
||||||
'list-item': props => <li {...props.attributes}>{props.children}</li>,
|
'heading-two': props => <h2 {...props.attributes}>{props.children}</h2>,
|
||||||
'numbered-list': props => <ol {...props.attributes}>{props.children}</ol>
|
'list-item': props => <li {...props.attributes}>{props.children}</li>,
|
||||||
}
|
'numbered-list': props => <ol {...props.attributes}>{props.children}</ol>
|
||||||
|
|
||||||
/**
|
|
||||||
* Define a set of mark renderers.
|
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
|
|
||||||
const MARKS = {
|
|
||||||
bold: {
|
|
||||||
fontWeight: 'bold'
|
|
||||||
},
|
},
|
||||||
code: {
|
marks: {
|
||||||
fontFamily: 'monospace',
|
bold: {
|
||||||
backgroundColor: '#eee',
|
fontWeight: 'bold'
|
||||||
padding: '3px',
|
},
|
||||||
borderRadius: '4px'
|
code: {
|
||||||
},
|
fontFamily: 'monospace',
|
||||||
italic: {
|
backgroundColor: '#eee',
|
||||||
fontStyle: 'italic'
|
padding: '3px',
|
||||||
},
|
borderRadius: '4px'
|
||||||
underlined: {
|
},
|
||||||
textDecoration: 'underline'
|
italic: {
|
||||||
|
fontStyle: 'italic'
|
||||||
|
},
|
||||||
|
underlined: {
|
||||||
|
textDecoration: 'underline'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,9 +278,8 @@ class RichText extends React.Component {
|
|||||||
<div className="editor">
|
<div className="editor">
|
||||||
<Editor
|
<Editor
|
||||||
placeholder={'Enter some rich text...'}
|
placeholder={'Enter some rich text...'}
|
||||||
|
schema={schema}
|
||||||
state={this.state.state}
|
state={this.state.state}
|
||||||
renderNode={this.renderNode}
|
|
||||||
renderMark={this.renderMark}
|
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
onKeyDown={this.onKeyDown}
|
onKeyDown={this.onKeyDown}
|
||||||
/>
|
/>
|
||||||
@@ -293,28 +287,6 @@ class RichText extends React.Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a node renderer for a Slate `node`.
|
|
||||||
*
|
|
||||||
* @param {Node} node
|
|
||||||
* @return {Component or Void}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderNode = (node) => {
|
|
||||||
return NODES[node.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a mark renderer for a Slate `mark`.
|
|
||||||
*
|
|
||||||
* @param {Mark} mark
|
|
||||||
* @return {Object or Void}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderMark = (mark) => {
|
|
||||||
return MARKS[mark.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -6,13 +6,15 @@ import Video from './video'
|
|||||||
import initialState from './state.json'
|
import initialState from './state.json'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a set of node renderers.
|
* Define a schema.
|
||||||
*
|
*
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const NODES = {
|
const schema = {
|
||||||
video: Video
|
nodes: {
|
||||||
|
video: Video
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,25 +55,14 @@ class Embeds extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="editor">
|
<div className="editor">
|
||||||
<Editor
|
<Editor
|
||||||
|
schema={schema}
|
||||||
state={this.state.state}
|
state={this.state.state}
|
||||||
renderNode={this.renderNode}
|
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Render a `node`.
|
|
||||||
*
|
|
||||||
* @param {Node} node
|
|
||||||
* @return {Element}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderNode = (node) => {
|
|
||||||
return NODES[node.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -6,26 +6,17 @@ import position from 'selection-position'
|
|||||||
import initialState from './state.json'
|
import initialState from './state.json'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a set of mark renderers.
|
* Define a schema.
|
||||||
*
|
*
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const MARKS = {
|
const schema = {
|
||||||
bold: {
|
marks: {
|
||||||
fontWeight: 'bold'
|
bold: props => <strong>{props.children}</strong>,
|
||||||
},
|
code: props => <code>{props.children}</code>,
|
||||||
code: {
|
italic: props => <em>{props.children}</em>,
|
||||||
fontFamily: 'monospace',
|
underlined: props => <u>{props.children}</u>,
|
||||||
backgroundColor: '#eee',
|
|
||||||
padding: '3px',
|
|
||||||
borderRadius: '4px'
|
|
||||||
},
|
|
||||||
italic: {
|
|
||||||
fontStyle: 'italic'
|
|
||||||
},
|
|
||||||
underlined: {
|
|
||||||
textDecoration: 'underline'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,25 +166,14 @@ class HoveringMenu extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="editor">
|
<div className="editor">
|
||||||
<Editor
|
<Editor
|
||||||
|
schema={schema}
|
||||||
state={this.state.state}
|
state={this.state.state}
|
||||||
renderMark={this.renderMark}
|
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a mark renderer for a Slate `mark`.
|
|
||||||
*
|
|
||||||
* @param {Mark} mark
|
|
||||||
* @return {Object or Void}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderMark = (mark) => {
|
|
||||||
return MARKS[mark.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the menu's absolute position.
|
* Update the menu's absolute position.
|
||||||
*/
|
*/
|
||||||
|
@@ -20,28 +20,23 @@ injector()
|
|||||||
const DEFAULT_NODE = 'paragraph'
|
const DEFAULT_NODE = 'paragraph'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a set of node renderers.
|
* Define a schema.
|
||||||
*
|
*
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const NODES = {
|
const schema = {
|
||||||
'block-code': props => <pre><code {...props.attributes}>{props.children}</code></pre>,
|
nodes: {
|
||||||
'block-quote': props => <blockquote {...props.attributes}>{props.children}</blockquote>,
|
'block-code': props => <pre><code {...props.attributes}>{props.children}</code></pre>,
|
||||||
'heading-two': props => <h2 {...props.attributes}>{props.children}</h2>,
|
'block-quote': props => <blockquote {...props.attributes}>{props.children}</blockquote>,
|
||||||
'paragraph': props => <p {...props.attributes}>{props.children}</p>
|
'heading-two': props => <h2 {...props.attributes}>{props.children}</h2>,
|
||||||
}
|
'paragraph': props => <p {...props.attributes}>{props.children}</p>,
|
||||||
|
},
|
||||||
/**
|
marks: {
|
||||||
* Define a set of mark renderers.
|
bold: props => <strong>{props.children}</strong>,
|
||||||
*
|
highlight: props => <mark>{props.children}</mark>,
|
||||||
* @type {Object}
|
italic: props => <em>{props.children}</em>,
|
||||||
*/
|
}
|
||||||
|
|
||||||
const MARKS = {
|
|
||||||
bold: props => <strong>{props.children}</strong>,
|
|
||||||
highlight: props => <mark>{props.children}</mark>,
|
|
||||||
italic: props => <em>{props.children}</em>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -274,37 +269,14 @@ class Iframes extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<Editor
|
<Editor
|
||||||
placeholder={'Enter some rich text...'}
|
placeholder={'Enter some rich text...'}
|
||||||
|
schema={schema}
|
||||||
state={this.state.state}
|
state={this.state.state}
|
||||||
renderNode={this.renderNode}
|
|
||||||
renderMark={this.renderMark}
|
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
onKeyDown={this.onKeyDown}
|
onKeyDown={this.onKeyDown}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a node renderer for a Slate `node`.
|
|
||||||
*
|
|
||||||
* @param {Node} node
|
|
||||||
* @return {Component or Void}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderNode = (node) => {
|
|
||||||
return NODES[node.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a mark renderer for a Slate `mark`.
|
|
||||||
*
|
|
||||||
* @param {Mark} mark
|
|
||||||
* @return {Object or Void}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderMark = (mark) => {
|
|
||||||
return MARKS[mark.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Iframes
|
export default Iframes
|
||||||
|
@@ -7,20 +7,22 @@ import isImage from 'is-image'
|
|||||||
import isUrl from 'is-url'
|
import isUrl from 'is-url'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a set of node renderers.
|
* Define a schema.
|
||||||
*
|
*
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const NODES = {
|
const schema = {
|
||||||
image: (props) => {
|
nodes: {
|
||||||
const { node, state } = props
|
image: (props) => {
|
||||||
const isFocused = state.selection.hasEdgeIn(node)
|
const { node, state } = props
|
||||||
const src = node.data.get('src')
|
const isFocused = state.selection.hasEdgeIn(node)
|
||||||
const className = isFocused ? 'active' : null
|
const src = node.data.get('src')
|
||||||
return (
|
const className = isFocused ? 'active' : null
|
||||||
<img src={src} className={className} {...props.attributes} />
|
return (
|
||||||
)
|
<img src={src} className={className} {...props.attributes} />
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,8 +85,8 @@ class Images extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="editor">
|
<div className="editor">
|
||||||
<Editor
|
<Editor
|
||||||
|
schema={schema}
|
||||||
state={this.state.state}
|
state={this.state.state}
|
||||||
renderNode={this.renderNode}
|
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
onDocumentChange={this.onDocumentChange}
|
onDocumentChange={this.onDocumentChange}
|
||||||
onDrop={this.onDrop}
|
onDrop={this.onDrop}
|
||||||
@@ -94,17 +96,6 @@ class Images extends React.Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Render a `node`.
|
|
||||||
*
|
|
||||||
* @param {Node} node
|
|
||||||
* @return {Element}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderNode = (node) => {
|
|
||||||
return NODES[node.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* On change.
|
* On change.
|
||||||
*
|
*
|
||||||
|
@@ -21,6 +21,11 @@ pre {
|
|||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:not(pre) > code {
|
||||||
|
background-color: #eee;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 20em;
|
max-height: 20em;
|
||||||
|
@@ -7,17 +7,19 @@ import isUrl from 'is-url'
|
|||||||
import { Map } from 'immutable'
|
import { Map } from 'immutable'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a set of node renderers.
|
* Define a schema.
|
||||||
*
|
*
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const NODES = {
|
const schema = {
|
||||||
paragraph: props => <p>{props.children}</p>,
|
nodes: {
|
||||||
link: (props) => {
|
paragraph: props => <p>{props.children}</p>,
|
||||||
const { data } = props.node
|
link: (props) => {
|
||||||
const href = data.get('href')
|
const { data } = props.node
|
||||||
return <a {...props.attributes} href={href}>{props.children}</a>
|
const href = data.get('href')
|
||||||
|
return <a {...props.attributes} href={href}>{props.children}</a>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,8 +183,8 @@ class Links extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="editor">
|
<div className="editor">
|
||||||
<Editor
|
<Editor
|
||||||
|
schema={schema}
|
||||||
state={this.state.state}
|
state={this.state.state}
|
||||||
renderNode={this.renderNode}
|
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
onPaste={this.onPaste}
|
onPaste={this.onPaste}
|
||||||
/>
|
/>
|
||||||
@@ -190,17 +192,6 @@ class Links extends React.Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Render a `node`.
|
|
||||||
*
|
|
||||||
* @param {Node} node
|
|
||||||
* @return {Element}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderNode = (node) => {
|
|
||||||
return NODES[node.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -4,51 +4,35 @@ import React from 'react'
|
|||||||
import initialState from './state.json'
|
import initialState from './state.json'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a set of node renderers.
|
* Define a schema.
|
||||||
*
|
*
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const NODES = {
|
const schema = {
|
||||||
'bulleted-list': props => <ul {...props.attributes}>{props.children}</ul>,
|
nodes: {
|
||||||
'code': props => <pre><code {...props.attributes}>{props.children}</code></pre>,
|
'bulleted-list': props => <ul {...props.attributes}>{props.children}</ul>,
|
||||||
'heading-one': props => <h1 {...props.attributes}>{props.children}</h1>,
|
'code': props => <pre><code {...props.attributes}>{props.children}</code></pre>,
|
||||||
'heading-two': props => <h2 {...props.attributes}>{props.children}</h2>,
|
'heading-one': props => <h1 {...props.attributes}>{props.children}</h1>,
|
||||||
'heading-three': props => <h3 {...props.attributes}>{props.children}</h3>,
|
'heading-two': props => <h2 {...props.attributes}>{props.children}</h2>,
|
||||||
'heading-four': props => <h4 {...props.attributes}>{props.children}</h4>,
|
'heading-three': props => <h3 {...props.attributes}>{props.children}</h3>,
|
||||||
'heading-five': props => <h5 {...props.attributes}>{props.children}</h5>,
|
'heading-four': props => <h4 {...props.attributes}>{props.children}</h4>,
|
||||||
'heading-six': props => <h6 {...props.attributes}>{props.children}</h6>,
|
'heading-five': props => <h5 {...props.attributes}>{props.children}</h5>,
|
||||||
'list-item': props => <li {...props.attributes}>{props.children}</li>,
|
'heading-six': props => <h6 {...props.attributes}>{props.children}</h6>,
|
||||||
'numbered-list': props => <ol {...props.attributes}>{props.children}</ol>,
|
'list-item': props => <li {...props.attributes}>{props.children}</li>,
|
||||||
'quote': props => <blockquote {...props.attributes}>{props.children}</blockquote>,
|
'numbered-list': props => <ol {...props.attributes}>{props.children}</ol>,
|
||||||
'link': (props) => {
|
'quote': props => <blockquote {...props.attributes}>{props.children}</blockquote>,
|
||||||
const { data } = props.node
|
'link': (props) => {
|
||||||
const href = data.get('href')
|
const { data } = props.node
|
||||||
return <a href={href} {...props.attributes}>{props.children}</a>
|
const href = data.get('href')
|
||||||
}
|
return <a href={href} {...props.attributes}>{props.children}</a>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Define a set of mark renderers.
|
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
|
|
||||||
const MARKS = {
|
|
||||||
bold: {
|
|
||||||
fontWeight: 'bold'
|
|
||||||
},
|
},
|
||||||
code: {
|
marks: {
|
||||||
fontFamily: 'monospace',
|
bold: props => <strong>{props.children}</strong>,
|
||||||
backgroundColor: '#eee',
|
code: props => <code>{props.children}</code>,
|
||||||
padding: '3px',
|
italic: props => <em>{props.children}</em>,
|
||||||
borderRadius: '4px'
|
underlined: props => <u>{props.children}</u>,
|
||||||
},
|
|
||||||
italic: {
|
|
||||||
fontStyle: 'italic'
|
|
||||||
},
|
|
||||||
underlined: {
|
|
||||||
textDecoration: 'underline'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,9 +196,8 @@ class PasteHtml extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="editor">
|
<div className="editor">
|
||||||
<Editor
|
<Editor
|
||||||
|
schema={schema}
|
||||||
state={this.state.state}
|
state={this.state.state}
|
||||||
renderNode={this.renderNode}
|
|
||||||
renderMark={this.renderMark}
|
|
||||||
onPaste={this.onPaste}
|
onPaste={this.onPaste}
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
/>
|
/>
|
||||||
@@ -222,28 +205,6 @@ class PasteHtml extends React.Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a node renderer for a Slate `node`.
|
|
||||||
*
|
|
||||||
* @param {Node} node
|
|
||||||
* @return {Component or Void}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderNode = (node) => {
|
|
||||||
return NODES[node.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a mark renderer for a Slate `mark`.
|
|
||||||
*
|
|
||||||
* @param {Mark} mark
|
|
||||||
* @return {Object or Void}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderMark = (mark) => {
|
|
||||||
return MARKS[mark.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -299,7 +299,6 @@ class RichText extends React.Component {
|
|||||||
placeholder={'Enter some rich text...'}
|
placeholder={'Enter some rich text...'}
|
||||||
schema={schema}
|
schema={schema}
|
||||||
state={this.state.state}
|
state={this.state.state}
|
||||||
renderMark={this.renderMark}
|
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
onKeyDown={this.onKeyDown}
|
onKeyDown={this.onKeyDown}
|
||||||
/>
|
/>
|
||||||
@@ -307,17 +306,6 @@ class RichText extends React.Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a mark renderer for a Slate `mark`.
|
|
||||||
*
|
|
||||||
* @param {Mark} mark
|
|
||||||
* @return {Object or Void}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderMark = (mark) => {
|
|
||||||
return MARKS[mark.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -5,13 +5,15 @@ import SoftBreak from 'slate-soft-break'
|
|||||||
import initialState from './state.json'
|
import initialState from './state.json'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a set of node renderers.
|
* Define a schema.
|
||||||
*
|
*
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const NODES = {
|
const schema = {
|
||||||
'block-quote': (props) => <blockquote {...props.attributes}>{props.children}</blockquote>,
|
nodes: {
|
||||||
|
'block-quote': (props) => <blockquote {...props.attributes}>{props.children}</blockquote>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,25 +71,14 @@ class PlainText extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<Editor
|
<Editor
|
||||||
placeholder={'Enter some plain text...'}
|
placeholder={'Enter some plain text...'}
|
||||||
|
schema={schema}
|
||||||
|
state={this.state.state}
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
onKeyDown={this.onKeyDown}
|
onKeyDown={this.onKeyDown}
|
||||||
renderNode={this.renderNode}
|
|
||||||
state={this.state.state}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a node renderer for a Slate `node`.
|
|
||||||
*
|
|
||||||
* @param {Node} node
|
|
||||||
* @return {Component or Void}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderNode = (node) => {
|
|
||||||
return NODES[node.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -5,26 +5,19 @@ import initialState from './state.json'
|
|||||||
import keycode from 'keycode'
|
import keycode from 'keycode'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a set of node renderers.
|
* Define a schema.
|
||||||
*
|
*
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const NODES = {
|
const schema = {
|
||||||
'table': props => <table><tbody {...props.attributes}>{props.children}</tbody></table>,
|
nodes: {
|
||||||
'table-row': props => <tr {...props.attributes}>{props.children}</tr>,
|
'table': props => <table><tbody {...props.attributes}>{props.children}</tbody></table>,
|
||||||
'table-cell': props => <td {...props.attributes}>{props.children}</td>
|
'table-row': props => <tr {...props.attributes}>{props.children}</tr>,
|
||||||
}
|
'table-cell': props => <td {...props.attributes}>{props.children}</td>,
|
||||||
|
},
|
||||||
/**
|
marks: {
|
||||||
* Define a set of mark renderers.
|
'bold': props => <strong>{props.children}</strong>
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
|
|
||||||
const MARKS = {
|
|
||||||
bold: {
|
|
||||||
fontWeight: 'bold'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,9 +118,8 @@ class Tables extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="editor">
|
<div className="editor">
|
||||||
<Editor
|
<Editor
|
||||||
|
schema={schema}
|
||||||
state={this.state.state}
|
state={this.state.state}
|
||||||
renderNode={this.renderNode}
|
|
||||||
renderMark={this.renderMark}
|
|
||||||
onKeyDown={this.onKeyDown}
|
onKeyDown={this.onKeyDown}
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
/>
|
/>
|
||||||
@@ -135,28 +127,6 @@ class Tables extends React.Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a node renderer for a Slate `node`.
|
|
||||||
*
|
|
||||||
* @param {Node} node
|
|
||||||
* @return {Component or Void}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderNode = (node) => {
|
|
||||||
return NODES[node.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a mark renderer for a Slate `mark`.
|
|
||||||
*
|
|
||||||
* @param {Mark} mark
|
|
||||||
* @return {Object or Void}
|
|
||||||
*/
|
|
||||||
|
|
||||||
renderMark = (mark) => {
|
|
||||||
return MARKS[mark.type]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -54,7 +54,7 @@ class Editor extends React.Component {
|
|||||||
static propTypes = {
|
static propTypes = {
|
||||||
className: React.PropTypes.string,
|
className: React.PropTypes.string,
|
||||||
onBeforeChange: React.PropTypes.func,
|
onBeforeChange: React.PropTypes.func,
|
||||||
onChange: React.PropTypes.func.isRequired,
|
onChange: React.PropTypes.func,
|
||||||
onDocumentChange: React.PropTypes.func,
|
onDocumentChange: React.PropTypes.func,
|
||||||
onSelectionChange: React.PropTypes.func,
|
onSelectionChange: React.PropTypes.func,
|
||||||
placeholder: React.PropTypes.any,
|
placeholder: React.PropTypes.any,
|
||||||
@@ -73,6 +73,7 @@ class Editor extends React.Component {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
onChange: noop,
|
||||||
onDocumentChange: noop,
|
onDocumentChange: noop,
|
||||||
onSelectionChange: noop,
|
onSelectionChange: noop,
|
||||||
plugins: [],
|
plugins: [],
|
||||||
|
@@ -31,7 +31,8 @@ class Void extends React.Component {
|
|||||||
children: React.PropTypes.any.isRequired,
|
children: React.PropTypes.any.isRequired,
|
||||||
editor: React.PropTypes.object.isRequired,
|
editor: React.PropTypes.object.isRequired,
|
||||||
node: React.PropTypes.object.isRequired,
|
node: React.PropTypes.object.isRequired,
|
||||||
state: React.PropTypes.object.isRequired
|
schema: React.PropTypes.object.isRequired,
|
||||||
|
state: React.PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,7 +118,7 @@ class Void extends React.Component {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
renderLeaf = () => {
|
renderLeaf = () => {
|
||||||
const { node, state } = this.props
|
const { node, schema, state } = this.props
|
||||||
const child = node.getTexts().first()
|
const child = node.getTexts().first()
|
||||||
const ranges = child.getRanges()
|
const ranges = child.getRanges()
|
||||||
const text = ''
|
const text = ''
|
||||||
@@ -133,6 +134,7 @@ class Void extends React.Component {
|
|||||||
isVoid
|
isVoid
|
||||||
renderMark={noop}
|
renderMark={noop}
|
||||||
key={offsetKey}
|
key={offsetKey}
|
||||||
|
schema={schema}
|
||||||
state={state}
|
state={state}
|
||||||
node={child}
|
node={child}
|
||||||
ranges={ranges}
|
ranges={ranges}
|
||||||
|
@@ -1,92 +0,0 @@
|
|||||||
|
|
||||||
/**
|
|
||||||
* The default Slate schema rules, which enforce the most basic constraints.
|
|
||||||
*
|
|
||||||
* @type {Array}
|
|
||||||
*/
|
|
||||||
|
|
||||||
const RULES = [
|
|
||||||
{
|
|
||||||
match: {
|
|
||||||
kind: 'document'
|
|
||||||
},
|
|
||||||
validate: {
|
|
||||||
anyOf: [
|
|
||||||
{ kind: 'block' }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
transform: (transform, match, reason) => {
|
|
||||||
return reason.value.reduce((tr, node) => {
|
|
||||||
return tr.removeNodeByKey(node.key)
|
|
||||||
}, transform)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
match: {
|
|
||||||
kind: 'block'
|
|
||||||
},
|
|
||||||
validate: {
|
|
||||||
anyOf: [
|
|
||||||
{ kind: 'block' },
|
|
||||||
{ kind: 'inline' },
|
|
||||||
{ kind: 'text' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
transform: (transform, match, reason) => {
|
|
||||||
return reason.value.reduce((tr, node) => {
|
|
||||||
return tr.removeNodeByKey(node.key)
|
|
||||||
}, transform)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
match: {
|
|
||||||
kind: 'inline'
|
|
||||||
},
|
|
||||||
validate: {
|
|
||||||
anyOf: [
|
|
||||||
{ kind: 'inline' },
|
|
||||||
{ kind: 'text' },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
transform: (transform, match, reason) => {
|
|
||||||
return reason.value.reduce((tr, node) => {
|
|
||||||
return tr.removeNodeByKey(node.key)
|
|
||||||
}, transform)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// match: { isVoid: true },
|
|
||||||
// validate: {
|
|
||||||
// text: ' '
|
|
||||||
// },
|
|
||||||
// transform: (transform, node) => {
|
|
||||||
// const { state } = transform
|
|
||||||
// const range = state.selection.moveToRangeOf(node)
|
|
||||||
// return transform.delete().insertText(' ')
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// match: (object) => {
|
|
||||||
// return (
|
|
||||||
// object.kind == 'block' &&
|
|
||||||
// object.nodes.size == 1 &&
|
|
||||||
// object.nodes.first().isVoid
|
|
||||||
// )
|
|
||||||
// },
|
|
||||||
// invalid: true,
|
|
||||||
// transform: (transform, node) => {
|
|
||||||
// const child = node.nodes.first()
|
|
||||||
// const text =
|
|
||||||
// return transform
|
|
||||||
// .insertNodeBeforeNodeByKey(child.)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export.
|
|
||||||
*
|
|
||||||
* @type {Array}
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default RULES
|
|
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import RULES from '../constants/rules'
|
|
||||||
import includes from 'lodash/includes'
|
import includes from 'lodash/includes'
|
||||||
import isReactComponent from '../utils/is-react-component'
|
import isReactComponent from '../utils/is-react-component'
|
||||||
import typeOf from 'type-of'
|
import typeOf from 'type-of'
|
||||||
@@ -171,7 +170,7 @@ class Schema extends new Record(DEFAULTS) {
|
|||||||
.filter(rule => rule.match(object) && rule.decorator)
|
.filter(rule => rule.match(object) && rule.decorator)
|
||||||
.map((rule) => {
|
.map((rule) => {
|
||||||
return (text) => {
|
return (text) => {
|
||||||
return rule.decorator(object, text)
|
return rule.decorator(text, object)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -250,7 +249,7 @@ function normalizeNodes(nodes) {
|
|||||||
type: key,
|
type: key,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.component) {
|
if (value.component || value.decorator || value.validate) {
|
||||||
rules.push({
|
rules.push({
|
||||||
match,
|
match,
|
||||||
...value,
|
...value,
|
||||||
@@ -283,7 +282,7 @@ function normalizeMarks(marks) {
|
|||||||
type: key,
|
type: key,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.component) {
|
if (value.component || value.decorator || value.validate) {
|
||||||
rules.push({
|
rules.push({
|
||||||
match,
|
match,
|
||||||
...value,
|
...value,
|
||||||
@@ -392,9 +391,9 @@ function normalizeTransform(transform) {
|
|||||||
|
|
||||||
function normalizeSpec(obj, giveReason) {
|
function normalizeSpec(obj, giveReason) {
|
||||||
const spec = { ...obj }
|
const spec = { ...obj }
|
||||||
if (spec.exactlyOf) spec.exactlyOf = spec.exactlyOf.map(normalizeSpec)
|
if (spec.exactlyOf) spec.exactlyOf = spec.exactlyOf.map(s => normalizeSpec(s))
|
||||||
if (spec.anyOf) spec.anyOf = spec.anyOf.map(normalizeSpec)
|
if (spec.anyOf) spec.anyOf = spec.anyOf.map(s => normalizeSpec(s))
|
||||||
if (spec.noneOf) spec.noneOf = spec.noneOf.map(normalizeSpec)
|
if (spec.noneOf) spec.noneOf = spec.noneOf.map(s => normalizeSpec(s))
|
||||||
|
|
||||||
return (node) => {
|
return (node) => {
|
||||||
for (const key in CHECKS) {
|
for (const key in CHECKS) {
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
"browserify-shim": "^3.8.12",
|
"browserify-shim": "^3.8.12",
|
||||||
"disc": "^1.3.2",
|
"disc": "^1.3.2",
|
||||||
"envify": "^3.4.1",
|
"envify": "^3.4.1",
|
||||||
|
"enzyme": "^2.4.1",
|
||||||
"eslint": "^3.0.1",
|
"eslint": "^3.0.1",
|
||||||
"eslint-plugin-import": "^1.10.2",
|
"eslint-plugin-import": "^1.10.2",
|
||||||
"eslint-plugin-react": "^5.2.2",
|
"eslint-plugin-react": "^5.2.2",
|
||||||
@@ -46,10 +47,12 @@
|
|||||||
"is-image": "^1.0.1",
|
"is-image": "^1.0.1",
|
||||||
"is-url": "^1.2.2",
|
"is-url": "^1.2.2",
|
||||||
"mocha": "^2.5.3",
|
"mocha": "^2.5.3",
|
||||||
|
"mocha-jsdom": "^1.1.0",
|
||||||
"npm-run-all": "^2.3.0",
|
"npm-run-all": "^2.3.0",
|
||||||
"prismjs": "^1.5.1",
|
"prismjs": "^1.5.1",
|
||||||
"react": "^15.2.0",
|
"react": "^15.2.0",
|
||||||
"react-addons-perf": "^15.2.1",
|
"react-addons-perf": "^15.2.1",
|
||||||
|
"react-addons-test-utils": "^15.3.0",
|
||||||
"react-dom": "^15.1.0",
|
"react-dom": "^15.1.0",
|
||||||
"react-frame-aware-selection-plugin": "0.0.2",
|
"react-frame-aware-selection-plugin": "0.0.2",
|
||||||
"react-frame-component": "^0.6.2",
|
"react-frame-component": "^0.6.2",
|
||||||
|
@@ -7,6 +7,8 @@ function Image(props) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderNode(node) {
|
export const schema = {
|
||||||
if (node.type == 'image') return Image
|
nodes: {
|
||||||
|
image: Image
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,8 @@ function Code(props) {
|
|||||||
return <pre {...props.attributes}><code>{props.children}</code></pre>
|
return <pre {...props.attributes}><code>{props.children}</code></pre>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderNode(node) {
|
export const schema = {
|
||||||
if (node.type == 'code') return Code
|
nodes: {
|
||||||
|
code: Code
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,16 +1,11 @@
|
|||||||
|
|
||||||
import React from 'react'
|
|
||||||
import { Mark } from '../../../..'
|
import { Mark } from '../../../..'
|
||||||
|
|
||||||
const BOLD = {
|
const BOLD = {
|
||||||
fontWeight: 'bold'
|
fontWeight: 'bold'
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderMark(mark) {
|
function decorator(text) {
|
||||||
if (mark.type == 'bold') return BOLD
|
|
||||||
}
|
|
||||||
|
|
||||||
export function renderDecorations(text) {
|
|
||||||
let { characters } = text
|
let { characters } = text
|
||||||
let second = characters.get(1)
|
let second = characters.get(1)
|
||||||
let mark = Mark.create({ type: 'bold' })
|
let mark = Mark.create({ type: 'bold' })
|
||||||
@@ -19,3 +14,14 @@ export function renderDecorations(text) {
|
|||||||
characters = characters.set(1, second)
|
characters = characters.set(1, second)
|
||||||
return characters
|
return characters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const schema = {
|
||||||
|
nodes: {
|
||||||
|
default: {
|
||||||
|
decorator
|
||||||
|
}
|
||||||
|
},
|
||||||
|
marks: {
|
||||||
|
bold: BOLD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -6,6 +6,8 @@ function Link(props) {
|
|||||||
return <a {...props.attributes} href={href}>{props.children}</a>
|
return <a {...props.attributes} href={href}>{props.children}</a>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderNode(node) {
|
export const schema = {
|
||||||
if (node.type == 'link') return Link
|
nodes: {
|
||||||
|
link: Link
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,29 +0,0 @@
|
|||||||
|
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
const BOLD = {
|
|
||||||
fontWeight: 'bold'
|
|
||||||
}
|
|
||||||
|
|
||||||
const ITALIC = {
|
|
||||||
fontStyle: 'italic'
|
|
||||||
}
|
|
||||||
|
|
||||||
const BOLD_ITALIC = {
|
|
||||||
fontFamily: 'bold-italic'
|
|
||||||
}
|
|
||||||
|
|
||||||
export function renderMark(mark, marks) {
|
|
||||||
if (
|
|
||||||
marks.size > 1 &&
|
|
||||||
marks.some(m => m.type == 'bold') &&
|
|
||||||
marks.some(m => m.type == 'italic')
|
|
||||||
) {
|
|
||||||
return mark.type == 'bold'
|
|
||||||
? BOLD_ITALIC
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mark.type == 'bold') return BOLD
|
|
||||||
if (mark.type == 'italic') return ITALIC
|
|
||||||
}
|
|
@@ -1,17 +0,0 @@
|
|||||||
|
|
||||||
nodes:
|
|
||||||
- kind: block
|
|
||||||
type: default
|
|
||||||
nodes:
|
|
||||||
- kind: text
|
|
||||||
ranges:
|
|
||||||
- text: one
|
|
||||||
marks:
|
|
||||||
- type: bold
|
|
||||||
- text: two
|
|
||||||
marks:
|
|
||||||
- type: italic
|
|
||||||
- text: three
|
|
||||||
marks:
|
|
||||||
- type: bold
|
|
||||||
- type: italic
|
|
@@ -1,10 +0,0 @@
|
|||||||
|
|
||||||
<div contenteditable="true">
|
|
||||||
<div style="position:relative;">
|
|
||||||
<span>
|
|
||||||
<span><span style="font-weight:bold;">one</span></span>
|
|
||||||
<span><span style="font-style:italic;">two</span></span>
|
|
||||||
<span><span style="font-family:bold-italic;">three</span></span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@@ -7,6 +7,8 @@ class Bold extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderMark(mark) {
|
export const schema = {
|
||||||
if (mark.type == 'bold') return Bold
|
marks: {
|
||||||
|
bold: Bold
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,12 @@
|
|||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
function BOLD(props) {
|
function Bold(props) {
|
||||||
return <strong>{props.children}</strong>
|
return <strong>{props.children}</strong>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderMark(mark) {
|
export const schema = {
|
||||||
if (mark.type == 'bold') return BOLD
|
marks: {
|
||||||
|
bold: Bold
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,9 @@ function ITALIC(props) {
|
|||||||
return <i>{props.children}</i>
|
return <i>{props.children}</i>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderMark(mark, marks) {
|
export const schema = {
|
||||||
if (mark.type == 'bold') return BOLD
|
marks: {
|
||||||
if (mark.type == 'italic') return ITALIC
|
bold: BOLD,
|
||||||
|
italic: ITALIC
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
export function renderMark(mark) {
|
export const schema = {
|
||||||
if (mark.type == 'bold') {
|
marks: {
|
||||||
return {
|
bold: {
|
||||||
fontWeight: 'bold'
|
fontWeight: 'bold'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
export function renderMark(mark) {
|
export const schema = {
|
||||||
if (mark.type == 'bold') return 'bold'
|
marks: {
|
||||||
|
bold: 'bold'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,8 @@ function Code(props) {
|
|||||||
return <pre {...props.attributes}><code>{props.children}</code></pre>
|
return <pre {...props.attributes}><code>{props.children}</code></pre>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderNode(node) {
|
export const schema = {
|
||||||
if (node.type == 'code') return Code
|
nodes: {
|
||||||
|
code: Code
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,8 @@ function Link(props) {
|
|||||||
return <a {...props.attributes} href={href}>{props.children}</a>
|
return <a {...props.attributes} href={href}>{props.children}</a>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderNode(node) {
|
export const schema = {
|
||||||
if (node.type == 'link') return Link
|
nodes: {
|
||||||
|
link: Link
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,17 +1,21 @@
|
|||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import strip from '../helpers/strip-dynamic'
|
import jsdom from 'mocha-jsdom'
|
||||||
import readMetadata from 'read-metadata'
|
import readMetadata from 'read-metadata'
|
||||||
|
import strip from '../helpers/strip-dynamic'
|
||||||
import { Raw, Editor, Schema } from '../..'
|
import { Raw, Editor, Schema } from '../..'
|
||||||
import { strictEqual } from '../helpers/assert-json'
|
import { mount } from 'enzyme'
|
||||||
import { resolve } from 'path'
|
import { resolve } from 'path'
|
||||||
|
import { strictEqual } from '../helpers/assert-json'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests.
|
* Tests.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
describe('schema', () => {
|
describe('schema', () => {
|
||||||
|
jsdom()
|
||||||
|
|
||||||
const tests = fs.readdirSync(resolve(__dirname, './fixtures'))
|
const tests = fs.readdirSync(resolve(__dirname, './fixtures'))
|
||||||
|
|
||||||
for (const test of tests) {
|
for (const test of tests) {
|
||||||
@@ -22,10 +26,16 @@ describe('schema', () => {
|
|||||||
const input = readMetadata.sync(resolve(dir, 'input.yaml'))
|
const input = readMetadata.sync(resolve(dir, 'input.yaml'))
|
||||||
const expected = readMetadata.sync(resolve(dir, 'output.yaml'))
|
const expected = readMetadata.sync(resolve(dir, 'output.yaml'))
|
||||||
const schema = Schema.create(require(dir))
|
const schema = Schema.create(require(dir))
|
||||||
|
|
||||||
const state = Raw.deserialize(input, { terse: true })
|
const state = Raw.deserialize(input, { terse: true })
|
||||||
const editor = <Editor state={state} schema={schema} />
|
const props = {
|
||||||
const output = Raw.serialize(state, { terse: true })
|
onChange: value => value,
|
||||||
|
schema,
|
||||||
|
state,
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = mount(<Editor {...props} />)
|
||||||
|
const normalized = wrapper.state().state
|
||||||
|
const output = Raw.serialize(normalized, { terse: true })
|
||||||
strictEqual(strip(output), strip(expected))
|
strictEqual(strip(output), strip(expected))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user