UNPKG

9.14 kBJavaScriptView Raw
1import _defineProperty from "@babel/runtime/helpers/defineProperty";
2function 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; }
3function _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) { _defineProperty(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; }
4import { Schema } from 'prosemirror-model';
5import { COLOR, FONT_STYLE, SEARCH_QUERY, LINK } from './groups';
6import { link, em, strong, textColor, strike, subsup, underline, code, typeAheadQuery, confluenceInlineComment, breakout, alignment, indentation, annotation, unsupportedMark, unsupportedNodeAttribute, dataConsumer, fragment, border } from './marks';
7import { confluenceJiraIssue, confluenceUnsupportedBlock, confluenceUnsupportedInline, doc, paragraph, text, bulletList, orderedListWithOrder, listItem, heading, blockquote, codeBlock, panel, rule, image, mention, media, mediaInline, mediaGroup, mediaSingleWithCaption, hardBreak, emoji, table, tableCell, tableHeader, tableRow, decisionList, decisionItem, taskList, taskItem, unknownBlock, extension, inlineExtension, bodiedExtension, date, placeholder, layoutSection, layoutColumn, inlineCard, blockCard, unsupportedBlock, unsupportedInline, status, expand, nestedExpand, embedCard, caption } from './nodes';
8function addItems(builtInItems, config) {
9 var customSpecs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
10 if (!config) {
11 return {};
12 }
13
14 /**
15 * Add built-in Node / Mark specs
16 */
17 var items = builtInItems.reduce(function (items, _ref) {
18 var name = _ref.name,
19 spec = _ref.spec;
20 if (config.indexOf(name) !== -1) {
21 items[name] = customSpecs[name] || spec;
22 }
23 return items;
24 }, {});
25
26 /**
27 * Add Custom Node / Mark specs
28 */
29 return Object.keys(customSpecs).reduce(function (items, name) {
30 if (items[name]) {
31 return items;
32 }
33 items[name] = customSpecs[name];
34 return items;
35 }, items);
36}
37
38// We use groups to allow schemas to be constructed in different shapes without changing node/mark
39// specs, but this means nodes/marks are defined with groups that might never be used in the schema.
40// In this scenario ProseMirror will complain and prevent the schema from being constructed.
41//
42// To avoid the problem, we include items that serve to "declare" the groups in the schema. This
43// approach unfortunately leaves unused items in the schema, but has the benefit of avoiding the
44// need to manipulate `exclude` or content expression values for potentially every schema item.
45function groupDeclaration(name) {
46 return {
47 name: "__".concat(name, "GroupDeclaration"),
48 spec: {
49 group: name
50 }
51 };
52}
53var markGroupDeclarations = [groupDeclaration(COLOR), groupDeclaration(FONT_STYLE), groupDeclaration(SEARCH_QUERY), groupDeclaration(LINK)];
54var markGroupDeclarationsNames = markGroupDeclarations.map(function (groupMark) {
55 return groupMark.name;
56});
57var nodesInOrder = [{
58 name: 'doc',
59 spec: doc
60}, {
61 name: 'paragraph',
62 spec: paragraph
63}, {
64 name: 'text',
65 spec: text
66}, {
67 name: 'bulletList',
68 spec: bulletList
69}, {
70 name: 'orderedList',
71 spec: orderedListWithOrder
72}, {
73 name: 'listItem',
74 spec: listItem
75}, {
76 name: 'heading',
77 spec: heading
78}, {
79 name: 'blockquote',
80 spec: blockquote
81}, {
82 name: 'codeBlock',
83 spec: codeBlock
84}, {
85 name: 'panel',
86 spec: panel(true)
87}, {
88 name: 'rule',
89 spec: rule
90}, {
91 name: 'image',
92 spec: image
93}, {
94 name: 'mention',
95 spec: mention
96}, {
97 name: 'caption',
98 spec: caption
99}, {
100 name: 'media',
101 spec: media
102}, {
103 name: 'mediaGroup',
104 spec: mediaGroup
105}, {
106 name: 'mediaSingle',
107 spec: mediaSingleWithCaption
108}, {
109 name: 'mediaInline',
110 spec: mediaInline
111}, {
112 name: 'placeholder',
113 spec: placeholder
114}, {
115 name: 'layoutSection',
116 spec: layoutSection
117}, {
118 name: 'layoutColumn',
119 spec: layoutColumn
120}, {
121 name: 'hardBreak',
122 spec: hardBreak
123}, {
124 name: 'emoji',
125 spec: emoji
126}, {
127 name: 'table',
128 spec: table
129}, {
130 name: 'tableCell',
131 spec: tableCell
132}, {
133 name: 'tableRow',
134 spec: tableRow
135}, {
136 name: 'tableHeader',
137 spec: tableHeader
138}, {
139 name: 'confluenceJiraIssue',
140 spec: confluenceJiraIssue
141}, {
142 name: 'confluenceUnsupportedInline',
143 spec: confluenceUnsupportedInline
144}, {
145 name: 'confluenceUnsupportedBlock',
146 spec: confluenceUnsupportedBlock
147}, {
148 name: 'decisionList',
149 spec: decisionList
150}, {
151 name: 'decisionItem',
152 spec: decisionItem
153}, {
154 name: 'taskList',
155 spec: taskList
156}, {
157 name: 'taskItem',
158 spec: taskItem
159}, {
160 name: 'date',
161 spec: date
162}, {
163 name: 'status',
164 spec: status
165}, {
166 name: 'expand',
167 spec: expand
168}, {
169 name: 'nestedExpand',
170 spec: nestedExpand
171}, {
172 name: 'extension',
173 spec: extension
174}, {
175 name: 'inlineExtension',
176 spec: inlineExtension
177}, {
178 name: 'bodiedExtension',
179 spec: bodiedExtension
180}, {
181 name: 'inlineCard',
182 spec: inlineCard
183}, {
184 name: 'blockCard',
185 spec: blockCard
186}, {
187 name: 'embedCard',
188 spec: embedCard
189}, {
190 name: 'unknownBlock',
191 spec: unknownBlock
192}, {
193 name: 'unsupportedBlock',
194 spec: unsupportedBlock
195}, {
196 name: 'unsupportedInline',
197 spec: unsupportedInline
198}];
199var marksInOrder = [{
200 name: 'link',
201 spec: link
202}, {
203 name: 'em',
204 spec: em
205}, {
206 name: 'strong',
207 spec: strong
208}, {
209 name: 'textColor',
210 spec: textColor
211}, {
212 name: 'strike',
213 spec: strike
214}, {
215 name: 'subsup',
216 spec: subsup
217}, {
218 name: 'underline',
219 spec: underline
220}, {
221 name: 'code',
222 spec: code
223}, {
224 name: 'typeAheadQuery',
225 spec: typeAheadQuery
226}, {
227 name: 'alignment',
228 spec: alignment
229}, {
230 name: 'annotation',
231 spec: annotation
232}, {
233 name: 'confluenceInlineComment',
234 spec: confluenceInlineComment
235}].concat(markGroupDeclarations, [{
236 name: 'breakout',
237 spec: breakout
238}, {
239 name: 'dataConsumer',
240 spec: dataConsumer
241}, {
242 name: 'fragment',
243 spec: fragment
244}, {
245 name: 'indentation',
246 spec: indentation
247}, {
248 name: 'border',
249 spec: border
250}, {
251 name: 'unsupportedMark',
252 spec: unsupportedMark
253}, {
254 name: 'unsupportedNodeAttribute',
255 spec: unsupportedNodeAttribute
256}]);
257
258/**
259 * Creates a schema preserving order of marks and nodes.
260 */
261export function createSchema(config) {
262 var customNodeSpecs = config.customNodeSpecs,
263 customMarkSpecs = config.customMarkSpecs;
264 var nodesConfig = Object.keys(customNodeSpecs || {}).concat(config.nodes);
265 var marksConfig = Object.keys(customMarkSpecs || {}).concat(config.marks || []).concat(markGroupDeclarationsNames);
266 var nodes = addItems(nodesInOrder, nodesConfig, customNodeSpecs);
267 var marks = addItems(marksInOrder, marksConfig, customMarkSpecs);
268 nodes = sanitizeNodes(nodes, marks);
269 return new Schema({
270 nodes: nodes,
271 marks: marks
272 });
273}
274export function sanitizeNodes(nodes, supportedMarks) {
275 var nodeNames = Object.keys(nodes);
276 nodeNames.forEach(function (nodeKey) {
277 var nodeSpec = _objectSpread({}, nodes[nodeKey]);
278 if (nodeSpec.marks && nodeSpec.marks !== '_') {
279 nodeSpec.marks = nodeSpec.marks.split(' ').filter(function (mark) {
280 return !!supportedMarks[mark];
281 }).join(' ');
282 }
283 if (nodeSpec.content) {
284 nodeSpec.content = sanitizeNodeSpecContent(nodes, nodeSpec.content);
285 }
286 nodes[nodeKey] = nodeSpec;
287 });
288 return nodes;
289}
290export function sanitizeNodeSpecContent(nodes, rawContent) {
291 var content = rawContent.replace(/\W/g, ' ');
292 var contentKeys = content.split(' ');
293 var unsupportedContentKeys = contentKeys.filter(function (contentKey) {
294 return !isContentSupported(nodes, contentKey);
295 });
296 return unsupportedContentKeys.reduce(function (newContent, nodeName) {
297 return sanitizedContent(newContent, nodeName);
298 }, rawContent);
299}
300function sanitizedContent(content, invalidContent) {
301 if (!invalidContent.length) {
302 return content || '';
303 }
304 if (!content || !content.match(/\w/)) {
305 return '';
306 }
307 var pattern = "(".concat(invalidContent, "((\\s)*\\|)+)|((\\|(\\s)*)+").concat(invalidContent, ")|(").concat(invalidContent, "$)|(").concat(invalidContent, "(\\+|\\*))");
308 return content.replace(new RegExp(pattern, 'g'), '').replace(' ', ' ').trim();
309}
310function isContentSupported(nodes, contentKey) {
311 var nodeKeys = Object.keys(nodes);
312
313 // content is with valid node
314 if (nodeKeys.indexOf(contentKey) > -1) {
315 return true;
316 }
317
318 // content is with valid group
319 for (var supportedKey in nodes) {
320 var nodeSpec = nodes[supportedKey];
321 if (nodeSpec && nodeSpec.group === contentKey) {
322 return true;
323 }
324 }
325 return false;
326}
327export var allowCustomPanel = true;
\No newline at end of file