1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-29 09:59:48 +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 React from 'react'
import groupByMarks from '../utils/group-by-marks'
import { List } from 'immutable'
/**
@@ -59,8 +58,7 @@ class Text extends React.Component {
renderLeaves() {
const { node } = this.props
const { characters, decorations } = node
const ranges = groupByMarks(decorations || characters)
const ranges = node.getDecoratedRanges()
return ranges.map((range, i, original) => {
const previous = original.slice(0, i)

View File

@@ -1,10 +1,19 @@
import Character from './character'
import Mark from './mark'
import groupByMarks from '../utils/group-by-marks'
import memoize from '../utils/memoize'
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.
@@ -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.
*
@@ -110,7 +129,53 @@ class Text extends new Record(DEFAULTS) {
*/
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, [
'getRanges'
'getDecoratedRanges',
'getRanges',
'getRangesForCharacters'
])
/**

View File

@@ -9,7 +9,6 @@ import ReactDOM from 'react-dom/server'
import State from '../models/state'
import Text from '../models/text'
import cheerio from 'cheerio'
import groupByMarks from '../utils/group-by-marks'
import { Record } from 'immutable'
/**
@@ -235,7 +234,7 @@ class Html {
serializeNode = (node) => {
if (node.kind == 'text') {
const ranges = groupByMarks(node.characters)
const ranges = node.getRanges()
return ranges.map(this.serializeRange)
}

View File

@@ -6,7 +6,6 @@ import Inline from '../models/inline'
import Mark from '../models/mark'
import State from '../models/state'
import Text from '../models/text'
import groupByMarks from '../utils/group-by-marks'
/**
* Serialize a `state`.
@@ -36,7 +35,7 @@ function serializeNode(node) {
case 'text': {
const obj = {}
obj.kind = node.kind
obj.ranges = serializeCharacters(node.characters)
obj.ranges = serializeRanges(node)
return obj
}
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}
*/
function serializeCharacters(characters) {
return groupByMarks(characters)
function serializeRanges(text) {
return text
.getRanges()
.toArray()
.map((range) => {
const obj = {}
@@ -182,7 +182,7 @@ function deserializeMark(object) {
export default {
serialize,
serializeCharacters,
serializeRanges,
serializeMark,
serializeNode,
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) {
const text = state.document.assertDescendant(key)
const ranges = text.getRanges()
const ranges = text.getDecoratedRanges()
const range = ranges.get(index)
const start = ranges
.slice(0, index)