@atlaskit/editor-plugin-synced-block 0.1.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 +12 -0
- package/LICENSE.md +11 -0
- package/README.md +1 -0
- package/SyncedBlock/package.json +15 -0
- package/afm-cc/tsconfig.json +44 -0
- package/build/tsconfig.json +22 -0
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/pm-plugins/SyncClient.js +167 -0
- package/dist/cjs/pm-plugins/main.js +50 -0
- package/dist/cjs/pm-plugins/utils.js +19 -0
- package/dist/cjs/syncedBlockPlugin.js +24 -0
- package/dist/cjs/syncedBlockPluginType.js +5 -0
- package/dist/cjs/types/index.js +1 -0
- package/dist/cjs/ui/extensions/synced-block/components/GlobalStyles.js +25 -0
- package/dist/cjs/ui/extensions/synced-block/components/SyncedBlockLiveView.js +25 -0
- package/dist/cjs/ui/extensions/synced-block/components/SyncedBlockRenderer.js +25 -0
- package/dist/cjs/ui/extensions/synced-block/constants.js +32 -0
- package/dist/cjs/ui/extensions/synced-block/getSyncedBlockExtensionProvider.js +11 -0
- package/dist/cjs/ui/extensions/synced-block/hooks/useLiveSyncedBlockContent.js +29 -0
- package/dist/cjs/ui/extensions/synced-block/hooks/usePollContentProperty.js +121 -0
- package/dist/cjs/ui/extensions/synced-block/index.js +19 -0
- package/dist/cjs/ui/extensions/synced-block/manifest.js +254 -0
- package/dist/cjs/ui/extensions/synced-block/utils/ari.js +29 -0
- package/dist/cjs/ui/extensions/synced-block/utils/content-property.js +159 -0
- package/dist/cjs/ui/extensions/synced-block/utils/synced-block.js +65 -0
- package/dist/es2019/index.js +4 -0
- package/dist/es2019/pm-plugins/SyncClient.js +102 -0
- package/dist/es2019/pm-plugins/main.js +47 -0
- package/dist/es2019/pm-plugins/utils.js +13 -0
- package/dist/es2019/syncedBlockPlugin.js +17 -0
- package/dist/es2019/syncedBlockPluginType.js +1 -0
- package/dist/es2019/types/index.js +0 -0
- package/dist/es2019/ui/extensions/synced-block/components/GlobalStyles.js +18 -0
- package/dist/es2019/ui/extensions/synced-block/components/SyncedBlockLiveView.js +19 -0
- package/dist/es2019/ui/extensions/synced-block/components/SyncedBlockRenderer.js +19 -0
- package/dist/es2019/ui/extensions/synced-block/constants.js +26 -0
- package/dist/es2019/ui/extensions/synced-block/getSyncedBlockExtensionProvider.js +5 -0
- package/dist/es2019/ui/extensions/synced-block/hooks/useLiveSyncedBlockContent.js +24 -0
- package/dist/es2019/ui/extensions/synced-block/hooks/usePollContentProperty.js +107 -0
- package/dist/es2019/ui/extensions/synced-block/index.js +5 -0
- package/dist/es2019/ui/extensions/synced-block/manifest.js +147 -0
- package/dist/es2019/ui/extensions/synced-block/utils/ari.js +19 -0
- package/dist/es2019/ui/extensions/synced-block/utils/content-property.js +108 -0
- package/dist/es2019/ui/extensions/synced-block/utils/synced-block.js +57 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/pm-plugins/SyncClient.js +160 -0
- package/dist/esm/pm-plugins/main.js +44 -0
- package/dist/esm/pm-plugins/utils.js +13 -0
- package/dist/esm/syncedBlockPlugin.js +17 -0
- package/dist/esm/syncedBlockPluginType.js +1 -0
- package/dist/esm/types/index.js +0 -0
- package/dist/esm/ui/extensions/synced-block/components/GlobalStyles.js +18 -0
- package/dist/esm/ui/extensions/synced-block/components/SyncedBlockLiveView.js +18 -0
- package/dist/esm/ui/extensions/synced-block/components/SyncedBlockRenderer.js +18 -0
- package/dist/esm/ui/extensions/synced-block/constants.js +26 -0
- package/dist/esm/ui/extensions/synced-block/getSyncedBlockExtensionProvider.js +5 -0
- package/dist/esm/ui/extensions/synced-block/hooks/useLiveSyncedBlockContent.js +23 -0
- package/dist/esm/ui/extensions/synced-block/hooks/usePollContentProperty.js +114 -0
- package/dist/esm/ui/extensions/synced-block/index.js +5 -0
- package/dist/esm/ui/extensions/synced-block/manifest.js +247 -0
- package/dist/esm/ui/extensions/synced-block/utils/ari.js +23 -0
- package/dist/esm/ui/extensions/synced-block/utils/content-property.js +153 -0
- package/dist/esm/ui/extensions/synced-block/utils/synced-block.js +58 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/pm-plugins/SyncClient.d.ts +14 -0
- package/dist/types/pm-plugins/main.d.ts +6 -0
- package/dist/types/pm-plugins/utils.d.ts +5 -0
- package/dist/types/syncedBlockPlugin.d.ts +2 -0
- package/dist/types/syncedBlockPluginType.d.ts +2 -0
- package/dist/types/types/index.d.ts +3 -0
- package/dist/types/ui/extensions/synced-block/components/GlobalStyles.d.ts +6 -0
- package/dist/types/ui/extensions/synced-block/components/SyncedBlockLiveView.d.ts +7 -0
- package/dist/types/ui/extensions/synced-block/components/SyncedBlockRenderer.d.ts +7 -0
- package/dist/types/ui/extensions/synced-block/constants.d.ts +8 -0
- package/dist/types/ui/extensions/synced-block/getSyncedBlockExtensionProvider.d.ts +2 -0
- package/dist/types/ui/extensions/synced-block/hooks/useLiveSyncedBlockContent.d.ts +6 -0
- package/dist/types/ui/extensions/synced-block/hooks/usePollContentProperty.d.ts +7 -0
- package/dist/types/ui/extensions/synced-block/index.d.ts +2 -0
- package/dist/types/ui/extensions/synced-block/manifest.d.ts +2 -0
- package/dist/types/ui/extensions/synced-block/utils/ari.d.ts +4 -0
- package/dist/types/ui/extensions/synced-block/utils/content-property.d.ts +33 -0
- package/dist/types/ui/extensions/synced-block/utils/synced-block.d.ts +24 -0
- package/dist/types-ts4.5/index.d.ts +3 -0
- package/dist/types-ts4.5/pm-plugins/SyncClient.d.ts +14 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +6 -0
- package/dist/types-ts4.5/pm-plugins/utils.d.ts +5 -0
- package/dist/types-ts4.5/syncedBlockPlugin.d.ts +2 -0
- package/dist/types-ts4.5/syncedBlockPluginType.d.ts +2 -0
- package/dist/types-ts4.5/types/index.d.ts +3 -0
- package/dist/types-ts4.5/ui/extensions/synced-block/components/GlobalStyles.d.ts +6 -0
- package/dist/types-ts4.5/ui/extensions/synced-block/components/SyncedBlockLiveView.d.ts +7 -0
- package/dist/types-ts4.5/ui/extensions/synced-block/components/SyncedBlockRenderer.d.ts +7 -0
- package/dist/types-ts4.5/ui/extensions/synced-block/constants.d.ts +8 -0
- package/dist/types-ts4.5/ui/extensions/synced-block/getSyncedBlockExtensionProvider.d.ts +2 -0
- package/dist/types-ts4.5/ui/extensions/synced-block/hooks/useLiveSyncedBlockContent.d.ts +6 -0
- package/dist/types-ts4.5/ui/extensions/synced-block/hooks/usePollContentProperty.d.ts +7 -0
- package/dist/types-ts4.5/ui/extensions/synced-block/index.d.ts +2 -0
- package/dist/types-ts4.5/ui/extensions/synced-block/manifest.d.ts +2 -0
- package/dist/types-ts4.5/ui/extensions/synced-block/utils/ari.d.ts +4 -0
- package/dist/types-ts4.5/ui/extensions/synced-block/utils/content-property.d.ts +33 -0
- package/dist/types-ts4.5/ui/extensions/synced-block/utils/synced-block.d.ts +24 -0
- package/docs/0-intro.tsx +43 -0
- package/package.json +88 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
3
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import SmartLinkIcon from '@atlaskit/icon/core/smart-link';
|
|
6
|
+
import SyncedBlockLiveView from './components/SyncedBlockLiveView';
|
|
7
|
+
import { getPageId } from './constants';
|
|
8
|
+
import { getConfluencePageAri, getContentPropertyAri } from './utils/ari';
|
|
9
|
+
import { createContentProperty } from './utils/content-property';
|
|
10
|
+
import { SYNCED_BLOCK_EXTENSION_KEY, SYNCED_BLOCK_EXTENSION_TYPE, SYNCED_BLOCK_REFERENCE_KEY, SYNCED_BLOCK_REFERENCE_NODE, SYNCED_BLOCK_SOURCE_KEY, SYNCED_BLOCK_SOURCE_NODE, getDefaultSyncedBlockContent, isSyncedBlockAttributes, stringifySyncedBlockContentPropertyValue } from './utils/synced-block';
|
|
11
|
+
var getRandomId = function getRandomId() {
|
|
12
|
+
if (!globalThis.crypto || typeof globalThis.crypto.randomUUID !== 'function') {
|
|
13
|
+
return new Date().toISOString();
|
|
14
|
+
}
|
|
15
|
+
return globalThis.crypto.randomUUID();
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Remaining tasks
|
|
19
|
+
// - Better location for content sync implementation – currently done in SyncedBlockSource renderer which won't work in editor
|
|
20
|
+
// - Could implement an editor plugin to do this, if there's no native way to do it with extensions
|
|
21
|
+
// - Implement separate content property for storage of the metadata of a synced block, separate from the content
|
|
22
|
+
// - Update polling to use the metadata content property, then if metadata updated, fetch the content property
|
|
23
|
+
// - Investigate re-rendering of SyncedBlockReference in editor on every document change (is this just atlaskit behavior?)
|
|
24
|
+
// - On copy of the synced block, transform into a reference
|
|
25
|
+
// - Move implementation into Confluence and test in branch environment
|
|
26
|
+
// - Dealing with orphaned synced block content properties data
|
|
27
|
+
// - Getting current page id in editor context and the cloud id
|
|
28
|
+
// - Explore hiding the frame for the extension in the editor, currently using `__hideFrame: true` and commented code to enable
|
|
29
|
+
export var getSyncedBlockManifest = function getSyncedBlockManifest() {
|
|
30
|
+
return {
|
|
31
|
+
title: 'Synced Block',
|
|
32
|
+
type: SYNCED_BLOCK_EXTENSION_TYPE,
|
|
33
|
+
key: SYNCED_BLOCK_EXTENSION_KEY,
|
|
34
|
+
description: 'Synced block spike',
|
|
35
|
+
icons: {
|
|
36
|
+
// Ignored via go/ees005
|
|
37
|
+
// eslint-disable-next-line require-await
|
|
38
|
+
'48': function () {
|
|
39
|
+
var _2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
40
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
41
|
+
while (1) switch (_context.prev = _context.next) {
|
|
42
|
+
case 0:
|
|
43
|
+
return _context.abrupt("return", function () {
|
|
44
|
+
return /*#__PURE__*/React.createElement(SmartLinkIcon, {
|
|
45
|
+
label: "Synced Block",
|
|
46
|
+
size: "medium"
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
case 1:
|
|
50
|
+
case "end":
|
|
51
|
+
return _context.stop();
|
|
52
|
+
}
|
|
53
|
+
}, _callee);
|
|
54
|
+
}));
|
|
55
|
+
function _() {
|
|
56
|
+
return _2.apply(this, arguments);
|
|
57
|
+
}
|
|
58
|
+
return _;
|
|
59
|
+
}()
|
|
60
|
+
},
|
|
61
|
+
modules: {
|
|
62
|
+
quickInsert: [{
|
|
63
|
+
key: 'quick-insert-synced-block-source',
|
|
64
|
+
action: function () {
|
|
65
|
+
var _action = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(_api) {
|
|
66
|
+
var contentPropertyKey, content, value, contentProperty, attributes;
|
|
67
|
+
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
68
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
69
|
+
case 0:
|
|
70
|
+
contentPropertyKey = "synced-block-" + getRandomId();
|
|
71
|
+
content = getDefaultSyncedBlockContent();
|
|
72
|
+
value = stringifySyncedBlockContentPropertyValue({
|
|
73
|
+
adf: content
|
|
74
|
+
});
|
|
75
|
+
_context2.next = 5;
|
|
76
|
+
return createContentProperty({
|
|
77
|
+
pageId: getPageId(),
|
|
78
|
+
key: contentPropertyKey,
|
|
79
|
+
value: value
|
|
80
|
+
});
|
|
81
|
+
case 5:
|
|
82
|
+
contentProperty = _context2.sent;
|
|
83
|
+
attributes = {
|
|
84
|
+
extensionType: SYNCED_BLOCK_EXTENSION_TYPE,
|
|
85
|
+
extensionKey: SYNCED_BLOCK_SOURCE_KEY,
|
|
86
|
+
parameters: {
|
|
87
|
+
sourceDocumentAri: getConfluencePageAri(getPageId()),
|
|
88
|
+
contentAri: getContentPropertyAri(contentProperty.id),
|
|
89
|
+
contentPropertyKey: contentPropertyKey
|
|
90
|
+
},
|
|
91
|
+
localId: 'testId'
|
|
92
|
+
};
|
|
93
|
+
content.attrs = attributes;
|
|
94
|
+
return _context2.abrupt("return", content);
|
|
95
|
+
case 9:
|
|
96
|
+
case "end":
|
|
97
|
+
return _context2.stop();
|
|
98
|
+
}
|
|
99
|
+
}, _callee2);
|
|
100
|
+
}));
|
|
101
|
+
function action(_x) {
|
|
102
|
+
return _action.apply(this, arguments);
|
|
103
|
+
}
|
|
104
|
+
return action;
|
|
105
|
+
}()
|
|
106
|
+
}],
|
|
107
|
+
nodes: _defineProperty(_defineProperty({}, SYNCED_BLOCK_SOURCE_NODE, {
|
|
108
|
+
type: 'bodiedExtension',
|
|
109
|
+
// Ignored via go/ees005
|
|
110
|
+
// eslint-disable-next-line require-await
|
|
111
|
+
render: function () {
|
|
112
|
+
var _render = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
|
|
113
|
+
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
|
|
114
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
115
|
+
case 0:
|
|
116
|
+
return _context3.abrupt("return", function (props) {
|
|
117
|
+
if (!isSyncedBlockAttributes(props.node)) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
var _props$node$parameter = props.node.parameters,
|
|
121
|
+
sourceDocumentAri = _props$node$parameter.sourceDocumentAri,
|
|
122
|
+
contentAri = _props$node$parameter.contentAri;
|
|
123
|
+
return /*#__PURE__*/React.createElement(SyncedBlockLiveView, {
|
|
124
|
+
sourceDocumentAri: sourceDocumentAri,
|
|
125
|
+
contentAri: contentAri
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
case 1:
|
|
129
|
+
case "end":
|
|
130
|
+
return _context3.stop();
|
|
131
|
+
}
|
|
132
|
+
}, _callee3);
|
|
133
|
+
}));
|
|
134
|
+
function render() {
|
|
135
|
+
return _render.apply(this, arguments);
|
|
136
|
+
}
|
|
137
|
+
return render;
|
|
138
|
+
}(),
|
|
139
|
+
// @ts-expect-error
|
|
140
|
+
__hideFrame: true
|
|
141
|
+
}), SYNCED_BLOCK_REFERENCE_NODE, {
|
|
142
|
+
type: 'extension',
|
|
143
|
+
// Ignored via go/ees005
|
|
144
|
+
// eslint-disable-next-line require-await
|
|
145
|
+
render: function () {
|
|
146
|
+
var _render2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
|
|
147
|
+
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
|
|
148
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
149
|
+
case 0:
|
|
150
|
+
return _context4.abrupt("return", function (props) {
|
|
151
|
+
if (!isSyncedBlockAttributes(props.node)) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
var _props$node$parameter2 = props.node.parameters,
|
|
155
|
+
sourceDocumentAri = _props$node$parameter2.sourceDocumentAri,
|
|
156
|
+
contentAri = _props$node$parameter2.contentAri;
|
|
157
|
+
return /*#__PURE__*/React.createElement(SyncedBlockLiveView, {
|
|
158
|
+
sourceDocumentAri: sourceDocumentAri,
|
|
159
|
+
contentAri: contentAri
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
case 1:
|
|
163
|
+
case "end":
|
|
164
|
+
return _context4.stop();
|
|
165
|
+
}
|
|
166
|
+
}, _callee4);
|
|
167
|
+
}));
|
|
168
|
+
function render() {
|
|
169
|
+
return _render2.apply(this, arguments);
|
|
170
|
+
}
|
|
171
|
+
return render;
|
|
172
|
+
}(),
|
|
173
|
+
// @ts-expect-error
|
|
174
|
+
__hideFrame: true
|
|
175
|
+
}),
|
|
176
|
+
contextualToolbars: [{
|
|
177
|
+
context: {
|
|
178
|
+
type: 'extension',
|
|
179
|
+
nodeType: 'bodiedExtension',
|
|
180
|
+
extensionType: SYNCED_BLOCK_EXTENSION_TYPE,
|
|
181
|
+
extensionKey: SYNCED_BLOCK_SOURCE_KEY
|
|
182
|
+
},
|
|
183
|
+
toolbarItems: [{
|
|
184
|
+
key: 'toolbar-item-key',
|
|
185
|
+
label: 'Referenece',
|
|
186
|
+
display: 'icon',
|
|
187
|
+
tooltip: 'Create reference',
|
|
188
|
+
// Ignored via go/ees005
|
|
189
|
+
// eslint-disable-next-line require-await
|
|
190
|
+
icon: function () {
|
|
191
|
+
var _icon = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
|
|
192
|
+
return _regeneratorRuntime.wrap(function _callee5$(_context5) {
|
|
193
|
+
while (1) switch (_context5.prev = _context5.next) {
|
|
194
|
+
case 0:
|
|
195
|
+
return _context5.abrupt("return", function () {
|
|
196
|
+
return /*#__PURE__*/React.createElement(SmartLinkIcon, {
|
|
197
|
+
label: "Synced Block",
|
|
198
|
+
size: "medium"
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
case 1:
|
|
202
|
+
case "end":
|
|
203
|
+
return _context5.stop();
|
|
204
|
+
}
|
|
205
|
+
}, _callee5);
|
|
206
|
+
}));
|
|
207
|
+
function icon() {
|
|
208
|
+
return _icon.apply(this, arguments);
|
|
209
|
+
}
|
|
210
|
+
return icon;
|
|
211
|
+
}(),
|
|
212
|
+
// Ignored via go/ees005
|
|
213
|
+
// eslint-disable-next-line require-await
|
|
214
|
+
action: function () {
|
|
215
|
+
var _action2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(contextNode, api) {
|
|
216
|
+
var _contextNode$attrs, _contextNode$attrs2, _contextNode$attrs3;
|
|
217
|
+
return _regeneratorRuntime.wrap(function _callee6$(_context6) {
|
|
218
|
+
while (1) switch (_context6.prev = _context6.next) {
|
|
219
|
+
case 0:
|
|
220
|
+
api.doc.insertAfter((_contextNode$attrs = contextNode.attrs) === null || _contextNode$attrs === void 0 ? void 0 : _contextNode$attrs.localId, {
|
|
221
|
+
type: 'extension',
|
|
222
|
+
attrs: {
|
|
223
|
+
extensionType: SYNCED_BLOCK_EXTENSION_TYPE,
|
|
224
|
+
extensionKey: SYNCED_BLOCK_REFERENCE_KEY,
|
|
225
|
+
parameters: {
|
|
226
|
+
sourceDocumentAri: (_contextNode$attrs2 = contextNode.attrs) === null || _contextNode$attrs2 === void 0 || (_contextNode$attrs2 = _contextNode$attrs2.parameters) === null || _contextNode$attrs2 === void 0 ? void 0 : _contextNode$attrs2.sourceDocumentAri,
|
|
227
|
+
contentAri: (_contextNode$attrs3 = contextNode.attrs) === null || _contextNode$attrs3 === void 0 || (_contextNode$attrs3 = _contextNode$attrs3.parameters) === null || _contextNode$attrs3 === void 0 ? void 0 : _contextNode$attrs3.contentAri
|
|
228
|
+
},
|
|
229
|
+
localId: 'testId'
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
case 1:
|
|
233
|
+
case "end":
|
|
234
|
+
return _context6.stop();
|
|
235
|
+
}
|
|
236
|
+
}, _callee6);
|
|
237
|
+
}));
|
|
238
|
+
function action(_x2, _x3) {
|
|
239
|
+
return _action2.apply(this, arguments);
|
|
240
|
+
}
|
|
241
|
+
return action;
|
|
242
|
+
}()
|
|
243
|
+
}]
|
|
244
|
+
}]
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { getCloudId } from '../constants';
|
|
2
|
+
export var getConfluencePageAri = function getConfluencePageAri(pageId) {
|
|
3
|
+
return "ari:cloud:confluence:".concat(getCloudId(), ":page/").concat(pageId);
|
|
4
|
+
};
|
|
5
|
+
export var getPageIdFromAri = function getPageIdFromAri(ari) {
|
|
6
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
7
|
+
var match = ari.match(/ari:cloud:confluence:[^:]+:page\/(\d+)/);
|
|
8
|
+
if (match) {
|
|
9
|
+
return match[1];
|
|
10
|
+
}
|
|
11
|
+
throw new Error("Invalid page ARI: ".concat(ari));
|
|
12
|
+
};
|
|
13
|
+
export var getContentPropertyAri = function getContentPropertyAri(contentPropertyId) {
|
|
14
|
+
return "ari:cloud:confluence:".concat(getCloudId(), ":content/").concat(contentPropertyId);
|
|
15
|
+
};
|
|
16
|
+
export var getContentPropertyIdFromAri = function getContentPropertyIdFromAri(ari) {
|
|
17
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
18
|
+
var match = ari.match(/ari:cloud:confluence:[^:]+:content\/([^/]+)/);
|
|
19
|
+
if (match) {
|
|
20
|
+
return match[1];
|
|
21
|
+
}
|
|
22
|
+
throw new Error("Invalid content property ARI: ".concat(ari));
|
|
23
|
+
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
2
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
3
|
+
import { getCloudId } from '../constants';
|
|
4
|
+
import { getConfluencePageAri } from './ari';
|
|
5
|
+
|
|
6
|
+
// Uncomment for proxy in Atlaskit, which will route to hello.atlassian.net
|
|
7
|
+
// const BASE_URL = 'https://localhost:9876';
|
|
8
|
+
var BASE_URL = "/gateway/api/ex/confluence/".concat(getCloudId());
|
|
9
|
+
var API_BASE_URL = "".concat(BASE_URL, "/wiki/api/v2");
|
|
10
|
+
var COMMON_HEADERS = {
|
|
11
|
+
'Content-Type': 'application/json',
|
|
12
|
+
Accept: 'application/json'
|
|
13
|
+
};
|
|
14
|
+
var getContentPropertiesUrl = function getContentPropertiesUrl(_ref) {
|
|
15
|
+
var pageId = _ref.pageId,
|
|
16
|
+
contentPropertyId = _ref.contentPropertyId;
|
|
17
|
+
var url = "".concat(API_BASE_URL, "/pages/").concat(pageId, "/properties");
|
|
18
|
+
if (contentPropertyId) {
|
|
19
|
+
return "".concat(url, "/").concat(contentPropertyId);
|
|
20
|
+
}
|
|
21
|
+
return url;
|
|
22
|
+
};
|
|
23
|
+
var getGraphQLPropertiesUrl = function getGraphQLPropertiesUrl() {
|
|
24
|
+
return "/cgraphql/api/graphql";
|
|
25
|
+
};
|
|
26
|
+
export var createContentProperty = /*#__PURE__*/function () {
|
|
27
|
+
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref2) {
|
|
28
|
+
var pageId, key, value, url, body, response, contentProperty;
|
|
29
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
30
|
+
while (1) switch (_context.prev = _context.next) {
|
|
31
|
+
case 0:
|
|
32
|
+
pageId = _ref2.pageId, key = _ref2.key, value = _ref2.value;
|
|
33
|
+
url = getContentPropertiesUrl({
|
|
34
|
+
pageId: pageId
|
|
35
|
+
});
|
|
36
|
+
body = JSON.stringify({
|
|
37
|
+
key: key,
|
|
38
|
+
value: value
|
|
39
|
+
});
|
|
40
|
+
_context.next = 5;
|
|
41
|
+
return fetch(url, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: COMMON_HEADERS,
|
|
44
|
+
body: body
|
|
45
|
+
});
|
|
46
|
+
case 5:
|
|
47
|
+
response = _context.sent;
|
|
48
|
+
if (response.ok) {
|
|
49
|
+
_context.next = 8;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
throw new Error("Failed to create content property: ".concat(response.statusText));
|
|
53
|
+
case 8:
|
|
54
|
+
_context.next = 10;
|
|
55
|
+
return response.json();
|
|
56
|
+
case 10:
|
|
57
|
+
contentProperty = _context.sent;
|
|
58
|
+
return _context.abrupt("return", contentProperty);
|
|
59
|
+
case 12:
|
|
60
|
+
case "end":
|
|
61
|
+
return _context.stop();
|
|
62
|
+
}
|
|
63
|
+
}, _callee);
|
|
64
|
+
}));
|
|
65
|
+
return function createContentProperty(_x) {
|
|
66
|
+
return _ref3.apply(this, arguments);
|
|
67
|
+
};
|
|
68
|
+
}();
|
|
69
|
+
export var getContentProperty = /*#__PURE__*/function () {
|
|
70
|
+
var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(_ref4) {
|
|
71
|
+
var pageId, contentPropertyId, signal, url, response, contentProperty;
|
|
72
|
+
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
73
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
74
|
+
case 0:
|
|
75
|
+
pageId = _ref4.pageId, contentPropertyId = _ref4.contentPropertyId, signal = _ref4.signal;
|
|
76
|
+
url = getContentPropertiesUrl({
|
|
77
|
+
pageId: pageId,
|
|
78
|
+
contentPropertyId: contentPropertyId
|
|
79
|
+
});
|
|
80
|
+
_context2.next = 4;
|
|
81
|
+
return fetch(url, {
|
|
82
|
+
method: 'GET',
|
|
83
|
+
headers: COMMON_HEADERS,
|
|
84
|
+
signal: signal
|
|
85
|
+
});
|
|
86
|
+
case 4:
|
|
87
|
+
response = _context2.sent;
|
|
88
|
+
if (response.ok) {
|
|
89
|
+
_context2.next = 7;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
throw new Error("Failed to get content property: ".concat(response.statusText));
|
|
93
|
+
case 7:
|
|
94
|
+
_context2.next = 9;
|
|
95
|
+
return response.json();
|
|
96
|
+
case 9:
|
|
97
|
+
contentProperty = _context2.sent;
|
|
98
|
+
return _context2.abrupt("return", contentProperty);
|
|
99
|
+
case 11:
|
|
100
|
+
case "end":
|
|
101
|
+
return _context2.stop();
|
|
102
|
+
}
|
|
103
|
+
}, _callee2);
|
|
104
|
+
}));
|
|
105
|
+
return function getContentProperty(_x2) {
|
|
106
|
+
return _ref5.apply(this, arguments);
|
|
107
|
+
};
|
|
108
|
+
}();
|
|
109
|
+
var getQuery = function getQuery(documentARI, key, value) {
|
|
110
|
+
return "mutation {\n\t confluence {\n\t updateValuePageProperty(input: {\n\t pageId: \"".concat(documentARI, "\",\n\t key: \"").concat(key, "\",\n\t value: \"").concat(value, "\",\n\t useSameVersion: true\n\t }) {\n\t pageProperty {\n\t key,\n\t value\n\t }\n\t }\n\t }\n\t}");
|
|
111
|
+
};
|
|
112
|
+
export var updateContentProperty = /*#__PURE__*/function () {
|
|
113
|
+
var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(_ref6) {
|
|
114
|
+
var pageId, key, value, url, documentARI, query, bodyData, response, contentProperty;
|
|
115
|
+
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
|
|
116
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
117
|
+
case 0:
|
|
118
|
+
pageId = _ref6.pageId, key = _ref6.key, value = _ref6.value;
|
|
119
|
+
url = getGraphQLPropertiesUrl();
|
|
120
|
+
documentARI = getConfluencePageAri(pageId); // eslint-disable-next-line require-unicode-regexp
|
|
121
|
+
query = getQuery(documentARI, key, value.replace(/"/g, '\\"'));
|
|
122
|
+
bodyData = {
|
|
123
|
+
query: query
|
|
124
|
+
};
|
|
125
|
+
_context3.next = 7;
|
|
126
|
+
return fetch(url, {
|
|
127
|
+
method: 'POST',
|
|
128
|
+
headers: COMMON_HEADERS,
|
|
129
|
+
body: JSON.stringify(bodyData)
|
|
130
|
+
});
|
|
131
|
+
case 7:
|
|
132
|
+
response = _context3.sent;
|
|
133
|
+
if (response.ok) {
|
|
134
|
+
_context3.next = 10;
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
throw new Error("Failed to update content property: ".concat(response.statusText));
|
|
138
|
+
case 10:
|
|
139
|
+
_context3.next = 12;
|
|
140
|
+
return response.json();
|
|
141
|
+
case 12:
|
|
142
|
+
contentProperty = _context3.sent;
|
|
143
|
+
return _context3.abrupt("return", contentProperty);
|
|
144
|
+
case 14:
|
|
145
|
+
case "end":
|
|
146
|
+
return _context3.stop();
|
|
147
|
+
}
|
|
148
|
+
}, _callee3);
|
|
149
|
+
}));
|
|
150
|
+
return function updateContentProperty(_x3) {
|
|
151
|
+
return _ref7.apply(this, arguments);
|
|
152
|
+
};
|
|
153
|
+
}();
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import _typeof from "@babel/runtime/helpers/typeof";
|
|
2
|
+
export var SYNCED_BLOCK_EXTENSION_TYPE = 'com.atlassian.platform.extensions';
|
|
3
|
+
export var SYNCED_BLOCK_EXTENSION_KEY = 'synced-block';
|
|
4
|
+
export var SYNCED_BLOCK_SOURCE_NODE = 'source';
|
|
5
|
+
export var SYNCED_BLOCK_SOURCE_KEY = "".concat(SYNCED_BLOCK_EXTENSION_KEY, ":").concat(SYNCED_BLOCK_SOURCE_NODE);
|
|
6
|
+
export var SYNCED_BLOCK_REFERENCE_NODE = 'reference';
|
|
7
|
+
export var SYNCED_BLOCK_REFERENCE_KEY = "".concat(SYNCED_BLOCK_EXTENSION_KEY, ":").concat(SYNCED_BLOCK_REFERENCE_NODE);
|
|
8
|
+
export var isSyncedBlockAttributes = function isSyncedBlockAttributes(attributes) {
|
|
9
|
+
return !!attributes && _typeof(attributes) === 'object' && 'extensionKey' in attributes && (attributes.extensionKey === SYNCED_BLOCK_SOURCE_KEY || attributes.extensionKey === SYNCED_BLOCK_REFERENCE_KEY);
|
|
10
|
+
};
|
|
11
|
+
export var getDefaultSyncedBlockContent = function getDefaultSyncedBlockContent() {
|
|
12
|
+
var attributes = {
|
|
13
|
+
extensionType: SYNCED_BLOCK_EXTENSION_TYPE,
|
|
14
|
+
extensionKey: SYNCED_BLOCK_SOURCE_KEY,
|
|
15
|
+
parameters: {
|
|
16
|
+
sourceDocumentAri: '',
|
|
17
|
+
contentAri: '',
|
|
18
|
+
contentPropertyKey: ''
|
|
19
|
+
},
|
|
20
|
+
localId: ''
|
|
21
|
+
};
|
|
22
|
+
return {
|
|
23
|
+
type: 'bodiedExtension',
|
|
24
|
+
attrs: attributes,
|
|
25
|
+
content: [{
|
|
26
|
+
type: 'paragraph',
|
|
27
|
+
content: [{
|
|
28
|
+
type: 'text',
|
|
29
|
+
text: 'This is a synced block. Please edit the source document to update the content.'
|
|
30
|
+
}]
|
|
31
|
+
}]
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export var parseSyncedBlockContentPropertyValue = function parseSyncedBlockContentPropertyValue(value) {
|
|
35
|
+
try {
|
|
36
|
+
if (typeof value === 'string') {
|
|
37
|
+
return JSON.parse(value);
|
|
38
|
+
}
|
|
39
|
+
return value;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
// eslint-disable-next-line no-console
|
|
42
|
+
console.error('Failed to parse synced block content:', error);
|
|
43
|
+
return {
|
|
44
|
+
adf: getDefaultSyncedBlockContent()
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
export var stringifySyncedBlockContentPropertyValue = function stringifySyncedBlockContentPropertyValue(value) {
|
|
49
|
+
try {
|
|
50
|
+
return JSON.stringify(value);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
// eslint-disable-next-line no-console
|
|
53
|
+
console.error('Failed to serialize synced block content:', error);
|
|
54
|
+
return JSON.stringify({
|
|
55
|
+
adf: getDefaultSyncedBlockContent()
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
export declare class SyncClient {
|
|
3
|
+
private requestMap;
|
|
4
|
+
constructor();
|
|
5
|
+
private getRequestState;
|
|
6
|
+
private setRequestState;
|
|
7
|
+
private sendRequest;
|
|
8
|
+
syncContent({ sourceDocumentAri, contentAri, contentPropertyKey, node, }: {
|
|
9
|
+
contentAri: string;
|
|
10
|
+
contentPropertyKey: string;
|
|
11
|
+
node: PMNode;
|
|
12
|
+
sourceDocumentAri: string;
|
|
13
|
+
}): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
export declare const syncedBlockPluginKey: PluginKey<any>;
|
|
4
|
+
type SyncedBlockPluginState = {};
|
|
5
|
+
export declare const createPlugin: () => SafePlugin<SyncedBlockPluginState>;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ResolvedPos } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
export declare const findSyncedBlockParent: ($pos: ResolvedPos) => {
|
|
3
|
+
node: import("prosemirror-model").Node;
|
|
4
|
+
attributes: import("../ui/extensions/synced-block/utils/synced-block").SyncedBlockAttributes;
|
|
5
|
+
} | undefined;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { SyncedBlockContentPropertyValue } from '../utils/synced-block';
|
|
3
|
+
type SyncedBlockRenderer = {
|
|
4
|
+
syncedBlockContent: SyncedBlockContentPropertyValue;
|
|
5
|
+
};
|
|
6
|
+
declare const SyncedBlockRenderer: ({ syncedBlockContent }: SyncedBlockRenderer) => React.JSX.Element;
|
|
7
|
+
export default SyncedBlockRenderer;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const getPageId: () => string;
|
|
2
|
+
/**
|
|
3
|
+
* This by no means is a stable way to get the cloud id, but it works for now.
|
|
4
|
+
* We should switch passing the cloud id from Confluence to a Editor plugin,
|
|
5
|
+
* for instance the user preferences plugin would have a seperate place for user and cloud info
|
|
6
|
+
* @returns the cloud id from the initial state
|
|
7
|
+
*/
|
|
8
|
+
export declare const getCloudId: () => string;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type UseLiveSyncedBlockContentOptions = {
|
|
2
|
+
contentAri: string;
|
|
3
|
+
sourceDocumentAri: string;
|
|
4
|
+
};
|
|
5
|
+
export declare const useLiveSyncedBlockContent: ({ sourceDocumentAri, contentAri, }: UseLiveSyncedBlockContentOptions) => import("../utils/synced-block").SyncedBlockContentPropertyValue | null;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ContentProperty } from '../utils/content-property';
|
|
2
|
+
type UsePollContentPropertyOptions = {
|
|
3
|
+
contentAri: string;
|
|
4
|
+
sourceDocumentAri: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const usePollContentProperty: ({ sourceDocumentAri, contentAri, }: UsePollContentPropertyOptions) => ContentProperty | undefined;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const getConfluencePageAri: (pageId: string) => string;
|
|
2
|
+
export declare const getPageIdFromAri: (ari: string) => string;
|
|
3
|
+
export declare const getContentPropertyAri: (contentPropertyId: string) => string;
|
|
4
|
+
export declare const getContentPropertyIdFromAri: (ari: string) => string;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type ContentProperty = {
|
|
2
|
+
id: string;
|
|
3
|
+
key: string;
|
|
4
|
+
value: string;
|
|
5
|
+
version: ContentPropertyVersion;
|
|
6
|
+
};
|
|
7
|
+
type ContentPropertyVersion = {
|
|
8
|
+
authorId: string;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
message: string;
|
|
11
|
+
minorEdit: boolean;
|
|
12
|
+
number: number;
|
|
13
|
+
};
|
|
14
|
+
type CreateContentPropertyOptions = {
|
|
15
|
+
key: string;
|
|
16
|
+
pageId: string;
|
|
17
|
+
value: string;
|
|
18
|
+
};
|
|
19
|
+
export declare const createContentProperty: ({ pageId, key, value, }: CreateContentPropertyOptions) => Promise<ContentProperty>;
|
|
20
|
+
type GetContentPropertyOptions = {
|
|
21
|
+
contentPropertyId: string;
|
|
22
|
+
pageId: string;
|
|
23
|
+
signal?: AbortSignal;
|
|
24
|
+
};
|
|
25
|
+
export declare const getContentProperty: ({ pageId, contentPropertyId, signal, }: GetContentPropertyOptions) => Promise<ContentProperty>;
|
|
26
|
+
type UpdateContentPropertyOptions = {
|
|
27
|
+
key: string;
|
|
28
|
+
pageId: string;
|
|
29
|
+
signal?: AbortSignal;
|
|
30
|
+
value: string;
|
|
31
|
+
};
|
|
32
|
+
export declare const updateContentProperty: ({ pageId, key, value, }: UpdateContentPropertyOptions) => Promise<ContentProperty>;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ADFEntity } from '@atlaskit/adf-utils/types';
|
|
2
|
+
export declare const SYNCED_BLOCK_EXTENSION_TYPE = "com.atlassian.platform.extensions";
|
|
3
|
+
export declare const SYNCED_BLOCK_EXTENSION_KEY = "synced-block";
|
|
4
|
+
export declare const SYNCED_BLOCK_SOURCE_NODE = "source";
|
|
5
|
+
export declare const SYNCED_BLOCK_SOURCE_KEY = "synced-block:source";
|
|
6
|
+
export declare const SYNCED_BLOCK_REFERENCE_NODE = "reference";
|
|
7
|
+
export declare const SYNCED_BLOCK_REFERENCE_KEY = "synced-block:reference";
|
|
8
|
+
export type SyncedBlockAttributes = {
|
|
9
|
+
extensionKey: typeof SYNCED_BLOCK_SOURCE_KEY | typeof SYNCED_BLOCK_REFERENCE_KEY;
|
|
10
|
+
extensionType: typeof SYNCED_BLOCK_EXTENSION_TYPE;
|
|
11
|
+
localId: string;
|
|
12
|
+
parameters: {
|
|
13
|
+
contentAri: string;
|
|
14
|
+
contentPropertyKey: string;
|
|
15
|
+
sourceDocumentAri: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export declare const isSyncedBlockAttributes: (attributes: unknown) => attributes is SyncedBlockAttributes;
|
|
19
|
+
export type SyncedBlockContentPropertyValue = {
|
|
20
|
+
adf: ADFEntity;
|
|
21
|
+
};
|
|
22
|
+
export declare const getDefaultSyncedBlockContent: () => ADFEntity;
|
|
23
|
+
export declare const parseSyncedBlockContentPropertyValue: (value: string | object) => SyncedBlockContentPropertyValue;
|
|
24
|
+
export declare const stringifySyncedBlockContentPropertyValue: (value: SyncedBlockContentPropertyValue) => string;
|