More and more fixes

This commit is contained in:
Tom Moor
2017-12-03 19:59:54 -08:00
parent 802f6e6594
commit 751b468e92
14 changed files with 194 additions and 257 deletions

View File

@ -4,7 +4,7 @@ import { observable } from 'mobx';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Value, Change } from 'slate'; import { Value, Change } from 'slate';
import { Editor } from 'slate-react'; import { Editor } from 'slate-react';
import type { SlateNodeProps } from './types'; import type { SlateNodeProps, Plugin } from './types';
import Plain from 'slate-plain-serializer'; import Plain from 'slate-plain-serializer';
import keydown from 'react-keydown'; import keydown from 'react-keydown';
import getDataTransferFiles from 'utils/getDataTransferFiles'; import getDataTransferFiles from 'utils/getDataTransferFiles';
@ -16,9 +16,10 @@ import Placeholder from './components/Placeholder';
import Contents from './components/Contents'; import Contents from './components/Contents';
import Markdown from './serializer'; import Markdown from './serializer';
import createPlugins from './plugins'; import createPlugins from './plugins';
import insertImage from './insertImage'; import { insertImageFile } from './changes';
import renderMark from './marks'; import renderMark from './marks';
import createRenderNode from './nodes'; import createRenderNode from './nodes';
import schema from './schema';
import styled from 'styled-components'; import styled from 'styled-components';
type Props = { type Props = {
@ -37,7 +38,7 @@ class MarkdownEditor extends Component {
props: Props; props: Props;
editor: Editor; editor: Editor;
renderNode: SlateNodeProps => *; renderNode: SlateNodeProps => *;
plugins: Object[]; plugins: Plugin[];
@observable editorValue: Value; @observable editorValue: Value;
constructor(props: Props) { constructor(props: Props) {
@ -60,12 +61,11 @@ class MarkdownEditor extends Component {
} }
componentDidMount() { componentDidMount() {
if (!this.props.readOnly) { if (this.props.readOnly) return;
if (this.props.text) { if (this.props.text) {
this.focusAtEnd(); this.focusAtEnd();
} else { } else {
this.focusAtStart(); this.focusAtStart();
}
} }
} }
@ -78,8 +78,8 @@ class MarkdownEditor extends Component {
onChange = (change: Change) => { onChange = (change: Change) => {
if (this.editorValue !== change.value) { if (this.editorValue !== change.value) {
this.props.onChange(Markdown.serialize(change.value)); this.props.onChange(Markdown.serialize(change.value));
this.editorValue = change.value;
} }
this.editorValue = change.value;
}; };
handleDrop = async (ev: SyntheticEvent) => { handleDrop = async (ev: SyntheticEvent) => {
@ -100,15 +100,13 @@ class MarkdownEditor extends Component {
}; };
insertImageFile = async (file: window.File) => { insertImageFile = async (file: window.File) => {
this.editor.change( this.editor.change(change =>
async change => change.call(
await insertImage( insertImageFile,
change, file,
file, this.props.onImageUploadStart,
this.editor, this.props.onImageUploadStop
this.props.onImageUploadStart, )
this.props.onImageUploadStop
)
); );
}; };
@ -206,10 +204,12 @@ class MarkdownEditor extends Component {
value={this.editorValue} value={this.editorValue}
renderNode={this.renderNode} renderNode={this.renderNode}
renderMark={renderMark} renderMark={renderMark}
schema={schema}
onKeyDown={this.onKeyDown} onKeyDown={this.onKeyDown}
onChange={this.onChange} onChange={this.onChange}
onSave={onSave} onSave={onSave}
readOnly={readOnly} readOnly={readOnly}
spellCheck={!readOnly}
/> />
<ClickablePadding <ClickablePadding
onClick={!readOnly ? this.focusAtEnd : undefined} onClick={!readOnly ? this.focusAtEnd : undefined}

View File

@ -1,18 +1,46 @@
// @flow // @flow
import uuid from 'uuid';
import uploadFile from 'utils/uploadFile';
import { Change } from 'slate'; import { Change } from 'slate';
import { Editor } from 'slate-react'; import uuid from 'uuid';
import EditList from './plugins/EditList';
import uploadFile from 'utils/uploadFile';
export default async function insertImageFile( const { changes } = EditList;
type Options = {
type: string | Object,
wrapper?: string | Object,
append?: string | Object,
};
export function splitAndInsertBlock(change: Change, options: Options) {
const { type, wrapper, append } = options;
const parent = change.value.document.getParent(change.value.startBlock.key);
// lists get some special treatment
if (parent && parent.type === 'list-item') {
change = changes.unwrapList(
changes
.splitListItem(change.collapseToStart())
.collapseToEndOfPreviousBlock()
);
}
change = change.insertBlock(type);
if (wrapper) change = change.wrapBlock(wrapper);
if (append) change = change.insertBlock(append);
return change;
}
export async function insertImageFile(
change: Change, change: Change,
file: window.File, file: window.File,
editor: Editor,
onImageUploadStart: () => void, onImageUploadStart: () => void,
onImageUploadStop: () => void onImageUploadStop: () => void
) { ) {
onImageUploadStart(); onImageUploadStart();
console.log(file);
try { try {
// load the file as a data URL // load the file as a data URL
const id = uuid.v4(); const id = uuid.v4();
@ -27,6 +55,7 @@ export default async function insertImageFile(
isVoid: true, isVoid: true,
data: { src, id, alt, loading: true }, data: { src, id, alt, loading: true },
}); });
console.log('insertBlock', change);
}); });
reader.readAsDataURL(file); reader.readAsDataURL(file);
@ -37,12 +66,12 @@ export default async function insertImageFile(
// we dont use the original change provided to the callback here // we dont use the original change provided to the callback here
// as the state may have changed significantly in the time it took to // as the state may have changed significantly in the time it took to
// upload the file. // upload the file.
const finalTransform = editor.value.change(); const placeholder = change.value.document.findDescendant(
const placeholder = editor.value.document.findDescendant(
node => node.data && node.data.get('id') === id node => node.data && node.data.get('id') === id
); );
console.log('placeholder', placeholder);
return finalTransform.setNodeByKey(placeholder.key, { return change.setNodeByKey(placeholder.key, {
data: { src, alt, loading: false }, data: { src, alt, loading: false },
}); });
} catch (err) { } catch (err) {

View File

@ -10,12 +10,9 @@ export default class TodoItem extends Component {
handleChange = (ev: SyntheticInputEvent) => { handleChange = (ev: SyntheticInputEvent) => {
const checked = ev.target.checked; const checked = ev.target.checked;
const { editor, node } = this.props; const { editor, node } = this.props;
const change = editor editor.change(change =>
.getState() change.setNodeByKey(node.key, { data: { checked } })
.change() );
.setNodeByKey(node.key, { data: { checked } });
editor.onChange(change);
}; };
render() { render() {

View File

@ -16,7 +16,7 @@ import ToolbarButton from './components/ToolbarButton';
import type { SlateNodeProps } from '../../types'; import type { SlateNodeProps } from '../../types';
import { color } from 'shared/styles/constants'; import { color } from 'shared/styles/constants';
import { fadeIn } from 'shared/styles/animations'; import { fadeIn } from 'shared/styles/animations';
import { splitAndInsertBlock } from '../../transforms'; import { splitAndInsertBlock } from '../../changes';
type Props = SlateNodeProps & { type Props = SlateNodeProps & {
onInsertImage: *, onInsertImage: *,
@ -61,7 +61,7 @@ class BlockToolbar extends Component {
editor.change(change => { editor.change(change => {
splitAndInsertBlock(change, options); splitAndInsertBlock(change, options);
change.value.document.nodes.forEach(node => { editor.value.document.nodes.forEach(node => {
if (node.type === 'block-toolbar') { if (node.type === 'block-toolbar') {
change.removeNodeByKey(node.key); change.removeNodeByKey(node.key);
} }

View File

@ -4,7 +4,6 @@ import ReactDOM from 'react-dom';
import { observable, action } from 'mobx'; import { observable, action } from 'mobx';
import { observer, inject } from 'mobx-react'; import { observer, inject } from 'mobx-react';
import { withRouter } from 'react-router-dom'; import { withRouter } from 'react-router-dom';
import { Change } from 'slate';
import { Editor } from 'slate-react'; import { Editor } from 'slate-react';
import styled from 'styled-components'; import styled from 'styled-components';
import ArrowKeyNavigation from 'boundless-arrow-key-navigation'; import ArrowKeyNavigation from 'boundless-arrow-key-navigation';
@ -28,7 +27,6 @@ class LinkToolbar extends Component {
link: Object, link: Object,
documents: DocumentsStore, documents: DocumentsStore,
onBlur: () => void, onBlur: () => void,
onChange: Change => *,
}; };
@observable isEditing: boolean = false; @observable isEditing: boolean = false;

View File

@ -22,7 +22,7 @@ type Options = {
onInsertImage: *, onInsertImage: *,
}; };
export default function createRenderNode({ onChange, onInsertImage }: Options) { export default function createRenderNode({ onInsertImage }: Options) {
return function renderNode(props: SlateNodeProps) { return function renderNode(props: SlateNodeProps) {
const { attributes } = props; const { attributes } = props;

View File

@ -1,5 +1,5 @@
// @flow // @flow
// import DropOrPasteImages from '@tommoor/slate-drop-or-paste-images'; import InsertImages from 'slate-drop-or-paste-images';
import PasteLinkify from 'slate-paste-linkify'; import PasteLinkify from 'slate-paste-linkify';
import CollapseOnEscape from 'slate-collapse-on-escape'; import CollapseOnEscape from 'slate-collapse-on-escape';
import TrailingBlock from 'slate-trailing-block'; import TrailingBlock from 'slate-trailing-block';
@ -8,7 +8,7 @@ import Prism from 'slate-prism';
import EditList from './plugins/EditList'; import EditList from './plugins/EditList';
import KeyboardShortcuts from './plugins/KeyboardShortcuts'; import KeyboardShortcuts from './plugins/KeyboardShortcuts';
import MarkdownShortcuts from './plugins/MarkdownShortcuts'; import MarkdownShortcuts from './plugins/MarkdownShortcuts';
// import insertImage from './insertImage'; import { insertImageFile } from './changes';
const onlyInCode = node => node.type === 'code'; const onlyInCode = node => node.type === 'code';
@ -23,18 +23,17 @@ const createPlugins = ({ onImageUploadStart, onImageUploadStop }: Options) => {
type: 'link', type: 'link',
collapseTo: 'end', collapseTo: 'end',
}), }),
// DropOrPasteImages({ InsertImages({
// extensions: ['png', 'jpg', 'gif'], extensions: ['png', 'jpg', 'gif'],
// applyTransform: (transform, file, editor) => { insertImage(change, file) {
// return insertImage( return change.call(
// transform, insertImageFile,
// file, file,
// editor, onImageUploadStart,
// onImageUploadStart, onImageUploadStop
// onImageUploadStop );
// ); },
// }, }),
// }),
EditList, EditList,
EditCode({ EditCode({
onlyIn: onlyInCode, onlyIn: onlyInCode,

View File

@ -4,4 +4,5 @@ import EditList from 'slate-edit-list';
export default EditList({ export default EditList({
types: ['ordered-list', 'bulleted-list', 'todo-list'], types: ['ordered-list', 'bulleted-list', 'todo-list'],
typeItem: 'list-item', typeItem: 'list-item',
typeDefault: 'paragraph',
}); });

View File

@ -182,8 +182,8 @@ export default function MarkdownShortcuts() {
change.removeMarkByKey( change.removeMarkByKey(
textNode.key, textNode.key,
change.startOffset - charsInCodeBlock.size, startOffset - charsInCodeBlock.size,
change.startOffset, startOffset,
'code' 'code'
); );
} }
@ -210,10 +210,13 @@ export default function MarkdownShortcuts() {
onEnter(ev: SyntheticKeyboardEvent, change: Change) { onEnter(ev: SyntheticKeyboardEvent, change: Change) {
const { value } = change; const { value } = change;
if (value.isExpanded) return; if (value.isExpanded) return;
const { startBlock, startOffset, endOffset } = value; const { startBlock, startOffset, endOffset } = value;
if (startOffset === 0 && startBlock.length === 0) if (startOffset === 0 && startBlock.length === 0)
return this.onBackspace(ev, change); return this.onBackspace(ev, change);
if (endOffset !== startBlock.length) return;
// Hitting enter at the end of the line reverts to standard behavior
if (endOffset === startBlock.length) return;
// Hitting enter while an image is selected should jump caret below and // Hitting enter while an image is selected should jump caret below and
// insert a new paragraph // insert a new paragraph
@ -225,19 +228,12 @@ export default function MarkdownShortcuts() {
// Hitting enter in a heading or blockquote will split the node at that // Hitting enter in a heading or blockquote will split the node at that
// point and make the new node a paragraph // point and make the new node a paragraph
if ( if (
startBlock.type !== 'heading1' && startBlock.type.startsWith('heading') ||
startBlock.type !== 'heading2' && startBlock.type === 'block-quote'
startBlock.type !== 'heading3' &&
startBlock.type !== 'heading4' &&
startBlock.type !== 'heading5' &&
startBlock.type !== 'heading6' &&
startBlock.type !== 'block-quote'
) { ) {
return; ev.preventDefault();
return change.splitBlock().setBlock('paragraph');
} }
ev.preventDefault();
change.splitBlock().setBlock('paragraph');
}, },
/** /**

View File

@ -1,133 +1,82 @@
// // @flow // @flow
// import React from 'react'; import { Block, Change, Node, Mark } from 'slate';
// import Code from './components/Code';
// import HorizontalRule from './components/HorizontalRule'; const schema = {
// import InlineCode from './components/InlineCode'; blocks: {
// import Image from './components/Image'; heading1: { marks: [''] },
// import Link from './components/Link'; heading2: { marks: [''] },
// import ListItem from './components/ListItem'; heading3: { marks: [''] },
// import TodoList from './components/TodoList'; heading4: { marks: [''] },
// import { heading5: { marks: [''] },
// Heading1, heading6: { marks: [''] },
// Heading2, 'ordered-list': {
// Heading3, nodes: [{ types: ['list-item'] }],
// Heading4, },
// Heading5, 'bulleted-list': {
// Heading6, nodes: [{ types: ['list-item'] }],
// } from './components/Heading'; },
// import Paragraph from './components/Paragraph'; table: {
// import BlockToolbar from './components/Toolbar/BlockToolbar'; nodes: [{ types: ['table-row', 'table-head', 'table-cell'] }],
// import type { Props, Node, Transform } from './types'; },
// image: {
// type Options = { isVoid: true,
// onInsertImage: Function, },
// onChange: Function, 'horizontal-rule': {
// }; isVoid: true,
// },
// const createSchema = ({ onInsertImage, onChange }: Options) => { 'block-toolbar': {
// return { isVoid: true,
// marks: { },
// bold: (props: Props) => <strong>{props.children}</strong>, },
// code: (props: Props) => <InlineCode>{props.children}</InlineCode>, document: {
// italic: (props: Props) => <em>{props.children}</em>, nodes: [
// underlined: (props: Props) => <u>{props.children}</u>, { types: ['heading1'], min: 1, max: 1 },
// deleted: (props: Props) => <del>{props.children}</del>, {
// added: (props: Props) => <mark>{props.children}</mark>, types: [
// }, 'paragraph',
// 'heading1',
// nodes: { 'heading2',
// 'block-toolbar': (props: Props) => ( 'heading3',
// <BlockToolbar 'heading4',
// onChange={onChange} 'heading5',
// onInsertImage={onInsertImage} 'heading6',
// {...props} 'code',
// /> 'horizontal-rule',
// ), 'image',
// paragraph: (props: Props) => <Paragraph {...props} />, 'bulleted-list',
// 'block-quote': (props: Props) => ( 'ordered-list',
// <blockquote {...props.attributes}>{props.children}</blockquote> 'todo-list',
// ), 'block-toolbar',
// 'horizontal-rule': HorizontalRule, 'table',
// 'bulleted-list': (props: Props) => ( ],
// <ul {...props.attributes}>{props.children}</ul> min: 1,
// ), },
// 'ordered-list': (props: Props) => ( ],
// <ol {...props.attributes}>{props.children}</ol> normalize: (
// ), change: Change,
// 'todo-list': (props: Props) => ( reason: string,
// <TodoList {...props.attributes}>{props.children}</TodoList> {
// ), node,
// table: (props: Props) => ( child,
// <table {...props.attributes}>{props.children}</table> mark,
// ), index,
// 'table-row': (props: Props) => ( }: { node: Node, mark?: Mark, child: Node, index: number }
// <tr {...props.attributes}>{props.children}</tr> ) => {
// ), switch (reason) {
// 'table-head': (props: Props) => ( case 'child_type_invalid': {
// <th {...props.attributes}>{props.children}</th> return change.setNodeByKey(
// ), child.key,
// 'table-cell': (props: Props) => ( index === 0 ? 'heading1' : 'paragraph'
// <td {...props.attributes}>{props.children}</td> );
// ), }
// code: Code, case 'child_required': {
// image: Image, const block = Block.create(index === 0 ? 'heading1' : 'paragraph');
// link: Link, return change.insertNodeByKey(node.key, index, block);
// 'list-item': ListItem, }
// heading1: (props: Props) => <Heading1 placeholder {...props} />, default:
// 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} />,
// }, export default schema;
//
// 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;

View File

@ -1,34 +0,0 @@
// @flow
import { Change } from 'slate';
import EditList from './plugins/EditList';
const { changes } = EditList;
type Options = {
type: string | Object,
wrapper?: string | Object,
append?: string | Object,
};
export function splitAndInsertBlock(change: Change, options: Options) {
const { type, wrapper, append } = options;
const { value } = change;
const { document } = value;
const parent = document.getParent(value.startBlock.key);
// lists get some special treatment
if (parent && parent.type === 'list-item') {
change = changes.unwrapList(
changes
.splitListItem(change.collapseToStart())
.collapseToEndOfPreviousBlock()
);
}
change = change.insertBlock(type);
if (wrapper) change = change.wrapBlock(wrapper);
if (append) change = change.insertBlock(append);
return change;
}

View File

@ -1,5 +1,5 @@
// @flow // @flow
import { Value, Node } from 'slate'; import { Value, Change, Node } from 'slate';
import { Editor } from 'slate-react'; import { Editor } from 'slate-react';
export type SlateNodeProps = { export type SlateNodeProps = {
@ -11,3 +11,9 @@ export type SlateNodeProps = {
node: Node, node: Node,
parent: Node, parent: Node,
}; };
export type Plugin = {
validateNode?: Node => *,
onClick?: SyntheticEvent => *,
onKeyDown?: (SyntheticKeyboardEvent, Change) => *,
};

View File

@ -61,7 +61,6 @@
"url": "git+ssh://git@github.com/outline/outline.git" "url": "git+ssh://git@github.com/outline/outline.git"
}, },
"dependencies": { "dependencies": {
"@tommoor/slate-drop-or-paste-images": "0.5.1",
"aws-sdk": "^2.135.0", "aws-sdk": "^2.135.0",
"babel-core": "^6.24.1", "babel-core": "^6.24.1",
"babel-eslint": "^7.2.3", "babel-eslint": "^7.2.3",
@ -163,9 +162,10 @@
"sequelize-encrypted": "0.1.0", "sequelize-encrypted": "0.1.0",
"slate": "^0.29.0", "slate": "^0.29.0",
"slate-collapse-on-escape": "^0.6.0", "slate-collapse-on-escape": "^0.6.0",
"slate-drop-or-paste-images": "^0.8.0",
"slate-edit-code": "^0.13.2", "slate-edit-code": "^0.13.2",
"slate-edit-list": "^0.10.1", "slate-edit-list": "^0.10.1",
"slate-md-serializer": "1.0.1", "slate-md-serializer": "^1.0.4",
"slate-paste-linkify": "^0.5.0", "slate-paste-linkify": "^0.5.0",
"slate-plain-serializer": "^0.4.12", "slate-plain-serializer": "^0.4.12",
"slate-prism": "^0.4.0", "slate-prism": "^0.4.0",

View File

@ -2,18 +2,6 @@
# yarn lockfile v1 # yarn lockfile v1
"@tommoor/slate-drop-or-paste-images@0.5.1":
version "0.5.1"
resolved "https://registry.yarnpkg.com/@tommoor/slate-drop-or-paste-images/-/slate-drop-or-paste-images-0.5.1.tgz#67a8853bb59d3a449f2fe7c7071dc19fe3aff93d"
dependencies:
data-uri-to-blob "0.0.4"
es6-promise "^4.0.5"
image-to-data-uri "^1.0.0"
is-data-uri "^0.1.0"
is-image "^1.0.1"
is-url "^1.2.2"
mime-types "^2.1.11"
"@types/geojson@^1.0.0": "@types/geojson@^1.0.0":
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-1.0.3.tgz#fbcf7fa5eb6dd108d51385cc6987ec1f24214523" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-1.0.3.tgz#fbcf7fa5eb6dd108d51385cc6987ec1f24214523"
@ -2172,10 +2160,6 @@ data-uri-regex@^0.1.2:
version "0.1.4" version "0.1.4"
resolved "https://registry.yarnpkg.com/data-uri-regex/-/data-uri-regex-0.1.4.tgz#1e1db6c8397eca8a48ecdb55ad1b927ec0bbac2e" resolved "https://registry.yarnpkg.com/data-uri-regex/-/data-uri-regex-0.1.4.tgz#1e1db6c8397eca8a48ecdb55ad1b927ec0bbac2e"
data-uri-to-blob@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/data-uri-to-blob/-/data-uri-to-blob-0.0.4.tgz#087a7bff42f41a6cc0b2e2fb7312a7c29904fbaa"
date-fns@^1.27.2: date-fns@^1.27.2:
version "1.28.5" version "1.28.5"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.5.tgz#257cfc45d322df45ef5658665967ee841cd73faf" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.5.tgz#257cfc45d322df45ef5658665967ee841cd73faf"
@ -8217,10 +8201,22 @@ slate-collapse-on-escape@^0.6.0:
dependencies: dependencies:
to-pascal-case "^1.0.0" to-pascal-case "^1.0.0"
slate-dev-logger@^0.1.25, slate-dev-logger@^0.1.36: slate-dev-logger@^0.1.0, slate-dev-logger@^0.1.25, slate-dev-logger@^0.1.36:
version "0.1.36" version "0.1.36"
resolved "https://registry.npmjs.org/slate-dev-logger/-/slate-dev-logger-0.1.36.tgz#ecdb37dbf944dfc742bab23b6a20d5a0472db95e" resolved "https://registry.npmjs.org/slate-dev-logger/-/slate-dev-logger-0.1.36.tgz#ecdb37dbf944dfc742bab23b6a20d5a0472db95e"
slate-drop-or-paste-images@^0.8.0:
version "0.8.0"
resolved "https://registry.npmjs.org/slate-drop-or-paste-images/-/slate-drop-or-paste-images-0.8.0.tgz#2c363a117688c1b57517ab9cd468c4060e09824e"
dependencies:
es6-promise "^4.0.5"
image-to-data-uri "^1.0.0"
is-data-uri "^0.1.0"
is-image "^1.0.1"
is-url "^1.2.2"
mime-types "^2.1.11"
slate-dev-logger "^0.1.0"
slate-edit-code@^0.13.2: slate-edit-code@^0.13.2:
version "0.13.2" version "0.13.2"
resolved "https://registry.npmjs.org/slate-edit-code/-/slate-edit-code-0.13.2.tgz#682a7640da076906e5b4a4c73ec0e46d31d92c62" resolved "https://registry.npmjs.org/slate-edit-code/-/slate-edit-code-0.13.2.tgz#682a7640da076906e5b4a4c73ec0e46d31d92c62"
@ -8234,9 +8230,9 @@ slate-edit-list@^0.10.1:
version "0.10.1" version "0.10.1"
resolved "https://registry.npmjs.org/slate-edit-list/-/slate-edit-list-0.10.1.tgz#9c6a142a314b0ff22a327f1b50c8f5c85468cb17" resolved "https://registry.npmjs.org/slate-edit-list/-/slate-edit-list-0.10.1.tgz#9c6a142a314b0ff22a327f1b50c8f5c85468cb17"
slate-md-serializer@1.0.1: slate-md-serializer@^1.0.4:
version "1.0.1" version "1.0.4"
resolved "https://registry.npmjs.org/slate-md-serializer/-/slate-md-serializer-1.0.1.tgz#10fb8118bf0b97addaf9d7fd77c1b19f3d767309" resolved "https://registry.npmjs.org/slate-md-serializer/-/slate-md-serializer-1.0.4.tgz#519b819b436706a31d93a8e787657694c0c75d35"
slate-paste-linkify@^0.5.0: slate-paste-linkify@^0.5.0:
version "0.5.0" version "0.5.0"