@atlaskit/adf-schema
Version:
Shared package that contains the ADF-schema (json) and ProseMirror node/mark specs
338 lines (331 loc) • 9.23 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.allowCustomPanel = void 0;
exports.createSchema = createSchema;
exports.sanitizeNodeSpecContent = sanitizeNodeSpecContent;
exports.sanitizeNodes = sanitizeNodes;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _prosemirrorModel = require("prosemirror-model");
var _groups = require("./groups");
var _marks = require("./marks");
var _nodes = require("./nodes");
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
function addItems(builtInItems, config) {
var customSpecs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
if (!config) {
return {};
}
/**
* Add built-in Node / Mark specs
*/
var items = builtInItems.reduce(function (items, _ref) {
var name = _ref.name,
spec = _ref.spec;
if (config.indexOf(name) !== -1) {
items[name] = customSpecs[name] || spec;
}
return items;
}, {});
/**
* Add Custom Node / Mark specs
*/
return Object.keys(customSpecs).reduce(function (items, name) {
if (items[name]) {
return items;
}
items[name] = customSpecs[name];
return items;
}, items);
}
// We use groups to allow schemas to be constructed in different shapes without changing node/mark
// specs, but this means nodes/marks are defined with groups that might never be used in the schema.
// In this scenario ProseMirror will complain and prevent the schema from being constructed.
//
// To avoid the problem, we include items that serve to "declare" the groups in the schema. This
// approach unfortunately leaves unused items in the schema, but has the benefit of avoiding the
// need to manipulate `exclude` or content expression values for potentially every schema item.
function groupDeclaration(name) {
return {
name: "__".concat(name, "GroupDeclaration"),
spec: {
group: name
}
};
}
var markGroupDeclarations = [groupDeclaration(_groups.COLOR), groupDeclaration(_groups.FONT_STYLE), groupDeclaration(_groups.SEARCH_QUERY), groupDeclaration(_groups.LINK)];
var markGroupDeclarationsNames = markGroupDeclarations.map(function (groupMark) {
return groupMark.name;
});
var nodesInOrder = [{
name: 'doc',
spec: _nodes.doc
}, {
name: 'paragraph',
spec: _nodes.paragraph
}, {
name: 'text',
spec: _nodes.text
}, {
name: 'bulletList',
spec: _nodes.bulletList
}, {
name: 'orderedList',
spec: _nodes.orderedListWithOrder
}, {
name: 'listItem',
spec: _nodes.listItem
}, {
name: 'heading',
spec: _nodes.heading
}, {
name: 'blockquote',
spec: _nodes.blockquote
}, {
name: 'codeBlock',
spec: _nodes.codeBlock
}, {
name: 'panel',
spec: (0, _nodes.panel)(true)
}, {
name: 'rule',
spec: _nodes.rule
}, {
name: 'image',
spec: _nodes.image
}, {
name: 'mention',
spec: _nodes.mention
}, {
name: 'caption',
spec: _nodes.caption
}, {
name: 'media',
spec: _nodes.media
}, {
name: 'mediaGroup',
spec: _nodes.mediaGroup
}, {
name: 'mediaSingle',
spec: _nodes.mediaSingleWithCaption
}, {
name: 'mediaInline',
spec: _nodes.mediaInline
}, {
name: 'placeholder',
spec: _nodes.placeholder
}, {
name: 'layoutSection',
spec: _nodes.layoutSection
}, {
name: 'layoutColumn',
spec: _nodes.layoutColumn
}, {
name: 'hardBreak',
spec: _nodes.hardBreak
}, {
name: 'emoji',
spec: _nodes.emoji
}, {
name: 'table',
spec: _nodes.table
}, {
name: 'tableCell',
spec: _nodes.tableCell
}, {
name: 'tableRow',
spec: _nodes.tableRow
}, {
name: 'tableHeader',
spec: _nodes.tableHeader
}, {
name: 'confluenceJiraIssue',
spec: _nodes.confluenceJiraIssue
}, {
name: 'confluenceUnsupportedInline',
spec: _nodes.confluenceUnsupportedInline
}, {
name: 'confluenceUnsupportedBlock',
spec: _nodes.confluenceUnsupportedBlock
}, {
name: 'decisionList',
spec: _nodes.decisionList
}, {
name: 'decisionItem',
spec: _nodes.decisionItem
}, {
name: 'taskList',
spec: _nodes.taskList
}, {
name: 'taskItem',
spec: _nodes.taskItem
}, {
name: 'date',
spec: _nodes.date
}, {
name: 'status',
spec: _nodes.status
}, {
name: 'expand',
spec: _nodes.expand
}, {
name: 'nestedExpand',
spec: _nodes.nestedExpand
}, {
name: 'extension',
spec: _nodes.extension
}, {
name: 'inlineExtension',
spec: _nodes.inlineExtension
}, {
name: 'bodiedExtension',
spec: _nodes.bodiedExtension
}, {
name: 'inlineCard',
spec: _nodes.inlineCard
}, {
name: 'blockCard',
spec: _nodes.blockCard
}, {
name: 'embedCard',
spec: _nodes.embedCard
}, {
name: 'unknownBlock',
spec: _nodes.unknownBlock
}, {
name: 'unsupportedBlock',
spec: _nodes.unsupportedBlock
}, {
name: 'unsupportedInline',
spec: _nodes.unsupportedInline
}];
var marksInOrder = [{
name: 'link',
spec: _marks.link
}, {
name: 'em',
spec: _marks.em
}, {
name: 'strong',
spec: _marks.strong
}, {
name: 'textColor',
spec: _marks.textColor
}, {
name: 'strike',
spec: _marks.strike
}, {
name: 'subsup',
spec: _marks.subsup
}, {
name: 'underline',
spec: _marks.underline
}, {
name: 'code',
spec: _marks.code
}, {
name: 'typeAheadQuery',
spec: _marks.typeAheadQuery
}, {
name: 'alignment',
spec: _marks.alignment
}, {
name: 'annotation',
spec: _marks.annotation
}, {
name: 'confluenceInlineComment',
spec: _marks.confluenceInlineComment
}].concat(markGroupDeclarations, [{
name: 'breakout',
spec: _marks.breakout
}, {
name: 'dataConsumer',
spec: _marks.dataConsumer
}, {
name: 'fragment',
spec: _marks.fragment
}, {
name: 'indentation',
spec: _marks.indentation
}, {
name: 'border',
spec: _marks.border
}, {
name: 'unsupportedMark',
spec: _marks.unsupportedMark
}, {
name: 'unsupportedNodeAttribute',
spec: _marks.unsupportedNodeAttribute
}]);
/**
* Creates a schema preserving order of marks and nodes.
*/
function createSchema(config) {
var customNodeSpecs = config.customNodeSpecs,
customMarkSpecs = config.customMarkSpecs;
var nodesConfig = Object.keys(customNodeSpecs || {}).concat(config.nodes);
var marksConfig = Object.keys(customMarkSpecs || {}).concat(config.marks || []).concat(markGroupDeclarationsNames);
var nodes = addItems(nodesInOrder, nodesConfig, customNodeSpecs);
var marks = addItems(marksInOrder, marksConfig, customMarkSpecs);
nodes = sanitizeNodes(nodes, marks);
return new _prosemirrorModel.Schema({
nodes: nodes,
marks: marks
});
}
function sanitizeNodes(nodes, supportedMarks) {
var nodeNames = Object.keys(nodes);
nodeNames.forEach(function (nodeKey) {
var nodeSpec = _objectSpread({}, nodes[nodeKey]);
if (nodeSpec.marks && nodeSpec.marks !== '_') {
nodeSpec.marks = nodeSpec.marks.split(' ').filter(function (mark) {
return !!supportedMarks[mark];
}).join(' ');
}
if (nodeSpec.content) {
nodeSpec.content = sanitizeNodeSpecContent(nodes, nodeSpec.content);
}
nodes[nodeKey] = nodeSpec;
});
return nodes;
}
function sanitizeNodeSpecContent(nodes, rawContent) {
var content = rawContent.replace(/\W/g, ' ');
var contentKeys = content.split(' ');
var unsupportedContentKeys = contentKeys.filter(function (contentKey) {
return !isContentSupported(nodes, contentKey);
});
return unsupportedContentKeys.reduce(function (newContent, nodeName) {
return sanitizedContent(newContent, nodeName);
}, rawContent);
}
function sanitizedContent(content, invalidContent) {
if (!invalidContent.length) {
return content || '';
}
if (!content || !content.match(/\w/)) {
return '';
}
var pattern = "(".concat(invalidContent, "((\\s)*\\|)+)|((\\|(\\s)*)+").concat(invalidContent, ")|(").concat(invalidContent, "$)|(").concat(invalidContent, "(\\+|\\*))");
return content.replace(new RegExp(pattern, 'g'), '').replace(' ', ' ').trim();
}
function isContentSupported(nodes, contentKey) {
var nodeKeys = Object.keys(nodes);
// content is with valid node
if (nodeKeys.indexOf(contentKey) > -1) {
return true;
}
// content is with valid group
for (var supportedKey in nodes) {
var nodeSpec = nodes[supportedKey];
if (nodeSpec && nodeSpec.group === contentKey) {
return true;
}
}
return false;
}
var allowCustomPanel = true;
exports.allowCustomPanel = allowCustomPanel;
;