UNPKG

4.61 kBJavaScriptView Raw
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 *
9 * @emails oncall+draft_js
10 */
11'use strict';
12
13function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
14
15function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
16
17function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
18
19var React = require("react");
20
21var UserAgent = require("fbjs/lib/UserAgent");
22
23var invariant = require("fbjs/lib/invariant");
24
25var isElement = require("./isElement"); // In IE, spans with <br> tags render as two newlines. By rendering a span
26// with only a newline character, we can be sure to render a single line.
27
28
29var useNewlineChar = UserAgent.isBrowser('IE <= 11');
30/**
31 * Check whether the node should be considered a newline.
32 */
33
34function isNewline(node) {
35 return useNewlineChar ? node.textContent === '\n' : node.tagName === 'BR';
36}
37/**
38 * Placeholder elements for empty text content.
39 *
40 * What is this `data-text` attribute, anyway? It turns out that we need to
41 * put an attribute on the lowest-level text node in order to preserve correct
42 * spellcheck handling. If the <span> is naked, Chrome and Safari may do
43 * bizarre things to do the DOM -- split text nodes, create extra spans, etc.
44 * If the <span> has an attribute, this appears not to happen.
45 * See http://jsfiddle.net/9khdavod/ for the failure case, and
46 * http://jsfiddle.net/7pg143f7/ for the fixed case.
47 */
48
49
50var NEWLINE_A = function NEWLINE_A(ref) {
51 return useNewlineChar ? React.createElement("span", {
52 key: "A",
53 "data-text": "true",
54 ref: ref
55 }, '\n') : React.createElement("br", {
56 key: "A",
57 "data-text": "true",
58 ref: ref
59 });
60};
61
62var NEWLINE_B = function NEWLINE_B(ref) {
63 return useNewlineChar ? React.createElement("span", {
64 key: "B",
65 "data-text": "true",
66 ref: ref
67 }, '\n') : React.createElement("br", {
68 key: "B",
69 "data-text": "true",
70 ref: ref
71 });
72};
73
74/**
75 * The lowest-level component in a `DraftEditor`, the text node component
76 * replaces the default React text node implementation. This allows us to
77 * perform custom handling of newline behavior and avoid re-rendering text
78 * nodes with DOM state that already matches the expectations of our immutable
79 * editor state.
80 */
81var DraftEditorTextNode = /*#__PURE__*/function (_React$Component) {
82 _inheritsLoose(DraftEditorTextNode, _React$Component);
83
84 function DraftEditorTextNode(props) {
85 var _this;
86
87 _this = _React$Component.call(this, props) || this; // By flipping this flag, we also keep flipping keys which forces
88 // React to remount this node every time it rerenders.
89
90 _defineProperty(_assertThisInitialized(_this), "_forceFlag", void 0);
91
92 _defineProperty(_assertThisInitialized(_this), "_node", void 0);
93
94 _this._forceFlag = false;
95 return _this;
96 }
97
98 var _proto = DraftEditorTextNode.prototype;
99
100 _proto.shouldComponentUpdate = function shouldComponentUpdate(nextProps) {
101 var node = this._node;
102 var shouldBeNewline = nextProps.children === '';
103 !isElement(node) ? process.env.NODE_ENV !== "production" ? invariant(false, 'node is not an Element') : invariant(false) : void 0;
104 var elementNode = node;
105
106 if (shouldBeNewline) {
107 return !isNewline(elementNode);
108 }
109
110 return elementNode.textContent !== nextProps.children;
111 };
112
113 _proto.componentDidMount = function componentDidMount() {
114 this._forceFlag = !this._forceFlag;
115 };
116
117 _proto.componentDidUpdate = function componentDidUpdate() {
118 this._forceFlag = !this._forceFlag;
119 };
120
121 _proto.render = function render() {
122 var _this2 = this;
123
124 if (this.props.children === '') {
125 return this._forceFlag ? NEWLINE_A(function (ref) {
126 return _this2._node = ref;
127 }) : NEWLINE_B(function (ref) {
128 return _this2._node = ref;
129 });
130 }
131
132 return React.createElement("span", {
133 key: this._forceFlag ? 'A' : 'B',
134 "data-text": "true",
135 ref: function ref(_ref) {
136 return _this2._node = _ref;
137 }
138 }, this.props.children);
139 };
140
141 return DraftEditorTextNode;
142}(React.Component);
143
144module.exports = DraftEditorTextNode;
\No newline at end of file