/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format * @flow * @emails oncall+draft_js */ 'use strict'; import type { BlockNodeRecord } from "./BlockNodeRecord"; import type CharacterMetadata from "./CharacterMetadata"; import type ContentState from "./ContentState"; import type { DraftDecoratorType } from "./DraftDecoratorType"; const findRangesImmutable = require("./findRangesImmutable"); const getOwnObjectValues = require("./getOwnObjectValues"); const Immutable = require("immutable"); const { List, Repeat, Record } = Immutable; const returnTrue = function () { return true; }; const defaultLeafRange: { start: ?number, end: ?number, ... } = { start: null, end: null }; const LeafRange = (Record(defaultLeafRange): any); export type DecoratorRangeRawType = { start: ?number, end: ?number, decoratorKey: ?string, leaves: ?Array, ... }; type DecoratorRangeType = { start: ?number, end: ?number, decoratorKey: ?string, leaves: ?List, ... }; const defaultDecoratorRange: DecoratorRangeType = { start: null, end: null, decoratorKey: null, leaves: null }; const DecoratorRange = (Record(defaultDecoratorRange): any); const BlockTree = { /** * Generate a block tree for a given ContentBlock/decorator pair. */ generate(contentState: ContentState, block: BlockNodeRecord, decorator: ?DraftDecoratorType): List { const textLength = block.getLength(); if (!textLength) { return List.of(new DecoratorRange({ start: 0, end: 0, decoratorKey: null, leaves: List.of(new LeafRange({ start: 0, end: 0 })) })); } const leafSets = []; const decorations = decorator ? decorator.getDecorations(block, contentState) : List(Repeat(null, textLength)); const chars = block.getCharacterList(); findRangesImmutable(decorations, areEqual, returnTrue, (start, end) => { leafSets.push(new DecoratorRange({ start, end, decoratorKey: decorations.get(start), leaves: generateLeaves(chars.slice(start, end).toList(), start) })); }); return List(leafSets); }, fromJS({ leaves, ...other }: DecoratorRangeRawType): DecoratorRange { return new DecoratorRange({ ...other, leaves: leaves != null ? List(Array.isArray(leaves) ? leaves : getOwnObjectValues(leaves)).map(leaf => LeafRange(leaf)) : null }); } }; /** * Generate LeafRange records for a given character list. */ function generateLeaves(characters: List, offset: number): List { const leaves = []; const inlineStyles = characters.map(c => c.getStyle()).toList(); findRangesImmutable(inlineStyles, areEqual, returnTrue, (start, end) => { leaves.push(new LeafRange({ start: start + offset, end: end + offset })); }); return List(leaves); } function areEqual(a: any, b: any): boolean { return a === b; } module.exports = BlockTree;