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