@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 +20 -0
- package/dist/cjs/editor-ssr-renderer/EditorSSRRenderer.js +101 -71
- package/dist/es2019/editor-ssr-renderer/EditorSSRRenderer.js +58 -23
- package/dist/esm/editor-ssr-renderer/EditorSSRRenderer.js +101 -71
- package/dist/types/editor-ssr-renderer/EditorSSRRenderer.d.ts +5 -5
- package/dist/types-ts4.5/editor-ssr-renderer/EditorSSRRenderer.d.ts +5 -5
- package/example-helpers/createExample.tsx +4 -2
- package/package.json +4 -4
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 = ["
|
|
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
|
|
75
|
-
|
|
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:
|
|
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
|
-
|
|
127
|
+
doc: doc,
|
|
128
|
+
schema: schema,
|
|
134
129
|
plugins: pmPlugins
|
|
135
130
|
})
|
|
136
131
|
});
|
|
137
|
-
}, [pmPlugins]);
|
|
138
|
-
var
|
|
139
|
-
|
|
140
|
-
var
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
var
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
var
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
-
}, [
|
|
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
|
-
|
|
33
|
-
|
|
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
|
|
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
|
-
|
|
85
|
+
doc,
|
|
86
|
+
schema,
|
|
90
87
|
plugins: pmPlugins
|
|
91
88
|
})
|
|
92
89
|
});
|
|
93
|
-
}, [pmPlugins]);
|
|
94
|
-
const
|
|
95
|
-
|
|
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(
|
|
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, () =>
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
}, [
|
|
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 = ["
|
|
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
|
|
67
|
-
|
|
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:
|
|
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
|
-
|
|
119
|
+
doc: doc,
|
|
120
|
+
schema: schema,
|
|
126
121
|
plugins: pmPlugins
|
|
127
122
|
})
|
|
128
123
|
});
|
|
129
|
-
}, [pmPlugins]);
|
|
130
|
-
var
|
|
131
|
-
|
|
132
|
-
var
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
var
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
var
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
-
}, [
|
|
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
|
-
|
|
15
|
+
plugins: EditorPlugin[];
|
|
16
16
|
portalProviderAPI: PortalProviderAPI;
|
|
17
|
-
|
|
17
|
+
schema: Schema;
|
|
18
18
|
}
|
|
19
|
-
export declare function EditorSSRRenderer({
|
|
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
|
-
|
|
15
|
+
plugins: EditorPlugin[];
|
|
16
16
|
portalProviderAPI: PortalProviderAPI;
|
|
17
|
-
|
|
17
|
+
schema: Schema;
|
|
18
18
|
}
|
|
19
|
-
export declare function EditorSSRRenderer({
|
|
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
|
-
|
|
33
|
-
|
|
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
|
+
"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.
|
|
31
|
-
"@atlaskit/editor-prosemirror": "7.
|
|
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.
|
|
36
|
+
"@atlaskit/editor-common": "^110.46.0",
|
|
37
37
|
"react": "^18.2.0"
|
|
38
38
|
}
|
|
39
39
|
}
|