1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-09-02 11:42:53 +02:00

move groupByMarks util into Text model as methods

This commit is contained in:
Ian Storm Taylor
2016-07-22 12:12:23 -07:00
parent ac59e94a15
commit 950617cd6c
6 changed files with 81 additions and 81 deletions

View File

@@ -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)

View File

@@ -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'
]) ])
/** /**

View File

@@ -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)
} }

View File

@@ -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,

View File

@@ -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

View File

@@ -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)