1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-31 02:49:56 +02:00

Add Prettier with ESLint integration (#1589)

* Add Prettier, with basic config and ESLint integration

* Apply Prettier to all files using `yarn lint --fix`

* Tell Prettier to ignore an empty text in a test output.

* Run Prettier on JS files not handled by ESLint, and lint them too
This commit is contained in:
Renaud Chaput
2018-02-06 23:12:00 +00:00
committed by Ian Storm Taylor
parent f28c59a26e
commit 3339d088e1
637 changed files with 4432 additions and 4281 deletions

View File

@@ -1,4 +1,3 @@
import { Value } from 'slate'
import { atob, btoa } from 'isomorphic-base64'
@@ -91,5 +90,5 @@ export default {
deserialize,
deserializeNode,
serialize,
serializeNode
serializeNode,
}

View File

@@ -6,11 +6,10 @@
* @type {Boolean}
*/
const IS_DEV = (
const IS_DEV =
typeof process !== 'undefined' &&
process.env &&
process.env.NODE_ENV !== 'production'
)
/**
* Has console?
@@ -18,12 +17,11 @@ const IS_DEV = (
* @type {Boolean}
*/
const HAS_CONSOLE = (
const HAS_CONSOLE =
typeof console != 'undefined' &&
typeof console.log == 'function' &&
typeof console.warn == 'function' &&
typeof console.error == 'function'
)
/**
* Log a `message` at `level`.
@@ -50,7 +48,6 @@ function log(level, message, ...args) {
* @param {Any} ...args
*/
function error(message, ...args) {
if (HAS_CONSOLE) {
console.error(message, ...args)

View File

@@ -13,23 +13,27 @@ const html = new Html({
switch (obj.object) {
case 'block': {
switch (obj.type) {
case 'paragraph': return React.createElement('p', {}, children)
case 'quote': return React.createElement('blockquote', {}, children)
case 'paragraph':
return React.createElement('p', {}, children)
case 'quote':
return React.createElement('blockquote', {}, children)
}
}
case 'mark': {
switch (obj.type) {
case 'bold': return React.createElement('strong', {}, children)
case 'italic': return React.createElement('em', {}, children)
case 'bold':
return React.createElement('strong', {}, children)
case 'italic':
return React.createElement('em', {}, children)
}
}
}
}
}
]
},
},
],
})
export default function (string) {
export default function(string) {
html.deserialize(string)
}
@@ -39,4 +43,6 @@ export const input = `
This is editable <strong>rich</strong> text, <em>much</em> better than a textarea!
</p>
</blockquote>
`.trim().repeat(10)
`
.trim()
.repeat(10)

View File

@@ -14,23 +14,27 @@ const html = new Html({
switch (obj.object) {
case 'block': {
switch (obj.type) {
case 'paragraph': return React.createElement('p', {}, children)
case 'quote': return React.createElement('blockquote', {}, children)
case 'paragraph':
return React.createElement('p', {}, children)
case 'quote':
return React.createElement('blockquote', {}, children)
}
}
case 'mark': {
switch (obj.type) {
case 'bold': return React.createElement('strong', {}, children)
case 'italic': return React.createElement('em', {}, children)
case 'bold':
return React.createElement('strong', {}, children)
case 'italic':
return React.createElement('em', {}, children)
}
}
}
}
}
]
},
},
],
})
export default function (state) {
export default function(state) {
html.serialize(state)
}
@@ -40,7 +44,8 @@ export const input = (
{Array.from(Array(10)).map(() => (
<quote>
<paragraph>
This is editable <b>rich</b> text, <i>much</i> better than a textarea!
This is editable <b>rich</b> text, <i>much</i> better than a
textarea!
</paragraph>
</quote>
))}

View File

@@ -9,9 +9,11 @@ import { __clear } from '../../slate/lib/utils/memoize'
*/
const categoryDir = resolve(__dirname)
const categories = fs.readdirSync(categoryDir).filter(c => c[0] != '.' && c != 'index.js')
const categories = fs
.readdirSync(categoryDir)
.filter(c => c[0] != '.' && c != 'index.js')
categories.forEach((category) => {
categories.forEach(category => {
suite(category, () => {
set('iterations', 50)
set('mintime', 1000)
@@ -23,9 +25,12 @@ categories.forEach((category) => {
}
const benchmarkDir = resolve(categoryDir, category)
const benchmarks = fs.readdirSync(benchmarkDir).filter(b => b[0] != '.' && !!~b.indexOf('.js')).map(b => basename(b, extname(b)))
const benchmarks = fs
.readdirSync(benchmarkDir)
.filter(b => b[0] != '.' && !!~b.indexOf('.js'))
.map(b => basename(b, extname(b)))
benchmarks.forEach((benchmark) => {
benchmarks.forEach(benchmark => {
const dir = resolve(benchmarkDir, benchmark)
const module = require(dir)
const fn = module.default

View File

@@ -1,4 +1,3 @@
import React from 'react'
import { renderToStaticMarkup } from 'react-dom/server'
import typeOf from 'type-of'
@@ -13,7 +12,7 @@ import { Record } from 'immutable'
const String = new Record({
object: 'string',
text: ''
text: '',
})
/**
@@ -24,15 +23,16 @@ const String = new Record({
*/
const TEXT_RULE = {
deserialize(el) {
if (el.tagName && el.tagName.toLowerCase() === 'br') {
return {
object: 'text',
leaves: [{
object: 'leaf',
text: '\n'
}]
leaves: [
{
object: 'leaf',
text: '\n',
},
],
}
}
@@ -41,26 +41,25 @@ const TEXT_RULE = {
return {
object: 'text',
leaves: [{
object: 'leaf',
text: el.nodeValue
}]
leaves: [
{
object: 'leaf',
text: el.nodeValue,
},
],
}
}
},
serialize(obj, children) {
if (obj.object === 'string') {
return children
.split('\n')
.reduce((array, text, i) => {
if (i != 0) array.push(<br />)
array.push(text)
return array
}, [])
return children.split('\n').reduce((array, text, i) => {
if (i != 0) array.push(<br />)
array.push(text)
return array
}, [])
}
}
},
}
/**
@@ -72,7 +71,9 @@ const TEXT_RULE = {
function defaultParseHtml(html) {
if (typeof DOMParser === 'undefined') {
throw new Error('The native `DOMParser` global which the `Html` serializer uses by default is not present in this environment. You must supply the `options.parseHtml` function instead.')
throw new Error(
'The native `DOMParser` global which the `Html` serializer uses by default is not present in this environment. You must supply the `options.parseHtml` function instead.'
)
}
const parsed = new DOMParser().parseFromString(html, 'text/html')
@@ -87,7 +88,6 @@ function defaultParseHtml(html) {
*/
class Html {
/**
* Create a new serializer with `rules`.
*
@@ -106,7 +106,7 @@ class Html {
defaultBlock = Node.createProperties(defaultBlock)
this.rules = [ ...rules, TEXT_RULE ]
this.rules = [...rules, TEXT_RULE]
this.defaultBlock = defaultBlock
this.parseHtml = parseHtml
}
@@ -154,24 +154,26 @@ class Html {
// TODO: pretty sure this is no longer needed.
if (nodes.length == 0) {
nodes = [{
object: 'block',
data: {},
isVoid: false,
...defaultBlock,
nodes: [
{
object: 'text',
leaves: [
{
object: 'leaf',
text: '',
marks: [],
}
]
}
],
}]
nodes = [
{
object: 'block',
data: {},
isVoid: false,
...defaultBlock,
nodes: [
{
object: 'text',
leaves: [
{
object: 'leaf',
text: '',
marks: [],
},
],
},
],
},
]
}
const json = {
@@ -180,7 +182,7 @@ class Html {
object: 'document',
data: {},
nodes,
}
},
}
const ret = toJSON ? json : Value.fromJSON(json)
@@ -197,7 +199,7 @@ class Html {
deserializeElements = (elements = []) => {
let nodes = []
elements.filter(this.cruftNewline).forEach((element) => {
elements.filter(this.cruftNewline).forEach(element => {
const node = this.deserializeElement(element)
switch (typeOf(node)) {
case 'array':
@@ -219,14 +221,14 @@ class Html {
* @return {Any}
*/
deserializeElement = (element) => {
deserializeElement = element => {
let node
if (!element.tagName) {
element.tagName = ''
}
const next = (elements) => {
const next = elements => {
if (Object.prototype.toString.call(elements) == '[object NodeList]') {
elements = Array.from(elements)
}
@@ -240,7 +242,9 @@ class Html {
case 'undefined':
return
default:
throw new Error(`The \`next\` argument was called with invalid children: "${elements}".`)
throw new Error(
`The \`next\` argument was called with invalid children: "${elements}".`
)
}
}
@@ -249,8 +253,15 @@ class Html {
const ret = rule.deserialize(element, next)
const type = typeOf(ret)
if (type != 'array' && type != 'object' && type != 'null' && type != 'undefined') {
throw new Error(`A rule returned an invalid deserialized representation: "${node}".`)
if (
type != 'array' &&
type != 'object' &&
type != 'null' &&
type != 'undefined'
) {
throw new Error(
`A rule returned an invalid deserialized representation: "${node}".`
)
}
if (ret === undefined) {
@@ -276,23 +287,19 @@ class Html {
* @return {Array}
*/
deserializeMark = (mark) => {
deserializeMark = mark => {
const { type, data } = mark
const applyMark = (node) => {
const applyMark = node => {
if (node.object == 'mark') {
return this.deserializeMark(node)
}
else if (node.object == 'text') {
node.leaves = node.leaves.map((leaf) => {
} else if (node.object == 'text') {
node.leaves = node.leaves.map(leaf => {
leaf.marks = leaf.marks || []
leaf.marks.push({ type, data })
return leaf
})
}
else {
} else {
node.nodes = node.nodes.map(applyMark)
}
@@ -333,7 +340,7 @@ class Html {
* @return {String}
*/
serializeNode = (node) => {
serializeNode = node => {
if (node.object === 'text') {
const leaves = node.getLeaves()
return leaves.map(this.serializeLeaf)
@@ -357,7 +364,7 @@ class Html {
* @return {String}
*/
serializeLeaf = (leaf) => {
serializeLeaf = leaf => {
const string = new String({ text: leaf.text })
const text = this.serializeString(string)
@@ -379,7 +386,7 @@ class Html {
* @return {String}
*/
serializeString = (string) => {
serializeString = string => {
for (const rule of this.rules) {
if (!rule.serialize) continue
const ret = rule.serialize(string, string.text)
@@ -394,10 +401,9 @@ class Html {
* @return {Boolean}
*/
cruftNewline = (element) => {
cruftNewline = element => {
return !(element.nodeName === '#text' && element.nodeValue == '\n')
}
}
/**

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -23,9 +22,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `
@@ -36,9 +35,7 @@ export const output = (
<value>
<document>
<quote>
<paragraph>
one
</paragraph>
<paragraph>one</paragraph>
</quote>
</document>
</value>

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -16,9 +15,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -17,9 +16,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `
@@ -29,9 +28,7 @@ export const input = `
export const output = (
<value>
<document>
<paragraph thing="value">
one
</paragraph>
<paragraph thing="value">one</paragraph>
</document>
</value>
)

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -16,9 +15,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -16,9 +15,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `
@@ -28,9 +27,7 @@ export const input = `
export const output = (
<value>
<document>
<paragraph>
one
</paragraph>
<paragraph>one</paragraph>
</document>
</value>
)

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -16,15 +15,15 @@ export const config = {
}
}
}
}
}
},
},
],
defaultBlock: {
type: 'default',
data: {
thing: 'value'
}
}
thing: 'value',
},
},
}
export const input = `
@@ -35,9 +34,7 @@ export const input = `
export const output = (
<value>
<document>
<paragraph>
one
</paragraph>
<paragraph>one</paragraph>
<block type="default" data={{ thing: 'value' }}>
two
</block>

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -16,9 +15,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `
@@ -29,9 +28,7 @@ export const input = `
export const output = (
<value>
<document>
<paragraph>
one
</paragraph>
<paragraph>one</paragraph>
</document>
</value>
)

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -30,9 +29,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `
@@ -44,9 +43,7 @@ export const output = (
<document>
<paragraph>
<link>
<hashtag>
one
</hashtag>
<hashtag>one</hashtag>
</link>
</paragraph>
</document>

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -23,9 +22,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -24,9 +23,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `
@@ -37,9 +36,7 @@ export const output = (
<value>
<document>
<paragraph>
<link thing="value">
one
</link>
<link thing="value">one</link>
</paragraph>
</document>
</value>

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -24,9 +23,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -23,9 +22,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `
@@ -36,9 +35,7 @@ export const output = (
<value>
<document>
<paragraph>
<link>
one
</link>
<link>one</link>
</paragraph>
</document>
</value>

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -30,9 +29,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -30,9 +29,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `
@@ -43,7 +42,9 @@ export const output = (
<value>
<document>
<paragraph>
o<i>n<b>e</b></i>
o<i>
n<b>e</b>
</i>
</paragraph>
</document>
</value>

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -24,9 +23,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -23,9 +22,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -11,7 +10,7 @@ export const config = {
object: 'block',
type: 'paragraph',
}
}
},
},
{
deserialize(el, next) {
@@ -19,9 +18,9 @@ export const config = {
object: 'block',
type: 'quote',
}
}
},
},
]
],
}
export const input = `

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -16,9 +15,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import h from '../helpers/h'
@@ -26,9 +25,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `

View File

@@ -1,4 +1,3 @@
export const config = {
rules: [
{
@@ -12,9 +11,9 @@ export const config = {
}
}
}
}
}
]
},
},
],
}
export const input = `
@@ -37,13 +36,13 @@ export const output = {
{
object: 'leaf',
text: 'one',
}
]
}
]
}
]
}
},
],
},
],
},
],
},
}
export const options = {

View File

@@ -1,4 +1,3 @@
import { createHyperscript } from 'slate-hyperscript'
/**
@@ -16,7 +15,7 @@ const h = createHyperscript({
image: {
type: 'image',
isVoid: true,
}
},
},
inlines: {
link: 'link',
@@ -25,7 +24,7 @@ const h = createHyperscript({
emoji: {
type: 'emoji',
isVoid: true,
}
},
},
marks: {
b: 'bold',

View File

@@ -1,4 +1,3 @@
/**
* Dependencies.
*/
@@ -25,7 +24,10 @@ beforeEach(() => {
describe('slate-html-serializer', () => {
describe('deserialize()', () => {
const dir = resolve(__dirname, './deserialize')
const tests = fs.readdirSync(dir).filter(t => t[0] != '.').map(t => basename(t, extname(t)))
const tests = fs
.readdirSync(dir)
.filter(t => t[0] != '.')
.map(t => basename(t, extname(t)))
for (const test of tests) {
it(test, async () => {
@@ -42,7 +44,10 @@ describe('slate-html-serializer', () => {
describe('serialize()', () => {
const dir = resolve(__dirname, './serialize')
const tests = fs.readdirSync(dir).filter(t => t[0] != '.').map(t => basename(t, extname(t)))
const tests = fs
.readdirSync(dir)
.filter(t => t[0] != '.')
.map(t => basename(t, extname(t)))
for (const test of tests) {
it(test, async () => {

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import React from 'react'
@@ -9,20 +8,20 @@ export const rules = [
serialize(obj, children) {
if (obj.object != 'block') return
switch (obj.type) {
case 'paragraph': return React.createElement('p', {}, children)
case 'quote': return React.createElement('blockquote', {}, children)
case 'paragraph':
return React.createElement('p', {}, children)
case 'quote':
return React.createElement('blockquote', {}, children)
}
}
}
},
},
]
export const input = (
<value>
<document>
<quote>
<paragraph>
one
</paragraph>
<paragraph>one</paragraph>
</quote>
</document>
</value>

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import React from 'react'
@@ -8,18 +7,20 @@ export const rules = [
{
serialize(obj, children) {
if (obj.object == 'block' && obj.type == 'paragraph') {
return React.createElement('p', { 'data-thing': obj.data.get('thing') }, children)
return React.createElement(
'p',
{ 'data-thing': obj.data.get('thing') },
children
)
}
}
}
},
},
]
export const input = (
<value>
<document>
<paragraph thing="value">
one
</paragraph>
<paragraph thing="value">one</paragraph>
</document>
</value>
)

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import React from 'react'
@@ -10,8 +9,8 @@ export const rules = [
if (obj.object == 'block' && obj.type == 'image') {
return React.createElement('img')
}
}
}
},
},
]
export const input = (

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import React from 'react'
@@ -14,8 +13,8 @@ export const rules = [
if (obj.object == 'mark' && obj.type == 'bold') {
return React.createElement('strong', {}, children)
}
}
}
},
},
]
export const input = (

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import React from 'react'
@@ -10,16 +9,14 @@ export const rules = [
if (obj.object == 'block' && obj.type == 'paragraph') {
return React.createElement('p', {}, children)
}
}
}
},
},
]
export const input = (
<value>
<document>
<paragraph>
one
</paragraph>
<paragraph>one</paragraph>
</document>
</value>
)

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import React from 'react'
@@ -18,8 +17,8 @@ export const rules = [
if (obj.object == 'inline' && obj.type == 'hashtag') {
return React.createElement('span', {}, children)
}
}
}
},
},
]
export const input = (
@@ -27,9 +26,7 @@ export const input = (
<document>
<paragraph>
<link>
<hashtag>
one
</hashtag>
<hashtag>one</hashtag>
</link>
</paragraph>
</document>

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import React from 'react'
@@ -12,19 +11,21 @@ export const rules = [
}
if (obj.object == 'inline' && obj.type == 'link') {
return React.createElement('a', { href: obj.data.get('href') }, children)
return React.createElement(
'a',
{ href: obj.data.get('href') },
children
)
}
}
}
},
},
]
export const input = (
<value>
<document>
<paragraph>
<link href="https://google.com">
one
</link>
<link href="https://google.com">one</link>
</paragraph>
</document>
</value>

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import React from 'react'
@@ -14,8 +13,8 @@ export const rules = [
if (obj.object == 'inline' && obj.type == 'emoji') {
return React.createElement('img')
}
}
}
},
},
]
export const input = (

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import React from 'react'
@@ -18,8 +17,8 @@ export const rules = [
if (obj.object == 'mark' && obj.type == 'bold') {
return React.createElement('strong', {}, children)
}
}
}
},
},
]
export const input = (

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import React from 'react'
@@ -14,17 +13,15 @@ export const rules = [
if (obj.object == 'inline' && obj.type == 'link') {
return React.createElement('a', {}, children)
}
}
}
},
},
]
export const input = (
<value>
<document>
<paragraph>
<link>
one
</link>
<link>one</link>
</paragraph>
</document>
</value>

View File

@@ -1,4 +1,3 @@
/** @jsx h */
import React from 'react'
@@ -7,23 +6,21 @@ import h from '../helpers/h'
export const rules = [
{},
{
serialize(obj, children) {}
serialize(obj, children) {},
},
{
serialize(obj, children) {
if (obj.object == 'block' && obj.type == 'paragraph') {
return React.createElement('p', {}, children)
}
}
}
},
},
]
export const input = (
<value>
<document>
<paragraph>
one
</paragraph>
<paragraph>one</paragraph>
</document>
</value>
)

View File

@@ -1,17 +1,7 @@
import isEmpty from 'is-empty'
import isPlainObject from 'is-plain-object'
import {
Block,
Document,
Inline,
Mark,
Node,
Range,
Text,
Value,
} from 'slate'
import { Block, Document, Inline, Mark, Node, Range, Text, Value } from 'slate'
/**
* Create selection point constants, for comparison by reference.
@@ -30,7 +20,6 @@ const FOCUS = {}
*/
const CREATORS = {
anchor(tagName, attributes, children) {
return ANCHOR
},
@@ -83,7 +72,7 @@ const CREATORS = {
// Search the document's texts to see if any of them have the anchor or
// focus information saved, so we can set the selection.
if (document) {
document.getTexts().forEach((text) => {
document.getTexts().forEach(text => {
if (text.__anchor != null) {
props.anchorKey = text.key
props.anchorOffset = text.__anchor
@@ -99,11 +88,15 @@ const CREATORS = {
}
if (props.anchorKey && !props.focusKey) {
throw new Error(`Slate hyperscript must have both \`<anchor/>\` and \`<focus/>\` defined if one is defined, but you only defined \`<anchor/>\`. For collapsed selections, use \`<cursor/>\`.`)
throw new Error(
`Slate hyperscript must have both \`<anchor/>\` and \`<focus/>\` defined if one is defined, but you only defined \`<anchor/>\`. For collapsed selections, use \`<cursor/>\`.`
)
}
if (!props.anchorKey && props.focusKey) {
throw new Error(`Slate hyperscript must have both \`<anchor/>\` and \`<focus/>\` defined if one is defined, but you only defined \`<focus/>\`. For collapsed selections, use \`<cursor/>\`.`)
throw new Error(
`Slate hyperscript must have both \`<anchor/>\` and \`<focus/>\` defined if one is defined, but you only defined \`<focus/>\`. For collapsed selections, use \`<cursor/>\`.`
)
}
if (!isEmpty(props)) {
@@ -118,7 +111,6 @@ const CREATORS = {
const nodes = createChildren(children, { key: attributes.key })
return nodes
},
}
/**
@@ -184,11 +176,12 @@ function createChildren(children, options = {}) {
node = next
}
children.forEach((child) => {
children.forEach(child => {
// If the child is a non-text node, push the current node and the new child
// onto the array, then creating a new node for future selection tracking.
if (Node.isNode(child) && !Text.isText(child)) {
if (node.text.length || node.__anchor != null || node.__focus != null) array.push(node)
if (node.text.length || node.__anchor != null || node.__focus != null)
array.push(node)
array.push(child)
node = Text.create()
length = 0
@@ -211,7 +204,7 @@ function createChildren(children, options = {}) {
setNode(node.set('key', child.key))
}
child.getLeaves().forEach((leaf) => {
child.getLeaves().forEach(leaf => {
let { marks } = leaf
if (options.marks) marks = marks.union(options.marks)
setNode(node.insertText(i, leaf.text, marks))
@@ -243,26 +236,22 @@ function createChildren(children, options = {}) {
*/
function resolveCreators(options) {
const {
blocks = {},
inlines = {},
marks = {},
} = options
const { blocks = {}, inlines = {}, marks = {} } = options
const creators = {
...CREATORS,
...(options.creators || {}),
}
Object.keys(blocks).map((key) => {
Object.keys(blocks).map(key => {
creators[key] = normalizeNode(key, blocks[key], 'block')
})
Object.keys(inlines).map((key) => {
Object.keys(inlines).map(key => {
creators[key] = normalizeNode(key, inlines[key], 'inline')
})
Object.keys(marks).map((key) => {
Object.keys(marks).map(key => {
creators[key] = normalizeMark(key, marks[key])
})
@@ -297,14 +286,16 @@ function normalizeNode(key, value, object) {
data: {
...(value.data || {}),
...rest,
}
},
}
return CREATORS[object](tagName, attrs, children)
}
}
throw new Error(`Slate hyperscript ${object} creators can be either functions, objects or strings, but you passed: ${value}`)
throw new Error(
`Slate hyperscript ${object} creators can be either functions, objects or strings, but you passed: ${value}`
)
}
/**
@@ -331,14 +322,16 @@ function normalizeMark(key, value) {
data: {
...(value.data || {}),
...attributes,
}
},
}
return CREATORS.mark(tagName, attrs, children)
}
}
throw new Error(`Slate hyperscript mark creators can be either functions, objects or strings, but you passed: ${value}`)
throw new Error(
`Slate hyperscript mark creators can be either functions, objects or strings, but you passed: ${value}`
)
}
/**

View File

@@ -9,9 +9,11 @@ import { __clear } from '../../slate/lib/utils/memoize'
*/
const categoryDir = resolve(__dirname)
const categories = fs.readdirSync(categoryDir).filter(c => c[0] != '.' && c != 'index.js')
const categories = fs
.readdirSync(categoryDir)
.filter(c => c[0] != '.' && c != 'index.js')
categories.forEach((category) => {
categories.forEach(category => {
suite(category, () => {
set('iterations', 50)
set('mintime', 1000)
@@ -23,9 +25,12 @@ categories.forEach((category) => {
}
const benchmarkDir = resolve(categoryDir, category)
const benchmarks = fs.readdirSync(benchmarkDir).filter(b => b[0] != '.' && !!~b.indexOf('.js')).map(b => basename(b, extname(b)))
const benchmarks = fs
.readdirSync(benchmarkDir)
.filter(b => b[0] != '.' && !!~b.indexOf('.js'))
.map(b => basename(b, extname(b)))
benchmarks.forEach((benchmark) => {
benchmarks.forEach(benchmark => {
const dir = resolve(benchmarkDir, benchmark)
const module = require(dir)
const fn = module.default

View File

@@ -3,10 +3,12 @@
import Plain from '../..'
export default function (string) {
export default function(string) {
Plain.deserialize(string)
}
export const input = `
This is editable plain text, just like a text area.
`.trim().repeat(10)
`
.trim()
.repeat(10)

View File

@@ -4,7 +4,7 @@
import Plain from '../..'
import h from '../../test/helpers/h'
export default function (state) {
export default function(state) {
Plain.serialize(state)
}
@@ -15,7 +15,8 @@ export const input = (
<quote>
<paragraph>
<paragraph>
This is editable <b>rich</b> text, <i>much</i> better than a textarea!
This is editable <b>rich</b> text, <i>much</i> better than a
textarea!
</paragraph>
</paragraph>
</quote>

View File

@@ -1,4 +1,3 @@
import { Block, Mark, Node, Value } from 'slate'
import { Set } from 'immutable'
@@ -14,11 +13,7 @@ import { Set } from 'immutable'
*/
function deserialize(string, options = {}) {
let {
defaultBlock = 'line',
defaultMarks = [],
toJSON = false,
} = options
let { defaultBlock = 'line', defaultMarks = [], toJSON = false } = options
if (Set.isSet(defaultMarks)) {
defaultMarks = defaultMarks.toArray()
@@ -32,7 +27,7 @@ function deserialize(string, options = {}) {
document: {
object: 'document',
data: {},
nodes: string.split('\n').map((line) => {
nodes: string.split('\n').map(line => {
return {
...defaultBlock,
object: 'block',
@@ -46,13 +41,13 @@ function deserialize(string, options = {}) {
object: 'leaf',
text: line,
marks: defaultMarks,
}
]
}
]
},
],
},
],
}
}),
}
},
}
const ret = toJSON ? json : Value.fromJSON(json)
@@ -79,7 +74,7 @@ function serialize(value) {
function serializeNode(node) {
if (
(node.object == 'document') ||
node.object == 'document' ||
(node.object == 'block' && Block.isBlockList(node.nodes))
) {
return node.nodes.map(serializeNode).join('\n')
@@ -96,5 +91,5 @@ function serializeNode(node) {
export default {
deserialize,
serialize
serialize,
}

View File

@@ -10,12 +10,8 @@ two
export const output = (
<value>
<document>
<line>
one
</line>
<line>
two
</line>
<line>one</line>
<line>two</line>
</document>
</value>
)

View File

@@ -9,9 +9,7 @@ one
export const output = (
<value>
<document>
<line>
one
</line>
<line>one</line>
</document>
</value>
)

View File

@@ -1,4 +1,3 @@
export const input = `
one
`.trim()
@@ -22,15 +21,15 @@ export const output = {
object: 'leaf',
text: 'one',
marks: [],
}
]
}
]
}
]
}
},
],
},
],
},
],
},
}
export const options = {
toJSON: true
toJSON: true,
}

View File

@@ -1,4 +1,3 @@
import { createHyperscript } from 'slate-hyperscript'
/**
@@ -16,7 +15,7 @@ const h = createHyperscript({
image: {
type: 'image',
isVoid: true,
}
},
},
inlines: {
link: 'link',
@@ -25,7 +24,7 @@ const h = createHyperscript({
emoji: {
type: 'emoji',
isVoid: true,
}
},
},
marks: {
b: 'bold',

View File

@@ -1,4 +1,3 @@
/**
* Dependencies.
*/
@@ -24,7 +23,10 @@ beforeEach(() => {
describe('slate-plain-serializer', () => {
describe('deserialize()', () => {
const dir = resolve(__dirname, './deserialize')
const tests = fs.readdirSync(dir).filter(t => t[0] != '.').map(t => basename(t, extname(t)))
const tests = fs
.readdirSync(dir)
.filter(t => t[0] != '.')
.map(t => basename(t, extname(t)))
for (const test of tests) {
it(test, async () => {
@@ -40,7 +42,10 @@ describe('slate-plain-serializer', () => {
describe('serialize()', () => {
const dir = resolve(__dirname, './serialize')
const tests = fs.readdirSync(dir).filter(t => t[0] != '.').map(t => basename(t, extname(t)))
const tests = fs
.readdirSync(dir)
.filter(t => t[0] != '.')
.map(t => basename(t, extname(t)))
for (const test of tests) {
it(test, async () => {

View File

@@ -5,13 +5,9 @@ import h from '../helpers/h'
export const input = (
<value>
<document>
<paragraph>
one
</paragraph>
<paragraph>one</paragraph>
<paragraph />
<paragraph>
three
</paragraph>
<paragraph>three</paragraph>
</document>
</value>
)

View File

@@ -5,15 +5,9 @@ import h from '../helpers/h'
export const input = (
<value>
<document>
<paragraph>
one
</paragraph>
<paragraph>
two
</paragraph>
<paragraph>
three
</paragraph>
<paragraph>one</paragraph>
<paragraph>two</paragraph>
<paragraph>three</paragraph>
</document>
</value>
)

View File

@@ -6,18 +6,12 @@ export const input = (
<value>
<document>
<quote>
<paragraph>
one
</paragraph>
<paragraph>
two
</paragraph>
<paragraph>one</paragraph>
<paragraph>two</paragraph>
</quote>
<quote>
<paragraph />
<paragraph>
four
</paragraph>
<paragraph>four</paragraph>
</quote>
</document>
</value>

View File

@@ -6,20 +6,12 @@ export const input = (
<value>
<document>
<quote>
<paragraph>
one
</paragraph>
<paragraph>
two
</paragraph>
<paragraph>one</paragraph>
<paragraph>two</paragraph>
</quote>
<quote>
<paragraph>
three
</paragraph>
<paragraph>
four
</paragraph>
<paragraph>three</paragraph>
<paragraph>four</paragraph>
</quote>
</document>
</value>

View File

@@ -7,20 +7,12 @@ export const input = (
<document>
<quote>
<quote>
<paragraph>
one
</paragraph>
<paragraph>
two
</paragraph>
<paragraph>one</paragraph>
<paragraph>two</paragraph>
</quote>
<quote>
<paragraph>
three
</paragraph>
<paragraph>
four
</paragraph>
<paragraph>three</paragraph>
<paragraph>four</paragraph>
</quote>
</quote>
</document>

View File

@@ -6,14 +6,10 @@ export const input = (
<value>
<document>
<quote>
<paragraph>
one
</paragraph>
<paragraph>one</paragraph>
<paragraph>
<link>
<hashtag>
two
</hashtag>
<hashtag>two</hashtag>
</link>
</paragraph>
</quote>

View File

@@ -7,14 +7,10 @@ export const input = (
<document>
<quote>
<paragraph>
<link>
one
</link>
<link>one</link>
</paragraph>
<paragraph>
<link>
two
</link>
<link>two</link>
</paragraph>
</quote>
</document>

View File

@@ -5,9 +5,7 @@ import h from '../helpers/h'
export const input = (
<value>
<document>
<paragraph thing="value">
one
</paragraph>
<paragraph thing="value">one</paragraph>
</document>
</value>
)

View File

@@ -5,9 +5,7 @@ import h from '../helpers/h'
export const input = (
<value>
<document>
<paragraph>
one
</paragraph>
<paragraph>one</paragraph>
</document>
</value>
)

View File

@@ -7,9 +7,7 @@ export const input = (
<document>
<paragraph>
<link>
<hashtag>
one
</hashtag>
<hashtag>one</hashtag>
</link>
</paragraph>
</document>

View File

@@ -6,9 +6,7 @@ export const input = (
<value>
<document>
<paragraph>
<link thing="value">
one
</link>
<link thing="value">one</link>
</paragraph>
</document>
</value>

View File

@@ -6,9 +6,7 @@ export const input = (
<value>
<document>
<paragraph>
<link>
one
</link>
<link>one</link>
</paragraph>
</document>
</value>

View File

@@ -1,4 +1,3 @@
import {
Block,
Change,
@@ -29,16 +28,21 @@ function create(name, validate) {
function check(isRequired, props, propName, componentName, location) {
const value = props[propName]
if (value == null && !isRequired) return null
if (value == null && isRequired) return new Error(`The ${location} \`${propName}\` is marked as required in \`${componentName}\`, but it was not supplied.`)
if (value == null && isRequired)
return new Error(
`The ${location} \`${propName}\` is marked as required in \`${componentName}\`, but it was not supplied.`
)
if (validate(value)) return null
return new Error(`Invalid ${location} \`${propName}\` supplied to \`${componentName}\`, expected a Slate \`${name}\` but received: ${value}`)
return new Error(
`Invalid ${location} \`${propName}\` supplied to \`${componentName}\`, expected a Slate \`${name}\` but received: ${value}`
)
}
function propType(...args) {
return check(false, ...args)
}
propType.isRequired = function (...args) {
propType.isRequired = function(...args) {
return check(true, ...args)
}

View File

@@ -8,17 +8,22 @@ import { basename, extname, resolve } from 'path'
*/
const categoryDir = resolve(__dirname)
const categories = fs.readdirSync(categoryDir).filter(c => c[0] != '.' && c != 'index.js')
const categories = fs
.readdirSync(categoryDir)
.filter(c => c[0] != '.' && c != 'index.js')
categories.forEach((category) => {
categories.forEach(category => {
suite(category, () => {
set('iterations', 50)
set('mintime', 1000)
const benchmarkDir = resolve(categoryDir, category)
const benchmarks = fs.readdirSync(benchmarkDir).filter(b => b[0] != '.' && !!~b.indexOf('.js')).map(b => basename(b, extname(b)))
const benchmarks = fs
.readdirSync(benchmarkDir)
.filter(b => b[0] != '.' && !!~b.indexOf('.js'))
.map(b => basename(b, extname(b)))
benchmarks.forEach((benchmark) => {
benchmarks.forEach(benchmark => {
const dir = resolve(benchmarkDir, benchmark)
const module = require(dir)
const fn = module.default

View File

@@ -6,7 +6,7 @@ import ReactDOM from 'react-dom/server'
import h from '../../test/helpers/h'
import { Editor } from '../..'
export default function (value) {
export default function(value) {
const el = React.createElement(Editor, { value })
ReactDOM.renderToStaticMarkup(el)
}
@@ -18,7 +18,8 @@ export const input = (
<quote>
<paragraph>
<paragraph>
This is editable <b>rich</b> text, <i>much</i> better than a textarea!
This is editable <b>rich</b> text, <i>much</i> better than a
textarea!
</paragraph>
</paragraph>
</quote>

View File

@@ -1,4 +1,3 @@
import Debug from 'debug'
import React from 'react'
import Types from 'prop-types'
@@ -15,7 +14,7 @@ import {
IS_FIREFOX,
IS_IOS,
IS_ANDROID,
SUPPORTED_EVENTS
SUPPORTED_EVENTS,
} from '../constants/environment'
/**
@@ -33,7 +32,6 @@ const debug = Debug('slate:content')
*/
class Content extends React.Component {
/**
* Property types.
*
@@ -77,8 +75,8 @@ class Content extends React.Component {
this.tmp.key = 0
this.tmp.isUpdatingSelection = false
EVENT_HANDLERS.forEach((handler) => {
this[handler] = (event) => {
EVENT_HANDLERS.forEach(handler => {
this[handler] = event => {
this.onEvent(handler, event)
}
})
@@ -96,7 +94,10 @@ class Content extends React.Component {
const { editor } = this.props
const window = getWindow(this.element)
window.document.addEventListener('selectionchange', this.onNativeSelectionChange)
window.document.addEventListener(
'selectionchange',
this.onNativeSelectionChange
)
// COMPAT: Restrict scope of `beforeinput` to mobile.
if ((IS_IOS || IS_ANDROID) && SUPPORTED_EVENTS.beforeinput) {
@@ -118,7 +119,10 @@ class Content extends React.Component {
const window = getWindow(this.element)
if (window) {
window.document.removeEventListener('selectionchange', this.onNativeSelectionChange)
window.document.removeEventListener(
'selectionchange',
this.onNativeSelectionChange
)
}
// COMPAT: Restrict scope of `beforeinput` to mobile.
@@ -169,16 +173,14 @@ class Content extends React.Component {
const range = findDOMRange(selection, window)
if (!range) {
logger.error('Unable to find a native DOM range from the current selection.', { selection })
logger.error(
'Unable to find a native DOM range from the current selection.',
{ selection }
)
return
}
const {
startContainer,
startOffset,
endContainer,
endOffset,
} = range
const { startContainer, startOffset, endContainer, endOffset } = range
// If the new range matches the current selection, there is nothing to fix.
// COMPAT: The native `Range` object always has it's "start" first and "end"
@@ -186,18 +188,14 @@ class Content extends React.Component {
// to check both orientations here. (2017/10/31)
if (current) {
if (
(
startContainer == current.startContainer &&
(startContainer == current.startContainer &&
startOffset == current.startOffset &&
endContainer == current.endContainer &&
endOffset == current.endOffset
) ||
(
startContainer == current.endContainer &&
endOffset == current.endOffset) ||
(startContainer == current.endContainer &&
startOffset == current.endOffset &&
endContainer == current.startContainer &&
endOffset == current.startOffset
)
endOffset == current.startOffset)
) {
return
}
@@ -251,7 +249,7 @@ class Content extends React.Component {
* @param {Element} element
*/
ref = (element) => {
ref = element => {
this.element = element
}
@@ -264,13 +262,13 @@ class Content extends React.Component {
* @return {Boolean}
*/
isInEditor = (target) => {
isInEditor = target => {
const { element } = this
// COMPAT: Text nodes don't have `isContentEditable` property. So, when
// `target` is a text node use its parent node for check.
const el = target.nodeType === 3 ? target.parentNode : target
return (
(el.isContentEditable) &&
el.isContentEditable &&
(el === element || el.closest('[data-slate-editor]') === element)
)
}
@@ -295,11 +293,7 @@ class Content extends React.Component {
// programmatically while updating selection.
if (
this.tmp.isUpdatingSelection &&
(
handler == 'onSelect' ||
handler == 'onBlur' ||
handler == 'onFocus'
)
(handler == 'onSelect' || handler == 'onBlur' || handler == 'onFocus')
) {
return
}
@@ -368,11 +362,11 @@ class Content extends React.Component {
* @param {InputEvent} event
*/
onNativeBeforeInput = (event) => {
onNativeBeforeInput = event => {
if (this.props.readOnly) return
if (!this.isInEditor(event.target)) return
const [ targetRange ] = event.getTargetRanges()
const [targetRange] = event.getTargetRanges()
if (!targetRange) return
const { editor } = this.props
@@ -391,7 +385,7 @@ class Content extends React.Component {
event.preventDefault()
const range = findRange(targetRange, editor.value)
editor.change((change) => {
editor.change(change => {
if (change.value.isInVoid) {
change.collapseToStartOfNextText()
} else {
@@ -407,9 +401,10 @@ class Content extends React.Component {
// `dataTransfer` should have the text for the `insertReplacementText`
// input type, but Safari uses `insertText` for spell check replacements
// and sets `data` to `null`.
const text = event.data == null
? event.dataTransfer.getData('text/plain')
: event.data
const text =
event.data == null
? event.dataTransfer.getData('text/plain')
: event.data
if (text == null) return
@@ -419,7 +414,7 @@ class Content extends React.Component {
const { selection } = value
const range = findRange(targetRange, value)
editor.change((change) => {
editor.change(change => {
change.insertTextAtRange(range, text, selection.marks)
// If the text was successfully inserted, and the selection had marks
@@ -443,7 +438,7 @@ class Content extends React.Component {
* @param {Event} event
*/
onNativeSelectionChange = throttle((event) => {
onNativeSelectionChange = throttle(event => {
if (this.props.readOnly) return
const window = getWindow(event.target)
@@ -526,7 +521,7 @@ class Content extends React.Component {
autoCorrect={props.autoCorrect ? 'on' : 'off'}
spellCheck={spellCheck}
style={style}
role={readOnly ? null : (role || 'textbox')}
role={readOnly ? null : role || 'textbox'}
tabIndex={tabIndex}
// COMPAT: The Grammarly Chrome extension works by changing the DOM out
// from under `contenteditable` elements, which leads to weird behaviors
@@ -567,14 +562,13 @@ class Content extends React.Component {
/>
)
}
}
/**
* Mix in handler prop types.
*/
EVENT_HANDLERS.forEach((handler) => {
EVENT_HANDLERS.forEach(handler => {
Content.propTypes[handler] = Types.func.isRequired
})

View File

@@ -1,4 +1,3 @@
import Debug from 'debug'
import Portal from 'react-portal'
import React from 'react'
@@ -28,7 +27,6 @@ const debug = Debug('slate:editor')
*/
class Editor extends React.Component {
/**
* Property types.
*
@@ -95,7 +93,7 @@ class Editor extends React.Component {
this.state.value = change.value
// Create a bound event handler for each event.
EVENT_HANDLERS.forEach((handler) => {
EVENT_HANDLERS.forEach(handler => {
this[handler] = (...args) => {
this.onEvent(handler, ...args)
}
@@ -109,7 +107,7 @@ class Editor extends React.Component {
* @param {Object} props
*/
componentWillReceiveProps = (props) => {
componentWillReceiveProps = props => {
let { schema, stack } = this
// Increment the updates counter as a baseline.
@@ -117,7 +115,10 @@ class Editor extends React.Component {
// If the plugins or the schema have changed, we need to re-resolve the
// plugins, since it will result in a new stack and new validations.
if (props.plugins != this.props.plugins || props.schema != this.props.schema) {
if (
props.plugins != this.props.plugins ||
props.schema != this.props.schema
) {
const plugins = this.resolvePlugins(props.plugins, props.schema)
stack = Stack.create({ plugins })
schema = Schema.create({ plugins })
@@ -129,7 +130,9 @@ class Editor extends React.Component {
// If we've resolved a few times already, and it's exactly in line with
// the updates, then warn the user that they may be doing something wrong.
if (this.tmp.resolves > 5 && this.tmp.resolves == this.tmp.updates) {
logger.warn('A Slate <Editor> is re-resolving `props.plugins` or `props.schema` on each update, which leads to poor performance. This is often due to passing in a new `schema` or `plugins` prop with each render by declaring them inline in your render function. Do not do this!')
logger.warn(
'A Slate <Editor> is re-resolving `props.plugins` or `props.schema` on each update, which leads to poor performance. This is often due to passing in a new `schema` or `plugins` prop with each render by declaring them inline in your render function. Do not do this!'
)
}
}
@@ -166,7 +169,7 @@ class Editor extends React.Component {
* @param {Change} change
*/
queueChange = (change) => {
queueChange = change => {
if (change.operations.size) {
debug('queueChange', { change })
this.tmp.change = change
@@ -239,7 +242,7 @@ class Editor extends React.Component {
*/
onEvent = (handler, event) => {
this.change((change) => {
this.change(change => {
this.stack.run(handler, event, change, this)
})
}
@@ -250,7 +253,7 @@ class Editor extends React.Component {
* @param {Change} change
*/
onChange = (change) => {
onChange = change => {
debug('onChange', { change })
this.stack.run('onChange', change, this)
@@ -271,7 +274,11 @@ class Editor extends React.Component {
const children = this.stack
.map('renderPortal', this.value, this)
.map((child, i) => <Portal key={i} isOpened>{child}</Portal>)
.map((child, i) => (
<Portal key={i} isOpened>
{child}
</Portal>
))
const props = { ...this.props, children }
const tree = this.stack.render('renderEditor', props, this)
@@ -296,7 +303,7 @@ class Editor extends React.Component {
const beforePlugin = BeforePlugin()
const afterPlugin = AfterPlugin()
const editorPlugin = {
schema: schema || {}
schema: schema || {},
}
for (const prop of PLUGINS_PROPS) {
@@ -313,17 +320,10 @@ class Editor extends React.Component {
}
}
return [
beforePlugin,
editorPlugin,
...(plugins || []),
afterPlugin
]
return [beforePlugin, editorPlugin, ...(plugins || []), afterPlugin]
}
}
/**
* Mix in the property types for the event handlers.
*/

View File

@@ -1,4 +1,3 @@
import Debug from 'debug'
import React from 'react'
import Types from 'prop-types'
@@ -21,7 +20,6 @@ const debug = Debug('slate:leaves')
*/
class Leaf extends React.Component {
/**
* Property types.
*
@@ -85,14 +83,10 @@ class Leaf extends React.Component {
const { node, index } = this.props
const offsetKey = OffsetKey.stringify({
key: node.key,
index
index,
})
return (
<span data-offset-key={offsetKey}>
{this.renderMarks()}
</span>
)
return <span data-offset-key={offsetKey}>{this.renderMarks()}</span>
}
/**
@@ -142,7 +136,6 @@ class Leaf extends React.Component {
// Otherwise, just return the text.
return text
}
}
/**

View File

@@ -1,4 +1,3 @@
import Debug from 'debug'
import ImmutableTypes from 'react-immutable-proptypes'
import React from 'react'
@@ -24,7 +23,6 @@ const debug = Debug('slate:node')
*/
class Node extends React.Component {
/**
* Property types.
*
@@ -62,10 +60,14 @@ class Node extends React.Component {
* @return {Boolean}
*/
shouldComponentUpdate = (nextProps) => {
shouldComponentUpdate = nextProps => {
const { props } = this
const { stack } = props.editor
const shouldUpdate = stack.find('shouldNodeComponentUpdate', props, nextProps)
const shouldUpdate = stack.find(
'shouldNodeComponentUpdate',
props,
nextProps
)
const n = nextProps
const p = props
@@ -78,7 +80,9 @@ class Node extends React.Component {
}
if (shouldUpdate === false) {
logger.warn('Returning false in `shouldNodeComponentUpdate` does not disable Slate\'s internal `shouldComponentUpdate` logic. If you want to prevent updates, use React\'s `shouldComponentUpdate` instead.')
logger.warn(
"Returning false in `shouldNodeComponentUpdate` does not disable Slate's internal `shouldComponentUpdate` logic. If you want to prevent updates, use React's `shouldComponentUpdate` instead."
)
}
}
@@ -148,15 +152,19 @@ class Node extends React.Component {
let placeholder = stack.find('renderPlaceholder', props)
if (placeholder) {
placeholder = React.cloneElement(placeholder, { key: `${node.key}-placeholder` })
placeholder = React.cloneElement(placeholder, {
key: `${node.key}-placeholder`,
})
children = [placeholder, ...children]
}
const element = stack.find('renderNode', { ...props, attributes, children })
const element = stack.find('renderNode', {
...props,
attributes,
children,
})
return node.isVoid
? <Void {...this.props}>{element}</Void>
: element
return node.isVoid ? <Void {...this.props}>{element}</Void> : element
}
/**
@@ -185,7 +193,6 @@ class Node extends React.Component {
/>
)
}
}
/**

View File

@@ -1,4 +1,3 @@
import Debug from 'debug'
import ImmutableTypes from 'react-immutable-proptypes'
import React from 'react'
@@ -22,7 +21,6 @@ const debug = Debug('slate:node')
*/
class Text extends React.Component {
/**
* Property types.
*
@@ -69,7 +67,7 @@ class Text extends React.Component {
* @return {Boolean}
*/
shouldComponentUpdate = (nextProps) => {
shouldComponentUpdate = nextProps => {
const { props } = this
const n = nextProps
const p = props
@@ -109,7 +107,7 @@ class Text extends React.Component {
const { document } = value
const { key } = node
const decs = decorations.filter((d) => {
const decs = decorations.filter(d => {
const { startKey, endKey } = d
if (startKey == key || endKey == key) return true
const startsBefore = document.areDescendantsSorted(startKey, key)
@@ -162,7 +160,6 @@ class Text extends React.Component {
/>
)
}
}
/**

View File

@@ -1,4 +1,3 @@
import Debug from 'debug'
import React from 'react'
import SlateTypes from 'slate-prop-types'
@@ -21,7 +20,6 @@ const debug = Debug('slate:void')
*/
class Void extends React.Component {
/**
* Property types.
*
@@ -78,11 +76,7 @@ class Void extends React.Component {
</Tag>
)
const content = (
<Tag draggable={readOnly ? null : true}>
{children}
</Tag>
)
const content = <Tag draggable={readOnly ? null : true}>{children}</Tag>
this.debug('render', { props })
@@ -110,7 +104,14 @@ class Void extends React.Component {
*/
renderText = () => {
const { block, decorations, isSelected, node, readOnly, editor } = this.props
const {
block,
decorations,
isSelected,
node,
readOnly,
editor,
} = this.props
const child = node.getFirstText()
return (
<Text
@@ -125,7 +126,6 @@ class Void extends React.Component {
/>
)
}
}
/**

View File

@@ -1,4 +1,3 @@
import browser from 'is-in-browser'
/**
@@ -26,9 +25,7 @@ const BROWSER_RULES = [
* @type {Array}
*/
const EVENT_RULES = [
['beforeinput', el => 'onbeforeinput' in el]
]
const EVENT_RULES = [['beforeinput', el => 'onbeforeinput' in el]]
/**
* Operating system matching rules.
@@ -59,14 +56,14 @@ let OS
if (browser) {
const { userAgent } = window.navigator
for (const [ name, regexp ] of BROWSER_RULES) {
for (const [name, regexp] of BROWSER_RULES) {
if (regexp.test(userAgent)) {
BROWSER = name
break
}
}
for (const [ name, regexp ] of OS_RULES) {
for (const [name, regexp] of OS_RULES) {
if (regexp.test(userAgent)) {
OS = name
break
@@ -76,7 +73,7 @@ if (browser) {
const testEl = window.document.createElement('div')
testEl.contentEditable = true
for (const [ name, testFn ] of EVENT_RULES) {
for (const [name, testFn] of EVENT_RULES) {
EVENTS[name] = testFn(testEl)
}
}

View File

@@ -1,4 +1,3 @@
/**
* Event handlers used by Slate plugins.
*

View File

@@ -1,4 +1,3 @@
import { isKeyHotkey } from 'is-hotkey'
import { IS_IOS, IS_MAC } from './environment'
@@ -33,8 +32,10 @@ const DELETE_FORWARD = e => DELETE(e) || SHIFT_DELETE(e)
const DELETE_CHAR_BACKWARD_MAC = isKeyHotkey('ctrl+h')
const DELETE_CHAR_FORWARD_MAC = isKeyHotkey('ctrl+d')
const DELETE_CHAR_BACKWARD = e => DELETE_BACKWARD(e) || (IS_APPLE && DELETE_CHAR_BACKWARD_MAC(e))
const DELETE_CHAR_FORWARD = e => DELETE_FORWARD(e) || (IS_APPLE && DELETE_CHAR_FORWARD_MAC(e))
const DELETE_CHAR_BACKWARD = e =>
DELETE_BACKWARD(e) || (IS_APPLE && DELETE_CHAR_BACKWARD_MAC(e))
const DELETE_CHAR_FORWARD = e =>
DELETE_FORWARD(e) || (IS_APPLE && DELETE_CHAR_FORWARD_MAC(e))
const DELETE_LINE_BACKWARD_MAC = isKeyHotkey('cmd+backspace')
const DELETE_LINE_FORWARD_MAC = isKeyHotkey('ctrl+k')
@@ -45,8 +46,10 @@ const DELETE_WORD_BACKWARD_MAC = isKeyHotkey('option+backspace')
const DELETE_WORD_BACKWARD_PC = isKeyHotkey('ctrl+backspace')
const DELETE_WORD_FORWARD_MAC = isKeyHotkey('option+delete')
const DELETE_WORD_FORWARD_PC = isKeyHotkey('ctrl+delete')
const DELETE_WORD_BACKWARD = e => IS_APPLE ? DELETE_WORD_BACKWARD_MAC(e) : DELETE_WORD_BACKWARD_PC(e)
const DELETE_WORD_FORWARD = e => IS_APPLE ? DELETE_WORD_FORWARD_MAC(e) : DELETE_WORD_FORWARD_PC(e)
const DELETE_WORD_BACKWARD = e =>
IS_APPLE ? DELETE_WORD_BACKWARD_MAC(e) : DELETE_WORD_BACKWARD_PC(e)
const DELETE_WORD_FORWARD = e =>
IS_APPLE ? DELETE_WORD_FORWARD_MAC(e) : DELETE_WORD_FORWARD_PC(e)
const RIGHT_ARROW = isKeyHotkey('right')
const LEFT_ARROW = isKeyHotkey('left')
@@ -69,12 +72,12 @@ const EXTEND_LINE_FORWARD = e => IS_APPLE && EXTEND_LINE_FORWARD_MAC(e)
const UNDO = isKeyHotkey('mod+z')
const REDO_MAC = isKeyHotkey('mod+shift+z')
const REDO_PC = isKeyHotkey('mod+y')
const REDO = e => IS_APPLE ? REDO_MAC(e) : REDO_PC(e)
const REDO = e => (IS_APPLE ? REDO_MAC(e) : REDO_PC(e))
const TRANSPOSE_CHARACTER_MAC = isKeyHotkey('ctrl+t')
const TRANSPOSE_CHARACTER = e => IS_APPLE && TRANSPOSE_CHARACTER_MAC(e)
const CONTENTEDITABLE = e => (
const CONTENTEDITABLE = e =>
BOLD(e) ||
DELETE_CHAR_BACKWARD(e) ||
DELETE_CHAR_FORWARD(e) ||
@@ -87,16 +90,14 @@ const CONTENTEDITABLE = e => (
SPLIT_BLOCK(e) ||
TRANSPOSE_CHARACTER(e) ||
UNDO(e)
)
const COMPOSING = e => (
const COMPOSING = e =>
e.key == 'ArrowDown' ||
e.key == 'ArrowLeft' ||
e.key == 'ArrowRight' ||
e.key == 'ArrowUp' ||
e.key == 'Backspace' ||
e.key == 'Enter'
)
/**
* Export.

View File

@@ -1,4 +1,3 @@
import EVENT_HANDLERS from './event-handlers'
/**

View File

@@ -1,4 +1,3 @@
/**
* The transfer types that Slate recognizes.
*

View File

@@ -1,4 +1,3 @@
import Editor from './components/editor'
import cloneFragment from './utils/clone-fragment'
import findDOMNode from './utils/find-dom-node'

View File

@@ -1,4 +1,3 @@
import Base64 from 'slate-base64-serializer'
import Debug from 'debug'
import Plain from 'slate-plain-serializer'
@@ -225,9 +224,11 @@ function AfterPlugin() {
selection.endKey == target.endKey &&
selection.endOffset < target.endOffset
) {
target = target.move(selection.startKey == selection.endKey
? 0 - selection.endOffset + selection.startOffset
: 0 - selection.endOffset)
target = target.move(
selection.startKey == selection.endKey
? 0 - selection.endOffset + selection.startOffset
: 0 - selection.endOffset
)
}
if (isDraggingInternally) {
@@ -252,12 +253,10 @@ function AfterPlugin() {
if (n) change.collapseToStartOf(n)
}
text
.split('\n')
.forEach((line, i) => {
if (i > 0) change.splitBlock()
change.insertText(line)
})
text.split('\n').forEach((line, i) => {
if (i > 0) change.splitBlock()
change.insertText(line)
})
}
if (type == 'fragment') {
@@ -280,11 +279,13 @@ function AfterPlugin() {
const el = findDOMNode(focusNode, window)
if (!el) return
el.dispatchEvent(new MouseEvent('mouseup', {
view: window,
bubbles: true,
cancelable: true
}))
el.dispatchEvent(
new MouseEvent('mouseup', {
view: window,
bubbles: true,
cancelable: true,
})
)
}
/**
@@ -316,11 +317,12 @@ function AfterPlugin() {
let start = 0
let end = 0
const leaf = leaves.find((r) => {
start = end
end += r.text.length
if (end >= point.offset) return true
}) || lastLeaf
const leaf =
leaves.find(r => {
start = end
end += r.text.length
if (end >= point.offset) return true
}) || lastLeaf
// Get the text information.
const { text } = leaf
@@ -342,12 +344,12 @@ function AfterPlugin() {
// Determine what the selection should be after changing the text.
const delta = textContent.length - text.length
const corrected = selection.collapseToEnd().move(delta)
const entire = selection.moveAnchorTo(point.key, start).moveFocusTo(point.key, end)
const entire = selection
.moveAnchorTo(point.key, start)
.moveFocusTo(point.key, end)
// Change the current value to have the leaf's text replaced.
change
.insertTextAtRange(entire, textContent, leaf.marks)
.select(corrected)
change.insertTextAtRange(entire, textContent, leaf.marks).select(corrected)
}
/**
@@ -432,7 +434,8 @@ function AfterPlugin() {
// browsers won't know what to do.
if (HOTKEYS.COLLAPSE_CHAR_BACKWARD(event)) {
const { document, isInVoid, previousText, startText } = value
const isPreviousInVoid = previousText && document.hasVoidParent(previousText.key)
const isPreviousInVoid =
previousText && document.hasVoidParent(previousText.key)
if (isInVoid || isPreviousInVoid || startText.text == '') {
event.preventDefault()
return change.collapseCharBackward()
@@ -450,7 +453,8 @@ function AfterPlugin() {
if (HOTKEYS.EXTEND_CHAR_BACKWARD(event)) {
const { document, isInVoid, previousText, startText } = value
const isPreviousInVoid = previousText && document.hasVoidParent(previousText.key)
const isPreviousInVoid =
previousText && document.hasVoidParent(previousText.key)
if (isInVoid || isPreviousInVoid || startText.text == '') {
event.preventDefault()
return change.extendCharBackward()
@@ -493,7 +497,8 @@ function AfterPlugin() {
const defaultBlock = startBlock
const defaultMarks = document.getInsertMarksAtRange(selection)
const frag = Plain.deserialize(text, { defaultBlock, defaultMarks }).document
const frag = Plain.deserialize(text, { defaultBlock, defaultMarks })
.document
change.insertFragment(frag)
}
}
@@ -621,7 +626,11 @@ function AfterPlugin() {
if (node.object != 'block' && node.object != 'inline') return
const Tag = node.object == 'block' ? 'div' : 'span'
const style = { position: 'relative' }
return <Tag {...attributes} style={style}>{children}</Tag>
return (
<Tag {...attributes} style={style}>
{children}
</Tag>
)
}
/**

View File

@@ -1,4 +1,3 @@
import Debug from 'debug'
import getWindow from 'get-window'
import { findDOMNode } from 'react-dom'
@@ -8,7 +7,7 @@ import {
IS_FIREFOX,
IS_IOS,
IS_ANDROID,
SUPPORTED_EVENTS
SUPPORTED_EVENTS,
} from '../constants/environment'
import findNode from '../utils/find-node'
@@ -117,9 +116,7 @@ function BeforePlugin() {
// happen on the initialization of the editor, or if the schema changes.
// This change isn't save into history since only schema is updated.
if (value.schema != editor.schema) {
change
.setValue({ schema: editor.schema }, { save: false })
.normalize()
change.setValue({ schema: editor.schema }, { save: false }).normalize()
}
debug('onChange')
@@ -183,7 +180,7 @@ function BeforePlugin() {
function onCopy(event, change, editor) {
const window = getWindow(event.target)
isCopying = true
window.requestAnimationFrame(() => isCopying = false)
window.requestAnimationFrame(() => (isCopying = false))
debug('onCopy', { event })
}
@@ -201,7 +198,7 @@ function BeforePlugin() {
const window = getWindow(event.target)
isCopying = true
window.requestAnimationFrame(() => isCopying = false)
window.requestAnimationFrame(() => (isCopying = false))
debug('onCut', { event })
}

View File

@@ -1,4 +1,3 @@
import Base64 from 'slate-base64-serializer'
import findDOMNode from './find-dom-node'
@@ -48,10 +47,10 @@ function cloneFragment(event, value, fragment = value.fragment) {
// check if there is marks involved. If so, set the range start just before the
// startText node
if ((IS_CHROME || IS_SAFARI) && !isVoid && startKey === endKey) {
const hasMarks = startText.characters
.slice(value.selection.anchorOffset, value.selection.focusOffset)
.filter(char => char.marks.size !== 0)
.size !== 0
const hasMarks =
startText.characters
.slice(value.selection.anchorOffset, value.selection.focusOffset)
.filter(char => char.marks.size !== 0).size !== 0
if (hasMarks) {
const r = range.cloneRange()
const node = findDOMNode(startText, window)
@@ -63,14 +62,18 @@ function cloneFragment(event, value, fragment = value.fragment) {
// Remove any zero-width space spans from the cloned DOM so that they don't
// show up elsewhere when pasted.
const zws = [].slice.call(contents.querySelectorAll('[data-slate-zero-width]'))
const zws = [].slice.call(
contents.querySelectorAll('[data-slate-zero-width]')
)
zws.forEach(zw => zw.parentNode.removeChild(zw))
// COMPAT: In Chrome and Safari, if the last element in the selection to
// copy has `contenteditable="false"` the copy will fail, and nothing will
// be put in the clipboard. So we remove them all. (2017/05/04)
if (IS_CHROME || IS_SAFARI) {
const els = [].slice.call(contents.querySelectorAll('[contenteditable="false"]'))
const els = [].slice.call(
contents.querySelectorAll('[contenteditable="false"]')
)
els.forEach(el => el.removeAttribute('contenteditable'))
}
@@ -104,7 +107,8 @@ function cloneFragment(event, value, fragment = value.fragment) {
div.style.border = '0px'
div.style.padding = '0px'
div.style.margin = '0px'
div.style.top = `${window.pageYOffset || window.document.documentElement.scrollTop}px`
div.style.top = `${window.pageYOffset ||
window.document.documentElement.scrollTop}px`
div.appendChild(contents)
editor.appendChild(div)

View File

@@ -1,4 +1,3 @@
/**
* Find the deepest descendant of a DOM `element`.
*
@@ -7,9 +6,7 @@
*/
function findDeepestNode(element) {
return element.firstChild
? findDeepestNode(element.firstChild)
: element
return element.firstChild ? findDeepestNode(element.firstChild) : element
}
/**

View File

@@ -1,4 +1,3 @@
import { Node } from 'slate'
/**
@@ -17,7 +16,9 @@ function findDOMNode(key, win = window) {
const el = win.document.querySelector(`[data-key="${key}"]`)
if (!el) {
throw new Error(`Unable to find a DOM node for "${key}". This is often because of forgetting to add \`props.attributes\` to a custom component.`)
throw new Error(
`Unable to find a DOM node for "${key}". This is often because of forgetting to add \`props.attributes\` to a custom component.`
)
}
return el

View File

@@ -1,4 +1,3 @@
import findDOMNode from './find-dom-node'
/**
@@ -24,7 +23,7 @@ function findDOMPoint(key, offset, win = window) {
false
)
while (n = iterator.nextNode()) {
while ((n = iterator.nextNode())) {
const { length } = n.textContent
const end = start + length

View File

@@ -1,4 +1,3 @@
import findDOMPoint from './find-dom-point'
/**
@@ -10,7 +9,14 @@ import findDOMPoint from './find-dom-point'
*/
function findDOMRange(range, win = window) {
const { anchorKey, anchorOffset, focusKey, focusOffset, isBackward, isCollapsed } = range
const {
anchorKey,
anchorOffset,
focusKey,
focusOffset,
isBackward,
isCollapsed,
} = range
const anchor = findDOMPoint(anchorKey, anchorOffset, win)
const focus = isCollapsed ? anchor : findDOMPoint(focusKey, focusOffset, win)
if (!anchor || !focus) return null

View File

@@ -1,4 +1,3 @@
/**
* Find a Slate node from a DOM `element`.
*

View File

@@ -1,4 +1,3 @@
import getWindow from 'get-window'
import OffsetKey from './offset-key'
@@ -24,10 +23,10 @@ const VOID_SELECTOR = '[data-slate-void]'
*/
function findPoint(nativeNode, nativeOffset, value) {
const {
node: nearestNode,
offset: nearestOffset,
} = normalizeNodeAndOffset(nativeNode, nativeOffset)
const { node: nearestNode, offset: nearestOffset } = normalizeNodeAndOffset(
nativeNode,
nativeOffset
)
const window = getWindow(nativeNode)
const { parentNode } = nearestNode
@@ -44,11 +43,9 @@ function findPoint(nativeNode, nativeOffset, value) {
range.setEnd(nearestNode, nearestOffset)
node = textNode
offset = range.toString().length
}
// For void nodes, the element with the offset key will be a cousin, not an
// ancestor, so find it by going down from the nearest void parent.
else {
} else {
// For void nodes, the element with the offset key will be a cousin, not an
// ancestor, so find it by going down from the nearest void parent.
const voidNode = parentNode.closest(VOID_SELECTOR)
if (!voidNode) return null
rangeNode = voidNode.querySelector(RANGE_SELECTOR)
@@ -138,7 +135,7 @@ function getEditableChild(parent, index, direction) {
// While the child is a comment node, or an element node with no children,
// keep iterating to find a sibling non-void, non-comment node.
while (
(child.nodeType == 8) ||
child.nodeType == 8 ||
(child.nodeType == 1 && child.childNodes.length == 0) ||
(child.nodeType == 1 && child.getAttribute('contenteditable') == 'false')
) {

View File

@@ -1,4 +1,3 @@
import getWindow from 'get-window'
import isBackward from 'selection-is-backward'
import { Range } from 'slate'
@@ -23,7 +22,10 @@ function findRange(native, value) {
// If the `native` object is a DOM `Range` or `StaticRange` object, change it
// into something that looks like a DOM `Selection` instead.
if (native instanceof window.Range || (window.StaticRange && native instanceof window.StaticRange)) {
if (
native instanceof window.Range ||
(window.StaticRange && native instanceof window.StaticRange)
) {
native = {
anchorNode: native.startContainer,
anchorOffset: native.startOffset,
@@ -32,7 +34,13 @@ function findRange(native, value) {
}
}
const { anchorNode, anchorOffset, focusNode, focusOffset, isCollapsed } = native
const {
anchorNode,
anchorOffset,
focusNode,
focusOffset,
isCollapsed,
} = native
const anchor = findPoint(anchorNode, anchorOffset, value)
const focus = isCollapsed ? anchor : findPoint(focusNode, focusOffset, value)
if (!anchor || !focus) return null

View File

@@ -1,4 +1,3 @@
import getWindow from 'get-window'
import { Range } from 'slate'
@@ -30,9 +29,10 @@ function getEventRange(event, value) {
// closest to.
if (node.isVoid) {
const rect = target.getBoundingClientRect()
const isPrevious = node.object == 'inline'
? x - rect.left < rect.left + rect.width - x
: y - rect.top < rect.top + rect.height - y
const isPrevious =
node.object == 'inline'
? x - rect.left < rect.left + rect.width - x
: y - rect.top < rect.top + rect.height - y
const text = node.getFirstText()
const range = Range.create()

View File

@@ -1,4 +1,3 @@
import Base64 from 'slate-base64-serializer'
import TRANSFER_TYPES from '../constants/transfer-types'
@@ -9,13 +8,7 @@ import TRANSFER_TYPES from '../constants/transfer-types'
* @type {String}
*/
const {
FRAGMENT,
HTML,
NODE,
RICH,
TEXT
} = TRANSFER_TYPES
const { FRAGMENT, HTML, NODE, RICH, TEXT } = TRANSFER_TYPES
/**
* Fragment matching regexp for HTML nodes.
@@ -47,13 +40,9 @@ function getEventTransfer(event) {
// If there isn't a fragment, but there is HTML, check to see if the HTML is
// actually an encoded fragment.
if (
!fragment &&
html &&
~html.indexOf(' data-slate-fragment="')
) {
if (!fragment && html && ~html.indexOf(' data-slate-fragment="')) {
const matches = FRAGMENT_MATCHER.exec(html)
const [ full, encoded ] = matches // eslint-disable-line no-unused-vars
const [full, encoded] = matches // eslint-disable-line no-unused-vars
if (encoded) fragment = encoded
}
@@ -77,7 +66,7 @@ function getEventTransfer(event) {
// Get and normalize files if they exist.
if (transfer.items && transfer.items.length) {
files = Array.from(transfer.items)
.map(item => item.kind == 'file' ? item.getAsFile() : null)
.map(item => (item.kind == 'file' ? item.getAsFile() : null))
.filter(exists => exists)
} else if (transfer.files && transfer.files.length) {
files = Array.from(transfer.files)

View File

@@ -1,4 +1,3 @@
import { findDOMNode } from 'react-dom'
/**

View File

@@ -1,4 +1,3 @@
/**
* Noop.
*

View File

@@ -1,4 +1,3 @@
/**
* Offset key parser regex.
*
@@ -21,10 +20,10 @@ function parse(string) {
throw new Error(`Invalid offset key string "${string}".`)
}
const [ original, key, index ] = matches // eslint-disable-line no-unused-vars
const [original, key, index] = matches // eslint-disable-line no-unused-vars
return {
key,
index: parseInt(index, 10)
index: parseInt(index, 10),
}
}
@@ -49,5 +48,5 @@ function stringify(object) {
export default {
parse,
stringify
stringify,
}

View File

@@ -1,4 +1,3 @@
import getWindow from 'get-window'
import isBackward from 'selection-is-backward'
import { IS_SAFARI, IS_IOS } from '../constants/environment'
@@ -9,11 +8,7 @@ import { IS_SAFARI, IS_IOS } from '../constants/environment'
* @type {Array}
*/
const OVERFLOWS = [
'auto',
'overlay',
'scroll',
]
const OVERFLOWS = ['auto', 'overlay', 'scroll']
/**
* Detect whether we are running IOS version 11
@@ -69,7 +64,9 @@ function scrollToSelection(selection) {
const window = getWindow(selection.anchorNode)
const scroller = findScrollContainer(selection.anchorNode, window)
const isWindow = scroller == window.document.body || scroller == window.document.documentElement
const isWindow =
scroller == window.document.body ||
scroller == window.document.documentElement
const backward = isBackward(selection)
const range = selection.getRangeAt(0).cloneRange()
@@ -136,8 +133,10 @@ function scrollToSelection(selection) {
height = offsetHeight
scrollerTop = scrollerRect.top + parseInt(borderTopWidth, 10)
scrollerLeft = scrollerRect.left + parseInt(borderLeftWidth, 10)
scrollerBordersY = parseInt(borderTopWidth, 10) + parseInt(borderBottomWidth, 10)
scrollerBordersX = parseInt(borderLeftWidth, 10) + parseInt(borderRightWidth, 10)
scrollerBordersY =
parseInt(borderTopWidth, 10) + parseInt(borderBottomWidth, 10)
scrollerBordersX =
parseInt(borderLeftWidth, 10) + parseInt(borderRightWidth, 10)
scrollerPaddingTop = parseInt(paddingTop, 10)
scrollerPaddingBottom = parseInt(paddingBottom, 10)
scrollerPaddingLeft = parseInt(paddingLeft, 10)
@@ -155,7 +154,10 @@ function scrollToSelection(selection) {
if (cursorLeft < xOffset) {
// selection to the left of viewport
x = cursorLeft - scrollerPaddingLeft
} else if (cursorLeft + cursorRect.width + scrollerBordersX > xOffset + width) {
} else if (
cursorLeft + cursorRect.width + scrollerBordersX >
xOffset + width
) {
// selection to the right of viewport
x = cursorLeft + scrollerBordersX + scrollerPaddingRight - width
}
@@ -163,12 +165,19 @@ function scrollToSelection(selection) {
if (cursorTop < yOffset) {
// selection above viewport
y = cursorTop - scrollerPaddingTop
} else if (cursorTop + cursorRect.height + scrollerBordersY > yOffset + height) {
} else if (
cursorTop + cursorRect.height + scrollerBordersY >
yOffset + height
) {
// selection below viewport
y = cursorTop + scrollerBordersY + scrollerPaddingBottom + cursorRect.height - height
y =
cursorTop +
scrollerBordersY +
scrollerPaddingBottom +
cursorRect.height -
height
}
if (isWindow) {
window.scrollTo(x, y)
} else {

View File

@@ -1,4 +1,3 @@
import TRANSFER_TYPES from '../constants/transfer-types'
/**
@@ -45,12 +44,12 @@ function setEventTransfer(event, type, content) {
try {
obj = JSON.parse(text.substring(prefix.length))
} catch (e) {
throw new Error('Failed to parse Slate data from `DataTransfer` object.')
throw new Error(
'Failed to parse Slate data from `DataTransfer` object.'
)
}
}
// Otherwise, it's just set it as is.
else {
} else {
// Otherwise, it's just set it as is.
obj[TEXT] = text
}

View File

@@ -1,16 +1,12 @@
import { JSDOM } from 'jsdom' // eslint-disable-line import/no-extraneous-dependencies
const UNWANTED_ATTRS = [
'data-key',
'data-offset-key'
]
const UNWANTED_ATTRS = ['data-key', 'data-offset-key']
const UNWANTED_TOP_LEVEL_ATTRS = [
'autocorrect',
'spellcheck',
'style',
'data-gramm'
'data-gramm',
]
/**

View File

@@ -1,4 +1,3 @@
import { createHyperscript } from 'slate-hyperscript'
/**
@@ -16,7 +15,7 @@ const h = createHyperscript({
image: {
type: 'image',
isVoid: true,
}
},
},
inlines: {
link: 'link',
@@ -25,7 +24,7 @@ const h = createHyperscript({
emoji: {
type: 'emoji',
isVoid: true,
}
},
},
marks: {
b: 'bold',

View File

@@ -1,4 +1,3 @@
/**
* Dependencies.
*/

View File

@@ -2,7 +2,7 @@
import h from '../../../helpers/h'
export default function (simulator) {
export default function(simulator) {
simulator.blur()
}

View File

@@ -2,7 +2,7 @@
import h from '../../../helpers/h'
export default function (simulator) {
export default function(simulator) {
simulator.keyDown({ key: 'Enter' })
}

View File

@@ -3,10 +3,13 @@
import h from '../../../helpers/h'
import { Range } from 'slate'
export default function (simulator) {
export default function(simulator) {
const { value } = simulator
const text = value.document.getTexts().first()
const selection = Range.create().collapseToStartOf(text).move(1).focus()
const selection = Range.create()
.collapseToStartOf(text)
.move(1)
.focus()
simulator.select(null, { selection })
}

Some files were not shown because too many files have changed in this diff Show More