Skip to content

Commit

Permalink
Fixed several bugs with getRangeTypes
Browse files Browse the repository at this point in the history
  • Loading branch information
Zaydek Michels-Gualtieri committed Jul 29, 2020
1 parent a1f716f commit 519a6de
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 88 deletions.
22 changes: 11 additions & 11 deletions src/Editor/useEditor/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import addOrRemoveTypesOnSelection from "./addOrRemoveTypesOnSelection"
import deleteOnSelection from "./deleteOnSelection"
import extendRangeLTR from "./extendRangeLTR"
import extendRangeRTL from "./extendRangeRTL"
import getIndexAtOffset from "./getIndexAtOffset"
import getIndex from "./getIndex"
import getRangeTypes from "./getRangeTypes"
import getShorthandVars from "./getShorthandVars"
import insertHardParagraphAtCollapsed from "./insertHardParagraphAtCollapsed"
Expand Down Expand Up @@ -47,17 +47,17 @@ export function select(e, { range }) {
// Clones the start text node or returns an empty text node.
function cloneStartTextNode(e) {
const { ch1 } = getShorthandVars(e)
let textNode = {
types: {},
props: {
children: "",
},
if (!ch1.length) {
const textNode = {
types: {},
props: {
children: "",
},
}
return textNode
}
const x = getIndexAtOffset(ch1, e.range.start.offset + testForSelection(e))
if (x >= 0) {
textNode = JSONClone(ch1[x])
}
return textNode
const x = getIndex(ch1, e.range.start.offset + testForSelection(e))
return JSONClone(ch1[x])
}

// Inserts text at the current range.
Expand Down
3 changes: 1 addition & 2 deletions src/Editor/useEditor/createIndexAtOffset.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import JSONClone from "lib/JSON/JSONClone"
import textContent from "./textContent"

// Non-idempotent function; creates an index for an offset.
// See getIndexAtOffset for idempotent version.
// TODO
function createIndexAtOffset(children, offset) {
// Eager returns:
if (!children.length) {
Expand Down
29 changes: 29 additions & 0 deletions src/Editor/useEditor/getIndex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import textContent from "./textContent"

// Creates a text node at a text offset and returns the node
// offset for the created text node.

// Converts a text offset to a node offset.
function getIndex(children, textOffset) {
if (!children.length) {
if (process.env.NODE_ENV !== "test") {
throw new Error("FIXME")
}
return -1
} else if (!textOffset) {
return 0
} else if (textOffset === textContent(children).length) {
return children.length - 1
}
let nodeOffset = 0
for (; nodeOffset < children.length; nodeOffset++) {
if (textOffset - children[nodeOffset].props.children.length <= 0) {
// No-op
break
}
textOffset -= children[nodeOffset].props.children.length
}
return nodeOffset
}

export default getIndex
25 changes: 25 additions & 0 deletions src/Editor/useEditor/getIndex.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import getIndex from "./getIndex"

const children = [
{ types: {}, props: { children: "Hello, " } },
{ types: { code: {} }, props: { children: "world" } },
{ types: {}, props: { children: "!" } },
]

test("getIndex(...)", () => {
expect(getIndex([], 0)).toBe(-1)
expect(getIndex(children, 0)).toBe(0)
expect(getIndex(children, 1)).toBe(0)
expect(getIndex(children, 2)).toBe(0)
expect(getIndex(children, 3)).toBe(0)
expect(getIndex(children, 4)).toBe(0)
expect(getIndex(children, 5)).toBe(0)
expect(getIndex(children, 6)).toBe(0)
expect(getIndex(children, 7)).toBe(0)
expect(getIndex(children, 8)).toBe(1)
expect(getIndex(children, 9)).toBe(1)
expect(getIndex(children, 10)).toBe(1)
expect(getIndex(children, 11)).toBe(1)
expect(getIndex(children, 12)).toBe(1)
expect(getIndex(children, 13)).toBe(2)
})
25 changes: 0 additions & 25 deletions src/Editor/useEditor/getIndexAtOffset.js

This file was deleted.

25 changes: 0 additions & 25 deletions src/Editor/useEditor/getIndexAtOffset.test.js

This file was deleted.

40 changes: 15 additions & 25 deletions src/Editor/useEditor/getRangeTypes.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,27 @@
import getIndexAtOffset from "./getIndexAtOffset" // TODO
import getIndex from "./getIndex" // TODO
import getShorthandVars from "./getShorthandVars"
import JSONClone from "lib/JSON/JSONClone"
import JSONEqual from "lib/JSON/JSONEqual"
import testForSelection from "./testForSelection"

function getNextIndexAtOffset(children, offset) {
if (!offset) {
return 0
}
return getIndexAtOffset(children, offset) + 1
}

// Gets text nodes from an array of elements.
function getTextNodes(elements, range) {
function aggregateOnSelection(elements, range) {
const ch = []
for (const each of elements) {
if (!each.props.children.length) {
const { key, props: { children } } = each

if (!children.length) {
// No-op
continue
}
let x1 = 0
if (each.key === range.start.key) {
x1 = getNextIndexAtOffset(each.props.children, range.start.offset)
if (key === range.start.key) {
x1 = getIndex(children, range.start.offset + 1)
}
let x2 = each.props.children.length
if (each.key === range.end.key) {
x2 = getNextIndexAtOffset(each.props.children, range.end.offset)
let x2 = children.length
if (key === range.end.key) {
x2 = getIndex(children, range.end.offset)
}
// if (x1 === x2) {
// x2++
// }
ch.push(...each.props.children.slice(x1, x2 + (x1 === x2)))
ch.push(...children.slice(x1, x2 + 1))
}
return ch
}
Expand All @@ -43,25 +34,24 @@ function getRangeTypes(e) {
if (!ch1.length) {
return {}
}
const x = getIndexAtOffset(ch1, e.range.start.offset)
const x = getIndex(ch1, e.range.start.offset)
return ch1[x].types
}

const ch = getTextNodes(e.elements.slice(x1, x2 + 1), e.range)
const ch = aggregateOnSelection(e.elements.slice(x1, x2 + 1), e.range)
if (!ch.length) {
return {}
}

const clonedTypes = JSONClone(ch[0].types)
const clonedTypesKeys = Object.keys(clonedTypes)
for (const textNode of ch.slice(1)) { // Step over clonedTypes

for (const textNode of ch.slice(1)) { // Steps over ch[0]
for (const key of clonedTypesKeys) {
if (!textNode.types[key] || !JSONEqual(textNode.types[key], clonedTypes[key])) {
delete clonedTypes[key]
}
}
}

return clonedTypes
}

Expand Down

0 comments on commit 519a6de

Please sign in to comment.