@atlaskit/editor-common 110.49.1 → 110.50.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 +21 -0
- package/dist/cjs/messages/index.js +10 -0
- package/dist/cjs/monitoring/error.js +1 -1
- package/dist/cjs/ui/DropList/index.js +1 -1
- package/dist/cjs/ui/Messages/index.js +14 -2
- package/dist/cjs/utils/create-adf-from-html.js +21 -0
- package/dist/cjs/utils/parse-html-text-content.js +224 -0
- package/dist/cjs/utils/processRawValue.js +17 -5
- package/dist/es2019/messages/index.js +10 -0
- package/dist/es2019/monitoring/error.js +1 -1
- package/dist/es2019/ui/DropList/index.js +1 -1
- package/dist/es2019/ui/Messages/index.js +37 -21
- package/dist/es2019/utils/create-adf-from-html.js +16 -0
- package/dist/es2019/utils/parse-html-text-content.js +179 -0
- package/dist/es2019/utils/processRawValue.js +19 -6
- package/dist/esm/messages/index.js +10 -0
- package/dist/esm/monitoring/error.js +1 -1
- package/dist/esm/ui/DropList/index.js +1 -1
- package/dist/esm/ui/Messages/index.js +14 -2
- package/dist/esm/utils/create-adf-from-html.js +16 -0
- package/dist/esm/utils/parse-html-text-content.js +217 -0
- package/dist/esm/utils/processRawValue.js +17 -5
- package/dist/types/messages/index.d.ts +10 -0
- package/dist/types/utils/create-adf-from-html.d.ts +13 -0
- package/dist/types/utils/parse-html-text-content.d.ts +19 -0
- package/dist/types-ts4.5/messages/index.d.ts +10 -0
- package/dist/types-ts4.5/utils/create-adf-from-html.d.ts +13 -0
- package/dist/types-ts4.5/utils/parse-html-text-content.d.ts +19 -0
- package/package.json +3 -3
- package/utils/create-adf-from-html/package.json +17 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @atlaskit/editor-common
|
|
2
2
|
|
|
3
|
+
## 110.50.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`909bd527e4564`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/909bd527e4564) -
|
|
8
|
+
Introduce a new createADFFromHTML function for use with the placeholder options.
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- [`fd5c8dd25d59a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/fd5c8dd25d59a) -
|
|
13
|
+
[ux] [ENGHEALTH-47470] remove redundant aria-label from ErrorIcon
|
|
14
|
+
|
|
15
|
+
## 110.49.2
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- [`2939bcb36abe7`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/2939bcb36abe7) -
|
|
20
|
+
Fix nested tables turning into unsupported block nodes under SSR renderer
|
|
21
|
+
- [`f41ee46c84bb1`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/f41ee46c84bb1) -
|
|
22
|
+
[EDITOR-3881] Fix table styling to work with SSR renderer
|
|
23
|
+
|
|
3
24
|
## 110.49.1
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
|
@@ -451,5 +451,15 @@ var _default = exports.default = (0, _reactIntlNext.defineMessages)({
|
|
|
451
451
|
id: 'fabric.editor.imageEdit',
|
|
452
452
|
defaultMessage: 'Edit image',
|
|
453
453
|
description: 'Crop, flip or rotate the image'
|
|
454
|
+
},
|
|
455
|
+
error: {
|
|
456
|
+
id: 'fabric.editor.error.message.label',
|
|
457
|
+
defaultMessage: 'Error',
|
|
458
|
+
description: 'Label for error message icon'
|
|
459
|
+
},
|
|
460
|
+
success: {
|
|
461
|
+
id: 'fabric.editor.success.message.label',
|
|
462
|
+
defaultMessage: 'Success',
|
|
463
|
+
description: 'Label for success message icon'
|
|
454
464
|
}
|
|
455
465
|
});
|
|
@@ -19,7 +19,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
19
19
|
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); }
|
|
20
20
|
var SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
|
|
21
21
|
var packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
|
|
22
|
-
var packageVersion = "110.49.
|
|
22
|
+
var packageVersion = "110.49.2";
|
|
23
23
|
var sanitiseSentryEvents = function sanitiseSentryEvents(data, _hint) {
|
|
24
24
|
// Remove URL as it has UGC
|
|
25
25
|
// Ignored via go/ees007
|
|
@@ -24,7 +24,7 @@ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.
|
|
|
24
24
|
* @jsx jsx
|
|
25
25
|
*/ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
26
26
|
var packageName = "@atlaskit/editor-common";
|
|
27
|
-
var packageVersion = "110.49.
|
|
27
|
+
var packageVersion = "110.49.2";
|
|
28
28
|
var halfFocusRing = 1;
|
|
29
29
|
var dropOffset = '0, 8';
|
|
30
30
|
var fadeIn = (0, _react2.keyframes)({
|
|
@@ -6,8 +6,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.ValidMessage = exports.HelperMessage = exports.ErrorMessage = void 0;
|
|
8
8
|
var _react = require("@emotion/react");
|
|
9
|
+
var _reactIntlNext = require("react-intl-next");
|
|
9
10
|
var _statusError = _interopRequireDefault(require("@atlaskit/icon/core/status-error"));
|
|
10
11
|
var _statusSuccess = _interopRequireDefault(require("@atlaskit/icon/core/status-success"));
|
|
12
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
13
|
+
var _messages = _interopRequireDefault(require("../../messages"));
|
|
11
14
|
/**
|
|
12
15
|
* @jsxRuntime classic
|
|
13
16
|
* @jsx jsx
|
|
@@ -52,13 +55,18 @@ var HelperMessage = exports.HelperMessage = function HelperMessage(_ref) {
|
|
|
52
55
|
};
|
|
53
56
|
var ErrorMessage = exports.ErrorMessage = function ErrorMessage(_ref2) {
|
|
54
57
|
var children = _ref2.children;
|
|
58
|
+
var intl = (0, _reactIntlNext.useIntl)();
|
|
55
59
|
return (0, _react.jsx)("div", {
|
|
56
60
|
css: function css() {
|
|
57
61
|
return [messageStyle(), errorColor];
|
|
58
62
|
}
|
|
59
63
|
}, (0, _react.jsx)("span", {
|
|
60
64
|
css: iconWrapperStyle
|
|
61
|
-
}, (0, _react.jsx)(_statusError.default, {
|
|
65
|
+
}, (0, _platformFeatureFlags.fg)('platform_editor_dec_a11y_fixes') ? (0, _react.jsx)(_statusError.default, {
|
|
66
|
+
LEGACY_size: "small",
|
|
67
|
+
label: intl.formatMessage(_messages.default.error)
|
|
68
|
+
})
|
|
69
|
+
/* eslint-disable-next-line @atlassian/i18n/no-literal-string-in-jsx */ : (0, _react.jsx)(_statusError.default, {
|
|
62
70
|
LEGACY_size: "small",
|
|
63
71
|
label: "error",
|
|
64
72
|
"aria-label": "error"
|
|
@@ -66,13 +74,17 @@ var ErrorMessage = exports.ErrorMessage = function ErrorMessage(_ref2) {
|
|
|
66
74
|
};
|
|
67
75
|
var ValidMessage = exports.ValidMessage = function ValidMessage(_ref3) {
|
|
68
76
|
var children = _ref3.children;
|
|
77
|
+
var intl = (0, _reactIntlNext.useIntl)();
|
|
69
78
|
return (0, _react.jsx)("div", {
|
|
70
79
|
css: function css() {
|
|
71
80
|
return [messageStyle(), validColor];
|
|
72
81
|
}
|
|
73
82
|
}, (0, _react.jsx)("span", {
|
|
74
83
|
css: iconWrapperStyle
|
|
75
|
-
}, (0, _react.jsx)(_statusSuccess.default, {
|
|
84
|
+
}, (0, _platformFeatureFlags.fg)('platform_editor_dec_a11y_fixes') ? (0, _react.jsx)(_statusSuccess.default, {
|
|
85
|
+
LEGACY_size: "small",
|
|
86
|
+
label: intl.formatMessage(_messages.default.success)
|
|
87
|
+
}) : (0, _react.jsx)(_statusSuccess.default, {
|
|
76
88
|
LEGACY_size: "small",
|
|
77
89
|
label: "success"
|
|
78
90
|
})), children);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createADFFromHTML = void 0;
|
|
7
|
+
var _parseHtmlTextContent = require("./parse-html-text-content");
|
|
8
|
+
/**
|
|
9
|
+
* Creates ADF from HTML string.
|
|
10
|
+
* This is particularly useful for providing translations in HTML to be supported and we convert back to ADF here
|
|
11
|
+
* See: https://developer.atlassian.com/platform/localization/i18n-formatting/avoiding-concatenation/
|
|
12
|
+
*
|
|
13
|
+
* This function only supports a subset of the schema as it is intended for translations, but it supports
|
|
14
|
+
* SSR as it has no DOM dependencies and is lightweight.
|
|
15
|
+
*
|
|
16
|
+
* @param html - The HTML string to convert to ADF
|
|
17
|
+
* @returns ADF DocNode or undefined if parsing fails
|
|
18
|
+
*/
|
|
19
|
+
var createADFFromHTML = exports.createADFFromHTML = function createADFFromHTML(html) {
|
|
20
|
+
return (0, _parseHtmlTextContent.parseHTMLTextContent)(html);
|
|
21
|
+
};
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.parseHTMLTextContent = exports.getNestingRulesFromSchema = void 0;
|
|
8
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
10
|
+
var _schemaDefault = require("@atlaskit/adf-schema/schema-default");
|
|
11
|
+
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
12
|
+
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; }
|
|
13
|
+
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; }
|
|
14
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
15
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
16
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
17
|
+
var domParser = _model.DOMParser.fromSchema(_schemaDefault.defaultSchema);
|
|
18
|
+
var getNestingRulesFromSchema = exports.getNestingRulesFromSchema = function getNestingRulesFromSchema() {
|
|
19
|
+
var KEYWORDS = ['inline', 'block', 'text', 'leaf', 'group', 'unsupportedBlock', 'unsupportedInline'];
|
|
20
|
+
var rules = {};
|
|
21
|
+
for (var _i = 0, _Object$keys = Object.keys(_schemaDefault.defaultSchema.nodes); _i < _Object$keys.length; _i++) {
|
|
22
|
+
var _defaultSchema$nodes$;
|
|
23
|
+
var nodeType = _Object$keys[_i];
|
|
24
|
+
var contentStr = (_defaultSchema$nodes$ = _schemaDefault.defaultSchema.nodes[nodeType]) === null || _defaultSchema$nodes$ === void 0 ? void 0 : _defaultSchema$nodes$.spec.content;
|
|
25
|
+
if (!contentStr) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
var allowedChildren =
|
|
29
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
30
|
+
(String(contentStr).match(/\b([a-zA-Z_][a-zA-Z0-9_]*)\b/g) || []).filter(function (match, index, arr) {
|
|
31
|
+
return !KEYWORDS.includes(match) && _schemaDefault.defaultSchema.nodes[match] && arr.indexOf(match) === index;
|
|
32
|
+
});
|
|
33
|
+
if (allowedChildren.length > 0) {
|
|
34
|
+
rules[nodeType] = allowedChildren;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return rules;
|
|
38
|
+
};
|
|
39
|
+
var NESTING_RULES = getNestingRulesFromSchema();
|
|
40
|
+
var canContainChildren = function canContainChildren(nodeType) {
|
|
41
|
+
var _NESTING_RULES$nodeTy;
|
|
42
|
+
return !!((_NESTING_RULES$nodeTy = NESTING_RULES[nodeType]) !== null && _NESTING_RULES$nodeTy !== void 0 && _NESTING_RULES$nodeTy.length);
|
|
43
|
+
};
|
|
44
|
+
var isAllowedChild = function isAllowedChild(parent, child) {
|
|
45
|
+
var _NESTING_RULES$parent, _NESTING_RULES$parent2;
|
|
46
|
+
return (_NESTING_RULES$parent = (_NESTING_RULES$parent2 = NESTING_RULES[parent]) === null || _NESTING_RULES$parent2 === void 0 ? void 0 : _NESTING_RULES$parent2.includes(child)) !== null && _NESTING_RULES$parent !== void 0 ? _NESTING_RULES$parent : false;
|
|
47
|
+
};
|
|
48
|
+
var shouldApplyMark = function shouldApplyMark(tag) {
|
|
49
|
+
return domParser.rules.some(function (rule) {
|
|
50
|
+
return 'mark' in rule && rule.tag === tag;
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
var isBlockElement = function isBlockElement(tag) {
|
|
54
|
+
return domParser.rules.some(function (rule) {
|
|
55
|
+
return rule.tag === tag && rule.node;
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
var getMarkTypes = function getMarkTypes(tags) {
|
|
59
|
+
var seen = new Set();
|
|
60
|
+
var marks = [];
|
|
61
|
+
var _iterator = _createForOfIteratorHelper(tags),
|
|
62
|
+
_step;
|
|
63
|
+
try {
|
|
64
|
+
var _loop = function _loop() {
|
|
65
|
+
var _domParser$rules$find;
|
|
66
|
+
var tag = _step.value;
|
|
67
|
+
var markType = (_domParser$rules$find = domParser.rules.find(function (rule) {
|
|
68
|
+
return rule.tag === tag;
|
|
69
|
+
})) === null || _domParser$rules$find === void 0 ? void 0 : _domParser$rules$find.mark;
|
|
70
|
+
if (markType && !seen.has(markType)) {
|
|
71
|
+
marks.push({
|
|
72
|
+
type: markType
|
|
73
|
+
});
|
|
74
|
+
seen.add(markType);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
78
|
+
_loop();
|
|
79
|
+
}
|
|
80
|
+
} catch (err) {
|
|
81
|
+
_iterator.e(err);
|
|
82
|
+
} finally {
|
|
83
|
+
_iterator.f();
|
|
84
|
+
}
|
|
85
|
+
return marks;
|
|
86
|
+
};
|
|
87
|
+
var createParagraph = function createParagraph() {
|
|
88
|
+
var content = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
89
|
+
return {
|
|
90
|
+
type: 'paragraph',
|
|
91
|
+
content: content
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
var getBlockType = function getBlockType(tag) {
|
|
95
|
+
var rule = domParser.rules.find(function (r) {
|
|
96
|
+
return r.tag === tag;
|
|
97
|
+
});
|
|
98
|
+
return rule && 'node' in rule && rule.node ? rule.node : 'paragraph';
|
|
99
|
+
};
|
|
100
|
+
var createTextNode = function createTextNode(text, marks) {
|
|
101
|
+
var markTypes = getMarkTypes(marks);
|
|
102
|
+
return _objectSpread({
|
|
103
|
+
type: 'text',
|
|
104
|
+
text: text
|
|
105
|
+
}, markTypes.length > 0 && {
|
|
106
|
+
marks: markTypes
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
var addText = function addText(text, marks, content) {
|
|
110
|
+
if (text) {
|
|
111
|
+
content.push(createTextNode(text, marks));
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
var handleBlockElement = function handleBlockElement(tag, innerContent, marks, blocks, currentParagraphContent, parseNode, nestedContainer) {
|
|
115
|
+
// Push any accumulated content as paragraph before block element
|
|
116
|
+
if (currentParagraphContent.length > 0) {
|
|
117
|
+
blocks.push(createParagraph((0, _toConsumableArray2.default)(currentParagraphContent)));
|
|
118
|
+
currentParagraphContent.length = 0;
|
|
119
|
+
}
|
|
120
|
+
var blockType = getBlockType(tag);
|
|
121
|
+
var newMarks = shouldApplyMark(tag) ? [].concat((0, _toConsumableArray2.default)(marks), [tag]) : marks;
|
|
122
|
+
var parentNodeType = nestedContainer === null || nestedContainer === void 0 ? void 0 : nestedContainer.parentType;
|
|
123
|
+
if (nestedContainer && parentNodeType && isAllowedChild(parentNodeType, blockType)) {
|
|
124
|
+
var elementContent = [];
|
|
125
|
+
var childNestedContainer = canContainChildren(blockType) ? {
|
|
126
|
+
parentType: blockType,
|
|
127
|
+
children: elementContent
|
|
128
|
+
} : nestedContainer;
|
|
129
|
+
parseNode(innerContent, newMarks, childNestedContainer);
|
|
130
|
+
if (currentParagraphContent.length > 0) {
|
|
131
|
+
elementContent.push(createParagraph((0, _toConsumableArray2.default)(currentParagraphContent)));
|
|
132
|
+
currentParagraphContent.length = 0;
|
|
133
|
+
}
|
|
134
|
+
nestedContainer.children.push({
|
|
135
|
+
type: blockType,
|
|
136
|
+
content: elementContent.length > 0 ? elementContent : [createParagraph()]
|
|
137
|
+
});
|
|
138
|
+
} else if (canContainChildren(blockType)) {
|
|
139
|
+
var children = [];
|
|
140
|
+
parseNode(innerContent, newMarks, {
|
|
141
|
+
parentType: blockType,
|
|
142
|
+
children: children
|
|
143
|
+
});
|
|
144
|
+
blocks.push({
|
|
145
|
+
type: blockType,
|
|
146
|
+
content: children.length > 0 ? children : [createParagraph()]
|
|
147
|
+
});
|
|
148
|
+
} else {
|
|
149
|
+
// Regular block elements
|
|
150
|
+
parseNode(innerContent, newMarks, nestedContainer);
|
|
151
|
+
|
|
152
|
+
// Push content generated from block parsing
|
|
153
|
+
if (currentParagraphContent.length > 0) {
|
|
154
|
+
if (blockType === 'paragraph' || blockType === 'codeBlock') {
|
|
155
|
+
blocks.push({
|
|
156
|
+
type: blockType,
|
|
157
|
+
content: (0, _toConsumableArray2.default)(currentParagraphContent)
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
currentParagraphContent.length = 0;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
var handleInlineElement = function handleInlineElement(tag, innerContent, marks, parseNode, nestedContainer) {
|
|
165
|
+
var newMarks = shouldApplyMark(tag) ? [].concat((0, _toConsumableArray2.default)(marks), [tag]) : marks;
|
|
166
|
+
parseNode(innerContent, newMarks, nestedContainer);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Simple SSR-compatible parser that recognises text wrapped in HTML elements
|
|
171
|
+
* and extracts their content as ADF.
|
|
172
|
+
*
|
|
173
|
+
* Designed specifically for parsing i18n strings for ADF which specifically need to be
|
|
174
|
+
* HTML strings for translation.
|
|
175
|
+
*
|
|
176
|
+
* Supports nested structures automatically derived from the ADF schema:
|
|
177
|
+
* - Lists: ul/ol → li (listItem)
|
|
178
|
+
* - Tables: table → tr (tableRow) → td/th (tableCell/tableHeader)
|
|
179
|
+
* - Paragraphs, code blocks, and text marks
|
|
180
|
+
* - Any other nested structures defined in the schema
|
|
181
|
+
*
|
|
182
|
+
* @param html - The HTML string to parse
|
|
183
|
+
* @returns ADF DocNode containing the parsed content
|
|
184
|
+
*/
|
|
185
|
+
var parseHTMLTextContent = exports.parseHTMLTextContent = function parseHTMLTextContent(html) {
|
|
186
|
+
var blocks = [];
|
|
187
|
+
var currentParagraphContent = [];
|
|
188
|
+
|
|
189
|
+
// Simple regex-based parser that works in both SSR and browser
|
|
190
|
+
var _parseNode = function parseNode(content) {
|
|
191
|
+
var marks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
192
|
+
var nestedContainer = arguments.length > 2 ? arguments[2] : undefined;
|
|
193
|
+
// Match HTML tags and text content
|
|
194
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
195
|
+
var tagRegex = /<\s*(\w+)([^>]*)>([\s\S]*?)<\s*\/\s*\1\s*>|([^<]+)/g;
|
|
196
|
+
var match = tagRegex.exec(content);
|
|
197
|
+
while (match !== null) {
|
|
198
|
+
if (match[4]) {
|
|
199
|
+
addText(match[4], marks, currentParagraphContent);
|
|
200
|
+
} else {
|
|
201
|
+
// HTML element
|
|
202
|
+
var tag = match[1].toLowerCase();
|
|
203
|
+
var innerContent = match[3];
|
|
204
|
+
if (isBlockElement(tag)) {
|
|
205
|
+
handleBlockElement(tag, innerContent, marks, blocks, currentParagraphContent, _parseNode, nestedContainer);
|
|
206
|
+
} else {
|
|
207
|
+
handleInlineElement(tag, innerContent, marks, _parseNode, nestedContainer);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
match = tagRegex.exec(content);
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
_parseNode(html);
|
|
214
|
+
|
|
215
|
+
// Push any remaining content
|
|
216
|
+
if (currentParagraphContent.length > 0) {
|
|
217
|
+
blocks.push(createParagraph(currentParagraphContent));
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
type: 'doc',
|
|
221
|
+
version: 1,
|
|
222
|
+
content: blocks.length > 0 ? blocks : [createParagraph()]
|
|
223
|
+
};
|
|
224
|
+
};
|
|
@@ -9,6 +9,7 @@ exports.processRawValueWithoutValidation = processRawValueWithoutValidation;
|
|
|
9
9
|
var _transforms = require("@atlaskit/adf-utils/transforms");
|
|
10
10
|
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
11
11
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
12
|
+
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
12
13
|
var _analytics = require("../analytics");
|
|
13
14
|
var _privacyFilter = require("./filter/privacy-filter");
|
|
14
15
|
var _trackUnsupportedContent = require("./track-unsupported-content");
|
|
@@ -215,10 +216,6 @@ function processRawValue(schema, value, providerFactory, sanitizePrivateContent,
|
|
|
215
216
|
eventType: _analytics.EVENT_TYPE.OPERATIONAL
|
|
216
217
|
});
|
|
217
218
|
}
|
|
218
|
-
|
|
219
|
-
// Convert nested-table extensions into nested tables
|
|
220
|
-
var _transformNestedTable3 = transformNestedTablesWithAnalytics(transformedAdf, dispatchAnalyticsEvent);
|
|
221
|
-
transformedAdf = _transformNestedTable3.transformedAdf;
|
|
222
219
|
if (dispatchAnalyticsEvent) {
|
|
223
220
|
var _transformedAdf$conte;
|
|
224
221
|
var hasSingleColumnLayout = (_transformedAdf$conte = transformedAdf.content) === null || _transformedAdf$conte === void 0 ? void 0 : _transformedAdf$conte.some(function (node) {
|
|
@@ -233,7 +230,22 @@ function processRawValue(schema, value, providerFactory, sanitizePrivateContent,
|
|
|
233
230
|
});
|
|
234
231
|
}
|
|
235
232
|
}
|
|
236
|
-
var entity
|
|
233
|
+
var entity;
|
|
234
|
+
if ((0, _expValEquals.expValEquals)('platform_editor_ssr_renderer', 'isEnabled', true)) {
|
|
235
|
+
// Validate ADF first before converting nested-table extensions into nested tables
|
|
236
|
+
// This matches the renderer's behavior in render-document.ts
|
|
237
|
+
entity = (0, _validateUsingSpec.validateADFEntity)(schema, transformedAdf || node, dispatchAnalyticsEvent);
|
|
238
|
+
|
|
239
|
+
// Convert nested-table extensions into nested tables
|
|
240
|
+
var _transformNestedTable3 = transformNestedTablesWithAnalytics(entity, dispatchAnalyticsEvent);
|
|
241
|
+
transformedAdf = _transformNestedTable3.transformedAdf;
|
|
242
|
+
entity = transformedAdf;
|
|
243
|
+
} else {
|
|
244
|
+
// Convert nested-table extensions into nested tables
|
|
245
|
+
var _transformNestedTable4 = transformNestedTablesWithAnalytics(transformedAdf, dispatchAnalyticsEvent);
|
|
246
|
+
transformedAdf = _transformNestedTable4.transformedAdf;
|
|
247
|
+
entity = (0, _validateUsingSpec.validateADFEntity)(schema, transformedAdf || node, dispatchAnalyticsEvent);
|
|
248
|
+
}
|
|
237
249
|
var newEntity = maySanitizePrivateContent(entity, providerFactory, sanitizePrivateContent);
|
|
238
250
|
var parsedDoc = _model.Node.fromJSON(schema, newEntity);
|
|
239
251
|
|
|
@@ -194,5 +194,15 @@ export default defineMessages({
|
|
|
194
194
|
id: 'fabric.editor.imageEdit',
|
|
195
195
|
defaultMessage: 'Edit image',
|
|
196
196
|
description: 'Crop, flip or rotate the image'
|
|
197
|
+
},
|
|
198
|
+
error: {
|
|
199
|
+
id: 'fabric.editor.error.message.label',
|
|
200
|
+
defaultMessage: 'Error',
|
|
201
|
+
description: 'Label for error message icon'
|
|
202
|
+
},
|
|
203
|
+
success: {
|
|
204
|
+
id: 'fabric.editor.success.message.label',
|
|
205
|
+
defaultMessage: 'Success',
|
|
206
|
+
description: 'Label for success message icon'
|
|
197
207
|
}
|
|
198
208
|
});
|
|
@@ -4,7 +4,7 @@ import { isFedRamp } from './environment';
|
|
|
4
4
|
import { normaliseSentryBreadcrumbs, SERIALIZABLE_ATTRIBUTES } from './normalise-sentry-breadcrumbs';
|
|
5
5
|
const SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
|
|
6
6
|
const packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
|
|
7
|
-
const packageVersion = "110.49.
|
|
7
|
+
const packageVersion = "110.49.2";
|
|
8
8
|
const sanitiseSentryEvents = (data, _hint) => {
|
|
9
9
|
// Remove URL as it has UGC
|
|
10
10
|
// Ignored via go/ees007
|
|
@@ -14,7 +14,7 @@ import withAnalyticsEvents from '@atlaskit/analytics-next/withAnalyticsEvents';
|
|
|
14
14
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
15
15
|
import Layer from '../Layer';
|
|
16
16
|
const packageName = "@atlaskit/editor-common";
|
|
17
|
-
const packageVersion = "110.49.
|
|
17
|
+
const packageVersion = "110.49.2";
|
|
18
18
|
const halfFocusRing = 1;
|
|
19
19
|
const dropOffset = '0, 8';
|
|
20
20
|
const fadeIn = keyframes({
|
|
@@ -5,8 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
7
7
|
import { css, jsx } from '@emotion/react';
|
|
8
|
+
import { useIntl } from 'react-intl-next';
|
|
8
9
|
import ErrorIcon from '@atlaskit/icon/core/status-error';
|
|
9
10
|
import SuccessIcon from '@atlaskit/icon/core/status-success';
|
|
11
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
12
|
+
import commonMessages from '../../messages';
|
|
10
13
|
const errorColor = css({
|
|
11
14
|
color: "var(--ds-text-danger, #AE2E24)"
|
|
12
15
|
});
|
|
@@ -40,26 +43,39 @@ export const HelperMessage = ({
|
|
|
40
43
|
}, children);
|
|
41
44
|
export const ErrorMessage = ({
|
|
42
45
|
children
|
|
43
|
-
}) =>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}, jsx(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
}) => {
|
|
47
|
+
const intl = useIntl();
|
|
48
|
+
return jsx("div", {
|
|
49
|
+
css: () => {
|
|
50
|
+
return [messageStyle(), errorColor];
|
|
51
|
+
}
|
|
52
|
+
}, jsx("span", {
|
|
53
|
+
css: iconWrapperStyle
|
|
54
|
+
}, fg('platform_editor_dec_a11y_fixes') ? jsx(ErrorIcon, {
|
|
55
|
+
LEGACY_size: "small",
|
|
56
|
+
label: intl.formatMessage(commonMessages.error)
|
|
57
|
+
})
|
|
58
|
+
/* eslint-disable-next-line @atlassian/i18n/no-literal-string-in-jsx */ : jsx(ErrorIcon, {
|
|
59
|
+
LEGACY_size: "small",
|
|
60
|
+
label: "error",
|
|
61
|
+
"aria-label": "error"
|
|
62
|
+
})), children);
|
|
63
|
+
};
|
|
54
64
|
export const ValidMessage = ({
|
|
55
65
|
children
|
|
56
|
-
}) =>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}, jsx(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
}) => {
|
|
67
|
+
const intl = useIntl();
|
|
68
|
+
return jsx("div", {
|
|
69
|
+
css: () => {
|
|
70
|
+
return [messageStyle(), validColor];
|
|
71
|
+
}
|
|
72
|
+
}, jsx("span", {
|
|
73
|
+
css: iconWrapperStyle
|
|
74
|
+
}, fg('platform_editor_dec_a11y_fixes') ? jsx(SuccessIcon, {
|
|
75
|
+
LEGACY_size: "small",
|
|
76
|
+
label: intl.formatMessage(commonMessages.success)
|
|
77
|
+
}) : jsx(SuccessIcon, {
|
|
78
|
+
LEGACY_size: "small",
|
|
79
|
+
label: "success"
|
|
80
|
+
})), children);
|
|
81
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { parseHTMLTextContent } from './parse-html-text-content';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates ADF from HTML string.
|
|
5
|
+
* This is particularly useful for providing translations in HTML to be supported and we convert back to ADF here
|
|
6
|
+
* See: https://developer.atlassian.com/platform/localization/i18n-formatting/avoiding-concatenation/
|
|
7
|
+
*
|
|
8
|
+
* This function only supports a subset of the schema as it is intended for translations, but it supports
|
|
9
|
+
* SSR as it has no DOM dependencies and is lightweight.
|
|
10
|
+
*
|
|
11
|
+
* @param html - The HTML string to convert to ADF
|
|
12
|
+
* @returns ADF DocNode or undefined if parsing fails
|
|
13
|
+
*/
|
|
14
|
+
export const createADFFromHTML = html => {
|
|
15
|
+
return parseHTMLTextContent(html);
|
|
16
|
+
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { defaultSchema } from '@atlaskit/adf-schema/schema-default';
|
|
2
|
+
import { DOMParser } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
+
const domParser = DOMParser.fromSchema(defaultSchema);
|
|
4
|
+
export const getNestingRulesFromSchema = () => {
|
|
5
|
+
const KEYWORDS = ['inline', 'block', 'text', 'leaf', 'group', 'unsupportedBlock', 'unsupportedInline'];
|
|
6
|
+
const rules = {};
|
|
7
|
+
for (const nodeType of Object.keys(defaultSchema.nodes)) {
|
|
8
|
+
var _defaultSchema$nodes$;
|
|
9
|
+
const contentStr = (_defaultSchema$nodes$ = defaultSchema.nodes[nodeType]) === null || _defaultSchema$nodes$ === void 0 ? void 0 : _defaultSchema$nodes$.spec.content;
|
|
10
|
+
if (!contentStr) {
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
const allowedChildren =
|
|
14
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
15
|
+
(String(contentStr).match(/\b([a-zA-Z_][a-zA-Z0-9_]*)\b/g) || []).filter((match, index, arr) => !KEYWORDS.includes(match) && defaultSchema.nodes[match] && arr.indexOf(match) === index);
|
|
16
|
+
if (allowedChildren.length > 0) {
|
|
17
|
+
rules[nodeType] = allowedChildren;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return rules;
|
|
21
|
+
};
|
|
22
|
+
const NESTING_RULES = getNestingRulesFromSchema();
|
|
23
|
+
const canContainChildren = nodeType => {
|
|
24
|
+
var _NESTING_RULES$nodeTy;
|
|
25
|
+
return !!((_NESTING_RULES$nodeTy = NESTING_RULES[nodeType]) !== null && _NESTING_RULES$nodeTy !== void 0 && _NESTING_RULES$nodeTy.length);
|
|
26
|
+
};
|
|
27
|
+
const isAllowedChild = (parent, child) => {
|
|
28
|
+
var _NESTING_RULES$parent, _NESTING_RULES$parent2;
|
|
29
|
+
return (_NESTING_RULES$parent = (_NESTING_RULES$parent2 = NESTING_RULES[parent]) === null || _NESTING_RULES$parent2 === void 0 ? void 0 : _NESTING_RULES$parent2.includes(child)) !== null && _NESTING_RULES$parent !== void 0 ? _NESTING_RULES$parent : false;
|
|
30
|
+
};
|
|
31
|
+
const shouldApplyMark = tag => domParser.rules.some(rule => 'mark' in rule && rule.tag === tag);
|
|
32
|
+
const isBlockElement = tag => domParser.rules.some(rule => rule.tag === tag && rule.node);
|
|
33
|
+
const getMarkTypes = tags => {
|
|
34
|
+
const seen = new Set();
|
|
35
|
+
const marks = [];
|
|
36
|
+
for (const tag of tags) {
|
|
37
|
+
var _domParser$rules$find;
|
|
38
|
+
const markType = (_domParser$rules$find = domParser.rules.find(rule => rule.tag === tag)) === null || _domParser$rules$find === void 0 ? void 0 : _domParser$rules$find.mark;
|
|
39
|
+
if (markType && !seen.has(markType)) {
|
|
40
|
+
marks.push({
|
|
41
|
+
type: markType
|
|
42
|
+
});
|
|
43
|
+
seen.add(markType);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return marks;
|
|
47
|
+
};
|
|
48
|
+
const createParagraph = (content = []) => ({
|
|
49
|
+
type: 'paragraph',
|
|
50
|
+
content
|
|
51
|
+
});
|
|
52
|
+
const getBlockType = tag => {
|
|
53
|
+
const rule = domParser.rules.find(r => r.tag === tag);
|
|
54
|
+
return rule && 'node' in rule && rule.node ? rule.node : 'paragraph';
|
|
55
|
+
};
|
|
56
|
+
const createTextNode = (text, marks) => {
|
|
57
|
+
const markTypes = getMarkTypes(marks);
|
|
58
|
+
return {
|
|
59
|
+
type: 'text',
|
|
60
|
+
text,
|
|
61
|
+
...(markTypes.length > 0 && {
|
|
62
|
+
marks: markTypes
|
|
63
|
+
})
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
const addText = (text, marks, content) => {
|
|
67
|
+
if (text) {
|
|
68
|
+
content.push(createTextNode(text, marks));
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const handleBlockElement = (tag, innerContent, marks, blocks, currentParagraphContent, parseNode, nestedContainer) => {
|
|
72
|
+
// Push any accumulated content as paragraph before block element
|
|
73
|
+
if (currentParagraphContent.length > 0) {
|
|
74
|
+
blocks.push(createParagraph([...currentParagraphContent]));
|
|
75
|
+
currentParagraphContent.length = 0;
|
|
76
|
+
}
|
|
77
|
+
const blockType = getBlockType(tag);
|
|
78
|
+
const newMarks = shouldApplyMark(tag) ? [...marks, tag] : marks;
|
|
79
|
+
const parentNodeType = nestedContainer === null || nestedContainer === void 0 ? void 0 : nestedContainer.parentType;
|
|
80
|
+
if (nestedContainer && parentNodeType && isAllowedChild(parentNodeType, blockType)) {
|
|
81
|
+
const elementContent = [];
|
|
82
|
+
const childNestedContainer = canContainChildren(blockType) ? {
|
|
83
|
+
parentType: blockType,
|
|
84
|
+
children: elementContent
|
|
85
|
+
} : nestedContainer;
|
|
86
|
+
parseNode(innerContent, newMarks, childNestedContainer);
|
|
87
|
+
if (currentParagraphContent.length > 0) {
|
|
88
|
+
elementContent.push(createParagraph([...currentParagraphContent]));
|
|
89
|
+
currentParagraphContent.length = 0;
|
|
90
|
+
}
|
|
91
|
+
nestedContainer.children.push({
|
|
92
|
+
type: blockType,
|
|
93
|
+
content: elementContent.length > 0 ? elementContent : [createParagraph()]
|
|
94
|
+
});
|
|
95
|
+
} else if (canContainChildren(blockType)) {
|
|
96
|
+
const children = [];
|
|
97
|
+
parseNode(innerContent, newMarks, {
|
|
98
|
+
parentType: blockType,
|
|
99
|
+
children
|
|
100
|
+
});
|
|
101
|
+
blocks.push({
|
|
102
|
+
type: blockType,
|
|
103
|
+
content: children.length > 0 ? children : [createParagraph()]
|
|
104
|
+
});
|
|
105
|
+
} else {
|
|
106
|
+
// Regular block elements
|
|
107
|
+
parseNode(innerContent, newMarks, nestedContainer);
|
|
108
|
+
|
|
109
|
+
// Push content generated from block parsing
|
|
110
|
+
if (currentParagraphContent.length > 0) {
|
|
111
|
+
if (blockType === 'paragraph' || blockType === 'codeBlock') {
|
|
112
|
+
blocks.push({
|
|
113
|
+
type: blockType,
|
|
114
|
+
content: [...currentParagraphContent]
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
currentParagraphContent.length = 0;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const handleInlineElement = (tag, innerContent, marks, parseNode, nestedContainer) => {
|
|
122
|
+
const newMarks = shouldApplyMark(tag) ? [...marks, tag] : marks;
|
|
123
|
+
parseNode(innerContent, newMarks, nestedContainer);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Simple SSR-compatible parser that recognises text wrapped in HTML elements
|
|
128
|
+
* and extracts their content as ADF.
|
|
129
|
+
*
|
|
130
|
+
* Designed specifically for parsing i18n strings for ADF which specifically need to be
|
|
131
|
+
* HTML strings for translation.
|
|
132
|
+
*
|
|
133
|
+
* Supports nested structures automatically derived from the ADF schema:
|
|
134
|
+
* - Lists: ul/ol → li (listItem)
|
|
135
|
+
* - Tables: table → tr (tableRow) → td/th (tableCell/tableHeader)
|
|
136
|
+
* - Paragraphs, code blocks, and text marks
|
|
137
|
+
* - Any other nested structures defined in the schema
|
|
138
|
+
*
|
|
139
|
+
* @param html - The HTML string to parse
|
|
140
|
+
* @returns ADF DocNode containing the parsed content
|
|
141
|
+
*/
|
|
142
|
+
export const parseHTMLTextContent = html => {
|
|
143
|
+
const blocks = [];
|
|
144
|
+
const currentParagraphContent = [];
|
|
145
|
+
|
|
146
|
+
// Simple regex-based parser that works in both SSR and browser
|
|
147
|
+
const parseNode = (content, marks = [], nestedContainer) => {
|
|
148
|
+
// Match HTML tags and text content
|
|
149
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
150
|
+
const tagRegex = /<\s*(\w+)([^>]*)>([\s\S]*?)<\s*\/\s*\1\s*>|([^<]+)/g;
|
|
151
|
+
let match = tagRegex.exec(content);
|
|
152
|
+
while (match !== null) {
|
|
153
|
+
if (match[4]) {
|
|
154
|
+
addText(match[4], marks, currentParagraphContent);
|
|
155
|
+
} else {
|
|
156
|
+
// HTML element
|
|
157
|
+
const tag = match[1].toLowerCase();
|
|
158
|
+
const innerContent = match[3];
|
|
159
|
+
if (isBlockElement(tag)) {
|
|
160
|
+
handleBlockElement(tag, innerContent, marks, blocks, currentParagraphContent, parseNode, nestedContainer);
|
|
161
|
+
} else {
|
|
162
|
+
handleInlineElement(tag, innerContent, marks, parseNode, nestedContainer);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
match = tagRegex.exec(content);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
parseNode(html);
|
|
169
|
+
|
|
170
|
+
// Push any remaining content
|
|
171
|
+
if (currentParagraphContent.length > 0) {
|
|
172
|
+
blocks.push(createParagraph(currentParagraphContent));
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
type: 'doc',
|
|
176
|
+
version: 1,
|
|
177
|
+
content: blocks.length > 0 ? blocks : [createParagraph()]
|
|
178
|
+
};
|
|
179
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { syncBlockFallbackTransform, transformDedupeMarks, transformIndentationMarks, transformInvalidMediaContent, transformMediaLinkMarks, transformNestedTablesIncomingDocument, transformNodesMissingContent, transformTextLinkCodeMarks, transformMediaSingleWidth } from '@atlaskit/adf-utils/transforms';
|
|
2
2
|
import { Fragment, Node } from '@atlaskit/editor-prosemirror/model';
|
|
3
3
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
4
5
|
import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '../analytics';
|
|
5
6
|
import { sanitizeNodeForPrivacy } from './filter/privacy-filter';
|
|
6
7
|
import { findAndTrackUnsupportedContentNodes } from './track-unsupported-content';
|
|
@@ -214,11 +215,6 @@ export function processRawValue(schema, value, providerFactory, sanitizePrivateC
|
|
|
214
215
|
eventType: EVENT_TYPE.OPERATIONAL
|
|
215
216
|
});
|
|
216
217
|
}
|
|
217
|
-
|
|
218
|
-
// Convert nested-table extensions into nested tables
|
|
219
|
-
({
|
|
220
|
-
transformedAdf
|
|
221
|
-
} = transformNestedTablesWithAnalytics(transformedAdf, dispatchAnalyticsEvent));
|
|
222
218
|
if (dispatchAnalyticsEvent) {
|
|
223
219
|
var _transformedAdf$conte;
|
|
224
220
|
const hasSingleColumnLayout = (_transformedAdf$conte = transformedAdf.content) === null || _transformedAdf$conte === void 0 ? void 0 : _transformedAdf$conte.some(node => {
|
|
@@ -233,7 +229,24 @@ export function processRawValue(schema, value, providerFactory, sanitizePrivateC
|
|
|
233
229
|
});
|
|
234
230
|
}
|
|
235
231
|
}
|
|
236
|
-
|
|
232
|
+
let entity;
|
|
233
|
+
if (expValEquals('platform_editor_ssr_renderer', 'isEnabled', true)) {
|
|
234
|
+
// Validate ADF first before converting nested-table extensions into nested tables
|
|
235
|
+
// This matches the renderer's behavior in render-document.ts
|
|
236
|
+
entity = validateADFEntity(schema, transformedAdf || node, dispatchAnalyticsEvent);
|
|
237
|
+
|
|
238
|
+
// Convert nested-table extensions into nested tables
|
|
239
|
+
({
|
|
240
|
+
transformedAdf
|
|
241
|
+
} = transformNestedTablesWithAnalytics(entity, dispatchAnalyticsEvent));
|
|
242
|
+
entity = transformedAdf;
|
|
243
|
+
} else {
|
|
244
|
+
// Convert nested-table extensions into nested tables
|
|
245
|
+
({
|
|
246
|
+
transformedAdf
|
|
247
|
+
} = transformNestedTablesWithAnalytics(transformedAdf, dispatchAnalyticsEvent));
|
|
248
|
+
entity = validateADFEntity(schema, transformedAdf || node, dispatchAnalyticsEvent);
|
|
249
|
+
}
|
|
237
250
|
const newEntity = maySanitizePrivateContent(entity, providerFactory, sanitizePrivateContent);
|
|
238
251
|
const parsedDoc = Node.fromJSON(schema, newEntity);
|
|
239
252
|
|
|
@@ -194,5 +194,15 @@ export default defineMessages({
|
|
|
194
194
|
id: 'fabric.editor.imageEdit',
|
|
195
195
|
defaultMessage: 'Edit image',
|
|
196
196
|
description: 'Crop, flip or rotate the image'
|
|
197
|
+
},
|
|
198
|
+
error: {
|
|
199
|
+
id: 'fabric.editor.error.message.label',
|
|
200
|
+
defaultMessage: 'Error',
|
|
201
|
+
description: 'Label for error message icon'
|
|
202
|
+
},
|
|
203
|
+
success: {
|
|
204
|
+
id: 'fabric.editor.success.message.label',
|
|
205
|
+
defaultMessage: 'Success',
|
|
206
|
+
description: 'Label for success message icon'
|
|
197
207
|
}
|
|
198
208
|
});
|
|
@@ -10,7 +10,7 @@ import { isFedRamp } from './environment';
|
|
|
10
10
|
import { normaliseSentryBreadcrumbs, SERIALIZABLE_ATTRIBUTES } from './normalise-sentry-breadcrumbs';
|
|
11
11
|
var SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
|
|
12
12
|
var packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
|
|
13
|
-
var packageVersion = "110.49.
|
|
13
|
+
var packageVersion = "110.49.2";
|
|
14
14
|
var sanitiseSentryEvents = function sanitiseSentryEvents(data, _hint) {
|
|
15
15
|
// Remove URL as it has UGC
|
|
16
16
|
// Ignored via go/ees007
|
|
@@ -21,7 +21,7 @@ import withAnalyticsEvents from '@atlaskit/analytics-next/withAnalyticsEvents';
|
|
|
21
21
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
22
22
|
import Layer from '../Layer';
|
|
23
23
|
var packageName = "@atlaskit/editor-common";
|
|
24
|
-
var packageVersion = "110.49.
|
|
24
|
+
var packageVersion = "110.49.2";
|
|
25
25
|
var halfFocusRing = 1;
|
|
26
26
|
var dropOffset = '0, 8';
|
|
27
27
|
var fadeIn = keyframes({
|
|
@@ -5,8 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
7
7
|
import { css, jsx } from '@emotion/react';
|
|
8
|
+
import { useIntl } from 'react-intl-next';
|
|
8
9
|
import ErrorIcon from '@atlaskit/icon/core/status-error';
|
|
9
10
|
import SuccessIcon from '@atlaskit/icon/core/status-success';
|
|
11
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
12
|
+
import commonMessages from '../../messages';
|
|
10
13
|
var errorColor = css({
|
|
11
14
|
color: "var(--ds-text-danger, #AE2E24)"
|
|
12
15
|
});
|
|
@@ -44,13 +47,18 @@ export var HelperMessage = function HelperMessage(_ref) {
|
|
|
44
47
|
};
|
|
45
48
|
export var ErrorMessage = function ErrorMessage(_ref2) {
|
|
46
49
|
var children = _ref2.children;
|
|
50
|
+
var intl = useIntl();
|
|
47
51
|
return jsx("div", {
|
|
48
52
|
css: function css() {
|
|
49
53
|
return [messageStyle(), errorColor];
|
|
50
54
|
}
|
|
51
55
|
}, jsx("span", {
|
|
52
56
|
css: iconWrapperStyle
|
|
53
|
-
}, jsx(ErrorIcon, {
|
|
57
|
+
}, fg('platform_editor_dec_a11y_fixes') ? jsx(ErrorIcon, {
|
|
58
|
+
LEGACY_size: "small",
|
|
59
|
+
label: intl.formatMessage(commonMessages.error)
|
|
60
|
+
})
|
|
61
|
+
/* eslint-disable-next-line @atlassian/i18n/no-literal-string-in-jsx */ : jsx(ErrorIcon, {
|
|
54
62
|
LEGACY_size: "small",
|
|
55
63
|
label: "error",
|
|
56
64
|
"aria-label": "error"
|
|
@@ -58,13 +66,17 @@ export var ErrorMessage = function ErrorMessage(_ref2) {
|
|
|
58
66
|
};
|
|
59
67
|
export var ValidMessage = function ValidMessage(_ref3) {
|
|
60
68
|
var children = _ref3.children;
|
|
69
|
+
var intl = useIntl();
|
|
61
70
|
return jsx("div", {
|
|
62
71
|
css: function css() {
|
|
63
72
|
return [messageStyle(), validColor];
|
|
64
73
|
}
|
|
65
74
|
}, jsx("span", {
|
|
66
75
|
css: iconWrapperStyle
|
|
67
|
-
}, jsx(SuccessIcon, {
|
|
76
|
+
}, fg('platform_editor_dec_a11y_fixes') ? jsx(SuccessIcon, {
|
|
77
|
+
LEGACY_size: "small",
|
|
78
|
+
label: intl.formatMessage(commonMessages.success)
|
|
79
|
+
}) : jsx(SuccessIcon, {
|
|
68
80
|
LEGACY_size: "small",
|
|
69
81
|
label: "success"
|
|
70
82
|
})), children);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { parseHTMLTextContent } from './parse-html-text-content';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates ADF from HTML string.
|
|
5
|
+
* This is particularly useful for providing translations in HTML to be supported and we convert back to ADF here
|
|
6
|
+
* See: https://developer.atlassian.com/platform/localization/i18n-formatting/avoiding-concatenation/
|
|
7
|
+
*
|
|
8
|
+
* This function only supports a subset of the schema as it is intended for translations, but it supports
|
|
9
|
+
* SSR as it has no DOM dependencies and is lightweight.
|
|
10
|
+
*
|
|
11
|
+
* @param html - The HTML string to convert to ADF
|
|
12
|
+
* @returns ADF DocNode or undefined if parsing fails
|
|
13
|
+
*/
|
|
14
|
+
export var createADFFromHTML = function createADFFromHTML(html) {
|
|
15
|
+
return parseHTMLTextContent(html);
|
|
16
|
+
};
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
3
|
+
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; }
|
|
4
|
+
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; }
|
|
5
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
6
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
7
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
8
|
+
import { defaultSchema } from '@atlaskit/adf-schema/schema-default';
|
|
9
|
+
import { DOMParser } from '@atlaskit/editor-prosemirror/model';
|
|
10
|
+
var domParser = DOMParser.fromSchema(defaultSchema);
|
|
11
|
+
export var getNestingRulesFromSchema = function getNestingRulesFromSchema() {
|
|
12
|
+
var KEYWORDS = ['inline', 'block', 'text', 'leaf', 'group', 'unsupportedBlock', 'unsupportedInline'];
|
|
13
|
+
var rules = {};
|
|
14
|
+
for (var _i = 0, _Object$keys = Object.keys(defaultSchema.nodes); _i < _Object$keys.length; _i++) {
|
|
15
|
+
var _defaultSchema$nodes$;
|
|
16
|
+
var nodeType = _Object$keys[_i];
|
|
17
|
+
var contentStr = (_defaultSchema$nodes$ = defaultSchema.nodes[nodeType]) === null || _defaultSchema$nodes$ === void 0 ? void 0 : _defaultSchema$nodes$.spec.content;
|
|
18
|
+
if (!contentStr) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
var allowedChildren =
|
|
22
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
23
|
+
(String(contentStr).match(/\b([a-zA-Z_][a-zA-Z0-9_]*)\b/g) || []).filter(function (match, index, arr) {
|
|
24
|
+
return !KEYWORDS.includes(match) && defaultSchema.nodes[match] && arr.indexOf(match) === index;
|
|
25
|
+
});
|
|
26
|
+
if (allowedChildren.length > 0) {
|
|
27
|
+
rules[nodeType] = allowedChildren;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return rules;
|
|
31
|
+
};
|
|
32
|
+
var NESTING_RULES = getNestingRulesFromSchema();
|
|
33
|
+
var canContainChildren = function canContainChildren(nodeType) {
|
|
34
|
+
var _NESTING_RULES$nodeTy;
|
|
35
|
+
return !!((_NESTING_RULES$nodeTy = NESTING_RULES[nodeType]) !== null && _NESTING_RULES$nodeTy !== void 0 && _NESTING_RULES$nodeTy.length);
|
|
36
|
+
};
|
|
37
|
+
var isAllowedChild = function isAllowedChild(parent, child) {
|
|
38
|
+
var _NESTING_RULES$parent, _NESTING_RULES$parent2;
|
|
39
|
+
return (_NESTING_RULES$parent = (_NESTING_RULES$parent2 = NESTING_RULES[parent]) === null || _NESTING_RULES$parent2 === void 0 ? void 0 : _NESTING_RULES$parent2.includes(child)) !== null && _NESTING_RULES$parent !== void 0 ? _NESTING_RULES$parent : false;
|
|
40
|
+
};
|
|
41
|
+
var shouldApplyMark = function shouldApplyMark(tag) {
|
|
42
|
+
return domParser.rules.some(function (rule) {
|
|
43
|
+
return 'mark' in rule && rule.tag === tag;
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
var isBlockElement = function isBlockElement(tag) {
|
|
47
|
+
return domParser.rules.some(function (rule) {
|
|
48
|
+
return rule.tag === tag && rule.node;
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
var getMarkTypes = function getMarkTypes(tags) {
|
|
52
|
+
var seen = new Set();
|
|
53
|
+
var marks = [];
|
|
54
|
+
var _iterator = _createForOfIteratorHelper(tags),
|
|
55
|
+
_step;
|
|
56
|
+
try {
|
|
57
|
+
var _loop = function _loop() {
|
|
58
|
+
var _domParser$rules$find;
|
|
59
|
+
var tag = _step.value;
|
|
60
|
+
var markType = (_domParser$rules$find = domParser.rules.find(function (rule) {
|
|
61
|
+
return rule.tag === tag;
|
|
62
|
+
})) === null || _domParser$rules$find === void 0 ? void 0 : _domParser$rules$find.mark;
|
|
63
|
+
if (markType && !seen.has(markType)) {
|
|
64
|
+
marks.push({
|
|
65
|
+
type: markType
|
|
66
|
+
});
|
|
67
|
+
seen.add(markType);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
71
|
+
_loop();
|
|
72
|
+
}
|
|
73
|
+
} catch (err) {
|
|
74
|
+
_iterator.e(err);
|
|
75
|
+
} finally {
|
|
76
|
+
_iterator.f();
|
|
77
|
+
}
|
|
78
|
+
return marks;
|
|
79
|
+
};
|
|
80
|
+
var createParagraph = function createParagraph() {
|
|
81
|
+
var content = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
82
|
+
return {
|
|
83
|
+
type: 'paragraph',
|
|
84
|
+
content: content
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
var getBlockType = function getBlockType(tag) {
|
|
88
|
+
var rule = domParser.rules.find(function (r) {
|
|
89
|
+
return r.tag === tag;
|
|
90
|
+
});
|
|
91
|
+
return rule && 'node' in rule && rule.node ? rule.node : 'paragraph';
|
|
92
|
+
};
|
|
93
|
+
var createTextNode = function createTextNode(text, marks) {
|
|
94
|
+
var markTypes = getMarkTypes(marks);
|
|
95
|
+
return _objectSpread({
|
|
96
|
+
type: 'text',
|
|
97
|
+
text: text
|
|
98
|
+
}, markTypes.length > 0 && {
|
|
99
|
+
marks: markTypes
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
var addText = function addText(text, marks, content) {
|
|
103
|
+
if (text) {
|
|
104
|
+
content.push(createTextNode(text, marks));
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
var handleBlockElement = function handleBlockElement(tag, innerContent, marks, blocks, currentParagraphContent, parseNode, nestedContainer) {
|
|
108
|
+
// Push any accumulated content as paragraph before block element
|
|
109
|
+
if (currentParagraphContent.length > 0) {
|
|
110
|
+
blocks.push(createParagraph(_toConsumableArray(currentParagraphContent)));
|
|
111
|
+
currentParagraphContent.length = 0;
|
|
112
|
+
}
|
|
113
|
+
var blockType = getBlockType(tag);
|
|
114
|
+
var newMarks = shouldApplyMark(tag) ? [].concat(_toConsumableArray(marks), [tag]) : marks;
|
|
115
|
+
var parentNodeType = nestedContainer === null || nestedContainer === void 0 ? void 0 : nestedContainer.parentType;
|
|
116
|
+
if (nestedContainer && parentNodeType && isAllowedChild(parentNodeType, blockType)) {
|
|
117
|
+
var elementContent = [];
|
|
118
|
+
var childNestedContainer = canContainChildren(blockType) ? {
|
|
119
|
+
parentType: blockType,
|
|
120
|
+
children: elementContent
|
|
121
|
+
} : nestedContainer;
|
|
122
|
+
parseNode(innerContent, newMarks, childNestedContainer);
|
|
123
|
+
if (currentParagraphContent.length > 0) {
|
|
124
|
+
elementContent.push(createParagraph(_toConsumableArray(currentParagraphContent)));
|
|
125
|
+
currentParagraphContent.length = 0;
|
|
126
|
+
}
|
|
127
|
+
nestedContainer.children.push({
|
|
128
|
+
type: blockType,
|
|
129
|
+
content: elementContent.length > 0 ? elementContent : [createParagraph()]
|
|
130
|
+
});
|
|
131
|
+
} else if (canContainChildren(blockType)) {
|
|
132
|
+
var children = [];
|
|
133
|
+
parseNode(innerContent, newMarks, {
|
|
134
|
+
parentType: blockType,
|
|
135
|
+
children: children
|
|
136
|
+
});
|
|
137
|
+
blocks.push({
|
|
138
|
+
type: blockType,
|
|
139
|
+
content: children.length > 0 ? children : [createParagraph()]
|
|
140
|
+
});
|
|
141
|
+
} else {
|
|
142
|
+
// Regular block elements
|
|
143
|
+
parseNode(innerContent, newMarks, nestedContainer);
|
|
144
|
+
|
|
145
|
+
// Push content generated from block parsing
|
|
146
|
+
if (currentParagraphContent.length > 0) {
|
|
147
|
+
if (blockType === 'paragraph' || blockType === 'codeBlock') {
|
|
148
|
+
blocks.push({
|
|
149
|
+
type: blockType,
|
|
150
|
+
content: _toConsumableArray(currentParagraphContent)
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
currentParagraphContent.length = 0;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
var handleInlineElement = function handleInlineElement(tag, innerContent, marks, parseNode, nestedContainer) {
|
|
158
|
+
var newMarks = shouldApplyMark(tag) ? [].concat(_toConsumableArray(marks), [tag]) : marks;
|
|
159
|
+
parseNode(innerContent, newMarks, nestedContainer);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Simple SSR-compatible parser that recognises text wrapped in HTML elements
|
|
164
|
+
* and extracts their content as ADF.
|
|
165
|
+
*
|
|
166
|
+
* Designed specifically for parsing i18n strings for ADF which specifically need to be
|
|
167
|
+
* HTML strings for translation.
|
|
168
|
+
*
|
|
169
|
+
* Supports nested structures automatically derived from the ADF schema:
|
|
170
|
+
* - Lists: ul/ol → li (listItem)
|
|
171
|
+
* - Tables: table → tr (tableRow) → td/th (tableCell/tableHeader)
|
|
172
|
+
* - Paragraphs, code blocks, and text marks
|
|
173
|
+
* - Any other nested structures defined in the schema
|
|
174
|
+
*
|
|
175
|
+
* @param html - The HTML string to parse
|
|
176
|
+
* @returns ADF DocNode containing the parsed content
|
|
177
|
+
*/
|
|
178
|
+
export var parseHTMLTextContent = function parseHTMLTextContent(html) {
|
|
179
|
+
var blocks = [];
|
|
180
|
+
var currentParagraphContent = [];
|
|
181
|
+
|
|
182
|
+
// Simple regex-based parser that works in both SSR and browser
|
|
183
|
+
var _parseNode = function parseNode(content) {
|
|
184
|
+
var marks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
185
|
+
var nestedContainer = arguments.length > 2 ? arguments[2] : undefined;
|
|
186
|
+
// Match HTML tags and text content
|
|
187
|
+
// eslint-disable-next-line require-unicode-regexp
|
|
188
|
+
var tagRegex = /<\s*(\w+)([^>]*)>([\s\S]*?)<\s*\/\s*\1\s*>|([^<]+)/g;
|
|
189
|
+
var match = tagRegex.exec(content);
|
|
190
|
+
while (match !== null) {
|
|
191
|
+
if (match[4]) {
|
|
192
|
+
addText(match[4], marks, currentParagraphContent);
|
|
193
|
+
} else {
|
|
194
|
+
// HTML element
|
|
195
|
+
var tag = match[1].toLowerCase();
|
|
196
|
+
var innerContent = match[3];
|
|
197
|
+
if (isBlockElement(tag)) {
|
|
198
|
+
handleBlockElement(tag, innerContent, marks, blocks, currentParagraphContent, _parseNode, nestedContainer);
|
|
199
|
+
} else {
|
|
200
|
+
handleInlineElement(tag, innerContent, marks, _parseNode, nestedContainer);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
match = tagRegex.exec(content);
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
_parseNode(html);
|
|
207
|
+
|
|
208
|
+
// Push any remaining content
|
|
209
|
+
if (currentParagraphContent.length > 0) {
|
|
210
|
+
blocks.push(createParagraph(currentParagraphContent));
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
type: 'doc',
|
|
214
|
+
version: 1,
|
|
215
|
+
content: blocks.length > 0 ? blocks : [createParagraph()]
|
|
216
|
+
};
|
|
217
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { syncBlockFallbackTransform, transformDedupeMarks, transformIndentationMarks, transformInvalidMediaContent, transformMediaLinkMarks, transformNestedTablesIncomingDocument, transformNodesMissingContent, transformTextLinkCodeMarks, transformMediaSingleWidth } from '@atlaskit/adf-utils/transforms';
|
|
2
2
|
import { Fragment, Node } from '@atlaskit/editor-prosemirror/model';
|
|
3
3
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
4
5
|
import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '../analytics';
|
|
5
6
|
import { sanitizeNodeForPrivacy } from './filter/privacy-filter';
|
|
6
7
|
import { findAndTrackUnsupportedContentNodes } from './track-unsupported-content';
|
|
@@ -207,10 +208,6 @@ export function processRawValue(schema, value, providerFactory, sanitizePrivateC
|
|
|
207
208
|
eventType: EVENT_TYPE.OPERATIONAL
|
|
208
209
|
});
|
|
209
210
|
}
|
|
210
|
-
|
|
211
|
-
// Convert nested-table extensions into nested tables
|
|
212
|
-
var _transformNestedTable3 = transformNestedTablesWithAnalytics(transformedAdf, dispatchAnalyticsEvent);
|
|
213
|
-
transformedAdf = _transformNestedTable3.transformedAdf;
|
|
214
211
|
if (dispatchAnalyticsEvent) {
|
|
215
212
|
var _transformedAdf$conte;
|
|
216
213
|
var hasSingleColumnLayout = (_transformedAdf$conte = transformedAdf.content) === null || _transformedAdf$conte === void 0 ? void 0 : _transformedAdf$conte.some(function (node) {
|
|
@@ -225,7 +222,22 @@ export function processRawValue(schema, value, providerFactory, sanitizePrivateC
|
|
|
225
222
|
});
|
|
226
223
|
}
|
|
227
224
|
}
|
|
228
|
-
var entity
|
|
225
|
+
var entity;
|
|
226
|
+
if (expValEquals('platform_editor_ssr_renderer', 'isEnabled', true)) {
|
|
227
|
+
// Validate ADF first before converting nested-table extensions into nested tables
|
|
228
|
+
// This matches the renderer's behavior in render-document.ts
|
|
229
|
+
entity = validateADFEntity(schema, transformedAdf || node, dispatchAnalyticsEvent);
|
|
230
|
+
|
|
231
|
+
// Convert nested-table extensions into nested tables
|
|
232
|
+
var _transformNestedTable3 = transformNestedTablesWithAnalytics(entity, dispatchAnalyticsEvent);
|
|
233
|
+
transformedAdf = _transformNestedTable3.transformedAdf;
|
|
234
|
+
entity = transformedAdf;
|
|
235
|
+
} else {
|
|
236
|
+
// Convert nested-table extensions into nested tables
|
|
237
|
+
var _transformNestedTable4 = transformNestedTablesWithAnalytics(transformedAdf, dispatchAnalyticsEvent);
|
|
238
|
+
transformedAdf = _transformNestedTable4.transformedAdf;
|
|
239
|
+
entity = validateADFEntity(schema, transformedAdf || node, dispatchAnalyticsEvent);
|
|
240
|
+
}
|
|
229
241
|
var newEntity = maySanitizePrivateContent(entity, providerFactory, sanitizePrivateContent);
|
|
230
242
|
var parsedDoc = Node.fromJSON(schema, newEntity);
|
|
231
243
|
|
|
@@ -191,5 +191,15 @@ declare const _default: {
|
|
|
191
191
|
defaultMessage: string;
|
|
192
192
|
description: string;
|
|
193
193
|
};
|
|
194
|
+
error: {
|
|
195
|
+
id: string;
|
|
196
|
+
defaultMessage: string;
|
|
197
|
+
description: string;
|
|
198
|
+
};
|
|
199
|
+
success: {
|
|
200
|
+
id: string;
|
|
201
|
+
defaultMessage: string;
|
|
202
|
+
description: string;
|
|
203
|
+
};
|
|
194
204
|
};
|
|
195
205
|
export default _default;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DocNode } from '@atlaskit/adf-schema';
|
|
2
|
+
/**
|
|
3
|
+
* Creates ADF from HTML string.
|
|
4
|
+
* This is particularly useful for providing translations in HTML to be supported and we convert back to ADF here
|
|
5
|
+
* See: https://developer.atlassian.com/platform/localization/i18n-formatting/avoiding-concatenation/
|
|
6
|
+
*
|
|
7
|
+
* This function only supports a subset of the schema as it is intended for translations, but it supports
|
|
8
|
+
* SSR as it has no DOM dependencies and is lightweight.
|
|
9
|
+
*
|
|
10
|
+
* @param html - The HTML string to convert to ADF
|
|
11
|
+
* @returns ADF DocNode or undefined if parsing fails
|
|
12
|
+
*/
|
|
13
|
+
export declare const createADFFromHTML: (html: string) => DocNode;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DocNode } from '@atlaskit/adf-schema';
|
|
2
|
+
export declare const getNestingRulesFromSchema: () => Record<string, string[]>;
|
|
3
|
+
/**
|
|
4
|
+
* Simple SSR-compatible parser that recognises text wrapped in HTML elements
|
|
5
|
+
* and extracts their content as ADF.
|
|
6
|
+
*
|
|
7
|
+
* Designed specifically for parsing i18n strings for ADF which specifically need to be
|
|
8
|
+
* HTML strings for translation.
|
|
9
|
+
*
|
|
10
|
+
* Supports nested structures automatically derived from the ADF schema:
|
|
11
|
+
* - Lists: ul/ol → li (listItem)
|
|
12
|
+
* - Tables: table → tr (tableRow) → td/th (tableCell/tableHeader)
|
|
13
|
+
* - Paragraphs, code blocks, and text marks
|
|
14
|
+
* - Any other nested structures defined in the schema
|
|
15
|
+
*
|
|
16
|
+
* @param html - The HTML string to parse
|
|
17
|
+
* @returns ADF DocNode containing the parsed content
|
|
18
|
+
*/
|
|
19
|
+
export declare const parseHTMLTextContent: (html: string) => DocNode;
|
|
@@ -191,5 +191,15 @@ declare const _default: {
|
|
|
191
191
|
defaultMessage: string;
|
|
192
192
|
description: string;
|
|
193
193
|
};
|
|
194
|
+
error: {
|
|
195
|
+
id: string;
|
|
196
|
+
defaultMessage: string;
|
|
197
|
+
description: string;
|
|
198
|
+
};
|
|
199
|
+
success: {
|
|
200
|
+
id: string;
|
|
201
|
+
defaultMessage: string;
|
|
202
|
+
description: string;
|
|
203
|
+
};
|
|
194
204
|
};
|
|
195
205
|
export default _default;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DocNode } from '@atlaskit/adf-schema';
|
|
2
|
+
/**
|
|
3
|
+
* Creates ADF from HTML string.
|
|
4
|
+
* This is particularly useful for providing translations in HTML to be supported and we convert back to ADF here
|
|
5
|
+
* See: https://developer.atlassian.com/platform/localization/i18n-formatting/avoiding-concatenation/
|
|
6
|
+
*
|
|
7
|
+
* This function only supports a subset of the schema as it is intended for translations, but it supports
|
|
8
|
+
* SSR as it has no DOM dependencies and is lightweight.
|
|
9
|
+
*
|
|
10
|
+
* @param html - The HTML string to convert to ADF
|
|
11
|
+
* @returns ADF DocNode or undefined if parsing fails
|
|
12
|
+
*/
|
|
13
|
+
export declare const createADFFromHTML: (html: string) => DocNode;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DocNode } from '@atlaskit/adf-schema';
|
|
2
|
+
export declare const getNestingRulesFromSchema: () => Record<string, string[]>;
|
|
3
|
+
/**
|
|
4
|
+
* Simple SSR-compatible parser that recognises text wrapped in HTML elements
|
|
5
|
+
* and extracts their content as ADF.
|
|
6
|
+
*
|
|
7
|
+
* Designed specifically for parsing i18n strings for ADF which specifically need to be
|
|
8
|
+
* HTML strings for translation.
|
|
9
|
+
*
|
|
10
|
+
* Supports nested structures automatically derived from the ADF schema:
|
|
11
|
+
* - Lists: ul/ol → li (listItem)
|
|
12
|
+
* - Tables: table → tr (tableRow) → td/th (tableCell/tableHeader)
|
|
13
|
+
* - Paragraphs, code blocks, and text marks
|
|
14
|
+
* - Any other nested structures defined in the schema
|
|
15
|
+
*
|
|
16
|
+
* @param html - The HTML string to parse
|
|
17
|
+
* @returns ADF DocNode containing the parsed content
|
|
18
|
+
*/
|
|
19
|
+
export declare const parseHTMLTextContent: (html: string) => DocNode;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-common",
|
|
3
|
-
"version": "110.
|
|
3
|
+
"version": "110.50.0",
|
|
4
4
|
"description": "A package that contains common classes and components for editor and renderer",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"@atlaskit/media-viewer": "^52.5.0",
|
|
66
66
|
"@atlaskit/mention": "^24.4.0",
|
|
67
67
|
"@atlaskit/menu": "^8.4.0",
|
|
68
|
-
"@atlaskit/onboarding": "^14.
|
|
68
|
+
"@atlaskit/onboarding": "^14.5.0",
|
|
69
69
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
70
70
|
"@atlaskit/platform-feature-flags-react": "^0.4.0",
|
|
71
71
|
"@atlaskit/popper": "^7.1.0",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"@atlaskit/task-decision": "^19.2.0",
|
|
82
82
|
"@atlaskit/textfield": "^8.2.0",
|
|
83
83
|
"@atlaskit/theme": "^21.0.0",
|
|
84
|
-
"@atlaskit/tmp-editor-statsig": "^16.
|
|
84
|
+
"@atlaskit/tmp-editor-statsig": "^16.3.0",
|
|
85
85
|
"@atlaskit/tokens": "^9.0.0",
|
|
86
86
|
"@atlaskit/tooltip": "^20.11.0",
|
|
87
87
|
"@atlaskit/width-detector": "^5.0.0",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaskit/editor-common/utils/create-adf-from-html",
|
|
3
|
+
"main": "../../dist/cjs/utils/create-adf-from-html.js",
|
|
4
|
+
"module": "../../dist/esm/utils/create-adf-from-html.js",
|
|
5
|
+
"module:es2019": "../../dist/es2019/utils/create-adf-from-html.js",
|
|
6
|
+
"sideEffects": [
|
|
7
|
+
"**/*.compiled.css"
|
|
8
|
+
],
|
|
9
|
+
"types": "../../dist/types/utils/create-adf-from-html.d.ts",
|
|
10
|
+
"typesVersions": {
|
|
11
|
+
">=4.5 <5.9": {
|
|
12
|
+
"*": [
|
|
13
|
+
"../../dist/types-ts4.5/utils/create-adf-from-html.d.ts"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|