@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
285 lines (279 loc) • 11.2 kB
JavaScript
import { transformDedupeMarks, transformIndentationMarks, transformInvalidMediaContent, transformMediaLinkMarks, transformNestedTablesIncomingDocument, transformNodesMissingContent, transformTextLinkCodeMarks } from '@atlaskit/adf-utils/transforms';
import { Fragment, Node } from '@atlaskit/editor-prosemirror/model';
import { fg } from '@atlaskit/platform-feature-flags';
import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '../analytics';
import { sanitizeNodeForPrivacy } from './filter/privacy-filter';
import { findAndTrackUnsupportedContentNodes } from './track-unsupported-content';
import { validateADFEntity } from './validate-using-spec';
var transformNestedTablesWithAnalytics = function transformNestedTablesWithAnalytics(node, dispatchAnalyticsEvent) {
try {
var _transformNestedTable = transformNestedTablesIncomingDocument(node),
transformedAdf = _transformNestedTable.transformedAdf,
isTransformed = _transformNestedTable.isTransformed;
if (isTransformed && dispatchAnalyticsEvent) {
dispatchAnalyticsEvent({
action: ACTION.NESTED_TABLE_TRANSFORMED,
actionSubject: ACTION_SUBJECT.EDITOR,
eventType: EVENT_TYPE.OPERATIONAL
});
return {
transformedAdf: transformedAdf,
isTransformed: isTransformed
};
}
} catch (e) {
// eslint-disable-next-line no-console
console.error('Failed to transform one or more nested tables in the document');
if (dispatchAnalyticsEvent) {
dispatchAnalyticsEvent({
action: ACTION.DOCUMENT_PROCESSING_ERROR,
actionSubject: ACTION_SUBJECT.EDITOR,
eventType: EVENT_TYPE.OPERATIONAL,
attributes: {
errorMessage: "".concat(e instanceof Error && e.name === 'NodeNestingTransformError' ? 'NodeNestingTransformError - Failed to transform one or more nested tables' : undefined)
}
});
}
}
return {
transformedAdf: node,
isTransformed: false
};
};
export function processRawValueWithoutValidation(schema, value, dispatchAnalyticsEvent) {
if (!value) {
return;
}
var node;
if (typeof value === 'string') {
try {
node = JSON.parse(value);
} catch (e) {
// eslint-disable-next-line no-console
console.error("Error processing value: ".concat(value, " isn't a valid JSON"));
return;
}
} else {
node = value;
}
if (fg('platform_editor_use_nested_table_pm_nodes')) {
// Convert nested-table extensions into nested tables
var _transformNestedTable2 = transformNestedTablesWithAnalytics(node, dispatchAnalyticsEvent),
transformedAdf = _transformNestedTable2.transformedAdf;
return Node.fromJSON(schema, transformedAdf);
} else {
return Node.fromJSON(schema, node);
}
}
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/max-params
export function processRawValue(schema, value, providerFactory, sanitizePrivateContent, contentTransformer, dispatchAnalyticsEvent) {
if (!value) {
return;
}
var node;
if (typeof value === 'string') {
try {
if (contentTransformer) {
var doc = contentTransformer.parse(value);
node = doc.toJSON();
} else {
node = JSON.parse(value);
}
} catch (e) {
// eslint-disable-next-line no-console
console.error("Error processing value: ".concat(value, " isn't a valid JSON"));
return;
}
} else {
node = value;
}
if (Array.isArray(node)) {
// eslint-disable-next-line no-console
console.error("Error processing value: ".concat(node, " is an array, but it must be an object."));
return;
}
try {
// ProseMirror always require a child under doc
if (node.type === 'doc') {
if (Array.isArray(node.content) && node.content.length === 0) {
node.content.push({
type: 'paragraph',
content: []
});
}
// Just making sure doc is always valid
if (!node.version) {
node.version = 1;
}
}
if (contentTransformer) {
return Node.fromJSON(schema, node);
}
// link mark on mediaSingle is deprecated, need to move link mark to child media node
// https://product-fabric.atlassian.net/browse/ED-14043
var _transformMediaLinkMa = transformMediaLinkMarks(node),
transformedAdf = _transformMediaLinkMa.transformedAdf,
isTransformed = _transformMediaLinkMa.isTransformed;
if (isTransformed && dispatchAnalyticsEvent) {
dispatchAnalyticsEvent({
action: ACTION.MEDIA_LINK_TRANSFORMED,
actionSubject: ACTION_SUBJECT.EDITOR,
eventType: EVENT_TYPE.OPERATIONAL
});
}
// See: HOT-97965 https://product-fabric.atlassian.net/browse/ED-14400
// We declared in code mark spec that links and marks should not co-exist on
// text nodes. This util strips code marks from bad text nodes and preserves links.
// Otherwise, prosemirror will try to repair the invalid document by stripping links
// and preserving code marks during content changes.
var _transformTextLinkCod = transformTextLinkCodeMarks(transformedAdf);
transformedAdf = _transformTextLinkCod.transformedAdf;
isTransformed = _transformTextLinkCod.isTransformed;
if (isTransformed && dispatchAnalyticsEvent) {
dispatchAnalyticsEvent({
action: ACTION.TEXT_LINK_MARK_TRANSFORMED,
actionSubject: ACTION_SUBJECT.EDITOR,
eventType: EVENT_TYPE.OPERATIONAL
});
}
var discardedMarks = [];
var _transformDedupeMarks = transformDedupeMarks(transformedAdf);
transformedAdf = _transformDedupeMarks.transformedAdf;
isTransformed = _transformDedupeMarks.isTransformed;
discardedMarks = _transformDedupeMarks.discardedMarks;
if (isTransformed && dispatchAnalyticsEvent) {
dispatchAnalyticsEvent({
action: ACTION.DEDUPE_MARKS_TRANSFORMED_V2,
actionSubject: ACTION_SUBJECT.EDITOR,
eventType: EVENT_TYPE.OPERATIONAL,
attributes: {
/** UGC WARNING
*
* DO NOT include the `mark` attributes inside, we map here to only
* extract the mark type as that is the only non-UGC safe information
* that we can add to event-attributes
*
*/
discardedMarkTypes: discardedMarks.map(function (mark) {
return mark.type;
})
}
});
}
var _transformNodesMissin = transformNodesMissingContent(transformedAdf);
transformedAdf = _transformNodesMissin.transformedAdf;
isTransformed = _transformNodesMissin.isTransformed;
if (isTransformed && dispatchAnalyticsEvent) {
dispatchAnalyticsEvent({
action: ACTION.NODES_MISSING_CONTENT_TRANSFORMED,
actionSubject: ACTION_SUBJECT.EDITOR,
eventType: EVENT_TYPE.OPERATIONAL
});
}
var _transformIndentation = transformIndentationMarks(transformedAdf);
transformedAdf = _transformIndentation.transformedAdf;
isTransformed = _transformIndentation.isTransformed;
if (isTransformed && dispatchAnalyticsEvent) {
dispatchAnalyticsEvent({
action: ACTION.INDENTATION_MARKS_TRANSFORMED,
actionSubject: ACTION_SUBJECT.EDITOR,
eventType: EVENT_TYPE.OPERATIONAL
});
}
var _transformInvalidMedi = transformInvalidMediaContent(transformedAdf);
transformedAdf = _transformInvalidMedi.transformedAdf;
isTransformed = _transformInvalidMedi.isTransformed;
if (isTransformed && dispatchAnalyticsEvent) {
dispatchAnalyticsEvent({
action: ACTION.INVALID_MEDIA_CONTENT_TRANSFORMED,
actionSubject: ACTION_SUBJECT.EDITOR,
eventType: EVENT_TYPE.OPERATIONAL
});
}
if (fg('platform_editor_use_nested_table_pm_nodes')) {
// Convert nested-table extensions into nested tables
var _transformNestedTable3 = transformNestedTablesWithAnalytics(transformedAdf, dispatchAnalyticsEvent);
transformedAdf = _transformNestedTable3.transformedAdf;
}
if (dispatchAnalyticsEvent && fg('platform_editor_advanced_layouts_post_fix_patch_3')) {
var _transformedAdf$conte;
var hasSingleColumnLayout = (_transformedAdf$conte = transformedAdf.content) === null || _transformedAdf$conte === void 0 ? void 0 : _transformedAdf$conte.some(function (node) {
var _node$content;
return node && node.type === 'layoutSection' && ((_node$content = node.content) === null || _node$content === void 0 ? void 0 : _node$content.length) === 1;
});
if (hasSingleColumnLayout) {
dispatchAnalyticsEvent({
action: ACTION.SINGLE_COL_LAYOUT_DETECTED,
actionSubject: ACTION_SUBJECT.EDITOR,
eventType: EVENT_TYPE.OPERATIONAL
});
}
}
var entity = validateADFEntity(schema, transformedAdf || node, dispatchAnalyticsEvent);
var newEntity = maySanitizePrivateContent(entity, providerFactory, sanitizePrivateContent);
var parsedDoc = Node.fromJSON(schema, newEntity);
// throws an error if the document is invalid
try {
parsedDoc.check();
} catch (err) {
if (dispatchAnalyticsEvent) {
dispatchAnalyticsEvent({
action: ACTION.INVALID_PROSEMIRROR_DOCUMENT,
actionSubject: ACTION_SUBJECT.EDITOR,
eventType: EVENT_TYPE.OPERATIONAL
});
}
throw err;
}
if (dispatchAnalyticsEvent) {
findAndTrackUnsupportedContentNodes(parsedDoc, schema, dispatchAnalyticsEvent);
}
return parsedDoc;
} catch (e) {
if (dispatchAnalyticsEvent) {
dispatchAnalyticsEvent({
action: ACTION.DOCUMENT_PROCESSING_ERROR,
actionSubject: ACTION_SUBJECT.EDITOR,
eventType: EVENT_TYPE.OPERATIONAL
});
}
// eslint-disable-next-line no-console
console.error("Error processing document:\n".concat(e instanceof Error ? e.message : String(e), "\n\n"), JSON.stringify(node));
if (isProseMirrorSchemaCheckError(e)) {
throw e;
}
return;
}
}
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/max-params
export function processRawFragmentValue(schema, value, providerFactory, sanitizePrivateContent, contentTransformer, dispatchAnalyticsEvent) {
if (!value) {
return;
}
var adfEntities = value.map(function (item) {
return processRawValue(schema, item, providerFactory, sanitizePrivateContent, contentTransformer, dispatchAnalyticsEvent);
}).filter(function (item) {
return Boolean(item);
});
if (adfEntities.length === 0) {
return;
}
return Fragment.from(adfEntities);
}
function isProseMirrorSchemaCheckError(error) {
return error instanceof RangeError && (
// Ignored via go/ees005
// eslint-disable-next-line require-unicode-regexp
!!error.message.match(/^Invalid collection of marks for node/) ||
// Ignored via go/ees005
// eslint-disable-next-line require-unicode-regexp
!!error.message.match(/^Invalid content for node/));
}
var maySanitizePrivateContent = function maySanitizePrivateContent(entity, providerFactory, sanitizePrivateContent) {
if (sanitizePrivateContent && providerFactory) {
return sanitizeNodeForPrivacy(entity, providerFactory);
}
return entity;
};