@atlaskit/editor-ssr-renderer 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @atlaskit/editor-ssr-renderer
2
2
 
3
+ ## 1.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`cbf58f8500db4`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/cbf58f8500db4) -
8
+ [https://hello.jira.atlassian.cloud/browse/EDITOR-3893](EDITOR-3893) - fix mussing <br /> in empty
9
+ textblocks in the `EditorSSRRenderer`
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies
14
+
15
+ ## 1.4.0
16
+
17
+ ### Minor Changes
18
+
19
+ - [`e4f9d3c00a126`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/e4f9d3c00a126) -
20
+ [EDITOR-3919](https://hello.jira.atlassian.cloud/browse/EDITOR-3919) - use the real `getPos`
21
+ function as `nodeViweFactory` prop in `EditorSSRRenderer`
22
+
3
23
  ## 1.3.0
4
24
 
5
25
  ### Minor Changes
@@ -18,10 +18,9 @@ var _react = _interopRequireWildcard(require("react"));
18
18
  var _view = require("@atlaskit/editor-prosemirror/view");
19
19
  var _state = require("@atlaskit/editor-prosemirror/state");
20
20
  var _model = require("@atlaskit/editor-prosemirror/model");
21
- var _schemaDefault = require("@atlaskit/adf-schema/schema-default");
22
21
  var _eventDispatcher = require("@atlaskit/editor-common/event-dispatcher");
23
22
  var _providerFactory = require("@atlaskit/editor-common/provider-factory");
24
- var _excluded = ["preset", "buildDoc", "portalProviderAPI", "intl", "pluginInjectionAPI"];
23
+ var _excluded = ["plugins", "schema", "doc", "portalProviderAPI", "intl"];
25
24
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
26
25
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
27
26
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -71,22 +70,17 @@ var SSREventDispatcher = /*#__PURE__*/function (_EventDispatcher) {
71
70
  }]);
72
71
  }(_eventDispatcher.EventDispatcher);
73
72
  function EditorSSRRenderer(_ref) {
74
- var preset = _ref.preset,
75
- buildDoc = _ref.buildDoc,
73
+ var plugins = _ref.plugins,
74
+ schema = _ref.schema,
75
+ doc = _ref.doc,
76
76
  portalProviderAPI = _ref.portalProviderAPI,
77
77
  intl = _ref.intl,
78
- pluginInjectionAPI = _ref.pluginInjectionAPI,
79
78
  divProps = (0, _objectWithoutProperties2.default)(_ref, _excluded);
80
79
  // PMPluginFactoryParams use `getIntl` function to get current intl instance,
81
80
  // so we don't need to add `intl` as a dependency to `useMemo`.
82
81
  // We will store intl in ref and access to it dynamically in `getIntl` function call.
83
82
  var intlRef = (0, _react.useRef)(intl);
84
83
  intlRef.current = intl;
85
- var plugins = (0, _react.useMemo)(function () {
86
- return preset.build({
87
- pluginInjectionAPI: pluginInjectionAPI
88
- });
89
- }, [pluginInjectionAPI, preset]);
90
84
  var pmPlugins = (0, _react.useMemo)(function () {
91
85
  var eventDispatcher = new SSREventDispatcher();
92
86
  var providerFactory = new _providerFactory.ProviderFactory();
@@ -101,7 +95,7 @@ function EditorSSRRenderer(_ref) {
101
95
  nodeViewPortalProviderAPI: portalProviderAPI,
102
96
  portalProviderAPI: portalProviderAPI,
103
97
  providerFactory: providerFactory,
104
- schema: _schemaDefault.defaultSchema
98
+ schema: schema
105
99
  };
106
100
  return plugins.reduce(function (acc, editorPlugin) {
107
101
  var _editorPlugin$pmPlugi;
@@ -116,7 +110,7 @@ function EditorSSRRenderer(_ref) {
116
110
  });
117
111
  return acc;
118
112
  }, []);
119
- }, [plugins, portalProviderAPI]);
113
+ }, [plugins, portalProviderAPI, schema]);
120
114
  var nodeViews = (0, _react.useMemo)(function () {
121
115
  return pmPlugins.reduce(function (acc, plugin) {
122
116
  return Object.assign(acc, plugin.props.nodeViews);
@@ -130,73 +124,109 @@ function EditorSSRRenderer(_ref) {
130
124
  var editorView = (0, _react.useMemo)(function () {
131
125
  return new SSREditorView(null, {
132
126
  state: _state.EditorState.create({
133
- schema: _schemaDefault.defaultSchema,
127
+ doc: doc,
128
+ schema: schema,
134
129
  plugins: pmPlugins
135
130
  })
136
131
  });
137
- }, [pmPlugins]);
138
- var serializer = (0, _react.useMemo)(function () {
139
- var toDomNodeRenderers = Object.fromEntries(Object.entries(_schemaDefault.defaultSchema.nodes).map(function (_ref3) {
140
- var _ref4 = (0, _slicedToArray2.default)(_ref3, 2),
141
- nodeName = _ref4[0],
142
- nodeType = _ref4[1];
143
- return [nodeName, nodeType.spec.toDOM];
144
- }).filter(function (_ref5) {
145
- var _ref6 = (0, _slicedToArray2.default)(_ref5, 2),
146
- toDOM = _ref6[1];
147
- return !!toDOM;
148
- }));
149
- var toDomMarkRenderers = Object.fromEntries(Object.entries(_schemaDefault.defaultSchema.marks).map(function (_ref7) {
150
- var _ref8 = (0, _slicedToArray2.default)(_ref7, 2),
151
- markName = _ref8[0],
152
- markType = _ref8[1];
153
- return [markName, markType.spec.toDOM];
154
- }).filter(function (_ref9) {
155
- var _ref0 = (0, _slicedToArray2.default)(_ref9, 2),
156
- toDOM = _ref0[1];
157
- return !!toDOM;
158
- }));
159
- var nodeViewRenderers = Object.fromEntries(Object.entries(nodeViews).map(function (_ref1) {
160
- var _ref10 = (0, _slicedToArray2.default)(_ref1, 2),
161
- nodeName = _ref10[0],
162
- nodeViewFactory = _ref10[1];
163
- return [nodeName, function (node) {
164
- var nodeViewInstance = nodeViewFactory(node, editorView, function () {
165
- return 0;
166
- }, [], _view.DecorationSet.create(node, []));
167
- return {
168
- dom: nodeViewInstance.dom,
169
- contentDOM: nodeViewInstance.contentDOM
170
- };
171
- }];
172
- }));
173
- var markViewRenderers = Object.fromEntries(Object.entries(markViews).map(function (_ref11) {
174
- var _ref12 = (0, _slicedToArray2.default)(_ref11, 2),
175
- markName = _ref12[0],
176
- markViewFactory = _ref12[1];
177
- return [markName, function (mark) {
178
- var markViewInstance = markViewFactory(mark, editorView, false);
179
- return {
180
- dom: markViewInstance.dom,
181
- contentDOM: markViewInstance.contentDOM
182
- };
183
- }];
184
- }));
185
- return new _model.DOMSerializer(_objectSpread(_objectSpread(_objectSpread({}, toDomNodeRenderers), nodeViewRenderers), {}, {
186
- text: renderText
187
- }), _objectSpread(_objectSpread({}, toDomMarkRenderers), markViewRenderers));
188
- }, [editorView, markViews, nodeViews]);
132
+ }, [doc, pmPlugins, schema]);
133
+ var _useMemo = (0, _react.useMemo)(function () {
134
+ var nodePositions = new WeakMap();
135
+ var toDomNodeRenderers = Object.fromEntries(Object.entries(schema.nodes).map(function (_ref3) {
136
+ var _ref4 = (0, _slicedToArray2.default)(_ref3, 2),
137
+ nodeName = _ref4[0],
138
+ nodeType = _ref4[1];
139
+ return [nodeName, nodeType.spec.toDOM];
140
+ }).filter(function (_ref5) {
141
+ var _ref6 = (0, _slicedToArray2.default)(_ref5, 2),
142
+ toDOM = _ref6[1];
143
+ return !!toDOM;
144
+ }));
145
+ var toDomMarkRenderers = Object.fromEntries(Object.entries(schema.marks).map(function (_ref7) {
146
+ var _ref8 = (0, _slicedToArray2.default)(_ref7, 2),
147
+ markName = _ref8[0],
148
+ markType = _ref8[1];
149
+ return [markName, markType.spec.toDOM];
150
+ }).filter(function (_ref9) {
151
+ var _ref0 = (0, _slicedToArray2.default)(_ref9, 2),
152
+ toDOM = _ref0[1];
153
+ return !!toDOM;
154
+ }));
155
+ var nodeViewRenderers = Object.fromEntries(Object.entries(nodeViews).map(function (_ref1) {
156
+ var _ref10 = (0, _slicedToArray2.default)(_ref1, 2),
157
+ nodeName = _ref10[0],
158
+ nodeViewFactory = _ref10[1];
159
+ return [nodeName, function (node) {
160
+ var nodeViewInstance = nodeViewFactory(node, editorView, function () {
161
+ var _nodePositions$get;
162
+ return (_nodePositions$get = nodePositions.get(node)) !== null && _nodePositions$get !== void 0 ? _nodePositions$get : 0;
163
+ }, [], _view.DecorationSet.create(node, []));
164
+
165
+ // ProseMirror View adds <br class="ProseMirror-trailingBreak" /> to empty nodes. Because we are using
166
+ // DOMSerializer, we should simulate the same behaviour to get the same HTML document.
167
+ //
168
+ // There are a lot of conditions that check for adding `<br />` but we could implement only the case when we
169
+ // are adding `<br />` to empty texblock, because if we add `<br />` in other cases it will change order of DOM nodes inside
170
+ // this node (`<br />`) will be the first, after will be other nodes. It's because we are adding `<br />` to root node before
171
+ // we are rendering child node.
172
+ //
173
+ // See: https://discuss.prosemirror.net/t/where-can-i-read-about-prosemirror-trailingbreak/6665
174
+ // See: https://github.com/ProseMirror/prosemirror-view/blob/76c7c47f03730b18397b94bd269ece8a9cb7f486/src/viewdesc.ts#L803
175
+ // See: https://github.com/ProseMirror/prosemirror-view/blob/76c7c47f03730b18397b94bd269ece8a9cb7f486/src/viewdesc.ts#L1365
176
+ if (nodeViewInstance.contentDOM &&
177
+ // if (this.node.isTextblock) updater.addTextblockHacks()
178
+ node.isTextblock &&
179
+ // !lastChild || // Empty textblock
180
+ !node.lastChild
181
+ // NOT IMPLEMENTED CASE !(lastChild instanceof TextViewDesc) ||
182
+ // NOT IMPLEMENTED CASE /\n$/.test(lastChild.node.text!) ||
183
+ // NOT IMPLEMENTED CASE (this.view.requiresGeckoHackNode && /\s$/.test(lastChild.node.text!))
184
+ ) {
185
+ var br = document.createElement('br');
186
+ br.classList.add('ProseMirror-trailingBreak');
187
+ nodeViewInstance.contentDOM.appendChild(br);
188
+ }
189
+ return {
190
+ dom: nodeViewInstance.dom,
191
+ contentDOM: nodeViewInstance.contentDOM
192
+ };
193
+ }];
194
+ }));
195
+ var markViewRenderers = Object.fromEntries(Object.entries(markViews).map(function (_ref11) {
196
+ var _ref12 = (0, _slicedToArray2.default)(_ref11, 2),
197
+ markName = _ref12[0],
198
+ markViewFactory = _ref12[1];
199
+ return [markName, function (mark) {
200
+ var markViewInstance = markViewFactory(mark, editorView, false);
201
+ return {
202
+ dom: markViewInstance.dom,
203
+ contentDOM: markViewInstance.contentDOM
204
+ };
205
+ }];
206
+ }));
207
+ var serializer = new _model.DOMSerializer(_objectSpread(_objectSpread(_objectSpread({}, toDomNodeRenderers), nodeViewRenderers), {}, {
208
+ text: renderText
209
+ }), _objectSpread(_objectSpread({}, toDomMarkRenderers), markViewRenderers));
210
+ return {
211
+ serializer: serializer,
212
+ nodePositions: nodePositions
213
+ };
214
+ }, [editorView, markViews, nodeViews, schema.marks, schema.nodes]),
215
+ serializer = _useMemo.serializer,
216
+ nodePositions = _useMemo.nodePositions;
189
217
  var editorHTML = (0, _react.useMemo)(function () {
218
+ if (!doc) {
219
+ return undefined;
220
+ }
190
221
  try {
191
- var pmDoc = buildDoc(editorView.state.schema);
192
- if (!pmDoc) {
193
- return undefined;
194
- }
195
- return serializer.serializeFragment(pmDoc.content);
222
+ doc.descendants(function (node, pos) {
223
+ nodePositions.set(node, pos);
224
+ });
225
+ return serializer.serializeFragment(doc.content);
196
226
  } catch (_unused2) {
197
227
  return undefined;
198
228
  }
199
- }, [editorView.state.schema, buildDoc, serializer]);
229
+ }, [doc, serializer, nodePositions]);
200
230
  var containerRef = (0, _react.useRef)(null);
201
231
  (0, _react.useLayoutEffect)(function () {
202
232
  if (containerRef.current && editorHTML) {
@@ -2,7 +2,6 @@ import React, { useMemo, useRef, useLayoutEffect } from 'react';
2
2
  import { EditorView, DecorationSet } from '@atlaskit/editor-prosemirror/view';
3
3
  import { EditorState } from '@atlaskit/editor-prosemirror/state';
4
4
  import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
5
- import { defaultSchema } from '@atlaskit/adf-schema/schema-default';
6
5
  import { EventDispatcher, createDispatch } from '@atlaskit/editor-common/event-dispatcher';
7
6
  import { ProviderFactory } from '@atlaskit/editor-common/provider-factory';
8
7
 
@@ -29,11 +28,11 @@ class SSREventDispatcher extends EventDispatcher {
29
28
  }
30
29
  }
31
30
  export function EditorSSRRenderer({
32
- preset,
33
- buildDoc,
31
+ plugins,
32
+ schema,
33
+ doc,
34
34
  portalProviderAPI,
35
35
  intl,
36
- pluginInjectionAPI,
37
36
  ...divProps
38
37
  }) {
39
38
  // PMPluginFactoryParams use `getIntl` function to get current intl instance,
@@ -41,9 +40,6 @@ export function EditorSSRRenderer({
41
40
  // We will store intl in ref and access to it dynamically in `getIntl` function call.
42
41
  const intlRef = useRef(intl);
43
42
  intlRef.current = intl;
44
- const plugins = useMemo(() => preset.build({
45
- pluginInjectionAPI
46
- }), [pluginInjectionAPI, preset]);
47
43
  const pmPlugins = useMemo(() => {
48
44
  const eventDispatcher = new SSREventDispatcher();
49
45
  const providerFactory = new ProviderFactory();
@@ -56,7 +52,7 @@ export function EditorSSRRenderer({
56
52
  nodeViewPortalProviderAPI: portalProviderAPI,
57
53
  portalProviderAPI: portalProviderAPI,
58
54
  providerFactory,
59
- schema: defaultSchema
55
+ schema
60
56
  };
61
57
  return plugins.reduce((acc, editorPlugin) => {
62
58
  var _editorPlugin$pmPlugi;
@@ -72,7 +68,7 @@ export function EditorSSRRenderer({
72
68
  });
73
69
  return acc;
74
70
  }, []);
75
- }, [plugins, portalProviderAPI]);
71
+ }, [plugins, portalProviderAPI, schema]);
76
72
  const nodeViews = useMemo(() => {
77
73
  return pmPlugins.reduce((acc, plugin) => {
78
74
  return Object.assign(acc, plugin.props.nodeViews);
@@ -86,21 +82,54 @@ export function EditorSSRRenderer({
86
82
  const editorView = useMemo(() => {
87
83
  return new SSREditorView(null, {
88
84
  state: EditorState.create({
89
- schema: defaultSchema,
85
+ doc,
86
+ schema,
90
87
  plugins: pmPlugins
91
88
  })
92
89
  });
93
- }, [pmPlugins]);
94
- const serializer = useMemo(() => {
95
- const toDomNodeRenderers = Object.fromEntries(Object.entries(defaultSchema.nodes).map(([nodeName, nodeType]) => {
90
+ }, [doc, pmPlugins, schema]);
91
+ const {
92
+ serializer,
93
+ nodePositions
94
+ } = useMemo(() => {
95
+ const nodePositions = new WeakMap();
96
+ const toDomNodeRenderers = Object.fromEntries(Object.entries(schema.nodes).map(([nodeName, nodeType]) => {
96
97
  return [nodeName, nodeType.spec.toDOM];
97
98
  }).filter(([, toDOM]) => !!toDOM));
98
- const toDomMarkRenderers = Object.fromEntries(Object.entries(defaultSchema.marks).map(([markName, markType]) => {
99
+ const toDomMarkRenderers = Object.fromEntries(Object.entries(schema.marks).map(([markName, markType]) => {
99
100
  return [markName, markType.spec.toDOM];
100
101
  }).filter(([, toDOM]) => !!toDOM));
101
102
  const nodeViewRenderers = Object.fromEntries(Object.entries(nodeViews).map(([nodeName, nodeViewFactory]) => {
102
103
  return [nodeName, node => {
103
- const nodeViewInstance = nodeViewFactory(node, editorView, () => 0, [], DecorationSet.create(node, []));
104
+ const nodeViewInstance = nodeViewFactory(node, editorView, () => {
105
+ var _nodePositions$get;
106
+ return (_nodePositions$get = nodePositions.get(node)) !== null && _nodePositions$get !== void 0 ? _nodePositions$get : 0;
107
+ }, [], DecorationSet.create(node, []));
108
+
109
+ // ProseMirror View adds <br class="ProseMirror-trailingBreak" /> to empty nodes. Because we are using
110
+ // DOMSerializer, we should simulate the same behaviour to get the same HTML document.
111
+ //
112
+ // There are a lot of conditions that check for adding `<br />` but we could implement only the case when we
113
+ // are adding `<br />` to empty texblock, because if we add `<br />` in other cases it will change order of DOM nodes inside
114
+ // this node (`<br />`) will be the first, after will be other nodes. It's because we are adding `<br />` to root node before
115
+ // we are rendering child node.
116
+ //
117
+ // See: https://discuss.prosemirror.net/t/where-can-i-read-about-prosemirror-trailingbreak/6665
118
+ // See: https://github.com/ProseMirror/prosemirror-view/blob/76c7c47f03730b18397b94bd269ece8a9cb7f486/src/viewdesc.ts#L803
119
+ // See: https://github.com/ProseMirror/prosemirror-view/blob/76c7c47f03730b18397b94bd269ece8a9cb7f486/src/viewdesc.ts#L1365
120
+ if (nodeViewInstance.contentDOM &&
121
+ // if (this.node.isTextblock) updater.addTextblockHacks()
122
+ node.isTextblock &&
123
+ // !lastChild || // Empty textblock
124
+ !node.lastChild
125
+ // NOT IMPLEMENTED CASE !(lastChild instanceof TextViewDesc) ||
126
+ // NOT IMPLEMENTED CASE /\n$/.test(lastChild.node.text!) ||
127
+ // NOT IMPLEMENTED CASE (this.view.requiresGeckoHackNode && /\s$/.test(lastChild.node.text!))
128
+ ) {
129
+ const br = document.createElement('br');
130
+ br.classList.add('ProseMirror-trailingBreak');
131
+ nodeViewInstance.contentDOM.appendChild(br);
132
+ }
104
133
  return {
105
134
  dom: nodeViewInstance.dom,
106
135
  contentDOM: nodeViewInstance.contentDOM
@@ -116,7 +145,7 @@ export function EditorSSRRenderer({
116
145
  };
117
146
  }];
118
147
  }));
119
- return new DOMSerializer({
148
+ const serializer = new DOMSerializer({
120
149
  ...toDomNodeRenderers,
121
150
  ...nodeViewRenderers,
122
151
  text: renderText
@@ -124,18 +153,24 @@ export function EditorSSRRenderer({
124
153
  ...toDomMarkRenderers,
125
154
  ...markViewRenderers
126
155
  });
127
- }, [editorView, markViews, nodeViews]);
156
+ return {
157
+ serializer,
158
+ nodePositions
159
+ };
160
+ }, [editorView, markViews, nodeViews, schema.marks, schema.nodes]);
128
161
  const editorHTML = useMemo(() => {
162
+ if (!doc) {
163
+ return undefined;
164
+ }
129
165
  try {
130
- const pmDoc = buildDoc(editorView.state.schema);
131
- if (!pmDoc) {
132
- return undefined;
133
- }
134
- return serializer.serializeFragment(pmDoc.content);
166
+ doc.descendants((node, pos) => {
167
+ nodePositions.set(node, pos);
168
+ });
169
+ return serializer.serializeFragment(doc.content);
135
170
  } catch {
136
171
  return undefined;
137
172
  }
138
- }, [editorView.state.schema, buildDoc, serializer]);
173
+ }, [doc, serializer, nodePositions]);
139
174
  const containerRef = useRef(null);
140
175
  useLayoutEffect(() => {
141
176
  if (containerRef.current && editorHTML) {
@@ -6,7 +6,7 @@ import _createClass from "@babel/runtime/helpers/createClass";
6
6
  import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
7
7
  import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
8
8
  import _inherits from "@babel/runtime/helpers/inherits";
9
- var _excluded = ["preset", "buildDoc", "portalProviderAPI", "intl", "pluginInjectionAPI"];
9
+ var _excluded = ["plugins", "schema", "doc", "portalProviderAPI", "intl"];
10
10
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
11
11
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
12
12
  function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
@@ -15,7 +15,6 @@ import React, { useMemo, useRef, useLayoutEffect } from 'react';
15
15
  import { EditorView, DecorationSet } from '@atlaskit/editor-prosemirror/view';
16
16
  import { EditorState } from '@atlaskit/editor-prosemirror/state';
17
17
  import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
18
- import { defaultSchema } from '@atlaskit/adf-schema/schema-default';
19
18
  import { EventDispatcher, createDispatch } from '@atlaskit/editor-common/event-dispatcher';
20
19
  import { ProviderFactory } from '@atlaskit/editor-common/provider-factory';
21
20
 
@@ -63,22 +62,17 @@ var SSREventDispatcher = /*#__PURE__*/function (_EventDispatcher) {
63
62
  }]);
64
63
  }(EventDispatcher);
65
64
  export function EditorSSRRenderer(_ref) {
66
- var preset = _ref.preset,
67
- buildDoc = _ref.buildDoc,
65
+ var plugins = _ref.plugins,
66
+ schema = _ref.schema,
67
+ doc = _ref.doc,
68
68
  portalProviderAPI = _ref.portalProviderAPI,
69
69
  intl = _ref.intl,
70
- pluginInjectionAPI = _ref.pluginInjectionAPI,
71
70
  divProps = _objectWithoutProperties(_ref, _excluded);
72
71
  // PMPluginFactoryParams use `getIntl` function to get current intl instance,
73
72
  // so we don't need to add `intl` as a dependency to `useMemo`.
74
73
  // We will store intl in ref and access to it dynamically in `getIntl` function call.
75
74
  var intlRef = useRef(intl);
76
75
  intlRef.current = intl;
77
- var plugins = useMemo(function () {
78
- return preset.build({
79
- pluginInjectionAPI: pluginInjectionAPI
80
- });
81
- }, [pluginInjectionAPI, preset]);
82
76
  var pmPlugins = useMemo(function () {
83
77
  var eventDispatcher = new SSREventDispatcher();
84
78
  var providerFactory = new ProviderFactory();
@@ -93,7 +87,7 @@ export function EditorSSRRenderer(_ref) {
93
87
  nodeViewPortalProviderAPI: portalProviderAPI,
94
88
  portalProviderAPI: portalProviderAPI,
95
89
  providerFactory: providerFactory,
96
- schema: defaultSchema
90
+ schema: schema
97
91
  };
98
92
  return plugins.reduce(function (acc, editorPlugin) {
99
93
  var _editorPlugin$pmPlugi;
@@ -108,7 +102,7 @@ export function EditorSSRRenderer(_ref) {
108
102
  });
109
103
  return acc;
110
104
  }, []);
111
- }, [plugins, portalProviderAPI]);
105
+ }, [plugins, portalProviderAPI, schema]);
112
106
  var nodeViews = useMemo(function () {
113
107
  return pmPlugins.reduce(function (acc, plugin) {
114
108
  return Object.assign(acc, plugin.props.nodeViews);
@@ -122,73 +116,109 @@ export function EditorSSRRenderer(_ref) {
122
116
  var editorView = useMemo(function () {
123
117
  return new SSREditorView(null, {
124
118
  state: EditorState.create({
125
- schema: defaultSchema,
119
+ doc: doc,
120
+ schema: schema,
126
121
  plugins: pmPlugins
127
122
  })
128
123
  });
129
- }, [pmPlugins]);
130
- var serializer = useMemo(function () {
131
- var toDomNodeRenderers = Object.fromEntries(Object.entries(defaultSchema.nodes).map(function (_ref3) {
132
- var _ref4 = _slicedToArray(_ref3, 2),
133
- nodeName = _ref4[0],
134
- nodeType = _ref4[1];
135
- return [nodeName, nodeType.spec.toDOM];
136
- }).filter(function (_ref5) {
137
- var _ref6 = _slicedToArray(_ref5, 2),
138
- toDOM = _ref6[1];
139
- return !!toDOM;
140
- }));
141
- var toDomMarkRenderers = Object.fromEntries(Object.entries(defaultSchema.marks).map(function (_ref7) {
142
- var _ref8 = _slicedToArray(_ref7, 2),
143
- markName = _ref8[0],
144
- markType = _ref8[1];
145
- return [markName, markType.spec.toDOM];
146
- }).filter(function (_ref9) {
147
- var _ref0 = _slicedToArray(_ref9, 2),
148
- toDOM = _ref0[1];
149
- return !!toDOM;
150
- }));
151
- var nodeViewRenderers = Object.fromEntries(Object.entries(nodeViews).map(function (_ref1) {
152
- var _ref10 = _slicedToArray(_ref1, 2),
153
- nodeName = _ref10[0],
154
- nodeViewFactory = _ref10[1];
155
- return [nodeName, function (node) {
156
- var nodeViewInstance = nodeViewFactory(node, editorView, function () {
157
- return 0;
158
- }, [], DecorationSet.create(node, []));
159
- return {
160
- dom: nodeViewInstance.dom,
161
- contentDOM: nodeViewInstance.contentDOM
162
- };
163
- }];
164
- }));
165
- var markViewRenderers = Object.fromEntries(Object.entries(markViews).map(function (_ref11) {
166
- var _ref12 = _slicedToArray(_ref11, 2),
167
- markName = _ref12[0],
168
- markViewFactory = _ref12[1];
169
- return [markName, function (mark) {
170
- var markViewInstance = markViewFactory(mark, editorView, false);
171
- return {
172
- dom: markViewInstance.dom,
173
- contentDOM: markViewInstance.contentDOM
174
- };
175
- }];
176
- }));
177
- return new DOMSerializer(_objectSpread(_objectSpread(_objectSpread({}, toDomNodeRenderers), nodeViewRenderers), {}, {
178
- text: renderText
179
- }), _objectSpread(_objectSpread({}, toDomMarkRenderers), markViewRenderers));
180
- }, [editorView, markViews, nodeViews]);
124
+ }, [doc, pmPlugins, schema]);
125
+ var _useMemo = useMemo(function () {
126
+ var nodePositions = new WeakMap();
127
+ var toDomNodeRenderers = Object.fromEntries(Object.entries(schema.nodes).map(function (_ref3) {
128
+ var _ref4 = _slicedToArray(_ref3, 2),
129
+ nodeName = _ref4[0],
130
+ nodeType = _ref4[1];
131
+ return [nodeName, nodeType.spec.toDOM];
132
+ }).filter(function (_ref5) {
133
+ var _ref6 = _slicedToArray(_ref5, 2),
134
+ toDOM = _ref6[1];
135
+ return !!toDOM;
136
+ }));
137
+ var toDomMarkRenderers = Object.fromEntries(Object.entries(schema.marks).map(function (_ref7) {
138
+ var _ref8 = _slicedToArray(_ref7, 2),
139
+ markName = _ref8[0],
140
+ markType = _ref8[1];
141
+ return [markName, markType.spec.toDOM];
142
+ }).filter(function (_ref9) {
143
+ var _ref0 = _slicedToArray(_ref9, 2),
144
+ toDOM = _ref0[1];
145
+ return !!toDOM;
146
+ }));
147
+ var nodeViewRenderers = Object.fromEntries(Object.entries(nodeViews).map(function (_ref1) {
148
+ var _ref10 = _slicedToArray(_ref1, 2),
149
+ nodeName = _ref10[0],
150
+ nodeViewFactory = _ref10[1];
151
+ return [nodeName, function (node) {
152
+ var nodeViewInstance = nodeViewFactory(node, editorView, function () {
153
+ var _nodePositions$get;
154
+ return (_nodePositions$get = nodePositions.get(node)) !== null && _nodePositions$get !== void 0 ? _nodePositions$get : 0;
155
+ }, [], DecorationSet.create(node, []));
156
+
157
+ // ProseMirror View adds <br class="ProseMirror-trailingBreak" /> to empty nodes. Because we are using
158
+ // DOMSerializer, we should simulate the same behaviour to get the same HTML document.
159
+ //
160
+ // There are a lot of conditions that check for adding `<br />` but we could implement only the case when we
161
+ // are adding `<br />` to empty texblock, because if we add `<br />` in other cases it will change order of DOM nodes inside
162
+ // this node (`<br />`) will be the first, after will be other nodes. It's because we are adding `<br />` to root node before
163
+ // we are rendering child node.
164
+ //
165
+ // See: https://discuss.prosemirror.net/t/where-can-i-read-about-prosemirror-trailingbreak/6665
166
+ // See: https://github.com/ProseMirror/prosemirror-view/blob/76c7c47f03730b18397b94bd269ece8a9cb7f486/src/viewdesc.ts#L803
167
+ // See: https://github.com/ProseMirror/prosemirror-view/blob/76c7c47f03730b18397b94bd269ece8a9cb7f486/src/viewdesc.ts#L1365
168
+ if (nodeViewInstance.contentDOM &&
169
+ // if (this.node.isTextblock) updater.addTextblockHacks()
170
+ node.isTextblock &&
171
+ // !lastChild || // Empty textblock
172
+ !node.lastChild
173
+ // NOT IMPLEMENTED CASE !(lastChild instanceof TextViewDesc) ||
174
+ // NOT IMPLEMENTED CASE /\n$/.test(lastChild.node.text!) ||
175
+ // NOT IMPLEMENTED CASE (this.view.requiresGeckoHackNode && /\s$/.test(lastChild.node.text!))
176
+ ) {
177
+ var br = document.createElement('br');
178
+ br.classList.add('ProseMirror-trailingBreak');
179
+ nodeViewInstance.contentDOM.appendChild(br);
180
+ }
181
+ return {
182
+ dom: nodeViewInstance.dom,
183
+ contentDOM: nodeViewInstance.contentDOM
184
+ };
185
+ }];
186
+ }));
187
+ var markViewRenderers = Object.fromEntries(Object.entries(markViews).map(function (_ref11) {
188
+ var _ref12 = _slicedToArray(_ref11, 2),
189
+ markName = _ref12[0],
190
+ markViewFactory = _ref12[1];
191
+ return [markName, function (mark) {
192
+ var markViewInstance = markViewFactory(mark, editorView, false);
193
+ return {
194
+ dom: markViewInstance.dom,
195
+ contentDOM: markViewInstance.contentDOM
196
+ };
197
+ }];
198
+ }));
199
+ var serializer = new DOMSerializer(_objectSpread(_objectSpread(_objectSpread({}, toDomNodeRenderers), nodeViewRenderers), {}, {
200
+ text: renderText
201
+ }), _objectSpread(_objectSpread({}, toDomMarkRenderers), markViewRenderers));
202
+ return {
203
+ serializer: serializer,
204
+ nodePositions: nodePositions
205
+ };
206
+ }, [editorView, markViews, nodeViews, schema.marks, schema.nodes]),
207
+ serializer = _useMemo.serializer,
208
+ nodePositions = _useMemo.nodePositions;
181
209
  var editorHTML = useMemo(function () {
210
+ if (!doc) {
211
+ return undefined;
212
+ }
182
213
  try {
183
- var pmDoc = buildDoc(editorView.state.schema);
184
- if (!pmDoc) {
185
- return undefined;
186
- }
187
- return serializer.serializeFragment(pmDoc.content);
214
+ doc.descendants(function (node, pos) {
215
+ nodePositions.set(node, pos);
216
+ });
217
+ return serializer.serializeFragment(doc.content);
188
218
  } catch (_unused2) {
189
219
  return undefined;
190
220
  }
191
- }, [editorView.state.schema, buildDoc, serializer]);
221
+ }, [doc, serializer, nodePositions]);
192
222
  var containerRef = useRef(null);
193
223
  useLayoutEffect(function () {
194
224
  if (containerRef.current && editorHTML) {
@@ -1,20 +1,20 @@
1
1
  import React from 'react';
2
2
  import type { IntlShape } from 'react-intl-next';
3
- import type { EditorPluginInjectionAPI, EditorPresetBuilder } from '@atlaskit/editor-common/preset';
4
3
  import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
5
4
  import { type Schema } from '@atlaskit/editor-prosemirror/model';
5
+ import type { EditorPlugin } from '@atlaskit/editor-common/types';
6
6
  import type { PortalProviderAPI } from '@atlaskit/editor-common/portal';
7
7
  interface Props {
8
8
  'aria-describedby'?: string;
9
9
  'aria-label': string;
10
- buildDoc: (schema: Schema) => PMNode | undefined;
11
10
  className: string;
12
11
  'data-editor-id': string;
12
+ doc: PMNode | undefined;
13
13
  id: string;
14
14
  intl: IntlShape;
15
- pluginInjectionAPI?: EditorPluginInjectionAPI;
15
+ plugins: EditorPlugin[];
16
16
  portalProviderAPI: PortalProviderAPI;
17
- preset: EditorPresetBuilder<any, any>;
17
+ schema: Schema;
18
18
  }
19
- export declare function EditorSSRRenderer({ preset, buildDoc, portalProviderAPI, intl, pluginInjectionAPI, ...divProps }: Props): React.JSX.Element;
19
+ export declare function EditorSSRRenderer({ plugins, schema, doc, portalProviderAPI, intl, ...divProps }: Props): React.JSX.Element;
20
20
  export {};
@@ -1,20 +1,20 @@
1
1
  import React from 'react';
2
2
  import type { IntlShape } from 'react-intl-next';
3
- import type { EditorPluginInjectionAPI, EditorPresetBuilder } from '@atlaskit/editor-common/preset';
4
3
  import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
5
4
  import { type Schema } from '@atlaskit/editor-prosemirror/model';
5
+ import type { EditorPlugin } from '@atlaskit/editor-common/types';
6
6
  import type { PortalProviderAPI } from '@atlaskit/editor-common/portal';
7
7
  interface Props {
8
8
  'aria-describedby'?: string;
9
9
  'aria-label': string;
10
- buildDoc: (schema: Schema) => PMNode | undefined;
11
10
  className: string;
12
11
  'data-editor-id': string;
12
+ doc: PMNode | undefined;
13
13
  id: string;
14
14
  intl: IntlShape;
15
- pluginInjectionAPI?: EditorPluginInjectionAPI;
15
+ plugins: EditorPlugin[];
16
16
  portalProviderAPI: PortalProviderAPI;
17
- preset: EditorPresetBuilder<any, any>;
17
+ schema: Schema;
18
18
  }
19
- export declare function EditorSSRRenderer({ preset, buildDoc, portalProviderAPI, intl, pluginInjectionAPI, ...divProps }: Props): React.JSX.Element;
19
+ export declare function EditorSSRRenderer({ plugins, schema, doc, portalProviderAPI, intl, ...divProps }: Props): React.JSX.Element;
20
20
  export {};
@@ -1,5 +1,6 @@
1
1
  import React, { useMemo } from 'react';
2
2
 
3
+ import { defaultSchema } from '@atlaskit/adf-schema/schema-default';
3
4
  import type { PortalProviderAPI } from '@atlaskit/editor-common/portal';
4
5
  import { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
5
6
  import { CardClient, SmartCardProvider } from '@atlaskit/link-provider';
@@ -29,8 +30,9 @@ function SSREditor({ adf }: { adf: DocNode }) {
29
30
  return (
30
31
  <EditorSSRRenderer
31
32
  intl={intl}
32
- preset={preset}
33
- buildDoc={(schema) => PMNode.fromJSON(schema, adf)}
33
+ doc={PMNode.fromJSON(defaultSchema, adf)}
34
+ plugins={preset.build({})}
35
+ schema={defaultSchema}
34
36
  portalProviderAPI={new SSRPortalProviderAPI()}
35
37
  id="ak-editor-textarea"
36
38
  data-editor-id="6f03e411-00a8-448b-bbc0-66f350895a5e"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-ssr-renderer",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "description": "SSR Renderer based on Editor",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "atlassian": {
@@ -27,13 +27,13 @@
27
27
  "sideEffects": false,
28
28
  "atlaskit:src": "src/index.ts",
29
29
  "dependencies": {
30
- "@atlaskit/adf-schema": "^51.5.1",
31
- "@atlaskit/editor-prosemirror": "7.0.0",
30
+ "@atlaskit/adf-schema": "^51.5.0",
31
+ "@atlaskit/editor-prosemirror": "^7.2.0",
32
32
  "@babel/runtime": "^7.0.0",
33
33
  "react-intl-next": "npm:react-intl@^5.18.1"
34
34
  },
35
35
  "peerDependencies": {
36
- "@atlaskit/editor-common": "^110.40.0",
36
+ "@atlaskit/editor-common": "^110.46.0",
37
37
  "react": "^18.2.0"
38
38
  }
39
39
  }