mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-09-02 03:32:36 +02:00
move groupByMarks util into Text model as methods
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
import Leaf from './leaf'
|
import Leaf from './leaf'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import groupByMarks from '../utils/group-by-marks'
|
|
||||||
import { List } from 'immutable'
|
import { List } from 'immutable'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,8 +58,7 @@ class Text extends React.Component {
|
|||||||
|
|
||||||
renderLeaves() {
|
renderLeaves() {
|
||||||
const { node } = this.props
|
const { node } = this.props
|
||||||
const { characters, decorations } = node
|
const ranges = node.getDecoratedRanges()
|
||||||
const ranges = groupByMarks(decorations || characters)
|
|
||||||
|
|
||||||
return ranges.map((range, i, original) => {
|
return ranges.map((range, i, original) => {
|
||||||
const previous = original.slice(0, i)
|
const previous = original.slice(0, i)
|
||||||
|
@@ -1,10 +1,19 @@
|
|||||||
|
|
||||||
import Character from './character'
|
import Character from './character'
|
||||||
import Mark from './mark'
|
import Mark from './mark'
|
||||||
import groupByMarks from '../utils/group-by-marks'
|
|
||||||
import memoize from '../utils/memoize'
|
import memoize from '../utils/memoize'
|
||||||
import uid from '../utils/uid'
|
import uid from '../utils/uid'
|
||||||
import { List, Record } from 'immutable'
|
import { List, Record, Set } from 'immutable'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Range.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const Range = new Record({
|
||||||
|
kind: 'range',
|
||||||
|
marks: new Set(),
|
||||||
|
text: ''
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default properties.
|
* Default properties.
|
||||||
@@ -103,6 +112,16 @@ class Text extends new Record(DEFAULTS) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the decorated characters grouped by marks.
|
||||||
|
*
|
||||||
|
* @return {List}
|
||||||
|
*/
|
||||||
|
|
||||||
|
getDecoratedRanges() {
|
||||||
|
return this.getRangesForCharacters(this.decorations || this.characters)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the characters grouped by marks.
|
* Get the characters grouped by marks.
|
||||||
*
|
*
|
||||||
@@ -110,7 +129,53 @@ class Text extends new Record(DEFAULTS) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
getRanges() {
|
getRanges() {
|
||||||
return groupByMarks(this.decorations || this.characters)
|
return this.getRangesForCharacters(this.characters)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derive the ranges for a list of `characters`.
|
||||||
|
*
|
||||||
|
* @param {List} characters
|
||||||
|
* @return {List}
|
||||||
|
*/
|
||||||
|
|
||||||
|
getRangesForCharacters(characters) {
|
||||||
|
if (characters.size == 0) {
|
||||||
|
let ranges = new List()
|
||||||
|
ranges = ranges.push(new Range())
|
||||||
|
return ranges
|
||||||
|
}
|
||||||
|
|
||||||
|
return characters
|
||||||
|
.toList()
|
||||||
|
.reduce((ranges, char, i) => {
|
||||||
|
const { marks, text } = char
|
||||||
|
|
||||||
|
// The first one can always just be created.
|
||||||
|
if (i == 0) {
|
||||||
|
return ranges.push(new Range({ text, marks }))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, compare to the previous and see if a new range should be
|
||||||
|
// created, or whether the text should be added to the previous range.
|
||||||
|
const previous = characters.get(i - 1)
|
||||||
|
const prevMarks = previous.marks
|
||||||
|
const added = marks.filterNot(mark => prevMarks.includes(mark))
|
||||||
|
const removed = prevMarks.filterNot(mark => marks.includes(mark))
|
||||||
|
const isSame = !added.size && !removed.size
|
||||||
|
|
||||||
|
// If the marks are the same, add the text to the previous range.
|
||||||
|
if (isSame) {
|
||||||
|
const index = ranges.size - 1
|
||||||
|
let prevRange = ranges.get(index)
|
||||||
|
let prevText = prevRange.get('text')
|
||||||
|
prevRange = prevRange.set('text', prevText += text)
|
||||||
|
return ranges.set(index, prevRange)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, create a new range.
|
||||||
|
return ranges.push(new Range({ text, marks }))
|
||||||
|
}, new List())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,7 +234,9 @@ class Text extends new Record(DEFAULTS) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
memoize(Text.prototype, [
|
memoize(Text.prototype, [
|
||||||
'getRanges'
|
'getDecoratedRanges',
|
||||||
|
'getRanges',
|
||||||
|
'getRangesForCharacters'
|
||||||
])
|
])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -9,7 +9,6 @@ import ReactDOM from 'react-dom/server'
|
|||||||
import State from '../models/state'
|
import State from '../models/state'
|
||||||
import Text from '../models/text'
|
import Text from '../models/text'
|
||||||
import cheerio from 'cheerio'
|
import cheerio from 'cheerio'
|
||||||
import groupByMarks from '../utils/group-by-marks'
|
|
||||||
import { Record } from 'immutable'
|
import { Record } from 'immutable'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -235,7 +234,7 @@ class Html {
|
|||||||
|
|
||||||
serializeNode = (node) => {
|
serializeNode = (node) => {
|
||||||
if (node.kind == 'text') {
|
if (node.kind == 'text') {
|
||||||
const ranges = groupByMarks(node.characters)
|
const ranges = node.getRanges()
|
||||||
return ranges.map(this.serializeRange)
|
return ranges.map(this.serializeRange)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,7 +6,6 @@ import Inline from '../models/inline'
|
|||||||
import Mark from '../models/mark'
|
import Mark from '../models/mark'
|
||||||
import State from '../models/state'
|
import State from '../models/state'
|
||||||
import Text from '../models/text'
|
import Text from '../models/text'
|
||||||
import groupByMarks from '../utils/group-by-marks'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize a `state`.
|
* Serialize a `state`.
|
||||||
@@ -36,7 +35,7 @@ function serializeNode(node) {
|
|||||||
case 'text': {
|
case 'text': {
|
||||||
const obj = {}
|
const obj = {}
|
||||||
obj.kind = node.kind
|
obj.kind = node.kind
|
||||||
obj.ranges = serializeCharacters(node.characters)
|
obj.ranges = serializeRanges(node)
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
case 'block':
|
case 'block':
|
||||||
@@ -56,14 +55,15 @@ function serializeNode(node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize a list of `characters`.
|
* Serialize the ranges of a text `node`.
|
||||||
*
|
*
|
||||||
* @param {List} characters
|
* @param {Text} text
|
||||||
* @return {Array}
|
* @return {Array}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function serializeCharacters(characters) {
|
function serializeRanges(text) {
|
||||||
return groupByMarks(characters)
|
return text
|
||||||
|
.getRanges()
|
||||||
.toArray()
|
.toArray()
|
||||||
.map((range) => {
|
.map((range) => {
|
||||||
const obj = {}
|
const obj = {}
|
||||||
@@ -182,7 +182,7 @@ function deserializeMark(object) {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
serialize,
|
serialize,
|
||||||
serializeCharacters,
|
serializeRanges,
|
||||||
serializeMark,
|
serializeMark,
|
||||||
serializeNode,
|
serializeNode,
|
||||||
deserialize,
|
deserialize,
|
||||||
|
@@ -1,64 +0,0 @@
|
|||||||
|
|
||||||
import { List, Map, Record, Set } from 'immutable'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Range.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const Range = new Record({
|
|
||||||
kind: 'range',
|
|
||||||
marks: new Set(),
|
|
||||||
text: ''
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Group a list of `characters` into ranges by the marks they have.
|
|
||||||
*
|
|
||||||
* @param {List} characters
|
|
||||||
* @return {List} ranges
|
|
||||||
*/
|
|
||||||
|
|
||||||
function groupByMarks(characters) {
|
|
||||||
if (characters.size == 0) {
|
|
||||||
let ranges = new List()
|
|
||||||
ranges = ranges.push(new Range())
|
|
||||||
return ranges
|
|
||||||
}
|
|
||||||
|
|
||||||
return characters
|
|
||||||
.toList()
|
|
||||||
.reduce((ranges, char, i) => {
|
|
||||||
const { marks, text } = char
|
|
||||||
|
|
||||||
// The first one can always just be created.
|
|
||||||
if (i == 0) {
|
|
||||||
return ranges.push(new Range({ text, marks }))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, compare to the previous and see if a new range should be
|
|
||||||
// created, or whether the text should be added to the previous range.
|
|
||||||
const previous = characters.get(i - 1)
|
|
||||||
const prevMarks = previous.marks
|
|
||||||
const added = marks.filterNot(mark => prevMarks.includes(mark))
|
|
||||||
const removed = prevMarks.filterNot(mark => marks.includes(mark))
|
|
||||||
const isSame = !added.size && !removed.size
|
|
||||||
|
|
||||||
// If the marks are the same, add the text to the previous range.
|
|
||||||
if (isSame) {
|
|
||||||
const index = ranges.size - 1
|
|
||||||
let prevRange = ranges.get(index)
|
|
||||||
let prevText = prevRange.get('text')
|
|
||||||
prevRange = prevRange.set('text', prevText += text)
|
|
||||||
return ranges.set(index, prevRange)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, create a new range.
|
|
||||||
return ranges.push(new Range({ text, marks }))
|
|
||||||
}, new List())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default groupByMarks
|
|
@@ -23,7 +23,7 @@ const SELECTOR = `[${ATTRIBUTE}]`
|
|||||||
|
|
||||||
function findBounds(key, index, state) {
|
function findBounds(key, index, state) {
|
||||||
const text = state.document.assertDescendant(key)
|
const text = state.document.assertDescendant(key)
|
||||||
const ranges = text.getRanges()
|
const ranges = text.getDecoratedRanges()
|
||||||
const range = ranges.get(index)
|
const range = ranges.get(index)
|
||||||
const start = ranges
|
const start = ranges
|
||||||
.slice(0, index)
|
.slice(0, index)
|
||||||
|
Reference in New Issue
Block a user