UNPKG

7.87 kBJavaScriptView Raw
1import { __assign, __read, __spread } from "tslib";
2import { Schema } from 'prosemirror-model';
3import { COLOR, FONT_STYLE, SEARCH_QUERY, LINK } from './groups';
4import { link, em, strong, textColor, strike, subsup, underline, code, typeAheadQuery, confluenceInlineComment, breakout, alignment, indentation, annotation, } from './marks';
5import { confluenceJiraIssue, confluenceUnsupportedBlock, confluenceUnsupportedInline, doc, paragraph, text, bulletList, orderedList, listItem, heading, blockquote, codeBlock, panel, rule, image, mention, media, mediaGroup, mediaSingle, 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, } from './nodes';
6function addItems(builtInItems, config, customSpecs) {
7 if (customSpecs === void 0) { customSpecs = {}; }
8 if (!config) {
9 return {};
10 }
11 /**
12 * Add built-in Node / Mark specs
13 */
14 var items = builtInItems.reduce(function (items, _a) {
15 var name = _a.name, spec = _a.spec;
16 if (config.indexOf(name) !== -1) {
17 items[name] = customSpecs[name] || spec;
18 }
19 return items;
20 }, {});
21 /**
22 * Add Custom Node / Mark specs
23 */
24 return Object.keys(customSpecs).reduce(function (items, name) {
25 if (items[name]) {
26 return items;
27 }
28 items[name] = customSpecs[name];
29 return items;
30 }, items);
31}
32// We use groups to allow schemas to be constructed in different shapes without changing node/mark
33// specs, but this means nodes/marks are defined with groups that might never be used in the schema.
34// In this scenario ProseMirror will complain and prevent the schema from being constructed.
35//
36// To avoid the problem, we include items that serve to "declare" the groups in the schema. This
37// approach unfortunately leaves unused items in the schema, but has the benefit of avoiding the
38// need to manipulate `exclude` or content expression values for potentially every schema item.
39function groupDeclaration(name) {
40 return {
41 name: "__" + name + "GroupDeclaration",
42 spec: {
43 group: name,
44 },
45 };
46}
47var markGroupDeclarations = [
48 groupDeclaration(COLOR),
49 groupDeclaration(FONT_STYLE),
50 groupDeclaration(SEARCH_QUERY),
51 groupDeclaration(LINK),
52];
53var markGroupDeclarationsNames = markGroupDeclarations.map(function (groupMark) { return groupMark.name; });
54var nodesInOrder = [
55 { name: 'doc', spec: doc },
56 { name: 'paragraph', spec: paragraph },
57 { name: 'text', spec: text },
58 { name: 'bulletList', spec: bulletList },
59 { name: 'orderedList', spec: orderedList },
60 { name: 'listItem', spec: listItem },
61 { name: 'heading', spec: heading },
62 { name: 'blockquote', spec: blockquote },
63 { name: 'codeBlock', spec: codeBlock },
64 { name: 'panel', spec: panel },
65 { name: 'rule', spec: rule },
66 { name: 'image', spec: image },
67 { name: 'mention', spec: mention },
68 { name: 'media', spec: media },
69 { name: 'mediaGroup', spec: mediaGroup },
70 { name: 'mediaSingle', spec: mediaSingle },
71 { name: 'placeholder', spec: placeholder },
72 { name: 'layoutSection', spec: layoutSection },
73 { name: 'layoutColumn', spec: layoutColumn },
74 { name: 'hardBreak', spec: hardBreak },
75 { name: 'emoji', spec: emoji },
76 { name: 'table', spec: table },
77 { name: 'tableCell', spec: tableCell },
78 { name: 'tableRow', spec: tableRow },
79 { name: 'tableHeader', spec: tableHeader },
80 { name: 'confluenceJiraIssue', spec: confluenceJiraIssue },
81 { name: 'confluenceUnsupportedInline', spec: confluenceUnsupportedInline },
82 { name: 'confluenceUnsupportedBlock', spec: confluenceUnsupportedBlock },
83 { name: 'decisionList', spec: decisionList },
84 { name: 'decisionItem', spec: decisionItem },
85 { name: 'taskList', spec: taskList },
86 { name: 'taskItem', spec: taskItem },
87 { name: 'date', spec: date },
88 { name: 'status', spec: status },
89 { name: 'expand', spec: expand },
90 { name: 'nestedExpand', spec: nestedExpand },
91 { name: 'extension', spec: extension },
92 { name: 'inlineExtension', spec: inlineExtension },
93 { name: 'bodiedExtension', spec: bodiedExtension },
94 { name: 'inlineCard', spec: inlineCard },
95 { name: 'blockCard', spec: blockCard },
96 { name: 'unknownBlock', spec: unknownBlock },
97 { name: 'unsupportedBlock', spec: unsupportedBlock },
98 { name: 'unsupportedInline', spec: unsupportedInline },
99];
100var marksInOrder = __spread([
101 { name: 'link', spec: link },
102 { name: 'em', spec: em },
103 { name: 'strong', spec: strong },
104 { name: 'textColor', spec: textColor },
105 { name: 'strike', spec: strike },
106 { name: 'subsup', spec: subsup },
107 { name: 'underline', spec: underline },
108 { name: 'code', spec: code },
109 { name: 'typeAheadQuery', spec: typeAheadQuery },
110 { name: 'alignment', spec: alignment },
111 { name: 'annotation', spec: annotation },
112 { name: 'confluenceInlineComment', spec: confluenceInlineComment }
113], markGroupDeclarations, [
114 { name: 'breakout', spec: breakout },
115 { name: 'indentation', spec: indentation },
116]);
117/**
118 * Creates a schema preserving order of marks and nodes.
119 */
120export function createSchema(config) {
121 var customNodeSpecs = config.customNodeSpecs, customMarkSpecs = config.customMarkSpecs;
122 var nodesConfig = Object.keys(customNodeSpecs || {}).concat(config.nodes);
123 var marksConfig = Object.keys(customMarkSpecs || {})
124 .concat(config.marks || [])
125 .concat(markGroupDeclarationsNames);
126 var nodes = addItems(nodesInOrder, nodesConfig, customNodeSpecs);
127 var marks = addItems(marksInOrder, marksConfig, customMarkSpecs);
128 nodes = sanitizeNodes(nodes, marks);
129 return new Schema({
130 nodes: nodes,
131 marks: marks,
132 });
133}
134export function sanitizeNodes(nodes, supportedMarks) {
135 var nodeNames = Object.keys(nodes);
136 nodeNames.forEach(function (nodeKey) {
137 var nodeSpec = __assign({}, nodes[nodeKey]);
138 if (nodeSpec.marks && nodeSpec.marks !== '_') {
139 nodeSpec.marks = nodeSpec.marks
140 .split(' ')
141 .filter(function (mark) { return !!supportedMarks[mark]; })
142 .join(' ');
143 }
144 if (nodeSpec.content) {
145 var content = nodeSpec.content.replace(/\W/g, ' ');
146 var contentKeys = content.split(' ');
147 var unsupportedContentKeys = contentKeys.filter(function (contentKey) { return !isContentSupported(nodes, contentKey); });
148 nodeSpec.content = unsupportedContentKeys.reduce(function (newContent, nodeName) { return sanitizedContent(newContent, nodeName); }, nodeSpec.content);
149 }
150 nodes[nodeKey] = nodeSpec;
151 });
152 return nodes;
153}
154function sanitizedContent(content, invalidContent) {
155 if (!invalidContent.length) {
156 return content || '';
157 }
158 if (!content || !content.match(/\w/)) {
159 return '';
160 }
161 var newContent = content
162 .replace(new RegExp("(" + invalidContent + "((\\s)*\\|)+)|((\\|(\\s)*)+" + invalidContent + ")|(" + invalidContent + "$)", 'g'), '')
163 .replace(' ', ' ')
164 .trim();
165 return newContent;
166}
167function isContentSupported(nodes, contentKey) {
168 var nodeKeys = Object.keys(nodes);
169 // content is with valid node
170 if (nodeKeys.indexOf(contentKey) > -1) {
171 return true;
172 }
173 // content is with valid group
174 for (var supportedKey in nodes) {
175 var nodeSpec = nodes[supportedKey];
176 if (nodeSpec && nodeSpec.group === contentKey) {
177 return true;
178 }
179 }
180 return false;
181}
182//# sourceMappingURL=create-schema.js.map
\No newline at end of file