UNPKG

@atlaskit/adf-schema

Version:

Shared package that contains the ADF-schema (json) and ProseMirror node/mark specs

338 lines (331 loc) 9.23 kB
"use strict"; 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;