Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 

162 Zeilen
4.6 KiB

  1. /**
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. *
  7. * @format
  8. * @flow strict-local
  9. * @emails oncall+draft_js
  10. *
  11. * This is unstable and not part of the public API and should not be used by
  12. * production systems. This file may be update/removed without notice.
  13. */
  14. import type { RawDraftContentBlock } from "./RawDraftContentBlock";
  15. import type { RawDraftContentState } from "./RawDraftContentState";
  16. const generateRandomKey = require("./generateRandomKey");
  17. const invariant = require("fbjs/lib/invariant");
  18. const traverseInDepthOrder = (blocks: Array<RawDraftContentBlock>, fn: (block: RawDraftContentBlock) => void) => {
  19. let stack = [...blocks].reverse();
  20. while (stack.length) {
  21. const block = stack.pop();
  22. fn(block);
  23. const children = block.children;
  24. invariant(Array.isArray(children), 'Invalid tree raw block');
  25. stack = stack.concat([...children.reverse()]);
  26. }
  27. };
  28. const isListBlock = (block?: RawDraftContentBlock): boolean => {
  29. if (!(block && block.type)) {
  30. return false;
  31. }
  32. const {
  33. type
  34. } = block;
  35. return type === 'unordered-list-item' || type === 'ordered-list-item';
  36. };
  37. const addDepthToChildren = (block: RawDraftContentBlock) => {
  38. if (Array.isArray(block.children)) {
  39. block.children = block.children.map(child => child.type === block.type ? { ...child,
  40. depth: (block.depth || 0) + 1
  41. } : child);
  42. }
  43. };
  44. /**
  45. * This adapter is intended to be be used as an adapter to draft tree data
  46. *
  47. * draft state <=====> draft tree state
  48. */
  49. const DraftTreeAdapter = {
  50. /**
  51. * Converts from a tree raw state back to draft raw state
  52. */
  53. fromRawTreeStateToRawState(draftTreeState: RawDraftContentState): RawDraftContentState {
  54. const {
  55. blocks
  56. } = draftTreeState;
  57. const transformedBlocks = [];
  58. invariant(Array.isArray(blocks), 'Invalid raw state');
  59. if (!Array.isArray(blocks) || !blocks.length) {
  60. return draftTreeState;
  61. }
  62. traverseInDepthOrder(blocks, block => {
  63. const newBlock = { ...block
  64. };
  65. if (isListBlock(block)) {
  66. newBlock.depth = newBlock.depth || 0;
  67. addDepthToChildren(block); // if it's a non-leaf node, we don't do anything else
  68. if (block.children != null && block.children.length > 0) {
  69. return;
  70. }
  71. }
  72. delete newBlock.children;
  73. transformedBlocks.push(newBlock);
  74. });
  75. draftTreeState.blocks = transformedBlocks;
  76. return { ...draftTreeState,
  77. blocks: transformedBlocks
  78. };
  79. },
  80. /**
  81. * Converts from draft raw state to tree draft state
  82. */
  83. fromRawStateToRawTreeState(draftState: RawDraftContentState): RawDraftContentState {
  84. const transformedBlocks = [];
  85. const parentStack = [];
  86. draftState.blocks.forEach(block => {
  87. const isList = isListBlock(block);
  88. const depth = block.depth || 0;
  89. const treeBlock = { ...block,
  90. children: []
  91. };
  92. if (!isList) {
  93. transformedBlocks.push(treeBlock);
  94. return;
  95. }
  96. let lastParent = parentStack[0]; // block is non-nested & there are no nested blocks, directly push block
  97. if (lastParent == null && depth === 0) {
  98. transformedBlocks.push(treeBlock); // block is first nested block or previous nested block is at a lower level
  99. } else if (lastParent == null || lastParent.depth < depth - 1) {
  100. // create new parent block
  101. const newParent = {
  102. key: generateRandomKey(),
  103. text: '',
  104. depth: depth - 1,
  105. type: block.type,
  106. children: [],
  107. entityRanges: [],
  108. inlineStyleRanges: []
  109. };
  110. parentStack.unshift(newParent);
  111. if (depth === 1) {
  112. // add as a root-level block
  113. transformedBlocks.push(newParent);
  114. } else if (lastParent != null) {
  115. // depth > 1 => also add as previous parent's child
  116. lastParent.children.push(newParent);
  117. }
  118. newParent.children.push(treeBlock);
  119. } else if (lastParent.depth === depth - 1) {
  120. // add as child of last parent
  121. lastParent.children.push(treeBlock);
  122. } else {
  123. // pop out parents at levels above this one from the parent stack
  124. while (lastParent != null && lastParent.depth >= depth) {
  125. parentStack.shift();
  126. lastParent = parentStack[0];
  127. }
  128. if (depth > 0) {
  129. lastParent.children.push(treeBlock);
  130. } else {
  131. transformedBlocks.push(treeBlock);
  132. }
  133. }
  134. });
  135. return { ...draftState,
  136. blocks: transformedBlocks
  137. };
  138. }
  139. };
  140. module.exports = DraftTreeAdapter;